diff --git a/cmake/Modules/LauraExternalDependencies.cmake b/cmake/Modules/LauraExternalDependencies.cmake index e0a7527..80aac17 100644 --- a/cmake/Modules/LauraExternalDependencies.cmake +++ b/cmake/Modules/LauraExternalDependencies.cmake @@ -1,32 +1,14 @@ # Laura++ needs ROOT, we just require that it is a version that exports CMake targets properly # We may depend on other things in the future, e.g. JSON or YAML for easier configuration of particle properties etc. if(DEFINED ENV{ROOTSYS}) list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS}) endif() if(LAURA_BUILD_ROOFIT_TASK) - find_package(ROOT 6.14 REQUIRED COMPONENTS EG RooFitCore RooFit) + find_package(ROOT 6.18 REQUIRED COMPONENTS EG RooFitCore RooFit) else() - find_package(ROOT 6.14 REQUIRED COMPONENTS EG) -endif() - -#message(STATUS "ROOT include directories: ${ROOT_INCLUDE_DIRS}") -#message(STATUS "ROOT libraries: ${ROOT_LIBRARIES}") -#message(STATUS "ROOT definitions: ${ROOT_DEFINITIONS}") -#message(STATUS "ROOT CXX flags: ${ROOT_CXX_FLAGS}") -#message(STATUS "ROOT CC flags: ${ROOT_CC_FLAGS}") -#message(STATUS "ROOT use file: ${ROOT_USE_FILE}") -# Don't want to do this because it uses old-style CMake -#include(${ROOT_USE_FILE}) - -if(EXISTS "${ROOT_DIR}/RootMacros.cmake") - message(STATUS "Laura++: Including ROOT macros module: ${ROOT_DIR}/RootMacros.cmake") - include(${ROOT_DIR}/RootMacros.cmake) -elseif(EXISTS "${ROOT_DIR}/modules/RootNewMacros.cmake") - message(STATUS "Laura++: Including ROOT macros module: ${ROOT_DIR}/modules/RootNewMacros.cmake") - include(${ROOT_DIR}/modules/RootNewMacros.cmake) -else() - message(WARNING "Laura++: Cannot locate ROOT macros module in ${ROOT_DIR}") + find_package(ROOT 6.18 REQUIRED COMPONENTS EG) endif() +message(STATUS "Laura++: Using ROOT installation: ${ROOT_DIR}") diff --git a/doc/ReleaseNotes.md b/doc/ReleaseNotes.md index 799aea2..3581142 100644 --- a/doc/ReleaseNotes.md +++ b/doc/ReleaseNotes.md @@ -1,894 +1,910 @@ # Laura++ release notes +16th Oct 2023 Thomas Latham +* Remove all uses of deprecated ROOT ClassImp macro +* Generate ROOT dictionary only for classes: LauAbsRValue, LauBlind and LauParameter + - Remove ClassDef macro from all other classes + - Remove all other classes from from LinkDef file and dictionary generation command +* Take advantage of related improvements in the ROOT CMake + - Consequently bump the minimum ROOT version to 6.18 +* See https://phab.hepforge.org/T213 for more details + 22nd June 2023 Thomas Latham * Added functionality to properly manage Gaussian constraints in toy generation - see https://phab.hepforge.org/T45 9th June 2023 Mark Whitehead * Added functionality to include n-dimensional Gaussian constraints - see https://phab.hepforge.org/T214 +10th February 2023 Thomas Latham +* Store the sqDP jacobian separately in weightEvents routines + - Previously the weight was multiplied by the jacobian + - Now the jacobian is stored in a separate branch + - New info messages give instructions on what to do depending on how the + input sample was generated + 21st November 2022 Andy Morris * Use Minuit to automatically determine ASq max for signal in LauIsobarDynamics - see https://phab.hepforge.org/D85 28th June 2022 Thomas Latham * Improvements to Doxygen config 31st May 2022 Thomas Latham * Add examples for easily generating toy samples uniformly in any DP or SqDP * Very minor updates to related QuasiFlatSqDalitz examples 30th November 2021 Thomas Latham * Update CI config to: - Simplify changing compiler version - Disallow dev build failure in scheduled pipelines 7th September 2021 Thomas Latham * Update CI to test future ROOT versions in dev3/dev4 LCG builds 1st July 2021 Thomas Latham * Add version of QuasiFlatSqDalitz where particle masses can be supplied on command line 28th June 2021 Thomas Latham * Fix for compilation with ROOT 6.24 18th May 2021 Mark Whitehead * Add new MIPW example - see https://phab.hepforge.org/T147 26th March 2021 Thomas Latham * Fix bug in setting for linear interpolation in Lau1DHistPdf - see https://phab.hepforge.org/T142 9th March 2021 Mark Whitehead * Update particle properties to PDG 2020 - see https://phab.hepforge.org/T140 5th March 2021 Dan Johnson * Alterations to allow Blatt-Weisskopf factor for parent to be created in a model with only a K-matrix - see https://phab.hepforge.org/D52 4th February 2021 Dan Johnson * Extend the K-matrix implementation to handle non-zero spin - see https://phab.hepforge.org/T135 1st February 2021 Dan Johnson * Allow floating of parameters in the K-matrix - see https://phab.hepforge.org/T59 2nd December 2020 Thomas Latham * Fix LauFormulaPar to follow change in behaviour of TFormula - see https://phab.hepforge.org/T129 27th November 2020 Dan Johnson * Allow slope of NR exponential model to vary negative - improves fit stability in low-statistics fits - see https://phab.hepforge.org/T128 17th September 2020 Mark Whitehead * Begin updates to use inclusive language. Simultaneous fits now handled by Coordinator and Tasks - see https://phab.hepforge.org/T112 19th August 2020 Thomas Latham * Remove explicit normalisation of numerator Blatt-Weisskopf factors - See https://phab.hepforge.org/T93 22nd May 2020 Thomas Latham * Fix uninitialised variable (related to rho-omega mixing) in LauIsobarDynamics 12th December 2019 Thomas Latham & Daniel Johnson * Fix issue with generation of events for categories with small expected yield - See https://phab.hepforge.org/T76 21st November 2019 Thomas Latham * Add QuasiFlatSqDalitz example, which generates toy according to EvtGen's FLATSQDALITZ model 6th - 20th November 2019 Thomas Latham * Adopt CMake as the build system - See https://phab.hepforge.org/T33 === ## Laura++ v3r5 6th August 2019 Thomas Latham * Add some extra charmonium states to list of known resonances * Minor modifications to code for importing parameter values from file 17th May 2019 Thomas Latham * Fix licences and Doxygen in pole, nonresonant form factors, and rescattering line shapes * Add journal reference for pole line shape * Fix class names and add Doxygen to LauCalcChiSq, LauResultsExtractor, LauMergeDataFiles * Update Doxyfile from more recent Doxygen version * Make consistent the use of ClassDef and ClassImp everywhere * Add functions to return the "sanitised" names of parent and daughters 8th January 2019 Thomas Latham * Workaround for issue with splitting toy MC files when generating large number of experiments 5th December 2018 Thomas Latham * Move sources and headers for the utilities library into the main library - makes examples dir executables only (in preparation for CMake build) 22nd, 23rd July and 4th August 2018 Juan Otalora * Add pole, nonresonant form factors, and rescattering line shapes 17th April 2018 Daniel O'Hanlon * Fix bug in rho-omega mixing fit-fraction calculation: rho fit-fraction was not normalised to the total DP rate 23rd March 2018 Thomas Latham * Some fixes in LauRhoOmegaMix that propagate the following settings to the subcomponents: - spinType_ - flipHelicity_ - ignoreMomenta_ - ignoreSpin_ - ignoreBarrierScaling_ 23rd February 2018 Thomas Latham * Add section on structure of package to README file (requested by CPC technial editor) * Add copyright notice to files in test directory 21st February 2018 Thomas Latham * Improve comments in functions calculating helicity angles in LauKinematics 19th February 2018 Daniel O'Hanlon * Fix bug in LauCPFitModel introduced in code for importing parameters (25/01/18) - When parameters are asked to be randomised via useRandomInitFitPars, those parameters that were already fixed in the model, in addition to those that are fixed on import, were being freed. 19th February 2018 Daniel O'Hanlon * Bug fixes in rho/omega fit fractions calculation 25th January 2018 Daniel O'Hanlon * Add feature for importing parameters into LauCPFitModels from previous fit output files. 23rd January 2018 Daniel O'Hanlon * Calculate separate rho and omega fit-fractions for LauRhoOmegaMix, when turned on with calculateRhoOmegaFitFractions in LauIsobarDynamics. === ## Laura++ v3r4 16th January 2018 Thomas Latham * Update licence for all files to the Apache Software License Version 2.0 14th December 2017 Thomas Latham * Correct LauFlatteRes to use the exact formulae from the papers that report the default parameter values for each supported resonance - Deals correctly now with the cases where the m0 is absorbed into the couplings - Now uses the correct value of g1 for the a_0(980) (needed to be squared) - Also sets the mass values to those reported in those papers - Added printout to specify what is being done in each case * Improve the consistency between the weightEvents functions in LauSimpleFitModel and LauCPFitModel - Also remove the unecessary division by ASqMax in LauIsobarDynamics::getEventWeight 4th December 2017 Thomas Latham * Allow background yields to be specified as any LauAbsRValue (i.e. LauParameter or now also LauFormulaPar) 30th November 2017 Thomas Latham * In LauFitDataTree::readExperimentData add a check that the tree contains the branch "iExpt" and if not: - If the requested experiment is 0 then read all data in the tree (and print a warning) - Otherwise print an error message and return 29th November 2017 Thomas Latham * Improve error messages in LauCPFitModel::weightEvents === ## Laura++ v3r3 23rd November 2017 Thomas Latham * Add an example written as a python script: GenFit3pi.py * Various improvements to the other example code 23rd November 2017 Thomas Latham * Fix bug in the LauAbsResonance constructor used by the K-matrix - "resonance" charge is now set to the sum of the daughter charges 1st November 2017 Thomas Latham * Fix bug in LauFlatteRes - m_0 factor multiplying the width was, if useAdlerTerm_ is true, replaced by f_Adler rather than being multiplied by it - only affected case where using LauFlatteRes to describe K_0*(1430) === ## Laura++ v3r2 18th October 2017 Thomas Latham * Modify LauDaughters::testDPSymmetry to: - produce an ERROR message and exit if the symmetric DP does not have its daughters arranged correctly - detect also flavour-conjugate DPs and set a corresponding flag that can be retrieved via LauDaughters::gotFlavourConjugateDP - in this case if the daughters are sub-optimally arranged print a WARNING * Modify LauIsobarDynamics::calcDPNormalisationScheme so that any narrow resonance regions are symmetrised appropriately if the DP is fully-symmetric, symmetric or is flavour-conjugate (and in this last case, symmetrisation of the integration has been forced via a new boolean function) 11th October 2017 Thomas Latham * Allow the user to specify the randomiser to be used to randomise the initial values of the isobar parameters - simply use the new static function LauAbsCoeffSet::setRandomiser - if not specified it defaults to the current use of LauRandom::zeroSeedRandom 10th October 2017 Thomas Latham * Make symmetrisation of vetoes automatic in LauVetoes for symmetric DPs - but add new allowed indices (4 and 5) to allow vetoes to be applied to mMin or mMax if desired * Also apply to fully symmetric DPs * In addition implement the more efficient calculation of the amplitude in the fully symmetric case 23rd September 2017 Thomas Latham * Fix expressions for Covariant option for Blatt-Weisskopf momentum for spin > 1 * Make use of setSpinFormalism to set the formalism to Legendre for NR types (instead of kludging with ignoreMomentum) 15th September 2017 Thomas Latham * Various improvements to the examples 6th September 2017 Thomas Latham * Improve doxygen comments for event-embedding functions in fit models 5th September 2017 Thomas Latham * Improve efficiency of Covariant spin factor calculations 31st August 2017 Thomas Latham * Add further option for parent Blatt-Weisskopf momentum - Covariant (corresponding to Covariant spin factor) 8th August 2017 Thomas Latham * Implement expressions for the spin factor based on covariant tensor formalism * Make it much simpler to switch between formalism options via new functions in LauResonanceMaker: - setSpinFormalism, setBWType, setBWBachelorRestFrame - default settings are unchanged (and are equivalent to setting LauAbsResonance::Zemach_P, LauBlattWeisskopfFactor::BWPrimeBarrier, LauBlattWeisskopfFactor::ResonanceFrame, respectively) 21st July 2017 Thomas Latham * Add note to README file about compilation issue on Ubuntu 16.04 LTS 21st July 2017 Thomas Latham * Create public functions to update the kinematics based on one invariant mass and the corresponding helicity angle 20th June 2017 Daniel O'Hanlon * Terminate when asked to read a non-existent K-matrix parameter file 8th June 2017 Thomas Latham * Fix compilation error on gcc 4.9 30th May 2017 Thomas Latham * Permit different efficiency histograms to be defined in classic/square DP and force enable calculation of square DP coords (here and for background PDFs) if required 29th May 2017 Thomas Latham * Propagate information on EDM from the minimiser to the fit models and into the fit results ntuple 29th May 2017 Thomas Latham * Ensure that the kinematics will calculate the square DP co-ordinates if the integration requires them 29th May 2017 Thomas Latham * Reintegrate the RooFit-slave branch into the trunk (and delete the branch) 28th March 2017 Thomas Latham (in branch for developing RooFit-based slave) * Rename cacheFitData to verifyFitData in all fit models and RF-slave 28th March 2017 Daniel O'Hanlon * Fix bug in LauCPFitModel::weightEvents 24th March 2017 Thomas Latham (in branch for developing RooFit-based slave) * Refactor code between fit models, master, slave and fit-object classes 22nd March 2017 Thomas Latham (in branch for developing RooFit-based slave) * Make the compilation of the RF-based slave class, and its associated example binary, optional 22nd March 2017 Thomas Latham (in branch for developing RooFit-based slave) * Complete working example of RooFit-based slave - Have identified some scope for refactoring of code - Also want to make the compilation of this class, and its associated example binary, optional 15th March 2017 Mark Whitehead (in branch for developing time-dependent model) * Handle event-by-event mistag probabilities 7th March 2017 Thomas Latham * Rename the command for weighting events from "reweight" to "weight" 3rd March 2017 Daniel O'Hanlon * Implement LauCPFitModel::weightEvents based on the same function in LauSimpleFitModel 1st March 2017 Thomas Latham (in branch for developing RooFit-based slave) * Fix root-cling related errors 28th February 2017 Thomas Latham (in branch for developing RooFit-based slave) * Start work on creation of RooFit-based slave class - Will allow RooFit-based fitters to plug-in straightforwardly to the simultaneous fitting (JFit) framework 20th February 2017 Thomas Latham * Add warning messages to LauBkgndDPModel::setBkgndHisto when supplied backgroud histogram pointers are null 31st January 2017 Thomas Latham * Audit of the code to automate the creation of the integration binning scheme. - Fix one bug, some tidy-ups, and reintroduce a couple of lost features: - the use of a single square-DP grid if a narrow resonance is found in m12 - extension of region down to threshold if the narrow resonance is close to threshold 22nd January 2017 Daniel O'Hanlon * Fix bug in automated integration scheme where resonances were assumed to have been added in order of ascending mass 14th December 2016 Daniel O'Hanlon * Add several light resonances to the list in LauResonanceMaker 13th December 2016 Daniel O'Hanlon * Automate the determination of the integration scheme for an arbitrary number of narrow resonances in m13 and m23 12th December 2016 Daniel O'Hanlon * Efficiency saving from modifying the behaviour of LauIsobarDynamics::calculateAmplitudes, LauIsobarDynamics::resAmp and LauIsobarDynamics::incohResAmp in the case of symmetric DPs - Previously, there were 2N calls to LauKinematics::flipAndUpdateKinematics for N resonances, now reduced to 2 21st November 2016 John Back * Added two K-matrix examples for creating pedagogical plots (with associated data files): - B3piKMatrixPlots for K-matrix elements, propagator, and pole and SVP production terms - B3piKMatrixMassProj for pole and SVP mass projections generated over the DP 17th November 2016 John Back * Modifications of the K matrix implementation: - Changed the format of the parameter file to use keywords, with updated examples - The scattering coefficients are now symmetrised, unless "ScattSymmetry 0" is used - Allow the option to use the Adler zero suppression term for the production poles and SVPs (default = off). These are specified with the useProdAdler boolean in the LauKMatrixProdPole/SVP constructors - Added a few helper functions for obtaining coefficients and (internal) matrices - Added a method to return the Lorentz-invariant transition amplitude for plots/tests 1st November 2016 Wenbin Qian * Add calculation of so-called covariant factors for spin amplitude === ## Laura++ v3r1 9th September 2016 Thomas Latham * Modification of LauFitNtuple to check the size of the covariance matrix wrt known number of parameters and act accordingly: - If it is empty, just fill a diagonal correlation matrix and issue a warning. - If it results from a failed first stage of a two-stage fit then the correlation matrix is padded with 1s and 0s for the parameters that were fixed in the first stage. * Remove the feature that allows parameters to float in first stage of a two-stage fit but to be fixed in second. * Minor fix to LauAbsCoeffSet: the names of parameters would be mangled if they were the same as the basename, e.g. A1_A would become A1_ while A1_B would be correct. 8th September 2016 Thomas Latham * Modifications to LauResonanceInfo to allow customisation of which extra parameters are shared between charge conjugate or shared-parameter records. - Where the parameters are not shared they are independently created instead of being cloned. * Modification of LauRhoOmegaMix to take advantage of the above to have the magB and phiB parameters independent. * Addition to LauResonanceMaker of rho(770)_COPY record that is a shared record with rho(770) - this allows the above new feature to be used. * Minor unrelated improvement to information messages in LauIsobarDynamics. 25th August 2016 John Back * Modified LauRhoOmegaMix to allow either a RelBW or GS lineshape for the rho, as well as allowing the option to set the second-order denominator term to be equal to unity. Also fixed the bug where the spinTerm was not included in the rho-omega amplitude. Changed the LauAbsResonance enum from RhoOmegaMix to RhoOmegaMix_GS, RhoOmegaMix_RBW, RhoOmegaMix_GS_1 and RhoOmegaMix_RBW_1, where _1 sets the denominator term to unity and _GS or _RBW sets the appropriate rho lineshape. The omega is always a RelBW. * Added to LauAbsResonance: ignoreSpin and ignoreBarrierScaling boolean flags, which ignore either the spin terms or the barrier scaling factors for the amplitude. The latter does not turn off the resonance barrier factor for mass-dependent widths * Added to LauResonanceMaker: getResInfo(resonanceName), which retrieves the resonance information. This is used to obtain the PDG omega values for initialising LauRhoOmegaMix * Made LauRelBreitWignerRes ignore momentum-dependent terms for the resonance width if ignoreMomenta is set. This is used in the LauRhoOmegaMix for the omega lineshape where its width does not depend on momentum 23rd May 2016 John Back * Added new lineshape model for rho-omega mass mixing, LauRhoOmegaMix. 12th April 2016 Thomas Latham * Switch to integrating in square DP when narrow resonances are found in m12. - The integration grid size can be specified by the user 19th January 2016 John Back * Correct the f(m^2) factor in the denominator of the LauGounarisSakuraiRes lineshape to use Gamma_0 instead of Gamma(m) 14th January 2016 Thomas Latham * Documentation improvements 7th December 2015 Thomas Latham * Resolve bug that meant the order of resonances in LauIsobarDynamics was assumed to match with the order in which the complex coefficients are supplied to the fit model - The ordering of resonances is defined by LauIsobarDynamics: - Firstly all coherent resonances in order of addition - Followed by all incoherent resonances in order of addition - The complex coefficients are now rearranged to match that order - Printout of the model summary at the end of initialisation has been enhanced to indicate the ordering - Doxygen updated to reflect these changes 12th November 2015 Daniel Craik * Added support for Akima splines and linear interpolation to Lau1DCubicSpline * LauAbsModIndPartWave, LauModIndPartWaveRealImag and LauModIndPartWaveMagPhase updated to allow choice of spline interpolation method * LauEFKLLMRes updated to use Akima splines 10th November 2015 Thomas Latham & Daniel Craik * Add the EFKLLM form-factor model for the Kpi S-wave and an example using this lineshape * Modify LauResonanceMaker::getResonance to use a switch for greater clarity and easier checking on missing cases 4th November 2015 Daniel Craik * Add checks to LauIsobarDynamics::addResonance and LauIsobarDynamics::addIncohResonance to stop the wrong type of LauResonanceModel being used - LauAbsResonance::isIncoherentModel method added to identify incoherent models 8th September 2015 Mark Whitehead * Add the ability to modify the error of parameters via the CoeffSet - setParameterError added to LauAbsCoeffSet * Tweak the handling of initial error values passed to MINUIT (to determine initial step size) in LauMinuit 7th September 2015 Mark Whitehead * Add the ability to Gaussian constrain parameters via the CoeffSet - addGaussianConstraint added to LauAbsCoeffSet 12th June 2015 Thomas Latham * Modifications to Belle-style nonresonant models - LauBelleNR modified to use pure Legendre polynomials of cos(theta) in the spin term (i.e. to remove the q*p factors) - New form added to LauBelleSymNR (LauAbsResonance::BelleSymNRNoInter) that removes the interference term between the two DP halves - The new form also works with non-zero spin (warning added if non-zero spin specified for BelleSymNR and TaylorNR) 8th June 2015 Thomas Latham * Further work on the blinding mechanism: - New method added LauParameter::blindParameter that activates the blinding. - The rest of the framework updated to use another new method LauParameter::unblindedValue in all likelihood calculations etc. - Example GenFitNoDP updated to include lines to optionally blind the yield parameters. 29th May 2015 Daniel Craik * Added LauBlind class for blinding and unblinding a value with an offset based on a blinding string 26th May 2015 Daniel Craik * Stopped LauCPFitModel passing fixed signal/background yields or asymmetries to Minuit to avoid hitting limit of 101 fixed parameters 22nd April 2015 Daniel Craik * Updated MIPW classes to use Lau1DCubicSpline 19th April 2015 Daniel Craik * Added Lau1DCubicSpline class for 1D spline interpolation 26th March 2015 Thomas Latham * Reworked MIPW code into abstract base class and derived classes to allow different representations of the amplitude at each knot 31st December 2015 Daniel Craik * Added unbinned goodness of fit tests to examples 12th January 2015 Daniel Craik * Calculate effective masses for virtual resonances above the upper kinematic limit 10th December 2014 Daniel Craik * Added coefficient sets to extract gamma from a simultaneous fit to CP and nonCP final states, such as the B0->D_CP K pi and B0->D0bar K pi Dalitz plots, as proposed in Phys. Rev. D79, 051301 (2009) - LauPolarGammaCPCoeffSet uses the CP parameters r, delta and gamma directly - LauRealImagGammaCPCoeffSet parameterises CPV as X_CP+/- and Y_CP+/- - LauCartesianGammaCPCoeffSet parameterises CPV as X_CP, Y_CP DeltaX_CP DeltaY_CP - Fixed CP parameters are not passed to the fitter so the same coefficient sets can be used for both the CP and nonCP Dalitz plots - LauPolarGammaCPCoeffSet allows for a single gamma parameter to be shared between multiple resonances - LauAbsCoeffSet::adjustName made virtual to allow global variables such as gamma to not receive a prefix === ## Laura++ v3r0p1 19th June 2015 Thomas Latham * Factor out the JFit slave code from LauAbsFitModel into a new base class LauSimFitSlave 19th June 2015 Thomas Latham * Fix check in LauIsobarDynamics::calcDPNormalisationScheme to avoid using hardcoded number === ## Laura++ v3r0 24th October 2014 Thomas Latham * Fixed bug in floating of Blatt-Weisskopf barrier radii - The values at the pole mass were not being updated when the radii changed 21st October 2014 Daniel Craik * Fixed bug in LauIsobarDynamics where multiple incoherent amplitudes led to nonsensical fit fractions 17th October 2014 John Back * Added the ability to calculate the transition amplitude matrix T in LauKMatrixPropagator, as well as a few other minor speed-up changes and code checks. Example/PlotKMatrixTAmp.cc can be used to check the T amplitude variation, phase shift and inelasticity, for a given K matrix channel, as a function of the invariant mass squared variable s 15th October 2014 Thomas Latham * Add methods to LauIsobarDynamics to make the integration binning more tunable by the user: - setNarrowResonanceThreshold - modify the value below which a resonance is considered to be narrow (defaults to 0.02 GeV/c2) - setIntegralBinningFactor - modify the factor by which the narrow resonance width is divided to obtain the bin size (defaults to 100) * Print warning messages if the memory usage is likely to be very large 13th October 2014 Thomas Latham * Modify Makefile to allow compilation with ROOT 6 (in addition to maintaining support for ROOT 5) * Fix a few compilation errors on MacOSX 10.9 13th October 2014 Daniel Craik * Update LauModIndPartWave to allow knots at kinematic limits to be modified - Add new method setKnotAmp to modify existing knots (and the knot at the upper kinematic limit which is automatically added at initialisation) * Update doxygen for LauIsobarDynamics::addIncoherentResonance to mention that incoherent resonances must be added last 10th October 2014 Thomas Latham * Add new method to LauResonanceMaker to set whether the radius of a given Blatt-Weisskopf category should be fixed of floated * Modify the methods of LauResonanceMaker to set the radius value and whether it should be floated so that they work before and after the resonances have been created 9th October 2014 John Back * Corrected the eta-eta' and 4pi phase space factors in LauKMatrixPropagator, which is used for the K-matrix amplitude: - calcEtaEtaPRho() does not include the mass difference term m_eta - m_eta' following the recommendation in hep-ph/0204328 and from advice from M Pennington - calcFourPiRho() incorporates a better parameterisation of the double integral of Eq 4 in hep-ph/0204328 which avoids the exponential increase for small values of s (~< 0.1) - More detailed comments are provided in the above two functions to explain what is going on and the reason for the choices made 6th October 2014 Thomas Latham * Implement the mechanism for floating Blatt-Weisskopf barrier factor radius parameters 30th September 2014 Thomas Latham * Fix issue in the checks on toy MC generation validity - in the case of exceeding max iterations it was possible to enter an infinite loop - the checks now detect all three possible states: - aSqMaxSet_ is too low (generation is biased) => increase aSqMaxSet_ value - aSqMaxSet_ is too high => reduce aSqMaxSet_ value to improve efficiency - aSqMaxSet_ is high (causing low efficiency) but cannot be lowered without biasing => increase iterationsMax_ limit * Update resonance parameter in LauResonanceMaker to match PDG 2014 * Modify behaviour when TTree objects are saved into files to avoid having multiple cycle numbers present 29th September 2014 Daniel Craik * Add support for incoherent resonances in the signal model - LauIsobarDynamics updated to include incoherent terms - ABC for incoherent resonances, LauAbsIncohRes, added deriving from LauAbsResonance - LauGaussIncohRes added to implement a Gaussian incoherent resonance, deriving from LauAbsIncohRes - Small changes to various other classes to enable incoherent terms * Fixed small bug in LauMagPhaseCoeffSet which could hang if phase is exactly pi or -pi * Added charged version of the BelleNR resonances to LauResonanceMaker * Updated parameters in LauConstants to match PDG 2014 14th July 2014 Thomas Latham * Add intial support for fully-symmetric final states such as B0 -> KS KS KS - Performs the symmetrisation of the signal model - Background (and efficiency) histogram classes need some work if the user wants to provide folded histograms 8th July 2014 Daniel Craik * Add class for model-independent partial wave - Uses splines to produce a smooth amplitude from a set of magnitude and phase values at given invariant masses - The individual magnitudes and phases can be floated in the fit 16th June 2014 Thomas Latham * Allow floating of resonance parameters in simultaneous fits 13th June 2014 Thomas Latham * Fix bug in LauResonanceInfo cloning method, where the width parameter was given a clone of the mass 10th June 2014 Thomas Latham * Add new function to allow sharing of resonance parameters between components that are not charged conjugates, e.g. LASS_BW and LASS_NR 9th June 2014 Thomas Latham and Daniel Craik * Fix bug in the new integration scheme - Was not accounting for cases where several resonances share a floating parameter - Meant that the integrals and caches for that resonance were not being updated * Introduce a change in the implementation of the helicity flip for neutral parent decays - Prior to this change the helicity was flipped for any neutral resonance in the decay of a neutral particle. - Now the flip no longer occurs in flavour-specific decays (such as Bs0 -> D0bar K- pi+ or B0 -> K+ pi- pi0) since it is only required in flavour-conjugate modes (such as B0 -> KS pi+ pi-). - This does not affect any physical results but it does contribute a pi phase flip to some odd-spin resonances (for example K*(892)0 in Bs0->D0barKpi). - Therefore results are not necessarily comparable between fits run before and after this changeset. - This change will first be released in v3r0. === ## Laura++ v2r2 5th June 2014 Thomas Latham * Fix issue in asymmetric efficiency histogram errors - Fluctuation of bins was incorrectly sampling - assumed area each side of peak was the same 5th June 2014 Thomas Latham (in branch for release in v3r0) * Introduce intelligent calculation of amplitudes during recalculation of integrals and recaching of data points - Floating resonance parameters is now much more efficient * Make resonance parameters second-stage, also improves fit timing when floating them 3rd June 2014 Rafael Coutinho * Implement generation of toy MC from fit results in fitSlave 27th May 2014 Thomas Latham (in branch for release in v3r0) * Complete audit of special functions * Remove unncessary LauAbsDPDynamics base class and move all functionality into LauIsobarDynamics 20th May 2014 Daniel Craik (in branch for release in v3r0) * Add support for K*_0(1430) and a_0(980) to LauFlatteRes 16th-19th May 2014 Thomas Latham and Daniel Craik (in branch for release in v3r0) * Update all other lineshapes so that their parameters can float - The only resonance parameters that now cannot float are the Blatt-Weisskopf barrier factor radii 15th May 2014 Thomas Latham (in branch for release in v3r0) * Change the mechanism for getting floating resonance parameters into the fit - Moved from LauResonanceMaker to the resonances themselves - Lays some groundwork for improving the efficiency of recalculating the integrals - LauBelleNR and LauBelleSymNR lineshape parameters can now be floated 13th May 2014 Daniel Craik (in branch for release in v3r0) * Fix bug where illegal characters were being propagated from resonance names into TBranch names 6th May 2014 Thomas Latham (in branch for release in v3r0) * Provide accessors for mass and width parameters 5th May 2014 Louis Henry * Fix compilation problem by making LauDatabasePDG destructor virtual 4th May 2014 Thomas Latham * Provide a new argument to LauSimpleFitModel::splitSignalComponent and LauCPFitModel::splitSignalComponent to allow fluctuation of the bins on the SCF fraction histogram 29th April 2014 Thomas Latham * Fix bug in the determination of the integration scheme - Nearby narrow resonances caused problems if their "zones" overlap - These zones are now merged together 29th April 2014 Thomas Latham (in branch for release in v3r0) * Some improvments to integration scheme storage 26th April 2014 Juan Otalora (in branch for release in v3r0) * Make integation scheme fixed after first determination - is stored in a new class LauDPPartialIntegralInfo - used on subsequent re-evaluations of the integrals 23rd April 2014 Thomas Latham * Attempt to improve clarity of LauIsobarDynamics::addResonance function - the 3rd argument is now an enumeration of the various resonance models - removed the optional arguments regarding the change of mass, width & spin - the same functionality can be obtained by using the returned pointer and calling changeResonance - the resonance name now only affects the lineshape in the LauPolNR case - the BelleSymNR / TaylorNR choice is now made in the 3rd argument - similarly for the BelleNR / (newly introduced) PowerLawNR choice * Add new PowerLawNR nonresonant model (part of LauBelleNR) * All examples updated to use new interface 23rd April 2014 Thomas Latham * Address issue of setting values of resonance parameters for all models - decided to do away with need to have LauIsobarDynamics know everything - LauIsobarDynamics::addResonance now returns a pointer to LauAbsResonance - parameters can be changed through LauAbsResonance::setResonanceParameter - LauIsobarDynamics still knows about Blatt-Weisskopf factors - better to only need to set this once - Update GenFit3pi example to demonstrate mechanism 22nd April 2014 Thomas Latham * Allow Gaussian constraints to be added in simultaneous fitting - constraints will be ignored by the slaves - those added directly to fit parameters will be propogated to the master and handled there - those on combinations of parameters should be added in the master process 22nd April 2014 Mark Whitehead * Update Laura to cope with resonances of spin 4 and spin 5 - Zemach spin terms added to src/LauAbsResonance.cc - BW barrier factors added to src/LauRelBreitWignerRes.cc 19th April 2014 Daniel Craik * Add LauWeightedSumEffModel which gives an efficiency model from the weighted sum of several LauEffModel objects. * Added pABC, LauAbsEffModel, for LauEffModel and LauWeightedSumEffModel. * Various classes updated to use pointers to LauAbsEffModel instead of LauEffModel. 15th April 2014 Daniel Craik * Enable LauEfficiencyModel to contain several Lau2DAbsDP objects with the total efficiency calculated as the product. 10th April 2014 Mark Whitehead * Fix an issue with the likelihood penalty term for Gaussian constraints - Factor two missing in the denominator - New penalty term is: ( x-mean )^2 / 2*(width^2) 4th April 2014 Thomas Latham * Add storage of fit fractions that have not been efficiency corrected === ## Laura++ v2r1 1st April 2014 Thomas Latham * Fix issue in LauFitter that prevents compilation with g++ 4.8 - Missing virtual destructor - Take opportunity to audit other special functions 31st March 2014 Mark Whitehead (in branch for release in v2r1) * Added an efficiency branch to the ntuple produced for toy data samples - Both LauSimpleFitModel and LauCPFitModel updated 28th March 2014 Daniel Craik (in branch for release in v2r2) * Added support for asymmetric errors to Lau2DHistDP, Lau2DSplineDP and LauEffModel. 27th March 2014 Daniel Craik * Changed histogram classes to use seeded random number generator for fluctuation and raising or lowering of bins and updated doxygen. 20th March 2014 Mark Whitehead (in branch for release in v2r1) * Added the ability to add Gaussian contraints to LauFormulaPars of fit parameters - User supplies the information but the LauFormulaPar is constructed behind the scenes 18th March 2014 Thomas Latham * Improve behaviour of toy generation from fit results 13th March 2014 Juan Otalora (in branch for release in v3r0) * Extended ability to float mass and width to other resonance lineshapes (Flatte, LASS and G-S) 11th March 2014 Mark Whitehead (in branch for release in v2r1) * Added the functionality to make LauFormulaPars usable in fits - Added a new class LauAbsRValue which LauParameter and LauFormularPar inherit from - Many files updated to accept LauAbsRValues instead of LauParameters * Fairly major clean up of obsolete functions in LauAbsPdf - Only LauLinearPdf used any of them, this has now been updated 10th March 2014 Thomas Latham (in branch for release in v3r0) * First attempt at floating resonance parameters (work mostly from Juan) - Only works for RelBW lineshape - Can only float mass and width - Works nicely! - Still needs much work to generalise and make more efficient === ## Laura++ v2r0 8th March 2014 Thomas Latham * Some additional functionality for the CoeffSet classes: - allow the parameter values to be set (optionally setting the initial and generated values as well) - allow the parameters to be set to float or to be fixed in the fit These are needed when cloning but wanting some of the parameters to have different values and/or floating behaviour from the cloned set. * Improve the printout of the setting of the coefficient values in the fit models and the creation of resonances * Add LauFlatNR for the unform NR model - ends its rather strange special treatment * Fix bug setting resAmpInt to 0 for LauPolNR * Many other improvements to the info/warning/error printouts * Modify GenFitBelleCPKpipi example to demonstrate cloning in action * Add -Werror to compiler flags (treats warnings as errors) 5th March 2014 Thomas Latham * Some improvements to LauPolNR to speed up amplitude calculation 2nd March 2014 Thomas Latham * A number of updates to the CoeffSet classes: - allow specification of the basename just after construction (before being given to the fit model) - allow configuration of the parameter fit ranges (through static methods of base class) - more adaptable cloning of the parameters (e.g. can only clone phase but allow magnitude to float independently) - allow CP-violating parameters to be second-stage in Belle and CLEO formats * Some improvements to the Doxygen and runtime information printouts 20th February 2014 Louis Henry * Add LauPolNR - class for modelling the nonresonant contribution based on BaBar 3K model (arXiv:1201.5897) 6th February 2014 Thomas Latham * Correct helicity convention information in Doxygen for LauKinematics === ## Laura++ v1r2 5th February 2014 Thomas Latham * Add rule to the Makefile that creates a rootmap file for the library 4th February 2014 Daniel Craik * Fixed bug in Lau2DSplineDPPdf - normalisation was not being calculated * Added out-of-range warning in LauBkgndDPModel and supressed excessive warnings 3rd February 2014 Mark Whitehead (in branch for release in v2r0) * Added a new class to allow parameters to be a function of other parameters - inc/LauFormulaPar.hh - src/LauFormulaPar.cc 28th January 2014 Daniel Craik * Improved out-of-range efficiency warnings in LauEffModel and supressed excessive errors * Modified LauIsobarDynamics to allow LASS parameters to be configured for LauLASSBWRes and LauLASSNRRes 27th January 2014 Daniel Craik * Added spline interpolation to DP backgrounds - Added Lau2DSplineDPPdf which uses a spline to model a normalised PDF across a DP - Added pABC, Lau2DAbsDPPdf, for Lau2DHistDPPdf and Lau2DSplineDPPdf and moved common code in Lau2DHistDPPdf and Lau2DSplineDPPdf into ABC Lau2DAbsHistDPPdf - LauBkgndDPModel, modified to use Lau2DAbsDPPdf instead of Lau2DHistDPPdf - setBkgndSpline method added to LauBkgndDPModel to allow use of splines 22nd January 2014 Thomas Latham * Improve some error checks and corresponding warning messages in LauCPFitModel::setSignalDPParameters 16th January 2014 Thomas Latham * Add LauRealImagCPCoeffSet, which provides an (x,y), (xbar,ybar) way of parametrising the complex coefficients. * Try to improve timing in the *CoeffSet classes by making the complex coeffs into member variables. 20th December 2013 Daniel Craik * Added Lau2DCubicSpline which provides cubic spline interpolation of a histogram - Added Lau2DSplineDP which uses a spline to model variation across a DP (eg efficiency) - Added pABC, Lau2DAbsDP, for Lau2DHistDP and Lau2DSplineDP and moved common code in Lau2DHistDP and Lau2DSplineDP into ABC Lau2DAbsHistDP - LauEffModel, LauDPDepSumPdf and LauDPDepMapPdf modified to use Lau2DAbsDP instead of Lau2DHistDP - setEffSpline method added to LauEffModel and useSpline flag added to constructor for LauDPDepSumPdf to allow use of splines 18th December 2013 Mark Whitehead (in branch for release in v2r0) * Added functionality to include Gaussian constraints on floated parameters in the fit. The files updated are: - inc/LauAbsFitModel.hh - inc/LauParameter.hh - src/LauAbsFitModel.cc - src/LauParameter.cc 5th December 2013 Thomas Latham * Fix small bug in GenFitKpipi example where background asymmetry parameter had its limits the wrong way around 4th December 2013 Daniel Craik * Updated 2D chi-squared code to use adaptive binning. 3rd December 2013 Thomas Latham * Generalise the Makefile in the examples directory - results in minor changes to the names of 3 of the binaries 3rd December 2013 Thomas Latham (in branch for release in v2r0) * Have the master save an ntuple with all fitter parameters and the full correlation matrix information. 29th November 2013 Thomas Latham * Fixed bug in ResultsExtractor where the output file was not written 29th November 2013 Thomas Latham (in branch for release in v2r0) * Allow the slave ntuples to store the partial covariance matrices in the simultaneous fitting 26th November 2013 Thomas Latham (in branch for release in v2r0) * Added first version of the simultaneous fitting framework === ## Laura++ v1r1p1 22nd November 2013 Thomas Latham * Fixed bug in LauCPFitModel where values of q = -1 extra PDFs were used regardless of the event charge. === ## Laura++ v1r1 20th November 2013 Mark Whitehead * Changed convention for the barrier factors, swapping from p* to p. This seems to give more physically reasonable results. The files updated are: - src/LauGounarisSakuraiRes.cc - src/LauRelBreitWignerRes.cc 18th October 2013 Thomas Latham * Fix dependency problem in Makefile 8th October 2013 Thomas Latham * Some fixes to yield implementation * Minor bug fix in DP background histogram class 7th October 2013 Mark Whitehead * Update to accept the yields and yield asymmetries as LauParameters. All examples have been updated to reflect this change. This updated the following files: - inc/LauCPFitModel.hh - inc/LauSimpleFitModel.hh - inc/LauAbsFitModel.hh - src/LauCPFitModel.cc - src/LauSimpleFitModel.cc * Addition of the following particles to src/LauResonanceMaker.cc Ds*+-, Ds0*(2317)+-, Ds2*(2573)+-, Ds1*(2700)+- and Bs*0 === ## Laura++ v1r0 13th September 2013 Thomas Latham * Initial import of the package into HEPforge diff --git a/inc/Lau1DCubicSpline.hh b/inc/Lau1DCubicSpline.hh index 95d0241..bf3ee8b 100644 --- a/inc/Lau1DCubicSpline.hh +++ b/inc/Lau1DCubicSpline.hh @@ -1,206 +1,205 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau1DCubicSpline.hh \brief File containing declaration of Lau1DCubicSpline class. */ /*! \class Lau1DCubicSpline \brief Class for defining a 1D cubic spline based on a set of knots. Class for defining a 1D cubic spline based on a set of knots. Interpolation between the knots is performed either by one of two types of cubic spline (standard or Akima) or by linear interpolation. The splines are defined by a piecewise cubic function which, between knots i and i+1, has the form f_i(x) = (1 - t)*y_i + t*y_i+1 + t*(1 - t)(a*(1 - t) + b*t) where t = (x - x_i)/(x_i+1 - x_i), a = k_i *(x_i+1 - x_i) - (y_i+1 - y_i), b = -k_i+1*(x_i+1 - x_i) + (y_i+1 - y_i) and k_i is (by construction) the first derivative at knot i. f(x) and f'(x) are continuous at the internal knots by construction. For the standard splines, f''(x) is required to be continuous at all internal knots placing n-2 constraints on the n parameters, k_i. The final two constraints are set by the boundary conditions. At each boundary, the function may be: (i) Clamped : f'(x) = C at the last knot (ii) Natural : f''(x) = 0 at the last knot (iii) Not a knot : f'''(x) continuous at the second last knot The algorithms used in these splines can be found on: http://en.wikipedia.org/wiki/Spline_interpolation#Algorithm_to_find_the_interpolating_cubic_spline http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm For the Akima splines, the values of k_i are determined from the slopes of the four nearest segments (a_i-1, a_i, a_i+1 and a_i+2) as k_i = ( | a_i+2 - a_i+1 | a_i + | a_i - a_i-1 | a_i+1 ) / ( | a_i+2 - a_i+1 | + | a_i - a_i-1 | ) and as k_i = ( a_i + a_i+1 ) / 2 in the special case a_i-1 == a_i != a_i+1 == a_i+2. Boundary conditions are specified by the relations a_2 - a_1 = a_1 - a_0 = a_0 - a_-1 and a_n-1 - a_n-2 = a_n - a_n-1 = a_n+1 - a_n The algorithms used in these splines can be found in: J.ACM vol. 17 no. 4 pp 589-602 */ #ifndef LAU_1DCUBICSPLINE #define LAU_1DCUBICSPLINE #include #include "Rtypes.h" class Lau1DCubicSpline { public: //! Define the allowed interpolation types enum LauSplineType { StandardSpline, /*!< standard cubic splines with f''(x) continuous at all internal knots */ AkimaSpline, /*!< Akima cubic splines with f'(x) at each knot defined locally by the positions of only five knots */ LinearInterpolation /*! Linear interpolation between each pair of knots */ }; //! Define the allowed boundary condition types /*! These are only supported by standard splines */ enum LauSplineBoundaryType { Clamped, /*!< clamped boundary - f'(x) = C */ Natural, /*!< natural boundary - f''(x) = 0 */ NotAKnot /*!< 'not a knot' boundary - f'''(x) continuous at second last knot */ }; //! Constructor /*! /param [in] xs the x-values of the knots /param [in] ys the y-values of the knots /param [in] leftBound the left-hand boundary condition /param [in] rightBound the right-hand boundary condition /param [in] dydx0 the gradient at the left-hand boundary of a clamped spline /param [in] dydxn the gradient at the right-hand boundary of a clamped spline */ Lau1DCubicSpline(const std::vector& xs, const std::vector& ys, LauSplineType type = Lau1DCubicSpline::StandardSpline, LauSplineBoundaryType leftBound = Lau1DCubicSpline::NotAKnot, LauSplineBoundaryType rightBound = Lau1DCubicSpline::NotAKnot, Double_t dydx0 = 0.0, Double_t dydxn = 0.0); //! Destructor virtual ~Lau1DCubicSpline(); //! Evaluate the function at given point /*! \param [in] x the x-coordinate \return the value of the spline at x */ Double_t evaluate(Double_t x) const; //! Update the y-values of the knots /*! \param [in] ys the y-values of the knots */ void updateYValues(const std::vector& ys); //! Update the type of interpolation to perform /*! \param [in] type the type of interpolation */ void updateType(LauSplineType type); //! Update the boundary conditions for the spline /*! /param [in] leftBound the left-hand boundary condition /param [in] rightBound the right-hand boundary condition /param [in] dydx0 the gradient at the left-hand boundary of a clamped spline /param [in] dydxn the gradient at the right-hand boundary of a clamped spline */ void updateBoundaryConditions(LauSplineBoundaryType leftBound, LauSplineBoundaryType rightBound, Double_t dydx0 = 0.0, Double_t dydxn = 0.0); private: //! Copy constructor - not implemented Lau1DCubicSpline( const Lau1DCubicSpline& rhs ); //! Copy assignment operator - not implemented Lau1DCubicSpline& operator=(const Lau1DCubicSpline& rhs); //! Initialise the class void init(); //! Calculate the first derivative at each knot void calcDerivatives(); //! Calculate the first derivatives according to the standard method void calcDerivativesStandard(); //! Calculate the first derivatives according to the Akima method void calcDerivativesAkima(); //! The number of knots in the spline const UInt_t nKnots_; //! The x-value at each knot std::vector x_; //! The y-value at each knot std::vector y_; //! The first derivative at each knot std::vector dydx_; //! The 'a' coefficients used to determine the derivatives std::vector a_; //! The 'b' coefficients used to determine the derivatives std::vector b_; //! The 'c' coefficients used to determine the derivatives std::vector c_; //! The 'd' coefficients used to determine the derivatives std::vector d_; //! The type of interpolation to be performed LauSplineType type_; //! The left-hand boundary condition on the spline LauSplineBoundaryType leftBound_; //! The right-hand boundary condition on the spline LauSplineBoundaryType rightBound_; //! The gradient at the left boundary for a clamped spline Double_t dydx0_; //! The gradient at the right boundary for a clamped spline Double_t dydxn_; - ClassDef(Lau1DCubicSpline, 0); // Class for defining a 1D cubic spline }; #endif diff --git a/inc/Lau1DHistPdf.hh b/inc/Lau1DHistPdf.hh index e075124..840a1cb 100644 --- a/inc/Lau1DHistPdf.hh +++ b/inc/Lau1DHistPdf.hh @@ -1,136 +1,135 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau1DHistPdf.hh \brief File containing declaration of Lau1DHistPdf class. */ /*! \class Lau1DHistPdf \brief Class for defining a 1D histogram PDF. Class for defining a 1D histogram PDF. Employs linear interpolation to get the PDF value based on how far away a point is from nearby bin centres. The returned values are normalised to the total area. */ #ifndef LAU_1DHIST_PDF #define LAU_1DHIST_PDF #include "LauAbsPdf.hh" class TH1; class Lau1DHistPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] hist the 1D histogram from which the PDF should be constructed \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. */ Lau1DHistPdf(const TString& theVarName, const TH1* hist, Double_t minAbscissa, Double_t maxAbscissa, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE); //! Destructor virtual ~Lau1DHistPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics (not strictly required in this case since PDF has no DP dependence) */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Fluctuate the histogram bin contents in accorance with their errors void doBinFluctuation(); //! Check the normalisation calculation void checkNormalisation(); //! Get the bin content from the histogram /*! \param [in] bin the bin number \return the bin content */ Double_t getBinHistValue(Int_t bin) const; //! Perform the interpolation (unnormalised) /*! \param [in] x the abscissa value \return the unnormalised PDF value */ Double_t interpolate(Double_t x) const; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the abscissa value \return the normalised PDF value */ Double_t interpolateNorm(Double_t x) const; private: //! Copy constructor (not implemented) Lau1DHistPdf(const Lau1DHistPdf& rhs); //! Copy assignment operator (not implemented) Lau1DHistPdf& operator=(const Lau1DHistPdf& rhs); //! The underlying histogram TH1* hist_; //! Control boolean for using the linear interpolation Bool_t useInterpolation_; //! Control boolean for performing the fluctuation of the histogram bin contents Bool_t fluctuateBins_; //! The number of bins in the histogram Int_t nBins_; //! The histogram axis minimum Double_t axisMin_; //! The histogram axis maximum Double_t axisMax_; //! The histogram axis range Double_t axisRange_; - ClassDef(Lau1DHistPdf,0) // 1D histogram pdf class }; #endif diff --git a/inc/Lau2DAbsDP.hh b/inc/Lau2DAbsDP.hh index 723f149..1d26bb7 100644 --- a/inc/Lau2DAbsDP.hh +++ b/inc/Lau2DAbsDP.hh @@ -1,74 +1,73 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsDP.hh \brief File containing declaration of Lau2DAbsDP class. */ /*! \class Lau2DAbsDP \brief Pure abstract base class for defining a variation across a 2D DP. Pure abstract base class for defining an unnormalised variation across a 2D DP. */ #ifndef LAU_2DABS_DP #define LAU_2DABS_DP #include "Rtypes.h" class Lau2DAbsDP { public: //!Constructor Lau2DAbsDP() {} //! Destructor virtual ~Lau2DAbsDP() {} //! Perform the interpolation /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the interpolated histogram value */ virtual Double_t interpolateXY(Double_t x, Double_t y) const=0; //! Determine whether the histogram is defined in the square DP /* \return kTRUE if the square DP is being used, kFALSE otherwise */ virtual Bool_t usingSquareDP() const=0; private: //! Copy constructor - not implemented Lau2DAbsDP( const Lau2DAbsDP& rhs ); //! Copy assignment operator - not implemented Lau2DAbsDP& operator=(const Lau2DAbsDP& rhs); - ClassDef(Lau2DAbsDP,0) // Abstract base class for 2D DP variation }; #endif diff --git a/inc/Lau2DAbsDPPdf.hh b/inc/Lau2DAbsDPPdf.hh index a8b5952..751b912 100644 --- a/inc/Lau2DAbsDPPdf.hh +++ b/inc/Lau2DAbsDPPdf.hh @@ -1,81 +1,80 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsDPPdf.hh \brief File containing declaration of Lau2DAbsDPPdf class. */ /*! \class Lau2DAbsDPPdf \brief Pure abstract base class for defining a variation across a 2D DP. Pure abstract base class for defining a normalised variation across a 2D DP. */ #ifndef LAU_2DABS_DP_PDF #define LAU_2DABS_DP_PDF #include "Rtypes.h" class Lau2DAbsDPPdf { public: //! Constructor Lau2DAbsDPPdf() {} //! Destructor virtual ~Lau2DAbsDPPdf() {} //! Retrieve maximum height virtual Double_t getMaxHeight() const=0; //! Retrieve PDF normalisation virtual Double_t getHistNorm() const=0; //! Perform the interpolation (unnormalised) /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the unnormalised PDF value */ virtual Double_t interpolateXY(Double_t x, Double_t y) const=0; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the x-axis abscissa value \param [in] y the y-axis abscissa value \return the normalised PDF value */ virtual Double_t interpolateXYNorm(Double_t x, Double_t y) const=0; private: //! Copy constructor - not implemented Lau2DAbsDPPdf( const Lau2DAbsDPPdf& rhs ); //! Copy assignment operator - not implemented Lau2DAbsDPPdf& operator=(const Lau2DAbsDPPdf& rhs); - ClassDef(Lau2DAbsDPPdf,0) // Abstract base class for 2D DP variation }; #endif diff --git a/inc/Lau2DAbsHistDP.hh b/inc/Lau2DAbsHistDP.hh index 3f6446e..f543e67 100644 --- a/inc/Lau2DAbsHistDP.hh +++ b/inc/Lau2DAbsHistDP.hh @@ -1,146 +1,145 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDP.hh \brief File containing declaration of Lau2DAbsHistDP class. */ /*! \class Lau2DAbsHistDP \brief Abstract base class for defining a variation across a 2D DP based on a histogram. Abstract base class for defining an unnormalised variation across a 2D DP based on a histogram. Contains helper methods to vary bin contents in the input histogram within uncertainties and scale the input histogram to match a given average value. The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP and one half can be used to describe symmetric DPs. */ #ifndef LAU_2DABSHIST_DP #define LAU_2DABSHIST_DP #include "Lau2DAbsDP.hh" class TH2; class LauDaughters; class LauKinematics; class Lau2DAbsHistDP : public Lau2DAbsDP { public: //! Constructor /*! \param [in] daughters the daughter particles \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DAbsHistDP(const LauDaughters* daughters, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Copy constructor //Lau2DAbsHistDP( const Lau2DAbsHistDP& rhs ); //! Destructor virtual ~Lau2DAbsHistDP(); //! Perform the interpolation /*! \param [in] x the x-axis value \param [in] y the y-axis value \return the interpolated histogram value */ virtual Double_t interpolateXY(Double_t x, Double_t y) const=0; //! Determine whether the histogram is defined in the square DP /* \return kTRUE if the square DP is being used, kFALSE otherwise */ virtual Bool_t usingSquareDP() const { return squareDP_; }; protected: //! Fluctuate the contents of each histogram bin independently, in accordance with their errors /*! \param [in,out] hist the histogram */ void doBinFluctuation(TH2* hist); //! Fluctuate the contents of each histogram bin independently, in accordance with their errors /*! \param [in,out] hist the histogram \param [in] errorHi the histogram containing the upper uncertainties on the bins \param [in] errorLo the histogram containing the lower uncertainties on the bins */ void doBinFluctuation(TH2* hist, const TH2* errorHi, const TH2* errorLo); //! Rescale the histogram bin contents based on the desired average efficiency and its uncertainty /*! The new average is sampled from a Gaussian distribution G(x;avEff,avEffError). The histogram is then rescaled according to newAvg/oldAvg. \param [in,out] hist the histogram \param [in] avEff the desired average efficiency \param [in] avEffError the error on that efficiency */ void raiseOrLowerBins(TH2* hist, const Double_t avEff, const Double_t avEffError); //! Compute the average bin content for bins within the kinematic boundary /*! This method just uses the raw bin contents with no interpolation \param [in] hist the histogram \return the average value over the DP */ Double_t computeAverageContents(const TH2* hist) const; //! Check whether the given co-ordinates are within the kinematic boundary /*! \param [in] x the x co-ordinate \param [in] y the y co-ordinate \return true if the co-ordinates are within the kinematic boundary, otherwise false */ Bool_t withinDPBoundaries(Double_t x, Double_t y) const; //! If only using the upper half of the (symmetric) DP then transform into the correct half /*! \param [in,out] x the x co-ordinate \param [in,out] y the y co-ordinate */ void getUpperHalf(Double_t& x, Double_t& y) const; private: //! Copy constructor - not implemented Lau2DAbsHistDP( const Lau2DAbsHistDP& rhs ); //! Copy assignment operator - not implemented Lau2DAbsHistDP& operator=(const Lau2DAbsHistDP& rhs); //! Kinematics used to check events are within DP boundary const LauKinematics* kinematics_; //! Boolean for using the upper half of DP Bool_t upperHalf_; //! Boolean for using square DP variables Bool_t squareDP_; - ClassDef(Lau2DAbsHistDP,0) // Abstract base class for 2D DP variations based on a histogram }; #endif diff --git a/inc/Lau2DAbsHistDPPdf.hh b/inc/Lau2DAbsHistDPPdf.hh index badc37e..0d9767d 100644 --- a/inc/Lau2DAbsHistDPPdf.hh +++ b/inc/Lau2DAbsHistDPPdf.hh @@ -1,163 +1,162 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDPPdf.hh \brief File containing declaration of Lau2DAbsHistDPPdf class. */ /*! \class Lau2DAbsHistDPPdf \brief Abstract base class for defining a variation across a 2D DP based on a histogram. Abstract base class for defining a normalised variation across a 2D DP based on a histogram. The returned values are normalised to the total area. The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP and one half can be used to describe symmetric DPs. */ #ifndef LAU_2DABSHIST_DP_PDF #define LAU_2DABSHIST_DP_PDF #include "Lau2DAbsDPPdf.hh" class TH2; class LauKinematics; class LauVetoes; class Lau2DAbsHistDPPdf : public Lau2DAbsDPPdf { public: //! Constructor /*! \param [in] kinematics the current DP kinematics \param [in] vetoes the vetoes within the DP \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DAbsHistDPPdf(LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Destructor virtual ~Lau2DAbsHistDPPdf(); //! Retrieve maximum height of the PDF /*! \return the maximum height */ Double_t getMaxHeight() const {return maxHeight_;} //! Retrieve PDF normalisation /*! \return the normalisation factor */ virtual Double_t getHistNorm() const=0; //! Perform the interpolation (unnormalised) /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the unnormalised PDF value */ virtual Double_t interpolateXY(Double_t x, Double_t y) const=0; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the x-axis abscissa value \param [in] y the y-axis abscissa value \return the normalised PDF value */ virtual Double_t interpolateXYNorm(Double_t x, Double_t y) const=0; protected: //! Get the kinematics object /*! \return the kinematics */ const LauKinematics * getKinematics() const {return kinematics_;} //! Get the vetoes object /*! \return the vetoes */ const LauVetoes * getVetoes() const {return vetoes_;} //! Calculate maximum height /*! \param [in,out] hist the histogram */ void calcMaxHeight(TH2* hist); //! Fluctuate the histogram bin contents in accordance with their errors /*! \param [in,out] hist the histogram */ void doBinFluctuation(TH2* hist); //! Check whether the given co-ordinates are within the kinematic boundary /*! \param [in] x the x co-ordinate \param [in] y the y co-ordinate \return true if the co-ordinates are within the kinematic boundary, otherwise false */ Bool_t withinDPBoundaries(Double_t x, Double_t y) const; //! Update the current co-ordinates in the kinematic space /*! \param [in] x the x co-ordinate \param [in] y the y co-ordinate */ void updateKinematics(Double_t x, Double_t y) const; //! If only using the upper half of the (symmetric) DP then transform into the correct half /*! \param [in,out] x the x co-ordinate \param [in,out] y the y co-ordinate */ void getUpperHalf(Double_t& x, Double_t& y) const; private: //! Copy constructor - not implemented Lau2DAbsHistDPPdf( const Lau2DAbsHistDPPdf& rhs ); //! Copy assignment operator - not implemented Lau2DAbsHistDPPdf& operator=(const Lau2DAbsHistDPPdf& rhs); //! DP kinematics LauKinematics* kinematics_; //! Vetos within DP const LauVetoes* vetoes_; //! The maximum height of 2D histogram Double_t maxHeight_; //! Boolean for using the upper half of DP Bool_t upperHalf_; //! Boolean for using square DP variables Bool_t squareDP_; - ClassDef(Lau2DAbsHistDPPdf,0) // Abstract base class for 2D DP variations based on a histogram }; #endif diff --git a/inc/Lau2DCubicSpline.hh b/inc/Lau2DCubicSpline.hh index a93044c..8d67323 100644 --- a/inc/Lau2DCubicSpline.hh +++ b/inc/Lau2DCubicSpline.hh @@ -1,218 +1,217 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DCubicSpline.hh \brief File containing declaration of Lau2DCubicSpline class. */ /*! \class Lau2DCubicSpline \brief Class for defining a 2D cubic spline based on an input histogram Class for defining a 2D cubic spline based on RooBinned2DBicubicBase by Manuel Tobias Schiller (2012-08-29). Smoothly interpolate between bin midpoints of a 2D histogram with equal-sized bins The interpolation function coincides with the saved histogram values in bin midpoints; a cubic interpolation polynomial is used. Bins must all have the same size. The interpolation polynomial in a "cell" between four bin midpoints is: \f[ p(x, y) = \sum_{i=0}^3 \sum_{j=0}^3 a_{ij} x^i y^j \f] The coefficients \f$a_{ij}\f$ are determined by the requirement that function value, first derivatives and the mixed second derivative must agree with that of the binned function at the four bin midpoints at the edges of the cell. Symmetric finite differences are used to approximate these derivatives. For each cell, the coefficients are determined at constuction time. The object also keeps a cache of 2D integrals over complete cells, such that 2D integrations can be done analytically in a reasonably short amount of time. */ #ifndef LAU_2DCUBICSPLINE #define LAU_2DCUBICSPLINE class TH2; class Lau2DCubicSpline { private: //! Length of coefficient record in array enum { NCoeff = 16, CoeffRecLen = 17 }; public: //! Constructor from histogram /*! /param h the histogram */ Lau2DCubicSpline(const TH2& h); //! Destructor virtual ~Lau2DCubicSpline(); //! Evaluate the function at given point /*! \param [in] x the x co-ordinate \param [in] y the y co-ordinate */ virtual Double_t evaluate(Double_t x, Double_t y) const; //! Evaluate analytical integral in x, y, or x and y /*! \param [in] x1 the lower x limit \param [in] x2 the upper x limit \param [in] y1 the lower y limit \param [in] y2 the upper y limit */ virtual Double_t analyticalIntegral(Double_t x1, Double_t x2, Double_t y1, Double_t y2) const; //! Evaluate analytical integral across the whole function virtual Double_t analyticalIntegral() const; private: //! Copy constructor - not implemented Lau2DCubicSpline( const Lau2DCubicSpline& rhs ); //! Copy assignment operator - not implemented Lau2DCubicSpline& operator=(const Lau2DCubicSpline& rhs); //! Number of bins in x axis Int_t nBinsX; //! Number of bins in y axis Int_t nBinsY; //! Bin size in x Double_t binSizeX; //! Bin size in y Double_t binSizeY; //! Minimum x value Double_t xmin; //! Maximum x value Double_t xmax; //! Minimum y value Double_t ymin; //! Maximum y value Double_t ymax; //! Coefficients of interpolation polynomials std::vector coeffs; //! Get contents of a given bin from a histogram /*! \param [in] h the histogram \param [in] xbin the x bin index \param [in] ybin the y bin index \return the bin contents */ Double_t histcont(const TH2& h, Int_t xbin, Int_t ybin) const; //! Get d/dx finite difference in a given bin from a histogram /*! \param [in] h the histogram \param [in] xbin the x bin index \param [in] ybin the y bin index \return the d/dx finite difference */ Double_t dhistdx(const TH2& h, Int_t xbin, Int_t ybin) const; //! Get d/dy finite difference in a given bin from a histogram /*! \param [in] h the histogram \param [in] xbin the x bin index \param [in] ybin the y bin index \return the d/dy finite difference */ Double_t dhistdy(const TH2& h, Int_t xbin, Int_t ybin) const; //! Get d^2/dydx finite difference in a given bin from a histogram /*! \param [in] h the histogram \param [in] xbin the x bin index \param [in] ybin the y bin index \return the d^2/dydx finite difference */ Double_t d2histdxdy(const TH2& h, Int_t xbin, Int_t ybin) const; //! Const access to coefficients /*! \param [in] binx the x bin index \param [in] biny the y bin index \param [in] theCoeff the coefficient index \return the coefficient */ inline const Double_t& coeff(Int_t binx, Int_t biny, Int_t theCoeff) const { return coeffs[theCoeff + CoeffRecLen * (binx + nBinsX * biny)]; } //! Access to coefficients /*! \param [in] binx the x bin index \param [in] biny the y bin index \param [in] theCoeff the coefficient index \return the coefficient */ inline Double_t& coeff(Int_t binx, Int_t biny, Int_t theCoeff) { return coeffs[theCoeff + CoeffRecLen * (binx + nBinsX * biny)]; } //! Evaluate integral over x at a given y from (x1, y) to (x2, y) /*! \param [in] x1 lower x limit \param [in] x2 upper x limit \param [in] y y value \return integral over x */ Double_t evalX(Double_t x1, Double_t x2, Double_t y) const; //! Evaluate integral over y at a given x from (x, y1) to (x, y2) /*! \param [in] x x value \param [in] y1 lower y limit \param [in] y2 upper y limit \return integral over y */ Double_t evalY(Double_t x, Double_t y1, Double_t y2) const; //! Evaluate integral over x and y from (x1, y1) to (x2, y2) /*! \param [in] x1 lower x limit \param [in] x2 upper x limit \param [in] y1 lower y limit \param [in] y2 upper y limit \return integral over x and y */ Double_t evalXY(Double_t x1, Double_t x2, Double_t y1, Double_t y2) const; - ClassDef(Lau2DCubicSpline, 0); // Class for defining a 2D cubic spline based on an input histogram }; #endif diff --git a/inc/Lau2DHistDP.hh b/inc/Lau2DHistDP.hh index 0f125d3..16b453f 100644 --- a/inc/Lau2DHistDP.hh +++ b/inc/Lau2DHistDP.hh @@ -1,150 +1,149 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDP.hh \brief File containing declaration of Lau2DHistDP class. */ /*! \class Lau2DHistDP \brief Class for defining a 2D DP histogram. Class for defining a 2D DP histogram. Employs linear interpolation to get the histogram value based on how far away a point in (x,y) is to nearby bin centres. The returned values are not normalised to the total histogram area (useful for efficiency histograms for example). The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP. */ #ifndef LAU_2DHIST_DP #define LAU_2DHIST_DP #include "Lau2DAbsHistDP.hh" class TH2; class LauDaughters; class LauKinematics; class Lau2DHistDP : public Lau2DAbsHistDP { public: //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] daughters the daughter particles \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] avEffError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DHistDP(const TH2* hist, const LauDaughters* daughters, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t avEffError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] errorHi the 2D DP histogram containing the upper uncertainty \param [in] errorLo the 2D DP histogram containing the lower uncertainty \param [in] daughters the daughter particles \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] avEffError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DHistDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t avEffError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Destructor virtual ~Lau2DHistDP(); //! Perform the interpolation /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the interpolated histogram value */ Double_t interpolateXY(Double_t x, Double_t y) const; protected: //! Get the raw bin content from the histogram /*! \param [in] xBinNo the x-axis bin number \param [in] yBinNo the y-axis bin number \return the bin conent */ Double_t getBinHistValue(Int_t xBinNo, Int_t yBinNo) const; private: //! Copy constructor - not implemented Lau2DHistDP( const Lau2DHistDP& rhs ); //! Copy assignment operator - not implemented Lau2DHistDP& operator=(const Lau2DHistDP& rhs); //! The underlying histogram TH2* hist_; //! The histogram containing the upper errors TH2* errorHi_; //! The histogram containing the lower errors TH2* errorLo_; //! The histogram x-axis minimum Double_t minX_; //! The histogram x-axis maximum Double_t maxX_; //! The histogram y-axis minimum Double_t minY_; //! The histogram y-axis maximum Double_t maxY_; //! The histogram x-axis range Double_t rangeX_; //! The histogram y-axis range Double_t rangeY_; //! The histogram x-axis bin width Double_t binXWidth_; //! The histogram y-axis bin width Double_t binYWidth_; //! The number of bins on the x-axis of the histogram Int_t nBinsX_; //! The number of bins on the y-axis of the histogram Int_t nBinsY_; //! Control boolean for using the linear interpolation Bool_t useInterpolation_; - ClassDef(Lau2DHistDP,0) // 2D Histogram utility class for DP analyses }; #endif diff --git a/inc/Lau2DHistDPPdf.hh b/inc/Lau2DHistDPPdf.hh index 2508c7b..a16fba0 100644 --- a/inc/Lau2DHistDPPdf.hh +++ b/inc/Lau2DHistDPPdf.hh @@ -1,154 +1,153 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDPPdf.hh \brief File containing declaration of Lau2DHistDPPdf class. */ /*! \class Lau2DHistDPPdf \brief Class for defining a 2D DP histogram PDF. Class for defining a 2D DP histogram PDF. Employs linear interpolation to get the histogram value based on how far away a point in (x,y) is to nearby bin centres. The returned values are normalised to the total area. The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP. */ #ifndef LAU_2DHIST_DP_PDF #define LAU_2DHIST_DP_PDF #include "Lau2DAbsHistDPPdf.hh" class TH2; class LauKinematics; class LauVetoes; class Lau2DHistDPPdf : public Lau2DAbsHistDPPdf { public: //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] kinematics the current DP kinematics \param [in] vetoes the vetoes within the DP \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DHistDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Destructor virtual ~Lau2DHistDPPdf(); //! Retrieve PDF normalisation /*! \return the normalisation factor */ Double_t getHistNorm() const {return norm_;} //! Perform the interpolation (unnormalised) /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the unnormalised PDF value */ Double_t interpolateXY(Double_t x, Double_t y) const; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the x-axis abscissa value \param [in] y the y-axis abscissa value \return the normalised PDF value */ Double_t interpolateXYNorm(Double_t x, Double_t y) const; protected: //! Get the bin content from the histogram /*! \param [in] xBinNo the x-axis bin number \param [in] yBinNo the y-axis bin number \return the bin conent */ Double_t getBinHistValue(Int_t xBinNo, Int_t yBinNo) const; //! Calculate the PDF normalisation void calcHistNorm(); //! Check the normalisation calculation void checkNormalisation(); private: //! Copy constructor - not implemented Lau2DHistDPPdf( const Lau2DHistDPPdf& rhs ); //! Copy assignment operator - not implemented Lau2DHistDPPdf& operator=(const Lau2DHistDPPdf& rhs); //! The underlying histogram TH2* hist_; //! The histogram x-axis minimum Double_t minX_; //! The histogram x-axis maximum Double_t maxX_; //! The histogram y-axis minimum Double_t minY_; //! The histogram y-axis maximum Double_t maxY_; //! The histogram x-axis range Double_t rangeX_; //! The histogram y-axis range Double_t rangeY_; //! The histogram x-axis bin width Double_t binXWidth_; //! The histogram y-axis bin width Double_t binYWidth_; //! The histogram x-axis inverse bin width Double_t invBinXWidth_; //! The histogram y-axis inverse bin width Double_t invBinYWidth_; //! The maximum height of 2D histogram Double_t maxHeight_; //! The number of bins on the x-axis of the histogram Int_t nBinsX_; //! The number of bins on the y-axis of the histogram Int_t nBinsY_; //! The histogram normalisation Double_t norm_; //! Control boolean for using the linear interpolation Bool_t useInterpolation_; - ClassDef(Lau2DHistDPPdf,0) // 2D Histogram utility class for DP analyses }; #endif diff --git a/inc/Lau2DHistPdf.hh b/inc/Lau2DHistPdf.hh index fd8a59a..c0f9dc0 100644 --- a/inc/Lau2DHistPdf.hh +++ b/inc/Lau2DHistPdf.hh @@ -1,218 +1,217 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistPdf.hh \brief File containing declaration of Lau2DHistPdf class. */ /*! \class Lau2DHistPdf \brief Class for defining a 2D histogram PDF. Class for defining a 2D histogram PDF. Employs linear interpolation to get the histogram value based on how far away a point is to nearby bin centres. The returned values are normalised to the total area. */ #ifndef LAU_2DHIST_PDF #define LAU_2DHIST_PDF #include "LauAbsPdf.hh" class TH2; class TH1; class Lau1DHistPdf; class Lau2DHistPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarNames the names of the abscissa variables \param [in] hist the 2D histogram from which the PDF should be constructed \param [in] minVals the minimum values of the abscissas \param [in] maxVals the maximum values of the abscissas \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. */ Lau2DHistPdf(const std::vector& theVarNames, const TH2* hist, const LauFitData& minVals, const LauFitData& maxVals, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE); //! Destructor virtual ~Lau2DHistPdf(); //! Get the minimum value of x-axis abscissa Double_t getMinX() const {return minX_;} //! Get the maximum value of x-axis abscissa Double_t getMaxX() const {return maxX_;} //! Get the range of x-axis abscissa values Double_t getRangeX() const {return rangeX_;} //! Get the minimum value of y-axis abscissa Double_t getMinY() const {return minY_;} //! Get the maximum value of y-axis abscissa Double_t getMaxY() const {return maxY_;} //! Get the range of y-axis abscissa values Double_t getRangeY() const {return rangeY_;} //! Cache information from data /*! \param [in] inputData the input data */ virtual void cacheInfo(const LauFitDataTree& inputData); //! Calculate the likelihood (and intermediate info) for a given value of the abscissas /*! \param [in] abscissas the abscissa values */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); //! Calculate the likelihood (and intermediate info) for a given event number /*! \param [in] iEvt event number */ virtual void calcLikelihoodInfo(UInt_t iEvt); //! Get likelihood only for the given variable /*! \param [in] theVarName the variable name (must be one of the two dimensions of this histogram!) \return likelihood value */ virtual Double_t getLikelihood( const TString& theVarName ) const; using LauAbsPdf::getLikelihood; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics (not strictly required in this case since PDF has no DP dependence) */ virtual void calcPDFHeight( const LauKinematics* kinematics ); //! Generate an event from the PDF /*! \param [in] kinematics the current DP kinematics (used to determine the DP position by some PDFs that have dependence on it) \return generated data */ virtual LauFitData generate(const LauKinematics* kinematics); protected: //! Fluctuate the histogram bin contents in accordance with their errors void doBinFluctuation(); //! Check the normalisation calculation void checkNormalisation(); //! Get the bin content from the histogram /*! \param [in] i the x-axis bin number \param [in] j the y-axis bin number \return the bin conent */ Double_t getBinHistValue(Int_t i, Int_t j) const; //! Perform the interpolation (unnormalised) /*! \param [in] x the x-axis abscissa value \param [in] y the y-aixs abscissa value \return the unnormalised PDF value */ Double_t interpolateXY(Double_t x, Double_t y) const; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the x-axis abscissa value \param [in] y the y-axis abscissa value \return the normalised PDF value */ Double_t interpolateXYNorm(Double_t x, Double_t y) const; private: //! Copy constructor (not implemented) Lau2DHistPdf(const Lau2DHistPdf& other); //! Copy assignment operator (not implemented) Lau2DHistPdf& operator=(const Lau2DHistPdf& other); //! The underlying histogram TH2* hist_; //! Projection of histogram x-axis TH1* xProj_; //! Projection of histogram y-axis TH1* yProj_; //! 1D PDF for x variable Lau1DHistPdf* xVarPdf_; //! 1D PDF for y variable Lau1DHistPdf* yVarPdf_; //! x variable name TString xName_; //! y variable name TString yName_; //! The number of bins on the x-axis of the histogram Int_t nBinsX_; //! The number of bins on the y-axis of the histogram Int_t nBinsY_; //! The histogram x-axis minimum Double_t minX_; //! The histogram x-axis maximum Double_t maxX_; //! The histogram y-axis minimum Double_t minY_; //! The histogram y-axis maximum Double_t maxY_; //! The histogram x-axis range Double_t rangeX_; //! The histogram y-axis range Double_t rangeY_; //! The histogram x-axis bin width Double_t binXWidth_; //! The histogram y-axis bin width Double_t binYWidth_; //! The histogram x-axis inverse bin width Double_t invBinXWidth_; //! The histogram y-axis inverse bin width Double_t invBinYWidth_; //! Control boolean for using the linear interpolation Bool_t useInterpolation_; //! Control boolean for performing the fluctuation of the histogram bin contents Bool_t fluctuateBins_; - ClassDef(Lau2DHistPdf,0) // 2D histogram pdf class }; #endif diff --git a/inc/Lau2DSplineDP.hh b/inc/Lau2DSplineDP.hh index a38cf91..5627c47 100644 --- a/inc/Lau2DSplineDP.hh +++ b/inc/Lau2DSplineDP.hh @@ -1,110 +1,109 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDP.hh \brief File containing declaration of Lau2DSplineDP class. */ /*! \class Lau2DSplineDP \brief Class for defining variations across a 2D DP using a spline. Class for defining variations across a 2D DP using a spline. Employs a 2D cubic spline to get the histogram value based on an input histogram. The returned values are not normalised to the total histogram area (useful for efficiency histograms for example). The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP. */ #ifndef LAU_2DSPLINE_DP #define LAU_2DSPLINE_DP #include "Lau2DAbsHistDP.hh" class TH2; class Lau2DCubicSpline; class LauDaughters; class LauKinematics; class Lau2DSplineDP : public Lau2DAbsHistDP { public: //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] daughters the daughter particles \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DSplineDP::raiseOrLowerBins. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] avEffError the error on that efficiency - see Lau2DSplineDP::raiseOrLowerBins \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DSplineDP(const TH2* hist, const LauDaughters* daughters, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t avEffError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] errorHi the 2D DP histogram containing the upper uncertainty \param [in] errorLo the 2D DP histogram containing the lower uncertainty \param [in] daughters the daughter particles \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DSplineDP::raiseOrLowerBins. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] avEffError the error on that efficiency - see Lau2DSplineDP::raiseOrLowerBins \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DSplineDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t avEffError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Destructor virtual ~Lau2DSplineDP(); //! Perform the interpolation /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the interpolated histogram value */ Double_t interpolateXY(Double_t x, Double_t y) const; private: //! Copy constructor - not implemented Lau2DSplineDP( const Lau2DSplineDP& rhs ); //! Copy assignment operator - not implemented Lau2DSplineDP& operator=(const Lau2DSplineDP& rhs); //! A 2D cubic spline generated from the histogram Lau2DCubicSpline* spline_; - ClassDef(Lau2DSplineDP,0) // 2D Spline utility class for DP analyses }; #endif diff --git a/inc/Lau2DSplineDPPdf.hh b/inc/Lau2DSplineDPPdf.hh index 83b0dfd..b104ff2 100644 --- a/inc/Lau2DSplineDPPdf.hh +++ b/inc/Lau2DSplineDPPdf.hh @@ -1,112 +1,111 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDPPdf.hh \brief File containing declaration of Lau2DSplineDPPdf class. */ /*! \class Lau2DSplineDPPdf \brief Class for defining a 2D DP spline PDF. Class for defining a 2D DP spline PDF. Employs a 2D cubic spline to get the histogram value based on an input histogram. The returned values are normalised to the total area. The histogram can be defined in the conventional DP (m13Sq vs m23Sq) or in the square DP. */ #ifndef LAU_2DSPLINE_DP_PDF #define LAU_2DSPLINE_DP_PDF #include "Lau2DAbsHistDPPdf.hh" class TH2; class Lau2DCubicSpline; class LauKinematics; class LauVetoes; class Lau2DSplineDPPdf: public Lau2DAbsHistDPPdf { public: //! Constructor /*! \param [in] hist the 2D DP histogram \param [in] kinematics the current DP kinematics \param [in] vetoes the vetoes within the DP \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors (useful for systematic error evaluation). The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to specify whether the supplied histogram is in square DP coordinates */ Lau2DSplineDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t fluctuateBins = kFALSE, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Destructor virtual ~Lau2DSplineDPPdf(); //! Retrieve PDF normalisation /*! \return the normalisation factor */ Double_t getHistNorm() const {return norm_;} //! Perform the interpolation (unnormalised) /*! \param [in] x the x-axis value \param [in] y the y-aixs value \return the unnormalised PDF value */ Double_t interpolateXY(Double_t x, Double_t y) const; //! Perform the interpolation and divide by the normalisation /*! \param [in] x the x-axis abscissa value \param [in] y the y-axis abscissa value \return the normalised PDF value */ Double_t interpolateXYNorm(Double_t x, Double_t y) const; protected: //! Calculate the PDF normalisation void calcHistNorm(); private: //! Copy constructor - not implemented Lau2DSplineDPPdf( const Lau2DSplineDPPdf& rhs ); //! Copy assignment operator - not implemented Lau2DSplineDPPdf& operator=(const Lau2DSplineDPPdf& rhs); //! The maximum height of 2D histogram Double_t maxHeight_; //! The histogram normalisation Double_t norm_; //! A 2D cubic spline generated from the histogram Lau2DCubicSpline* spline_; - ClassDef(Lau2DSplineDPPdf,0) // 2D Spline utility class for DP analyses }; #endif diff --git a/inc/LauASqMaxFinder.hh b/inc/LauASqMaxFinder.hh index e2ccba5..2f14894 100644 --- a/inc/LauASqMaxFinder.hh +++ b/inc/LauASqMaxFinder.hh @@ -1,94 +1,93 @@ /* Copyright 2022 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauASqMaxFinder.hh \brief File containing declaration of LauASqMaxFinder class. */ #ifndef LAU_ASQ_MAX_FINDER #define LAU_ASQ_MAX_FINDER #include "LauFitObject.hh" #include #include class LauIsobarDynamics; class LauParameter; /*! \class LauASqMaxFinder \brief Class for locating the |A|^2 max for a given model Currently supports finding the |A|^2 max for a LauIsobarDynamics object */ class LauASqMaxFinder : public LauFitObject { public: //! Constructor /*! \param [in] iso the isobar dynamics for which we need to find the maximum |A|^2 value */ explicit LauASqMaxFinder(LauIsobarDynamics& iso); //! Run the minimisation to locate the maximum |A|^2 value /*! \return the maximum |A|^2 value */ Double_t find(); //! 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 */ void setParsFromMinuit(Double_t* par, Int_t npar) override; //! Calculate the new value of the 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() override; private: //! The isobar dynamics for which we need to find the maximum |A|^2 value LauIsobarDynamics& iso_; //! Flag to control printing of warnings if the fit wanders outside the DP Bool_t printMinimisationWarnings_{kTRUE}; //! The fit parameters (owned by us) std::vector> ownedParams_; //! The fit parameters in a form to be passed to the minimiser std::vector params_; - ClassDefOverride(LauASqMaxFinder,0) }; #endif diff --git a/inc/LauAbsBkgndDPModel.hh b/inc/LauAbsBkgndDPModel.hh index 9688409..8066f9e 100644 --- a/inc/LauAbsBkgndDPModel.hh +++ b/inc/LauAbsBkgndDPModel.hh @@ -1,155 +1,154 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsBkgndDPModel.hh \brief File containing declaration of LauAbsBkgndDPModel class. */ /*! \class LauAbsBkgndDPModel \brief The abstract interface for a background Dalitz plot model Class which defines the abstract interface for a background Dalitz plot model */ #ifndef LAU_ABS_BKGND_DP_MODEL #define LAU_ABS_BKGND_DP_MODEL #include "Rtypes.h" class LauDaughters; class LauKinematics; class LauFitDataTree; class LauVetoes; class LauAbsBkgndDPModel { public: //! Destructor virtual ~LauAbsBkgndDPModel() {} //! Initialise the model virtual void initialise() = 0; //! Generate a toy MC event from the model /*! \return success/failure flag */ virtual Bool_t generate() = 0; //! Get likelihood for a given event /*! \param [in] iEvt the event number \return the likelihood value */ virtual Double_t getLikelihood(UInt_t iEvt) = 0; //! Get unnormalised likelihood for a given event /*! \param [in] iEvt the event number \return the unnormalised likelihood value */ virtual Double_t getUnNormValue(UInt_t iEvt) = 0; //! Get PDF normalisation constant /*! \return the PDF normalisation constant */ virtual Double_t getPdfNorm() const = 0; //! Cache the input data and (if appropriate) the per-event likelihood values /*! \param [in] fitDataTree the input data */ virtual void fillDataTree(const LauFitDataTree& fitDataTree) = 0; //! Get the daughter particles /*! \return the daughters */ const LauDaughters* getDaughters() const {return daughters_;} //! Get the daughter particles /*! \return the daughters */ LauDaughters* getDaughters() {return daughters_;} //! Get the Dalitz plot kinematics /*! \return the kinematics */ const LauKinematics* getKinematics() const {return kinematics_;} //! Get the Dalitz plot kinematics /*! \return the kinematics */ LauKinematics* getKinematics() {return kinematics_;} //! Get vetoes in the Dalitz plot /*! \return the vetoes */ const LauVetoes* getVetoes() const {return vetoes_;} //! Get vetoes in the Dalitz plot /*! \return the vetoes */ LauVetoes* getVetoes() {return vetoes_;} protected: //! Constructor /*! \param [in] daughters the daughter particles \param [in] vetoes the vetoes within the Dalitz plot */ LauAbsBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes); //! Set data event number /*! \param [in] iEvt the event number */ virtual void setDataEventNo(UInt_t iEvt) = 0; private: //! Copy constructor (not implemented) LauAbsBkgndDPModel(const LauAbsBkgndDPModel& rhs); //! Copy assignment operator (not implemented) LauAbsBkgndDPModel& operator=(const LauAbsBkgndDPModel& rhs); //! The daughter particles LauDaughters* daughters_; //! Dalitz plot kinematics LauKinematics* kinematics_; //! Vetoes within the Dalitz plot LauVetoes* vetoes_; - ClassDef(LauAbsBkgndDPModel,0) // Abstract DP background model }; #endif diff --git a/inc/LauAbsCoeffSet.hh b/inc/LauAbsCoeffSet.hh index 51af166..f11b03f 100644 --- a/inc/LauAbsCoeffSet.hh +++ b/inc/LauAbsCoeffSet.hh @@ -1,333 +1,332 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsCoeffSet.hh \brief File containing declaration of LauAbsCoeffSet class. */ /*! \class LauAbsCoeffSet \brief Class for defining the abstract interface for complex coefficient classes. Class for defining the abstract interface for complex coefficient classes. Some common code is implemented but most methods are not. */ #ifndef LAU_ABS_COEFF_SET #define LAU_ABS_COEFF_SET #include #include #include "TString.h" class TRandom; class LauComplex; class LauParameter; class LauAbsCoeffSet { public: //! Options for cloning operation enum CloneOption { All, /*!< no special operation, all parameters cloned */ TiePhase, /*!< phase cloned, magnitude free to vary */ TieMagnitude, /*!< magnitude cloned, phase free to vary */ TieRealPart, /*!< real part cloned, imaginary part free to vary */ TieImagPart, /*!< imaginary part cloned, real part free to vary */ TieCPPars /*!< CP-violating parameters cloned, CP-conserving ones free to vary */ }; //! Destructor virtual ~LauAbsCoeffSet(){} //! Retrieve the parameters of the coefficient so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters() = 0; //! Print the current values of the parameters virtual void printParValues() const = 0; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const = 0; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const = 0; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues() = 0; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues() = 0; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff() = 0; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff() = 0; //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) = 0; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp() = 0; //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor by which to multiply the cloned parameters \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0) = 0; //! Retrieve the name of the coefficient set /*! The name should correspond to the name of the resonance in the model. \return the name of the coefficient set */ virtual TString name() const {return name_;} //! Set the name of the coefficient set /*! The name should correspond to the name of the resonance in the model. \param [in] theName the name to set */ virtual void name(const TString& theName) {name_ = theName;} //! Retrieve the base name of the coefficient set /*! The base name is generally of the form "Ai", where i is an integer. This is used in the fit results ntuple. \return the base name of the coefficient set */ virtual const TString& baseName() const {return basename_;} //! Set the base name of the coefficient set /*! The base name is generally of the form "Ai", where i is an integer. This is used in the fit results ntuple. \param [in] theBasename the base name to set */ virtual void baseName(const TString& theBasename) {basename_ = theBasename;} //! Retrieve the index number of the coefficient set /*! \return the index number of the coefficient set */ virtual UInt_t index() const {return index_;} //! Set the index number of the coefficient set /*! \param [in] newIndex the new index */ virtual void index(UInt_t newIndex); //! Set the value of the named parameter /*! \param [in] parName the name of the parameter to adjust \param [in] value the new value for the parameter to take \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setParameterValue(const TString& parName, Double_t value, Bool_t init); //! Set the error of the named parameter /*! This is particularly useful for tuning the step size used by MINUIT \param [in] parName the name of the parameter to adjust \param [in] error the new error value for the parameter to take */ virtual void setParameterError(const TString& parName, Double_t error); //! Set the named parameter to be fixed in the fit /*! \param [in] parName the name of the parameter to adjust */ virtual void fixParameter(const TString& parName); //! Set the named parameter to float in the fit /*! \param [in] parName the name of the parameter to adjust */ virtual void floatParameter(const TString& parName); //! Blind the named parameter /*! See LauBlind documentation for details of blinding procedure \param [in] parName the name of the parameter to adjust \param [in] blindingString the unique blinding string used to seed the random number generator \param [in] width the width of the Gaussian from which the offset should be sampled */ virtual void blindParameter(const TString& parName, const TString& blindingString, const Double_t width); //! Add Gaussian constraint to the named parameter /*! \param [in] parName the name of the parameter to adjust \param [in] mean the mean of the Gaussian constraint \param [in] width the width of the Gaussian constraint */ virtual void addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width); //! Add suffix to the name of the given parameter /*! \param [in] parName the name of the parameter to adjust \param [in] suffix the suffix to add to the parameter name */ virtual void addSuffixToParameterName(const TString& parName, const TString& suffix); //! Set the allowed range for magnitude parameters /*! \param [in] minMag the lower edge of the range \param [in] maxMag the upper edge of the range */ static void setMagnitudeRange(Double_t minMag, Double_t maxMag) { minMagnitude_ = minMag; maxMagnitude_ = maxMag; } //! Set the allowed range for phase parameters /*! \param [in] minPhase the lower edge of the range \param [in] maxPhase the upper edge of the range */ static void setPhaseRange(Double_t minPhase, Double_t maxPhase) { minPhase_ = minPhase; maxPhase_ = maxPhase; } //! Set the allowed range for real/imaginary part parameters /*! \param [in] minPar the lower edge of the range \param [in] maxPar the upper edge of the range */ static void setRealImagRange(Double_t minPar, Double_t maxPar) { minRealImagPart_ = minPar; maxRealImagPart_ = maxPar; } //! Set the allowed range for CP-violating parameters /*! \param [in] minPar the lower edge of the range \param [in] maxPar the upper edge of the range */ static void setCPParRange(Double_t minPar, Double_t maxPar) { minDelta_ = minPar; maxDelta_ = maxPar; } //! Set the randomiser /*! Set the random number generator to use for randomising parameter starting values. Will default to LauRandom::zeroSeedRandom if not explicitly supplied via this function. \param [in] randomiser the random number generator to use for randomising parameter starting values */ static void setRandomiser(TRandom* randomiser) { randomiser_ = randomiser; } //! Access the randomiser /*! \return the random number generator to use for randomising parameter starting values */ static TRandom* getRandomiser(); protected: //! Constructor /*! \param [in] theName the name of the coefficient set \param [in] theBaseName the single character base for the parameter names */ LauAbsCoeffSet(const TString& theName, const TString& theBaseName = "A"); //! Find the parameter with the given name /*! \param [in] parName the name of the parameter to be found return the retrieved parameter */ LauParameter* findParameter(const TString& parName); //! Prepend the base name and index to the name of a parameter /*! \param [in,out] par pointer to the parameter \param [in] oldBaseName the old base name, which might need to be removed before adding the new one */ virtual void adjustName(LauParameter* par, const TString& oldBaseName); //! Minimum allowed value of magnitude parameters static Double_t minMagnitude_; //! Maximum allowed value of magnitude parameters static Double_t maxMagnitude_; //! Minimum allowed value of phase parameters static Double_t minPhase_; //! Maximum allowed value of phase parameters static Double_t maxPhase_; //! Minimum allowed value of real/imaginary part parameters static Double_t minRealImagPart_; //! Maximum allowed value of real/imaginary part parameters static Double_t maxRealImagPart_; //! Minimum allowed value of CP-violating real/imaginary part parameters static Double_t minDelta_; //! Maximum allowed value of CP-violating real/imaginary part parameters static Double_t maxDelta_; //! Copy constructor /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet(const LauAbsCoeffSet& rhs); //! Copy assignment operator /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet& operator=(const LauAbsCoeffSet& rhs); private: //! Random number generator to use for randomising parameter starting values static TRandom* randomiser_; //! The name of the coefficient set TString name_; //! The base name of the coefficient set TString basename_; //! The index number of the coefficient set UInt_t index_; - ClassDef(LauAbsCoeffSet, 0) }; #endif diff --git a/inc/LauAbsEffModel.hh b/inc/LauAbsEffModel.hh index aeaae13..a91b17f 100644 --- a/inc/LauAbsEffModel.hh +++ b/inc/LauAbsEffModel.hh @@ -1,89 +1,88 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsEffModel.hh \brief File containing declaration of LauAbsEffModel class. */ /*! \class LauAbsEffModel \brief Pure abstract base class for defining the efficiency description across the signal Dalitz plot. Pure abstract base class for defining the efficiency description across the signal Dalitz plot. The efficiency variation is defined in terms of x = m_13^2, y = m_23^2 for the Dalitz plot (default) or x = m', y = theta' for the square Dalitz plot */ #ifndef LAUABSEFFMODEL #define LAUABSEFFMODEL #include "Rtypes.h" class LauDaughters; class LauKinematics; class LauAbsEffModel { public: //! Constructor LauAbsEffModel() {} //! Destructor virtual ~LauAbsEffModel() {} //! Determine the efficiency for a given point in the Dalitz plot. /*! \param [in] kinematics the object that defines the DP position \return the efficiency value at the given point in the DP */ virtual Double_t calcEfficiency( const LauKinematics* kinematics ) const=0; //! Determine whether the given DP position is outside the vetoes /*! \param [in] kinematics the object that defines the DP position \return kTRUE if the DP position is outside all veto regions, kFALSE otherwise */ virtual Bool_t passVeto( const LauKinematics* kinematics ) const=0; //! Determine whether the efficiency histogram has had its bins fluctuated within their errors virtual Bool_t fluctuateEffHisto() const=0; //! Return the daughters object /* \return the LauDaughters object associated with the DP */ virtual const LauDaughters* getDaughters() const=0; private: //! Copy constructor - not implemented LauAbsEffModel( const LauAbsEffModel& rhs ); //! Copy assignment operator - not implemented LauAbsEffModel& operator=( const LauAbsEffModel& rhs ); - ClassDef(LauAbsEffModel, 0) // pABC for the signal efficiency across the DP }; #endif diff --git a/inc/LauAbsFitModel.hh b/inc/LauAbsFitModel.hh index 646c2e7..5a33feb 100644 --- a/inc/LauAbsFitModel.hh +++ b/inc/LauAbsFitModel.hh @@ -1,834 +1,833 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsFitModel.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() - setAmpCoeffSet() - setNBkgndEvents() - setNSigEvents() - setupBkgndVectors() - setupGenNtupleBranches() - setupSPlotNtupleBranches() - splitSignal() - storePerEvtLlhds() - twodimPDFs() - updateCoeffs() - variableNames() - weightEvents() - writeOutTable() */ #ifndef LAU_ABS_FIT_MODEL #define LAU_ABS_FIT_MODEL #include "TMatrixDfwd.h" #include "TString.h" #include "TStopwatch.h" #include #include #include #include "LauFitObject.hh" #include "LauFormulaPar.hh" #include "LauSimFitTask.hh" // LauSPlot included to get LauSPlot::NameSet typedef #include "LauSPlot.hh" class LauAbsCoeffSet; class LauAbsPdf; class LauFitDataTree; class LauGenNtuple; class LauAbsRValue; class LauParameter; class LauAbsFitModel : public LauSimFitTask { 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 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;} //! 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;} //! save files containing graphs of the resonance's PDFs Bool_t saveFilePDF() const {return savePDF_;} //! Turn on or off the save of files containing graphs of the resonance's PDFs /*! \param [in] savePDF boolean specifying whether or not the save of files containing graphs of the resonance's PDFs */ void saveFilePDF(Bool_t savePDF) {savePDF_ = savePDF;} //! 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;} //! Setup the background class names /*! \param [in] names a vector of all the background names */ virtual void setBkgndClassNames( const std::vector& 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(LauAbsRValue* nBkgndEvents) = 0; //! Set the DP amplitude coefficients /*! The name of the coeffSet must match the name of one of the resonances in the DP model. The supplied order of coefficients will be rearranged to match the order in which the resonances are stored in the dynamics, see LauIsobarDynamics::addResonance. \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); //! 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 = ""); //! 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! */ virtual Double_t getTotNegLogLikelihood(); //! Set model parameters from a file /*! \param [in] fileName the name of the file with parameters to set \param [in] treeName the name of the tree in the file corresponding to the parameters to set \param [in] fix whether to fix (set constant) the loaded parameters, or leave them floating */ void setParametersFromFile(const TString& fileName, const TString& treeName, const Bool_t fix); //! Set model parameters from a given std::map /*! Only parameters named in the map are imported, all others are set to their values specified in the model configuration. \param [in] parameters map from parameter name to imported value \param [in] fix whether to fix (set constant) the loaded parameters, or leave them floating */ void setParametersFromMap(const std::map& parameters, const Bool_t fix); //! Set named model parameters from a file /*! Identical to setParametersFromFile, but only import parameters named from parameters set. All others are set to their values specified in the model configuration. \param [in] fileName the name of the file with parameters to set \param [in] treeName the name of the tree in the file corresponding to the parameters to set \param [in] parameters the set of parameters to import from the file \param [in] fix whether to fix (set constant) the loaded parameters, or leave them floating */ void setNamedParameters(const TString& fileName, const TString& treeName, const std::set& parameters, const Bool_t fix); //! Set named model parameters from a given std::map, with fallback to those from a file /*! Parameters named in the map are imported with their specified values. All other parameters are set to the values corresponding to the value in the given file. \param [in] fileName the name of the file with parameters to set \param [in] treeName the name of the tree in the file corresponding to the parameters to set \param [in] parameters map from parameter name to imported value (override parameters form the file) \param [in] fix whether to fix (set constant) the loaded parameters, or leave them floating */ void setParametersFileFallback(const TString& fileName, const TString& treeName, const std::map& parameters, const Bool_t fix); protected: // Some typedefs //! List of Pdfs typedef std::vector LauPdfList; //! List of parameter pointers typedef std::vector LauParameterPList; //! List of parameter pointers typedef std::vector LauAbsRValuePList; //! Set of parameter pointers typedef std::set LauParameterPSet; //! List of parameters typedef std::vector LauParameterList; //! A type to store background classes typedef std::map LauBkgndClassMap; //! Clear the vectors containing fit parameters void clearFitParVectors(); //! Clear the vectors containing extra ntuple variables void clearExtraVarVectors(); //! Weighting - 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; //! 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); //! 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); //! Read in the data for the current experiment /*! \return the number of events read in */ virtual UInt_t readExperimentData(); //! Open the input file and verify that all required variables are present /*! \param [in] dataFileName the name of the input file \param [in] dataTreeName the name of the input tree */ virtual Bool_t verifyFitData(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; //! Setup saving of fit results to ntuple/LaTeX table etc. /*! \param [in] histFileName the file name for the output histograms \param [in] tableFileName the file name for the latex output file */ virtual void setupResultsOutputs( const TString& histFileName, const TString& tableFileName ); //! Package the initial fit parameters for transmission to the coordinator /*! \param [out] array the array to be filled with the LauParameter objects */ virtual void prepareInitialParArray( TObjArray& array ); //! Perform all finalisation actions /*! - Receive the results of the fit from the coordinator - Perform any finalisation routines - Package the finalised fit parameters for transmission back to the coordinator \param [in] fitStat the status of the fit, e.g. status code, EDM, NLL \param [in] parsFromCoordinator the parameters at the fit minimum \param [in] covMat the fit covariance matrix \param [out] parsToCoordinator the array to be filled with the finalised LauParameter objects */ virtual void finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromCoordinator, const TMatrixD* covMat, TObjArray& parsToCoordinator ); //! 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; //! Save the pdf Plots for all the resonances of experiment number fitExp /*! \param [in] label prefix for the file name to be saved */ virtual void savePDFPlots(const TString& label) = 0; //! Save the pdf Plots for the sum of ressonances correspondint to "sin" of experiment number fitExp /*! \param [in] label prefix for the file name to be saved \param [in] spin spin of the wave to be saved */ virtual void savePDFPlotsWave(const TString& label, const Int_t& spin) = 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; //! 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; //! 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; } //! Const access the fit variables const LauParameterPList& fitPars() const {return fitVars_;} //! Access the fit variables LauParameterPList& fitPars() {return fitVars_;} //! Const access the fit variables which affect the DP normalisation const LauParameterPSet& resPars() const {return resVars_;} //! Access the fit variables which affect the DP normalisation LauParameterPSet& resPars() {return resVars_;} //! Const access the extra variables const LauParameterList& extraPars() const {return extraVars_;} //! Access the extra variables LauParameterList& extraPars() {return extraVars_;} //! Const access the Gaussian constrained variables const LauAbsRValuePList& conPars() const {return conVars_;} //! Access the Gaussian constrained variables LauAbsRValuePList& conPars() {return conVars_;} //! Const access the gen ntuple const LauGenNtuple* genNtuple() const {return genNtuple_;} //! Access the gen ntuple LauGenNtuple* genNtuple() {return genNtuple_;} //! Const access the sPlot ntuple const LauGenNtuple* sPlotNtuple() const {return sPlotNtuple_;} //! Access the sPlot ntuple LauGenNtuple* sPlotNtuple() {return sPlotNtuple_;} //! Const access the data store const LauFitDataTree* fitData() const {return inputFitData_;} //! Access the data store LauFitDataTree* fitData() {return inputFitData_;} //! Imported parameters file name TString fixParamFileName_; //! Imported parameters tree name TString fixParamTreeName_; //! Map from imported parameter name to value std::map fixParamMap_; //! Imported parameter names std::set fixParamNames_; //! Whether to fix the loaded parameters (kTRUE) or leave them floating (kFALSE) Bool_t fixParams_; //! The set of parameters that are imported (either from a file or by value) and not // set to be fixed in the fit. In addition to those from fixParamNames_, these // include those imported from a file. std::set allImportedFreeParams_; private: //! Copy constructor (not implemented) LauAbsFitModel(const LauAbsFitModel& rhs); //! Copy assignment operator (not implemented) LauAbsFitModel& operator=(const LauAbsFitModel& rhs); // Various control booleans //! Option to make toy from 1st successful experiment Bool_t compareFitData_; //! Option to output a .C file of PDF's Bool_t savePDF_; //! 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 //! Internal vector of fit parameters LauParameterPList fitVars_; //! Internal set of fit parameters upon which the DP normalisation depends LauParameterPSet resVars_; //! Extra variables that aren't in the fit but are stored in the ntuple LauParameterList extraVars_; //! Internal vectors of Gaussian parameters LauAbsRValuePList conVars_; // Input data and output ntuple //! The input data LauFitDataTree* inputFitData_; //! The generated ntuple LauGenNtuple* genNtuple_; //! The sPlot ntuple LauGenNtuple* sPlotNtuple_; // 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 sWeights_; //! The sWeight scaling factor Double_t sWeightScaleFactor_; // Fit timers //! The fit timer TStopwatch timer_; //! The total fit timer TStopwatch cumulTimer_; //! The output table name TString outputTableName_; // 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_; - ClassDef(LauAbsFitModel,0) // Abstract interface to fit/toyMC model }; #endif diff --git a/inc/LauAbsFitter.hh b/inc/LauAbsFitter.hh index 2846900..f2d2c5b 100644 --- a/inc/LauAbsFitter.hh +++ b/inc/LauAbsFitter.hh @@ -1,146 +1,145 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsFitter.hh \brief File containing declaration of LauAbsFitter class. */ /*! \class LauAbsFitter \brief The abstract interface to the fitter. The abstract interface to the fitter. Concrete implementations provide the singleton interface with a particular fitter, e.g. Minuit. */ #ifndef LAU_ABS_FITTER #define LAU_ABS_FITTER #include "Rtypes.h" #include "TMatrixDfwd.h" #include class LauFitObject; class LauParameter; class LauAbsFitter { public: /*! \struct FitStatus \brief Struct to store fit status information */ struct FitStatus { //! The status code of the fit Int_t status; //! The negative log-likelihood Double_t NLL; //! The estimated distance to the minimum Double_t EDM; }; //! Destructor virtual ~LauAbsFitter() = default; //! Initialise the fitter, setting the information on the parameters /*! \param [in] fitObj the object that controls the likelihood calculation \param [in] parameters the list of parameters of the fit */ virtual void initialise( LauFitObject* fitObj, const std::vector& parameters ) = 0; //! Get the object that controls the calculation of the likelihood virtual LauFitObject* getFitObject() = 0; //! Get the total number of fit parameters virtual UInt_t nParameters() const = 0; //! Get the number of floating fit parameters virtual UInt_t nFreeParameters() const = 0; //! Determine whether the two-stage fit is enabled virtual Bool_t twoStageFit() const = 0; //! 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) = 0; //! Determine whether calculation of asymmetric errors is enabled virtual Bool_t useAsymmFitErrors() const = 0; //! 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 */ virtual void useAsymmFitErrors(Bool_t useAsymmErrors) = 0; //! Perform the minimisation of the fit function /*! \return the status code of the fit and the minimised value */ virtual const FitStatus& minimise() = 0; //! Fix parameters marked as "second stage" virtual void fixSecondStageParameters() = 0; //! Release parameters marked as "second stage" virtual void releaseSecondStageParameters() = 0; //! Update the values and errors of the parameters based on the fit minimum virtual void updateParameters() = 0; //! Retrieve the fit covariance matrix virtual const TMatrixD& covarianceMatrix() const = 0; protected: //! Constructor LauAbsFitter() = default; private: //! Copy constructor - private and not implemented LauAbsFitter( const LauAbsFitter& ) = delete; //! Move constructor - private and not implemented LauAbsFitter( LauAbsFitter&& ) = delete; //! Copy assignment operator - private and not implemented LauAbsFitter& operator=( const LauAbsFitter& rhs ) = delete; //! Move assignment operator - private and not implemented LauAbsFitter& operator=( LauAbsFitter&& rhs ) = delete; - ClassDef(LauAbsFitter,0); }; #endif diff --git a/inc/LauAbsIncohRes.hh b/inc/LauAbsIncohRes.hh index 9fbc4d4..57929e6 100644 --- a/inc/LauAbsIncohRes.hh +++ b/inc/LauAbsIncohRes.hh @@ -1,82 +1,81 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsIncohRes.hh \brief File containing declaration of LauAbsIncohRes class. */ /*! \class LauAbsIncohRes \brief Abstract class for defining incoherent resonant amplitude models */ #ifndef LAU_ABS_INCOH_RES #define LAU_ABS_INCOH_RES #include "TString.h" #include "LauAbsResonance.hh" class LauKinematics; class LauAbsIncohRes : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauAbsIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauAbsIncohRes(); //! Get intensity factor /*! /param [in] kinematics kinematic parameters of the parent and daughter particles /return the intensity factor */ virtual Double_t intensityFactor(const LauKinematics* kinematics)=0; protected: //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauAbsIncohRes(const LauAbsIncohRes& rhs); //! Copy assignment operator (not implemented) LauAbsIncohRes& operator=(const LauAbsIncohRes& rhs); - ClassDef(LauAbsIncohRes,0) // Abstract incoherent resonance class }; #endif diff --git a/inc/LauAbsModIndPartWave.hh b/inc/LauAbsModIndPartWave.hh index ead918f..a23069b 100644 --- a/inc/LauAbsModIndPartWave.hh +++ b/inc/LauAbsModIndPartWave.hh @@ -1,249 +1,248 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsModIndPartWave.hh \brief File containing declaration of LauAbsModIndPartWave class. */ /*! \class LauAbsModIndPartWave \brief Abstract base class for defining a model independent partial wave component Abstract base class for defining a model independent partial wave component. This model uses splines to produce a partial wave from two sets of real numbers that represent the amplitude at a series of points in the phase space. These real numbers at each point can be floated in the fit. Classes inheriting from this define whether these real numbers are e.g. the magnitude and phase or e.g. the real and imaginary part of the amplitude. */ #ifndef LAU_ABSMODINDPARTWAVE #define LAU_ABSMODINDPARTWAVE #include #include "LauComplex.hh" #include "LauAbsResonance.hh" #include "Lau1DCubicSpline.hh" class LauAbsModIndPartWave : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauAbsModIndPartWave(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauAbsModIndPartWave(); //! Initialise the model virtual void initialise(); //! Define the knot positions /*! If absent from the set provided, knots are added automatically at the upper and lower kinematic limits \param [in] masses the mass values at which the knots are placed */ void defineKnots(const std::set& masses); //! Return the number of knots that have been defined (including those at the upper and lower kinematic limits) /*! \return the number of knots */ UInt_t nKnots() const { return nKnots_; } //! Set the values of the two real parameters that define the amplitude at a given knot /*! \param [in] knot the knot to be updated \param [in] ampVal1 the value of first real parameter representing the amplitude at the knot \param [in] ampVal2 the value of second real parameter representing the amplitude at the knot \param [in] fixAmpVal1 whether the first real parameter should be fixed \param [in] fixAmpVal2 whether the second real parameter should be fixed */ virtual void setKnotAmp(const UInt_t knot, const Double_t ampVal1, const Double_t ampVal2, const Bool_t fixAmpVal1, const Bool_t fixAmpVal2) = 0; //! Set whether the parameters should be floated only in the second-stage of a two-stage fit /*! By default, the parameters describing the amplitude at each knot will float from the outset of a fit. If, however, a good estimate of these is already known, it can be more efficient to initially fix them and then to float them only in a second stage (as is done for other resonance lineshape parameters). This function allows the toggling of this behaviour. \param secondStage whether the parameters should float only in the second stage */ void floatKnotsSecondStage(const Bool_t secondStage); //! Retrieve the value of the second stage flag Bool_t floatKnotsSecondStage() const {return secondStage_;}; //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); //! Evaluate the amplitude at the given point from the splines /*! \param [in] mass appropriate invariant mass for the resonance */ virtual void evaluateAmplitude(const Double_t mass) = 0; //! Method to check that the supplied knot positions are valid /*! \param [in] masses the mass values at which the knots are placed */ virtual std::set checkKnots(const std::set& masses); //! Method to create the parameter objects for the given knot /*! \param [in] iKnot the index of the knot */ virtual void createAmpParameters(const UInt_t iKnot) = 0; //! Method to set the type of interpolation used for the splines /*! \param [in] type1 the type of interpolation for the first spline \param [in] type2 the type of interpolation for the second spline */ void setSplineType(Lau1DCubicSpline::LauSplineType type1, Lau1DCubicSpline::LauSplineType type2); //! Method to set the boundary conditions of the splines /*! \param [in] leftBound1 the type of boundary condition for the left edge of the first spline \param [in] rightBound1 the type of boundary condition for the right edge of the first spline \param [in] leftBound2 the type of boundary condition for the left edge of the second spline \param [in] rightBound2 the type of boundary condition for the right edge of the second spline \param [in] leftGrad1 the gradient at the left edge of the first spline if clamped \param [in] rightGrad1 the gradient at the right edge of the first spline if clamped \param [in] leftGrad2 the gradient at the left edge of the second spline if clamped \param [in] rightGrad2 the gradient at the right edge of the second spline if clamped */ void setSplineBoundaryConditions(Lau1DCubicSpline::LauSplineBoundaryType leftBound1, Lau1DCubicSpline::LauSplineBoundaryType rightBound1, Lau1DCubicSpline::LauSplineBoundaryType leftBound2, Lau1DCubicSpline::LauSplineBoundaryType rightBound2, Double_t leftGrad1 = 0.0, Double_t rightGrad1 = 0.0, Double_t leftGrad2 = 0.0, Double_t rightGrad2 = 0.0); //! Helper function to set the current amplitude value /*! \param [in] realPart the real part of the amplitude \param [in] imagPart the imaginary part of the amplitude */ void setAmp(const Double_t realPart, const Double_t imagPart) { amp_.setRealImagPart(realPart,imagPart); } //! Helper function to access the masses const std::vector& getMasses() {return masses_;} //! Helper function to access the 1st parameter set std::vector& getAmp1Vals() {return amp1Vals_;} //! Helper function to access the 2nd parameter set std::vector& getAmp2Vals() {return amp2Vals_;} //! Helper function to access the 1st parameter set std::vector& getAmp1Pars() {return amp1Pars_;} //! Helper function to access the 2nd parameter set std::vector& getAmp2Pars() {return amp2Pars_;} //! Helper function to access the 1st spline const Lau1DCubicSpline* getSpline1() const {return spline1_;} //! Helper function to access the 1st spline const Lau1DCubicSpline* getSpline2() const {return spline2_;} private: //! The number of knots UInt_t nKnots_; //! The masses at which knots are defined in the magnitude and phase splines std::vector masses_; //! The values of the first real parameter at each knot std::vector amp1Vals_; //! The values of the second real parameter at each knot std::vector amp2Vals_; //! The parameters for the first real value at the knots std::vector amp1Pars_; //! The parameters for the second real value at the knots std::vector amp2Pars_; //! The spline used to interpolate the values of the first real parameter Lau1DCubicSpline* spline1_; //! The spline used to interpolate the values of the second real parameter Lau1DCubicSpline* spline2_; //! The type of interpolation used for the first spline Lau1DCubicSpline::LauSplineType type1_; //! The type of interpolation used for the second spline Lau1DCubicSpline::LauSplineType type2_; //! The lower boundary condition type for the first spline Lau1DCubicSpline::LauSplineBoundaryType leftBound1_; //! The upper boundary condition type for the first spline Lau1DCubicSpline::LauSplineBoundaryType rightBound1_; //! The lower boundary condition type for the second spline Lau1DCubicSpline::LauSplineBoundaryType leftBound2_; //! The upper boundary condition type for the second spline Lau1DCubicSpline::LauSplineBoundaryType rightBound2_; //! The gradient at the left boundary for the first spline if clamped Double_t leftGrad1_; //! The gradient at the right boundary for the first spline if clamped Double_t rightGrad1_; //! The gradient at the left boundary for the second spline if clamped Double_t leftGrad2_; //! The gradient at the right boundary for the second spline if clamped Double_t rightGrad2_; //! Flag to determine if the parameters should be floated only in the second stage of the fit Bool_t secondStage_; //! The current value of the amplitude LauComplex amp_; - ClassDef(LauAbsModIndPartWave,0) // model independent partial wave }; #endif diff --git a/inc/LauAbsPdf.hh b/inc/LauAbsPdf.hh index c05ae51..3716e28 100644 --- a/inc/LauAbsPdf.hh +++ b/inc/LauAbsPdf.hh @@ -1,552 +1,551 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsPdf.hh \brief File containing declaration of LauAbsPdf class. */ /*! \class LauAbsPdf \brief Class for defining the abstract interface for PDF classes. Class for defining the abstract interface for PDF classes. Much common code is implemented but the following three methods are not: evaluatePDF, calcNorm, calcPDFHeight */ #ifndef LAU_ABS_PDF #define LAU_ABS_PDF #include #include #include "Rtypes.h" #include "TRandom.h" #include "TString.h" #include "LauFitDataTree.hh" #include "LauAbsRValue.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" class LauKinematics; class LauAbsPdf { public: //! The type used for containing multiple abscissa values. typedef std::vector LauAbscissas; //! The possible numerical intergration methods. enum IntMethod { GaussLegendre, /*!< Gauss-Legendre integration */ Trapezoid /*!< Simple trapezoid integration */ }; //! Constructor for a 1D PDF /*! \param [in] theVarName the name of the abscissa variable \param [in] params the parameters of the PDF \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauAbsPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Constructor for a multidimensional PDF /*! \param [in] theVarNames the names of the abscissa variables \param [in] params the parameters of the PDF \param [in] minAbscissas the minimum values of the abscissas \param [in] maxAbscissas the maximum values of the abscissas */ LauAbsPdf(const std::vector& theVarNames, const std::vector& params, const LauFitData& minAbscissas, const LauFitData& maxAbscissas); //! Destructor virtual ~LauAbsPdf() {} //! Retrieve the name of the abscissa /*! \return the abscissa's name */ virtual const TString& varName() const {return varNames_.find(0)->second;} //! Retrieve the names of the abscissas /*! \return the abscissas' names */ virtual std::vector varNames() const; //! Retrieve the number of PDF parameters /*! \return the number of PDF parameters */ virtual UInt_t nParameters() const {return param_.size();} //! Retrieve the number of fixed PDF parameters /*! \return the number of fixed PDF parameters */ virtual UInt_t nFixedParameters() const; //! Retrieve the number of abscissas /*! \return the number of abscissas */ virtual UInt_t nInputVars() const {return varNames_.size();} //! Specifies whether or not the PDF is DP dependent. /*! DP-dependent PDFs should override this method. \return true if the PDF is DP-dependent, false otherwise (the default) */ virtual Bool_t isDPDependent() const {return kFALSE;} //! Retrieve the minimum value of the (primary) abscissa /*! \return the minimum value of the (primary) abscissa */ virtual Double_t getMinAbscissa() const {return minAbscissas_.front();} //! Retrieve the maximum value of the (primary) abscissa /*! \return the maximum value of the (primary) abscissa */ virtual Double_t getMaxAbscissa() const {return maxAbscissas_.front();} //! Retrieve the range of the (primary) abscissa /*! \return the range of the (primary) abscissa */ virtual Double_t getRange() const {return this->getMaxAbscissa() - this->getMinAbscissa();} //! Retrieve the minimum value of the specified abscissa /*! \param [in] theVarName the name of the abscissa \return the minimum value of the specified abscissa */ virtual Double_t getMinAbscissa( const TString& theVarName ) const; //! Retrieve the maximum value of the specified abscissa /*! \param [in] theVarName the name of the abscissa \return the maximum value of the specified abscissa */ virtual Double_t getMaxAbscissa( const TString& theVarName ) const; //! Retrieve the range of the specified abscissa /*! \param [in] theVarName the name of the abscissa \return the range of the specified abscissa */ virtual Double_t getRange( const TString& theVarName ) const {return this->getMaxAbscissa(theVarName) - this->getMinAbscissa(theVarName);} //! Retrieve the minimum values of all the abscissas /*! \return the minimum values of the abscissas */ virtual LauFitData getMinAbscissas() const; //! Retrieve the maximum values of all the abscissas /*! \return the maximum values of the abscissas */ virtual LauFitData getMaxAbscissas() const; //! Retrieve the ranges of all the abscissas /*! \return the ranges of the abscissas */ virtual LauFitData getRanges() const; //! Update the pulls for all parameters virtual void updatePulls(); //! Cache information from data /*! Will cache, for every event, the abscissa values and, if all parameters are fixed, the PDF value. \param [in] inputData the data to be used to calculate everything */ virtual void cacheInfo(const LauFitDataTree& inputData); //! Calculate the likelihood (and all associated information) given value(s) of the abscissa(s) /*! \param [in] abscissas the value(s) of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas) = 0; //! Retrieve the likelihood (and all associated information) given the event number /*! \param [in] iEvt the event number */ virtual void calcLikelihoodInfo(UInt_t iEvt); //! Retrieve the unnormalised likelihood value /*! \return the unnormalised likelihood value */ virtual Double_t getUnNormLikelihood() const {return unNormPDFVal_;} //! Retrieve the normalisation factor /*! \return the normalisation factor */ virtual Double_t getNorm() const {return norm_;} //! Retrieve the normalised likelihood value /*! \return the normalised likelihood value */ virtual Double_t getLikelihood() const; //! For multidimentional PDFs, retrieve the normalised likelihood value of a named variable /*! Defaults to simply returning the complete likelihood. Should be overridden by multidimensional PDFs. \return the normalised likelihood value of the named variable */ virtual Double_t getLikelihood( const TString& theVarName ) const; //! Retrieve the maximum height /*! \return the maximum height */ virtual Double_t getMaxHeight() const {return maxHeight_;} //! Generate an event from the PDF /*! \param [in] kinematics used by some PDFs to determine the DP position, on which they have dependence */ virtual LauFitData generate(const LauKinematics* kinematics); //! Set the random function used for toy MC generation /*! \param [in] randomFun the random function to be used */ virtual void setRandomFun(TRandom* randomFun) {randomFun_ = randomFun;} //! Retrieve the parameters of the PDF, e.g. so that they can be loaded into a fit /*! \return the parameters of the PDF */ virtual const std::vector& getParameters() const { return param_; } //! Retrieve the parameters of the PDF, e.g. so that they can be loaded into a fit /*! \return the parameters of the PDF */ virtual std::vector& getParameters() { return param_; } //! Calculate the normalisation factor of the PDF /*! By default uses numerical integration. PDFs with analytical integrals should override this method. */ virtual void calcNorm(); //! Calculate the maximum height of the PDF /*! \param [in] kinematics used by some PDFs to determine the DP position, on which they have dependence */ virtual void calcPDFHeight( const LauKinematics* kinematics ) = 0; //! Check if the maximum height of the PDF is up to date /*! \return true if the maximum height is up to date */ virtual Bool_t heightUpToDate() const {return heightUpToDate_;} //! Set whether the height is up to date /*! \param [in] hutd whether the height is up to date */ virtual void heightUpToDate(Bool_t hutd) {heightUpToDate_ = hutd;} //! Check if the PDF is to be cached /*! \return true if the PDF is to be cached */ virtual Bool_t cachePDF() const {return cachePDF_;} //! Retrieve the number of points to integrate over when normalising /*! \return the number of points to integrate over when normalising */ virtual Int_t nNormPoints() const {return nNormPoints_;} //! Set the number of points to integrate over when normalising /*! \param [in] nPoints the number of points */ virtual void nNormPoints(Int_t nPoints) {nNormPoints_ = nPoints;} //! Retrieve the integration method used to normalise the PDF /*! \return the integration method used to normalise the PDF */ virtual IntMethod integMethod() const {return integMethod_;} //! Set the integration method used to normalise the PDF /*! \param [in] method the integration method to be used */ virtual void integMethod(IntMethod method) {integMethod_ = method;} protected: //! Set whether the PDF is to be cached /*! \param [in] doCachePDF whether the PDF is to be cached */ virtual void cachePDF( Bool_t doCachePDF ) {cachePDF_ = doCachePDF;} //! Integrate the PDF using the Gauss-Legendre method /*! \return the integral of the PDF */ virtual Double_t integrGaussLegendre(); //! Integrate the PDF using the simple trapezoid method /*! \return the integral of the PDF */ virtual Double_t integTrapezoid(); //! Set the normalisation factor /*! \param [in] norm the normalisation factor */ virtual void setNorm(Double_t norm) {norm_ = norm;} //! Set the maximum height /*! \param [in] maxHeight the new maximum height */ virtual void setMaxHeight(Double_t maxHeight) { maxHeight_ = maxHeight; this->heightUpToDate(kTRUE); } //! Set the minimum value of the specified abscissa /*! \param [in] theVarName the name of the abscissa \param [in] minAbscissa value to set as minimum */ virtual void setMinAbscissa(const TString& theVarName, Double_t minAbscissa); //! Set the maximum value of the specified abscissa /*! \param [in] theVarName the name of the abscissa \param [in] maxAbscissa value to set as maximum */ virtual void setMaxAbscissa(const TString& theVarName, Double_t maxAbscissa); //! Set the range of the specified abscissa /*! \param [in] theVarName the name of the abscissa \param [in] minAbscissa value to set as minimum \param [in] maxAbscissa value to set as maximum */ virtual void setRange(const TString& theVarName, Double_t minAbscissa, Double_t maxAbscissa) { this->setMinAbscissa(theVarName, minAbscissa); this->setMaxAbscissa(theVarName, maxAbscissa); } //! Check that all abscissas are within their allowed ranges /*! \param [in] abscissas the value(s) of the abscissa(s) \return true if all abscissas are within their allowed ranges */ virtual Bool_t checkRange(const LauAbscissas& abscissas) const; //! Set the unnormalised likelihood virtual void setUnNormPDFVal(Double_t unNormPDFVal) {unNormPDFVal_ = unNormPDFVal;} //! Retrieve the specified parameter /*! \param [in] parName the parameter to retrieve */ virtual LauAbsRValue* findParameter(const TString& parName); //! Retrieve the specified parameter /*! \param [in] parName the parameter to retrieve */ virtual const LauAbsRValue* findParameter(const TString& parName) const; //! Retrieve the random function used for MC generation /*! \return the random function used for MC generation */ virtual TRandom* getRandomFun() const {return randomFun_;} //! Retrieve the abscissa(s) /*! \return the abscissa(s) */ virtual std::vector& getAbscissas() {return abscissas_;} //! Retrieve the abscissa(s) /*! \return the abscissa(s) */ virtual const std::vector& getAbscissas() const {return abscissas_;} //! Retrieve the cached unnormalised likelihood values /*! \return the cached unnormalised likelihood values */ virtual std::vector& getUnNormPDFValues() {return unNormPDFValues_;} //! Retrieve the cached unnormalised likelihood values /*! \return the cached unnormalised likelihood values */ virtual const std::vector& getUnNormPDFValues() const {return unNormPDFValues_;} //! Add parameters to the PDF /*! \param [in] params the parameters to add */ virtual void addParameters(std::vector& params); //! Check whether the calcNorm method is running /*! \return true if the calcNorm method is running */ virtual Bool_t withinNormCalc() const {return withinNormCalc_;} //! Set flag to track whether the calcNorm method is running /*! \param [in] yorn whether the calcNorm method is running */ virtual void withinNormCalc(Bool_t yorn) {withinNormCalc_ = yorn;} //! Check whether the generate method is running /*! \return true if the generate method is running */ virtual Bool_t withinGeneration() const {return withinGeneration_;} //! Set flag to track whether the generate method is running /*! \param [in] yorn whether the generate method is running */ virtual void withinGeneration(Bool_t yorn) {withinGeneration_ = yorn;} //! Check whether the normalisation weights have been calculated /*! \return true if the normalisation weights have been calculated */ virtual Bool_t normWeightsDone() const {return normWeightsDone_;} //! Set whether the normalisation weights have been calculated /*! \param [in] yorn whether the normalisation weights have been calculated */ virtual void normWeightsDone(Bool_t yorn) {normWeightsDone_ = yorn;} //! Calculate the weights and abscissas used for normalisation virtual void getNormWeights(); //! Retrieve the abscissa points used for normalisation /*! \return the abscissa points used for normalisation */ virtual const std::vector& normAbscissas() const {return normAbscissas_;} //! Retrieve the weights used for normalisation /*! \return the weights used for normalisation */ virtual const std::vector& normWeights() const {return normWeights_;} private: //! Copy constructor (not implemented) LauAbsPdf(const LauAbsPdf& rhs); //! Copy assignment operator (not implemented) LauAbsPdf& operator=(const LauAbsPdf& rhs); //! The names of the PDF variables std::map varNames_; //! The parameters of the PDF (if any) std::vector param_; //! Normalisation factor of the PDF Double_t norm_; //! Maximum height of the PDF Double_t maxHeight_; //! Track whether the height is up to date Bool_t heightUpToDate_; //! The minimum value(s) of the abscissa(s) LauAbscissas minAbscissas_; //! The maximum value(s) of the abscissa(s) LauAbscissas maxAbscissas_; //! The random function used for MC generation TRandom* randomFun_; //! Cached values of the abscissas std::vector abscissas_; //! Cached unnormalised likelihood values std::vector unNormPDFValues_; //! Whether the unnormalised PDF values are cached /*! They are only cached if all parameters are fixed. */ Bool_t cachePDF_; //! The unnormalised liklihood value Double_t unNormPDFVal_; //! number of points to integrate over when normalising Int_t nNormPoints_; //! The integration method used for normalising the PDF IntMethod integMethod_; //! Flag to keep track of whether the calcNorm method is running Bool_t withinNormCalc_; //! Flag to keep track of whether the generate method is running Bool_t withinGeneration_; //! Whether the normalisation weights have been calculated Bool_t normWeightsDone_; //! The normalisation abscissas std::vector normAbscissas_; //! The normalisation weights std::vector normWeights_; - ClassDef(LauAbsPdf,0) // Define the abstract PDF class }; #endif diff --git a/inc/LauAbsResonance.hh b/inc/LauAbsResonance.hh index 02a6b1a..5a3a034 100644 --- a/inc/LauAbsResonance.hh +++ b/inc/LauAbsResonance.hh @@ -1,579 +1,578 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsResonance.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 "LauBlattWeisskopfFactor.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauDaughters; class LauKinematics; class LauResonanceInfo; 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 */ EFKLLM, /*!< a form-factor-based description of the Kpi S-wave */ KMatrix, /*!< description using K-matrix and P-vector */ FlatNR, /*!< a uniform nonresonant amplitude */ NRModel, /*!< a theoretical model nonresonant amplitude */ BelleNR, /*!< an empirical exponential nonresonant amplitude */ PowerLawNR, /*!< an empirical power law nonresonant amplitude */ BelleSymNR, /*!< an empirical exponential nonresonant amplitude for symmetrised DPs */ BelleSymNRNoInter, /*!< an empirical exponential nonresonant amplitude for symmetrised DPs without interference */ TaylorNR, /*!< an empirical Taylor expansion nonresonant amplitude for symmetrised DPs */ PolNR, /*!< an empirical polynomial nonresonant amplitude */ Pole, /*!< scalar Pole lineshape */ PolarFFNR, /*!< Polar Form Factor nonresonant amplitude */ PolarFFSymNR, /*!< Polar Form Factor nonresonant amplitude for symmetrised DPs */ PolarFFSymNRNoInter, /*!< Polar Form Factor nonresonant amplitude for symmetrised DPs without interference */ Rescattering, /*!< KK-PiPi inelastic scattering amplitude */ Rescattering2, /*!< KK-PiPi inelastic scattering amplitude */ RescatteringNoInter, /*!< KK-PiPi inelastic scattering amplitude */ MIPW_MagPhase, /*!< a model independent partial wave - magnitude and phase representation */ MIPW_RealImag, /*!< a model independent partial wave - real and imaginary part representation */ GaussIncoh, /*!< an incoherent Gaussian shape */ RhoOmegaMix_GS, /*!< mass mixing model using GS for res 1 and RBW for res 2 */ RhoOmegaMix_RBW, /*!< mass mixing model using two RBWs */ RhoOmegaMix_GS_1, /*!< mass mixing model using GS for res 1 and RBW for res 2, with denominator factor = 1 */ RhoOmegaMix_RBW_1 /*!< mass mixing model using two RBWs, with denominator factor = 1 */ }; //! Define the allowed spin formalisms enum LauSpinType { Zemach_P, /*!< Zemach tensor formalism, bachelor momentum in resonance rest frame */ Zemach_Pstar, /*!< Zemach tensor formalism, bachelor momentum in parent rest frame */ Covariant, /*!< Covariant tensor formalism */ Legendre /*!< Legendre polynomials only */ }; //! Is the resonance model incoherent? /*! \param [in] model the resonance model \return true if the model is incoherent */ static bool isIncoherentModel(LauResonanceModel model); //! Constructor (for use by standard resonances) /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauAbsResonance(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Constructor (for use by K-matrix components) /*! \param [in] resName the name of the component \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles \param [in] resSpin the spin of the final channel into which the K-matrix scatters */ LauAbsResonance(const TString& resName, const Int_t resPairAmpInt, const LauDaughters* daughters, const Int_t resSpin); //! 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 spin type /*! \return the spin formalism */ LauSpinType getSpinType() const {return spinType_;} //! Get the name of the resonance /*! \return the resonance name */ const TString& getResonanceName() const {return resName_;} //! Get the name of the resonance /*! \return the resonance name */ const TString& getSanitisedName() const {return sanitisedName_;} //! 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_!=0) ? resMass_->unblindValue() : -1.0;} //! Get the width of the resonance /*! \return the resonance width */ Double_t getWidth() const {return (resWidth_!=0) ? resWidth_->unblindValue() : -1.0;} //! Get the mass parameter of the resonance /*! \return the resonance mass parameter */ LauParameter* getMassPar() {return resMass_;} //! Get the width parameter of the resonance /*! \return the resonance width parameter */ LauParameter* getWidthPar() {return resWidth_;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters() { return this->getParameters(); }; //! Is the amplitude pre-symmetrised? /*! The default value is kFALSE, so pre-symmetrised lineshapes should override this. \return whether the amplitude is already symmetrised */ virtual Bool_t preSymmetrised() const {return kFALSE;} //! 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(const Bool_t boolean) {flipHelicity_ = boolean;} //! Get the ignore momenta flag /*! Whether to ignore the momentum factors in both the spin factor and the mass-dependent width \return the ignore momenta flag */ Bool_t ignoreMomenta() const {return ignoreMomenta_;} //! Set the ignore momenta flag /*! Whether to ignore the momentum factors in both the spin factor and the mass-dependent width \param [in] boolean the ignore momenta status */ void ignoreMomenta(const Bool_t boolean) {ignoreMomenta_ = boolean;} //! Get the ignore spin flag /*! Whether to set the spinTerm to unity always \return the ignore spin flag */ Bool_t ignoreSpin() const {return ignoreSpin_;} //! Set the ignore spin flag /*! Whether to set the spinTerm to unity always \param [in] boolean the ignore spin status */ void ignoreSpin(const Bool_t boolean) {ignoreSpin_ = boolean;} //! Get the ignore barrier factor scaling flag /*! Whether to ignore barrier factor scaling in the amplitude numerator, they are still used for the mass-dependent width \return the ignore barrier amplitude scaling flag */ Bool_t ignoreBarrierScaling() const {return ignoreBarrierScaling_;} //! Set the ignore barrier factor scaling flag /*! Whether to ignore barrier factor scaling in the amplitude numerator, they are still used for the mass-dependent width \param [in] boolean the ignore barrier factor scaling status */ void ignoreBarrierScaling(const Bool_t boolean) {ignoreBarrierScaling_ = boolean;} //! Allow the mass, width and spin of the resonance to be changed /*! Negative values wil be ignored, so if, for example, you want to only change the spin you can provide negative values for the mass and width \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(const Double_t newMass, const Double_t newWidth, const Int_t newSpin); //! Allow the Blatt-Weisskopf radius for the resonance and parent factors to be changed /*! Negative values wil be ignored, so if, for example, you want to only change the parent radius you can provide a negative value for the resonance radius \param [in] resRadius new value of the resonance radius \param [in] parRadius new value of the parent radius */ void changeBWBarrierRadii(const Double_t resRadius, const Double_t parRadius); //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Fix or release the resonance mass /*! \param [in] parFixed new status of mass */ void fixMass(const Bool_t parFixed) { if (resMass_!=0) { resMass_->fixed(parFixed); } } //! Fix or release the resonance width /*! \param [in] parFixed new status of width */ void fixWidth(const 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; } //! Set the spin formalism to be used /*! \param [in] spinType the spin formalism */ void setSpinType(const LauSpinType spinType) {spinType_ = spinType;} //! Set the form factor model and parameters /*! \param [in] resFactor the barrier factor for the resonance decay \param [in] parFactor the barrier factor for the parent decay */ void setBarrierRadii(LauBlattWeisskopfFactor* resFactor, LauBlattWeisskopfFactor* parFactor) { resBWFactor_ = resFactor; parBWFactor_ = parFactor; } //! Fix or release the Blatt-Weisskopf barrier radii void fixBarrierRadii(const Bool_t fixResRadius, const Bool_t fixParRadius); //! Get the status of resonance barrier radius (fixed or released) Bool_t fixResRadius() const; //! Get the status of parent barrier radius (fixed or released) Bool_t fixParRadius() const; //! Get the radius of the resonance barrier factor Double_t getResRadius() const; //! Get the radius of the parent barrier factor Double_t getParRadius() const; 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_;} //! Get the current value of the full spin-dependent covariant factor Double_t getCovFactor() const {return covFactor_;} //! Get the centrifugal barrier for the parent decay LauBlattWeisskopfFactor* getParBWFactor() {return parBWFactor_;} const LauBlattWeisskopfFactor* getParBWFactor() const {return parBWFactor_;} //! Get the centrifugal barrier for the resonance decay LauBlattWeisskopfFactor* getResBWFactor() {return resBWFactor_;} const LauBlattWeisskopfFactor* getResBWFactor() const {return resBWFactor_;} //! Access the resonance info object LauResonanceInfo* getResInfo() const {return resInfo_;} //! Access the daughters object const LauDaughters* getDaughters() const {return daughters_;} //! Calculate the amplitude spin term using the Zemach tensor formalism /*! \param [in] pProd the momentum factor (either q * p or q * pstar) */ Double_t calcZemachSpinFactor( const Double_t pProd ) const; //! Calculate the amplitude spin term using the covariant tensor formalism /*! \param [in] pProd the momentum factor (q * pstar) */ Double_t calcCovSpinFactor( const Double_t pProd ); //! Calculate the spin-dependent covariant factor /*! \param [in] erm E_ij in the parent rest-frame divided by m_ij (equivalent to sqrt(1 + p^2/mParent^2)) */ void calcCovFactor( const Double_t erm ); //! Calculate the Legendre polynomial for the spin factor /*! Uses the current-event value of cosHel_ */ Double_t calcLegendrePoly() const; //! Calculate the Legendre polynomial for the spin factor (specifying the cosHel value) /*! \param [in] cosHel the cosine of the helicity angle */ Double_t calcLegendrePoly( const Double_t cosHel ); //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm) = 0; //! Clear list of floating parameters void clearFloatingParameters() { resParameters_.clear(); } //! Add parameter to the list of floating parameters /*! \param [in] param the parameter to be added to the list */ void addFloatingParameter( LauParameter* param ); //! Access the list of floating parameters std::vector& getParameters() { return resParameters_; } private: //! Copy constructor (not implemented) LauAbsResonance(const LauAbsResonance& rhs); //! Copy assignment operator (not implemented) LauAbsResonance& operator=(const LauAbsResonance& rhs); //! Information on the resonance LauResonanceInfo* resInfo_{0}; //! 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_{0}; //! Daughter 1 charge Int_t chargeDaug1_{0}; //! Daughter 2 charge Int_t chargeDaug2_{0}; //! Bachelor charge Int_t chargeBachelor_{0}; //! Parent mass Double_t massParent_{0.0}; //! Daughter 1 mass Double_t massDaug1_{0.0}; //! Daughter 2 mass Double_t massDaug2_{0.0}; // Bachelor mass Double_t massBachelor_{0.0}; //! Resonance name TString resName_; //! Resonance name with illegal characters removed TString sanitisedName_; //! Resonance mass LauParameter* resMass_{0}; //! Resonance width LauParameter* resWidth_{0}; //! All parameters of the resonance std::vector resParameters_; //! Resonance spin Int_t resSpin_; //! Resonance charge Int_t resCharge_{0}; //! DP axis identifier Int_t resPairAmpInt_; //! Blatt Weisskopf barrier for parent decay LauBlattWeisskopfFactor* parBWFactor_{0}; //! Blatt Weisskopf barrier for resonance decay LauBlattWeisskopfFactor* resBWFactor_{0}; //! Spin formalism LauSpinType spinType_{Zemach_P}; //! Boolean to flip helicity Bool_t flipHelicity_{kFALSE}; //! Boolean to ignore the momentum factors in both the spin factor and the mass-dependent width Bool_t ignoreMomenta_{kFALSE}; //! Boolean to set the spinTerm to unity always Bool_t ignoreSpin_{kFALSE}; //! Boolean to ignore barrier factor scaling in the amplitude numerator, they are still used for the mass-dependent width Bool_t ignoreBarrierScaling_{kFALSE}; // Event kinematics information //! Invariant mass Double_t mass_{0.0}; //! Helicity angle cosine Double_t cosHel_{0.0}; //! Daughter momentum in resonance rest frame Double_t q_{0.0}; //! Bachelor momentum in resonance rest frame Double_t p_{0.0}; //! Bachelor momentum in parent rest frame Double_t pstar_{0.0}; //! Covariant factor /*! sqrt(1 + z*z), where z = p / mParent Can also be expressed as E_ij in the parent rest-frame divided by m_ij - indeed this is how LauKinematics calculates it. \see LauKinematics::getcov12 \see LauKinematics::getcov13 \see LauKinematics::getcov23 */ Double_t erm_{1.0}; //! Covariant factor (full spin-dependent expression) Double_t covFactor_{1.0}; - ClassDef(LauAbsResonance,0) // Abstract resonance class }; #endif diff --git a/inc/LauArgusPdf.hh b/inc/LauArgusPdf.hh index a255839..b235a95 100644 --- a/inc/LauArgusPdf.hh +++ b/inc/LauArgusPdf.hh @@ -1,98 +1,97 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauArgusPdf.hh \brief File containing declaration of LauArgusPdf class. */ /*! \class LauArgusPdf \brief Class for defining an ARGUS PDF. Class that allows the user to define an ARGUS PDF: Phys. Lett. B 241, 278 (1990) */ #ifndef LAU_ARGUS_PDF #define LAU_ARGUS_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauArgusPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the curve parameters - the shape, xi, and the end-point, m0, of the curve \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauArgusPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauArgusPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauArgusPdf(const LauArgusPdf& other); //! Copy assignment operator (not implemented) LauArgusPdf& operator=(const LauArgusPdf& other); //! Shape of curve LauAbsRValue* xi_; //! Endpoint of curve LauAbsRValue* m0_; - ClassDef(LauArgusPdf,0) // Define the ARGUS PDF }; #endif diff --git a/inc/LauAsymmCalc.hh b/inc/LauAsymmCalc.hh index 6477cfb..4edfc90 100644 --- a/inc/LauAsymmCalc.hh +++ b/inc/LauAsymmCalc.hh @@ -1,84 +1,83 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAsymmCalc.hh \brief File containing declaration of LauAsymmCalc class. */ /*! \class LauAsymmCalc \brief Class for calculating the asymmetry between two variables. */ #ifndef LAU_ASYMM_CALC #define LAU_ASYMM_CALC #include "Rtypes.h" class LauAsymmCalc { public: //! Constructor /*! \param [in] negValue the negative value \param [in] posValue the positive value */ LauAsymmCalc(Double_t negValue, Double_t posValue); //! Destructor virtual ~LauAsymmCalc(); //! Copy constructor LauAsymmCalc(const LauAsymmCalc& rhs); //! Copy assignment operator LauAsymmCalc& operator=(const LauAsymmCalc& rhs); //! Retrieve the asymmetry /*! \return the asymmetry */ Double_t getAsymmetry() {return asymm_;} protected: //! Calculate the asymmetry /*! \return the asymmetry */ Double_t calcAsymmetry(); private: //! The negative value Double_t negValue_; //! The positive value Double_t posValue_; //! The asymmetry Double_t asymm_; - ClassDef(LauAsymmCalc,0) // Calculate asymmetry between two variables }; #endif diff --git a/inc/LauBelleCPCoeffSet.hh b/inc/LauBelleCPCoeffSet.hh index fb0364f..d439822 100644 --- a/inc/LauBelleCPCoeffSet.hh +++ b/inc/LauBelleCPCoeffSet.hh @@ -1,177 +1,176 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleCPCoeffSet.hh \brief File containing declaration of LauBelleCPCoeffSet class. */ /*! \class LauBelleCPCoeffSet \brief Class for defining a complex coefficient using the Belle CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form a * exp(i*delta) * ( 1 +/- b * exp(i*phi) ) where a is a CP conserving magnitude, b is a CP violating magnitude, delta is the strong phase and phi is the weak phase. [Phys.Rev.Lett. 96 (2006) 251803] */ #ifndef LAU_BELLECP_COEFF_SET #define LAU_BELLECP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauBelleCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] a the magnitude a \param [in] delta the strong phase \param [in] b the magnitude b \param [in] phi the weak phase \param [in] aFixed whether a is fixed \param [in] deltaFixed whether delta is fixed \param [in] bFixed whether b is fixed \param [in] phiFixed whether phi is fixed \param [in] bSecondStage whether b should be floated only in the second stage of the fit \param [in] phiSecondStage whether phi should be floated only in the second stage of the fit */ LauBelleCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage = kFALSE, Bool_t phiSecondStage = kFALSE); //! Destructor virtual ~LauBelleCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauBelleCPCoeffSet(const LauBelleCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet& operator=(const LauBelleCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude a LauParameter* a_; //! The magnitude b LauParameter* b_; //! The strong phase LauParameter* delta_; //! The weak phase LauParameter* phi_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauBelleCPCoeffSet, 0) }; #endif diff --git a/inc/LauBelleNR.hh b/inc/LauBelleNR.hh index e50bd0a..f4b7ce5 100644 --- a/inc/LauBelleNR.hh +++ b/inc/LauBelleNR.hh @@ -1,155 +1,154 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleNR.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 LauParameter; class LauBelleNR : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauBelleNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauBelleNR(); //! Override the enforcement of pure Legendre polynomial spin factors /*! By default this model uses pure Legendre polynomial spin factors, regardless of the default type set in LauResonanceMaker or any specific request from the user. This function allows the enforcement to be overridden. \param [in] forceLegendre boolean flag (kTRUE, the default, implies enforcement of pure Legendre spin factors, kFALSE overrides this to allow use of other formalisms) */ void enforceLegendreSpinFactors( const Bool_t forceLegendre ) { forceLegendre_ = forceLegendre; } //! Initialise the model virtual void initialise(); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return model_;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the parameter alpha, the effective range /*! \param [in] alpha the new effective range parameter value */ void setAlpha(const Double_t alpha); //! Get the effective range parameter /*! \return the effective range parameter */ Double_t getAlpha() const {return (alpha_!=0) ? alpha_->unblindValue() : 0.0;} //! See if the alpha parameter is fixed or floating /*! \return kTRUE if the effective range parameter is fixed, kFALSE otherwise */ Bool_t fixAlpha() const {return (alpha_!=0) ? alpha_->fixed() : kTRUE;} //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauBelleNR(const LauBelleNR& rhs); //! Copy assignment operator (not implemented) LauBelleNR& operator=(const LauBelleNR& rhs); //! The range parameter LauParameter* alpha_; //! The model to use LauAbsResonance::LauResonanceModel model_; //! Force use of Legendre spin factors Bool_t forceLegendre_; - ClassDef(LauBelleNR,0) }; #endif diff --git a/inc/LauBelleSymNR.hh b/inc/LauBelleSymNR.hh index 62e800c..8958b3c 100644 --- a/inc/LauBelleSymNR.hh +++ b/inc/LauBelleSymNR.hh @@ -1,147 +1,146 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleSymNR.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauBelleSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauBelleSymNR(); //! Initialise virtual void initialise(); //! 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 model_;} //! Is the amplitude pre-symmetrised? /*! \return kTRUE, indicating that the amplitude is already symmetrised */ virtual Bool_t preSymmetrised() const {return kTRUE;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the parameter alpha, the effective range /*! \param [in] alpha the new effective range parameter */ void setAlpha(const Double_t alpha); //! Get the effective range parameter /*! \return the effective range parameter */ Double_t getAlpha() const {return (alpha_!=0) ? alpha_->unblindValue() : 0.0;} //! See if the alpha parameter is fixed or floating Bool_t fixAlpha() const {return (alpha_!=0) ? alpha_->fixed() : kTRUE;} //! This is not called, amplitude is used directly instead virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauBelleSymNR(const LauBelleSymNR& rhs); //! Copy assignment operator (not implemented) LauBelleSymNR& operator=(const LauBelleSymNR& rhs); //! The range parameter LauParameter* alpha_; //! The model to use LauAbsResonance::LauResonanceModel model_; - ClassDef(LauBelleSymNR,0) // Belle Non-resonant model }; #endif diff --git a/inc/LauBifurcatedGaussPdf.hh b/inc/LauBifurcatedGaussPdf.hh index e4af84c..839c8cf 100644 --- a/inc/LauBifurcatedGaussPdf.hh +++ b/inc/LauBifurcatedGaussPdf.hh @@ -1,101 +1,100 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBifurcatedGaussPdf.hh \brief File containing declaration of LauBifurcatedGaussPdf class. */ /*! \class LauBifurcatedGaussPdf \brief Class for defining a bifurcated Gaussian PDF. Class that allows the user to define a bifurcated Gaussian PDF, a Gaussian that has different widths either side of the peak position. */ #ifndef LAU_BIFURCATED_GAUSS_PDF #define LAU_BIFURCATED_GAUSS_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauBifurcatedGaussPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean, sigmaL and sigmaR \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauBifurcatedGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauBifurcatedGaussPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauBifurcatedGaussPdf(const LauBifurcatedGaussPdf& other); //! Copy assignment operator (not implemented) LauBifurcatedGaussPdf& operator=(const LauBifurcatedGaussPdf& other); //! Gaussian mean LauAbsRValue* mean_; //! Sigma of left Gaussian LauAbsRValue* sigmaL_; //! Sigma of right Gaussian LauAbsRValue* sigmaR_; - ClassDef(LauBifurcatedGaussPdf,0) // Define the Bifurcated Gaussian PDF }; #endif diff --git a/inc/LauBkgndDPModel.hh b/inc/LauBkgndDPModel.hh index 7ea3d3f..54d8a16 100644 --- a/inc/LauBkgndDPModel.hh +++ b/inc/LauBkgndDPModel.hh @@ -1,172 +1,171 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBkgndDPModel.hh \brief File containing declaration of LauBkgndDPModel class. */ /*! \class LauBkgndDPModel \brief Class for defining a histogram-based background Dalitz plot model Class for defining a histogram-based background Dalitz plot model */ #ifndef LAU_BKGND_DP_MODEL #define LAU_BKGND_DP_MODEL #include #include "LauAbsBkgndDPModel.hh" class TH2; class Lau2DAbsDPPdf; class LauDaughters; class LauFitDataTree; class LauVetoes; class LauBkgndDPModel : public LauAbsBkgndDPModel { public: //! Constructor /*! \param [in] daughters the daughters in the decay \param [in] vetoes the vetoes in the Datliz plot */ LauBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes); //! Destructor virtual ~LauBkgndDPModel(); //! Set background histogram /*! \param [in] histo the 2D histogram describing the DP distribution \param [in] useInterpolation boolean flag to determine whether linear interpolation between bins should be used or simply the raw bin values \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setBkgndHisto(const TH2* histo, Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP = kFALSE); //! Set the background histogram and generate a spline /*! \param [in] histo the 2D histogram describing the DP distribution \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setBkgndSpline(const TH2* histo, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP); //! Initialise the model virtual void initialise(); //! Generate a toy MC event from the model /*! \return success/failure flag */ virtual Bool_t generate(); //! Get unnormalised likelihood for a given event /*! \param [in] iEvt the event number \return the unnormalised likelihood value */ virtual Double_t getUnNormValue(UInt_t iEvt); //! Get PDF normalisation constant /*! \return the PDF normalisation constant */ virtual Double_t getPdfNorm() const {return pdfNorm_;} //! Get likelihood for a given event /*! \param [in] iEvt the event number \return the likelihood value */ virtual Double_t getLikelihood(UInt_t iEvt); //! Cache the input data and (if appropriate) the per-event likelihood values /*! \param [in] fitDataTree the input data */ virtual void fillDataTree(const LauFitDataTree& fitDataTree); protected: //! Calulate histogram value at a given point /*! \param [in] xVal the x-value \param [in] yVal the y-value \return the histogram value */ Double_t calcHistValue(Double_t xVal, Double_t yVal); //! Set data event number /*! \param [in] iEvt the event number */ virtual void setDataEventNo(UInt_t iEvt); private: //! Copy constructor (not implemented) LauBkgndDPModel(const LauBkgndDPModel& rhs); //! Copy assignment operator (not implemented) LauBkgndDPModel& operator=(const LauBkgndDPModel& rhs); //! Flags whether the DP is symmetrical or not Bool_t symmetricalDP_; //! Flags whether or not to work in square DP coordinates Bool_t squareDP_; //! PDF of Dalitz plot background, from a 2D histogram Lau2DAbsDPPdf* bgHistDPPdf_; //! Cached histogram values for each event std::vector bgData_; //! Histogram value for the current event Double_t curEvtHistVal_; //! Maximum height of PDF Double_t maxPdfHeight_; //! Normalisation of PDF Double_t pdfNorm_; //! Boolean to indicate if the warning that there is no histogram has already been issued Bool_t doneGenWarning_; //! Flag to track whether a warning has been issued for bin values less than zero mutable Bool_t lowBinWarningIssued_; - ClassDef(LauBkgndDPModel,0) // DP background model }; #endif diff --git a/inc/LauBlattWeisskopfFactor.hh b/inc/LauBlattWeisskopfFactor.hh index 1f9d325..bb8ad05 100644 --- a/inc/LauBlattWeisskopfFactor.hh +++ b/inc/LauBlattWeisskopfFactor.hh @@ -1,146 +1,145 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBlattWeisskopfFactor.hh \brief File containing declaration of LauBlattWeisskopfFactor class. */ /*! \class LauBlattWeisskopfFactor \brief Class that implements the Blatt-Weisskopf barrier factor This factor is used in resonance models such as the Relativistic Breit-Wigner. */ #ifndef LAU_BLATTWEISSKOPFFACTOR #define LAU_BLATTWEISSKOPFFACTOR #include "Rtypes.h" #include "TString.h" class LauParameter; class LauResonanceInfo; class LauBlattWeisskopfFactor final { public: //! 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) */ }; //! Define the rest frame in which the momentum should be calculated (only relevant for bachelor) enum RestFrame { Covariant, /*!< use expression from Covariant spin factor */ ParentFrame, /*!< momentum calculated in parent rest frame */ ResonanceFrame /*!< momentum calculated in resonance rest frame */ }; //! Define resonance categories that will share common barrier factor radii enum BlattWeisskopfCategory { Default, //*!< indicates that LauResonanceMaker should use the appropriate category for the given resonance */ Parent, //*!< indicates that this is the factor for the decay of the parent particle */ Indep, //*!< indicates that this resonance should be independent of all others */ Light, //*!< default category for light unflavoured states, e.g. rho(77), f0(980), etc. */ Kstar, //*!< default category for K* states */ Charm, //*!< default category for D* states */ StrangeCharm, //*!< default category for Ds* states */ Charmonium, //*!< default category for ccbar states */ Beauty, //*!< default category for B* states */ StrangeBeauty, //*!< default category for Bs* states */ CharmBeauty, //*!< default category for Bc* states */ Custom1, //*!< user-defined category */ Custom2, //*!< user-defined category */ Custom3, //*!< user-defined category */ Custom4 //*!< user-defined category */ }; //! Constructor LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ); //! Constructor LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ); //! Constructor LauBlattWeisskopfFactor( const Int_t spin, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ); //! Method to create a new factor with cloned radius parameter /*! \param newSpin the value of the spin to use for the created instance \param newBarrierType the BarrierType to use for the created instance */ LauBlattWeisskopfFactor* createClone( const UInt_t newSpin , const BarrierType newBarrierType ); //! Retrieve the radius parameter const LauParameter* getRadiusParameter() const { return radius_; } //! Retrieve the radius parameter LauParameter* getRadiusParameter() { return radius_; } //! Retrieve the barrier type BarrierType getBarrierType() const { return barrierType_; } //! Retrieve the rest frame information RestFrame getRestFrame() const { return restFrame_; } //! Calculate form factor value /*! \param p the value of the momentum */ Double_t calcFormFactor( const Double_t p ) const; private: //! Copy constructor LauBlattWeisskopfFactor( const LauBlattWeisskopfFactor& other, const UInt_t newSpin, const BarrierType newBarrierType ); //! Copy assignment operator (not implemented) LauBlattWeisskopfFactor& operator=( const LauBlattWeisskopfFactor& other ); //! Set the name of the radius parameter TString setRadiusName( const LauResonanceInfo& resInfo, const BlattWeisskopfCategory category ); //! Set the name of the radius parameter TString setRadiusName( const BlattWeisskopfCategory category ); //! Set the name of the radius parameter TString setRadiusName( const TString& categoryName ); //! Resonance spin const UInt_t spin_; //! Radius parameter LauParameter* radius_; //! Barrier type const BarrierType barrierType_; //! Rest frame const RestFrame restFrame_; - ClassDef(LauBlattWeisskopfFactor, 0) }; #endif diff --git a/inc/LauBreitWignerRes.hh b/inc/LauBreitWignerRes.hh index efee832..d275d40 100644 --- a/inc/LauBreitWignerRes.hh +++ b/inc/LauBreitWignerRes.hh @@ -1,93 +1,92 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBreitWignerRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauBreitWignerRes(LauResonanceInfo* resInfo, const 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;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauBreitWignerRes(const LauBreitWignerRes& rhs); //! Copy assignment operator (not implemented) LauBreitWignerRes& operator=(const LauBreitWignerRes& rhs); - ClassDef(LauBreitWignerRes,0) // Breit-Wigner resonance model }; #endif diff --git a/inc/LauCPFitModel.hh b/inc/LauCPFitModel.hh index 8a052f4..38765c7 100644 --- a/inc/LauCPFitModel.hh +++ b/inc/LauCPFitModel.hh @@ -1,712 +1,711 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCPFitModel.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 #include "TString.h" #include "LauAbsFitModel.hh" #include "LauComplex.hh" #include "LauParameter.hh" class TH2; class LauAbsBkgndDPModel; class LauAbsCoeffSet; class LauIsobarDynamics; class LauAbsPdf; class LauEffModel; class LauEmbeddedData; class LauKinematics; class LauScfMap; class LauCPFitModel : public LauAbsFitModel { public: //! Constructor /*! \param [in] negModel DP model for the antiparticle \param [in] posModel DP model for the particle \param [in] tagged is the analysis tagged or untagged? \param [in] tagVarName the variable name in the data tree that specifies the event tag */ LauCPFitModel(LauIsobarDynamics* negModel, LauIsobarDynamics* 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 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(LauAbsRValue* 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 and option to fix it */ virtual void setNBkgndEvents(LauAbsRValue* nBkgndEvents, LauAbsRValue* 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 boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] fluctuateBins whether the bins on the histogram should be varied in accordance with their uncertainties (for evaluation of systematic uncertainties) \param [in] scfMap the (optional) smearing matrix */ void splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf = kFALSE, const Bool_t fluctuateBins = 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( const Double_t scfFrac, const 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement \param [in] useReweighting perform an accept/reject routine using the configured signal amplitude model based on the MC-truth DP coordinate */ 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement */ 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement \param [in] useReweighting perform an accept/reject routine using the configured signal amplitude model based on the MC-truth DP coordinate */ 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement */ void embedPosBkgnd(const TString& bgClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE); //! Set the DP amplitude coefficients /*! The name of the coeffSet must match the name of one of the resonances in the DP model for the antiparticle (the name of the conjugate state in the model for the particle will be automatically determined). The supplied order of coefficients will be rearranged to match the order in which the resonances are stored in the dynamics, see LauIsobarDynamics::addResonance. \param [in] coeffSet the set of coefficients */ virtual void setAmpCoeffSet(LauAbsCoeffSet* coeffSet); protected: //! Define a map to be used to store a category name and numbers typedef std::map< std::pair, std::pair > LauGenInfo; //! Typedef for a vector of background DP models typedef std::vector LauBkgndDPModelList; //! Typedef for a vector of background PDFs typedef std::vector LauBkgndPdfsList; //! Typedef for a vector of background yields typedef std::vector LauBkgndYieldList; //! Typedef for a vector of embedded data objects typedef std::vector LauBkgndEmbDataList; //! Typedef for a vector of booleans to flag if events are reused typedef std::vector LauBkgndReuseEventsList; //! 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 ); //! 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 stream to which to print */ virtual void printFitFractions(std::ostream& output); //! Print the asymmetries /*! \param [out] output the stream to which to print */ 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); //! Save the pdf Plots for all the resonances /*! \param [in] label prefix for the file name to be saved */ virtual void savePDFPlots(const TString& label); //! Save the pdf Plots for the sum of resonances of a given spin /*! \param [in] label prefix for the file name to be saved \param [in] spin spin of the wave to be saved */ virtual void savePDFPlotsWave(const TString& label, const Int_t& spin); //! 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 std::pair 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);} //! Append fake data points to the inputData for each bin in the SCF smearing matrix /*! 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 ); LauIsobarDynamics* getNegSigModel() {return negSigModel_;} LauIsobarDynamics* getPosSigModel() {return posSigModel_;} //! Retrieve a named parameter from a TTree /*! \param [in] tree a reference to the tree from which to obtain the parameters \param [in] name the name of the parameter to retrive */ Double_t getParamFromTree( TTree& tree, const TString& name ); //! Set a LauParameter to a given value /*! \param [in] param a pointer to the LauParameter to set \param [in] val the value to set \param [in] fix whether to fix the LauParameter or leave it floating */ void fixParam( LauParameter* param, const Double_t val, const Bool_t fix ); //! Set a vector of LauParameters according to the specified method /*! \param [in] params the vector of pointers to LauParameter to set values of */ void fixParams( std::vector& params ); private: //! Copy constructor (not implemented) LauCPFitModel(const LauCPFitModel& rhs); //! Copy assignment operator (not implemented) LauCPFitModel& operator=(const LauCPFitModel& rhs); //! The B- signal Dalitz plot model LauIsobarDynamics *negSigModel_; //! The B+ signal Dalitz plot model LauIsobarDynamics *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 normalisation parameters (yields, asymmetries) UInt_t nNormPar_; //! Magnitudes and Phases std::vector coeffPars_; //! The B- fit fractions LauParArray negFitFrac_; //! The B+ fit fractions LauParArray posFitFrac_; //! Fit B- fractions (uncorrected for the efficiency) LauParArray negFitFracEffUnCorr_; //! Fit B+ fractions (uncorrected for the efficiency) LauParArray posFitFracEffUnCorr_; //! The CP violating fit fraction LauParArray CPVFitFrac_; //! The CP conserving fit fraction LauParArray CPCFitFrac_; //! The fit fraction asymmetries std::vector fitFracAsymm_; //! A_CP parameter std::vector 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 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 recoSCFFracs_; //! The cached values of the SCF fraction for each bin centre std::vector fakeSCFFracs_; //! The cached values of the sqDP jacobians for each event std::vector recoJacobians_; //! The cached values of the sqDP jacobians for each true bin std::vector 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 negCoeffs_; //! The complex coefficients for B+ std::vector posCoeffs_; // Embedding full simulation 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 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 bkgndExtraLike_; //! Total signal likelihood Double_t sigTotalLike_; //! Total SCF likelihood Double_t scfTotalLike_; //! Total background likelihood(s) std::vector bkgndTotalLike_; - ClassDef(LauCPFitModel,0) // CP fit/ToyMC model }; #endif diff --git a/inc/LauCacheData.hh b/inc/LauCacheData.hh index 05492f5..a979cc0 100644 --- a/inc/LauCacheData.hh +++ b/inc/LauCacheData.hh @@ -1,254 +1,253 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCacheData.hh \brief File containing declaration of LauCacheData class. */ /*! \class LauCacheData \brief Class to contain cached data relating to an event. Contains information on the dynamics of the event and some additional information such as the efficiency and the self cross feed fraction. Used by the DP dynamics classes to store the cached event information. */ #ifndef LAU_CACHE_DATA #define LAU_CACHE_DATA #include #include class LauCacheData { public: //! Constructor LauCacheData(); //! Destructor virtual ~LauCacheData(); //! Copy constructor /*! \param [in] rhs the object to copy */ LauCacheData(const LauCacheData& rhs); //! Copy assignment operator /*! \param [in] rhs the object to clone */ LauCacheData& operator=(const LauCacheData& rhs); //! Set the invariant mass squared of the first and third daugthers /*! \param [in] m13Sq the invariant mass squared of the first and third daugthers */ inline void storem13Sq(Double_t m13Sq) {m13Sq_ = m13Sq;} //! Set the invariant mass squared of the second and third daugthers /*! \param [in] m23Sq the invariant mass squared of the second and third daugthers */ inline void storem23Sq(Double_t m23Sq) {m23Sq_ = m23Sq;} //! Set the square Dalitz plot coordinate, m' /*! \param [in] mPrime the square Dalitz plot coordinate, m' */ inline void storemPrime(Double_t mPrime) {mPrime_ = mPrime;} //! Set the square Dalitz plot coordinate, theta' /*! \param [in] thPrime the square Dalitz plot coordinate, theta' */ inline void storethPrime(Double_t thPrime) {thPrime_ = thPrime;} //! Set the tagging category /*! \param [in] tagCat the tagging category */ inline void storeTagCat(Int_t tagCat) {tagCat_ = tagCat;} //! Set the efficiency /*! \param [in] eff the efficiency */ inline void storeEff(Double_t eff) {eff_ = eff;} //! Set the fraction of poorly constructed events (the self cross feed fraction) /*! \param [in] scfFraction the fraction of poorly constructed events */ inline void storeScfFraction(Double_t scfFraction) {scfFraction_ = scfFraction;} //! Set the Jacobian for the transformation into square Dalitz coordinates /*! \param [in] jacobian the Jacobian */ inline void storeJacobian(Double_t jacobian) {jacobian_ = jacobian;} //! Set the real parts of the amplitudes /*! \param [in] realAmp the real parts of the amplitudes */ inline void storeRealAmp(const std::vector& realAmp) {realAmp_ = realAmp;} //! Set the imaginary parts of the amplitudes /*! \param [in] imagAmp the imaginary parts of the amplitudes */ inline void storeImagAmp(const std::vector& imagAmp) {imagAmp_ = imagAmp;} //! Set the incoherent intensities /*! \param [in] incohIntensities the intensities of the incoherent contributions */ inline void storeIncohIntensities(const std::vector& incohIntensities) {incohIntensities_ = incohIntensities;} //! Retrieve the invariant mass squared of the first and third daugthers /*! \return m13 squared */ inline Double_t retrievem13Sq() const {return m13Sq_;} //! Retrieve the invariant mass squared of the second and third daugthers /*! \return m23 squared */ inline Double_t retrievem23Sq() const {return m23Sq_;} //! Retrieve the square Dalitz plot coordinate, m' /*! \return m' */ inline Double_t retrievemPrime() const {return mPrime_;} //! Retrieve the square Dalitz plot coordinate, theta' /*! \return theta' */ inline Double_t retrievethPrime() const {return thPrime_;} //! Retrieve the tagging category /*! \return the tagging category */ inline Int_t retrieveTagCat() const {return tagCat_;} //! Retrieve the efficiency /*! \return the efficiency */ inline Double_t retrieveEff() const {return eff_;} //! Retrieve the fraction of poorly reconstructed events (the so-called self cross feed fraction) /*! \return the fraction of poorly reconstructed events */ inline Double_t retrieveScfFraction() const {return scfFraction_;} //! Retrieve the Jacobian for the transformation into square-Dalitz-plot coordinates /*! \return the Jacobian */ inline Double_t retrieveJacobian() const {return jacobian_;} //! Retrieve the real parts of the amplitudes /*! \return the real parts of the amplitudes */ inline const std::vector& retrieveRealAmp() const {return realAmp_;} //! Retrieve the imaginary parts of the amplitudes /*! \return the imaginary parts of the amplitudes */ inline const std::vector& retrieveImagAmp() const {return imagAmp_;} //! Retrieve the incoherent intensities /*! \return the intensities of the incoherent contributions */ inline const std::vector& retrieveIncohIntensities() const {return incohIntensities_;} //! Retrieve the real parts of the amplitudes /*! \return the real parts of the amplitudes */ inline std::vector& retrieveRealAmp() {return realAmp_;} //! Retrieve the imaginary parts of the amplitudes /*! \return the imaginary parts of the amplitudes */ inline std::vector& retrieveImagAmp() {return imagAmp_;} //! Retrieve the incoherent intensities /*! \return the intensities of the incoherent contributions */ inline std::vector& retrieveIncohIntensities() {return incohIntensities_;} protected: private: //! The invariant mass squared of the first and third daugthers Double_t m13Sq_; //! The invariant mass squared of the second and third daugthers Double_t m23Sq_; //! The square Dalitz plot coordinate, m' Double_t mPrime_; //! The square Dalitz plot coordinate, theta' Double_t thPrime_; //! The tagging category Int_t tagCat_; //! The efficiency Double_t eff_; //! The fraction of poorly constructed events (the self cross feed fraction) Double_t scfFraction_; //! The Jacobian for the transformation into square Dalitz coordinates Double_t jacobian_; //! The real parts of the amplitudes std::vector realAmp_; //! The imaginary parts of the amplitudes std::vector imagAmp_; //! The intensities of the incoherent contributions std::vector incohIntensities_; - ClassDef(LauCacheData,0) // Cached Data Class }; #endif diff --git a/inc/LauCalcChiSq.hh b/inc/LauCalcChiSq.hh index 7fec5cd..6160a49 100644 --- a/inc/LauCalcChiSq.hh +++ b/inc/LauCalcChiSq.hh @@ -1,163 +1,162 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #include "TH2Poly.h" #include "TString.h" #include /*! \file LauCalcChiSq.hh \brief File containing declaration of LauCalcChiSq class. */ /*! \class LauCalcChiSq \brief Utility class to allow the calculation of the chisq of the fit to the Dalitz plot A utility class to allow the calculation of the chisq of the fit to the Dalitz plot. A text config file is provided that gives the datasets for the data and toy MC generated from the fit results. These can be in the traditional DP or the square DP. A sample config file is provided. The fields are: */ class LauCalcChiSq { public: //! Constructor /*! \param [in] inputFileName name of the config file */ LauCalcChiSq(const TString& inputFileName = "chiSqInput.txt"); //! Destructor virtual ~LauCalcChiSq(); //! Toggle verbose printout /*! \param [in] flag true to enable verbose printout, false to disable */ inline void setVerbose(const Bool_t flag) {verbose_ = flag;} //! Run the calculations void run(); private: //! Read the config file, read the data and create histograms void initialiseHistos(); //! Choose the binning scheme /*! \param [in] xs x coordinates of low statistics sample \param [in] ys y coordinates of low statistics sample \param [in] nEntries number of entries in low statistics sample \param [out] divisions resulting binning scheme */ void pickBinning(const Double_t* xs, const Double_t* ys, const Int_t nEntries, std::vector& divisions); //! Create the template histogram based on the binning scheme /*! This function is called recursively to perform subdivisions \param [in] xMin the minimum x coordinate of the region to be (sub)divided \param [in] xMax the maximum x coordinate of the region to be (sub)divided \param [in] yMin the minimum y coordinate of the region to be (sub)divided \param [in] yMax the maximum y coordinate of the region to be (sub)divided \param [in] xs x coordinates of low statistics sample \param [in] ys y coordinates of low statistics sample \param [in] nEntries number of entries in low statistics sample \param [in] divisions the binning scheme \param [in] iter indicates depth of the subdivisions */ void getHisto(const Double_t xMin, const Double_t xMax, const Double_t yMin, const Double_t yMax, const Double_t* xs, const Double_t* ys, const Int_t nEntries, const std::vector& divisions, const UInt_t iter=0); //! Calculate the chisq from the data histograms void calculateChiSq(); //! Create plots void makePlots(); //! Name of the config file TString inputFileName_; //! Name of the low stats data file TString fileName1_; //! Name of the high stats data file TString fileName2_; //! Name of the low stats data tree TString treeName1_; //! Name of the high stats data tree TString treeName2_; //! Name of the x-coordinate branch in tree 1 TString xName1_; //! Name of the x-coordinate branch in tree 2 TString xName2_; //! Name of the y-coordinate branch in tree 1 TString yName1_; //! Name of the y-coordinate branch in tree 2 TString yName2_; //! The minimum bin content Float_t minContent_; //! Template histogram constructed from the binning scheme TH2Poly* theHisto_; //! Histogram (constructed from template) filled from tree 1 TH2Poly* histo1_; //! Histogram (constructed from template) filled from tree 2 TH2Poly* histo2_; //! Histogram (constructed from template) filled with pulls of tree1 vs tree2 TH2Poly* pullHisto_; //! Histogram (constructed from template) filled with chisq of tree1 vs tree2 TH2Poly* chiSqHisto_; //! Histogram (constructed from template) filled with signed chisq of tree1 vs tree2 TH2Poly* chiSqSignedHisto_; //! Minimum x coordinate of histograms Float_t xMin_; //! Maximum x coordinate of histograms Float_t xMax_; //! Minimum y coordinate of histograms Float_t yMin_; //! Maximum y coordinate of histograms Float_t yMax_; //! Number of free parameters in fit (used for calculating the ndof) Int_t nParams_; //! Scalefactor between low and high stats data samples Float_t scaleFactor_; //! Verbose flag Bool_t verbose_; - ClassDef(LauCalcChiSq,0) }; diff --git a/inc/LauCartesianCPCoeffSet.hh b/inc/LauCartesianCPCoeffSet.hh index 5e0a061..3bb0723 100644 --- a/inc/LauCartesianCPCoeffSet.hh +++ b/inc/LauCartesianCPCoeffSet.hh @@ -1,173 +1,172 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianCPCoeffSet.hh \brief File containing declaration of LauCartesianCPCoeffSet class. */ /*! \class LauCartesianCPCoeffSet \brief Class for defining a complex coefficient using the Cartesian CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form x +/- delta_x + i * ( y +/- delta_y ). [Phys.Rev. D78 (2008) 012004] */ #ifndef LAU_CARTESIANCP_COEFF_SET #define LAU_CARTESIANCP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauCartesianCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] x the average real part \param [in] y the average imaginary part \param [in] deltaX the asymmetric real part \param [in] deltaY the asymmetric imaginary part \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed \param [in] deltaXFixed whether deltaX is fixed \param [in] deltaYFixed whether deltaY is fixed \param [in] deltaXSecondStage whether deltaX should be floated only in the second stage of the fit \param [in] deltaYSecondStage whether deltaY should be floated only in the second stage of the fit */ LauCartesianCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t deltaX, Double_t deltaY, Bool_t xFixed, Bool_t yFixed, Bool_t deltaXFixed, Bool_t deltaYFixed, Bool_t deltaXSecondStage = kFALSE, Bool_t deltaYSecondStage = kFALSE); //! Destructor virtual ~LauCartesianCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauCartesianCPCoeffSet(const LauCartesianCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet& operator=(const LauCartesianCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The average real part LauParameter* x_; //! The average imaginary part LauParameter* y_; //! The asymmetric real part LauParameter* deltaX_; //! The asymmetric imaginary part LauParameter* deltaY_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauCartesianCPCoeffSet, 0) }; #endif diff --git a/inc/LauCartesianGammaCPCoeffSet.hh b/inc/LauCartesianGammaCPCoeffSet.hh index 6949c01..f500919 100644 --- a/inc/LauCartesianGammaCPCoeffSet.hh +++ b/inc/LauCartesianGammaCPCoeffSet.hh @@ -1,190 +1,189 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianGammaCPCoeffSet.hh \brief File containing declaration of LauCartesianGammaCPCoeffSet class. */ /*! \class LauCartesianGammaCPCoeffSet \brief Class for defining a complex coefficient using the Cartesian gamma CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form ( x + i * y ) * ( 1 + xCP +/- delta_xCP + i * ( yCP +/- delta_yCP ) ). [Phys. Rev. D79, 051301 (2009)] */ #ifndef LAU_CARTESIANGAMMACP_COEFF_SET #define LAU_CARTESIANGAMMACP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauCartesianGammaCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] x the real nonCP part \param [in] y the imaginary nonCP part \param [in] xCP the average real CP part \param [in] yCP the average imaginary CP part \param [in] deltaXCP the asymmetric real CP part \param [in] deltaYCP the asymmetric imaginary CP part \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed \param [in] xCPFixed whether xCP is fixed \param [in] yCPFixed whether yCP is fixed \param [in] deltaXCPFixed whether deltaXCP is fixed \param [in] deltaYCPFixed whether deltaYCP is fixed \param [in] deltaXCPSecondStage whether deltaXCP should be floated only in the second stage of the fit \param [in] deltaYCPSecondStage whether deltaYCP should be floated only in the second stage of the fit */ LauCartesianGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t deltaXCP, const Double_t deltaYCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t deltaXCPFixed, const Bool_t deltaYCPFixed, const Bool_t deltaXCPSecondStage = kFALSE, const Bool_t deltaYCPSecondStage = kFALSE); //! Destructor virtual ~LauCartesianGammaCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! This method is not supported by this class because there are more than four parameters so there is not a unique solution. \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauCartesianGammaCPCoeffSet(const LauCartesianGammaCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet& operator=(const LauCartesianGammaCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The nonCP real part LauParameter* x_; //! The nonCP imaginary part LauParameter* y_; //! The average CP real part LauParameter* xCP_; //! The average CP imaginary part LauParameter* yCP_; //! The asymmetric CP real part LauParameter* deltaXCP_; //! The asymmetric CP imaginary part LauParameter* deltaYCP_; //! The nonCP part of the complex coefficient LauComplex nonCPPart_; //! The CP part of the complex coefficient for the particle LauComplex cpPart_; //! The CP part of the complex coefficient for the antiparticle LauComplex cpAntiPart_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauCartesianGammaCPCoeffSet, 0) }; #endif diff --git a/inc/LauChebychevPdf.hh b/inc/LauChebychevPdf.hh index 2eeb7e9..b94b650 100644 --- a/inc/LauChebychevPdf.hh +++ b/inc/LauChebychevPdf.hh @@ -1,108 +1,107 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauChebychevPdf.hh \brief File containing declaration of LauChebychevPdf class. */ /*! \class LauChebychevPdf \brief Class for defining a Chebychev Polynomial (1st kind) PDF. Class that allows the user to define a Chebychev Polynomial (1st kind) PDF. The guts of the implementation are from Gerhard Raven's RooFit class. */ /***************************************************************************** * Class based on RooFit/RooChebychev. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef LAU_CHEBYCHEV_PDF #define LAU_CHEBYCHEV_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauChebychevPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - the polynomial coefficients (polynomial can be anything from 0 to 7 orders). \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauChebychevPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauChebychevPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); private: //! Copy constructor (not implemented) LauChebychevPdf(const LauChebychevPdf& other); //! Copy assignment operator (not implemented) LauChebychevPdf& operator=(const LauChebychevPdf& other); //! Coefficients of polynomial std::vector coeffs_; - ClassDef(LauChebychevPdf,0) // Chebychev PDF }; #endif diff --git a/inc/LauCleoCPCoeffSet.hh b/inc/LauCleoCPCoeffSet.hh index 7ef14a5..5e3eecb 100644 --- a/inc/LauCleoCPCoeffSet.hh +++ b/inc/LauCleoCPCoeffSet.hh @@ -1,177 +1,176 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCleoCPCoeffSet.hh \brief File containing declaration of LauCleoCPCoeffSet class. */ /*! \class LauCleoCPCoeffSet \brief Class for defining a complex coefficient using the Cleo CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form (a +/- b) * exp( i*(delta +/- phi) ) where a is the average magnitude, b is the asymmetric magnitude, delta is the strong phase and phi is the weak phase. [Phys.Rev. D70 (2004) 091101] */ #ifndef LAU_CLEOCP_COEFF_SET #define LAU_CLEOCP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauCleoCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] a the magnitude a \param [in] delta the strong phase \param [in] b the magnitude b \param [in] phi the weak phase \param [in] aFixed whether a is fixed \param [in] deltaFixed whether delta is fixed \param [in] bFixed whether b is fixed \param [in] phiFixed whether phi is fixed \param [in] bSecondStage whether b should be floated only in the second stage of the fit \param [in] phiSecondStage whether phi should be floated only in the second stage of the fit */ LauCleoCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage = kFALSE, Bool_t phiSecondStage = kFALSE); //! Destructor virtual ~LauCleoCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauCleoCPCoeffSet(const LauCleoCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet& operator=(const LauCleoCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude a LauParameter* a_; //! The magnitude b LauParameter* b_; //! The strong phase LauParameter* delta_; //! The weak phase LauParameter* phi_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauCleoCPCoeffSet, 0) }; #endif diff --git a/inc/LauComplex.hh b/inc/LauComplex.hh index 935a283..e285ac7 100644 --- a/inc/LauComplex.hh +++ b/inc/LauComplex.hh @@ -1,357 +1,356 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauComplex.hh \brief File containing declaration of LauComplex class. */ /*! \class LauComplex \brief Class for defining a complex number Class for complex number manipulation. In the function descriptions, the form (a,b) is used to represent a complex number. This is equivalent to the mathematical expression a + ib. */ /***************************************************************************** * Class based on RooFit/RooComplex. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef LAU_COMPLEX #define LAU_COMPLEX #include #include "Rtypes.h" #include "TMath.h" class LauComplex { public: //! Default Constructor inline LauComplex() : re_(0.0), im_(0.0) {} //! Constructor /*! \param [in] a the value corresponding to the real part of the complex number \param [in] b the value corresponding to the imaginary part of the complex number */ inline LauComplex(Double_t a, Double_t b) : re_(a), im_(b) {} //! Destructor virtual ~LauComplex() {} //! Copy constructor /*! \param [in] other the complex number to be copied */ inline LauComplex(const LauComplex& other) : re_(other.re_), im_(other.im_) {} //! Copy assignment operator /*! \param [in] other the complex number to be copied \return the assigned complex number */ inline LauComplex& operator=(const LauComplex& other) { if ( &other != this ) { re_ = other.re_; im_ = other.im_; } return *this; } //! Unary minus operator /*! \return the negated complex number */ inline LauComplex operator-() const { return LauComplex(-re_,-im_); } //! Addition operator /*! \param [in] other the object to added to this one \return the sum of the two complex numbers */ inline LauComplex operator+(const LauComplex& other) const { LauComplex tmpCmplx( *this ); tmpCmplx += other; return tmpCmplx; } //! Subtraction operator /*! \param [in] other the object to be subtracted from this one \return the difference of the two complex numbers */ inline LauComplex operator-(const LauComplex& other) const { LauComplex tmpCmplx( *this ); tmpCmplx -= other; return tmpCmplx; } //! Multiplication operator /*! \param [in] other the object this one is to be multiplied by \return the product of the two complex numbers */ inline LauComplex operator*(const LauComplex& other) const { LauComplex tmpCmplx( *this ); tmpCmplx *= other; return tmpCmplx; } //! Division operator /*! \param [in] other the object this one is to be divided by \return the ratio of the two complex numbers */ inline LauComplex operator/(const LauComplex& other) const { LauComplex tmpCmplx( *this ); tmpCmplx /= other; return tmpCmplx; } //! Addition assignment operator /*! \param [in] other the object to be added to this one \return the result of the addition */ inline LauComplex operator+=(const LauComplex& other) { this->re_ += other.re_; this->im_ += other.im_; return (*this); } //! Subtraction assignment operator /*! \param [in] other the object to be subtracted from this one \return the result of the subtraction */ inline LauComplex operator-=(const LauComplex& other) { this->re_ -= other.re_; this->im_ -= other.im_; return (*this); } //! Multiplication assignment operator /*! \param [in] other the object this one is to be multiplied by \return the result of the multiplication */ inline LauComplex operator*=(const LauComplex& other) { Double_t realPart = this->re_*other.re_ - this->im_*other.im_; Double_t imagPart = this->re_*other.im_ + this->im_*other.re_; this->setRealImagPart( realPart, imagPart ); return (*this); } //! Division assignment operator /*! \param [in] other the object this one is to be divided by \return the results of the division */ inline LauComplex operator/=(const LauComplex& other) { Double_t x(other.abs2()); Double_t realPart = (this->re_*other.re_ + this->im_*other.im_)/x; Double_t imagPart = (this->im_*other.re_ - this->re_*other.im_)/x; this->setRealImagPart( realPart, imagPart ); return (*this); } //! Boolean comparison operator /*! \param [in] other the object to compared with this one \return true/false for the comparison */ inline Bool_t operator==(const LauComplex& other) const { return (re_==other.re_ && im_==other.im_) ; } //! Get the real part /*! \return the real part of the complex number */ inline Double_t re() const { return re_; } //! Get the imaginary part /*! \return the imaginary part of the complex number */ inline Double_t im() const { return im_; } //! Obtain the absolute value of the complex number /*! \return the absolute value (magnitude) */ inline Double_t abs() const { return TMath::Sqrt( this->abs2() ); } //! Obtain the square of the absolute value of the complex number /*! \return the square of the absolute value (magnitude^2) */ inline Double_t abs2() const { return re_*re_ + im_*im_; } //! Obtain the phase angle of the complex number /*! \return the phase angle of the complex number */ inline Double_t arg() const { return TMath::ATan2( im_, re_ ); } //! Obtain the exponential of the complex number /*! \return the exponential of the complex number */ inline LauComplex exp() const { Double_t mag(TMath::Exp(re_)); return LauComplex(mag*TMath::Cos(im_),mag*TMath::Sin(im_)); } //! Obtain the complex conjugate /*! \return the complex conjugate */ inline LauComplex conj() const { return LauComplex(re_,-im_); } //! Transform this to its complex conjugate inline void makeConj() { im_ = -im_; } //! Obtain the complex number scaled by some factor /*! \param [in] scaleVal the value used to scale the complex number \return the complex number scaled by the scaleVal */ inline LauComplex scale(Double_t scaleVal) const { return LauComplex(scaleVal*re_, scaleVal*im_); } //! Scale this by a factor /*! \param [in] scaleVal the value used to scale the complex number */ inline void rescale(Double_t scaleVal) { re_ *= scaleVal; im_ *= scaleVal; } //! Set the real part /*! \param [in] realpart the value to be set as the real part */ inline void setRealPart(Double_t realpart) { re_ = realpart; } //! Set the imaginary part /*! \param [in] imagpart the value to be set as the imaginary part */ inline void setImagPart(Double_t imagpart) { im_ = imagpart; } //! Set both real and imaginary part /*! \param [in] realpart the value to be set as the real part \param [in] imagpart the value to be set as the imaginary part */ inline void setRealImagPart(Double_t realpart, Double_t imagpart) { this->setRealPart( realpart ); this->setImagPart( imagpart ); } //! Set both real and imaginary part to zero inline void zero() { this->setRealImagPart(0.0,0.0); } //! Print the complex number void print() const; private: //! The real part Double_t re_; //! The imaginary part Double_t im_; - ClassDef(LauComplex,0) // a non-persistent bare-bones complex class }; //! input/output operator formatting of a complex number std::istream& operator>>(std::istream& os, LauComplex& z); std::ostream& operator<<(std::ostream& os, const LauComplex& z); #endif diff --git a/inc/LauCruijffPdf.hh b/inc/LauCruijffPdf.hh index f54998b..23ccce9 100644 --- a/inc/LauCruijffPdf.hh +++ b/inc/LauCruijffPdf.hh @@ -1,116 +1,115 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCruijffPdf.hh \brief File containing declaration of LauCruijffPdf class. */ /*! \class LauCruijffPdf \brief Class for defining a Cruijff PDF. Class that allows the user to define a Cruijff PDF, a bifurcated Gaussian with asymmetric tails. The guts of the implementation have been copied from Wouter Hulsbergen's RooFit class. */ /***************************************************************************** * Class based on RooFit/RooCruijff. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef LAU_CRUIJFF_PDF #define LAU_CRUIJFF_PDF #include "TString.h" #include "TRandom.h" #include "LauAbsPdf.hh" #include "LauParameter.hh" #include using std::vector; class LauCruijffPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean, sigmaR, sigmaL, alphaR and alphaL \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauCruijffPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauCruijffPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauCruijffPdf(const LauCruijffPdf& other); //! Copy assignment operator (not implemented) LauCruijffPdf& operator=(const LauCruijffPdf& other); //! Gaussian mean LauAbsRValue* mean_; //! Sigma of left Gaussian LauAbsRValue* sigmaL_; //! Sigma of right Gaussian LauAbsRValue* sigmaR_; //! Alpha of left Gaussian LauAbsRValue* alphaL_; //! Alpha of right Gaussian LauAbsRValue* alphaR_; - ClassDef(LauCruijffPdf,0) // Define the Cruijff PDF }; #endif diff --git a/inc/LauCrystalBallPdf.hh b/inc/LauCrystalBallPdf.hh index d6ec37a..b256b13 100644 --- a/inc/LauCrystalBallPdf.hh +++ b/inc/LauCrystalBallPdf.hh @@ -1,124 +1,123 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCrystalBallPdf.hh \brief File containing declaration of LauCrystalBallPdf class. */ /*! \class LauCrystalBallPdf \brief Class for defining a Crystal Ball PDF. Class that allows the user to define a Crystal Ball PDF, a Gaussian with power law tail on one side. The guts of the implementation have been copied from RooFit. */ /***************************************************************************** * Class based on RooFit/RooCBShape. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef LAU_CRYSTAL_BALL_PDF #define LAU_CRYSTAL_BALL_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauCrystalBallPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean and sigma of the Gaussian, alpha (the distance from the mean in which the Gaussian and the tail are matched up), n (power for the tail) \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauCrystalBallPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauCrystalBallPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Calculate the approximate error function of argument /*! \param [in] arg the argument for which to calculate the error function \return error function of argument */ Double_t approxErf(Double_t arg) const; private: //! Copy constructor (not implemented) LauCrystalBallPdf(const LauCrystalBallPdf& other); //! Copy assignment operator (not implemented) LauCrystalBallPdf& operator=(const LauCrystalBallPdf& other); //! Gaussian mean LauAbsRValue* mean_; //! Gaussian sigma LauAbsRValue* sigma_; //! Alpha - distance from the mean in which the Gaussian and the tail are matched up LauAbsRValue* alpha_; //! Power for tail (goes as 1/x^n) LauAbsRValue* n_; - ClassDef(LauCrystalBallPdf,0) // Define the Crystal Ball PDF }; #endif diff --git a/inc/LauDPDepBifurGaussPdf.hh b/inc/LauDPDepBifurGaussPdf.hh index a649484..f849139 100644 --- a/inc/LauDPDepBifurGaussPdf.hh +++ b/inc/LauDPDepBifurGaussPdf.hh @@ -1,175 +1,174 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepBifurGaussPdf.hh \brief File containing declaration of LauDPDepBifurGaussPdf class. */ /*! \class LauDPDepBifurGaussPdf \brief Class for defining a Bifurcated Gaussian PDF (DP dependent). Class that allows the user to define a Bifurcated Gaussian PDF where one or more of the parameters have a dependence on the DP position. */ #ifndef LAU_DPDEP_BIFURGAUSS_PDF #define LAU_DPDEP_BIFURGAUSS_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauDPDepBifurGaussPdf : public LauAbsPdf { public: //! Define possibilties for the DP axes enum DPAxis { M12, /*!< dependence is on m^2_12 */ M13, /*!< dependence is on m^2_13 */ M23, /*!< dependence is on m^2_23 */ CentreDist, /*!< dependence is on the distance from the DP centre */ MMIN, /*!< dependence is on the minimum of m^2_13 and m^2_23 */ MMAX /*!< dependence is on the maximum of m^2_13 and m^2_23 */ }; //! Define possibilties for the scaling method enum ScaleMethod { poly, /*!< dependence is polynomial */ polyNegPower /*!< dependence is a Laurent polynomial with only negative powers */ }; //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean and sigma \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa \param [in] daughters the daughter particles \param [in] meanCoeffs the coefficients of the DP dependence of the Gaussian mean \param [in] sigmaLCoeffs the coefficients of the DP dependence of the sigma for the left Gaussian \param [in] sigmaRCoeffs the coefficients of the DP dependence of the sigma for the right Gaussian \param [in] dpAxis the DP axis that defines the parameter dependence */ LauDPDepBifurGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaLCoeffs, const std::vector& sigmaRCoeffs, DPAxis dpAxis); //! Destructor virtual ~LauDPDepBifurGaussPdf(); //! Specifies whether or not the PDF is DP dependent. /*! \return true if the PDF is DP-dependent (the default) */ virtual Bool_t isDPDependent() const {return kTRUE;} //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); //! Retrieve scaling method information /*! \return scaling method */ ScaleMethod scaleMethod() const {return scaleMethod_;} //! Set the scaling method /*! \param [in] method the scaling method */ void scaleMethod(ScaleMethod method) {scaleMethod_ = method;} protected: //! Scale the Gaussian parameters with polynomial method /*! \param [in] perEventDist the event distribution */ void scalePars_poly(Double_t perEventDist); //! Scale the Gaussian parameters with negative power polynomial method /*! \param [in] perEventDist the event distribution */ void scalePars_polyNegPower(Double_t perEventDist); private: //! Copy constructor (not implemented) LauDPDepBifurGaussPdf(const LauDPDepBifurGaussPdf& other); //! Copy assignment operator (not implemented) LauDPDepBifurGaussPdf& operator=(const LauDPDepBifurGaussPdf& other); //! The current DP kinematics const LauKinematics* kinematics_; //! Gaussian mean LauAbsRValue* mean_; //! Left Gaussian sigma LauAbsRValue* sigmaL_; //! Right Gaussian sigma LauAbsRValue* sigmaR_; //! Gaussian mean Double_t meanVal_; //! Left Gaussian sigma Double_t sigmaLVal_; //! Right Gaussian sigma Double_t sigmaRVal_; //! Coefficients of Gaussian mean const std::vector meanCoeffs_; //! Coefficients of left Gaussian sigma const std::vector sigmaLCoeffs_; //! Coefficients of right Gaussian sigma const std::vector sigmaRCoeffs_; //! The DP axis we depend on DPAxis dpAxis_; //! Scaling method information ScaleMethod scaleMethod_; - ClassDef(LauDPDepBifurGaussPdf,0) // Define the MVA PDF }; #endif diff --git a/inc/LauDPDepCruijffPdf.hh b/inc/LauDPDepCruijffPdf.hh index f22a185..2b4fd8b 100644 --- a/inc/LauDPDepCruijffPdf.hh +++ b/inc/LauDPDepCruijffPdf.hh @@ -1,186 +1,185 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepCruijffPdf.hh \brief File containing declaration of LauDPDepCruijffPdf class. */ /*! \class LauDPDepCruijffPdf \brief Class for defining a Cruijff PDF (with DP dependence). Class that allows the user to define a Cruijff PDF where one or more of the parameters have a polynomial dependence on the DP position. */ #ifndef LAU_DPDEP_CRUIJFF_PDF #define LAU_DPDEP_CRUIJFF_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauDaughters; class LauKinematics; class LauParameter; class LauDPDepCruijffPdf : public LauAbsPdf { public: //! Define possibilties for the DP axes enum DPAxis { M12, /*!< dependence is on m^2_12 */ M13, /*!< dependence is on m^2_13 */ M23, /*!< dependence is on m^2_23 */ CentreDist, /*!< dependence is on the distance from the DP centre */ MMIN, /*!< dependence is on the minimum of m^2_13 and m^2_23 */ MMAX /*!< dependence is on the maximum of m^2_13 and m^2_23 */ }; //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean, sigmaR, sigmaL, alphaR and alphaL \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa \param [in] daughters the daughter particles \param [in] meanCoeffs the coefficients of the DP dependence of the Gaussian mean \param [in] sigmaLCoeffs the coefficients of the DP dependence of the sigma for the left Gaussian \param [in] sigmaRCoeffs the coefficients of the DP dependence of the sigma for the right Gaussian \param [in] alphaLCoeffs the coefficients of the DP dependence of the alpha for the left Gaussian \param [in] alphaRCoeffs the coefficients of the DP dependence of the alpha for the right Gaussian \param [in] dpAxis the DP axis that defines the parameter dependence */ LauDPDepCruijffPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaLCoeffs, const std::vector& sigmaRCoeffs, const std::vector& alphaLCoeffs, const std::vector& alphaRCoeffs, DPAxis dpAxis); //! Destructor virtual ~LauDPDepCruijffPdf(); //! Specifies whether or not the PDF is DP dependent. /*! \return true if the PDF is DP-dependent (the default) */ virtual Bool_t isDPDependent() const {return kTRUE;} //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Scale parameters by their dependence on the DP position /*! \param [in] dpPos the DP position */ void scalePars( Double_t dpPos ); //! Current PDF value /*! \param [in] abscissa the values of the abscissa(s) */ Double_t currentPDFValue(Double_t abscissa) const; //! Integrate the PDF using the Gauss-Legendre method /*! \return the integral of the PDF */ virtual Double_t integrGaussLegendre(); //! Integrate the PDF using the simple trapezoid method /*! \return the integral of the PDF */ virtual Double_t integTrapezoid(); private: //! Copy constructor (not implemented) LauDPDepCruijffPdf(const LauDPDepCruijffPdf& other); //! Copy assignment operator (not implemented) LauDPDepCruijffPdf& operator=(const LauDPDepCruijffPdf& other); //! The current DP kinematics const LauKinematics* kinematics_; //! Gaussian mean LauAbsRValue* mean_; //! Sigma of left Gaussian LauAbsRValue* sigmaL_; //! Sigma of right Gaussian LauAbsRValue* sigmaR_; //! Alpha of left Gaussian LauAbsRValue* alphaL_; //! Alpha of right Gaussian LauAbsRValue* alphaR_; //! Gaussian mean Double_t meanVal_; //! Sigma of left Gaussian Double_t sigmaLVal_; //! Sigma of right Gaussian Double_t sigmaRVal_; //! Alpha of left Gaussian Double_t alphaLVal_; //! Alpha of right Gaussian Double_t alphaRVal_; //! Coefficients of Gaussian mean const std::vector meanCoeffs_; //! Coefficients of sigma for the left Gaussian const std::vector sigmaLCoeffs_; //! Coefficients of sigma for the right Gaussian const std::vector sigmaRCoeffs_; //! Coefficients of alpha for the left Gaussian const std::vector alphaLCoeffs_; //! Coefficients of alpha for the right Gaussian const std::vector alphaRCoeffs_; //! The DP axis we depend on DPAxis dpAxis_; - ClassDef(LauDPDepCruijffPdf,0) // Define the Cruijff PDF }; #endif diff --git a/inc/LauDPDepGaussPdf.hh b/inc/LauDPDepGaussPdf.hh index dfc88b6..4df9e01 100644 --- a/inc/LauDPDepGaussPdf.hh +++ b/inc/LauDPDepGaussPdf.hh @@ -1,144 +1,143 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepGaussPdf.hh \brief File containing declaration of LauDPDepGaussPdf class. */ /*! \class LauDPDepGaussPdf \brief Class for defining a Gaussian PDF (DP dependent). Class that allows the user to define a Gaussian PDF where one or more of the parameters have a polynomial dependence on the DP position. */ #ifndef LAU_DPDEP_GAUSS_PDF #define LAU_DPDEP_GAUSS_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauDaughters; class LauKinematics; class LauParameter; class LauDPDepGaussPdf : public LauAbsPdf { public: //! Define possibilties for the DP axes enum DPAxis { M12, /*!< dependence is on m^2_12 */ M13, /*!< dependence is on m^2_13 */ M23, /*!< dependence is on m^2_23 */ CentreDist, /*!< dependence is on the distance from the DP centre */ MMIN, /*!< dependence is on the minimum of m^2_13 and m^2_23 */ MMAX /*!< dependence is on the maximum of m^2_13 and m^2_23 */ }; //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean and sigma \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa \param [in] daughters the daughter particles \param [in] meanCoeffs the coefficients of the DP dependence of the Gaussian mean \param [in] sigmaCoeffs the coefficients of the DP dependence of the Gaussian sigma \param [in] dpAxis the DP axis that defines the parameter dependence */ LauDPDepGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaCoeffs, DPAxis dpAxis); //! Destructor virtual ~LauDPDepGaussPdf(); //! Specifies whether or not the PDF is DP dependent. /*! \return true if the PDF is DP-dependent (the default) */ virtual Bool_t isDPDependent() const {return kTRUE;} //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Scale parameters by their dependence on the DP position /*! \param [in] dpPos the DP position */ void scalePars( Double_t dpPos ); private: //! Copy constructor (not implemented) LauDPDepGaussPdf(const LauDPDepGaussPdf& other); //! Copy assignment operator (not implemented) LauDPDepGaussPdf& operator=(const LauDPDepGaussPdf& other); //! The current DP kinematics const LauKinematics* kinematics_; //! Gaussian mean LauAbsRValue* mean_; //! Gaussian sigma LauAbsRValue* sigma_; //! Gaussian mean Double_t meanVal_; //! Gaussian sigma Double_t sigmaVal_; //! Coefficients of Gaussian mean const std::vector meanCoeffs_; //! Coefficients of Gaussian sigma const std::vector sigmaCoeffs_; //! The DP axis we depend on DPAxis dpAxis_; - ClassDef(LauDPDepGaussPdf,0) // Define the Gaussian PDF }; #endif diff --git a/inc/LauDPDepMapPdf.hh b/inc/LauDPDepMapPdf.hh index 35d2b6f..ac585d2 100644 --- a/inc/LauDPDepMapPdf.hh +++ b/inc/LauDPDepMapPdf.hh @@ -1,161 +1,160 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepMapPdf.hh \brief File containing declaration of LauDPDepMapPdf class. */ /*! \class LauDPDepMapPdf \brief Class to allow having different PDFs in different regions of the DP. Class to allow having different PDFs in different regions of the DP. The DP regions are specified in a 2D histogram or in a 1D histogram of some projection of the DP. Each PDF is then associated with that region. */ #ifndef LAU_DPDEPMAP_PDF #define LAU_DPDEPMAP_PDF #include #include "Rtypes.h" #include "LauAbsPdf.hh" class LauDaughters; class Lau2DAbsDP; class LauParameter; class TH2; class TH1; class LauDPDepMapPdf : public LauAbsPdf { public: //! Define possibilties for the DP axes enum DPAxis { M12, /*!< dependence is on m^2_12 */ M13, /*!< dependence is on m^2_13 */ M23, /*!< dependence is on m^2_23 */ CentreDist, /*!< dependence is on the distance from the DP centre */ MMIN, /*!< dependence is on the minimum of m^2_13 and m^2_23 */ MMAX /*!< dependence is on the maximum of m^2_13 and m^2_23 */ }; //! Constructor - map described by 2D histogram /*! \param [in] pdfs the PDFs \param [in] daughters the daughter particles \param [in] dpHisto the 2D histogram \param [in] upperHalf boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) */ LauDPDepMapPdf( const std::vector &pdfs, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf = kFALSE); //! Constructor - map described by 1D histogram of a DP "axis" /*! \param [in] pdfs the PDFs \param [in] daughters the daughter particles \param [in] dpAxisHisto the 1D histogram \param [in] dpAxis the DP axis */ LauDPDepMapPdf( const std::vector &pdfs, const LauDaughters* daughters, const TH1* dpAxisHisto, DPAxis dpAxis); //! Destructor virtual ~LauDPDepMapPdf(); //! Specifies whether or not the PDF is DP dependent. /*! \return true if the PDF is DP-dependent (the default) */ virtual Bool_t isDPDependent() const {return kTRUE;} //! Cache information from data /*! \param [in] inputData the input data */ virtual void cacheInfo(const LauFitDataTree& inputData); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); //! Calculate the likelihood (and intermediate info) for a given event number /*! \param [in] iEvt event number */ virtual void calcLikelihoodInfo(UInt_t iEvt); //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Determine the DP region /*! \param [in] m13Sq the invariant mass squared of daughters 1 and 3 \param [in] m23Sq the invariant mass squared of daughters 2 and 3 */ UInt_t determineDPRegion( Double_t m13Sq, Double_t m23Sq ) const; private: //! Copy constructor - not implemented LauDPDepMapPdf(const LauDPDepMapPdf& other); //! Copy assignment operator - not implemented LauDPDepMapPdf& operator=(const LauDPDepMapPdf& other); //! Daughter particles LauDaughters* daughters_; //! The PDFs std::vector pdfs_; //! 2D histogram - DP Lau2DAbsDP* dpDependence_; //! 1D histogram - DP axis TH1* dpAxisDependence_; //! The DP axis we depend on DPAxis dpAxis_; //! Cached indices values std::vector indices_; - ClassDef(LauDPDepMapPdf,0) // Define the sum PDF }; #endif diff --git a/inc/LauDPDepSumPdf.hh b/inc/LauDPDepSumPdf.hh index aa358fa..f2eef3f 100644 --- a/inc/LauDPDepSumPdf.hh +++ b/inc/LauDPDepSumPdf.hh @@ -1,167 +1,166 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepSumPdf.hh \brief File containing declaration of LauDPDepSumPdf class. */ /*! \class LauDPDepSumPdf \brief Class for defining a PDF that is the DP-dependent sum of two other PDFs. Class for defining a PDF that is the sum of two other PDFs, where the relative fraction of the two PDFs depends on the Dalitz-plot position. */ #ifndef LAU_DPDEPSUM_PDF #define LAU_DPDEPSUM_PDF #include "Rtypes.h" #include "LauAbsPdf.hh" class LauDaughters; class LauEffModel; class LauParameter; class TH2; class LauDPDepSumPdf : public LauAbsPdf { public: //! Define possibilties for the DP axes enum DPAxis { M12, /*!< dependence is on m^2_12 */ M13, /*!< dependence is on m^2_13 */ M23, /*!< dependence is on m^2_23 */ CentreDist, /*!< dependence is on the distance from the DP centre */ MMIN, /*!< dependence is on the minimum of m^2_13 and m^2_23 */ MMAX /*!< dependence is on the maximum of m^2_13 and m^2_23 */ }; //! Constructor - fraction determined by 2D histogram /*! \param [in] pdf1 the first PDF \param [in] pdf2 the second PDF \param [in] daughters the daughter particles \param [in] dpHisto the 2D histogram \param [in] upperHalf boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] useSpline specifies whether a spline is used to interpolate the histogram */ LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf = kFALSE, Bool_t useSpline = kFALSE); //! Constructor - fraction determined by a polynomial of a DP "axis" /*! \param [in] pdf1 the first PDF \param [in] pdf2 the second PDF \param [in] frac the fractional contribution of the first PDF to the final PDF \param [in] daughters the daughter particles \param [in] fracCoeffs the coefficients of the DP dependence of the PDF fraction \param [in] dpAxis the DP axis that defines the parameter dependence */ LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac, const LauDaughters* daughters, const std::vector& fracCoeffs, DPAxis dpAxis); //! Destructor virtual ~LauDPDepSumPdf(); //! Specifies whether or not the PDF is DP dependent. /*! \return true if the PDF is DP-dependent (the default) */ virtual Bool_t isDPDependent() const {return kTRUE;} //! Cache information from data /*! \param [in] inputData the input data */ virtual void cacheInfo(const LauFitDataTree& inputData); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); //! Calculate the likelihood (and intermediate info) for a given event number /*! \param [in] iEvt event number */ virtual void calcLikelihoodInfo(UInt_t iEvt); //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Scale fraction according to DP position /*! \param [in] dpPos the DP position */ void scaleFrac( Double_t dpPos ); private: //! Copy constructor - not implemented LauDPDepSumPdf(const LauDPDepSumPdf& other); //! Copy assignment operator - not implemented LauDPDepSumPdf& operator=(const LauDPDepSumPdf& other); //! Daughter particles LauDaughters* daughters_; //! First PDF LauAbsPdf* pdf1_; //! Second PDF LauAbsPdf* pdf2_; //! Fractional contribution of first PDF to the final PDF LauAbsRValue* frac_; //! Fractional contribution of first PDF to the final PDF Double_t fracVal_; //! DP dependence LauEffModel* dpDependence_; //! Polynomial used to scale fraction const std::vector fracCoeffs_; //! The DP axis we depend on DPAxis dpAxis_; //! Cached values of fractions std::vector fractions_; - ClassDef(LauDPDepSumPdf,0) // Define the sum PDF }; #endif diff --git a/inc/LauDPPartialIntegralInfo.hh b/inc/LauDPPartialIntegralInfo.hh index b50fb8f..9f30398 100644 --- a/inc/LauDPPartialIntegralInfo.hh +++ b/inc/LauDPPartialIntegralInfo.hh @@ -1,275 +1,274 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPPartialIntegralInfo.hh \brief File containing declaration of LauDPPartialIntegralInfo class. */ /*! \class LauDPPartialIntegralInfo \brief Class for defining (a section of) the Dalitz plot integration binning scheme Defines the range and bin size of the integration grid. Stores the weights and Jacobian for each grid point. Also stores the amplitude values for each model component at each grid point. */ #ifndef LAU_DPPARTIALINTEGRAL_INFO #define LAU_DPPARTIALINTEGRAL_INFO #include #include "TString.h" #include "LauComplex.hh" class LauKinematics; class LauDPPartialIntegralInfo { public: //! Constructor /*! \param [in] minm13 the minimum of the m13 range \param [in] maxm13 the maximum of the m13 range \param [in] minm23 the minimum of the m23 range \param [in] maxm23 the maximum of the m23 range \param [in] m13BinWidth the m13 bin width \param [in] m23BinWidth the m23 bin width \param [in] precision the precision required for the Gauss-Legendre weights \param [in] nAmp the number of coherent amplitude components \param [in] nIncohAmp the number of incoherent amplitude components \param [in] squareDP whether or not to use the square DP for the integration - if so, m13 is actually mPrime and m23 is actually thetaPrime \param [in] kinematics the kinematics object to use to calculate the Jacobians (only relevant if squareDP is true) */ LauDPPartialIntegralInfo(const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp, const Bool_t squareDP = kFALSE, const LauKinematics* kinematics = 0); //! Destructor virtual ~LauDPPartialIntegralInfo(); //! Retrieve the minm13 of DP /*! \return the the minm13 of DP */ inline Double_t getMinm13() const {return minm13_;} //! Retrieve the maxm13 of DP /*! \return the the maxm13 of DP */ inline Double_t getMaxm13() const {return maxm13_;} //! Retrieve the minm23 of DP /*! \return the the minm23 of DP */ inline Double_t getMinm23() const {return minm23_;} //! Retrieve the maxm23 of DP /*! \return the the maxm23 of DP */ inline Double_t getMaxm23() const {return maxm23_;} //! Retrieve the m13BinWidth of DP /*! \return the the m13BinWidth of DP */ inline Double_t getM13BinWidth() const {return m13BinWidth_;} //! Retrieve the m23BinWidth of DP /*! \return the the m23BinWidth of DP */ inline Double_t getM23BinWidth() const {return m23BinWidth_;} //! Retrieve the number of bins in m13 /*! \return the number of bins in m13 */ inline UInt_t getnm13Points() const {return nm13Points_;} //! Retrieve the number of bins in m23 /*! \return the number of bins in m23 */ inline UInt_t getnm23Points() const {return nm23Points_;} //! Retrieve the square DP flag /*! \return whether or not the integration is performed in the square DP */ inline Bool_t getSquareDP() const {return squareDP_;} //! Retrieve the weight for the given grid point /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \return the value of the weight */ inline Double_t getWeight(const UInt_t m13Point, const UInt_t m23Point) const {return weights_[m13Point][m23Point];} //! Retrieve the m13 value at the given grid point /*! \param [in] m13Point the grid index in m13 \return the m13 value */ inline Double_t getM13Value(const UInt_t m13Point) const {return m13Points_[m13Point];} //! Retrieve the m23 value at the given grid point /*! \param [in] m23Point the grid index in m23 \return the m23 value */ inline Double_t getM23Value(const UInt_t m23Point) const {return m23Points_[m23Point];} //! Retrieve the efficiency for the given grid point /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \return the efficiency value */ inline Double_t getEfficiency(const UInt_t m13Point, const UInt_t m23Point) const { return efficiencies_[m13Point][m23Point]; } //! Store the efficiency for the given grid point /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \param [in] efficiency the new efficiency value */ inline void storeEfficiency(const UInt_t m13Point, const UInt_t m23Point, const Double_t efficiency) { efficiencies_[m13Point][m23Point] = efficiency; } //! Retrieve the amplitude for the given grid point and amplitude index /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \param [in] iAmp the amplitude index \return the amplitude value */ inline const LauComplex& getAmplitude(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp) const { return amplitudes_[m13Point][m23Point][iAmp]; } //! Store the amplitude for the given grid point and amplitude index /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \param [in] iAmp the amplitude index \param [in] amplitude the new amplitude value */ inline void storeAmplitude(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp, const LauComplex& amplitude) { amplitudes_[m13Point][m23Point][iAmp] = amplitude; } //! Retrieve the intensity for the given grid point and intensity index /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \param [in] iAmp the intensity index \return the intensity value */ inline Double_t getIntensity(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp) const { return incohIntensities_[m13Point][m23Point][iAmp]; } //! Store the intensity for the given grid point and intensity index /*! \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 \param [in] iAmp the intensity index \param [in] intensity the new intensity value */ inline void storeIntensity(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp, const Double_t intensity) { incohIntensities_[m13Point][m23Point][iAmp] = intensity; } private: //! Copy constructor (not implemented) LauDPPartialIntegralInfo( const LauDPPartialIntegralInfo& other ); //! Copy assignment operator (not implemented) LauDPPartialIntegralInfo& operator=( const LauDPPartialIntegralInfo& other ); //! The minimum of the m13 range const Double_t minm13_; //! The maximum of the m13 range const Double_t maxm13_; //! The minimum of the m23 range const Double_t minm23_; //! The maximum of the m23 range const Double_t maxm23_; //! The bin width for m13 const Double_t m13BinWidth_; //! The bin width for m23 const Double_t m23BinWidth_; //! The number of bins in m13 const UInt_t nm13Points_; //! The number of bins in m23 const UInt_t nm23Points_; //! The number of amplitude components const UInt_t nAmp_; //! The number of amplitude components const UInt_t nIncohAmp_; //! Flag whether or not we're using the square DP for the integration const Bool_t squareDP_; //! The m13 positions of the grid points std::vector m13Points_; //! The m23 positions of the grid points std::vector m23Points_; //! The Gauss-Legendre weights of the m13 grid points std::vector m13Weights_; //! The Gauss-Legendre weights of the m23 grid points std::vector m23Weights_; //! The combined weights at each 2D grid point std::vector< std::vector > weights_; //! The efficiency at each 2D grid point std::vector< std::vector > efficiencies_; //! The amplitude values at each 2D grid point std::vector< std::vector< std::vector > > amplitudes_; //! The incoherent intensity values at each 2D grid point std::vector< std::vector< std::vector > > incohIntensities_; - ClassDef(LauDPPartialIntegralInfo, 0) }; std::ostream& operator<<( std::ostream& stream, const LauDPPartialIntegralInfo& infoRecord ); #endif diff --git a/inc/LauDabbaRes.hh b/inc/LauDabbaRes.hh index a77ef7f..e3609bc 100644 --- a/inc/LauDabbaRes.hh +++ b/inc/LauDabbaRes.hh @@ -1,182 +1,181 @@ /* Copyright 2010 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file 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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauDabbaRes(LauResonanceInfo* resInfo, const 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 value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the b parameter /*! \param [in] b new value for b parameter */ void setBValue(const Double_t b); //! Set the alpha parameter /*! \param [in] alpha new value for alpha parameter */ void setAlphaValue(const Double_t alpha); //! Set the beta parameter /*! \param [in] beta new value for beta parameter */ void setBetaValue(const Double_t beta); //! Get the b parameter value /*! \return value of the b parameter */ Double_t getBValue() const { return (b_!=0) ? b_->unblindValue() : 0.0; } //! Get the alpha parameter value /*! \return value of the alpha parameter */ Double_t getAlphaValue() const { return (alpha_!=0) ? alpha_->unblindValue() : 0.0; } //! Get the beta parameter value /*! \return value of the beta parameter */ Double_t getBetaValue() const { return (beta_!=0) ? beta_->unblindValue() : 0.0; } //! Fix the b parameter value /*! \return kTRUE if the b parameter is fixed, kFALSE otherwise */ Bool_t fixBValue() const { return (b_!=0) ? b_->fixed() : 0.0; } //! Fix the alpha parameter value /*! \return kTRUE if the alpha parameter is fixed, kFALSE otherwise */ Bool_t fixAlphaValue() const { return (alpha_!=0) ? alpha_->fixed() : 0.0; } //! Fix the beta parameter value /*! \return kTRUE if the beta parameter is fixed, kFALSE otherwise */ Bool_t fixBetaValue() const { return (beta_!=0) ? beta_->fixed() : 0.0; } //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); //! Check that the daughter particles are D and pi void checkDaughterTypes() const; private: //! Copy constructor (not implemented) LauDabbaRes(const LauDabbaRes& rhs); //! Copy assignment operator (not implemented) LauDabbaRes& operator=(const LauDabbaRes& rhs); //! Defined as mD + mPi all squared Double_t mSumSq_; //! Defined as mD*mD - 0.5*mPi*mPi Double_t sAdler_; //! Constant factor LauParameter* b_; //! Constant factor LauParameter* alpha_; //! Constant factor LauParameter* beta_; - ClassDef(LauDabbaRes,0) // Dabba resonance model }; #endif diff --git a/inc/LauDatabasePDG.hh b/inc/LauDatabasePDG.hh index acb60a1..9f37e9b 100644 --- a/inc/LauDatabasePDG.hh +++ b/inc/LauDatabasePDG.hh @@ -1,147 +1,146 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDatabasePDG.hh \brief File containing declaration of LauDatabasePDG class. */ /*! \class LauDatabasePDG \brief Singleton class that provides access to particle property records. Singleton class that provides access to particle property records from the ROOT database and adds missing particles to the default setup. Particles may be accessed by both string and PDG code. */ #ifndef LAU_DATABASE_PDG #define LAU_DATABASE_PDG #include #include "TString.h" class TDatabasePDG; class LauParticlePDG; class LauDatabasePDG { public: //! Get particle object based on the PDG code /*! \param [in] code PDG code \return pointer to the particle record */ static const LauParticlePDG* particle(Int_t code); //! Get particle object based on the particle name string /*! \param [in] string particle name string \return pointer to the particle record */ static const LauParticlePDG* particle(const TString& string); //! Method to convert from a particle name string into a PDG code /*! \param [in] string the particle name string \return the corresponding PDG code */ static Int_t code(const TString& string); //! Method to convert from a PDG code to a particle name string /*! \param [in] code the particle PDG code \return the corresponding particle name */ static TString string(Int_t code); private: // private methods //! Constructor LauDatabasePDG(); //! Destructor virtual ~LauDatabasePDG(); //! Copy constructor (not inplemented) LauDatabasePDG( const LauDatabasePDG& other ); //! Copy assignment (not implemented) LauDatabasePDG& operator=( const LauDatabasePDG& other ); //! Get the database instance static LauDatabasePDG& get(); //! Add particles to the ROOT database that are missing from the default setup void addMissingParticles(); //! Create particle in the database for a given PDG code and return the new particle /*! \param [in] theCode PDG code of the associated particle \return pointer to the particle record */ const LauParticlePDG* createParticle(Int_t theCode); //! Create particle in the database for a given string and return the new particle /*! \param [in] theString particle string to be created \return pointer to the particle record */ const LauParticlePDG* createParticle(const TString& theString); //! Get the associated pdgCode for a given particle name string /*! \param [in] theString particle string to be associated to the pdgCode \return the corresponding PDG code */ Int_t pdgCode(const TString& theString); //! Get the associated name string for a given pdgCode /*! \param [in] theCode particle pdgCode \return the corresponding particle name */ TString pdgName(Int_t theCode); // private data //! The singleton instance static LauDatabasePDG* theInstance_; //! The ROOT database TDatabasePDG* theDatabase_; //! The type to hold the list of wrapped particle objects typedef std::map LauPDGList; //! The list of particle objects LauPDGList particles_; //! Debug flag - set in constructor const Bool_t debug_; - ClassDef(LauDatabasePDG,0) }; #endif diff --git a/inc/LauDaughters.hh b/inc/LauDaughters.hh index 7329515..bfd213a 100644 --- a/inc/LauDaughters.hh +++ b/inc/LauDaughters.hh @@ -1,219 +1,218 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDaughters.hh \brief File containing declaration of LauDaughters class. */ /*! \class LauDaughters \brief Class that defines the particular 3-body decay under study. The decay has the form P -> h1 h2 h3 (P stands for the parent particle, and h for the daughters). The constructor accepts both string name and PDG code types to describe the particles. */ #ifndef LAU_DAUGHTERS #define LAU_DAUGHTERS #include #include "TString.h" #include "LauKinematics.hh" class LauParticlePDG; class LauDaughters { public: //! Constructor from PDG codes /*! \param [in] codeParent the parent particle PDG code \param [in] code1 the first daughter PDG code \param [in] code2 the second daughter PDG code \param [in] code3 the third daughter PDG code \param [in] useSquareDP the boolean flag decision to use Square Dalitz plot (kTRUE) or standard Dalitz plot (kFALSE). Default value is kFALSE. */ LauDaughters(Int_t codeParent, Int_t code1, Int_t code2, Int_t code3, Bool_t useSquareDP = kFALSE); //! Constructor from particle names /*! \param [in] nameParent the parent particle string name \param [in] name1 the first daughter string name \param [in] name2 the second daughter string name \param [in] name3 the third daughter string name \param [in] useSquareDP the boolean flag decision to use Square Dalitz plot (kTRUE) or standard Dalitz plot (kFALSE). Default value is kFALSE. */ LauDaughters(const TString& nameParent, const TString& name1, const TString& name2, const TString& name3, Bool_t useSquareDP = kFALSE); //! Destructor virtual ~LauDaughters(); //! Copy constructor LauDaughters( const LauDaughters& rhs ); //! Is Dalitz plot symmetric, i.e. 2 identical particles /*! \return true/false whether the DP is symmetric */ Bool_t gotSymmetricalDP() const {return symmetricalDP_;} //! Is Dalitz plot fully symmetric, i.e. 3 identical particles /*! \return true/false whether the DP is fully symmetric */ Bool_t gotFullySymmetricDP() const {return fullySymmetricDP_;} //! Is Dalitz plot flavour-conjugate, i.e. CP(d1) = d2 and CP(d3) = d3 /*! \return true/false whether the DP is flavour-conjugate */ Bool_t gotFlavourConjugateDP() const {return flavourConjugateDP_;} //! Determine to use or not the square Dalitz plot /*! \return true/false to use the squareDP model */ Bool_t squareDP() const {return kinematics_->squareDP();} //! Get mass of first daughter particle Double_t getMassDaug1() const; //! Get mass of second daughter particle Double_t getMassDaug2() const; //! Get mass of third daughter particle Double_t getMassDaug3() const; //! Get mass of the parent particle Double_t getMassParent() const; //! Get name of the first daughter particle TString getNameDaug1() const; //! Get name of the second daughter particle TString getNameDaug2() const; //! Get name of the third daughter particle TString getNameDaug3() const; //! Get name of the parent particle TString getNameParent() const; //! Get sanitised name of the first daughter particle TString getSanitisedNameDaug1() const; //! Get sanitised name of the second daughter particle TString getSanitisedNameDaug2() const; //! Get sanitised name of the third daughter particle TString getSanitisedNameDaug3() const; //! Get sanitised name of the parent particle TString getSanitisedNameParent() const; //! Get PDG code of the first daughter particle Int_t getTypeDaug1() const; //! Get PDG code of the second daughter particle Int_t getTypeDaug2() const; //! Get PDG code of the third daughter particle Int_t getTypeDaug3() const; //! Get PDG code of the parent particle Int_t getTypeParent() const; //! Get charge of the first daughter particle Int_t getChargeDaug1() const; //! Get charge of the second daughter particle Int_t getChargeDaug2() const; //! Get charge of the third daughter particle Int_t getChargeDaug3() const; //! Get charge of the parent particle Int_t getChargeParent() const; //! Get charge of a particular two-daughter combination /*! \param [in] resPairAmpInt the index of the daughter not in the combination \return the charge of the two-daughter combination */ Int_t getCharge(Int_t resPairAmpInt) const; //! Retrieve the Dalitz plot kinematics /*! \return the Dalitz plot kinematics */ LauKinematics* getKinematics() {return kinematics_;} //! Retrieve the Dalitz plot kinematics /*! \return the Dalitz plot kinematics */ const LauKinematics* getKinematics() const {return kinematics_;} protected: //! Create list of all the allowed parent/daughter particles void createParticleLists(); //! Set the parent particle type /*! \param [in] nameParent the name of the parent particle */ void setParentType(const TString& nameParent); //! Set the three daughter types /*! \param [in] name1 the name of the first daughter \param [in] name2 the name of the second daughter \param [in] name3 the name of the third daughter */ void setDaugType(const TString& name1, const TString& name2, const TString& name3); //! Check whether there is a symmetrical Dalitz plot void testDPSymmetry(); //! Check masses and charges of daughters void sanityCheck(); private: //! Copy assignment operator (not implemented) LauDaughters& operator=( const LauDaughters& rhs ); //! Dalitz plot kinematics LauKinematics* kinematics_; //! All possible daughter types std::vector allowedDaughters_; //! All possible parent types std::vector allowedParents_; //! The parent particle const LauParticlePDG* parent_; //! The daughter particles std::vector daughters_; //! Boolean flag for symmetrical Dalitz plot Bool_t symmetricalDP_; //! Boolean flag for fully symmetric Dalitz plot Bool_t fullySymmetricDP_; //! Flavour-conjugate Dalitz plot Bool_t flavourConjugateDP_; - ClassDef(LauDaughters, 0) }; #endif diff --git a/inc/LauEFKLLMRes.hh b/inc/LauEFKLLMRes.hh index a05868b..ec67a53 100644 --- a/inc/LauEFKLLMRes.hh +++ b/inc/LauEFKLLMRes.hh @@ -1,147 +1,146 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEFKLLMRes.hh \brief File containing declaration of LauEFKLLMRes class. */ /*! \class LauEFKLLMRes \brief Class for defining the EFKLLM K-pi S-wave model Class for defining the EFKLLM form-factor model for the K-pi S-wave. The model consists of a tabulated form-factor, which is interpolated using cubic splines (one for magnitude values and one for phase values), multiplied by a mass-dependence (e.g. constant, 1/m^2, etc.). The massFactor resonance parameter is the power of the mass dependence - defaults to zero, i.e. constant. For more details see B. El-Bennich et al. Phys. Rev. D 79, 094005 (2009), arXiv:0902.3645 [hep-ph]. (The acronym EFKLLM is constructed from the surnames of the authors of the above paper.) */ #ifndef LAU_EFKLLM_RES #define LAU_EFKLLM_RES #include "TString.h" #include "LauComplex.hh" #include "LauAbsResonance.hh" class Lau1DCubicSpline; class LauEFKLLMRes : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauEFKLLMRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauEFKLLMRes(); //! Read the form factor information from text file /*! Creates the splines from the tabulated form factor data. These are shared between all instances of this class. \param [in] inputFile the name of the file to be read */ static void setupFormFactor(const TString& inputFile); //! Initialise the model virtual void initialise(); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::EFKLLM;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the power of the mass dependence /*! \param [in] massFactor the new power of the mass dependence */ void setMassFactor(const Double_t massFactor); //! Get the power of the mass dependence /*! \return the power of the mass dependence */ Double_t getMassFactor() const {return (massFactor_!=0) ? massFactor_->unblindValue() : 0.0;} //! See if the mass factor parameter is fixed or floating /*! \return kTRUE if the mass factor parameter is fixed, kFALSE otherwise */ Bool_t fixMassFactor() const {return (massFactor_!=0) ? massFactor_->fixed() : kTRUE;} //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Spline describing the magnitude variation of the form-factor static Lau1DCubicSpline* magSpline_; //! Spline describing the phase variation of the form-factor static Lau1DCubicSpline* phaseSpline_; //! The power of the mass dependence LauParameter* massFactor_; - ClassDef(LauEFKLLMRes,0) // EFKLLM resonance model }; #endif diff --git a/inc/LauEffModel.hh b/inc/LauEffModel.hh index d6ae85a..366eaae 100644 --- a/inc/LauEffModel.hh +++ b/inc/LauEffModel.hh @@ -1,270 +1,269 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEffModel.hh \brief File containing declaration of LauEffModel class. */ /*! \class LauEffModel \brief Class that implements the efficiency description across the signal Dalitz plot. Class that defines the efficiency model variation across the signal Dalitz plot. The method is based in a predetermined two-dimensional histogram to characterize the phase space acceptance. The efficiency variation is defined in terms of x = m_13^2, y = m_23^2 for the Dalitz plot (default) or x = m', y = theta' for the square Dalitz plot */ #ifndef LAUEFFMODEL #define LAUEFFMODEL #include "LauAbsEffModel.hh" class TH2; class LauDaughters; class LauKinematics; class LauVetoes; class Lau2DAbsDP; class LauEffModel : public LauAbsEffModel { public: //! Constructor /*! \param [in] daughters the daughters particles of the Dalitz plot model \param [in] vetoes the object describing the vetoes applied in the phase space */ LauEffModel(const LauDaughters* daughters, const LauVetoes* vetoes); //! Destructor virtual ~LauEffModel(); //! Set the efficiency variation across the phase space using a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] useInterpolation boolean flag decision to switch on/off linear interpolation between bins should be used or simply the raw bin values. \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setEffHisto(const TH2* effHisto, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Set the efficiency variation across the phase space using a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] errorHi the 2-dimensional histogram that describes the upper uncertainty on the efficiency variation \param [in] errorLo the 2-dimensional histogram that describes the lower uncertainty on the efficiency variation \param [in] useInterpolation boolean flag decision to switch on/off linear interpolation between bins should be used or simply the raw bin values. \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setEffHisto(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t useInterpolation = kTRUE, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Set the efficiency variation across the phase space using a spline based on a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setEffSpline(const TH2* effHisto, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Set the efficiency variation across the phase space using a spline based on a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] errorHi the 2-dimensional histogram that describes the upper uncertainty on the efficiency variation \param [in] errorLo the 2-dimensional histogram that describes the lower uncertainty on the efficiency variation \param [in] fluctuateBins boolean flag to determine whether the bin contents should be fluctuated in accordance with their errors. The seed for the random number generator used to fluctuate the bins should first be set using LauRandom::setSeed. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void setEffSpline(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t fluctuateBins = kFALSE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Add a multiplicative efficiency variation across the phase space using a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] useInterpolation boolean flag decision to switch on/off linear interpolation between bins should be used or simply the raw bin values. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void addEffHisto(const TH2* effHisto, Bool_t useInterpolation = kTRUE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Add a multiplicative efficiency variation across the phase space using a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] errorHi the 2-dimensional histogram that describes the upper uncertainty on the efficiency variation \param [in] errorLo the 2-dimensional histogram that describes the lower uncertainty on the efficiency variation \param [in] useInterpolation boolean flag decision to switch on/off linear interpolation between bins should be used or simply the raw bin values. \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void addEffHisto(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t useInterpolation = kTRUE, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Add a multiplicative efficiency variation across the phase space using a spline based on a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void addEffSpline(const TH2* effHisto, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Add a multiplicative efficiency variation across the phase space using a spline based on a predetermined 2D histogram. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effHisto the 2-dimensional histogram that describes the efficiency variation \param [in] errorHi the 2-dimensional histogram that describes the upper uncertainty on the efficiency variation \param [in] errorLo the 2-dimensional histogram that describes the lower uncertainty on the efficiency variation \param [in] avEff the desired average efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour. The seed for the random number generator used to raise or lower the bins should first be set using LauRandom::setSeed. \param [in] absError the error on that efficiency - see Lau2DHistDP::raiseOrLowerBins, values less than zero switch off this behaviour \param [in] useUpperHalfOnly boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] squareDP boolean flag to determine whether the supplied histogram is given in square DP coordinates */ void addEffSpline(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Double_t avEff = -1.0, Double_t absError = -1.0, Bool_t useUpperHalfOnly = kFALSE, Bool_t squareDP = kFALSE); //! Determine the efficiency for a given point in the Dalitz plot. /*! The method uses the 2D histogram set by the setEffHisto() function and the vetoes information. \param [in] kinematics the object that defines the DP position \return the efficiency value at the given point in the DP */ Double_t calcEfficiency( const LauKinematics* kinematics ) const; //! Determine whether the given DP position is outside the vetoes /*! \param [in] kinematics the object that defines the DP position \return kTRUE if the DP position is outside all veto regions, kFALSE otherwise */ Bool_t passVeto( const LauKinematics* kinematics ) const; //! Determine whether the efficiency histogram has had its bins fluctuated within their errors Bool_t fluctuateEffHisto() const {return fluctuateEffHisto_;} //! Return the daughters object /* \return the LauDaughters object associated with the DP */ const LauDaughters* getDaughters() const {return daughters_;} private: //! Copy constructor - not implemented LauEffModel( const LauEffModel& rhs ); //! Copy assignment operator - not implemented LauEffModel& operator=( const LauEffModel& rhs ); //! Get the efficiency from a two-dimensional histogram /*! \param [in] kinematics the object that defines the DP position */ Double_t getEffHistValue( const LauKinematics* kinematics ) const; //! The daughters object const LauDaughters* daughters_; //! The vetoes object const LauVetoes* vetoes_; //! The efficiency histogram objects std::vector effHisto_; //! Fluctuate histogram within the error Bool_t fluctuateEffHisto_; //! Flag to track whether a warning has been issued for bin values less than zero mutable Bool_t lowBinWarningIssued_; //! Flag to track whether a warning has been issued for bin values greater than one mutable Bool_t highBinWarningIssued_; - ClassDef(LauEffModel, 0) // Implement the signal efficiency across the DP }; #endif diff --git a/inc/LauEmbeddedData.hh b/inc/LauEmbeddedData.hh index 92d1ce2..3fbf98d 100644 --- a/inc/LauEmbeddedData.hh +++ b/inc/LauEmbeddedData.hh @@ -1,146 +1,145 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEmbeddedData.hh \brief File containing declaration of LauEmbeddedData class. */ /*! \class LauEmbeddedData \brief Class to store the data for embedding in toy experiments Class to store the data from external data sources, such as full simulation, for embedding in toy experiments */ #ifndef LAU_EMBEDDED_DATA #define LAU_EMBEDDED_DATA #include #include #include "LauFitDataTree.hh" class LauKinematics; class LauIsobarDynamics; class LauEmbeddedData { public: //! Constructor /*! \param [in] fileName the ntuple file name \param [in] treeName the tree name \param [in] allowReuseOfEvents flag to indicated whether events are allowed to be sampled more than once */ LauEmbeddedData(const TString& fileName, const TString& treeName, Bool_t allowReuseOfEvents); //! Destructor virtual ~LauEmbeddedData(); //! Find and read the branches in data tree /*! \return success/failure flag */ Bool_t findBranches(); //! Retrieve the number of branches /*! \return the number of branches */ UInt_t nBranches() const {return theDataTree_ ? theDataTree_->nBranches() : 0;} //! Retrieve the number of events /*! \return the number of events */ UInt_t nEvents() const {return theDataTree_ ? theDataTree_->nEvents() : 0;} //! Retrieve the number of events that have already been sampled /*! \return the number of used events */ UInt_t nUsedEvents() const {return usedEvents_.size();} //! Boolean to determine whether branch exists /*! \param [in] name the branch name */ Bool_t haveBranch(const TString& name) const {return theDataTree_ ? theDataTree_->haveBranch(name) : kFALSE;} //! Retrieve an event from the data sample /*! \param [in] kinematics object in which to store the kinematics of the Dalitz plot */ void getEmbeddedEvent(LauKinematics* kinematics); //! Retrieve an event from the data sample, applying an accept/reject based on the given DP model /*! \param [in] dynamics the amplitude model */ Bool_t getReweightedEvent(LauIsobarDynamics* dynamics); //! Get the value of a specified branch /*! \param [in] name the branch name \return the branch value */ Double_t getValue(const TString& name) const; //! Get values of specified branches /*! \param [in] names the branch names \return the branch values */ LauFitData getValues(const std::vector& names) const; //! Clear the list of used events void clearUsedList() {usedEvents_.clear();} protected: //! Boolean determining whether events should be reused /*! \return flag determining whether events should be reused */ Bool_t reuseEvents() const {return reuseEvents_;} private: //! Copy constructor (not implemented) LauEmbeddedData(const LauEmbeddedData& rhs); //! Copy assignment operator (not implemented) LauEmbeddedData& operator=(const LauEmbeddedData& rhs); //! The structure containing the data LauFitDataTree* theDataTree_; //! The data for the currently retrieved event LauFitData theData_; //! Flag whether events can be reused Bool_t reuseEvents_; //! Used events std::set usedEvents_; - ClassDef(LauEmbeddedData, 0) // a non-persistent bare-bones complex class }; #endif diff --git a/inc/LauExponentialPdf.hh b/inc/LauExponentialPdf.hh index f6ee6f1..fed666e 100644 --- a/inc/LauExponentialPdf.hh +++ b/inc/LauExponentialPdf.hh @@ -1,96 +1,95 @@ /* Copyright 2011 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauExponentialPdf.hh \brief File containing declaration of LauExponentialPdf class. */ /*! \class LauExponentialPdf \brief Class for defining an Exponential PDF Class that allows the user to define an Exponential PDF, requires a single parameter for the slope of the exponential: exp(slope*x) */ #ifndef LAU_EXPONENTIAL_PDF #define LAU_EXPONENTIAL_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauExponentialPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - slope \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauExponentialPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauExponentialPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauExponentialPdf(const LauExponentialPdf& rhs); //! Copy assignment operator (not implemented) LauExponentialPdf& operator=(const LauExponentialPdf& rhs); //! Exponential slope ie exp(slope*x) LauAbsRValue* slope_; - ClassDef(LauExponentialPdf,0) // Define the Exponential PDF }; #endif diff --git a/inc/LauFitDataTree.hh b/inc/LauFitDataTree.hh index d713a0f..639a4f3 100644 --- a/inc/LauFitDataTree.hh +++ b/inc/LauFitDataTree.hh @@ -1,224 +1,223 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitDataTree.hh \brief File containing declaration of LauFitDataTree class. */ /*! \class LauFitDataTree \brief Class to store the input fit variables. Events are loaded from a tree and fake events may be added manually. */ #ifndef LAU_FIT_DATA_TREE #define LAU_FIT_DATA_TREE #include #include #include "TEventList.h" #include "TTree.h" class TFile; class TLeaf; //! Type for holding event data typedef std::map LauFitData; class LauFitDataTree { public: //! Constructor /*! \param [in] rootFileName the name of the file containing the data \param [in] rootTreeName the name of the tree containing the data */ LauFitDataTree(const TString& rootFileName, const TString& rootTreeName); //! Destructor virtual ~LauFitDataTree(); //! Retrieve the file name /*! \return the file name */ const TString& fileName() const {return rootFileName_;} //! Retrieve the tree name /*! \return the tree name */ const TString& treeName() const {return rootTreeName_;} //! Find all of the branches in the tree /*! \returns true if sucessful, otherwise returns false and prints an error message */ Bool_t findBranches(); //! Read all events from the tree void readAllData(); //! Read events only for the given experiment /*! \param [in] iExpt the experiment to read */ void readExperimentData( UInt_t iExpt ); //! Add fake events to the data /*! Used, for example, for storing the information on the histogram bin centres for calculating the DP smearing of mis-reconstructed events, see, for example, LauSimpleFitModel::splitSignalComponent and LauScfMap \param [in] xCoords the values of m13 squared for the fake events \param [in] yCoords the values of m23 squared for the fake events */ void appendFakePoints(const std::vector& xCoords, const std::vector& yCoords); //! Obtain the number of branches in the tree /*! \return the number of branches */ UInt_t nBranches() const; //! Retrieve the number of events in the tree /*! \return the number of events in the tree */ UInt_t nTreeEvents() const {return rootTree_ ? static_cast(rootTree_->GetEntries()) : 0;} //! Retrieve the number of events /*! \return the number of events in the current experiment if one is selected, otherwise the total number of events in the tree */ UInt_t nEvents() const {return eventList_ ? static_cast(eventList_->GetN()) : this->nTreeEvents();} //! Retrieve the number of fake events /*! \return the number of fake events */ UInt_t nFakeEvents() const {return fakeEvents_.size();} //! Retrieve the total number of events /*! \return the total number of events */ UInt_t nTotalEvents() const {return this->nTreeEvents()+this->nFakeEvents();} //! Check if the named branch is stored /*! \param [in] name the name of the branch \return true if the branch is stored, otherwise return false */ Bool_t haveBranch(const TString& name) const; //! Retrieve the data for a given event /*! \param [in] iEvt the index of the event \return the event data */ const LauFitData& getData(UInt_t iEvt) const; //! Disable all branches void disableAllBranches() const; //! Enable all branches void enableAllBranches() const; //! Enable the named branch /*! \param [in] name the name of the branch */ void enableBranch(const TString& name) const; //! Disable the named branch /*! \param [in] name the name of the branch */ void disableBranch(const TString& name) const; protected: //! Open the file and tree void openFileAndTree(); //! Load events from the tree /*! If an event list is present, load only those events, otherwise load all events */ void loadData(); private: //! Copy constructor (not implemented) LauFitDataTree(const LauFitDataTree& rhs); //! Copy assignment operator (not implemented) LauFitDataTree& operator=(const LauFitDataTree& rhs); //! The type used to map the leaf names to the vector indices typedef std::map LauNameIndexMap; //! The type used to contain the data for each event typedef std::vector LauEventData; //! The type used to hold the leaves typedef std::vector LauLeafList; //! The name of the file containing the data TString rootFileName_; //! The name of the tree ocntaining the data TString rootTreeName_; //! The file containing the data TFile* rootFile_; //! The tree containing the data TTree* rootTree_; //! A list of the events in the current experiment TEventList* eventList_; //! Stores the mapping from the leaf names to the vector indices LauNameIndexMap leafNames_; //! Stores the current event mutable LauEventData eventData_; //! Stores the current event (for external use) mutable LauFitData eventDataOut_; //! The leaf objects LauLeafList leaves_; //! The events read from the tree std::vector treeEvents_; //! The fake events, which are not from the tree std::vector fakeEvents_; - ClassDef(LauFitDataTree, 0) }; #endif diff --git a/inc/LauFitNtuple.hh b/inc/LauFitNtuple.hh index 8eb69ed..088a82b 100644 --- a/inc/LauFitNtuple.hh +++ b/inc/LauFitNtuple.hh @@ -1,134 +1,133 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitNtuple.hh \brief File containing declaration of LauFitNtuple class. */ /*! \class LauFitNtuple \brief Class to store the results from the fit into an ntuple Class to store the results from the fit into an ntuple. The fitted values and their errors are stored. In the case of toy MC, the true values are also stored, along with the pulls. Derived quantities can also be stored, such as the fit fractions. What precisely is stored depends on the fit model. */ //**************************************************************************** // Class to store the results from the fit/toy MC into an ntuple // -- CLASS DESCRIPTION [MISC] -- /// Class to store the results from the fit/toy MC into an ntuple #ifndef LAU_FIT_NTUPLE #define LAU_FIT_NTUPLE #include #include "TMatrixDfwd.h" #include "TString.h" #include "LauAbsFitter.hh" class TFile; class TTree; class LauParameter; class LauFitNtuple { public: //! Constructor /*! \param [in] fileName the name for the ntuple \param [in] storeAsymErrors whether or not to store the asymmetric error variables */ LauFitNtuple(const TString& fileName, Bool_t storeAsymErrors); //! Destructor virtual ~LauFitNtuple(); //! Store the correlation matrix and other fit information /*! \param [in] iExpt the experiment number \param [in] fitStatus the status of the fit \param [in] covMatrix the fit covariance matrix */ void storeCorrMatrix(const UInt_t iExpt, const LauAbsFitter::FitStatus& fitStatus, const TMatrixD& covMatrix); //! Store parameters and their errors /*! \param [in] fitVars the fit parameters \param [in] extraVars variables in addition to the fit parameters, e.g. derived quantities such as fit fractions */ void storeParsAndErrors(const std::vector& fitVars, const std::vector& extraVars); //! Update the fit ntuple void updateFitNtuple(); //! Write out fit results void writeOutFitResults(); private: //! Copy constructor (not implemented) LauFitNtuple(const LauFitNtuple& rhs); //! Copy assignment operator (not implemented) LauFitNtuple& operator=(const LauFitNtuple& rhs); //! Name of root file TString rootFileName_; //! Root file TFile* rootFile_; //! Fit results TTree* fitResults_; //! Fit variables std::vector fitVars_; //! Extra variables std::vector extraVars_; //! Correlation matrix std::vector< std::vector > corrMatrix_; //! Flags whether the fit tree has been defined Bool_t definedFitTree_; //! Flags whether or not to store the asymmetric error information Bool_t storeAsymErrors_; //! Status of fit LauAbsFitter::FitStatus fitStatus_; //! Number of fit parameters UInt_t nFitPars_; //! Number of free parameters UInt_t nFreePars_; //! Number of extra parameters UInt_t nExtraPars_; //! Experiment number Int_t iExpt_; - ClassDef(LauFitNtuple,0) // Fit/toyMC results ntuple }; #endif diff --git a/inc/LauFitObject.hh b/inc/LauFitObject.hh index c67a1ce..dff7888 100644 --- a/inc/LauFitObject.hh +++ b/inc/LauFitObject.hh @@ -1,374 +1,373 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitObject.hh \brief File containing declaration of LauFitObject class. */ #ifndef LAU_FIT_OBJECT #define LAU_FIT_OBJECT #include #include "TMatrixD.h" #include "TObject.h" #include "TString.h" #include "TVectorD.h" #include "LauAbsFitter.hh" #include "LauFormulaPar.hh" /*! \class LauFitObject \brief The abstract interface for the objects that control the calculation of the likelihood. */ class LauFitObject : public TObject { public: //! Destructor virtual ~LauFitObject() = default; //! 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;} //! Report whether or not calculation of asymmetric errors is enabled Bool_t useAsymmFitErrors() const {return useAsymmFitErrors_;} //! 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 */ void twoStageFit(Bool_t doTwoStageFit) {twoStageFit_ = doTwoStageFit;} //! Report whether the two-stage fit is enabled Bool_t twoStageFit() const {return twoStageFit_;} //! 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(const Bool_t inAsymErrCalc) {withinAsymErrorCalc_ = inAsymErrCalc;} //! Query whether the fit is calculating the asymmetric errors /*! \return kTRUE if the fit is calculating the asymmetric errors, kFALSE otherwise */ Bool_t withinAsymErrorCalc() const {return withinAsymErrorCalc_;} //! Set the number of experiments, the first experiment, and whether this is toy /*! The default settings are nExperiments = 1, firstExperiment = 0, toyExpts = kFALSE, i.e. the settings for fitting a single data sample. As such, this function only needs to be called if generating/fitting toy samples. \param [in] nExperiments the number of experiments \param [in] firstExperiment the number of the first experiment \param [in] toyExpts whether this is toy - determines whether to generate per-experiment means for each Gaussian constraint, as per arXiv:1210.7141 */ void setNExpts(UInt_t nExperiments, UInt_t firstExperiment, Bool_t toyExpts); //! 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_;} //! Obtain whether this is toy Bool_t toyExpts() const {return toyExpts_;} //! 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) = 0; //! Calculate the new value of the negative log likelihood /*! This function has to be public since it is called from the global FCN. It should not be called otherwise! */ virtual Double_t getTotNegLogLikelihood() = 0; //! Store constraint information for fit parameters /*! \deprecated Renamed to addFormulaConstraint, please switch to use this. Will be dropped in next major release. \param [in] formula the formula to be used in the LauFormulaPar \param [in] pars a vector of LauParameter names to be used in the Formula, in the order specified by the formula \param [in] mean the value of the mean of the Gaussian constraint \param [in] width the value of the width of the Gaussian constraint */ virtual void addConstraint(const TString& formula, const std::vector& pars, const Double_t mean, const Double_t width); //! Store constraint information for fit parameters /*! \param [in] formula the formula to be used in the LauFormulaPar \param [in] pars a vector of LauParameter names to be used in the Formula, in the order specified by the formula \param [in] mean the value of the mean of the Gaussian constraint \param [in] width the value of the width of the Gaussian constraint */ virtual void addFormulaConstraint(const TString& formula, const std::vector& pars, const Double_t mean, const Double_t width); //! Store n-dimensional constraint information for fit parameters /*! \param [in] pars a vector of LauParameter names to be used in the constraint \param [in] means the values of the means of the Gaussian constraint \param [in] covMat the covariance matrix of the parameters of the Gaussian constraint */ virtual void addMultiDimConstraint(const std::vector& pars, const TVectorD& means, const TMatrixD& covMat); //! Check if parameters names for constraints have already been used elsewhere /*! \param [in] names a vector of parameter names \return kTRUE if no repetitions found, kFALSE if one or more repetitions found */ virtual Bool_t checkRepetition(const std::vector& names); protected: //! Constructor LauFitObject(); // Setup a struct to store information on constrained fit parameters /*! \struct FormulaConstraint \brief Struct to store formula-based constraint information */ struct FormulaConstraint { //! The formula to be used in the LauFormulaPar TString formula_; //! The list of LauParameter names to be used in the LauFormulaPar std::vector conPars_; //! The mean value of the Gaussian constraint to be applied Double_t mean_; //! The width of the Gaussian constraint to be applied Double_t width_; //! The LauFormulaPar pointer std::unique_ptr formulaPar_; }; // Setup a class to store information on n-dimensional constrained fit parameters /*! \class MultiDimConstraint \brief Class to store n-dimensional constraint information */ class MultiDimConstraint { public: //! Default constructor MultiDimConstraint() = default; //! Constructor MultiDimConstraint( const std::vector& parNames, const TVectorD& means, const TMatrixD& covMat ); //! Get the penalty term Double_t constraintPenalty() const; //! Generate per-experiment constraint means void generateConstraintMeans(); //! The list of LauParameter names to be used in the constraint std::vector conPars_; //! The true mean values of the constraint TVectorD trueMeans_; //! The per-experiment mean values of the constraint TVectorD means_; //! The inverse covariance matrix of the parameters TMatrixD invCovMat_; //! The Cholesky Decomposition of the covariance matrix of the parameters TMatrixD sqrtCovMat_; //! The LauParameters used in the constraints std::vector conLauPars_; }; //! Generate per-experiment mean for each Gaussian constraint /*! Generates a new mean for all Gaussian constraints. The constraints on a single fit parameter and the formula-based constraints are provided as the argument, while the multi-dimensional constraints are already a member variable. \param [in,out] conVars the fit parameter and formula-based constraints */ void generateConstraintMeans( std::vector& conVars ); //! Const access to the constraints store const std::vector& formulaConstraints() const {return formulaConstraints_;} //! Access to the constraints store std::vector& formulaConstraints() {return formulaConstraints_;} //! Const access to the ND constraints store const std::vector& multiDimConstraints() const {return multiDimConstraints_;} //! Access to the ND constraints store std::vector& multiDimConstraints() {return multiDimConstraints_;} //! Reset the good/bad fit counters void resetFitCounters(); //! Set the ID of the current experiment /*! \param [in] curExpt the experiment number */ void setCurrentExperiment( const UInt_t curExpt ) { iExpt_ = curExpt; } //! Indicate the start of a new fit /*! \param [in] nPars the total number of fit parameters \param [in] nFreePars the number of free fit parameters */ void startNewFit( const UInt_t nPars, const UInt_t nFreePars ); //! Set the number of events in the current experiment void eventsPerExpt(UInt_t nEvents) {evtsPerExpt_ = nEvents;} //! Access the worst log likelihood found so far Double_t worstLogLike() const {return worstLogLike_;} //! Set a new value for the worst log likelihood /*! \param [in] newWorstLogLike the new value of the worst log likelihood */ void worstLogLike( const Double_t newWorstLogLike ) {worstLogLike_ = newWorstLogLike;} //! Store fit status information /*! \param [in] status the status information of the fit \param [in] covMatrix the fit covariance matrix */ void storeFitStatus( const LauAbsFitter::FitStatus& status, const TMatrixD& covMatrix ); //! Access the total number of fit parameters UInt_t nTotParams() const {return nParams_;} //! Access the total number of fit parameters UInt_t nFreeParams() const {return nFreeParams_;} //! Access the fit status information const LauAbsFitter::FitStatus& fitStatus() const {return fitStatus_;} //! Access the current NLL value Double_t nll() const {return fitStatus_.NLL;} //! Access the current EDM value Double_t edm() const {return fitStatus_.EDM;} //! Access the fit status code Int_t statusCode() const {return fitStatus_.status;} //! Access the fit covariance matrix const TMatrixD& covarianceMatrix() const {return covMatrix_;} //! Access the number of successful fits UInt_t numberOKFits() const {return numberOKFits_;} //! Access the number of failed fits UInt_t numberBadFits() const {return numberBadFits_;} private: //! Copy constructor (not implemented) LauFitObject(const LauFitObject& rhs); //! Copy assignment operator (not implemented) LauFitObject& operator=(const LauFitObject& rhs); //! Store the constraints for fit parameters until initialisation is complete std::vector formulaConstraints_; //! Store the ND constraints for fit parameters until initialisation is complete std::vector multiDimConstraints_; //! Option to perform a two stage fit Bool_t twoStageFit_; //! Option to use asymmetric errors Bool_t useAsymmFitErrors_; //! The number of fit parameters UInt_t nParams_; //! The number of free fit parameters UInt_t nFreeParams_; //! Flag to indicate if the asymmetric error calculation (e.g. MINOS) is currently running Bool_t withinAsymErrorCalc_; //! Flag to indicate whether this is toy /*! Determines whether to generate per-experiment means for each Gaussian constraint, as per arXiv:1210.7141 */ Bool_t toyExpts_; //! The number of the first experiment to consider UInt_t firstExpt_; //! The number of experiments to consider UInt_t nExpt_; //! The current experiment number UInt_t iExpt_; //! The number of events in the current experiment UInt_t evtsPerExpt_; //! The status of the current fit LauAbsFitter::FitStatus fitStatus_; //! The worst log likelihood value found so far Double_t worstLogLike_; //! The fit covariance matrix TMatrixD covMatrix_; //! The number of successful fits UInt_t numberOKFits_; //! The number of fit failures UInt_t numberBadFits_; - ClassDef(LauFitObject,0) }; #endif diff --git a/inc/LauFitter.hh b/inc/LauFitter.hh index 67edbe0..6253d34 100644 --- a/inc/LauFitter.hh +++ b/inc/LauFitter.hh @@ -1,119 +1,118 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitter.hh \brief File containing declaration of LauFitter class. */ #ifndef LAU_FITTER #define LAU_FITTER #include "LauPrint.hh" #include "Rtypes.h" #include "TString.h" #include class LauAbsFitter; /*! \class LauFitter \brief Factory class for creating and providing access to the fitter. The fitter type and verbosity can be set before first access to determine which fitter is used. */ class LauFitter final { public: //! The types of fitter available enum class Type { Minuit /*!< the Minuit fitter */ }; //! Set the type of the fitter /*! \param [in] type the type of the fitter (default set to Minuit) */ static void setFitterType( const Type type ); //! Set the verbosity level of the fitter /*! \param [in] level the level of verbosity of the fitter (default set to Standard) */ static void setFitterVerbosity( const LauOutputLevel level ); //! Set the maximum number of parameters for the fitter /*! \param [in] maxPars the maximum number of parameters for the fitter (default set to 100) */ static void setFitterMaxPars( const UInt_t maxPars ); //! Method that provides access to the singleton fitter /*! \return a reference to a singleton LauAbsFitter object */ static LauAbsFitter& fitter(); //! Destroy the current fitter /*! A new fitter will be created on the next call to LauFitter::fitter */ static void destroyFitter(); private: //! Constructor LauFitter() = default; //! Destructor ~LauFitter() = default; //! Copy constructor (deleted) LauFitter( const LauFitter& ) = delete; //! Move constructor (deleted) LauFitter( LauFitter&& ) = delete; //! Copy assignment operator (deleted) LauFitter& operator=( const LauFitter& ) = delete; //! Move assignment operator (deleted) LauFitter& operator=( LauFitter&& ) = delete; //! Pointer to the singleton fitter instance static std::unique_ptr theInstance_; //! The fitter type static Type fitterType_; //! The fitter verbosity static LauOutputLevel fitterVerbosity_; //! The maximum number of parameters for the fitter static UInt_t fitterMaxPars_; - ClassDef(LauFitter,0); }; #endif diff --git a/inc/LauFlatNR.hh b/inc/LauFlatNR.hh index b1ebf69..70bdbbe 100644 --- a/inc/LauFlatNR.hh +++ b/inc/LauFlatNR.hh @@ -1,88 +1,87 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatNR.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauFlatNR(LauResonanceInfo* resInfo, const 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: //! Copy constructor (not implemented) LauFlatNR(const LauFlatNR& rhs); //! Copy assignment operator (not implemented) LauFlatNR& operator=(const LauFlatNR& rhs); - ClassDef(LauFlatNR,0) // Uniform non-resonant model }; #endif diff --git a/inc/LauFlatteRes.hh b/inc/LauFlatteRes.hh index b6c20d0..b067539 100644 --- a/inc/LauFlatteRes.hh +++ b/inc/LauFlatteRes.hh @@ -1,171 +1,170 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatteRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauFlatteRes(LauResonanceInfo* resInfo, const 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;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the g1 parameter /*! \param [in] g1 constant factor */ void setg1Parameter(const Double_t g1); //! Set the g2 parameter /*! \param [in] g2 constant factor */ void setg2Parameter(const Double_t g2); //! Get the g1 parameter /*! \return constant factor g1 */ Double_t getg1Parameter() const {return (g1_!=0) ? g1_->unblindValue() : 0.0;} //! Get the g2 parameter /*! \return constant factor g2 */ Double_t getg2Parameter() const {return (g2_!=0) ? g2_->unblindValue() : 0.0;} //! See if the g1 parameter is fixed or floating /*! \return kTRUE if the g1 parameter is fixed, kFALSE otherwise */ Double_t fixg1Parameter() const {return (g1_!=0) ? g1_->fixed() : kTRUE;} //! See if the g2 parameter is fixed or floating /*! \return kTRUE if the g2 parameter is fixed, kFALSE otherwise */ Double_t fixg2Parameter() const {return (g2_!=0) ? g2_->fixed() : kTRUE;} //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauFlatteRes(const LauFlatteRes& rhs); //! Copy assignment operator (not implemented) LauFlatteRes& operator=(const LauFlatteRes& rhs); //! Channel 1 coupling parameter LauParameter* g1_; //! Channel 1 coupling parameter LauParameter* g2_; //! Channel 1, subchannel 1 invariant mass Double_t mSumSq0_; //! Channel 1, subchannel 2 invariant mass Double_t mSumSq1_; //! Channel 2, subchannel 1 invariant mass Double_t mSumSq2_; //! Channel 2, subchannel 2 invariant mass Double_t mSumSq3_; //! Flag to turn on Adler term in the width Bool_t useAdlerTerm_; //! The Adler zero Double_t sA_; //! Flag to specify whether the couplings absorb the m_0 factor Bool_t absorbM0_; - ClassDef(LauFlatteRes,0) }; #endif diff --git a/inc/LauFormulaPar.hh b/inc/LauFormulaPar.hh index efcba71..52674fd 100644 --- a/inc/LauFormulaPar.hh +++ b/inc/LauFormulaPar.hh @@ -1,182 +1,181 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFormulaPar.hh \brief File containing declaration of LauFormulaPar class. */ /*! \class LauFormulaPar \brief Class for defining combinations of fit parameter objects. Allows for combinations of LauParameters to be passed to the fit models. Equations of the form [0]*2 + 3*[1] are accepted, with a vector of LauParameters to define inputs [0] and [1]. The parameter for [0] must be stored first in the vector, and so on. */ #ifndef LAU_FORMULAPAR #define LAU_FORMULAPAR #include #include #include "TString.h" #include "TFormula.h" #include "LauAbsRValue.hh" #include "LauParameter.hh" class LauFormulaPar : public LauAbsRValue { public: //! Constructor /*! \param [in] forName the name of the formula \param [in] formula the desired expression, using TFormula syntax \param [in] params a vector of LauParameters used in the formula */ LauFormulaPar(const TString& forName, const TString& formula, const std::vector& params); // Destructor virtual ~LauFormulaPar(); //! Copy constructor LauFormulaPar(const LauFormulaPar& rhs); //! Copy assignment operator LauFormulaPar& operator=(const LauFormulaPar& rhs); //! Return the value of the LauFormalaPar /*! \return the value of the formula */ Double_t value() const; //! The unblinded value of the parameter /*! \return the unblinded value of the parameter */ Double_t unblindValue() const; //! The value generated for the parameter /*! \return the value generated for the parameter */ Double_t genValue() const; //! The initial value of the parameter /*! \return the initial value of the parameter given to the fitter */ Double_t initValue() const; //! The parameter name /*! \return the name of the parameter */ inline const TString& name() const {return name_;} //! Set the parameter name /*! \param [in] newName the name of the parameter */ inline void name(const TString& newName) {name_ = newName;}; //! Get the LauParameters used in LauFormulaPar /*! \return the list of LauParameters */ std::vector getPars() {return paramVec_;} //! Boolean to say it is not an L value /*! \return kFALSE, LauFormulaPars are not L values */ inline Bool_t isLValue() const {return kFALSE;} //! Boolean to say if the LauFormulaPar is fixed /*! \return kFALSE unless all LauParameters in the formula are fixed */ Bool_t fixed() const; //! The blinding state /*! \return kTRUE if any of the LauParameters in the formula are blinded, kFALSE otherwise */ Bool_t blind() const; //! Check whether a Gaussian constraints is applied /*! \return the boolean flag true/false whether a Gaussian constraint is applied */ inline Bool_t gaussConstraint() const {return gaussConstraint_;} //! The penalty term from the Gaussian constraint /*! \return the penalty term from the Gaussian constraint */ Double_t constraintPenalty() const; //! Add a Gaussian constraint (or modify an existing one) /*! \param [in] newGaussMean the new value of the Gaussian constraint mean \param [in] newGaussWidth the new value of the Gaussian constraint width */ void addGaussianConstraint(Double_t newGaussMean, Double_t newGaussWidth); //! Remove the Gaussian constraint void removeGaussianConstraint(); //! Generate per-experiment constraint mean void generateConstraintMean(); protected: private: //! The parameter name TString name_; //! The formula mutable TFormula formula_; //! Vector of LauParameters in the formula std::vector paramVec_; //! Array to hold parameter values to pass to formula Double_t* paramArray_; //! Choice to use Gaussian constraint Bool_t gaussConstraint_; //! True mean of the Gaussian constraint Double_t constraintTrueMean_; //! Mean value of the Gaussian constraint Double_t constraintMean_; //! Width of the Gaussian constraint Double_t constraintWidth_; - ClassDef(LauFormulaPar, 0) }; #endif diff --git a/inc/LauGaussIncohRes.hh b/inc/LauGaussIncohRes.hh index 0e2291d..4ee1fb1 100644 --- a/inc/LauGaussIncohRes.hh +++ b/inc/LauGaussIncohRes.hh @@ -1,92 +1,91 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussIncohRes.hh \brief File containing declaration of LauGaussIncohRes class. */ /*! \class LauGaussIncohRes \brief Class for defining an incoherent resonance with a Gaussian mass dependence Useful for modelling resolution-dominated sharp structures such as D*(2010) */ #ifndef LAU_GAUSS_INCOH_RES #define LAU_GAUSS_INCOH_RES #include "TString.h" #include "LauAbsIncohRes.hh" #include "LauComplex.hh" class LauKinematics; class LauGaussIncohRes : public LauAbsIncohRes { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauGaussIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauGaussIncohRes(); //! Initialise the model virtual void initialise(); //! Get intensity factor /*! /param [in] kinematics kinematic parameters of the parent and daughter particles /return the intensity factor */ virtual Double_t intensityFactor(const LauKinematics* kinematics); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::GaussIncoh;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); private: //! Copy constructor (not implemented) LauGaussIncohRes(const LauGaussIncohRes& rhs); //! Copy assignment operator (not implemented) LauGaussIncohRes& operator=(const LauGaussIncohRes& rhs); - ClassDef(LauGaussIncohRes,0) // Gaussian incoherent resonance model }; #endif diff --git a/inc/LauGaussPdf.hh b/inc/LauGaussPdf.hh index 763c500..c777e7b 100644 --- a/inc/LauGaussPdf.hh +++ b/inc/LauGaussPdf.hh @@ -1,96 +1,95 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussPdf.hh \brief File containing declaration of LauGaussPdf class. */ /*! \class LauGaussPdf \brief Class for defining a Gaussian PDF. Class that allows the user to define a Gaussian PDF. */ #ifndef LAU_GAUSS_PDF #define LAU_GAUSS_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauGaussPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean, sigma \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauGaussPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauGaussPdf(const LauGaussPdf& rhs); //! Copy assignment operator (not implemented) LauGaussPdf& operator=(const LauGaussPdf& rhs); //! Gaussian mean LauAbsRValue* mean_; //! Gaussian sigma LauAbsRValue* sigma_; - ClassDef(LauGaussPdf,0) // Define the Gaussian PDF }; #endif diff --git a/inc/LauGenNtuple.hh b/inc/LauGenNtuple.hh index 5aa34cb..b2de1e0 100644 --- a/inc/LauGenNtuple.hh +++ b/inc/LauGenNtuple.hh @@ -1,189 +1,188 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGenNtuple.hh \brief File containing declaration of LauGenNtuple class. */ /*! \class LauGenNtuple \brief Class to store the results from the toy MC generation into an ntuple Class to store the results from the toy MC generation into an ntuple */ #ifndef LAU_GEN_NTUPLE #define LAU_GEN_NTUPLE #include #include "TString.h" class TFile; class TTree; class LauGenNtuple { public: //! Constructor /*! \param [in] rootFileName the name for the ntuple \param [in] rootTreeName the name for the tree in the ntuple */ LauGenNtuple(const TString& rootFileName, const TString& rootTreeName); //! Destructor virtual ~LauGenNtuple(); //! Ntuple file name /*! \return the name of the ntuple */ const TString& fileName() const {return rootFileName_;} //! Ntuple tree name /*! \return the name of the tree */ const TString& treeName() const {return rootTreeName_;} //! Add integer branch to tree /*! \param [in] name the name of the branch */ void addIntegerBranch(const TString& name); //! Add double branch to tree /*! \param [in] name the name of the branch */ void addDoubleBranch(const TString& name); //! Set value of an integer branch /*! \param [in] name the name of the branch \param [in] value the value to set the branch */ void setIntegerBranchValue(const TString& name, Int_t value); //! Set value of a double branch /*! \param [in] name the name of the branch \param [in] value the value to set the branch */ void setDoubleBranchValue(const TString& name, Double_t value); //! Get value of an integer branch /*! \param [in] name the name of the branch \return the value of the branch */ Int_t getIntegerBranchValue(const TString& name) const; //! Get value of a double branch /*! \param [in] name the name of the branch \return the value of the branch */ Double_t getDoubleBranchValue(const TString& name) const; //! Fill branches in the ntuple void fillBranches(); //! Delete and recreate tree void deleteAndRecreateTree(); //! Create an index table using leaves of the tree /*! \param [in] majorName the majorname \param [in] minorName the minorname \return the number of entries in the index (< 0 indicates failure) */ Int_t buildIndex(const TString& majorName, const TString& minorName = "0"); //! Write out the results from the generation void writeOutGenResults(); //! Add a friend tree /*! \param [in] rootFileName the name of the root file \param [in] rootTreeName the name of the root tree */ void addFriendTree(const TString& rootFileName, const TString& rootTreeName); protected: //! Create ntuple file and the tree void createFileAndTree(); //! Define branches of the tree void defineBranches(); //! Flags whether branches have been defined /*! \return boolean to determine whether branches have been defined */ Bool_t definedBranches() const {return definedBranches_;} //! Flags whether branches have been defined /*! \param [in] defined boolean to determine whether branches have been defined */ void definedBranches(Bool_t defined) {definedBranches_ = defined;} private: //! Copy constructor (not implemented) LauGenNtuple(const LauGenNtuple& rhs); //! Copy assignment operator (not implemented) LauGenNtuple& operator=(const LauGenNtuple& rhs); //! Name of root file TString rootFileName_; //! Name of root tree TString rootTreeName_; //! Root file TFile* rootFile_; //! Root tree TTree* rootTree_; //! Flags whether branches are defined Bool_t definedBranches_; //! Type to hold integer variables typedef std::map IntVarMap; //! Type to hold double precision floating point variables typedef std::map DoubleVarMap; //! Integer variables IntVarMap intVars_; //! Double variables DoubleVarMap doubleVars_; - ClassDef(LauGenNtuple,0) // Generated toyMC ntuple }; #endif diff --git a/inc/LauGounarisSakuraiRes.hh b/inc/LauGounarisSakuraiRes.hh index cefa227..410036b 100644 --- a/inc/LauGounarisSakuraiRes.hh +++ b/inc/LauGounarisSakuraiRes.hh @@ -1,126 +1,125 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGounarisSakuraiRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauGounarisSakuraiRes(LauResonanceInfo* resInfo, const 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;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauGounarisSakuraiRes(const LauGounarisSakuraiRes& rhs); //! Copy assignment operator (not implemented) LauGounarisSakuraiRes& operator=(const LauGounarisSakuraiRes& rhs); //! Momentum of the daughters in the resonance rest frame (at pole mass) Double_t q0_; //! The resonance mass Double_t resMass_; //! Square of the resonance mass Double_t resMassSq_; //! The resonance width Double_t resWidth_; //! The resonance barrier radius Double_t resRadius_; //! The parent barrier radius Double_t parRadius_; //! 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_; //! Value of the form factor for resonance decay (at pole mass) Double_t FR0_; - ClassDef(LauGounarisSakuraiRes,0) // Gounaris-Sakurai resonance model }; #endif diff --git a/inc/LauIntegrals.hh b/inc/LauIntegrals.hh index 168ba71..ba50301 100644 --- a/inc/LauIntegrals.hh +++ b/inc/LauIntegrals.hh @@ -1,85 +1,84 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIntegrals.hh \brief File containing declaration of LauIntegrals class. */ /*! \class LauIntegrals \brief Class for performing numerical integration routines. Class for calculating the Gauss-Legendre or Gauss-Hermite weights required for numerical integration of DP and other PDFs. */ #ifndef LAU_INTEGRALS #define LAU_INTEGRALS #include #include "Rtypes.h" class LauIntegrals { public: //! Constructor /*! \param [in] weightsPrecision the desired precision to which the weights should be calculated */ LauIntegrals(Double_t weightsPrecision = 1.0e-6); //! Destructor virtual ~LauIntegrals(); //! Copy constructor LauIntegrals(const LauIntegrals& rhs); //! Copy assignment operator LauIntegrals& operator=(const LauIntegrals& rhs); //! Calculate the Gauss-Legendre weights /*! \param [in] numPoints the number of points in the integration \param [out] abscissas the values of the abscissa at each integration point \param [out] weights the weight at each integration point */ void calcGaussLegendreWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights); //! Calculate the Gauss-Hermite weights /*! \param [in] numPoints the number of points in the integration \param [out] abscissas the values of the abscissa at each integration point \param [out] weights the weight at each integration point */ void calcGaussHermiteWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights); private: //! The precision to which the weights should be calculated Double_t weightsPrecision_; - ClassDef(LauIntegrals,0) }; #endif diff --git a/inc/LauIsobarDynamics.hh b/inc/LauIsobarDynamics.hh index a64f029..53941f5 100644 --- a/inc/LauIsobarDynamics.hh +++ b/inc/LauIsobarDynamics.hh @@ -1,989 +1,988 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIsobarDynamics.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 #include #include "TString.h" #include "LauAbsResonance.hh" #include "LauComplex.hh" class LauCacheData; class LauDaughters; class LauAbsEffModel; class LauAbsIncohRes; class LauFitDataTree; class LauKMatrixPropagator; class LauDPPartialIntegralInfo; class LauKinematics; class LauIsobarDynamics { public: //! The type used for containing multiple self cross feed fraction models for different categories (e.g. tagging categories) typedef std::map LauTagCatScfFractionModelMap; //! 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) */ }; //! 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, LauAbsEffModel* effModel, LauAbsEffModel* 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, LauAbsEffModel* effModel, LauTagCatScfFractionModelMap scfFractionModel); //! Destructor virtual ~LauIsobarDynamics(); //! Initialise the Dalitz plot dynamics /*! \param [in] coeffs the complex coefficients for the resonances */ void initialise(const std::vector& coeffs); //! recalculate Normalization 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 or square Dalitz plot /*! Specify the bin widths required when performing the DP integration. Note that the integration is not performed in m13^2 vs m23^2 space but in either m13 vs m23 space or mPrime vs thetaPrime space, with the appropriate Jacobian applied. The default bin widths in m13 vs m23 space are 0.005 GeV. The default bin widths in mPrime vs thetaPrime space are 0.001. \param [in] m13BinWidth the bin width to use when integrating over m13 \param [in] m23BinWidth the bin width to use when integrating over m23 \param [in] mPrimeBinWidth the bin width to use when integrating over mPrime \param [in] thPrimeBinWidth the bin width to use when integrating over thetaPrime */ void setIntegralBinWidths(const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t mPrimeBinWidth = 0.001, const Double_t thPrimeBinWidth = 0.001); //! Set the value below which a resonance width is considered to be narrow /*! Narrow resonances trigger different integration behaviour - dividing the DP into regions where a finer binning is used. This can cause high memory usage, so use this method and LauIsobarDynamics::setIntegralBinningFactor to tune this behaviour, if needed. \param [in] narrowWidth the value below which a resonance is considered to be narrow (defaults to 0.02 GeV/c2) */ void setNarrowResonanceThreshold(const Double_t narrowWidth) { narrowWidth_ = narrowWidth; } //! Set the factor relating the width of a narrow resonance and the binning size in its integration region /*! Narrow resonances trigger different integration behaviour - dividing the DP into regions where a finer binning is used. This can cause high memory usage, so use this method and LauIsobarDynamics::setNarrowResonanceThreshold to tune this behaviour, if needed. \param [in] binningFactor the factor by which the resonance width is divided to obtain the bin size (defaults to 100) */ void setIntegralBinningFactor(const Double_t binningFactor) { binningFactor_ = binningFactor; } //! Force the symmetrisation of the integration in m13 <-> m23 for non-symmetric but flavour-conjugate final states /*! This can be necessary for time-dependent fits (where interference terms between A and Abar need to be integrated) \param [in] force toggle forcing symmetrisation of the integration for apparently flavour-conjugate final states */ void forceSymmetriseIntegration(const Bool_t force) { forceSymmetriseIntegration_ = force; } //! Add a resonance to the Dalitz plot /*! NB the stored order of resonances is: - Firstly, all coherent resonances (i.e. those added using addResonance() or addKMatrixProdPole() or addKMatrixProdSVP()) in order of addition - Followed by all incoherent resonances (i.e. those added using addIncoherentResonance()) in order of addition \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 model for the resonance dynamics \param [in] bwCategory the Blatt-Weisskopf barrier factor category \return the newly created resonance */ LauAbsResonance* addResonance(const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory = LauBlattWeisskopfFactor::Default); //! Add an incoherent resonance to the Dalitz plot /*! NB the stored order of resonances is: - Firstly, all coherent resonances (i.e. those added using addResonance() or addKMatrixProdPole() or addKMatrixProdSVP()) in order of addition - Followed by all incoherent resonances (i.e. those added using addIncoherentResonance()) in order of addition \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 model for the resonance dynamics \return the newly created resonance */ LauAbsResonance* addIncoherentResonance(const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType); //! 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. */ LauKMatrixPropagator* 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 /*! NB the stored order of resonances is: - Firstly, all coherent resonances (i.e. those added using addResonance() or addKMatrixProdPole() or addKMatrixProdSVP()) in order of addition - Followed by all incoherent resonances (i.e. those added using addIncoherentResonance()) in order of addition \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 \param [in] useProdAdler boolean to turn on/off the production Adler zero factor (default = off) */ void addKMatrixProdPole(const TString& poleName, const TString& propName, Int_t poleIndex, Bool_t useProdAdler = kFALSE); //! Add a K-matrix slowly-varying part (SVP) term to the model /*! NB the stored order of resonances is: - Firstly, all coherent resonances (i.e. those added using addResonance() or addKMatrixProdPole() or addKMatrixProdSVP()) in order of addition - Followed by all incoherent resonances (i.e. those added using addIncoherentResonance()) in order of addition \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 \param [in] useProdAdler boolean to turn on/off the production Adler zero factor (default = off) */ void addKMatrixProdSVP(const TString& SVPName, const TString& propName, Int_t channelIndex, Bool_t useProdAdler = kFALSE); //! Set the maximum value of A squared to be used in the accept/reject /*! Disables the automatic determination of ASqMax \param [in] value the new value */ inline void setASqMaxValue(Double_t value) {aSqMaxSet_ = value; aSqMaxAuto_ = kFALSE;} //! 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_; } //! Generate a toy MC signal event /*! \return kTRUE if the event is successfully generated, kFALSE otherwise */ 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 */ 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 */ void calcLikelihoodInfo(const 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 */ void calcLikelihoodInfo(const Double_t m13Sq, const 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 */ void calcLikelihoodInfo(const Double_t m13Sq, const Double_t m23Sq, const Int_t tagCat); //! 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 */ void calcExtraInfo(const 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 */ 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 */ Double_t getEventWeight(); //! Retrieve the total amplitude for the current event /*! \return the total amplitude */ inline 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 */ inline 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 */ inline 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 */ inline 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 */ inline Double_t getEvtthPrime() const {return thPrime_;} //! Retrieve the efficiency for the current event /*! \return the efficiency for the current event */ inline 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 */ inline 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 */ inline Double_t getEvtJacobian() const {return jacobian_;} //! Retrieve the total intensity multiplied by the efficiency for the current event /*! \return the total intensity multiplied by the efficiency for the current event */ inline Double_t getEvtIntensity() const {return ASq_;} //! Retrieve the likelihood for the current event /*! The likelihood is the normalised total intensity: evtLike_ = ASq_/DPNorm_ \return the likelihood for the current event */ inline Double_t getEvtLikelihood() const {return evtLike_;} //! 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 component within the model \return the amplitude of the given component */ inline LauComplex getDynamicAmp(const Int_t resID) const {return ff_[resID].scale(fNorm_[resID]);} //! Retrieve the Amplitude of resonance resID /*! \param [in] resID the index of the component within the model \return the amplitude of the given component */ inline LauComplex getFullAmplitude(const Int_t resID) const {return Amp_[resID] * this->getDynamicAmp(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 >& 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 >& 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& getFNorm() const {return fNorm_;} //! Fill the internal data structure that caches the resonance dynamics /*! \param [in] fitDataTree the data source */ void fillDataTree(const LauFitDataTree& fitDataTree); //! Recache the amplitude values for those that have changed void modifyDataTree(); //! Check whether this model includes a named resonance /*! \param [in] resName the resonance \return true if the resonance is present, false otherwise */ Bool_t hasResonance(const TString& resName) const; //! Retrieve the index for the given resonance /*! \param [in] resName the resonance \return the index of the resonance if it is present, -1 otherwise */ Int_t resonanceIndex(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 */ TString getConjResName(const TString& resName) const; //! Retrieve the named resonance /*! \param [in] resName the name of the resonance to retrieve \return the requested resonance */ const LauAbsResonance* findResonance(const TString& resName) const; //! Retrieve a resonance by its index /*! \param [in] resIndex the index of the resonance to retrieve \return the requested resonance */ const LauAbsResonance* getResonance(const UInt_t resIndex) const; //! Update the complex coefficients for the resonances /*! \param [in] coeffs the new set of coefficients */ void updateCoeffs(const std::vector& coeffs); //! Collate the resonance parameters to initialise (or re-initialise) the model /*! NB: This has been factored out of the initialise() method to allow for use in the importation of parameters in LauAbsFitModel */ void collateResonanceParameters(); //! Set the helicity flip flag for new amplitude components /*! \param [in] boolean the helicity flip flag */ inline void flipHelicityForCPEigenstates(const Bool_t boolean) {flipHelicity_ = boolean;} //! Retrieve the mean efficiency across the Dalitz plot /*! \return the mean efficiency across the Dalitz plot */ inline const LauParameter& getMeanEff() const {return meanDPEff_;} //! Retrieve the overall Dalitz plot rate /*! \return the overall Dalitz plot rate */ inline const 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 fit fractions for the amplitude components /*! \return the fit fractions */ inline const LauParArray& getFitFractionsEfficiencyUncorrected() const {return fitFracEffUnCorr_;} //! Retrieve the total number of amplitude components /*! \return the total number of amplitude components */ inline UInt_t getnTotAmp() const {return nAmp_+nIncohAmp_;} //! Retrieve the number of coherent amplitude components /*! \return the number of coherent amplitude components */ inline UInt_t getnCohAmp() const {return nAmp_;} //! Retrieve the number of incoherent amplitude components /*! \return the number of incoherent amplitude components */ inline UInt_t getnIncohAmp() const {return nIncohAmp_;} //! Retrieve the normalisation factor for the log-likelihood function /*! \return the normalisation factor */ inline Double_t getDPNorm() const {return DPNorm_;} //! Retrieve the daughters /*! \return the daughters */ inline const LauDaughters* getDaughters() const {return daughters_;} //! Retrieve the Dalitz plot kinematics /*! \return the Dalitz plot kinematics */ inline const LauKinematics* getKinematics() const {return kinematics_;} //! 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 const LauAbsEffModel* getEffModel() const {return effModel_;} //! 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() const { return ! scfFractionModel_.empty(); } //! Retrieve any extra parameters/quantities (e.g. K-matrix total fit fractions) /*! \return any extra parameters */ inline const std::vector& getExtraParameters() const {return extraParameters_;} //! Retrieve the floating parameters of the resonance models /*! \return the list of floating parameters */ inline std::vector& getFloatingParameters() {return resonancePars_;} //! Whether to calculate separate rho and omega fit-fractions from LauRhoOmegaMix inline void calculateRhoOmegaFitFractions(const Bool_t calcFF) { calculateRhoOmegaFitFractions_ = calcFF; } protected: //! Print a summary of the model to be used void initSummary(); //! Initialise the internal storage for this model void initialiseVectors(); //! Zero the various values used to store integrals info void resetNormVectors(); //! Calculate the Dalitz plot normalisation integrals across the whole Dalitz plot void calcDPNormalisation(); //! Form the regions that are produced by the spaces between narrow resonances /*! \param [in] regions the regions defined around narrow resonances \param [in] min the minimum value of the invariant mass \param [in] max the maximum value of the invariant mass \return vector of pointers to LauDPPartialIntegralInfo objects that contain the individual coarse regions */ std::vector< std::pair > formGapsFromRegions(const std::vector< std::pair >& regions, const Double_t min, const Double_t max) const; //! Removes entries in the vector of LauDPPartialIntegralInfo* that are null /*! \param [in] regions the list of region pointers */ void cullNullRegions(std::vector& regions) const; //! Wrapper for LauDPPartialIntegralInfo constructor /*! \param [in] minm13 the minimum of the m13 range \param [in] maxm13 the maximum of the m13 range \param [in] minm23 the minimum of the m23 range \param [in] maxm23 the maximum of the m23 range \param [in] m13BinWidth the m13 bin width \param [in] m23BinWidth the m23 bin width \param [in] precision the precision required for the Gauss-Legendre weights \param [in] nAmp the number of coherent amplitude components \param [in] nIncohAmp the number of incoherent amplitude components \return 0 if the integration region has no internal points, otherwise returns a pointer to the newly constructed LauDPPartialIntegralInfo object */ LauDPPartialIntegralInfo* newDPIntegrationRegion(const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp) const; //! Correct regions to ensure that the finest integration grid takes precedence /*! \param [in] regions the windows in invariant mass \param [in] binnings the corresponding binnings for each window */ void correctDPOverlap(std::vector< std::pair >& regions, const std::vector& binnings) const; //! Create the integration grid objects for the m23 narrow resonance regions, including the overlap regions with the m13 narrow resonances /*! The overlap regions will have an m13Binnings x m23Binnings grid. The other regions will have a defaultBinning x m23Binnings grid. \param [in] m13Regions the limits of each narrow-resonance region in m13 \param [in] m23Regions the limits of each narrow-resonance region in m23 \param [in] m13Binnings the binning of each narrow-resonance region in m13 \param [in] m23Binnings the binning of each narrow-resonance region in m23 \param [in] precision the precision required for the Gauss-Legendre weights \param [in] defaultBinning the binning used in the bulk of the phase space \return vector of pointers to LauDPPartialIntegralInfo objects that contain the individual regions */ std::vector m23IntegrationRegions(const std::vector< std::pair >& m13Regions, const std::vector< std::pair >& m23Regions, const std::vector& m13Binnings, const std::vector& m23Binnings, const Double_t precision, const Double_t defaultBinning) const; //! Create the integration grid objects for the m13 narrow resonance regions, excluding the overlap regions with the m23 narrow resonances /*! The regions will have a m13Binnings x defaultBinning grid. The overlap regions are created by the m23IntegrationRegions function. \param [in] m13Regions the limits of each narrow-resonance region in m13 \param [in] m23Regions the limits of each narrow-resonance region in m23 \param [in] m13Binnings the binning of each narrow-resonance region in m13 \param [in] precision the precision required for the Gauss-Legendre weights \param [in] defaultBinning the binning used in the bulk of the phase space \return vector of pointers to LauDPPartialIntegralInfo objects that contain the individual regions */ std::vector m13IntegrationRegions(const std::vector< std::pair >& m13Regions, const std::vector< std::pair >& m23Regions, const std::vector& m13Binnings, const Double_t precision, const Double_t defaultBinning) const; //! Calculate the Dalitz plot normalisation integrals across the whole Dalitz plot void calcDPNormalisationScheme(); //! Determine which amplitudes and integrals need to be recalculated void findIntegralsToBeRecalculated(); //! Calculate the Dalitz plot normalisation integrals over a given range /*! \param [in] intInfo the integration information object */ void calcDPPartialIntegral(LauDPPartialIntegralInfo* intInfo); //! Write the results of the integrals (and related information) to a file 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 */ void setFFTerm(const UInt_t index, const Double_t realPart, const Double_t imagPart); //! Set the dynamic part of the intensity for a given incoherent amplitude component at the current point in the Dalitz plot /*! \param [in] index the index of the incoherent amplitude component \param [in] value the intensity */ void setIncohIntenTerm(const UInt_t index, const Double_t value); //! Calculate the amplitudes for all resonances for the current kinematics void calculateAmplitudes(); //! Calculate or retrieve the cached value of the amplitudes for all resonances at the specified integration grid point /*! \param [in,out] intInfo the integration information object \param [in] m13Point the grid index in m13 \param [in] m23Point the grid index in m23 */ void calculateAmplitudes( LauDPPartialIntegralInfo* intInfo, const UInt_t m13Point, const UInt_t m23Point ); //! Add the amplitude values (with the appropriate weight) at the current grid point to the running integral values /*! \param [in] weight the weight to apply */ void addGridPointToIntegrals(const Double_t weight); //! Calculate the total Dalitz plot amplitude at the current point in the Dalitz plot /*! \param [in] useEff whether to apply efficiency corrections */ void calcTotalAmp(const Bool_t useEff); //! Obtain the efficiency of the current event from the model /*! \return the efficiency */ 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 */ Double_t retrieveScfFraction(Int_t tagCat); //! 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 */ 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 */ LauComplex resAmp(const UInt_t index); //! Calculate the dynamic part of the intensity for a given incoherent component at the current point in the Dalitz plot /*! \param [in] index the index of the incoherent component within the model */ Double_t incohResAmp(const UInt_t index); //! Load the data for a given event /*! \param [in] iEvt the number of the event */ void setDataEventNo(UInt_t iEvt); //! Retrieve the named resonance /*! \param [in] resName the name of the resonance to retrieve \return the requested resonance */ LauAbsResonance* findResonance(const TString& resName); //! Retrieve a resonance by its index /*! \param [in] resIndex the index of the resonance to retrieve \return the requested resonance */ LauAbsResonance* getResonance(const UInt_t resIndex); //! Remove the charge from the given particle name /*! \param [in,out] string the particle name */ 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: //! Copy constructor (not implemented) LauIsobarDynamics(const LauIsobarDynamics& rhs); //! Copy assignment operator (not implemented) LauIsobarDynamics& operator=(const LauIsobarDynamics& rhs); //! The type used for containing the K-matrix propagators typedef std::map KMPropMap; //! The type used for mapping K-matrix components to their propagators typedef std::map KMStringMap; //! The daughters of the decay LauDaughters* daughters_; //! The kinematics of the decay LauKinematics* kinematics_; //! The efficiency model across the Dalitz plot LauAbsEffModel* 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 incoherent amplitude components UInt_t nIncohAmp_; //! The complex coefficients for the amplitude components std::vector Amp_; //! The normalisation factor for the log-likelihood function Double_t DPNorm_; //! The fit fractions for the amplitude components LauParArray fitFrac_; //! The efficiency-uncorrected fit fractions for the amplitude components LauParArray fitFracEffUnCorr_; //! The overall Dalitz plot rate LauParameter DPRate_; //! The mean efficiency across the Dalitz plot LauParameter meanDPEff_; //! The cached data for all events std::vector data_; //! The cached data for the current event LauCacheData* currentEvent_; //! any extra parameters/quantities (e.g. K-matrix total fit fractions) std::vector extraParameters_; //! The resonances in the model std::vector sigResonances_; //! The incoherent resonances in the model std::vector sigIncohResonances_; //! 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 resTypAmp_; //! The index of the daughter not produced by the resonance for each amplitude component std::vector resPairAmp_; //! The resonance types of all of the incoherent amplitude components std::vector incohResTypAmp_; //! The index of the daughter not produced by the resonance for each incoherent amplitude component std::vector incohResPairAmp_; //! The PDG codes of the daughters std::vector typDaug_; //! Whether the Dalitz plot is symmetrical Bool_t symmetricalDP_; //! Whether the Dalitz plot is fully symmetric Bool_t fullySymmetricDP_; //! Whether the Dalitz plot is a flavour-conjugate final state Bool_t flavConjDP_; //! Whether the integrals have been performed Bool_t integralsDone_; //! Whether the scheme for the integration has been determined Bool_t normalizationSchemeDone_; //! Force the symmetrisation of the integration in m13 <-> m23 for non-symmetric but flavour-conjugate final states Bool_t forceSymmetriseIntegration_; //! The storage of the integration scheme std::vector dpPartialIntegralInfo_; //! 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 bin width to use when integrating over mPrime Double_t mPrimeBinWidth_; //! The bin width to use when integrating over thetaPrime Double_t thPrimeBinWidth_; //! The value below which a resonance width is considered to be narrow Double_t narrowWidth_; //! The factor relating the width of the narrowest resonance and the binning size Double_t binningFactor_; //! 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 tagging category Int_t tagCat_; //! 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 > 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 > fifjSum_; //! The dynamic part of the amplitude for each amplitude component at the current point in the Dalitz plot std::vector ff_; //! The dynamic part of the intensity for each incoherent amplitude component at the current point in the Dalitz plot std::vector incohInten_; //! The event-by-event running total of the dynamical amplitude squared for each amplitude component std::vector fSqSum_; //! The event-by-event running total of the dynamical amplitude squared for each amplitude component std::vector fSqEffSum_; //! The normalisation factors for the dynamic parts of the amplitude for each amplitude component std::vector 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_; //! Flag to generate aSqMaxSet_ once generate is called Bool_t aSqMaxAuto_{kTRUE}; //! The helicity flip flag for new amplitude components Bool_t flipHelicity_; //! Flag to recalculate the normalisation Bool_t recalcNormalisation_; //! List of floating resonance parameters std::vector resonancePars_; //! List of floating resonance parameter values from previous calculation std::vector resonanceParValues_; //! Indices in sigResonances_ to point to the corresponding signal resonance(s) for each floating parameter std::vector< std::vector > resonanceParResIndex_; //! Resonance indices for which the amplitudes and integrals should be recalculated std::set integralsToBeCalculated_; //! Whether to calculate separate rho and omega fit fractions from the LauRhoOmegaMix model Bool_t calculateRhoOmegaFitFractions_; - ClassDef(LauIsobarDynamics,0) }; #endif diff --git a/inc/LauKMatrixProdPole.hh b/inc/LauKMatrixProdPole.hh index 25c7bee..f5e4191 100644 --- a/inc/LauKMatrixProdPole.hh +++ b/inc/LauKMatrixProdPole.hh @@ -1,107 +1,106 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdPole.hh \brief File containing declaration of LauKMatrixProdPole class. */ /*! \class LauKMatrixProdPole \brief Class for defining a K-matrix production pole amplitude term. Class for defining a K-matrix production pole amplitude term */ #ifndef LAU_KMATRIX_PROD_POLE #define LAU_KMATRIX_PROD_POLE #include "LauAbsResonance.hh" #include "TString.h" class LauKMatrixPropagator; class LauDaughters; class LauKinematics; class LauKMatrixProdPole : public LauAbsResonance { public: //! Constructor /*! \param [in] poleName name of the pole \param [in] poleIndex number of pole \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] propagator a K-matrix propagator \param [in] daughters the daughter particles \param [in] useProdAdler boolean to turn on/off the production Adler zero factor */ LauKMatrixProdPole( const TString& poleName, Int_t poleIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler = kFALSE); //! Destructor virtual ~LauKMatrixProdPole(); // Initialise the model virtual void initialise() {return;} //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::KMatrix;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! The amplitude calculation /*! \param [in] mass the invariant-mass for the channel \param [in] spinTerm the spin-term for the final channel \return the complex amplitude */ virtual LauComplex resAmp(const Double_t mass, const Double_t spinTerm); private: //! Copy constructor (not implemented) LauKMatrixProdPole(const LauKMatrixProdPole& rhs); //! Copy assignment operator (not implemented) LauKMatrixProdPole& operator=(const LauKMatrixProdPole& rhs); //! The K-matrix propagator LauKMatrixPropagator* thePropagator_; //! The number of the pole Int_t poleIndex_; //! Boolean to turn on/off the production Adler zero factor Bool_t useProdAdler_; - ClassDef(LauKMatrixProdPole, 0) // K-matrix production pole }; #endif diff --git a/inc/LauKMatrixProdSVP.hh b/inc/LauKMatrixProdSVP.hh index 50f8f53..8fd97c7 100644 --- a/inc/LauKMatrixProdSVP.hh +++ b/inc/LauKMatrixProdSVP.hh @@ -1,107 +1,106 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdSVP.hh \brief File containing declaration of LauKMatrixProdSVP class. */ /*! \class LauKMatrixProdSVP \brief Class for defining a K-matrix production "slowly-varying part" (SVP) amplitude Class for defining a K-matrix production "slowly-varying part" (SVP) amplitude */ #ifndef LAU_KMATRIX_PROD_SVP #define LAU_KMATRIX_PROD_SVP #include "LauAbsResonance.hh" #include "TString.h" class LauKMatrixPropagator; class LauDaughters; class LauKinematics; class LauKMatrixProdSVP : public LauAbsResonance { public: //! Constructor /*! \param [in] SVPName name of the slowly varying part (SVP) \param [in] channelIndex the channel number \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] propagator a K-matrix propagator \param [in] daughters the daughter particles \param [in] useProdAdler boolean to turn on/off the production Adler zero factor */ LauKMatrixProdSVP( const TString& SVPName, Int_t channelIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler = kFALSE); //! Destructor virtual ~LauKMatrixProdSVP(); //! Initialise the model virtual void initialise() {return;} //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::KMatrix;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ const std::vector& getFloatingParameters(); protected: //! The amplitude calculation /*! \param [in] mass the invariant-mass for the channel \param [in] spinTerm the spin-term for the final channel \return the complex amplitude */ virtual LauComplex resAmp(const Double_t mass, const Double_t spinTerm); private: //! Copy constructor (not implemented) LauKMatrixProdSVP(const LauKMatrixProdSVP& rhs); //! Copy assignment operator (not implemented) LauKMatrixProdSVP& operator=(const LauKMatrixProdSVP& rhs); //! The K-matrix propagator LauKMatrixPropagator* thePropagator_; //! The number of the channel Int_t channelIndex_; //! Boolean to turn on/off the production Adler zero factor Bool_t useProdAdler_; - ClassDef(LauKMatrixProdSVP, 0) // K-matrix production SVP term }; #endif \ No newline at end of file diff --git a/inc/LauKMatrixPropFactory.hh b/inc/LauKMatrixPropFactory.hh index 3af5191..0565e38 100644 --- a/inc/LauKMatrixPropFactory.hh +++ b/inc/LauKMatrixPropFactory.hh @@ -1,91 +1,90 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropFactory.hh \brief File containing declaration of LauKMatrixPropFactory class. */ /*! \class LauKMatrixPropFactory \brief Factory class for the K-matrix propagators. Factory class for creating and storing K-matrix propagator objects. */ #ifndef LAU_KMATRIX_PROP_FACTORY #define LAU_KMATRIX_PROP_FACTORY class LauKMatrixPropagator; #include "TString.h" #include class LauKMatrixPropFactory { public: //! Destructor virtual ~LauKMatrixPropFactory(); //! Get a static instance of this factory class. Only one is created per application. static LauKMatrixPropFactory* getInstance(); //! Retrieve the propagator if it already exists, otherwise create one. /*! \param [in] name name of the propagator \param [in] paramFileName the parameter file \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] nChannels the number of channels \param [in] nPoles the number of poles \param [in] rowIndex this specifies which row of the propagator should be used when summing over the amplitude channels \return the propagator */ LauKMatrixPropagator* getPropagator(const TString& name, const TString& paramFileName, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex); protected: //! A typedef to define a map used to keep track of which propagators have been created. typedef std::map KMatrixPropMap; private: //! Private constructor (to ensure the singleton nature of this class) LauKMatrixPropFactory(); //! Copy constructor (not implemented) LauKMatrixPropFactory(const LauKMatrixPropFactory& rhs); //! Copy assignment operator (not implemented) LauKMatrixPropFactory& operator=(const LauKMatrixPropFactory& rhs); //! The singleton instance static LauKMatrixPropFactory* theFactory_; //! The map used to store the propagator information KMatrixPropMap map_; - ClassDef(LauKMatrixPropFactory,0) }; #endif diff --git a/inc/LauKMatrixPropagator.hh b/inc/LauKMatrixPropagator.hh index 3c11acd..d013a78 100644 --- a/inc/LauKMatrixPropagator.hh +++ b/inc/LauKMatrixPropagator.hh @@ -1,637 +1,634 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropagator.hh \brief File containing declaration of LauKMatrixPropagator class. */ /*! \class LauKMatrixPropagator \brief Class for defining a K-matrix propagator. Class used to define a K-matrix propagator. See the following papers for info: hep-ph/0204328, hep-ex/0312040, [hep-ex]0804.2089 and hep-ph/9705401. */ #ifndef LAU_KMATRIX_PROPAGATOR #define LAU_KMATRIX_PROPAGATOR #include "LauConstants.hh" #include "LauResonanceMaker.hh" #include "LauResonanceInfo.hh" #include "TMatrixD.h" #include "TString.h" #include #include class LauParameter; class LauKinematics; class LauComplex; class LauKMatrixPropagator { public: //! Constructor /*! \param [in] name name of the propagator \param [in] paramFileName the parameter file name \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] nChannels the number of channels \param [in] nPoles the number of poles \param [in] rowIndex this specifies which row of the propagator should be used when summing over the amplitude channels */ LauKMatrixPropagator( const TString& name, const TString& paramFileName, const Int_t resPairAmpInt, const Int_t nChannels, const Int_t nPoles, const Int_t rowIndex = 1 ); //! Destructor virtual ~LauKMatrixPropagator(); //! Calculate the K-matrix propagator for the given s value /*! \param [in] s the invariant mass squared */ void updatePropagator(const Double_t s); //! Read an input file to set parameters /*! \param [in] inputFile name of the input file */ void setParameters(const TString& inputFile); //! Set flag to ignore Blatt-Weisskopf-like barrier factor void ignoreBWBarrierFactor() {includeBWBarrierFactor_=kFALSE;} //! Get the scattering K matrix /*! \return the real, symmetric scattering K matrix */ TMatrixD getKMatrix() const {return ScattKMatrix_;} //! Get the real part of the propagator full matrix /*! \return the real part of the propagator full matrix */ TMatrixD getRealPropMatrix() const {return realProp_;} //! Get the negative imaginary part of the full propagator matrix /*! \return the negative imaginary part of the full propagator matrix */ TMatrixD getNegImagPropMatrix() const {return negImagProp_;} //! Get the real part of the term of the propagator /*! \param [in] channelIndex the channel number \return the real part of the propagator term */ Double_t getRealPropTerm(const Int_t channelIndex) const; //! Get the imaginary part of the term of the propagator /*! \param [in] channelIndex the channel number \return the imaginiary part of the propagator term */ Double_t getImagPropTerm(const Int_t channelIndex) const; //! Get the 1/(m_pole^2 -s) terms for the scattering and production K-matrix formulae /*! \param [in] poleIndex the number of the pole required \return the value of 1/(m_pole^2 -s) */ Double_t getPoleDenomTerm(const Int_t poleIndex) const; //! Get spin of K-matrix /*! \param [in] iChannel the index of the channel \return the value of the orbital angular momentum, L_, for this channel */ Int_t getL(const Int_t iChannel) const {return L_[iChannel];} //! Get index of final channel /*! \return the index of the channel into which the scattering happens */ Int_t getIndex() const {return index_;}; //! Get pole mass parameters, set according to the input file /*! \param [in] poleIndex number of the required pole \return the parameter of the pole mass */ LauParameter& getPoleMassSqParameter(const Int_t poleIndex); //! Get coupling constants that were loaded from the input file /*! \param [in] poleIndex number of the required pole \param [in] channelIndex number of the required channel \return the value of the coupling constant */ Double_t getCouplingConstant(const Int_t poleIndex, const Int_t channelIndex) const; //! Get coupling parameters, set according to the input file /*! \param [in] poleIndex number of the required pole \param [in] channelIndex number of the required channel \return the parameter of the coupling constant */ LauParameter& getCouplingParameter(const Int_t poleIndex, const Int_t channelIndex); //! Get scattering constants that were loaded from the input file /*! \param [in] channel1Index number of the first channel index \param [in] channel2Index number of the second channel index \return the value of the scattering constant */ Double_t getScatteringConstant(const Int_t channel1Index, const Int_t channel2Index) const; //! Get scattering parameters, set according to the input file /*! \param [in] channel1Index number of the first channel index \param [in] channel2Index number of the second channel index \return the parameter of the scattering constant */ LauParameter& getScatteringParameter(const Int_t channel1Index, const Int_t channel2Index); //! Get mSq0 production parameter /*! \return the mSq0 parameter */ LauParameter& getmSq0() {return mSq0_;} //! Get s0Scatt production parameter /*! \return the s0Scatt parameter */ LauParameter& gets0Scatt() {return s0Scatt_;} //! Get s0 production parameter /*! \return the s0Prod parameter */ LauParameter& gets0Prod() {return s0Prod_;} //! Get sA production parameter /*! \return the sA parameter */ LauParameter& getsA() {return sA_;} //! Get sA0 production parameter /*! \return the sA0 parameter */ LauParameter& getsA0() {return sA0_;} //! Get the "slowly-varying part" term of the amplitude /*! \return the svp term */ Double_t getProdSVPTerm() const {return prodSVP_;} //! Get the full complex propagator term for a given channel /*! \param [in] channelIndex the number of the required channel \return the complex propagator term */ LauComplex getPropTerm(const Int_t channelIndex) const; //! Get the DP axis identifier /*! \return the value to identify the DP axis in question */ Int_t getResPairAmpInt() const {return resPairAmpInt_;} //! Get the number of channels /*! \return the number of channels */ Int_t getNChannels() const {return nChannels_;} //! Get the number of poles /*! \return the number of poles */ Int_t getNPoles() const {return nPoles_;} //! Get the propagator name /*! \return the name of the propagator */ TString getName() const {return name_;} //! Get the unitary transition amplitude for the given channel /*! \param [in] s The invariant mass squared \param [in] channel The index number of the channel process \return the complex amplitude T */ LauComplex getTransitionAmp(const Double_t s, const Int_t channel); //! Get the complex phase space term for the given channel and invariant mass squared /*! \param [in] s The invariant mass squared \param [in] channel The index number of the channel process \return the complex phase space term rho(channel, channel) */ LauComplex getPhaseSpaceTerm(const Double_t s, const Int_t channel); //! Get the Adler zero factor, which is set when updatePropagator is called /*! \return the Adler zero factor */ Double_t getAdlerZero() const {return adlerZeroFactor_;} //! Get the THat amplitude for the given s and channel number /*! \param [in] s The invariant mass squared \param [in] channel The index number of the channel process \return the complex THat amplitude */ LauComplex getTHat(const Double_t s, const Int_t channel); protected: // Integers to specify the allowed channels for the phase space calculations. // Please keep Zero at the start and leave TotChannels at the end // whenever more channels are added to this. //! Integers to specify the allowed channels for the phase space calculations enum class KMatrixChannels {Zero, PiPi, KK, FourPi, EtaEta, EtaEtaP, KPi, KEtaP, KThreePi, D0K, Dstar0K, TotChannels}; //! Calculate the scattering K-matrix for the given value of s /*! \param [in] s the invariant mass squared */ void calcScattKMatrix(const Double_t s); //! Calculate the real and imaginary part of the phase space density diagonal matrix /*! \param [in] s the invariant mass squared */ void calcRhoMatrix(const Double_t s); //! Retrieve the complex phasespace density for a given channel /*! \param [in] s the invariant mass squared \param [in] phaseSpaceIndex the phasespace index of the channel \return the complex phasespace density */ LauComplex getRho(const Double_t s, const LauKMatrixPropagator::KMatrixChannels) const; //! Calculate the (real) gamma angular-momentum barrier matrix /*! \param [in] s the invariant mass squared */ void calcGammaMatrix(const Double_t s); //! Calculate the gamma angular-momentum barrier /*! \param [in] iCh the channel index \param [in] s the invariant mass squared \return the centrifugal barrier factor for L=0,1, or 2 */ Double_t calcGamma(const Int_t iCh, const Double_t s) const; //! Calulate the term 1/(m_pole^2 - s) for the scattering and production K-matrix formulae /*! \param [in] s the invariant mass squared */ void calcPoleDenomVect(const Double_t s); //! Calculate the D0K+ phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcD0KRho(const Double_t s) const; //! Calculate the D*0K+ phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcDstar0KRho(const Double_t s) const; //! Calculate the pipi phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcPiPiRho(const Double_t s) const; //! Calculate the KK phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcKKRho(const Double_t s) const; //! Calculate the 4 pi phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcFourPiRho(const Double_t s) const; //! Calculate the eta-eta phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcEtaEtaRho(const Double_t s) const; //! Calculate the eta-eta' phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcEtaEtaPRho(const Double_t s) const; //! Calculate the Kpi phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcKPiRho(const Double_t s) const; //! Calculate the K-eta' phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcKEtaPRho(const Double_t s) const; //! Calculate the Kpipipi phase space factor /*! \param [in] s the invariant mass squared \return the complex phase space factor */ LauComplex calcKThreePiRho(const Double_t s) const; //! Calculate the "slow-varying part" /*! \param [in] s the invariant mass squared \param [in] s0 the invariant mass squared at the Adler zero \return the SVP term */ Double_t calcSVPTerm(const Double_t s, const Double_t s0) const; //! Update the scattering "slowly-varying part" /*! \param [in] s the invariant mass squared */ void updateScattSVPTerm(const Double_t s); //! Update the production "slowly-varying part" /*! \param [in] s the invariant mass squared */ void updateProdSVPTerm(const Double_t s); //! Calculate the multiplicative factor containing severa Adler zero constants /*! \param [in] s the invariant mass squared */ void updateAdlerZeroFactor(const Double_t s); //! Check the phase space factors that need to be used /*! \param [in] phaseSpaceInt phase space types \return true of false */ Bool_t checkPhaseSpaceType(const Int_t phaseSpaceInt) const; //! Get the unitary transition amplitude matrix for the given kinematics /*! \param [in] kinematics The pointer to the constant kinematics */ void getTMatrix(const LauKinematics* kinematics); //! Get the unitary transition amplitude matrix for the given kinematics /*! \param [in] s The invariant mass squared of the system */ void getTMatrix(const Double_t s); //! Get the square root of the phase space matrix void getSqrtRhoMatrix(); private: //! Copy constructor (not implemented) LauKMatrixPropagator(const LauKMatrixPropagator& rhs)=delete; //! Copy assignment operator (not implemented) LauKMatrixPropagator& operator=(const LauKMatrixPropagator& rhs)=delete; //! Initialise and set the dimensions for the internal matrices and parameter arrays void initialiseMatrices(); //! Store the (phase space) channel indices from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file */ void storeChannels(const std::vector& theLine); //! Store the pole mass and couplings from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file */ void storePole(const std::vector& theLine); //! Store the scattering coefficients from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file */ void storeScattering(const std::vector& theLine); //! Store the channels' characteristic radii from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file */ void storeRadii(const std::vector& theLine); //! Store the channels' angular momenta from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file \param [in] a Vector of integers corresponding to parameter in the propagator denominator */ void storeOrbitalAngularMomenta(const std::vector& theLine, std::vector& a); //! Store the barrier-factor parameter from a line in the parameter file /*! \param [in] theLine Vector of strings corresponding to the line from the parameter file \param [in] a Vector of integers corresponding to parameter in the propagator denominator */ void storeBarrierFactorParameter(const std::vector& theLine, std::vector& a); //! Store miscelleanous parameters from a line in the parameter file /*! \param [in] keyword the name of the parameter to be set \param [in] parString the string containing the value of the parameter */ void storeParameter(const TString& keyword, const TString& parString); //! String to store the propagator name TString name_; //! Name of the input parameter file TString paramFileName_; //! Number to identify the DP axis in question Int_t resPairAmpInt_; //! Row index - 1 Int_t index_; //! s value of the previous pole Double_t previousS_{0.0}; //! "slowly-varying part" for the scattering K-matrix Double_t scattSVP_{0.0}; //! "slowly-varying part" for the production K-matrix Double_t prodSVP_{0.0}; //! Real part of the propagator matrix TMatrixD realProp_; //! Imaginary part of the propagator matrix TMatrixD negImagProp_; //! Scattering K-matrix TMatrixD ScattKMatrix_; //! Real part of the phase space density diagonal matrix TMatrixD ReRhoMatrix_; //! Imaginary part of the phase space density diagonal matrix TMatrixD ImRhoMatrix_; //! Gamma angular-momentum barrier matrix TMatrixD GammaMatrix_; //! Identity matrix TMatrixD IMatrix_; //! Null matrix TMatrixD zeroMatrix_; //! Real part of the square root of the phase space density diagonal matrix TMatrixD ReSqrtRhoMatrix_; //! Imaginary part of the square root of the phase space density diagonal matrix TMatrixD ImSqrtRhoMatrix_; //! Real part of the unitary T matrix TMatrixD ReTMatrix_; //! Imaginary part of the unitary T matrix TMatrixD ImTMatrix_; //! Number of channels Int_t nChannels_; //! Number of poles Int_t nPoles_; //! Vector of orbital angular momenta std::vector L_; //! Boolean to indicate whether storeBarrierFactorParameter has been called Bool_t haveCalled_storeBarrierFactorParameter{kFALSE}; //! Boolean to dictate whether to include Blatt-Weisskopf-like denominator in K-matrix centrifugal barrier factor Bool_t includeBWBarrierFactor_{kTRUE}; //! Vector of squared pole masses std::vector mSqPoles_; //! Array of coupling constants LauParArray gCouplings_; //! Array of scattering SVP values LauParArray fScattering_; //! Vector of characteristic radii std::vector radii_; //! Vector of ratio a/R^2 std::vector gamAInvRadSq_; //! Vector of phase space types std::vector phaseSpaceTypes_; //! Vector of squared masses std::vector mSumSq_; //! Vector of mass differences std::vector mDiffSq_; //! Vector of 1/(m_pole^2 - s) terms for scattering and production K-matrix formulae std::vector poleDenomVect_; //! Constant from input file LauParameter mSq0_; //! Constant from input file LauParameter s0Scatt_; //! Constant from input file LauParameter s0Prod_; //! Constant from input file LauParameter sA_; //! Constant from input file LauParameter sA0_; //! Defined as 0.5*sA*mPi*mPi Double_t sAConst_{0.0}; //! Defined as 4*mPi*mPi const Double_t m2piSq_{4.0*LauConstants::mPiSq}; //! Defined as 4*mK*mK const Double_t m2KSq_{4.0*LauConstants::mKSq}; //! Defined as 4*mEta*mEta const Double_t m2EtaSq_{4.0*LauConstants::mEtaSq}; //! Defined as (mEta+mEta')^2 const Double_t mEtaEtaPSumSq_{(LauConstants::mEta + LauConstants::mEtaPrime)*(LauConstants::mEta + LauConstants::mEtaPrime)}; - //! Defined as (mEta-mEta')^2 - const Double_t mEtaEtaPDiffSq_{(LauConstants::mEta - LauConstants::mEtaPrime)*(LauConstants::mEta - LauConstants::mEtaPrime)}; //! Defined as (mK+mPi)^2 const Double_t mKpiSumSq_{(LauConstants::mK + LauConstants::mPi)*(LauConstants::mK + LauConstants::mPi)}; //! Defined as (mK-mPi)^2 const Double_t mKpiDiffSq_{(LauConstants::mK - LauConstants::mPi)*(LauConstants::mK - LauConstants::mPi)}; //! Defined as (mK+mEta')^2 const Double_t mKEtaPSumSq_{(LauConstants::mK + LauConstants::mEtaPrime)*(LauConstants::mK + LauConstants::mEtaPrime)}; //! Defined as (mK-mEta')^2 const Double_t mKEtaPDiffSq_{(LauConstants::mK - LauConstants::mEtaPrime)*(LauConstants::mK - LauConstants::mEtaPrime)}; //! Defined as (mK-3*mPi)^2 const Double_t mK3piDiffSq_{(LauConstants::mK - 3.0*LauConstants::mPi)*(LauConstants::mK - 3.0*LauConstants::mPi)}; //! Factor used to calculate the Kpipipi phase space term const Double_t k3piFactor_{TMath::Power((1.44 - mK3piDiffSq_)/1.44, -2.5)}; //! Factor used to calculate the pipipipi phase space term const Double_t fourPiFactor1_{16.0*LauConstants::mPiSq}; //! Factor used to calculate the pipipipi phase space term const Double_t fourPiFactor2_{TMath::Sqrt(1.0 - fourPiFactor1_)}; //! Defined as (mD0+mK)^2 const Double_t mD0KSumSq_{(LauConstants::mD0 + LauConstants::mK)*(LauConstants::mD0 + LauConstants::mK)}; //! Defined as (mD0-mK)^2 const Double_t mD0KDiffSq_{(LauConstants::mD0 - LauConstants::mK)*(LauConstants::mD0 - LauConstants::mK)}; //! Defined as (mD*0+mK)^2 const Double_t mDstar0KSumSq_{(LauResonanceMaker::get().getResInfo("D*0")->getMass()->value() + LauConstants::mK)*(LauResonanceMaker::get().getResInfo("D*0")->getMass()->value() + LauConstants::mK)}; //! Defined as (mD*0-mK)^2 const Double_t mDstar0KDiffSq_{(LauResonanceMaker::get().getResInfo("D*0")->getMass()->value() - LauConstants::mK)*(LauResonanceMaker::get().getResInfo("D*0")->getMass()->value() - LauConstants::mK)}; //! Multiplicative factor containing various Adler zero constants Double_t adlerZeroFactor_{0.0}; //! Tracks if all params have been set Bool_t parametersSet_{kFALSE}; //! Control the output of the functions static constexpr Bool_t verbose_{kFALSE}; //! Control if scattering constants are channel symmetric: f_ji = f_ij Bool_t scattSymmetry_{kFALSE}; - ClassDef(LauKMatrixPropagator,0) // K-matrix amplitude model }; #endif diff --git a/inc/LauKappaRes.hh b/inc/LauKappaRes.hh index 5a9bc5d..78d06d7 100644 --- a/inc/LauKappaRes.hh +++ b/inc/LauKappaRes.hh @@ -1,203 +1,202 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKappaRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauKappaRes(LauResonanceInfo* resInfo, const 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 value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the b1 parameter /*! \param [in] b1 new value for b1 parameter */ void setB1Value(const Double_t b1); //! Set the b2 parameter /*! \param [in] b2 new value for b2 parameter */ void setB2Value(const Double_t b2); //! Set the A parameter /*! \param [in] A new value for A parameter */ void setAValue(const Double_t A); //! Set the m0 parameter /*! \param [in] m0 new value for m0 parameter */ void setM0Value(const Double_t m0); //! Get the b1 parameter value /*! \return value of the b1 parameter */ Double_t getB1Value() const { return (b1_!=0) ? b1_->unblindValue() : 0.0; } //! Get the b2 parameter value /*! \return value of the b2 parameter */ Double_t getB2Value() const { return (b2_!=0) ? b2_->unblindValue() : 0.0; } //! Get the A parameter value /*! \return value of the A parameter */ Double_t getAValue() const { return (a_!=0) ? a_->unblindValue() : 0.0; } //! Get the m0 parameter value /*! \return value of the m0 parameter */ Double_t getM0Value() const { return (m0_!=0) ? m0_->unblindValue() : 0.0; } //! Fix the b1 parameter value /*! \return kTRUE if the b1 parameter is fixed, kFALSE otherwise */ Bool_t fixB1Value() const { return (b1_!=0) ? b1_->fixed() : 0.0; } //! Fix the b2 parameter value /*! \return kTRUE if the b2 parameter is fixed, kFALSE otherwise */ Bool_t fixB2Value() const { return (b2_!=0) ? b2_->fixed() : 0.0; } //! Fix the A parameter value /*! \return kTRUE if the A parameter is fixed, kFALSE otherwise */ Bool_t fixAValue() const { return (a_!=0) ? a_->fixed() : 0.0; } //! Fix the m0 parameter value /*! \return kTRUE if the m0 parameter is fixed, kFALSE otherwise */ Bool_t fixM0Value() const { return (m0_!=0) ? m0_->fixed() : 0.0; } //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); //! Check that Kappa daughters are K and pi void checkDaughterTypes() const; private: //! Copy constructor (not implemented) LauKappaRes(const LauKappaRes& rhs); //! Copy assignment operator (not implemented) LauKappaRes& operator=(const LauKappaRes& rhs); //! Square of (mK + mPi) const Double_t mSumSq_; //! Defined as mK*mK - 0.5*mPi*mPi const Double_t sAdler_; //! Factor from BES data LauParameter* b1_; //! Factor from BES data LauParameter* b2_; //! Factor from BES data LauParameter* a_; //! Factor from BES data LauParameter* m0_; - ClassDef(LauKappaRes,0) // Kappa resonance model }; #endif diff --git a/inc/LauKinematics.hh b/inc/LauKinematics.hh index 1ab595b..9061795 100644 --- a/inc/LauKinematics.hh +++ b/inc/LauKinematics.hh @@ -1,675 +1,674 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKinematics.hh \brief File containing declaration of LauKinematics class. */ /*! \class LauKinematics \brief Class for calculating 3-body kinematic quantities. Class for defining the many routines related to the three body kinematics. Given the two DP co-ordinates, all other useful quantities e.g. the helicity angles are calculated. Optionally, the so-called ``square Dalitz plot'' quantities can also be calculated. */ #ifndef LAU_KINEMATICS #define LAU_KINEMATICS #include #include "Rtypes.h" #include "TMath.h" class LauKinematics { public: //! Constructor /*! \param [in] m1 the first daughter mass \param [in] m2 the second daughter mass \param [in] m3 the third daughter mass \param [in] mParent the parent particle mass \param [in] calcSquareDPCoords boolean flag to enable/disable calculation of the square Dalitz plot co-ordinates \param [in] symmetricalDP boolean flag to indicate whether the DP is symmetric (i.e. two identical particle in final state) \param [in] fullySymmetricDP boolean flag to indicate whether the DP is fully symmetric (i.e. all three final-state particles are identical) */ LauKinematics(const Double_t m1, const Double_t m2, const Double_t m3, const Double_t mParent, const Bool_t calcSquareDPCoords = kFALSE, const Bool_t symmetricalDP = kFALSE, const Bool_t fullySymmetricDP = kFALSE); //! Destructor virtual ~LauKinematics(); //! Enable/disable the calculation of square Dalitz plot co-ordinates /*! \param [in] calcSquareDPCoords kTRUE/kFALSE to enable/disable calculation of the square DP co-ordinates */ inline void squareDP( const Bool_t calcSquareDPCoords ) { squareDP_ = calcSquareDPCoords; } //! Are the square Dalitz plot co-ordinates being calculated? /*! \return kTRUE if the square Dalitz plot co-ordinates are being calculated, kFALSE otherwise */ inline Bool_t squareDP() const { return squareDP_; } //! Is the DP symmetric? /*! \return kTRUE if the DP is symmetric (i.e. daughters 1 and 2 are identical), kFALSE otherwise */ inline Bool_t gotSymmetricalDP() const { return (symmetricalDP_ && ! fullySymmetricDP_); } //! Is the DP fully symmetric? /*! \return kTRUE if the DP is fully symmetric (i.e. daughters 1, 2 and 3 are identical), kFALSE otherwise */ inline Bool_t gotFullySymmetricDP() const { return fullySymmetricDP_; } //! Enable/disable warning messages inline void warningMessages(const Bool_t boolean) { warnings_ = boolean; } //! Update all kinematic quantities based on the DP co-ordinates m13Sq and m23Sq /*! It can be useful to first check that the point is within the kinematic boundary (using LauKinematics::withinDPLimits) before calling this method. \param [in] m13Sq the invariant mass squared of daughters 1 and 3 \param [in] m23Sq the invariant mass squared of daughters 2 and 3 */ void updateKinematics(const Double_t m13Sq, const Double_t m23Sq); //! Update all kinematic quantities based on the square DP co-ordinates m' and theta' /*! It can be useful to first check that the point is within the kinematic boundary (using LauKinematics::withinSqDPLimits) before calling this method. \param [in] mPrime the m' co-ordinate \param [in] thetaPrime the theta' co-ordinate */ void updateSqDPKinematics(const Double_t mPrime, const Double_t thetaPrime); //! Update all kinematic quantities based on m23 and cos(theta23) /*! \param [in] m23 the invariant mass of daughters 2 and 3 \param [in] c23 the cosine of the helicity angle theta23, \see getc23 */ void updateKinematicsFrom23(const Double_t m23, const Double_t c23); //! Update all kinematic quantities based on m13 and cos(theta13) /*! \param [in] m13 the invariant mass of daughters 1 and 3 \param [in] c13 the cosine of the helicity angle theta13, \see getc13 */ void updateKinematicsFrom13(const Double_t m13, const Double_t c13); //! Update all kinematic quantities based on m12 and cos(theta12) /*! \param [in] m12 the invariant mass of daughters 1 and 2 \param [in] c12 the cosine of the helicity angle theta12, \see getc12 */ void updateKinematicsFrom12(const Double_t m12, const Double_t c12); //! Calculate the Jacobian for the transformation m23^2, m13^2 -> m', theta' (square DP) at the given point in the square DP /*! \param [in] mPrime the m' co-ordinate \param [in] thPrime the theta' co-ordinate \return the jacobian of the transformation */ Double_t calcSqDPJacobian(const Double_t mPrime, const Double_t thPrime) const; //! Calculate the Jacobian for the transformation m23^2, m13^2 -> m', theta' (square DP) at the currently stored point in the square DP /*! \return the jacobian of the transformation */ Double_t calcSqDPJacobian() const; //! Routine to generate events flat in phase-space /*! \param [out] m13Sq the invariant mass squared of daughters 1 and 3 \param [out] m23Sq the invariant mass squared of daughters 2 and 3 */ void genFlatPhaseSpace(Double_t& m13Sq, Double_t& m23Sq) const; //! Routine to generate events flat in the square Dalitz plot /*! \param [out] mPrime the m' variable \param [out] thetaPrime the theta' variable */ void genFlatSqDP(Double_t& mPrime, Double_t& thetaPrime) const; //! Check whether a given (m13Sq,m23Sq) point is within the kinematic limits of the Dalitz plot /*! This method first checks that m13Sq is within its absolute min and max and then for the given m13Sq calculates the local min and max of m23Sq and checks whether the given m23Sq satisfies these bounds. \param [in] m13Sq the invariant mass squared of daughters 1 and 3 \param [in] m23Sq the invariant mass squared of daughters 2 and 3 \return kTRUE if the event is inside the kinematic limit, kFALSE otherwise */ Bool_t withinDPLimits(const Double_t m13Sq, const Double_t m23Sq) const; //! Check whether a given (m13Sq,m23Sq) point is within the kinematic limits of the Dalitz plot (alternate method) /*! This method first checks that m23Sq is within its absolute min and max and then for the given m23Sq calculates the local min and max of m13Sq and checks whether the given m13Sq satisfies these bounds. \param [in] m13Sq the m13 invariant mass pair squared \param [in] m23Sq the m23 invariant mass pair squared \return kTRUE if the event is inside the kinematic limit, kFALSE otherwise */ Bool_t withinDPLimits2(const Double_t m13Sq, const Double_t m23Sq) const; //! Check whether a given (m',theta') point is within the kinematic limits of the Dalitz plot /*! \param [in] mPrime the m' co-ordinate \param [in] thetaPrime the theta' co-ordinate \return kTRUE if the event is inside the kinematic limit, kFALSE otherwise */ Bool_t withinSqDPLimits(const Double_t mPrime, const Double_t thetaPrime) const; //! Calculate the third invariant mass square from the two provided (e.g. mjkSq from mijSq and mikSq) /*! \param [in] firstMassSq the first invariant mass squared \param [in] secondMassSq the second invariant mass squared \return the third invariant mass square */ Double_t calcThirdMassSq(const Double_t firstMassSq, const Double_t secondMassSq) const; //! Calculate the distance from the currently set (m13Sq, m23Sq) point to the centre of the Dalitz plot (which is defined as the point where m12=m13=m23) /*! \return the distance to the DP centre */ Double_t distanceFromDPCentre() const; //! Calculate the distance from a given (m13Sq, m23Sq) point to the centre of the Dalitz plot (which is defined as the point where m12=m13=m23) /*! \return the distance to the DP centre */ Double_t distanceFromDPCentre(const Double_t m13Sq, const Double_t m23Sq) const; //! Get the m12 invariant mass /*! \return the m12 invariant mass */ inline Double_t getm12() const {return m12_;} //! Get the m23 invariant mass /*! \return the m23 invariant mass */ inline Double_t getm23() const {return m23_;} //! Get the m13 invariant mass /*! \return the m13 invariant mass */ inline Double_t getm13() const {return m13_;} //! Get the m12 invariant mass square /*! \return the m12 invariant mass square */ inline Double_t getm12Sq() const {return m12Sq_;} //! Get the m23 invariant mass square /*! \return the m23 invariant mass square */ inline Double_t getm23Sq() const {return m23Sq_;} //! Get the m13 invariant mass square /*! \return the m13 invariant mass square */ inline Double_t getm13Sq() const {return m13Sq_;} //! Get the cosine of the helicity angle theta12 /*! theta12 is defined as the angle between 1&3 in the rest frame of 1&2 \return the cosine of the helicity angle theta12 */ inline Double_t getc12() const {return c12_;} //! Get the cosine of the helicity angle theta23 /*! theta23 is defined as the angle between 3&1 in the rest frame of 2&3 \return the cosine of the helicity angle theta23 */ inline Double_t getc23() const {return c23_;} //! Get the cosine of the helicity angle theta13 /*! theta13 is defined as the angle between 3&2 in the rest frame of 1&3 \return the cosine of the helicity angle theta13 */ inline Double_t getc13() const {return c13_;} //! Get m' value /*! \return m' value */ inline Double_t getmPrime() const {return mPrime_;} //! Get theta' value /*! \return theta' value */ inline Double_t getThetaPrime() const {return thetaPrime_;} //! Get parent mass /*! \return parent mass */ inline Double_t getmParent() const {return mParent_;} //! Get parent mass squared /*! \return parent mass squared */ inline Double_t getmParentSq() const {return mParentSq_;} //! Get the box area defined from the kinematic bounds /*! The box area is defined as:\n [(M-m3)^2 - (m1+m2)^2]*[(M-m2)^2 - (m1+m3)^2] .:. (m13SqMax - m13SqMin)*(m23SqMax - m23SqMin) \return the Dalitz plot box area */ inline Double_t getDPBoxArea() const {return (mSqMax_[1] - mSqMin_[1])*(mSqMax_[0] - mSqMin_[0]);} //! Flips the DP variables m13^2 <-> m23^2 and recalculates all kinematic quantities /*! Useful in the case of symmetrical Dalitz plots, i.e. when two final state particles are identical */ void flipAndUpdateKinematics(); //! Cyclically rotates the DP variables (m12 -> m23, m23 -> m13, m13 -> m12) and recalculates all kinematic quantities /*! Useful in the case of a fully symmetric Dalitz plot, i.e. when all three final state particles are identical */ void rotateAndUpdateKinematics(); //! Get the m1 mass /*! \return the m1 mass */ inline Double_t getm1() const {return m1_;} //! Get the m2 mass /*! \return the m2 mass */ inline Double_t getm2() const {return m2_;} //! Get the m3 mass /*! \return the m3 mass */ inline Double_t getm3() const {return m3_;} //! Get the m23 minimum defined as (m2 + m3) /*! \return the minimum value for m23 */ inline Double_t getm23Min() const {return TMath::Sqrt(mSqMin_[0]);} //! Get the m13 minimum defined as (m1 + m3) /*! \return the minimum value for m13 */ inline Double_t getm13Min() const {return TMath::Sqrt(mSqMin_[1]);} //! Get the m12 minimum defined as (m1 + m2) /*! \return the minimum value for m12 */ inline Double_t getm12Min() const {return TMath::Sqrt(mSqMin_[2]);} //! Get the m23 maximum defined as (mParent - m1) /*! \return the maximum value for m23 */ inline Double_t getm23Max() const {return TMath::Sqrt(mSqMax_[0]);} //! Get the m13 maximum defined as (mParent - m2) /*! \return the maximum value for m13 */ inline Double_t getm13Max() const {return TMath::Sqrt(mSqMax_[1]);} //! Get the m12 maximum defined as (mParent - m3) /*! \return the maximum value for m12 */ inline Double_t getm12Max() const {return TMath::Sqrt(mSqMax_[2]);} //! Get the m23Sq minimum, (m2 + m3)^2 /*! \return the minimum value for m23Sq */ inline Double_t getm23SqMin() const {return mSqMin_[0];} //! Get the m13Sq minimum, (m1 + m3)^2 /*! \return the minimum value for m13Sq */ inline Double_t getm13SqMin() const {return mSqMin_[1];} //! Get the m12Sq minimum, (m1 + m2)^2 /*! \return the minimum value for m12Sq */ inline Double_t getm12SqMin() const {return mSqMin_[2];} //! Get the m23Sq maximum, (mParent - m1)^2 /*! \return the maximum value for m23Sq */ inline Double_t getm23SqMax() const {return mSqMax_[0];} //! Get the m13Sq maximum, (mParent - m2)^2 /*! \return the maximum value for m13Sq */ inline Double_t getm13SqMax() const {return mSqMax_[1];} //! Get the m12Sq maximum, (mParent - m3)^2 /*! \return the maximum value for m12Sq */ inline Double_t getm12SqMax() const {return mSqMax_[2];} //! Get the momentum of the track 1 in 12 rest frame /*! \return the momentum of track 1 in 12 rest frame */ inline Double_t getp1_12() const {return p1_12_;} //! Get the momentum of the track 3 in 12 rest frame /*! \return the momentum of track 3 in 12 rest frame */ inline Double_t getp3_12() const {return p3_12_;} //! Get the momentum of the track 2 in 23 rest frame /*! \return the momentum of track 2 in 23 rest frame */ inline Double_t getp2_23() const {return p2_23_;} //! Get the momentum of the track 1 in 23 rest frame /*! \return the momentum of track 1 in 23 rest frame */ inline Double_t getp1_23() const {return p1_23_;} //! Get the momentum of the track 1 in 13 rest frame /*! \return the momentum of track 1 in 13 rest frame */ inline Double_t getp1_13() const {return p1_13_;} //! Get the momentum of the track 2 in 13 rest frame /*! \return the momentum of track 2 in 13 rest frame */ inline Double_t getp2_13() const {return p2_13_;} //! Get the momentum of the track 1 in parent rest frame /*! \return the momentum of track 1 in parent rest frame */ inline Double_t getp1_Parent() const {return p1_Parent_;} //! Get the momentum of the track 2 in parent rest frame /*! \return the momentum of track 2 in parent rest frame */ inline Double_t getp2_Parent() const {return p2_Parent_;} //! Get the momentum of the track 3 in parent rest frame /*! \return the momentum of track 3 in parent rest frame */ inline Double_t getp3_Parent() const {return p3_Parent_;} //! Method to draw the Dalitz plot contours on the top of the histo previously drawn /*! \param [in] orientation orientation used for the draw, with default set to 1323 that corresponds x = m13, y = m23 \param [in] nbins number of bins for the contour to be sampled over (default = 100) */ void drawDPContour(const Int_t orientation = 1323, const Int_t nbins = 100); //! Get covariant factor in 12 axis /*! \return covariant factor in 12 axis */ inline Double_t getcov12() const {return (mParentSq_ + m12Sq_ - m3Sq_)/(2.*mParent_*m12_);} //! Get covariant factor in 13 axis /*! \return covariant factor in 13 axis */ inline Double_t getcov13() const {return (mParentSq_ + m13Sq_ - m2Sq_)/(2.*mParent_*m13_);} //! Get covariant factor in 23 axis /*! \return covariant factor in 23 axis */ inline Double_t getcov23() const {return (mParentSq_ + m23Sq_ - m1Sq_)/(2.*mParent_*m23_);} protected: //! Update the variables m23Sq_ and m13Sq_ given the invariant mass m12 and the cosine of the helicity angle c12 /*! \param [in] m12 the invariant mass m12 \param [in] c12 the cosine of the helicity angle c12 */ void updateMassSq_m12(const Double_t m12, const Double_t c12); //! Update the variables m12Sq_ and m13Sq_ given the invariant mass m23 and the cosine of the helicity angle c23 /*! \param [in] m23 the invariant mass m12 \param [in] c23 the cosine of the helicity angle c23 */ void updateMassSq_m23(const Double_t m23, const Double_t c23); //! Update the variables m12Sq_ and m23Sq_ given the invariant mass m13 and the cosine of the helicity angle c13 /*! \param [in] m13 the invariant mass m13 \param [in] c13 the cosine of the helicity angle c13 */ void updateMassSq_m13(const Double_t m13, const Double_t c13); //! Update some kinematic quantities based on the DP co-ordinates m13Sq and m23Sq /*! Only the three invariant masses and their squares, plus the parent rest-frame momenta are updated. \param [in] m13Sq the invariant mass squared of daughters 1 and 3 \param [in] m23Sq the invariant mass squared of daughters 2 and 3 */ void updateMassSquares(const Double_t m13Sq, const Double_t m23Sq); //! Update some kinematic quantities based on the square DP co-ordinates m' and theta' /*! Only m', theta', the three invariant masses and their squares, plus the parent rest-frame momenta are updated. \param [in] mPrime the m' co-ordinate \param [in] thetaPrime the theta' co-ordinate */ void updateSqDPMassSquares(const Double_t mPrime, const Double_t thetaPrime); //! General method to calculate the cos(helicity) variables from the masses of the particles /*! \param [in] mijSq the mij invariant mass square \param [in] mikSq the mik invariant mass square \param [in] mij the mij invariant mass \param [in] i the index for the first track \param [in] j the index for the second track \param [in] k the index for the third track \return helicity angle in the ij rest frame */ Double_t cFromM(const Double_t mijSq, const Double_t mikSq, const Double_t mij, const Int_t i, const Int_t j, const Int_t k) const; //! General method to calculate mikSq given mijSq and cosHel_ij /*! \param [in] mijSq the mij invariant mass square \param [in] cij the helicity angle for the pair which is made from tracks i and j \param [in] mij the mij invariant mass \param [in] i the index for the first track \param [in] j the index for the second track \param [in] k the index for the third track \return the invariant mass square mikSq */ Double_t mFromC(const Double_t mijSq, const Double_t cij, const Double_t mij, const Int_t i, const Int_t j, const Int_t k) const; //! General method to calculate the momentum of a particle, given its energy and invariant mass squared. /*! \param [in] energy the energy of the particle \param [in] massSq the invariant mass squared of the particle \return the momentum of the particle */ Double_t pCalc(const Double_t energy, const Double_t massSq) const; //! Randomly generate the invariant mass squared m13Sq /*! \return the invariant mass squared m13Sq */ Double_t genm13Sq() const; //! Randomly generate the invariant mass squared m23Sq /*! \return the invariant mass squared m23Sq */ Double_t genm23Sq() const; //! Randomly generate the invariant mass squared m12Sq /*! \return the invariant mass squared m12Sq */ Double_t genm12Sq() const; //! Calculate m12Sq from m13Sq and m23Sq void calcm12Sq(); //! Calculate cosines of the helicity angles, momenta of daughters and bachelor in various ij rest frames void calcHelicities(); //! Calculate the m' and theta' variables for the square Dalitz plot void calcSqDPVars(); //! Calculate the momenta of each daughter in the parent rest frame void calcParentFrameMomenta(); private: //! Copy constructor (not implemented) LauKinematics(const LauKinematics& rhs); //! Copy assignment operator (not implemented) LauKinematics& operator=(const LauKinematics& rhs); //! Symmetrical DP const Bool_t symmetricalDP_; //! Fully-symmetrical DP const Bool_t fullySymmetricDP_; //! Mass of particle 1 const Double_t m1_; //! Mass of particle 2 const Double_t m2_; //! Mass of particle 3 const Double_t m3_; //! Mass of parent particle const Double_t mParent_; //! Mass of particle 1 squared const Double_t m1Sq_; //! Mass of particle 2 squared const Double_t m2Sq_; //! Mass of particle 3 squared const Double_t m3Sq_; //! Mass of parent particle squared const Double_t mParentSq_; //! Vector of daughter particles masses std::vector mass_; //! Vector of the minimum mij values std::vector mMin_; //! Vector of the maximum mij values std::vector mMax_; //! Vector of the difference between the mMax and mMin std::vector mDiff_; //! Vector of daughter particles masses squared std::vector mSq_; //! Vector of the minimum mijSq values std::vector mSqMin_; //! Vector of the maximum mijSq values std::vector mSqMax_; //! Vector of the difference between the mSqMax and mSqMin std::vector mSqDiff_; //! Sum of the daughter masses const Double_t mDTot_; //! Mass difference between the parent particle and the sum of the daughter particles const Double_t massInt_; //! Sum of the squares of the daughter masses const Double_t mSqDTot_; //! Invariant mass m12 Double_t m12_; //! Invariant mass m23 Double_t m23_; //! Invariant mass m13 Double_t m13_; //! Invariant mass m12 squared Double_t m12Sq_; //! Invariant mass m23 squared Double_t m23Sq_; //! Invariant mass m13 squared Double_t m13Sq_; //! Cosine of the helicity angle theta12, which is defined as the angle between 1&3 in the rest frame of 1&2 Double_t c12_; //! Cosine of the helicity angle theta23, which is defined as the angle between 1&2 in the rest frame of 2&3 Double_t c23_; //! Cosine of the helicity angle theta13, which is defined as the angle between 1&2 in the rest frame of 1&3 Double_t c13_; //! m' co-ordinate Double_t mPrime_; //! theta' co-ordinate Double_t thetaPrime_; //! Momentum q of particle i mutable Double_t qi_; //! Momentum q of particle k mutable Double_t qk_; //! Momentum of track 1 in 1-2 rest frame Double_t p1_12_; //! Momentum of track 3 in 1-2 rest frame Double_t p3_12_; //! Momentum of track 2 in 2-3 rest frame Double_t p2_23_; //! Momentum of track 1 in 2-3 rest frame Double_t p1_23_; //! Momentum of track 1 in 1-3 rest frame Double_t p1_13_; //! Momentum of track 2 in 1-3 rest frame Double_t p2_13_; //! Momentum of track 1 in parent rest frame Double_t p1_Parent_; //! Momentum of track 2 in parent rest frame Double_t p2_Parent_; //! Momentum of track 3 in parent rest frame Double_t p3_Parent_; //! Should we calculate the square DP co-ordinates or not? Bool_t squareDP_; //! Enable/disable warning messages Bool_t warnings_; - ClassDef(LauKinematics,0) }; Double_t dal(Double_t* x, Double_t* par); #endif diff --git a/inc/LauLASSBWRes.hh b/inc/LauLASSBWRes.hh index 6467ee8..e788417 100644 --- a/inc/LauLASSBWRes.hh +++ b/inc/LauLASSBWRes.hh @@ -1,171 +1,170 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file 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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauLASSBWRes(LauResonanceInfo* resInfo, const 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;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the effective range parameter value /*! \param [in] r the new effective range parameter value */ void setEffectiveRange(const Double_t r); //! Set the scattering length parameter value /*! \param [in] a the new scattering length parameter value */ void setScatteringLength(const Double_t a); //! Get the effective range parameter /*! \return the effective range parameter */ Double_t getEffectiveRange() const {return (r_!=0) ? r_->unblindValue() : 0.0;} //! Get the scattering length range parameter /*! \return the scattering length parameter */ Double_t getScatteringLength() const {return (a_!=0) ? a_->unblindValue() : 0.0;} //! See if the effective range parameter is fixed or floating /*! \return kTRUE if the effective range parameter is fixed, kFALSE otherwise */ Bool_t fixEffectiveRange() const {return (r_!=0) ? r_->fixed() : kTRUE;} //! See if the scattering length parameter is fixed or floating /*! \return kTRUE if the scattering length parameter is fixed, kFALSE otherwise */ Bool_t fixScatteringLength() const {return (a_!=0) ? a_->fixed() : kTRUE;} //! Utility function to calculate the q0 value void calcQ0(); //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauLASSBWRes(const LauLASSBWRes& rhs); //! Copy assignment operator (not implemented) LauLASSBWRes& operator=(const LauLASSBWRes& rhs); //! 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_; //! The resonance mass Double_t resMass_; //! Square of the resonance mass Double_t resMassSq_; //! LASS effective range parameter LauParameter* r_; //! LASS scattering length parameter LauParameter* a_; - ClassDef(LauLASSBWRes,0) }; #endif diff --git a/inc/LauLASSNRRes.hh b/inc/LauLASSNRRes.hh index bd1a7c7..eba97c1 100644 --- a/inc/LauLASSNRRes.hh +++ b/inc/LauLASSNRRes.hh @@ -1,168 +1,167 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file 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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauLASSNRRes(LauResonanceInfo* resInfo, const 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 cut off parameter /*! \return the cut off parameter */ Double_t getCutOff() const {return cutOff_;} //! Set the cut off parameter /*! \param [in] cutOff the cut off parameter */ void setCutOff(const Double_t cutOff) {cutOff_ = cutOff;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the effective range parameter value /*! \param [in] r the new effective range parameter value */ void setEffectiveRange(const Double_t r); //! Set the scattering length parameter value /*! \param [in] a the new scattering length parameter value */ void setScatteringLength(const Double_t a); //! Get the effective range parameter /*! \return the effective range parameter */ Double_t getEffectiveRange() const {return (r_!=0) ? r_->unblindValue() : 0.0;} //! Get the scattering length range parameter /*! \return the scattering length parameter */ Double_t getScatteringLength() const {return (a_!=0) ? a_->unblindValue() : 0.0;} //! See if the effective range parameter is fixed or floating /*! \return kTRUE if the effective range parameter is fixed, kFALSE otherwise */ Bool_t fixEffectiveRange() const {return (r_!=0) ? r_->fixed() : kTRUE;} //! See if the scattering length parameter is fixed or floating /*! \return kTRUE if the scattering length parameter is fixed, kFALSE otherwise */ Bool_t fixScatteringLength() const {return (a_!=0) ? a_->fixed() : kTRUE;} //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauLASSNRRes(const LauLASSNRRes& rhs); //! Copy assignment operator (not implemented) LauLASSNRRes& operator=(const LauLASSNRRes& rhs); //! LASS effective range parameter LauParameter* r_; //! LASS scattering length parameter LauParameter* a_; //! LASS cut off Double_t cutOff_; - ClassDef(LauLASSNRRes,0) }; #endif diff --git a/inc/LauLASSRes.hh b/inc/LauLASSRes.hh index 3214b94..b583e11 100644 --- a/inc/LauLASSRes.hh +++ b/inc/LauLASSRes.hh @@ -1,186 +1,185 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLASSRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauLASSRes(LauResonanceInfo* resInfo, const 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 cut off parameter /*! \return the cut off parameter */ Double_t getCutOff() const {return cutOff_;} //! Set the cut off parameter /*! \param [in] cutOff the cut off parameter */ void setCutOff(const Double_t cutOff) {cutOff_ = cutOff;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the effective range parameter value /*! \param [in] r the new effective range parameter value */ void setEffectiveRange(const Double_t r); //! Set the scattering length parameter value /*! \param [in] a the new scattering length parameter value */ void setScatteringLength(const Double_t a); //! Get the effective range parameter /*! \return the effective range parameter */ Double_t getEffectiveRange() const {return (r_!=0) ? r_->unblindValue() : 0.0;} //! Get the scattering length range parameter /*! \return the scattering length parameter */ Double_t getScatteringLength() const {return (a_!=0) ? a_->unblindValue() : 0.0;} //! See if the effective range parameter is fixed or floating /*! \return kTRUE if the effective range parameter is fixed, kFALSE otherwise */ Bool_t fixEffectiveRange() const {return (r_!=0) ? r_->fixed() : kTRUE;} //! See if the scattering length parameter is fixed or floating /*! \return kTRUE if the scattering length parameter is fixed, kFALSE otherwise */ Bool_t fixScatteringLength() const {return (a_!=0) ? a_->fixed() : kTRUE;} //! Utility function to calculate the q0 value void calcQ0(); //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauLASSRes(const LauLASSRes& rhs); //! Copy assignment operator (not implemented) LauLASSRes& operator=(const LauLASSRes& rhs); //! 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_; //! The resonance mass Double_t resMass_; //! Square of the resonance mass Double_t resMassSq_; //! LASS effective range parameter LauParameter* r_; //! LASS scattering length parameter LauParameter* a_; //! LASS cut off Double_t cutOff_; - ClassDef(LauLASSRes,0) }; #endif diff --git a/inc/LauLinearPdf.hh b/inc/LauLinearPdf.hh index 242bc49..d9baadf 100644 --- a/inc/LauLinearPdf.hh +++ b/inc/LauLinearPdf.hh @@ -1,94 +1,93 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLinearPdf.hh \brief File containing declaration of LauLinearPdf class. */ /*! \class LauLinearPdf \brief Class for defining a straight line PDF. Class that allows the user to define a straight line PDF. */ #ifndef LAU_LINEAR_PDF #define LAU_LINEAR_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauLinearPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameter - slope \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauLinearPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauLinearPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauLinearPdf(const LauLinearPdf& rhs); //! Copy assignment operator (not implemented) LauLinearPdf& operator=(const LauLinearPdf& rhs); //! Line slope LauAbsRValue* slope_; Bool_t posflag_; - ClassDef(LauLinearPdf,0) // Define the Linear PDF }; #endif diff --git a/inc/LauMagPhaseCPCoeffSet.hh b/inc/LauMagPhaseCPCoeffSet.hh index 9c0739f..4229b8d 100644 --- a/inc/LauMagPhaseCPCoeffSet.hh +++ b/inc/LauMagPhaseCPCoeffSet.hh @@ -1,174 +1,173 @@ /* Copyright 2011 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCPCoeffSet.hh \brief File containing declaration of LauMagPhaseCPCoeffSet class. */ /*! \class LauMagPhaseCPCoeffSet \brief Class for defining a complex coefficient using seperate magnitudes and phases for particles and antiparticles. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitudes have the form: c = mag * exp(i*phase) cBar = magBar * exp(i*phaseBar) where mag and magBar are the magnitudes for particle and antiparticle and phase and phaseBar are the phases for particle and antiparticle. */ #ifndef LAU_MAGPHASECP_COEFF_SET #define LAU_MAGPHASECP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauMagPhaseCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] mag the magnitude for particles \param [in] phase the phase for particles \param [in] magBar the magnitude for antiparticles \param [in] phaseBar the phase for antiparticles \param [in] magFixed whether mag is fixed \param [in] phaseFixed whether phase is fixed \param [in] magBarFixed whether magBar is fixed \param [in] phaseBarFixed whether phaseBar is fixed */ LauMagPhaseCPCoeffSet(const TString& compName, Double_t mag, Double_t phase, Double_t magBar, Double_t phaseBar, Bool_t magFixed, Bool_t phaseFixed, Bool_t magBarFixed, Bool_t phaseBarFixed); //! Destructor virtual ~LauMagPhaseCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet& operator=(const LauMagPhaseCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude for particles LauParameter* mag_; //! The phase for particles LauParameter* phase_; //! The magnitude for antiparticles LauParameter* magBar_; //! The phase for antiparticles LauParameter* phaseBar_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauMagPhaseCPCoeffSet, 0) }; #endif diff --git a/inc/LauMagPhaseCoeffSet.hh b/inc/LauMagPhaseCoeffSet.hh index 391b08f..c2f4ce8 100644 --- a/inc/LauMagPhaseCoeffSet.hh +++ b/inc/LauMagPhaseCoeffSet.hh @@ -1,157 +1,156 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCoeffSet.hh \brief File containing declaration of LauMagPhaseCoeffSet class. */ /*! \class LauMagPhaseCoeffSet \brief Class for defining a complex coefficient using a magnitude and a phase. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form mag*exp(i*phase). */ #ifndef LAU_MAGPHASE_COEFF_SET #define LAU_MAGPHASE_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauMagPhaseCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] magnitude the magnitude \param [in] phase the phase \param [in] magFixed whether mag is fixed \param [in] phaseFixed whether phase is fixed */ LauMagPhaseCoeffSet(const TString& compName, Double_t magnitude, Double_t phase, Bool_t magFixed, Bool_t phaseFixed); //! Destructor virtual ~LauMagPhaseCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! This class does not support CP violation so this method takes the average of the two inputs. \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry (zero by design) */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet& operator=(const LauMagPhaseCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude LauParameter* magnitude_; //! The phase LauParameter* phase_; //! The complex coefficient LauComplex coeff_; - ClassDef(LauMagPhaseCoeffSet, 0) }; #endif diff --git a/inc/LauMergeDataFiles.hh b/inc/LauMergeDataFiles.hh index 940d6e0..b68985c 100644 --- a/inc/LauMergeDataFiles.hh +++ b/inc/LauMergeDataFiles.hh @@ -1,127 +1,126 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #include #include #include "TFile.h" #include "TString.h" #include "TTree.h" /*! \file LauMergeDataFiles.hh \brief File containing declaration of LauMergeDataFiles class. */ /*! \class LauResultsExtractor \brief Utility class to allow the merging of data files on a expt-by-expt basis The files are merged such that events for expt 0 from tree 1 will be followed by events for expt 0 from tree 2, then expt 1 from tree1, expt 1 from tree 2, etc. */ class LauMergeDataFiles { public: //! Constructor /*! \param [in] fileName1 name of first file to be merged \param [in] fileName2 name of second file to be merged \param [in] treeName name of the tree to read from the input files */ LauMergeDataFiles(const TString& fileName1, const TString& fileName2, const TString& treeName); //! Destructor virtual ~LauMergeDataFiles(); //! Do the merge /*! \param [in] fileName name of file to which to write the merged tree */ void process(const TString& fileName); protected: //! Type to relate leaf names with their double-precision value typedef std::map LeafDoubleMap; //! Type to relate leaf names with their integer value typedef std::map LeafIntegerMap; //! Type to hold for each experiment the first and last entry numbers in a tree typedef std::map< Int_t,std::pair > ExptsMap; //! Open the specified input files and check that the trees can be read void openInputFiles(); //! Read the structure of the input trees, create appropriate storage and set the branch addresses void setupInputTrees(); //! Create the structure of the output tree void setupOutputTree(); //! Determine the experiments stored a given tree void findExperiments(TTree* tree, ExptsMap& exptsMap); //! Check that the experiments in each tree match Bool_t checkExperimentMaps() const; //! Read the entries for a given experiment from the given tree and store in the output tree void readExperiment(TTree* tree, const ExptsMap::const_iterator& exptsMap, Int_t offset); //! Write the output file void writeFile(); private: //! Name of file 1 TString fileName1_; //! Name of file 2 TString fileName2_; //! Name of the tree TString treeName_; //! Input file 1 TFile * inputFile1_; //! Input file 2 TFile * inputFile2_; //! Input tree 1 TTree * inputTree1_; //! Input tree 2 TTree * inputTree2_; //! Output file TFile * outputFile_; //! Output tree TTree * outputTree_; // Tree variables //! Storage for the experiment index variable Int_t iExpt_; //! Storage for the event-within-experiment index variable Int_t iEvtWithinExpt_; //! Storage for double-precision leaves LeafDoubleMap doubleVars_; //! Storage for integer leaves LeafIntegerMap integerVars_; //! Experiment -> first and last tree entry for tree 1 ExptsMap tree1Expts_; //! Experiment -> first and last tree entry for tree 2 ExptsMap tree2Expts_; - ClassDef(LauMergeDataFiles,0) }; diff --git a/inc/LauMinuit.hh b/inc/LauMinuit.hh index e24ae86..ad4e847 100644 --- a/inc/LauMinuit.hh +++ b/inc/LauMinuit.hh @@ -1,169 +1,168 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMinuit.hh \brief File containing declaration of LauMinuit class. */ /*! \class LauMinuit \brief The interface to the Minuit fitter. The singleton interface to the Minuit fitter. */ #ifndef LAU_MINUIT #define LAU_MINUIT #include "LauAbsFitter.hh" #include "LauPrint.hh" #include "Rtypes.h" #include "TMatrixD.h" #include #include class LauParameter; class TVirtualFitter; class LauMinuit : public LauAbsFitter { public: //! Destructor virtual ~LauMinuit() = default; //! Initialise the fitter, setting the information on the parameters /*! \param [in] fitObj the object that controls the likelihood calculation \param [in] parameters the list of parameters of the fit */ virtual void initialise( LauFitObject* fitObj, const std::vector& parameters ); //! Get the object that controls the calculation of the likelihood virtual LauFitObject* getFitObject(); //! Get the total number of fit parameters virtual UInt_t nParameters() const { return nParams_; } //! Get the number of floating fit parameters virtual UInt_t nFreeParameters() const { return nFreeParams_; } //! 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 virtual Bool_t useAsymmFitErrors() const {return useAsymmFitErrors_;} //! Turn on or off the computation of asymmetric errors (i.e. the MINOS routine) /*! \param [in] useAsymmErrors boolean specifying whether or not the computation of asymmetric errors is enabled */ virtual void useAsymmFitErrors(Bool_t useAsymmErrors) {useAsymmFitErrors_ = useAsymmErrors;} //! Perform the minimisation of the fit function /*! \return the status code of the fit and the minimised value */ virtual const FitStatus& minimise(); //! Fix parameters marked as "second stage" virtual void fixSecondStageParameters(); //! Release parameters marked as "second stage" virtual void releaseSecondStageParameters(); //! Update the values and errors of the parameters based on the fit minimum virtual void updateParameters(); //! Retrieve the fit covariance matrix virtual const TMatrixD& covarianceMatrix() const { return covMatrix_; } private: //! Allow the factory class to access private methods friend class LauFitter; //! Constructor LauMinuit( const UInt_t maxPar = 100, const LauOutputLevel verbosity = LauOutputLevel::Standard ); //! Copy constructor - private and not implemented LauMinuit( const LauMinuit& ) = delete; //! Move constructor - private and not implemented LauMinuit( LauMinuit&& ) = delete; //! Copy assignment operator - private and not implemented LauMinuit& operator=( const LauMinuit& ) = delete; //! Move assignment operator - private and not implemented LauMinuit& operator=( LauMinuit&& ) = delete; //! The interface to Minuit TVirtualFitter* minuit_{nullptr}; //! The maximum number of parameters const UInt_t maxPar_{100}; //! The verbosity level of the fitter const LauOutputLevel outputLevel_{LauOutputLevel::Standard}; //! The fit parameters std::vector params_; //! The total number of parameters UInt_t nParams_{0}; //! The number of free parameters UInt_t nFreeParams_{0}; //! Option to perform a two stage fit Bool_t twoStageFit_{kFALSE}; //! Option to use asymmetric errors Bool_t useAsymmFitErrors_{kFALSE}; //! The status of the fit FitStatus fitStatus_{-1,0.0,0.0}; //! The covariance matrix TMatrixD covMatrix_; - ClassDef(LauMinuit,0); }; #endif diff --git a/inc/LauModIndPartWaveMagPhase.hh b/inc/LauModIndPartWaveMagPhase.hh index 2149bd2..f1c06f9 100644 --- a/inc/LauModIndPartWaveMagPhase.hh +++ b/inc/LauModIndPartWaveMagPhase.hh @@ -1,125 +1,124 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveMagPhase.hh \brief File containing declaration of LauModIndPartWaveMagPhase class. */ /*! \class LauModIndPartWaveMagPhase \brief Class for defining a model independent partial wave component where the amplitudes are parameterised in terms of magnitude and phase This model uses splines to produce a partial wave from the magnitude and phase values of the amplitude at a series of points in the phase space. The magnitude and phase at each point can be floated in the fit. */ #ifndef LAU_MODINDPARTWAVE_MAGPHASE #define LAU_MODINDPARTWAVE_MAGPHASE #include "LauComplex.hh" #include "LauAbsModIndPartWave.hh" class TSpline3; class LauModIndPartWaveMagPhase : public LauAbsModIndPartWave { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauModIndPartWaveMagPhase(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauModIndPartWaveMagPhase(); //! Set the values of the two real parameters that define the amplitude at a given knot /*! \param [in] knot the knot to be updated \param [in] magVal the value of the magnitude at the knot \param [in] phaseVal the value of the phase at the knot \param [in] fixMagnitude whether the magnitude should be fixed \param [in] fixPhase whether the phase should be fixed */ virtual void setKnotAmp(const UInt_t knot, const Double_t magVal, const Double_t phaseVal, const Bool_t fixMagnitude, const Bool_t fixPhase); //! Method to set the type of interpolation used for the splines /*! \param [in] magType the type of interpolation for the magnitude spline \param [in] phaseType the type of interpolation for the phase spline */ void setType(Lau1DCubicSpline::LauSplineType magType, Lau1DCubicSpline::LauSplineType phaseType) { this->setSplineType(magType,phaseType); } //! Method to set the boundary conditions of the splines /*! \param [in] magLeftBound the type of boundary condition for the left edge of the magnitude spline \param [in] magRightBound the type of boundary condition for the right edge of the magnitude spline \param [in] phaseLeftBound the type of boundary condition for the left edge of the phase spline \param [in] phaseRightBound the type of boundary condition for the right edge of the phase spline \param [in] magLeftGrad the gradient at the left edge of the magnitude spline if clamped \param [in] magRightGrad the gradient at the right edge of the magnitude spline if clamped \param [in] phaseLeftGrad the gradient at the left edge of the phase spline if clamped \param [in] phaseRightGrad the gradient at the right edge of the phase spline if clamped */ void setBoundaryConditions(Lau1DCubicSpline::LauSplineBoundaryType magLeftBound, Lau1DCubicSpline::LauSplineBoundaryType magRightBound, Lau1DCubicSpline::LauSplineBoundaryType phaseLeftBound, Lau1DCubicSpline::LauSplineBoundaryType phaseRightBound, Double_t magLeftGrad = 0.0, Double_t magRightGrad = 0.0, Double_t phaseLeftGrad = 0.0, Double_t phaseRightGrad = 0.0) { this->setSplineBoundaryConditions(magLeftBound,magRightBound,phaseLeftBound,phaseRightBound,magLeftGrad,magRightGrad,phaseLeftGrad,phaseRightGrad); } //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::MIPW_MagPhase;} protected: //! Evaluate the amplitude at the given point from the splines /*! \param [in] mass appropriate invariant mass for the resonance */ virtual void evaluateAmplitude(const Double_t mass); //! Method to create the parameter objects for the given knot /*! \param [in] iKnot the index of the knot */ virtual void createAmpParameters(const UInt_t iKnot); private: - ClassDef(LauModIndPartWaveMagPhase,0) // model independent partial wave }; #endif diff --git a/inc/LauModIndPartWaveRealImag.hh b/inc/LauModIndPartWaveRealImag.hh index e8da06d..5495b3a 100644 --- a/inc/LauModIndPartWaveRealImag.hh +++ b/inc/LauModIndPartWaveRealImag.hh @@ -1,125 +1,124 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveRealImag.hh \brief File containing declaration of LauModIndPartWaveRealImag class. */ /*! \class LauModIndPartWaveRealImag \brief Class for defining a model independent partial wave component where the amplitudes are parameterised in terms of real and imaginary parts This model uses splines to produce a partial wave from the values of the real and imaginary parts of the amplitude at a series of points in the phase space. The values at each point can be floated in the fit. */ #ifndef LAU_MODINDPARTWAVE_REALIMAG #define LAU_MODINDPARTWAVE_REALIMAG #include "LauComplex.hh" #include "LauAbsModIndPartWave.hh" class TSpline3; class LauModIndPartWaveRealImag : public LauAbsModIndPartWave { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauModIndPartWaveRealImag(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauModIndPartWaveRealImag(); //! Set the values of the two real parameters that define the amplitude at a given knot /*! \param [in] knot the knot to be updated \param [in] realVal the value of the real part at the knot \param [in] imagVal the value of the imaginary part at the knot \param [in] fixRealPart whether the real part should be fixed \param [in] fixImagPart whether the imaginary part should be fixed */ virtual void setKnotAmp(const UInt_t knot, const Double_t realVal, const Double_t imagVal, const Bool_t fixRealPart, const Bool_t fixImagPart); //! Method to set the type of interpolation used for the splines /*! \param [in] realType the type of interpolation for the real part spline \param [in] imagType the type of interpolation for the imaginary part spline */ void setType(Lau1DCubicSpline::LauSplineType realType, Lau1DCubicSpline::LauSplineType imagType) { this->setSplineType(realType,imagType); } //! Method to set the boundary conditions of the splines /*! \param [in] realLeftBound the type of boundary condition for the left edge of the real part spline \param [in] realRightBound the type of boundary condition for the right edge of the real part spline \param [in] imagLeftBound the type of boundary condition for the left edge of the imaginary part spline \param [in] imagRightBound the type of boundary condition for the right edge of the imaginary part spline \param [in] realLeftGrad the gradient at the left edge of the real part spline if clamped \param [in] realRightGrad the gradient at the right edge of the real part spline if clamped \param [in] imagLeftGrad the gradient at the left edge of the imaginary part spline if clamped \param [in] imagRightGrad the gradient at the right edge of the imaginary part spline if clamped */ void setBoundaryConditions(Lau1DCubicSpline::LauSplineBoundaryType realLeftBound, Lau1DCubicSpline::LauSplineBoundaryType realRightBound, Lau1DCubicSpline::LauSplineBoundaryType imagLeftBound, Lau1DCubicSpline::LauSplineBoundaryType imagRightBound, Double_t realLeftGrad = 0.0, Double_t realRightGrad = 0.0, Double_t imagLeftGrad = 0.0, Double_t imagRightGrad = 0.0) { this->setSplineBoundaryConditions(realLeftBound,realRightBound,imagLeftBound,imagRightBound,realLeftGrad,realRightGrad,imagLeftGrad,imagRightGrad); } //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::MIPW_RealImag;} protected: //! Evaluate the amplitude at the given point from the splines /*! \param [in] mass appropriate invariant mass for the resonance */ virtual void evaluateAmplitude(const Double_t mass); //! Method to create the parameter objects for the given knot /*! \param [in] iKnot the index of the knot */ virtual void createAmpParameters(const UInt_t iKnot); private: - ClassDef(LauModIndPartWaveRealImag,0) // model independent partial wave }; #endif diff --git a/inc/LauNRAmplitude.hh b/inc/LauNRAmplitude.hh index 27a59df..03334cf 100644 --- a/inc/LauNRAmplitude.hh +++ b/inc/LauNRAmplitude.hh @@ -1,227 +1,226 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNRAmplitude.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauNRAmplitude(LauResonanceInfo* resInfo, const 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;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); 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) )) */ Double_t f(const Double_t s, const Double_t c, const Double_t p) const; //! Set the d parameter value /*! \param [in] d the new d parameter value */ void setdParameter(const Double_t d); //! Set the c1 parameter value /*! \param [in] c1 the new c1 parameter value */ void setc1Parameter(const Double_t c1); //! Set the c2 parameter value /*! \param [in] c2 the new c2 parameter value */ void setc2Parameter(const Double_t c2); //! Set the p1 parameter value /*! \param [in] p1 the new p1 parameter value */ void setp1Parameter(const Double_t p1); //! Set the p2 parameter value /*! \param [in] p2 the new p2 parameter value */ void setp2Parameter(const Double_t p2); //! Get the d parameter value /*! \return the new d parameter value */ Double_t getdParameter() const {return (d_!=0) ? d_->unblindValue() : 0.0;} //! Get the c1 parameter value /*! \return the new c1 parameter value */ Double_t getc1Parameter() const {return (c1_!=0) ? c1_->unblindValue() : 0.0;} //! Get the c2 parameter value /*! \return the new c2 parameter value */ Double_t getc2Parameter() const {return (c2_!=0) ? c2_->unblindValue() : 0.0;} //! Get the p1 parameter value /*! \return the new p1 parameter value */ Double_t getp1Parameter() const {return (p1_!=0) ? p1_->unblindValue() : 0.0;} //! Get the p2 parameter value /*! \return the new p2 parameter value */ Double_t getp2Parameter() const {return (p2_!=0) ? p2_->unblindValue() : 0.0;} //! See if the d parameter is fixed or floating /*! \return kTRUE if the d parameter is fixed, kFALSE otherwise */ Bool_t fixdParameter() const {return (d_!=0) ? d_->fixed() : kTRUE;} //! See if the c1 parameter is fixed or floating /*! \return kTRUE if the c1 parameter is fixed, kFALSE otherwise */ Bool_t fixc1Parameter() const {return (c1_!=0) ? c1_->fixed() : kTRUE;} //! See if the c2 parameter is fixed or floating /*! \return kTRUE if the c2 parameter is fixed, kFALSE otherwise */ Bool_t fixc2Parameter() const {return (c2_!=0) ? c2_->fixed() : kTRUE;} //! See if the p1 parameter is fixed or floating /*! \return kTRUE if the p1 parameter is fixed, kFALSE otherwise */ Bool_t fixp1Parameter() const {return (p1_!=0) ? p1_->fixed() : kTRUE;} //! See if the p2 parameter is fixed or floating /*! \return kTRUE if the p2 parameter is fixed, kFALSE otherwise */ Bool_t fixp2Parameter() const {return (p2_!=0) ? p2_->fixed() : kTRUE;} private: //! Copy constructor (not implemented) LauNRAmplitude(const LauNRAmplitude& rhs); //! Copy assignment operator (not implemented) LauNRAmplitude& operator=(const LauNRAmplitude& rhs); //! Parameter from arXiv:0709.0075v1 [hep-ph] LauParameter* d_; //! Parameter from arXiv:0709.0075v1 [hep-ph] LauParameter* c1_; //! Parameter from arXiv:0709.0075v1 [hep-ph] LauParameter* c2_; //! Parameter from arXiv:0709.0075v1 [hep-ph] LauParameter* p1_; //! Parameter from arXiv:0709.0075v1 [hep-ph] LauParameter* p2_; - ClassDef(LauNRAmplitude,0) // Non-resonant amplitude model }; #endif diff --git a/inc/LauNovosibirskPdf.hh b/inc/LauNovosibirskPdf.hh index 0e88b81..9801e7f 100644 --- a/inc/LauNovosibirskPdf.hh +++ b/inc/LauNovosibirskPdf.hh @@ -1,95 +1,94 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNovosibirskPdf.hh \brief File containing declaration of LauNovosibirskPdf class. */ /*! \class LauNovosibirskPdf \brief Class for defining a Novosibirsk function PDF. Class that allows the user to define a Novosibirsk function PDF. */ #ifndef LAU_NOVOSIBIRSK_PDF #define LAU_NOVOSIBIRSK_PDF #include "TString.h" #include "TRandom.h" #include "LauAbsPdf.hh" #include "LauParameter.hh" #include using std::vector; class LauNovosibirskPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - mean, sigma and tail \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauNovosibirskPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauNovosibirskPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauNovosibirskPdf(const LauNovosibirskPdf& rhs); //! Copy assignment operator (not implemented) LauNovosibirskPdf& operator=(const LauNovosibirskPdf& rhs); //! Gaussian mean LauAbsRValue* mean_; //! Gaussian sigma LauAbsRValue* sigma_; //! Gaussian tail LauAbsRValue* tail_; - ClassDef(LauNovosibirskPdf,0) // Define the Novosibirsk PDF }; #endif diff --git a/inc/LauParametricStepFuncPdf.hh b/inc/LauParametricStepFuncPdf.hh index 2243240..8c25991 100644 --- a/inc/LauParametricStepFuncPdf.hh +++ b/inc/LauParametricStepFuncPdf.hh @@ -1,131 +1,130 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParametricStepFuncPdf.hh \brief File containing declaration of LauParametricStepFuncPdf class. */ /*! \class LauParametricStepFuncPdf \brief Class for defining a Parametric Step Function PDF. Class that allows the user to define a Parametric Step Function PDF. Code mostly copied from RooFit/RooParametricStepFunction. */ /***************************************************************************** * Class based on RooFit/RooParametricStepFunction. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #ifndef LAU_PAR_STEP_FUNC_PDF #define LAU_PAR_STEP_FUNC_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauParametricStepFuncPdf : public LauAbsPdf { public: //! Define the allowed options for the normalisation bin enum NormBin { First, /*!< The height of the first bin is determined from the rest to satisfy the normalisation */ Last /*!< The height of the last bin is determined from the rest to satisfy the normalisation */ }; //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the bin contents of all the but the normalisation bin, so (N_bins - 1 entries) \param [in] limits the limits of the bins (lower limit of all bins and upper limit of the last), so (N_bins + 1) entries \param [in] normalisationBin the normalisation bin */ LauParametricStepFuncPdf(const TString& theVarName, const std::vector& params, const std::vector& limits, NormBin normalisationBin = Last); //! Destructor virtual ~LauParametricStepFuncPdf(); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: //! Number of bins /*! \return the number of bins */ UInt_t nBins() const {return limits_.size()-1;} //! Normalisation bin /*! \return the normalisation bin */ NormBin normBin() const {return normBin_;} private: //! Copy constructor (not implemented) LauParametricStepFuncPdf(const LauParametricStepFuncPdf& rhs); //! Copy assignment operator (not implemented) LauParametricStepFuncPdf& operator=(const LauParametricStepFuncPdf& rhs); //! normalisation bin NormBin normBin_; //! limits of the bins std::vector limits_; - ClassDef(LauParametricStepFuncPdf,0) // Define the PSF PDF }; #endif diff --git a/inc/LauParticlePDG.hh b/inc/LauParticlePDG.hh index b1c47e5..28a7e1c 100644 --- a/inc/LauParticlePDG.hh +++ b/inc/LauParticlePDG.hh @@ -1,189 +1,188 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParticlePDG.hh \brief File containing declaration of LauParticlePDG class. */ /*! \class LauParticlePDG \brief Class for storing particle properties Class that provides the properties of particles, including mapping particles and their anti-particles. */ #ifndef LAU_PARTICLE_PDG #define LAU_PARTICLE_PDG #include "TMath.h" #include "TString.h" class TParticlePDG; class LauParticlePDG { public: //! Destructor virtual ~LauParticlePDG(); //! Method to access the record for the charge conjugate of this particle /*! \return pointer to the anti-particle */ const LauParticlePDG* antiParticle() const { return antiParticle_; } //! The particle PDG code /*! \return the PDG code of the particle */ Int_t code() const; //! The anti-particle PDG code /*! \return the PDG code of the charge conjugate of the particle */ Int_t conjugateCode() const; //! The PDG code for the particle/antiparticle /*! \return the modulus of the PDG code of the particle */ Int_t type() const { return TMath::Abs( this->code() ); } //! The charge of the particle /*! \return the charge of the particle */ Int_t charge() const; //! The mass of the particle /*! \return the mass of the particle */ Double_t mass() const { return mass_; } //! The mass square of the particle /*! \return the mass square of the particle */ Double_t massSq() const { return mass_*mass_; } //! Check whether the particle is a kaon (K+, K-, K0, K0bar, KS or KL) /*! \return true if the particle is a kaon, false otherwise */ Bool_t isKaon() const { return kaon_; } //! Check whether the particle is a pion (pi+, pi- or pi0) /*! \return true if the particle is a pion, false otherwise */ Bool_t isPion() const { return pion_; } //! Check whether the particle is a KS /*! \return true if the particle is a KS, false otherwise */ Bool_t isKs() const { return ks_; } //! Check whether the particle is a pi0 /*! \return true if the particle is a pi0, false otherwise */ Bool_t isPi0() const { return pi0_; } //! Check whether the particle is a D /*! \return true if the particle is a D, false otherwise */ Bool_t isD() const { return D_; } //! Check whether the particle is a B /*! \return true if the particle is a B, false otherwise */ Bool_t isB() const { return B_; } //! Particle name /*! \return the name of the particle */ TString string() const; //! Particle name, containing only alphanumeric characters /*! \return the name of the particle, removing all non-alphanumeric characters */ TString stringAlphaNum() const; protected: private: //! LauDataBasePDG is a friend class friend class LauDatabasePDG; //! Constructor /*! \param [in] particle the particle */ explicit LauParticlePDG(const TParticlePDG* particle); //! Copy constructor (not implemented) LauParticlePDG(const LauParticlePDG& rhs); //! Copy assignment operator (not implemented) LauParticlePDG& operator=(const LauParticlePDG& rhs); //! Set the antiparticle /*! \param [in] antiPart the antiparticle */ void setAntiParticle( const LauParticlePDG* antiPart ) { antiParticle_ = antiPart; } //! The particle const TParticlePDG* theParticle_; //!The antiparticle const LauParticlePDG* antiParticle_; //! The mass of the particle Double_t mass_; //! Flag whether the particle is a kaon Bool_t kaon_; //! Flag whether the particle is a pion Bool_t pion_; //! Flag whether the particle is a KS Bool_t ks_; //! Flag whether the particle is a pi0 Bool_t pi0_; //! Flag whether the particle is a D Bool_t D_; //! Flag whether the particle is a B Bool_t B_; - ClassDef(LauParticlePDG,0) }; #endif diff --git a/inc/LauPolNR.hh b/inc/LauPolNR.hh index 714104d..96d9b4e 100644 --- a/inc/LauPolNR.hh +++ b/inc/LauPolNR.hh @@ -1,106 +1,105 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolNR.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauPolNR(LauResonanceInfo* resInfo, const 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(const 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 spin term */ virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); private: //! Copy constructor (not implemented) LauPolNR(const LauPolNR& rhs); //! Copy assignment operator (not implemented) LauPolNR& operator=(const LauPolNR& rhs); //! 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/LauPolarFormFactorNR.hh b/inc/LauPolarFormFactorNR.hh index a4d248f..8ff25c9 100644 --- a/inc/LauPolarFormFactorNR.hh +++ b/inc/LauPolarFormFactorNR.hh @@ -1,141 +1,140 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorNR.hh \brief File containing declaration of LauPolarFormFactorNR class. */ /*! \class LauPolarFormFactorNR \brief Class for defining a nonresonant form factor model Defines the nonresonant form factor model from: Nogueira, Bediaga, Cavalcante, Frederico, Lorenco: Phys. Rev. D92 (2015) 054010, arXiv:1506.08332 [hep-ph] Pelaez, Yndurain: Phys. Rev. D71 (2005) 074016, arXiv:hep-ph/0411334 */ #ifndef LAU_POLAR_FORM_FACTOR_NR #define LAU_POLAR_FORM_FACTOR_NR #include "TString.h" #include "LauComplex.hh" #include "LauAbsResonance.hh" class LauKinematics; class LauParameter; class LauPolarFormFactorNR : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauPolarFormFactorNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauPolarFormFactorNR(); //! Initialise the model virtual void initialise(); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return model_;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the parameter lambda, the NR shape parameter /*! \param [in] lambda the NR shape parameter */ void setLambda(const Double_t lambda); //! Get the parameter lambda, the NR shape parameter /*! \return lambda, the NR shape parameter */ Double_t getLambda() const {return (lambda_!=0) ? lambda_->value() : 0.0;} //! See if the lambda parameter is fixed or floating /*! \return kTRUE if the lambda parameter is fixed, kFALSE otherwise */ Bool_t fixLambda() const {return (lambda_!=0) ? lambda_->fixed() : kTRUE;} //! 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: //! Copy constructor (not implemented) LauPolarFormFactorNR(const LauPolarFormFactorNR& rhs); //! Copy assignment operator (not implemented) LauPolarFormFactorNR& operator=(const LauPolarFormFactorNR& rhs); LauParameter* lambda_; //! The model to use LauAbsResonance::LauResonanceModel model_; - ClassDef(LauPolarFormFactorNR,0) }; #endif diff --git a/inc/LauPolarFormFactorSymNR.hh b/inc/LauPolarFormFactorSymNR.hh index f79de32..65bd7f0 100644 --- a/inc/LauPolarFormFactorSymNR.hh +++ b/inc/LauPolarFormFactorSymNR.hh @@ -1,149 +1,148 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorSymNR.hh \brief File containing declaration of LauPolarFormFactorSymNR class. */ /*! \class LauPolarFormFactorSymNR \brief Class for defining a nonresonant form factor model Defines the nonresonant form factor model from: Nogueira, Bediaga, Cavalcante, Frederico, Lorenco: Phys. Rev. D92 (2015) 054010, arXiv:1506.08332 [hep-ph] Pelaez, Yndurain: Phys. Rev. D71 (2005) 074016, arXiv:hep-ph/0411334 modified for symmetric DPs. */ #ifndef LAU_POLAR_FORM_FACTOR_SYM_NR #define LAU_POLAR_FORM_FACTOR_SYM_NR #include "TString.h" #include "LauComplex.hh" #include "LauAbsResonance.hh" class LauKinematics; class LauParameter; class LauPolarFormFactorSymNR : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauPolarFormFactorSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauPolarFormFactorSymNR(); //! Initialise the model virtual void initialise(); //! 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 model_;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the parameter lambda, the NR shape parameter /*! \param [in] lambda the NR shape parameter */ void setLambda(const Double_t lambda); //! Get the parameter lambda, the NR shape parameter /*! \return lambda the NR shape parameter */ Double_t getLambda() const {return (lambda_!=0) ? lambda_->value() : 0.0;} //! See if the lambda parameter is fixed or floating /*! \return kTRUE if the lambda parameter is fixed, kFALSE otherwise */ Bool_t fixLambda() const {return (lambda_!=0) ? lambda_->fixed() : kTRUE;} //! 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: //! Copy constructor (not implemented) LauPolarFormFactorSymNR(const LauPolarFormFactorSymNR& rhs); //! Copy assignment operator (not implemented) LauPolarFormFactorSymNR& operator=(const LauPolarFormFactorSymNR& rhs); LauParameter* lambda_; //! The model to use LauAbsResonance::LauResonanceModel model_; - ClassDef(LauPolarFormFactorSymNR,0) }; #endif diff --git a/inc/LauPolarGammaCPCoeffSet.hh b/inc/LauPolarGammaCPCoeffSet.hh index 77263fd..048989b 100644 --- a/inc/LauPolarGammaCPCoeffSet.hh +++ b/inc/LauPolarGammaCPCoeffSet.hh @@ -1,260 +1,259 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarGammaCPCoeffSet.hh \brief File containing declaration of LauPolarGammaCPCoeffSet class. */ /*! \class LauPolarGammaCPCoeffSet \brief Class for defining a complex coefficient useful for extracting the CKM angle gamma from B -> D h h Dalitz plots. Holds a set of real values that define the complex coefficient of an amplitude component. Depending on the type of the D decay, the amplitude has one of the following forms: CP-odd eigenstate: ( x + i * y ) * ( 1 - rB * exp( i * ( deltaB +/- gamma ) ) ) CP-even eigenstate: ( x + i * y ) * ( 1 + rB * exp( i * ( deltaB +/- gamma ) ) ) ADS favoured state: ( x + i * y ) * ( 1 + rB * rD * exp( i * ( deltaB - deltaD +/- gamma ) ) ) ADS suppressed state: ( x + i * y ) * ( rD * exp( - i * deltaD ) + rB * exp( i * ( deltaB +/- gamma ) ) ) [Phys. Rev. D79, 051301 (2009)] */ #ifndef LAU_POLARGAMMACP_COEFF_SET #define LAU_POLARGAMMACP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauPolarGammaCPCoeffSet : public LauAbsCoeffSet { public: //! The possible D decay modes enum DecayType { GLW_CPOdd, /*!< GLW CP-odd, e.g. D0 -> K0 pi0 */ GLW_CPEven, /*!< GLW CP-even, e.g. D0 -> K+ K- */ ADS_Favoured, /*!< ADS Favoured, e.g. D0 -> K- pi+ */ ADS_Suppressed, /*!< ADS Suppressed, e.g. D0 -> K+ pi- */ GLW_CPOdd_btouOnly, /*!< GLW CP-odd, e.g. D0 -> K0 pi0, where B decay only proceeds via b -> u transition */ GLW_CPEven_btouOnly, /*!< GLW CP-even, e.g. D0 -> K+ K-, where B decay only proceeds via b -> u transition */ ADS_Favoured_btouOnly, /*!< ADS Favoured, e.g. D0 -> K- pi+, where B decay only proceeds via b -> u transition */ ADS_Suppressed_btouOnly, /*!< ADS Suppressed, e.g. D0 -> K+ pi-, where B decay only proceeds via b -> u transition */ }; //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] decayType the type of the D decay \param [in] x the real part of the b -> c amplitude \param [in] y the imaginary part of the b -> c amplitude \param [in] rB the magnitude of the ratio of the b -> u and b -> c amplitudes \param [in] deltaB the relative CP-conserving (strong) phase of the b -> u and b -> c amplitudes \param [in] gamma the relative CP-violating (weak) phase of the b -> u and b -> c amplitudes \param [in] rD the magnitude of the ratio of the favoured and suppressed D-decay amplitudes \param [in] deltaD the relative strong phase of the favoured and suppressed D-decay amplitudes \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed \param [in] rBFixed whether rB is fixed \param [in] deltaBFixed whether deltaB is fixed \param [in] gammaFixed whether gamma is fixed \param [in] rDFixed whether rD is fixed \param [in] deltaDFixed whether deltaD is fixed \param [in] rBSecondStage whether rB should be floated only in the second stage of the fit \param [in] deltaBSecondStage whether deltaB should be floated only in the second stage of the fit \param [in] gammaSecondStage whether gamma should be floated only in the second stage of the fit \param [in] rDSecondStage whether rD should be floated only in the second stage of the fit \param [in] deltaDSecondStage whether deltaD should be floated only in the second stage of the fit \param [in] useGlobalGamma whether gamma should be shared with other resonances \param [in] useGlobalADSPars whether rD and deltaD should be shared with other resonances */ LauPolarGammaCPCoeffSet(const TString& compName, const DecayType decayType, const Double_t x, const Double_t y, const Double_t rB, const Double_t deltaB, const Double_t gamma, const Double_t rD, const Double_t deltaD, const Bool_t xFixed, const Bool_t yFixed, const Bool_t rBFixed, const Bool_t deltaBFixed, const Bool_t gammaFixed, const Bool_t rDFixed, const Bool_t deltaDFixed, const Bool_t rBSecondStage = kFALSE, const Bool_t deltaBSecondStage = kFALSE, const Bool_t gammaSecondStage = kFALSE, const Bool_t rDSecondStage = kFALSE, const Bool_t deltaDSecondStage = kFALSE, const Bool_t useGlobalGamma = kFALSE, const Bool_t useGlobalADSPars = kFALSE); //! Destructor virtual ~LauPolarGammaCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! This method is not supported by this class because there are more than four parameters, hence there is not a unique solution. \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauPolarGammaCPCoeffSet(const LauPolarGammaCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauPolarGammaCPCoeffSet& operator=(const LauPolarGammaCPCoeffSet& rhs); //! Prepend the base name and index to the name of a parameter /*! \param [in,out] par pointer to the parameter \param [in] oldBaseName the old base name, which might need to be removed before adding the new one */ virtual void adjustName(LauParameter* par, const TString& oldBaseName); //! Update the amplitudes based on the new values of the parameters void updateAmplitudes(); //! The type of the D decay const DecayType decayType_; // the actual fit parameters // (need to be pointers so they can be cloned) //! The real part of the b -> c amplitude LauParameter* x_; //! The imaginary part of the b -> c amplitude LauParameter* y_; //! the magnitude of the ratio of the b -> u and b -> c amplitudes LauParameter* rB_; //! the relative CP-conserving (strong) phase of the b -> u and b -> c amplitudes LauParameter* deltaB_; //! the relative CP-violating (weak) phase of the b -> u and b -> c amplitudes LauParameter* gamma_; //! the magnitude of the ratio of the favoured and suppressed D-decay amplitudes LauParameter* rD_; //! the relative strong phase of the favoured and suppressed D-decay amplitudes LauParameter* deltaD_; //! The CP-violating phase (shared by multiple resonances) static LauParameter* gammaGlobal_; //! the magnitude of the ratio of the favoured and suppressed D-decay amplitudes (shared by multiple resonances) static LauParameter* rDGlobal_; //! the relative strong phase of the favoured and suppressed D-decay amplitudes (shared by multiple resonances) static LauParameter* deltaDGlobal_; //! Whether the global gamma is used for this resonance const Bool_t useGlobalGamma_; //! Whether the global rD and deltaD are used for this resonance const Bool_t useGlobalADSPars_; //! The b -> c part of the complex coefficient LauComplex nonCPPart_; //! The b -> u part of the complex coefficient for the particle LauComplex cpPart_; //! The b -> u part of the complex coefficient for the antiparticle LauComplex cpAntiPart_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauPolarGammaCPCoeffSet, 0) }; #endif diff --git a/inc/LauPoleRes.hh b/inc/LauPoleRes.hh index f7e1ba4..998bfa9 100644 --- a/inc/LauPoleRes.hh +++ b/inc/LauPoleRes.hh @@ -1,94 +1,93 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPoleRes.hh \brief File containing declaration of LauPoleRes class. */ /*! \class LauPoleRes \brief Class for defining a pole-type resonance model Class for defining a pole-type resonance model. This is a pole type resonance 1/((m_s)^2-m^2); m_s=m0-iw0, good to represent the sigma (f0(500)). J. A. Oller, Final state interactions in hadronic D decays, Phys. Rev. D71 (2005) 054030, arXiv:hep-ph/0411105. */ #ifndef LAU_POLE_RES #define LAU_POLE_RES #include "TString.h" #include "LauComplex.hh" #include "LauAbsResonance.hh" class LauPoleRes : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauPoleRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauPoleRes(); //! Initialise the model virtual void initialise(); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Pole;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); 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: //! Copy constructor (not implemented) LauPoleRes(const LauPoleRes& rhs); //! Copy assignment operator (not implemented) LauPoleRes& operator=(const LauPoleRes& rhs); - ClassDef(LauPoleRes,0) // Pole resonance model }; #endif diff --git a/inc/LauPrint.hh b/inc/LauPrint.hh index f7eea37..d7747a5 100644 --- a/inc/LauPrint.hh +++ b/inc/LauPrint.hh @@ -1,82 +1,81 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPrint.hh \brief File containing declaration of LauPrint class and LauOutputLevel enum. */ #ifndef LAU_PRINT #define LAU_PRINT #include "Rtypes.h" #include /*! \enum LauOutputLevel \brief Enumeration to define verbosity level for various printouts */ enum class LauOutputLevel { None = -1, //!< Zero printout Quiet = 0, //!< Reduced printout Standard = 1, //!< Normal level of printout Verbose = 2, //!< Verbose printout ExtraVerbose = 3 //!< Highly verbose printout }; /*! \class LauPrint \brief Class to define various output print commands. Class to define various output print commands (for output tables etc..) */ class LauPrint { public: //! Constructor LauPrint(); //! Destructor virtual ~LauPrint(); //! Method to choose the printing format to a specified level of precision /*! \param [in,out] stream the output stream to be printed to \param [in] value the double value to be printed */ void printFormat(std::ostream& stream, Double_t value) const; private: //! Copy constructor (not implemented) LauPrint(const LauPrint& rhs); //! Copy assignment operator (not implemented) LauPrint& operator=(const LauPrint& rhs); - ClassDef(LauPrint,0) }; #endif diff --git a/inc/LauRealImagCPCoeffSet.hh b/inc/LauRealImagCPCoeffSet.hh index b339b14..8f88e97 100644 --- a/inc/LauRealImagCPCoeffSet.hh +++ b/inc/LauRealImagCPCoeffSet.hh @@ -1,172 +1,171 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagCPCoeffSet.hh \brief File containing declaration of LauRealImagCPCoeffSet class. */ /*! \class LauRealImagCPCoeffSet \brief Class for defining a complex coefficient using a simple Cartesian CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitudes have the form: c = x + i * y cbar = xbar + i * ybar */ #ifndef LAU_REALIMAGCP_COEFF_SET #define LAU_REALIMAGCP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauRealImagCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] x the real part for the particle \param [in] y the imaginary part for the particle \param [in] xbar the real part for the antiparticle \param [in] ybar the imaginary part for the antiparticle \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed \param [in] xbarFixed whether xbar is fixed \param [in] ybarFixed whether ybar is fixed */ LauRealImagCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t xbar, Double_t ybar, Bool_t xFixed, Bool_t yFixed, Bool_t xbarFixed, Bool_t ybarFixed); //! Destructor virtual ~LauRealImagCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauRealImagCPCoeffSet(const LauRealImagCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet& operator=(const LauRealImagCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The real part for the particle LauParameter* x_; //! The imaginary part for the particle LauParameter* y_; //! The real part for the antiparticle LauParameter* xbar_; //! The imaginary part for the antiparticle LauParameter* ybar_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauRealImagCPCoeffSet, 0) }; #endif diff --git a/inc/LauRealImagCoeffSet.hh b/inc/LauRealImagCoeffSet.hh index e35a507..a5d5284 100644 --- a/inc/LauRealImagCoeffSet.hh +++ b/inc/LauRealImagCoeffSet.hh @@ -1,157 +1,156 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagCoeffSet.hh \brief File containing declaration of LauRealImagCoeffSet class. */ /*! \class LauRealImagCoeffSet \brief Class for defining a complex coefficient using real and imaginary parts. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitude has the form x + i*y. */ #ifndef LAU_REALIMAG_COEFF_SET #define LAU_REALIMAG_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauRealImagCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] x the real part \param [in] y the imaginary part \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed */ LauRealImagCoeffSet(const TString& compName, Double_t x, Double_t y, Bool_t xFixed, Bool_t yFixed); //! Destructor virtual ~LauRealImagCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! This class does not support CP violation so this method takes the average of the two inputs. \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry (zero by design) */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet& operator=(const LauRealImagCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The real part LauParameter* x_; //! The imaginary part LauParameter* y_; //! The complex coefficient LauComplex coeff_; - ClassDef(LauRealImagCoeffSet, 0) }; #endif diff --git a/inc/LauRealImagGammaCPCoeffSet.hh b/inc/LauRealImagGammaCPCoeffSet.hh index d0908a7..42ff3f8 100644 --- a/inc/LauRealImagGammaCPCoeffSet.hh +++ b/inc/LauRealImagGammaCPCoeffSet.hh @@ -1,189 +1,188 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagGammaCPCoeffSet.hh \brief File containing declaration of LauRealImagGammaCPCoeffSet class. */ /*! \class LauRealImagGammaCPCoeffSet \brief Class for defining a complex coefficient using a Cartesian nonCP part multiplied by a simple Cartesian CP convention. Holds a set of real values that define the complex coefficient of an amplitude component. The amplitudes have the form: c = ( x + i * y ) * ( 1 + xCP + i * yCP ) cbar = ( x + i * y ) * ( 1 + xbarCP + i * ybarCP ) [Phys. Rev. D79, 051301 (2009)] */ #ifndef LAU_REALIMAGGAMMACP_COEFF_SET #define LAU_REALIMAGGAMMACP_COEFF_SET #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauRealImagGammaCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] x the real nonCP part \param [in] y the imaginary nonCP part \param [in] xCP the real CP part for the particle \param [in] yCP the imaginary CP part for the particle \param [in] xbarCP the real CP part for the antiparticle \param [in] ybarCP the imaginary CP part for the antiparticle \param [in] xFixed whether x is fixed \param [in] yFixed whether y is fixed \param [in] xCPFixed whether x is fixed \param [in] yCPFixed whether y is fixed \param [in] xbarCPFixed whether xbar is fixed \param [in] ybarCPFixed whether ybar is fixed */ LauRealImagGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t xbarCP, const Double_t ybarCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t xbarCPFixed, const Bool_t ybarCPFixed); //! Destructor virtual ~LauRealImagGammaCPCoeffSet(){} //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient */ virtual std::vector getParameters(); //! Print the current values of the parameters virtual void printParValues() const; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ virtual void printTableHeading(std::ostream& stream) const; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ virtual void printTableRow(std::ostream& stream) const; //! Randomise the starting values of the parameters for a fit virtual void randomiseInitValues(); //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi virtual void finaliseValues(); //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ virtual const LauComplex& particleCoeff(); //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ virtual const LauComplex& antiparticleCoeff(); //! Set the parameters based on the complex coefficients for particles and antiparticles /*! This method is not supported by this class because there are more than four parameters so there is not a unique solution. \param [in] coeff the complex coefficient for a particle \param [in] coeffBar the complex coefficient for an antiparticle \param [in] init whether or not the initial and generated values should also be adjusted */ virtual void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ); //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp(); //! Create a clone of the coefficient set /*! \param [in] newName the clone's name \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone(const TString& newName, CloneOption cloneOption = All, Double_t constFactor = 1.0); private: //! Copy constructor /*! This creates cloned parameters, not copies. \param [in] rhs the coefficient to clone \param [in] cloneOption special option for the cloning operation \param [in] constFactor a constant factor to multiply the clone's parameters by */ LauRealImagGammaCPCoeffSet(const LauRealImagGammaCPCoeffSet& rhs, CloneOption cloneOption = All, Double_t constFactor = 1.0); //! Copy assignment operator (not implemented) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet& operator=(const LauRealImagGammaCPCoeffSet& rhs); // the actual fit parameters // (need to be pointers so they can be cloned) //! The real nonCP part LauParameter* x_; //! The imaginary nonCP part LauParameter* y_; //! The real CP part for the particle LauParameter* xCP_; //! The imaginary CP part for the particle LauParameter* yCP_; //! The real CP part for the antiparticle LauParameter* xbarCP_; //! The imaginary CP part for the antiparticle LauParameter* ybarCP_; //! The nonCP part of the complex coefficient LauComplex nonCPPart_; //! The CP part of the complex coefficient for the particle LauComplex cpPart_; //! The CP part of the complex coefficient for the antiparticle LauComplex cpAntiPart_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; - ClassDef(LauRealImagGammaCPCoeffSet, 0) }; #endif diff --git a/inc/LauRelBreitWignerRes.hh b/inc/LauRelBreitWignerRes.hh index 1923a6d..2e2de43 100644 --- a/inc/LauRelBreitWignerRes.hh +++ b/inc/LauRelBreitWignerRes.hh @@ -1,128 +1,127 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRelBreitWignerRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauRelBreitWignerRes(LauResonanceInfo* resInfo, const 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;} //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Complex resonant amplitude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm 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: //! Copy constructor (not implemented) LauRelBreitWignerRes(const LauRelBreitWignerRes& rhs); //! Copy assignment operator (not implemented) LauRelBreitWignerRes& operator=(const LauRelBreitWignerRes& rhs); //! Momentum of the daughters in the resonance rest frame (at pole mass) Double_t q0_; //! The resonance mass Double_t resMass_; //! Square of the resonance mass Double_t resMassSq_; //! The resonance width Double_t resWidth_; //! The resonance barrier radius Double_t resRadius_; //! The parent barrier radius Double_t parRadius_; //! 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_; //! Value of the form factor for resonance decay (at pole mass) Double_t FR0_; - ClassDef(LauRelBreitWignerRes,0) // Relativistic Breit-Wigner resonance model }; #endif diff --git a/inc/LauRescattering2Res.hh b/inc/LauRescattering2Res.hh index 401aeda..09ca916 100644 --- a/inc/LauRescattering2Res.hh +++ b/inc/LauRescattering2Res.hh @@ -1,187 +1,186 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescattering2Res.hh \brief File containing declaration of LauRescattering2Res class. */ /*! \class LauRescattering2Res \brief Class for defining an alternative rescattering model. Model for pipi SWave proposed by J.Schechter as used by Cleo (PRD76,01200(2007) to replace the sigma and f0(980) contributions. */ #ifndef LAU_RESCATTERING2_RES #define LAU_RESCATTERING2_RES #include "TString.h" #include "LauAbsResonance.hh" #include "LauComplex.hh" class LauKinematics; class LauRescattering2Res : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauRescattering2Res(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauRescattering2Res(); //! Initialise the model virtual void initialise(); //! Get the resonance model type /*! \return the resonance model type */ virtual LauAbsResonance::LauResonanceModel getResonanceModel() const {return LauAbsResonance::Rescattering2;} //! Set value of a resonance parameter /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! This is not meant to be called virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); Double_t pn(const Double_t x, const Double_t n) const; Double_t x(const Double_t sqr_t, const Int_t i) const; Double_t phi00(const Double_t sqr_t, const Int_t i) const; Double_t g00(const Double_t sqr_t, const Int_t i) const; void setB1Parameter(const Double_t B1); void setB2Parameter(const Double_t B2); void setB3Parameter(const Double_t B3); void setC1Parameter(const Double_t C1); void setC2Parameter(const Double_t C2); void setC3Parameter(const Double_t C3); void setC4Parameter(const Double_t C4); void setC5Parameter(const Double_t C5); void setD0Parameter(const Double_t D0); void setD1Parameter(const Double_t D1); void setD2Parameter(const Double_t D2); void setD3Parameter(const Double_t D3); void setF1Parameter(const Double_t F1); void setF2Parameter(const Double_t F2); void setF3Parameter(const Double_t F3); void setF4Parameter(const Double_t F4); Double_t getB1Parameter() const {return (B1_!=0) ? B1_->value() : 0.0;} Bool_t fixB1Parameter() const {return (B1_!=0) ? B1_->fixed() : kTRUE;} Double_t getB2Parameter() const {return (B2_!=0) ? B2_->value() : 0.0;} Bool_t fixB2Parameter() const {return (B2_!=0) ? B2_->fixed() : kTRUE;} Double_t getB3Parameter() const {return (B3_!=0) ? B3_->value() : 0.0;} Bool_t fixB3Parameter() const {return (B3_!=0) ? B3_->fixed() : kTRUE;} Double_t getC1Parameter() const {return (C1_!=0)? C1_->value() : 0.0;} Bool_t fixC1Parameter() const {return (C1_!=0) ?C1_->fixed() : kTRUE;} Double_t getC2Parameter() const {return (C2_!=0)? C2_->value() : 0.0;} Bool_t fixC2Parameter() const {return (C2_!=0) ?C2_->fixed() : kTRUE;} Double_t getC3Parameter() const {return (C3_!=0)? C3_->value() : 0.0;} Bool_t fixC3Parameter() const {return (C3_!=0) ?C3_->fixed() : kTRUE;} Double_t getC4Parameter() const {return (C4_!=0)? C4_->value() : 0.0;} Bool_t fixC4Parameter() const {return (C4_!=0) ?C4_->fixed() : kTRUE;} Double_t getC5Parameter() const {return (C5_!=0)? C5_->value() : 0.0;} Bool_t fixC5Parameter() const {return (C5_!=0) ?C5_->fixed() : kTRUE;} Double_t getD0Parameter() const {return (D0_!=0) ? D0_->value() : 0.0;} Bool_t fixD0Parameter() const {return (D0_!=0) ? D0_->fixed() : kTRUE;} Double_t getD1Parameter() const {return (D1_!=0) ? D1_->value() : 0.0;} Bool_t fixD1Parameter() const {return (D1_!=0) ? D1_->fixed() : kTRUE;} Double_t getD2Parameter() const {return (D2_!=0) ? D2_->value() : 0.0;} Bool_t fixD2Parameter() const {return (D2_!=0) ? D2_->fixed() : kTRUE;} Double_t getD3Parameter() const {return (D3_!=0) ? D3_->value() : 0.0;} Bool_t fixD3Parameter() const {return (D3_!=0) ? D3_->fixed() : kTRUE;} Double_t getF1Parameter() const {return (F1_!=0) ? F1_->value() : 0.0;} Bool_t fixF1Parameter() const {return (F1_!=0) ? F1_->fixed() : kTRUE;} Double_t getF2Parameter() const {return (F2_!=0) ? F2_->value() : 0.0;} Bool_t fixF2Parameter() const {return (F2_!=0) ? F2_->fixed() : kTRUE;} Double_t getF3Parameter() const {return (F3_!=0) ? F3_->value() : 0.0;} Bool_t fixF3Parameter() const {return (F3_!=0) ? F3_->fixed() : kTRUE;} Double_t getF4Parameter() const {return (F4_!=0) ? F4_->value() : 0.0;} Bool_t fixF4Parameter() const {return (F4_!=0) ? F4_->fixed() : kTRUE;} private: //! Copy constructor (not implemented) LauRescattering2Res(const LauRescattering2Res& rhs); //! Copy assignment operator (not implemented) LauRescattering2Res& operator=(const LauRescattering2Res& rhs); //! Parameter LauParameter* B1_; LauParameter* B2_; LauParameter* B3_; LauParameter* C1_; LauParameter* C2_; LauParameter* C3_; LauParameter* C4_; LauParameter* C5_; LauParameter* D0_; LauParameter* D1_; LauParameter* D2_; LauParameter* D3_; LauParameter* F1_; LauParameter* F2_; LauParameter* F3_; LauParameter* F4_; Double_t sqr_tmin[3], sqr_tmax[3]; Double_t B0_, C0_, F0_; - ClassDef(LauRescattering2Res,0) // pipi S wave model by Schechter amplitude model }; #endif diff --git a/inc/LauRescatteringRes.hh b/inc/LauRescatteringRes.hh index fb56a23..b175280 100644 --- a/inc/LauRescatteringRes.hh +++ b/inc/LauRescatteringRes.hh @@ -1,304 +1,303 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescatteringRes.hh \brief File containing declaration of LauRescatteringRes class. */ /*! \class LauRescatteringRes \brief Class for defining the rescattering model. Defines the Rescatering models from PiPi-KK Inelastic Scatering : 2005: J.R. Pelaez, F. J. Ynduráin: PHYSICAL REVIEW D 71, 074016 (2005) 2015: J. H. Alvarenga Nogueira, I. Bediaga, A. B. R. Cavalcante, T. Frederico, and O. Lourenço: PHYSICAL REVIEW D 92, 054010 (2015) 2018: J.R. Pelaez, A.Rodas: Unpublished yet PiPi -> KK scattering up to 1.47 GeV with hyperbolic dispersion relations. */ #ifndef LAU_RESCATTERING_RES #define LAU_RESCATTERING_RES #include "TString.h" #include "LauComplex.hh" #include "LauAbsResonance.hh" class LauKinematics; class LauParameter; class LauRescatteringRes : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauRescatteringRes(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauRescatteringRes(); //! Initialise the model virtual void initialise(); //! 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 model_;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the parameter lambdaPiPi, the term for the PiPi /*! \param [in] lambda the term for the PiPi */ void setLambdaPiPi(const Double_t lambda); //! Get the lambdaPiPi, the term for the PiPi /*! \return lambdaPiPi, the term for the PiPi */ Double_t getLambdaPiPi() const {return (lambdaPiPi_!=0) ? lambdaPiPi_->value() : 0.0;} //! See if the lambdaPiPi parameter is fixed or floating /*! \return kTRUE if the lambdaPiPi parameter is fixed, kFALSE otherwise */ Bool_t fixLambdaPiPi() const {return (lambdaPiPi_!=0) ? lambdaPiPi_->fixed() : kTRUE;} //! Set the parameter lambdaKK, the term for the KK /*! \param [in] lambda the term for the KK */ void setLambdaKK(const Double_t lambda); //! Get the lambdaKK, the term for the KK /*! \return lambdaKK, the term for the KK */ Double_t getLambdaKK() const {return (lambdaKK_!=0) ? lambdaKK_->value() : 0.0;} //! See if the lambdaKK parameter is fixed or floating /*! \return kTRUE if the lambdaKK parameter is fixed, kFALSE otherwise */ Bool_t fixLambdaKK() const {return (lambdaKK_!=0) ? lambdaKK_->fixed() : kTRUE;} //! Set the parameter Ms /*! \param [in] Ms */ void setMs(const Double_t Ms); //! Get the Ms /*! \return the Ms */ Double_t getMs() const {return (Ms_!=0) ? Ms_->value() : 0.0;} //! See if the Ms parameter is fixed or floating /*! \return kTRUE if the Ms parameter is fixed, kFALSE otherwise */ Bool_t fixMs() const {return (Ms_!=0) ? Ms_->fixed() : kTRUE;} //! Set the parameter Mf /*! \param [in] Mf */ void setMf(const Double_t Mf); //! Get the Mf /*! \return the Mf */ Double_t getMf() const {return (Mf_!=0) ? Mf_->value() : 0.0;} //! See if the Mf parameter is fixed or floating /*! \return kTRUE if the Mf parameter is fixed, kFALSE otherwise */ Bool_t fixMf() const {return (Mf_!=0) ? Mf_->fixed() : kTRUE;} //! Set the parameter Mprime /*! \param [in] Mprime */ void setMprime(const Double_t Mprime); //! Get the Mprime /*! \return the Mprime */ Double_t getMprime() const {return (Mprime_!=0) ? Mprime_->value() : 0.0;} //! See if the Mprime parameter is fixed or floating /*! \return kTRUE if the Mprime parameter is fixed, kFALSE otherwise */ Bool_t fixMprime() const {return (Mprime_!=0) ? Mprime_->fixed() : kTRUE;} //! Set the parameter Eps1 /*! \param [in] Eps1 */ void setEps1(const Double_t Eps1); //! Get the Eps1 /*! \return the Eps1 */ Double_t getEps1() const {return (Eps1_!=0) ? Eps1_->value() : 0.0;} //! See if the Eps1 parameter is fixed or floating /*! \return kTRUE if the Eps1 parameter is fixed, kFALSE otherwise */ Bool_t fixEps1() const {return (Eps1_!=0) ? Eps1_->fixed() : kTRUE;} //! Set the parameter Eps2 /*! \param [in] Eps2 */ void setEps2(const Double_t Eps2); //! Get the Eps2 /*! \return the Eps2 */ Double_t getEps2() const {return (Eps2_!=0) ? Eps2_->value() : 0.0;} //! See if the Eps2 parameter is fixed or floating /*! \return kTRUE if the Eps2 parameter is fixed, kFALSE otherwise */ Bool_t fixEps2() const {return (Eps2_!=0) ? Eps2_->fixed() : kTRUE;} //! Set the parameter C0 /*! \param [in] C0 */ void setC0(const Double_t C0); //! Get the C0 /*! \return the C0 */ Double_t getC0() const {return (C0_!=0) ? C0_->value() : 0.0;} //! See if the C0 parameter is fixed or floating /*! \return kTRUE if the C0 parameter is fixed, kFALSE otherwise */ Bool_t fixC0() const {return (C0_!=0) ? C0_->fixed() : kTRUE;} //! 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: //! Copy constructor (not implemented) LauRescatteringRes(const LauRescatteringRes& rhs); //! Copy assignment operator (not implemented) LauRescatteringRes& operator=(const LauRescatteringRes& rhs); //! the term for the PiPi LauParameter* lambdaPiPi_; //! the term for the KK LauParameter* lambdaKK_; //! the term for the Mf_ LauParameter* Mf_; //! the term for the Ms LauParameter* Ms_; //! the term for the Mprime LauParameter* Mprime_; //! the term for the Eps1 LauParameter* Eps1_; //! the term for the Eps2 LauParameter* Eps2_; //! the term for the C0 LauParameter* C0_; //! The model to use LauAbsResonance::LauResonanceModel model_; - ClassDef(LauRescatteringRes,0) }; #endif diff --git a/inc/LauResonanceInfo.hh b/inc/LauResonanceInfo.hh index cb7d701..e8f9bb0 100644 --- a/inc/LauResonanceInfo.hh +++ b/inc/LauResonanceInfo.hh @@ -1,204 +1,203 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceInfo.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 #include #include "TString.h" #include "LauBlattWeisskopfFactor.hh" 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] bwCategory the Blatt-Weisskopf barrier factor category \param [in] bwRadius the Blatt-Weisskopf radius of the resonant particle */ LauResonanceInfo(const TString& name, const Double_t mass, const Double_t width, const Int_t spin, const Int_t charge, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius = 4.0); //! Destructor virtual ~LauResonanceInfo(); //! Retrieve the name of the resonant particle /*! \return the name of the resonant particle */ TString getName() const {return name_;} //! Retrieve the sanitised name of the resonant particle /*! Removes/replaces characters from the name that cause problems when used in TBranch names \return the sanitised name of the resonant particle */ TString getSanitisedName() const {return sanitisedName_;} //! Retrieve the mass of the resonant particle /*! \return the mass of the resonant particle */ LauParameter* getMass() const {return mass_;} //! Retrieve the width of the resonant particle /*! \return the width of the resonant particle */ LauParameter* getWidth() const {return width_;} //! Retrieve the spin of the resonant particle /*! \return the spin of the resonant particle */ UInt_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 BW category of the resonant particle /*! \return the BW category of the resonant particle */ LauBlattWeisskopfFactor::BlattWeisskopfCategory getBWCategory() const {return bwCategory_;} //! Retrieve the BW radius of the resonant particle /*! \return the BW radius of the resonant particle */ Double_t getBWRadius() const {return bwRadius_;} //! Create the charge conjugate particle info record /*! The mass and width parameters are cloned */ LauResonanceInfo* createChargeConjugate(); //! Create another record that will share parameters with this one /*! The name needs to be specified. The spin and charge are assumed to be the same. The mass, width and other parameters will be cloned. \param [in] name the name of the resonant particle */ LauResonanceInfo* createSharedParameterRecord( const TString& name ); //! Retrieve an extra parameter of the resonance /*! \return the extra parameter (or null pointer if not found) */ LauParameter* getExtraParameter( const TString& parName ); //! Add an extra parameter of the resonance /*! \param [in] param the extra parameter to be added \param [in] independentPar governs whether any info record that usually shares parameters with this one should also share this one (the default) or make its own independent version */ void addExtraParameter( LauParameter* param, const Bool_t independentPar = kFALSE ); protected: //! Add a clone of an extra parameter of the resonance /*! \param [in] param the extra parameter to be added \param [in] copyNotClone should we create an unlinked copy instead of cloning - default is to clone */ void addCloneOfExtraParameter( LauParameter* param, const Bool_t copyNotClone = kFALSE ); private: //! Copy constructor (not implemented) 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 ); //! Create the sanitised name by removing characters that are illegal in TBranch names void sanitiseName(); //! The name of the resonant particle TString name_; //! The name of the resonant particle with illegal characters removed TString sanitisedName_; //! The mass of the resonant particle LauParameter* mass_; //! The width of the resonant particle LauParameter* width_; //! The spin of the resonant particle UInt_t spin_; //! The charge of the resonant particle Int_t charge_; //! The Blatt-Weisskopf barrier factor category LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory_; //! The Blatt-Weisskopf radius of the resonant particle Double_t bwRadius_; //! The conjugate info object LauResonanceInfo* conjugate_; //! Other info objects that share parameters with this one std::vector sharedParRecords_; //! Extra parameters std::set extraPars_; - ClassDef(LauResonanceInfo, 0) // Specify each allowed resonance }; std::ostream& operator<<( std::ostream& stream, const LauResonanceInfo& infoRecord ); #endif diff --git a/inc/LauResonanceMaker.hh b/inc/LauResonanceMaker.hh index 0f09938..5d8c227 100644 --- a/inc/LauResonanceMaker.hh +++ b/inc/LauResonanceMaker.hh @@ -1,199 +1,198 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceMaker.hh \brief File containing declaration of LauResonanceMaker class. */ /*! \class LauResonanceMaker \brief Singleton factory class for creating resonances. 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 #include #include "TString.h" #include "LauAbsResonance.hh" class LauDaughters; class LauResonanceInfo; class LauResonanceMaker { public: //! Get the factory instance static LauResonanceMaker& get(); //! Set the type of BW factor (for all categories) /*! This must be used before creating any resonances \param [in] bwType the Blatt-Weisskopf barrier type */ void setBWType(const LauBlattWeisskopfFactor::BarrierType bwType); //! Set the rest frame in which the bachelor momentum should be calculated (for all BW categories) /*! This must be used before creating any resonances \param [in] restFrame the rest frame in which the bachelor momentum should be calculated for the Blatt-Weisskopf factors */ void setBWBachelorRestFrame(const LauBlattWeisskopfFactor::RestFrame restFrame); //! Set the spin formalism to be used for all resonances /*! This must be used before creating any resonances \param [in] spinType the spin formalism to be used */ void setSpinFormalism(const LauAbsResonance::LauSpinType spinType); //! Set the BW radius for the given category /*! \param [in] bwCategory the Blatt-Weisskopf barrier factor category \param [in] bwRadius the radius value to be used for the given category */ void setDefaultBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius); //! Fix or release the Blatt-Weisskopf barrier radius for the given category /*! \param [in] bwCategory the Blatt-Weisskopf barrier factor category \param [in] fixRadius new status of the radius (kTRUE = fixed, kFALSE = floating) */ void fixBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Bool_t fixRadius); //! 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 \param [in] bwCategory the Blatt-Weisskopf barrier factor category \return the resonance */ LauAbsResonance* getResonance(const LauDaughters* daughters, const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory = LauBlattWeisskopfFactor::Default); //! 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_;} //! 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( std::ostream& stream ) const; //! Get the information for the given resonance name /*! \param [in] resName the name of the resonant particle \return the LauResonanceInfo pointer if we can find the resonance name */ LauResonanceInfo* getResInfo(const TString& resName) const; //! Retrieve parent Blatt-Weisskopf factor (for use by K-matrix pole/SVP which doesn't have a `resInfo') LauBlattWeisskopfFactor* getParentBWFactor(Int_t newSpin, LauBlattWeisskopfFactor::BarrierType barrierType); protected: //! Create the list of known resonances void createResonanceVector(); //! Retrieve Blatt-Weisskopf factor for the given category LauBlattWeisskopfFactor* getBWFactor(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const LauResonanceInfo* resInfo); private: /*! \struct BlattWeisskopfCategoryInfo \brief Data structure to store information on a given Blatt-Weisskopf category */ struct BlattWeisskopfCategoryInfo { //! The BW factor object LauBlattWeisskopfFactor* bwFactor_; //! The default value for the radius in this category Double_t defaultRadius_; //! Whether or not the radius value for this category should be fixed in the fit Bool_t radiusFixed_; }; //! Define a type to hold information on each BW category typedef std::map BWFactorCategoryMap; //! 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 known resonances std::vector resInfo_; //! The type of the Blatt-Weisskopf barrier to use for all resonances LauBlattWeisskopfFactor::BarrierType bwBarrierType_; //! The rest frame in which the bachelor momentum used in the Blatt-Weisskopf factors should be calculated LauBlattWeisskopfFactor::RestFrame bwRestFrame_; //! The spin formalism that should be used for all resonances LauAbsResonance::LauSpinType spinFormalism_; //! The Blatt-Weisskopf factor objects (and related information) for each category BWFactorCategoryMap bwFactors_; //! The Blatt-Weisskopf factor objects for resonances in the independent category std::vector bwIndepFactors_; //! Boolean flag to control printing a summary of the formalism to be used when the first resonance is created Bool_t summaryPrinted_; - ClassDef(LauResonanceMaker,0) // Kinematic routines }; #endif diff --git a/inc/LauResultsExtractor.hh b/inc/LauResultsExtractor.hh index 29f7ea5..63c03ec 100644 --- a/inc/LauResultsExtractor.hh +++ b/inc/LauResultsExtractor.hh @@ -1,126 +1,125 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #include #include #include "TString.h" class TChain; class TFile; class TH1; class TTree; /*! \file LauResultsExtractor.hh \brief File containing declaration of LauResultsExtractor class. */ /*! \class LauResultsExtractor \brief Utility class to allow the extraction of the best fit from a series of fits to a given data sample A utility class to allow the extraction of the best fit from a series of fits to a given data sample. When fitting amplitude models, the likelihood parameter space is highly complex. Hence the fitter can often wander into local minima. To mitigate this effect a data sample can be fitted many times with randomised starting values of the isobar parameters. It is then necessary to determine which of these fits gives the best solution, i.e. the minimum NLL. This class performs this task, reading in a series of fits for each data sample and writing out a single file that contains the results of the best fit for each data sample. */ class LauResultsExtractor { public: //! Constructor /*! \param [in] inputFileName name of text file containing the input ROOT files \param [in] outputFileName name of the file to which the best fit info should be written \param [in] treeName name of the tree to read from the input files */ LauResultsExtractor(const TString& inputFileName, const TString& outputFileName, const TString& treeName); //! Destructor virtual ~LauResultsExtractor(); //! Run the calculations /*! \param [in] numExpts the number of experiments to process */ void process(const Int_t numExpts); protected: //! Create storage for leaves and call SetBranchAddress for each void setupInputTree(); //! Create branches in the output tree void setupOutputTree(TTree * tree); //! Toggle branch status of input tree branches (except iExpt, fitStatus and NLL) void setInputTreeBranchStatus(const Bool_t status); //! Clear all information void clearMaps(); //! Write the output file void writeFile(); private: //! Name of text file containing list of input files TString inputFileName_; //! Name of output ROOT file TString outputFileName_; //! Name of tree in input ROOT files TString treeName_; //! Chain of inputs TChain * inputTree_; //! Output file TFile * outputFile_; //! Output tree TTree * outputTree_; //! Number of entries in the input chain Int_t nEntries_; // Tree variables //! Storage for experiment ID variable Int_t iExpt_; //! Storage for fit status variable Int_t fitStatus_; //! Storage for NLL variable Double_t NLL_; //! Storage for EDM variable Double_t EDM_; //! Storage for other input variables std::map otherVars_; //! Best NLL and corresponding tree entries for each experiment std::map< Int_t, std::pair > bestNLL_; //! Worst NLL and corresponding tree entries for each experiment std::map< Int_t, std::pair > worstNLL_; //! All NLL values for each experiment std::map< Int_t, std::vector > allNLLs_; //! Histograms of the NLL values for each experiment std::map< Int_t, TH1* > nllHistos_; - ClassDef(LauResultsExtractor,0) }; diff --git a/inc/LauRhoOmegaMix.hh b/inc/LauRhoOmegaMix.hh index 127fa1a..d2eb315 100644 --- a/inc/LauRhoOmegaMix.hh +++ b/inc/LauRhoOmegaMix.hh @@ -1,285 +1,284 @@ /* Copyright 2016 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRhoOmegaMix.hh \brief File containing declaration of LauRhoOmegaMix class. */ /*! \class LauRhoOmegaMix \brief Class for defining the rho-omega resonance mixing model Formulae from Paul Rensing thesis, SLAC Report 421 and Bill Dunwoodie's note http://www.slac.stanford.edu/~wmd/omega-rho_mixing/omega-rho_mixing.note */ #ifndef LAU_RHO_OMEGA_MIX #define LAU_RHO_OMEGA_MIX #include "TString.h" #include "LauAbsResonance.hh" #include "LauComplex.hh" #include class LauResonanceInfo; class LauDaughters; class LauParameter; class LauRhoOmegaMix : public LauAbsResonance { public: //! Constructor /*! \param [in] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resType the model of the resonance \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauRhoOmegaMix(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters); //! Destructor virtual ~LauRhoOmegaMix(); //! Initialise the model virtual void initialise(); //! Initialise the rho resonance void initialiseRho(); //! Initialise the omega resonance void initialiseOmega(); //! 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 model_;} //! Set value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); //! Set which rho/omega amplitude to calculate for FF void setWhichAmpSq(Int_t which) { whichAmpSq_ = which; } protected: //! Set the omega pole mass parameter /*! \param [in] mOmega new value for the omega mass parameter */ void setmOmegaValue(const Double_t mOmega); //! Get the omega pole mass parameter value /*! \return value of the omega pole mass parameter */ Double_t getmOmegaValue() const { return (mOmega_!=0) ? mOmega_->unblindValue() : 0.0; } //! Fix the omega pole mass parameter value /*! \return kTRUE if the omega pole mass parameter is fixed, kFALSE otherwise */ Bool_t fixmOmegaValue() const { return (mOmega_!=0) ? mOmega_->fixed() : 0.0; } //! Set the omega pole width parameter /*! \param [in] wOmega new value for the omega width parameter */ void setwOmegaValue(const Double_t wOmega); //! Get the omega pole width parameter value /*! \return value of the omega pole width parameter */ Double_t getwOmegaValue() const { return (wOmega_!=0) ? wOmega_->unblindValue() : 0.0; } //! Fix the omega pole width parameter value /*! \return kTRUE if the omega pole width parameter is fixed, kFALSE otherwise */ Bool_t fixwOmegaValue() const { return (wOmega_!=0) ? wOmega_->fixed() : 0.0; } //! Set the omega B magnitude mixing parameter /*! \param [in] magB new value for the omega B magnitude mixing parameter */ void setmagBValue(const Double_t magB); //! Get the omega B magnitude mixing parameter /*! \return value of the omega B magnitude mixing parameter */ Double_t getmagBValue() const { return (magB_!=0) ? magB_->unblindValue() : 0.0; } //! Fix the omega B magnitude mixing parameter value /*! \return kTRUE if the omega B magnitude mixing parameter is fixed, kFALSE otherwise */ Bool_t fixmagBValue() const { return (magB_!=0) ? magB_->fixed() : 0.0; } //! Set the omega B phase mixing parameter /*! \param [in] phiB new value for the omega B phase mixing parameter */ void setphiBValue(const Double_t phiB); //! Get the omega B phase mixing parameter /*! \return value of the omega B phase mixing parameter */ Double_t getphiBValue() const { return (phiB_!=0) ? phiB_->unblindValue() : 0.0; } //! Fix the omega B phase mixing parameter value /*! \return kTRUE if the omega B phase mixing parameter is fixed, kFALSE otherwise */ Bool_t fixphiBValue() const { return (phiB_!=0) ? phiB_->fixed() : 0.0; } //! Set the omega mixing parameter delta /*! \param [in] delta new value for the omega mixing parameter delta */ void setdeltaValue(const Double_t delta); //! Get the omega mixing parameter delta /*! \return value of the omega mixing parameter delta */ Double_t getdeltaValue() const { return (delta_!=0) ? delta_->unblindValue() : 0.0; } //! Fix the omega mixing parameter delta value /*! \return kTRUE if the omega mixing parameter delta is fixed, kFALSE otherwise */ Bool_t fixdeltaValue() const { return (delta_!=0) ? delta_->fixed() : 0.0; } //! This is not called, amplitude is used directly instead virtual LauComplex resAmp(Double_t mass, Double_t spinTerm); //! Check that both daughters are the same type of particle void checkDaughterTypes() const; private: //! Copy constructor (not implemented) LauRhoOmegaMix(const LauRhoOmegaMix& rhs); //! Copy assignment operator (not implemented) LauRhoOmegaMix& operator=(const LauRhoOmegaMix& rhs); //! The model to use LauAbsResonance::LauResonanceModel model_; //! Previous value of the pole mass of the rho resonance Double_t rhoMass_; //! Previous value of the barrier radius of the rho resonance Double_t rhoResRadius_; //! Previous value of the parents barrier radius of the rho resonance Double_t rhoParRadius_; //! Pole mass of the omega contribution LauParameter* mOmega_; //! Initial default value of the omega pole mass from LauResonanceMaker Double_t mOmega0_; //! Current value of the omega pole mass (floating or fixed) Double_t mOmegaCur_; //! Pole width of the omega contribution LauParameter* wOmega_; //! Initial default value of the omega pole width from LauResonanceMaker Double_t wOmega0_; //! Current value of the omega pole mass (floating or fixed) Double_t wOmegaCur_; //! B magnitude parameter of the omega mixing contribution LauParameter* magB_; //! B phase parameter of the omega mixing contribution LauParameter* phiB_; //! delta parameter of the omega mixing contribution LauParameter* delta_; //! Boolean to specify if we want to use the denominator factor Bool_t useDenom_; //! Boolean to specify if we have performed the first initialisation Bool_t doneFirstInit_; //! Pointer to the rho (or first) resonance lineshape LauAbsResonance* rhoRes_; //! Pointer to the omega (second) resonance lineshape LauAbsResonance* omegaRes_; //! Which amplitude to calculate for rho/omega fit fractions Int_t whichAmpSq_; - ClassDef(LauRhoOmegaMix,0) // Rho-omega mixing model }; #endif diff --git a/inc/LauRooFitTask.hh b/inc/LauRooFitTask.hh index bb6ccd2..8d54d79 100644 --- a/inc/LauRooFitTask.hh +++ b/inc/LauRooFitTask.hh @@ -1,173 +1,172 @@ /* Copyright 2017 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRooFitTask.hh \brief File containing declaration of LauRooFitTask class. */ /*! \class LauRooFitTask \brief A class for creating a RooFit-based task process for simultaneous/combined fits Implementation of the JFit method described in arXiv:1409.5080 [physics.data-an]. */ #ifndef LAU_ROO_FIT_TASK #define LAU_ROO_FIT_TASK #include #include #include #include "RooAbsPdf.h" #include "RooAbsData.h" #include "RooCategory.h" #include "RooNLLVar.h" #include "TMatrixDfwd.h" #include "TString.h" #include "LauSimFitTask.hh" class LauParameter; class LauRooFitTask : public LauSimFitTask { public: //! Constructor LauRooFitTask( RooAbsPdf& model, const Bool_t extended, const RooArgSet& vars, const TString& weightVarName = "" ); //! Destructor virtual ~LauRooFitTask(); //! Initialise the fit model virtual void initialise(); //! This function sets the parameter values from Minuit /*! \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 virtual Double_t getTotNegLogLikelihood(); protected: //! Package the initial fit parameters for transmission to the coordinator /*! \param [out] array the array to be filled with the LauParameter objects */ virtual void prepareInitialParArray( TObjArray& array ); //! Convert a RooRealVar into a LauParameter /*! \param [in] rooParameter the RooRealVar to be converted \return the newly created LauParameter */ LauParameter* convertToLauParameter( const RooRealVar* rooParameter ) const; //! Convert a RooFormulaVar into LauParameters /*! \param [in] rooFormula the RooFormulaVar to be converted \return the vector of pointers to the RooRealVars and newly created LauParameters */ std::vector< std::pair > convertToLauParameters( const RooFormulaVar* rooFormula ) const; //! Perform all finalisation actions /*! - Receive the results of the fit from the coordinator - Perform any finalisation routines - Package the finalised fit parameters for transmission back to the coordinator \param [in] fitStat the status of the fit, e.g. status code, EDM, NLL \param [in] parsFromCoordinator the parameters at the fit minimum \param [in] covMat the fit covariance matrix \param [out] parsToCoordinator the array to be filled with the finalised LauParameter objects */ virtual void finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromCoordinator, const TMatrixD* covMat, TObjArray& parsToCoordinator ); //! Open the input file and verify that all required variables are present /*! \param [in] dataFileName the name of the input file \param [in] dataTreeName the name of the input tree */ virtual Bool_t verifyFitData(const TString& dataFileName, const TString& dataTreeName); //! Read in the data for the current experiment /*! \return the number of events read in */ virtual UInt_t readExperimentData(); //! Cache the input data values to calculate the likelihood during the fit virtual void cacheInputFitVars(); private: //! Cleanup the data void cleanData(); //! Copy constructor (not implemented) LauRooFitTask(const LauRooFitTask& rhs); //! Copy assignment operator (not implemented) LauRooFitTask& operator=(const LauRooFitTask& rhs); //! The model RooAbsPdf& model_; //! The dataset variables RooArgSet dataVars_; //! The name of the (optional) weight variable in the dataset TString weightVarName_; //! The data file TFile* dataFile_; //! The data tree TTree* dataTree_; //! The data for the current experiment RooAbsData* exptData_; //! Is the PDF extended? const Bool_t extended_; //! The experiment category variable std::set iExptSet_; //! The NLL variable RooNLLVar* nllVar_; //! The fit parameters (as RooRealVar's) std::vector fitVars_; //! The fit parameters (as LauParameter's) std::vector fitPars_; - ClassDef(LauRooFitTask,0); }; #endif diff --git a/inc/LauSPlot.hh b/inc/LauSPlot.hh index 3f90555..053f468 100644 --- a/inc/LauSPlot.hh +++ b/inc/LauSPlot.hh @@ -1,374 +1,373 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSPlot.hh \brief File containing declaration of LauSPlot class. */ /*! \class LauSPlot \brief Class for defining the SPlot technique Class for defining the SPlot technique based on TSplot from ROOT by the following authors: Muriel Pivk, Anna Kreshuk (10/2005). (Original copyright notice below) Code extended to deal with the following two extra scenarios: - Extended sPlots (see appendix B of sPlot paper) - 2D PDFs, i.e. one PDF for 2 variables When performing a multidimensional fit, the sWeights are calculated excluding each dimension in turn and excluding none of the variables. This allows sPlots of the fit variables to be made by using the weight calculated when that variable is excluded, while variables not in the fit can be plotted from the complete information. */ /********************************************************************** * * * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #ifndef LAU_SPLOT #define LAU_SPLOT #include #include #include #include "TMatrixD.h" #include "TString.h" class TEventList; class TLeaf; class TFile; class TTree; class LauSPlot : public TObject { public: //! Type to store names, e.g. of the discriminating/control variables typedef std::set NameSet; //! Type to associate a category name with a double precision number, e.g. a yield or PDF value for a given species typedef std::map NumbMap; //! Type to associate a variable name with the leaf of the input tree typedef std::map LeafMap; //! Type to associate the name of the species that have 2D PDFs with the names of the two variables involved in each such PDF typedef std::multimap< TString, std::pair > TwoDMap; //! Constructor /*! \param [in] fileName the name of the data file (containing the input tree) \param [in] treeName the name of the input tree (containing the per-event llhds) \param [in] firstExpt the first experiment \param [in] nExpt the number of experiments \param [in] variableNames the names of the discriminating variables \param [in] freeSpecies the species that are free to float in the fit \param [in] fixdSpecies the species that are fixed in the fit \param [in] twodimPDFs the species that have 2D PDFs and the name of the variables involved in each such PDF \param [in] sigSplit boolean flag to check whether the signal is split into Truth Matched and Self Cross Feed \param [in] scfDPSmeared boolean flag to check whether the SCF is smeared in the DP */ LauSPlot(const TString& fileName, const TString& treeName, Int_t firstExpt, Int_t nExpt, const NameSet& variableNames, const LauSPlot::NumbMap& freeSpecies, const LauSPlot::NumbMap& fixdSpecies, const TwoDMap& twodimPDFs, Bool_t sigSplit = kFALSE, Bool_t scfDPSmeared = kFALSE); //! Destructor virtual ~LauSPlot(); //! Method to calculate the sWeights and cN coeffs. /*! \param [in] option control print level (default set to no print out)\n "Q" - no print out (default)\n "V" - prints the estimated # of events in species\n "VV" - as "V" + the MINUIT printing + sums of weights for control */ void runCalculations(const TString& option = "q"); //! Save the sWeight results as a friend tree to the input tree (in the same file) void writeOutResults(); //! Access the per-event total PDF values for each species /*! \return the per-event total PDF values */ const std::vector& totalPdf() const {return pdfTot_;} protected: //! Check whether the input tree has been successfully read /*! \return true/false whether the task have been successfully performed */ Bool_t readInput() const {return readInput_;} //! Set that the input tree has been successfully read /*! \param [in] ok set that the input tree has been succeessfully read */ void readInput(Bool_t ok) {readInput_ = ok;} //! Check whether the signal is split into Truth Matched and Self Cross Feed /*! \return true/false whether the signal is split into TM and SCF */ Bool_t signalSplit() const {return signalSplit_;} //! Check whether the Self Cross Feed is smeared in the DP /*! \return true/false whether the Self Cross Feed is smeared in the DP */ Bool_t scfDPSmear() const {return scfDPSmear_;} //! Check whether the cN branches have been already created /*! \return true/false whether cN branches have been already created */ Bool_t definedCNBranches() const {return definedCNBranches_;} //! Set that the cN branches have been already defined /*! \param [in] defined set that the cN branches have been already defined */ void definedCNBranches(Bool_t defined) {definedCNBranches_ = defined;} //! Check whether the sWeights branches have been already created /*! \return true/false whether sWeights branches have been already created */ Bool_t definedSWeightBranches() const {return definedSWeightBranches_;} //! Set that the sWeights branches have been already defined /*! \param [in] defined set that the sWeights branches have been already defined */ void definedSWeightBranches(Bool_t defined) {definedSWeightBranches_ = defined;} //! Method to open the file in "update" mode and grab the input tree for reading void openInputFileAndTree(); //! Read the leaf structure from the tree and check the status of the read (calls LauSPlot::readInputLeaves and LauSPlot::checkLeaves) void readInputInfo(); //! Read the leaf structure from the tree and setup the leaf map Bool_t readInputLeaves(); //! Check whether the leaf structure makes sense given the PDFs we are expecting Bool_t checkLeaves() const; //! Create (if not already done) the tree for storing the cN coeffs void createCNTree(); //! Create the branches for each cN coefficient void defineCNBranches(); //! Create (if not already done) the tree for storing the sWeights void createSWeightTree(); //! Create the branches to store the sWeights void defineSWeightBranches(); //! Set the event list to contain only events from the given experiment /*! \param [in] iExpt the required experiment number */ void setExperiment(Int_t iExpt); //! Reads the values of each PDF likelihood for every event in the experiment void readExpt(); //! Make sure that we're using Minuit void checkFitter() const; //! Initialise Minuit, set the verbosity /*! \param [in] opt option to set the print level (opt = "Q", "V" or "W" == "VV") */ void initialiseFitter(const TString& opt); //! Add the species yields as fit parameters and fix them as appropriate void setFitParameters() const; //! Perform the minimisation wrt the yields alone void runFit(); //! Update the yields with the newly fitted values and print them (unless print option is "Q"). /*! \param [in] opt option to set the print level (opt = "Q", "V" or "W") */ void retrieveFittedParameters(const TString& opt); //! Print the supplied covariance matrix or, if pointer is null, the one previously calculated /*! \param [in] covmat 2D array containing the covariace matrix elements */ void printCovMatrixElements(const Double_t * covmat = 0) const; //! Print the sum of sWeights for all species /*! \param [in] exclName the name of variable excluded (or "none") */ void printSumOfWeights(const TString& exclName) const; // Calculate the covariance matrix from the various PDFs /*! \return true if calculation succeeded or false in case the covariance matrix can not be inverted */ Bool_t calcCovMatrix(); //! Calculate the total likelihood for each species by multiply together all the PDFs for that species /*! \param [in] exclName the name of excluded variable (or "none") */ void calcTotPDFValues(const TString& exclName); //! Computes the cN for the extended sPlots from the covariance matrix /*! \param [in] exclName the name of excluded variable (or "none") \param [in] covmat 2D array containing the covariace matrix elements */ void calcCNCoeffs(const TString& exclName, const Double_t * covmat = 0); //! Computes the sWeights from the PDFs and covariance matrix /*! \param [in] exclName the name of excluded variable (or "none") \param [in] covmat 2D array containing the covariace matrix elements */ void calcSWeights(const TString& exclName, Double_t * covmat = 0); //! Copy the sWeight of a given event into LauSPlot::sWeightsCurrent_, from which they can be stored in the output tree /*! \param [in] iEvent the requested event */ void copyEventWeights(Int_t iEvent); //! Fill the cN branches void fillCNBranches(); //! Fill the sWeights branches void fillSWeightBranches(); //! Add the sWeightTree as a friend tree of the input tree void addFriendTree(); private: //! Copy constructor (not implemented) LauSPlot(const LauSPlot& rhs); //! Copy assignment operator (not implemented) LauSPlot& operator=(const LauSPlot& rhs); //! The name of the data file TString fileName_; //! The name of the input tree (containing the per-event llhds) TString inputTreeName_; //! The name of the cn tree (containing the cN coefficients) TString cnTreeName_; //! The name of the sweight tree (containing the sWeights) TString sweightTreeName_; //! Pointer to the data file object TFile* file_; //! Pointer to the input tree TTree* inputTree_; //! Pointer to the output tree containing the cN coefficients TTree* cnTree_; //! Pointer to the output tree containing the sWeights TTree* sweightTree_; //! Pointer to an event list, that is used to loop through the experiments TEventList* eventList_; //! Collection to hold pointers to the leaves of the input tree LeafMap leaves_; //! The names of the discriminating variables NameSet variableNames_; //! The names and estimated yields of the free species NumbMap freeSpecies_; //! The names and estimated yields of the fixed species NumbMap fixdSpecies_; //! The names and estimated yields of the free species - need to keep the original values NumbMap origFreeSpecies_; //! The names and estimated yields of the fixed species - need to keep the original values NumbMap origFixdSpecies_; //! The names of the species that have 2D PDFs and the names of the variables involved TwoDMap twodimPDFs_; //! Is the signal split into TM and SCF? const Bool_t signalSplit_; //! If so then is the SCF smeared in the DP? const Bool_t scfDPSmear_; //! Flag whether the input tree has been successfully read Bool_t readInput_; //! Flag whether the cN branches have already been created Bool_t definedCNBranches_; //! Flag whether the sWeights branches have already been created Bool_t definedSWeightBranches_; //! First experiment Int_t firstExpt_; //! Number of experiments Int_t nExpt_; //! The current experiment Int_t iExpt_; //! Number of events in current experiment Int_t nEvents_; //! Number of discriminating variables Int_t nDiscVars_; //! Number of species free to float in the fit Int_t nFreeSpecies_; //! Number of species fixed in the fit Int_t nFixdSpecies_; //! Total number of species (free + fixed) Int_t nSpecies_; //! The per-event values of the total PDF for each species std::vector pdfTot_; //! The per-event values of the PDFs for each species for each disc variable std::vector > discPdf_; //! The per-event values of the SCF fraction std::vector scfFrac_; //! The calculated covariance matrix TMatrixD covMat_; //! The per-event values of the computed sWeights (for each species and for each combination of excluded vars) std::vector< std::map > sWeights_; //! The current-event values of the computed sWeights std::map sWeightsCurrent_; //! The extended sPlot coefficients (for each species and for each combination of excluded vars) std::map cN_; - ClassDef(LauSPlot, 0) }; #endif diff --git a/inc/LauScfMap.hh b/inc/LauScfMap.hh index 26df077..e1c573b 100644 --- a/inc/LauScfMap.hh +++ b/inc/LauScfMap.hh @@ -1,135 +1,134 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauScfMap.hh \brief File containing declaration of LauScfMap class. */ /*! \class LauScfMap \brief Class for representing the 4D smearing matrix for mis-reconstructed signal (self cross feed) The smearing matrix is formed from a 2D array of 2D histograms */ #ifndef LAU_SCF_MAP #define LAU_SCF_MAP #include #include class TH2; class LauScfMap { public: //! Constructor LauScfMap(); //! Destructor virtual ~LauScfMap(); //! Construct the smearing matrix from the supplied histograms /*! The histograms should give the migration probabilities from a given true bin to a given reco bin. These can be constructed as follows:\n Each histogram contains only the events that were generated in a given true bin.\n The events are plotted at their reconstructed co-ordinates.\n The histogram is then normalised. All histograms should be identically binned.\n There should be as many histograms supplied as there are bins in each.\n The order of the histograms in the vector should match the ROOT "global bin number" ordering. \param [in] histos vector of two-dimensional histograms */ void setHistos(const std::vector& histos); //! Get the number of bins /*! \return the number of bins */ Int_t getNumberOfBins() const { return numberOfBins_; }; //! Create lists of the co-ordinates of the centres of true bins /*! \param [out] xCoords the vector of x co-ordinates of the centre of each true bin \param [out] yCoords the vector of y co-ordinates of the centre of each true bin */ void listBinCentres( std::vector& xCoords, std::vector& yCoords) const; //! Find the global bin number for the given co-ordinates /*! \param [in] xCoord the vector of x co-ordinate \param [in] yCoord the vector of y co-ordinate \return the global bin number */ Int_t binNumber(Double_t xCoord, Double_t yCoord) const; //! Find which true bins contribute to the given reco bin /*! \param [in] recoBin the reco global bin number \return the list of true bins that contribute (the numbers returned are not global bin numbers but the index in the LauScfMap::histos_ storage) */ const std::vector* trueBins(Int_t recoBin) const; //! Probability of a true event in the given true bin migrating to the reco bin /*! \param [in] recoBin the reco global bin number \param [in] trueBin the true bin index in the LauScfMap::histos_ storage (as provided by LauScfMap::trueBins) \return the migration probability */ Double_t prob(Int_t recoBin, Int_t trueBin) const; //! Retrieve the migration histogram for trueBin /*! \param [in] trueBin the true global bin number \return the migration histogram */ TH2* trueHist(Int_t trueBin); private: //! Copy constructor (not implemented) LauScfMap( const LauScfMap& rhs ); //! Copy assignment operator (not implemented) LauScfMap& operator=( const LauScfMap& rhs ); //! The vector of two-dimensional histograms std::vector histos_; //! Map that links each reco global bin number and the vector of true bin indices into LauScfMap::histos_ std::map< Int_t, std::vector > contribs_; //! Number of bins in the x-axis Int_t nBinsX_; //! Number of bins in the y-axis Int_t nBinsY_; //! Number of bins in a 2D histogram (nBinsX_*nBinsY_) Int_t numberOfBins_; - ClassDef(LauScfMap, 0) }; #endif diff --git a/inc/LauSigmaRes.hh b/inc/LauSigmaRes.hh index 99875e3..5e63863 100644 --- a/inc/LauSigmaRes.hh +++ b/inc/LauSigmaRes.hh @@ -1,202 +1,201 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmaRes.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] resInfo the object containing information on the resonance name, mass, width, spin, charge, etc. \param [in] resPairAmpInt the number of the daughter not produced by the resonance \param [in] daughters the daughter particles */ LauSigmaRes(LauResonanceInfo* resInfo, const 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 value of the various parameters /*! \param [in] name the name of the parameter to be changed \param [in] value the new parameter value */ virtual void setResonanceParameter(const TString& name, const Double_t value); //! Allow the various parameters to float in the fit /*! \param [in] name the name of the parameter to be floated */ virtual void floatResonanceParameter(const TString& name); //! Access the given resonance parameter /*! \param [in] name the name of the parameter \return the corresponding parameter */ virtual LauParameter* getResonanceParameter(const TString& name); //! Retrieve the resonance parameters, e.g. so that they can be loaded into a fit /*! \return floating parameters of the resonance */ virtual const std::vector& getFloatingParameters(); protected: //! Set the b1 parameter /*! \param [in] b1 new value for b1 parameter */ void setB1Value(const Double_t b1); //! Set the b2 parameter /*! \param [in] b2 new value for b2 parameter */ void setB2Value(const Double_t b2); //! Set the A parameter /*! \param [in] A new value for A parameter */ void setAValue(const Double_t A); //! Set the m0 parameter /*! \param [in] m0 new value for m0 parameter */ void setM0Value(const Double_t m0); //! Get the b1 parameter value /*! \return value of the b1 parameter */ Double_t getB1Value() const { return (b1_!=0) ? b1_->unblindValue() : 0.0; } //! Get the b2 parameter value /*! \return value of the b2 parameter */ Double_t getB2Value() const { return (b2_!=0) ? b2_->unblindValue() : 0.0; } //! Get the A parameter value /*! \return value of the A parameter */ Double_t getAValue() const { return (a_!=0) ? a_->unblindValue() : 0.0; } //! Get the m0 parameter value /*! \return value of the m0 parameter */ Double_t getM0Value() const { return (m0_!=0) ? m0_->unblindValue() : 0.0; } //! Fix the b1 parameter value /*! \return kTRUE if the b1 parameter is fixed, kFALSE otherwise */ Bool_t fixB1Value() const { return (b1_!=0) ? b1_->fixed() : 0.0; } //! Fix the b2 parameter value /*! \return kTRUE if the b2 parameter is fixed, kFALSE otherwise */ Bool_t fixB2Value() const { return (b2_!=0) ? b2_->fixed() : 0.0; } //! Fix the A parameter value /*! \return kTRUE if the A parameter is fixed, kFALSE otherwise */ Bool_t fixAValue() const { return (a_!=0) ? a_->fixed() : 0.0; } //! Fix the m0 parameter value /*! \return kTRUE if the m0 parameter is fixed, kFALSE otherwise */ Bool_t fixM0Value() const { return (m0_!=0) ? m0_->fixed() : 0.0; } //! Complex resonant ampltiude /*! \param [in] mass appropriate invariant mass for the resonance \param [in] spinTerm 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: //! Copy constructor (not implemented) LauSigmaRes(const LauSigmaRes& rhs); //! Copy assignment operator (not implemented) LauSigmaRes& operator=(const LauSigmaRes& rhs); //! Defined as 4*mPi*mPi Double_t mPiSq4_; //! Defined as 0.5*mPi*mPi Double_t sAdler_; //! Factor from BES data LauParameter* b1_; //! Factor from BES data LauParameter* b2_; //! Factor from BES data LauParameter* a_; //! Factor from BES data LauParameter* m0_; - ClassDef(LauSigmaRes,0) // Sigma resonance model }; #endif diff --git a/inc/LauSigmoidPdf.hh b/inc/LauSigmoidPdf.hh index 1f74fad..bea8433 100644 --- a/inc/LauSigmoidPdf.hh +++ b/inc/LauSigmoidPdf.hh @@ -1,96 +1,95 @@ /* Copyright 2012 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmoidPdf.hh \brief File containing declaration of LauSigmoidPdf class. */ /*! \class LauSigmoidPdf \brief Class for defining a generalised sigmoid PDF. Class for defining a generalised sigmoid PDF: f(x) = 1 / ( 1 + e^(b - ax) ) The standard sigmoid is obtained when a = 1 and b = 0. */ #ifndef LAU_SIGMOID_PDF #define LAU_SIGMOID_PDF #include #include "TString.h" #include "LauAbsPdf.hh" class LauParameter; class LauSigmoidPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] theVarName the name of the abscissa variable \param [in] params the PDF parameters - a and b \param [in] minAbscissa the minimum value of the abscissa \param [in] maxAbscissa the maximum value of the abscissa */ LauSigmoidPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa); //! Destructor virtual ~LauSigmoidPdf(); //! Copy constructor LauSigmoidPdf(const LauSigmoidPdf& other); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); using LauAbsPdf::calcLikelihoodInfo; //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Parameter a LauAbsRValue* a_; //! Parameter b LauAbsRValue* b_; - ClassDef(LauSigmoidPdf,0) // Define the Sigmoid PDF }; #endif diff --git a/inc/LauSimFitCoordinator.hh b/inc/LauSimFitCoordinator.hh index 6f2bd57..9b95525 100644 --- a/inc/LauSimFitCoordinator.hh +++ b/inc/LauSimFitCoordinator.hh @@ -1,232 +1,231 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitCoordinator.hh \brief File containing declaration of LauSimFitCoordinator class. */ /*! \class LauSimFitCoordinator \brief The coordinator process for simultaneous/combined fits Implementation of the JFit method described in arXiv:1409.5080 [physics.data-an]. This class acts as the interface between the task processes and the minimiser. */ #ifndef LAU_SIM_FIT_COORDINATOR #define LAU_SIM_FIT_COORDINATOR #include #include #include "TMatrixD.h" #include "TStopwatch.h" #include "TString.h" #include "LauFitObject.hh" class TMessage; class TMonitor; class TSocket; class LauAbsRValue; class LauParameter; class LauFitNtuple; class LauSimFitCoordinator : public LauFitObject { public: //! Constructor /*! \param [in] numTasks the number of tasks processes to expect connections from \param [in] port the port on which to listen for connections from the tasks */ LauSimFitCoordinator( UInt_t numTasks, UInt_t port = 9090 ); //! Destructor virtual ~LauSimFitCoordinator(); //! Run the fit /*! \param [in] fitNtupleFileName the file to which the ntuple containing the fit results should be written \param [in] nExp the number of experiments to be fitted \param [in] firstExp the ID of the first experiment to be fitted \param [in] useAsymmErrors should asymmetric errors be calculated or not \param [in] doTwoStageFit should the fit be performed in two stages or not */ void runSimFit( const TString& fitNtupleFileName, const UInt_t nExp, const UInt_t firstExp = 0, const Bool_t useAsymmErrors = kFALSE, const Bool_t doTwoStageFit = kFALSE ); //! Mark that the fit is calculating asymmetric errors /*! This function has to be public since it is called by the fitter interface to mark when entering and exiting the asymmetric error calculation. It should not be called otherwise! \param [in] inAsymErrCalc boolean marking that the fit is calculating the asymmetric errors */ virtual void withinAsymErrorCalc(const Bool_t inAsymErrCalc); // Need to unshadow the query method defined in the base class using LauFitObject::withinAsymErrorCalc; //! 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); //! Calculate the new value of the negative log likelihood /*! This function has to be public since it is called from the global FCN. It should not be called otherwise! */ virtual Double_t getTotNegLogLikelihood(); protected: //! Print information on the parameters void printParInfo() const; //! Initialise void initialise(); //! Initialise socket connections for the tasks void initSockets(); //! Determine/update the parameter initial values from all tasks void getParametersFromTasks(); //! Determine the parameter names and initial values from all tasks void getParametersFromTasksFirstTime(); //! Update and verify the parameter initial values from all tasks void updateParametersFromTasks(); //! Check for compatibility between two same-named parameters, which should therefore be identical void checkParameter( const LauParameter* param, UInt_t index ) const; //! Add parameters to the list of Gaussian constrained parameters void addConParameters(); //! Calculate the penalty terms to the log likelihood from Gaussian constraints Double_t getLogLikelihoodPenalty(); //! Instruct the tasks to read the input data for the given experiment /*! \return success/failure of the reading operations */ Bool_t readData(); //! Instruct the tasks to perform the caching /*! \return success/failure of the caching operations */ Bool_t cacheInputData(); //! Perform the fit for the current experiment void fitExpt(); //! Instruct the tasks to update the initial fit parameter values, if required void checkInitFitParams(); //! Return the final parameters to the tasks and instruct them to perform their finalisation Bool_t finalise(); //! Instruct the tasks to write out the fit results Bool_t writeOutResults(); private: //! Copy constructor (not implemented) LauSimFitCoordinator(const LauSimFitCoordinator& rhs); //! Copy assignment operator (not implemented) LauSimFitCoordinator& operator=(const LauSimFitCoordinator& rhs); //! The number of tasks const UInt_t nTasks_; //! The requested port const UInt_t reqPort_; //! The covariance sub-matrices for each task std::vector covMatrices_; //! Parallel setup monitor TMonitor* socketMonitor_; //! Sockets for each of the tasks std::vector socketTasks_; //! Messages to tasks std::vector messagesToTasks_; //! Message from tasks to the coordinator TMessage* messageFromTask_; //! Map of parameter names to index in the values vector std::map< TString, UInt_t > parIndices_; //! Reverse map of index in the values vector to parameter names std::map< UInt_t, TString > parNames_; //! Parameters std::vector params_; //! Gaussian constraints std::vector conVars_; //! Parameter values std::vector parValues_; //! Lists of indices for each task std::vector< std::vector > taskIndices_; //! Lists of indices of free parameters for each task std::vector< std::vector > taskFreeIndices_; //! Parameter values to send to the tasks std::vector vectorPar_; //! Likelihood values returned from the tasks std::vector vectorRes_; //! The fit timer TStopwatch timer_; //! The total fit timer TStopwatch cumulTimer_; //! The fit results ntuple LauFitNtuple* fitNtuple_; - ClassDef(LauSimFitCoordinator,0); }; #endif diff --git a/inc/LauSimFitTask.hh b/inc/LauSimFitTask.hh index 1441807..e96c765 100644 --- a/inc/LauSimFitTask.hh +++ b/inc/LauSimFitTask.hh @@ -1,190 +1,189 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitTask.hh \brief File containing declaration of LauSimFitTask class. */ /*! \class LauSimFitTask \brief The base class for any task process for simultaneous/combined fits Implementation of the JFit method described in arXiv:1409.5080 [physics.data-an]. This class acts as the base class from which tasks should inherit. This allows any fitting framework to plug in to the JFit method. */ #ifndef LAU_SIM_FIT_TASK #define LAU_SIM_FIT_TASK #include "TMatrixDfwd.h" #include "LauFitObject.hh" class TMessage; class TSocket; class TString; class LauFitNtuple; class LauSimFitTask : public LauFitObject { public: //! Constructor LauSimFitTask(); //! Destructor virtual ~LauSimFitTask(); //! Obtain the number of tasks UInt_t nTasks() const {return nTasks_;} //! Obtain the ID number of this task UInt_t taskId() const {return taskId_;} //! Start the task 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] addressCoordinator the hostname of the machine running the coordinator process \param [in] portCoordinator the port number on which the coordinator process is listening */ virtual void runTask(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileName = "", const TString& addressCoordinator = "localhost", const UInt_t portCoordinator = 9090); //! Initialise the fit model /*! Each class that inherits from this one must implement this to do what is appropriate */ virtual void initialise() = 0; //! This function sets the parameter values from Minuit /*! \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) = 0; //! Calculates the total negative log-likelihood virtual Double_t getTotNegLogLikelihood() = 0; protected: //! Const access to the fit ntuple const LauFitNtuple* fitNtuple() const {return fitNtuple_;} //! Access to the fit ntuple LauFitNtuple* fitNtuple() {return fitNtuple_;} //! Establish the connection to the coordinator process /*! \param [in] addressCoordinator the hostname of the machine running the coordinator process \param [in] portCoordinator the port number on which the coordinator process is listening */ void connectToCoordinator( const TString& addressCoordinator, const UInt_t portCoordinator ); //! Listen for requests from the coordinator and act accordingly void processCoordinatorRequests(); //! Setup saving of fit results to ntuple/LaTeX table etc. /*! Provide here a default implementation that produces an ntuple only. Derived classes can override as they wish. \param [in] histFileName the file name for the output histograms \param [in] tableFileName the file name for the latex output file */ virtual void setupResultsOutputs( const TString& histFileName, const TString& tableFileName ); //! Package the initial fit parameters for transmission to the coordinator /*! \param [out] array the array to be filled with the LauParameter objects */ virtual void prepareInitialParArray( TObjArray& array ) = 0; //! Perform all finalisation actions /*! - Receive the results of the fit from the coordinator - Perform any finalisation routines - Package the finalised fit parameters for transmission back to the coordinator \param [in] fitStat the status of the fit, e.g. status code, EDM, NLL \param [in] parsFromCoordinator the parameters at the fit minimum \param [in] covMat the fit covariance matrix \param [out] parsToCoordinator the array to be filled with the finalised LauParameter objects */ virtual void finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromCoordinator, const TMatrixD* covMat, TObjArray& parsToCoordinator ) = 0; //! Open the input file and verify that all required variables are present /*! \param [in] dataFileName the name of the input file \param [in] dataTreeName the name of the input tree */ virtual Bool_t verifyFitData(const TString& dataFileName, const TString& dataTreeName) = 0; //! Read in the data for the current experiment /*! \return the number of events read in */ virtual UInt_t readExperimentData() = 0; //! Cache the input data values to calculate the likelihood during the fit virtual void cacheInputFitVars() = 0; //! Write out any fit results virtual void writeOutAllFitResults(); private: //! Copy constructor (not implemented) LauSimFitTask(const LauSimFitTask& rhs); //! Copy assignment operator (not implemented) LauSimFitTask& operator=(const LauSimFitTask& rhs); //! A socket to enable parallel setup TSocket* socketCoordinator_; //! Message from coordinator to the tasks TMessage* messageFromCoordinator_; //! Task id number UInt_t taskId_; //! The total number of tasks UInt_t nTasks_; //! Parameter values array (for reading from the coordinator) Double_t* parValues_; //! The fit ntuple LauFitNtuple* fitNtuple_; - ClassDef(LauSimFitTask,0); }; #endif diff --git a/inc/LauSimpleFitModel.hh b/inc/LauSimpleFitModel.hh index 5de2db0..f8526ef 100644 --- a/inc/LauSimpleFitModel.hh +++ b/inc/LauSimpleFitModel.hh @@ -1,530 +1,529 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimpleFitModel.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 #include "TString.h" #include "LauAbsFitModel.hh" #include "LauComplex.hh" #include "LauParameter.hh" class TH2; class LauAbsBkgndDPModel; class LauAbsCoeffSet; class LauIsobarDynamics; 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(LauIsobarDynamics* 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(LauAbsRValue* 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 boolean flag to specify that the supplied histogram contains only the upper half of a symmetric DP (or lower half if using square DP coordinates) \param [in] fluctuateBins whether the bins on the histogram should be varied in accordance with their uncertainties (for evaluation of systematic uncertainties) \param [in] scfMap the (optional) smearing matrix */ void splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf = kFALSE, const Bool_t fluctuateBins = 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( const Double_t scfFrac, const 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement \param [in] useReweighting perform an accept/reject routine using the configured signal amplitude model based on the MC-truth DP coordinate */ 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 the events \param [in] treeName the name of the tree \param [in] reuseEventsWithinEnsemble sample with replacement but only replace events once each experiment has been generated \param [in] reuseEventsWithinExperiment sample with immediate replacement */ void embedBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment = kFALSE); //! Set the DP amplitude coefficients /*! The name of the coeffSet must match the name of one of the resonances in the DP model. The supplied order of coefficients will be rearranged to match the order in which the resonances are stored in the dynamics, see LauIsobarDynamics::addResonance. \param [in] coeffSet the set of coefficients */ virtual void setAmpCoeffSet(LauAbsCoeffSet* coeffSet); protected: //! Define a map to be used to store a category name and numbers typedef std::map< TString, std::pair > LauGenInfo; //! Typedef for a vector of background DP models typedef std::vector LauBkgndDPModelList; //! Typedef for a vector of background PDFs typedef std::vector LauBkgndPdfsList; //! Typedef for a vector of background yields typedef std::vector LauBkgndYieldList; //! Typedef for a vector of embedded data objects typedef std::vector LauBkgndEmbDataList; //! Typedef for a vector of booleans to flag if events are reused typedef std::vector LauBkgndReuseEventsList; //! 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 ); //! 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 stream to which to print */ 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); //! Save the pdf Plots for all the resonances of experiment number fitExp /*! \param [in] label prefix for the file name to be saved */ virtual void savePDFPlots(const TString& label); //! Save the pdf Plots for the sum of ressonances correspondint to "sin" of experiment number fitExp /*! \param [in] label prefix for the file name to be saved \param [in] spin spin of the wave to be saved */ virtual void savePDFPlotsWave(const TString& label, const Int_t& spin); //! 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 std::pair 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);} //! Append fake data points to the inputData for each bin in the SCF smearing matrix /*! 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: //! Copy constructor (not implemented) LauSimpleFitModel(const LauSimpleFitModel& rhs); //! Copy assignment operator (not implemented) LauSimpleFitModel& operator=(const LauSimpleFitModel& rhs); //! The signal Dalitz plot model LauIsobarDynamics* 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 normalisation parameters (i.e. yields) UInt_t nNormPar_; //! Magnitudes and Phases std::vector coeffPars_; //! Fit fractions LauParArray fitFrac_; //! Fit fractions (uncorrected for the efficiency) LauParArray fitFracEffUnCorr_; //! 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 recoSCFFracs_; //! The cached values of the SCF fraction for each bin centre std::vector fakeSCFFracs_; //! The cached values of the sqDP jacobians for each event std::vector recoJacobians_; //! The cached values of the sqDP jacobians for each true bin std::vector fakeJacobians_; //! Run choice variables Bool_t compareFitData_; //! The complex coefficients std::vector coeffs_; // Embedding full simulation 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 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 bkgndExtraLike_; //! Total signal likelihood Double_t sigTotalLike_; //! Total SCF likelihood Double_t scfTotalLike_; //! Total background likelihood(s) std::vector bkgndTotalLike_; - ClassDef(LauSimpleFitModel,0) // Total fit/ToyMC model }; #endif diff --git a/inc/LauSumPdf.hh b/inc/LauSumPdf.hh index 4231669..52f6fa2 100644 --- a/inc/LauSumPdf.hh +++ b/inc/LauSumPdf.hh @@ -1,120 +1,119 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSumPdf.hh \brief File containing declaration of LauSumPdf class. */ /*! \class LauSumPdf \brief Class for defining a PDF that is the sum of two other PDFs. Class that allows the user to define PDF that is the sum of two other PDFs. The relative fraction of the two PDFs is user-defined and can be a free parameter. */ #ifndef LAU_SUM_PDF #define LAU_SUM_PDF #include "Rtypes.h" #include "LauAbsPdf.hh" class LauParameter; class LauSumPdf : public LauAbsPdf { public: //! Constructor /*! \param [in] pdf1 the first PDF \param [in] pdf2 the second PDF \param [in] frac1 the fractional contribution of the first PDF to the final PDF */ LauSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac1); //! Destructor virtual ~LauSumPdf(); //! Returns the number of input variables /*! \return the number of input variables */ UInt_t nInputVars() const {return pdf1_->nInputVars();} //! Boolean for the DP dependence of PDFs in the sum /*! \return DP dependence of PDF */ virtual Bool_t isDPDependent() const {return (pdf1_->isDPDependent() || pdf2_->isDPDependent());} //! Cache information from data /*! \param [in] inputData the input data */ virtual void cacheInfo(const LauFitDataTree& inputData); //! Calculate the likelihood (and intermediate info) for a given abscissa /*! \param [in] abscissas the values of the abscissa(s) */ virtual void calcLikelihoodInfo(const LauAbscissas& abscissas); //! Calculate the likelihood (and intermediate info) for a given event number /*! \param [in] iEvt event number */ virtual void calcLikelihoodInfo(UInt_t iEvt); //! Calculate the normalisation virtual void calcNorm(); //! Calculate the PDF height /*! \param [in] kinematics the current DP kinematics */ virtual void calcPDFHeight( const LauKinematics* kinematics ); protected: private: //! Copy constructor (not implemented) LauSumPdf(const LauSumPdf& rhs); //! Copy assignment operator (not implemented) LauSumPdf& operator=(const LauSumPdf& rhs); //! First PDF LauAbsPdf* pdf1_; //! Second PDF LauAbsPdf* pdf2_; //! Fractional contribution of first PDF to the final PDF LauAbsRValue* frac_; - ClassDef(LauSumPdf,0) // Define the sum PDF }; #endif diff --git a/inc/LauVetoes.hh b/inc/LauVetoes.hh index 83fe5e0..0126d6b 100644 --- a/inc/LauVetoes.hh +++ b/inc/LauVetoes.hh @@ -1,147 +1,146 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauVetoes.hh \brief File containing declaration of LauVetoes class. */ /*! \class LauVetoes \brief Class for defining vetoes within the Dalitz plot. Each veto is defined by an index corresponding to one of the three invariant mass-squared variables, and maximum and minimum values for the veto's range in the specified variable. Each mass-squared variable is numbered according to the index of the daughter not involved in the vetoed mass-squared variable. For example a veto in m12 squared would receive the index 3. Since v3r2, in the case of a symmetric DP, vetoes in m13 or m23 will automatically be symmetrised to the other variable (so only one needs to be specified). However, if one wants to veto a region from a symmetric DP in the already-symmetrised co-ordinates, the special indices 4 and 5 can be used that will apply the veto to mMin or mMax, respectively. */ #ifndef LAU_VETOES #define LAU_VETOES #include #include "Rtypes.h" class LauKinematics; class LauVetoes { public: //! Constructor LauVetoes(); //! Destructor virtual ~LauVetoes(); //! Copy constructor /*! \param [in] other the object to be copied */ LauVetoes(const LauVetoes& other); //! Copy assignment operator /*! \param [in] other the object to be copied \return the assigned vetoes object */ LauVetoes& operator=(const LauVetoes& other); //! Add a veto to the Dalitz plot /*! \param [in] resPairAmpInt the index of the mass-squared variable to be vetoed (in the case of symmetric DPs the special indices 4 and 5 can be used to indicate that a veto should be applied to mMin or mMax) \param [in] minMass the minimum mass of the veto \param [in] maxMass the maximum mass of the veto */ void addMassVeto(const Int_t resPairAmpInt, const Double_t minMass, const Double_t maxMass); //! Add a veto to the Dalitz plot /*! \param [in] resPairAmpInt the index of the mass-squared variable to be vetoed (in the case of symmetric DPs the special indices 4 and 5 can be used to indicate that a veto should be applied to mMinSq or mMaxSq) \param [in] minMassSq the minimum mass-squared of the veto \param [in] maxMassSq the maximum mass-squared of the veto */ void addMassSqVeto(const Int_t resPairAmpInt, const Double_t minMassSq, const Double_t maxMassSq); //! Check whether the specified Dalitz plot point passes the vetoes /*! \param [in] kinematics a point in the Dalitz plot \return true if the specified Dalitz plot point is outside all veto regions, false otherwise */ Bool_t passVeto(const LauKinematics* kinematics) const; protected: //! Check whether the specified Dalitz plot point passes the vetoes /*! \param [in] m12Sq the mass-squared of the first and second daughters \param [in] m23Sq the mass-squared of the second and third daughters \param [in] m13Sq the mass-squared of the first and third daughters \param [in] symmetricDP is the DP symmetric \param [in] fullySymmetricDP is the DP fully symmetric \return true if the specified Dalitz plot point is outside all veto regions, false otherwise */ Bool_t passVeto(const Double_t m12Sq, const Double_t m23Sq, const Double_t m13Sq, const Bool_t symmetricDP, const Bool_t fullySymmetricDP) const; //! Retrieve the number of vetoes /*! \return the number of vetoes */ UInt_t getNVetoes() const {return nVetoes_;} //! Retrieve the index of the vetoed mass-squared variable for each veto /*! \return the index of the vetoed mass-squared variable for each veto */ const std::vector& getVetoPairs() const {return vetoPair_;} //! Retrieve the minimum mass-squared for each veto /*! \return the minimum mass-squared for each veto */ const std::vector& getVetoMinMass() const {return vetoMinMass_;} //! Retrieve the maximum mass-squared for each veto /*! \return the maximum mass-squared for each veto */ const std::vector& getVetoMaxMass() const {return vetoMaxMass_;} private: //! The number of vetoes UInt_t nVetoes_; //! The index of the vetoed mass-squared variable for each veto std::vector vetoPair_; //! The minimum mass-squared for each veto std::vector vetoMinMass_; //! The maximum mass-squared for each veto std::vector vetoMaxMass_; - ClassDef(LauVetoes,0) // Vetoes in the Dalitz plot }; #endif diff --git a/inc/LauWeightedSumEffModel.hh b/inc/LauWeightedSumEffModel.hh index 485246e..387f04a 100644 --- a/inc/LauWeightedSumEffModel.hh +++ b/inc/LauWeightedSumEffModel.hh @@ -1,123 +1,122 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauWeightedSumEffModel.hh \brief File containing declaration of LauWeightedSumEffModel class. */ /*! \class LauWeightedSumEffModel \brief Class that implements the efficiency description across the signal Dalitz plot. Class that defines the efficiency model variation across the signal Dalitz plot. The phase space acceptance is determined from a weighted sum of LauAbsEffModel objects. This is useful for samples that contain two different categories of signal with different efficiencies. The efficiency variation is defined in terms of x = m_13^2, y = m_23^2 for the Dalitz plot (default) or x = m', y = theta' for the square Dalitz plot */ #ifndef LAUWEIGHTEDSUMEFFMODEL #define LAUWEIGHTEDSUMEFFMODEL #include "LauAbsEffModel.hh" class LauDaughters; class LauKinematics; class LauWeightedSumEffModel : public LauAbsEffModel { public: //! Constructor /*! \param [in] daughters the daughters particles of the Dalitz plot model */ LauWeightedSumEffModel(const LauDaughters* daughters); //! Destructor virtual ~LauWeightedSumEffModel() {} //! Add an efficiency variation across the phase space using a predetermined LauAbsEffModel object. /*! The efficiency is defined in terms of x = m_13^2, y = m_23^2 or x = m', y = theta' for the square Dalitz plot \param [in] effModel the LauAbsEffModel object that describes the efficiency variation \param [in] coeff the coefficient to multiply this efficiency by */ void addEffModel(const LauAbsEffModel* effModel, Double_t coeff); //! Determine the efficiency for a given point in the Dalitz plot. /*! The method uses the models set by the addEffModel() function and the vetoes information. \param [in] kinematics the object that defines the DP position \return the efficiency value at the given point in the DP */ Double_t calcEfficiency( const LauKinematics* kinematics ) const; //! Determine whether the given DP position is outside the vetoes /*! \param [in] kinematics the object that defines the DP position \return kTRUE if the DP position is outside all veto regions, kFALSE otherwise */ Bool_t passVeto( const LauKinematics* kinematics ) const; //! Determine whether the efficiency histogram has had its bins fluctuated within their errors Bool_t fluctuateEffHisto() const {return fluctuateEffHisto_;} //! Return the daughters object /* \return the LauDaughters object associated with the DP */ const LauDaughters* getDaughters() const {return daughters_;} private: //! Copy constructor - not implemented LauWeightedSumEffModel( const LauWeightedSumEffModel& rhs ); //! Copy assignment operator - not implemented LauWeightedSumEffModel& operator=( const LauWeightedSumEffModel& rhs ); //! The daughters object const LauDaughters* daughters_; //! The efficiency model objects std::vector effModel_; //! The efficiency model objects std::vector coeff_; //! Fluctuate histogram within the error Bool_t fluctuateEffHisto_; //! Flag to track whether a warning has been issued for bin values less than zero mutable Bool_t lowBinWarningIssued_; //! Flag to track whether a warning has been issued for bin values greater than one mutable Bool_t highBinWarningIssued_; - ClassDef(LauWeightedSumEffModel, 0) // Implement the signal efficiency across the DP }; #endif diff --git a/inc/Laura++_LinkDef.h b/inc/Laura++_LinkDef.h index 7d0f3d1..a604755 100644 --- a/inc/Laura++_LinkDef.h +++ b/inc/Laura++_LinkDef.h @@ -1,156 +1,38 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #ifdef __CINT__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class Lau1DCubicSpline+; -#pragma link C++ class Lau1DHistPdf+; -#pragma link C++ class Lau2DAbsDP+; -#pragma link C++ class Lau2DAbsDPPdf+; -#pragma link C++ class Lau2DAbsHistDP+; -#pragma link C++ class Lau2DAbsHistDPPdf+; -#pragma link C++ class Lau2DCubicSpline+; -#pragma link C++ class Lau2DHistDP+; -#pragma link C++ class Lau2DHistDPPdf+; -#pragma link C++ class Lau2DHistPdf+; -#pragma link C++ class Lau2DSplineDP+; -#pragma link C++ class Lau2DSplineDPPdf+; -#pragma link C++ class LauAbsBkgndDPModel+; -#pragma link C++ class LauAbsCoeffSet+; -#pragma link C++ class LauAbsEffModel+; -#pragma link C++ class LauAbsFitter+; -#pragma link C++ class LauAbsFitModel+; -#pragma link C++ class LauAbsIncohRes+; -#pragma link C++ class LauAbsModIndPartWave+; -#pragma link C++ class LauAbsPdf+; -#pragma link C++ class LauAbsResonance+; +#pragma link C++ nestedclasses; +#pragma link C++ nestedtypedefs; + #pragma link C++ class LauAbsRValue+; -#pragma link C++ class LauArgusPdf+; -#pragma link C++ class LauASqMaxFinder+; -#pragma link C++ class LauAsymmCalc+; -#pragma link C++ class LauBelleCPCoeffSet+; -#pragma link C++ class LauBelleNR+; -#pragma link C++ class LauBelleSymNR+; -#pragma link C++ class LauBifurcatedGaussPdf+; -#pragma link C++ class LauBkgndDPModel+; -#pragma link C++ class LauBlattWeisskopfFactor+; #pragma link C++ class LauBlind+; -#pragma link C++ class LauBreitWignerRes+; -#pragma link C++ class LauCacheData+; -#pragma link C++ class LauCalcChiSq+; -#pragma link C++ class LauCartesianCPCoeffSet+; -#pragma link C++ class LauCartesianGammaCPCoeffSet+; -#pragma link C++ class LauChebychevPdf+; -#pragma link C++ class LauCleoCPCoeffSet+; -#pragma link C++ class LauComplex+; -#pragma link C++ class LauCPFitModel+; -#pragma link C++ class LauCruijffPdf+; -#pragma link C++ class LauCrystalBallPdf+; -#pragma link C++ class LauDabbaRes+; -#pragma link C++ class LauDatabasePDG+; -#pragma link C++ class LauDaughters+; -#pragma link C++ class LauDPDepBifurGaussPdf+; -#pragma link C++ class LauDPDepCruijffPdf+; -#pragma link C++ class LauDPDepGaussPdf+; -#pragma link C++ class LauDPDepMapPdf+; -#pragma link C++ class LauDPDepSumPdf+; -#pragma link C++ class LauEffModel+; -#pragma link C++ class LauEFKLLMRes+; -#pragma link C++ class LauEmbeddedData+; -#pragma link C++ class LauExponentialPdf+; -#pragma link C++ class LauFitDataTree+; -#pragma link C++ class LauFitNtuple+; -#pragma link C++ class LauFitter+; -#pragma link C++ class LauFitObject+; -#pragma link C++ class LauFlatteRes+; -#pragma link C++ class LauFlatNR+; -#pragma link C++ class LauFormulaPar+; -#pragma link C++ class LauGaussIncohRes+; -#pragma link C++ class LauGaussPdf+; -#pragma link C++ class LauGenNtuple+; -#pragma link C++ class LauGounarisSakuraiRes+; -#pragma link C++ class LauIntegrals+; -#pragma link C++ class LauDPPartialIntegralInfo+; -#pragma link C++ class LauIsobarDynamics+; -#pragma link C++ class LauKappaRes+; -#pragma link C++ class LauKinematics+; -#pragma link C++ class LauKMatrixProdPole+; -#pragma link C++ class LauKMatrixProdSVP+; -#pragma link C++ class LauKMatrixPropagator+; -#pragma link C++ class LauKMatrixPropFactory+; -#pragma link C++ class LauLASSBWRes+; -#pragma link C++ class LauLASSNRRes+; -#pragma link C++ class LauLASSRes+; -#pragma link C++ class LauLinearPdf+; -#pragma link C++ class LauMagPhaseCoeffSet+; -#pragma link C++ class LauMagPhaseCPCoeffSet+; -#pragma link C++ class LauMergeDataFiles+; -#pragma link C++ class LauMinuit+; -#pragma link C++ class LauModIndPartWaveMagPhase+; -#pragma link C++ class LauModIndPartWaveRealImag+; -#pragma link C++ class LauNovosibirskPdf+; -#pragma link C++ class LauNRAmplitude+; #pragma link C++ class LauParameter+; -#pragma link C++ class LauParametricStepFuncPdf+; -#pragma link C++ class LauParamFixed+; -#pragma link C++ class LauParticlePDG+; -#pragma link C++ class LauPolNR+; -#pragma link C++ class LauPoleRes+; -#pragma link C++ class LauPolarFormFactorNR+; -#pragma link C++ class LauPolarFormFactorSymNR+; -#pragma link C++ class LauPolarGammaCPCoeffSet+; -#pragma link C++ class LauPrint+; -#pragma link C++ class LauRealImagCoeffSet+; -#pragma link C++ class LauRealImagCPCoeffSet+; -#pragma link C++ class LauRealImagGammaCPCoeffSet+; -#pragma link C++ class LauRelBreitWignerRes+; -#pragma link C++ class LauResonanceInfo+; -#pragma link C++ class LauRescatteringRes+; -#pragma link C++ class LauRescattering2Res+; -#pragma link C++ class LauResonanceMaker+; -#pragma link C++ class LauResultsExtractor+; -#pragma link C++ class LauRhoOmegaMix+; -#ifdef DOLAUROOFITTASK -#pragma link C++ class LauRooFitTask+; -#endif -#pragma link C++ class LauScfMap+; -#pragma link C++ class LauSigmaRes+; -#pragma link C++ class LauSigmoidPdf+; -#pragma link C++ class LauSimpleFitModel+; -#pragma link C++ class LauSimFitCoordinator+; -#pragma link C++ class LauSimFitTask+; -#pragma link C++ class LauSPlot+; -#pragma link C++ class LauString+; -#pragma link C++ class LauSumPdf+; -#pragma link C++ class LauTextFileParser+; -#pragma link C++ class LauVetoes+; -#pragma link C++ class LauWeightedSumEffModel+; -#pragma link C++ namespace LauConstants+; -#pragma link C++ namespace LauRandom+; #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d70d5e..912ba61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,54 +1,45 @@ -# Set the include directory (unfortunately this old-style stuff is necessary for the ROOT_GENERATE_DICTIONARY macro) -include_directories(${PROJECT_SOURCE_DIR}/inc) - -# Use glob to find the headers and sources -file(GLOB LAURA_HEADERS ${PROJECT_SOURCE_DIR}/inc/*.hh) +# Use glob to find the sources file(GLOB LAURA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) if (NOT LAURA_BUILD_ROOFIT_TASK) - list(REMOVE_ITEM LAURA_HEADERS ${PROJECT_SOURCE_DIR}/inc/LauRooFitTask.hh) list(REMOVE_ITEM LAURA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/LauRooFitTask.cc) endif() -# Generate the rootcint file -set(LAURA_LINKDEF ${PROJECT_SOURCE_DIR}/inc/Laura++_LinkDef.h) -set(LAURA_DICTIONARY_ROOT G__Laura++) -set(LAURA_DICTIONARY ${LAURA_DICTIONARY_ROOT}.cxx) -if (LAURA_BUILD_ROOFIT_TASK) - ROOT_GENERATE_DICTIONARY( - ${LAURA_DICTIONARY_ROOT} - ${LAURA_HEADERS} - LINKDEF ${LAURA_LINKDEF} - OPTIONS -DDOLAUROOFITTASK - ) -else() - ROOT_GENERATE_DICTIONARY( - ${LAURA_DICTIONARY_ROOT} - ${LAURA_HEADERS} - LINKDEF ${LAURA_LINKDEF} - ) -endif() - # Build the shared library -add_library(Laura++ SHARED ${LAURA_SOURCES} ${LAURA_DICTIONARY}) +add_library(Laura++ SHARED ${LAURA_SOURCES}) set_target_properties(Laura++ PROPERTIES OUTPUT_NAME Laura++) set_target_properties(Laura++ PROPERTIES VERSION ${CMAKE_PROJECT_VERSION} SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR}) set_target_properties(Laura++ PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) target_include_directories(Laura++ PUBLIC $ $) target_link_libraries(Laura++ ROOT::Core ROOT::Hist ROOT::Matrix ROOT::Physics ROOT::Minuit ROOT::EG ROOT::Tree) if (LAURA_BUILD_ROOFIT_TASK) target_link_libraries(Laura++ ROOT::RooFit ROOT::RooFitCore) endif() +# Generate the dictionary file for those classes that require I/O +list(APPEND LAURA_DICT_HEADERS + LauAbsRValue.hh + LauBlind.hh + LauParameter.hh + ) +set(LAURA_LINKDEF ${PROJECT_SOURCE_DIR}/inc/Laura++_LinkDef.h) +set(LAURA_DICTIONARY G__Laura++) +ROOT_GENERATE_DICTIONARY( + ${LAURA_DICTIONARY} + ${LAURA_DICT_HEADERS} + MODULE Laura++ + LINKDEF ${LAURA_LINKDEF} + ) + # Install the libraries install( TARGETS Laura++ EXPORT "LauraTargets" LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # Install the pcm and rootmap files generated by ROOT_GENERATE_DICTIONARY install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libLaura++.rootmap ${CMAKE_CURRENT_BINARY_DIR}/libLaura++_rdict.pcm DESTINATION ${CMAKE_INSTALL_LIBDIR} ) diff --git a/src/Lau1DCubicSpline.cc b/src/Lau1DCubicSpline.cc index c1eb757..4d94fcd 100644 --- a/src/Lau1DCubicSpline.cc +++ b/src/Lau1DCubicSpline.cc @@ -1,343 +1,342 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau1DCubicSpline.cc \brief File containing implementation of Lau1DCubicSpline class. */ #include #include #include #include #include #include "Lau1DCubicSpline.hh" -ClassImp(Lau1DCubicSpline) Lau1DCubicSpline::Lau1DCubicSpline(const std::vector& xs, const std::vector& ys, LauSplineType type, LauSplineBoundaryType leftBound, LauSplineBoundaryType rightBound, Double_t dydx0, Double_t dydxn) : nKnots_(xs.size()), x_(xs), y_(ys), type_(type), leftBound_(leftBound), rightBound_(rightBound), dydx0_(dydx0), dydxn_(dydxn) { init(); } Lau1DCubicSpline::~Lau1DCubicSpline() { } Double_t Lau1DCubicSpline::evaluate(Double_t x) const { // do not attempt to extrapolate the spline if( xx_[nKnots_-1] ) { std::cout << "WARNING in Lau1DCubicSpline::evaluate : function is only defined between " << x_[0] << " and " << x_[nKnots_-1] << std::endl; std::cout << " value at " << x << " returned as 0" << std::endl; return 0.; } // first determine which 'cell' of the spline x is in // cell i runs from knot i to knot i+1 Int_t cell(0); while( x > x_[cell+1] ) { ++cell; } // obtain x- and y-values of the neighbouring knots Double_t xLow = x_[cell]; Double_t xHigh = x_[cell+1]; Double_t yLow = y_[cell]; Double_t yHigh = y_[cell+1]; if(type_ == Lau1DCubicSpline::LinearInterpolation) { return yHigh*(x-xLow)/(xHigh-xLow) + yLow*(xHigh-x)/(xHigh-xLow); } // obtain t, the normalised x-coordinate within the cell, // and the coefficients a and b, which are defined in cell i as: // // a_i = k_i *(x_i+1 - x_i) - (y_i+1 - y_i), // b_i = -k_i+1*(x_i+1 - x_i) + (y_i+1 - y_i) // // where k_i is (by construction) the first derivative at knot i Double_t t = (x - xLow) / (xHigh - xLow); Double_t a = dydx_[cell] * (xHigh - xLow) - (yHigh - yLow); Double_t b = -1.*dydx_[cell+1] * (xHigh - xLow) + (yHigh - yLow); Double_t retVal = (1 - t) * yLow + t * yHigh + t * (1 - t) * ( a * (1 - t) + b * t ); return retVal; } void Lau1DCubicSpline::updateYValues(const std::vector& ys) { y_ = ys; this->calcDerivatives(); } void Lau1DCubicSpline::updateType(LauSplineType type) { if(type_ != type) { type_ = type; this->calcDerivatives(); } } void Lau1DCubicSpline::updateBoundaryConditions(LauSplineBoundaryType leftBound, LauSplineBoundaryType rightBound, Double_t dydx0, Double_t dydxn) { Bool_t updateDerivatives(kFALSE); if(leftBound_ != leftBound || rightBound_ != rightBound) { leftBound_ = leftBound; rightBound_ = rightBound; updateDerivatives = kTRUE; } if(dydx0_ != dydx0) { dydx0_ = dydx0; if(leftBound_ == Lau1DCubicSpline::Clamped) updateDerivatives = kTRUE; } if(dydxn_ != dydxn) { dydxn_ = dydxn; if(rightBound_ == Lau1DCubicSpline::Clamped) updateDerivatives = kTRUE; } if(updateDerivatives) { this->calcDerivatives(); } } void Lau1DCubicSpline::init() { if( y_.size() != x_.size()) { std::cout << "ERROR in Lau1DCubicSpline::init : The number of y-values given does not match the number of x-values" << std::endl; std::cout << " Found " << y_.size() << ", expected " << x_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } dydx_.insert(dydx_.begin(),nKnots_,0.); a_.insert(a_.begin(),nKnots_,0.); b_.insert(b_.begin(),nKnots_,0.); c_.insert(c_.begin(),nKnots_,0.); d_.insert(d_.begin(),nKnots_,0.); this->calcDerivatives(); } void Lau1DCubicSpline::calcDerivatives() { switch ( type_ ) { case Lau1DCubicSpline::StandardSpline : this->calcDerivativesStandard(); break; case Lau1DCubicSpline::AkimaSpline : this->calcDerivativesAkima(); break; case Lau1DCubicSpline::LinearInterpolation : //derivatives not needed for linear interpolation break; } } void Lau1DCubicSpline::calcDerivativesStandard() { // derivatives are determined such that the second derivative is continuous at internal knots // derivatives, k_i, are the solutions to a set of linear equations of the form: // a_i * k_i-1 + b_i * k+i + c_i * k_i+1 = d_i with a_0 = 0, c_n-1 = 0 // this is solved using the tridiagonal matrix algorithm as on en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm // first and last equations give boundary conditions // - for natural boundary, require f''(x) = 0 at end knot // - for 'not a knot' boundary, require f'''(x) continuous at second knot // - for clamped boundary, require predefined value of f'(x) at end knot // non-zero values of a_0 and c_n-1 would give cyclic boundary conditions a_[0] = 0.; c_[nKnots_-1] = 0.; // set left boundary condition if(leftBound_ == Lau1DCubicSpline::Natural) { b_[0] = 2./(x_[1]-x_[0]); c_[0] = 1./(x_[1]-x_[0]); d_[0] = 3.*(y_[1]-y_[0])/((x_[1]-x_[0])*(x_[1]-x_[0])); } else if(leftBound_ == Lau1DCubicSpline::NotAKnot) { // define the width, h, and the 'slope', delta, of the first cell Double_t h1(x_[1]-x_[0]), h2(x_[2]-x_[0]); Double_t delta1((y_[1]-y_[0])/h1), delta2((y_[2]-y_[1])/h2); // these coefficients can be determined by requiring f'''_0(x_1) = f'''_1(x_1) // the requirement f''_0(x_1) = f''_1(x_1) has been used to remove the dependence on k_2 b_[0] = h2; c_[0] = h1+h2; d_[0] = delta1*(2.*h2*h2 + 3.*h1*h2)/(h1+h2) + delta2*5.*h1*h1/(h1+h2); } else { //Clamped b_[0] = 1.; c_[0] = 0.; d_[0] = dydx0_; } // set right boundary condition if(rightBound_ == Lau1DCubicSpline::Natural) { a_[nKnots_-1] = 1./(x_[nKnots_-1]-x_[nKnots_-2]); b_[nKnots_-1] = 2./(x_[nKnots_-1]-x_[nKnots_-2]); d_[nKnots_-1] = 3.*(y_[nKnots_-1]-y_[nKnots_-2])/((x_[nKnots_-1]-x_[nKnots_-2])*(x_[nKnots_-1]-x_[nKnots_-2])); } else if(rightBound_ == Lau1DCubicSpline::NotAKnot) { // define the width, h, and the 'slope', delta, of the last cell Double_t hnm1(x_[nKnots_-1]-x_[nKnots_-2]), hnm2(x_[nKnots_-2]-x_[nKnots_-3]); Double_t deltanm1((y_[nKnots_-1]-y_[nKnots_-2])/hnm1), deltanm2((y_[nKnots_-2]-y_[nKnots_-3])/hnm2); // these coefficients can be determined by requiring f'''_n-3(x_n-2) = f'''_n-2(x_n-2) // the requirement f''_n-3(x_n-2) = f''_n-2(x_n-2) has been used to remove // the dependence on k_n-3 a_[nKnots_-1] = hnm2 + hnm1; b_[nKnots_-1] = hnm1; d_[nKnots_-1] = deltanm2*hnm1*hnm1/(hnm2+hnm1) + deltanm1*(2.*hnm2*hnm2 + 3.*hnm2*hnm1)/(hnm2+hnm1); } else { //Clamped a_[nKnots_-1] = 0.; b_[nKnots_-1] = 1.; d_[nKnots_-1] = dydxn_; } // the remaining equations ensure that f_i-1''(x_i) = f''_i(x_i) for all internal knots for(UInt_t i=1; i=0; --i) { dydx_[i] = d_[i] - c_[i]*dydx_[i+1]; } } void Lau1DCubicSpline::calcDerivativesAkima() { //derivatives are calculated according to the Akima method // J.ACM vol. 17 no. 4 pp 589-602 Double_t am1(0.), an(0.), anp1(0.); // a[i] is the slope of the segment from point i-1 to point i // // n.b. segment 0 is before point 0 and segment n is after point n-1 // internal segments are numbered 1 - n-1 for(UInt_t i=1; i #include #include #include "TAxis.h" #include "TH1.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "LauRandom.hh" class LauParameter; -ClassImp(Lau1DHistPdf) Lau1DHistPdf::Lau1DHistPdf(const TString& theVarName, const TH1* hist, Double_t minAbscissa, Double_t maxAbscissa, Bool_t useInterpolation, Bool_t fluctuateBins) : LauAbsPdf(theVarName, std::vector(), minAbscissa, maxAbscissa), hist_(hist ? dynamic_cast(hist->Clone()) : 0), useInterpolation_(useInterpolation), fluctuateBins_(fluctuateBins), nBins_(0), axisMin_(0.0), axisMax_(0.0), axisRange_(0.0) { // Constructor // Set the directory for the histogram hist_->SetDirectory(0); // Save various attributes of the histogram nBins_ = hist_->GetNbinsX(); TAxis* xAxis = hist_->GetXaxis(); axisMin_ = xAxis->GetXmin(); axisMax_ = xAxis->GetXmax(); axisRange_ = axisMax_ - axisMin_; // Check that axis range corresponds to range of abscissa if (TMath::Abs(this->getMinAbscissa() - axisMin_)>1e-6) { std::cerr << "ERROR in Lau1DHistPdf::Lau1DHistPdf : Histogram axis minimum: " << axisMin_ << " does not correspond to abscissa minimum: " << this->getMinAbscissa() << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(this->getMaxAbscissa() - axisMax_)>1e-6) { std::cerr << "ERROR in Lau1DHistPdf::Lau1DHistPdf : Histogram axis maximum: " << axisMax_ << " does not correspond to abscissa maximum: " << this->getMaxAbscissa() << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(); } // Calculate the PDF normalisation. this->calcNorm(); // And check it is OK. this->checkNormalisation(); } Lau1DHistPdf::~Lau1DHistPdf() { // Destructor delete hist_; hist_ = 0; } void Lau1DHistPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the maximum height of the histogram Int_t maxBin = hist_->GetMaximumBin(); Double_t height = hist_->GetBinContent(maxBin); this->setMaxHeight(height); } void Lau1DHistPdf::calcNorm() { // Calculate the histogram normalisation. // Loop over the range to get the total area. // Just sum the contributions up using 1e-3 increments of the range. // Multiply the end result by dx. Double_t dx(1e-3*axisRange_); Double_t area(0.0); Double_t x(axisMin_ + dx/2.0); while (x > axisMin_ && x < axisMax_) { area += this->interpolate(x); x += dx; } Double_t norm = area*dx; this->setNorm(norm); } void Lau1DHistPdf::checkNormalisation() { Double_t dx(1e-3*axisRange_); Double_t area(0.0); Double_t areaNoNorm(0.0); const Bool_t useInterpolationOrig { useInterpolation_ }; Double_t x(axisMin_ + dx/2.0); while (x > axisMin_ && x < axisMax_) { area += this->interpolateNorm(x); useInterpolation_ = kFALSE; areaNoNorm += this->interpolate(x); useInterpolation_ = useInterpolationOrig; x += dx; } Double_t norm = area*dx; std::cout << "INFO in Lau1DHistPdf::checkNormalisation : Area = " << area << ", dx = " << dx << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx = " << areaNoNorm*dx << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } Double_t Lau1DHistPdf::getBinHistValue(Int_t bin) const { // Check that bin is in range [1 , nBins_] if ((bin < 1) || (bin > nBins_)) { return 0.0; } Double_t value = static_cast(hist_->GetBinContent(bin)); // protect against negative values if ( value < 0.0 ) { std::cerr << "WARNING in Lau1DHistPdf::getBinHistValue : Negative bin content set to zero!" << std::endl; value = 0.0; } return value; } Double_t Lau1DHistPdf::interpolateNorm(Double_t x) const { // Get the normalised interpolated value. Double_t value = this->interpolate(x); Double_t norm = this->getNorm(); return value/norm; } void Lau1DHistPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Calculate the interpolated value Double_t value = this->interpolate(abscissa); this->setUnNormPDFVal(value); } Double_t Lau1DHistPdf::interpolate(Double_t x) const { // This function returns the interpolated value of the histogram function // for the given value of x by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Find the histogram bin Int_t bin = hist_->FindFixBin(x); // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(bin); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = hist_->GetBinCenter(bin); // Find the adjacent bins Double_t deltax = x - cbinx; Int_t bin_adj(0); if (deltax > 0.0) { bin_adj = bin + 1; } else { bin_adj = bin - 1; } Bool_t isBoundary(kFALSE); if ( bin_adj > nBins_ || bin_adj < 1 ) { isBoundary = kTRUE; } // At the edges, do no interpolation, use entry in bin. if (isBoundary == kTRUE) { return this->getBinHistValue(bin); } // Linear interpolation using inverse distance as weights. // Find the adjacent bin centre Double_t cbinx_adj = hist_->GetBinCenter(bin_adj); Double_t deltax_adj = cbinx_adj - x; Double_t dx0 = TMath::Abs(deltax); Double_t dx1 = TMath::Abs(deltax_adj); Double_t denom = dx0 + dx1; Double_t value0 = this->getBinHistValue(bin); Double_t value1 = this->getBinHistValue(bin_adj); Double_t value = value0*dx1 + value1*dx0; value /= denom; return value; } void Lau1DHistPdf::doBinFluctuation() { TRandom* random = LauRandom::randomFun(); for (Int_t bin(0); binGetBinContent(bin+1); Double_t currentError = hist_->GetBinError(bin+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist_->SetBinContent(bin+1,0.0); } else { hist_->SetBinContent(bin+1,newContent); } } } diff --git a/src/Lau2DAbsHistDP.cc b/src/Lau2DAbsHistDP.cc index 26fa795..da6e84a 100644 --- a/src/Lau2DAbsHistDP.cc +++ b/src/Lau2DAbsHistDP.cc @@ -1,195 +1,194 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDP.cc \brief File containing implementation of Lau2DAbsHistDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DAbsHistDP.hh" #include "LauBifurcatedGaussPdf.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DAbsHistDP) Lau2DAbsHistDP::Lau2DAbsHistDP(const LauDaughters* daughters, Bool_t useUpperHalfOnly, Bool_t squareDP) : kinematics_( (daughters!=0) ? daughters->getKinematics() : 0 ), upperHalf_(useUpperHalfOnly), squareDP_(squareDP) { if ( squareDP && ! daughters->squareDP() ) { // The histogram provided is defined in the square DP but the // kinematics object has calculation of the square DP // co-ordinates disabled, so need to enable it, // which requires a bit of a unpleasant const_cast std::cerr << "WARNING in Lau2DAbsHistDP constructor : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; LauKinematics* kine = const_cast( kinematics_ ); kine->squareDP(kTRUE); } } Lau2DAbsHistDP::~Lau2DAbsHistDP() { } void Lau2DAbsHistDP::doBinFluctuation(TH2* hist) { TRandom* random = LauRandom::randomFun(); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist->SetBinContent(i+1,j+1,0.0); } else { hist->SetBinContent(i+1,j+1,newContent); } } } } void Lau2DAbsHistDP::doBinFluctuation(TH2* hist, const TH2* errorHi, const TH2* errorLo) { LauParameter* mean = new LauParameter("mean", 0.5, 0.0, 1.0, kFALSE); LauParameter* sigL = new LauParameter("sigmaL", 0.5, 0.0, 1.0, kFALSE); LauParameter* sigR = new LauParameter("sigmaR", 0.5, 0.0, 1.0, kFALSE); std::vector pars(3); pars[0] = mean; pars[1] = sigL; pars[2] = sigR; const TString varName("tmp"); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); LauFitData genData; for (Int_t i(0); iGetBinContent(i+1,j+1); const Double_t currentErrorLo = errorLo->GetBinContent(i+1,j+1); const Double_t currentErrorHi = errorHi->GetBinContent(i+1,j+1); mean->value( currentContent ); sigL->value( currentErrorLo ); sigR->value( currentErrorHi ); const Double_t minVal = TMath::Max( 0.0, currentContent-5.0*currentErrorLo ); const Double_t maxVal = TMath::Min( 1.0, currentContent+5.0*currentErrorHi ); LauBifurcatedGaussPdf bfgaus(varName, pars, minVal, maxVal); bfgaus.heightUpToDate(kFALSE); genData = bfgaus.generate(0); const Double_t newContent = genData[varName]; hist->SetBinContent(i+1,j+1,newContent); } } delete pars[0]; delete pars[1]; delete pars[2]; pars.clear(); } void Lau2DAbsHistDP::raiseOrLowerBins(TH2* hist, const Double_t avEff, const Double_t avEffError) { TRandom* random = LauRandom::randomFun(); Double_t curAvg = this->computeAverageContents(hist); Double_t newAvg = random->Gaus(avEff,avEffError); hist->Scale( newAvg / curAvg ); } Double_t Lau2DAbsHistDP::computeAverageContents(const TH2* hist) const { Double_t totalContent(0.0); Int_t binsWithinDPBoundary(0); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); // Loop through the bins and include any that have their centre or any // of the four corners within the kinematic boundary for ( Int_t i(0); iGetXaxis()->GetBinCenter(i+1); Double_t binXLowerEdge = hist->GetXaxis()->GetBinLowEdge(i+1); Double_t binXUpperEdge = hist->GetXaxis()->GetBinUpEdge(i+1); for ( Int_t j(0); jGetYaxis()->GetBinCenter(i+1); Double_t binYLowerEdge = hist->GetYaxis()->GetBinLowEdge(i+1); Double_t binYUpperEdge = hist->GetYaxis()->GetBinUpEdge(i+1); if ( this->withinDPBoundaries( binXCentre, binYCentre ) || this->withinDPBoundaries( binXLowerEdge, binYLowerEdge ) || this->withinDPBoundaries( binXUpperEdge, binYUpperEdge ) || this->withinDPBoundaries( binXLowerEdge, binYUpperEdge ) || this->withinDPBoundaries( binXUpperEdge, binYLowerEdge ) ) { totalContent += hist->GetBinContent(i+1, j+1); ++binsWithinDPBoundary; } } } return totalContent/binsWithinDPBoundary; } Bool_t Lau2DAbsHistDP::withinDPBoundaries(Double_t x, Double_t y) const { return squareDP_ ? kinematics_->withinSqDPLimits(x,y) : kinematics_->withinDPLimits(x,y); } void Lau2DAbsHistDP::getUpperHalf(Double_t& x, Double_t& y) const { if ( upperHalf_ == kTRUE ) { if ( squareDP_ == kFALSE && x > y ) { Double_t temp = y; y = x; x = temp; } else if ( squareDP_ == kTRUE && y > 0.5 ) { y = 1.0 - y; } } } diff --git a/src/Lau2DAbsHistDPPdf.cc b/src/Lau2DAbsHistDPPdf.cc index 9e71168..fec3c57 100644 --- a/src/Lau2DAbsHistDPPdf.cc +++ b/src/Lau2DAbsHistDPPdf.cc @@ -1,124 +1,123 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DAbsHistDPPdf.cc \brief File containing implementation of Lau2DAbsHistDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "Lau2DAbsHistDPPdf.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(Lau2DAbsHistDPPdf) Lau2DAbsHistDPPdf::Lau2DAbsHistDPPdf(LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useUpperHalfOnly, Bool_t squareDP) : kinematics_(kinematics), vetoes_(vetoes), upperHalf_(useUpperHalfOnly), squareDP_(squareDP) { if ( squareDP && ! kinematics->squareDP() ) { // The histogram provided is defined in the square DP but the // kinematics object has calculation of the square DP // co-ordinates disabled, so need to enable it, std::cerr << "WARNING in Lau2DAbsHistDPPdf constructor : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; kinematics->squareDP(kTRUE); } } Lau2DAbsHistDPPdf::~Lau2DAbsHistDPPdf() { } void Lau2DAbsHistDPPdf::calcMaxHeight(TH2* hist) { // Get the maximum height of the 2D histogram maxHeight_ = 1.0; if ( hist ) { Int_t maxBin = hist->GetMaximumBin(); maxHeight_ = hist->GetBinContent(maxBin); } std::cout << "INFO in Lau2DAbsHistDPPdf::calcMaxHeight : Max height = " << maxHeight_ << std::endl; } void Lau2DAbsHistDPPdf::doBinFluctuation(TH2* hist) { if ( !hist ) { return; } TRandom* random = LauRandom::randomFun(); Int_t nBinsX = static_cast(hist->GetNbinsX()); Int_t nBinsY = static_cast(hist->GetNbinsY()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist->SetBinContent(i+1,j+1,0.0); } else { hist->SetBinContent(i+1,j+1,newContent); } } } } Bool_t Lau2DAbsHistDPPdf::withinDPBoundaries(Double_t x, Double_t y) const { return squareDP_ ? kinematics_->withinSqDPLimits(x,y) : kinematics_->withinDPLimits(x,y); } void Lau2DAbsHistDPPdf::getUpperHalf(Double_t& x, Double_t& y) const { if ( upperHalf_ == kTRUE ) { if ( squareDP_ == kFALSE && x > y ) { Double_t temp = y; y = x; x = temp; } else if ( squareDP_ == kTRUE && y > 0.5 ) { y = 1.0 - y; } } } void Lau2DAbsHistDPPdf::updateKinematics(Double_t x, Double_t y) const { if (squareDP_ == kTRUE) { kinematics_->updateSqDPKinematics(x,y); } else { kinematics_->updateKinematics(x,y); } } diff --git a/src/Lau2DCubicSpline.cc b/src/Lau2DCubicSpline.cc index 775beb2..116f1e8 100644 --- a/src/Lau2DCubicSpline.cc +++ b/src/Lau2DCubicSpline.cc @@ -1,374 +1,373 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DCubicSpline.cc \brief File containing implementation of Lau2DCubicSpline class. Class for defining a 2D cubic spline based on RooBinned2DBicubicBase by Manuel Tobias Schiller (2012-08-29). */ #include #include #include #include #include #include "Lau2DCubicSpline.hh" -ClassImp(Lau2DCubicSpline) Lau2DCubicSpline::~Lau2DCubicSpline() { } inline Double_t Lau2DCubicSpline::histcont( const TH2& h, Int_t xbin, Int_t ybin) const { //reflect until we're in range while(xbin < 0 || xbin >= nBinsX - 1) { if(xbin < 0) xbin = -xbin-1; if(xbin >= nBinsX -1) xbin = 2*(nBinsX-1) - xbin - 1; } while(ybin < 0 || ybin >= nBinsY - 1) { if(ybin < 0) ybin = -ybin-1; if(ybin >= nBinsY -1) ybin = 2*(nBinsY-1) - ybin - 1; } return h.GetBinContent(1 + xbin, 1 + ybin); } inline Double_t Lau2DCubicSpline::dhistdx( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin + 1, ybin) - histcont(h, xbin - 1, ybin)); } inline Double_t Lau2DCubicSpline::dhistdy( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin, ybin + 1) - histcont(h, xbin, ybin - 1)); } inline Double_t Lau2DCubicSpline::d2histdxdy( const TH2& h, Int_t xbin, Int_t ybin) const { return 0.5 * (histcont(h, xbin - 1, ybin - 1) - histcont(h, xbin + 1, ybin - 1) + histcont(h, xbin + 1, ybin + 1) - histcont(h, xbin - 1, ybin + 1)); } Lau2DCubicSpline::Lau2DCubicSpline(const TH2& h) : nBinsX(1 + h.GetNbinsX()), nBinsY(1 + h.GetNbinsY()), binSizeX(h.GetXaxis()->GetBinWidth(1)), binSizeY(h.GetYaxis()->GetBinWidth(1)), xmin(h.GetXaxis()->GetBinCenter(1) - binSizeX), xmax(h.GetXaxis()->GetBinCenter(nBinsX - 1) + binSizeX), ymin(h.GetYaxis()->GetBinCenter(1) - binSizeY), ymax(h.GetYaxis()->GetBinCenter(nBinsY - 1) + binSizeY), coeffs(CoeffRecLen * nBinsX * nBinsY) { const TAxis* xaxis = h.GetXaxis(); const TAxis* yaxis = h.GetYaxis(); // verify that all bins have same size for (Int_t i = 1; i < nBinsX; ++i) { if (std::abs(xaxis->GetBinWidth(i) / binSizeX - 1.) > 1e-9) { std::cerr << "ERROR in Lau2DCubicSpline constructor : the histogram has variable bin sizes." << std::endl; gSystem->Exit(EXIT_FAILURE); } } for (Int_t i = 1; i < nBinsY; ++i) { if (std::abs(yaxis->GetBinWidth(i) / binSizeY - 1.) > 1e-9) { std::cerr << "ERROR in Lau2DCubicSpline constructor : the histogram has variable bin sizes." << std::endl; gSystem->Exit(EXIT_FAILURE); } } // ok, go through histogram to precalculate the interpolation coefficients // in rectangles between bin centres // // for that purpose, we map each of those rectangles to the unit square for (Int_t j = -1; j < nBinsY - 1; ++j) { for (Int_t i = -1; i < nBinsX - 1; ++i) { const Double_t rhs[NCoeff] = { // function values in bin centres histcont(h, i, j), histcont(h, i + 1, j), histcont(h, i, j + 1), histcont(h, i + 1, j + 1), // df/dx in bin centres (finite difference approximation) dhistdx(h, i, j), dhistdx(h, i + 1, j), dhistdx(h, i, j + 1), dhistdx(h, i + 1, j + 1), // df/dy in bin centres (finite difference approximation) dhistdy(h, i, j), dhistdy(h, i + 1, j), dhistdy(h, i, j + 1), dhistdy(h, i + 1, j + 1), // d^2f/dxdy in bin centres (finite difference approximation) d2histdxdy(h, i, j), d2histdxdy(h, i + 1, j), d2histdxdy(h, i, j + 1), d2histdxdy(h, i + 1, j + 1) }; // work out solution - strange array placement is due to the fact // that terms with x/y to high powers can be small, so they should // be added up first during evaluation to avoid cancellation // issues; at the same time you want to access them in order to // not confuse the CPU cache, so they're stored back to front // // a_00 ... a_30 coeff(1 + i, 1 + j, 15) = rhs[0]; coeff(1 + i, 1 + j, 14) = rhs[4]; coeff(1 + i, 1 + j, 13) = 3. * (-rhs[0] + rhs[1]) - 2. * rhs[4] - rhs[5]; coeff(1 + i, 1 + j, 12) = 2. * (rhs[0] - rhs[1]) + rhs[4] + rhs[5]; // a_31 ... a_31 coeff(1 + i, 1 + j, 11) = rhs[8]; coeff(1 + i, 1 + j, 10) = rhs[12]; coeff(1 + i, 1 + j, 9) = 3. * (-rhs[8] + rhs[9]) - 2. * rhs[12] - rhs[13]; coeff(1 + i, 1 + j, 8) = 2. * (rhs[8] - rhs[9]) + rhs[12] + rhs[13]; // a_02 ... a_32 coeff(1 + i, 1 + j, 7) = 3. * (-rhs[0] + rhs[2]) - 2. * rhs[8] - rhs[10]; coeff(1 + i, 1 + j, 6) = 3. * (-rhs[4] + rhs[6]) - 2. * rhs[12] - rhs[14]; coeff(1 + i, 1 + j, 5) = 9. * (rhs[0] - rhs[1] - rhs[2] + rhs[3]) + 6. * (rhs[4] - rhs[6] + rhs[8] - rhs[9]) + 4. * rhs[12] + 3. * (rhs[5] - rhs[7] + rhs[10] - rhs[11]) + 2. * (rhs[13] + rhs[14]) + rhs[15]; coeff(1 + i, 1 + j, 4) = 6. * (-rhs[0] + rhs[1] + rhs[2] - rhs[3]) + 4. * (-rhs[8] + rhs[9]) + 3. * (-rhs[4] - rhs[5] + rhs[6] + rhs[7]) + 2. * (-rhs[10] + rhs[11] - rhs[12] - rhs[13]) - rhs[14] - rhs[15]; // a_03 ... a_33 coeff(1 + i, 1 + j, 3) = 2. * (rhs[0] - rhs[2]) + rhs[8] + rhs[10]; coeff(1 + i, 1 + j, 2) = 2. * (rhs[4] - rhs[6]) + rhs[12] + rhs[14]; coeff(1 + i, 1 + j, 1) = 6. * (-rhs[0] + rhs[1] + rhs[2] - rhs[3]) + 4. * (-rhs[4] + rhs[6]) + 3. * (-rhs[8] + rhs[9] - rhs[10] + rhs[11]) + 2. * (- rhs[5] + rhs[7] - rhs[12] - rhs[14]) - rhs[13] - rhs[15]; coeff(1 + i, 1 + j, 0) = 4. * (rhs[0] - rhs[1] - rhs[2] + rhs[3]) + 2. * (rhs[4] + rhs[5] - rhs[6] - rhs[7] + rhs[8] - rhs[9] + rhs[10] - rhs[11]) + rhs[12] + rhs[13] + rhs[14] + rhs[15]; // coeff(1 + i, 1 + j, 17) contains integral of function over the // square in "unit square coordinates", i.e. neglecting bin widths // this is done to help speed up calculations of 2D integrals Double_t sum = 0.; for (Int_t k = 0; k < NCoeff; ++k) sum += coeff(1 + i, 1 + j, k) / Double_t((4 - (k % 4)) * (4 - (k / 4))); coeff(1 + i, 1 + j, NCoeff) = sum; } } } Double_t Lau2DCubicSpline::evaluate(Double_t x, Double_t y) const { // protect against NaN and out of range if (x <= xmin || x >= xmax || y <= ymin || y >= ymax || x != x || y != y) return 0.; // find the bin in question const Int_t binx = Int_t(Double_t(nBinsX) * (x - xmin) / (xmax - xmin)); const Int_t biny = Int_t(Double_t(nBinsY) * (y - ymin) / (ymax - ymin)); // get low edge of bin const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; // normalise to coordinates in unit sqare const Double_t hx = (x - xlo) / binSizeX; const Double_t hy = (y - ylo) / binSizeY; // monomials const Double_t hxton[4] = { hx * hx * hx, hx * hx, hx, 1. }; const Double_t hyton[4] = { hy * hy * hy, hy * hy, hy, 1. }; // sum up Double_t retVal = 0.; for (Int_t k = 0; k < NCoeff; ++k) retVal += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; return retVal; } Double_t Lau2DCubicSpline::analyticalIntegral() const { return evalXY(xmin,xmax,ymin,ymax); } Double_t Lau2DCubicSpline::analyticalIntegral(Double_t x1, Double_t x2, Double_t y1, Double_t y2) const { if(y1==y2) return evalX(x1, x2, y1); if(x1==x2) return evalY(x1, y1, y2); return evalXY(x1, x2, y1, y2); } Double_t Lau2DCubicSpline::evalX(Double_t x1, Double_t x2, Double_t y) const { // protect against NaN if (x1 != x1 || x2 != x2 || y != y) return 0.; // find the bin in question const Int_t biny = Int_t(Double_t(nBinsY) * (y - ymin) / (ymax - ymin)); // get low edge of bin const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; // normalise to coordinates in unit sqare const Double_t hy = (y - ylo) / binSizeY; // monomials const Double_t hyton[4] = { hy * hy * hy, hy * hy, hy, 1. }; // integral Double_t sum = 0.; for (Int_t binx = 0; binx < nBinsX; ++binx) { // get low/high edge of bin const Double_t xhi = Double_t(nBinsX - binx - 1) / Double_t(nBinsX) * xmin + Double_t(binx + 1) / Double_t(nBinsX) * xmax; if (xhi < x1) continue; const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; if (xlo > x2) break; // work out integration range const Double_t a = ((xlo > x1) ? 0. : (x1 - xlo)) / binSizeX; const Double_t b = ((xhi < x2) ? binSizeX : (x2 - xlo)) / binSizeX; // integrated monomials const Double_t hxton[4] = { 0.25 * (b * b * b * b - a * a * a * a), (b * b * b - a * a * a) / 3., 0.5 * (b * b - a * a), b - a }; Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } // move from unit square coordinates to user coordinates return sum * binSizeX; } Double_t Lau2DCubicSpline::evalY(Double_t x, Double_t y1, Double_t y2) const { // protect against NaN if (x != x || y1 != y1 || y2 != y2) return 0.; // find the bin in question const Int_t binx = Int_t(Double_t(nBinsX) * (x - xmin) / (xmax - xmin)); // get low edge of bin const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; // normalise to coordinates in unit sqare const Double_t hx = (x - xlo) / binSizeX; // monomials const Double_t hxton[4] = { hx * hx * hx, hx * hx, hx, 1. }; // integral Double_t sum = 0.; for (Int_t biny = 0; biny < nBinsY; ++biny) { // get low/high edge of bin const Double_t yhi = Double_t(nBinsY - biny - 1) / Double_t(nBinsY) * ymin + Double_t(biny + 1) / Double_t(nBinsY) * ymax; if (yhi < y1) continue; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; if (ylo > y2) break; // work out integration range const Double_t a = ((ylo > y1) ? 0. : (y1 - ylo)) / binSizeY; const Double_t b = ((yhi < y2) ? binSizeY : (y2 - ylo)) / binSizeY; // integrated monomials const Double_t hyton[4] = { 0.25 * (b * b * b * b - a * a * a * a), (b * b * b - a * a * a) / 3., 0.5 * (b * b - a * a), b - a }; Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } // move from unit square coordinates to user coordinates return sum * binSizeY; } Double_t Lau2DCubicSpline::evalXY( Double_t x1, Double_t x2, Double_t y1, Double_t y2) const { // protect against NaN if (x1 != x1 || x2 != x2 || y1 != y1 || y2 != y2) return 0.; // integral Double_t sum = 0.; for (Int_t biny = 0; biny < nBinsY; ++biny) { // get low/high edge of bin const Double_t yhi = Double_t(nBinsY - biny - 1) / Double_t(nBinsY) * ymin + Double_t(biny + 1) / Double_t(nBinsY) * ymax; if (yhi < y1) continue; const Double_t ylo = Double_t(nBinsY - biny) / Double_t(nBinsY) * ymin + Double_t(biny) / Double_t(nBinsY) * ymax; if (ylo > y2) break; // work out integration range const Double_t ay = ((ylo > y1) ? 0. : (y1 - ylo)) / binSizeY; const Double_t by = ((yhi < y2) ? binSizeY : (y2 - ylo)) / binSizeY; const Bool_t yFullyContained = std::abs(by - ay - 1.0) < 1e-15; // integrated monomials const Double_t hyton[4] = { 0.25 * (by * by * by * by - ay * ay * ay * ay), (by * by * by - ay * ay * ay) / 3., 0.5 * (by * by - ay * ay), by - ay }; for (Int_t binx = 0; binx < nBinsX; ++binx) { // get low/high edge of bin const Double_t xhi = Double_t(nBinsX - binx - 1) / Double_t(nBinsX) * xmin + Double_t(binx + 1) / Double_t(nBinsX) * xmax; if (xhi < x1) continue; const Double_t xlo = Double_t(nBinsX - binx) / Double_t(nBinsX) * xmin + Double_t(binx) / Double_t(nBinsX) * xmax; if (xlo > x2) break; // work out integration range const Double_t ax = ((xlo > x1) ? 0. : (x1 - xlo)) / binSizeX; const Double_t bx = ((xhi < x2) ? binSizeX : (x2 - xlo)) / binSizeX; const Bool_t xFullyContained = std::abs(bx - ax - 1.0) < 1e-15; if (xFullyContained && yFullyContained) { // for fully contained bins, we have cached the integral sum += coeff(binx, biny, NCoeff); continue; } // integrated monomials const Double_t hxton[4] = { 0.25 * (bx * bx * bx * bx - ax * ax * ax * ax), (bx * bx * bx - ax * ax * ax) / 3., 0.5 * (bx * bx - ax * ax), bx - ax }; // integrate over bin Double_t lsum = 0.; for (Int_t k = 0; k < NCoeff; ++k) lsum += coeff(binx, biny, k) * hxton[k % 4] * hyton[k / 4]; sum += lsum; } } // move from unit square coordinates to user coordinates return sum * binSizeX * binSizeY; } diff --git a/src/Lau2DHistDP.cc b/src/Lau2DHistDP.cc index 7d1ef4a..1148164 100644 --- a/src/Lau2DHistDP.cc +++ b/src/Lau2DHistDP.cc @@ -1,360 +1,359 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDP.cc \brief File containing implementation of Lau2DHistDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DHistDP.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DHistDP) Lau2DHistDP::Lau2DHistDP(const TH2* hist, const LauDaughters* daughters, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), errorHi_(0), errorLo_(0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), nBinsX_(0), nBinsY_(0), useInterpolation_(useInterpolation) { if ( ! hist_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Save various attributes of the histogram // (axis ranges, number of bins, areas) TAxis* xAxis = hist_->GetXaxis(); minX_ = static_cast(xAxis->GetXmin()); maxX_ = static_cast(xAxis->GetXmax()); rangeX_ = maxX_ - minX_; TAxis* yAxis = hist_->GetYaxis(); minY_ = static_cast(yAxis->GetXmin()); maxY_ = static_cast(yAxis->GetXmax()); rangeY_ = maxY_ - minY_; nBinsX_ = static_cast(hist_->GetNbinsX()); nBinsY_ = static_cast(hist_->GetNbinsY()); binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if (fluctuateBins) { this->doBinFluctuation(hist_); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(hist_,avEff,avEffError); } } Lau2DHistDP::Lau2DHistDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), errorHi_(errorHi ? dynamic_cast(errorHi->Clone()) : 0), errorLo_(errorLo ? dynamic_cast(errorLo->Clone()) : 0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), nBinsX_(0), nBinsY_(0), useInterpolation_(useInterpolation) { if ( ! hist_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! errorHi_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! errorLo_ ) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Save various attributes of the histogram // (axis ranges, number of bins, areas) TAxis* xAxis = hist_->GetXaxis(); minX_ = static_cast(xAxis->GetXmin()); maxX_ = static_cast(xAxis->GetXmax()); rangeX_ = maxX_ - minX_; TAxis* yAxis = hist_->GetYaxis(); minY_ = static_cast(yAxis->GetXmin()); maxY_ = static_cast(yAxis->GetXmax()); rangeY_ = maxY_ - minY_; nBinsX_ = static_cast(hist_->GetNbinsX()); nBinsY_ = static_cast(hist_->GetNbinsY()); binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if(static_cast(errorLo_->GetNbinsX()) != nBinsX_ || static_cast(errorLo_->GetNbinsY()) != nBinsY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(errorHi_->GetNbinsX()) != nBinsX_ || static_cast(errorHi_->GetNbinsY()) != nBinsY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = errorLo_->GetXaxis(); yAxis = errorLo_->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX_ || static_cast(xAxis->GetXmax()) != maxX_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY_ || static_cast(yAxis->GetXmax()) != maxY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = errorHi_->GetXaxis(); yAxis = errorHi_->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX_ || static_cast(xAxis->GetXmax()) != maxX_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY_ || static_cast(yAxis->GetXmax()) != maxY_) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(hist_,errorHi_,errorLo_); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(hist_,avEff,avEffError); } } Lau2DHistDP::~Lau2DHistDP() { delete hist_; hist_ = 0; if(errorHi_) { delete errorHi_; errorHi_=0; } if(errorLo_) { delete errorLo_; errorLo_=0; } } Double_t Lau2DHistDP::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const { if (xBinNo < 0) { xBinNo = 0; } else if (xBinNo >= nBinsX_) { return 0.0; } if (yBinNo < 0) { yBinNo = 0; } else if (yBinNo >= nBinsY_) { return 0.0; } Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1); return value; } Double_t Lau2DHistDP::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP this->getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (this->withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DHistDP::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } // Find the 2D histogram bin for x and y Int_t i = Int_t((x - minX_)*nBinsX_/rangeX_); Int_t j = Int_t((y - minY_)*nBinsY_/rangeY_); if (i >= nBinsX_) {i = nBinsX_ - 1;} if (j >= nBinsY_) {j = nBinsY_ - 1;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) {return this->getBinHistValue(i,j);} // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = Double_t(i+0.5)*rangeX_/nBinsX_ + minX_; Double_t cbiny = Double_t(j+0.5)*rangeY_/nBinsY_ + minY_; // If bin centres are outside kinematic region, do not extrapolate if (this->withinDPBoundaries(cbinx,cbiny) == kFALSE) {return this->getBinHistValue(i,j);} // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;} if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = Double_t(i_adj+0.5)*rangeX_/nBinsX_ + minX_; if (this->withinDPBoundaries(cbinx_adj, y) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = Double_t(j_adj+0.5)*rangeY_/nBinsY_ + minY_; if (this->withinDPBoundaries(x, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = Double_t(i_adj+0.5)*rangeX_/nBinsX_ + minX_; Double_t cbiny_adj = Double_t(j_adj+0.5)*rangeY_/nBinsY_ + minY_; if (this->withinDPBoundaries(cbinx_adj, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } } return value; } diff --git a/src/Lau2DHistDPPdf.cc b/src/Lau2DHistDPPdf.cc index f46a51f..1fd4c8a 100644 --- a/src/Lau2DHistDPPdf.cc +++ b/src/Lau2DHistDPPdf.cc @@ -1,371 +1,370 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistDPPdf.cc \brief File containing implementation of Lau2DHistDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "Lau2DHistDPPdf.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(Lau2DHistDPPdf) Lau2DHistDPPdf::Lau2DHistDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDPPdf(kinematics,vetoes,useUpperHalfOnly,squareDP), hist_(hist ? dynamic_cast(hist->Clone()) : 0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), invBinXWidth_(0.0), invBinYWidth_(0.0), nBinsX_(0), nBinsY_(0), norm_(0.0), useInterpolation_(useInterpolation) { // For square Dalitz plots, the co-ordinates must be m', theta' // The input data to the fit is still in m13^2, m23^2 co-ords, and a // transformation is applied to go from one co-ordinate system to the // other. // Save various attributes of the histogram // (axis ranges, number of bins, areas) if ( hist_ ) { TAxis* xAxis = hist_->GetXaxis(); minX_ = xAxis->GetXmin(); maxX_ = xAxis->GetXmax(); TAxis* yAxis = hist_->GetYaxis(); minY_ = yAxis->GetXmin(); maxY_ = yAxis->GetXmax(); nBinsX_ = hist_->GetNbinsX(); nBinsY_ = hist_->GetNbinsY(); } else { minX_ = getKinematics()->getm13SqMin(); maxX_ = getKinematics()->getm13SqMax(); minY_ = getKinematics()->getm23SqMin(); maxY_ = getKinematics()->getm23SqMax(); nBinsX_ = 1; nBinsY_ = 1; } rangeX_ = maxX_ - minX_; rangeY_ = maxY_ - minY_; if (nBinsX_ > 0) { binXWidth_ = TMath::Abs(rangeX_)/(nBinsX_*1.0); } if (nBinsY_ > 0) { binYWidth_ = TMath::Abs(rangeY_)/(nBinsY_*1.0); } if (binXWidth_ > 1e-10) { invBinXWidth_ = 1.0/binXWidth_; } if (binYWidth_ > 1e-10) { invBinYWidth_ = 1.0/binYWidth_; } // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(hist_); } // Calculate the PDF normalisation. this->calcHistNorm(); // And check it is OK. this->checkNormalisation(); // Also obtain the maximum height this->calcMaxHeight(hist_); } Lau2DHistDPPdf::~Lau2DHistDPPdf() { // Destructor delete hist_; hist_ = 0; } void Lau2DHistDPPdf::calcHistNorm() { // Calculate the histogram normalisation. We must integrate // over the allowed kinematic DP region. // Loop over the total x and y range to get the total area // under x and y. Just sum the contributions up using 1e-3 increments // of the range in x and y. Multiply the end result by dx and dy. const Double_t axisMin = TMath::Min( minX_, minY_ ); const Double_t axisMax = TMath::Max( maxX_, maxY_ ); const Double_t axisRange = axisMax - axisMin; const Double_t dx(1e-3 * axisRange); const Double_t dy(dx); Double_t area(0.0); Double_t x(axisMin + dx/2.0); while (x < axisMax) { Double_t y(axisMin + dy/2.0); while (y < axisMax) { area += this->interpolateXY(x,y); y += dy; } // y while loop x += dx; } // x while loop norm_ = area*dx*dy; std::cout << "INFO in Lau2DHistDPPdf::calcHistNorm : Norm = " << norm_ << ", bX*bY = " << binXWidth_ << "*" << binYWidth_ << " = " << binXWidth_*binYWidth_ << std::endl; } Double_t Lau2DHistDPPdf::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const { if (xBinNo < 0) { xBinNo = 0; } else if (xBinNo >= nBinsX_) { return 0.0; } if (yBinNo < 0) { yBinNo = 0; } else if (yBinNo >= nBinsY_) { return 0.0; } if ( hist_ == 0 ) { return 1.0; } Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1); return value; } Double_t Lau2DHistDPPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); return value/norm_; } Double_t Lau2DHistDPPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (withinDPBoundaries(x,y) == kFALSE) {return 0.0;} // Update the kinematics to the position of interest. updateKinematics(x,y); // Check that we're not inside a veto Bool_t vetoOK(kTRUE); if (getVetoes()) { vetoOK = getVetoes()->passVeto(getKinematics()); } if (vetoOK == kFALSE) {return 0.0;} // Find the 2D histogram bin for x and y Int_t i = TMath::FloorNint((x - minX_)*invBinXWidth_); Int_t j = TMath::FloorNint((y - minY_)*invBinYWidth_); if (i >= nBinsX_) {i = nBinsX_ - 1;} if (j >= nBinsY_) {j = nBinsY_ - 1;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(i,j); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = (i+0.5)*binXWidth_ + minX_; Double_t cbiny = (j+0.5)*binYWidth_ + minY_; // If bin centres are outside kinematic region, do not extrapolate if (withinDPBoundaries(cbinx, cbiny) == kFALSE) { return this->getBinHistValue(i,j); } // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;} if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_; if (withinDPBoundaries(cbinx_adj, y) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_; if (withinDPBoundaries(x, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_; Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_; if (withinDPBoundaries(cbinx_adj, cbiny_adj) == kFALSE) { // The adjacent bin is outside the DP range. Don't extrapolate. value = this->getBinHistValue(i,j); } else { Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } } return value; } void Lau2DHistDPPdf::checkNormalisation() { // Loop over the total x and y range to get the total area // under x and y. Just sum the contributions up using 1e-3 increments // of the range in x and y. Multiply the end result by dx and dy. const Double_t axisMin = TMath::Min( minX_, minY_ ); const Double_t axisMax = TMath::Max( maxX_, maxY_ ); const Double_t axisRange = axisMax - axisMin; const Double_t dx(1e-3 * axisRange); const Double_t dy(dx); Double_t area(0.0); Double_t areaNoNorm(0.0); // Preserve the value of a variable we change temporarily Bool_t interpolate = useInterpolation_; Double_t x(axisMin + dx/2.0); while (x < axisMax) { Double_t y(axisMin + dy/2.0); while (y < axisMax) { area += this->interpolateXYNorm(x,y); useInterpolation_ = kFALSE; areaNoNorm += this->interpolateXY(x,y); useInterpolation_ = kTRUE; y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; useInterpolation_ = interpolate; //Restore old value std::cout << "INFO in Lau2DHistDPPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } diff --git a/src/Lau2DHistPdf.cc b/src/Lau2DHistPdf.cc index 9bc41bc..b7c52d3 100644 --- a/src/Lau2DHistPdf.cc +++ b/src/Lau2DHistPdf.cc @@ -1,486 +1,485 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DHistPdf.cc \brief File containing implementation of Lau2DHistPdf class. */ #include #include #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "Lau2DHistPdf.hh" #include "LauRandom.hh" class LauParameter; -ClassImp(Lau2DHistPdf) Lau2DHistPdf::Lau2DHistPdf(const std::vector& theVarNames, const TH2* hist, const LauFitData& minVals, const LauFitData& maxVals, Bool_t useInterpolation, Bool_t fluctuateBins) : LauAbsPdf(theVarNames, std::vector(), minVals, maxVals), hist_(hist ? dynamic_cast(hist->Clone()) : 0), xProj_(0), yProj_(0), xVarPdf_(0), yVarPdf_(0), xName_(""), yName_(""), nBinsX_(0), nBinsY_(0), minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0), binXWidth_(0.0), binYWidth_(0.0), invBinXWidth_(0.0), invBinYWidth_(0.0), useInterpolation_(useInterpolation), fluctuateBins_(fluctuateBins) { // Constructor // Check that we have two variables if ( this->nInputVars() != 2 ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Have not been provided with exactly two variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Set the variable names from the abstract class xName_ = this->varNames()[0]; yName_ = this->varNames()[1]; // Set the variable limits from the abstract class minX_ = this->getMinAbscissa(xName_); maxX_ = this->getMaxAbscissa(xName_); minY_ = this->getMinAbscissa(yName_); maxY_ = this->getMaxAbscissa(yName_); rangeX_ = maxX_ - minX_; rangeY_ = maxY_ - minY_; // Have we got a valid histogram if ( hist_ == 0 ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Set the directory for the histogram hist_->SetDirectory(0); // Save various attributes of the histogram nBinsX_ = hist_->GetNbinsX(); nBinsY_ = hist_->GetNbinsY(); TAxis* xAxis = hist_->GetXaxis(); Double_t xAxisMin = xAxis->GetXmin(); Double_t xAxisMax = xAxis->GetXmax(); TAxis* yAxis = hist_->GetYaxis(); Double_t yAxisMin = yAxis->GetXmin(); Double_t yAxisMax = yAxis->GetXmax(); // Check that axis ranges corresponds to ranges of abscissas if (TMath::Abs(minX_ - xAxisMin)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram x-axis minimum: " << xAxisMin << " does not correspond to " << xName_ << " minimum: " << minX_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(maxX_ - xAxisMax)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram x-axis maximum: " << xAxisMax << " does not correspond to " << xName_ << " maximum: " << maxX_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(minY_ - yAxisMin)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram y-axis minimum: " << yAxisMin << " does not correspond to " << yName_ << " minimum: " << minY_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (TMath::Abs(maxY_ - yAxisMax)>1e-6) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Histogram y-axis maximum: " << yAxisMax << " does not correspond to " << yName_ << " maximum: " << maxY_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Calculate the bin widths and inverse bin widths binXWidth_ = static_cast(TMath::Abs(rangeX_)/(nBinsX_*1.0)); binYWidth_ = static_cast(TMath::Abs(rangeY_)/(nBinsY_*1.0)); if (binXWidth_ > 1e-10) {invBinXWidth_ = 1.0/binXWidth_;} if (binYWidth_ > 1e-10) {invBinYWidth_ = 1.0/binYWidth_;} // If the bins are to be fluctuated then do so now before // calculating anything that depends on the bin content. if (fluctuateBins) { this->doBinFluctuation(); } // Create the projections and 1D PDFs from those xProj_ = hist_->ProjectionX(); yProj_ = hist_->ProjectionY(); if ( !xProj_ || !yProj_ ) { std::cerr << "ERROR in Lau2DHistPdf::Lau2DHistPdf : Can't get X or Y projection from 2D histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xVarPdf_ = new Lau1DHistPdf(xName_, xProj_, minX_, maxX_, useInterpolation_, fluctuateBins_); yVarPdf_ = new Lau1DHistPdf(yName_, yProj_, minY_, maxY_, useInterpolation_, fluctuateBins_); // Calculate the PDF normalisation. this->calcNorm(); // And check it is OK. this->checkNormalisation(); } Lau2DHistPdf::~Lau2DHistPdf() { // Destructor delete hist_; hist_ = 0; delete xProj_; xProj_ = 0; delete yProj_; yProj_ = 0; delete xVarPdf_; xVarPdf_ = 0; delete yVarPdf_; yVarPdf_ = 0; } void Lau2DHistPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the maximum height of the histogram Int_t maxBin = hist_->GetMaximumBin(); Double_t height = hist_->GetBinContent(maxBin); this->setMaxHeight(height); } void Lau2DHistPdf::calcNorm() { // Calculate the histogram normalisation. // Loop over the total x and y range to get the total area under x // and y. Just sum the contributions up using 1e-3 increments of // the range in x and y. Multiply the end result by dx and dy. Double_t dx(1e-3*rangeX_), dy(1e-3*rangeY_); Double_t area(0.0); Double_t x(minX_ + dx/2.0); while (x > minX_ && x < maxX_) { Double_t y(minY_ + dy/2.0); while (y > minY_ && y < maxY_) { area += this->interpolateXY(x,y); y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; this->setNorm(norm); } void Lau2DHistPdf::checkNormalisation() { Double_t dx(1e-3*rangeX_), dy(1e-3*rangeY_); Double_t area(0.0); Double_t areaNoNorm(0.0); // Preserve the value of a variable we change temporarily Bool_t interpolate = useInterpolation_; Double_t x(minX_ + dx/2.0); while (x > minX_ && x < maxX_) { Double_t y(minY_ + dy/2.0); while (y > minY_ && y < maxY_) { area += this->interpolateXYNorm(x,y); useInterpolation_ = kFALSE; areaNoNorm += this->interpolateXY(x,y); useInterpolation_ = kTRUE; y += dy; } // y while loop x += dx; } // x while loop Double_t norm = area*dx*dy; useInterpolation_ = interpolate; //Restore old value std::cout << "INFO in Lau2DHistPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl; std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl; std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl; } Double_t Lau2DHistPdf::getBinHistValue(Int_t i, Int_t j) const { // Check that x co-ord is in range [1 , nBinsX_] if ((i < 1) || (i > nBinsX_)) { return 0.0; } // Check that y co-ord is in range [1 , nBinsY_] if ((j < 1) || (j > nBinsY_)) { return 0.0; } Double_t value = hist_->GetBinContent(i,j); // protect against negative values if ( value < 0.0 ) { std::cerr << "WARNING in Lau2DHistPdf::getBinHistValue : Negative bin content set to zero!" << std::endl; value = 0.0; } return value; } Double_t Lau2DHistPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); Double_t norm = this->getNorm(); return value/norm; } Double_t Lau2DHistPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram // function for the given values of x and y by finding the adjacent // bins and extrapolating using weights based on the inverse // distance of the point from the adajcent bin centres. // Find the 2D histogram bin for x and y Int_t i = static_cast((x - minX_)*invBinXWidth_)+1; Int_t j = static_cast((y - minY_)*invBinYWidth_)+1; if (i > nBinsX_) {i = nBinsX_;} if (j > nBinsY_) {j = nBinsY_;} // Ask whether we want to do the interpolation, since this method is // not reliable for low statistics histograms. if (useInterpolation_ == kFALSE) { return this->getBinHistValue(i,j); } // Find the bin centres (actual co-ordinate positions, not histogram indices) Double_t cbinx = static_cast(i-0.5)*binXWidth_ + minX_; Double_t cbiny = static_cast(j-0.5)*binYWidth_ + minY_; // Find the adjacent bins Double_t deltax = x - cbinx; Double_t deltay = y - cbiny; Int_t i_adj(0), j_adj(0); if (deltax > 0.0) { i_adj = i + 1; } else { i_adj = i - 1; } if (deltay > 0.0) { j_adj = j + 1; } else { j_adj = j - 1; } Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE); Double_t value(0.0); if (i_adj > nBinsX_ || i_adj < 1) {isYBoundary = kTRUE;} if (j_adj > nBinsY_ || j_adj < 1) {isXBoundary = kTRUE;} // In the corners, do no interpolation. Use entry in bin (i,j) if (isXBoundary == kTRUE && isYBoundary == kTRUE) { value = this->getBinHistValue(i,j); } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) { // Find the adjacent x bin centre Double_t cbinx_adj = static_cast(i_adj-0.5)*binXWidth_ + minX_; Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t inter_denom = dx0 + dx1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); value = (value1*dx1 + value2*dx0)/inter_denom; } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) { // Find the adjacent y bin centre Double_t cbiny_adj = static_cast(j_adj-0.5)*binYWidth_ + minY_; Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = dy0 + dy1; Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i,j_adj); value = (value1*dy1 + value2*dy0)/inter_denom; } else { // 2D linear interpolation using inverse distance as weights. // Find the adjacent x and y bin centres Double_t cbinx_adj = static_cast(i_adj-0.5)*binXWidth_ + minX_; Double_t cbiny_adj = static_cast(j_adj-0.5)*binYWidth_ + minY_; Double_t dx0 = TMath::Abs(x - cbinx); Double_t dx1 = TMath::Abs(cbinx_adj - x); Double_t dy0 = TMath::Abs(y - cbiny); Double_t dy1 = TMath::Abs(cbiny_adj - y); Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1); Double_t value1 = this->getBinHistValue(i,j); Double_t value2 = this->getBinHistValue(i_adj,j); Double_t value3 = this->getBinHistValue(i,j_adj); Double_t value4 = this->getBinHistValue(i_adj,j_adj); value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0; value /= inter_denom; } return value; } void Lau2DHistPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Calculate the interpolated value Double_t x = abscissas[0]; Double_t y = abscissas[1]; Double_t value = this->interpolateXY(x,y); this->setUnNormPDFVal(value); // TODO - do we need this? I think probably not. // Have the 1D PDFs calculate their likelihoods as well //xVarPdf_->calcLikelihoodInfo(x); //yVarPdf_->calcLikelihoodInfo(y); } void Lau2DHistPdf::calcLikelihoodInfo(UInt_t iEvt) { // Call the base class method this->LauAbsPdf::calcLikelihoodInfo(iEvt); // Have the 1D PDFs retrieve their values as well xVarPdf_->calcLikelihoodInfo(iEvt); yVarPdf_->calcLikelihoodInfo(iEvt); } Double_t Lau2DHistPdf::getLikelihood( const TString& theVarName ) const { if ( theVarName == xName_ ) { return xVarPdf_->getLikelihood(); } else if ( theVarName == yName_ ) { return yVarPdf_->getLikelihood(); } else { std::cerr << "ERROR in Lau2DHistPdf::getLikelihood : Unrecognised variable name \"" << theVarName << "\", cannot determine likelihood." << std::endl; return 0.0; } } void Lau2DHistPdf::cacheInfo(const LauFitDataTree& inputData) { // Call the base class method this->LauAbsPdf::cacheInfo(inputData); // Have the 1D PDFs cache their info as well xVarPdf_->cacheInfo(inputData); yVarPdf_->cacheInfo(inputData); } void Lau2DHistPdf::doBinFluctuation() { TRandom* random(LauRandom::randomFun()); for (Int_t i(0); iGetBinContent(i+1,j+1); Double_t currentError = hist_->GetBinError(i+1,j+1); Double_t newContent = random->Gaus(currentContent,currentError); if (newContent<0.0) { hist_->SetBinContent(i+1,j+1,0.0); } else { hist_->SetBinContent(i+1,j+1,newContent); } } } } LauFitData Lau2DHistPdf::generate(const LauKinematics* kinematics) { this->withinGeneration(kTRUE); // Check that the PDF height is up to date this->calcPDFHeight( kinematics ); // Generate the value of the abscissa. Bool_t gotAbscissa(kFALSE); if (this->getRandomFun() == 0) { std::cerr << "ERROR in Lau2DHistPdf::generate : Please set the random number generator for this PDF by using the setRandomFun(TRandom*) function." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } Double_t genPDFVal(0.0); LauAbscissas genAbscissas(2); Double_t PDFheight = this->getMaxHeight()*(1.0+1e-11); while (!gotAbscissa) { genAbscissas[0] = this->getRandomFun()->Rndm()*this->getRange(xName_) + this->getMinAbscissa(xName_); genAbscissas[1] = this->getRandomFun()->Rndm()*this->getRange(yName_) + this->getMinAbscissa(yName_); this->calcLikelihoodInfo(genAbscissas); genPDFVal = this->getUnNormLikelihood(); if (this->getRandomFun()->Rndm() <= genPDFVal/PDFheight) {gotAbscissa = kTRUE;} if (genPDFVal > PDFheight) { std::cerr << "WARNING in LauAbsPdf::generate : genPDFVal = " << genPDFVal << " is larger than the specified PDF height " << this->getMaxHeight() << " for (x,y) = (" << genAbscissas[0] << "," << genAbscissas[1] << ")." << std::endl; std::cerr << " : Need to reset height to be larger than " << genPDFVal << " by using the setMaxHeight(Double_t) function and re-run the Monte Carlo generation!" << std::endl; } } LauFitData genData; genData[ xName_ ] = genAbscissas[0]; genData[ yName_ ] = genAbscissas[1]; this->withinGeneration(kFALSE); return genData; } diff --git a/src/Lau2DSplineDP.cc b/src/Lau2DSplineDP.cc index dc609d9..a21edd5 100644 --- a/src/Lau2DSplineDP.cc +++ b/src/Lau2DSplineDP.cc @@ -1,189 +1,188 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDP.cc \brief File containing implementation of Lau2DSplineDP class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DSplineDP.hh" #include "Lau2DCubicSpline.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DSplineDP) Lau2DSplineDP::Lau2DSplineDP(const TH2* hist, const LauDaughters* daughters, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(tempHist,avEff,avEffError); } spline_ = new Lau2DCubicSpline(*tempHist); delete tempHist; } Lau2DSplineDP::Lau2DSplineDP(const TH2* hist, const TH2* errorHi, const TH2* errorLo, const LauDaughters* daughters, Bool_t fluctuateBins, Double_t avEff, Double_t avEffError, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDP(daughters,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); TH2* tempErrorHi(errorHi ? dynamic_cast(errorHi->Clone()) : 0); TH2* tempErrorLo(errorLo ? dynamic_cast(errorLo->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDP constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! tempErrorHi ) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! tempErrorLo ) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } TAxis* xAxis = tempHist->GetXaxis(); Double_t minX = static_cast(xAxis->GetXmin()); Double_t maxX = static_cast(xAxis->GetXmax()); TAxis* yAxis = tempHist->GetYaxis(); Double_t minY = static_cast(yAxis->GetXmin()); Double_t maxY = static_cast(yAxis->GetXmax()); Int_t nBinsX = static_cast(tempHist->GetNbinsX()); Int_t nBinsY = static_cast(tempHist->GetNbinsY()); if(static_cast(tempErrorLo->GetNbinsX()) != nBinsX || static_cast(tempErrorLo->GetNbinsY()) != nBinsY) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(tempErrorHi->GetNbinsX()) != nBinsX || static_cast(tempErrorHi->GetNbinsY()) != nBinsY) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different number of bins to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = tempErrorLo->GetXaxis(); yAxis = tempErrorLo->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX || static_cast(xAxis->GetXmax()) != maxX) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY || static_cast(yAxis->GetXmax()) != maxY) { std::cerr << "ERROR in Lau2DHistDP constructor : the lower error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } xAxis = tempErrorHi->GetXaxis(); yAxis = tempErrorHi->GetYaxis(); if(static_cast(xAxis->GetXmin()) != minX || static_cast(xAxis->GetXmax()) != maxX) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different x range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if(static_cast(yAxis->GetXmin()) != minY || static_cast(yAxis->GetXmax()) != maxY) { std::cerr << "ERROR in Lau2DHistDP constructor : the upper error histogram has a different y range to the main histogram." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist,tempErrorHi,tempErrorLo); } if (avEff > 0.0 && avEffError > 0.0) { this->raiseOrLowerBins(tempHist,avEff,avEffError); } spline_ = new Lau2DCubicSpline(*tempHist); delete tempHist; delete tempErrorHi; delete tempErrorLo; } Lau2DSplineDP::~Lau2DSplineDP() { delete spline_; spline_ = 0; } Double_t Lau2DSplineDP::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP this->getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (this->withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DSplineDP::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } return spline_->evaluate(x,y); } diff --git a/src/Lau2DSplineDPPdf.cc b/src/Lau2DSplineDPPdf.cc index 15259ea..86327b9 100644 --- a/src/Lau2DSplineDPPdf.cc +++ b/src/Lau2DSplineDPPdf.cc @@ -1,112 +1,111 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file Lau2DSplineDPPdf.cc \brief File containing implementation of Lau2DSplineDPPdf class. */ #include #include "TAxis.h" #include "TH2.h" #include "TRandom.h" #include "TSystem.h" #include "Lau2DSplineDPPdf.hh" #include "Lau2DCubicSpline.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(Lau2DSplineDPPdf) Lau2DSplineDPPdf::Lau2DSplineDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) : Lau2DAbsHistDPPdf(kinematics,vetoes,useUpperHalfOnly,squareDP), spline_(0) { //We may need to modify the histogram so clone it TH2* tempHist(hist ? dynamic_cast(hist->Clone()) : 0); if ( ! tempHist ) { std::cerr << "ERROR in Lau2DSplineDPPdf constructor : the histogram pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (fluctuateBins) { this->doBinFluctuation(tempHist); } spline_ = new Lau2DCubicSpline(*tempHist); // Calculate the PDF normalisation. this->calcHistNorm(); // Also obtain the maximum height this->calcMaxHeight(tempHist); delete tempHist; } Lau2DSplineDPPdf::~Lau2DSplineDPPdf() { delete spline_; spline_ = 0; } Double_t Lau2DSplineDPPdf::interpolateXYNorm(Double_t x, Double_t y) const { // Get the normalised interpolated value. Double_t value = this->interpolateXY(x,y); return value/norm_; } Double_t Lau2DSplineDPPdf::interpolateXY(Double_t x, Double_t y) const { // This function returns the interpolated value of the histogram function // for the given values of x and y by finding the adjacent bins and extrapolating // using weights based on the inverse distance of the point from the adajcent // bin centres. // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates // If we're only using one half then flip co-ordinates // appropriately for conventional or square DP getUpperHalf(x,y); // First ask whether the point is inside the kinematic region. if (withinDPBoundaries(x,y) == kFALSE) { std::cerr << "WARNING in Lau2DSplineDPPdf::interpolateXY : Given position is outside the DP boundary, returning 0.0." << std::endl; return 0.0; } return spline_->evaluate(x,y); } void Lau2DSplineDPPdf::calcHistNorm() { norm_ = spline_->analyticalIntegral(); } diff --git a/src/LauASqMaxFinder.cc b/src/LauASqMaxFinder.cc index 3866067..eb5a2f0 100644 --- a/src/LauASqMaxFinder.cc +++ b/src/LauASqMaxFinder.cc @@ -1,172 +1,171 @@ /* Copyright 2022 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauASqMaxFinder.cc \brief File containing implementation of LauASqMaxFinder class. */ #include "LauASqMaxFinder.hh" #include "LauAbsResonance.hh" #include "LauFitter.hh" #include "LauIsobarDynamics.hh" #include "LauKinematics.hh" #include "LauParameter.hh" #include "TSystem.h" #include #include #include -ClassImp( LauASqMaxFinder ) LauASqMaxFinder::LauASqMaxFinder(LauIsobarDynamics& iso) : iso_{iso} { const LauKinematics* kinematics { iso_.getKinematics() }; const Double_t m13SqMin{kinematics->getm13SqMin()}; const Double_t m13SqMax{kinematics->getm13SqMax()}; const Double_t m23SqMin{kinematics->getm23SqMin()}; const Double_t m23SqMax{kinematics->getm23SqMax()}; ownedParams_.resize(2); ownedParams_[0] = std::make_unique("m13Sq", 0.5*(m13SqMin+m13SqMax), m13SqMin, m13SqMax, kFALSE ); ownedParams_[1] = std::make_unique("m23Sq", 0.5*(m23SqMin+m23SqMax), m23SqMin, m23SqMax, kFALSE ); params_.resize(2); params_[0] = ownedParams_[0].get(); params_[1] = ownedParams_[1].get(); } void LauASqMaxFinder::setParsFromMinuit(Double_t* par, Int_t npar) { if ( static_cast(npar) != params_.size() ) { std::cerr << "ERROR in LauASqMaxFinder::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << params_.size() << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } for ( Int_t i{0}; i < npar; ++i ) { params_[i]->value( par[i] ); } return; } Double_t LauASqMaxFinder::getTotNegLogLikelihood() { const Double_t m13Sq { params_[0]->unblindValue() }; const Double_t m23Sq { params_[1]->unblindValue() }; if ( ! iso_.getKinematics()->withinDPLimits(m13Sq, m23Sq) ) { if ( printMinimisationWarnings_ ) { std::cerr << "WARNING in LauASqMaxFinder::getTotNegLogLikelihood : Fit has wandered outside the phase space boundary\n"; std::cerr << " : Returning 0.0 value (further warnings of this type will be suppressed)" << std::endl; printMinimisationWarnings_ = kFALSE; } return 0.0; } iso_.calcLikelihoodInfo( m13Sq, m23Sq ); return -iso_.getEvtIntensity(); } Double_t LauASqMaxFinder::find() { Double_t ASqMax{-1.0}; const LauKinematics* kinematics { iso_.getKinematics() }; LauKinematics localKin { kinematics->getm1(), kinematics->getm2(), kinematics->getm3(), kinematics->getmParent() }; const Double_t m13SqMin { localKin.getm13Min() }; const Double_t m13SqMax { localKin.getm13Max() }; const Double_t m23SqMin { localKin.getm23Min() }; const Double_t m23SqMax { localKin.getm23Max() }; LauFitter::setFitterMaxPars( 2 ); LauFitter::setFitterVerbosity( LauOutputLevel::None ); for ( UInt_t iRes{0}; iRes < iso_.getnTotAmp(); ++iRes ) { // Find the center of the resonance and set that as the start of the search const LauAbsResonance* res { const_cast(iso_).getResonance(iRes) }; const Int_t bachelor { res->getPairInt() }; const Double_t mass { res->getMass() }; const Double_t width { res->getWidth() }; const std::array massVals { mass - width, mass, mass + width }; const std::array cosHelVals { -1.0, 0.0, 1.0 }; for ( Double_t massVal : massVals ) { for ( Double_t cosHel : cosHelVals ) { switch ( bachelor ) { case 0 : localKin.updateKinematics( 0.5*(m13SqMax+m13SqMin), 0.5*(m23SqMax+m23SqMin) ); break; case 1 : localKin.updateKinematicsFrom23( massVal, cosHel ); break; case 2 : localKin.updateKinematicsFrom13( massVal, cosHel ); break; case 3 : localKin.updateKinematicsFrom12( massVal, cosHel ); break; default : break; } params_[0]->initValue( localKin.getm13Sq() ); params_[1]->initValue( localKin.getm23Sq() ); params_[0]->error(0.1); params_[1]->error(0.1); LauFitter::fitter().initialise( this, params_ ); const LauAbsFitter::FitStatus fitResult { LauFitter::fitter().minimise() }; if ( fitResult.status != 0 and -fitResult.NLL > ASqMax ) { ASqMax = -fitResult.NLL; } } } } LauFitter::destroyFitter(); if ( ASqMax < 0.0 ) { std::cerr << "WARNING in LauASqMaxFinder::find : Could not find ASqMax\n"; std::cerr << " : Returning -1.0" << std::endl; } return ASqMax; } diff --git a/src/LauAbsBkgndDPModel.cc b/src/LauAbsBkgndDPModel.cc index 9ed44f7..86f56d1 100644 --- a/src/LauAbsBkgndDPModel.cc +++ b/src/LauAbsBkgndDPModel.cc @@ -1,41 +1,40 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsBkgndDPModel.cc \brief File containing implementation of LauAbsBkgndDPModel class. */ #include "LauAbsBkgndDPModel.hh" #include "LauDaughters.hh" -ClassImp(LauAbsBkgndDPModel) LauAbsBkgndDPModel::LauAbsBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes) : daughters_(daughters), kinematics_(daughters ? daughters->getKinematics() : 0), vetoes_(vetoes) { } diff --git a/src/LauAbsCoeffSet.cc b/src/LauAbsCoeffSet.cc index 66110b3..3a86174 100644 --- a/src/LauAbsCoeffSet.cc +++ b/src/LauAbsCoeffSet.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsCoeffSet.cc \brief File containing implementation of LauAbsCoeffSet class. */ #include #include "TString.h" #include "LauAbsCoeffSet.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauAbsCoeffSet); TRandom* LauAbsCoeffSet::randomiser_ = 0; Double_t LauAbsCoeffSet::minMagnitude_ = -10.0; Double_t LauAbsCoeffSet::maxMagnitude_ = 10.0; Double_t LauAbsCoeffSet::minPhase_ = -LauConstants::threePi; Double_t LauAbsCoeffSet::maxPhase_ = LauConstants::threePi; Double_t LauAbsCoeffSet::minRealImagPart_ = -10.0; Double_t LauAbsCoeffSet::maxRealImagPart_ = 10.0; Double_t LauAbsCoeffSet::minDelta_ = -2.0; Double_t LauAbsCoeffSet::maxDelta_ = 2.0; LauAbsCoeffSet::LauAbsCoeffSet(const TString& theName, const TString& theBaseName) : name_(theName), basename_(theBaseName), index_(0) { } LauAbsCoeffSet::LauAbsCoeffSet(const LauAbsCoeffSet& rhs) : name_(rhs.name_), basename_(rhs.basename_), index_(rhs.index_) { } LauAbsCoeffSet& LauAbsCoeffSet::operator=(const LauAbsCoeffSet& rhs) { if ( &rhs != this ) { name_ = rhs.name_; basename_ = rhs.basename_; index_ = rhs.index_; } return *this; } TRandom* LauAbsCoeffSet::getRandomiser() { if ( randomiser_ == 0 ) { randomiser_ = LauRandom::zeroSeedRandom(); } return randomiser_; } void LauAbsCoeffSet::index(UInt_t newIndex) { index_ = newIndex; const TString oldBaseName( this->baseName() ); TString basename( oldBaseName ); if ( basename.Length() != 1 ) { basename.Remove(1); } basename += newIndex; basename += "_"; this->baseName(basename); std::vector pars = this->getParameters(); for ( std::vector::iterator iter = pars.begin(); iter != pars.end(); ++iter ) { this->adjustName( *iter, oldBaseName ); } } void LauAbsCoeffSet::adjustName(LauParameter* par, const TString& oldBaseName) { TString theName(par->name()); if ( theName.BeginsWith( oldBaseName ) && theName != oldBaseName ) { theName.Remove(0,oldBaseName.Length()); } theName.Prepend(this->baseName()); par->name(theName); } void LauAbsCoeffSet::setParameterValue(const TString& parName, Double_t value, Bool_t init) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterValue : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->value( value ); if ( init ) { par->genValue( value ); par->initValue( value ); } } void LauAbsCoeffSet::setParameterError(const TString& parName, Double_t error) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterError : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->error( error ); } void LauAbsCoeffSet::fixParameter(const TString& parName) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::fixParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kTRUE ); } void LauAbsCoeffSet::floatParameter(const TString& parName) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::floatParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kFALSE ); } void LauAbsCoeffSet::blindParameter(const TString& parName, const TString& blindingString, const Double_t width) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::blindParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->blindParameter( blindingString, width ); } void LauAbsCoeffSet::addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::addGaussianConstraint : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->addGaussianConstraint( mean, width ); } void LauAbsCoeffSet::addSuffixToParameterName(const TString& parName, const TString& suffix) { LauParameter* par = this->findParameter( parName ); if ( par == 0 ) { std::cerr << "ERROR in LauAbsCoeffSet::addSuffixToParameterName : Unable to find parameter \"" << parName << "\"" << std::endl; return; } TString newName( par->name() ); if ( ! suffix.BeginsWith('_') ) { newName += "_"; } newName += suffix; par->name( newName ); } LauParameter* LauAbsCoeffSet::findParameter(const TString& parName) { std::vector pars = this->getParameters(); for ( std::vector::iterator iter = pars.begin(); iter != pars.end(); ++iter ) { const TString& iName = (*iter)->name(); if ( iName.EndsWith( parName ) ) { return (*iter); } } return 0; } diff --git a/src/LauAbsFitModel.cc b/src/LauAbsFitModel.cc index 8c7bca9..a47c15c 100644 --- a/src/LauAbsFitModel.cc +++ b/src/LauAbsFitModel.cc @@ -1,1108 +1,1107 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsFitModel.cc \brief File containing implementation of LauAbsFitModel class. */ #include #include #include #include "TMessage.h" #include "TMonitor.h" #include "TSystem.h" #include "TVirtualFitter.h" #include "LauAbsFitModel.hh" #include "LauAbsFitter.hh" #include "LauAbsPdf.hh" #include "LauComplex.hh" #include "LauFitter.hh" #include "LauFitDataTree.hh" #include "LauGenNtuple.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" #include "LauPrint.hh" #include "LauSPlot.hh" -ClassImp(LauAbsFitModel) LauAbsFitModel::LauAbsFitModel() : fixParams_(kFALSE), compareFitData_(kFALSE), savePDF_(kFALSE), writeLatexTable_(kFALSE), writeSPlotData_(kFALSE), storeDPEff_(kFALSE), randomFit_(kFALSE), emlFit_(kFALSE), poissonSmear_(kFALSE), enableEmbedding_(kFALSE), usingDP_(kTRUE), pdfsDependOnDP_(kFALSE), inputFitData_(0), genNtuple_(0), sPlotNtuple_(0), nullString_(""), doSFit_(kFALSE), sWeightBranchName_(""), sWeightScaleFactor_(1.0), outputTableName_(""), fitToyMCFileName_("fitToyMC.root"), fitToyMCTableName_("fitToyMCTable"), fitToyMCScale_(10), fitToyMCPoissonSmear_(kFALSE), sPlotFileName_(""), sPlotTreeName_(""), sPlotVerbosity_("") { } LauAbsFitModel::~LauAbsFitModel() { delete inputFitData_; inputFitData_ = 0; delete genNtuple_; genNtuple_ = 0; delete sPlotNtuple_; sPlotNtuple_ = 0; } void LauAbsFitModel::run(const TString& applicationCode, const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileName) { // Chose whether you want to generate or fit events in the Dalitz plot. // To generate events choose applicationCode = "gen", to fit events choose // applicationCode = "fit". TString runCode(applicationCode); runCode.ToLower(); TString histFileNameCopy(histFileName); TString tableFileNameCopy(tableFileName); TString dataFileNameCopy(dataFileName); TString dataTreeNameCopy(dataTreeName); // Initialise the fit par vectors. Each class that inherits from this one // must implement this sensibly for all vectors specified in clearFitParVectors, // i.e. specify parameter names, initial, min, max and fixed values this->initialise(); // Add variables to Gaussian constrain to a list this->addConParameters(); if (dataFileNameCopy == "") {dataFileNameCopy = "data.root";} if (dataTreeNameCopy == "") {dataTreeNameCopy = "genResults";} if (runCode.Contains("gen")) { if (histFileNameCopy == "") {histFileNameCopy = "parInfo.root";} if (tableFileNameCopy == "") {tableFileNameCopy = "genResults";} this->setGenValues(); this->generate(dataFileNameCopy, dataTreeNameCopy, histFileNameCopy, tableFileNameCopy); } else if (runCode.Contains("fit")) { if (histFileNameCopy == "") {histFileNameCopy = "parInfo.root";} if (tableFileNameCopy == "") {tableFileNameCopy = "fitResults";} this->fit(dataFileNameCopy, dataTreeNameCopy, histFileNameCopy, tableFileNameCopy); } else if (runCode.Contains("plot")) { this->savePDFPlots("plot"); } else if (runCode.Contains("weight")) { this->weightEvents(dataFileNameCopy, dataTreeNameCopy); } } void LauAbsFitModel::doSFit( const TString& sWeightBranchName, Double_t scaleFactor ) { if ( sWeightBranchName == "" ) { std::cerr << "WARNING in LauAbsFitModel::doSFit : sWeight branch name is empty string, not setting-up sFit." << std::endl; return; } doSFit_ = kTRUE; sWeightBranchName_ = sWeightBranchName; sWeightScaleFactor_ = scaleFactor; } void LauAbsFitModel::setBkgndClassNames( const std::vector& names ) { if ( !bkgndClassNames_.empty() ) { std::cerr << "WARNING in LauAbsFitModel::setBkgndClassNames : Names already stored, not changing them." << std::endl; return; } UInt_t nBkgnds = names.size(); for ( UInt_t i(0); i < nBkgnds; ++i ) { bkgndClassNames_.insert( std::make_pair( i, names[i] ) ); } this->setupBkgndVectors(); } Bool_t LauAbsFitModel::validBkgndClass( const TString& className ) const { if ( bkgndClassNames_.empty() ) { return kFALSE; } Bool_t found(kFALSE); for ( LauBkgndClassMap::const_iterator iter = bkgndClassNames_.begin(); iter != bkgndClassNames_.end(); ++iter ) { if ( iter->second == className ) { found = kTRUE; break; } } return found; } UInt_t LauAbsFitModel::bkgndClassID( const TString& className ) const { if ( ! this->validBkgndClass( className ) ) { std::cerr << "ERROR in LauAbsFitModel::bkgndClassID : Request for ID for invalid background class \"" << className << "\"." << std::endl; return (bkgndClassNames_.size() + 1); } UInt_t bgID(0); for ( LauBkgndClassMap::const_iterator iter = bkgndClassNames_.begin(); iter != bkgndClassNames_.end(); ++iter ) { if ( iter->second == className ) { bgID = iter->first; break; } } return bgID; } const TString& LauAbsFitModel::bkgndClassName( UInt_t classID ) const { LauBkgndClassMap::const_iterator iter = bkgndClassNames_.find( classID ); if ( iter == bkgndClassNames_.end() ) { std::cerr << "ERROR in LauAbsFitModel::bkgndClassName : Request for name of invalid background class ID " << classID << "." << std::endl; return nullString_; } return iter->second; } void LauAbsFitModel::clearFitParVectors() { std::cout << "INFO in LauAbsFitModel::clearFitParVectors : Clearing fit variable vectors" << std::endl; // Remove the components created to apply constraints to fit parameters for (std::vector::iterator iter = conVars_.begin(); iter != conVars_.end(); ++iter){ if ( !(*iter)->isLValue() ){ delete (*iter); (*iter) = 0; } } conVars_.clear(); fitVars_.clear(); } void LauAbsFitModel::clearExtraVarVectors() { std::cout << "INFO in LauAbsFitModel::clearExtraVarVectors : Clearing extra ntuple variable vectors" << std::endl; extraVars_.clear(); } void LauAbsFitModel::setGenValues() { // makes sure each parameter holds its genValue as its current value for (LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter) { (*iter)->value((*iter)->genValue()); } this->propagateParUpdates(); } void LauAbsFitModel::writeSPlotData(const TString& fileName, const TString& treeName, Bool_t storeDPEfficiency, const TString& verbosity) { if (this->writeSPlotData()) { std::cerr << "ERROR in LauAbsFitModel::writeSPlotData : Already have an sPlot ntuple setup, not doing it again." << std::endl; return; } writeSPlotData_ = kTRUE; sPlotFileName_ = fileName; sPlotTreeName_ = treeName; sPlotVerbosity_ = verbosity; storeDPEff_ = storeDPEfficiency; } // TODO : histFileName isn't used here at the moment but could be used for // storing the values of the parameters used in the generation. // These could then be read and used for setting the "true" values // in a subsequent fit. void LauAbsFitModel::generate(const TString& dataFileName, const TString& dataTreeName, const TString& /*histFileName*/, const TString& tableFileNameBase) { // Create the ntuple for storing the results std::cout << "INFO in LauAbsFitModel::generate : Creating generation ntuple." << std::endl; if (genNtuple_ != 0) {delete genNtuple_; genNtuple_ = 0;} genNtuple_ = new LauGenNtuple(dataFileName,dataTreeName); // add branches for storing the experiment number and the number of // the event within the current experiment this->addGenNtupleIntegerBranch("iExpt"); this->addGenNtupleIntegerBranch("iEvtWithinExpt"); this->setupGenNtupleBranches(); // Start the cumulative timer cumulTimer_.Start(); const UInt_t firstExp = this->firstExpt(); const UInt_t nExp = this->nExpt(); Bool_t genOK(kTRUE); do { // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each experiment takes to generate timer_.Start(); // Store the experiment number in the ntuple this->setGenNtupleIntegerBranchValue("iExpt",iExp); // Do the generation for this experiment std::cout << "INFO in LauAbsFitModel::generate : Generating experiment number " << iExp << std::endl; genOK = this->genExpt(); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); if (!genOK) { // delete and recreate an empty tree genNtuple_->deleteAndRecreateTree(); // then break out of the experiment loop std::cerr << "WARNING in LauAbsFitModel::generate : Problem in toy MC generation. Starting again with updated parameters..." << std::endl; break; } if (this->writeLatexTable()) { TString tableFileName(tableFileNameBase); tableFileName += "_"; tableFileName += iExp; tableFileName += ".tex"; this->writeOutTable(tableFileName); } } // Loop over number of experiments } while (!genOK); // Print out total timing info. cumulTimer_.Stop(); std::cout << "INFO in LauAbsFitModel::generate : Finished generating all experiments." << std::endl; std::cout << "INFO in LauAbsFitModel::generate : Cumulative timing:" << std::endl; cumulTimer_.Print(); // Build the event index std::cout << "INFO in LauAbsFitModel::generate : Building experiment:event index." << std::endl; // TODO - can test this return value? //Int_t nIndexEntries = genNtuple_->buildIndex("iExpt","iEvtWithinExpt"); // Write out toy MC ntuple std::cout << "INFO in LauAbsFitModel::generate : Writing data to file " << dataFileName << "." << std::endl; genNtuple_->writeOutGenResults(); } void LauAbsFitModel::addGenNtupleIntegerBranch(const TString& name) { genNtuple_->addIntegerBranch(name); } void LauAbsFitModel::addGenNtupleDoubleBranch(const TString& name) { genNtuple_->addDoubleBranch(name); } void LauAbsFitModel::setGenNtupleIntegerBranchValue(const TString& name, Int_t value) { genNtuple_->setIntegerBranchValue(name,value); } void LauAbsFitModel::setGenNtupleDoubleBranchValue(const TString& name, Double_t value) { genNtuple_->setDoubleBranchValue(name,value); } Int_t LauAbsFitModel::getGenNtupleIntegerBranchValue(const TString& name) const { return genNtuple_->getIntegerBranchValue(name); } Double_t LauAbsFitModel::getGenNtupleDoubleBranchValue(const TString& name) const { return genNtuple_->getDoubleBranchValue(name); } void LauAbsFitModel::fillGenNtupleBranches() { genNtuple_->fillBranches(); } void LauAbsFitModel::addSPlotNtupleIntegerBranch(const TString& name) { sPlotNtuple_->addIntegerBranch(name); } void LauAbsFitModel::addSPlotNtupleDoubleBranch(const TString& name) { sPlotNtuple_->addDoubleBranch(name); } void LauAbsFitModel::setSPlotNtupleIntegerBranchValue(const TString& name, Int_t value) { sPlotNtuple_->setIntegerBranchValue(name,value); } void LauAbsFitModel::setSPlotNtupleDoubleBranchValue(const TString& name, Double_t value) { sPlotNtuple_->setDoubleBranchValue(name,value); } void LauAbsFitModel::fillSPlotNtupleBranches() { sPlotNtuple_->fillBranches(); } void LauAbsFitModel::fit(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileNameBase) { // Routine to perform the total fit. const UInt_t firstExp = this->firstExpt(); const UInt_t nExp = this->nExpt(); std::cout << "INFO in LauAbsFitModel::fit : First experiment = " << firstExp << std::endl; std::cout << "INFO in LauAbsFitModel::fit : Number of experiments = " << nExp << std::endl; // Start the cumulative timer cumulTimer_.Start(); this->resetFitCounters(); // Create and setup the fit results ntuple this->setupResultsOutputs( histFileName, tableFileNameBase ); // Create and setup the sPlot ntuple if (this->writeSPlotData()) { std::cout << "INFO in LauAbsFitModel::fit : Creating sPlot ntuple." << std::endl; if (sPlotNtuple_ != 0) {delete sPlotNtuple_; sPlotNtuple_ = 0;} sPlotNtuple_ = new LauGenNtuple(sPlotFileName_,sPlotTreeName_); this->setupSPlotNtupleBranches(); } // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauAbsFitModel::fit : Problem caching the fit data." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each fit takes timer_.Start(); this->setCurrentExperiment( iExp ); UInt_t nEvents = this->readExperimentData(); if (nEvents < 1) { std::cerr << "WARNING in LauAbsFitModel::fit : Zero events in experiment " << iExp << ", skipping..." << std::endl; timer_.Stop(); continue; } // Now the sub-classes must implement whatever they need to do // to cache any more input fit data they need in order to // calculate the likelihoods during the fit. // They need to use the inputFitData_ tree as input. For example, // inputFitData_ contains m13Sq and m23Sq. The appropriate fit model // then caches the resonance dynamics for the signal model, as // well as the background likelihood values in the Dalitz plot this->cacheInputFitVars(); if ( this->doSFit() ) { this->cacheInputSWeights(); } // If we're fitting toy experiments then re-generate the means of any constraints this->generateConstraintMeans( conVars_ ); // Do the fit for this experiment this->fitExpt(); // Write the results into the ntuple this->finaliseFitResults( outputTableName_ ); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); // Store the per-event likelihood values if ( this->writeSPlotData() ) { this->storePerEvtLlhds(); } // Create a toy MC sample using the fitted parameters so that // the user can compare the fit to the data. if (compareFitData_ == kTRUE && this->statusCode() == 3) { this->createFitToyMC(fitToyMCFileName_, fitToyMCTableName_); } } // Loop over number of experiments // Print out total timing info. cumulTimer_.Stop(); std::cout << "INFO in LauAbsFitModel::fit : Cumulative timing:" << std::endl; cumulTimer_.Print(); // Print out stats on OK fits. const UInt_t nOKFits = this->numberOKFits(); const UInt_t nBadFits = this->numberBadFits(); std::cout << "INFO in LauAbsFitModel::fit : Number of OK Fits = " << nOKFits << std::endl; std::cout << "INFO in LauAbsFitModel::fit : Number of Failed Fits = " << nBadFits << std::endl; Double_t fitEff(0.0); if (nExp != 0) {fitEff = nOKFits/(1.0*nExp);} std::cout << "INFO in LauAbsFitModel::fit : Fit efficiency = " << fitEff*100.0 << "%." << std::endl; // Write out any fit results (ntuples etc...). this->writeOutAllFitResults(); if ( this->writeSPlotData() ) { this->calculateSPlotData(); } } void LauAbsFitModel::setupResultsOutputs( const TString& histFileName, const TString& tableFileName ) { this->LauSimFitTask::setupResultsOutputs( histFileName, tableFileName ); outputTableName_ = tableFileName; } Bool_t LauAbsFitModel::verifyFitData(const TString& dataFileName, const TString& dataTreeName) { // From the input data stream, store the variables into the // internal tree inputFitData_ that can be used by the sub-classes // in calculating their likelihood functions for the fit delete inputFitData_; inputFitData_ = new LauFitDataTree(dataFileName,dataTreeName); Bool_t dataOK = inputFitData_->findBranches(); if (!dataOK) { delete inputFitData_; inputFitData_ = 0; } return dataOK; } void LauAbsFitModel::cacheInputSWeights() { Bool_t hasBranch = inputFitData_->haveBranch( sWeightBranchName_ ); if ( ! hasBranch ) { std::cerr << "ERROR in LauAbsFitModel::cacheInputSWeights : Input data does not contain variable \"" << sWeightBranchName_ << "\".\n"; std::cerr << " : Turning off sFit!" << std::endl; doSFit_ = kFALSE; return; } UInt_t nEvents = this->eventsPerExpt(); sWeights_.clear(); sWeights_.reserve( nEvents ); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputFitData_->getData(iEvt); LauFitData::const_iterator iter = dataValues.find( sWeightBranchName_ ); sWeights_.push_back( iter->second * sWeightScaleFactor_ ); } } void LauAbsFitModel::fitExpt() { // Routine to perform the actual fit for the given experiment // Update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Initialise the fitter LauFitter::fitter().useAsymmFitErrors( this->useAsymmFitErrors() ); LauFitter::fitter().twoStageFit( this->twoStageFit() ); LauFitter::fitter().initialise( this, fitVars_ ); this->startNewFit( LauFitter::fitter().nParameters(), LauFitter::fitter().nFreeParameters() ); // Now ready for minimisation step std::cout << "\nINFO in LauAbsFitModel::fitExpt : Start minimisation...\n"; LauAbsFitter::FitStatus fitResult = LauFitter::fitter().minimise(); // If we're doing a two stage fit we can now release (i.e. float) // the 2nd stage parameters and re-fit if (this->twoStageFit()) { if ( fitResult.status != 3 ) { std::cerr << "WARNING in LauAbsFitModel:fitExpt : Not running second stage fit since first stage failed." << std::endl; LauFitter::fitter().releaseSecondStageParameters(); } else { LauFitter::fitter().releaseSecondStageParameters(); this->startNewFit( LauFitter::fitter().nParameters(), LauFitter::fitter().nFreeParameters() ); fitResult = LauFitter::fitter().minimise(); } } const TMatrixD& covMat = LauFitter::fitter().covarianceMatrix(); this->storeFitStatus( fitResult, covMat ); // Store the final fit results and errors into protected internal vectors that // all sub-classes can use within their own finalFitResults implementation // used below (e.g. putting them into an ntuple in a root file) LauFitter::fitter().updateParameters(); } void LauAbsFitModel::calculateSPlotData() { if (sPlotNtuple_ != 0) { sPlotNtuple_->addFriendTree(inputFitData_->fileName(), inputFitData_->treeName()); sPlotNtuple_->writeOutGenResults(); LauSPlot splot(sPlotNtuple_->fileName(), sPlotNtuple_->treeName(), this->firstExpt(), this->nExpt(), this->variableNames(), this->freeSpeciesNames(), this->fixdSpeciesNames(), this->twodimPDFs(), this->splitSignal(), this->scfDPSmear()); splot.runCalculations(sPlotVerbosity_); splot.writeOutResults(); } } void LauAbsFitModel::compareFitData(UInt_t toyMCScale, const TString& mcFileName, const TString& tableFileName, Bool_t poissonSmearing) { compareFitData_ = kTRUE; fitToyMCScale_ = toyMCScale; fitToyMCFileName_ = mcFileName; fitToyMCTableName_ = tableFileName; fitToyMCPoissonSmear_ = poissonSmearing; } void LauAbsFitModel::createFitToyMC(const TString& mcFileName, const TString& tableFileName) { // Create a toy MC sample so that the user can compare the fitted // result with the data. // Generate more toy MC to reduce statistical fluctuations: // - use the rescaling value fitToyMCScale_ // Store the info on the number of experiments, first expt and current expt const UInt_t oldNExpt(this->nExpt()); const UInt_t oldFirstExpt(this->firstExpt()); const UInt_t oldIExpt(this->iExpt()); const Bool_t oldToyExpt(this->toyExpts()); // Turn off Poisson smearing if required const Bool_t poissonSmearing(this->doPoissonSmearing()); this->doPoissonSmearing(fitToyMCPoissonSmear_); // Turn off embedding, since we need toy MC, not reco'ed events const Bool_t enableEmbeddingOrig(this->enableEmbedding()); this->enableEmbedding(kFALSE); // Need to make sure that the generation of the DP co-ordinates is // switched on if any of our PDFs depend on it const Bool_t origUseDP = this->useDP(); if ( !origUseDP && this->pdfsDependOnDP() ) { this->useDP( kTRUE ); this->initialiseDPModels(); } // Construct a unique filename for this experiment TString exptString("_expt"); exptString += oldIExpt; TString fileName( mcFileName ); fileName.Insert( fileName.Last('.'), exptString ); // Generate the toy MC std::cout << "INFO in LauAbsFitModel::createFitToyMC : Generating toy MC in " << fileName << " to compare fit with data..." << std::endl; std::cout << " : Number of experiments to generate = " << fitToyMCScale_ << "." << std::endl; std::cout << " : This is to allow the toy MC to be made with reduced statistical fluctuations." << std::endl; // Set the genValue of each parameter to its current (fitted) value // but first store the original genValues for restoring later std::vector origGenValues; origGenValues.reserve(this->nTotParams()); Bool_t blind(kFALSE); for (LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter) { origGenValues.push_back((*iter)->genValue()); (*iter)->genValue((*iter)->unblindValue()); if ( (*iter)->blind() ) { blind = kTRUE; } } if ( blind ) { std::cerr << "WARNING in LauAbsFitModel::createFitToyMC : One or more parameters are blind but the toy will be created using the unblind values - use with caution!!" << std::endl; } // If we're asked to generate more than 100 experiments then split it // up into multiple files since otherwise can run into memory issues // when building the index // TODO - this obviously depends on the number of events per experiment as well, so should do this properly UInt_t totalExpts = fitToyMCScale_; if ( totalExpts > 100 ) { UInt_t nFiles = totalExpts/100; if ( totalExpts%100 ) { nFiles += 1; } TString fileNameBase {fileName}; for ( UInt_t iFile(0); iFile < nFiles; ++iFile ) { UInt_t firstExp( iFile*100 ); // Set number of experiments and first experiment to generate UInt_t nExp = ((firstExp + 100)>totalExpts) ? totalExpts-firstExp : 100; this->setNExpts(nExp, firstExp, kTRUE); // Create a unique filename and generate the events fileName = fileNameBase; TString extraname = "_file"; extraname += iFile; fileName.Insert( fileName.Last('.'), extraname ); this->generate(fileName, "genResults", "dummy.root", tableFileName); } } else { // Set number of experiments to new value this->setNExpts(fitToyMCScale_, 0, kTRUE); // Generate the toy this->generate(fileName, "genResults", "dummy.root", tableFileName); } // Reset number of experiments to original value this->setNExpts(oldNExpt, oldFirstExpt, oldToyExpt); this->setCurrentExperiment(oldIExpt); // Restore the Poisson smearing to its former value this->doPoissonSmearing(poissonSmearing); // Restore the embedding status this->enableEmbedding(enableEmbeddingOrig); // Restore "useDP" to its former status this->useDP( origUseDP ); // Restore the original genValue to each parameter for (UInt_t i(0); inTotParams(); ++i) { fitVars_[i]->genValue(origGenValues[i]); } std::cout << "INFO in LauAbsFitModel::createFitToyMC : Finished in createFitToyMC." << std::endl; } Double_t LauAbsFitModel::getTotNegLogLikelihood() { // Calculate the total negative log-likelihood over all events. // This function assumes that the fit parameters and data tree have // already been set-up correctly. // Loop over the data points to calculate the log likelihood Double_t logLike = this->getLogLikelihood( 0, this->eventsPerExpt() ); // Include the Poisson term in the extended likelihood if required if (this->doEMLFit()) { logLike -= this->getEventSum(); } // Calculate any penalty terms from Gaussian constrained variables const auto& multiDimCons = this->multiDimConstraints(); if ( ! conVars_.empty() || ! multiDimCons.empty() ){ logLike -= this->getLogLikelihoodPenalty(); } Double_t totNegLogLike = -logLike; return totNegLogLike; } Double_t LauAbsFitModel::getLogLikelihoodPenalty() { Double_t penalty{0.0}; for ( LauAbsRValue* par : conVars_ ) { penalty += par->constraintPenalty(); } auto& multiDimCons = this->multiDimConstraints(); for ( auto& constraint : multiDimCons ) { penalty += constraint.constraintPenalty(); } return penalty; } Double_t LauAbsFitModel::getLogLikelihood( UInt_t iStart, UInt_t iEnd ) { // Calculate the total negative log-likelihood over all events. // This function assumes that the fit parameters and data tree have // already been set-up correctly. // Loop over the data points to calculate the log likelihood Double_t logLike(0.0); const Double_t worstLL = this->worstLogLike(); // Loop over the number of events in this experiment Bool_t ok(kTRUE); for (UInt_t iEvt = iStart; iEvt < iEnd; ++iEvt) { Double_t likelihood = this->getTotEvtLikelihood(iEvt); if (likelihood > std::numeric_limits::min()) { // Is the likelihood zero? Double_t evtLogLike = TMath::Log(likelihood); if ( doSFit_ ) { evtLogLike *= sWeights_[iEvt]; } logLike += evtLogLike; } else { ok = kFALSE; std::cerr << "WARNING in LauAbsFitModel::getLogLikelihood : Strange likelihood value for event " << iEvt << ": " << likelihood << "\n"; this->printEventInfo(iEvt); this->printVarsInfo(); //Write the values of the floated variables for which the likelihood is zero break; } } if (!ok) { std::cerr << " : Returning worst NLL found so far to force MINUIT out of this region." << std::endl; logLike = worstLL; } else if (logLike < worstLL) { this->worstLogLike( logLike ); } return logLike; } void LauAbsFitModel::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check if ( ! this->withinAsymErrorCalc() ) { const UInt_t nFreePars = this->nFreeParams(); if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauAbsFitModel::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the floating ones with their new values // Also check if we have any parameters on which the DP integrals depend // and whether they have changed since the last iteration Bool_t recalcNorm(kFALSE); const LauParameterPSet::const_iterator resVarsEnd = resVars_.end(); for (UInt_t i(0); inTotParams(); ++i) { if (!fitVars_[i]->fixed()) { if ( resVars_.find( fitVars_[i] ) != resVarsEnd ) { if ( fitVars_[i]->value() != par[i] ) { recalcNorm = kTRUE; } } fitVars_[i]->value(par[i]); } } // If so, then recalculate the normalisation if (recalcNorm) { this->recalculateNormalisation(); } this->propagateParUpdates(); } UInt_t LauAbsFitModel::addFitParameters(LauPdfList& pdfList) { UInt_t nParsAdded(0); for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { LauAbsPdf* pdf = (*pdf_iter); if ( pdf->isDPDependent() ) { this->pdfsDependOnDP( kTRUE ); } LauAbsRValuePList& pars = pdf->getParameters(); for (LauAbsRValuePList::iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) { LauParameterPList params = (*pars_iter)->getPars(); for (LauParameterPList::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter) { if ( !(*params_iter)->clone() && ( !(*params_iter)->fixed() || ( this->twoStageFit() && (*params_iter)->secondStage() ) ) ) { fitVars_.push_back(*params_iter); ++nParsAdded; } } } } return nParsAdded; } void LauAbsFitModel::addConParameters() { // Add penalties from the constraints to fit parameters // First, constraints on the fit parameters themselves for ( LauParameter* param : fitVars_ ) { if ( param->gaussConstraint() ) { conVars_.push_back( param ); std::cout << "INFO in LauAbsFitModel::addConParameters : Added Gaussian constraint to parameter "<< param->name() << std::endl; } } // Second, constraints on arbitrary combinations auto& conStore = this->formulaConstraints(); for ( auto& constraint : conStore ) { std::vector params; for ( const auto& name : constraint.conPars_ ) { for ( LauParameter* par : fitVars_ ) { if ( par->name() == name ){ params.push_back( par ); } } } // If the parameters are not found, skip it if ( params.size() != constraint.conPars_.size() ) { std::cerr << "WARNING in LauAbsFitModel::addConParameters: Could not find parameters to constrain in the formula... skipping" << std::endl; continue; } constraint.formulaPar_ = std::make_unique( constraint.formula_, constraint.formula_, params ); constraint.formulaPar_->addGaussianConstraint( constraint.mean_, constraint.width_ ); conVars_.push_back( constraint.formulaPar_.get() ); std::cout << "INFO in LauAbsFitModel::addConParameters : Added Gaussian constraint to formula\n"; std::cout << " : Formula: " << constraint.formula_ << std::endl; for ( LauParameter* param : params ) { std::cout << " : Parameter: " << param->name() << std::endl; } } // Add n-dimensional constraints auto& multiDimCons = this->multiDimConstraints(); for ( auto& constraint : multiDimCons ){ for ( auto& parname : constraint.conPars_ ){ for ( auto& fitPar : fitVars_ ){ if ( parname == fitPar->name() ){ // Check parameters do not have a 1D Gaussian constraint applied if ( fitPar->gaussConstraint() ){ std::cerr << "ERROR in LauAbsFitModel::addConParameters: parameter in n-dimensional constraint already has a 1d constraint applied" << std::endl; gSystem->Exit(EXIT_FAILURE); } constraint.conLauPars_.push_back(fitPar); } } } if ( constraint.conLauPars_.size() != constraint.conPars_.size() ){ std::cerr << "Error in LauAbsFitModel::addConParameters : Could not match parameter names for n-dimensional constraint" << std::endl; gSystem->Exit(EXIT_FAILURE); } } } void LauAbsFitModel::updateFitParameters(LauPdfList& pdfList) { for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->updatePulls(); } } void LauAbsFitModel::printFitParameters(const LauPdfList& pdfList, std::ostream& fout) const { LauPrint print; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { const LauAbsRValuePList& pars = (*pdf_iter)->getParameters(); for (LauAbsRValuePList::const_iterator pars_iter = pars.begin(); pars_iter != pars.end(); ++pars_iter) { LauParameterPList params = (*pars_iter)->getPars(); for (LauParameterPList::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter) { if (!(*params_iter)->clone()) { fout << (*params_iter)->name() << " & $"; print.printFormat(fout, (*params_iter)->value()); if ((*params_iter)->fixed() == kTRUE) { fout << "$ (fixed) \\\\"; } else { fout << " \\pm "; print.printFormat(fout, (*params_iter)->error()); fout << "$ \\\\" << std::endl; } } } } } } void LauAbsFitModel::cacheInfo(LauPdfList& pdfList, const LauFitDataTree& theData) { for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->cacheInfo(theData); } } Double_t LauAbsFitModel::prodPdfValue(LauPdfList& pdfList, UInt_t iEvt) { Double_t pdfVal = 1.0; for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->calcLikelihoodInfo(iEvt); pdfVal *= (*pdf_iter)->getLikelihood(); } return pdfVal; } void LauAbsFitModel::printEventInfo(UInt_t iEvt) const { const LauFitData& data = inputFitData_->getData(iEvt); std::cerr << " : Input data values for this event:" << std::endl; for (LauFitData::const_iterator iter = data.begin(); iter != data.end(); ++iter) { std::cerr << " " << iter->first << " = " << iter->second << std::endl; } } void LauAbsFitModel::printVarsInfo() const { std::cerr << " : Current values of fit parameters:" << std::endl; for (UInt_t i(0); inTotParams(); ++i) { std::cerr << " " << (fitVars_[i]->name()).Data() << " = " << fitVars_[i]->value() << std::endl; } } void LauAbsFitModel::prepareInitialParArray( TObjArray& array ) { // Update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Store the total number of parameters and the number of free parameters UInt_t nPars = fitVars_.size(); UInt_t nFreePars = 0; // Send the fit parameters for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) { if ( ! (*iter)->fixed() ) { ++nFreePars; } array.Add( *iter ); } this->startNewFit( nPars, nFreePars ); } void LauAbsFitModel::finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromCoordinator, const TMatrixD* covMat, TObjArray& parsToCoordinator ) { // Copy the fit status information this->storeFitStatus( fitStat, *covMat ); // Now process the parameters const UInt_t nPars = this->nTotParams(); UInt_t nParsFromCoordinator = parsFromCoordinator->GetEntries(); if ( nParsFromCoordinator != nPars ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Unexpected number of parameters received from coordinator" << std::endl; std::cerr << " : Received " << nParsFromCoordinator << " when expecting " << nPars << std::endl; gSystem->Exit( EXIT_FAILURE ); } for ( UInt_t iPar(0); iPar < nParsFromCoordinator; ++iPar ) { LauParameter* parameter = dynamic_cast( (*parsFromCoordinator)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Error reading parameter from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } if ( parameter->name() != fitVars_[iPar]->name() ) { std::cerr << "ERROR in LauAbsFitModel::finaliseExperiment : Error reading parameter from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } *(fitVars_[iPar]) = *parameter; } // Write the results into the ntuple this->finaliseFitResults( outputTableName_ ); // Store the per-event likelihood values if ( this->writeSPlotData() ) { this->storePerEvtLlhds(); } // Create a toy MC sample using the fitted parameters so that // the user can compare the fit to the data. if (compareFitData_ == kTRUE && fitStat.status == 3) { this->createFitToyMC(fitToyMCFileName_, fitToyMCTableName_); } // Send the finalised fit parameters for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) { parsToCoordinator.Add( *iter ); } } UInt_t LauAbsFitModel::readExperimentData() { // retrieve the data and find out how many events have been read const UInt_t exptIndex = this->iExpt(); inputFitData_->readExperimentData( exptIndex ); const UInt_t nEvent = inputFitData_->nEvents(); this->eventsPerExpt( nEvent ); return nEvent; } void LauAbsFitModel::setParametersFromFile(const TString& fileName, const TString& treeName, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParams_ = fix; } void LauAbsFitModel::setParametersFromMap(const std::map& parameters, const Bool_t fix) { fixParamMap_ = parameters; fixParams_ = fix; } void LauAbsFitModel::setNamedParameters(const TString& fileName, const TString& treeName, const std::set& parameters, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParamNames_ = parameters; fixParams_ = fix; } void LauAbsFitModel::setParametersFileFallback(const TString& fileName, const TString& treeName, const std::map& parameters, const Bool_t fix) { fixParamFileName_ = fileName; fixParamTreeName_ = treeName; fixParamMap_ = parameters; fixParams_ = fix; } diff --git a/src/LauAbsIncohRes.cc b/src/LauAbsIncohRes.cc index 7f9123f..f7e2559 100644 --- a/src/LauAbsIncohRes.cc +++ b/src/LauAbsIncohRes.cc @@ -1,49 +1,48 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsIncohRes.cc \brief File containing implementation of LauAbsIncohRes class. */ #include "LauAbsIncohRes.hh" #include "LauDaughters.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsIncohRes) // Constructor LauAbsIncohRes::LauAbsIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) {} // Destructor LauAbsIncohRes::~LauAbsIncohRes() { } LauComplex LauAbsIncohRes::resAmp(Double_t /*mass*/, Double_t spinTerm) { return LauComplex(spinTerm, 0.0); } diff --git a/src/LauAbsModIndPartWave.cc b/src/LauAbsModIndPartWave.cc index c81314c..3fa1732 100644 --- a/src/LauAbsModIndPartWave.cc +++ b/src/LauAbsModIndPartWave.cc @@ -1,249 +1,248 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsModIndPartWave.cc \brief File containing implementation of LauAbsModIndPartWave class. */ #include #include #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauAbsModIndPartWave.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsModIndPartWave) LauAbsModIndPartWave::LauAbsModIndPartWave(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), nKnots_(0), spline1_(0), spline2_(0), type1_(Lau1DCubicSpline::StandardSpline), type2_(Lau1DCubicSpline::StandardSpline), leftBound1_(Lau1DCubicSpline::NotAKnot), rightBound1_(Lau1DCubicSpline::NotAKnot), leftBound2_(Lau1DCubicSpline::NotAKnot), rightBound2_(Lau1DCubicSpline::NotAKnot), leftGrad1_(0.), rightGrad1_(0.), leftGrad2_(0.), rightGrad2_(0.), secondStage_(kFALSE) { } LauAbsModIndPartWave::~LauAbsModIndPartWave() { delete spline1_; delete spline2_; } void LauAbsModIndPartWave::floatKnotsSecondStage(const Bool_t secondStage) { secondStage_ = secondStage; // if the parameters have not yet been created we can now just return if ( amp1Pars_.size() != nKnots_ ) { return; } // otherwise we need to toggle their second-stage parameter for ( UInt_t i(0); i < nKnots_; ++i ) { amp1Pars_[i]->secondStage(secondStage_); amp2Pars_[i]->secondStage(secondStage_); } } std::set LauAbsModIndPartWave::checkKnots(const std::set& masses) { std::set knots = masses; const std::set::const_iterator first = knots.begin(); const std::set::const_reverse_iterator last = knots.rbegin(); const Double_t lower_limit = this->getMassDaug1() + this->getMassDaug2(); const Double_t upper_limit = this->getMassParent() - this->getMassBachelor(); // check whether we have been given knots at unphysical masses if ( *first < lower_limit ) { std::cerr << "WARNING in LauAbsModIndPartWave::checkKnots : Knot found at mass " << *first << " is below the lower kinematic limit." << std::endl; std::cerr << " : Lower kinematic limit is at mass " << lower_limit << std::endl; std::cerr << " : Aborting definition of knot positions." << std::endl; knots.clear(); return knots; } if ( *last > upper_limit ) { std::cerr << "WARNING in LauAbsModIndPartWave::checkKnots : Knot found at mass " << *last << " is above the upper kinematic limit." << std::endl; std::cerr << " : Upper kinematic limit is at mass " << upper_limit << std::endl; std::cerr << " : Aborting definition of knot positions." << std::endl; knots.clear(); return knots; } // check if we have knots at each extreme - if not, add them in if ( (*first) != lower_limit ) { knots.insert( lower_limit ); } if ( (*last) != upper_limit ) { knots.insert( upper_limit ); } return knots; } void LauAbsModIndPartWave::defineKnots(const std::set& masses) { if ( ! masses_.empty() ) { std::cerr << "WARNING in LauAbsModIndPartWave::defineKnots : Knot positions have already been defined, not making any changes." << std::endl; return; } const std::set knots = this->checkKnots( masses ); nKnots_ = knots.size(); if ( nKnots_ == 0 ) { return; } masses_.reserve(nKnots_); amp1Vals_.reserve(nKnots_); amp2Vals_.reserve(nKnots_); amp1Pars_.reserve(nKnots_); amp2Pars_.reserve(nKnots_); UInt_t counter(0); for ( std::set::const_iterator iter = knots.begin(); iter != knots.end(); ++iter ) { masses_.push_back( *iter ); amp1Vals_.push_back(1.0); amp2Vals_.push_back(1.0); this->createAmpParameters(counter); ++counter; } for ( std::vector::const_iterator iter = masses_.begin(); iter != masses_.end(); ++iter ) { std::cout << "INFO in LauAbsModIndPartWave::defineKnots : Knot added to resonance " << this->getResonanceName() << " at mass " << *iter << std::endl; } } void LauAbsModIndPartWave::initialise() { if ( spline1_ != 0 ) { delete spline1_; spline1_ = 0; } if ( spline2_ != 0 ) { delete spline2_; spline2_ = 0; } for ( UInt_t i(0); i < nKnots_; ++i ) { amp1Vals_[i] = amp1Pars_[i]->unblindValue(); amp2Vals_[i] = amp2Pars_[i]->unblindValue(); } spline1_ = new Lau1DCubicSpline(masses_, amp1Vals_, type1_, leftBound1_, rightBound1_, leftGrad1_, rightGrad1_); spline2_ = new Lau1DCubicSpline(masses_, amp2Vals_, type2_, leftBound2_, rightBound2_, leftGrad2_, rightGrad2_); } LauComplex LauAbsModIndPartWave::resAmp(Double_t mass, Double_t spinTerm) { amp_.zero(); Bool_t paramChanged1(kFALSE), paramChanged2(kFALSE); for ( UInt_t i(0); i < nKnots_; ++i ) { if ( !amp1Pars_[i]->fixed() && amp1Pars_[i]->unblindValue() != amp1Vals_[i] ) { paramChanged1 = kTRUE; amp1Vals_[i] = amp1Pars_[i]->unblindValue(); } if ( !amp2Pars_[i]->fixed() && amp2Pars_[i]->unblindValue() != amp2Vals_[i] ) { paramChanged2 = kTRUE; amp2Vals_[i] = amp2Pars_[i]->unblindValue(); } } if ( spline1_ == 0 || spline2_ == 0) { std::cerr << "ERROR in LauAbsModIndPartWave::resAmp : One of the splines is null" << std::endl; return amp_; } if ( paramChanged1 ) { spline1_->updateYValues(amp1Vals_); } if ( paramChanged2 ) { spline2_->updateYValues(amp2Vals_); } this->evaluateAmplitude( mass ); amp_.rescale( spinTerm ); return amp_; } void LauAbsModIndPartWave::setSplineType(Lau1DCubicSpline::LauSplineType type1, Lau1DCubicSpline::LauSplineType type2) { type1_ = type1; type2_ = type2; } void LauAbsModIndPartWave::setSplineBoundaryConditions(Lau1DCubicSpline::LauSplineBoundaryType leftBound1, Lau1DCubicSpline::LauSplineBoundaryType rightBound1, Lau1DCubicSpline::LauSplineBoundaryType leftBound2, Lau1DCubicSpline::LauSplineBoundaryType rightBound2, Double_t leftGrad1, Double_t rightGrad1, Double_t leftGrad2, Double_t rightGrad2) { leftBound1_ = leftBound1; rightBound1_ = rightBound1; leftBound2_ = leftBound2; rightBound2_ = rightBound2; leftGrad1_ = leftGrad1; rightGrad1_ = rightGrad1; leftGrad2_ = leftGrad2; rightGrad2_ = rightGrad2; } const std::vector& LauAbsModIndPartWave::getFloatingParameters() { this->clearFloatingParameters(); for ( UInt_t i(0); i < nKnots_; ++i ) { if ( !amp1Pars_[i]->fixed() ) { this->addFloatingParameter( amp1Pars_[i] ); } if ( !amp2Pars_[i]->fixed() ) { this->addFloatingParameter( amp2Pars_[i] ); } } return this->getParameters(); } diff --git a/src/LauAbsPdf.cc b/src/LauAbsPdf.cc index e93b858..aefba2d 100644 --- a/src/LauAbsPdf.cc +++ b/src/LauAbsPdf.cc @@ -1,577 +1,579 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsPdf.cc \brief File containing implementation of LauAbsPdf class. */ #include #include #include #include #include "TSystem.h" #include "LauAbsPdf.hh" #include "LauRandom.hh" #include "LauIntegrals.hh" #include "LauKinematics.hh" -ClassImp(LauAbsPdf) // Constructor for the abstract PDF class. LauAbsPdf::LauAbsPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : varNames_(), param_(params), norm_(0.0), maxHeight_(0.0), heightUpToDate_(kFALSE), minAbscissas_(), maxAbscissas_(), randomFun_(LauRandom::randomFun()), cachePDF_(kFALSE), unNormPDFVal_(0.0), nNormPoints_(50), integMethod_(GaussLegendre), withinNormCalc_(kFALSE), withinGeneration_(kFALSE), normWeightsDone_(kFALSE) { // Store the variable name varNames_.insert( std::make_pair( 0, theVarName ) ); // Store the min and max values minAbscissas_.push_back( minAbscissa ); maxAbscissas_.push_back( maxAbscissa ); } LauAbsPdf::LauAbsPdf(const std::vector& theVarNames, const std::vector& params, const LauFitData& minAbscissas, const LauFitData& maxAbscissas) : varNames_(), param_(params), norm_(0.0), maxHeight_(0.0), heightUpToDate_(kFALSE), minAbscissas_(), maxAbscissas_(), randomFun_(LauRandom::randomFun()), cachePDF_(kFALSE), unNormPDFVal_(0.0), nNormPoints_(50), integMethod_(GaussLegendre), withinNormCalc_(kFALSE), withinGeneration_(kFALSE), normWeightsDone_(kFALSE) { // Check that we have at least one variable if ( theVarNames.empty() ) { std::cerr << "ERROR in LauAbsPdf::LauAbsPdf : No variables supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Store the variable names for ( UInt_t i(0); i < theVarNames.size(); ++i ) { varNames_.insert( std::make_pair( i, theVarNames[i] ) ); } // Store the min and max abcissas for every variable UInt_t nVars = varNames_.size(); minAbscissas_.resize( nVars ); maxAbscissas_.resize( nVars ); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; LauFitData::const_iterator min_iter = minAbscissas.find( theVarName ); LauFitData::const_iterator max_iter = maxAbscissas.find( theVarName ); if ( min_iter == minAbscissas.end() || max_iter == maxAbscissas.end() ) { std::cerr << "ERROR in LauAbsPdf::LauAbsPdf : Either min or max abscissa not provided for variable \"" << theVarName << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } minAbscissas_[ varIndex ] = min_iter->second; maxAbscissas_[ varIndex ] = max_iter->second; } } std::vector LauAbsPdf::varNames() const { std::vector theVarNames; theVarNames.reserve( varNames_.size() ); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { theVarNames.push_back( iter->second ); } return theVarNames; } UInt_t LauAbsPdf::nFixedParameters() const { LauParamFixed pred; return std::count_if(param_.begin(),param_.end(),pred); } Double_t LauAbsPdf::getMinAbscissa( const TString& theVarName ) const { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { return minAbscissas_[ index ]; } } std::cerr << "ERROR in LauAbsPdf::getMinAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; return 0.0; } Double_t LauAbsPdf::getMaxAbscissa( const TString& theVarName ) const { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { return maxAbscissas_[ index ]; } } std::cerr << "ERROR in LauAbsPdf::getMaxAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; return 0.0; } LauFitData LauAbsPdf::getMinAbscissas() const { LauFitData minAbscissas; for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; minAbscissas[ theVarName ] = minAbscissas_[ varIndex ]; } return minAbscissas; } LauFitData LauAbsPdf::getMaxAbscissas() const { LauFitData maxAbscissas; for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t varIndex = iter->first; const TString& theVarName = iter->second; maxAbscissas[ theVarName ] = maxAbscissas_[ varIndex ]; } return maxAbscissas; } LauFitData LauAbsPdf::getRanges() const { LauFitData minVals = this->getMinAbscissas(); LauFitData maxVals = this->getMaxAbscissas(); LauFitData range; for ( LauFitData::const_iterator iter = maxVals.begin(); iter != maxVals.end(); ++iter ) { const TString& theVarName = iter->first; Double_t maxVal = iter->second; Double_t minVal = minVals.find(theVarName)->second; range[theVarName] = maxVal - minVal; } return range; } void LauAbsPdf::setMinAbscissa(const TString& theVarName, Double_t minAbscissa) { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { minAbscissas_[ index ] = minAbscissa; return; } } std::cerr << "ERROR in LauAbsPdf::setMinAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; } void LauAbsPdf::setMaxAbscissa(const TString& theVarName, Double_t maxAbscissa) { for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { UInt_t index = iter->first; const TString& name = iter->second; if ( name == theVarName ) { maxAbscissas_[ index ] = maxAbscissa; return; } } std::cerr << "ERROR in LauAbsPdf::setMaxAbscissa : Variable \"" << theVarName << "\" not found." << std::endl; } Bool_t LauAbsPdf::checkRange(const LauAbscissas& abscissas) const { // This method assumes the ordering of the abscissas provided match // those of the min and max vectors // check that the size is correct UInt_t nVars = abscissas.size(); if ( this->isDPDependent() ) { nVars = abscissas.size() - 2; // if we depend on the DP we'll have been provided with the DP co-ordinates as well } if ( nVars != minAbscissas_.size() || nVars != maxAbscissas_.size() ) { std::cerr << "ERROR in LauAbsPdf::checkRange : Unexpected number of absicssas: " << nVars << std::endl; - std::cerr << " : " << this->IsA()->GetName() << " expects " << minAbscissas_.size() << std::endl; + std::cerr << " : Expected: " << minAbscissas_.size() << std::endl; + for ( auto [ _, varName ] : varNames_ ) { + std::cerr << " : " << varName << std::endl; + } return kFALSE; } for ( UInt_t i(0); i < nVars; ++i ) { Double_t abscissa = abscissas[i]; Double_t minVal = minAbscissas_[i]; Double_t maxVal = maxAbscissas_[i]; if ( (abscissa < minVal) || (abscissa > maxVal) ) { std::cerr << "ERROR in LauAbsPdf::checkRange : " << abscissa << " outside allowed range: [" << minVal << "," << maxVal << "]" << std::endl; return kFALSE; } } return kTRUE; } void LauAbsPdf::cacheInfo(const LauFitDataTree& inputData) { Bool_t hasBranch(kTRUE); for ( std::map::const_iterator iter = varNames_.begin(); iter != varNames_.end(); ++iter ) { hasBranch &= inputData.haveBranch( iter->second ); if (!hasBranch) { std::cerr << "ERROR in LauAbsPdf::cacheInfo : Input data does not contain variable \"" << iter->second << "\"." << std::endl; return; } } // determine whether we are caching our PDF value Bool_t doCaching( this->nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); // clear the vectors and reserve enough space UInt_t nEvents = inputData.nEvents(); abscissas_.clear(); abscissas_.reserve(nEvents); unNormPDFValues_.clear(); unNormPDFValues_.reserve(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputData.getData(iEvt); LauAbscissas myData; // add all our variables into the data for ( std::map::const_iterator var_iter = varNames_.begin(); var_iter != varNames_.end(); ++var_iter ) { LauFitData::const_iterator iter = dataValues.find( var_iter->second ); myData.push_back( iter->second ); } // if we're DP dependent then we'll need the DP co-ordinates as well if ( this->isDPDependent() ) { LauFitData::const_iterator iter = dataValues.find( "m13Sq" ); myData.push_back( iter->second ); iter = dataValues.find( "m23Sq" ); myData.push_back( iter->second ); } if (!this->checkRange(myData)) { gSystem->Exit(EXIT_FAILURE); } abscissas_.push_back( myData ); if (this->cachePDF()) { this->calcLikelihoodInfo( myData ); unNormPDFValues_.push_back( this->getUnNormLikelihood() ); } } if (!this->cachePDF()) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } } LauFitData LauAbsPdf::generate(const LauKinematics* kinematics) { this->withinGeneration(kTRUE); // Check that the PDF height is up to date // N.B. this must now called every time (the method will simply // return if there is nothing to do) this->calcPDFHeight( kinematics ); Bool_t gotAbscissa(kFALSE); if (randomFun_ == 0) { std::cerr << "ERROR in LauAbsPdf::generate : Please set the random number generator for this PDF by using the setRandomFun(TRandom*) function." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } if ( this->isDPDependent() && !kinematics ) { std::cerr << "ERROR in LauAbsPdf::generate : PDF depends on the DP and an invalid kinematics pointer has been provided." << std::endl; this->withinGeneration(kFALSE); gSystem->Exit(EXIT_FAILURE); } // container for holding the generated abscissa(s) LauAbscissas genAbscissa(1); // Generate the value of the abscissa. Double_t genPDFVal(0.0); Double_t PDFheight = this->getMaxHeight()*(1.0+1e-11); while (!gotAbscissa) { if ( this->isDPDependent() ) { genAbscissa.resize(3); genAbscissa[1] = kinematics->getm13Sq(); genAbscissa[2] = kinematics->getm23Sq(); } genAbscissa[0] = randomFun_->Rndm()*this->getRange() + this->getMinAbscissa(); this->calcLikelihoodInfo(genAbscissa); genPDFVal = this->getUnNormLikelihood(); if (randomFun_->Rndm() <= genPDFVal/PDFheight) {gotAbscissa = kTRUE;} if (genPDFVal > PDFheight) { std::cerr << "WARNING in LauAbsPdf::generate : genPDFVal = " << genPDFVal << " is larger than the maximum PDF height " << this->getMaxHeight() << " for the abscissa = " << genAbscissa[0] << "." << std::endl; std::cerr << " : Need to reset height to be larger than " << genPDFVal << " by using the setMaxHeight(Double_t) function and re-run the Monte Carlo generation!" << std::endl; } } LauFitData genData; genData[ this->varName() ] = genAbscissa[0]; this->withinGeneration(kFALSE); return genData; } Double_t LauAbsPdf::getLikelihood() const { if (TMath::Abs(norm_) > 1e-10) { return unNormPDFVal_/norm_; } else { return 0.0; } } Double_t LauAbsPdf::getLikelihood( const TString& theVarName ) const { if ( theVarName != this->varName() ) { std::cerr << "ERROR in LauAbsPdf::getLikelihood : Unrecognised variable name \"" << theVarName << "\", cannot determine likelihood." << std::endl; return 0.0; } return this->getLikelihood(); } void LauAbsPdf::calcLikelihoodInfo(UInt_t iEvt) { if (this->cachePDF() && (unNormPDFValues_.size() == abscissas_.size())) { unNormPDFVal_ = unNormPDFValues_[iEvt]; } else { this->calcLikelihoodInfo( abscissas_[iEvt] ); } } LauAbsRValue* LauAbsPdf::findParameter(const TString& parName) { for ( std::vector::iterator iter = param_.begin(); iter != param_.end(); ++iter ) { // std::vector params = (*iter)->getPars(); // for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if ((*iter)->name().Contains(parName)) { return (*iter); } // } } std::cerr << "ERROR in LauAbsPdf::findParameter : Parameter \"" << parName << "\" not found." << std::endl; return 0; } const LauAbsRValue* LauAbsPdf::findParameter(const TString& parName) const { for ( std::vector::const_iterator iter = param_.begin(); iter != param_.end(); ++iter ) { // std::vector params = (*iter)->getPars(); // for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if ((*iter)->name().Contains(parName)) { return (*iter); // } } } std::cerr << "ERROR in LauAbsPdf::findParameter : Parameter \"" << parName << "\" not found." << std::endl; return 0; } void LauAbsPdf::updatePulls() { for ( std::vector::iterator iter = param_.begin(); iter != param_.end(); ++iter ) { std::vector params = (*iter)->getPars(); for (std::vector::iterator params_iter = params.begin(); params_iter != params.end(); ++params_iter ) { if (!(*iter)->fixed()) { (*params_iter)->updatePull(); } } } } void LauAbsPdf::addParameters(std::vector& params) { for ( std::vector::iterator iter = params.begin(); iter != params.end(); ++iter ) { param_.push_back(*iter); } } void LauAbsPdf::calcNorm() { this->withinNormCalc(kTRUE); if ( this->nInputVars() > 1 ) { std::cerr << "ERROR in LauAbsPdf::calcNorm : Numeric integration only works for 1D PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } IntMethod sumMethod = this->integMethod(); Double_t normFac = (sumMethod == GaussLegendre) ? this->integrGaussLegendre() : this->integTrapezoid(); this->setNorm(normFac); this->withinNormCalc(kFALSE); } Double_t LauAbsPdf::integrGaussLegendre() { if (!this->normWeightsDone()) { this->getNormWeights(); } // Now compute the integral Double_t norm(0.0); for (UInt_t i = 0; i < normWeights_.size(); i++) { this->calcLikelihoodInfo(normAbscissas_[i]); Double_t fun = this->getUnNormLikelihood(); Double_t intFactor = 0.5 * this->getRange(); norm += normWeights_[i]*intFactor*fun; } //std::cout<<"====================================================="<normWeightsDone()) { std::cerr << "WARNING in LauAbsPdf::getNormWeights : Already calculated weights, not doing it again." << std::endl; return; } // Avoid integral if we have no points in x space if (nNormPoints_ == 0) { std::cerr << "ERROR in LauAbsPdf::getNormWeights : Zero points specified, this is daft!" << std::endl; return; } // Calculate the normalisation weights and abscissas Double_t precision(1e-6); Double_t intMean = 0.5*(this->getMaxAbscissa() + this->getMinAbscissa()); Double_t range = this->getMaxAbscissa() - this->getMinAbscissa(); Double_t halfRange = 0.5*range; std::vector abscissas; LauIntegrals funIntegrals(precision); funIntegrals.calcGaussLegendreWeights(nNormPoints_, abscissas, normWeights_); //std::cout<<"====================================================="<(normWeights_.size()); normAbscissas_.resize(nWeights); // Use same number of abscissas for x and y co-ordinates Int_t m = (nWeights + 1)/2; for (Int_t i = 0; i < m; ++i) { Int_t ii = nWeights - 1 - i; // symmetric i index Double_t dx = halfRange*abscissas[i]; Double_t tmpVal = intMean - dx; normAbscissas_[i].push_back( tmpVal ); tmpVal = intMean + dx; normAbscissas_[ii].push_back( tmpVal ); } this->normWeightsDone(kTRUE); } Double_t LauAbsPdf::integTrapezoid() { Double_t abscVal, tnm, sum, del; Int_t it, j; static Double_t norm(0.0); Double_t range = this->getRange(); if (this->nNormPoints()==1){ LauAbscissas abscissa(1); abscissa[0] = this->getMinAbscissa(); this->calcLikelihoodInfo(abscissa); Double_t funAbsMin = this->getUnNormLikelihood(); abscissa[0] = this->getMinAbscissa(); this->calcLikelihoodInfo(abscissa); Double_t funAbsMax = this->getUnNormLikelihood(); norm = 0.5*range*(funAbsMin+funAbsMax); return norm; } else { for (it=1, j=1; j< this->nNormPoints()-1; j++) {it<<=1;} tnm=it; del=range/tnm; abscVal= this->getMinAbscissa()+ 0.5*del; for (sum = 0.0, j=1; jcalcLikelihoodInfo(abscissa); Double_t funVal = this->getUnNormLikelihood(); sum+=funVal; } norm = 0.5*(norm + sum*range/tnm); return norm; } } diff --git a/src/LauAbsResonance.cc b/src/LauAbsResonance.cc index 185e22b..699ecd4 100644 --- a/src/LauAbsResonance.cc +++ b/src/LauAbsResonance.cc @@ -1,682 +1,681 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsResonance.cc \brief File containing implementation of LauAbsResonance class. */ #include #include "TSystem.h" #include "LauAbsResonance.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauAbsResonance) bool LauAbsResonance::isIncoherentModel(LauResonanceModel model) { switch(model) { case BW: case RelBW: case GS: case Flatte: case Sigma: case Kappa: case Dabba: case LASS: case LASS_BW: case LASS_NR: case EFKLLM: case KMatrix: case FlatNR: case NRModel: case BelleNR: case PowerLawNR: case BelleSymNR: case BelleSymNRNoInter: case TaylorNR: case PolNR: case Pole: case PolarFFNR: case PolarFFSymNR: case PolarFFSymNRNoInter: case Rescattering: case Rescattering2: case RescatteringNoInter: case MIPW_MagPhase: case MIPW_RealImag: case RhoOmegaMix_GS: case RhoOmegaMix_RBW: case RhoOmegaMix_GS_1: case RhoOmegaMix_RBW_1: break; case GaussIncoh: return true; } return false; } // Constructor LauAbsResonance::LauAbsResonance(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : resInfo_(resInfo), daughters_(daughters), resName_( (resInfo!=0) ? resInfo->getName() : "" ), sanitisedName_( (resInfo!=0) ? resInfo->getSanitisedName() : "" ), resMass_( (resInfo!=0) ? resInfo->getMass() : 0 ), resWidth_( (resInfo!=0) ? resInfo->getWidth() : 0 ), resSpin_( (resInfo!=0) ? resInfo->getSpin() : 0 ), resCharge_( (resInfo!=0) ? resInfo->getCharge() : 0 ), resPairAmpInt_(resPairAmpInt) { if ( resInfo == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauResonanceInfo object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( daughters_ == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauDaughters object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } nameParent_ = this->getNameParent(); nameDaug1_ = this->getNameDaug1(); nameDaug2_ = this->getNameDaug2(); nameBachelor_ = this->getNameBachelor(); massParent_ = this->getMassParent(); massDaug1_ = this->getMassDaug1(); massDaug2_ = this->getMassDaug2(); massBachelor_ = this->getMassBachelor(); chargeParent_ = this->getChargeParent(); chargeDaug1_ = this->getChargeDaug1(); chargeDaug2_ = this->getChargeDaug2(); chargeBachelor_ = this->getChargeBachelor(); // check that the total charge adds up to that of the resonance Int_t totalCharge = chargeDaug1_ + chargeDaug2_; if ( (totalCharge != resCharge_) && (resPairAmpInt_ != 0) ) { std::cerr << "ERROR in LauAbsResonance : Total charge of daughters = " << totalCharge << ". Resonance charge = " << resCharge_ << "." << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Constructor LauAbsResonance::LauAbsResonance(const TString& resName, const Int_t resPairAmpInt, const LauDaughters* daughters, const Int_t resSpin) : daughters_(daughters), resName_(resName), sanitisedName_(resName), resSpin_(resSpin), resPairAmpInt_(resPairAmpInt) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauAbsResonance constructor : null LauDaughters object provided" << std::endl; gSystem->Exit(EXIT_FAILURE); } nameParent_ = this->getNameParent(); nameDaug1_ = this->getNameDaug1(); nameDaug2_ = this->getNameDaug2(); nameBachelor_ = this->getNameBachelor(); massParent_ = this->getMassParent(); massDaug1_ = this->getMassDaug1(); massDaug2_ = this->getMassDaug2(); massBachelor_ = this->getMassBachelor(); chargeParent_ = this->getChargeParent(); chargeDaug1_ = this->getChargeDaug1(); chargeDaug2_ = this->getChargeDaug2(); chargeBachelor_ = this->getChargeBachelor(); // Since we haven't been provided with a LauResonanceInfo object we can just // set the change of the resonance to be the sum of the daughter charges resCharge_ = chargeDaug1_ + chargeDaug2_; } // Destructor LauAbsResonance::~LauAbsResonance() { } LauComplex LauAbsResonance::amplitude(const LauKinematics* kinematics) { // Use LauKinematics interface for amplitude // For resonance made from tracks i, j, we need the momenta // of tracks i and k in the i-j rest frame for spin helicity calculations // in the Zemach tensor formalism. // Also need the momentum of track k in the parent rest-frame for // calculation of the Blatt-Weisskopf factors. mass_ = 0.0; cosHel_ = 0.0; q_ = 0.0; p_ = 0.0; pstar_ = 0.0; erm_ = 1.0; covFactor_ = 1.0; if (resPairAmpInt_ == 1) { mass_ = kinematics->getm23(); cosHel_ = kinematics->getc23(); q_ = kinematics->getp2_23(); p_ = kinematics->getp1_23(); pstar_ = kinematics->getp1_Parent(); erm_ = kinematics->getcov23(); } else if (resPairAmpInt_ == 2) { mass_ = kinematics->getm13(); cosHel_ = kinematics->getc13(); q_ = kinematics->getp1_13(); p_ = kinematics->getp2_13(); pstar_ = kinematics->getp2_Parent(); erm_ = kinematics->getcov13(); } else if (resPairAmpInt_ == 3) { mass_ = kinematics->getm12(); cosHel_ = kinematics->getc12(); q_ = kinematics->getp1_12(); p_ = kinematics->getp3_12(); pstar_ = kinematics->getp3_Parent(); erm_ = kinematics->getcov12(); } else { std::cerr << "ERROR in LauAbsResonance::amplitude : Nonsense setup of resPairAmp array." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (this->flipHelicity()) { cosHel_ *= -1.0; } if (this->ignoreMomenta()) { q_ = 1.0; p_ = 1.0; pstar_ = 1.0; erm_ = 1.0; } // Calculate the spin factors Double_t spinTerm(1.0); Double_t pProd(1.0); if (!this->ignoreSpin()) { switch ( this->getSpinType() ) { case Zemach_P: pProd = q_*p_; spinTerm = this->calcZemachSpinFactor( pProd ); break; case Zemach_Pstar: pProd = q_*pstar_; spinTerm = this->calcZemachSpinFactor( pProd ); break; case Covariant: pProd = q_*pstar_; spinTerm = this->calcCovSpinFactor( pProd ); break; case Legendre: spinTerm = this->calcLegendrePoly(); break; } } // Calculate the full amplitude LauComplex resAmplitude = this->resAmp(mass_, spinTerm); return resAmplitude; } void LauAbsResonance::calcCovFactor( const Double_t erm ) { if (resSpin_ == 0) { covFactor_ = 1.0; } else if (resSpin_ == 1) { covFactor_ = erm; } else if (resSpin_ == 2) { covFactor_ = erm*erm + 0.5; } else if (resSpin_ == 3) { covFactor_ = erm*(erm*erm + 1.5); } else if (resSpin_ == 4) { covFactor_ = (8.*erm*erm*erm*erm + 24.*erm*erm + 3.)/35.; } else if (resSpin_ > 4) { std::cerr << "WARNING in LauAbsResonance::calcCovFactor : covariant spin factor cannot (yet) be fully calculated for spin >= 5" << std::endl; std::cerr << " : the function of sqrt(1 + (p/mParent)^2) part will be missing" << std::endl; covFactor_ = 1.0; } } Double_t LauAbsResonance::calcCovSpinFactor( const Double_t pProd ) { if (resSpin_ == 0) { covFactor_ = 1.0; return 1.0; } // Covariant spin factor is (p* q)^L * f_L(erm) * P_L(cosHel) Double_t spinFactor(pProd); for ( Int_t i(1); i < resSpin_; ++i ) { spinFactor *= pProd; } this->calcCovFactor( erm_ ); spinFactor *= covFactor_; spinFactor *= this->calcLegendrePoly(); return spinFactor; } Double_t LauAbsResonance::calcZemachSpinFactor( const Double_t pProd ) const { // Calculate the spin factors // // These are calculated as follows // // -2^j * (q*p)^j * cj * Pj(cosHel) // // where Pj(coshHel) is the jth order Legendre polynomial and // // cj = j! / (2j-1)!! if (resSpin_ == 0) { return 1.0; } Double_t spinFactor(pProd); for ( Int_t i(1); i < resSpin_; ++i ) { spinFactor *= pProd; } spinFactor *= this->calcLegendrePoly(); return spinFactor; } Double_t LauAbsResonance::calcLegendrePoly( const Double_t cosHel ) { cosHel_ = cosHel; return this->calcLegendrePoly(); } Double_t LauAbsResonance::calcLegendrePoly() const { Double_t legPol = 1.0; if (resSpin_ == 1) { // Calculate vector resonance Legendre polynomial legPol = -2.0*cosHel_; } else if (resSpin_ == 2) { // Calculate tensor resonance Legendre polynomial legPol = 4.0*(3.0*cosHel_*cosHel_ - 1.0)/3.0; } else if (resSpin_ == 3) { // Calculate spin 3 resonance Legendre polynomial legPol = -8.0*(5.0*cosHel_*cosHel_*cosHel_ - 3.0*cosHel_)/5.0; } else if (resSpin_ == 4) { // Calculate spin 4 resonance Legendre polynomial legPol = 16.0*(35.0*cosHel_*cosHel_*cosHel_*cosHel_ - 30.0*cosHel_*cosHel_ + 3.0)/35.0; } else if (resSpin_ == 5) { // Calculate spin 5 resonance Legendre polynomial legPol = -32.0*(63.0*cosHel_*cosHel_*cosHel_*cosHel_*cosHel_ - 70.0*cosHel_*cosHel_*cosHel_ + 15.0*cosHel_)/63.0; } else if (resSpin_ > 5) { std::cerr << "WARNING in LauAbsResonance::calcLegendrePoly : Legendre polynomials not (yet) implemented for spin > 5" << std::endl; } return legPol; } void LauAbsResonance::changeResonance(const Double_t newMass, const Double_t newWidth, const Int_t newSpin) { if (newMass > 0.0) { resMass_->valueAndRange(newMass,0.0,3.0*newMass); resMass_->initValue(newMass); resMass_->genValue(newMass); std::cout << "INFO in LauAbsResonance::changeResonance : Setting mass to " << resMass_->value() << std::endl; } if (newWidth > 0.0) { resWidth_->valueAndRange(newWidth,0.0,3.0*newWidth); resWidth_->initValue(newWidth); resWidth_->genValue(newWidth); std::cout << "INFO in LauAbsResonance::changeResonance : Setting width to " << resWidth_->value() << std::endl; } if (newSpin > -1) { resSpin_ = newSpin; std::cout << "INFO in LauAbsResonance::changeResonance : Setting spin to " << resSpin_ << std::endl; } } void LauAbsResonance::changeBWBarrierRadii(const Double_t resRadius, const Double_t parRadius) { if ( resRadius >= 0.0 && resBWFactor_ != 0 ) { LauParameter* resBWRadius = resBWFactor_->getRadiusParameter(); resBWRadius->value(resRadius); resBWRadius->initValue(resRadius); resBWRadius->genValue(resRadius); std::cout << "INFO in LauAbsResonance::changeBWBarrierRadii : Setting resonance factor radius to " << resBWRadius->value() << std::endl; } if ( parRadius >= 0.0 && parBWFactor_ != 0 ) { LauParameter* parBWRadius = parBWFactor_->getRadiusParameter(); parBWRadius->value(parRadius); parBWRadius->initValue(parRadius); parBWRadius->genValue(parRadius); std::cout << "INFO in LauAbsResonance::changeBWBarrierRadii : Setting parent factor radius to " << parBWRadius->value() << std::endl; } } void LauAbsResonance::setResonanceParameter(const TString& name, const Double_t value) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::setResonanceParameter : Unable to set parameter \"" << name << "\" to value: " << value << "." << std::endl; } void LauAbsResonance::floatResonanceParameter(const TString& name) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::floatResonanceParameter : Unable to release parameter \"" << name << "\"." << std::endl; } LauParameter* LauAbsResonance::getResonanceParameter(const TString& name) { //This function should always be overwritten if needed in classes inheriting from LauAbsResonance. std::cerr << "WARNING in LauAbsResonance::getResonanceParameter : Unable to get parameter \"" << name << "\"." << std::endl; return 0; } void LauAbsResonance::addFloatingParameter( LauParameter* param ) { if ( param == 0 ) { return; } if ( param->clone() ) { resParameters_.push_back( param->parent() ); } else { resParameters_.push_back( param ); } } void LauAbsResonance::fixBarrierRadii(const Bool_t fixResRad, const Bool_t fixParRad) { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixBarrierRadii : resonance barrier factor not present, cannot fix/float it" << std::endl; return; } if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixBarrierRadii : parent barrier factor not present, cannot fix/float it" << std::endl; return; } LauParameter* resBWRadius = resBWFactor_->getRadiusParameter(); resBWRadius->fixed(fixResRad); LauParameter* parBWRadius = parBWFactor_->getRadiusParameter(); parBWRadius->fixed(fixParRad); } Bool_t LauAbsResonance::fixResRadius() const { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixResRadius : resonance barrier factor not present" << std::endl; return kTRUE; } LauParameter* bwRadius = resBWFactor_->getRadiusParameter(); return bwRadius->fixed(); } Bool_t LauAbsResonance::fixParRadius() const { if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::fixParRadius : parent barrier factor not present" << std::endl; return kTRUE; } LauParameter* bwRadius = parBWFactor_->getRadiusParameter(); return bwRadius->fixed(); } Double_t LauAbsResonance::getResRadius() const { if ( resBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::getResRadius : resonance barrier factor not present" << std::endl; return -1.0; } LauParameter* bwRadius = resBWFactor_->getRadiusParameter(); return bwRadius->unblindValue(); } Double_t LauAbsResonance::getParRadius() const { if ( parBWFactor_ == 0 ) { std::cerr << "WARNING in LauAbsResonance::getParRadius : parent barrier factor not present" << std::endl; return -1.0; } LauParameter* bwRadius = parBWFactor_->getRadiusParameter(); return bwRadius->unblindValue(); } Double_t LauAbsResonance::getMassParent() const { // Get the parent mass Double_t mass(LauConstants::mB); if (daughters_) { mass = daughters_->getMassParent(); } return mass; } Double_t LauAbsResonance::getMassDaug1() const { // Get the daughter mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug2(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug1(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug1(); } } return mass; } Double_t LauAbsResonance::getMassDaug2() const { // Get the daughter mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug3(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug3(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug2(); } } return mass; } Double_t LauAbsResonance::getMassBachelor() const { // Get the bachelor mass Double_t mass(LauConstants::mPi); if (daughters_) { if (resPairAmpInt_ == 1) { mass = daughters_->getMassDaug1(); } else if (resPairAmpInt_ == 2) { mass = daughters_->getMassDaug2(); } else if (resPairAmpInt_ == 3) { mass = daughters_->getMassDaug3(); } } return mass; } Int_t LauAbsResonance::getChargeParent() const { // Get the parent charge Int_t charge(0); if (daughters_) { charge = daughters_->getChargeParent(); } return charge; } Int_t LauAbsResonance::getChargeDaug1() const { // Get the daughter charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug2(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug1(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug1(); } } return charge; } Int_t LauAbsResonance::getChargeDaug2() const { // Get the daughter charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug3(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug3(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug2(); } } return charge; } Int_t LauAbsResonance::getChargeBachelor() const { // Get the bachelor charge Int_t charge(0); if (daughters_) { if (resPairAmpInt_ == 1) { charge = daughters_->getChargeDaug1(); } else if (resPairAmpInt_ == 2) { charge = daughters_->getChargeDaug2(); } else if (resPairAmpInt_ == 3) { charge = daughters_->getChargeDaug3(); } } return charge; } TString LauAbsResonance::getNameParent() const { // Get the parent name TString name(""); if (daughters_) { name = daughters_->getNameParent(); } return name; } TString LauAbsResonance::getNameDaug1() const { // Get the daughter name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug2(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug1(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug1(); } } return name; } TString LauAbsResonance::getNameDaug2() const { // Get the daughter name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug3(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug3(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug2(); } } return name; } TString LauAbsResonance::getNameBachelor() const { // Get the bachelor name TString name(""); if (daughters_) { if (resPairAmpInt_ == 1) { name = daughters_->getNameDaug1(); } else if (resPairAmpInt_ == 2) { name = daughters_->getNameDaug2(); } else if (resPairAmpInt_ == 3) { name = daughters_->getNameDaug3(); } } return name; } diff --git a/src/LauArgusPdf.cc b/src/LauArgusPdf.cc index 593b4b0..87b7a9f 100644 --- a/src/LauArgusPdf.cc +++ b/src/LauArgusPdf.cc @@ -1,149 +1,148 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauArgusPdf.cc \brief File containing implementation of LauArgusPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauArgusPdf.hh" #include "LauConstants.hh" -ClassImp(LauArgusPdf) LauArgusPdf::LauArgusPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), xi_(0), m0_(0) { // Constructor for the ARGUS PDF. // // The parameters in params are the shape, xi, and the end-point of the curve. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. xi_ = this->findParameter("xi"); m0_ = this->findParameter("m0"); if ((this->nParameters() != 2) || (xi_ == 0) || (m0_ == 0)) { std::cerr << "ERROR in LauArgusPdf constructor: LauArgusPdf requires 2 parameters: argus shape parameter, \"xi\", and end-point, \"m0\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor. this->calcNorm(); } LauArgusPdf::~LauArgusPdf() { // Destructor } void LauArgusPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // Calculate the value of the ARGUS function for the given value of the abscissa. Double_t x = abscissa/m0; Double_t term = 1.0 - x*x; if (term < 0.0) {term = 0.0;} // In case |x| > 1.0 (which should happen rarely). Double_t value = abscissa*TMath::Sqrt(term)*TMath::Exp(-xi*term); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauArgusPdf::calcNorm() { // Calculate the PDF normalisation and cache it // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // Since the PDF is 0 above m0 by definition need to check whether m0 is within the range, above it or below it Double_t min = (this->getMinAbscissa() < m0) ? this->getMinAbscissa() : m0; Double_t max = (this->getMaxAbscissa() < m0) ? this->getMaxAbscissa() : m0; // Define variables equivalent to "term" in calcLikelihoodInfo above but at the min and max points Double_t termMin = 1.0 - (min/m0)*(min/m0); Double_t termMax = 1.0 - (max/m0)*(max/m0); // Calculate the various terms in the integrals Double_t norm1 = TMath::Sqrt(termMax)*TMath::Exp(-xi*termMax) - TMath::Sqrt(termMin)*TMath::Exp(-xi*termMin); Double_t norm2 = LauConstants::rootPi/(2.0*TMath::Sqrt(xi)) * ( TMath::Erf(TMath::Sqrt(xi*termMax)) - TMath::Erf(TMath::Sqrt(xi*termMin)) ); // Combine them and set the normalisation Double_t norm = m0*m0*(norm1 - norm2)/(2.0*xi); this->setNorm(norm); } void LauArgusPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Calculate the PDF height of the ARGUS function. // Get the up to date parameter values Double_t xi = xi_->unblindValue(); Double_t m0 = m0_->unblindValue(); // First make sure that the limits are not larger than the end-point. // (Btw, use the logarithmic derivative to derive this formula) Double_t term = xi*xi + 1.0; Double_t x = TMath::Sqrt((TMath::Sqrt(term) - 1.0 + xi)/(2.0*xi)); x = (x*m0 >= this->getMinAbscissa()) ? x*m0 : this->getMinAbscissa(); LauAbscissas abscissa(1); abscissa[0] = x; this->calcLikelihoodInfo(abscissa); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauAsymmCalc.cc b/src/LauAsymmCalc.cc index 388ab32..cee5894 100644 --- a/src/LauAsymmCalc.cc +++ b/src/LauAsymmCalc.cc @@ -1,76 +1,75 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAsymmCalc.cc \brief File containing implementation of LauAsymmCalc class. */ #include "TMath.h" #include "LauAsymmCalc.hh" -ClassImp(LauAsymmCalc) LauAsymmCalc::LauAsymmCalc(Double_t negValue, Double_t posValue) : negValue_(negValue), posValue_(posValue), asymm_(0.0) { asymm_ = calcAsymmetry(); } LauAsymmCalc::LauAsymmCalc(const LauAsymmCalc& rhs) : negValue_(rhs.negValue_), posValue_(rhs.posValue_), asymm_(rhs.asymm_) { } LauAsymmCalc& LauAsymmCalc::operator=(const LauAsymmCalc& rhs) { if ( &rhs != this ) { negValue_ = rhs.negValue_; posValue_ = rhs.posValue_; asymm_ = rhs.asymm_; } return *this; } LauAsymmCalc::~LauAsymmCalc() { } Double_t LauAsymmCalc::calcAsymmetry() { Double_t num = negValue_ - posValue_; Double_t denom = negValue_ + posValue_; Double_t asymm(0.0); if (TMath::Abs(denom) > 1e-10) { asymm = num/denom; } return asymm; } diff --git a/src/LauBelleCPCoeffSet.cc b/src/LauBelleCPCoeffSet.cc index 5fe967f..edfe493 100644 --- a/src/LauBelleCPCoeffSet.cc +++ b/src/LauBelleCPCoeffSet.cc @@ -1,349 +1,348 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleCPCoeffSet.cc \brief File containing implementation of LauBelleCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauBelleCPCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauBelleCPCoeffSet) LauBelleCPCoeffSet::LauBelleCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage, Bool_t phiSecondStage) : LauAbsCoeffSet(compName), a_(new LauParameter("A", a, minMagnitude_, maxMagnitude_, aFixed)), b_(new LauParameter("B", b, minMagnitude_, maxMagnitude_, bFixed)), delta_(new LauParameter("Delta", delta, minPhase_, maxPhase_, deltaFixed)), phi_(new LauParameter("Phi", phi, minPhase_, maxPhase_, phiFixed)), particleCoeff_(0.0,0.0), antiparticleCoeff_(0.0,0.0), acp_("ACP", (-2.0*b*TMath::Cos(phi))/(1.0+b*b), -1.0, 1.0, bFixed&&phiFixed) { if (bSecondStage && !bFixed) { b_->secondStage(kTRUE); b_->initValue(0.0); } if (phiSecondStage && !phiFixed) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } } LauBelleCPCoeffSet::LauBelleCPCoeffSet(const LauBelleCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), a_(0), b_(0), delta_(0), phi_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { a_ = rhs.a_->createClone(constFactor); } else { a_ = new LauParameter("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); if ( rhs.a_->blind() ) { const LauBlind* blinder = rhs.a_->blinder(); a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { b_ = rhs.b_->createClone(constFactor); } else { b_ = new LauParameter("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); if ( rhs.b_->blind() ) { const LauBlind* blinder = rhs.b_->blinder(); b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { delta_ = rhs.delta_->createClone(constFactor); } else { delta_ = new LauParameter("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); if ( rhs.delta_->blind() ) { const LauBlind* blinder = rhs.delta_->blinder(); delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { phi_ = rhs.phi_->createClone(constFactor); } else { phi_ = new LauParameter("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); if ( rhs.phi_->blind() ) { const LauBlind* blinder = rhs.phi_->blinder(); phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauBelleCPCoeffSet::getParameters() { std::vector pars; pars.push_back(a_); pars.push_back(b_); pars.push_back(delta_); pars.push_back(phi_); return pars; } void LauBelleCPCoeffSet::printParValues() const { std::cout<<"INFO in LauBelleCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"a-magnitude = "<value()<<",\t"; std::cout<<"delta = "<value()<<",\t"; std::cout<<"b-magnitude = "<value()<<",\t"; std::cout<<"phi = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, a_->error()); stream<<"$ & $"; print.printFormat(stream, delta_->value()); stream<<" \\pm "; print.printFormat(stream, delta_->error()); stream<<"$ & $"; print.printFormat(stream, b_->value()); stream<<" \\pm "; print.printFormat(stream, b_->error()); stream<<"$ & $"; print.printFormat(stream, phi_->value()); stream<<" \\pm "; print.printFormat(stream, phi_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose an a-magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; a_->initValue(mag); a_->value(mag); } if (b_->fixed() == kFALSE && b_->secondStage() == kFALSE) { // Choose a b-magnitude between 0.0 and 0.1 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*0.1; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; delta_->initValue(phase); delta_->value(phase); } if (phi_->fixed() == kFALSE && phi_->secondStage() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phi_->initValue(phase); phi_->value(phase); } } void LauBelleCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t aVal = a_->value(); Double_t bVal = b_->value(); Double_t deltaVal = delta_->value(); Double_t phiVal = phi_->value(); Double_t genDelta = delta_->genValue(); Double_t genPhi = phi_->genValue(); // Check whether we have a negative "a" magnitude. // If so make it positive and add pi to the "delta" phase. if (aVal < 0.0) { aVal *= -1.0; deltaVal += LauConstants::pi; } // Check whether we have a negative "b" magnitude. // If so make it positive and add pi to the "phi" phase. if (bVal < 0.0) { bVal *= -1.0; phiVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t deltaWithinRange(kFALSE); Bool_t phiWithinRange(kFALSE); while (deltaWithinRange == kFALSE && phiWithinRange == kFALSE) { if (deltaVal > -LauConstants::pi && deltaVal < LauConstants::pi) { deltaWithinRange = kTRUE; } else { // Not within the specified range if (deltaVal > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (deltaVal < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } } if (phiVal > -LauConstants::pi && phiVal < LauConstants::pi) { phiWithinRange = kTRUE; } else { // Not within the specified range if (phiVal > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (phiVal < -LauConstants::pi) { phiVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaVal - genDelta; if (diff > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } diff = phiVal - genPhi; if (diff > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phiVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls a_->value(aVal); a_->updatePull(); b_->value(bVal); b_->updatePull(); delta_->value(deltaVal); delta_->updatePull(); phi_->value(phiVal); phi_->updatePull(); } const LauComplex& LauBelleCPCoeffSet::particleCoeff() { LauComplex aTerm(a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())); LauComplex bTerm(b_->unblindValue()*TMath::Cos(phi_->unblindValue()), b_->unblindValue()*TMath::Sin(phi_->unblindValue())); particleCoeff_.setRealImagPart(1.0,0.0); particleCoeff_ += bTerm; particleCoeff_ *= aTerm; return particleCoeff_; } const LauComplex& LauBelleCPCoeffSet::antiparticleCoeff() { LauComplex aTerm(a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())); LauComplex bTerm(b_->unblindValue()*TMath::Cos(phi_->unblindValue()), b_->unblindValue()*TMath::Sin(phi_->unblindValue())); antiparticleCoeff_.setRealImagPart(1.0,0.0); antiparticleCoeff_ -= bTerm; antiparticleCoeff_ *= aTerm; return antiparticleCoeff_; } void LauBelleCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex sum = coeff + coeffBar; LauComplex diff = coeff - coeffBar; LauComplex ratio = diff / sum; Double_t aVal( 0.5 * sum.abs() ); Double_t deltaVal( sum.arg() ); Double_t bVal( ratio.abs() ); Double_t phiVal( ratio.arg() ); a_->value( aVal ); delta_->value( deltaVal ); b_->value( bVal ); phi_->value( phiVal ); if ( init ) { a_->genValue( aVal ); delta_->genValue( deltaVal ); b_->genValue( bVal ); phi_->genValue( phiVal ); a_->initValue( aVal ); delta_->initValue( deltaVal ); b_->initValue( bVal ); phi_->initValue( phiVal ); } } LauParameter LauBelleCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t value = (-2.0*b_->value()*TMath::Cos(phi_->value()))/(1.0+b_->value()*b_->value()); // is it fixed? Bool_t fixed = b_->fixed() && phi_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauBelleCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude || cloneOption == TieCPPars ) { clone = new LauBelleCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauBelleCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauBelleNR.cc b/src/LauBelleNR.cc index 23c1785..940228c 100644 --- a/src/LauBelleNR.cc +++ b/src/LauBelleNR.cc @@ -1,150 +1,149 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleNR.cc \brief File containing implementation of LauBelleNR class. */ #include #include "TMath.h" #include "LauBelleNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBelleNR) LauBelleNR::LauBelleNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), alpha_(0), model_(resType), forceLegendre_(kTRUE) { TString parName = this->getSanitisedName(); parName += "_alpha"; alpha_ = resInfo->getExtraParameter( parName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( parName, 0.0, -2.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } } LauBelleNR::~LauBelleNR() { } void LauBelleNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauBelleNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } if ( model_ != LauAbsResonance::BelleNR && model_ != LauAbsResonance::PowerLawNR ) { std::cerr << "WARNING in LauBelleNR::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::BelleNR; } // Make the spin term purely the Legendre polynomial of the cos(helicity angle) if ( forceLegendre_ ) { this->setSpinType( LauAbsResonance::Legendre ); } } LauComplex LauBelleNR::resAmp(Double_t mass, Double_t spinTerm) { Double_t magnitude(1.0); Double_t alpha = this->getAlpha(); if ( model_ == LauAbsResonance::BelleNR ) { magnitude = spinTerm * TMath::Exp(-alpha*mass*mass); } else if ( model_ == LauAbsResonance::PowerLawNR ) { magnitude = spinTerm * TMath::Power(mass*mass, -alpha); } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauBelleNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixAlpha() ) { this->addFloatingParameter( alpha_ ); } return this->getParameters(); } void LauBelleNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "alpha") { this->setAlpha(value); std::cout << "INFO in LauBelleNR::setResonanceParameter : Setting parameter alpha = " << this->getAlpha() << std::endl; } else { std::cerr << "WARNING in LauBelleNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauBelleNR::floatResonanceParameter(const TString& name) { if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauBelleNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauBelleNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauBelleNR::getResonanceParameter(const TString& name) { if (name == "alpha") { return alpha_; } else { std::cerr << "WARNING in LauBelleNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauBelleNR::setAlpha(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } diff --git a/src/LauBelleSymNR.cc b/src/LauBelleSymNR.cc index a862bc6..6f26bf9 100644 --- a/src/LauBelleSymNR.cc +++ b/src/LauBelleSymNR.cc @@ -1,187 +1,186 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleSymNR.cc \brief File containing implementation of LauBelleSymNR class. */ #include #include "TMath.h" #include "LauBelleSymNR.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBelleSymNR) LauBelleSymNR::LauBelleSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), alpha_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_alpha"; alpha_ = resInfo->getExtraParameter( parName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( parName, 0.0, 0.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } } LauBelleSymNR::~LauBelleSymNR() { } void LauBelleSymNR::initialise() { const LauDaughters* daughters = this->getDaughters(); if ( ! daughters->gotSymmetricalDP() ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } Int_t resPairAmpInt = this->getPairInt(); if ( resPairAmpInt == 3 ) { std::cerr << "WARNING in LauBelleSymNR::initialise : This lineshape is intended to be on the symmetrised axes of the DP." << std::endl; } if ( (model_ != LauAbsResonance::BelleSymNR) && (model_ != LauAbsResonance::BelleSymNRNoInter) && (model_ != LauAbsResonance::TaylorNR) ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::BelleSymNR; } if ( (model_ != LauAbsResonance::BelleSymNRNoInter) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauBelleSymNR::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::BelleSymNRNoInter instead" << std::endl; } // NB we do not need to call setSpinType(LauAbsResonance::Legendre) here (as is done in LauBelleNR) since override the amplitude method and explicitly use calcLegendrePoly } LauComplex LauBelleSymNR::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Belle Non-Resonant distribution // Calculate for symmetric DPs, e.g. 3pi or 3K, by using shapeNo = 1 or 2 // Have s<->t symmetry already done in Dynamics flip function. // For Kpipi or similar plots, one can use the separate exponentials // and consider them as two separate components with their own mag and phase. // For this shapeNo = 3 and shapeNo = 4 need to be used to create the two // individual amplitudes (with the same value of alpha). // Calculate Mandelstam variables. // s = m_13^2, t = m_23^2 const Double_t s = kinematics->getm13Sq(); const Double_t t = kinematics->getm23Sq(); Double_t magnitude(1.0); const Double_t alpha = this->getAlpha(); if ( model_ == LauAbsResonance::BelleSymNR ) { magnitude = TMath::Exp(-alpha*s) + TMath::Exp(-alpha*t); } else if ( model_ == LauAbsResonance::BelleSymNRNoInter ) { magnitude = (s <= t) ? TMath::Exp(-alpha*s) : TMath::Exp(-alpha*t); const Double_t cosHel = (s <= t) ? kinematics->getc13() : kinematics->getc23(); magnitude *= this->calcLegendrePoly( cosHel ); } else if ( model_ == LauAbsResonance::TaylorNR ) { const Double_t mParentSq = kinematics->getmParentSq(); magnitude = alpha*(s + t)/mParentSq + 1.0; } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } LauComplex LauBelleSymNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauBelleSymNR : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauBelleSymNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixAlpha() ) { this->addFloatingParameter( alpha_ ); } return this->getParameters(); } void LauBelleSymNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "alpha") { this->setAlpha(value); std::cout << "INFO in LauBelleSymNR::setResonanceParameter : Setting parameter alpha = " << this->getAlpha() << std::endl; } else { std::cerr << "WARNING in LauBelleSymNR::setResonanceParameter : Parameter name not reconised. No parameter changes made." << std::endl; } } void LauBelleSymNR::floatResonanceParameter(const TString& name) { if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauBelleSymNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauBelleSymNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauBelleSymNR::getResonanceParameter(const TString& name) { if (name == "alpha") { return alpha_; } else { std::cerr << "WARNING in LauBelleSymNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauBelleSymNR::setAlpha(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } diff --git a/src/LauBifurcatedGaussPdf.cc b/src/LauBifurcatedGaussPdf.cc index 9d51c99..340e492 100644 --- a/src/LauBifurcatedGaussPdf.cc +++ b/src/LauBifurcatedGaussPdf.cc @@ -1,165 +1,164 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBifurcatedGaussPdf.cc \brief File containing implementation of LauBifurcatedGaussPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauBifurcatedGaussPdf.hh" #include "LauConstants.hh" -ClassImp(LauBifurcatedGaussPdf) LauBifurcatedGaussPdf::LauBifurcatedGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigmaL_(0), sigmaR_(0) { // Constructor for the bifurcated Gaussian PDF. // The bifurcated Gaussian combines the left half of a // Gaussian with resolution sigmaL with the right half // of a Gaussian with resolution sigmaR, both having // a common mean (or more correctly, peak position). // NB the parameters in params are the mean, sigmaL and sigmaR // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaL_ = this->findParameter("sigmaL"); sigmaR_ = this->findParameter("sigmaR"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigmaL_ == 0) || (sigmaR_ == 0) ) { std::cerr << "ERROR in LauBifurcatedGaussPdf constructor: LauBifurcatedGaussPdf requires 3 parameters: \"mean\", \"sigmaL\" and \"sigmaR\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauBifurcatedGaussPdf::~LauBifurcatedGaussPdf() { // Destructor } void LauBifurcatedGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigmaL = sigmaL_->unblindValue(); Double_t sigmaR = sigmaR_->unblindValue(); // Evaluate the Birfucated Gaussian PDF value Double_t arg = abscissa - mean; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaL) > 1e-30) { coef = -0.5/(sigmaL*sigmaL); } } else { if (TMath::Abs(sigmaR) > 1e-30) { coef = -0.5/(sigmaR*sigmaR); } } value = TMath::Exp(coef*arg*arg); // Calculate the norm Double_t xscaleL = LauConstants::root2*sigmaL; Double_t xscaleR = LauConstants::root2*sigmaR; Double_t integral(0.0); Double_t norm(0.0); Double_t result(0.0); if(this->getMaxAbscissa() < mean){ integral = sigmaL * ( TMath::Erf((this->getMaxAbscissa() - mean)/xscaleL) - TMath::Erf((this->getMinAbscissa() - mean)/xscaleL)); }else if (this->getMinAbscissa() > mean){ integral = sigmaR * (TMath::Erf((this->getMaxAbscissa() - mean)/xscaleR) - TMath::Erf((this->getMinAbscissa() - mean)/xscaleR)); }else{ integral = sigmaR*TMath::Erf((this->getMaxAbscissa() -mean)/xscaleR) - sigmaL*TMath::Erf((this->getMinAbscissa() - mean)/xscaleL); } norm = LauConstants::rootPiBy2*integral; // the result result = value/norm; this->setUnNormPDFVal(result); } void LauBifurcatedGaussPdf::calcNorm() { // Nothing to do here, since it already normalized this->setNorm(1.0); } void LauBifurcatedGaussPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Bifurcated Gaussian function. if (mean>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meangetMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauBkgndDPModel.cc b/src/LauBkgndDPModel.cc index 4730d4c..6cf2ffa 100644 --- a/src/LauBkgndDPModel.cc +++ b/src/LauBkgndDPModel.cc @@ -1,306 +1,305 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBkgndDPModel.cc \brief File containing implementation of LauBkgndDPModel class. */ #include #include #include "TRandom.h" #include "TSystem.h" #include "Lau2DHistDPPdf.hh" #include "Lau2DSplineDPPdf.hh" #include "LauBkgndDPModel.hh" #include "LauDaughters.hh" #include "LauFitDataTree.hh" #include "LauKinematics.hh" #include "LauRandom.hh" #include "LauVetoes.hh" -ClassImp(LauBkgndDPModel) LauBkgndDPModel::LauBkgndDPModel(LauDaughters* daughters, LauVetoes* vetoes) : LauAbsBkgndDPModel(daughters, vetoes), symmetricalDP_(kFALSE), squareDP_(kFALSE), bgHistDPPdf_(0), curEvtHistVal_(0.0), maxPdfHeight_(1.0), pdfNorm_(1.0), doneGenWarning_(kFALSE), lowBinWarningIssued_(kFALSE) { if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); } } LauBkgndDPModel::~LauBkgndDPModel() { if (bgHistDPPdf_ != 0) { delete bgHistDPPdf_; bgHistDPPdf_ = 0; } } void LauBkgndDPModel::setBkgndHisto(const TH2* histo, Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) { if ( ! histo ) { std::cerr << "WARNING in LauBkgndDPModel::setBkgndHisto : Supplied background histogram pointer is null, likelihood for this component will be flat in the Dalitz plot" << std::endl; } Bool_t upperHalf = kFALSE; if (symmetricalDP_ == kTRUE && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauBkgndDPModel::setBkgndHisto : Background histogram has upperHalf = "<(upperHalf)<getKinematics(); const LauVetoes* vetoes = this->getVetoes(); bgHistDPPdf_ = new Lau2DHistDPPdf(histo, kinematics, vetoes, useInterpolation, fluctuateBins, upperHalf, squareDP); maxPdfHeight_ = bgHistDPPdf_->getMaxHeight(); pdfNorm_ = bgHistDPPdf_->getHistNorm(); } void LauBkgndDPModel::setBkgndSpline(const TH2* histo, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) { if ( ! histo ) { std::cerr << "WARNING in LauBkgndDPModel::setBkgndSpline : Supplied background histogram pointer is null, construction of spline will fail" << std::endl; } Bool_t upperHalf = kFALSE; if (symmetricalDP_ == kTRUE && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauBkgndDPModel::setBkgndSpline : Background histogram has upperHalf = "<(upperHalf)<getKinematics(); const LauVetoes* vetoes = this->getVetoes(); bgHistDPPdf_ = new Lau2DSplineDPPdf(histo, kinematics, vetoes, fluctuateBins, upperHalf, squareDP); maxPdfHeight_ = bgHistDPPdf_->getMaxHeight(); pdfNorm_ = bgHistDPPdf_->getHistNorm(); } Double_t LauBkgndDPModel::calcHistValue(Double_t xVal, Double_t yVal) { // Get the likelihood value of the background in the Dalitz plot. // Check that we have a valid histogram PDF if (bgHistDPPdf_ == 0) { std::cerr << "WARNING in LauBkgndDPModel::calcHistValue : We don't have a histogram so assuming the likelihood is flat in the Dalitz plot." << std::endl; this->setBkgndHisto( 0, kFALSE, kFALSE, kFALSE, kFALSE ); } // Find out the un-normalised PDF value Double_t value = bgHistDPPdf_->interpolateXY(xVal, yVal); // Check that the value is greater than zero // If we're using a spline then negative values can be caused by adjacent bins that all contain a value of zero. // The spline requires the value, its first derivatives and the mixed second derivative to be continuous and to match the input histogram // at the bin centres. Derivatives are calculated using a finite difference approximation taking the difference between the neighbouring bins. // If two bins are zero but the third is not then the second bin will have a positive first derivative causing the spline to dip below zero // between the two zero bins to remain smooth. Such dips are unavoidable but are correctly removed here. if ( value < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauBkgndDPModel::calcHistValue : Value " << value << " is less than 0 - setting to 0. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent empty bins. Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } return 0.0; } LauKinematics* kinematics = this->getKinematics(); // For square DP co-ordinates, need to divide by Jacobian if (squareDP_ == kTRUE) { // Make sure that square DP kinematics are correct, then get Jacobian kinematics->updateSqDPKinematics(xVal, yVal); Double_t jacobian = kinematics->calcSqDPJacobian(); value /= jacobian; } return value; } void LauBkgndDPModel::initialise() { } Bool_t LauBkgndDPModel::generate() { // Routine to generate the background, using data provided by an // already defined histogram. LauKinematics* kinematics = this->getKinematics(); Bool_t gotBG(kFALSE); while (gotBG == kFALSE) { if (squareDP_ == kTRUE) { // Generate a point in m', theta' space. By construction, this point // is already within the DP region. Double_t mPrime(0.0), thetaPrime(0.0); kinematics->genFlatSqDP(mPrime, thetaPrime); // If we're in a symmetrical DP then we should only generate events in one half if ( symmetricalDP_ && thetaPrime > 0.5 ) { thetaPrime = 1.0 - thetaPrime; } // Calculate histogram height for DP point and // compare with the maximum height if ( bgHistDPPdf_ != 0 ) { Double_t bgContDP = bgHistDPPdf_->interpolateXY(mPrime, thetaPrime)/maxPdfHeight_; if (LauRandom::randomFun()->Rndm() < bgContDP) { kinematics->updateSqDPKinematics(mPrime, thetaPrime); gotBG = kTRUE; } } else { if ( !doneGenWarning_ ) { std::cerr << "WARNING in LauBkgndDPModel::generate : We don't have a histogram so generating flat in the square DP, which won't be flat in the conventional DP!" << std::endl; std::cerr << "WARNING in LauBkgndDPModel::generate : This should never happen!! What have you done?!" << std::endl; doneGenWarning_ = kTRUE; } kinematics->updateSqDPKinematics(mPrime, thetaPrime); gotBG = kTRUE; } } else { // Generate a point in the Dalitz plot (phase-space). Double_t m13Sq(0.0), m23Sq(0.0); kinematics->genFlatPhaseSpace(m13Sq, m23Sq); // If we're in a symmetrical DP then we should only generate events in one half if ( symmetricalDP_ && m13Sq > m23Sq ) { Double_t tmpSq = m13Sq; m13Sq = m23Sq; m23Sq = tmpSq; } // Calculate histogram height for DP point and // compare with the maximum height if ( bgHistDPPdf_ != 0 ) { Double_t bgContDP = bgHistDPPdf_->interpolateXY(m13Sq, m23Sq)/maxPdfHeight_; if (LauRandom::randomFun()->Rndm() < bgContDP) { kinematics->updateKinematics(m13Sq, m23Sq); gotBG = kTRUE; } } else { if ( !doneGenWarning_ ) { std::cerr << "WARNING in LauBkgndDPModel::generate : We don't have a histogram so generating flat in the DP." << std::endl; doneGenWarning_ = kTRUE; } kinematics->updateKinematics(m13Sq, m23Sq); gotBG = kTRUE; } } } // Implement veto Bool_t vetoOK(kTRUE); const LauVetoes* vetoes = this->getVetoes(); if (vetoes) { vetoOK = vetoes->passVeto(kinematics); } // Call this function recusively until we pass the veto. if (vetoOK == kFALSE) { this->generate(); } return kTRUE; } void LauBkgndDPModel::fillDataTree(const LauFitDataTree& inputFitTree) { // In LauFitDataTree, the first two variables should always be // m13^2 and m23^2. Other variables follow thus: charge. Int_t nBranches = inputFitTree.nBranches(); if (nBranches < 2) { std::cerr<<"ERROR in LauBkgndDPModel::fillDataTree : Expecting at least 2 variables "<<"in input data tree, but there are "<getKinematics(); // clear and resize the data vector bgData_.clear(); bgData_.resize(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitTree.getData(iEvt); LauFitData::const_iterator iter = dataValues.find("m13Sq"); m13Sq = iter->second; iter = dataValues.find("m23Sq"); m23Sq = iter->second; // Update the kinematics. This will also update m' and theta' if squareDP = true kinematics->updateKinematics(m13Sq, m23Sq); if (squareDP_ == kTRUE) { mPrime = kinematics->getmPrime(); thetaPrime = kinematics->getThetaPrime(); curEvtHistVal_ = this->calcHistValue(mPrime, thetaPrime); } else { curEvtHistVal_ = this->calcHistValue(m13Sq, m23Sq); } bgData_[iEvt] = curEvtHistVal_; } } Double_t LauBkgndDPModel::getUnNormValue(UInt_t iEvt) { // Retrieve the likelihood for the given event this->setDataEventNo(iEvt); return curEvtHistVal_; } Double_t LauBkgndDPModel::getLikelihood(UInt_t iEvt) { // Retrieve the likelihood for the given event this->setDataEventNo(iEvt); Double_t llhd = curEvtHistVal_ / this->getPdfNorm(); return llhd; } void LauBkgndDPModel::setDataEventNo(UInt_t iEvt) { // Retrieve the data for event iEvt if (bgData_.size() > iEvt) { curEvtHistVal_ = bgData_[iEvt]; } else { std::cerr<<"ERROR in LauBkgndDPModel::setDataEventNo : Event index too large: "<= "< #include "TMath.h" #include "LauBlattWeisskopfFactor.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauBlattWeisskopfFactor) // Constructor LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ) : spin_(resInfo.getSpin()), radius_(new LauParameter("NEED_A_GOOD_NAME",resInfo.getBWRadius(),0.0,10.0,kTRUE)), barrierType_(barrierType), restFrame_(restFrame) { TString categoryName = this->setRadiusName( resInfo, category ); std::cout << "INFO in LauBlattWeisskopfFactor constructor : creating radius parameter for category \"" << categoryName << "\", with initial value " << resInfo.getBWRadius() << std::endl; } LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ) : spin_(resInfo.getSpin()), radius_(new LauParameter("NEED_A_GOOD_NAME",resRadius,0.0,10.0,kTRUE)), barrierType_(barrierType), restFrame_(restFrame) { TString categoryName = this->setRadiusName( resInfo, category ); std::cout << "INFO in LauBlattWeisskopfFactor constructor : creating radius parameter for category \"" << categoryName << "\", with initial value " << resRadius << std::endl; } LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const Int_t spin, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const BlattWeisskopfCategory category ) : spin_(spin), radius_(new LauParameter("NEED_A_GOOD_NAME",resRadius,0.0,10.0,kTRUE)), barrierType_(barrierType), restFrame_(restFrame) { TString categoryName = this->setRadiusName( category ); std::cout << "INFO in LauBlattWeisskopfFactor constructor : creating radius parameter for category \"" << categoryName << "\", with initial value " << resRadius << std::endl; } LauBlattWeisskopfFactor::LauBlattWeisskopfFactor( const LauBlattWeisskopfFactor& other, const UInt_t newSpin, const BarrierType newBarrierType ) : spin_(newSpin), radius_(other.radius_->createClone()), barrierType_(newBarrierType), restFrame_(other.restFrame_) { } TString LauBlattWeisskopfFactor::setRadiusName( const LauResonanceInfo& resInfo, const BlattWeisskopfCategory category ) { switch (category) { case Indep : return this->setRadiusName( resInfo.getSanitisedName() ); default : return this->setRadiusName( category ); } } TString LauBlattWeisskopfFactor::setRadiusName( const BlattWeisskopfCategory category ) { switch (category) { case Default : return this->setRadiusName("Unknown"); case Indep : // We shouldn't ever end up here return this->setRadiusName("Unknown"); case Parent : return this->setRadiusName("Parent"); case Light : return this->setRadiusName("Light"); case Kstar : return this->setRadiusName("Kstar"); case Charm : return this->setRadiusName("Charm"); case StrangeCharm : return this->setRadiusName("StrangeCharm"); case Charmonium : return this->setRadiusName("Charmonium"); case Beauty : return this->setRadiusName("Beauty"); case StrangeBeauty : return this->setRadiusName("StrangeBeauty"); case CharmBeauty : return this->setRadiusName("CharmBeauty"); case Custom1 : return this->setRadiusName("Custom1"); case Custom2 : return this->setRadiusName("Custom2"); case Custom3 : return this->setRadiusName("Custom3"); case Custom4 : return this->setRadiusName("Custom4"); } // We should never get here but gcc seems to think we can return this->setRadiusName("Unknown"); } TString LauBlattWeisskopfFactor::setRadiusName( const TString& categoryName ) { TString name = "BarrierRadius_"; name.Append(categoryName); radius_->name(name); return categoryName; } LauBlattWeisskopfFactor* LauBlattWeisskopfFactor::createClone( const UInt_t newSpin, const BarrierType newBarrierType ) { LauBlattWeisskopfFactor* clone = new LauBlattWeisskopfFactor( *this, newSpin, newBarrierType ); return clone; } Double_t LauBlattWeisskopfFactor::calcFormFactor( const Double_t p ) const { // Calculate the requested form factor for the resonance, given the momentum value Double_t fFactor(1.0); // For scalars the form factor is always unity // TODO: and we currently don't have formulae for spin > 5 if ( (spin_ == 0) || (spin_ > 5) ) { return fFactor; } const Double_t radius = radius_->unblindValue(); const Double_t z = radius*radius*p*p; if ( barrierType_ == BWBarrier ) { if (spin_ == 1) { fFactor = TMath::Sqrt(2.0*z/(z + 1.0)); } else if (spin_ == 2) { fFactor = TMath::Sqrt(13.0*z*z/(z*z + 3.0*z + 9.0)); } else if (spin_ == 3) { fFactor = TMath::Sqrt(277.0*z*z*z/(z*z*z + 6.0*z*z + 45.0*z + 225.0)); } else if (spin_ == 4) { fFactor = TMath::Sqrt(12746.0*z*z*z*z/(z*z*z*z + 10.0*z*z*z + 135.0*z*z + 1575.0*z + 11025.0)); } else if (spin_ == 5) { fFactor = TMath::Sqrt(998881.0*z*z*z*z*z/(z*z*z*z*z + 15.0*z*z*z*z + 315.0*z*z*z + 6300.0*z*z + 99225.0*z + 893025.0)); } } else if ( barrierType_ == BWPrimeBarrier ) { if (spin_ == 1) { fFactor = TMath::Sqrt(1.0/(z + 1.0)); } else if (spin_ == 2) { fFactor = TMath::Sqrt(1.0/(z*z + 3.0*z + 9.0)); } else if (spin_ == 3) { fFactor = TMath::Sqrt(1.0/(z*z*z + 6.0*z*z + 45.0*z + 225.0)); } else if (spin_ == 4) { fFactor = TMath::Sqrt(1.0/(z*z*z*z + 10.0*z*z*z + 135.0*z*z + 1575.0*z + 11025.0)); } else if (spin_ == 5) { fFactor = TMath::Sqrt(1.0/(z*z*z*z*z + 15.0*z*z*z*z + 315.0*z*z*z + 6300.0*z*z + 99225.0*z + 893025.0)); } } else if ( barrierType_ == ExpBarrier ) { if (spin_ == 1) { fFactor = TMath::Exp( -TMath::Sqrt(z) ); } else if (spin_ == 2) { fFactor = TMath::Exp( -z ); } else if (spin_ == 3) { fFactor = TMath::Exp( -TMath::Sqrt(z*z*z) ); } else if (spin_ == 4) { fFactor = TMath::Exp( -z*z ); } else if (spin_ == 5) { fFactor = TMath::Exp( -TMath::Sqrt(z*z*z*z*z) ); } } return fFactor; } diff --git a/src/LauBlind.cc b/src/LauBlind.cc index 087e8dd..ecaa34e 100644 --- a/src/LauBlind.cc +++ b/src/LauBlind.cc @@ -1,71 +1,70 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBlind.cc \brief File containing implementation of LauBlind class. */ #include "LauBlind.hh" #include "TMath.h" #include "TRandom3.h" -ClassImp(LauBlind) LauBlind::LauBlind() : blindingString_(""), blindingWidth_(0.0), offset_(0.0) { } LauBlind::LauBlind(const TString& blindingStr, const Double_t width) : blindingString_(blindingStr), blindingWidth_(width), offset_(0.0) { this->calcOffset(); } LauBlind::LauBlind(const LauBlind& rhs) : blindingString_(rhs.blindingString_), blindingWidth_(rhs.blindingWidth_), offset_(rhs.offset_) { } LauBlind::~LauBlind() { } void LauBlind::calcOffset() { //hash the blinding string to obtain a seed TRandom3 r(TMath::Hash(blindingString_)); //offsets are Gaussian distributed with defined width offset_ = blindingWidth_ * r.Gaus(); } diff --git a/src/LauBreitWignerRes.cc b/src/LauBreitWignerRes.cc index 81d1543..892bccc 100644 --- a/src/LauBreitWignerRes.cc +++ b/src/LauBreitWignerRes.cc @@ -1,78 +1,77 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBreitWignerRes.cc \brief File containing implementation of LauBreitWignerRes class. */ #include "LauBreitWignerRes.hh" -ClassImp(LauBreitWignerRes) LauBreitWignerRes::LauBreitWignerRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauBreitWignerRes::~LauBreitWignerRes() { } void LauBreitWignerRes::initialise() { } LauComplex LauBreitWignerRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. Double_t resMass = this->getMass(); Double_t deltaM = mass - resMass; Double_t resWidthO2 = 0.5 * this->getWidth(); Double_t resWidthO2Sq = resWidthO2*resWidthO2; LauComplex resAmplitude(deltaM, resWidthO2); resAmplitude.rescale(spinTerm/(deltaM*deltaM + resWidthO2Sq)); return resAmplitude; } const std::vector& LauBreitWignerRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauCPFitModel.cc b/src/LauCPFitModel.cc index dbced77..816d90c 100644 --- a/src/LauCPFitModel.cc +++ b/src/LauCPFitModel.cc @@ -1,3459 +1,3458 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCPFitModel.cc \brief File containing implementation of LauCPFitModel class. */ #include #include #include #include #include "TVirtualFitter.h" #include "TSystem.h" #include "TMinuit.h" #include "TRandom.h" #include "TFile.h" #include "TTree.h" #include "TBranch.h" #include "TLeaf.h" #include "TMath.h" #include "TH2.h" #include "TGraph2D.h" #include "TGraph.h" #include "TStyle.h" #include "TCanvas.h" #include "LauAbsBkgndDPModel.hh" #include "LauAbsCoeffSet.hh" #include "LauIsobarDynamics.hh" #include "LauAbsPdf.hh" #include "LauAsymmCalc.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauCPFitModel.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauEmbeddedData.hh" #include "LauFitNtuple.hh" #include "LauGenNtuple.hh" #include "LauKinematics.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauScfMap.hh" -ClassImp(LauCPFitModel) LauCPFitModel::LauCPFitModel(LauIsobarDynamics* negModel, LauIsobarDynamics* posModel, Bool_t tagged, const TString& tagVarName) : LauAbsFitModel(), negSigModel_(negModel), posSigModel_(posModel), negKinematics_(negModel ? negModel->getKinematics() : 0), posKinematics_(posModel ? posModel->getKinematics() : 0), usingBkgnd_(kFALSE), nSigComp_(0), nSigDPPar_(0), nExtraPdfPar_(0), nNormPar_(0), negMeanEff_("negMeanEff",0.0,0.0,1.0), posMeanEff_("posMeanEff",0.0,0.0,1.0), negDPRate_("negDPRate",0.0,0.0,100.0), posDPRate_("posDPRate",0.0,0.0,100.0), signalEvents_(0), signalAsym_(0), forceAsym_(kFALSE), tagged_(tagged), tagVarName_(tagVarName), curEvtCharge_(0), useSCF_(kFALSE), useSCFHist_(kFALSE), scfFrac_("scfFrac",0.0,0.0,1.0), scfFracHist_(0), scfMap_(0), compareFitData_(kFALSE), negParent_("B-"), posParent_("B+"), negSignalTree_(0), posSignalTree_(0), reuseSignal_(kFALSE), useNegReweighting_(kFALSE), usePosReweighting_(kFALSE), sigDPLike_(0.0), scfDPLike_(0.0), sigExtraLike_(0.0), scfExtraLike_(0.0), sigTotalLike_(0.0), scfTotalLike_(0.0) { const LauDaughters* negDaug = negSigModel_->getDaughters(); if (negDaug != 0) {negParent_ = negDaug->getNameParent();} const LauDaughters* posDaug = posSigModel_->getDaughters(); if (posDaug != 0) {posParent_ = posDaug->getNameParent();} } LauCPFitModel::~LauCPFitModel() { delete negSignalTree_; delete posSignalTree_; for (LauBkgndEmbDataList::iterator iter = negBkgndTree_.begin(); iter != negBkgndTree_.end(); ++iter) { delete (*iter); } for (LauBkgndEmbDataList::iterator iter = posBkgndTree_.begin(); iter != posBkgndTree_.end(); ++iter) { delete (*iter); } delete scfFracHist_; } void LauCPFitModel::setupBkgndVectors() { UInt_t nBkgnds = this->nBkgndClasses(); negBkgndDPModels_.resize( nBkgnds ); posBkgndDPModels_.resize( nBkgnds ); negBkgndPdfs_.resize( nBkgnds ); posBkgndPdfs_.resize( nBkgnds ); bkgndEvents_.resize( nBkgnds ); bkgndAsym_.resize( nBkgnds ); negBkgndTree_.resize( nBkgnds ); posBkgndTree_.resize( nBkgnds ); reuseBkgnd_.resize( nBkgnds ); bkgndDPLike_.resize( nBkgnds ); bkgndExtraLike_.resize( nBkgnds ); bkgndTotalLike_.resize( nBkgnds ); } void LauCPFitModel::setNSigEvents(LauParameter* nSigEvents) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } if ( signalAsym_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl; return; } signalEvents_ = nSigEvents; TString name = signalEvents_->name(); if ( ! name.Contains("signalEvents") && !( name.BeginsWith("signal") && name.EndsWith("Events") ) ) { signalEvents_->name("signalEvents"); } Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); signalAsym_ = new LauParameter("signalAsym",0.0,-1.0,1.0,kTRUE); } void LauCPFitModel::setNSigEvents( LauParameter* nSigEvents, LauParameter* sigAsym, Bool_t forceAsym ) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The event LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( sigAsym == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The asym LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } if ( signalAsym_ != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl; return; } signalEvents_ = nSigEvents; signalEvents_->name("signalEvents"); Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); signalAsym_ = sigAsym; signalAsym_->name("signalAsym"); signalAsym_->range(-1.0,1.0); forceAsym_ = forceAsym; } void LauCPFitModel::setNBkgndEvents( LauAbsRValue* nBkgndEvents ) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBgkndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } if ( bkgndAsym_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; bkgndAsym_[bkgndID] = new LauParameter(nBkgndEvents->name()+"Asym",0.0,-1.0,1.0,kTRUE); } void LauCPFitModel::setNBkgndEvents(LauAbsRValue* nBkgndEvents, LauAbsRValue* bkgndAsym) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( bkgndAsym == 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background asym LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } if ( bkgndAsym_[bkgndID] != 0 ) { std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; bkgndAsym->name( nBkgndEvents->name()+"Asym" ); if ( bkgndAsym->isLValue() ) { LauParameter* asym = dynamic_cast( bkgndAsym ); asym->range(-1.0, 1.0); } bkgndAsym_[bkgndID] = bkgndAsym; } void LauCPFitModel::splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf, const Bool_t fluctuateBins, LauScfMap* scfMap ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } if ( dpHisto == 0 ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : The histogram pointer is null." << std::endl; return; } const LauDaughters* daughters = negSigModel_->getDaughters(); scfFracHist_ = new LauEffModel( daughters, 0 ); scfFracHist_->setEffHisto( dpHisto, kTRUE, fluctuateBins, 0.0, 0.0, upperHalf, daughters->squareDP() ); scfMap_ = scfMap; useSCF_ = kTRUE; useSCFHist_ = kTRUE; } void LauCPFitModel::splitSignalComponent( const Double_t scfFrac, const Bool_t fixed ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } scfFrac_.range( 0.0, 1.0 ); scfFrac_.value( scfFrac ); scfFrac_.initValue( scfFrac ); scfFrac_.genValue( scfFrac ); scfFrac_.fixed( fixed ); useSCF_ = kTRUE; useSCFHist_ = kFALSE; } void LauCPFitModel::setBkgndDPModels(const TString& bkgndClass, LauAbsBkgndDPModel* negModel, LauAbsBkgndDPModel* posModel) { if ((negModel==0) || (posModel==0)) { std::cerr << "ERROR in LauCPFitModel::setBkgndDPModels : One or both of the model pointers is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass) ) { std::cerr << "ERROR in LauCPFitModel::setBkgndDPModel : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); negBkgndDPModels_[bkgndID] = negModel; posBkgndDPModels_[bkgndID] = posModel; usingBkgnd_ = kTRUE; } void LauCPFitModel::setSignalPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setSignalPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } negSignalPdfs_.push_back(negPdf); posSignalPdfs_.push_back(posPdf); } void LauCPFitModel::setSCFPdfs(LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setSCFPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } negScfPdfs_.push_back(negPdf); posScfPdfs_.push_back(posPdf); } void LauCPFitModel::setBkgndPdfs(const TString& bkgndClass, LauAbsPdf* negPdf, LauAbsPdf* posPdf) { if ( tagged_ ) { if (negPdf==0 || posPdf==0) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : One or both of the PDF pointers is null." << std::endl; return; } } else { // if we're doing an untagged analysis we will only use the negative PDFs if ( negPdf==0 ) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : The negative PDF pointer is null." << std::endl; return; } if ( posPdf!=0 ) { std::cerr << "WARNING in LauCPFitModel::setBkgndPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl; } } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); negBkgndPdfs_[bkgndID].push_back(negPdf); posBkgndPdfs_[bkgndID].push_back(posPdf); usingBkgnd_ = kTRUE; } void LauCPFitModel::setAmpCoeffSet(LauAbsCoeffSet* coeffSet) { // Resize the coeffPars vector if not already done if ( coeffPars_.empty() ) { const UInt_t nNegAmp = negSigModel_->getnTotAmp(); const UInt_t nPosAmp = posSigModel_->getnTotAmp(); if ( nNegAmp != nPosAmp ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl; gSystem->Exit(EXIT_FAILURE); } coeffPars_.resize( nNegAmp ); for (std::vector::iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) { (*iter) = 0; } fitFracAsymm_.resize( nNegAmp ); acp_.resize( nNegAmp ); } // Is there a component called compName in the signal model? TString compName(coeffSet->name()); TString conjName = negSigModel_->getConjResName(compName); const Int_t negIndex = negSigModel_->resonanceIndex(compName); const Int_t posIndex = posSigModel_->resonanceIndex(conjName); if ( negIndex < 0 ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model doesn't contain component \"" << compName << "\"." << std::endl; return; } if ( posIndex < 0 ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << posParent_ << " signal DP model doesn't contain component \"" << conjName << "\"." << std::endl; return; } if ( posIndex != negIndex ) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model and " << posParent_ << " signal DP model have different indices for components \"" << compName << "\" and \"" << conjName << "\"." << std::endl; return; } // Do we already have it in our list of names? if ( coeffPars_[negIndex] != 0 && coeffPars_[negIndex]->name() == compName) { std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl; return; } coeffSet->index(negIndex); coeffPars_[negIndex] = coeffSet; TString parName = coeffSet->baseName(); parName += "FitFracAsym"; fitFracAsymm_[negIndex] = LauParameter(parName, 0.0, -1.0, 1.0); acp_[negIndex] = coeffSet->acp(); ++nSigComp_; std::cout << "INFO in LauCPFitModel::setAmpCoeffSet : Added coefficients for component \"" << compName << "\" to the fit model." << std::endl; coeffSet->printParValues(); } void LauCPFitModel::initialise() { // Initialisation if (!this->useDP() && negSignalPdfs_.empty()) { std::cerr << "ERROR in LauCPFitModel::initialise : Signal model doesn't exist for any variable." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( this->useDP() ) { // Check that we have all the Dalitz-plot models if ((negSigModel_ == 0) || (posSigModel_ == 0)) { std::cerr << "ERROR in LauCPFitModel::initialise : the pointer to one (neg or pos) of the signal DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); } if ( usingBkgnd_ ) { if ( negBkgndDPModels_.empty() || posBkgndDPModels_.empty() ) { std::cerr << "ERROR in LauCPFitModel::initialise : No background DP models found.\n"; std::cerr << " : Removing the Dalitz plot from the model." << std::endl; this->useDP(kFALSE); } for (LauBkgndDPModelList::const_iterator dpmodel_iter = negBkgndDPModels_.begin(); dpmodel_iter != negBkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } for (LauBkgndDPModelList::const_iterator dpmodel_iter = posBkgndDPModels_.begin(); dpmodel_iter != posBkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } } // Need to check that the number of components we have and that the dynamics has matches up const UInt_t nNegAmp = negSigModel_->getnTotAmp(); const UInt_t nPosAmp = posSigModel_->getnTotAmp(); if ( nNegAmp != nPosAmp ) { std::cerr << "ERROR in LauCPFitModel::initialise : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( nNegAmp != nSigComp_ ) { std::cerr << "ERROR in LauCPFitModel::initialise : Number of signal DP components in the model (" << nNegAmp << ") not equal to number of coefficients supplied (" << nSigComp_ << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( !fixParamFileName_.IsNull() || !fixParamMap_.empty() ) { // Set coefficients std::vector params; for ( auto itr = coeffPars_.begin(); itr != coeffPars_.end(); ++itr ) { std::vector p = (*itr)->getParameters(); params.insert(params.end(), p.begin(), p.end()); } this->fixParams(params); // Set resonance parameters (if they exist) negSigModel_->collateResonanceParameters(); posSigModel_->collateResonanceParameters(); this->fixParams(negSigModel_->getFloatingParameters()); this->fixParams(posSigModel_->getFloatingParameters()); } // From the initial parameter values calculate the coefficients // so they can be passed to the signal model this->updateCoeffs(); // If all is well, go ahead and initialise them this->initialiseDPModels(); } // Next check that, if a given component is being used we've got the // right number of PDFs for all the variables involved // TODO - should probably check variable names and so on as well UInt_t nsigpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nsigpdfvars; } } } if (useSCF_) { UInt_t nscfpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nscfpdfvars; } } } if (nscfpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " TM signal PDF variables but " << nscfpdfvars << " SCF signal PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } if (usingBkgnd_) { for (LauBkgndPdfsList::const_iterator bgclass_iter = negBkgndPdfs_.begin(); bgclass_iter != negBkgndPdfs_.end(); ++bgclass_iter) { UInt_t nbkgndpdfvars(0); const LauPdfList& pdfList = (*bgclass_iter); for ( LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nbkgndpdfvars; } } } if (nbkgndpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " signal PDF variables but " << nbkgndpdfvars << " bkgnd PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } } // Clear the vectors of parameter information so we can start from scratch this->clearFitParVectors(); // Set the fit parameters for signal and background models this->setSignalDPParameters(); // Set the fit parameters for the various extra PDFs this->setExtraPdfParameters(); // Set the initial bg and signal events this->setFitNEvents(); // Check that we have the expected number of fit variables const LauParameterPList& fitVars = this->fitPars(); if (fitVars.size() != (nSigDPPar_ + nExtraPdfPar_ + nNormPar_)) { std::cerr << "ERROR in LauCPFitModel::initialise : Number of fit parameters not of expected size. Exiting" << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setExtraNtupleVars(); } void LauCPFitModel::recalculateNormalisation() { //std::cout << "INFO in LauCPFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl; negSigModel_->recalculateNormalisation(); posSigModel_->recalculateNormalisation(); negSigModel_->modifyDataTree(); posSigModel_->modifyDataTree(); } void LauCPFitModel::initialiseDPModels() { std::cout << "INFO in LauCPFitModel::initialiseDPModels : Initialising signal DP model" << std::endl; negSigModel_->initialise(negCoeffs_); posSigModel_->initialise(posCoeffs_); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } } } void LauCPFitModel::setSignalDPParameters() { // Set the fit parameters for the signal model. nSigDPPar_ = 0; if ( ! this->useDP() ) { return; } std::cout << "INFO in LauCPFitModel::setSignalDPParameters : Setting the initial fit parameters for the signal DP model." << std::endl; // Place isobar coefficient parameters in vector of fit variables LauParameterPList& fitVars = this->fitPars(); for (UInt_t i = 0; i < nSigComp_; i++) { LauParameterPList pars = coeffPars_[i]->getParameters(); for (LauParameterPList::iterator iter = pars.begin(); iter != pars.end(); ++iter) { if ( !(*iter)->clone() ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } // Obtain the resonance parameters and place them in the vector of fit variables and in a separate vector // Need to make sure that they are unique because some might appear in both DP models LauParameterPSet& resVars = this->resPars(); resVars.clear(); LauParameterPList& negSigDPPars = negSigModel_->getFloatingParameters(); LauParameterPList& posSigDPPars = posSigModel_->getFloatingParameters(); for ( LauParameterPList::iterator iter = negSigDPPars.begin(); iter != negSigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } for ( LauParameterPList::iterator iter = posSigDPPars.begin(); iter != posSigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } void LauCPFitModel::setExtraPdfParameters() { // Include all the parameters of the PDF in the fit // NB all of them are passed to the fit, even though some have been fixed through parameter.fixed(kTRUE) // With the new "cloned parameter" scheme only "original" parameters are passed to the fit. // Their clones are updated automatically when the originals are updated. nExtraPdfPar_ = 0; nExtraPdfPar_ += this->addFitParameters(negSignalPdfs_); if ( tagged_ ) { nExtraPdfPar_ += this->addFitParameters(posSignalPdfs_); } if (useSCF_ == kTRUE) { nExtraPdfPar_ += this->addFitParameters(negScfPdfs_); if ( tagged_ ) { nExtraPdfPar_ += this->addFitParameters(posScfPdfs_); } } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } if ( tagged_ ) { for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } } } } void LauCPFitModel::setFitNEvents() { if ( signalEvents_ == 0 ) { std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Signal yield not defined." << std::endl; return; } nNormPar_ = 0; // initialise the total number of events to be the sum of all the hypotheses Double_t nTotEvts = signalEvents_->value(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { nTotEvts += (*iter)->value(); if ( (*iter) == 0 ) { std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Background yield not defined." << std::endl; return; } } this->eventsPerExpt(TMath::FloorNint(nTotEvts)); LauParameterPList& fitVars = this->fitPars(); // if doing an extended ML fit add the number of signal events into the fit parameters if (this->doEMLFit()) { std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for signal and background components..." << std::endl; // add the signal fraction to the list of fit parameters if(!signalEvents_->fixed()) { fitVars.push_back(signalEvents_); ++nNormPar_; } } else { std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for background components (and hence signal)..." << std::endl; } // if not using the DP in the model we need an explicit signal asymmetry parameter if (this->useDP() == kFALSE) { if(!signalAsym_->fixed()) { fitVars.push_back(signalAsym_); ++nNormPar_; } } if (useSCF_ && !useSCFHist_) { if(!scfFrac_.fixed()) { fitVars.push_back(&scfFrac_); ++nNormPar_; } } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if(!parameter->clone()) { fitVars.push_back(parameter); ++nNormPar_; } } } for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if(!parameter->clone()) { fitVars.push_back(parameter); ++nNormPar_; } } } } } void LauCPFitModel::setExtraNtupleVars() { // Set-up other parameters derived from the fit results, e.g. fit fractions. if (this->useDP() != kTRUE) { return; } // First clear the vectors so we start from scratch this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add the positive and negative fit fractions for each signal component negFitFrac_ = negSigModel_->getFitFractions(); if (negFitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } posFitFrac_ = posSigModel_->getFitFractions(); if (posFitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } // Add the positive and negative fit fractions that have not been corrected for the efficiency for each signal component negFitFracEffUnCorr_ = negSigModel_->getFitFractionsEfficiencyUncorrected(); if (negFitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } posFitFracEffUnCorr_ = posSigModel_->getFitFractionsEfficiencyUncorrected(); if (posFitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); i negExtraPars = negSigModel_->getExtraParameters(); std::vector::iterator negExtraIter; for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) { LauParameter negExtraParameter = (*negExtraIter); extraVars.push_back(negExtraParameter); } std::vector posExtraPars = posSigModel_->getExtraParameters(); std::vector::iterator posExtraIter; for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) { LauParameter posExtraParameter = (*posExtraIter); extraVars.push_back(posExtraParameter); } // Now add in the DP efficiency value Double_t initMeanEff = negSigModel_->getMeanEff().initValue(); negMeanEff_.value(initMeanEff); negMeanEff_.genValue(initMeanEff); negMeanEff_.initValue(initMeanEff); extraVars.push_back(negMeanEff_); initMeanEff = posSigModel_->getMeanEff().initValue(); posMeanEff_.value(initMeanEff); posMeanEff_.genValue(initMeanEff); posMeanEff_.initValue(initMeanEff); extraVars.push_back(posMeanEff_); // Also add in the DP rates Double_t initDPRate = negSigModel_->getDPRate().initValue(); negDPRate_.value(initDPRate); negDPRate_.genValue(initDPRate); negDPRate_.initValue(initDPRate); extraVars.push_back(negDPRate_); initDPRate = posSigModel_->getDPRate().initValue(); posDPRate_.value(initDPRate); posDPRate_.genValue(initDPRate); posDPRate_.initValue(initDPRate); extraVars.push_back(posDPRate_); // Calculate the CPC and CPV Fit Fractions, ACPs and FitFrac asymmetries this->calcExtraFractions(kTRUE); this->calcAsymmetries(kTRUE); // Add the CP violating and CP conserving fit fractions for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(CPVFitFrac_[i][j]); } } for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(CPCFitFrac_[i][j]); } } // Add the Fit Fraction asymmetry for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { extraVars.push_back(fitFracAsymm_[i]); } // Add the calculated CP asymmetry for each signal component for (UInt_t i = 0; i < nSigComp_; i++) { extraVars.push_back(acp_[i]); } } void LauCPFitModel::calcExtraFractions(Bool_t initValues) { // Calculate the CP-conserving and CP-violating fit fractions if (initValues) { // create the structure CPCFitFrac_.clear(); CPVFitFrac_.clear(); CPCFitFrac_.resize(nSigComp_); CPVFitFrac_.resize(nSigComp_); for (UInt_t i(0); iacp(); LauAsymmCalc asymmCalc(negFitFrac_[i][i].value(), posFitFrac_[i][i].value()); Double_t asym = asymmCalc.getAsymmetry(); fitFracAsymm_[i].value(asym); if (initValues) { fitFracAsymm_[i].genValue(asym); fitFracAsymm_[i].initValue(asym); } } } void LauCPFitModel::finaliseFitResults(const TString& tablePrefixName) { // Retrieve parameters from the fit results for calculations and toy generation // and eventually store these in output root ntuples/text files // Now take the fit parameters and update them as necessary // i.e. to make mag > 0.0, phase in the right range. // This function will also calculate any other values, such as the // fit fractions, using any errors provided by fitParErrors as appropriate. // Also obtain the pull values: (measured - generated)/(average error) if (this->useDP() == kTRUE) { for (UInt_t i = 0; i < nSigComp_; ++i) { // Check whether we have "a/b > 0.0", and phases in the right range coeffPars_[i]->finaliseValues(); } } // update the pulls on the event fractions and asymmetries if (this->doEMLFit()) { signalEvents_->updatePull(); } if (this->useDP() == kFALSE) { signalAsym_->updatePull(); } if (useSCF_ && !useSCFHist_) { scfFrac_.updatePull(); } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } } // Update the pulls on all the extra PDFs' parameters this->updateFitParameters(negSignalPdfs_); this->updateFitParameters(posSignalPdfs_); if (useSCF_ == kTRUE) { this->updateFitParameters(negScfPdfs_); this->updateFitParameters(posScfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } } // Fill the fit results to the ntuple // update the coefficients and then calculate the fit fractions and ACP's if (this->useDP() == kTRUE) { this->updateCoeffs(); negSigModel_->updateCoeffs(negCoeffs_); negSigModel_->calcExtraInfo(); posSigModel_->updateCoeffs(posCoeffs_); posSigModel_->calcExtraInfo(); LauParArray negFitFrac = negSigModel_->getFitFractions(); if (negFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFrac = posSigModel_->getFitFractions(); if (posFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray negFitFracEffUnCorr = negSigModel_->getFitFractionsEfficiencyUncorrected(); if (negFitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFracEffUnCorr = posSigModel_->getFitFractionsEfficiencyUncorrected(); if (posFitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); posMeanEff_.value(posSigModel_->getMeanEff().value()); negDPRate_.value(negSigModel_->getDPRate().value()); posDPRate_.value(posSigModel_->getDPRate().value()); this->calcExtraFractions(); this->calcAsymmetries(); // Then store the final fit parameters, and any extra parameters for // the signal model (e.g. fit fractions, FF asymmetries, ACPs, mean efficiency and DP rate) this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add the positive and negative fit fractions for each signal component for (UInt_t i(0); i negExtraPars = negSigModel_->getExtraParameters(); std::vector::iterator negExtraIter; for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) { LauParameter negExtraParameter = (*negExtraIter); extraVars.push_back(negExtraParameter); } std::vector posExtraPars = posSigModel_->getExtraParameters(); std::vector::iterator posExtraIter; for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) { LauParameter posExtraParameter = (*posExtraIter); extraVars.push_back(posExtraParameter); } extraVars.push_back(negMeanEff_); extraVars.push_back(posMeanEff_); extraVars.push_back(negDPRate_); extraVars.push_back(posDPRate_); for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j(i); jprintFitFractions(std::cout); this->printAsymmetries(std::cout); } const LauParameterPList& fitVars = this->fitPars(); const LauParameterList& extraVars = this->extraPars(); LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitVars, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); // Print out the partial fit fractions, phases and the // averaged efficiency, reweighted by the dynamics (and anything else) if (this->writeLatexTable()) { TString sigOutFileName(tablePrefixName); sigOutFileName += "_"; sigOutFileName += this->iExpt(); sigOutFileName += "Expt.tex"; this->writeOutTable(sigOutFileName); } } void LauCPFitModel::printFitFractions(std::ostream& output) { // Print out Fit Fractions, total DP rate and mean efficiency // First for the B- events for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << negParent_ << " FitFraction for component " << i << " (" << compName << ") = " << negFitFrac_[i][i] << std::endl; } output << negParent_ << " overall DP rate (integral of matrix element squared) = " << negDPRate_ << std::endl; output << negParent_ << " average efficiency weighted by whole DP dynamics = " << negMeanEff_ << std::endl; // Then for the positive sample for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); const TString conjName(negSigModel_->getConjResName(compName)); output << posParent_ << " FitFraction for component " << i << " (" << conjName << ") = " << posFitFrac_[i][i] << std::endl; } output << posParent_ << " overall DP rate (integral of matrix element squared) = " << posDPRate_ << std::endl; output << posParent_ << " average efficiency weighted by whole DP dynamics = " << posMeanEff_ << std::endl; } void LauCPFitModel::printAsymmetries(std::ostream& output) { for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << "Fit Fraction asymmetry for component " << i << " (" << compName << ") = " << fitFracAsymm_[i] << std::endl; } for (UInt_t i = 0; i < nSigComp_; i++) { const TString compName(coeffPars_[i]->name()); output << "ACP for component " << i << " (" << compName << ") = " << acp_[i] << std::endl; } } void LauCPFitModel::writeOutTable(const TString& outputFile) { // Write out the results of the fit to a tex-readable table // TODO - need to include the yields in this table std::ofstream fout(outputFile); LauPrint print; std::cout << "INFO in LauCPFitModel::writeOutTable : Writing out results of the fit to the tex file " << outputFile << std::endl; if (this->useDP() == kTRUE) { // print the fit coefficients in one table coeffPars_.front()->printTableHeading(fout); for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->printTableRow(fout); } fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; // print the fit fractions and asymmetries in another fout << "\\begin{tabular}{|l|c|c|c|c|}" << std::endl; fout << "\\hline" << std::endl; fout << "Component & " << negParent_ << " Fit Fraction & " << posParent_ << " Fit Fraction & Fit Fraction Asymmetry & ACP \\\\" << std::endl; fout << "\\hline" << std::endl; Double_t negFitFracSum(0.0); Double_t posFitFracSum(0.0); for (UInt_t i = 0; i < nSigComp_; i++) { TString resName = coeffPars_[i]->name(); resName = resName.ReplaceAll("_", "\\_"); Double_t negFitFrac = negFitFrac_[i][i].value(); Double_t posFitFrac = posFitFrac_[i][i].value(); negFitFracSum += negFitFrac; posFitFracSum += posFitFrac; Double_t fitFracAsymm = fitFracAsymm_[i].value(); Double_t acp = acp_[i].value(); Double_t acpErr = acp_[i].error(); fout << resName << " & $"; print.printFormat(fout, negFitFrac); fout << "$ & $"; print.printFormat(fout, posFitFrac); fout << "$ & $"; print.printFormat(fout, fitFracAsymm); fout << "$ & $"; print.printFormat(fout, acp); fout << " \\pm "; print.printFormat(fout, acpErr); fout << "$ \\\\" << std::endl; } fout << "\\hline" << std::endl; // Also print out sum of fit fractions fout << "Fit Fraction Sum & $"; print.printFormat(fout, negFitFracSum); fout << "$ & $"; print.printFormat(fout, posFitFracSum); fout << "$ & & \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "DP rate & $"; print.printFormat(fout, negDPRate_.value()); fout << "$ & $"; print.printFormat(fout, posDPRate_.value()); fout << "$ & & \\\\" << std::endl; fout << "$< \\varepsilon > $ & $"; print.printFormat(fout, negMeanEff_.value()); fout << "$ & $"; print.printFormat(fout, posMeanEff_.value()); fout << "$ & & \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; } if (!negSignalPdfs_.empty()) { fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; if (useSCF_ == kTRUE) { fout << "\\Extra TM Signal PDFs' Parameters: & \\\\" << std::endl; } else { fout << "\\Extra Signal PDFs' Parameters: & \\\\" << std::endl; } this->printFitParameters(negSignalPdfs_, fout); if ( tagged_ ) { this->printFitParameters(posSignalPdfs_, fout); } if (useSCF_ == kTRUE && !negScfPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra SCF Signal PDFs' Parameters: & \\\\" << std::endl; this->printFitParameters(negScfPdfs_, fout); if ( tagged_ ) { this->printFitParameters(posScfPdfs_, fout); } } if (usingBkgnd_ == kTRUE && !negBkgndPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra Background PDFs' Parameters: & \\\\" << std::endl; for (LauBkgndPdfsList::const_iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } if ( tagged_ ) { for (LauBkgndPdfsList::const_iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } } } fout << "\\hline \n\\end{tabular}" << std::endl << std::endl; } } void LauCPFitModel::checkInitFitParams() { // Update the number of signal events to be total-sum(background events) this->updateSigEvents(); // Check whether we want to have randomised initial fit parameters for the signal model if (this->useRandomInitFitPars() == kTRUE) { std::cout << "INFO in LauCPFitModel::checkInitFitParams : Setting random parameters for the signal model" << std::endl; this->randomiseInitFitPars(); } } void LauCPFitModel::randomiseInitFitPars() { // Only randomise those parameters that are not fixed! std::cout << "INFO in LauCPFitModel::randomiseInitFitPars : Randomising the initial fit magnitudes and phases of the components..." << std::endl; if ( fixParamFileName_.IsNull() && fixParamMap_.empty() ) { // No params are imported - randomise as normal for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } } else { // Only randomise those that are not imported (i.e., not found in allImportedFreeParams_) // by temporarily fixing all imported parameters, and then freeing those not set to be fixed when imported, // except those that are previously set to be fixed anyhow. // Convoluted, but beats changing the behaviour of functions that call checkInitFitParams or the coeffSet // itself. for (auto p : allImportedFreeParams_) { p->fixed(kTRUE); } for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } for (auto p : allImportedFreeParams_) { p->fixed(kFALSE); } } } std::pair LauCPFitModel::eventsToGenerate() { // Determine the number of events to generate for each hypothesis // If we're smearing then smear each one individually LauGenInfo nEvtsGen; // Keep track of whether any yield or asymmetry parameters are blinded Bool_t blind = kFALSE; // Signal if ( signalEvents_->blind() ) { blind = kTRUE; } Double_t evtWeight(1.0); Double_t nEvts = signalEvents_->genValue(); if ( nEvts < 0.0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } Double_t sigAsym(0.0); // need to include this as an alternative in case the DP isn't in the model if ( !this->useDP() || forceAsym_ ) { sigAsym = signalAsym_->genValue(); if ( signalAsym_->blind() ) { blind = kTRUE; } } else { Double_t negRate = negSigModel_->getDPNorm(); Double_t posRate = posSigModel_->getDPNorm(); if (negRate+posRate>1e-30) { sigAsym = (negRate-posRate)/(negRate+posRate); } } Double_t nPosEvts = (nEvts/2.0 * (1.0 - sigAsym)); Double_t nNegEvts = (nEvts/2.0 * (1.0 + sigAsym)); Int_t nPosEvtsToGen { static_cast(nPosEvts) }; Int_t nNegEvtsToGen { static_cast(nNegEvts) }; if (this->doPoissonSmearing()) { nPosEvtsToGen = LauRandom::randomFun()->Poisson(nPosEvts); nNegEvtsToGen = LauRandom::randomFun()->Poisson(nNegEvts); } nEvtsGen[std::make_pair("signal",+1)] = std::make_pair(nPosEvtsToGen,evtWeight); nEvtsGen[std::make_pair("signal",-1)] = std::make_pair(nNegEvtsToGen,evtWeight); // backgrounds const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; const LauAbsRValue* asymPar = bkgndAsym_[bkgndID]; if ( evtsPar->blind() || asymPar->blind() ) { blind = kTRUE; } evtWeight = 1.0; nEvts = evtsPar->genValue(); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } const Double_t asym = asymPar->genValue(); nPosEvts = (nEvts/2.0 * (1.0 - asym)); nNegEvts = (nEvts/2.0 * (1.0 + asym)); nPosEvtsToGen = static_cast(nPosEvts); nNegEvtsToGen = static_cast(nNegEvts); if (this->doPoissonSmearing()) { nPosEvtsToGen = LauRandom::randomFun()->Poisson(nPosEvts); nNegEvtsToGen = LauRandom::randomFun()->Poisson(nNegEvts); } const TString& bkgndClass = this->bkgndClassName(bkgndID); nEvtsGen[std::make_pair(bkgndClass,+1)] = std::make_pair(nPosEvtsToGen,evtWeight); nEvtsGen[std::make_pair(bkgndClass,-1)] = std::make_pair(nNegEvtsToGen,evtWeight); } // Print out the information on what we're generating, but only if none of the parameters are blind (otherwise we risk unblinding them!) if ( !blind ) { std::cout << "INFO in LauCPFitModel::eventsToGenerate : Generating toy MC with:" << std::endl; std::cout << " : Signal asymmetry = " << sigAsym << " and number of signal events = " << signalEvents_->genValue() << std::endl; for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const TString& bkgndClass = this->bkgndClassName(bkgndID); const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; const LauAbsRValue* asymPar = bkgndAsym_[bkgndID]; std::cout << " : " << bkgndClass << " asymmetry = " << asymPar->genValue() << " and number of " << bkgndClass << " events = " << evtsPar->genValue() << std::endl; } } return std::make_pair( nEvtsGen, blind ); } Bool_t LauCPFitModel::genExpt() { // Routine to generate toy Monte Carlo events according to the various models we have defined. // Determine the number of events to generate for each hypothesis std::pair info = this->eventsToGenerate(); LauGenInfo nEvts = info.first; const Bool_t blind = info.second; Bool_t genOK(kTRUE); Int_t evtNum(0); const UInt_t nBkgnds = this->nBkgndClasses(); std::vector bkgndClassNames(nBkgnds); std::vector bkgndClassNamesGen(nBkgnds); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); bkgndClassNames[iBkgnd] = name; bkgndClassNamesGen[iBkgnd] = "gen"+name; } const Bool_t storeSCFTruthInfo = ( useSCF_ || ( this->enableEmbedding() && negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") && posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) ); // Loop over the hypotheses and generate the requested number of events for each one for (LauGenInfo::const_iterator iter = nEvts.begin(); iter != nEvts.end(); ++iter) { const TString& type(iter->first.first); curEvtCharge_ = iter->first.second; Double_t evtWeight( iter->second.second ); Int_t nEvtsGen( iter->second.first ); for (Int_t iEvt(0); iEvtsetGenNtupleDoubleBranchValue( "evtWeight", evtWeight ); this->setGenNtupleDoubleBranchValue( "efficiency", 1.0 ); if (type == "signal") { this->setGenNtupleIntegerBranchValue("genSig",1); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 ); } genOK = this->generateSignalEvent(); if ( curEvtCharge_ > 0 ){ this->setGenNtupleDoubleBranchValue( "efficiency", posSigModel_->getEvtEff() ); } else { this->setGenNtupleDoubleBranchValue( "efficiency", negSigModel_->getEvtEff() ); } } else { this->setGenNtupleIntegerBranchValue("genSig",0); if ( storeSCFTruthInfo ) { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",0); } UInt_t bkgndID(0); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { Int_t gen(0); if ( bkgndClassNames[iBkgnd] == type ) { gen = 1; bkgndID = iBkgnd; } this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], gen ); } genOK = this->generateBkgndEvent(bkgndID); } if (!genOK) { // If there was a problem with the generation then break out and return. // The problem model will have adjusted itself so that all should be OK next time. break; } if (this->useDP() == kTRUE) { this->setDPBranchValues(); } // Store the event charge this->setGenNtupleIntegerBranchValue(tagVarName_,curEvtCharge_); // Store the event number (within this experiment) // and then increment it this->setGenNtupleIntegerBranchValue("iEvtWithinExpt",evtNum); ++evtNum; this->fillGenNtupleBranches(); if ( !blind && (iEvt%500 == 0) ) { std::cout << "INFO in LauCPFitModel::genExpt : Generated event number " << iEvt << " out of " << nEvtsGen << " " << type << " events." << std::endl; } } if (!genOK) { break; } } if (this->useDP() && genOK) { negSigModel_->checkToyMC(kTRUE,kTRUE); posSigModel_->checkToyMC(kTRUE,kTRUE); // Get the fit fractions if they're to be written into the latex table if (this->writeLatexTable()) { LauParArray negFitFrac = negSigModel_->getFitFractions(); if (negFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray posFitFrac = posSigModel_->getFitFractions(); if (posFitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); posMeanEff_.value(posSigModel_->getMeanEff().value()); negDPRate_.value(negSigModel_->getDPRate().value()); posDPRate_.value(posSigModel_->getDPRate().value()); } } // If we're reusing embedded events or if the generation is being // reset then clear the lists of used events if (reuseSignal_ || !genOK) { if (negSignalTree_) { negSignalTree_->clearUsedList(); } if (posSignalTree_) { posSignalTree_->clearUsedList(); } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = negBkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = posBkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } return genOK; } Bool_t LauCPFitModel::generateSignalEvent() { // Generate signal event Bool_t genOK(kTRUE); Bool_t genSCF(kFALSE); LauIsobarDynamics* model(0); LauKinematics* kinematics(0); LauEmbeddedData* embeddedData(0); LauPdfList* sigPdfs(0); LauPdfList* scfPdfs(0); Bool_t doReweighting(kFALSE); if (curEvtCharge_<0) { model = negSigModel_; kinematics = negKinematics_; sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; if (this->enableEmbedding()) { embeddedData = negSignalTree_; doReweighting = useNegReweighting_; } } else { model = posSigModel_; kinematics = posKinematics_; if ( tagged_ ) { sigPdfs = &posSignalPdfs_; scfPdfs = &posScfPdfs_; } else { sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; } if (this->enableEmbedding()) { embeddedData = posSignalTree_; doReweighting = usePosReweighting_; } } if (this->useDP()) { if (embeddedData) { if (doReweighting) { // Select a (random) event from the generated data. Then store the // reconstructed DP co-ords, together with other pdf information, // as the embedded data. genOK = embeddedData->getReweightedEvent(model); } else { // Just get the information of a (randomly) selected event in the // embedded data embeddedData->getEmbeddedEvent(kinematics); } genSCF = this->storeSignalMCMatch( embeddedData ); } else { genOK = model->generate(); if ( genOK && useSCF_ ) { Double_t frac(0.0); if ( useSCFHist_ ) { frac = scfFracHist_->calcEfficiency( kinematics ); } else { frac = scfFrac_.genValue(); } if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; // Optionally smear the DP position // of the SCF event if ( scfMap_ != 0 ) { Double_t xCoord(0.0), yCoord(0.0); if ( kinematics->squareDP() ) { xCoord = kinematics->getmPrime(); yCoord = kinematics->getThetaPrime(); } else { xCoord = kinematics->getm13Sq(); yCoord = kinematics->getm23Sq(); } // Find the bin number where this event is generated Int_t binNo = scfMap_->binNumber( xCoord, yCoord ); // Retrieve the migration histogram TH2* histo = scfMap_->trueHist( binNo ); const LauAbsEffModel * effModel = model->getEffModel(); do { // Get a random point from the histogram histo->GetRandom2( xCoord, yCoord ); // Update the kinematics if ( kinematics->squareDP() ) { kinematics->updateSqDPKinematics( xCoord, yCoord ); } else { kinematics->updateKinematics( xCoord, yCoord ); } } while ( ! effModel->passVeto( kinematics ) ); } } } } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); genSCF = this->storeSignalMCMatch( embeddedData ); } else if ( useSCF_ ) { Double_t frac = scfFrac_.genValue(); if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } if (genOK) { if ( useSCF_ ) { if ( genSCF ) { this->generateExtraPdfValues(scfPdfs, embeddedData); } else { this->generateExtraPdfValues(sigPdfs, embeddedData); } } else { this->generateExtraPdfValues(sigPdfs, embeddedData); } } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { std::cerr << "WARNING in LauCPFitModel::generateSignalEvent : Source of embedded signal events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } Bool_t LauCPFitModel::generateBkgndEvent(UInt_t bkgndID) { // Generate Bkgnd event Bool_t genOK(kTRUE); LauAbsBkgndDPModel* model(0); LauEmbeddedData* embeddedData(0); LauPdfList* extraPdfs(0); LauKinematics* kinematics(0); if (curEvtCharge_<0) { model = negBkgndDPModels_[bkgndID]; if (this->enableEmbedding()) { embeddedData = negBkgndTree_[bkgndID]; } extraPdfs = &negBkgndPdfs_[bkgndID]; kinematics = negKinematics_; } else { model = posBkgndDPModels_[bkgndID]; if (this->enableEmbedding()) { embeddedData = posBkgndTree_[bkgndID]; } if ( tagged_ ) { extraPdfs = &posBkgndPdfs_[bkgndID]; } else { extraPdfs = &negBkgndPdfs_[bkgndID]; } kinematics = posKinematics_; } if (this->useDP()) { if (embeddedData) { embeddedData->getEmbeddedEvent(kinematics); } else { if (model == 0) { const TString& bkgndClass = this->bkgndClassName(bkgndID); std::cerr << "ERROR in LauCPFitModel::generateBkgndEvent : Can't find the DP model for background class \"" << bkgndClass << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } genOK = model->generate(); } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); } } if (genOK) { this->generateExtraPdfValues(extraPdfs, embeddedData); } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { const TString& bkgndClass = this->bkgndClassName(bkgndID); std::cerr << "WARNING in LauCPFitModel::generateBkgndEvent : Source of embedded " << bkgndClass << " events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } void LauCPFitModel::setupGenNtupleBranches() { // Setup the required ntuple branches this->addGenNtupleDoubleBranch("evtWeight"); this->addGenNtupleIntegerBranch("genSig"); this->addGenNtupleDoubleBranch("efficiency"); if ( useSCF_ || ( this->enableEmbedding() && negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") && posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) ) { this->addGenNtupleIntegerBranch("genTMSig"); this->addGenNtupleIntegerBranch("genSCFSig"); } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name.Prepend("gen"); this->addGenNtupleIntegerBranch(name); } this->addGenNtupleIntegerBranch("charge"); if (this->useDP() == kTRUE) { this->addGenNtupleDoubleBranch("m12"); this->addGenNtupleDoubleBranch("m23"); this->addGenNtupleDoubleBranch("m13"); this->addGenNtupleDoubleBranch("m12Sq"); this->addGenNtupleDoubleBranch("m23Sq"); this->addGenNtupleDoubleBranch("m13Sq"); this->addGenNtupleDoubleBranch("cosHel12"); this->addGenNtupleDoubleBranch("cosHel23"); this->addGenNtupleDoubleBranch("cosHel13"); if (negKinematics_->squareDP() && posKinematics_->squareDP()) { this->addGenNtupleDoubleBranch("mPrime"); this->addGenNtupleDoubleBranch("thPrime"); } } for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { this->addGenNtupleDoubleBranch( (*var_iter) ); } } } } void LauCPFitModel::setDPBranchValues() { LauKinematics* kinematics(0); if (curEvtCharge_<0) { kinematics = negKinematics_; } else { kinematics = posKinematics_; } // Store all the DP information this->setGenNtupleDoubleBranchValue("m12", kinematics->getm12()); this->setGenNtupleDoubleBranchValue("m23", kinematics->getm23()); this->setGenNtupleDoubleBranchValue("m13", kinematics->getm13()); this->setGenNtupleDoubleBranchValue("m12Sq", kinematics->getm12Sq()); this->setGenNtupleDoubleBranchValue("m23Sq", kinematics->getm23Sq()); this->setGenNtupleDoubleBranchValue("m13Sq", kinematics->getm13Sq()); this->setGenNtupleDoubleBranchValue("cosHel12", kinematics->getc12()); this->setGenNtupleDoubleBranchValue("cosHel23", kinematics->getc23()); this->setGenNtupleDoubleBranchValue("cosHel13", kinematics->getc13()); if (kinematics->squareDP()) { this->setGenNtupleDoubleBranchValue("mPrime", kinematics->getmPrime()); this->setGenNtupleDoubleBranchValue("thPrime", kinematics->getThetaPrime()); } } void LauCPFitModel::generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData) { LauKinematics* kinematics(0); if (curEvtCharge_<0) { kinematics = negKinematics_; } else { kinematics = posKinematics_; } if (!extraPdfs) { std::cerr << "ERROR in LauCPFitModel::generateExtraPdfValues : Null pointer to PDF list." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (extraPdfs->empty()) { //std::cerr << "WARNING in LauCPFitModel::generateExtraPdfValues : PDF list is empty." << std::endl; return; } // Generate from the extra PDFs for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { LauFitData genValues; if (embeddedData) { genValues = embeddedData->getValues( (*pdf_iter)->varNames() ); } else { genValues = (*pdf_iter)->generate(kinematics); } for ( LauFitData::const_iterator var_iter = genValues.begin(); var_iter != genValues.end(); ++var_iter ) { TString varName = var_iter->first; if ( varName != "m13Sq" && varName != "m23Sq" ) { Double_t value = var_iter->second; this->setGenNtupleDoubleBranchValue(varName,value); } } } } Bool_t LauCPFitModel::storeSignalMCMatch(LauEmbeddedData* embeddedData) { // Default to TM Bool_t genSCF(kFALSE); Int_t match(1); // Check that we have a valid pointer and that embedded data has // the mcMatch branch. If so then get the match value. if ( embeddedData && embeddedData->haveBranch("mcMatch") ) { match = TMath::Nint( embeddedData->getValue("mcMatch") ); } // Set the variables accordingly. if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } return genSCF; } void LauCPFitModel::propagateParUpdates() { // Update the signal parameters and then the total normalisation for the signal likelihood if (this->useDP() == kTRUE) { this->updateCoeffs(); negSigModel_->updateCoeffs(negCoeffs_); posSigModel_->updateCoeffs(posCoeffs_); } // Update the signal fraction from the background fractions if not doing an extended fit if ( !this->doEMLFit() && !signalEvents_->fixed() ) { this->updateSigEvents(); } } void LauCPFitModel::updateSigEvents() { // The background parameters will have been set from Minuit. // We need to update the signal events using these. Double_t nTotEvts = this->eventsPerExpt(); signalEvents_->range(-2.0*nTotEvts,2.0*nTotEvts); for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { LauAbsRValue* nBkgndEvents = (*iter); if ( nBkgndEvents->isLValue() ) { LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*nTotEvts,2.0*nTotEvts); } } if (signalEvents_->fixed()) { return; } // Subtract background events (if any) from signal. Double_t signalEvents = nTotEvts; if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { signalEvents -= (*iter)->value(); } } signalEvents_->value(signalEvents); } void LauCPFitModel::cacheInputFitVars() { // Fill the internal data trees of the signal and background models. // Note that we store the events of both charges in both the // negative and the positive models. It's only later, at the stage // when the likelihood is being calculated, that we separate them. LauFitDataTree* inputFitData = this->fitData(); // First the Dalitz plot variables (m_ij^2) if (this->useDP() == kTRUE) { // need to append SCF smearing bins before caching DP amplitudes if ( scfMap_ != 0 ) { this->appendBinCentres( inputFitData ); } negSigModel_->fillDataTree(*inputFitData); posSigModel_->fillDataTree(*inputFitData); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } } } // ...and then the extra PDFs this->cacheInfo(negSignalPdfs_, *inputFitData); this->cacheInfo(negScfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } if ( tagged_ ) { this->cacheInfo(posSignalPdfs_, *inputFitData); this->cacheInfo(posScfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } } // the SCF fractions and jacobians if ( useSCF_ && useSCFHist_ ) { if ( !inputFitData->haveBranch( "m13Sq" ) || !inputFitData->haveBranch( "m23Sq" ) ) { std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain DP branches and so can't cache the SCF fraction." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); recoSCFFracs_.clear(); recoSCFFracs_.reserve( nEvents ); if ( negKinematics_->squareDP() ) { recoJacobians_.clear(); recoJacobians_.reserve( nEvents ); } for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator m13_iter = dataValues.find("m13Sq"); LauFitData::const_iterator m23_iter = dataValues.find("m23Sq"); negKinematics_->updateKinematics( m13_iter->second, m23_iter->second ); Double_t scfFrac = scfFracHist_->calcEfficiency( negKinematics_ ); recoSCFFracs_.push_back( scfFrac ); if ( negKinematics_->squareDP() ) { recoJacobians_.push_back( negKinematics_->calcSqDPJacobian() ); } } } // finally cache the event charge evtCharges_.clear(); if ( tagged_ ) { if ( !inputFitData->haveBranch( tagVarName_ ) ) { std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain branch \"" << tagVarName_ << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); evtCharges_.reserve( nEvents ); for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator iter = dataValues.find( tagVarName_ ); curEvtCharge_ = static_cast( iter->second ); evtCharges_.push_back( curEvtCharge_ ); } } } void LauCPFitModel::appendBinCentres( LauFitDataTree* inputData ) { // We'll be caching the DP amplitudes and efficiencies of the centres of the true bins. // To do so, we attach some fake points at the end of inputData, the number of the entry // minus the total number of events corresponding to the number of the histogram for that // given true bin in the LauScfMap object. (What this means is that when Laura is provided with // the LauScfMap object by the user, it's the latter who has to make sure that it contains the // right number of histograms and in exactly the right order!) // Get the x and y co-ordinates of the bin centres std::vector binCentresXCoords; std::vector binCentresYCoords; scfMap_->listBinCentres(binCentresXCoords, binCentresYCoords); // The SCF histograms could be in square Dalitz plot histograms. // The dynamics takes normal Dalitz plot coords, so we might have to convert them back. Bool_t sqDP = negKinematics_->squareDP(); UInt_t nBins = binCentresXCoords.size(); fakeSCFFracs_.clear(); fakeSCFFracs_.reserve( nBins ); if ( sqDP ) { fakeJacobians_.clear(); fakeJacobians_.reserve( nBins ); } for (UInt_t iBin = 0; iBin < nBins; ++iBin) { if ( sqDP ) { negKinematics_->updateSqDPKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); binCentresXCoords[iBin] = negKinematics_->getm13Sq(); binCentresYCoords[iBin] = negKinematics_->getm23Sq(); fakeJacobians_.push_back( negKinematics_->calcSqDPJacobian() ); } else { negKinematics_->updateKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); } fakeSCFFracs_.push_back( scfFracHist_->calcEfficiency( negKinematics_ ) ); } // Set up inputFitVars_ object to hold the fake events inputData->appendFakePoints(binCentresXCoords,binCentresYCoords); } Double_t LauCPFitModel::getTotEvtLikelihood(UInt_t iEvt) { // Find out whether we have B- or B+ if ( tagged_ ) { curEvtCharge_ = evtCharges_[iEvt]; // check that the charge is either +1 or -1 if (TMath::Abs(curEvtCharge_)!=1) { std::cerr << "ERROR in LauCPFitModel::getTotEvtLikelihood : Charge/tag not accepted value: " << curEvtCharge_ << std::endl; if (curEvtCharge_>0) { curEvtCharge_ = +1; } else { curEvtCharge_ = -1; } std::cerr << " : Making it: " << curEvtCharge_ << "." << std::endl; } } // Get the DP likelihood for signal and backgrounds this->getEvtDPLikelihood(iEvt); // Get the combined extra PDFs likelihood for signal and backgrounds this->getEvtExtraLikelihoods(iEvt); // If appropriate, combine the TM and SCF likelihoods Double_t sigLike = sigDPLike_ * sigExtraLike_; if ( useSCF_ ) { Double_t scfFrac(0.0); if (useSCFHist_) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } sigLike *= (1.0 - scfFrac); if ( (scfMap_ != 0) && (this->useDP() == kTRUE) ) { // if we're smearing the SCF DP PDF then the SCF frac // is already included in the SCF DP likelihood sigLike += (scfDPLike_ * scfExtraLike_); } else { sigLike += (scfFrac * scfDPLike_ * scfExtraLike_); } } // Get the correct event fractions depending on the charge // Signal asymmetry is built into the DP model... but when the DP // isn't in the fit we need an explicit parameter Double_t signalEvents = signalEvents_->unblindValue() * 0.5; if (this->useDP() == kFALSE) { signalEvents *= (1.0 - curEvtCharge_ * signalAsym_->unblindValue()); } // Construct the total event likelihood Double_t likelihood(0.0); if (usingBkgnd_) { likelihood = sigLike*signalEvents; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { Double_t bkgndEvents = bkgndEvents_[bkgndID]->unblindValue() * 0.5 * (1.0 - curEvtCharge_ * bkgndAsym_[bkgndID]->unblindValue()); likelihood += bkgndEvents*bkgndDPLike_[bkgndID]*bkgndExtraLike_[bkgndID]; } } else { likelihood = sigLike*0.5; } return likelihood; } Double_t LauCPFitModel::getEventSum() const { Double_t eventSum(0.0); eventSum += signalEvents_->unblindValue(); if (usingBkgnd_) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { eventSum += (*iter)->unblindValue(); } } return eventSum; } void LauCPFitModel::getEvtDPLikelihood(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // Dalitz plot for the given event evtNo. if ( ! this->useDP() ) { // There's always going to be a term in the likelihood for the // signal, so we'd better not zero it. sigDPLike_ = 1.0; scfDPLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 1.0; } else { bkgndDPLike_[bkgndID] = 0.0; } } return; } const UInt_t nBkgnds = this->nBkgndClasses(); if ( tagged_ ) { if (curEvtCharge_==+1) { posSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = posSigModel_->getEvtIntensity(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = posBkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } else { negSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = negSigModel_->getEvtIntensity(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = negBkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } } else { posSigModel_->calcLikelihoodInfo(iEvt); negSigModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = 0.5 * ( posSigModel_->getEvtIntensity() + negSigModel_->getEvtIntensity() ); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 0.5 * ( posBkgndDPModels_[bkgndID]->getLikelihood(iEvt) + negBkgndDPModels_[bkgndID]->getLikelihood(iEvt) ); } else { bkgndDPLike_[bkgndID] = 0.0; } } } if ( useSCF_ == kTRUE ) { if ( scfMap_ == 0 ) { // we're not smearing the SCF DP position // so the likelihood is the same as the TM scfDPLike_ = sigDPLike_; } else { // calculate the smeared SCF DP likelihood scfDPLike_ = this->getEvtSCFDPLikelihood(iEvt); } } // Calculate the signal normalisation // NB the 2.0 is there so that the 0.5 factor is applied to // signal and background in the same place otherwise you get // normalisation problems when you switch off the DP in the fit Double_t norm = negSigModel_->getDPNorm() + posSigModel_->getDPNorm(); sigDPLike_ *= 2.0/norm; scfDPLike_ *= 2.0/norm; } Double_t LauCPFitModel::getEvtSCFDPLikelihood(UInt_t iEvt) { Double_t scfDPLike(0.0); Double_t recoJacobian(1.0); Double_t xCoord(0.0); Double_t yCoord(0.0); Bool_t squareDP = negKinematics_->squareDP(); if ( squareDP ) { xCoord = negSigModel_->getEvtmPrime(); yCoord = negSigModel_->getEvtthPrime(); recoJacobian = recoJacobians_[iEvt]; } else { xCoord = negSigModel_->getEvtm13Sq(); yCoord = negSigModel_->getEvtm23Sq(); } // Find the bin that our reco event falls in Int_t recoBin = scfMap_->binNumber( xCoord, yCoord ); // Find out which true Bins contribute to the given reco bin const std::vector* trueBins = scfMap_->trueBins(recoBin); const Int_t nDataEvents = this->eventsPerExpt(); // Loop over the true bins for (std::vector::const_iterator iter = trueBins->begin(); iter != trueBins->end(); ++iter) { Int_t trueBin = (*iter); // prob of a true event in the given true bin migrating to the reco bin Double_t pRecoGivenTrue = scfMap_->prob( recoBin, trueBin ); Double_t pTrue(0.0); // We've cached the DP amplitudes and the efficiency for the // true bin centres, just after the data points if ( tagged_ ) { LauIsobarDynamics* sigModel(0); if (curEvtCharge_<0) { sigModel = negSigModel_; } else { sigModel = posSigModel_; } sigModel->calcLikelihoodInfo( nDataEvents + trueBin ); pTrue = sigModel->getEvtIntensity(); } else { posSigModel_->calcLikelihoodInfo( nDataEvents + trueBin ); negSigModel_->calcLikelihoodInfo( nDataEvents + trueBin ); pTrue = 0.5 * ( posSigModel_->getEvtIntensity() + negSigModel_->getEvtIntensity() ); } // Get the cached SCF fraction (and jacobian if we're using the square DP) Double_t scfFraction = fakeSCFFracs_[ trueBin ]; Double_t jacobian(1.0); if ( squareDP ) { jacobian = fakeJacobians_[ trueBin ]; } scfDPLike += pTrue * jacobian * scfFraction * pRecoGivenTrue; } // Divide by the reco jacobian scfDPLike /= recoJacobian; return scfDPLike; } void LauCPFitModel::getEvtExtraLikelihoods(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // extra variables for the given event evtNo. sigExtraLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); if ( ! tagged_ || curEvtCharge_ < 0 ) { sigExtraLike_ = this->prodPdfValue( negSignalPdfs_, iEvt ); if (useSCF_) { scfExtraLike_ = this->prodPdfValue( negScfPdfs_, iEvt ); } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = this->prodPdfValue( negBkgndPdfs_[bkgndID], iEvt ); } else { bkgndExtraLike_[bkgndID] = 0.0; } } } else { sigExtraLike_ = this->prodPdfValue( posSignalPdfs_, iEvt ); if (useSCF_) { scfExtraLike_ = this->prodPdfValue( posScfPdfs_, iEvt ); } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = this->prodPdfValue( posBkgndPdfs_[bkgndID], iEvt ); } else { bkgndExtraLike_[bkgndID] = 0.0; } } } } void LauCPFitModel::updateCoeffs() { negCoeffs_.clear(); posCoeffs_.clear(); negCoeffs_.reserve(nSigComp_); posCoeffs_.reserve(nSigComp_); for (UInt_t i = 0; i < nSigComp_; i++) { negCoeffs_.push_back(coeffPars_[i]->antiparticleCoeff()); posCoeffs_.push_back(coeffPars_[i]->particleCoeff()); } } void LauCPFitModel::setupSPlotNtupleBranches() { // add branches for storing the experiment number and the number of // the event within the current experiment this->addSPlotNtupleIntegerBranch("iExpt"); this->addSPlotNtupleIntegerBranch("iEvtWithinExpt"); // Store the efficiency of the event (for inclusive BF calculations). if (this->storeDPEff()) { this->addSPlotNtupleDoubleBranch("efficiency"); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->addSPlotNtupleDoubleBranch("scffraction"); } } // Store the total event likelihood for each species. if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFFrac"); } else { this->addSPlotNtupleDoubleBranch("sigTotalLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "TotalLike"; this->addSPlotNtupleDoubleBranch(name); } } // Store the DP likelihoods if (this->useDP()) { if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMDPLike"); this->addSPlotNtupleDoubleBranch("sigSCFDPLike"); } else { this->addSPlotNtupleDoubleBranch("sigDPLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "DPLike"; this->addSPlotNtupleDoubleBranch(name); } } } // Store the likelihoods for each extra PDF if (useSCF_) { this->addSPlotNtupleBranches(&negSignalPdfs_, "sigTM"); this->addSPlotNtupleBranches(&negScfPdfs_, "sigSCF"); } else { this->addSPlotNtupleBranches(&negSignalPdfs_, "sig"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList* pdfList = &(negBkgndPdfs_[iBkgnd]); this->addSPlotNtupleBranches(pdfList, bkgndClass); } } } void LauCPFitModel::addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix) { if (extraPdfs) { // Loop through each of the PDFs for (LauPdfList::const_iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply add one branch for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else if ( nVars == 2 ) { // If the PDF has two variables then we // need a branch for them both together and // branches for each TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; this->addSPlotNtupleDoubleBranch(name); } TString name(prefix); name += allVars; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else { std::cerr << "WARNING in LauCPFitModel::addSPlotNtupleBranches : Can't yet deal with 3D PDFs." << std::endl; } } } } Double_t LauCPFitModel::setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt) { // Store the PDF value for each variable in the list Double_t totalLike(1.0); Double_t extraLike(0.0); if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // calculate the likelihood for this event (*pdf_iter)->calcLikelihoodInfo(iEvt); extraLike = (*pdf_iter)->getLikelihood(); totalLike *= extraLike; // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply store the value for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else if ( nVars == 2 ) { // If the PDF has two variables then we // store the value for them both together // and for each on their own TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; Double_t indivLike = (*pdf_iter)->getLikelihood( (*var_iter) ); this->setSPlotNtupleDoubleBranchValue(name, indivLike); } TString name(prefix); name += allVars; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else { std::cerr << "WARNING in LauCPFitModel::setSPlotNtupleBranchValues : Can't yet deal with 3D PDFs." << std::endl; } } } return totalLike; } LauSPlot::NameSet LauCPFitModel::variableNames() const { LauSPlot::NameSet nameSet; if (this->useDP()) { nameSet.insert("DP"); } // Loop through all the signal PDFs for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { // Loop over the variables involved in each PDF std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { // If they are not DP coordinates then add them if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { nameSet.insert( (*var_iter) ); } } } return nameSet; } LauSPlot::NumbMap LauCPFitModel::freeSpeciesNames() const { LauSPlot::NumbMap numbMap; if (!signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (!par->fixed()) { numbMap[bkgndClass] = par->genValue(); if ( ! par->isLValue() ) { std::cerr << "WARNING in LauCPFitModel::freeSpeciesNames : \"" << par->name() << "\" is a LauFormulaPar, which implies it is perhaps not entirely free to float in the fit, so the sWeight calculation may not be reliable" << std::endl; } } } } return numbMap; } LauSPlot::NumbMap LauCPFitModel::fixdSpeciesNames() const { LauSPlot::NumbMap numbMap; if (signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (par->fixed()) { numbMap[bkgndClass] = par->genValue(); } } } return numbMap; } LauSPlot::TwoDMap LauCPFitModel::twodimPDFs() const { // This makes the assumption that the form of the positive and // negative PDFs are the same, which seems reasonable to me LauSPlot::TwoDMap twodimMap; for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { if (useSCF_) { twodimMap.insert( std::make_pair( "sigTM", std::make_pair( varNames[0], varNames[1] ) ) ); } else { twodimMap.insert( std::make_pair( "sig", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if ( useSCF_ ) { for (LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( "sigSCF", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList& pdfList = negBkgndPdfs_[iBkgnd]; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( bkgndClass, std::make_pair( varNames[0], varNames[1] ) ) ); } } } } return twodimMap; } void LauCPFitModel::storePerEvtLlhds() { std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Storing per-event likelihood values..." << std::endl; // if we've not been using the DP model then we need to cache all // the info here so that we can get the efficiency from it LauFitDataTree* inputFitData = this->fitData(); if (!this->useDP() && this->storeDPEff()) { negSigModel_->initialise(negCoeffs_); posSigModel_->initialise(posCoeffs_); negSigModel_->fillDataTree(*inputFitData); posSigModel_->fillDataTree(*inputFitData); } UInt_t evtsPerExpt(this->eventsPerExpt()); LauIsobarDynamics* sigModel(0); LauPdfList* sigPdfs(0); LauPdfList* scfPdfs(0); LauBkgndPdfsList* bkgndPdfs(0); for (UInt_t iEvt = 0; iEvt < evtsPerExpt; ++iEvt) { this->setSPlotNtupleIntegerBranchValue("iExpt",this->iExpt()); this->setSPlotNtupleIntegerBranchValue("iEvtWithinExpt",iEvt); // Find out whether we have B- or B+ if ( tagged_ ) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator iter = dataValues.find("charge"); curEvtCharge_ = static_cast(iter->second); if (curEvtCharge_==+1) { sigModel = posSigModel_; sigPdfs = &posSignalPdfs_; scfPdfs = &posScfPdfs_; bkgndPdfs = &posBkgndPdfs_; } else { sigModel = negSigModel_; sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; bkgndPdfs = &negBkgndPdfs_; } } else { sigPdfs = &negSignalPdfs_; scfPdfs = &negScfPdfs_; bkgndPdfs = &negBkgndPdfs_; } // the DP information this->getEvtDPLikelihood(iEvt); if (this->storeDPEff()) { if (!this->useDP()) { posSigModel_->calcLikelihoodInfo(iEvt); negSigModel_->calcLikelihoodInfo(iEvt); } if ( tagged_ ) { this->setSPlotNtupleDoubleBranchValue("efficiency",sigModel->getEvtEff()); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",sigModel->getEvtScfFraction()); } } else { this->setSPlotNtupleDoubleBranchValue("efficiency",0.5*(posSigModel_->getEvtEff() + negSigModel_->getEvtEff()) ); if ( negSigModel_->usingScfModel() && posSigModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",0.5*(posSigModel_->getEvtScfFraction() + negSigModel_->getEvtScfFraction())); } } } if (this->useDP()) { sigTotalLike_ = sigDPLike_; if (useSCF_) { scfTotalLike_ = scfDPLike_; this->setSPlotNtupleDoubleBranchValue("sigTMDPLike",sigDPLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFDPLike",scfDPLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigDPLike",sigDPLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "DPLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndDPLike_[iBkgnd]); } } } else { sigTotalLike_ = 1.0; if (useSCF_) { scfTotalLike_ = 1.0; } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { bkgndTotalLike_[iBkgnd] = 1.0; } } } // the signal PDF values if ( useSCF_ ) { sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sigTM", iEvt); scfTotalLike_ *= this->setSPlotNtupleBranchValues(scfPdfs, "sigSCF", iEvt); } else { sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sig", iEvt); } // the background PDF values if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); LauPdfList& pdfs = (*bkgndPdfs)[iBkgnd]; bkgndTotalLike_[iBkgnd] *= this->setSPlotNtupleBranchValues(&(pdfs), bkgndClass, iEvt); } } // the total likelihoods if (useSCF_) { Double_t scfFrac(0.0); if ( useSCFHist_ ) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } this->setSPlotNtupleDoubleBranchValue("sigSCFFrac",scfFrac); sigTotalLike_ *= ( 1.0 - scfFrac ); if ( scfMap_ == 0 ) { scfTotalLike_ *= scfFrac; } this->setSPlotNtupleDoubleBranchValue("sigTMTotalLike",sigTotalLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFTotalLike",scfTotalLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigTotalLike",sigTotalLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "TotalLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndTotalLike_[iBkgnd]); } } // fill the tree this->fillSPlotNtupleBranches(); } std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Finished storing per-event likelihood values." << std::endl; } void LauCPFitModel::embedNegSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (negSignalTree_) { std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Already embedding signal from a file." << std::endl; return; } negSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = negSignalTree_->findBranches(); if (!dataOK) { delete negSignalTree_; negSignalTree_ = 0; std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; useNegReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedNegBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (negBkgndTree_[bkgndID]) { std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Already embedding background from a file." << std::endl; return; } negBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = negBkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete negBkgndTree_[bkgndID]; negBkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedPosSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (posSignalTree_) { std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Already embedding signal from a file." << std::endl; return; } posSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = posSignalTree_->findBranches(); if (!dataOK) { delete posSignalTree_; posSignalTree_ = 0; std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; usePosReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::embedPosBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (posBkgndTree_[bkgndID]) { std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Already embedding background from a file." << std::endl; return; } posBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = posBkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete posBkgndTree_[bkgndID]; posBkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);} } void LauCPFitModel::weightEvents( const TString& dataFileName, const TString& dataTreeName ) { // Routine to provide weights for events that are uniformly distributed // in the DP (or square DP) so as to reproduce the given DP model const Bool_t squareDP { posKinematics_->squareDP() || negKinematics_->squareDP() }; if ( squareDP ) { std::cout << "INFO in LauCPFitModel::weightEvents : will store DP model weights and the square DP jacobian\n"; std::cout << " : the DP model weights can be used on their own to weight events that were generated flat in phase space\n"; std::cout << " : or they can be multiplied by the jacobian to weight events that were generated flat in the square DP\n"; std::cout << " : or they can be multiplied by max(1.0, jacobian) to weight events that were generated quasi-flat in the square DP" << std::endl; } else { std::cout << "INFO in LauCPFitModel::weightEvents : will store DP model weights suitable for weighting events that 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. const Bool_t dataOK { this->verifyFitData( dataFileName, dataTreeName ) }; if ( ! dataOK ) { std::cerr << "ERROR in LauCPFitModel::weightEvents : Problem caching the data." << std::endl; return; } LauFitDataTree* inputFitData { this->fitData() }; if ( ! inputFitData->haveBranch( "m13Sq_MC" ) || ! inputFitData->haveBranch( "m23Sq_MC" ) ) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Cannot find MC truth DP coordinate branches in supplied data, aborting." << std::endl; return; } if ( ! inputFitData->haveBranch( "charge" ) ) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Cannot find branch specifying event charge in supplied data, aborting." << std::endl; return; } // Create the ntuple to hold the DP weights TString weightsFileName{ dataFileName }; const Ssiz_t index { weightsFileName.Last('.') }; weightsFileName.Insert( index, "_DPweights" ); LauGenNtuple weightsTuple { weightsFileName, dataTreeName }; weightsTuple.addIntegerBranch( "iExpt" ); weightsTuple.addIntegerBranch( "iEvtWithinExpt" ); weightsTuple.addDoubleBranch( "dpModelWeight" ); if ( squareDP ) { weightsTuple.addDoubleBranch( "sqDPJacobian" ); } const UInt_t nExpmt { this->nExpt() }; const UInt_t firstExpmt { this->firstExpt() }; for (UInt_t iExpmt {firstExpmt}; iExpmt < (firstExpmt+nExpmt); ++iExpmt) { inputFitData->readExperimentData(iExpmt); const UInt_t nEvents { inputFitData->nEvents() }; if ( nEvents < 1 ) { std::cerr << "WARNING in LauCPFitModel::weightEvents : Zero events in experiment " << iExpmt << ", skipping..." << std::endl; continue; } weightsTuple.setIntegerBranchValue( "iExpt", iExpmt ); // Calculate and store the weights for the events in this experiment for ( UInt_t iEvent{0}; iEvent < nEvents; ++iEvent ) { weightsTuple.setIntegerBranchValue( "iEvtWithinExpt", iEvent ); const LauFitData& evtData = inputFitData->getData( iEvent ); const auto m13Sq_MC { evtData.at( "m13Sq_MC" ) }; const auto m23Sq_MC { evtData.at( "m23Sq_MC" ) }; const auto charge { static_cast( evtData.at( "charge" ) ) }; Double_t dpModelWeight{0.0}; Double_t jacobian{1.0}; LauKinematics * kinematics{nullptr}; LauIsobarDynamics * dpModel{nullptr}; if (charge > 0) { kinematics = posKinematics_; dpModel = posSigModel_; } else { kinematics = negKinematics_; dpModel = negSigModel_; } if ( kinematics->withinDPLimits( m13Sq_MC, m23Sq_MC ) ) { kinematics->updateKinematics( m13Sq_MC, m23Sq_MC ); dpModelWeight = dpModel->getEventWeight(); if ( squareDP ) { jacobian = kinematics->calcSqDPJacobian(); } const Double_t norm { 0.5 * ( negSigModel_->getDPNorm() + posSigModel_->getDPNorm() ) }; dpModelWeight /= norm; } weightsTuple.setDoubleBranchValue( "dpModelWeight", dpModelWeight ); if ( squareDP ) { weightsTuple.setDoubleBranchValue( "sqDPJacobian", jacobian ); } weightsTuple.fillBranches(); } } weightsTuple.buildIndex( "iExpt", "iEvtWithinExpt" ); weightsTuple.addFriendTree( dataFileName, dataTreeName ); weightsTuple.writeOutGenResults(); } void LauCPFitModel::savePDFPlots(const TString& label) { savePDFPlotsWave(label, 0); savePDFPlotsWave(label, 1); savePDFPlotsWave(label, 2); std::cout << "LauCPFitModel::plot" << std::endl; // ((LauIsobarDynamics*)negSigModel_)->plot(); //Double_t minm13 = negSigModel_->getKinematics()->getm13Min(); Double_t minm13 = 0.0; Double_t maxm13 = negSigModel_->getKinematics()->getm13Max(); //Double_t minm23 = negSigModel_->getKinematics()->getm23Min(); Double_t minm23 = 0.0; Double_t maxm23 = negSigModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, posChPdf, negChPdf; TString xLabel = "s13"; TString yLabel = "s23"; if (negSigModel_->getDaughters()->gotSymmetricalDP()) { xLabel = "sHigh"; yLabel = "sLow";} Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = negSigModel_->getnCohAmp(); for (UInt_t resID = 0; resID <= nAmp; ++resID) { TGraph2D *posDt = new TGraph2D(); TGraph2D *negDt = new TGraph2D(); TGraph2D *acpDt = new TGraph2D(); TString resName = "TotalAmp"; if (resID != nAmp){ TString tStrResID = Form("%d", resID); const LauIsobarDynamics* model = negSigModel_; const LauAbsResonance* resonance = model->getResonance(resID); resName = resonance->getResonanceName(); std::cout << "resName = " << resName << std::endl; } resName.ReplaceAll("(", ""); resName.ReplaceAll(")", ""); resName.ReplaceAll("*", "Star"); posDt->SetName(resName+label); posDt->SetTitle(resName+" ("+label+") Positive"); negDt->SetName(resName+label); negDt->SetTitle(resName+" ("+label+") Negative"); acpDt->SetName(resName+label); acpDt->SetTitle(resName+" ("+label+") Asymmetry"); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue; negSigModel_->calcLikelihoodInfo(s13, s23); posSigModel_->calcLikelihoodInfo(s13, s23); LauComplex negChAmp = negSigModel_->getEvtDPAmp(); LauComplex posChAmp = posSigModel_->getEvtDPAmp(); if (resID != nAmp){ negChAmp = negSigModel_->getFullAmplitude(resID); posChAmp = posSigModel_->getFullAmplitude(resID); } negChPdf = negChAmp.abs2(); posChPdf = posChAmp.abs2(); negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow count++; } } } gStyle->SetPalette(1); TCanvas *posC = new TCanvas("c"+resName+label + "Positive",resName+" ("+label+") Positive",0,0,600,400); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posDt->Draw("SURF1"); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posC->SaveAs("plot_2D_"+resName + "_"+label+"Positive.C"); TCanvas *negC = new TCanvas("c"+resName+label + "Negative",resName+" ("+label+") Negative",0,0,600,400); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negDt->Draw("SURF1"); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negC->SaveAs("plot_2D_"+resName + "_"+label+"Negative.C"); TCanvas *acpC = new TCanvas("c"+resName+label + "Asymmetry",resName+" ("+label+") Asymmetry",0,0,600,400); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpDt->Draw("SURF1"); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpC->SaveAs("plot_2D_"+resName + "_"+label+"Asymmetry.C"); } } void LauCPFitModel::savePDFPlotsWave(const TString& label, const Int_t& spin) { std::cout << "label = "<< label << ", spin = "<< spin << std::endl; TString tStrResID = "S_Wave"; if (spin == 1) tStrResID = "P_Wave"; if (spin == 2) tStrResID = "D_Wave"; TString xLabel = "s13"; TString yLabel = "s23"; std::cout << "LauCPFitModel::savePDFPlotsWave: "<< tStrResID << std::endl; Double_t minm13 = 0.0; Double_t maxm13 = negSigModel_->getKinematics()->getm13Max(); Double_t minm23 = 0.0; Double_t maxm23 = negSigModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, posChPdf, negChPdf; TGraph2D *posDt = new TGraph2D(); TGraph2D *negDt = new TGraph2D(); TGraph2D *acpDt = new TGraph2D(); posDt->SetName(tStrResID+label); posDt->SetTitle(tStrResID+" ("+label+") Positive"); negDt->SetName(tStrResID+label); negDt->SetTitle(tStrResID+" ("+label+") Negative"); acpDt->SetName(tStrResID+label); acpDt->SetTitle(tStrResID+" ("+label+") Asymmetry"); Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = negSigModel_->getnCohAmp(); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue; LauComplex negChAmp(0,0); LauComplex posChAmp(0,0); Bool_t noWaveRes = kTRUE; negSigModel_->calcLikelihoodInfo(s13, s23); for (UInt_t resID = 0; resID < nAmp; ++resID) { const LauIsobarDynamics* model = negSigModel_; const LauAbsResonance* resonance = model->getResonance(resID); Int_t spin_res = resonance->getSpin(); if (spin != spin_res) continue; noWaveRes = kFALSE; negChAmp += negSigModel_->getFullAmplitude(resID); posChAmp += posSigModel_->getFullAmplitude(resID); } if (noWaveRes) return; negChPdf = negChAmp.abs2(); posChPdf = posChAmp.abs2(); negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow count++; } } } gStyle->SetPalette(1); TCanvas *posC = new TCanvas("c"+tStrResID+label + "Positive",tStrResID+" ("+label+") Positive",0,0,600,400); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posDt->Draw("SURF1"); posDt->GetXaxis()->SetTitle(xLabel); posDt->GetYaxis()->SetTitle(yLabel); posC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Positive.C"); TCanvas *negC = new TCanvas("c"+tStrResID+label + "Negative",tStrResID+" ("+label+") Negative",0,0,600,400); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negDt->Draw("SURF1"); negDt->GetXaxis()->SetTitle(xLabel); negDt->GetYaxis()->SetTitle(yLabel); negC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Negative.C"); TCanvas *acpC = new TCanvas("c"+tStrResID+label + "Asymmetry",tStrResID+" ("+label+") Asymmetry",0,0,600,400); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpDt->Draw("SURF1"); acpDt->GetXaxis()->SetTitle(xLabel); acpDt->GetYaxis()->SetTitle(yLabel); acpC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Asymmetry.C"); } Double_t LauCPFitModel::getParamFromTree( TTree& tree, const TString& name ) { TBranch* branch{tree.FindBranch( name )}; if ( branch ) { TLeaf* leaf{branch->GetLeaf( name )}; if ( leaf ) { tree.GetEntry(0); return leaf->GetValue(); } else { std::cout << "ERROR in LauCPFitModel::getParamFromTree : Leaf name " + name + " not found in parameter file!" << std::endl; } } else { std::cout << "ERROR in LauCPFitModel::getParamFromTree : Branch name " + name + " not found in parameter file!" << std::endl; } return -1.1; } void LauCPFitModel::fixParam( LauParameter* param, const Double_t val, const Bool_t fix) { std::cout << "INFO in LauCPFitModel::fixParam : Setting " << param->name() << " to " << val << std::endl; param->value(val); param->genValue(val); param->initValue(val); if (fix) { param->fixed(kTRUE); } else if (!param->fixed()){ // Add parameter name to list to indicate that this should not be randomised by randomiseInitFitPars // (otherwise only those that are fixed are not randomised). // This is only done to those that are not already fixed (see randomiseInitFitPars). allImportedFreeParams_.insert(param); } } void LauCPFitModel::fixParams( std::vector& params ) { const Bool_t fix{fixParams_}; // TODO: Allow some parameters to be fixed and some to remain floating (but initialised) if ( !fixParamFileName_.IsNull() ) { // Take param values from a file TFile * paramFile = TFile::Open(fixParamFileName_, "READ"); if (!paramFile) { std::cerr << "ERROR in LauCPFitModel::fixParams : File '" + fixParamFileName_ + "' could not be opened for reading!" << std::endl; return; } TTree * paramTree = dynamic_cast(paramFile->Get(fixParamTreeName_)); if (!paramTree) { std::cerr << "ERROR in LauCPFitModel::fixParams : Tree '" + fixParamTreeName_ + "' not found in parameter file!" << std::endl; return; } if ( !fixParamNames_.empty() ) { // Fix params from file, according to vector of names for( auto itr = params.begin(); itr != params.end(); ++itr ) { auto itrName = fixParamNames_.find( (*itr)->name() ); if ( itrName != fixParamNames_.end() ) { this->fixParam(*itr, this->getParamFromTree(*paramTree, *itrName), fix); } } } else { // Fix some (unspecified) parameters from file, prioritising the map (if it exists) for( auto itr = params.begin(); itr != params.end(); ++itr) { const TString& name = (*itr)->name(); if ( ! fixParamMap_.empty() ) { auto nameValItr = fixParamMap_.find(name); if ( nameValItr != fixParamMap_.end() ) { this->fixParam(*itr, nameValItr->second, fix); } } else { this->fixParam(*itr, this->getParamFromTree(*paramTree, name), fix); } } } // Vector of names? } else { // Fix param names fom map, leave others floating for( auto itr = params.begin(); itr != params.end(); ++itr ) { auto nameValItr = this->fixParamMap_.find( (*itr)->name() ); if ( nameValItr != this->fixParamMap_.end() ) { this->fixParam(*itr, nameValItr->second, fix); } } } } diff --git a/src/LauCacheData.cc b/src/LauCacheData.cc index 2801928..4e134dd 100644 --- a/src/LauCacheData.cc +++ b/src/LauCacheData.cc @@ -1,79 +1,78 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCacheData.cc \brief File containing implementation of LauCacheData class. */ #include "LauCacheData.hh" -ClassImp(LauCacheData) LauCacheData::LauCacheData() : m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), eff_(0.0), scfFraction_(0.0), jacobian_(0.0) { } LauCacheData::~LauCacheData() { } LauCacheData::LauCacheData(const LauCacheData& rhs) { this->storem13Sq(rhs.retrievem13Sq()); this->storem23Sq(rhs.retrievem23Sq()); this->storemPrime(rhs.retrievemPrime()); this->storethPrime(rhs.retrievethPrime()); this->storeEff(rhs.retrieveEff()); this->storeScfFraction(rhs.retrieveScfFraction()); this->storeJacobian(rhs.retrieveJacobian()); this->storeRealAmp(rhs.retrieveRealAmp()); this->storeImagAmp(rhs.retrieveImagAmp()); this->storeIncohIntensities(rhs.retrieveIncohIntensities()); } LauCacheData& LauCacheData::operator=(const LauCacheData& rhs) { if (&rhs != this) { this->storem13Sq(rhs.retrievem13Sq()); this->storem23Sq(rhs.retrievem23Sq()); this->storemPrime(rhs.retrievemPrime()); this->storethPrime(rhs.retrievethPrime()); this->storeEff(rhs.retrieveEff()); this->storeScfFraction(rhs.retrieveScfFraction()); this->storeJacobian(rhs.retrieveJacobian()); this->storeRealAmp(rhs.retrieveRealAmp()); this->storeImagAmp(rhs.retrieveImagAmp()); this->storeIncohIntensities(rhs.retrieveIncohIntensities()); } return *this; } diff --git a/src/LauCalcChiSq.cc b/src/LauCalcChiSq.cc index b687c25..b89a16f 100644 --- a/src/LauCalcChiSq.cc +++ b/src/LauCalcChiSq.cc @@ -1,543 +1,542 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCalcChiSq.cc \brief File containing implementation of LauCalcChiSq class. Code to produce an adaptive binning scheme and calculate the 2D chi-square between two datasets (e.g. low-stat data and high-stat toyMC). Note that the low and high stat histograms must have the same bin axes ranges and number of bins. It works by using the low stat (first) histogram to find a binning scheme such that the total number of entries in each bin is >= Min_bin_content. The number of entries in the histogram is divided by the desired minimum bin content to give a target number of bins. The largest number of bins that can be expressed as a product of powers of 4, 9, 25, 49 and 121 that does not exceed the target value is chosen. The histogram is the recursively subdivided in 2x2, 3x3, 5x5, 7x7 or 11x11 bins. For each stage of the subdivision, each bin is first divided into equally populated bins in x then each of these is further divded into equally popiulated bins in y. The (Pearson) chi-squared is then the sum of the chi-squared contributions of all bins: (low_stat_number - high_stat_number)^2/(high_stat_number) The nDof = number of bins - number of free params - 1 */ #include "LauCalcChiSq.hh" #include "TAxis.h" #include "TFile.h" #include "TMath.h" #include "TSystem.h" #include "TTree.h" #include "TCanvas.h" #include "TColor.h" #include "TStyle.h" #include #include #include #include -ClassImp(LauCalcChiSq) LauCalcChiSq::LauCalcChiSq(const TString& inputFileName) : inputFileName_(inputFileName), fileName1_(""), fileName2_(""), treeName1_(""), treeName2_(""), xName1_(""), xName2_(""), yName1_(""), yName2_(""), minContent_(10.0), histo1_(0), histo2_(0), chiSqHisto_(0), chiSqSignedHisto_(0), xMin_(0.0), xMax_(0.0), yMin_(0.0), yMax_(0.0), nParams_(0), scaleFactor_(1.0), verbose_(kFALSE) { } LauCalcChiSq::~LauCalcChiSq() { } void LauCalcChiSq::run() { std::cout<<"Running chi-squared algorithm"<initialiseHistos(); std::cout<<"Calculating chi-squared"<calculateChiSq(); //make plots this->makePlots(); // Output the various histograms std::cout<<"Writing out histogram output"<SetDirectory(outFile); histo2_->SetDirectory(outFile); pullHisto_->SetDirectory(outFile); chiSqHisto_->SetDirectory(outFile); chiSqSignedHisto_->SetDirectory(outFile); outFile->Write(); outFile->Close(); std::cout<<"Done"<GetBinContent(1); for(Int_t i=1; i<=histo1_->GetNumberOfBins(); ++i) { //keep track of actual minimum if(histo1_->GetBinContent(i)GetBinContent(i); } // Calculate Pearson chi-square for this bin, using the // second histogram for the expected distribution chiSq = 0.; toyVal = histo2_->GetBinContent(i); dataVal = histo1_->GetBinContent(i); diff = dataVal-toyVal; if(toyVal>0) chiSq = (diff*diff)/toyVal; totalChiSq += chiSq; chiSqHisto_->SetBinContent(i, chiSq); if(diff>0) { chiSqSignedHisto_->SetBinContent(i, chiSq); pullHisto_->SetBinContent(i, sqrt(chiSq)); } else { chiSqSignedHisto_->SetBinContent(i, -chiSq); pullHisto_->SetBinContent(i, -sqrt(chiSq)); } } ndof = histo1_->GetNumberOfBins()-nParams_-1; std::cout<<"Total ChiSq/nDof = "<SetPalette(1,0); const Int_t NRGBs = 5; const Int_t NCont = 255; Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00}; Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51}; Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00}; Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00}; TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont); gStyle->SetNumberContours(NCont); gStyle->SetOptStat(0000); TCanvas can; can.SetTopMargin(0.05); can.SetRightMargin(0.17); can.SetBottomMargin(0.16); can.SetLeftMargin(0.14); histo1_->SetLabelFont(62,"x"); histo1_->SetLabelFont(62,"y"); histo1_->SetTitleFont(62,"x"); histo1_->SetTitleFont(62,"y"); histo1_->SetTitleSize(0.06,"x"); histo1_->SetTitleSize(0.06,"y"); histo1_->SetLabelSize(0.05,"x"); histo1_->SetLabelSize(0.05,"y"); histo1_->SetXTitle(xName1_); histo1_->SetYTitle(yName1_); histo1_->Draw("colz"); can.SaveAs("data.pdf"); histo2_->SetLabelFont(62,"x"); histo2_->SetLabelFont(62,"y"); histo2_->SetTitleFont(62,"x"); histo2_->SetTitleFont(62,"y"); histo2_->SetTitleSize(0.06,"x"); histo2_->SetTitleSize(0.06,"y"); histo2_->SetLabelSize(0.05,"x"); histo2_->SetLabelSize(0.05,"y"); histo2_->SetXTitle(xName1_); histo2_->SetYTitle(yName1_); histo2_->Draw("colz"); can.SaveAs("toy.pdf"); if(-1.*pullHisto_->GetMinimum() > pullHisto_->GetMaximum()) pullHisto_->SetMaximum(-1.*pullHisto_->GetMinimum()); else pullHisto_->SetMinimum(-1.*pullHisto_->GetMaximum()); pullHisto_->SetLabelFont(62,"x"); pullHisto_->SetLabelFont(62,"y"); pullHisto_->SetTitleFont(62,"x"); pullHisto_->SetTitleFont(62,"y"); pullHisto_->SetTitleSize(0.06,"x"); pullHisto_->SetTitleSize(0.06,"y"); pullHisto_->SetLabelSize(0.05,"x"); pullHisto_->SetLabelSize(0.05,"y"); pullHisto_->SetXTitle(xName1_); pullHisto_->SetYTitle(yName1_); pullHisto_->Draw("colz"); can.SaveAs("pull.pdf"); chiSqHisto_->SetLabelFont(62,"x"); chiSqHisto_->SetLabelFont(62,"y"); chiSqHisto_->SetTitleFont(62,"x"); chiSqHisto_->SetTitleFont(62,"y"); chiSqHisto_->SetTitleSize(0.06,"x"); chiSqHisto_->SetTitleSize(0.06,"y"); chiSqHisto_->SetLabelSize(0.05,"x"); chiSqHisto_->SetLabelSize(0.05,"y"); chiSqHisto_->SetXTitle(xName1_); chiSqHisto_->SetYTitle(yName1_); chiSqHisto_->Draw("colz"); can.SaveAs("chiSq.pdf"); chiSqSignedHisto_->SetLabelFont(62,"x"); chiSqSignedHisto_->SetLabelFont(62,"y"); chiSqSignedHisto_->SetTitleFont(62,"x"); chiSqSignedHisto_->SetTitleFont(62,"y"); chiSqSignedHisto_->SetTitleSize(0.06,"x"); chiSqSignedHisto_->SetTitleSize(0.06,"y"); chiSqSignedHisto_->SetLabelSize(0.05,"x"); chiSqSignedHisto_->SetLabelSize(0.05,"y"); chiSqSignedHisto_->SetXTitle(xName1_); chiSqSignedHisto_->SetYTitle(yName1_); chiSqSignedHisto_->Draw("colz"); can.SaveAs("chiSqSigned.pdf"); } void LauCalcChiSq::initialiseHistos() { // Open the input control file: // Low_stat_file_name Low_stat_tree_name Low_stat_x_axis_name Low_stat_y_axis_name // High_stat_file_name High_stat_tree_name High_stat_x_axis_name High_stat_y_axis_name // Min_bin_content N_free_params Low/high_stat_histo_ratio xMin xMax yMin yMax std::ifstream getData(inputFileName_.Data()); // get the info on the low stat histo getData >> fileName1_ >> treeName1_ >> xName1_ >> yName1_; if (!getData.good()) { std::cerr<<"Error. Could not read first line of the input file "<Exit(EXIT_FAILURE); } // open the file that contains the low stat histogram TFile * file1 = TFile::Open(fileName1_.Data(), "read"); if (file1 == 0) {gSystem->Exit(EXIT_FAILURE);} // retrieve the low stat histogram TTree* tree1 = dynamic_cast(file1->Get(treeName1_.Data())); if (tree1 == 0) { std::cerr<<"Error. Could not find the tree "<Exit(EXIT_FAILURE); } // get the info on the high stat histogram getData >> fileName2_ >> treeName2_ >> xName2_ >> yName2_; if (!getData.good()) { std::cerr<<"Error. Could not read the second line of the input file "<Exit(EXIT_FAILURE); } // if both histograms are in the same file then just retrieve the // high stat histogram from the file we already have open TFile * file2(0); TTree* tree2(0); if ( fileName2_ == fileName1_ ) { tree2 = dynamic_cast(file1->Get(treeName2_.Data())); } // otherwise open the other file and retrieve the high stat histogram from there else { file2 = TFile::Open(fileName2_.Data(), "read"); if (file2 == 0) {gSystem->Exit(EXIT_FAILURE);} tree2 = dynamic_cast(file2->Get(treeName2_.Data())); } if (tree2 == 0) { std::cerr<<"Error. Could not find the tree "<Exit(EXIT_FAILURE); } // get the info on the minimum content, number of parameters and scalefactor Int_t nParameters(0); Float_t minContent(0.0), scaleFactor(1.0), xMin(0.0), xMax(1.0), yMin(0.0), yMax(1.0); getData >> minContent >> nParameters >> scaleFactor >> xMin >> xMax >> yMin >> yMax; if (getData.good()) { minContent_ = minContent; nParams_ = nParameters; scaleFactor_ = scaleFactor; xMin_ = xMin; xMax_ = xMax; yMin_ = yMin; yMax_ = yMax; } // close the text file getData.close(); std::cout<<"Using the files and trees: "<SetBranchAddress(xName1_.Data(),&x); tree1->SetBranchAddress(yName1_.Data(),&y); Int_t nEntries = tree1->GetEntries(); Double_t* xs = new Double_t[nEntries]; Double_t* ys = new Double_t[nEntries]; for ( Int_t i=0; i < nEntries; ++i ) { tree1->GetEntry( i ); xs[i] = x; ys[i] = y; } theHisto_ = new TH2Poly("theHisto_", "", xMin_, xMax_, yMin_, yMax_); //select the number of divisions to get us closest to minContent entries per bin std::vector divisions; this->pickBinning(xs,ys,nEntries,divisions); //perform the adaptive bining based on histo1_ this->getHisto(xMin_, xMax_, yMin_, yMax_, xs, ys, nEntries, divisions); histo1_ = dynamic_cast(theHisto_->Clone("histo1_")); histo2_ = dynamic_cast(theHisto_->Clone("histo2_")); pullHisto_ = dynamic_cast(theHisto_->Clone("pullHisto_")); chiSqHisto_ = dynamic_cast(theHisto_->Clone("chiSqHisto_")); chiSqSignedHisto_ = dynamic_cast(theHisto_->Clone("chiSqSignedHisto_")); delete[] xs; delete[] ys; //fill the two histograms from the trees TString drawString1, drawString2, weightString2; drawString1 += yName1_; drawString1 += ":"; drawString1 += xName1_; drawString1 += ">>histo1_"; drawString2 += yName2_; drawString2 += ":"; drawString2 += xName2_; drawString2 += ">>histo2_"; weightString2 += scaleFactor_; tree1->Draw(drawString1); tree2->Draw(drawString2,weightString2); histo1_->SetDirectory(0); histo2_->SetDirectory(0); pullHisto_->SetDirectory(0); chiSqHisto_->SetDirectory(0); chiSqSignedHisto_->SetDirectory(0); // close the file(s) containing the trees if (file1 != 0) {file1->Close();} delete file1; if (file2 != 0) {file2->Close();} delete file2; } void LauCalcChiSq::pickBinning(const Double_t* xs, const Double_t* ys, const Int_t nEntries, std::vector& divisions) { //first check how many events we have within the histogram limits Int_t nIn(0); for(Int_t i=0; i= xMin_ && ys[i]= yMin_) { ++nIn; } } //aim to have exactly minContent events in each bin Int_t nBinsTarget = nIn / minContent_; std::cout << "Target is " << minContent_ << " entries per bin" << std::endl; std::cout << "Aiming to divide " << nIn << " entries between " << nBinsTarget << " bins" << std::endl; //we will iteratively sub-divide histogram bins into either 4, 9, 25, 49 or 121 //here we figure out how many 4s, 9s, 25s, 49s and 121s to use to best match our target without exceeding it Int_t nDivisions(0), nNines(0), nTwentyFives(0), nFortyNines(0), nEleventyElevens(0), nBins(1); Int_t nDivisionsBest(0), nNinesBest(0), nTwentyFivesBest(0), nFortyNinesBest(0), nEleventyElevensBest(0), nBinsBest(1); do { ++nDivisions; for(nNines=0; nNines<=nDivisions; ++nNines) { for(nTwentyFives=0; nTwentyFives<=nDivisions-nNines; ++nTwentyFives) { for(nFortyNines=0; nFortyNines<=nDivisions-nNines-nTwentyFives; ++nFortyNines) { for(nEleventyElevens=0; nEleventyElevens<=nDivisions-nNines-nTwentyFives-nFortyNines; ++nEleventyElevens) { nBins = TMath::Power(4,nDivisions-nNines-nTwentyFives-nFortyNines-nEleventyElevens) *TMath::Power(9,nNines)*TMath::Power(25,nTwentyFives) *TMath::Power(49,nFortyNines)*TMath::Power(121,nEleventyElevens); if(nBins < nBinsTarget && nBins > nBinsBest) { //keep track of the best number of bins so far nBinsBest = nBins; nDivisionsBest = nDivisions; nNinesBest = nNines; nTwentyFivesBest = nTwentyFives; nFortyNinesBest = nFortyNines; nEleventyElevensBest = nEleventyElevens; } } } } } } while(TMath::Power(4,nDivisions+1) < nBinsTarget);//if 4^n > target then we've gone far enough std::cout << "Using " << nBinsBest << " bins" << std::endl; //fill the vector with the divisions that we want to make for(Int_t i=0; i& divisions, const UInt_t iter) { //If it's the last iteration create the bin and return if(iter == divisions.size()) { Double_t * x_new = new Double_t[5]; Double_t * y_new = new Double_t[5]; x_new[0] = xMin; x_new[1] = xMin; x_new[2] = xMax; x_new[3] = xMax; x_new[4] = xMin; y_new[0] = yMin; y_new[1] = yMax; y_new[2] = yMax; y_new[3] = yMin; y_new[4] = yMin; theHisto_->AddBin(5, x_new, y_new); if(verbose_) std::cout << "Adding bin from (" << xMin << "," << yMin << ") to (" << xMax << "," << yMax << ")" << std::endl; return; } //If not the last iteration then divide the bin Int_t n_divx=divisions[iter]; Int_t n_divy=divisions[iter]; if(verbose_) std::cout << "Dividing bin from (" << xMin << "," << yMin << ") to (" << xMax << "," << yMax << ") into " << n_divx << " by " << n_divy << " subbins" << std::endl; Double_t *xIn = new Double_t[nEntries]; Double_t *yIn = new Double_t[nEntries]; Int_t *xIndex = new Int_t [nEntries+2]; Int_t *yIndex = new Int_t [nEntries+2]; Int_t xCountIn = 0; for(Int_t i = 0; ixMax)||(ys[i]yMax)) continue; xIn[xCountIn] = xs[i]; ++xCountIn; } //find the delimitting x and y values for the sub bins Double_t xLimits[n_divx + 1]; Double_t yLimits[n_divx][n_divy + 1]; //first sort entries in x and divide bin into equally populated bins in x TMath::Sort(xCountIn, xIn, xIndex, false); xLimits[0] = xMin; xLimits[n_divx] = xMax; for (Int_t nDivx = 0; nDivx < n_divx; ++nDivx){ if (nDivx < (n_divx-1)){ xLimits[nDivx+1] = xIn[xIndex[xCountIn*(nDivx+1)/n_divx]]; } //for each bin in x divide into equally populated bins in y yLimits[nDivx][0] = yMin; yLimits[nDivx][n_divy] = yMax; Int_t yCountIn = 0; for(Int_t i = 0; ixMax)||(ys[i]yMax)) continue; if ((xs[i]=xLimits[nDivx+1])||(ys[i]yMax)) continue; yIn[yCountIn] = ys[i]; ++yCountIn; } TMath::Sort(yCountIn, yIn, yIndex, false); for (Int_t nDivy = 1; nDivy < n_divy; ++nDivy){ yLimits[nDivx][nDivy] = yIn[yIndex[yCountIn*nDivy/n_divy]]; } } delete[] xIn; delete[] yIn; delete[] xIndex; delete[] yIndex; //call for each sub bin for (Int_t nDivx = 0; nDivx < n_divx; ++nDivx){ for (Int_t nDivy = 0; nDivy < n_divy; ++nDivy){ this->getHisto(xLimits[nDivx], xLimits[nDivx + 1], yLimits[nDivx][nDivy], yLimits[nDivx][nDivy + 1], xs, ys, nEntries, divisions,iter+1); } } } diff --git a/src/LauCartesianCPCoeffSet.cc b/src/LauCartesianCPCoeffSet.cc index 18ed134..0a1eba1 100644 --- a/src/LauCartesianCPCoeffSet.cc +++ b/src/LauCartesianCPCoeffSet.cc @@ -1,280 +1,279 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianCPCoeffSet.cc \brief File containing implementation of LauCartesianCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCartesianCPCoeffSet) LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t deltaX, Double_t deltaY, Bool_t xFixed, Bool_t yFixed, Bool_t deltaXFixed, Bool_t deltaYFixed, Bool_t deltaXSecondStage, Bool_t deltaYSecondStage) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), deltaX_(new LauParameter("DeltaX", deltaX, minDelta_, maxDelta_, deltaXFixed)), deltaY_(new LauParameter("DeltaY", deltaY, minDelta_, maxDelta_, deltaYFixed)), particleCoeff_( x+deltaX, y+deltaY ), antiparticleCoeff_( x-deltaX, y-deltaY ), acp_("ACP", -2.0*(x*deltaX + y*deltaY)/(x*x + deltaX*deltaX + y*y + deltaY*deltaY), -1.0, 1.0, deltaXFixed&&deltaYFixed) { if (deltaXSecondStage && !deltaXFixed) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if (deltaYSecondStage && !deltaYFixed) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } } LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const LauCartesianCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), deltaX_(0), deltaY_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { deltaX_ = rhs.deltaX_->createClone(constFactor); deltaY_ = rhs.deltaY_->createClone(constFactor); } else { deltaX_ = new LauParameter("DeltaX", rhs.deltaX_->value(), minDelta_, maxDelta_, rhs.deltaX_->fixed()); deltaY_ = new LauParameter("DeltaY", rhs.deltaY_->value(), minDelta_, maxDelta_, rhs.deltaY_->fixed()); if ( rhs.deltaX_->secondStage() && !rhs.deltaX_->fixed() ) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if ( rhs.deltaY_->secondStage() && !rhs.deltaY_->fixed() ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } if ( rhs.deltaX_->blind() ) { const LauBlind* blinder = rhs.deltaX_->blinder(); deltaX_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaY_->blind() ) { const LauBlind* blinder = rhs.deltaY_->blinder(); deltaY_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); pars.push_back(deltaX_); pars.push_back(deltaY_); return pars; } void LauCartesianCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCartesianCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; std::cout<<"Delta x = "<value()<<",\t"; std::cout<<"Delta y = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, deltaX_->value()); stream<<" \\pm "; print.printFormat(stream, deltaX_->error()); stream<<"$ & $"; print.printFormat(stream, deltaY_->value()); stream<<" \\pm "; print.printFormat(stream, deltaY_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (deltaX_->fixed() == kFALSE && deltaX_->secondStage() == kFALSE) { // Choose a value for "Delta X" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaX_->initValue(value); deltaX_->value(value); } if (deltaY_->fixed() == kFALSE && deltaY_->secondStage() == kFALSE) { // Choose a value for "Delta Y" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaY_->initValue(value); deltaY_->value(value); } } void LauCartesianCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); deltaX_->updatePull(); deltaY_->updatePull(); } const LauComplex& LauCartesianCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( x_->unblindValue()+deltaX_->unblindValue(), y_->unblindValue()+deltaY_->unblindValue() ); return particleCoeff_; } const LauComplex& LauCartesianCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( x_->unblindValue()-deltaX_->unblindValue(), y_->unblindValue()-deltaY_->unblindValue() ); return antiparticleCoeff_; } void LauCartesianCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t xVal( average.re() ); Double_t yVal( average.im() ); Double_t deltaXVal( coeff.re() - average.re() ); Double_t deltaYVal( coeff.im() - average.im() ); x_->value( xVal ); y_->value( yVal ); deltaX_->value( deltaXVal ); deltaY_->value( deltaYVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); deltaX_->genValue( deltaXVal ); deltaY_->genValue( deltaYVal ); x_->initValue( xVal ); y_->initValue( yVal ); deltaX_->initValue( deltaXVal ); deltaY_->initValue( deltaYVal ); } } LauParameter LauCartesianCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t numer = x_->value()*deltaX_->value() + y_->value()*deltaY_->value(); Double_t denom = x_->value()*x_->value() + deltaX_->value()*deltaX_->value() + y_->value()*y_->value() + deltaY_->value()*deltaY_->value(); Double_t value = -2.0*numer/denom; // is it fixed? Bool_t fixed = deltaX_->fixed() && deltaY_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCartesianCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauCartesianCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCartesianCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauCartesianGammaCPCoeffSet.cc b/src/LauCartesianGammaCPCoeffSet.cc index b9cca1f..95d692a 100644 --- a/src/LauCartesianGammaCPCoeffSet.cc +++ b/src/LauCartesianGammaCPCoeffSet.cc @@ -1,312 +1,311 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianGammaCPCoeffSet.cc \brief File containing implementation of LauCartesianGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCartesianGammaCPCoeffSet) LauCartesianGammaCPCoeffSet::LauCartesianGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t deltaXCP, const Double_t deltaYCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t deltaXCPFixed, const Bool_t deltaYCPFixed, const Bool_t deltaXCPSecondStage, const Bool_t deltaYCPSecondStage) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xCP_(new LauParameter("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed)), yCP_(new LauParameter("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed)), deltaXCP_(new LauParameter("DeltaXCP", deltaXCP, minDelta_, maxDelta_, deltaXCPFixed)), deltaYCP_(new LauParameter("DeltaYCP", deltaYCP, minDelta_, maxDelta_, deltaYCPFixed)), nonCPPart_( x, y), cpPart_( 1+xCP+deltaXCP, yCP+deltaYCP), cpAntiPart_( 1+xCP-deltaXCP, yCP-deltaYCP), particleCoeff_( nonCPPart_ * cpPart_ ), antiparticleCoeff_( nonCPPart_ * cpAntiPart_ ), acp_("ACP", (antiparticleCoeff_.abs2()-particleCoeff_.abs2())/(antiparticleCoeff_.abs2()+particleCoeff_.abs2()), -1.0, 1.0, deltaXCPFixed&&deltaYCPFixed) { if (deltaXCPSecondStage && !deltaXCPFixed) { deltaXCP_->secondStage(kTRUE); deltaXCP_->initValue(0.0); } if (deltaYCPSecondStage && !deltaYCPFixed) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } } LauCartesianGammaCPCoeffSet::LauCartesianGammaCPCoeffSet(const LauCartesianGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xCP_(0), yCP_(0), deltaXCP_(0), deltaYCP_(0), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { xCP_ = rhs.xCP_->createClone(constFactor); yCP_ = rhs.yCP_->createClone(constFactor); deltaXCP_ = rhs.deltaXCP_->createClone(constFactor); deltaYCP_ = rhs.deltaYCP_->createClone(constFactor); } else { xCP_ = new LauParameter("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); if ( rhs.xCP_->blind() ) { const LauBlind* blinder = rhs.xCP_->blinder(); xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } yCP_ = new LauParameter("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); if ( rhs.yCP_->blind() ) { const LauBlind* blinder = rhs.yCP_->blinder(); yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaXCP_ = new LauParameter("DeltaXCP", rhs.deltaXCP_->value(), minDelta_, maxDelta_, rhs.deltaXCP_->fixed()); deltaYCP_ = new LauParameter("DeltaYCP", rhs.deltaYCP_->value(), minDelta_, maxDelta_, rhs.deltaYCP_->fixed()); if ( rhs.deltaXCP_->secondStage() && !rhs.deltaXCP_->fixed() ) { deltaXCP_->secondStage(kTRUE); deltaXCP_->initValue(0.0); } if ( rhs.deltaYCP_->secondStage() && !rhs.deltaYCP_->fixed() ) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } if ( rhs.deltaXCP_->blind() ) { const LauBlind* blinder = rhs.deltaXCP_->blinder(); deltaXCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaYCP_->blind() ) { const LauBlind* blinder = rhs.deltaYCP_->blinder(); deltaYCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if(!xCP_->fixed()) pars.push_back(xCP_); if(!yCP_->fixed()) pars.push_back(yCP_); if(!deltaXCP_->fixed()) pars.push_back(deltaXCP_); if(!deltaYCP_->fixed()) pars.push_back(deltaYCP_); return pars; } void LauCartesianGammaCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCartesianGammaCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; std::cout<<"xCP = "<value()<<",\t"; std::cout<<"yCP = "<value()<<",\t"; std::cout<<"Delta xCP = "<value()<<",\t"; std::cout<<"Delta yCP = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xCP_->value()); stream<<" \\pm "; print.printFormat(stream, xCP_->error()); stream<<"$ & $"; print.printFormat(stream, yCP_->value()); stream<<" \\pm "; print.printFormat(stream, yCP_->error()); stream<<"$ & $"; print.printFormat(stream, deltaXCP_->value()); stream<<" \\pm "; print.printFormat(stream, deltaXCP_->error()); stream<<"$ & $"; print.printFormat(stream, deltaYCP_->value()); stream<<" \\pm "; print.printFormat(stream, deltaYCP_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xCP_->fixed() == kFALSE) { // Choose a value for "XCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xCP_->initValue(value); xCP_->value(value); } if (yCP_->fixed() == kFALSE) { // Choose a value for "YCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; yCP_->initValue(value); yCP_->value(value); } if (deltaXCP_->fixed() == kFALSE && deltaXCP_->secondStage() == kFALSE) { // Choose a value for "Delta XCP" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaXCP_->initValue(value); deltaXCP_->value(value); } if (deltaYCP_->fixed() == kFALSE && deltaYCP_->secondStage() == kFALSE) { // Choose a value for "Delta YCP" between -0.5 and 0.5 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*1.0 - 0.5; deltaYCP_->initValue(value); deltaYCP_->value(value); } } void LauCartesianGammaCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xCP_->updatePull(); yCP_->updatePull(); deltaXCP_->updatePull(); deltaYCP_->updatePull(); } const LauComplex& LauCartesianGammaCPCoeffSet::particleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpPart_.setRealImagPart( 1.0+xCP_->unblindValue()+deltaXCP_->unblindValue(), yCP_->unblindValue()+deltaYCP_->unblindValue() ); particleCoeff_ = nonCPPart_ * cpPart_; return particleCoeff_; } const LauComplex& LauCartesianGammaCPCoeffSet::antiparticleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpAntiPart_.setRealImagPart( 1.0+xCP_->unblindValue()-deltaXCP_->unblindValue(), yCP_->unblindValue()-deltaYCP_->unblindValue() ); antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; return antiparticleCoeff_; } void LauCartesianGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauCartesianGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value const LauComplex nonCPPart( x_->value(), y_->value() ); const LauComplex cpPart( 1.0+xCP_->value()+deltaXCP_->value(), yCP_->value()+deltaYCP_->value() ); const LauComplex cpAntiPart( 1.0+xCP_->value()-deltaXCP_->value(), yCP_->value()-deltaYCP_->value() ); const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = deltaXCP_->fixed() && deltaYCP_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCartesianGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauCartesianGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauChebychevPdf.cc b/src/LauChebychevPdf.cc index 11f9e3f..7078357 100644 --- a/src/LauChebychevPdf.cc +++ b/src/LauChebychevPdf.cc @@ -1,177 +1,176 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauChebychevPdf.cc \brief File containing implementation of LauChebychevPdf class. */ /***************************************************************************** * Class based on RooFit/RooChebychev. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include #include "TMath.h" #include "TSystem.h" #include "LauChebychevPdf.hh" -ClassImp(LauChebychevPdf) LauChebychevPdf::LauChebychevPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), coeffs_(params.size(),0) { // Constructor for the Chebychev Polynomial PDF. // // The parameters in params are the coefficients of the polynomial // (polynomial can be anything from 0 to 7 orders). // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. if ( (this->nParameters() > 7) ) { std::cerr << "ERROR in LauChebychevPdf constructor: Too many coeffs - can only cope with order <=7 polynomial." << std::endl; gSystem->Exit(EXIT_FAILURE); } for ( UInt_t i(0); i < this->nParameters(); ++i ) { TString name = "c"; name += i+1; coeffs_[i] = this->findParameter( name ); } // Cache the normalisation factor this->calcNorm(); } LauChebychevPdf::~LauChebychevPdf() { // Destructor } //inline static double p0(double ,double a) { return a; } inline static double p1(double t,double a,double b) { return a*t+b; } inline static double p2(double t,double a,double b,double c) { return p1(t,p1(t,a,b),c); } inline static double p3(double t,double a,double b,double c,double d) { return p2(t,p1(t,a,b),c,d); } //inline static double p4(double t,double a,double b,double c,double d,double e) { return p3(t,p1(t,a,b),c,d,e); } void LauChebychevPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; Double_t xmin = this->getMinAbscissa(); Double_t xmax = this->getMaxAbscissa(); Double_t x(-1.0+2.0*(abscissa-xmin)/(xmax-xmin)); Double_t x2(x*x); Double_t sum(0) ; switch ( coeffs_.size() ) { case 7: sum += coeffs_[6]->unblindValue()*x*p3(x2,64,-112,56,-7); [[fallthrough]]; case 6: sum += coeffs_[5]->unblindValue()*p3(x2,32,-48,18,-1); [[fallthrough]]; case 5: sum += coeffs_[4]->unblindValue()*x*p2(x2,16,-20,5); [[fallthrough]]; case 4: sum += coeffs_[3]->unblindValue()*p2(x2,8,-8,1); [[fallthrough]]; case 3: sum += coeffs_[2]->unblindValue()*x*p1(x2,4,-3); [[fallthrough]]; case 2: sum += coeffs_[1]->unblindValue()*p1(x2,2,-1); [[fallthrough]]; case 1: sum += coeffs_[0]->unblindValue()*x; [[fallthrough]]; case 0: sum +=1; } this->setUnNormPDFVal( sum ); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauChebychevPdf::calcNorm() { Double_t xmin = this->getMinAbscissa(); Double_t xmax = this->getMaxAbscissa(); Double_t norm(0) ; switch( coeffs_.size() ) { case 7: case 6: norm += coeffs_[5]->unblindValue()*(-1 + 18./3. - 48./5. + 32./7.); [[fallthrough]]; case 5: case 4: norm += coeffs_[3]->unblindValue()*( 1 - 8./3. + 8./5.); [[fallthrough]]; case 3: case 2: norm += coeffs_[1]->unblindValue()*(-1 + 2./3.); [[fallthrough]]; case 1: case 0: norm += 1; } norm *= xmax-xmin; this->setNorm(norm); } void LauChebychevPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { // TODO - this method can hopefully be improved // At present it scans through the range and then increases by a 20% safety factor // Maybe there's a better way? if (this->heightUpToDate()) { return; } // Calculate the PDF height LauAbscissas maxPoint(1); Double_t minAbs = this->getMinAbscissa(); Double_t maxAbs = this->getMaxAbscissa(); Double_t range = maxAbs - minAbs; Double_t maxHeight(0.0); // Just scan through the range for ( Double_t point = minAbs; point <= maxAbs; point += range/1000.0 ) { maxPoint[0] = point; this->calcLikelihoodInfo(maxPoint); Double_t heightAtPoint = this->getUnNormLikelihood(); if ( heightAtPoint > maxHeight ) { maxHeight = heightAtPoint; } } // Mutliply by 120% to be on the safe side maxHeight *= 1.2; this->setMaxHeight(maxHeight); } diff --git a/src/LauCleoCPCoeffSet.cc b/src/LauCleoCPCoeffSet.cc index 976dbf8..d6d3041 100644 --- a/src/LauCleoCPCoeffSet.cc +++ b/src/LauCleoCPCoeffSet.cc @@ -1,342 +1,341 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCleoCPCoeffSet.cc \brief File containing implementation of LauCleoCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCleoCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauCleoCPCoeffSet) LauCleoCPCoeffSet::LauCleoCPCoeffSet(const TString& compName, Double_t a, Double_t delta, Double_t b, Double_t phi, Bool_t aFixed, Bool_t deltaFixed, Bool_t bFixed, Bool_t phiFixed, Bool_t bSecondStage, Bool_t phiSecondStage) : LauAbsCoeffSet(compName), a_(new LauParameter("A", a, minMagnitude_, maxMagnitude_, aFixed)), b_(new LauParameter("B", b, minMagnitude_, maxMagnitude_, bFixed)), delta_(new LauParameter("Delta", delta, minPhase_, maxPhase_, deltaFixed)), phi_(new LauParameter("Phi", phi, minPhase_, maxPhase_, phiFixed)), particleCoeff_( (a+b)*TMath::Cos(delta+phi), (a+b)*TMath::Sin(delta+phi) ), antiparticleCoeff_( (a-b)*TMath::Cos(delta-phi), (a-b)*TMath::Sin(delta-phi) ), acp_("ACP", (-2.0*a*b)/(a*a+b*b), -1.0, 1.0, bFixed&&phiFixed) { if (bSecondStage && !bFixed) { b_->secondStage(kTRUE); b_->initValue(0.0); } if (phiSecondStage && !phiFixed) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } } LauCleoCPCoeffSet::LauCleoCPCoeffSet(const LauCleoCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), a_(0), b_(0), delta_(0), phi_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { a_ = rhs.a_->createClone(constFactor); } else { a_ = new LauParameter("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); if ( rhs.a_->blind() ) { const LauBlind* blinder = rhs.a_->blinder(); a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { b_ = rhs.b_->createClone(constFactor); } else { b_ = new LauParameter("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); if ( rhs.b_->blind() ) { const LauBlind* blinder = rhs.b_->blinder(); b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { delta_ = rhs.delta_->createClone(constFactor); } else { delta_ = new LauParameter("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); if ( rhs.delta_->blind() ) { const LauBlind* blinder = rhs.delta_->blinder(); delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { phi_ = rhs.phi_->createClone(constFactor); } else { phi_ = new LauParameter("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); if ( rhs.phi_->blind() ) { const LauBlind* blinder = rhs.phi_->blinder(); phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCleoCPCoeffSet::getParameters() { std::vector pars; pars.push_back(a_); pars.push_back(b_); pars.push_back(delta_); pars.push_back(phi_); return pars; } void LauCleoCPCoeffSet::printParValues() const { std::cout<<"INFO in LauCleoCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"a-magnitude = "<value()<<",\t"; std::cout<<"delta = "<value()<<",\t"; std::cout<<"b-magnitude = "<value()<<",\t"; std::cout<<"phi = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, a_->error()); stream<<"$ & $"; print.printFormat(stream, delta_->value()); stream<<" \\pm "; print.printFormat(stream, delta_->error()); stream<<"$ & $"; print.printFormat(stream, b_->value()); stream<<" \\pm "; print.printFormat(stream, b_->error()); stream<<"$ & $"; print.printFormat(stream, phi_->value()); stream<<" \\pm "; print.printFormat(stream, phi_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose an a-magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; a_->initValue(mag); a_->value(mag); } if (b_->fixed() == kFALSE && b_->secondStage() == kFALSE) { // Choose a b-magnitude between 0.0 and 0.1 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*0.1; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; delta_->initValue(phase); delta_->value(phase); } if (phi_->fixed() == kFALSE && phi_->secondStage() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phi_->initValue(phase); phi_->value(phase); } } void LauCleoCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t aVal = a_->value(); Double_t bVal = b_->value(); Double_t deltaVal = delta_->value(); Double_t phiVal = phi_->value(); Double_t genDelta = delta_->genValue(); Double_t genPhi = phi_->genValue(); // Check whether we have a negative "a" magnitude. // If so make it positive and add pi to the "delta" phase. if (aVal < 0.0) { aVal *= -1.0; bVal *= -1.0; deltaVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t deltaWithinRange(kFALSE); Bool_t phiWithinRange(kFALSE); while (deltaWithinRange == kFALSE && phiWithinRange == kFALSE) { if (deltaVal > -LauConstants::pi && deltaVal < LauConstants::pi) { deltaWithinRange = kTRUE; } else { // Not within the specified range if (deltaVal > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (deltaVal < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } } if (phiVal > -LauConstants::pi && phiVal < LauConstants::pi) { phiWithinRange = kTRUE; } else { // Not within the specified range if (phiVal > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (phiVal < -LauConstants::pi) { phiVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaVal - genDelta; if (diff > LauConstants::pi) { deltaVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaVal += LauConstants::twoPi; } diff = phiVal - genPhi; if (diff > LauConstants::pi) { phiVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phiVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls a_->value(aVal); a_->updatePull(); b_->value(bVal); b_->updatePull(); delta_->value(deltaVal); delta_->updatePull(); phi_->value(phiVal); phi_->updatePull(); } const LauComplex& LauCleoCPCoeffSet::particleCoeff() { Double_t magnitude = a_->unblindValue() + b_->unblindValue(); Double_t phase = delta_->unblindValue() + phi_->unblindValue(); particleCoeff_.setRealImagPart(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)); return particleCoeff_; } const LauComplex& LauCleoCPCoeffSet::antiparticleCoeff() { Double_t magnitude = a_->unblindValue() - b_->unblindValue(); Double_t phase = delta_->unblindValue() - phi_->unblindValue(); antiparticleCoeff_.setRealImagPart(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)); return antiparticleCoeff_; } void LauCleoCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t mag = coeff.abs(); Double_t magBar = coeffBar.abs(); Double_t phase = coeff.arg(); Double_t phaseBar = coeffBar.arg(); Double_t aVal( 0.5 * ( mag + magBar ) ); Double_t deltaVal( 0.5 * ( phase + phaseBar ) ); Double_t bVal( 0.5 * ( mag - magBar ) ); Double_t phiVal( 0.5 * ( phase - phaseBar ) ); a_->value( aVal ); delta_->value( deltaVal ); b_->value( bVal ); phi_->value( phiVal ); if ( init ) { a_->genValue( aVal ); delta_->genValue( deltaVal ); b_->genValue( bVal ); phi_->genValue( phiVal ); a_->initValue( aVal ); delta_->initValue( deltaVal ); b_->initValue( bVal ); phi_->initValue( phiVal ); } } LauParameter LauCleoCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t numer = -2.0*a_->value()*b_->value(); Double_t denom = a_->value()*a_->value()+b_->value()*b_->value(); Double_t value = numer/denom; // is it fixed? Bool_t fixed = a_->fixed() && b_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauCleoCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude || cloneOption == TieCPPars ) { clone = new LauCleoCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauCleoCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauComplex.cc b/src/LauComplex.cc index 7642d6f..c5ecc53 100644 --- a/src/LauComplex.cc +++ b/src/LauComplex.cc @@ -1,70 +1,69 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauComplex.cc \brief File containing implementation of LauComplex class. */ /***************************************************************************** * Class based on RooFit/RooComplex. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include "LauComplex.hh" -ClassImp(LauComplex); void LauComplex::print() const { std::cout << (*this) << std::endl; } std::ostream& operator<<(std::ostream& os, const LauComplex& z) { return os<<"("<>(std::istream& ios, LauComplex& z) { Double_t a(0.0), b(0.0); char temp; ios >> temp >> a >> temp >> b >> temp; z.setRealImagPart( a, b ); return ios; } diff --git a/src/LauCruijffPdf.cc b/src/LauCruijffPdf.cc index 6fa8b41..0517963 100644 --- a/src/LauCruijffPdf.cc +++ b/src/LauCruijffPdf.cc @@ -1,168 +1,167 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCruijffPdf.cc \brief File containing implementation of LauCruijffPdf class. */ /***************************************************************************** * Class based on RooFit/RooCruijff. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauCruijffPdf.hh" #include "LauConstants.hh" -ClassImp(LauCruijffPdf) LauCruijffPdf::LauCruijffPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigmaL_(0), sigmaR_(0), alphaL_(0), alphaR_(0) { // Constructor for the Cruijff PDF. // // The parameters in params are the mean, sigmaR, sigmaL, alphaR // and alphaL. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaR_ = this->findParameter("sigmaR"); sigmaL_ = this->findParameter("sigmaL"); alphaR_ = this->findParameter("alphaR"); alphaL_ = this->findParameter("alphaL"); if ((this->nParameters() != 5) || (mean_ == 0) || (sigmaR_ == 0) || (sigmaL_ == 0) || (alphaL_ == 0) || (alphaR_ == 0)) { cerr<<"ERROR in LauCruijffPdf constructor: LauCruijffPdf requires 5 parameters: \"mean\", \"sigmaL\", \"sigmaR\", \"alphaR\" and \"alphaL\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauCruijffPdf::~LauCruijffPdf() { // Destructor } void LauCruijffPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigmaL = sigmaL_->unblindValue(); Double_t sigmaR = sigmaR_->unblindValue(); Double_t alphaL = alphaL_->unblindValue(); Double_t alphaR = alphaR_->unblindValue(); // Evaluate the LauCruijff PDF value Double_t arg = abscissa - mean; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaL) > 1e-30) { coef = -1.0/(2.0*sigmaL*sigmaL + alphaL*arg*arg); } } else { if (TMath::Abs(sigmaR) > 1e-30) { coef = -1.0/(2.0*sigmaR*sigmaR+ alphaR*arg*arg); } } value = TMath::Exp(coef*arg*arg); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } this->setUnNormPDFVal(value); } void LauCruijffPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height if (mean < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (mean > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= (1.0 + 1e-1); this->setMaxHeight(height); } diff --git a/src/LauCrystalBallPdf.cc b/src/LauCrystalBallPdf.cc index 9c7da10..7128bfa 100644 --- a/src/LauCrystalBallPdf.cc +++ b/src/LauCrystalBallPdf.cc @@ -1,230 +1,229 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCrystalBallPdf.cc \brief File containing implementation of LauCrystalBallPdf class. */ /***************************************************************************** * Class based on RooFit/RooCBShape. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauCrystalBallPdf.hh" -ClassImp(LauCrystalBallPdf) LauCrystalBallPdf::LauCrystalBallPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0), alpha_(0), n_(0) { // Constructor for the Crystal Ball PDF, which is a gaussian and a decaying tail // smoothly matched up. The tail goes as a 1/x^n // // The parameters in params are the mean and the sigma (half the width) of the gaussian, // the distance from the mean in which the gaussian and the tail are matched up (which // can be negative or positive), and the power "n" for the tail. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); alpha_ = this->findParameter("alpha"); n_ = this->findParameter("order"); if ((this->nParameters() != 4) || (mean_ == 0) || (sigma_ == 0) || (alpha_ == 0) || (n_ == 0)) { cerr<<"ERROR in LauCrystalBallPdf constructor: LauCrystalBallPdf requires 4 parameters: \"mean\", \"sigma\", \"alpha\" and \"order\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauCrystalBallPdf::~LauCrystalBallPdf() { // Destructor } void LauCrystalBallPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t alpha = alpha_->unblindValue(); Double_t n = n_->unblindValue(); Double_t result(0.0); Double_t t = (abscissa - mean)/sigma; if (alpha < 0.0) { t = -t; } Double_t absAlpha = TMath::Abs(alpha); if (t >= -absAlpha) { result = TMath::Exp(-0.5*t*t); } else { Double_t a = TMath::Power(n/absAlpha,n)*TMath::Exp(-0.5*absAlpha*absAlpha); Double_t b = n/absAlpha - absAlpha; result = a/TMath::Power(b - t, n); } this->setUnNormPDFVal(result); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauCrystalBallPdf::calcNorm() { // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t alpha = alpha_->unblindValue(); Double_t n = n_->unblindValue(); Double_t result = 0.0; Bool_t useLog = kFALSE; if ( TMath::Abs(n-1.0) < 1.0e-05 ) { useLog = kTRUE; } Double_t sig = TMath::Abs(sigma); Double_t tmin = (this->getMinAbscissa() - mean)/sig; Double_t tmax = (this->getMaxAbscissa() - mean)/sig; if (alpha < 0) { Double_t tmp = tmin; tmin = -tmax; tmax = -tmp; } Double_t absAlpha = TMath::Abs(alpha); if ( tmin >= -absAlpha ) { result += sig*LauConstants::rootPiBy2*( this->approxErf( tmax / LauConstants::root2 ) - approxErf( tmin / LauConstants::root2 ) ); } else if ( tmax <= -absAlpha ) { Double_t a = TMath::Power(n/absAlpha, n)*TMath::Exp( -0.5*absAlpha*absAlpha); Double_t b = n/absAlpha - absAlpha; if ( useLog == kTRUE ) { result += a*sig*( TMath::Log(b - tmin) - TMath::Log(b - tmax) ); } else { result += a*sig/(1.0 - n)*( 1.0/(TMath::Power( b - tmin, n - 1.0)) - 1.0/(TMath::Power( b - tmax, n - 1.0)) ); } } else { Double_t a = TMath::Power(n/absAlpha, n)*TMath::Exp( -0.5*absAlpha*absAlpha ); Double_t b = n/absAlpha - absAlpha; Double_t term1 = 0.0; if ( useLog == kTRUE ) term1 = a*sig*( TMath::Log(b - tmin) - TMath::Log(n / absAlpha)); else term1 = a*sig/(1.0 - n)*( 1.0/(TMath::Power( b - tmin, n - 1.0)) - 1.0/(TMath::Power( n/absAlpha, n - 1.0)) ); Double_t term2 = sig*LauConstants::rootPiBy2*( this->approxErf( tmax / LauConstants::root2 ) - this->approxErf( -absAlpha / LauConstants::root2 ) ); result += term1 + term2; } this->setNorm(result); } void LauCrystalBallPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); // The Crystall Ball function is a Gaussian with an exponentially decaying tail // Therefore, calculate the PDF height for the Gaussian function. LauAbscissas abscissa(1); abscissa[0] = mean; this->calcLikelihoodInfo(abscissa); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } Double_t LauCrystalBallPdf::approxErf(Double_t arg) const { static const Double_t erflim = 5.0; if ( arg > erflim ) { return 1.0; } if ( arg < -erflim ) { return -1.0; } return TMath::Erf(arg); } diff --git a/src/LauDPDepBifurGaussPdf.cc b/src/LauDPDepBifurGaussPdf.cc index 9974d6b..585a056 100644 --- a/src/LauDPDepBifurGaussPdf.cc +++ b/src/LauDPDepBifurGaussPdf.cc @@ -1,283 +1,282 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepBifurGaussPdf.cc \brief File containing implementation of LauDPDepBifurGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TRandom.h" #include "TSystem.h" #include "Lau1DHistPdf.hh" #include "LauConstants.hh" #include "LauComplex.hh" #include "LauDaughters.hh" #include "LauFitDataTree.hh" #include "LauKinematics.hh" #include "LauDPDepBifurGaussPdf.hh" -ClassImp(LauDPDepBifurGaussPdf) LauDPDepBifurGaussPdf::LauDPDepBifurGaussPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const vector& meanCoeffs, const vector& sigmaLCoeffs, const vector& sigmaRCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigmaL_(0), sigmaR_(0), meanVal_(0.0), sigmaLVal_(0.0), sigmaRVal_(0.0), meanCoeffs_(meanCoeffs), sigmaLCoeffs_(sigmaLCoeffs), sigmaRCoeffs_(sigmaRCoeffs), dpAxis_(dpAxis), scaleMethod_(poly) { // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepBifurGaussPdf::LauDPDepBifurGaussPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters are: // - the mean, the sigmaL and the sigmaR of the Bifurcated Gaussian // // The next two arguments specify the range in which the PDF is defined, // and the PDF will be normalised w.r.t. these limits. // // The final three argument define whether the BF Gaussian parameters should be scaled or not mean_ = this->findParameter("mean"); sigmaL_ = this->findParameter("sigmaL"); sigmaR_ = this->findParameter("sigmaR"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigmaL_ == 0) || (sigmaR_ == 0) ) { cerr<<"ERROR in LauDPDepBifurGaussPdf constructor: LauDPDepBifurGaussPdf requires 3 parameters:" <<" \"mean\", \"sigmaL\" and \"sigmaR\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepBifurGaussPdf::~LauDPDepBifurGaussPdf() { // Destructor } void LauDPDepBifurGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissas are within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the gaussian parameters by the dpPos (if appropriate) ScaleMethod scale = this->scaleMethod(); if ( scale==poly ) { this->scalePars_poly(dpPos); } else if ( scale==polyNegPower ) { this->scalePars_polyNegPower(dpPos); } else { cerr<<"Scaling method unknown! Methods available: and ."<Exit(EXIT_FAILURE); } // Evaluate the Birfucated Gaussian PDF value Double_t arg = abscissa - meanVal_; Double_t coef(0.0); Double_t value(0.0); if (arg < 0.0) { if (TMath::Abs(sigmaLVal_) > 1e-30) { coef = -0.5/(sigmaLVal_*sigmaLVal_); } } else { if (TMath::Abs(sigmaRVal_) > 1e-30) { coef = -0.5/(sigmaRVal_*sigmaRVal_); } } value = TMath::Exp(coef*arg*arg); // Calculate the norm Double_t xscaleL = LauConstants::root2*sigmaLVal_; Double_t xscaleR = LauConstants::root2*sigmaRVal_; Double_t integral(0.0); Double_t norm(0.0); Double_t result(0.0); if ( this->getMaxAbscissa() < meanVal_ ) { integral = sigmaLVal_ * ( TMath::Erf((this->getMaxAbscissa() - meanVal_)/xscaleL) - TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleL)); } else if ( this->getMinAbscissa() > meanVal_ ) { integral = sigmaRVal_ * (TMath::Erf((this->getMaxAbscissa() - meanVal_)/xscaleR) - TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleR)); } else { integral = sigmaRVal_*TMath::Erf((this->getMaxAbscissa() -meanVal_)/xscaleR) - sigmaLVal_*TMath::Erf((this->getMinAbscissa() - meanVal_)/xscaleL); } norm = LauConstants::rootPiBy2*integral; // the result result = value/norm; this->setUnNormPDFVal(result); } void LauDPDepBifurGaussPdf::scalePars_poly(Double_t dpPos) { Int_t power = 1; for (vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepBifurGaussPdf::scalePars_polyNegPower(Double_t dpPos) { Int_t power = -1; for (vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); --power; } power = -1; for (vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); --power; } power = -1; for (vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); --power; } } void LauDPDepBifurGaussPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepBifurGaussPdf::calcPDFHeight( const LauKinematics* kinematics ) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); // Scale the gaussian parameters by the dpCentreDist (if appropriate) Double_t dpCentreDist = kinematics->distanceFromDPCentre(); ScaleMethod scale = this->scaleMethod(); if ( scale==poly ) { this->scalePars_poly(dpCentreDist); } else if ( scale==polyNegPower ) { this->scalePars_polyNegPower(dpCentreDist); } else { cerr<<"Scaling method unknown! Methods available: and ."<Exit(EXIT_FAILURE); } // Calculate the PDF height for the Bifurcated Gaussian function. LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); if ( meanVal_ > this->getMaxAbscissa() ) { maxPoint[0] = this->getMaxAbscissa(); } else if ( meanVal_ < this->getMinAbscissa() ) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= 1.001; this->setMaxHeight(height); } diff --git a/src/LauDPDepCruijffPdf.cc b/src/LauDPDepCruijffPdf.cc index dc17d27..41cc2d6 100644 --- a/src/LauDPDepCruijffPdf.cc +++ b/src/LauDPDepCruijffPdf.cc @@ -1,321 +1,320 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepCruijffPdf.cc \brief File containing implementation of LauDPDepCruijffPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPDepCruijffPdf.hh" #include "LauKinematics.hh" -ClassImp(LauDPDepCruijffPdf) LauDPDepCruijffPdf::LauDPDepCruijffPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaLCoeffs, const std::vector& sigmaRCoeffs, const std::vector& alphaLCoeffs, const std::vector& alphaRCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigmaL_(0), sigmaR_(0), alphaL_(0), alphaR_(0), meanVal_(0.0), sigmaLVal_(0.0), sigmaRVal_(0.0), alphaLVal_(0.0), alphaRVal_(0.0), meanCoeffs_(meanCoeffs), sigmaLCoeffs_(sigmaLCoeffs), sigmaRCoeffs_(sigmaRCoeffs), alphaLCoeffs_(alphaLCoeffs), alphaRCoeffs_(alphaRCoeffs), dpAxis_(dpAxis) { // Constructor for the Dalitz-plot dependent Cruijff PDF. // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepCruijffPdf::LauDPDepCruijffPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters in params are the mean, sigmaR, sigmaL, alphaR and alphaL. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigmaR_ = this->findParameter("sigmaR"); sigmaL_ = this->findParameter("sigmaL"); alphaR_ = this->findParameter("alphaR"); alphaL_ = this->findParameter("alphaL"); if ((this->nParameters() != 5) || (mean_ == 0) || (sigmaR_ == 0) || (sigmaL_ == 0) || (alphaL_ == 0) || (alphaR_ == 0)) { cerr<<"ERROR in LauDPDepCruijffPdf constructor: LauDPDepCruijffPdf requires 5 parameters: \"mean\", \"sigmaL\", \"sigmaR\", \"alphaR\" and \"alphaL\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepCruijffPdf::~LauDPDepCruijffPdf() { // Destructor } void LauDPDepCruijffPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepCruijffPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); alphaLVal_ = alphaL_->unblindValue(); alphaRVal_ = alphaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the PDF value Double_t value = this->currentPDFValue( abscissa ); // Calculate the normalisation IntMethod sumMethod = this->integMethod(); Double_t normFac = (sumMethod == GaussLegendre) ? this->integrGaussLegendre() : this->integTrapezoid(); value /= normFac; this->setUnNormPDFVal(value); } Double_t LauDPDepCruijffPdf::currentPDFValue(Double_t abscissa) const { Double_t arg = abscissa - meanVal_; Double_t coef(0.0); if (arg < 0.0){ if (TMath::Abs(sigmaLVal_) > 1e-30) { coef = -1.0/(2.0*sigmaLVal_*sigmaLVal_ + alphaLVal_*arg*arg); } } else { if (TMath::Abs(sigmaRVal_) > 1e-30) { coef = -1.0/(2.0*sigmaRVal_*sigmaRVal_ + alphaRVal_*arg*arg); } } return TMath::Exp(coef*arg*arg); } Double_t LauDPDepCruijffPdf::integrGaussLegendre() { if (!this->normWeightsDone()) { this->getNormWeights(); } const std::vector& norm_abscissas = this->normAbscissas(); const std::vector& norm_weights = this->normWeights(); // Now compute the integral Double_t norm(0.0); for (UInt_t i = 0; i < norm_weights.size(); i++) { Double_t fun = this->currentPDFValue( norm_abscissas[i][0] ); Double_t intFactor = 0.5 * this->getRange(); norm += norm_weights[i]*intFactor*fun; } return norm; } Double_t LauDPDepCruijffPdf::integTrapezoid() { static Double_t norm(0.0); Double_t range = this->getRange(); if (this->nNormPoints()==1){ Double_t abscissa = this->getMinAbscissa(); Double_t funAbsMin = this->currentPDFValue(abscissa); abscissa = this->getMaxAbscissa(); Double_t funAbsMax = this->currentPDFValue(abscissa); norm = 0.5*range*(funAbsMin+funAbsMax); return norm; } else { Double_t abscVal(0.0), tnm(0.0), sum(0.0), del(0.0); Int_t it(0), j(0); for (it=1, j=1; j< this->nNormPoints()-1; j++) {it<<=1;} tnm=it; del=range/tnm; abscVal= this->getMinAbscissa()+ 0.5*del; for (sum = 0.0, j=1; jcurrentPDFValue(abscVal); sum+=funVal; } norm = 0.5*(norm + sum*range/tnm); return norm; } } void LauDPDepCruijffPdf::scalePars(Double_t dpPos) { Int_t power = 1; for (std::vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaLCoeffs_.begin(); iter != sigmaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaRCoeffs_.begin(); iter != sigmaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = alphaLCoeffs_.begin(); iter != alphaLCoeffs_.end(); ++iter) { Double_t coeff = (*iter); alphaLVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = alphaRCoeffs_.begin(); iter != alphaRCoeffs_.end(); ++iter) { Double_t coeff = (*iter); alphaRVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepCruijffPdf::calcPDFHeight( const LauKinematics* kinematics ) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaLVal_ = sigmaL_->unblindValue(); sigmaRVal_ = sigmaR_->unblindValue(); alphaLVal_ = alphaL_->unblindValue(); alphaRVal_ = alphaR_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else { dpPos = kinematics->distanceFromDPCentre(); } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the PDF height LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); if (meanVal_ < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (meanVal_ > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= 1.01; this->setMaxHeight(height); } diff --git a/src/LauDPDepGaussPdf.cc b/src/LauDPDepGaussPdf.cc index e7bebfe..aeecdc7 100644 --- a/src/LauDPDepGaussPdf.cc +++ b/src/LauDPDepGaussPdf.cc @@ -1,217 +1,216 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepGaussPdf.cc \brief File containing implementation of LauDPDepGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPDepGaussPdf.hh" #include "LauKinematics.hh" -ClassImp(LauDPDepGaussPdf) LauDPDepGaussPdf::LauDPDepGaussPdf(const TString& theVarName, const std::vector& params, Double_t minAbscissa, Double_t maxAbscissa, const LauDaughters* daughters, const std::vector& meanCoeffs, const std::vector& sigmaCoeffs, DPAxis dpAxis) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), kinematics_(daughters ? daughters->getKinematics() : 0), mean_(0), sigma_(0), meanVal_(0.0), sigmaVal_(0.0), meanCoeffs_(meanCoeffs), sigmaCoeffs_(sigmaCoeffs), dpAxis_(dpAxis) { // Constructor for the Gaussian PDF. // Check we have a valid kinematics object if ( ! kinematics_ ) { cerr<<"ERROR in LauDPDepGaussPdf::LauDPDepGaussPdf : Have not been provided with a valid DP kinematics object."<Exit(EXIT_FAILURE); } // The parameters in params are the mean and the sigma (half the width) of the gaussian. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); if ((this->nParameters() != 2) || (mean_ == 0) || (sigma_ == 0)) { cerr<<"ERROR in LauDPDepGaussPdf constructor: LauDPDepGaussPdf requires 2 parameters: \"mean\" and \"sigma\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepGaussPdf::~LauDPDepGaussPdf() { // Destructor } void LauDPDepGaussPdf::calcNorm() { this->setNorm(1.0); } void LauDPDepGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values meanVal_ = mean_->unblindValue(); sigmaVal_ = sigma_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; if ( dpAxis_ == M12 ) { dpPos = kinematics_->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics_->distanceFromDPCentre(m13Sq,m23Sq); } } // Scale the parameters according to the DP position this->scalePars( dpPos ); // Calculate the value of the Gaussian for the given value of the abscissa. Double_t arg = abscissa - meanVal_; Double_t exponent(0.0); if (TMath::Abs(sigmaVal_) > 1e-10) { exponent = -0.5*arg*arg/(sigmaVal_*sigmaVal_); } Double_t value = TMath::Exp(exponent); Double_t norm(0.0); Double_t scale = LauConstants::root2*sigmaVal_; if (TMath::Abs(sigmaVal_) > 1e-10) { norm = LauConstants::rootPiBy2*sigmaVal_*(TMath::Erf((this->getMaxAbscissa() - meanVal_)/scale) - TMath::Erf((this->getMinAbscissa() - meanVal_)/scale)); } value /= norm; this->setUnNormPDFVal(value); } void LauDPDepGaussPdf::scalePars(Double_t dpPos) { Int_t power = 1; for (std::vector::const_iterator iter = meanCoeffs_.begin(); iter != meanCoeffs_.end(); ++iter) { Double_t coeff = (*iter); meanVal_ += coeff * TMath::Power(dpPos,power); ++power; } power = 1; for (std::vector::const_iterator iter = sigmaCoeffs_.begin(); iter != sigmaCoeffs_.end(); ++iter) { Double_t coeff = (*iter); sigmaVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepGaussPdf::calcPDFHeight(const LauKinematics* kinematics) { // Get the up to date parameter values meanVal_ = mean_->unblindValue(); // Find out the DP position Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else if ( dpAxis_ == MMIN ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(); } // Scale the parameters according to the DP position this->scalePars( dpPos ); LauAbscissas maxPoint(3); maxPoint[0] = meanVal_; maxPoint[1] = kinematics->getm13Sq(); maxPoint[2] = kinematics->getm23Sq(); // Calculate the PDF height for the Gaussian function. if (meanVal_>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meanVal_getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauDPDepMapPdf.cc b/src/LauDPDepMapPdf.cc index 67c195e..087d45d 100644 --- a/src/LauDPDepMapPdf.cc +++ b/src/LauDPDepMapPdf.cc @@ -1,369 +1,368 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepMapPdf.cc \brief File containing implementation of LauDPDepMapPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; #include "TH1.h" #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "Lau2DHistDP.hh" #include "LauParameter.hh" #include "LauDPDepMapPdf.hh" -ClassImp(LauDPDepMapPdf) LauDPDepMapPdf::LauDPDepMapPdf(const std::vector& pdfs, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf) : LauAbsPdf((!pdfs.empty() && pdfs[0]) ? pdfs[0]->varNames() : std::vector(), std::vector(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMinAbscissas() : LauFitData(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdfs_(pdfs), dpDependence_( new Lau2DHistDP(dpHisto, daughters, kFALSE, kFALSE, 0, 0, upperHalf, daughters->squareDP()) ), dpAxisDependence_(0), dpAxis_( CentreDist ), indices_(0) { // Constructor for the PDF map. // The index into the PDF collection is read from the DP histogram. // So the first thing we have to do is check the pointers are all valid. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ if (!(*iter)) { cerr<<"ERROR in LauDPDepMapPdf constructor: one of the PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdfs_[0]->getMinAbscissa() != (*iter)->getMinAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: minimum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } if (pdfs_[0]->getMaxAbscissa() != (*iter)->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: maximum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdfs_[0]->nInputVars() != (*iter)->nInputVars()) { cerr<<"ERROR in LauDPDepMapPdf constructor: number of input variables not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdfs_[0]->varNames() != (*iter)->varNames()) { cerr<<"ERROR in LauDPDepMapPdf constructor: variable name(s) not the same for two PDFs."<Exit(EXIT_FAILURE); } } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ std::vector& pdfpars = (*iter)->getParameters(); this->addParameters(pdfpars); } // Cache the normalisation factor this->calcNorm(); } LauDPDepMapPdf::LauDPDepMapPdf(const std::vector& pdfs, const LauDaughters* daughters, const TH1* dpAxisHisto, DPAxis dpAxis) : LauAbsPdf((!pdfs.empty() && pdfs[0]) ? pdfs[0]->varNames() : std::vector(), std::vector(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMinAbscissas() : LauFitData(), (!pdfs.empty() && pdfs[0]) ? pdfs[0]->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdfs_(pdfs), dpDependence_( 0 ), dpAxisDependence_(dpAxisHisto ? dynamic_cast(dpAxisHisto->Clone()) : 0), dpAxis_( dpAxis ), indices_( 0 ) { // Constructor for the PDFs map. // The index into the PDF collection is read from one of // the DP axes. if ( dpAxisDependence_ ) { dpAxisDependence_->SetDirectory(0); } // So the first thing we have to do is check the pointers are all valid. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ if (!(*iter)) { cerr<<"ERROR in LauDPDepMapPdf constructor: one of the PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdfs_[0]->getMinAbscissa() != (*iter)->getMinAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: minimum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } if (pdfs_[0]->getMaxAbscissa() != (*iter)->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepMapPdf constructor: maximum abscissa values not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdfs_[0]->nInputVars() != (*iter)->nInputVars()) { cerr<<"ERROR in LauDPDepMapPdf constructor: number of input variables not the same for two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdfs_[0]->varNames() != (*iter)->varNames()) { cerr<<"ERROR in LauDPDepMapPdf constructor: variable name(s) not the same for two PDFs."<Exit(EXIT_FAILURE); } } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ std::vector& pdfpars = (*iter)->getParameters(); this->addParameters(pdfpars); } // Cache the normalisation factor this->calcNorm(); } LauDPDepMapPdf::~LauDPDepMapPdf() { // Destructor delete daughters_; daughters_ = 0; delete dpDependence_; dpDependence_ = 0; delete dpAxisDependence_; dpAxisDependence_ = 0; } UInt_t LauDPDepMapPdf::determineDPRegion( Double_t m13Sq, Double_t m23Sq ) const { UInt_t regionIndex(0); LauKinematics* kinematics = daughters_->getKinematics(); kinematics->updateKinematics( m13Sq, m23Sq ); if ( dpDependence_ ) { if (daughters_->squareDP()){ Double_t mprime = kinematics->getmPrime(); Double_t thprime = kinematics->getThetaPrime(); regionIndex = static_cast( dpDependence_->interpolateXY( mprime, thprime ) ); } else { regionIndex = static_cast( dpDependence_->interpolateXY( m13Sq, m23Sq ) ); } } else if ( dpAxisDependence_ ) { Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } Int_t bin = dpAxisDependence_->FindFixBin( dpPos ); regionIndex = static_cast( dpAxisDependence_->GetBinContent( bin ) ); } else { // This should never happen cerr << "ERROR in LauDPDepMapPdf::determineDPRegion : No means of determining the region!" << endl; gSystem->Exit(EXIT_FAILURE); } return regionIndex; } void LauDPDepMapPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Create a set of absissas that doesn't contain the DP variables UInt_t nVars = this->nInputVars(); LauAbscissas noDPVars( nVars ); for ( UInt_t i(0); i < nVars; ++i ) { noDPVars[i] = abscissas[i]; } // Find which region of the DP we're in // The DP variables will be abscissas[nInputVars] and // abscissas[nInputVars+1] (if present). UInt_t regionIndex(0); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; regionIndex = this->determineDPRegion( m13Sq, m23Sq ); } else { // This should never happen cerr << "ERROR in LauDPDepMapPdf::calcLikelihoodInfo : DP vars not supplied, no means of determining the region!" << endl; gSystem->Exit(EXIT_FAILURE); } // Check that the region index is valid if ( regionIndex >= pdfs_.size() ) { cerr << "ERROR in LauDPDepMapPdf::calcLikelihoodInfo : No PDF supplied for region " << regionIndex << endl; gSystem->Exit(EXIT_FAILURE); } // Evaluate the normalised PDF values LauAbsPdf* pdf = pdfs_[regionIndex]; if ( pdf->isDPDependent() ) { pdf->calcLikelihoodInfo(abscissas); } else { pdf->calcLikelihoodInfo(noDPVars); } Double_t result = pdf->getUnNormLikelihood(); this->setUnNormPDFVal(result); Double_t norm = pdf->getNorm(); this->setNorm(norm); } void LauDPDepMapPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauDPDepMapPdf::calcPDFHeight( const LauKinematics* kinematics ) { // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); // Find which region of the DP we're in UInt_t regionIndex = this->determineDPRegion( m13Sq, m23Sq ); // Check that the region index is valid if ( regionIndex >= pdfs_.size() ) { cerr << "ERROR in LauDPDepMapPdf::calcPDFHeight : No PDF supplied for region " << regionIndex << endl; gSystem->Exit(EXIT_FAILURE); } // Evaluate the normalised PDF values LauAbsPdf* pdf = pdfs_[regionIndex]; // Update the heights of the individual PDFs pdf->calcPDFHeight( kinematics ); // Find the PDF maximum Double_t height = pdf->getMaxHeight(); this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate some functionality to the constituent PDFs. void LauDPDepMapPdf::cacheInfo(const LauFitDataTree& inputData) { // delegate to the sub-PDFs to cache their information for ( std::vector::const_iterator iter = pdfs_.begin(); iter != pdfs_.end(); ++iter){ (*iter)->cacheInfo( inputData ); } // now check that the DP variables are included in the data Bool_t hasBranch = inputData.haveBranch( "m13Sq" ); hasBranch &= inputData.haveBranch( "m23Sq" ); if (!hasBranch) { cerr<<"ERROR in LauDPDepMapPdf::cacheInfo : Input data does not contain Dalitz plot variables m13Sq and/or m23Sq."<nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); if ( !doCaching ) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } // clear the vector and reserve enough space UInt_t nEvents = inputData.nEvents(); indices_.clear(); indices_.reserve(nEvents); // loop through the events, determine the fraction and store for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputData.getData(iEvt); Double_t m13Sq = dataValues.find("m13Sq")->second; Double_t m23Sq = dataValues.find("m23Sq")->second; UInt_t regionIndex = this->determineDPRegion( m13Sq, m23Sq ); indices_.push_back( regionIndex ); } } void LauDPDepMapPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the fraction value for this event UInt_t regionIndex = indices_[iEvt]; // Evaluate the normalised PDF value LauAbsPdf* pdf = pdfs_[regionIndex]; pdf->calcLikelihoodInfo(iEvt); Double_t result = pdf->getUnNormLikelihood(); this->setUnNormPDFVal(result); Double_t norm = pdf->getNorm(); this->setNorm(norm); } diff --git a/src/LauDPDepSumPdf.cc b/src/LauDPDepSumPdf.cc index 47f0815..fae9a6e 100644 --- a/src/LauDPDepSumPdf.cc +++ b/src/LauDPDepSumPdf.cc @@ -1,432 +1,431 @@ /* Copyright 2009 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPDepSumPdf.cc \brief File containing implementation of LauDPDepSumPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauParameter.hh" #include "LauDPDepSumPdf.hh" -ClassImp(LauDPDepSumPdf) LauDPDepSumPdf::LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, const LauDaughters* daughters, const TH2* dpHisto, Bool_t upperHalf, Bool_t useSpline) : LauAbsPdf(pdf1 ? pdf1->varNames() : vector(), vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdf1_(pdf1), pdf2_(pdf2), frac_(0), fracVal_(0.5), dpDependence_( new LauEffModel(daughters, 0) ), dpAxis_( CentreDist ) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // The value of the fraction is read from the DP histogram. if(useSpline) { dpDependence_->setEffSpline( dpHisto, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP()); } else { dpDependence_->setEffHisto( dpHisto, kTRUE, kFALSE, 0.0, 0.0, upperHalf, daughters->squareDP() ); } // So the first thing we have to do is check the pointers are all valid. if (!pdf1 || !pdf2) { cerr<<"ERROR in LauDPDepSumPdf constructor: one of the 2 PDF pointers is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: minimum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: maximum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { cerr<<"ERROR in LauDPDepSumPdf constructor: number of input variables not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdf1->varNames() != pdf2->varNames()) { cerr<<"ERROR in LauDPDepSumPdf constructor: variable name(s) not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2. UInt_t nPar(pdf1->nParameters()+pdf2->nParameters()); vector params; params.reserve(nPar); vector& pdf1pars = pdf1->getParameters(); vector& pdf2pars = pdf2->getParameters(); for (vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Cache the normalisation factor this->calcNorm(); } LauDPDepSumPdf::LauDPDepSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac, const LauDaughters* daughters, const std::vector& fracCoeffs, DPAxis dpAxis) : LauAbsPdf(pdf1 ? pdf1->varNames() : vector(), vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), daughters_( new LauDaughters(*daughters) ), pdf1_(pdf1), pdf2_(pdf2), frac_(frac), fracVal_( frac ? frac->unblindValue() : 0.0 ), dpDependence_( 0 ), fracCoeffs_( fracCoeffs ), dpAxis_( dpAxis ) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // The value of the fraction has a polynomial dependence on one of // the DP axes. // So the first thing we have to do is check the pointers are all valid. if (!pdf1 || !pdf2) { cerr<<"ERROR in LauDPDepSumPdf constructor: one of the 2 PDF pointers is null."<Exit(EXIT_FAILURE); } if ( !frac ) { cerr<<"ERROR in LauDPDepSumPdf constructor: the fraction parameter pointer is null."<Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: minimum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { cerr<<"ERROR in LauDPDepSumPdf constructor: maximum abscissa values not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { cerr<<"ERROR in LauDPDepSumPdf constructor: number of input variables not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name(s) if (pdf1->varNames() != pdf2->varNames()) { cerr<<"ERROR in LauDPDepSumPdf constructor: variable name(s) not the same for the two PDFs."<Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2. UInt_t nPar( pdf1->nParameters() + pdf2->nParameters() + 1 ); vector params; params.reserve(nPar); params.push_back(frac); vector& pdf1pars = pdf1->getParameters(); vector& pdf2pars = pdf2->getParameters(); for (vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Now check that we can find the fraction parameter ok frac_ = this->findParameter("frac"); if (frac_ == 0) { cerr<<"ERROR in LauDPDepSumPdf constructor: parameter \"frac\" not found."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauDPDepSumPdf::~LauDPDepSumPdf() { // Destructor delete daughters_; daughters_ = 0; delete dpDependence_; dpDependence_ = 0; } void LauDPDepSumPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } LauAbscissas noDPVars(1); noDPVars[0] = abscissas[0]; // Evaluate the normalised PDF values if ( pdf1_->isDPDependent() ) { pdf1_->calcLikelihoodInfo(abscissas); } else { pdf1_->calcLikelihoodInfo(noDPVars); } if ( pdf2_->isDPDependent() ) { pdf2_->calcLikelihoodInfo(abscissas); } else { pdf2_->calcLikelihoodInfo(noDPVars); } Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Determine the fraction // The DP variables will be abscissas[nInputVars] and // abscissas[nInputVars+1] (if present). UInt_t nVars = this->nInputVars(); if ( abscissas.size() == nVars+2 ) { Double_t m13Sq = abscissas[nVars]; Double_t m23Sq = abscissas[nVars+1]; LauKinematics* kinematics = daughters_->getKinematics(); if ( dpDependence_ ) { kinematics->updateKinematics( m13Sq, m23Sq ); fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } this->scaleFrac( dpPos ); } } // Add them together Double_t result = fracVal_ * result1 + (1.0-fracVal_) * result2; this->setUnNormPDFVal(result); } void LauDPDepSumPdf::scaleFrac( Double_t dpPos ) { Int_t power = 1; for (std::vector::const_iterator iter = fracCoeffs_.begin(); iter != fracCoeffs_.end(); ++iter) { Double_t coeff = (*iter); fracVal_ += coeff * TMath::Power(dpPos,power); ++power; } } void LauDPDepSumPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauDPDepSumPdf::calcPDFHeight( const LauKinematics* kinematics ) { // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. // Update the heights of the individual PDFs pdf1_->calcPDFHeight( kinematics ); pdf2_->calcPDFHeight( kinematics ); // Get the up to date parameter values if ( dpDependence_ ) { fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->getm12Sq(); } else if ( dpAxis_ == M13 ) { dpPos = kinematics->getm13Sq(); } else if ( dpAxis_ == M23 ) { dpPos = kinematics->getm23Sq(); } else if ( dpAxis_ == MMIN ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { Double_t m13Sq = kinematics->getm13Sq(); Double_t m23Sq = kinematics->getm23Sq(); dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(); } this->scaleFrac( dpPos ); } // Find the (un-normalised) individual PDF maxima Double_t height1 = pdf1_->getMaxHeight(); Double_t height2 = pdf2_->getMaxHeight(); // Get the individual PDF normalisation factors Double_t norm1 = pdf1_->getNorm(); Double_t norm2 = pdf2_->getNorm(); // Calculate the normalised individual PDF maxima height1 /= norm1; height2 /= norm2; // Combine these heights together Double_t height = fracVal_ * height1 + (1-fracVal_) * height2; this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate to the two constituent PDFs. void LauDPDepSumPdf::cacheInfo(const LauFitDataTree& inputData) { // delegate to the two sub-PDFs to cache their information pdf1_->cacheInfo(inputData); pdf2_->cacheInfo(inputData); // now check that the DP variables are included in the data Bool_t hasBranch = inputData.haveBranch( "m13Sq" ); hasBranch &= inputData.haveBranch( "m23Sq" ); if (!hasBranch) { cerr<<"ERROR in LauDPDepSumPdf::cacheInfo : Input data does not contain Dalitz plot variables m13Sq and/or m23Sq."<nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); if ( !doCaching ) { // in this case we seem to be doing a fit where the parameters are floating // so need to mark that the PDF height is no longer up to date this->heightUpToDate(kFALSE); } // clear the vector and reserve enough space UInt_t nEvents = inputData.nEvents(); fractions_.clear(); fractions_.reserve(nEvents); // loop through the events, determine the fraction and store for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputData.getData(iEvt); Double_t m13Sq = dataValues.find("m13Sq")->second; Double_t m23Sq = dataValues.find("m23Sq")->second; LauKinematics* kinematics = daughters_->getKinematics(); if ( dpDependence_ ) { // if we're using the histogram then just // determine the fraction and store kinematics->updateKinematics( m13Sq, m23Sq ); fracVal_ = dpDependence_->calcEfficiency( kinematics ); } else { // if we're scaling the fraction parameter then we // just store the scaling info since the parameter // might be floating fracVal_ = frac_->unblindValue(); Double_t dpPos(0.0); if ( dpAxis_ == M12 ) { dpPos = kinematics->calcThirdMassSq(m13Sq,m23Sq); } else if ( dpAxis_ == M13 ) { dpPos = m13Sq; } else if ( dpAxis_ == M23 ) { dpPos = m23Sq; } else if ( dpAxis_ == MMIN ) { dpPos = TMath::Min( m13Sq, m23Sq ); } else if ( dpAxis_ == MMAX ) { dpPos = TMath::Max( m13Sq, m23Sq ); } else { dpPos = kinematics->distanceFromDPCentre(m13Sq,m23Sq); } this->scaleFrac( dpPos ); fracVal_ -= frac_->unblindValue(); } fractions_.push_back( fracVal_ ); } } void LauDPDepSumPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the fraction value for this event fracVal_ = fractions_[iEvt]; if ( frac_ ) { // if we're scaling the parameter then need to add the // current value of the parameter fracVal_ += frac_->unblindValue(); } // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(iEvt); pdf2_->calcLikelihoodInfo(iEvt); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = fracVal_ * result1 + (1-fracVal_) * result2; this->setUnNormPDFVal(result); } diff --git a/src/LauDPPartialIntegralInfo.cc b/src/LauDPPartialIntegralInfo.cc index 0da95b6..35f5427 100644 --- a/src/LauDPPartialIntegralInfo.cc +++ b/src/LauDPPartialIntegralInfo.cc @@ -1,187 +1,186 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDPPartialIntegralInfo.cc \brief File containing implementation of LauDPPartialIntegralInfo class. */ #include #include "LauDPPartialIntegralInfo.hh" #include "LauIntegrals.hh" #include "LauKinematics.hh" -ClassImp(LauDPPartialIntegralInfo) LauDPPartialIntegralInfo::LauDPPartialIntegralInfo(const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp, const Bool_t squareDP, const LauKinematics* kinematics) : minm13_(minm13), maxm13_(maxm13), minm23_(minm23), maxm23_(maxm23), m13BinWidth_(m13BinWidth), m23BinWidth_(m23BinWidth), nm13Points_(static_cast((maxm13-minm13)/m13BinWidth)), nm23Points_(static_cast((maxm23-minm23)/m23BinWidth)), nAmp_(nAmp), nIncohAmp_(nIncohAmp), squareDP_(squareDP) { const Double_t meanm13 = 0.5*(minm13 + maxm13); const Double_t rangem13 = maxm13 - minm13; const Double_t halfRangem13 = 0.5*rangem13; const Double_t meanm23 = 0.5*(minm23 + maxm23); const Double_t rangem23 = maxm23 - minm23; const Double_t halfRangem23 = 0.5*rangem23; const Double_t intFactor = halfRangem13*halfRangem23; // Raise error if squareDP is true but the kinematics object is not provided if ( squareDP_ && kinematics == 0 ) { std::cerr << "ERROR in LauDPPartialIntegralInfo constructor : Integration in the square DP has been specified but no valid kinematics object has been provided!" << std::endl; return; } // Avoid integral if we have no points in either x or y space if (nm13Points_ == 0 || nm23Points_ == 0) { std::cerr << "ERROR in LauDPPartialIntegralInfo constructor : Range has zero grid points in one or both of the dimensions!" << std::endl; return; } // Print a warning if we have a very large number of points if ( (nm13Points_ * nm23Points_) > 8000000 ) { std::cerr << "WARNING in LauDPPartialIntegralInfo constructor : The integration binning scheme has a very large number of bins, this could cause high memory consumption!" << std::endl; std::cerr << " : In case of problems, consider using LauIsobarDynamics::setNarrowResonanceThreshold and/or LauIsobarDynamics::setIntegralBinningFactor to tune the binning behaviour." << std::endl; } LauIntegrals dpIntegrals(precision); dpIntegrals.calcGaussLegendreWeights(nm13Points_, m13Points_, m13Weights_); dpIntegrals.calcGaussLegendreWeights(nm23Points_, m23Points_, m23Weights_); // Print out total weights for the integration Double_t totm13Weight(0.0), totm23Weight(0.0); for (UInt_t i = 0; i < nm13Points_; ++i) { totm13Weight += m13Weights_[i]; } for (UInt_t i = 0; i < nm23Points_; ++i) { totm23Weight += m23Weights_[i]; } if ( squareDP_ ) { std::cout<<"INFO in LauDPPartialIntegralInfo constructor : nmPrimePoints = "< #include "LauConstants.hh" #include "LauDabbaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauDabbaRes) LauDabbaRes::LauDabbaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mSumSq_(0.0), sAdler_(0.0), b_(0), alpha_(0), beta_(0) { // Default constant factors const Double_t bVal = 24.49; const Double_t alphaVal = 0.1; const Double_t betaVal = 0.1; const TString& parNameBase = this->getSanitisedName(); TString bName(parNameBase); bName += "_b"; b_ = resInfo->getExtraParameter( bName ); if ( b_ == 0 ) { b_ = new LauParameter( bName, bVal, 0.0, 100.0, kTRUE ); b_->secondStage(kTRUE); resInfo->addExtraParameter( b_ ); } TString alphaName(parNameBase); alphaName += "_alpha"; alpha_ = resInfo->getExtraParameter( alphaName ); if ( alpha_ == 0 ) { alpha_ = new LauParameter( alphaName, alphaVal, 0.0, 10.0, kTRUE ); alpha_->secondStage(kTRUE); resInfo->addExtraParameter( alpha_ ); } TString betaName(parNameBase); betaName += "_beta"; beta_ = resInfo->getExtraParameter( betaName ); if ( beta_ == 0 ) { beta_ = new LauParameter( betaName, betaVal, 0.0, 10.0, kTRUE ); beta_->secondStage(kTRUE); resInfo->addExtraParameter( beta_ ); } } LauDabbaRes::~LauDabbaRes() { } void LauDabbaRes::initialise() { // check that we have a D and a pi this->checkDaughterTypes(); // Initialise various constants Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t mSum = massDaug1 + massDaug2; mSumSq_ = mSum*mSum; Double_t massDaug1Sq = massDaug1*massDaug1; Double_t massDaug2Sq = massDaug2*massDaug2; sAdler_ = TMath::Max(massDaug1Sq,massDaug2Sq) - 0.5*TMath::Min(massDaug1Sq,massDaug2Sq); // Adler zero at (mD)^2 - 0.5*(mpi)^2 Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauDabbaRes::initialise : Spin = " << resSpin << " is not zero! It will be ignored anyway!" << std::endl; } } void LauDabbaRes::checkDaughterTypes() const { // Check that the daughter tracks are D and pi. Otherwise issue a warning. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauDabbaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } // Check that daughter types agree const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if ( !( nameDaug1.Contains("pi", TString::kIgnoreCase) && nameDaug2.Contains("d", TString::kIgnoreCase) ) ) { if ( !( nameDaug2.Contains("pi", TString::kIgnoreCase) && nameDaug1.Contains("d", TString::kIgnoreCase) ) ) { std::cerr << "ERROR in LauDabbaRes::checkDaughterTypes : Dabba model is using daughters \"" << nameDaug1 << "\" and \"" << nameDaug2 << "\" that are not a D meson and a pion." << std::endl; } } } LauComplex LauDabbaRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Dabba distribution // given the invariant mass and cos(helicity) values. // Invariant mass squared combination for the system Double_t s = mass*mass; // Dabba is spin zero - so there are no helicity factors. // Just set it to 1.0 in case anyone decides to use it at a later date. spinTerm = 1.0; // Phase-space factor Double_t rho(0.0); Double_t sDiff = s - mSumSq_; if ( sDiff > 0.0 ) { rho = TMath::Sqrt(1.0 - mSumSq_/s); } const Double_t bVal = this->getBValue(); const Double_t alphaVal = this->getAlphaValue(); const Double_t betaVal = this->getBetaValue(); Double_t realPart = 1.0 - betaVal * sDiff; Double_t imagPart = bVal * TMath::Exp( - alphaVal * sDiff ) * ( s - sAdler_ ) * rho; LauComplex resAmplitude( realPart, imagPart ); Double_t denomFactor = realPart*realPart + imagPart*imagPart; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauDabbaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixBValue() ) { this->addFloatingParameter( b_ ); } if ( ! this->fixAlphaValue() ) { this->addFloatingParameter( alpha_ ); } if ( ! this->fixBetaValue() ) { this->addFloatingParameter( beta_ ); } return this->getParameters(); } void LauDabbaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b") { this->setBValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter b = " << this->getBValue() << std::endl; } else if (name == "alpha") { this->setAlphaValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter alpha = " << this->getAlphaValue() << std::endl; } else if (name == "beta") { this->setBetaValue(value); std::cout << "INFO in LauDabbaRes::setResonanceParameter : Setting parameter beta = " << this->getBetaValue() << std::endl; } else { std::cerr << "WARNING in LauDabbaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauDabbaRes::floatResonanceParameter(const TString& name) { if (name == "b") { if ( b_->fixed() ) { b_->fixed( kFALSE ); this->addFloatingParameter( b_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "alpha") { if ( alpha_->fixed() ) { alpha_->fixed( kFALSE ); this->addFloatingParameter( alpha_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "beta") { if ( beta_->fixed() ) { beta_->fixed( kFALSE ); this->addFloatingParameter( beta_ ); } else { std::cerr << "WARNING in LauDabbaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauDabbaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauDabbaRes::getResonanceParameter(const TString& name) { if (name == "b") { return b_; } else if (name == "alpha") { return alpha_; } else if (name == "beta") { return beta_; } else { std::cerr << "WARNING in LauDabbaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauDabbaRes::setBValue(const Double_t b) { b_->value( b ); b_->genValue( b ); b_->initValue( b ); } void LauDabbaRes::setAlphaValue(const Double_t alpha) { alpha_->value( alpha ); alpha_->genValue( alpha ); alpha_->initValue( alpha ); } void LauDabbaRes::setBetaValue(const Double_t beta) { beta_->value( beta ); beta_->genValue( beta ); beta_->initValue( beta ); } diff --git a/src/LauDatabasePDG.cc b/src/LauDatabasePDG.cc index b925b59..ec03665 100644 --- a/src/LauDatabasePDG.cc +++ b/src/LauDatabasePDG.cc @@ -1,269 +1,268 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDatabasePDG.cc \brief File containing implementation of LauDatabasePDG class. */ #include using std::cout; using std::cerr; using std::endl; #include "TDatabasePDG.h" #include "LauDatabasePDG.hh" #include "LauParticlePDG.hh" LauDatabasePDG* LauDatabasePDG::theInstance_ = 0; -ClassImp(LauDatabasePDG) // Constructor LauDatabasePDG::LauDatabasePDG() : theDatabase_( new TDatabasePDG() ), particles_(), debug_(kFALSE) { } // Destructor LauDatabasePDG::~LauDatabasePDG() { delete theDatabase_; theDatabase_ = 0; for (LauPDGList::iterator iter = particles_.begin(); iter != particles_.end(); ++iter) { delete iter->second; iter->second = 0; } } // Private static method to access the instance // Will create it and add the missing particles if it doesn't already exist LauDatabasePDG& LauDatabasePDG::get() { if (theInstance_ == 0) { theInstance_ = new LauDatabasePDG(); theInstance_->addMissingParticles(); } return *theInstance_; } // All static methods grab the instance and call the private non-static // methods - this ensures that the database exists and that the missing // particles are added to it. const LauParticlePDG* LauDatabasePDG::particle(Int_t theCode) { return LauDatabasePDG::get().createParticle( theCode ); } const LauParticlePDG* LauDatabasePDG::particle(const TString& theString) { return LauDatabasePDG::get().createParticle( theString ); } Int_t LauDatabasePDG::code(const TString& theString) { return LauDatabasePDG::get().pdgCode( theString ); } TString LauDatabasePDG::string(Int_t theCode) { return LauDatabasePDG::get().pdgName( theCode ); } // The following method adds particles to the ROOT database that are // missing from it's default setup. This should only be called once, // immediately after the creation of the instance. void LauDatabasePDG::addMissingParticles() { TParticlePDG* part(0); TParticlePDG* antipart(0); // format is: // name, title, mass, stable?, width, 3*Q, category, PDG code part = theDatabase_->AddParticle("deuteron", "deuteron", 1.8756134, kTRUE, 0.0, 3, "Nucleus", 1011); antipart = theDatabase_->AddAntiParticle("anti-deuteron", -1011); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("tritium", "tritium", 2.80925, kTRUE, 0.0, 3, "Nucleus", 1021); antipart = theDatabase_->AddAntiParticle("anti-tritium", -1021); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("He3", "He3", 2.80923, kTRUE, 0.0, 6, "Nucleus", 1012); antipart = theDatabase_->AddAntiParticle("anti-He3", -1012); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("alpha", "alpha", 3.727417, kTRUE, 0.0, 3, "Nucleus", 1022); antipart = theDatabase_->AddAntiParticle("anti-alpha", -1022); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("eta_c(2S)", "eta_c(2S)", 3.628, kTRUE, 0.0195, 0, "Meson", 20441); part = theDatabase_->AddParticle("psi(3770)", "psi(3770)", 3.7699, kTRUE, 0.0236, 0, "Meson", 40443); part = theDatabase_->AddParticle("rho(2S)0", "rho(2S)0", 1.46, kTRUE, 0.31, 0, "Meson", 30113); part = theDatabase_->AddParticle("rho(2S)+", "rho(2S)+", 1.46, kTRUE, 0.31, 3, "Meson", 30213); antipart = theDatabase_->AddAntiParticle("rho(2S)-", -30213); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("rho(3S)0", "rho(3S)0", 1.46, kTRUE, 0.31, 0, "Meson", 40113); part = theDatabase_->AddParticle("rho(3S)+", "rho(3S)+", 1.46, kTRUE, 0.31, 3, "Meson", 40213); antipart = theDatabase_->AddAntiParticle("rho(3S)-", -40213); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xsu", "Xsu", 1.6, kTRUE, 0.5, 3, "Meson", 30353); antipart = theDatabase_->AddAntiParticle("anti-Xsu", -30353); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xu0", "Xu0", 1., kTRUE, 0., 0, "Special", 41); part = theDatabase_->AddParticle("Xu+", "Xu+", 1., kTRUE, 0., 3, "Special", 42); antipart = theDatabase_->AddAntiParticle("Xu-", -42); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("Xsd", "Xsd", 1.6, kTRUE, 0.5, 0, "Meson", 30343); antipart = theDatabase_->AddAntiParticle("anti-Xsd", -30343); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K'*0", "K'*0", 1.414, kTRUE, 0.232, 0, "Meson", 100313); antipart = theDatabase_->AddAntiParticle("anti-K'*0", -100313); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K'*+", "K'*+", 1.414, kTRUE, 0.232, 3, "Meson", 100323); antipart = theDatabase_->AddAntiParticle("K'*-", -100323); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K''*0", "K''*0", 1.717, kTRUE, 0.322, 0, "Meson", 30313); antipart = theDatabase_->AddAntiParticle("anti-K''*0", -30313); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); part = theDatabase_->AddParticle("K''*+", "K''*+", 1.717, kTRUE, 0.322, 3, "Meson", 30323); antipart = theDatabase_->AddAntiParticle("K''*-", -30323); part->SetAntiParticle(antipart); antipart->SetAntiParticle(part); } // These next two methods are the ones that actually build-up our database. const LauParticlePDG* LauDatabasePDG::createParticle(Int_t theCode) { // if we've already created this one simply return it LauPDGList::iterator iter = particles_.find(theCode); if ( iter != particles_.end() ) { return iter->second; } // otherwise we'll have to make it... // first get the particle from the database TParticlePDG* theTParticle = theDatabase_->GetParticle( theCode ); if (theTParticle == 0) { cerr<<"ERROR in LauDatabasePDG::createParticle : Invalid PDG code: "< insertResult = particles_.insert( std::make_pair( theCode, theParticle ) ); if ( ! insertResult.second ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Something went wrong inserting particle "<AntiParticle(); // check if we have a self-conjugate particle if ( theTAntiParticle == 0 || theTAntiParticle == theTParticle ) { // if so then set it to be it's own anti-particle and return theParticle->setAntiParticle( theParticle ); if ( debug_ ) { cout<<"INFO in LauDatabasePDG::createParticle : Created self-conjugate particle "<GetName()<code(); insertResult = particles_.insert( std::make_pair( conjCode, antiParticle ) ); if ( ! insertResult.second ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Something went wrong inserting anti-particle "<setAntiParticle( antiParticle ); antiParticle->setAntiParticle( theParticle ); // and finally return the particle we've created if ( debug_ ) { cout<<"INFO in LauDatabasePDG::createParticle : Created particle "<GetName()<<" and its conjugate "<GetName()<pdgCode(theString); if ( theCode == 0 ) { cerr<<"ERROR in LauDatabasePDG::createParticle : Invalid particle string: "<createParticle(theCode); } // These last two methods have to be independent of our own database since // they are used by the methods that create the particles and so we'd end // up with an infinite loop. Int_t LauDatabasePDG::pdgCode(const TString& theString) { TParticlePDG* theParticle = theDatabase_->GetParticle(theString); if (theParticle == 0) { cerr<<"ERROR in LauDatabasePDG::pdgCode : Invalid particle string: "<PdgCode(); } TString LauDatabasePDG::pdgName(Int_t theCode) { TParticlePDG* theParticle = theDatabase_->GetParticle(theCode); if (theParticle == 0) { cerr<<"ERROR in LauDatabasePDG::pdgName : Invalid particle code: "<GetName(); } diff --git a/src/LauDaughters.cc b/src/LauDaughters.cc index 2914c78..08705c1 100644 --- a/src/LauDaughters.cc +++ b/src/LauDaughters.cc @@ -1,345 +1,344 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDaughters.cc \brief File containing implementation of LauDaughters class. */ #include #include "TSystem.h" #include "LauDatabasePDG.hh" #include "LauDaughters.hh" #include "LauKinematics.hh" #include "LauParticlePDG.hh" -ClassImp(LauDaughters) LauDaughters::LauDaughters(Int_t codeParent, Int_t code1, Int_t code2, Int_t code3, Bool_t useSquareDP) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); TString nameParent = LauDatabasePDG::string( codeParent ); TString name1 = LauDatabasePDG::string( code1 ); TString name2 = LauDatabasePDG::string( code2 ); TString name3 = LauDatabasePDG::string( code3 ); this->setParentType(nameParent); this->setDaugType(name1, name2, name3); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), useSquareDP, symmetricalDP_, fullySymmetricDP_); } LauDaughters::LauDaughters(const TString& nameParent, const TString& name1, const TString& name2, const TString& name3, Bool_t useSquareDP) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); this->setParentType(nameParent); this->setDaugType(name1, name2, name3); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), useSquareDP, symmetricalDP_, fullySymmetricDP_); } LauDaughters::~LauDaughters() { delete kinematics_; kinematics_ = 0; } LauDaughters::LauDaughters( const LauDaughters& rhs ) : kinematics_(0), parent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavourConjugateDP_(kFALSE) { this->createParticleLists(); this->setParentType( rhs.getNameParent() ); this->setDaugType( rhs.getNameDaug1() , rhs.getNameDaug2() , rhs.getNameDaug3() ); // Create kinematics object kinematics_ = new LauKinematics(this->getMassDaug1(), this->getMassDaug2(), this->getMassDaug3(), this->getMassParent(), rhs.squareDP(), rhs.gotSymmetricalDP(), rhs.gotFullySymmetricDP()); } void LauDaughters::createParticleLists() { // Create list of allowed daughters allowedDaughters_.clear(); allowedDaughters_.push_back(LauDatabasePDG::particle("pi+")); allowedDaughters_.push_back(LauDatabasePDG::particle("pi-")); allowedDaughters_.push_back(LauDatabasePDG::particle("pi0")); allowedDaughters_.push_back(LauDatabasePDG::particle("K+")); allowedDaughters_.push_back(LauDatabasePDG::particle("K-")); allowedDaughters_.push_back(LauDatabasePDG::particle("K_S0")); allowedDaughters_.push_back(LauDatabasePDG::particle("eta")); allowedDaughters_.push_back(LauDatabasePDG::particle("eta'")); allowedDaughters_.push_back(LauDatabasePDG::particle("D+")); allowedDaughters_.push_back(LauDatabasePDG::particle("D-")); allowedDaughters_.push_back(LauDatabasePDG::particle("D0")); allowedDaughters_.push_back(LauDatabasePDG::particle("D0_bar")); allowedDaughters_.push_back(LauDatabasePDG::particle("D_s+")); allowedDaughters_.push_back(LauDatabasePDG::particle("D_s-")); // Create list of allowed parents allowedParents_.clear(); allowedParents_.push_back(LauDatabasePDG::particle("B+")); allowedParents_.push_back(LauDatabasePDG::particle("B-")); allowedParents_.push_back(LauDatabasePDG::particle("B0")); allowedParents_.push_back(LauDatabasePDG::particle("B0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("B_s0")); allowedParents_.push_back(LauDatabasePDG::particle("B_s0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("D+")); allowedParents_.push_back(LauDatabasePDG::particle("D-")); allowedParents_.push_back(LauDatabasePDG::particle("D0")); allowedParents_.push_back(LauDatabasePDG::particle("D0_bar")); allowedParents_.push_back(LauDatabasePDG::particle("D_s+")); allowedParents_.push_back(LauDatabasePDG::particle("D_s-")); } void LauDaughters::setParentType(const TString& nameParent) { parent_ = 0; const Int_t codeParent = LauDatabasePDG::code( nameParent ); for ( std::vector::const_iterator iter = allowedParents_.begin(); iter != allowedParents_.end(); ++iter ) { const Int_t code = (*iter)->code(); if ( codeParent == code ) { parent_ = (*iter); std::cout<<"INFO in LauDaughters::setParentType : Setting parent to be "<string()<<" == "<code()<Exit(EXIT_FAILURE); } } void LauDaughters::setDaugType(const TString& name1, const TString& name2, const TString& name3) { const TString names[3] = { name1, name2, name3 }; const Int_t codes[3] = { LauDatabasePDG::code( name1 ), LauDatabasePDG::code( name2 ), LauDatabasePDG::code( name3 ) }; daughters_.clear(); daughters_.resize(3); for ( int i(0); i<3; ++i ) { for ( std::vector::const_iterator iter = allowedDaughters_.begin(); iter != allowedDaughters_.end(); ++iter ) { Int_t code = (*iter)->code(); if ( codes[i] == code ) { daughters_[i] = (*iter); std::cout<<"INFO in LauDaughters::setDaugType : Setting daughter "<string()<<" == "<code()<Exit(EXIT_FAILURE); } } // Initialise the various data members concerning particle masses this->sanityCheck(); // Check whether we have a symmetrical Dalitz plot this->testDPSymmetry(); } void LauDaughters::testDPSymmetry() { // Check to see if we have a symmetrical or flavour-conjugate DP. symmetricalDP_ = kFALSE; fullySymmetricDP_ = kFALSE; flavourConjugateDP_ = kFALSE; if ( daughters_[0]->code() == daughters_[1]->code() && daughters_[0]->code() == daughters_[2]->code() ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a fully symmetric DP. "<code() == daughters_[1]->code() ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a symmetrical DP. "<code() == daughters_[2]->code() ) { std::cerr<<"ERROR in LauDaughters::testDPSymmetry : daughter 1 and daughter 3 are both "<string()<<" but DP can only fold on daughters 1 and 2."<Exit(EXIT_FAILURE); } else if ( daughters_[1]->code() == daughters_[2]->code() ) { std::cerr<<"ERROR in LauDaughters::testDPSymmetry : daughter 2 and daughter 3 are both "<string()<<" but DP can only fold on daughters 1 and 2."<Exit(EXIT_FAILURE); } else if ( daughters_[0]->type() == daughters_[1]->type() && daughters_[2]->charge() == 0 ) { std::cout<<"INFO in LauDaughters::testDPSymmetry : We have a flavour-conjugate DP. "<type() == daughters_[2]->type() && daughters_[1]->charge() == 0 ) { std::cerr<<"WARNING in LauDaughters::testDPSymmetry : it looks like we have a flavour-conjugate DP but the "<string()<<" and "<string()<<" are not positioned as daughters 1 and 2." << std::endl; } else if ( daughters_[1]->type() == daughters_[2]->type() && daughters_[0]->charge() == 0 ) { std::cerr<<"WARNING in LauDaughters::testDPSymmetry : it looks like we have a flavour-conjugate DP but the "<string()<<" and "<string()<<" are not positioned as daughters 1 and 2." << std::endl; } } void LauDaughters::sanityCheck() { // Check masses and charges of daughters Int_t totCharge(0); Double_t totMass(0.0); for ( std::vector::const_iterator iter = daughters_.begin(); iter != daughters_.end(); ++iter ) { totCharge += (*iter)->charge(); totMass += (*iter)->mass(); } if (totCharge != parent_->charge()) { std::cerr<<"ERROR in LauDaughters::sanityCheck : Total charge of daughters ("<charge()<<")."<Exit(EXIT_FAILURE); } if (totMass > parent_->mass()) { std::cerr<<"ERROR in LauDaughters::sanityCheck : Total mass of daughters ("<mass()<<")."<Exit(EXIT_FAILURE); } } Double_t LauDaughters::getMassDaug1() const { return daughters_[0]->mass(); } Double_t LauDaughters::getMassDaug2() const { return daughters_[1]->mass(); } Double_t LauDaughters::getMassDaug3() const { return daughters_[2]->mass(); } Double_t LauDaughters::getMassParent() const { return parent_->mass(); } TString LauDaughters::getNameDaug1() const { return daughters_[0]->string(); } TString LauDaughters::getNameDaug2() const { return daughters_[1]->string(); } TString LauDaughters::getNameDaug3() const { return daughters_[2]->string(); } TString LauDaughters::getNameParent() const { return parent_->string(); } TString LauDaughters::getSanitisedNameDaug1() const { return daughters_[0]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameDaug2() const { return daughters_[1]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameDaug3() const { return daughters_[2]->stringAlphaNum(); } TString LauDaughters::getSanitisedNameParent() const { return parent_->stringAlphaNum(); } Int_t LauDaughters::getTypeDaug1() const { return daughters_[0]->code(); } Int_t LauDaughters::getTypeDaug2() const { return daughters_[1]->code(); } Int_t LauDaughters::getTypeDaug3() const { return daughters_[2]->code(); } Int_t LauDaughters::getTypeParent() const { return parent_->code(); } Int_t LauDaughters::getChargeDaug1() const { return daughters_[0]->charge(); } Int_t LauDaughters::getChargeDaug2() const { return daughters_[1]->charge(); } Int_t LauDaughters::getChargeDaug3() const { return daughters_[2]->charge(); } Int_t LauDaughters::getChargeParent() const { return parent_->charge(); } Int_t LauDaughters::getCharge(Int_t resPairAmpInt) const { Int_t charge = this->getChargeParent(); if ( resPairAmpInt>0 && resPairAmpInt<4 ) { charge -= daughters_[resPairAmpInt-1]->charge(); } return charge; } diff --git a/src/LauEFKLLMRes.cc b/src/LauEFKLLMRes.cc index 1d9a7f8..443c310 100644 --- a/src/LauEFKLLMRes.cc +++ b/src/LauEFKLLMRes.cc @@ -1,175 +1,174 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEFKLLMRes.cc \brief File containing implementation of LauEFKLLMRes class. */ #include #include "Lau1DCubicSpline.hh" #include "LauKinematics.hh" #include "LauEFKLLMRes.hh" #include "LauResonanceInfo.hh" #include "LauTextFileParser.hh" -ClassImp(LauEFKLLMRes); Lau1DCubicSpline* LauEFKLLMRes::magSpline_ = 0; Lau1DCubicSpline* LauEFKLLMRes::phaseSpline_ = 0; LauEFKLLMRes::LauEFKLLMRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), massFactor_(0) { const Double_t massFactorVal = 0.; const TString& parNameBase = this->getSanitisedName(); TString massFactorName(parNameBase); massFactorName += "_massFactor"; massFactor_ = resInfo->getExtraParameter( massFactorName ); if ( massFactor_ == 0 ) { massFactor_ = new LauParameter( massFactorName, massFactorVal, -10.0, 10.0, kTRUE ); massFactor_->secondStage(kTRUE); resInfo->addExtraParameter( massFactor_ ); } } LauEFKLLMRes::~LauEFKLLMRes() { } void LauEFKLLMRes::initialise() { } void LauEFKLLMRes::setResonanceParameter(const TString& name, const Double_t value) { if(name=="massFactor") { this->setMassFactor(value); std::cout << "INFO in LauEFKLLMRes::setResonanceParameter: Mass factor set to " << value << std::endl; } else { std::cerr << "WARNING in LauEFKLLMRes::setResonanceParameter: Parameter name not reconised." << std::endl; } } void LauEFKLLMRes::floatResonanceParameter(const TString& name) { if(name=="massFactor") { if ( massFactor_->fixed() ) { massFactor_->fixed( kFALSE ); this->addFloatingParameter( massFactor_ ); } else { std::cerr << "WARNING in LauEFKLLMRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauEFKLLMRes::floatResonanceParameter: Parameter name not reconised." << std::endl; } } LauParameter* LauEFKLLMRes::getResonanceParameter(const TString& name) { if(name=="massFactor") { return massFactor_; } else { std::cerr << "WARNING in LauEFKLLMRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } const std::vector& LauEFKLLMRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMassFactor() ) { this->addFloatingParameter( massFactor_ ); } return this->getParameters(); } LauComplex LauEFKLLMRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex amp(0.0, 0.0); if (magSpline_ == 0 || phaseSpline_ == 0) { std::cerr << "ERROR in LauEFKLLMRes::resAmp : One of the splines is null." << std::endl; return amp; } const Double_t massSq = mass*mass; const Double_t mag = magSpline_->evaluate(massSq); const Double_t phase = TMath::DegToRad()*phaseSpline_->evaluate(massSq); LauComplex ff(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); amp = ff.scale(TMath::Power(mass,this->getMassFactor())); return amp; } void LauEFKLLMRes::setupFormFactor(const TString& inputFile) { LauTextFileParser readFile(inputFile); readFile.processFile(); std::vector mSqVals; std::vector magVals; std::vector phaseVals; std::vector line; line=readFile.getNextLine(); while(!line.empty()) { UInt_t length = line.size(); if(length!=3) { std::cerr << "ERROR in LauEFKLLMRes::setupFormFactor : Unexpected number of fields in text file, aborting reading of form-factor information." << std::endl; return; } mSqVals.push_back( atof(line[0].c_str())); magVals.push_back( atof(line[1].c_str())); phaseVals.push_back(atof(line[2].c_str())); line=readFile.getNextLine(); } // Destroy any splines we already had defined but issue a warning just in case if ( magSpline_ != 0 || phaseSpline_ != 0 ) { std::cerr << "WARNING in LauEFKLLMRes::setupFormFactor : Overwriting previous form-factor splines with newly read values." << std::endl; delete magSpline_; delete phaseSpline_; } magSpline_ = new Lau1DCubicSpline(mSqVals, magVals, Lau1DCubicSpline::AkimaSpline); phaseSpline_ = new Lau1DCubicSpline(mSqVals, phaseVals, Lau1DCubicSpline::AkimaSpline); } void LauEFKLLMRes::setMassFactor(const Double_t massFactor) { massFactor_->value( massFactor ); massFactor_->genValue( massFactor ); massFactor_->initValue( massFactor ); } diff --git a/src/LauEffModel.cc b/src/LauEffModel.cc index 8c1913f..f58bc93 100644 --- a/src/LauEffModel.cc +++ b/src/LauEffModel.cc @@ -1,323 +1,322 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEffModel.cc \brief File containing implementation of LauEffModel class. */ #include #include #include "TSystem.h" #include "Lau2DHistDP.hh" #include "Lau2DSplineDP.hh" #include "LauDaughters.hh" #include "LauEffModel.hh" #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauEffModel) LauEffModel::LauEffModel(const LauDaughters* daughters, const LauVetoes* vetoes) : daughters_( daughters ), vetoes_( vetoes ), effHisto_( 0 ), fluctuateEffHisto_( kFALSE ), lowBinWarningIssued_( kFALSE ), highBinWarningIssued_( kFALSE ) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauEffModel Constructor : invalid pointer to daughters object supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } } LauEffModel::~LauEffModel() { std::vector::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); } void LauEffModel::setEffHisto(const TH2* effHisto, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DHistDP(effHisto, daughters_, useInterpolation, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffHisto(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t useInterpolation, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DHistDP(effHisto, errorHi, errorLo, daughters_, useInterpolation, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffSpline(const TH2* effHisto, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DSplineDP(effHisto, daughters_, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::setEffSpline(const TH2* effHisto, const TH2* errorHi, const TH2* errorLo, Bool_t fluctuateBins, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::setEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::iterator it = effHisto_.begin(); std::vector::iterator end = effHisto_.end(); for( ; it!=end; ++it) { delete *it; *it=0; } effHisto_.clear(); // Copy the histogram. effHisto_.push_back(new Lau2DSplineDP(effHisto, errorHi, errorLo, daughters_, fluctuateBins, avEff, absError, upperHalf, squareDP)); fluctuateEffHisto_ = fluctuateBins; if (avEff > 0.0 && absError > 0.0) { fluctuateEffHisto_ = kTRUE; } } void LauEffModel::addEffHisto(const TH2* effHisto, Bool_t useInterpolation, Double_t avEff, Double_t absError, Bool_t useUpperHalfOnly, Bool_t squareDP) { // Set the efficiency across the Dalitz plot using a predetermined 2D histogram // with x = m_13^2, y = m_23^2. Bool_t upperHalf( kFALSE ); if ( daughters_->gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffHisto : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<gotSymmetricalDP() && useUpperHalfOnly == kTRUE) {upperHalf = kTRUE;} std::cout<<"INFO in LauEffModel::addEffSpline : Efficiency histogram has upperHalf = "<(upperHalf)<::const_iterator it = effHisto_.begin(); const std::vector::const_iterator end = effHisto_.end(); for( ; it!=end; ++it) { if ( (*it)->usingSquareDP() ) { xVal = kinematics->getmPrime(); yVal = kinematics->getThetaPrime(); } else { xVal = kinematics->getm13Sq(); yVal = kinematics->getm23Sq(); } eff *= (*it)->interpolateXY(xVal, yVal); } return eff; } Double_t LauEffModel::calcEfficiency( const LauKinematics* kinematics ) const { // Routine to calculate the efficiency for the given event/point in // the Dalitz plot. This routine uses the 2D histogram set by the // setEffHisto() function. Double_t eff(1.0); // Check for vetoes Bool_t vetoOK(kTRUE); if ( vetoes_ != 0 ) { vetoOK = vetoes_->passVeto(kinematics); } if (vetoOK == kFALSE) { // We failed the veto. eff = 0.0; } else { // We are using a 2D histogram representation of the efficiency across the Dalitz plot. eff = this->getEffHistValue( kinematics ); } // Check that the efficiency is in the allowed range (0-1) // If we're using a spline then out-of-range efficiencies can be caused by adjacent bins that all contain a value of either zero or one. // The spline requires the efficiency, its first derivatives and the mixed second derivative to be continuous and to match the input histogram // at the bin centres. Derivatives are calculated using a finite difference approximation taking the difference between the neighbouring bins. // If two bins are zero but the third is not then the second bin will have a positive first derivative causing the spline to dip below zero // between the two zero bins to remain smooth. The analogous case with adjacent maximised bins will cause peaks above one. Such dips are // unavoidable but are correctly removed here. if ( eff < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauEffModel::calcEfficiency : Efficiency " << eff << " is less than 0 - setting to 0. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent empty bins. Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } eff = 0.0; } else if ( eff > 1.0 ) { if(!highBinWarningIssued_) { std::cerr << "WARNING in LauEffModel::calcEfficiency : Efficiency " << eff << " is greater than 1 - setting to 1. You may want to check your histogram!" << std::endl << " : If you are using a spline then this could be caused by adjacent full bins. Further warnings will be suppressed." << std::endl; highBinWarningIssued_=kTRUE; } eff = 1.0; } return eff; } Bool_t LauEffModel::passVeto( const LauKinematics* kinematics ) const { Bool_t pass = kTRUE; if ( vetoes_ != 0 ) { pass = vetoes_->passVeto( kinematics ); } return pass; } diff --git a/src/LauEmbeddedData.cc b/src/LauEmbeddedData.cc index 3054b7f..56659a7 100644 --- a/src/LauEmbeddedData.cc +++ b/src/LauEmbeddedData.cc @@ -1,216 +1,215 @@ /* Copyright 2007 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauEmbeddedData.cc \brief File containing implementation of LauEmbeddedData class. */ #include #include using std::cerr; using std::endl; #include "TRandom.h" #include "LauIsobarDynamics.hh" #include "LauEmbeddedData.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(LauEmbeddedData) LauEmbeddedData::LauEmbeddedData(const TString& fileName, const TString& treeName, Bool_t allowReuseOfEvents) : theDataTree_(new LauFitDataTree(fileName,treeName)), reuseEvents_(allowReuseOfEvents) { } LauEmbeddedData::~LauEmbeddedData() { delete theDataTree_; } Bool_t LauEmbeddedData::findBranches() { if ( theDataTree_ == 0 ) { cerr<<"ERROR in LauEmbeddedData::findBranches : Invalid pointer to the data tree object."<findBranches(); if ( ! branchesReadOK ) { cerr<<"ERROR in LauEmbeddedData::findBranches : Problem finding branches."<readAllData(); return kTRUE; } Bool_t LauEmbeddedData::getReweightedEvent(LauIsobarDynamics* dynamics) { if (!theDataTree_) { cerr<<"ERROR in LauEmbeddedData::getReweightedEvent : Invalid pointer to the data tree object."<nEvents(); UInt_t iEvt(0); // First select a random event within the embedded data sample if (this->reuseEvents()) { iEvt = LauRandom::randomFun()->Integer(numEvents); } else { if (this->nUsedEvents() == numEvents) { cerr<<"ERROR in LauEmbeddedData::getReweightedEvent : Have already used all events in the tree."<Integer(numEvents); ok = usedEvents_.insert(iEvt).second; } } // Retrieve the data for the selected event theData_ = theDataTree_->getData(iEvt); LauKinematics* kinematics = dynamics->getKinematics(); if (kinematics != 0) { // Get the true m13Sq, m23Sq variables. Double_t m13Sq_MC = this->getValue("m13Sq_MC"); Double_t m23Sq_MC = this->getValue("m23Sq_MC"); if (kinematics->withinDPLimits(m13Sq_MC,m23Sq_MC)) { // Update the kinematics with the true m13Sq, m23Sq variables kinematics->updateKinematics(m13Sq_MC, m23Sq_MC); // Use this event or not, according to whether the amplitude model selects it. // The LauIsobarDynamics uses an accept/reject method based on the // ratio of the current to maximum ASq value. Other models may use alternative methods, // but they must provide a yes/no answer if the event is accepted. Bool_t gotReweightedEvent = dynamics->gotReweightedEvent(); if (gotReweightedEvent == kTRUE) { // Event is accepted. // Update the kinematics to use the reco variables. Double_t m13Sq = this->getValue("m13Sq"); Double_t m23Sq = this->getValue("m23Sq"); kinematics->updateKinematics(m13Sq, m23Sq); if (LauIsobarDynamics::GenOK != dynamics->checkToyMC(kFALSE,kFALSE)) { return kFALSE; } } else { // Recursively run this function until we get an accepted event return this->getReweightedEvent(dynamics); } } else { cerr<<"WARNING in LauEmbeddedData::getReweightedEvent : Skipping event "<getReweightedEvent(dynamics); } } return kTRUE; } void LauEmbeddedData::getEmbeddedEvent(LauKinematics* kinematics) { if (!theDataTree_) { cerr<<"ERROR in LauEmbeddedData::getEmbeddedEvent : Invalid pointer to the data tree object."<nEvents(); UInt_t iEvt(0); if (this->reuseEvents()) { iEvt = LauRandom::randomFun()->Integer(numEvents); } else { if (this->nUsedEvents() == numEvents) { cerr<<"ERROR in LauEmbeddedData::getEmbeddedEvent : Have already used all events in the tree."<Integer(numEvents); ok = usedEvents_.insert(iEvt).second; } } theData_ = theDataTree_->getData(iEvt); if (kinematics!=0) { Double_t m13Sq = this->getValue("m13Sq"); Double_t m23Sq = this->getValue("m23Sq"); if (kinematics->withinDPLimits(m13Sq,m23Sq)) { kinematics->updateKinematics(m13Sq,m23Sq); } else { cerr<<"WARNING in LauEmbeddedData::getEmbeddedEvent : Skipping event that isn't within the DP boundary."<getEmbeddedEvent(kinematics); } } } Double_t LauEmbeddedData::getValue(const TString& name) const { LauFitData::const_iterator iter = theData_.find(name); if (iter == theData_.end()) { cerr<<"ERROR in LauEmbeddedData::getValue : Could not find branch \""<second; } } LauFitData LauEmbeddedData::getValues(const std::vector& names) const { LauFitData retVal; for ( std::vector::const_iterator iter = names.begin(); iter != names.end(); ++iter ) { const TString& name = (*iter); LauFitData::const_iterator data_iter = theData_.find(name); if ( data_iter == theData_.end() ) { cerr<<"WARNING in LauEmbeddedData::getValues : Could not find branch \""< #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauExponentialPdf.hh" -ClassImp(LauExponentialPdf) LauExponentialPdf::LauExponentialPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), slope_(0) { // Constructor for the Exponential PDF. // // The parameter in param is the slope of the exponential ie exp(slope*x). // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. slope_ = this->findParameter("slope"); if ((this->nParameters() != 1) || (slope_ == 0)) { cerr<<"ERROR in LauExponentialPdf constructor: LauExponentialPdf requires 1 parameter: \"slope\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauExponentialPdf::~LauExponentialPdf() { // Destructor } void LauExponentialPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the value of the Exponential for the given value of the abscissa. Double_t exponent(0.0); if(slope != 0){ exponent = slope*abscissa; } Double_t value = TMath::Exp(exponent); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauExponentialPdf::calcNorm() { // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the normalisation of the exponential and cache it. Double_t norm(0.0); if(slope != 0){ norm = (1/slope)*(TMath::Exp(slope*this->getMaxAbscissa()) - TMath::Exp(slope*this->getMinAbscissa())) ; } this->setNorm(norm); } void LauExponentialPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t slope = slope_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = 0; // Calculate the PDF height for the Exponential function. if (slope > 0) { maxPoint[0] = this->getMaxAbscissa(); } else if (slope < 0) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauFitDataTree.cc b/src/LauFitDataTree.cc index 02abec6..efc01ae 100644 --- a/src/LauFitDataTree.cc +++ b/src/LauFitDataTree.cc @@ -1,388 +1,387 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitDataTree.cc \brief File containing implementation of LauFitDataTree class. */ #include #include #include #include "TFile.h" #include "TLeaf.h" #include "TString.h" #include "TSystem.h" #include "LauFitDataTree.hh" -ClassImp(LauFitDataTree) LauFitDataTree::LauFitDataTree(const TString& rootFileName, const TString& rootTreeName) : rootFileName_(rootFileName), rootTreeName_(rootTreeName), rootFile_(0), rootTree_(0), eventList_(0) { if (rootFileName_ != "" && rootTreeName_ != "") { this->openFileAndTree(); } } LauFitDataTree::~LauFitDataTree() { if (rootFile_ && rootFile_->IsOpen()) { delete rootTree_; rootTree_ = 0; delete eventList_; eventList_ = 0; } delete rootFile_; rootFile_ = 0; } void LauFitDataTree::openFileAndTree() { // first check whether we've already opened up the file or not if (!rootFile_) { // if not, first check the filename and if all ok create the file if (rootFileName_ == "") { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Bad filename supplied, not creating file or tree." << std::endl; return; } rootFile_ = TFile::Open(rootFileName_, "read"); if (!rootFile_ || rootFile_->IsZombie() || !rootFile_->IsOpen()) { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem opening file \"" << rootFileName_ << "\" for reading." << std::endl; return; } } // check whether we've already created the tree if (!rootTree_) { // if not change to the file's directory and grab the tree rootFile_->cd(); rootTree_ = dynamic_cast(rootFile_->Get(rootTreeName_)); if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem reading tree \"" << rootTreeName_ << "\" from file." << std::endl; return; } rootTree_->SetDirectory(rootFile_); } } Bool_t LauFitDataTree::findBranches() { if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::findBranches : Invalid pointer to data tree." << std::endl; return kFALSE; } // this method should only be called once if ( ! leafNames_.empty() ) { std::cerr << "ERROR in LauFitDataTree::findBranches : Branches already found, not running again." << std::endl; return kFALSE; } leafNames_.clear(); eventData_.clear(); eventDataOut_.clear(); leaves_.clear(); treeEvents_.clear(); fakeEvents_.clear(); const UInt_t numBranches(this->nBranches()); eventData_.reserve( numBranches ); TObjArray* pLeaves = rootTree_->GetListOfLeaves(); if (!pLeaves) { std::cerr << "ERROR in LauFitDataTree::findBranches : Problem retrieving leaves from the tree." << std::endl; return kFALSE; } TObjArray& leaves = *pLeaves; const UInt_t numLeaves = static_cast( leaves.GetEntries() ); if ( numBranches != numLeaves ) { std::cerr << "ERROR in LauFitDataTree::findBranches : List of leaves is not the same size as the number of branches - this is strange!" << std::endl; std::cerr << " : There are " << numLeaves << " leaves and " << numBranches << " branches" << std::endl; return kFALSE; } for (UInt_t iLeaf = 0; iLeaf < numBranches; ++iLeaf) { TLeaf * leaf = dynamic_cast(leaves[iLeaf]); // we can't deal with arrays Int_t size = leaf->GetNdata(); if (size != 1) { std::cerr << "ERROR in LauFitDataTree::findBranches : Tree has array branches, can't deal with those." << std::endl; return kFALSE; } // find the name and type of the leaf TString name = leaf->GetName(); // initialise an entry in the maps to hold the value leafNames_[ name ] = iLeaf; leaves_.push_back( leaf ); eventData_.push_back( 0.0 ); eventDataOut_[ name ] = 0.0; } const UInt_t numEvents(this->nTotalEvents()); std::cout << "INFO in LauFitDataTree::findBranches : Finished finding data tree branches." << std::endl; std::cout << " : Tree contains " << numBranches << " branches and a total of " << numEvents << " events." << std::endl; return kTRUE; } void LauFitDataTree::readExperimentData(UInt_t iExpt) { // Check that we have a valid tree to read from if (!rootTree_) { std::cerr << "ERROR in LauFitDataTree::readExperimentData : Invalid pointer to data tree." << std::endl; return; } rootFile_->cd(); // If the event list doesn't exist, create it if (!eventList_) { eventList_ = new TEventList("elist","elist"); eventList_->SetDirectory(rootFile_); } // Reset the event list so it contains no entries eventList_->Reset(); // Check that the tree contains the iExpt branch if (!this->haveBranch("iExpt")) { // If it doesn't, check which experiment we've been asked to read if ( iExpt == 0 ) { // If it's experiment 0, assume that we should read all events in the tree (but print a warning since this is an assumption) std::cerr << "WARNING in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch, will read all data in the tree" << std::endl; this->readAllData(); return; } else { // Otherwise we can't really do anything, so print an error and return std::cerr << "ERROR in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch and experiment requested is > 0, will not read anything" << std::endl; return; } } // Fill the event list with the entries for the requested experiment TString listName(eventList_->GetName()); listName.Prepend(">>"); TString selection("iExpt=="); selection += iExpt; std::cout << "INFO in LauFitDataTree::readExperimentData : Setting tree to experiment number " << iExpt << "." << std::endl; rootTree_->Draw(listName,selection); std::cout << " : Found " << this->nEvents() << " events." << std::endl; // Load the data this->loadData(); } UInt_t LauFitDataTree::nBranches() const { if ( rootTree_ ) { return static_cast(rootTree_->GetNbranches()); } else if ( ! fakeEvents_.empty() ) { std::vector::const_iterator fakeIter = fakeEvents_.begin(); return (*fakeIter).size(); } else { return 0; } } void LauFitDataTree::appendFakePoints( const std::vector& xCoords, const std::vector& yCoords) { if ( xCoords.size() != yCoords.size() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : The co-ordinate vectors are not the same size!" << std::endl; gSystem->Exit(EXIT_FAILURE); } // clear the list of fake events and reserve enough space fakeEvents_.clear(); fakeEvents_.reserve(xCoords.size()); // loop over the event data zeroing everything for (LauEventData::iterator iter = eventData_.begin(); iter != eventData_.end(); ++iter) { *iter = 0.0; } // find the vector indices for the DP co-ordinates LauNameIndexMap::const_iterator iter = leafNames_.find( "m13Sq" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m13Sq\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t m13SqIdx = iter->second; iter = leafNames_.find( "m23Sq" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m23Sq\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t m23SqIdx = iter->second; // TODO - is this really needed? Comment out for now. /* // and a fake tagCat which we don't care about, but the program // needs a number here for comptibility with conventional events. iter = leafNames_.find( "tagCat" ); if ( iter == leafNames_.end() ) { std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"tagCat\" in event data map." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t tagCatIdx = iter->second; */ for (UInt_t iEvt = 0; iEvt < xCoords.size() ; ++iEvt) { // set the values eventData_[ m13SqIdx ] = xCoords[iEvt]; eventData_[ m23SqIdx ] = yCoords[iEvt]; //eventData_[ tagCatIdx ] = 0.0; // append to the list of fake events fakeEvents_.push_back(eventData_); } } Bool_t LauFitDataTree::haveBranch(const TString& name) const { LauNameIndexMap::const_iterator iter = leafNames_.find( name ); return (iter != leafNames_.end()); } void LauFitDataTree::disableAllBranches() const { rootTree_->SetBranchStatus("*", 0); } void LauFitDataTree::enableAllBranches() const { rootTree_->SetBranchStatus("*", 1); } void LauFitDataTree::enableBranch(const TString& name) const { if (this->haveBranch(name)) {rootTree_->SetBranchStatus(name, 1);} } void LauFitDataTree::disableBranch(const TString& name) const { if (this->haveBranch(name)) {rootTree_->SetBranchStatus(name, 0);} } void LauFitDataTree::loadData() { // Clear any data from previous expts treeEvents_.clear(); // Reserve enough space in the vector Long64_t nEvts = this->nEvents(); treeEvents_.reserve( nEvts ); const UInt_t nLeaves = this->nBranches(); // Loop through the tree and store the data for ( Long64_t iEvt(0); iEvt < nEvts; ++iEvt ) { // Find which entry from the full tree contains the requested event Long64_t iEntry = eventList_ ? eventList_->GetEntry(iEvt) : iEvt; if (iEntry<0) { // this shouldn't happen, but just in case... std::cerr << "ERROR in LauFitDataTree::loadData : Requested event not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Then retrieve that entry from the tree rootTree_->GetEntry(iEntry); // Copy the leaf values into eventData_ for ( UInt_t iLeaf(0); iLeaf < nLeaves; ++iLeaf ) { const TLeaf * leaf = leaves_[ iLeaf ]; Double_t value = leaf->GetValue(); if ( std::isnan( value ) || std::isinf( value ) ) { std::cerr << "ERROR in LauFitDataTree::loadData : Event " << iEvt << " has infinite or NaN entry for variable " << leaf->GetName() << std::endl; gSystem->Exit(EXIT_FAILURE); } eventData_[ iLeaf ] = value; } // Store the event in the vector treeEvents_.push_back( eventData_ ); } } void LauFitDataTree::readAllData() { delete eventList_; eventList_ = 0; this->loadData(); } const LauFitData& LauFitDataTree::getData(UInt_t iEvt) const { // For a given event, within the current experiment, // retrieve the input fit variables const UInt_t numTreeEvents = this->nEvents(); const UInt_t numFakeEvents = this->nFakeEvents(); // Does the requested event come from the tree or from the fake events list? if ( iEvt < numTreeEvents ) { if ( iEvt > treeEvents_.size() ) { // this shouldn't happen, but just in case... std::cerr << "ERROR in LauFitDataTree::getData : Requested event, " << iEvt << ", not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Retrieve that event from the vector eventData_ = treeEvents_[iEvt]; } else if ( iEvt < (numTreeEvents + numFakeEvents) ) { // Find the entry from the fake events list contains the requested event UInt_t iEntry = iEvt - numTreeEvents; // Copy the entry into eventData_ eventData_ = fakeEvents_[iEntry]; } else { std::cerr << "ERROR in LauFitDataTree::getData : Requested event " << iEvt << " not found for " << rootTreeName_ << std::endl; gSystem->Exit(EXIT_FAILURE); } for ( LauNameIndexMap::const_iterator iter = leafNames_.begin(); iter != leafNames_.end(); ++iter ) { const TString& name = iter->first; UInt_t index = iter->second; LauFitData::iterator outIter = eventDataOut_.find( name ); if ( outIter == eventDataOut_.end() ) { std::cerr << "ERROR in LauFitDataTree::getData : Something very strange happening." << std::endl; gSystem->Exit(EXIT_FAILURE); } outIter->second = eventData_[ index ]; } return eventDataOut_; } diff --git a/src/LauFitNtuple.cc b/src/LauFitNtuple.cc index 3b8fc6f..e4caa8e 100644 --- a/src/LauFitNtuple.cc +++ b/src/LauFitNtuple.cc @@ -1,342 +1,341 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitNtuple.cc \brief File containing implementation of LauFitNtuple class. */ #include #include "TFile.h" #include "TMath.h" #include "TMatrixD.h" #include "TSystem.h" #include "TTree.h" #include "LauAbsFitter.hh" #include "LauFitNtuple.hh" #include "LauFitter.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" -ClassImp(LauFitNtuple) LauFitNtuple::LauFitNtuple(const TString& fileName, Bool_t storeAsymErrors) : rootFileName_(fileName), rootFile_(0), fitResults_(0), definedFitTree_(kFALSE), storeAsymErrors_(storeAsymErrors), fitStatus_({-1,0.0,0.0}), nFitPars_(0), nFreePars_(0), nExtraPars_(0), iExpt_(0) { rootFile_ = TFile::Open(rootFileName_, "recreate"); rootFile_->cd(); fitResults_ = new TTree("fitResults", "fitResults"); fitResults_->SetDirectory(rootFile_); fitVars_.clear(); extraVars_.clear(); } LauFitNtuple::~LauFitNtuple() { if (rootFile_ && rootFile_->IsOpen()) { delete fitResults_; fitResults_ = 0; } delete rootFile_; rootFile_ = 0; } void LauFitNtuple::storeCorrMatrix(const UInt_t iExpt, const LauAbsFitter::FitStatus& fitStatus, const TMatrixD& covMatrix) { // store the minimised NLL value, correlation matrix status and experiment number iExpt_ = iExpt; fitStatus_ = fitStatus; // make the correlation matrix the correct dimensions if (definedFitTree_ == kFALSE) { corrMatrix_.clear(); corrMatrix_.resize(nFitPars_); for (UInt_t i = 0; i < nFitPars_; ++i) {corrMatrix_[i].resize(nFitPars_);} } // under certain circumstances, e.g. if the fit has failed in the first // stage of a two-stage fit, the covariance matrix might not have the // expected dimensions, or it might even be empty Bool_t needsPadding = kFALSE; const UInt_t nElements = covMatrix.GetNoElements(); if ( nElements == 0 ) { // if it's empty we can just make a diagonal matrix std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received empty covariance matrix - will store diagonal correlation matrix" << std::endl; for (UInt_t i = 0; i < nFitPars_; ++i) { for (UInt_t j = 0; j < nFitPars_; ++j) { if (i == j) { corrMatrix_[i][j] = 1.0; } else { corrMatrix_[i][j] = 0.0; } } } return; } else if ( nElements != nFreePars_*nFreePars_ ) { UInt_t dimension = covMatrix.GetNrows(); UInt_t nSecondStage = 0; for (UInt_t i = 0; i < nFitPars_; ++i) { if ( fitVars_[i]->secondStage() ) { ++nSecondStage; } } if ( (dimension + nSecondStage) == nFreePars_ ) { needsPadding = kTRUE; std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, likely due to failure of first stage fit - will pad the correlation matrix" << std::endl; std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl; std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl; std::cerr << " : nSecondStage = " << nSecondStage << std::endl; std::cerr << " : covMatrix size = " << dimension << std::endl; } else { std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, for unknown reasons - will store diagonal correlation matrix" << std::endl; std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl; std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl; std::cerr << " : nSecondStage = " << nSecondStage << std::endl; std::cerr << " : covMatrix size = " << dimension << std::endl; for (UInt_t i = 0; i < nFitPars_; ++i) { for (UInt_t j = 0; j < nFitPars_; ++j) { if (i == j) { corrMatrix_[i][j] = 1.0; } else { corrMatrix_[i][j] = 0.0; } } } return; } } // calculate the correlation matrix information from the fitter covariance matrix Bool_t iFixed(kFALSE); Bool_t jFixed(kFALSE); Bool_t iSecondStage(kFALSE); Bool_t jSecondStage(kFALSE); UInt_t iFree(0); UInt_t jFree(0); for (UInt_t i = 0; i < nFitPars_; ++i) { iFixed = fitVars_[i]->fixed(); iSecondStage = fitVars_[i]->secondStage(); // reset the "j" free parameter counter jFree = 0; // NB the supplied covariance matrix is of dimension nFreePars_ x nFreePars_ for (UInt_t j = 0; j < nFitPars_; ++j) { jFixed = fitVars_[j]->fixed(); jSecondStage = fitVars_[j]->secondStage(); if (i == j) { corrMatrix_[i][j] = 1.0; } else if (iFixed == kTRUE || jFixed == kTRUE) { corrMatrix_[i][j] = 0.0; } else if ( needsPadding && ( iSecondStage || jSecondStage ) ) { corrMatrix_[i][j] = 0.0; } else { Double_t r_ij = covMatrix(iFree,jFree); Double_t r_ii = covMatrix(iFree,iFree); Double_t r_jj = covMatrix(jFree,jFree); Double_t denom = r_ii * r_jj; if (denom < 0.0) { r_ij = 0.0; denom = 1.0; } denom = TMath::Sqrt(denom); if (denom < 1e-30) { r_ij = 0.0; denom = 1.0; } corrMatrix_[i][j] = r_ij / denom; } if ( !jFixed && !(needsPadding && jSecondStage) ) { ++jFree; } } if ( !iFixed && !(needsPadding && iSecondStage) ) { ++iFree; } } } void LauFitNtuple::storeParsAndErrors(const std::vector& fitVars, const std::vector& extraVars) { fitVars_ = fitVars; UInt_t nFitPars = fitVars_.size(); // the number of parameters being given to us should be the same as the number from the last fit // OR it's the first time so the "last" number is zero if (nFitPars_ != 0 && nFitPars_ != nFitPars) { std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected total number of parameters (" << nFitPars_ << ") not the same as the number provided (" << nFitPars << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } LauParamFixed pred; UInt_t nFreePars = nFitPars - std::count_if(fitVars_.begin(),fitVars_.end(),pred); // the number of free parameters being given to us should be the same as the number from the last fit // OR it's the first time so the "last" number is zero // (NB we check whether nFitPars_ is zero for this since it is possible to have zero free parameters, albeit rather daft) if (nFitPars_ != 0 && nFreePars_ != nFreePars) { std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected number of free parameters (" << nFreePars_ << ") not the same as the number provided (" << nFreePars << ")." << std::endl; gSystem->Exit(EXIT_FAILURE); } nFitPars_ = nFitPars; nFreePars_ = nFreePars; extraVars_ = extraVars; nExtraPars_ = extraVars_.size(); } void LauFitNtuple::updateFitNtuple() { // Now create and fill the stored fit results into an ntuple (TTree) if (definedFitTree_ == kFALSE) { std::cout << "INFO in LauFitNtuple::updateFitNtuple : totNoPars = " << nFitPars_ << std::endl; // Add experiment number as a branch fitResults_->Branch("iExpt", &iExpt_, "iExpt/I"); fitResults_->Branch("fitStatus", &fitStatus_.status, "fitStatus/I"); // Add NLL (negative log-likelihood) and EDM values from fit fitResults_->Branch("NLL", &fitStatus_.NLL, "NLL/D"); fitResults_->Branch("EDM", &fitStatus_.EDM, "EDM/D"); for (UInt_t i = 0; i < nFitPars_; i++) { TString parName = fitVars_[i]->name(); TString parNameD(parName); parNameD += "/D"; fitResults_->Branch(parName.Data(), &fitVars_[i]->value_, parNameD.Data()); TString parInitName(parName); parInitName += "_True"; TString parInitNameD(parInitName); parInitNameD += "/D"; fitResults_->Branch(parInitName.Data(), &fitVars_[i]->genValue_, parInitNameD.Data()); if (!fitVars_[i]->fixed()) { TString parErrName(parName); parErrName += "_Error"; TString parErrNameD(parErrName); parErrNameD += "/D"; fitResults_->Branch(parErrName.Data(), &fitVars_[i]->error_, parErrNameD.Data()); if ( storeAsymErrors_ ) { TString parNegErrName(parName); parNegErrName += "_NegError"; TString parNegErrNameD(parNegErrName); parNegErrNameD += "/D"; fitResults_->Branch(parNegErrName.Data(), &fitVars_[i]->negError_, parNegErrNameD.Data()); TString parPosErrName(parName); parPosErrName += "_PosError"; TString parPosErrNameD(parPosErrName); parPosErrNameD += "/D"; fitResults_->Branch(parPosErrName.Data(), &fitVars_[i]->posError_, parPosErrNameD.Data()); } TString parPullName(parName); parPullName += "_Pull"; TString parPullNameD(parPullName); parPullNameD += "/D"; fitResults_->Branch(parPullName.Data(), &fitVars_[i]->pull_, parPullNameD.Data()); } // Now add in the correlation matrix values (only for floating parameters) if (!fitVars_[i]->fixed()) { // First the global correlation coeffs TString parGCCName(parName); parGCCName += "_GCC"; TString parGCCNameD(parGCCName); parGCCNameD += "/D"; fitResults_->Branch(parGCCName.Data(), &fitVars_[i]->gcc_, parGCCNameD.Data()); if ( ! corrMatrix_.empty() ) { // Then the rest for (UInt_t j = 0; j < nFitPars_; j++) { if (!fitVars_[j]->fixed() && i!=j) { TString parName2 = fitVars_[j]->name(); TString corrName("corr__"); corrName += parName; corrName += "__"; corrName += parName2; TString corrNameD(corrName); corrNameD += "/D"; fitResults_->Branch(corrName.Data(), &corrMatrix_[i][j], corrNameD.Data()); } } } } } // Update extra parameter values... for (UInt_t i = 0; i < nExtraPars_; i++) { TString parName = extraVars_[i].name(); TString parNameD(parName); parNameD += "/D"; fitResults_->Branch(parName.Data(), &extraVars_[i].value_, parNameD.Data()); TString parInitName(parName); parInitName += "_True"; TString parInitNameD(parInitName); parInitNameD += "/D"; fitResults_->Branch(parInitName.Data(), &extraVars_[i].genValue_, parInitNameD.Data()); //TString parErrName(parName); parErrName += "_Error"; //TString parErrNameD(parErrName); parErrNameD += "/D"; //fitResults_->Branch(parErrName.Data(), &extraVars_[i].error_, parErrNameD.Data()); // Also find the fit fraction pull and store it //TString pullName(parName); pullName += "_Pull"; //TString pullNameD(pullName); pullNameD += "/D"; //fitResults_->Branch(pullName.Data(), &extraVars_[i].pull_, pullNameD.Data()); } definedFitTree_ = kTRUE; } std::cout << "INFO in LauFitNtuple::updateFitNtuple : Stored fit values for experiment " << iExpt_ << "\n"; std::cout << " : fitStatus = " << fitStatus_.status << std::endl; std::cout << " : NLL = " << fitStatus_.NLL << std::endl; std::cout << " : EDM = " << fitStatus_.EDM << std::endl; fitResults_->Fill(); } void LauFitNtuple::writeOutFitResults() { // Write out the fit ntuple to the appropriate root file rootFile_->cd(); fitResults_->Write("",TObject::kOverwrite); rootFile_->Close(); delete rootFile_; rootFile_ = 0; } diff --git a/src/LauFitObject.cc b/src/LauFitObject.cc index 0b73591..ea9f767 100644 --- a/src/LauFitObject.cc +++ b/src/LauFitObject.cc @@ -1,251 +1,250 @@ /* Copyright 2017 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitObject.cc \brief File containing implementation of LauFitObject class. */ #include #include "TDecompChol.h" #include "TMatrixD.h" #include "TRandom.h" #include "TSystem.h" #include "TVectorD.h" #include "LauFitObject.hh" #include "LauRandom.hh" -ClassImp(LauFitObject) LauFitObject::LauFitObject() : TObject(), twoStageFit_(kFALSE), useAsymmFitErrors_(kFALSE), nParams_(0), nFreeParams_(0), withinAsymErrorCalc_(kFALSE), toyExpts_(kFALSE), firstExpt_(0), nExpt_(1), iExpt_(0), evtsPerExpt_(0), fitStatus_({-1,0.0,0.0}), worstLogLike_(std::numeric_limits::max()), covMatrix_(), numberOKFits_(0), numberBadFits_(0) { } void LauFitObject::setNExpts(UInt_t nExperiments, UInt_t firstExperiment, Bool_t toyExpts) { nExpt_ = nExperiments; firstExpt_ = firstExperiment; toyExpts_ = toyExpts; if ( ! toyExpts && ( nExperiments > 1 || firstExperiment > 0 ) ) { std::cerr << "WARNING in LauFitObject::setNExpts : toyExpts is set to kFALSE but the values of nExperiments and firstExperiment indicate otherwise, please check" << std::endl; } else if ( toyExpts && nExperiments == 1 && firstExperiment == 0 ) { std::cerr << "WARNING in LauFitObject::setNExpts : toyExpts is set to kTRUE but the values of nExperiments and firstExperiment perhaps indicate otherwise, please check" << std::endl; } } void LauFitObject::resetFitCounters() { numberOKFits_ = 0; numberBadFits_ = 0; fitStatus_ = { -1, 0.0, 0.0 }; } void LauFitObject::startNewFit( const UInt_t nPars, const UInt_t nFreePars ) { // Reset the worst likelihood found to its catch-all value worstLogLike_ = std::numeric_limits::max(); // Store the number of fit parameters (total and floating) nParams_ = nPars; nFreeParams_ = nFreePars; } void LauFitObject::storeFitStatus( const LauAbsFitter::FitStatus& status, const TMatrixD& covMatrix ) { fitStatus_ = status; covMatrix_.Clear(); covMatrix_.ResizeTo( covMatrix.GetNrows(), covMatrix.GetNcols() ); covMatrix_.SetMatrixArray( covMatrix.GetMatrixArray() ); // Keep track of how many fits worked or failed // NB values of fitStatus_ indicate the status of the error matrix: // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix if (fitStatus_.status == 3) { ++numberOKFits_; } else { ++numberBadFits_; } } void LauFitObject::addConstraint(const TString& formula, const std::vector& pars, const Double_t mean, const Double_t width) { std::cerr << "WARNING in LauFitObject::addConstraint : This function is deprecated, please switch to addFormulaConstraint!" << std::endl; this->addFormulaConstraint( formula, pars, mean, width ); } void LauFitObject::addFormulaConstraint(const TString& formula, const std::vector& pars, const Double_t mean, const Double_t width) { if ( ! this->checkRepetition(pars) ){ std::cerr << "WARNING in LauFitObject::addFormulaConstraint : Parameter(s) added to multiple constraints!" << std::endl; } formulaConstraints_.emplace_back( FormulaConstraint{formula, pars, mean, width, nullptr} ); std::cout << "INFO in LauFitObject::addFormulaConstraint : Added formula constraint" << std::endl; } void LauFitObject::addMultiDimConstraint( const std::vector& pars, const TVectorD& means, const TMatrixD& covMat) { if ( ! this->checkRepetition(pars) ){ std::cerr << "WARNING in LauFitObject::addMultiDimConstraint : Parameter(s) added to multiple constraints!" << std::endl; } multiDimConstraints_.emplace_back( pars, means, covMat ); std::cout << "INFO in LauFitObject::addMultiDimConstraint : Added multi-dimensional constraint" << std::endl; } void LauFitObject::generateConstraintMeans( std::vector& conVars ) { if ( ! this->toyExpts() ) { return; } // For reproducibility, set a seed based on the experiment number // First, store the current seed, so that it can be restored afterwards const UInt_t oldSeed { LauRandom::randomFun()->GetSeed() }; LauRandom::randomFun()->SetSeed( 827375 + this->iExpt() ); for ( LauAbsRValue* par : conVars ) { par->generateConstraintMean(); } for ( auto& constraint : multiDimConstraints_ ) { constraint.generateConstraintMeans(); } // Restore the old random seed LauRandom::randomFun()->SetSeed( oldSeed ); } Bool_t LauFitObject::checkRepetition( const std::vector& names ) { Bool_t allOK(kTRUE); if ( formulaConstraints_.size()==0 && multiDimConstraints_.size()==0 ) { return allOK; } //Check in formula constraints for ( auto& constraint : formulaConstraints_ ){ for ( auto& parname : constraint.conPars_ ){ for ( auto& newname : names ){ if ( parname == newname ){ std::cerr << "WARNING in LauFitObject::checkRepetition: named parameter " << newname << " already used in a constraint" << std::endl; allOK = kFALSE; } } } } //Check in ND constraints for ( auto& constraint : multiDimConstraints_ ){ for ( auto& parname : constraint.conPars_ ){ for ( auto& newname : names ){ if ( parname == newname ){ std::cerr << "WARNING in LauFitObject::checkRepetition: named parameter " << newname << " already used in a constraint" << std::endl; allOK = kFALSE; } } } } return allOK; } LauFitObject::MultiDimConstraint::MultiDimConstraint( const std::vector& parNames, const TVectorD& means, const TMatrixD& covMat ) : conPars_{parNames}, trueMeans_{means}, means_{means}, invCovMat_{covMat.GetNrows(),covMat.GetNcols()}, sqrtCovMat_{covMat.GetNrows(),covMat.GetNcols()} { if ( covMat.GetNcols() != covMat.GetNrows() ){ std::cerr << "ERROR in LauFitObject::MultiDimConstraint : Covariance matrix is not square!" << std::endl; gSystem->Exit( EXIT_FAILURE ); } if ( ( parNames.size() != static_cast(means.GetNrows()) ) || ( parNames.size() != static_cast(covMat.GetNrows()) ) ){ std::cerr << "ERROR in LauFitObject::MultiDimConstraint : Different number of elements in vectors/covariance matrix!" << std::endl; gSystem->Exit( EXIT_FAILURE ); } // Check invertion of the covariance matrix was successful TMatrixD invCovMat {TMatrixD::kInverted, covMat}; if ( invCovMat == covMat ){ std::cerr << "ERROR in LauFitObject::MultiDimConstraint : covariance matrix inversion failed, check your input!" << std::endl; gSystem->Exit( EXIT_FAILURE ); } invCovMat_ = invCovMat; // Check invertion of the covariance matrix was successful TDecompChol cholDecomp {covMat}; if ( ! cholDecomp.Decompose() ) { std::cerr << "ERROR in LauFitObject::MultiDimConstraint : covariance matrix decomposition failed, check your input!" << std::endl; gSystem->Exit( EXIT_FAILURE ); } sqrtCovMat_ = TMatrixD{TMatrixD::kTransposed, cholDecomp.GetU()}; } Double_t LauFitObject::MultiDimConstraint::constraintPenalty() const { TVectorD diff{ means_.GetNrows() }; for ( ULong_t j {0}; j < conLauPars_.size(); ++j ) { LauParameter* param = conLauPars_[j]; diff[j] = param->unblindValue(); } diff -= means_; return 0.5 * invCovMat_.Similarity( diff ); } void LauFitObject::MultiDimConstraint::generateConstraintMeans() { TRandom* random = LauRandom::randomFun(); for ( Int_t j {0}; j < trueMeans_.GetNrows(); ++j ) { means_[j] = random->Gaus(0.0, 1.0); } means_ *= sqrtCovMat_; means_ += trueMeans_; } diff --git a/src/LauFitter.cc b/src/LauFitter.cc index f03bee0..2c62d33 100644 --- a/src/LauFitter.cc +++ b/src/LauFitter.cc @@ -1,99 +1,98 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFitter.cc \brief File containing implementation of LauFitter methods. */ #include "LauFitter.hh" #include "LauMinuit.hh" #include #include #include std::unique_ptr LauFitter::theInstance_ = nullptr; LauFitter::Type LauFitter::fitterType_ = LauFitter::Type::Minuit; LauOutputLevel LauFitter::fitterVerbosity_ = LauOutputLevel::Standard; UInt_t LauFitter::fitterMaxPars_ = 100; -ClassImp(LauFitter) void LauFitter::setFitterType( const Type type ) { if ( theInstance_ != nullptr ) { std::cerr << "ERROR in LauFitter::setFitterType : The fitter has already been created, cannot change the type now." << std::endl; return; } fitterType_ = type; } void LauFitter::setFitterVerbosity( const LauOutputLevel level ) { if ( theInstance_ != nullptr ) { std::cerr << "ERROR in LauFitter::setFitterVerbosity : The fitter has already been created, cannot change the verbosity now." << std::endl; return; } fitterVerbosity_ = level; } void LauFitter::setFitterMaxPars( const UInt_t maxPars ) { if ( theInstance_ != nullptr ) { std::cerr << "ERROR in LauFitter::setFitterMaxPars : The fitter has already been created, cannot change the maximum number of parameters now." << std::endl; return; } fitterMaxPars_ = maxPars; } LauAbsFitter& LauFitter::fitter() { // Returns a reference to a singleton LauAbsFitter object. // Creates the object the first time it is called. if ( theInstance_ == nullptr ) { if ( fitterType_ == Type::Minuit ) { // NB cannot use std::make_unique here since the LauMinuit constructor is private theInstance_.reset( new LauMinuit( fitterMaxPars_, fitterVerbosity_ ) ); } } return *theInstance_; } void LauFitter::destroyFitter() { // destroy the current fitter theInstance_.reset(); // restore the default settings fitterType_ = LauFitter::Type::Minuit; fitterVerbosity_ = LauOutputLevel::Standard; fitterMaxPars_ = 100; } diff --git a/src/LauFlatNR.cc b/src/LauFlatNR.cc index 41ea817..24d6e33 100644 --- a/src/LauFlatNR.cc +++ b/src/LauFlatNR.cc @@ -1,61 +1,60 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatNR.cc \brief File containing implementation of LauFlatNR class. */ #include #include "LauKinematics.hh" #include "LauFlatNR.hh" -ClassImp(LauFlatNR) LauFlatNR::LauFlatNR(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauFlatNR::~LauFlatNR() { } void LauFlatNR::initialise() { } LauComplex LauFlatNR::amplitude(const LauKinematics* /*kinematics*/) { // return the uniform amplitude return LauComplex(1.0, 0.0); } LauComplex LauFlatNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauFlatNR::resAmp : This method shouldn't get called." << std::endl; std::cerr << " Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } diff --git a/src/LauFlatteRes.cc b/src/LauFlatteRes.cc index 80c4e54..0feed54 100644 --- a/src/LauFlatteRes.cc +++ b/src/LauFlatteRes.cc @@ -1,369 +1,368 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFlatteRes.cc \brief File containing implementation of LauFlatteRes class. */ #include #include "LauConstants.hh" #include "LauFlatteRes.hh" #include "LauResonanceInfo.hh" #include "TSystem.h" -ClassImp(LauFlatteRes) LauFlatteRes::LauFlatteRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), g1_(0), g2_(0), mSumSq0_(0.0), mSumSq1_(0.0), mSumSq2_(0.0), mSumSq3_(0.0), useAdlerTerm_(kFALSE), sA_(0.0), absorbM0_(kFALSE) { Double_t resMass(0.0); Double_t g1Val(0.0); Double_t g2Val(0.0); const TString& resName = this->getResonanceName(); if ( resName == "f_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mPi0 + LauConstants::mPi0) * (LauConstants::mPi0 + LauConstants::mPi0); mSumSq1_ = (LauConstants::mPi + LauConstants::mPi) * (LauConstants::mPi + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mK) * (LauConstants::mK + LauConstants::mK); mSumSq3_ = (LauConstants::mK0 + LauConstants::mK0) * (LauConstants::mK0 + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Lett. B 607, 243 (2005) resMass = 0.965; // 0.965 +/- 0.008 +/- 0.006 GeV/c^2 g1Val = 0.165; // 0.165 +/- 0.010 +/- 0.015 GeV^2 g2Val = 4.21*g1Val; // 4.21 +/- 0.25 +/- 0.21 useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } else if ( resName == "K*0_0(1430)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mK0 + LauConstants::mPi0) * (LauConstants::mK0 + LauConstants::mPi0); mSumSq1_ = (LauConstants::mK + LauConstants::mPi) * (LauConstants::mK + LauConstants::mPi); mSumSq2_ = (LauConstants::mK0 + LauConstants::mEtaPrime) * (LauConstants::mK0 + LauConstants::mEtaPrime); mSumSq3_ = (LauConstants::mK0 + LauConstants::mEtaPrime) * (LauConstants::mK0 + LauConstants::mEtaPrime); // Set values of mass and coupling constants from: // Phys. Lett. B 572, 1 (2003) resMass = 1.513; // GeV/c^2 g1Val = 0.304; // GeV g2Val = 0.380; // GeV useAdlerTerm_ = kTRUE; sA_ = 0.234; absorbM0_ = kFALSE; } else if ( resName == "K*+_0(1430)" || resName == "K*-_0(1430)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mK + LauConstants::mPi0) * (LauConstants::mK + LauConstants::mPi0); mSumSq1_ = (LauConstants::mK0 + LauConstants::mPi) * (LauConstants::mK0 + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mEtaPrime) * (LauConstants::mK + LauConstants::mEtaPrime); mSumSq3_ = (LauConstants::mK + LauConstants::mEtaPrime) * (LauConstants::mK + LauConstants::mEtaPrime); // Set values of mass and coupling constants from: // Phys. Lett. B 572, 1 (2003) resMass = 1.513; // GeV/c^2 g1Val = 0.304; // GeV g2Val = 0.380; // GeV useAdlerTerm_ = kTRUE; sA_ = 0.234; absorbM0_ = kFALSE; } else if ( resName == "a0_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mEta + LauConstants::mPi0) * (LauConstants::mEta + LauConstants::mPi0); mSumSq1_ = (LauConstants::mEta + LauConstants::mPi0) * (LauConstants::mEta + LauConstants::mPi0); mSumSq2_ = (LauConstants::mK + LauConstants::mK) * (LauConstants::mK + LauConstants::mK); mSumSq3_ = (LauConstants::mK0 + LauConstants::mK0) * (LauConstants::mK0 + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Rev. D 57, 3860 (1998) resMass = 0.982; // 0.982 +/- 0.003 GeV/c^2 g1Val = 0.324*0.324; // 0.324 +/- 0.015 GeV (NB this value needs to be squared since the paper uses g_1^2 and g_2^2) g2Val = 1.03*g1Val; // 1.03 +/- 0.14 (NB this is indeed the ratio of what the paper refers to as g_2^2 and g_1^2, so can be used unchanged here) useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } else if ( resName == "a+_0(980)" || resName == "a-_0(980)" ) { // Set the mass threshold values mSumSq0_ = (LauConstants::mEta + LauConstants::mPi) * (LauConstants::mEta + LauConstants::mPi); mSumSq1_ = (LauConstants::mEta + LauConstants::mPi) * (LauConstants::mEta + LauConstants::mPi); mSumSq2_ = (LauConstants::mK + LauConstants::mK0) * (LauConstants::mK + LauConstants::mK0); mSumSq3_ = (LauConstants::mK + LauConstants::mK0) * (LauConstants::mK + LauConstants::mK0); // Set values of mass and coupling constants from: // Phys. Rev. D 57, 3860 (1998) resMass = 0.982; // 0.982 +/- 0.003 GeV/c^2 g1Val = 0.324*0.324; // 0.324 +/- 0.015 GeV (NB this value needs to be squared since the paper uses g_1^2 and g_2^2) g2Val = 1.03*g1Val; // 1.03 +/- 0.14 (NB this is indeed the ratio of what the paper refers to as g_2^2 and g_1^2, so can be used unchanged here) useAdlerTerm_ = kFALSE; sA_ = 0.0; absorbM0_ = kTRUE; } const TString couplingUnits = (absorbM0_) ? "GeV^2" : "GeV"; std::cout << "INFO in LauFlatteRes::LauFlatteRes : Setting default parameters for " << resName << ":\n"; std::cout << " : mass = " << resMass << " GeV/c^2\n"; std::cout << " : g1 = " << g1Val << " " << couplingUnits << "\n"; std::cout << " : g2 = " << g2Val << " " << couplingUnits << "\n"; if ( absorbM0_ ) { std::cout << " : Will absorb m0 into couplings\n"; } else { std::cout << " : Will not absorb m0 into couplings\n"; } if ( useAdlerTerm_ ) { std::cout << " : Will use Adler zero term\n"; std::cout << " : sA = " << sA_ << " GeV^2/c^4\n"; } else { std::cout << " : Will not use Adler zero term\n"; } // Set the mass value LauParameter* massPar = this->getMassPar(); if ( massPar ) { massPar->valueAndRange(resMass,0.0,3.0*resMass); massPar->initValue(resMass); massPar->genValue(resMass); } else { std::cerr << "ERROR in LauFlatteRes::LauFlatteRes : Unable to retrieve mass parameter" << std::endl; } // Create the parameters for the coupling constants const TString& parNameBase = this->getSanitisedName(); TString g1Name(parNameBase); g1Name += "_g1"; g1_ = resInfo->getExtraParameter( g1Name ); if ( g1_ == 0 ) { g1_ = new LauParameter( g1Name, g1Val, 0.0, 10.0, kTRUE ); g1_->secondStage(kTRUE); resInfo->addExtraParameter( g1_ ); } TString g2Name(parNameBase); g2Name += "_g2"; g2_ = resInfo->getExtraParameter( g2Name ); if ( g2_ == 0 ) { g2_ = new LauParameter( g2Name, g2Val, 0.0, 10.0, kTRUE ); g2_->secondStage(kTRUE); resInfo->addExtraParameter( g2_ ); } } LauFlatteRes::~LauFlatteRes() { } void LauFlatteRes::initialise() { const TString& resName = this->getResonanceName(); if ( resName != "f_0(980)" && resName != "K*0_0(1430)" && resName != "K*+_0(1430)" && resName != "K*-_0(1430)" && resName != "a0_0(980)" && resName != "a+_0(980)" && resName != "a-_0(980)" ) { std::cerr << "ERROR in LauFlatteRes::initialise : Unexpected resonance name \"" << resName << "\" for Flatte shape." << std::endl; gSystem->Exit(EXIT_FAILURE); } Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauFlatteRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Flatte amplitude is only defined for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } LauComplex LauFlatteRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Flatte distribution // given the invariant mass and cos(helicity) values. const Double_t resMass = this->getMass(); const Double_t resMassSq = resMass*resMass; const Double_t s = mass*mass; // Invariant mass squared combination for the system const Double_t g1Val = this->getg1Parameter(); const Double_t g2Val = this->getg2Parameter(); Double_t dMSq = resMassSq - s; Double_t rho1(0.0), rho2(0.0); if (s > mSumSq0_) { rho1 = TMath::Sqrt(1.0 - mSumSq0_/s)/3.0; if (s > mSumSq1_) { rho1 += 2.0*TMath::Sqrt(1.0 - mSumSq1_/s)/3.0; if (s > mSumSq2_) { rho2 = 0.5*TMath::Sqrt(1.0 - mSumSq2_/s); if (s > mSumSq3_) { rho2 += 0.5*TMath::Sqrt(1.0 - mSumSq3_/s); } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator dMSq += g2Val*resMass*0.5*TMath::Sqrt(mSumSq3_/s - 1.0); } } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator rho2 = 0.0; dMSq += g2Val*resMass*(0.5*TMath::Sqrt(mSumSq2_/s - 1.0) + 0.5*TMath::Sqrt(mSumSq3_/s - 1.0)); } } else { // Continue analytically below higher channel thresholds // This contributes to the real part of the amplitude denominator dMSq += g1Val*resMass*2.0*TMath::Sqrt(mSumSq1_/s - 1.0)/3.0; } } Double_t massFactor = 1.0; if ( ! absorbM0_ ) { massFactor = resMass; } if (useAdlerTerm_) { massFactor *= ( s - sA_ ) / ( resMassSq - sA_ ); } const Double_t width1 = g1Val*rho1*massFactor; const Double_t width2 = g2Val*rho2*massFactor; const Double_t widthTerm = width1 + width2; LauComplex resAmplitude(dMSq, widthTerm); const Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauFlatteRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } // NB the width is given in terms of g1 and g2 so the normal width // parameter should be ignored, hence it is not added to the list if ( ! this->fixg1Parameter() ) { this->addFloatingParameter( g1_ ); } if ( ! this->fixg2Parameter() ) { this->addFloatingParameter( g2_ ); } return this->getParameters(); } void LauFlatteRes::setResonanceParameter(const TString& name, const Double_t value) { if (name == "g1") { this->setg1Parameter(value); std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting g1 parameter to " << this->getg1Parameter() << std::endl; } else if (name == "g2") { this->setg2Parameter(value); std::cout << "INFO in LauFlatteRes::setResonanceParameter : Setting g2 parameter to " << this->getg2Parameter() << std::endl; } else { std::cerr << "WARNING in LauFlatteRes::setResonanceParameter : Parameter name \"" << name << "\" not recognised." << std::endl; } } void LauFlatteRes::floatResonanceParameter(const TString& name) { if (name == "g1") { if ( g1_->fixed() ) { g1_->fixed( kFALSE ); this->addFloatingParameter( g1_ ); } else { std::cerr << "WARNING in LauFlatteRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "g2") { if ( g2_->fixed() ) { g2_->fixed( kFALSE ); this->addFloatingParameter( g2_ ); } else { std::cerr << "WARNING in LauFlatteRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauFlatteRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauFlatteRes::getResonanceParameter(const TString& name) { if (name == "g1") { return g1_; } else if (name == "g2") { return g2_; } else { std::cerr << "WARNING in LauFlatteRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauFlatteRes::setg1Parameter(const Double_t g1) { g1_->value( g1 ); g1_->genValue( g1 ); g1_->initValue( g1 ); } void LauFlatteRes::setg2Parameter(const Double_t g2) { g2_->value( g2 ); g2_->genValue( g2 ); g2_->initValue( g2 ); } diff --git a/src/LauFormulaPar.cc b/src/LauFormulaPar.cc index 56dd17d..b0b9b25 100644 --- a/src/LauFormulaPar.cc +++ b/src/LauFormulaPar.cc @@ -1,215 +1,214 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauFormulaPar.cc \brief File containing implementation of LauFormulaPar class. */ #include #include #include #include #include "TRandom.h" #include "TMessage.h" #include "TSystem.h" #include "LauFormulaPar.hh" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauFormulaPar) LauFormulaPar::LauFormulaPar(const TString& forName, const TString& formula, const std::vector& params) : name_(forName), formula_(forName,formula), paramVec_(params), paramArray_(nullptr), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0) { // Check length of vector matches number of parameter in the formula Int_t nPars = paramVec_.size(); if (formula_.GetNpar() != nPars){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Number of parameters in the formula is : "<Exit(EXIT_FAILURE); } if (formula_.GetNdim() != 0){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Given formula of dimension: "<Exit(EXIT_FAILURE); } // Array of input parameters paramArray_ = new Double_t[nPars]; } LauFormulaPar::~LauFormulaPar() { delete[] paramArray_; } LauFormulaPar::LauFormulaPar(const LauFormulaPar& rhs) : LauAbsRValue(rhs), name_(rhs.name_), formula_(rhs.formula_), paramVec_(rhs.paramVec_), paramArray_(nullptr), gaussConstraint_(rhs.gaussConstraint_), constraintTrueMean_(rhs.constraintTrueMean_), constraintMean_(rhs.constraintMean_), constraintWidth_(rhs.constraintWidth_) { // Check length of vector matches number of parameter in the formula Int_t nPars = paramVec_.size(); if (formula_.GetNpar() != nPars){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Number of parameters in the formula is : "<Exit(EXIT_FAILURE); } if (formula_.GetNdim() != 0){ std::cerr<<"ERROR in LauFormulaPar::evaluate : Given formula of dimension: "<Exit(EXIT_FAILURE); } // Array of input parameters paramArray_ = new Double_t[nPars]; } LauFormulaPar& LauFormulaPar::operator=(const LauFormulaPar& rhs) { if ( &rhs != this ) { name_ = rhs.name_; formula_ = rhs.formula_; Int_t nOldPars = paramVec_.size(); Int_t nNewPars = rhs.paramVec_.size(); paramVec_ = rhs.paramVec_; if ( nOldPars != nNewPars ) { delete [] paramArray_; paramArray_ = new Double_t[nNewPars]; } gaussConstraint_ = rhs.gaussConstraint_; constraintTrueMean_ = rhs.constraintTrueMean_; constraintMean_ = rhs.constraintMean_; constraintWidth_ = rhs.constraintWidth_; } return *this; } Double_t LauFormulaPar::value() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; ivalue(); } return formula_.EvalPar(nullptr,paramArray_); } Double_t LauFormulaPar::unblindValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; iunblindValue(); } return formula_.EvalPar(nullptr,paramArray_); } Double_t LauFormulaPar::genValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; igenValue(); } return formula_.EvalPar(nullptr,paramArray_); } Double_t LauFormulaPar::initValue() const { //Assign vector values to array Int_t nPars = paramVec_.size(); for(Int_t i=0; iinitValue(); } return formula_.EvalPar(nullptr,paramArray_); } Bool_t LauFormulaPar::fixed() const { for ( std::vector::const_iterator iter = paramVec_.begin(); iter != paramVec_.end(); ++iter ) { if ( !(*iter)->fixed() ) { return kFALSE; } } return kTRUE; } Bool_t LauFormulaPar::blind() const { for ( std::vector::const_iterator iter = paramVec_.begin(); iter != paramVec_.end(); ++iter ) { if ( (*iter)->blind() ) { return kTRUE; } } return kFALSE; } void LauFormulaPar::addGaussianConstraint(Double_t newGaussMean, Double_t newGaussWidth) { gaussConstraint_ = kTRUE; constraintTrueMean_ = newGaussMean; constraintMean_ = newGaussMean; constraintWidth_ = newGaussWidth; } void LauFormulaPar::removeGaussianConstraint() { gaussConstraint_ = kFALSE; } void LauFormulaPar::generateConstraintMean() { constraintMean_ = LauRandom::randomFun()->Gaus( constraintTrueMean_, constraintWidth_ ); } Double_t LauFormulaPar::constraintPenalty() const { const Double_t val { this->unblindValue() }; const Double_t diff { val - constraintMean_ }; const Double_t term { diff * diff }; return term / ( 2.0 * constraintWidth_ * constraintWidth_ ); } diff --git a/src/LauGaussIncohRes.cc b/src/LauGaussIncohRes.cc index 12229af..3a2a682 100644 --- a/src/LauGaussIncohRes.cc +++ b/src/LauGaussIncohRes.cc @@ -1,99 +1,98 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussIncohRes.cc \brief File containing implementation of LauGaussIncohRes class. */ #include #include "LauConstants.hh" #include "LauGaussIncohRes.hh" #include "LauKinematics.hh" -ClassImp(LauGaussIncohRes) LauGaussIncohRes::LauGaussIncohRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsIncohRes(resInfo, resPairAmpInt, daughters) { } LauGaussIncohRes::~LauGaussIncohRes() { } void LauGaussIncohRes::initialise() { } Double_t LauGaussIncohRes::intensityFactor(const LauKinematics* kinematics) { Int_t pair = this->getPairInt(); Double_t mass(0.); switch(pair) { case 1: mass = kinematics->getm23(); break; case 2: mass = kinematics->getm13(); break; case 3: mass = kinematics->getm12(); break; default: std::cerr << "ERROR in LauGaussIncohRes::intensityFactor : Incorrect daughter pair defined." << std::endl; std::cerr << " Returning zero intensity." << std::endl; return 0.; } Double_t m0 = this->getMass(); Double_t G0 = this->getWidth(); if(G0==0) { std::cerr << "ERROR in LauGaussIncohRes::intensityFactor : Gaussian width cannot be zero." << std::endl; std::cerr << " Returning zero intensity." << std::endl; return 0.; } Double_t exponent = -0.5 * ( mass - m0 ) * (mass - m0 ) / (G0*G0); Double_t intensity = TMath::Exp(exponent); return intensity; } const std::vector& LauGaussIncohRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauGaussPdf.cc b/src/LauGaussPdf.cc index 0c519bc..f0237d0 100644 --- a/src/LauGaussPdf.cc +++ b/src/LauGaussPdf.cc @@ -1,146 +1,145 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGaussPdf.cc \brief File containing implementation of LauGaussPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauGaussPdf.hh" -ClassImp(LauGaussPdf) LauGaussPdf::LauGaussPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0) { // Constructor for the Gaussian PDF. // // The parameters in params are the mean and the sigma (half the width) of the gaussian. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); if ((this->nParameters() != 2) || (mean_ == 0) || (sigma_ == 0)) { cerr<<"ERROR in LauGaussPdf constructor: LauGaussPdf requires 2 parameters: \"mean\" and \"sigma\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauGaussPdf::~LauGaussPdf() { // Destructor } void LauGaussPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); // Calculate the value of the Gaussian for the given value of the abscissa. Double_t arg = abscissa - mean; Double_t exponent(0.0); if (TMath::Abs(sigma) > 1e-10) { exponent = -0.5*arg*arg/(sigma*sigma); } Double_t value = TMath::Exp(exponent); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauGaussPdf::calcNorm() { // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); // Calculate the normalisation of the gaussian and cache it. Double_t scale = LauConstants::root2*sigma; Double_t norm(0.0); if (TMath::Abs(sigma) > 1e-10) { norm = LauConstants::rootPiBy2*sigma*(TMath::Erf((this->getMaxAbscissa() - mean)/scale) - TMath::Erf((this->getMinAbscissa() - mean)/scale)); } this->setNorm(norm); } void LauGaussPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Gaussian function. if (mean>this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } else if (meangetMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauGenNtuple.cc b/src/LauGenNtuple.cc index a67c704..8686e05 100644 --- a/src/LauGenNtuple.cc +++ b/src/LauGenNtuple.cc @@ -1,217 +1,216 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGenNtuple.cc \brief File containing implementation of LauGenNtuple class. */ #include using std::cout; using std::cerr; using std::endl; #include "TFile.h" #include "TTree.h" #include "LauGenNtuple.hh" -ClassImp(LauGenNtuple) LauGenNtuple::LauGenNtuple(const TString& rootFileName, const TString& rootTreeName) : rootFileName_(rootFileName), rootTreeName_(rootTreeName), rootFile_(0), rootTree_(0), definedBranches_(kFALSE) { this->createFileAndTree(); } LauGenNtuple::~LauGenNtuple() { // seems that closing the file deletes the tree // so only delete if the file is still open for some reason if (rootFile_ && rootFile_->IsOpen()) { delete rootTree_; rootTree_ = 0; } delete rootFile_; rootFile_ = 0; } void LauGenNtuple::createFileAndTree() { // first check whether we've already opened up the file or not if (!rootFile_) { // if not, first check the filename and if all ok create the file if (rootFileName_ == "") { cerr<<"ERROR in LauGenNtuple::createFileAndTree : Bad filename supplied, not creating file or tree."<IsZombie() || !rootFile_->IsWritable()) { cerr<<"ERROR in LauGenNtuple::createFileAndTree : Problem opening file \""<cd(); rootTree_ = new TTree(rootTreeName_, rootTreeName_); rootTree_->SetDirectory(rootFile_); this->definedBranches(kFALSE); } } void LauGenNtuple::addIntegerBranch(const TString& name) { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::addIntegerBranch : Already defined branches, can't add further ones."<setIntegerBranchValue(name, 0); } void LauGenNtuple::addDoubleBranch(const TString& name) { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::addDoubleBranch : Already defined branches, can't add further ones."<setDoubleBranchValue(name, 0.0); } void LauGenNtuple::setIntegerBranchValue(const TString& name, Int_t value) { intVars_[name] = value; } void LauGenNtuple::setDoubleBranchValue(const TString& name, Double_t value) { doubleVars_[name] = value; } Int_t LauGenNtuple::getIntegerBranchValue(const TString& name) const { IntVarMap::const_iterator iter = intVars_.find( name ); if ( iter == intVars_.end() ) { cerr<<"ERROR in LauGenNtuple::getIntegerBranchValue : no such branch \""<second; } } Double_t LauGenNtuple::getDoubleBranchValue(const TString& name) const { DoubleVarMap::const_iterator iter = doubleVars_.find( name ); if ( iter == doubleVars_.end() ) { cerr<<"ERROR in LauGenNtuple::getDoubleBranchValue : no such branch \""<second; } } void LauGenNtuple::defineBranches() { if (this->definedBranches()) { cerr<<"ERROR in LauGenNtuple::defineBranches : Already defined branches, not doing it again."<first; Int_t * pointer = &(iter->second); TString thirdPart(name); thirdPart += "/I"; rootTree_->Branch(name, pointer, thirdPart); } for (DoubleVarMap::iterator iter = doubleVars_.begin(); iter != doubleVars_.end(); ++iter) { TString name = iter->first; Double_t * pointer = &(iter->second); TString thirdPart(name); thirdPart += "/D"; rootTree_->Branch(name, pointer, thirdPart); } this->definedBranches(kTRUE); } void LauGenNtuple::fillBranches() { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::fillBranches : Tree not created, cannot fill branches."<definedBranches()) { this->defineBranches(); } rootTree_->Fill(); } void LauGenNtuple::deleteAndRecreateTree() { if (rootTree_) { delete rootTree_; rootTree_ = 0; } this->createFileAndTree(); } Int_t LauGenNtuple::buildIndex(const TString& majorName, const TString& minorName) { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::buildIndex : Tree not created, cannot build index."<BuildIndex(majorName, minorName); } void LauGenNtuple::writeOutGenResults() { // Write out the generated ntuple // Check that the file is open if ( rootFile_ == 0 ) { cerr<<"ERROR in LauGenNtuple::writeOutGenResults : File not opened, can't write anything."<GetCurrentFile(); } rootFile_->cd(); rootTree_->Write("",TObject::kOverwrite); rootFile_->Close(); delete rootFile_; rootFile_ = 0; } void LauGenNtuple::addFriendTree(const TString& rootFileName, const TString& rootTreeName) { if (!rootTree_) { cerr<<"ERROR in LauGenNtuple::addFriendTree : Tree not created, cannot add friend."<AddFriend(rootTreeName,rootFileName); } diff --git a/src/LauGounarisSakuraiRes.cc b/src/LauGounarisSakuraiRes.cc index 1b5d780..5be8bf0 100644 --- a/src/LauGounarisSakuraiRes.cc +++ b/src/LauGounarisSakuraiRes.cc @@ -1,253 +1,252 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauGounarisSakuraiRes.cc \brief File containing implementation of LauGounarisSakuraiRes class. */ #include #include "LauConstants.hh" #include "LauGounarisSakuraiRes.hh" -ClassImp(LauGounarisSakuraiRes) LauGounarisSakuraiRes::LauGounarisSakuraiRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), resMass_(0.0), resMassSq_(0.0), resWidth_(0.0), resRadius_(0.0), parRadius_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), mParentSq_(0.0), mBachSq_(0.0), h0_(0.0), dhdm0_(0.0), d_(0.0), FR0_(1.0) { } LauGounarisSakuraiRes::~LauGounarisSakuraiRes() { } void LauGounarisSakuraiRes::initialise() { // Set-up various constants. This must be called again if the mass/width/spin // of a resonance changes... resMass_ = this->getMass(); resWidth_ = this->getWidth(); resRadius_ = this->getResRadius(); parRadius_ = this->getParRadius(); Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t massBachelor = this->getMassBachelor(); Double_t massParent = this->getMassParent(); // Check that the spin is 1 Int_t resSpin = this->getSpin(); if (resSpin != 1) { std::cerr << "WARNING in LauGounarisSakuraiRes::initialise : Resonance spin is != 1. This lineshape is for the rho(770), setting the spin to 1." << std::endl; this->changeResonance( -1.0, -1.0, 1 ); resSpin = this->getSpin(); } // Create the mass squares, sums, differences etc. resMassSq_ = resMass_*resMass_; mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; mParentSq_ = massParent*massParent; mBachSq_ = massBachelor*massBachelor; // Create an effective resonance pole mass to protect against resonances // that are below threshold Double_t effResMass = resMass_; Double_t effResMassSq = resMassSq_; if ( resMassSq_ - mDaugSumSq_ < 0.0 ) { Double_t minMass = mDaugSum_; Double_t maxMass = massParent - massBachelor; Double_t tanhTerm = std::tanh( (resMass_ - ((minMass + maxMass)/2))/(maxMass-minMass)); effResMass = minMass + (maxMass-minMass)*(1+tanhTerm)/2; effResMassSq = effResMass*effResMass; } // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t term1 = effResMassSq - mDaugSumSq_; Double_t term2 = effResMassSq - mDaugDiffSq_; Double_t term12 = term1*term2; if (term12 > 0.0) { q0_ = TMath::Sqrt(term12)/(2.0*effResMass); } else { q0_ = 0.0; } // Calculate the Blatt-Weisskopf form factor for the case when m = m_0 FR0_ = 1.0; if ( this->getSpin() > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); if ( resBWFactor != nullptr ) { FR0_ = resBWFactor->calcFormFactor(q0_); } } // Calculate the extra things needed by the G-S shape h0_ = 2.0*LauConstants::invPi * q0_/effResMass * TMath::Log((effResMass + 2.0*q0_)/(2.0*LauConstants::mPi)); dhdm0_ = h0_ * (1.0/(8.0*q0_*q0_) - 1.0/(2.0*effResMassSq)) + 1.0/(LauConstants::twoPi*effResMassSq); d_ = 3.0*LauConstants::invPi * LauConstants::mPi*LauConstants::mPi/(q0_*q0_) * TMath::Log((effResMass + 2.0*q0_)/(2.0*LauConstants::mPi)) + effResMass/(LauConstants::twoPi*q0_) - LauConstants::mPi*LauConstants::mPi*effResMass/(LauConstants::pi*q0_*q0_*q0_); } LauComplex LauGounarisSakuraiRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauGounarisSakuraiRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } else if (q0_ < 1e-30) { return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // First, calculate the various form factors. // NB // q is the momentum of either daughter in the resonance rest-frame, // p is the momentum of the bachelor in the resonance rest-frame, // pstar is the momentum of the bachelor in the parent rest-frame. // These quantities have been calculate in LauAbsResonance::amplitude(...) const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); const Double_t resRadius = this->getResRadius(); const Double_t parRadius = this->getParRadius(); // If the mass is floating and its value has changed we need to // recalculate everything that assumes that value // Similarly for the BW radii if ( ( (!this->fixMass()) && resMass != resMass_ ) || ( (!this->fixResRadius()) && resRadius != resRadius_ ) || ( (!this->fixParRadius()) && parRadius != parRadius_ ) ) { this->initialise(); } const Int_t resSpin = this->getSpin(); const Double_t q = this->getQ(); const Double_t p = this->getP(); const Double_t pstar = this->getPstar(); Double_t fFactorR(1.0); Double_t fFactorB(1.0); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); if ( resBWFactor != nullptr ) { fFactorR = resBWFactor->calcFormFactor(q); } const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); if ( parBWFactor != nullptr ) { switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = parBWFactor->calcFormFactor(p); break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = parBWFactor->calcFormFactor(pstar); break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = parBWFactor->calcFormFactor(pstar*covFactor); break; } } } } const Double_t fFactorRRatio = fFactorR/FR0_; const Double_t qRatio = q/q0_; const Double_t qTerm = qRatio*qRatio*qRatio; const Double_t totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio; const Double_t massSq = mass*mass; const Double_t massSqTerm = resMassSq_ - massSq; const Double_t h = 2.0*LauConstants::invPi * q/mass * TMath::Log((mass + 2.0*q)/(2.0*LauConstants::mPi)); const Double_t f = resWidth * resMassSq_/(q0_*q0_*q0_) * (q*q * (h - h0_) + massSqTerm * q0_*q0_ * dhdm0_); // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm + f, resMass*totWidth); // Scale by the denominator factor, as well as the spin term and Blatt-Weisskopf factors Double_t numerFactor = spinTerm*(1.0 + d_ * resWidth/resMass); if (!this->ignoreBarrierScaling()) { numerFactor *= fFactorR * fFactorB; } const Double_t denomFactor = (massSqTerm + f)*(massSqTerm + f) + resMassSq_*totWidth*totWidth; resAmplitude.rescale(numerFactor/denomFactor); return resAmplitude; } const std::vector& LauGounarisSakuraiRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } diff --git a/src/LauIntegrals.cc b/src/LauIntegrals.cc index 6e0f685..05aa3f7 100644 --- a/src/LauIntegrals.cc +++ b/src/LauIntegrals.cc @@ -1,178 +1,177 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIntegrals.cc \brief File containing implementation of LauIntegrals class. */ #include using std::cout; using std::endl; #include "TMath.h" #include "LauConstants.hh" #include "LauIntegrals.hh" -ClassImp(LauIntegrals) LauIntegrals::LauIntegrals(Double_t weightsPrecision) : weightsPrecision_( weightsPrecision ) { } LauIntegrals::~LauIntegrals() { } LauIntegrals::LauIntegrals(const LauIntegrals& rhs) : weightsPrecision_( rhs.weightsPrecision_ ) { } LauIntegrals& LauIntegrals::operator=(const LauIntegrals& rhs) { if ( &rhs != this ) { weightsPrecision_ = rhs.weightsPrecision_; } return *this; } void LauIntegrals::calcGaussLegendreWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights) { // Calculate the Gauss-Legendre weights that will be used for the // simple Gaussian integration method given the number of points abscissas.clear(); weights.clear(); abscissas.resize(numPoints); weights.resize(numPoints); Int_t m = (numPoints+1)/2; Double_t dnumPoints(numPoints); Double_t dnumPointsPlusHalf = static_cast(numPoints + 0.5); Int_t i(0), j(0); Double_t p1(0.0), p2(0.0), p3(0.0), pp(0.0), z(0.0), zSq(0.0), z1(0.0), di(0.0); for (i = 1; i <= m; i++){ di = static_cast(i); z = TMath::Cos(LauConstants::pi*(di - 0.25)/dnumPointsPlusHalf); zSq = z*z; // Starting with the above approximation for the ith root, we enter the // main loop of refinement by Newton's method do{ p1 = 1.0; p2 = 0.0; // Calculate the Legendre polynomial at z - recurrence relation for (j = 1; j <= numPoints; j++){ p3 = p2; p2 = p1; p1 = (( 2.0*j - 1.0) * z * p2 - (j - 1.0)*p3)/static_cast(j); } // p1 = Legendre polynomial. Compute its derivative, pp. pp = dnumPoints * (z*p1 - p2)/(zSq - 1.0); z1 = z; z = z1 - p1/pp; // Newton's method } while (TMath::Abs(z-z1) > weightsPrecision_); // Scale the root to the desired interval // Remember that the vector entries start with 0, hence i-1 (where first i value is 1) abscissas[i-1] = z; abscissas[numPoints-i] = abscissas[i-1]; // Symmetric abscissa weights[i-1] = 2.0/((1.0 - zSq)*pp*pp); weights[numPoints-i] = weights[i-1]; // Symmetric weight } } void LauIntegrals::calcGaussHermiteWeights(const Int_t numPoints, std::vector& abscissas, std::vector& weights) { // Calculate the Gauss-Hermite weights that will be used for the // simple Gaussian integration method for a function weighted by an exp(-x**2) term // These weights are common to all integration intervals - therefore they // should only be calculated once - when the constructor is called, for example. abscissas.clear(); weights.clear(); abscissas.resize(numPoints); weights.resize(numPoints); Int_t m = (numPoints+1)/2; Double_t dnumPoints(numPoints); Int_t i(0), j(0), its(0); Double_t p1(0.0), p2(0.0), p3(0.0), pp(0.0), z(0.0), z1(0.0); Double_t numPointsTerm(2*numPoints+1); // The roots are symmetric about the origin. Therefore, we only need to find half of them // Loop over the desired roots. for (i = 1; i <= m; i++) { if (i == 1) { // Initial guess for largest root z = TMath::Sqrt(numPointsTerm) - 1.85575*TMath::Power(numPointsTerm, -0.16667); } else if (i == 2) { // Initial guess for second largest root z -= 1.14*TMath::Power(dnumPoints, 0.426)/z; } else if (i == 3) { // Initial guess for third largest root z = 1.86*z - 0.86*abscissas[0]; } else if (i == 4) { // Initial guess for fourth largest root z = 1.91*z - 0.91*abscissas[1]; } else { // Initial guess for other roots z = 2.0*z - abscissas[i-3]; } for (its = 1; its <= 10; its++) { p1 = LauConstants::pim4; p2 = 0.0; for (j = 1; j <= numPoints; j++) { Double_t dj(j); p3 = p2; p2 = p1; p1 = z*TMath::Sqrt(2.0/dj)*p2 - TMath::Sqrt((dj-1.0)/dj)*p3; } // p1 is now the desired Hermite polynomial. Compute its derivative, pp pp = TMath::Sqrt(2.0*dnumPoints)*p2; z1 = z; if (pp > 1e-10) {z = z1 - p1/pp;} if (TMath::Abs(z - z1) < weightsPrecision_) break; } // Scale the root to the desired interval // Remember that the vector entries start with 0, hence i-1 (where first i value is 1) abscissas[i-1] = z; abscissas[numPoints-i] = -z; // Symmetric abscissa weights[i-1] = 2.0/(pp*pp); weights[numPoints-i] = weights[i-1]; // Symmetric weight } } diff --git a/src/LauIsobarDynamics.cc b/src/LauIsobarDynamics.cc index b94751d..df75822 100644 --- a/src/LauIsobarDynamics.cc +++ b/src/LauIsobarDynamics.cc @@ -1,2700 +1,2699 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauIsobarDynamics.cc \brief File containing implementation of LauIsobarDynamics class. */ #include #include #include #include #include #include "TFile.h" #include "TRandom.h" #include "TSystem.h" #include "LauAbsEffModel.hh" #include "LauAbsResonance.hh" #include "LauAbsIncohRes.hh" #include "LauBelleNR.hh" #include "LauBelleSymNR.hh" #include "LauCacheData.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauDPPartialIntegralInfo.hh" #include "LauFitDataTree.hh" #include "LauIsobarDynamics.hh" #include "LauKinematics.hh" #include "LauKMatrixProdPole.hh" #include "LauKMatrixProdSVP.hh" #include "LauKMatrixPropagator.hh" #include "LauKMatrixPropFactory.hh" #include "LauNRAmplitude.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" #include "LauRhoOmegaMix.hh" #include "LauASqMaxFinder.hh" -ClassImp(LauIsobarDynamics) // for Kpipi: only one scfFraction 2D histogram is needed LauIsobarDynamics::LauIsobarDynamics(LauDaughters* daughters, LauAbsEffModel* effModel, LauAbsEffModel* scfFractionModel) : daughters_(daughters), kinematics_(daughters_ ? daughters_->getKinematics() : 0), effModel_(effModel), nAmp_(0), nIncohAmp_(0), DPNorm_(0.0), DPRate_("DPRate", 0.0, 0.0, 1000.0), meanDPEff_("meanDPEff", 0.0, 0.0, 1.0), currentEvent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavConjDP_(kFALSE), integralsDone_(kFALSE), normalizationSchemeDone_(kFALSE), forceSymmetriseIntegration_(kFALSE), intFileName_("integ.dat"), m13BinWidth_(0.005), m23BinWidth_(0.005), mPrimeBinWidth_(0.001), thPrimeBinWidth_(0.001), narrowWidth_(0.020), binningFactor_(100.0), m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), tagCat_(-1), eff_(1.0), scfFraction_(0.0), jacobian_(0.0), ASq_(0.0), evtLike_(0.0), iterationsMax_(100000), nSigGenLoop_(0), aSqMaxSet_(1.25), aSqMaxVar_(0.0), flipHelicity_(kTRUE), recalcNormalisation_(kFALSE), calculateRhoOmegaFitFractions_(kFALSE) { if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); fullySymmetricDP_ = daughters->gotFullySymmetricDP(); flavConjDP_ = daughters->gotFlavourConjugateDP(); typDaug_.push_back(daughters->getTypeDaug1()); typDaug_.push_back(daughters->getTypeDaug2()); typDaug_.push_back(daughters->getTypeDaug3()); } if (scfFractionModel != 0) { scfFractionModel_[0] = scfFractionModel; } sigResonances_.clear(); sigIncohResonances_.clear(); kMatrixPropagators_.clear(); kMatrixPropSet_.clear(); extraParameters_.clear(); } // for Kspipi, we need a scfFraction 2D histogram for each tagging category. They are provided by the map. // Also, we need to know the place that the tagging category of the current event occupies in the data structure inputFitTree LauIsobarDynamics::LauIsobarDynamics(LauDaughters* daughters, LauAbsEffModel* effModel, LauTagCatScfFractionModelMap scfFractionModel) : daughters_(daughters), kinematics_(daughters_ ? daughters_->getKinematics() : 0), effModel_(effModel), scfFractionModel_(scfFractionModel), nAmp_(0), nIncohAmp_(0), DPNorm_(0.0), DPRate_("DPRate", 0.0, 0.0, 1000.0), meanDPEff_("meanDPEff", 0.0, 0.0, 1.0), currentEvent_(0), symmetricalDP_(kFALSE), fullySymmetricDP_(kFALSE), flavConjDP_(kFALSE), integralsDone_(kFALSE), normalizationSchemeDone_(kFALSE), forceSymmetriseIntegration_(kFALSE), intFileName_("integ.dat"), m13BinWidth_(0.005), m23BinWidth_(0.005), mPrimeBinWidth_(0.001), thPrimeBinWidth_(0.001), narrowWidth_(0.020), binningFactor_(100.0), m13Sq_(0.0), m23Sq_(0.0), mPrime_(0.0), thPrime_(0.0), tagCat_(-1), eff_(1.0), scfFraction_(0.0), jacobian_(0.0), ASq_(0.0), evtLike_(0.0), iterationsMax_(100000), nSigGenLoop_(0), aSqMaxSet_(1.25), aSqMaxVar_(0.0), flipHelicity_(kTRUE), recalcNormalisation_(kFALSE), calculateRhoOmegaFitFractions_(kFALSE) { // Constructor for the isobar signal model if (daughters != 0) { symmetricalDP_ = daughters->gotSymmetricalDP(); fullySymmetricDP_ = daughters->gotFullySymmetricDP(); flavConjDP_ = daughters->gotFlavourConjugateDP(); typDaug_.push_back(daughters->getTypeDaug1()); typDaug_.push_back(daughters->getTypeDaug2()); typDaug_.push_back(daughters->getTypeDaug3()); } sigResonances_.clear(); sigIncohResonances_.clear(); kMatrixPropagators_.clear(); kMatrixPropSet_.clear(); extraParameters_.clear(); } LauIsobarDynamics::~LauIsobarDynamics() { extraParameters_.clear(); for ( std::vector::iterator iter = data_.begin(); iter != data_.end(); ++iter ) { delete (*iter); } data_.clear(); for (std::vector::iterator it = dpPartialIntegralInfo_.begin(); it != dpPartialIntegralInfo_.end(); ++it) { delete (*it); } dpPartialIntegralInfo_.clear(); } void LauIsobarDynamics::resetNormVectors() { for (UInt_t i = 0; i < nAmp_; i++) { fSqSum_[i] = 0.0; fSqEffSum_[i] = 0.0; fNorm_[i] = 0.0; ff_[i].zero(); for (UInt_t j = 0; j < nAmp_; j++) { fifjEffSum_[i][j].zero(); fifjSum_[i][j].zero(); } } for (UInt_t i = 0; i < nIncohAmp_; i++) { fSqSum_[i+nAmp_] = 0.0; fSqEffSum_[i+nAmp_] = 0.0; fNorm_[i+nAmp_] = 0.0; incohInten_[i] = 0.0; } } void LauIsobarDynamics::recalculateNormalisation() { if ( recalcNormalisation_ == kFALSE ) { return; } // We need to calculate the normalisation constants for the // Dalitz plot generation/fitting. integralsDone_ = kFALSE; this->resetNormVectors(); this->findIntegralsToBeRecalculated(); this->calcDPNormalisation(); integralsDone_ = kTRUE; } void LauIsobarDynamics::findIntegralsToBeRecalculated() { // Loop through the resonance parameters and see which ones have changed // For those that have changed mark the corresponding resonance(s) as needing to be re-evaluated integralsToBeCalculated_.clear(); const UInt_t nResPars = resonancePars_.size(); for ( UInt_t iPar(0); iPar < nResPars; ++iPar ) { const Double_t newValue = resonancePars_[iPar]->value(); if ( newValue != resonanceParValues_[iPar] ) { resonanceParValues_[iPar] = newValue; const std::vector& indices = resonanceParResIndex_[iPar]; std::vector::const_iterator indexIter = indices.begin(); const std::vector::const_iterator indexEnd = indices.end(); for( ; indexIter != indexEnd; ++indexIter) { integralsToBeCalculated_.insert(*indexIter); } } } } void LauIsobarDynamics::collateResonanceParameters() { // Initialise all resonance models resonancePars_.clear(); resonanceParValues_.clear(); resonanceParResIndex_.clear(); std::set uniqueResPars; UInt_t resIndex(0); for ( std::vector::iterator resIter = sigResonances_.begin(); resIter != sigResonances_.end(); ++resIter ) { (*resIter)->initialise(); // Check if this resonance has floating parameters // Append all unique parameters to our list const std::vector& resPars = (*resIter)->getFloatingParameters(); for ( std::vector::const_iterator parIter = resPars.begin(); parIter != resPars.end(); ++parIter ) { if ( uniqueResPars.insert( *parIter ).second ) { // This parameter has not already been added to // the list of unique ones. Add it, its value // and its associated resonance ID to the // appropriate lists. resonancePars_.push_back( *parIter ); resonanceParValues_.push_back( (*parIter)->value() ); std::vector resIndices( 1, resIndex ); resonanceParResIndex_.push_back( resIndices ); } else { // This parameter has already been added to the // list of unique ones. However, we still need // to indicate that this resonance should be // associated with it. std::vector::const_iterator uniqueParIter = resonancePars_.begin(); std::vector >::iterator indicesIter = resonanceParResIndex_.begin(); while( (*uniqueParIter) != (*parIter) ) { ++uniqueParIter; ++indicesIter; } ( *indicesIter ).push_back( resIndex ); } } ++resIndex; } for ( std::vector::iterator resIter = sigIncohResonances_.begin(); resIter != sigIncohResonances_.end(); ++resIter ) { (*resIter)->initialise(); // Check if this resonance has floating parameters // Append all unique parameters to our list const std::vector& resPars = (*resIter)->getFloatingParameters(); for ( std::vector::const_iterator parIter = resPars.begin(); parIter != resPars.end(); ++parIter ) { if ( uniqueResPars.insert( *parIter ).second ) { // This parameter has not already been added to // the list of unique ones. Add it, its value // and its associated resonance ID to the // appropriate lists. resonancePars_.push_back( *parIter ); resonanceParValues_.push_back( (*parIter)->value() ); std::vector resIndices( 1, resIndex ); resonanceParResIndex_.push_back( resIndices ); } else { // This parameter has already been added to the // list of unique ones. However, we still need // to indicate that this resonance should be // associated with it. std::vector::const_iterator uniqueParIter = resonancePars_.begin(); std::vector >::iterator indicesIter = resonanceParResIndex_.begin(); while( (*uniqueParIter) != (*parIter) ) { ++uniqueParIter; ++indicesIter; } ( *indicesIter ).push_back( resIndex ); } } ++resIndex; } } void LauIsobarDynamics::initialise(const std::vector& coeffs) { // Check whether we have a valid set of integration constants for // the normalisation of the signal likelihood function. this->initialiseVectors(); // Mark the DP integrals as undetermined integralsDone_ = kFALSE; this->collateResonanceParameters(); if ( resonancePars_.empty() ) { recalcNormalisation_ = kFALSE; } else { recalcNormalisation_ = kTRUE; } // Print summary of what we have so far to screen this->initSummary(); if ( nAmp_+nIncohAmp_ == 0 ) { std::cout << "INFO in LauIsobarDynamics::initialise : No contributions to DP model, not performing normalisation integrals." << std::endl; } else { // We need to calculate the normalisation constants for the Dalitz plot generation/fitting. std::cout<<"INFO in LauIsobarDynamics::initialise : Starting special run to generate the integrals for normalising the PDF..."<calcDPNormalisation(); // Write the integrals to a file (mainly for debugging purposes) this->writeIntegralsFile(); } integralsDone_ = kTRUE; std::cout << std::setprecision(10); std::cout<<"INFO in LauIsobarDynamics::initialise : Summary of the integrals:"<getResonanceModel(); getChar << resModelInt << " "; } getChar << std::endl; // Write out the track pairings for each resonance. This is specified // by the resPairAmpInt integer in the addResonance function. for (i = 0; i < nAmp_; i++) { getChar << resPairAmp_[i] << " "; } getChar << std::endl; // Write out the fSqSum = |ff|^2, where ff = resAmp() for (i = 0; i < nAmp_; i++) { getChar << fSqSum_[i] << " "; } getChar << std::endl; // Similar to fSqSum, but with the efficiency term included. for (i = 0; i < nAmp_; i++) { getChar << fSqEffSum_[i] << " "; } getChar << std::endl; // Write out the f_i*f_j_conj*eff values = resAmp_i*resAmp_j_conj*eff. // Note that only the top half of the i*j "matrix" is required, as it // is symmetric w.r.t i, j. for (i = 0; i < nAmp_; i++) { for (j = i; j < nAmp_; j++) { getChar << fifjEffSum_[i][j] << " "; } } getChar << std::endl; // Similar to fifjEffSum, but without the efficiency term included. for (i = 0; i < nAmp_; i++) { for (j = i; j < nAmp_; j++) { getChar << fifjSum_[i][j] << " "; } } getChar << std::endl; // Write out number of incoherent resonances in the Dalitz plot model getChar << nIncohAmp_ << std::endl; // Write out the incoherent resonances for (i = 0; i < nIncohAmp_; i++) { getChar << incohResTypAmp_[i] << " "; } getChar << std::endl; // Write out the incoherent resonance model types (BW, RelBW etc...) for (i = 0; i < nIncohAmp_; i++) { LauAbsResonance* theResonance = sigIncohResonances_[i]; Int_t resModelInt = theResonance->getResonanceModel(); getChar << resModelInt << " "; } getChar << std::endl; // Write out the track pairings for each incoherent resonance. This is specified // by the resPairAmpInt integer in the addIncohResonance function. for (i = 0; i < nIncohAmp_; i++) { getChar << incohResPairAmp_[i] << " "; } getChar << std::endl; // Write out the fSqSum = |ff|^2, where |ff|^2 = incohResAmp() for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { getChar << fSqSum_[i] << " "; } getChar << std::endl; // Similar to fSqSum, but with the efficiency term included. for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { getChar << fSqEffSum_[i] << " "; } getChar << std::endl; } LauAbsResonance* LauIsobarDynamics::addResonance(const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory) { // Function to add a resonance in a Dalitz plot. // No check is made w.r.t flavour and charge conservation rules, and so // the user is responsible for checking the internal consistency of // their function statements with these laws. For example, the program // will not prevent the user from asking for a rho resonance in a K-pi // pair or a K* resonance in a pi-pi pair. // However, to assist the user, a summary of the resonant structure requested // by the user is printed before the program runs. It is important to check this // information when you first define your Dalitz plot model before doing // any fitting/generating. // Arguments are: resonance name, integer to specify the resonance track pairing // (1 => m_23, 2 => m_13, 3 => m_12), i.e. the bachelor track number. // The third argument resType specifies whether the resonance is a Breit-Wigner (BW) // Relativistic Breit-Wigner (RelBW) or Flatte distribution (Flatte), for example. if( LauAbsResonance::isIncoherentModel(resType) == true ) { std::cerr<<"ERROR in LauIsobarDynamics::addResonance : Resonance type \""<getCharge(resPairAmpInt) == 0 && daughters_->getChargeParent() == 0 && daughters_->getTypeParent() > 0 ) { if ( ( resPairAmpInt == 1 && TMath::Abs(daughters_->getTypeDaug2()) == TMath::Abs(daughters_->getTypeDaug3()) ) || ( resPairAmpInt == 2 && TMath::Abs(daughters_->getTypeDaug1()) == TMath::Abs(daughters_->getTypeDaug3()) ) || ( resPairAmpInt == 3 && TMath::Abs(daughters_->getTypeDaug1()) == TMath::Abs(daughters_->getTypeDaug2()) ) ) { theResonance->flipHelicity(kTRUE); } } // Set the resonance name and what track is the bachelor TString resonanceName = theResonance->getResonanceName(); resTypAmp_.push_back(resonanceName); // Always force the non-resonant amplitude pair to have resPairAmp = 0 // in case the user chooses the wrong number. if ( resType == LauAbsResonance::FlatNR || resType == LauAbsResonance::NRModel ) { std::cout<<"INFO in LauIsobarDynamics::addResonance : Setting resPairAmp to 0 for "<( resonanceMaker.getResonance(daughters_, resName, resPairAmpInt, resType) ); if (theResonance == 0) { std::cerr<<"ERROR in LauIsobarDynamics::addIncohResonance : Couldn't create the resonance \""<getResonanceName(); incohResTypAmp_.push_back(resonanceName); incohResPairAmp_.push_back(resPairAmpInt); // Increment the number of resonance amplitudes we have so far ++nIncohAmp_; // Finally, add the resonance object to the internal array sigIncohResonances_.push_back(theResonance); std::cout<<"INFO in LauIsobarDynamics::addIncohResonance : Successfully added incoherent resonance. Total number of incoherent resonances so far = "< nChannels) { std::cerr << "ERROR in LauIsobarDynamics::defineKMatrixPropagator. The rowIndex, which is set to " << rowIndex << ", must be between 1 and the number of channels " << nChannels << std::endl; gSystem->Exit(EXIT_FAILURE); } TString propagatorName(propName), parameterFile(paramFileName); LauKMatrixPropagator* thePropagator = LauKMatrixPropFactory::getInstance()->getPropagator(propagatorName, parameterFile, resPairAmpInt, nChannels, nPoles, rowIndex); kMatrixPropagators_[propagatorName] = thePropagator; return thePropagator; } void LauIsobarDynamics::addKMatrixProdPole(const TString& poleName, const TString& propName, Int_t poleIndex, Bool_t useProdAdler) { // Add a K-matrix production pole term, using the K-matrix propagator given by the propName. // Here, poleIndex is the integer specifying the pole number. // First, find the K-matrix propagator. KMPropMap::iterator mapIter = kMatrixPropagators_.find(propName); if (mapIter != kMatrixPropagators_.end()) { LauKMatrixPropagator* thePropagator = mapIter->second; // Make sure the pole index is valid Int_t nPoles = thePropagator->getNPoles(); if (poleIndex < 1 || poleIndex > nPoles) { std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdPole : The pole index "<getResPairAmpInt(); LauAbsResonance* prodPole = new LauKMatrixProdPole(poleName, poleIndex, resPairAmpInt, thePropagator, daughters_, useProdAdler); prodPole->setSpinType( LauAbsResonance::Legendre ); resTypAmp_.push_back(poleName); resPairAmp_.push_back(resPairAmpInt); ++nAmp_; sigResonances_.push_back(prodPole); // Also store the propName-poleName pair for calculating total fit fractions later on // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type) kMatrixPropSet_[poleName] = propName; std::cout<<"INFO in LauIsobarDynamics::addKMatrixProdPole : Successfully added K-matrix production pole term. Total number of resonances so far = "<second; // Make sure the channel index is valid Int_t nChannels = thePropagator->getNChannels(); if (channelIndex < 1 || channelIndex > nChannels) { std::cerr<<"ERROR in LauIsobarDynamics::addKMatrixProdSVP : The channel index "<getResPairAmpInt(); LauAbsResonance* prodSVP = new LauKMatrixProdSVP(SVPName, channelIndex, resPairAmpInt, thePropagator, daughters_, useProdAdler); prodSVP->setSpinType( LauAbsResonance::Legendre ); resTypAmp_.push_back(SVPName); resPairAmp_.push_back(resPairAmpInt); ++nAmp_; sigResonances_.push_back(prodSVP); // Also store the SVPName-propName pair for calculating total fit fractions later on // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type) kMatrixPropSet_[SVPName] = propName; std::cout<<"INFO in LauIsobarDynamics::addKMatrixProdSVP : Successfully added K-matrix production slowly-varying (SVP) term. Total number of resonances so far = "<::const_iterator iter=sigResonances_.begin(); iter!=sigResonances_.end(); ++iter) { theResonance = (*iter); if (theResonance != 0) { const TString& resString = theResonance->getResonanceName(); if (resString == resName) { return index; } } ++index; } for (std::vector::const_iterator iter=sigIncohResonances_.begin(); iter!=sigIncohResonances_.end(); ++iter) { theResonance = (*iter); if (theResonance != 0) { const TString& resString = theResonance->getResonanceName(); if (resString == resName) { return index; } } ++index; } return -1; } Bool_t LauIsobarDynamics::hasResonance(const TString& resName) const { const Int_t index = this->resonanceIndex(resName); if (index < 0) { return kFALSE; } else { return kTRUE; } } const LauAbsResonance* LauIsobarDynamics::getResonance(const UInt_t resIndex) const { if ( resIndex < this->getnCohAmp() ) { return sigResonances_[resIndex]; } else if ( resIndex < this->getnTotAmp() ) { return sigIncohResonances_[ resIndex - nAmp_ ]; } else { std::cerr<<"ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""<getnCohAmp() ) { return sigResonances_[resIndex]; } else if ( resIndex < this->getnTotAmp() ) { return sigIncohResonances_[ resIndex - nAmp_ ]; } else { std::cerr<<"ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""<resonanceIndex( resName ); if ( index < 0 ) { std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""<getResonance( index ); } } const LauAbsResonance* LauIsobarDynamics::findResonance(const TString& resName) const { const Int_t index = this->resonanceIndex( resName ); if ( index < 0 ) { std::cerr<<"ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""<getResonance( index ); } } void LauIsobarDynamics::removeCharge(TString& string) const { Ssiz_t index = string.Index("+"); if (index != -1) { string.Remove(index,1); } index = string.Index("-"); if (index != -1) { string.Remove(index,1); } } void LauIsobarDynamics::calcDPNormalisation() { if (!normalizationSchemeDone_) { this->calcDPNormalisationScheme(); } for (std::vector::iterator it = dpPartialIntegralInfo_.begin(); it != dpPartialIntegralInfo_.end(); ++it) { this->calcDPPartialIntegral( *it ); } for (UInt_t i = 0; i < nAmp_+nIncohAmp_; ++i) { fNorm_[i] = 0.0; if (fSqSum_[i] > 0.0) {fNorm_[i] = TMath::Sqrt(1.0/(fSqSum_[i]));} } } std::vector< std::pair > LauIsobarDynamics::formGapsFromRegions( const std::vector< std::pair >& regions, const Double_t min, const Double_t max ) const { std::vector< std::pair > gaps(regions.size() + 1, std::make_pair(0., 0.)); // Given some narrow resonance regions, find the regions that correspond to the gaps between them gaps[0].first = min; for (UInt_t i = 0; i < regions.size(); ++i) { gaps[i].second = regions[i].first; gaps[i + 1].first = regions[i].second; } gaps[gaps.size() - 1].second = max; return gaps; } void LauIsobarDynamics::cullNullRegions( std::vector& regions ) const { LauDPPartialIntegralInfo* tmp(0); regions.erase( std::remove(regions.begin(), regions.end(), tmp), regions.end() ); } void LauIsobarDynamics::correctDPOverlap( std::vector< std::pair >& regions, const std::vector& binnings ) const { if (regions.empty()) { return; } // If the regions overlap, ensure that the one with the finest binning takes precedence (i.e., extends its full width) for (UInt_t i = 0; i < regions.size() - 1; ++i) { if ( regions[i + 1].first <= regions[i].second ) { if ((binnings[i] < binnings[i + 1])) { regions[i + 1] = std::make_pair(regions[i].second, regions[i + 1].second); } else { regions[i] = std::make_pair(regions[i].first, regions[i + 1].first); } } } } std::vector LauIsobarDynamics::m13IntegrationRegions( const std::vector< std::pair >& m13Regions, const std::vector< std::pair >& m23Regions, const std::vector& m13Binnings, const Double_t precision, const Double_t defaultBinning ) const { // Create integration regions for all narrow resonances in m13 except for the overlaps with narrow resonances in m23 std::vector integrationRegions; const Double_t m23Min = kinematics_->getm23Min(); const Double_t m23Max = kinematics_->getm23Max(); // Loop over narrow resonances in m13 for (UInt_t m13i = 0; m13i < m13Regions.size(); ++m13i) { const Double_t m13Binning = m13Binnings[m13i]; const Double_t resMin13 = m13Regions[m13i].first; const Double_t resMax13 = m13Regions[m13i].second; // Initialise to the full height of the DP in case there are no narrow resonances in m23 Double_t lastResMax23 = m23Min; // Loop over narrow resonances in m23 for (UInt_t m23i = 0; m23i < m23Regions.size(); m23i++) { const Double_t resMin23 = m23Regions[m23i].first; const Double_t resMax23 = m23Regions[m23i].second; // For the first entry, add the area between m23 threshold and this first entry if (m23i == 0) { integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, m23Min, resMin23, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } // For all entries except the last one, add the area between this and the next entry if (m23i != (m23Regions.size() - 1)) { const Double_t nextResMin23 = m23Regions[m23i + 1].first; integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, resMax23, nextResMin23, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } else { lastResMax23 = resMax23; } } // Add the area between the last entry and the maximum m23 (which could be the whole strip if there are no entries in m23Regions) integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, lastResMax23, m23Max, m13Binning, defaultBinning, precision, nAmp_, nIncohAmp_)); } return integrationRegions; } std::vector LauIsobarDynamics::m23IntegrationRegions( const std::vector >& m13Regions, const std::vector >& m23Regions, const std::vector& m13Binnings, const std::vector& m23Binnings, const Double_t precision, const Double_t defaultBinning ) const { // Create integration regions for all narrow resonances in m23 (including the overlap regions with m13 narrow resonances) std::vector integrationRegions; const Double_t m13Min = kinematics_->getm13Min(); const Double_t m13Max = kinematics_->getm13Max(); // Loop over narrow resonances in m23 for (UInt_t m23i = 0; m23i < m23Regions.size(); m23i++) { const Double_t m23Binning = m23Binnings[m23i]; const Double_t resMin23 = m23Regions[m23i].first; const Double_t resMax23 = m23Regions[m23i].second; // Initialise to the full width of the DP in case there are no narrow resonances in m13 Double_t lastResMax13 = m13Min; // Loop over narrow resonances in m13 for (UInt_t m13i = 0; m13i < m13Regions.size(); m13i++){ const Double_t m13Binning = m13Binnings[m23i]; const Double_t resMin13 = m13Regions[m13i].first; const Double_t resMax13 = m13Regions[m13i].second; // Overlap region (only needed in m23) integrationRegions.push_back(this->newDPIntegrationRegion(resMin13, resMax13, resMin23, resMax23, m13Binning, m23Binning, precision, nAmp_, nIncohAmp_)); // For the first entry, add the area between m13 threshold and this first entry if (m13i == 0) { integrationRegions.push_back(this->newDPIntegrationRegion(m13Min, resMin13, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } // For all entries except the last one, add the area between this and the next entry if (m13i != m13Regions.size() - 1) { const Double_t nextResMin13 = m23Regions[m13i + 1].first; integrationRegions.push_back(this->newDPIntegrationRegion(resMax13, nextResMin13, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } else { lastResMax13 = resMax13; } } // Add the area between the last entry and the maximum m13 (which could be the whole strip if there are no entries in m13Regions) integrationRegions.push_back(this->newDPIntegrationRegion(lastResMax13, m13Max, resMin23, resMax23, defaultBinning, m23Binning, precision, nAmp_, nIncohAmp_)); } return integrationRegions; } LauDPPartialIntegralInfo* LauIsobarDynamics::newDPIntegrationRegion( const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp ) const { const UInt_t nm13Points = static_cast((maxm13-minm13)/m13BinWidth); const UInt_t nm23Points = static_cast((maxm23-minm23)/m23BinWidth); // If we would create a region with no interior points, just return a null pointer if (nm13Points == 0 || nm23Points == 0) { return 0; } return new LauDPPartialIntegralInfo(minm13, maxm13, minm23, maxm23, m13BinWidth, m23BinWidth, precision, nAmp, nIncohAmp); } void LauIsobarDynamics::calcDPNormalisationScheme() { if ( ! dpPartialIntegralInfo_.empty() ) { std::cerr << "ERROR in LauIsobarDynamics::calcDPNormalisationScheme : Scheme already stored!" << std::endl; return; } // The precision for the Gauss-Legendre weights const Double_t precision(1e-6); // Get the rectangle that encloses the DP const Double_t minm13 = kinematics_->getm13Min(); const Double_t maxm13 = kinematics_->getm13Max(); const Double_t minm23 = kinematics_->getm23Min(); const Double_t maxm23 = kinematics_->getm23Max(); const Double_t minm12 = kinematics_->getm12Min(); const Double_t maxm12 = kinematics_->getm12Max(); // Find out whether we have narrow resonances in the DP (defined here as width < 20 MeV). std::vector< std::pair > m13NarrowRes; std::vector< std::pair > m23NarrowRes; std::vector< std::pair > m12NarrowRes; // Rho-omega mixing models implicitly contains omega(782) model, but width is of rho(770) - handle as a special case LauResonanceMaker& resonanceMaker = LauResonanceMaker::get(); LauResonanceInfo* omega_info = resonanceMaker.getResInfo("omega(782)"); const Double_t omegaMass = (omega_info!=0) ? omega_info->getMass()->unblindValue() : 0.78265; const Double_t omegaWidth = (omega_info!=0) ? omega_info->getWidth()->unblindValue() : 0.00849; for ( std::vector::const_iterator iter = sigResonances_.begin(); iter != sigResonances_.end(); ++iter ) { LauAbsResonance::LauResonanceModel model = (*iter)->getResonanceModel(); const TString& name = (*iter)->getResonanceName(); Int_t pair = (*iter)->getPairInt(); Double_t mass = (*iter)->getMass(); Double_t width = (*iter)->getWidth(); if ( model == LauAbsResonance::RhoOmegaMix_GS || model == LauAbsResonance::RhoOmegaMix_GS_1 || model == LauAbsResonance::RhoOmegaMix_RBW || model == LauAbsResonance::RhoOmegaMix_RBW_1 ) { mass = omegaMass; width = omegaWidth; } if ( width > narrowWidth_ || width <= 0.0 ) { continue; } std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: " << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair << std::endl; if ( pair == 1 ) { if ( mass < minm23 || mass > maxm23 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m23NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 2 ) { if ( mass < minm13 || mass > maxm13 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m13NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 3 ) { if ( mass < minm12 || mass > maxm12 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m12NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } } } else { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, " << pair << ", for resonance \"" << (*iter)->getResonanceName() << std::endl; } } for ( std::vector::const_iterator iter = sigIncohResonances_.begin(); iter != sigIncohResonances_.end(); ++iter ) { const TString& name = (*iter)->getResonanceName(); Int_t pair = (*iter)->getPairInt(); Double_t mass = (*iter)->getMass(); Double_t width = (*iter)->getWidth(); if ( width > narrowWidth_ || width == 0.0 ) { continue; } std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: " << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair << std::endl; if ( pair == 1 ) { if ( mass < minm23 || mass > maxm23 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m23NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 2 ) { if ( mass < minm13 || mass > maxm13 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m13NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) { m23NarrowRes.push_back( std::make_pair(mass,width) ); } } } else if ( pair == 3 ) { if ( mass < minm12 || mass > maxm12 ){ std::cout << std::string(53, ' ') << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration" << std::endl; } else { m12NarrowRes.push_back( std::make_pair(mass,width) ); if ( fullySymmetricDP_ ) { m13NarrowRes.push_back( std::make_pair(mass,width) ); m12NarrowRes.push_back( std::make_pair(mass,width) ); } } } else { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, " << pair << ", for resonance \"" << (*iter)->getResonanceName() << std::endl; } } // Depending on how many narrow resonances we have and where they are // we adopt different approaches if ( ! m12NarrowRes.empty() ) { // We have at least one narrow resonance in m12 // Switch to using the square DP for the integration // TODO - for the time being just use a single, reasonably fine by default and tunable, grid // - can later consider whether there's a need to split up the mPrime axis into regions around particularly narrow resonances in m12 // - but it seems that this isn't really needed since even the default tune gives a good resolution for most narrow resonances such as phi / chi_c0 std::cout<<"INFO in LauIsobarDynamics::calcDPNormalisationScheme : One or more narrow resonances found in m12, integrating over whole square Dalitz plot with bin widths of "<squareDP() ) { std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : forcing kinematics to calculate the required square DP co-ordinates" << std::endl; kinematics_->squareDP(kTRUE); } dpPartialIntegralInfo_.push_back(new LauDPPartialIntegralInfo(0.0, 1.0, 0.0, 1.0, mPrimeBinWidth_, thPrimeBinWidth_, precision, nAmp_, nIncohAmp_, kTRUE, kinematics_)); } else if (m13NarrowRes.empty() && m23NarrowRes.empty()) { // There are no narrow resonances, so we just do a single grid over the whole DP std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : No narrow resonances found, integrating over whole Dalitz plot..." << std::endl; dpPartialIntegralInfo_.push_back(new LauDPPartialIntegralInfo(minm13, maxm13, minm23, maxm23, m13BinWidth_, m23BinWidth_, precision, nAmp_, nIncohAmp_)); } else { // Get regions in that correspond to narrow resonances in m13 and m23, and correct for overlaps in each dimension (to use the finest binning) // Sort resonances by ascending mass to calculate regions properly std::sort(m13NarrowRes.begin(), m13NarrowRes.end()); std::sort(m23NarrowRes.begin(), m23NarrowRes.end()); // For each narrow resonance in m13, determine the corresponding window and its binning std::vector > m13Regions; std::vector m13Binnings; for ( std::vector >::const_iterator iter = m13NarrowRes.begin(); iter != m13NarrowRes.end(); ++iter ) { Double_t mass = iter->first; Double_t width = iter->second; Double_t regionBegin = mass - 5.0 * width; Double_t regionEnd = mass + 5.0 * width; Double_t binning = width / binningFactor_; // check if we ought to extend the region to the edge of the phase space (in either direction) if ( regionBegin < (minm13+50.0*m13BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = " << mass << " is close to threshold, extending integration region" << std::endl; regionBegin = minm13; } if ( regionEnd > (maxm13-50.0*m13BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = " << mass << " is close to upper edge of phase space, extending integration region" << std::endl; regionEnd = maxm13; } m13Regions.push_back(std::make_pair(regionBegin, regionEnd)); m13Binnings.push_back(binning); } // For each narrow resonance in m23, determine the corresponding window and its binning std::vector > m23Regions; std::vector m23Binnings; for ( std::vector >::const_iterator iter = m23NarrowRes.begin(); iter != m23NarrowRes.end(); ++iter ) { Double_t mass = iter->first; Double_t width = iter->second; Double_t regionBegin = mass - 5.0 * width; Double_t regionEnd = mass + 5.0 * width; Double_t binning = width / binningFactor_; // check if we ought to extend the region to the edge of the phase space (in either direction) if ( regionBegin < (minm23+50.0*m23BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = " << mass << " is close to threshold, extending integration region" << std::endl; regionBegin = minm23; } if ( regionEnd > (maxm23-50.0*m23BinWidth_) ) { std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = " << mass << " is close to upper edge of phase space, extending integration region" << std::endl; regionEnd = maxm23; } m23Regions.push_back(std::make_pair(regionBegin, regionEnd)); m23Binnings.push_back(binning); } // Sort out overlaps between regions in the same mass pairing this->correctDPOverlap(m13Regions, m13Binnings); this->correctDPOverlap(m23Regions, m23Binnings); // Get the narrow resonance regions plus any overlap region std::vector fineScheme13 = this->m13IntegrationRegions(m13Regions, m23Regions, m13Binnings, precision, m13BinWidth_); std::vector fineScheme23 = this->m23IntegrationRegions(m13Regions, m23Regions, m13Binnings, m23Binnings, precision, m23BinWidth_); // Get coarse regions by calculating the gaps between the // narrow resonances and using the same functions to create // the integration grid object for each std::vector< std::pair > coarseRegions = this->formGapsFromRegions(m13Regions, minm13, maxm13); std::vector coarseBinning( fineScheme13.size()+1, m13BinWidth_ ); std::vector coarseScheme = this->m13IntegrationRegions(coarseRegions, m23Regions, coarseBinning, precision, m13BinWidth_); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), fineScheme13.begin(), fineScheme13.end()); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), fineScheme23.begin(), fineScheme23.end()); dpPartialIntegralInfo_.insert(dpPartialIntegralInfo_.end(), coarseScheme.begin(), coarseScheme.end()); // Remove any null pointer entries in the integral list // (that are produced when an integration region with no // interior points is defined) this->cullNullRegions(dpPartialIntegralInfo_); } normalizationSchemeDone_ = kTRUE; } void LauIsobarDynamics::setIntegralBinWidths(const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t mPrimeBinWidth, const Double_t thPrimeBinWidth) { // Set the bin widths for the m13 vs m23 integration grid m13BinWidth_ = m13BinWidth; m23BinWidth_ = m23BinWidth; // Set the bin widths for the m' vs theta' integration grid mPrimeBinWidth_ = mPrimeBinWidth; thPrimeBinWidth_ = thPrimeBinWidth; } void LauIsobarDynamics::calcDPPartialIntegral(LauDPPartialIntegralInfo* intInfo) { // Calculate the integrals for all parts of the amplitude in the given region of the DP const Bool_t squareDP = intInfo->getSquareDP(); const UInt_t nm13Points = intInfo->getnm13Points(); const UInt_t nm23Points = intInfo->getnm23Points(); //Double_t dpArea(0.0); for (UInt_t i = 0; i < nm13Points; ++i) { const Double_t m13 = intInfo->getM13Value(i); const Double_t m13Sq = m13*m13; for (UInt_t j = 0; j < nm23Points; ++j) { const Double_t m23 = intInfo->getM23Value(j); const Double_t m23Sq = m23*m23; const Double_t weight = intInfo->getWeight(i,j); // Calculate the integral contributions for each resonance. // Only points within the DP area contribute. // This also calculates the total DP area as a check. // NB if squareDP is true, m13 and m23 are actually mPrime and thetaPrime Bool_t withinDP = squareDP ? kinematics_->withinSqDPLimits(m13, m23) : kinematics_->withinDPLimits(m13Sq, m23Sq); if (withinDP == kTRUE) { if ( squareDP ) { // NB m13 and m23 are actually mPrime and thetaPrime kinematics_->updateSqDPKinematics(m13, m23); } else { kinematics_->updateKinematics(m13Sq, m23Sq); } this->calculateAmplitudes(intInfo, i, j); this->addGridPointToIntegrals(weight); // Increment total DP area //dpArea += weight; } } // j weights loop } // i weights loop // Print out DP area to check whether we have a sensible output //std::cout<<" : dpArea = "<::const_iterator intEnd = integralsToBeCalculated_.end(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( integralsToBeCalculated_.find(iAmp) != intEnd ) { // Calculate the dynamics for this resonance ff_[iAmp] = this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } else { // Retrieve the cached value of the amplitude ff_[iAmp] = intInfo->getAmplitude( m13Point, m23Point, iAmp ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd ) { // Calculate the dynamics for this resonance incohInten_[iAmp] = this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } else { // Retrieve the cached value of the amplitude incohInten_[iAmp] = intInfo->getIntensity( m13Point, m23Point, iAmp ); } } // If symmetric, do as above with flipped kinematics and add to amplitude // (No need to retrive the cache if this was done in the first case) if ( symmetricalDP_ == kTRUE ) { kinematics_->flipAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } kinematics_->flipAndUpdateKinematics(); } if (fullySymmetricDP_ == kTRUE) { // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate, flip and evaluate kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for (UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance ff_[iAmp] += this->resAmp(iAmp); // Store the new value in the integration info object intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] ); } } for (UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp) { if ( (integralsToBeCalculated_.find(iAmp+nAmp_) != intEnd) && !sigResonances_[iAmp]->preSymmetrised() ) { // Calculate the dynamics for this resonance incohInten_[iAmp] += this->incohResAmp(iAmp); // Store the new value in the integration info object intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] ); } } // rotate and flip to get us back to where we started kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); } // If we haven't cached the data, then we need to find out the efficiency. eff_ = this->retrieveEfficiency(); intInfo->storeEfficiency( m13Point, m23Point, eff_ ); } void LauIsobarDynamics::calculateAmplitudes() { std::set::const_iterator iter = integralsToBeCalculated_.begin(); const std::set::const_iterator intEnd = integralsToBeCalculated_.end(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { // Calculate the dynamics for this resonance if(*iter < nAmp_) { ff_[*iter] = this->resAmp(*iter); } else { incohInten_[*iter-nAmp_] = this->incohResAmp(*iter-nAmp_); } } if ( symmetricalDP_ == kTRUE ) { kinematics_->flipAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { // Calculate the dynamics for this resonance if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } kinematics_->flipAndUpdateKinematics(); } if ( fullySymmetricDP_ == kTRUE ) { // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate, flip and evaluate kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and evaluate kinematics_->rotateAndUpdateKinematics(); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { if(*iter < nAmp_ && !sigResonances_[*iter]->preSymmetrised() ) { ff_[*iter] += this->resAmp(*iter); } else if (*iter >= nAmp_ && !sigResonances_[*iter-nAmp_]->preSymmetrised() ){ incohInten_[*iter-nAmp_] += this->incohResAmp(*iter-nAmp_); } } // rotate and flip to get us back to where we started kinematics_->rotateAndUpdateKinematics(); kinematics_->flipAndUpdateKinematics(); } // If we haven't cached the data, then we need to find out the efficiency. eff_ = this->retrieveEfficiency(); } void LauIsobarDynamics::calcTotalAmp(const Bool_t useEff) { // Reset the total amplitude to zero totAmp_.zero(); // Loop over all signal amplitudes LauComplex ATerm; for (UInt_t i = 0; i < nAmp_; ++i) { // Get the partial complex amplitude - (mag, phase)*(resonance dynamics) ATerm = Amp_[i]*ff_[i]; // Scale this contribution by its relative normalisation w.r.t. the whole dynamics ATerm.rescale(fNorm_[i]); // Add this partial amplitude to the sum totAmp_ += ATerm; } // Loop over amplitudes // |Sum of partial amplitudes|^2 ASq_ = totAmp_.abs2(); for (UInt_t i = 0; i < nIncohAmp_; ++i) { // Get the partial complex amplitude - (mag, phase) ATerm = Amp_[i+nAmp_]; // Scale this contribution by its relative normalisation w.r.t. the whole dynamics ATerm.rescale(fNorm_[i+nAmp_]); // Add this partial amplitude to the sum ASq_ += ATerm.abs2()*incohInten_[i]; } // Apply the efficiency correction for this event. // Multiply the amplitude squared sum by the DP efficiency if ( useEff ) { ASq_ *= eff_; } } void LauIsobarDynamics::addGridPointToIntegrals(const Double_t weight) { // Combine the Gauss-Legendre weight with the efficiency const Double_t effWeight = eff_*weight; LauComplex fifjEffSumTerm; LauComplex fifjSumTerm; // Calculates the half-matrix of amplitude-squared and interference // terms (dynamical part only) // Add the values at this point on the integration grid to the sums // (one weighted only by the integration weights, one also weighted by // the efficiency) for (UInt_t i = 0; i < nAmp_; ++i) { // Add the dynamical amplitude squared for this resonance. Double_t fSqVal = ff_[i].abs2(); fSqSum_[i] += fSqVal*weight; fSqEffSum_[i] += fSqVal*effWeight; for (UInt_t j = i; j < nAmp_; ++j) { fifjEffSumTerm = fifjSumTerm = ff_[i]*ff_[j].conj(); fifjEffSumTerm.rescale(effWeight); fifjEffSum_[i][j] += fifjEffSumTerm; fifjSumTerm.rescale(weight); fifjSum_[i][j] += fifjSumTerm; } } for (UInt_t i = 0; i < nIncohAmp_; ++i) { // Add the dynamical amplitude squared for this resonance. Double_t fSqVal = incohInten_[i]; fSqSum_[i+nAmp_] += fSqVal*weight; fSqEffSum_[i+nAmp_] += fSqVal*effWeight; } } LauComplex LauIsobarDynamics::resAmp(const UInt_t index) { // Routine to calculate the resonance dynamics (amplitude) // using the appropriate Breit-Wigner/Form Factors. LauComplex amp = LauComplex(0.0, 0.0); if ( index >= nAmp_ ) { std::cerr<<"ERROR in LauIsobarDynamics::resAmp : index = "<= nIncohAmp_ ) { std::cerr<<"ERROR in LauIsobarDynamics::setFFTerm : index = "<= nAmp_) { //Set off-diagonal incoherent terms to zero fitFrac_[i][j].value(0.); fitFracEffUnCorr_[i][j].value(0.); continue; } LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; Double_t crossTerm = 2.0*(AmpTerm*fifjSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; fifjTot += crossTerm; Double_t crossEffTerm = 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; fifjEffTot += crossEffTerm; fitFrac_[i][j].value(crossTerm); fitFracEffUnCorr_[i][j].value(crossEffTerm); } } for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { // Calculate the incoherent terms TString name = "A"; name += i; name += "Sq_FitFrac"; fitFrac_[i][i].name(name); name += "EffUnCorr"; fitFracEffUnCorr_[i][i].name(name); Double_t sumTerm = Amp_[i].abs2()*fSqSum_[i]*fNorm_[i]*fNorm_[i]; fifjTot += sumTerm; Double_t sumEffTerm = Amp_[i].abs2()*fSqEffSum_[i]*fNorm_[i]*fNorm_[i]; fifjEffTot += sumEffTerm; fitFrac_[i][i].value(sumTerm); fitFracEffUnCorr_[i][i].value(sumEffTerm); } for (i = nAmp_; i < nAmp_+nIncohAmp_; i++) { for (j = i+1; j < nAmp_+nIncohAmp_; j++) { //Set off-diagonal incoherent terms to zero TString name = "A"; name += i; name += "A"; name += j; name += "_FitFrac"; fitFrac_[i][j].name(name); name += "EffUnCorr"; fitFracEffUnCorr_[i][j].name(name); fitFrac_[i][j].value(0.); fitFracEffUnCorr_[i][j].value(0.); } } if (TMath::Abs(fifjTot) > 1e-10) { meanDPEff_.value(fifjEffTot/fifjTot); if (init) { meanDPEff_.genValue( meanDPEff_.value() ); meanDPEff_.initValue( meanDPEff_.value() ); } } DPRate_.value(fifjTot); if (init) { DPRate_.genValue( DPRate_.value() ); DPRate_.initValue( DPRate_.value() ); } // Now divide the fitFraction sums by the overall integral for (i = 0; i < nAmp_+nIncohAmp_; i++) { for (j = i; j < nAmp_+nIncohAmp_; j++) { // Get the actual fractions by dividing by the total DP rate Double_t fitFracVal = fitFrac_[i][j].value(); fitFracVal /= fifjTot; fitFrac_[i][j].value( fitFracVal ); Double_t fitFracEffUnCorrVal = fitFracEffUnCorr_[i][j].value(); fitFracEffUnCorrVal /= fifjEffTot; fitFracEffUnCorr_[i][j].value( fitFracEffUnCorrVal ); if (init) { fitFrac_[i][j].genValue( fitFrac_[i][j].value() ); fitFrac_[i][j].initValue( fitFrac_[i][j].value() ); fitFracEffUnCorr_[i][j].genValue( fitFracEffUnCorr_[i][j].value() ); fitFracEffUnCorr_[i][j].initValue( fitFracEffUnCorr_[i][j].value() ); } } } // Work out total fit fraction over all K-matrix components (for each propagator) KMPropMap::iterator mapIter; Int_t propInt(0); for (mapIter = kMatrixPropagators_.begin(); mapIter != kMatrixPropagators_.end(); ++mapIter) { LauKMatrixPropagator* thePropagator = mapIter->second; TString propName = thePropagator->getName(); // Now loop over all resonances and find those which are K-matrix components for this propagator Double_t kMatrixTotFitFrac(0.0); for (i = 0; i < nAmp_; i++) { Bool_t gotKMRes1 = this->gotKMatrixMatch(i, propName); if (gotKMRes1 == kFALSE) {continue;} Double_t fifjSumReal = fifjSum_[i][i].re(); Double_t sumTerm = Amp_[i].abs2()*fifjSumReal*fNorm_[i]*fNorm_[i]; //Double_t fifjEffSumReal = fifjEffSum_[i][i].re(); //Double_t sumEffTerm = Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i]; kMatrixTotFitFrac += sumTerm; for (j = i+1; j < nAmp_; j++) { Bool_t gotKMRes2 = this->gotKMatrixMatch(j, propName); if (gotKMRes2 == kFALSE) {continue;} LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; Double_t crossTerm = 2.0*(AmpTerm*fifjSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; //Double_t crossEffTerm = 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; kMatrixTotFitFrac += crossTerm; } } kMatrixTotFitFrac /= fifjTot; TString parName("KMatrixTotFF_"); parName += propInt; extraParameters_[propInt].name( parName ); extraParameters_[propInt].value(kMatrixTotFitFrac); if (init) { extraParameters_[propInt].genValue(kMatrixTotFitFrac); extraParameters_[propInt].initValue(kMatrixTotFitFrac); } std::cout<<"INFO in LauIsobarDynamics::calcExtraInfo : Total K-matrix fit fraction for propagator "<calculateRhoOmegaFitFractions_ && !init) { int omegaID = 0; int storeID = 1; // Check which B flavour (and therefore which rho_COPY we are) by whether the FF is non-zero // Only for CP fit though - for a 'simple' fit this is more complicated if (fitFrac_[omegaID][omegaID].value() < 1E-4) { omegaID = 1; storeID = 0; } // Check this is really the correct model LauRhoOmegaMix * rhomega = dynamic_cast(getResonance(omegaID)); if (rhomega != NULL) { // Bail out std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Calculating omega fit fraction from resonance " << omegaID << std::endl; std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Storing omega fit fraction in resonance " << storeID << std::endl; // Tell the RhoOmegaMix model only to give us the omega amplitude-squared rhomega->setWhichAmpSq(1); // Recalculate the integrals for the omega fit-fraction integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; Double_t fifjSumRealOmega = fifjSum_[omegaID][omegaID].re(); // Recalculate the integrals for the rho fit-fraction rhomega->setWhichAmpSq(2); integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; Double_t fitFracPartRho = Amp_[omegaID].abs2()*fifjSum_[omegaID][omegaID].re(); // Reset the RhoOmegaMix model and the integrals rhomega->setWhichAmpSq(0); integralsDone_ = kFALSE; this->resetNormVectors(); for ( UInt_t k(0); k < nAmp_+nIncohAmp_; ++k ) { integralsToBeCalculated_.insert(k); } this->calcDPNormalisation(); integralsDone_ = kTRUE; // Store the omega fit-fraction in the rho_COPY location (which is otherwise empty) // Store the rho fit-fraction in the rho location (overwriting the combined FF) Double_t omegaFF = fifjSumRealOmega * fitFrac_[omegaID][omegaID].value(); fitFrac_[storeID][storeID].value(omegaFF); fitFrac_[omegaID][omegaID].value(fitFracPartRho * fNorm_[omegaID] * fNorm_[omegaID] / DPRate_.value()); } else { std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : calculateRhoOmegaFitFractions is set, but the RhoOmegaMix model isn't in the right place. Ignoring this option." << std::endl; } } } Bool_t LauIsobarDynamics::gotKMatrixMatch(UInt_t resAmpInt, const TString& propName) const { Bool_t gotMatch(kFALSE); if (resAmpInt >= nAmp_) {return kFALSE;} const LauAbsResonance* theResonance = sigResonances_[resAmpInt]; if (theResonance == 0) {return kFALSE;} Int_t resModelInt = theResonance->getResonanceModel(); if (resModelInt == LauAbsResonance::KMatrix) { TString resName = theResonance->getResonanceName(); KMStringMap::const_iterator kMPropSetIter = kMatrixPropSet_.find(resName); if (kMPropSetIter != kMatrixPropSet_.end()) { TString kmPropString = kMPropSetIter->second; if (kmPropString == propName) {gotMatch = kTRUE;} } } return gotMatch; } Double_t LauIsobarDynamics::calcSigDPNorm() { // Calculate the normalisation for the log-likelihood function. DPNorm_ = 0.0; for (UInt_t i = 0; i < nAmp_; i++) { // fifjEffSum is the contribution from the term involving the resonance // dynamics (f_i for resonance i) and the efficiency term. Double_t fifjEffSumReal = fifjEffSum_[i][i].re(); // We need to normalise this contribution w.r.t. the complete dynamics in the DP. // Hence we scale by the fNorm_i factor (squared), which is calculated by the // initialise() function, when the normalisation integrals are calculated and cached. // We also include the complex amplitude squared to get the total normalisation // contribution from this resonance. DPNorm_ += Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i]; } // We now come to the cross-terms (between resonances i and j) in the normalisation. for (UInt_t i = 0; i < nAmp_; i++) { for (UInt_t j = i+1; j < nAmp_; j++) { LauComplex AmpjConj = Amp_[j].conj(); LauComplex AmpTerm = Amp_[i]*AmpjConj; // Again, fifjEffSum is the contribution from the term involving the resonance // dynamics (f_i*f_j_conjugate) and the efficiency cross term. // Also include the relative normalisation between these two resonances w.r.t. the // total DP dynamical structure (fNorm_i and fNorm_j) and the complex // amplitude squared (mag,phase) part. DPNorm_ += 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j]; } } for (UInt_t i = 0; i < nIncohAmp_; i++) { DPNorm_ += Amp_[i+nAmp_].abs2()*fSqEffSum_[i+nAmp_]*fNorm_[i+nAmp_]*fNorm_[i+nAmp_]; } return DPNorm_; } Bool_t LauIsobarDynamics::generate() { // Routine to generate a signal event according to the Dalitz plot // model we have defined. // We need to make sure to calculate everything for every resonance integralsToBeCalculated_.clear(); for ( UInt_t i{0}; i < nAmp_+nIncohAmp_; ++i ) { integralsToBeCalculated_.insert(i); } if ( aSqMaxAuto_ ) { std::cout<<"INFO in LauIsobarDynamics::generate : Starting auto-location of |A|^2 maximum"<genFlatPhaseSpace(m13Sq, m23Sq); // If we're in a symmetrical DP then we should only generate events in one half // TODO - what do we do for fully symmetric? if ( symmetricalDP_ && !fullySymmetricDP_ && m13Sq > m23Sq ) { Double_t tmpSq = m13Sq; m13Sq = m23Sq; m23Sq = tmpSq; } // Calculate the amplitudes and total amplitude for the given DP point this->calcLikelihoodInfo(m13Sq, m23Sq); // Throw the random number and check it against the ratio of ASq and the accept/reject ceiling const Double_t randNo = LauRandom::randomFun()->Rndm(); if (randNo > ASq_/aSqMaxSet_) { ++nSigGenLoop_; } else { generatedSig = kTRUE; nSigGenLoop_ = 0; // Keep a note of the maximum ASq that we've found if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;} } } // while loop // Check that all is well with the generation Bool_t sigGenOK(kTRUE); if (GenOK != this->checkToyMC(kTRUE,kFALSE)) { sigGenOK = kFALSE; } return sigGenOK; } LauIsobarDynamics::ToyMCStatus LauIsobarDynamics::checkToyMC(Bool_t printErrorMessages, Bool_t printInfoMessages) { // Check whether we have generated the toy MC OK. ToyMCStatus ok(GenOK); if (nSigGenLoop_ >= iterationsMax_) { // Exceeded maximum allowed iterations - the generation is too inefficient if (printErrorMessages) { std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : More than "< 1.01 * aSqMaxVar_ ) { if (printErrorMessages) { std::cerr<<" : |A|^2 maximum was set to "< aSqMaxSet_) { // Found a value of ASq higher than the accept/reject ceiling - the generation is biased if (printErrorMessages) { std::cerr<<"WARNING in LauIsobarDynamics::checkToyMC : |A|^2 maximum was set to "< "<= "<retrievem13Sq(); m23Sq_ = currentEvent_->retrievem23Sq(); mPrime_ = currentEvent_->retrievemPrime(); thPrime_ = currentEvent_->retrievethPrime(); tagCat_ = currentEvent_->retrieveTagCat(); eff_ = currentEvent_->retrieveEff(); scfFraction_ = currentEvent_->retrieveScfFraction(); // These two are necessary, even though the dynamics don't actually use scfFraction_ or jacobian_, jacobian_ = currentEvent_->retrieveJacobian(); // since this is at the heart of the caching mechanism. } void LauIsobarDynamics::calcLikelihoodInfo(const UInt_t iEvt) { // Calculate the likelihood and associated info // for the given event using cached information evtLike_ = 0.0; // retrieve the cached dynamics from the tree: // realAmp, imagAmp for each resonance plus efficiency, scf fraction and jacobian this->setDataEventNo(iEvt); // use realAmp and imagAmp to create the resonance amplitudes const std::vector& realAmp = currentEvent_->retrieveRealAmp(); const std::vector& imagAmp = currentEvent_->retrieveImagAmp(); const std::vector& incohInten = currentEvent_->retrieveIncohIntensities(); for (UInt_t i = 0; i < nAmp_; i++) { this->setFFTerm(i, realAmp[i], imagAmp[i]); } for (UInt_t i = 0; i < nIncohAmp_; i++) { this->setIncohIntenTerm(i, incohInten[i]); } // Update the dynamics - calculates totAmp_ and then ASq_ = totAmp_.abs2() * eff_ // All calculated using cached information on the individual amplitudes and efficiency. this->calcTotalAmp(kTRUE); // Calculate the normalised matrix element squared value if (DPNorm_ > 1e-10) { evtLike_ = ASq_/DPNorm_; } } void LauIsobarDynamics::calcLikelihoodInfo(const Double_t m13Sq, const Double_t m23Sq) { this->calcLikelihoodInfo(m13Sq, m23Sq, -1); } void LauIsobarDynamics::calcLikelihoodInfo(const Double_t m13Sq, const Double_t m23Sq, const Int_t tagCat) { // Calculate the likelihood and associated info // for the given point in the Dalitz plot // Also retrieves the SCF fraction in the bin where the event lies (done // here to cache it along with the the rest of the DP quantities, like eff) // The jacobian for the square DP is calculated here for the same reason. evtLike_ = 0.0; // update the kinematics for the specified DP point kinematics_->updateKinematics(m13Sq, m23Sq); // calculate the jacobian and the scfFraction to cache them later scfFraction_ = this->retrieveScfFraction(tagCat); if (kinematics_->squareDP() == kTRUE) { jacobian_ = kinematics_->calcSqDPJacobian(); } // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() * eff_ this->calcTotalAmp(kTRUE); // Calculate the normalised matrix element squared value if (DPNorm_ > 1e-10) { evtLike_ = ASq_/DPNorm_; } } void LauIsobarDynamics::modifyDataTree() { if ( recalcNormalisation_ == kFALSE ) { return; } const UInt_t nEvents = data_.size(); std::set::const_iterator iter = integralsToBeCalculated_.begin(); const std::set::const_iterator intEnd = integralsToBeCalculated_.end(); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { currentEvent_ = data_[iEvt]; std::vector& realAmp = currentEvent_->retrieveRealAmp(); std::vector& imagAmp = currentEvent_->retrieveImagAmp(); std::vector& incohInten = currentEvent_->retrieveIncohIntensities(); const Double_t m13Sq = currentEvent_->retrievem13Sq(); const Double_t m23Sq = currentEvent_->retrievem23Sq(); const Int_t tagCat = currentEvent_->retrieveTagCat(); this->calcLikelihoodInfo(m13Sq, m23Sq, tagCat); for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter) { const UInt_t i = *iter; if(*iter < nAmp_) { realAmp[i] = ff_[i].re(); imagAmp[i] = ff_[i].im(); } else { incohInten[i-nAmp_] = incohInten_[i-nAmp_]; } } } } void LauIsobarDynamics::fillDataTree(const LauFitDataTree& inputFitTree) { // In LauFitDataTree, the first two variables should always be m13^2 and m23^2. // Other variables follow thus: charge/flavour tag prob, etc. // Since this is the first caching, we need to make sure to calculate everything for every resonance integralsToBeCalculated_.clear(); for ( UInt_t i(0); i < nAmp_+nIncohAmp_; ++i ) { integralsToBeCalculated_.insert(i); } UInt_t nBranches = inputFitTree.nBranches(); if (nBranches < 2) { std::cerr<<"ERROR in LauIsobarDynamics::fillDataTree : Expecting at least 2 variables " <<"in input data tree, but there are "<Exit(EXIT_FAILURE); } // Data structure that will cache the variables required to // calculate the signal likelihood for this experiment for ( std::vector::iterator iter = data_.begin(); iter != data_.end(); ++iter ) { delete (*iter); } data_.clear(); Double_t m13Sq(0.0), m23Sq(0.0); Double_t mPrime(0.0), thPrime(0.0); Int_t tagCat(-1); std::vector realAmp(nAmp_), imagAmp(nAmp_); Double_t eff(0.0), scfFraction(0.0), jacobian(0.0); UInt_t nEvents = inputFitTree.nEvents() + inputFitTree.nFakeEvents(); data_.reserve(nEvents); for (UInt_t iEvt = 0; iEvt < nEvents; ++iEvt) { const LauFitData& dataValues = inputFitTree.getData(iEvt); LauFitData::const_iterator iter = dataValues.find("m13Sq"); m13Sq = iter->second; iter = dataValues.find("m23Sq"); m23Sq = iter->second; // is there more than one tagging category? // if so then we need to know the category from the data if (scfFractionModel_.size()>1) { iter = dataValues.find("tagCat"); tagCat = static_cast(iter->second); } // calculates the amplitudes and total amplitude for the given DP point // tagging category not needed by dynamics, but to find out the scfFraction this->calcLikelihoodInfo(m13Sq, m23Sq, tagCat); // extract the real and imaginary parts of the ff_ terms for storage for (UInt_t i = 0; i < nAmp_; i++) { realAmp[i] = ff_[i].re(); imagAmp[i] = ff_[i].im(); } if ( kinematics_->squareDP() ) { mPrime = kinematics_->getmPrime(); thPrime = kinematics_->getThetaPrime(); } eff = this->getEvtEff(); scfFraction = this->getEvtScfFraction(); jacobian = this->getEvtJacobian(); // store the data for each event in the list data_.push_back( new LauCacheData() ); data_[iEvt]->storem13Sq(m13Sq); data_[iEvt]->storem23Sq(m23Sq); data_[iEvt]->storemPrime(mPrime); data_[iEvt]->storethPrime(thPrime); data_[iEvt]->storeTagCat(tagCat); data_[iEvt]->storeEff(eff); data_[iEvt]->storeScfFraction(scfFraction); data_[iEvt]->storeJacobian(jacobian); data_[iEvt]->storeRealAmp(realAmp); data_[iEvt]->storeImagAmp(imagAmp); data_[iEvt]->storeIncohIntensities(incohInten_); } } Bool_t LauIsobarDynamics::gotReweightedEvent() { // Select the event (kinematics_) using an accept/reject method based on the // ratio of the current value of ASq to the maximal value. Bool_t accepted(kFALSE); // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!) this->calcTotalAmp(kFALSE); // Compare the ASq value with the maximal value (set by the user) if (LauRandom::randomFun()->Rndm() < ASq_/aSqMaxSet_) { accepted = kTRUE; } if (ASq_ > aSqMaxVar_) {aSqMaxVar_ = ASq_;} return accepted; } Double_t LauIsobarDynamics::getEventWeight() { // calculate the ff_ terms and retrieves eff_ from the efficiency model this->calculateAmplitudes(); // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!) this->calcTotalAmp(kFALSE); // return the event weight = the value of the squared amplitude return ASq_; } void LauIsobarDynamics::updateCoeffs(const std::vector& coeffs) { // Check that the number of coeffs is correct if (coeffs.size() != this->getnTotAmp()) { std::cerr << "ERROR in LauIsobarDynamics::updateCoeffs : Expected " << this->getnTotAmp() << " but got " << coeffs.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } // Now check if the coeffs have changed Bool_t changed = (Amp_ != coeffs); if (changed) { // Copy the coeffs Amp_ = coeffs; } // TODO should perhaps keep track of whether the resonance parameters have changed here and if none of those and none of the coeffs have changed then we don't need to update the norm // Update the total normalisation for the signal likelihood this->calcSigDPNorm(); } TString LauIsobarDynamics::getConjResName(const TString& resName) const { // Get the name of the charge conjugate resonance TString conjName(resName); Ssiz_t index1 = resName.Index("+"); Ssiz_t index2 = resName.Index("-"); if (index1 != -1) { conjName.Replace(index1, 1, "-"); } else if (index2 != -1) { conjName.Replace(index2, 1, "+"); } return conjName; } Double_t LauIsobarDynamics::retrieveEfficiency() { Double_t eff(1.0); if (effModel_ != 0) { eff = effModel_->calcEfficiency(kinematics_); } return eff; } Double_t LauIsobarDynamics::retrieveScfFraction(Int_t tagCat) { Double_t scfFraction(0.0); // scf model and eff model are exactly the same, functionally // so we use an instance of LauAbsEffModel, and the method // calcEfficiency actually calculates the scf fraction if (tagCat == -1) { if (!scfFractionModel_.empty()) { scfFraction = scfFractionModel_[0]->calcEfficiency(kinematics_); } } else { scfFraction = scfFractionModel_[tagCat]->calcEfficiency(kinematics_); } return scfFraction; } diff --git a/src/LauKMatrixProdPole.cc b/src/LauKMatrixProdPole.cc index 266ff16..2d62cef 100644 --- a/src/LauKMatrixProdPole.cc +++ b/src/LauKMatrixProdPole.cc @@ -1,168 +1,167 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdPole.cc \brief File containing implementation of LauKMatrixProdPole class. */ #include "LauKMatrixProdPole.hh" #include "LauKMatrixPropagator.hh" #include "LauResonanceMaker.hh" #include -ClassImp(LauKMatrixProdPole) LauKMatrixProdPole::LauKMatrixProdPole( const TString& poleName, Int_t poleIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler) : LauAbsResonance( poleName, resPairAmpInt, daughters, propagator->getL(propagator->getIndex()) ), thePropagator_(propagator), poleIndex_(poleIndex - 1), // poleIndex goes from 1 to nPoles useProdAdler_(useProdAdler) { if (useProdAdler_) { std::cout <<"Creating K matrix production pole "<setBarrierRadii( nullptr,LauResonanceMaker::get().getParentBWFactor( propagator->getL(propagator->getIndex()), LauBlattWeisskopfFactor::BWBarrier ) ); } LauKMatrixProdPole::~LauKMatrixProdPole() { } LauComplex LauKMatrixProdPole::resAmp(const Double_t mass, const Double_t spinTerm) { // Calculate the amplitude for the K-matrix production pole. LauComplex amp(0.0, 0.0); if (thePropagator_ == 0) { std::cerr << "ERROR in LauKMatrixProdPole::amplitude : The propagator is null" << std::endl; return amp; } // Get barrier factors ('resonance' factor is already accounted for internally via propagator 'Gamma' matrix) Double_t fFactorB(1.0); const Int_t resSpin = this->getSpin(); const Double_t pstar = this->getPstar(); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); if ( parBWFactor != nullptr ) { switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = parBWFactor->calcFormFactor(this->getP()); break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = parBWFactor->calcFormFactor(pstar); break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = parBWFactor->calcFormFactor(pstar*covFactor); break; } } } } // Make sure the K-matrix propagator is up-to-date for // the given centre-of-mass squared value ("s") thePropagator_->updatePropagator(mass*mass); // Sum the pole denominator terms over all channels j, multiplying by // the propagator terms. Note that we do not sum over poles, since we // only want one of the production pole terms. Int_t nChannels = thePropagator_->getNChannels(); Int_t jChannel; for (jChannel = 0; jChannel < nChannels; jChannel++) { Double_t gj = thePropagator_->getCouplingConstant(poleIndex_, jChannel); LauComplex prodTerm = thePropagator_->getPropTerm(jChannel); prodTerm.rescale(gj); amp += prodTerm; } Double_t poleDenom = thePropagator_->getPoleDenomTerm(poleIndex_); // Include Adler zero factor if requested Double_t adlerZero(1.0); if (useProdAdler_) {adlerZero = thePropagator_->getAdlerZero();} amp.rescale(poleDenom*adlerZero); // Scale by the spin term Double_t scale = spinTerm; // Include Blatt-Weisskopf barrier factor for parent scale *= fFactorB; amp.rescale(scale); return amp; } const std::vector& LauKMatrixProdPole::getFloatingParameters() { this->clearFloatingParameters(); Int_t nChannels = thePropagator_->getNChannels(); for (int jChannel = 0 ; jChannel < nChannels ; jChannel++) { LauParameter& par_gj_ = thePropagator_->getCouplingParameter(poleIndex_, jChannel); if ( !par_gj_.fixed() ) { this->addFloatingParameter( &par_gj_ ); } } LauParameter& par_polemasssq_ = thePropagator_->getPoleMassSqParameter(poleIndex_); if ( !par_polemasssq_.fixed() ) { this->addFloatingParameter( &par_polemasssq_ ); } return this->getParameters(); } diff --git a/src/LauKMatrixProdSVP.cc b/src/LauKMatrixProdSVP.cc index 1a1fefa..f034a28 100644 --- a/src/LauKMatrixProdSVP.cc +++ b/src/LauKMatrixProdSVP.cc @@ -1,177 +1,176 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixProdSVP.cc \brief File containing implementation of LauKMatrixProdSVP class. */ #include "LauKMatrixProdSVP.hh" #include "LauKMatrixPropagator.hh" #include -ClassImp(LauKMatrixProdSVP) LauKMatrixProdSVP::LauKMatrixProdSVP( const TString& SVPName, Int_t channelIndex, Int_t resPairAmpInt, LauKMatrixPropagator* propagator, const LauDaughters* daughters, Bool_t useProdAdler) : LauAbsResonance( SVPName, resPairAmpInt, daughters, propagator->getL(propagator->getIndex()) ), thePropagator_(propagator), channelIndex_(channelIndex - 1), // channelIndex goes from 1 to nChannels. useProdAdler_(useProdAdler) { // Constructor if (useProdAdler_) { std::cout <<"Creating K matrix production SVP "<getSpin(); const Double_t pstar = this->getPstar(); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); if ( parBWFactor != nullptr ) { switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = parBWFactor->calcFormFactor(this->getP()); break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = parBWFactor->calcFormFactor(pstar); break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = parBWFactor->calcFormFactor(pstar*covFactor); break; } } } } thePropagator_->updatePropagator(mass*mass); Double_t SVPTerm = thePropagator_->getProdSVPTerm(); amp = thePropagator_->getPropTerm(channelIndex_); // Include Adler zero factor if requested Double_t adlerZero(1.0); if (useProdAdler_) {adlerZero = thePropagator_->getAdlerZero();} amp.rescale(SVPTerm*adlerZero); // Scale by the spin term Double_t scale = spinTerm; // Include Blatt-Weisskopf barrier factor for parent scale *= fFactorB; amp.rescale(scale); return amp; } const std::vector& LauKMatrixProdSVP::getFloatingParameters() { this->clearFloatingParameters(); Int_t nChannels = thePropagator_->getNChannels(); for (int jChannel = 0 ; jChannel < nChannels ; jChannel++) { LauParameter& par_f_ = thePropagator_->getScatteringParameter(channelIndex_, jChannel); if ( !par_f_.fixed() ) { this->addFloatingParameter( &par_f_ ); } } LauParameter& par_mSq0_ = thePropagator_->getmSq0(); if ( !par_mSq0_.fixed() ) { this->addFloatingParameter( &par_mSq0_ ); } LauParameter& par_s0Scatt_ = thePropagator_->gets0Scatt(); if ( !par_s0Scatt_.fixed() ) { this->addFloatingParameter( &par_s0Scatt_ ); } LauParameter& par_s0Prod_ = thePropagator_->gets0Prod(); if ( !par_s0Prod_.fixed() ) { this->addFloatingParameter( &par_s0Prod_ ); } LauParameter& par_sA_ = thePropagator_->getsA(); if ( !par_sA_.fixed() ) { this->addFloatingParameter( &par_sA_ ); } LauParameter& par_sA0_ = thePropagator_->getsA0(); if ( !par_sA0_.fixed() ) { this->addFloatingParameter( &par_sA0_ ); } return this->getParameters(); } \ No newline at end of file diff --git a/src/LauKMatrixPropFactory.cc b/src/LauKMatrixPropFactory.cc index be6d06f..6189451 100644 --- a/src/LauKMatrixPropFactory.cc +++ b/src/LauKMatrixPropFactory.cc @@ -1,90 +1,89 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropFactory.cc \brief File containing implementation of LauKMatrixPropFactory class. */ // Class for storing K-matrix propagator objects // using the factory method. #include "LauKMatrixPropFactory.hh" #include "LauKMatrixPropagator.hh" #include using std::cout; using std::endl; // the singleton instance LauKMatrixPropFactory* LauKMatrixPropFactory::theFactory_ = 0; -ClassImp(LauKMatrixPropFactory) LauKMatrixPropFactory::LauKMatrixPropFactory() { // Constructor map_.clear(); } LauKMatrixPropFactory::~LauKMatrixPropFactory() { // Destructor KMatrixPropMap::iterator iter; for (iter = map_.begin(); iter != map_.end(); ++iter) { LauKMatrixPropagator* thePropagator = iter->second; delete thePropagator; } map_.clear(); } LauKMatrixPropFactory* LauKMatrixPropFactory::getInstance() { if (theFactory_ == 0) { theFactory_ = new LauKMatrixPropFactory(); } return theFactory_; } LauKMatrixPropagator* LauKMatrixPropFactory::getPropagator(const TString& name, const TString& paramFileName, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex) { LauKMatrixPropagator* thePropagator(0); KMatrixPropMap::iterator iter = map_.find(name); if ( iter != map_.end() ) { // We have already made this propagator thePropagator = iter->second; } else { // The propagator does not exist. Create it and store it in the map. thePropagator = new LauKMatrixPropagator(name, paramFileName, resPairAmpInt, nChannels, nPoles, rowIndex); map_[name] = thePropagator; } return thePropagator; } diff --git a/src/LauKMatrixPropagator.cc b/src/LauKMatrixPropagator.cc index 0955961..a2b2b1c 100644 --- a/src/LauKMatrixPropagator.cc +++ b/src/LauKMatrixPropagator.cc @@ -1,1425 +1,1424 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKMatrixPropagator.cc \brief File containing implementation of LauKMatrixPropagator class. */ #include "LauKMatrixPropagator.hh" #include "LauTextFileParser.hh" #include "LauKinematics.hh" #include "LauComplex.hh" #include "TMath.h" #include "TSystem.h" #include #include #include #include using std::cout; using std::endl; using std::cerr; -ClassImp(LauKMatrixPropagator) LauKMatrixPropagator::LauKMatrixPropagator(const TString& name, const TString& paramFile, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex) : name_(name), paramFileName_(paramFile), resPairAmpInt_(resPairAmpInt), index_(rowIndex - 1), nChannels_(nChannels), nPoles_(nPoles) { // Constructor // Check that the index is OK if (index_ < 0 || index_ >= nChannels_) { std::cerr << "ERROR in LauKMatrixPropagator constructor. The rowIndex, which is set to " << rowIndex << ", must be between 1 and the number of channels " << nChannels_ << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setParameters(paramFile); } LauKMatrixPropagator::~LauKMatrixPropagator() { // Destructor realProp_.Clear(); negImagProp_.Clear(); ScattKMatrix_.Clear(); ReRhoMatrix_.Clear(); ImRhoMatrix_.Clear(); GammaMatrix_.Clear(); ReTMatrix_.Clear(); ImTMatrix_.Clear(); IMatrix_.Clear(); zeroMatrix_.Clear(); } LauComplex LauKMatrixPropagator::getPropTerm(const Int_t channel) const { // Get the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. Double_t realTerm = this->getRealPropTerm(channel); Double_t imagTerm = this->getImagPropTerm(channel); LauComplex propTerm(realTerm, imagTerm); return propTerm; } Double_t LauKMatrixPropagator::getRealPropTerm(const Int_t channel) const { // Get the real part of the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. if (parametersSet_ == kFALSE) {return 0.0;} Double_t propTerm = realProp_[index_][channel]; return propTerm; } Double_t LauKMatrixPropagator::getImagPropTerm(const Int_t channel) const { // Get the imaginary part of the (i,j) = (index_, channel) term of the propagator // matrix. This allows us not to return the full propagator matrix. if (parametersSet_ == kFALSE) {return 0.0;} Double_t imagTerm = -1.0*negImagProp_[index_][channel]; return imagTerm; } void LauKMatrixPropagator::updatePropagator(const Double_t s) { // Calculate the K-matrix propagator for the given s value. // The K-matrix amplitude is given by // T_i = sum_{ij} (I - iK*rho)^-1 * P_j, where P is the production K-matrix. // i = index for the state (e.g. S-wave index = 0). // Here, we only find the (I - iK*rho)^-1 matrix part. // Check if we have almost the same s value as before. If so, don't re-calculate // the propagator nor any of the pole mass summation terms. if (TMath::Abs(s - previousS_) < 1e-6*s) { //cout<<"Already got propagator for s = "<calcPoleDenomVect(s); this->updateAdlerZeroFactor(s); // Calculate the scattering K-matrix (real and symmetric) this->calcScattKMatrix(s); // Calculate the phase space density matrix, which is diagonal, but can be complex // if the quantity s is below various threshold values (analytic continuation). this->calcRhoMatrix(s); // Calculate the angular momentum barrier matrix, which is real and diagonal this->calcGammaMatrix(s); // Calculate K*rho*(gamma^2) (real and imaginary parts, since rho can be complex) TMatrixD GammaMatrixSq = (GammaMatrix_*GammaMatrix_); TMatrixD K_realRhoGammaSq(ScattKMatrix_); K_realRhoGammaSq *= ReRhoMatrix_; K_realRhoGammaSq *= GammaMatrixSq; TMatrixD K_imagRhoGammaSq(ScattKMatrix_); K_imagRhoGammaSq *= ImRhoMatrix_; K_imagRhoGammaSq *= GammaMatrixSq; // A = I + K*Imag(rho)Gamma^2, B = -K*Real(Rho)Gamma^2 // Calculate C and D matrices such that (A + iB)*(C + iD) = I, // ie. C + iD = (I - i K*rhoGamma^2)^-1, separated into real and imaginary parts. // realProp C = (A + B A^-1 B)^-1, imagProp D = -A^-1 B C TMatrixD A(IMatrix_); A += K_imagRhoGammaSq; TMatrixD B(zeroMatrix_); B -= K_realRhoGammaSq; TMatrixD invA(TMatrixD::kInverted, A); TMatrixD invA_B(invA); invA_B *= B; TMatrixD B_invA_B(B); B_invA_B *= invA_B; TMatrixD invC(A); invC += B_invA_B; // Set the real part of the propagator matrix ("C") realProp_ = TMatrixD(TMatrixD::kInverted, invC); // Set the (negative) imaginary part of the propagator matrix ("-D") TMatrixD BC(B); BC *= realProp_; negImagProp_ = TMatrixD(invA); negImagProp_ *= BC; // Pre-multiply by the Gamma matrix: realProp_ = GammaMatrix_ * realProp_; negImagProp_ = GammaMatrix_ * negImagProp_; if(verbose_) { std::cout << "In LauKMatrixPropagator::updatePropagator(s). D[1-iKrhoD^2]^-1: " << std::endl; TString realOutput("Real part:"), imagOutput("Imag part:"); for (int iChannel = 0; iChannel < nChannels_; iChannel++) { for (int jChannel = 0; jChannel < nChannels_; jChannel++) { realOutput += Form("\t%.6f",realProp_[iChannel][jChannel]); imagOutput += Form("\t%.6f",-1*negImagProp_[iChannel][jChannel]); } realOutput += "\n "; imagOutput += "\n "; } std::cout << realOutput << std::endl; std::cout << imagOutput << std::endl; } // Also calculate the production SVP term, since this uses Adler-zero parameters // defined in the parameter file. this->updateProdSVPTerm(s); // Finally, keep track of the value of s we just used. previousS_ = s; } void LauKMatrixPropagator::setParameters(const TString& inputFile) { // Read an input file that specifies the values of the coupling constants g_i for // the given number of poles and their (bare) masses. Also provided are the f_{ab} // slow-varying constants. The input file should also provide the Adler zero // constants s_0, s_A and s_A0. parametersSet_ = kFALSE; cout<<"Initialising K-matrix propagator "<Exit(EXIT_FAILURE); } UInt_t iLine(0); for (iLine = 1; iLine <= nTotLines; iLine++) { // Get the line of strings std::vector theLine = readFile.getLine(iLine); // There should always be at least two strings: a keyword and at least 1 value if (theLine.size() < 2) {continue;} TString keyword(theLine[0].c_str()); keyword.ToLower(); // Use lowercase if (!keyword.CompareTo("channels")) { // Channel indices for phase-space factors this->storeChannels(theLine); } else if (!keyword.CompareTo("pole")) { // Pole terms this->storePole(theLine); } else if (!keyword.CompareTo("scatt")) { // Scattering terms this->storeScattering(theLine); } else if (!keyword.CompareTo("angularmomentum")) { // Orbital angular momentum state for each channel & set default a values if called before storeBarrierFactorParameter this->storeOrbitalAngularMomenta(theLine, a); } else if (!keyword.CompareTo("barrierfactorparameter")) { // Value of parameter "a" in denominator of centrifugal barrier factor, gamma this->storeBarrierFactorParameter(theLine, a); } else if (!keyword.CompareTo("radii")) { // Values of characteristic radius this->storeRadii(theLine); } else { // Usually Adler-zero constants TString parString(theLine[1].c_str()); this->storeParameter(keyword, parString); } } sAConst_ = 0.5*sA_.unblindValue()*LauConstants::mPiSq; // Symmetrise scattering parameters if enabled if (scattSymmetry_ == kTRUE) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { for (Int_t jChannel = iChannel; jChannel < nChannels_; jChannel++) { LauParameter fPar = fScattering_[iChannel][jChannel]; fScattering_[jChannel][iChannel] = LauParameter(fPar); } } } // Now that radii and barrier-factor-denominator parameters have been set, cache the value of "a/(R*R)" for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { gamAInvRadSq_[iChannel] = a[iChannel]/(radii_[iChannel]*radii_[iChannel]); } // All required parameters have been set parametersSet_ = kTRUE; cout<<"Finished initialising K-matrix propagator "< >. // Set their sizes using the number of poles and channels defined in the constructor gCouplings_.clear(); gCouplings_.resize(nPoles_); for (Int_t iPole = 0; iPole < nPoles_; iPole++) { gCouplings_[iPole].resize(nChannels_); } fScattering_.clear(); fScattering_.resize(nChannels_); for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { fScattering_[iChannel].resize(nChannels_); } // Clear other vectors phaseSpaceTypes_.clear(); phaseSpaceTypes_.resize(nChannels_); mSqPoles_.clear(); mSqPoles_.resize(nPoles_); haveCalled_storeBarrierFactorParameter = kFALSE; } void LauKMatrixPropagator::storeChannels(const std::vector& theLine) { // Get the list of channel indices to specify what phase space factors should be used // e.g. pipi, Kpi, eta eta', 4pi etc.. // Check that the line has nChannels_+1 strings Int_t nTypes = static_cast(theLine.size()) - 1; if (nTypes != nChannels_) { cerr<<"Error in LauKMatrixPropagator::storeChannels. The input file defines " <checkPhaseSpaceType(phaseSpaceInt); if (checkChannel == kTRUE) { cout<<"Adding phase space channel index "<(phaseSpaceInt); } else { cerr<<"Phase space channel index "<(LauKMatrixPropagator::KMatrixChannels::TotChannels)-1<& theLine) { // Store the pole mass and its coupling constants for each channel. // Each line will contain: Pole poleNumber poleMass poleCouplingsPerChannel // Check that the line has nChannels_ + 3 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 3; if (nWords == nExpect) { Int_t poleIndex = std::atoi(theLine[1].c_str()) - 1; if (poleIndex >= 0 && poleIndex < nPoles_) { Double_t poleMass = std::atof(theLine[2].c_str()); Double_t poleMassSq = poleMass*poleMass; LauParameter mPoleParam(Form("KM_%s_poleMassSq_%i",name_.Data(),poleIndex),poleMassSq); mSqPoles_[poleIndex] = mPoleParam; cout<<"Added bare pole mass "<& theLine) { // Store the scattering constants (along one of the channel rows). // Each line will contain: Scatt ScattIndex ScattConstantsPerChannel // Check that the line has nChannels_ + 2 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 2; if (nWords == nExpect) { Int_t scattIndex = std::atoi(theLine[1].c_str()) - 1; if (scattIndex >= 0 && scattIndex < nChannels_) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { Double_t scattConst = std::atof(theLine[iChannel+2].c_str()); LauParameter scattParam(Form("KM_%s_fScatteringConst_%i_%i",name_.Data(),scattIndex,iChannel),scattConst); fScattering_[scattIndex][iChannel] = scattParam; cout<<"Added scattering parameter f("<& theLine, std::vector& a) { // Store the orbital angular momentum for each channel // Each line will contain: angularmomentum OrbitalAngularMomentumPerChannel // Check that the line has nChannels_ + 1 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 1; if (nWords == nExpect) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { Int_t angularMomentum = std::atoi(theLine[iChannel+1].c_str()); L_[iChannel] = angularMomentum; cout<<"Defined K-matrix orbital angular momentum "<Exit(EXIT_FAILURE); } } } } void LauKMatrixPropagator::storeRadii(const std::vector& theLine) { // Store the characteristic radii (measured in GeV^{-1}) // Each line will contain: Radii RadiusConstantsPerChannel // Check that the line has nChannels_ + 1 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 1; if (nWords == nExpect) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { Double_t radiusConst = std::atof(theLine[iChannel+1].c_str()); radii_[iChannel] = radiusConst; cout<<"Added K-matrix radius "<& theLine, std::vector& a) { // Store the parameter of the barrier factor // Each line will contain: barrierfactorparameter ParameterValuePerchannel // Check that the line has nChannels_ + 1 strings Int_t nWords = static_cast(theLine.size()); Int_t nExpect = nChannels_ + 1; if (nWords == nExpect) { for (Int_t iChannel = 0; iChannel < nChannels_; iChannel++) { Double_t parameterValue = std::atof(theLine[iChannel+1].c_str()); a[iChannel] = parameterValue; cout<<"Added K-matrix barrier factor parameter value "<updateScattSVPTerm(s); // Now loop over iChannel, jChannel to calculate Kij = Kji. for (iChannel = 0; iChannel < nChannels_; iChannel++) { // Scattering matrix is real and symmetric. Start j loop from i. for (jChannel = iChannel; jChannel < nChannels_; jChannel++) { Double_t Kij(0.0); // Calculate pole mass summation term for (iPole = 0; iPole < nPoles_; iPole++) { Double_t g_i = this->getCouplingConstant(iPole, iChannel); Double_t g_j = this->getCouplingConstant(iPole, jChannel); Kij += poleDenomVect_[iPole]*g_i*g_j; if (verbose_) {cout<<"1: Kij for i = "<getScatteringConstant(iChannel, jChannel); Kij += fij*scattSVP_; Kij *= adlerZeroFactor_; if (verbose_) {cout<<"2: Kij for i = "< 1.0e-6) {invPoleTerm = 1.0/poleTerm;} poleDenomVect_.push_back(invPoleTerm); } } Double_t LauKMatrixPropagator::getPoleDenomTerm(const Int_t poleIndex) const { if (parametersSet_ == kFALSE) {return 0.0;} Double_t poleDenom(0.0); poleDenom = poleDenomVect_[poleIndex]; return poleDenom; } LauParameter& LauKMatrixPropagator::getPoleMassSqParameter(const Int_t poleIndex) { if ( (parametersSet_ == kFALSE) || (poleIndex < 0 || poleIndex >= nPoles_) ) { std::cerr << "ERROR from LauKMatrixPropagator::getPoleMassSqParameter(). Invalid pole." << std::endl; gSystem->Exit(EXIT_FAILURE); } return mSqPoles_[poleIndex]; } Double_t LauKMatrixPropagator::getCouplingConstant(const Int_t poleIndex, const Int_t channelIndex) const { if (parametersSet_ == kFALSE) {return 0.0;} if (poleIndex < 0 || poleIndex >= nPoles_) {return 0.0;} if (channelIndex < 0 || channelIndex >= nChannels_) {return 0.0;} Double_t couplingConst = gCouplings_[poleIndex][channelIndex].unblindValue(); return couplingConst; } LauParameter& LauKMatrixPropagator::getCouplingParameter(const Int_t poleIndex, const Int_t channelIndex) { if ( (parametersSet_ == kFALSE) || (poleIndex < 0 || poleIndex >= nPoles_) || (channelIndex < 0 || channelIndex >= nChannels_) ) { std::cerr << "ERROR from LauKMatrixPropagator::getCouplingParameter(). Invalid coupling." << std::endl; gSystem->Exit(EXIT_FAILURE); } //std::cout << "Minvalue + range for " << poleIndex << ", " << channelIndex << ": " << gCouplings_[poleIndex][channelIndex].minValue() << " => + " << gCouplings_[poleIndex][channelIndex].range() << // " and init value: " << gCouplings_[poleIndex][channelIndex].initValue() << std::endl; return gCouplings_[poleIndex][channelIndex]; } Double_t LauKMatrixPropagator::getScatteringConstant(const Int_t channel1Index, const Int_t channel2Index) const { if (parametersSet_ == kFALSE) {return 0.0;} if (channel1Index < 0 || channel1Index >= nChannels_) {return 0.0;} if (channel2Index < 0 || channel2Index >= nChannels_) {return 0.0;} Double_t scatteringConst = fScattering_[channel1Index][channel2Index].unblindValue(); return scatteringConst; } LauParameter& LauKMatrixPropagator::getScatteringParameter(const Int_t channel1Index, const Int_t channel2Index) { if ( (parametersSet_ == kFALSE) || (channel1Index < 0 || channel1Index >= nChannels_) || (channel2Index < 0 || channel2Index >= nChannels_) ) { std::cerr << "ERROR from LauKMatrixPropagator::getScatteringParameter(). Invalid chanel index." << std::endl; gSystem->Exit(EXIT_FAILURE); } return fScattering_[channel1Index][channel2Index]; } Double_t LauKMatrixPropagator::calcSVPTerm(const Double_t s, const Double_t s0) const { if (parametersSet_ == kFALSE) {return 0.0;} // Calculate the "slowly-varying part" (SVP) Double_t result(0.0); Double_t deltaS = s - s0; if (TMath::Abs(deltaS) > 1.0e-6) { result = (mSq0_.unblindValue() - s0)/deltaS; } return result; } void LauKMatrixPropagator::updateScattSVPTerm(const Double_t s) { // Update the scattering "slowly-varying part" (SVP) Double_t s0Scatt = s0Scatt_.unblindValue(); scattSVP_ = this->calcSVPTerm(s, s0Scatt); } void LauKMatrixPropagator::updateProdSVPTerm(const Double_t s) { // Update the production "slowly-varying part" (SVP) Double_t s0Prod = s0Prod_.unblindValue(); prodSVP_ = this->calcSVPTerm(s, s0Prod); } void LauKMatrixPropagator::updateAdlerZeroFactor(const Double_t s) { // Calculate the multiplicative factor containing various Adler zero // constants. adlerZeroFactor_ = 0.0; Double_t sA0Val = sA0_.unblindValue(); Double_t deltaS = s - sA0Val; if (TMath::Abs(deltaS) > 1e-6) { adlerZeroFactor_ = (s - sAConst_)*(1.0 - sA0Val)/deltaS; } } void LauKMatrixPropagator::calcGammaMatrix(const Double_t s) { // Calculate the gamma angular momentum barrier matrix // for the given invariant mass squared quantity, s. // Initialise all entries to zero GammaMatrix_.Zero(); Double_t gamma(0.0); for (Int_t iChannel (0); iChannel < nChannels_; ++iChannel) { if ( L_[iChannel] != 0 ) { gamma = this->calcGamma(iChannel,s); } else { gamma = 1.0; // S-wave } if (verbose_) { cout<<"GammaMatrix("<Exit(EXIT_FAILURE); } return rho; } LauComplex LauKMatrixPropagator::calcD0KRho(const Double_t s) const { // Calculate the D0K+ phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mD0KSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mD0KDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcDstar0KRho(const Double_t s) const { // Calculate the Dstar0K+ phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mDstar0KSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mDstar0KDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcPiPiRho(const Double_t s) const { // Calculate the pipi phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-m2piSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKKRho(const Double_t s) const { // Calculate the KK phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-m2KSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcFourPiRho(const Double_t s) const { // Calculate the 4pi phase space factor. This uses a 6th-order polynomial // parameterisation that approximates the multi-body phase space double integral // defined in Eq 4 of the A&S paper hep-ph/0204328. This form agrees with the // BaBar model (another 6th order polynomial from s^4 down to 1/s^2), but avoids the // exponential increase at small values of s (~< 0.1) arising from 1/s and 1/s^2. // Eq 4 is evaluated for each value of s by assuming incremental steps of 1e-3 GeV^2 // for s1 and s2, the invariant energy squared of each of the di-pion states, // with the integration limits of s1 = (2*mpi)^2 to (sqrt(s) - 2*mpi)^2 and // s2 = (2*mpi)^2 to (sqrt(s) - sqrt(s1))^2. The mass M of the rho is taken to be // 0.775 GeV and the energy-dependent width of the 4pi system // Gamma(s) = gamma_0*rho1^3(s), where rho1 = sqrt(1.0 - 4*mpiSq/s) and gamma_0 is // the "width" of the 4pi state at s = 1, which is taken to be 0.3 GeV // (~75% of the total width from PDG estimates of the f0(1370) -> 4pi state). // The normalisation term rho_0 is found by ensuring that the phase space integral // at s = 1 is equal to sqrt(1.0 - 16*mpiSq/s). Note that the exponent for this // factor in hep-ph/0204328 is wrong; it should be 0.5, i.e. sqrt, not n = 1 to 5. // Plotting the value of this double integral as a function of s can then be fitted // to a 6th-order polynomial (for s < 1), which is the result used below LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} if (s <= 1.0) { Double_t rhoTerm = ((1.07885*s + 0.13655)*s - 0.29744)*s - 0.20840; rhoTerm = ((rhoTerm*s + 0.13851)*s - 0.01933)*s + 0.00051; // For some values of s (below 2*mpi), this term is a very small // negative number. Check for this and set the rho term to zero. if (rhoTerm < 0.0) {rhoTerm = 0.0;} rho.setRealPart( rhoTerm ); } else { rho.setRealPart( TMath::Sqrt(1.0 - (fourPiFactor1_/s)) ); } return rho; } LauComplex LauKMatrixPropagator::calcEtaEtaRho(const Double_t s) const { // Calculate the eta-eta phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-m2EtaSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcEtaEtaPRho(const Double_t s) const { // Calculate the eta-eta' phase space factor. Note that the // mass difference term m_eta - m_eta' is not included, // since this corresponds to a "t or u-channel crossing", // which means that we cannot simply analytically continue // this part of the phase space factor below threshold, which // we can do for s-channel contributions. This is actually an // unsolved problem, e.g. see Guo et al 1409.8652, and // Danilkin et al 1409.7708. Anisovich and Sarantsev in // hep-ph/0204328 "solve" this issue by setting the mass // difference term to unity, which is what we do here... LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm = (-mEtaEtaPSumSq_/s) + 1.0; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKPiRho(const Double_t s) const { // Calculate the K-pi phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mKpiSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mKpiDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKEtaPRho(const Double_t s) const { // Calculate the K-eta' phase space factor LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} Double_t sqrtTerm1 = (-mKEtaPSumSq_/s) + 1.0; Double_t sqrtTerm2 = (-mKEtaPDiffSq_/s) + 1.0; Double_t sqrtTerm = sqrtTerm1*sqrtTerm2; if (sqrtTerm < 0.0) { rho.setImagPart( TMath::Sqrt(-sqrtTerm) ); } else { rho.setRealPart( TMath::Sqrt(sqrtTerm) ); } return rho; } LauComplex LauKMatrixPropagator::calcKThreePiRho(const Double_t s) const { // Calculate the Kpipipi + multimeson phase space factor. // Use the simplest definition in hep-ph/9705401 (Eq 14), which is the form // used for the rest of that paper (thankfully, the amplitude does not depend // significantly on the form used for the K3pi phase space factor). LauComplex rho(0.0, 0.0); if (TMath::Abs(s) < 1e-10) {return rho;} if (s < 1.44) { Double_t powerTerm = (-mK3piDiffSq_/s) + 1.0; if (powerTerm < 0.0) { rho.setImagPart( k3piFactor_*TMath::Power(-powerTerm, 2.5) ); } else { rho.setRealPart( k3piFactor_*TMath::Power(powerTerm, 2.5) ); } } else { rho.setRealPart( 1.0 ); } return rho; } Bool_t LauKMatrixPropagator::checkPhaseSpaceType(const Int_t phaseSpaceInt) const { Bool_t passed(kFALSE); if (phaseSpaceInt >= 1 && phaseSpaceInt < static_cast(LauKMatrixPropagator::KMatrixChannels::TotChannels)) { passed = kTRUE; } return passed; } LauComplex LauKMatrixPropagator::getTransitionAmp(const Double_t s, const Int_t channel) { // Get the complex (unitary) transition amplitude T for the given channel LauComplex TAmp(0.0, 0.0); if (channel <= 0 || channel > nChannels_) {return TAmp;} this->getTMatrix(s); TAmp.setRealPart(ReTMatrix_[index_][channel-1]); TAmp.setImagPart(ImTMatrix_[index_][channel-1]); return TAmp; } LauComplex LauKMatrixPropagator::getPhaseSpaceTerm(const Double_t s, const Int_t channel) { // Get the complex (unitary) transition amplitude T for the given channel LauComplex rho(0.0, 0.0); if (channel <= 0 || channel > nChannels_) {return rho;} // If s has changed from the previous value, recalculate rho if (TMath::Abs(s - previousS_) > 1e-6*s) { this->calcRhoMatrix(s); } rho.setRealPart(ReRhoMatrix_[channel][channel-1]); rho.setImagPart(ImRhoMatrix_[channel][channel-1]); return rho; } void LauKMatrixPropagator::getTMatrix(const LauKinematics* kinematics) { // Find the unitary T matrix, where T = [sqrt(rho)]^{*} T_hat sqrt(rho), // and T_hat = (I - i K rho)^-1 * K is the Lorentz-invariant T matrix, // which has phase-space factors included (rho). This function is not // needed to calculate the K-matrix amplitudes, but allows us // to check the variation of T as a function of s (kinematics) if (!kinematics) {return;} // Get the invariant mass squared (s) from the kinematics object. // Use the resPairAmpInt to find which mass-squared combination to use. Double_t s(0.0); if (resPairAmpInt_ == 1) { s = kinematics->getm23Sq(); } else if (resPairAmpInt_ == 2) { s = kinematics->getm13Sq(); } else if (resPairAmpInt_ == 3) { s = kinematics->getm12Sq(); } this->getTMatrix(s); } void LauKMatrixPropagator::getTMatrix(const Double_t s) { // Find the unitary transition T matrix, where // T = [sqrt(rho)]^{*} T_hat sqrt(rho), and // T_hat = (I - i K rho)^-1 * K is the Lorentz-invariant T matrix, // which has phase-space factors included (rho). Note that the first // sqrt of the rho matrix is complex conjugated. // This function is not needed to calculate the K-matrix amplitudes, but // allows us to check the variation of T as a function of s (kinematics) // Initialse the real and imaginary parts of the T matrix to zero ReTMatrix_.Zero(); ImTMatrix_.Zero(); if (parametersSet_ == kFALSE) {return;} // Update K, rho and the propagator (I - i K rho)^-1 this->updatePropagator(s); // Find the real and imaginary T_hat matrices TMatrixD THatReal = realProp_*ScattKMatrix_; TMatrixD THatImag(zeroMatrix_); THatImag -= negImagProp_*ScattKMatrix_; // Find the square-root of the phase space matrix this->getSqrtRhoMatrix(); // Let sqrt(rho) = A + iB and T_hat = C + iD // => T = A(CA-DB) + B(DA+CB) + i[A(DA+CB) + B(DB-CA)] TMatrixD CA(THatReal); CA *= ReSqrtRhoMatrix_; TMatrixD DA(THatImag); DA *= ReSqrtRhoMatrix_; TMatrixD CB(THatReal); CB *= ImSqrtRhoMatrix_; TMatrixD DB(THatImag); DB *= ImSqrtRhoMatrix_; TMatrixD CAmDB(CA); CAmDB -= DB; TMatrixD DApCB(DA); DApCB += CB; TMatrixD DBmCA(DB); DBmCA -= CA; // Find the real and imaginary parts of the transition matrix T ReTMatrix_ = ReSqrtRhoMatrix_*CAmDB + ImSqrtRhoMatrix_*DApCB; ImTMatrix_ = ReSqrtRhoMatrix_*DApCB + ImSqrtRhoMatrix_*DBmCA; } void LauKMatrixPropagator::getSqrtRhoMatrix() { // Find the square root of the (current) phase space matrix so that // we can find T = [sqrt(rho)}^{*} T_hat sqrt(rho), where T_hat is the // Lorentz-invariant T matrix = (I - i K rho)^-1 * K; note that the first // sqrt of rho matrix is complex conjugated // If rho = rho_i + i rho_r = a + i b, then sqrt(rho) = c + i d, where // c = sqrt(0.5*(r+a)) and d = sqrt(0.5(r-a)), where r = sqrt(a^2 + b^2). // Since rho is diagonal, then the square root of rho will also be diagonal, // with its real and imaginary matrix elements equal to c and d, respectively // Initialise the real and imaginary parts of the square root of // the rho matrix to zero ReSqrtRhoMatrix_.Zero(); ImSqrtRhoMatrix_.Zero(); for (Int_t iChannel (0); iChannel < nChannels_; ++iChannel) { Double_t realRho = ReRhoMatrix_[iChannel][iChannel]; Double_t imagRho = ImRhoMatrix_[iChannel][iChannel]; Double_t rhoMag = sqrt(realRho*realRho + imagRho*imagRho); Double_t rhoSum = rhoMag + realRho; Double_t rhoDiff = rhoMag - realRho; Double_t reSqrtRho(0.0), imSqrtRho(0.0); if (rhoSum > 0.0) {reSqrtRho = sqrt(0.5*rhoSum);} if (rhoDiff > 0.0) {imSqrtRho = sqrt(0.5*rhoDiff);} ReSqrtRhoMatrix_[iChannel][iChannel] = reSqrtRho; ImSqrtRhoMatrix_[iChannel][iChannel] = imSqrtRho; } } LauComplex LauKMatrixPropagator::getTHat(const Double_t s, const Int_t channel) { LauComplex THat(0.0, 0.0); if (channel <= 0 || channel > nChannels_) {return THat;} this->updatePropagator(s); // Find the real and imaginary T_hat matrices TMatrixD THatReal = realProp_*ScattKMatrix_; TMatrixD THatImag(zeroMatrix_); THatImag -= negImagProp_*ScattKMatrix_; // Return the specific THat component THat.setRealPart(THatReal[index_][channel-1]); THat.setImagPart(THatImag[index_][channel-1]); return THat; } diff --git a/src/LauKappaRes.cc b/src/LauKappaRes.cc index ba10e34..24834d2 100644 --- a/src/LauKappaRes.cc +++ b/src/LauKappaRes.cc @@ -1,300 +1,299 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKappaRes.cc \brief File containing implementation of LauKappaRes class. */ #include #include "LauConstants.hh" #include "LauKappaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauKappaRes) LauKappaRes::LauKappaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mSumSq_((LauConstants::mPi+LauConstants::mK)*(LauConstants::mPi+LauConstants::mK)), sAdler_(LauConstants::mKSq-0.5*LauConstants::mPiSq), b1_(0), b2_(0), a_(0), m0_(0) { // Default constant factors from BES data const Double_t b1Val = 24.49; const Double_t b2Val = 0.0; const Double_t aVal = 2.5; const Double_t m0Val = 3.3; const TString& parNameBase = this->getSanitisedName(); TString b1Name(parNameBase); b1Name += "_b1"; b1_ = resInfo->getExtraParameter( b1Name ); if ( b1_ == 0 ) { b1_ = new LauParameter( b1Name, b1Val, 0.0, 100.0, kTRUE ); b1_->secondStage(kTRUE); resInfo->addExtraParameter( b1_ ); } TString b2Name(parNameBase); b2Name += "_b2"; b2_ = resInfo->getExtraParameter( b2Name ); if ( b2_ == 0 ) { b2_ = new LauParameter( b2Name, b2Val, 0.0, 100.0, kTRUE ); b2_->secondStage(kTRUE); resInfo->addExtraParameter( b2_ ); } TString aName(parNameBase); aName += "_A"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } TString m0Name(parNameBase); m0Name += "_m0"; m0_ = resInfo->getExtraParameter( m0Name ); if ( m0_ == 0 ) { m0_ = new LauParameter( m0Name, m0Val, 0.0, 10.0, kTRUE ); m0_->secondStage(kTRUE); resInfo->addExtraParameter( m0_ ); } } LauKappaRes::~LauKappaRes() { } void LauKappaRes::initialise() { this->checkDaughterTypes(); Double_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauKappaRes::initialise : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Kappa amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } void LauKappaRes::checkDaughterTypes() const { // Check that the daughter tracks are K and pi. Otherwise issue a warning. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauKappaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if ( !( nameDaug1.Contains("pi", TString::kIgnoreCase) && nameDaug2.Contains("k", TString::kIgnoreCase) ) ) { if ( !( nameDaug2.Contains("pi", TString::kIgnoreCase) && nameDaug1.Contains("k", TString::kIgnoreCase) ) ) { std::cerr << "ERROR in LauKappaRes::checkDaughterTypes : Kappa model is using daughters \"" << nameDaug1 << "\" and \"" << nameDaug2 << "\" that are not a kaon and a pion." << std::endl; } } } LauComplex LauKappaRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Kappa distribution // given the invariant mass and cos(helicity) values. // First check that the appropriate daughters are either pi+pi- or K+K- // Check that the daughter tracks are the same type. Otherwise issue a warning // and set the type to be pion for the Kappa distribution. Returns the // integer defined by the enum LauKappaRes::KappaPartType. Double_t s = mass*mass; // Invariant mass squared combination for the system Double_t rho(0.0); // Phase-space factor if (s > mSumSq_) {rho = TMath::Sqrt(1.0 - mSumSq_/s);} const Double_t m0Val = this->getM0Value(); const Double_t m0Sq = m0Val * m0Val; const Double_t aVal = this->getAValue(); const Double_t b1Val = this->getB1Value(); const Double_t b2Val = this->getB2Value(); Double_t f = b2Val*s + b1Val; // f(s) function Double_t numerator = s - sAdler_; Double_t denom = m0Sq - sAdler_; Double_t gamma(0.0); if (TMath::Abs(denom) > 1e-10 && TMath::Abs(aVal) > 1e-10) { // Decay width of the system gamma = rho*(numerator/denom)*f*TMath::Exp(-(s - m0Sq)/aVal); } // Now form the complex amplitude - use relativistic BW form (without barrier factors) // Note that the M factor in the denominator is not the "pole" at ~500 MeV, but is // m0_ = 0.9264, the mass when the phase shift goes through 90 degrees. Double_t dMSq = m0Sq - s; Double_t widthTerm = gamma*m0Val; LauComplex resAmplitude(dMSq, widthTerm); Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauKappaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Value() ) { this->addFloatingParameter( b1_ ); } if ( ! this->fixB2Value() ) { this->addFloatingParameter( b2_ ); } if ( ! this->fixAValue() ) { this->addFloatingParameter( a_ ); } if ( ! this->fixM0Value() ) { this->addFloatingParameter( m0_ ); } return this->getParameters(); } void LauKappaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b1") { this->setB1Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter b1 = " << this->getB1Value() << std::endl; } else if (name == "b2") { this->setB2Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter b2 = " << this->getB2Value() << std::endl; } else if (name == "A") { this->setAValue(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter A = " << this->getAValue() << std::endl; } else if (name == "m0") { this->setM0Value(value); std::cout << "INFO in LauKappaRes::setResonanceParameter : Setting parameter m0 = " << this->getM0Value() << std::endl; } else { std::cerr << "WARNING in LauKappaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauKappaRes::floatResonanceParameter(const TString& name) { if (name == "b1") { if ( b1_->fixed() ) { b1_->fixed( kFALSE ); this->addFloatingParameter( b1_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "b2") { if ( b2_->fixed() ) { b2_->fixed( kFALSE ); this->addFloatingParameter( b2_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "A") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "m0") { if ( m0_->fixed() ) { m0_->fixed( kFALSE ); this->addFloatingParameter( m0_ ); } else { std::cerr << "WARNING in LauKappaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauKappaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauKappaRes::getResonanceParameter(const TString& name) { if (name == "b1") { return b1_; } else if (name == "b2") { return b2_; } else if (name == "A") { return a_; } else if (name == "m0") { return m0_; } else { std::cerr << "WARNING in LauKappaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauKappaRes::setB1Value(const Double_t b1) { b1_->value( b1 ); b1_->genValue( b1 ); b1_->initValue( b1 ); } void LauKappaRes::setB2Value(const Double_t b2) { b2_->value( b2 ); b2_->genValue( b2 ); b2_->initValue( b2 ); } void LauKappaRes::setAValue(const Double_t A) { a_->value( A ); a_->genValue( A ); a_->initValue( A ); } void LauKappaRes::setM0Value(const Double_t m0) { m0_->value( m0 ); m0_->genValue( m0 ); m0_->initValue( m0 ); } diff --git a/src/LauKinematics.cc b/src/LauKinematics.cc index eb7d9f4..98499dc 100644 --- a/src/LauKinematics.cc +++ b/src/LauKinematics.cc @@ -1,744 +1,743 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauKinematics.cc \brief File containing implementation of LauKinematics class. */ #include #include "TF2.h" #include "TMath.h" #include "TRandom.h" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauRandom.hh" -ClassImp(LauKinematics) LauKinematics::LauKinematics(const Double_t m1, const Double_t m2, const Double_t m3, const Double_t mParent, const Bool_t calcSquareDPCoords, const Bool_t symmetricalDP, const Bool_t fullySymmetricDP) : symmetricalDP_(symmetricalDP), fullySymmetricDP_(fullySymmetricDP), m1_(m1), m2_(m2), m3_(m3), mParent_(mParent), m1Sq_(m1*m1), m2Sq_(m2*m2), m3Sq_(m3*m3), mParentSq_(mParent*mParent), mDTot_(m1 + m2 + m3), massInt_(mParent - (m1+m2+m3)), mSqDTot_(m1*m1 + m2*m2 + m3*m3), m12_(0.0), m23_(0.0), m13_(0.0), m12Sq_(0.0), m23Sq_(0.0), m13Sq_(0.0), c12_(0.0), c23_(0.0), c13_(0.0), mPrime_(0.0), thetaPrime_(0.0), qi_(0.0), qk_(0.0), p1_12_(0.0), p3_12_(0.0), p2_23_(0.0), p1_23_(0.0), p1_13_(0.0), p2_13_(0.0), p1_Parent_(0.0), p2_Parent_(0.0), p3_Parent_(0.0), squareDP_(calcSquareDPCoords), warnings_(kTRUE) { // Constructor mass_.clear(); mMin_.clear(); mMax_.clear(); mSqMin_.clear(); mSqMax_.clear(); mSq_.clear(); mSqDiff_.clear(); mDiff_.clear(); mass_.push_back(m1_); mass_.push_back(m2_); mass_.push_back(m3_); mSq_.push_back(m1Sq_); mSq_.push_back(m2Sq_); mSq_.push_back(m3Sq_); // DP max and min kinematic boundary for circumscribed box // (see figure in PDG book). for (Int_t i = 0; i < 3; i++) { mMin_.push_back(mDTot_ - mass_[i]); mMax_.push_back(mParent_ - mass_[i]); mSqMin_.push_back(mMin_[i]*mMin_[i]); mSqMax_.push_back(mMax_[i]*mMax_[i]); mSqDiff_.push_back(mSqMax_[i] - mSqMin_[i]); mDiff_.push_back(mMax_[i] - mMin_[i]); } if (this->squareDP()) { std::cout<<"INFO in LauKinematics::LauKinematics : squareDP = kTRUE"<updateMassSquares(m13Sq, m23Sq); // Now update the helicity cosines this->calcHelicities(); // Also calculate the m', theta' variables if (squareDP_) {this->calcSqDPVars();} } void LauKinematics::updateSqDPKinematics(const Double_t mPrime, const Double_t thetaPrime) { // From square DP co-ordinates, calculate remaining kinematic variables this->updateSqDPMassSquares(mPrime, thetaPrime); // Finally calculate the helicities and track momenta this->calcHelicities(); } void LauKinematics::calcSqDPVars() { // For given m_12 and cos(theta_12) values, calculate m' and theta' for the square Dalitz plot Double_t value = (2.0*(m12_ - mMin_[2])/mDiff_[2]) - 1.0; mPrime_ = LauConstants::invPi*TMath::ACos(value); thetaPrime_ = LauConstants::invPi*TMath::ACos(c12_); // Sometimes events are assigned exactly thetaPrime = 0.0 or 1.0 // which gives problems with efficiency and other histograms if (thetaPrime_ == 0.0) { thetaPrime_ += 1.0e-10; } else if (thetaPrime_ == 1.0) { thetaPrime_ -= 1.0e-10; } } Double_t LauKinematics::calcSqDPJacobian() const { return this->calcSqDPJacobian(mPrime_,thetaPrime_); } Double_t LauKinematics::calcSqDPJacobian(const Double_t mPrime, const Double_t thPrime) const { // Calculate the Jacobian for the transformation // m23^2, m13^2 -> m', theta' (square DP) const Double_t m12 = 0.5*mDiff_[2]*(1.0 + TMath::Cos(LauConstants::pi*mPrime)) + mMin_[2]; const Double_t m12Sq = m12*m12; const Double_t e1Cms12 = (m12Sq - m2Sq_ + m1Sq_)/(2.0*m12); const Double_t e3Cms12 = (mParentSq_ - m12Sq - m3Sq_)/(2.0*m12); const Double_t p1Cms12 = this->pCalc(e1Cms12, m1Sq_); const Double_t p3Cms12 = this->pCalc(e3Cms12, m3Sq_); const Double_t deriv1 = LauConstants::piBy2*mDiff_[2]*TMath::Sin(LauConstants::pi*mPrime); const Double_t deriv2 = LauConstants::pi*TMath::Sin(LauConstants::pi*thPrime); const Double_t jacobian = 4.0*p1Cms12*p3Cms12*m12*deriv1*deriv2; return jacobian; } void LauKinematics::updateMassSquares(const Double_t m13Sq, const Double_t m23Sq) { m13Sq_ = m13Sq; if (m13Sq_ > 0.0) { m13_ = TMath::Sqrt(m13Sq_); } else { m13_ = 0.0; } m23Sq_ = m23Sq; if (m23Sq_ > 0.0) { m23_ = TMath::Sqrt(m23Sq_); } else { m23_ = 0.0; } // Now calculate m12Sq and m12. this->calcm12Sq(); // Calculate momenta of tracks in parent (B, D etc.) rest-frame this->calcParentFrameMomenta(); } void LauKinematics::updateSqDPMassSquares(const Double_t mPrime, const Double_t thetaPrime) { // From square DP co-ordinates, calculate only the mass-squares // First set the square-DP variables mPrime_ = mPrime; thetaPrime_ = thetaPrime; // Next calculate m12 and c12 Double_t m12 = 0.5*mDiff_[2]*(1.0 + TMath::Cos(LauConstants::pi*mPrime)) + mMin_[2]; Double_t c12 = TMath::Cos(LauConstants::pi*thetaPrime); // From these calculate m13Sq and m23Sq this->updateMassSq_m12(m12, c12); // Calculate momenta of tracks in parent (B, D etc.) rest-frame this->calcParentFrameMomenta(); } void LauKinematics::calcm12Sq() { // Calculate m12Sq from m13Sq and m23Sq. m12Sq_ = mParentSq_ + mSqDTot_ - m13Sq_ - m23Sq_; // If m12Sq is too low, return lower limit, // and modify m13Sq accordingly. if (m12Sq_ < mSqMin_[2]) { m12Sq_ = mSqMin_[2] + 1.0e-3; m13Sq_ = mParentSq_ + mSqDTot_ - m12Sq_ - m23Sq_; } if (m12Sq_ > 0.0) { m12_ = TMath::Sqrt(m12Sq_); } else { m12_ = 0.0; } } void LauKinematics::calcParentFrameMomenta() { Double_t e1 = (mParentSq_ + m1Sq_ - m23Sq_) / (2.0*mParent_); Double_t e2 = (mParentSq_ + m2Sq_ - m13Sq_) / (2.0*mParent_); Double_t e3 = (mParentSq_ + m3Sq_ - m12Sq_) / (2.0*mParent_); p1_Parent_ = this->pCalc(e1, m1Sq_); p2_Parent_ = this->pCalc(e2, m2Sq_); p3_Parent_ = this->pCalc(e3, m3Sq_); } void LauKinematics::calcHelicities() { // Calculate helicity angle cosines, given m12Sq, m13Sq and m23Sq. // cij_ is the cosine of the helicity angle in the rest frame of the // system of particles i and j. // It is (but note the caveat below) the angle between tracks i and k // in the ij rest frame with indices permuted cyclically. // However, it is important to note that it is not exactly a cyclic // permutation (there is a special treatment for c23 inside the cFromM // function) for reasons of preserving the symmetry about m13=m23 for // symmetric final states. // The precise definitions are: // theta12 is defined as the angle between 1&3 in the rest frame of 1&2 // theta23 is defined as the angle between 3&1 in the rest frame of 2&3 // theta13 is defined as the angle between 3&2 in the rest frame of 1&3 // // It is a prerequisite that all mij_ and mijSq_ variables be correctly set. Int_t zero(0), one(1), two(2); c12_ = cFromM(m12Sq_, m13Sq_, m12_, zero, one, two); p1_12_ = qi_; p3_12_ = qk_; // i, j = 12 (rest frame), k = 3 c23_ = cFromM(m23Sq_, m12Sq_, m23_, one, two, zero); p2_23_ = qi_; p1_23_ = qk_; // i, j = 23 (rest frame), k = 1 c13_ = cFromM(m13Sq_, m23Sq_, m13_, two, zero, one); p1_13_ = qi_; p2_13_ = qk_; // i, j = 31 (rest frame), k = 2 } Double_t LauKinematics::cFromM(const Double_t mijSq, const Double_t mikSq, const Double_t mij, const Int_t i, const Int_t j, const Int_t k) const { // Routine to calculate the cos(helicity) variables from the masses of the particles. // (See comment in LauKinematics::calcHelicities for futher information.) Double_t EiCmsij = (mijSq - mSq_[j] + mSq_[i])/(2.0*mij); Double_t EkCmsij = (mParentSq_ - mijSq - mSq_[k])/(2.0*mij); if (EiCmsij < mass_[i]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::cFromM : EiCmsij = "< 1e-6 && EkCmsij < mass_[k]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::mFromC : EkCmsij = "<pCalc(EiCmsij, mSq_[i]); Double_t qk = this->pCalc(EkCmsij, mSq_[k]); // Find mikSq Double_t massSq = mSq_[i] + mSq_[k] + 2.0*EiCmsij*EkCmsij - 2.0*qi*qk*cosHel; if (massSq < mSqMin_[j]) { if (warnings_) { std::cerr<<"WARNING in LauKinematics::mFromC : mFromC below bound: i, j, k = "<Rndm()*mSqDiff_[1]; m23Sq = mSqMin_[0] + LauRandom::randomFun()->Rndm()*mSqDiff_[0]; } while ( ! this->withinDPLimits( m13Sq, m23Sq ) ); } void LauKinematics::genFlatSqDP(Double_t& mPrime, Double_t& thetaPrime) const { // Generate random event in the square Dalitz plot mPrime = LauRandom::randomFun()->Rndm(); thetaPrime = LauRandom::randomFun()->Rndm(); } Bool_t LauKinematics::withinDPLimits(const Double_t m13Sq, const Double_t m23Sq) const { // Find out whether the point (m13Sq,m23Sq) is within the limits of the // Dalitz plot. The limits are specified by the invariant masses // of the parent (e.g. B) and its three daughters that were // defined in the constructor of this class. Here // m_13Sq = square of invariant mass of daughters 1 and 3 // m_23Sq = square of invariant mass of daughters 2 and 3. Bool_t withinDP = kFALSE; // First check that m13Sq is within its absolute min and max if (!((m13Sq > mSqMin_[1]) && (m13Sq < mSqMax_[1]))) { return kFALSE; } // Now for the given value of m13Sq calculate the local min and max of m23Sq Double_t m13 = TMath::Sqrt(m13Sq); Double_t e3Cms13 = (m13Sq - m1Sq_ + m3Sq_)/(2.0*m13); Double_t p3Cms13 = this->pCalc(e3Cms13, m3Sq_); Double_t e2Cms13 = (mParentSq_ - m13Sq - m2Sq_)/(2.0*m13); Double_t p2Cms13 = this->pCalc(e2Cms13, m2Sq_); Double_t term = 2.0*e2Cms13*e3Cms13 + m2Sq_ + m3Sq_; Double_t m23SqLocMin = term - 2.0*p2Cms13*p3Cms13; Double_t m23SqLocMax = term + 2.0*p2Cms13*p3Cms13; // Check whether the given value of m23Sq satisfies these bounds if (m23Sq > m23SqLocMin && m23Sq < m23SqLocMax) { withinDP = kTRUE; } return withinDP; } Bool_t LauKinematics::withinDPLimits2(const Double_t m13Sq, const Double_t m23Sq) const { // Same as withinDPLimits, but this time testing whether the m13Sq // variable is within the kinematic boundary for the given m23Sq value Bool_t withinDP = kFALSE; // First check that m13Sq is within its absolute min and max if (!((m23Sq > mSqMin_[0]) && (m23Sq < mSqMax_[0]))) { return kFALSE; } // Now for the given value of m13Sq calculate the local min and max of m23Sq Double_t m23 = TMath::Sqrt(m23Sq); Double_t e3Cms23 = (m23Sq - m2Sq_ + m3Sq_)/(2.0*m23); Double_t p3Cms23 = this->pCalc(e3Cms23, m3Sq_); Double_t e1Cms23 = (mParentSq_ - m23Sq - m1Sq_)/(2.0*m23); Double_t p1Cms23 = this->pCalc(e1Cms23, m1Sq_); Double_t term = 2.0*e3Cms23*e1Cms23 + m1Sq_ + m3Sq_; Double_t m13SqLocMin = term - 2.0*p3Cms23*p1Cms23; Double_t m13SqLocMax = term + 2.0*p3Cms23*p1Cms23; // Check whether the given value of m23Sq satisfies these bounds if (m13Sq > m13SqLocMin && m13Sq < m13SqLocMax) { withinDP = kTRUE; } return withinDP; } Bool_t LauKinematics::withinSqDPLimits(const Double_t mPrime, const Double_t thetaPrime) const { // Check whether m' and theta' are between 0 and 1 Bool_t withinDP(kFALSE); if (mPrime > 0.0 && mPrime < 1.0 && thetaPrime > 0.0 && thetaPrime < 1.0) { withinDP = kTRUE; } return withinDP; } Double_t LauKinematics::calcThirdMassSq(const Double_t firstMassSq, const Double_t secondMassSq) const { // Calculate one massSq from the other two return mParentSq_ + mSqDTot_ - firstMassSq - secondMassSq; } Double_t LauKinematics::distanceFromDPCentre() const { return this->distanceFromDPCentre(m13Sq_,m23Sq_); } Double_t LauKinematics::distanceFromDPCentre(const Double_t m13Sq, const Double_t m23Sq) const { // DP centre is defined as the point where m12=m13=m23 // First find the m^2_ij value for the centre Double_t centreMijSq = (mParentSq_ + m1Sq_ + m2Sq_ + m3Sq_)/3.0; // Then find the difference between this and the two provided co-ords Double_t diff13 = m13Sq - centreMijSq; Double_t diff23 = m23Sq - centreMijSq; // Calculate the total distance Double_t distance = TMath::Sqrt(diff13*diff13 + diff23*diff23); return distance; } Double_t LauKinematics::pCalc(const Double_t energy, const Double_t massSq) const { // Routine to calculate the momentum of a particle, given its energy and // invariant mass (squared). Double_t arg = energy*energy - massSq; if (arg < 0.0) { //if (warnings_) { //std::cerr<<"WARNING in LauKinematics::pCalc : arg < 0.0: "<SetParameter(0,mParent); if (orientation == 1323) { f2->SetParameter(1,m1); f2->SetParameter(2,m2); f2->SetParameter(3,m3); } else if (orientation == 2313) { f2->SetParameter(1,m2); f2->SetParameter(2,m1); f2->SetParameter(3,m3); } else if (orientation == 1213) { f2->SetParameter(1,m2); f2->SetParameter(2,m3); f2->SetParameter(3,m1); } else if (orientation == 1312) { f2->SetParameter(1,m3); f2->SetParameter(2,m2); f2->SetParameter(3,m1); } else if (orientation == 1223) { f2->SetParameter(1,m1); f2->SetParameter(2,m3); f2->SetParameter(3,m2); } else if (orientation == 2312) { f2->SetParameter(1,m3); f2->SetParameter(2,m1); f2->SetParameter(3,m2); } // Set up the contour to be drawn when the value of the function == 1.0 Double_t b[]={1.0}; f2->SetContour(1,b); // Set the number of bins for the contour to be sampled over f2->SetNpx(nbins); f2->SetNpy(nbins); // and the line style f2->SetLineWidth(3); f2->SetLineStyle(kSolid); // Draw the contour on top of the histo that should already have been drawn f2->DrawCopy("same"); delete f2; } Double_t dal(Double_t* x, Double_t* par) { Double_t mParent = par[0]; Double_t mi = par[1]; Double_t mj = par[2]; Double_t mk = par[3]; Double_t mikSq=x[0]; Double_t mjkSq=x[1]; Double_t mik = TMath::Sqrt(mikSq); Double_t mjk = TMath::Sqrt(mjkSq); Double_t ejcmsik = (mParent*mParent-mj*mj-mik*mik)/(2.0*mik); Double_t ekcmsik = (mik*mik+mk*mk-mi*mi)/(2.0*mik); if (ekcmsik #include "LauConstants.hh" #include "LauLASSBWRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSBWRes) LauLASSBWRes::LauLASSBWRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), resMassSq_(0.0), r_(0), a_(0) { // Default values for LASS parameters const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSBWRes::~LauLASSBWRes() { } void LauLASSBWRes::initialise() { // Create the mass sums and differences Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSBWRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } this->calcQ0(); } void LauLASSBWRes::calcQ0() { // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) resMass_ = this->getMass(); resMassSq_ = resMass_*resMass_; q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass_); } LauComplex LauLASSBWRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSBWRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); // If the mass is floating and their value have changed // we need to recalculate everything that assumes this value if ( (!this->fixMass()) && resMass != resMass_ ) { this->calcQ0(); } Double_t qRatio = q/q0_; Double_t totWidth = resWidth*qRatio*(resMass/mass); Double_t massSq = mass*mass; Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor resAmplitude.rescale((resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth)); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t tandeltaB = (2.0*aVal*q)/(2.0 + aVal*rVal*q*q); const Double_t tanSq = tandeltaB*tandeltaB; const Double_t cos2PhaseShift = (1.0 - tanSq) / (1.0 + tanSq); const Double_t sin2PhaseShift = 2.0*tandeltaB / (1.0 + tanSq); LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift); // Multiply by the phase shift resAmplitude = resAmplitude * phaseShift; return resAmplitude; } const std::vector& LauLASSBWRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSBWRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSBWRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSBWRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSBWRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSBWRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSBWRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSBWRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSBWRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSBWRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSBWRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSBWRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLASSNRRes.cc b/src/LauLASSNRRes.cc index 6180e03..2c19a78 100644 --- a/src/LauLASSNRRes.cc +++ b/src/LauLASSNRRes.cc @@ -1,196 +1,195 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLASSNRRes.cc \brief File containing implementation of LauLASSNRRes class. */ #include #include "LauConstants.hh" #include "LauLASSNRRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSNRRes) LauLASSNRRes::LauLASSNRRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), r_(0), a_(0), cutOff_(0.0) { // Default values for LASS parameters cutOff_ = 1.8; const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSNRRes::~LauLASSNRRes() { } void LauLASSNRRes::initialise() { Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSNRRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } LauComplex LauLASSNRRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex bkgAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSNRRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } if (mass < cutOff_) { // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t qcotdeltaB = 1.0/aVal + (rVal*q*q)/2.0; // Compute the complex amplitude bkgAmplitude = LauComplex(qcotdeltaB, q); // Scale by the numerator and denominator factors bkgAmplitude.rescale(mass/(qcotdeltaB*qcotdeltaB + q*q)); } return bkgAmplitude; } const std::vector& LauLASSNRRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSNRRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSNRRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSNRRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSNRRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSNRRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSNRRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSNRRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSNRRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSNRRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSNRRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSNRRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLASSRes.cc b/src/LauLASSRes.cc index 790412d..e63b4a5 100644 --- a/src/LauLASSRes.cc +++ b/src/LauLASSRes.cc @@ -1,275 +1,274 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLASSRes.cc \brief File containing implementation of LauLASSRes class. */ #include #include "LauConstants.hh" #include "LauLASSRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauLASSRes) LauLASSRes::LauLASSRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), resMassSq_(0.0), r_(0), a_(0), cutOff_(0.0) { // Default values for LASS parameters cutOff_ = 1.8; const Double_t rVal = 3.32; const Double_t aVal = 2.07; const TString& parNameBase = this->getSanitisedName(); TString rName(parNameBase); rName += "_r"; r_ = resInfo->getExtraParameter( rName ); if ( r_ == 0 ) { r_ = new LauParameter( rName, rVal, 0.0, 10.0, kTRUE ); r_->secondStage(kTRUE); resInfo->addExtraParameter( r_ ); } TString aName(parNameBase); aName += "_a"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } } LauLASSRes::~LauLASSRes() { } void LauLASSRes::initialise() { // Create the mass sums and differences Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; Int_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauLASSRes::amplitude : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : LASS amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } this->calcQ0(); } void LauLASSRes::calcQ0() { // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) resMass_ = this->getMass(); resMassSq_ = resMass_*resMass_; q0_ = TMath::Sqrt((resMassSq_ - mDaugSumSq_)*(resMassSq_ - mDaugDiffSq_))/(2.0*resMass_); } LauComplex LauLASSRes::resAmp(Double_t mass, Double_t /*spinTerm*/) { LauComplex resAmplitude(0.0, 0.0); LauComplex bkgAmplitude(0.0, 0.0); LauComplex totAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauLASSRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } //--------------------------- // First do the resonant part //--------------------------- // Calculate the width of the resonance (as a function of mass) // q is the momentum of either daughter in the resonance rest-frame const Double_t q = this->getQ(); const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); // If the mass is floating and their value have changed // we need to recalculate everything that assumes this value if ( (!this->fixMass()) && resMass != resMass_ ) { this->calcQ0(); } Double_t qRatio = q/q0_; Double_t totWidth = resWidth*qRatio*(resMass/mass); Double_t massSq = mass*mass; Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor resAmplitude.rescale((resMassSq_*resWidth/q0_)/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth)); // Calculate the phase shift term const Double_t rVal = this->getEffectiveRange(); const Double_t aVal = this->getScatteringLength(); const Double_t tandeltaB = (2.0*aVal*q)/(2.0 + aVal*rVal*q*q); const Double_t tanSq = tandeltaB*tandeltaB; const Double_t cos2PhaseShift = (1.0 - tanSq) / (1.0 + tanSq); const Double_t sin2PhaseShift = 2.0*tandeltaB / (1.0 + tanSq); LauComplex phaseShift(cos2PhaseShift, sin2PhaseShift); // Multiply by the phase shift resAmplitude = resAmplitude * phaseShift; //-------------------------------- // Now do the effective range part //-------------------------------- // Form the real and imaginary parts const Double_t qcotdeltaB = 1.0/aVal + (rVal*q*q)/2.0; // Compute the complex amplitude bkgAmplitude = LauComplex(qcotdeltaB, q); // Scale by the numerator and denominator factors bkgAmplitude.rescale(mass/(qcotdeltaB*qcotdeltaB + q*q)); //------------------ // Add them together //------------------ if (mass > cutOff_) { totAmplitude = resAmplitude; } else { totAmplitude = bkgAmplitude + resAmplitude; } return totAmplitude; } const std::vector& LauLASSRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixEffectiveRange() ) { this->addFloatingParameter( r_ ); } if ( ! this->fixScatteringLength() ) { this->addFloatingParameter( a_ ); } return this->getParameters(); } void LauLASSRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the LASS lineshape dynamics if (name == "a") { this->setScatteringLength(value); std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Scattering Length = " << this->getScatteringLength() << std::endl; } else if (name == "r") { this->setEffectiveRange(value); std::cout << "INFO in LauLASSRes::setResonanceParameter : Setting LASS Effective Range = " << this->getEffectiveRange() << std::endl; } else { std::cerr << "WARNING in LauLASSRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauLASSRes::floatResonanceParameter(const TString& name) { if (name == "a") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauLASSRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "r") { if ( r_->fixed() ) { r_->fixed( kFALSE ); this->addFloatingParameter( r_ ); } else { std::cerr << "WARNING in LauLASSRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauLASSRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauLASSRes::getResonanceParameter(const TString& name) { if (name == "a") { return a_; } else if (name == "r") { return r_; } else { std::cerr << "WARNING in LauLASSRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauLASSRes::setEffectiveRange(const Double_t r) { r_->value( r ); r_->genValue( r ); r_->initValue( r ); } void LauLASSRes::setScatteringLength(const Double_t a) { a_->value( a ); a_->genValue( a ); a_->initValue( a ); } diff --git a/src/LauLinearPdf.cc b/src/LauLinearPdf.cc index 5ae16bc..c9922d5 100644 --- a/src/LauLinearPdf.cc +++ b/src/LauLinearPdf.cc @@ -1,129 +1,128 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauLinearPdf.cc \brief File containing implementation of LauLinearPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauLinearPdf.hh" -ClassImp(LauLinearPdf) LauLinearPdf::LauLinearPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), slope_(0),posflag_(kTRUE) { // Constructor for the linear PDF. // // The parameters in params are the slope and y-intercept of the line. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. slope_ = this->findParameter("slope"); if ((this->nParameters() != 1) || (slope_ == 0)) { cerr<<"Warning. LauLinearPdf requires 1 parameter: \"slope\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor. this->calcNorm(); } LauLinearPdf::~LauLinearPdf() { // Destructor } void LauLinearPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the value of the straight line for the given value of the abscissa. Double_t constVal = 1.0/(this->getMaxAbscissa() - this->getMinAbscissa()); constVal -= slope * (this->getMaxAbscissa() + this->getMinAbscissa()) * 0.5; Double_t value = slope*abscissa + constVal; // Make sure the PDF doesn't go negative if ( value < 0.0 ) { if ( posflag_ ) { std::cerr << "WARNING in LauLinearPdf::calcLikelihoodInfo : The PDF is negative, setting to zero" << std::endl; } value = 0.0; posflag_= kFALSE; } this->setUnNormPDFVal(value); } void LauLinearPdf::calcNorm() { // Nothing to calculate here since the PDF is already normalised to 1 this->setNorm(1.0); } void LauLinearPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t slope = slope_->unblindValue(); // Calculate the PDF height for the straight line LauAbscissas maxPoint(1); if (slope>0.0) { maxPoint[0] = this->getMaxAbscissa(); } else { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauMagPhaseCPCoeffSet.cc b/src/LauMagPhaseCPCoeffSet.cc index f7c066a..7839357 100644 --- a/src/LauMagPhaseCPCoeffSet.cc +++ b/src/LauMagPhaseCPCoeffSet.cc @@ -1,322 +1,321 @@ /* Copyright 2011 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCPCoeffSet.cc \brief File containing implementation of LauMagPhaseCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauMagPhaseCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauMagPhaseCPCoeffSet) LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const TString& compName, Double_t mag, Double_t phase, Double_t magBar, Double_t phaseBar, Bool_t magFixed, Bool_t phaseFixed,Bool_t magBarFixed, Bool_t phaseBarFixed) : LauAbsCoeffSet(compName), mag_(new LauParameter("Mag", mag, minMagnitude_, maxMagnitude_, magFixed)), phase_(new LauParameter("Phase", phase, minPhase_, maxPhase_, phaseFixed)), magBar_(new LauParameter("MagBar", magBar, minMagnitude_, maxMagnitude_, magBarFixed)), phaseBar_(new LauParameter("PhaseBar", phaseBar, minPhase_, maxPhase_, phaseBarFixed)), particleCoeff_( mag*TMath::Cos(phase), mag*TMath::Sin(phase) ), antiparticleCoeff_( magBar*TMath::Cos(phaseBar), magBar*TMath::Sin(phaseBar) ), acp_("ACP", (magBar*magBar - mag*mag)/(magBar*magBar + mag*mag), -1.0, 1.0) { } LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), mag_(0), phase_(0), magBar_(0), phaseBar_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { mag_ = rhs.mag_->createClone(constFactor); magBar_ = rhs.magBar_->createClone(constFactor); } else { mag_ = new LauParameter("Mag", rhs.mag_->value(), minMagnitude_, maxMagnitude_, rhs.mag_->fixed()); if ( rhs.mag_->blind() ) { const LauBlind* blinder = rhs.mag_->blinder(); mag_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } magBar_ = new LauParameter("MagBar", rhs.magBar_->value(), minMagnitude_, maxMagnitude_, rhs.magBar_->fixed()); if ( rhs.magBar_->blind() ) { const LauBlind* blinder = rhs.magBar_->blinder(); magBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { phase_ = rhs.phase_->createClone(constFactor); phaseBar_ = rhs.phaseBar_->createClone(constFactor); } else { phase_ = new LauParameter("Phase", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); if ( rhs.phase_->blind() ) { const LauBlind* blinder = rhs.phase_->blinder(); phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } phaseBar_ = new LauParameter("PhaseBar", rhs.phaseBar_->value(), minPhase_, maxPhase_, rhs.phaseBar_->fixed()); if ( rhs.phaseBar_->blind() ) { const LauBlind* blinder = rhs.phaseBar_->blinder(); phaseBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCPCoeffSet::getParameters() { std::vector pars; pars.push_back(mag_); pars.push_back(phase_); pars.push_back(magBar_); pars.push_back(phaseBar_); return pars; } void LauMagPhaseCPCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"mag = "<value()<<",\t"; std::cout<<"phase = "<value()<<",\t"; std::cout<<"magBar = "<value()<<",\t"; std::cout<<"phaseBar = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, mag_->error()); stream<<"$ & $"; print.printFormat(stream, phase_->value()); stream<<" \\pm "; print.printFormat(stream, phase_->error()); stream<<"$ & $"; print.printFormat(stream, magBar_->value()); stream<<" \\pm "; print.printFormat(stream, magBar_->error()); stream<<"$ & $"; print.printFormat(stream, phaseBar_->value()); stream<<" \\pm "; print.printFormat(stream, phaseBar_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "magnitude" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; mag_->initValue(value); mag_->value(value); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phase_->initValue(value); phase_->value(value); } if (magBar_->fixed() == kFALSE) { // Choose a value for "magnitude" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; magBar_->initValue(value); magBar_->value(value); } if (phaseBar_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phaseBar_->initValue(value); phaseBar_->value(value); } } void LauMagPhaseCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t mVal= mag_->value(); Double_t pVal= phase_->value(); Double_t mBarVal= magBar_->value(); Double_t pBarVal= phaseBar_->value(); Double_t genPhase = phase_->genValue(); Double_t genPhaseBar = phaseBar_->genValue(); // Check whether we have a negative magnitude. // If so make it positive and add pi to the phase. if (mVal < 0.0) { mVal *= -1.0; pVal += LauConstants::pi; } if (mBarVal < 0.0) { mBarVal *= -1.0; pBarVal += LauConstants::pi; } // Check now whether the phases lies in the right range (-pi to pi). Bool_t pWithinRange(kFALSE); Bool_t pBarWithinRange(kFALSE); while (pWithinRange == kFALSE && pBarWithinRange == kFALSE) { if (pVal > -LauConstants::pi && pVal < LauConstants::pi) { pWithinRange = kTRUE; } else { // Not within the specified range if (pVal > LauConstants::pi) { pVal -= LauConstants::twoPi; } else if (pVal < -LauConstants::pi) { pVal += LauConstants::twoPi; } } if (pBarVal > -LauConstants::pi && pBarVal < LauConstants::pi) { pBarWithinRange = kTRUE; } else { // Not within the specified range if (pBarVal > LauConstants::pi) { pBarVal -= LauConstants::twoPi; } else if (pBarVal < -LauConstants::pi) { pBarVal += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = pVal - genPhase; if (diff > LauConstants::pi) { pVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { pVal += LauConstants::twoPi; } diff = pBarVal - genPhaseBar; if (diff > LauConstants::pi) { pBarVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { pBarVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls mag_->value(mVal); mag_->updatePull(); phase_->value(pVal); phase_->updatePull(); magBar_->value(mBarVal); magBar_->updatePull(); phaseBar_->value(pBarVal); phaseBar_->updatePull(); } const LauComplex& LauMagPhaseCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( mag_->unblindValue()*TMath::Cos(phase_->unblindValue()), mag_->unblindValue()*TMath::Sin(phase_->unblindValue()) ); return particleCoeff_; } const LauComplex& LauMagPhaseCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( magBar_->unblindValue()*TMath::Cos(phaseBar_->unblindValue()), magBar_->unblindValue()*TMath::Sin(phaseBar_->unblindValue()) ); return antiparticleCoeff_; } void LauMagPhaseCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t magVal( coeff.abs() ); Double_t phaseVal( coeff.arg() ); Double_t magBarVal( coeffBar.abs() ); Double_t phaseBarVal( coeffBar.arg() ); mag_->value( magVal ); phase_->value( phaseVal ); magBar_->value( magBarVal ); phaseBar_->value( phaseBarVal ); if ( init ) { mag_->genValue( magVal ); phase_->genValue( phaseVal ); magBar_->genValue( magBarVal ); phaseBar_->genValue( phaseBarVal ); mag_->initValue( magVal ); phase_->initValue( phaseVal ); magBar_->initValue( magBarVal ); phaseBar_->initValue( phaseBarVal ); } } LauParameter LauMagPhaseCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t value(-99.0); value = (magBar_->value()*magBar_->value() - mag_->value()*mag_->value())/(magBar_->value()*magBar_->value() + mag_->value()*mag_->value()); // is it fixed? Bool_t fixed = magBar_->fixed() && mag_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauMagPhaseCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude ) { clone = new LauMagPhaseCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauMagPhaseCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauMagPhaseCoeffSet.cc b/src/LauMagPhaseCoeffSet.cc index b0addb0..4636873 100644 --- a/src/LauMagPhaseCoeffSet.cc +++ b/src/LauMagPhaseCoeffSet.cc @@ -1,224 +1,223 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCoeffSet.cc \brief File containing implementation of LauMagPhaseCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauMagPhaseCoeffSet) LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const TString& compName, Double_t magnitude, Double_t phase, Bool_t magFixed, Bool_t phaseFixed) : LauAbsCoeffSet(compName), magnitude_(new LauParameter("A",magnitude,minMagnitude_,maxMagnitude_,magFixed)), phase_(new LauParameter("Delta",phase,minPhase_,maxPhase_,phaseFixed)), coeff_(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)) { } LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), magnitude_(0), phase_(0), coeff_( rhs.coeff_ ) { if ( cloneOption == All || cloneOption == TieMagnitude ) { magnitude_ = rhs.magnitude_->createClone(constFactor); } else { magnitude_ = new LauParameter("A", rhs.magnitude_->value(), minMagnitude_, maxMagnitude_, rhs.magnitude_->fixed()); if ( rhs.magnitude_->blind() ) { const LauBlind* blinder = rhs.magnitude_->blinder(); magnitude_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TiePhase ) { phase_ = rhs.phase_->createClone(constFactor); } else { phase_ = new LauParameter("Delta", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); if ( rhs.phase_->blind() ) { const LauBlind* blinder = rhs.phase_->blinder(); phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCoeffSet::getParameters() { std::vector pars; pars.push_back(magnitude_); pars.push_back(phase_); return pars; } void LauMagPhaseCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCoeffSet::printParValues : Component \""<name()<<"\" has magnitude = "<value()<<" and phase = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, magnitude_->error()); stream<<"$ & $"; print.printFormat(stream, phase_->value()); stream<<" \\pm "; print.printFormat(stream, phase_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a magnitude between 0.0 and 2.0 Double_t mag = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; magnitude_->initValue(mag); magnitude_->value(mag); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi Double_t phase = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; phase_->initValue(phase); phase_->value(phase); } } void LauMagPhaseCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t mag = magnitude_->value(); Double_t phase = phase_->value(); Double_t genPhase = phase_->genValue(); // Check whether we have a negative magnitude. // If so make it positive and add pi to the phase. if (mag < 0.0) { mag *= -1.0; phase += LauConstants::pi; } // Check now whether the phase lies in the right range (-pi to pi). Bool_t withinRange(kFALSE); while (withinRange == kFALSE) { if (phase > -LauConstants::pi && phase <= LauConstants::pi) { withinRange = kTRUE; } else { // Not within the specified range if (phase > LauConstants::pi) { phase -= LauConstants::twoPi; } else if (phase <= -LauConstants::pi) { phase += LauConstants::twoPi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = phase - genPhase; if (diff > LauConstants::pi) { phase -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { phase += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls magnitude_->value(mag); magnitude_->updatePull(); phase_->value(phase); phase_->updatePull(); } const LauComplex& LauMagPhaseCoeffSet::particleCoeff() { coeff_.setRealImagPart(magnitude_->unblindValue()*TMath::Cos(phase_->unblindValue()), magnitude_->unblindValue()*TMath::Sin(phase_->unblindValue())); return coeff_; } const LauComplex& LauMagPhaseCoeffSet::antiparticleCoeff() { return this->particleCoeff(); } void LauMagPhaseCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t magVal( average.abs() ); Double_t phaseVal( average.arg() ); magnitude_->value( magVal ); phase_->value( phaseVal ); if ( init ) { magnitude_->genValue( magVal ); phase_->genValue( phaseVal ); magnitude_->initValue( magVal ); phase_->initValue( phaseVal ); } } LauParameter LauMagPhaseCoeffSet::acp() { TString parName(this->baseName()); parName += "_ACP"; return LauParameter(parName,0.0); } LauAbsCoeffSet* LauMagPhaseCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TiePhase || cloneOption == TieMagnitude ) { clone = new LauMagPhaseCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauMagPhaseCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauMergeDataFiles.cc b/src/LauMergeDataFiles.cc index 10328b1..ee4873d 100644 --- a/src/LauMergeDataFiles.cc +++ b/src/LauMergeDataFiles.cc @@ -1,310 +1,309 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMergeDataFiles.cc \brief File containing implementation of LauMergeDataFiles class. */ #include "LauMergeDataFiles.hh" #include #include #include "TLeaf.h" #include "TObjArray.h" #include "TSystem.h" -ClassImp(LauMergeDataFiles) LauMergeDataFiles::LauMergeDataFiles(const TString& fileName1, const TString& fileName2, const TString& treeName) : fileName1_(fileName1), fileName2_(fileName2), treeName_(treeName), inputFile1_(0), inputFile2_(0), inputTree1_(0), inputTree2_(0), outputFile_(0), outputTree_(0) { } LauMergeDataFiles::~LauMergeDataFiles() { if (inputFile1_ && inputFile1_->IsOpen()) { inputFile1_->Close(); } delete inputFile1_; if (inputFile2_ && inputFile2_->IsOpen()) { inputFile2_->Close(); } delete inputFile2_; if (outputFile_ && outputFile_->IsOpen()) { outputFile_->Close(); } delete outputFile_; } void LauMergeDataFiles::openInputFiles() { // open the two input ROOT files inputFile1_ = TFile::Open(fileName1_); if (!inputFile1_ || inputFile1_->IsZombie()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } inputTree1_ = dynamic_cast( inputFile1_->Get(treeName_) ); if (!inputTree1_) { std::cerr<<"Problem getting tree called "<Exit(EXIT_FAILURE); } inputFile2_ = TFile::Open(fileName2_); if (!inputFile2_ || inputFile2_->IsZombie()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } inputTree2_ = dynamic_cast( inputFile2_->Get(treeName_) ); if (!inputTree2_) { std::cerr<<"Problem getting tree called "<Exit(EXIT_FAILURE); } } void LauMergeDataFiles::setupInputTrees() { TObjArray* leaves1 = inputTree1_->GetListOfLeaves(); TObjArray* leaves2 = inputTree2_->GetListOfLeaves(); Int_t nLeaves1 = leaves1->GetEntries(); Int_t nLeaves2 = leaves2->GetEntries(); if ( nLeaves1 != nLeaves2 ) { std::cerr<<"Different number of leaves in the two input trees, not continuing."<SetBranchAddress("iExpt",&iExpt_); inputTree1_->SetBranchAddress("iEvtWithinExpt",&iEvtWithinExpt_); inputTree2_->SetBranchAddress("iExpt",&iExpt_); inputTree2_->SetBranchAddress("iEvtWithinExpt",&iEvtWithinExpt_); for (Int_t iLeaf(0); iLeaf((*leaves1)[iLeaf]); TString type = leaf->GetTypeName(); TString name = leaf->GetName(); Int_t size = leaf->GetNdata(); if ((name == "iExpt") || (name == "iEvtWithinExpt") || (size != 1)) { continue; } if ( type == "Double_t" ) { std::pair result = doubleVars_.insert(std::make_pair(name,0.0)); LeafDoubleMap::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree1_->SetBranchAddress(name,&(iter->second)); inputTree2_->SetBranchAddress(name,&(iter->second)); } } else if ( type == "Int_t" ) { std::pair result = integerVars_.insert(std::make_pair(name,0)); LeafIntegerMap::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree1_->SetBranchAddress(name,&(iter->second)); inputTree2_->SetBranchAddress(name,&(iter->second)); } } } std::cout<<"Set branch addresses for "<GetName()<<"\"..."<Branch("iExpt",&iExpt_,"iExpt/I"); outputTree_->Branch("iEvtWithinExpt",&iEvtWithinExpt_,"iEvtWithinExpt/I"); for (LeafDoubleMap::iterator iter = doubleVars_.begin(); iter != doubleVars_.end(); ++iter) { TString name = iter->first; Double_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/D"; outputTree_->Branch(name,address,thirdBit); } for (LeafIntegerMap::iterator iter = integerVars_.begin(); iter != integerVars_.end(); ++iter) { TString name = iter->first; Int_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/I"; outputTree_->Branch(name,address,thirdBit); } std::cout<<"Created "<openInputFiles(); this->setupInputTrees(); outputFile_ = TFile::Open(fileName,"recreate"); outputTree_ = new TTree(treeName_,""); this->setupOutputTree(); // loop over the trees and combine the corresponding experiments std::cout<<"Starting to combine the trees..."<findExperiments( inputTree1_, tree1Expts_ ); this->findExperiments( inputTree2_, tree2Expts_ ); // Check that the experiments in the two trees match if ( !this->checkExperimentMaps() ) { return; } // Loop through the experiments for ( ExptsMap::const_iterator iter1 = tree1Expts_.begin(); iter1 != tree1Expts_.end(); ++iter1 ) { // get the map element for tree2 Int_t expt = iter1->first; ExptsMap::const_iterator iter2 = tree2Expts_.find( expt ); // determine the number of entries in tree1 Int_t nEntriesInTree1 = iter1->second.second - iter1->second.first + 1; // read the entries from the trees, filling the output tree this->readExperiment( inputTree1_, iter1, 0 ); this->readExperiment( inputTree2_, iter2, nEntriesInTree1 ); } // Write the output file this->writeFile(); } void LauMergeDataFiles::findExperiments(TTree* tree, ExptsMap& exptsMap) { const Int_t nEntries = tree->GetEntries(); // loop through the tree for ( Int_t iEntry(0); iEntryGetEntry(iEntry); // see if we already have an element in the map for the // current experiment ExptsMap::iterator iter = exptsMap.find(iExpt_); if ( iter == exptsMap.end() ) { // if not, we need to add an element that points to // this entry in the tree as the start entry exptsMap.insert( std::make_pair( iExpt_, std::make_pair( iEntry, -99 ) ) ); // also we need to complete the map element for the // previous experiment with the previous tree entry // as the last entry ExptsMap::iterator previter = exptsMap.find(iExpt_-1); if ( previter != exptsMap.end() ) { previter->second.second = iEntry-1; } } } // need to complete the map element for the final experiment exptsMap[iExpt_].second = nEntries-1; } Bool_t LauMergeDataFiles::checkExperimentMaps() const { // first check that the two maps are the same size UInt_t size1 = tree1Expts_.size(); UInt_t size2 = tree2Expts_.size(); if ( size1 != size2 ) { std::cerr<<"ERROR in LauMergeDataFiles::checkExperimentMaps : Experiment maps are not the same size.\n"; std::cerr<<" : Tree from "<first; ExptsMap::const_iterator iter2 = tree2Expts_.find( expt ); if ( iter2 == tree2Expts_.end() ) { std::cerr<<"ERROR in LauMergeDataFiles::checkExperimentMaps : Cannot find experiment "<second.first; const Int_t lastEntry = expt->second.second; // loop through all the entries for ( Int_t iEntry(firstEntry); iEntry<=lastEntry; ++iEntry ) { // get the entry from the tree tree->GetEntry( iEntry ); // apply the offset to the "event within experiment" variable iEvtWithinExpt_ += offset; // fill the output tree outputTree_->Fill(); } } void LauMergeDataFiles::writeFile() { std::cout<<"Building experiment:event index"<BuildIndex("iExpt","iEvtWithinExpt"); std::cout<<"Writing data to outputfile "<GetName()<SetDirectory(outputFile_); outputFile_->Write(); // clean-up outputFile_->Close(); delete outputFile_; outputFile_ = 0; outputTree_ = 0; inputFile1_->Close(); delete inputFile1_; inputFile1_ = 0; inputTree1_ = 0; inputFile2_->Close(); delete inputFile2_; inputFile2_ = 0; inputTree2_ = 0; doubleVars_.clear(); integerVars_.clear(); tree1Expts_.clear(); tree2Expts_.clear(); } diff --git a/src/LauMinuit.cc b/src/LauMinuit.cc index b682b34..cdf3825 100644 --- a/src/LauMinuit.cc +++ b/src/LauMinuit.cc @@ -1,301 +1,300 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMinuit.cc \brief File containing implementation of LauMinuit methods. */ #include "LauMinuit.hh" #include "LauFitObject.hh" #include "LauFitter.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" #include "TMatrixD.h" #include "TVirtualFitter.h" #include #include #include // It's necessary to define an external function that specifies the address of the function // that Minuit needs to minimise. Minuit doesn't know about any classes - therefore // use gMinuit->SetFCN(external_function), gMinuit->SetObjectFit(this). // Here, we use TVirtualFitter* fitter instead of gMinuit, defined below. // Then, within the external function, invoke an object from this class (LauAllModel), // and use the member functions to access the parameters/variables. extern void logLikeFun(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag); -ClassImp(LauMinuit) LauMinuit::LauMinuit( const UInt_t maxPar, const LauOutputLevel verbosity ) : LauAbsFitter(), maxPar_{maxPar}, outputLevel_{verbosity} { TVirtualFitter::SetDefaultFitter( "Minuit" ); minuit_ = TVirtualFitter::Fitter( nullptr, maxPar_ ); // Set the printout level std::array argL { static_cast(outputLevel_) }; minuit_->ExecuteCommand("SET PRINT", argL.data(), argL.size()); if ( outputLevel_ == LauOutputLevel::None ) { minuit_->ExecuteCommand("SET NOWARNINGS", argL.data(), 0); } } void LauMinuit::initialise( LauFitObject* fitObj, const std::vector& parameters ) { // Check whether we're going to use asymmetric errors if ( outputLevel_ > LauOutputLevel::Quiet ) { if (useAsymmFitErrors_ == kTRUE) { std::cout << "INFO in LauMinuit::fit : We are going to calculate the asymmetric fit errors." << std::endl; std::cout << " : This will, in general, significantly increase the CPU time required for fitting." << std::endl; } else { std::cout << "INFO in LauMinuit::fit : Only parabolic errors will be calculated." << std::endl; } } // Store the parameters params_ = parameters; // Hook the external likelihood function to this LauFitter::fitter() and this class. minuit_->SetFCN( logLikeFun ); minuit_->SetObjectFit( fitObj ); // Clear any stored parameters etc... before using minuit_->Clear(); nParams_ = params_.size(); if ( outputLevel_ > LauOutputLevel::Quiet ) { std::cout << "INFO in LauMinuit::initialise : Setting fit parameters" << std::endl; std::cout << " : Total number of parameters = " << nParams_ << std::endl; } // Define the default relative error const Double_t defaultError(0.01); // Set-up the parameters for (UInt_t i = 0; i < nParams_; ++i) { TString name = params_[i]->name(); Double_t initVal = params_[i]->initValue(); Double_t initErr = params_[i]->error(); // If we do not have a supplied estimate of the error, we should make a reasonable guess if ( initErr == 0.0 ) { if ( initVal == 0.0 ) { initErr = defaultError; } else if ( TMath::Abs(initErr/initVal) < 1e-6 ) { initErr = TMath::Abs(defaultError * initVal); } } Double_t minVal = params_[i]->minValue(); Double_t maxVal = params_[i]->maxValue(); Bool_t secondStage = params_[i]->secondStage(); if (this->twoStageFit() && secondStage == kTRUE) { params_[i]->fixed(kTRUE); } Bool_t fixVar = params_[i]->fixed(); if ( outputLevel_ > LauOutputLevel::Quiet ) { std::cout << " : Setting parameter " << i << " called " << name << " to have initial value " << initVal << ", error " << initErr << " and range " << minVal << " to " << maxVal << std::endl; } minuit_->SetParameter(i, name, initVal, initErr, minVal, maxVal); // Fix parameter if required if (fixVar == kTRUE) { if ( outputLevel_ > LauOutputLevel::Quiet ) { std::cout << " : Fixing parameter " << i << std::endl; } minuit_->FixParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); // Need to set the "SET ERR" command to +0.5 for +/-1 sigma errors // for maximum likelihood fit. Very important command, otherwise all // extracted errors will be too big, and pull distributions will be too narrow! // TODO - The alternative to this is to make FCN = -2log(L) rather than -log(L) std::array argL { 0.5 }; fitStatus_.status = minuit_->ExecuteCommand("SET ERR", argL.data(), argL.size()); //argL[0] = 0; //fitStatus_.status = minuit_->ExecuteCommand("SET STRATEGY", argL.data(), argL.size()); } LauFitObject* LauMinuit::getFitObject() { return (minuit_!=nullptr) ? dynamic_cast( minuit_->GetObjectFit() ) : nullptr; } const LauAbsFitter::FitStatus& LauMinuit::minimise() { std::array arglist { 1000.0*nParams_, // maximum iterations 0.05 // tolerance -> min EDM = 0.001*tolerance (0.05) }; fitStatus_.status = minuit_->ExecuteCommand("MIGRAD", arglist.data(), arglist.size()); // Dummy variables - need to feed them to the function // used for getting NLL, EDM and error matrix status Double_t errdef; Int_t nvpar, nparx; if (fitStatus_.status != 0) { if ( outputLevel_ > LauOutputLevel::None ) { std::cerr << "ERROR in LauMinuit::minimise : Error in minimising loglike." << std::endl; } } else { // Check that the error matrix is ok fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); if ( outputLevel_ > LauOutputLevel::Quiet ) { std::cout << "INFO in LauMinuit::minimise : Error matrix status after MIGRAD is: " << fitStatus_.status << std::endl; } // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix // Fit result was OK. Now get the more precise errors. fitStatus_.status = minuit_->ExecuteCommand("HESSE", arglist.data(), 1); if (fitStatus_.status != 0) { if ( outputLevel_ > LauOutputLevel::None ) { std::cerr << "ERROR in LauMinuit::minimise : Error in HESSE routine." << std::endl; } } else { // Check that the error matrix is ok fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); if ( outputLevel_ > LauOutputLevel::Quiet ) { std::cout << "INFO in LauMinuit::minimise : Error matrix status after HESSE is: " << fitStatus_.status << std::endl; } // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix // Symmetric errors and eror matrix were OK. // Get asymmetric errors if asked for. if (useAsymmFitErrors_ == kTRUE) { LauFitObject* fitObj = this->getFitObject(); fitObj->withinAsymErrorCalc( kTRUE ); fitStatus_.status = minuit_->ExecuteCommand("MINOS", arglist.data(), 1); fitObj->withinAsymErrorCalc( kFALSE ); if (fitStatus_.status != 0) { std::cerr << "ERROR in LauMinuit::minimise : Error in MINOS routine." << std::endl; } } } } // Print results fitStatus_.status = minuit_->GetStats(fitStatus_.NLL, fitStatus_.EDM, errdef, nvpar, nparx); if ( outputLevel_ > LauOutputLevel::None ) { std::cout << "INFO in LauMinuit::minimise : Final error matrix status is: " << fitStatus_.status << std::endl; } // 0= not calculated at all // 1= approximation only, not accurate // 2= full matrix, but forced positive-definite // 3= full accurate covariance matrix if ( outputLevel_ > LauOutputLevel::None ) { minuit_->PrintResults(3, fitStatus_.NLL); } // Retrieve the covariance matrix from the fitter // For some reason the array returned is as if the matrix is of dimension nParams_ x nParams_ // but only the elements within the sub-matrix nFreeParams_ x nFreeParams_ have values, // the "trailing" elements are zero, so we trim them off. Double_t* covMatrix = minuit_->GetCovarianceMatrix(); covMatrix_.Clear(); covMatrix_.ResizeTo( nParams_, nParams_ ); covMatrix_.SetMatrixArray( covMatrix ); covMatrix_.ResizeTo( nFreeParams_, nFreeParams_ ); return fitStatus_; } void LauMinuit::fixSecondStageParameters() { for (UInt_t i{0}; i < nParams_; ++i) { if ( params_[i]->secondStage() ) { params_[i]->fixed(kTRUE); minuit_->FixParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); } void LauMinuit::releaseSecondStageParameters() { for (UInt_t i{0}; i < nParams_; ++i) { if ( params_[i]->secondStage() ) { params_[i]->fixed(kFALSE); minuit_->ReleaseParameter(i); } } LauParamFixed pred; nFreeParams_ = nParams_ - std::count_if(params_.begin(),params_.end(),pred); } void LauMinuit::updateParameters() { for (UInt_t i{0}; i < nParams_; ++i) { // Get the value and errors from MINUIT Double_t value { minuit_->GetParameter(i) }; Double_t error{0.0}; Double_t negError{0.0}; Double_t posError{0.0}; Double_t globalcc{0.0}; minuit_->GetErrors(i, posError, negError, error, globalcc); params_[i]->valueAndErrors(value, error, negError, posError); params_[i]->globalCorrelationCoeff(globalcc); } } // Definition of the fitting function for Minuit void logLikeFun(Int_t& npar, Double_t* /*first_derivatives*/, Double_t& f, Double_t* par, Int_t /*iflag*/) { // Routine that specifies the negative log-likelihood function for the fit. // Used by the MINUIT minimising code. LauFitObject* theModel = LauFitter::fitter().getFitObject(); // Set the internal parameters for this model using parameters from Minuit (pars): theModel->setParsFromMinuit( par, npar ); // Set the value of f to be the total negative log-likelihood for the data sample. f = theModel->getTotNegLogLikelihood(); } diff --git a/src/LauModIndPartWaveMagPhase.cc b/src/LauModIndPartWaveMagPhase.cc index c9176eb..0168eae 100644 --- a/src/LauModIndPartWaveMagPhase.cc +++ b/src/LauModIndPartWaveMagPhase.cc @@ -1,141 +1,140 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveMagPhase.cc \brief File containing implementation of LauModIndPartWaveMagPhase class. */ #include #include #include "Lau1DCubicSpline.hh" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauModIndPartWaveMagPhase.hh" #include "LauResonanceInfo.hh" -ClassImp(LauModIndPartWaveMagPhase) LauModIndPartWaveMagPhase::LauModIndPartWaveMagPhase(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsModIndPartWave(resInfo, resPairAmpInt, daughters) { } LauModIndPartWaveMagPhase::~LauModIndPartWaveMagPhase() { } void LauModIndPartWaveMagPhase::createAmpParameters(const UInt_t iKnot) { const TString& parNameBase = this->getSanitisedName(); const Bool_t secondStage = this->floatKnotsSecondStage(); std::vector& magnitudePars = this->getAmp1Pars(); std::vector& phasePars = this->getAmp2Pars(); TString magName(parNameBase); magName += "_A"; magName += iKnot; magnitudePars.push_back(this->getResInfo()->getExtraParameter( magName )); if( magnitudePars[iKnot] == 0) { magnitudePars[iKnot] = new LauParameter( magName, 1.0, 0.0, 10.0, kFALSE); magnitudePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(magnitudePars[iKnot]); } TString phaseName(parNameBase); phaseName += "_d"; phaseName += iKnot; phasePars.push_back(this->getResInfo()->getExtraParameter( phaseName )); if( phasePars[iKnot] == 0) { phasePars[iKnot] = new LauParameter( phaseName, 1.0, -6.0*LauConstants::pi, 6.0*LauConstants::pi, kFALSE); phasePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(phasePars[iKnot]); } } void LauModIndPartWaveMagPhase::setKnotAmp(const UInt_t knot, const Double_t magVal, const Double_t phaseVal, const Bool_t fixMagnitude, const Bool_t fixPhase) { const UInt_t nknots = this->nKnots(); if ( knot >= nknots ) { std::cerr << "WARNING in LauModIndPartWaveMagPhase::setKnotAmp : Index " << knot << " does not correspond to an existing knot in resonance " << this->getResonanceName() << std::endl; std::cerr << " : Index must be in range 0 to " << nknots-1 << std::endl; return; } const std::vector& masses = this->getMasses(); std::vector& magnitudes = this->getAmp1Vals(); std::vector& phases = this->getAmp2Vals(); std::vector& magnitudePars = this->getAmp1Pars(); std::vector& phasePars = this->getAmp2Pars(); magnitudes[knot] = magVal; magnitudePars[knot]->value(magVal); magnitudePars[knot]->genValue(magVal); magnitudePars[knot]->initValue(magVal); magnitudePars[knot]->fixed(fixMagnitude); phases[knot] = phaseVal; phasePars[knot]->value(phaseVal); phasePars[knot]->genValue(phaseVal); phasePars[knot]->initValue(phaseVal); phasePars[knot]->fixed(fixPhase); if ( knot == 0 ) { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at lower kinematic limit (" << masses[knot] << ")" << std::endl; } else if ( knot == nknots-1 ) { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at upper kinematic limit (" << masses[knot] << ")" << std::endl; } else { std::cout << "INFO in LauModIndPartWaveMagPhase::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at mass " << masses[knot] << std::endl; } if ( fixMagnitude ) { std::cout << " : Magnitude fixed to " << magVal << std::endl; } else { std::cout << " : Magnitude set to " << magVal << std::endl; } if ( fixPhase ) { std::cout << " : Phase fixed to " << phaseVal << std::endl; } else { std::cout << " : Phase set to " << phaseVal << std::endl; } } void LauModIndPartWaveMagPhase::evaluateAmplitude(const Double_t mass) { const Lau1DCubicSpline* splineMag = this->getSpline1(); const Lau1DCubicSpline* splinePhase = this->getSpline2(); const Double_t mag = splineMag->evaluate(mass); const Double_t phase = splinePhase->evaluate(mass); this->setAmp(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); } diff --git a/src/LauModIndPartWaveRealImag.cc b/src/LauModIndPartWaveRealImag.cc index 7e63ba0..2d224e8 100644 --- a/src/LauModIndPartWaveRealImag.cc +++ b/src/LauModIndPartWaveRealImag.cc @@ -1,141 +1,140 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauModIndPartWaveRealImag.cc \brief File containing implementation of LauModIndPartWaveRealImag class. */ #include #include #include "Lau1DCubicSpline.hh" #include "LauConstants.hh" #include "LauKinematics.hh" #include "LauModIndPartWaveRealImag.hh" #include "LauResonanceInfo.hh" -ClassImp(LauModIndPartWaveRealImag) LauModIndPartWaveRealImag::LauModIndPartWaveRealImag(LauResonanceInfo* resInfo, Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsModIndPartWave(resInfo, resPairAmpInt, daughters) { } LauModIndPartWaveRealImag::~LauModIndPartWaveRealImag() { } void LauModIndPartWaveRealImag::createAmpParameters(const UInt_t iKnot) { const TString& parNameBase = this->getSanitisedName(); const Bool_t secondStage = this->floatKnotsSecondStage(); std::vector& rePars = this->getAmp1Pars(); std::vector& imPars = this->getAmp2Pars(); TString reName(parNameBase); reName += "_Re"; reName += iKnot; rePars.push_back(this->getResInfo()->getExtraParameter( reName )); if( rePars[iKnot] == 0) { rePars[iKnot] = new LauParameter( reName, 1.0, -10.0, 10.0, kFALSE); rePars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(rePars[iKnot]); } TString imName(parNameBase); imName += "_Im"; imName += iKnot; imPars.push_back(this->getResInfo()->getExtraParameter( imName )); if( imPars[iKnot] == 0) { imPars[iKnot] = new LauParameter( imName, 1.0, -10.0, 10.0, kFALSE); imPars[iKnot]->secondStage(secondStage); this->getResInfo()->addExtraParameter(imPars[iKnot]); } } void LauModIndPartWaveRealImag::setKnotAmp(const UInt_t knot, const Double_t realVal, const Double_t imagVal, const Bool_t fixRealPart, const Bool_t fixImagPart) { const UInt_t nknots = this->nKnots(); if ( knot >= nknots ) { std::cerr << "WARNING in LauModIndPartWaveRealImag::setKnotAmp : Index " << knot << " does not correspond to an existing knot in resonance " << this->getResonanceName() << std::endl; std::cerr << " : Index must be in range 0 to " << nknots-1 << std::endl; return; } const std::vector& masses = this->getMasses(); std::vector& realVals = this->getAmp1Vals(); std::vector& imagVals = this->getAmp2Vals(); std::vector& realPars = this->getAmp1Pars(); std::vector& imagPars = this->getAmp2Pars(); realVals[knot] = realVal; realPars[knot]->value(realVal); realPars[knot]->genValue(realVal); realPars[knot]->initValue(realVal); realPars[knot]->fixed(fixRealPart); imagVals[knot] = imagVal; imagPars[knot]->value(imagVal); imagPars[knot]->genValue(imagVal); imagPars[knot]->initValue(imagVal); imagPars[knot]->fixed(fixImagPart); if ( knot == 0 ) { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at lower kinematic limit (" << masses[knot] << ")" << std::endl; } else if ( knot == nknots-1 ) { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at upper kinematic limit (" << masses[knot] << ")" << std::endl; } else { std::cout << "INFO in LauModIndPartWaveRealImag::setKnotAmp : Knot updated in resonance " << this->getResonanceName() << " at mass " << masses[knot] << std::endl; } if ( fixRealPart ) { std::cout << " : Real part fixed to " << realVal << std::endl; } else { std::cout << " : Real part set to " << realVal << std::endl; } if ( fixImagPart ) { std::cout << " : Imaginary part fixed to " << imagVal << std::endl; } else { std::cout << " : Imaginary part set to " << imagVal << std::endl; } } void LauModIndPartWaveRealImag::evaluateAmplitude(const Double_t mass) { const Lau1DCubicSpline* splineReal = this->getSpline1(); const Lau1DCubicSpline* splineImag = this->getSpline2(); const Double_t re = splineReal->evaluate(mass); const Double_t im = splineImag->evaluate(mass); this->setAmp(re, im); } diff --git a/src/LauNRAmplitude.cc b/src/LauNRAmplitude.cc index e3c2e4f..3e906c8 100644 --- a/src/LauNRAmplitude.cc +++ b/src/LauNRAmplitude.cc @@ -1,284 +1,283 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNRAmplitude.cc \brief File containing implementation of LauNRAmplitude class. */ #include #include "LauKinematics.hh" #include "LauNRAmplitude.hh" #include "LauResonanceInfo.hh" -ClassImp(LauNRAmplitude) LauNRAmplitude::LauNRAmplitude(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), d_(0), c1_(0), c2_(0), p1_(0), p2_(0) { // Default values for parameters, taken from arXiv:0709.0075v1 [hep-ph] const Double_t dVal(1.3232e-3); const Double_t c1Val(0.65); const Double_t c2Val(0.55); const Double_t p1Val(18.0); const Double_t p2Val(15.0); const TString& parNameBase = this->getSanitisedName(); TString dName(parNameBase); dName += "_d"; d_ = resInfo->getExtraParameter( dName ); if ( d_ == 0 ) { d_ = new LauParameter( dName, dVal, 0.0, 1.0, kTRUE ); d_->secondStage(kTRUE); resInfo->addExtraParameter( d_ ); } TString c1Name(parNameBase); c1Name += "_c1"; c1_ = resInfo->getExtraParameter( c1Name ); if ( c1_ == 0 ) { c1_ = new LauParameter( c1Name, c1Val, 0.0, 2.0, kTRUE ); c1_->secondStage(kTRUE); resInfo->addExtraParameter( c1_ ); } TString c2Name(parNameBase); c2Name += "_c2"; c2_ = resInfo->getExtraParameter( c2Name ); if ( c2_ == 0 ) { c2_ = new LauParameter( c2Name, c2Val, 0.0, 2.0, kTRUE ); c2_->secondStage(kTRUE); resInfo->addExtraParameter( c2_ ); } TString p1Name(parNameBase); p1Name += "_p1"; p1_ = resInfo->getExtraParameter( p1Name ); if ( p1_ == 0 ) { p1_ = new LauParameter( p1Name, p1Val, 0.0, 50.0, kTRUE ); p1_->secondStage(kTRUE); resInfo->addExtraParameter( p1_ ); } TString p2Name(parNameBase); p2Name += "_p2"; p2_ = resInfo->getExtraParameter( p2Name ); if ( p2_ == 0 ) { p2_ = new LauParameter( p2Name, p2Val, 0.0, 50.0, kTRUE ); p2_->secondStage(kTRUE); resInfo->addExtraParameter( p2_ ); } } LauNRAmplitude::~LauNRAmplitude() { } void LauNRAmplitude::initialise() { } LauComplex LauNRAmplitude::amplitude(const LauKinematics* kinematics) { // Get the information from the kinematics object const Double_t m13Sq = kinematics->getm13Sq(); const Double_t m23Sq = kinematics->getm23Sq(); const Double_t m13 = kinematics->getm13(); const Double_t m23 = kinematics->getm23(); // Calculate the magnitude Double_t magnitude = TMath::Sqrt( m13 * m23 * this->f(m23Sq, c1_->unblindValue(), p1_->unblindValue()) * this->f(m13Sq, c2_->unblindValue(), p2_->unblindValue()) * TMath::Exp( -1.0 * d_->unblindValue() * m13Sq*m13Sq * m23Sq*m23Sq ) ); // return the amplitude LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } LauComplex LauNRAmplitude::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauNRAmplitude::resAmp : This method shouldn't get called." << std::endl; std::cerr << " Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } Double_t LauNRAmplitude::f(const Double_t s, const Double_t c, const Double_t p) const { return 1.0 / (1.0 + TMath::Exp( c * (s-p) )); } const std::vector& LauNRAmplitude::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixdParameter() ) { this->addFloatingParameter( d_ ); } if ( ! this->fixc1Parameter() ) { this->addFloatingParameter( c1_ ); } if ( ! this->fixc2Parameter() ) { this->addFloatingParameter( c2_ ); } if ( ! this->fixp1Parameter() ) { this->addFloatingParameter( p1_ ); } if ( ! this->fixp2Parameter() ) { this->addFloatingParameter( p2_ ); } return this->getParameters(); } void LauNRAmplitude::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the NRAmplitude lineshape dynamics if (name == "d") { this->setdParameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude d = " << this->getdParameter() << std::endl; } else if (name == "c1") { this->setc1Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude c1 = " << this->getc1Parameter() << std::endl; } else if (name == "c2") { this->setc2Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude c2 = " << this->getc2Parameter() << std::endl; } else if (name == "p1") { this->setp1Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude p1 = " << this->getp1Parameter() << std::endl; } else if (name == "p2") { this->setp2Parameter(value); std::cout << "INFO in LauNRAmplitude::setResonanceParameter : Setting NRAmplitude p2 = " << this->getp2Parameter() << std::endl; } else { std::cerr << "WARNING in LauNRAmplitude::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauNRAmplitude::floatResonanceParameter(const TString& name) { if (name == "d") { if ( d_->fixed() ) { d_->fixed( kFALSE ); this->addFloatingParameter( d_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "c1") { if ( c1_->fixed() ) { c1_->fixed( kFALSE ); this->addFloatingParameter( c1_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "c2") { if ( c2_->fixed() ) { c2_->fixed( kFALSE ); this->addFloatingParameter( c2_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "p1") { if ( p1_->fixed() ) { p1_->fixed( kFALSE ); this->addFloatingParameter( p1_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "p2") { if ( p2_->fixed() ) { p2_->fixed( kFALSE ); this->addFloatingParameter( p2_ ); } else { std::cerr << "WARNING in LauNRAmplitude::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauNRAmplitude::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauNRAmplitude::getResonanceParameter(const TString& name) { if (name == "d") { return d_; } else if (name == "c1") { return c1_; } else if (name == "c2") { return c2_; } else if (name == "p1") { return p1_; } else if (name == "p2") { return p2_; } else { std::cerr << "WARNING in LauNRAmplitude::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauNRAmplitude::setdParameter(const Double_t d) { d_->value( d ); d_->genValue( d ); d_->initValue( d ); } void LauNRAmplitude::setc1Parameter(const Double_t c1) { c1_->value( c1 ); c1_->genValue( c1 ); c1_->initValue( c1 ); } void LauNRAmplitude::setc2Parameter(const Double_t c2) { c2_->value( c2 ); c2_->genValue( c2 ); c2_->initValue( c2 ); } void LauNRAmplitude::setp1Parameter(const Double_t p1) { p1_->value( p1 ); p1_->genValue( p1 ); p1_->initValue( p1 ); } void LauNRAmplitude::setp2Parameter(const Double_t p2) { p2_->value( p2 ); p2_->genValue( p2 ); p2_->initValue( p2 ); } diff --git a/src/LauNovosibirskPdf.cc b/src/LauNovosibirskPdf.cc index 3e363e4..2f304c1 100644 --- a/src/LauNovosibirskPdf.cc +++ b/src/LauNovosibirskPdf.cc @@ -1,152 +1,151 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauNovosibirskPdf.cc \brief File containing implementation of LauNovosibirskPdf class. */ #include using std::cout; using std::cerr; using std::endl; #include "TMath.h" #include "TSystem.h" #include "LauNovosibirskPdf.hh" #include "LauConstants.hh" -ClassImp(LauNovosibirskPdf) LauNovosibirskPdf::LauNovosibirskPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), mean_(0), sigma_(0), tail_(0) { // Constructor for the Novosibirsk PDF. // // The parameters in params are the mean, sigma and tail. // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. mean_ = this->findParameter("mean"); sigma_ = this->findParameter("sigma"); tail_ = this->findParameter("tail"); if ((this->nParameters() != 3) || (mean_ == 0) || (sigma_ == 0) || (tail_ == 0)) { cerr<<"ERROR in LauNovosibirskPdf constructor: LauNovosibirskPdf requires 3 parameters: \"mean\", \"sigma\"and \"tail\" "<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauNovosibirskPdf::~LauNovosibirskPdf() { // Destructor } void LauNovosibirskPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t mean = mean_->unblindValue(); Double_t sigma = sigma_->unblindValue(); Double_t tail = tail_->unblindValue(); // Evaluate the Novosibirsk PDF value Double_t qa(0.0), qb(0.0), qx(0.0), qy(0.0); Double_t arg(0.0); Double_t value(0.0); if(TMath::Abs(tail) < 1.e-7) arg = 0.5*((abscissa - mean)/sigma)*((abscissa - mean)/sigma); else { qa = tail*TMath::Sqrt(LauConstants::log4); qb = TMath::SinH(qa)/qa; qx = (abscissa - mean)/sigma*qb; qy = 1.0+ tail*qx; //---- Cutting curve from right side if( qy > 1.E-7) { arg = 0.5*( (log(qy)/tail)*(log(qy)/tail) + tail*tail); }else{ arg = 15.0; } } value = TMath::Exp(-arg); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } this->setUnNormPDFVal(value); } void LauNovosibirskPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t mean = mean_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = mean; // Calculate the PDF height for the Bifurcated Gaussian function. if (mean < this->getMinAbscissa()) { maxPoint[0] = this->getMinAbscissa(); } else if (mean > this->getMaxAbscissa()) { maxPoint[0] = this->getMaxAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); // Multiply by a small factor to avoid problems from rounding errors height *= (1.0 + 1e-1); this->setMaxHeight(height); } diff --git a/src/LauParameter.cc b/src/LauParameter.cc index 535e017..02cab82 100644 --- a/src/LauParameter.cc +++ b/src/LauParameter.cc @@ -1,762 +1,761 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParameter.cc \brief File containing implementation of LauParameter class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::map; #include "TRandom.h" #include "LauParameter.hh" #include "LauRandom.hh" -ClassImp(LauParameter) LauParameter::LauParameter() : name_(""), value_(0.0), error_(0.0), negError_(0.0), posError_(0.0), genValue_(0.0), initValue_(0.0), minValue_(0.0), maxValue_(0.0), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(const TString& parName) : name_(parName), value_(0.0), error_(0.0), negError_(0.0), posError_(0.0), genValue_(0.0), initValue_(0.0), minValue_(0.0), maxValue_(0.0), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(Double_t parValue) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(parValue-1e-6), maxValue_(parValue+1e-6), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(const TString& parName, Double_t parValue) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(parValue-1e-6), maxValue_(parValue+1e-6), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { } LauParameter::LauParameter(Double_t parValue, Double_t min, Double_t max) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(Double_t parValue, Double_t parError, Double_t min, Double_t max) : name_(""), value_(parValue), error_(parError), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(Double_t parValue, Double_t min, Double_t max, Bool_t parFixed) : name_(""), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(parFixed), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t min, Double_t max) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t min, Double_t max, Bool_t parFixed) : name_(parName), value_(parValue), error_(0.0), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(parFixed), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const TString& parName, Double_t parValue, Double_t parError, Double_t min, Double_t max) : name_(parName), value_(parValue), error_(parError), negError_(0.0), posError_(0.0), genValue_(parValue), initValue_(parValue), minValue_(min), maxValue_(max), fixed_(kTRUE), secondStage_(kFALSE), gaussConstraint_(kFALSE), constraintTrueMean_(0.0), constraintMean_(0.0), constraintWidth_(0.0), gcc_(0.0), bias_(0.0), pull_(0.0), clone_(kFALSE), parent_(0), blinder_(0) { this->checkRange(); } LauParameter::LauParameter(const LauParameter& rhs) : TObject(rhs), LauAbsRValue(rhs), name_(rhs.name_), value_(rhs.value_), error_(rhs.error_), negError_(rhs.negError_), posError_(rhs.posError_), genValue_(rhs.genValue_), initValue_(rhs.initValue_), minValue_(rhs.minValue_), maxValue_(rhs.maxValue_), fixed_(rhs.fixed_), secondStage_(rhs.secondStage_), gaussConstraint_(rhs.gaussConstraint_), constraintTrueMean_(rhs.constraintTrueMean_), constraintMean_(rhs.constraintMean_), constraintWidth_(rhs.constraintWidth_), gcc_(rhs.gcc_), bias_(rhs.bias_), pull_(rhs.pull_), clone_(rhs.clone_), parent_(rhs.parent_), clones_(rhs.clones_), blinder_((rhs.blinder_==0) ? 0 : new LauBlind(*(rhs.blinder_))) { } LauParameter& LauParameter::operator=(const LauParameter& rhs) { if (&rhs != this) { TObject::operator=(rhs); LauAbsRValue::operator=(rhs); name_ = rhs.name_; value_ = rhs.value_; error_ = rhs.error_; negError_ = rhs.negError_; posError_ = rhs.posError_; genValue_ = rhs.genValue_; initValue_ = rhs.initValue_; minValue_ = rhs.minValue_; maxValue_ = rhs.maxValue_; fixed_ = rhs.fixed_; secondStage_ = rhs.secondStage_; gaussConstraint_ = rhs.gaussConstraint_; constraintTrueMean_ = rhs.constraintTrueMean_; constraintMean_ = rhs.constraintMean_; constraintWidth_ = rhs.constraintWidth_; gcc_ = rhs.gcc_; bias_ = rhs.bias_; pull_ = rhs.pull_; clone_ = rhs.clone_; parent_ = rhs.parent_; clones_ = rhs.clones_; delete blinder_; blinder_ = (rhs.blinder_==0) ? 0 : new LauBlind(*(rhs.blinder_)); } return *this; } LauParameter::~LauParameter() { delete blinder_; } std::vector LauParameter::getPars() { std::vector list; list.push_back(this); return list; } void LauParameter::value(Double_t newValue) { if (this->clone()) { parent_->value(newValue); } else { this->checkRange(newValue,this->minValue(),this->maxValue()); this->updateClones(kTRUE); } } void LauParameter::error(Double_t newError) { if (this->clone()) { parent_->error(newError); } else { error_ = TMath::Abs(newError); this->updateClones(kFALSE); } } void LauParameter::negError(Double_t newNegError) { if (this->clone()) { parent_->negError(newNegError); } else { negError_ = TMath::Abs(newNegError); this->updateClones(kFALSE); } } void LauParameter::posError(Double_t newPosError) { if (this->clone()) { parent_->posError(newPosError); } else { posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::errors(Double_t newError, Double_t newNegError, Double_t newPosError) { if (this->clone()) { parent_->errors(newError,newNegError,newPosError); } else { error_ = TMath::Abs(newError); negError_ = TMath::Abs(newNegError); posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::valueAndErrors(Double_t newValue, Double_t newError, Double_t newNegError, Double_t newPosError) { if (this->clone()) { parent_->valueAndErrors(newValue,newError,newNegError,newPosError); } else { this->checkRange(newValue,this->minValue(),this->maxValue()); error_ = TMath::Abs(newError); negError_ = TMath::Abs(newNegError); posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::globalCorrelationCoeff(Double_t newGCCValue) { if (this->clone()) { parent_->globalCorrelationCoeff(newGCCValue); } else { gcc_ = newGCCValue; this->updateClones(kFALSE); } } void LauParameter::genValue(Double_t newGenValue) { if (this->clone()) { parent_->genValue(newGenValue); } else { genValue_ = newGenValue; this->updateClones(kFALSE); } } void LauParameter::initValue(Double_t newInitValue) { if (this->clone()) { parent_->initValue(newInitValue); } else { initValue_ = newInitValue; this->updateClones(kFALSE); } } void LauParameter::minValue(Double_t newMinValue) { if (this->clone()) { parent_->minValue(newMinValue); } else { this->checkRange(this->value(),newMinValue,this->maxValue()); this->updateClones(kFALSE); } } void LauParameter::maxValue(Double_t newMaxValue) { if (this->clone()) { parent_->maxValue(newMaxValue); } else { this->checkRange(this->value(),this->minValue(),newMaxValue); this->updateClones(kFALSE); } } void LauParameter::range(Double_t newMinValue, Double_t newMaxValue) { if (this->clone()) { parent_->range(newMinValue,newMaxValue); } else { this->checkRange(this->value(),newMinValue,newMaxValue); this->updateClones(kFALSE); } } void LauParameter::valueAndRange(Double_t newValue, Double_t newMinValue, Double_t newMaxValue) { if (this->clone()) { parent_->valueAndRange(newValue,newMinValue,newMaxValue); } else { this->checkRange(newValue,newMinValue,newMaxValue); this->updateClones(kFALSE); } } void LauParameter::name(const TString& newName) { // no need to update clones here // clones are allowed to have different names name_ = newName; } void LauParameter::fixed(Bool_t parFixed) { if (this->clone()) { parent_->fixed(parFixed); } else { fixed_ = parFixed; this->updateClones(kFALSE); } } void LauParameter::secondStage(Bool_t secondStagePar) { if (this->clone()) { parent_->secondStage(secondStagePar); } else { secondStage_ = secondStagePar; this->updateClones(kFALSE); } } void LauParameter::addGaussianConstraint(Double_t newGaussMean, Double_t newGaussWidth) { if (this->clone()) { parent_->addGaussianConstraint(newGaussMean,newGaussWidth); } else { gaussConstraint_ = kTRUE; constraintTrueMean_ = newGaussMean; constraintMean_ = newGaussMean; constraintWidth_ = newGaussWidth; this->updateClones(kFALSE); } } void LauParameter::removeGaussianConstraint() { if (this->clone()) { parent_->removeGaussianConstraint(); } else { gaussConstraint_ = kFALSE; this->updateClones(kFALSE); } } void LauParameter::generateConstraintMean() { if (this->clone()) { parent_->generateConstraintMean(); } else { constraintMean_ = LauRandom::randomFun()->Gaus( constraintTrueMean_, constraintWidth_ ); this->updateClones(kFALSE); } } Double_t LauParameter::constraintPenalty() const { const Double_t val { this->unblindValue() }; const Double_t diff { val - constraintMean_ }; const Double_t term { diff * diff }; return term / ( 2.0 * constraintWidth_ * constraintWidth_ ); } void LauParameter::blindParameter(const TString& blindingString, const Double_t width) { if (this->clone()) { parent_->blindParameter(blindingString,width); return; } if ( blinder_ != 0 ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for this parameter" << std::endl; return; } blinder_ = new LauBlind(blindingString,width); for (map::iterator iter = clones_.begin(); iter != clones_.end(); ++iter) { LauParameter* clonePar = iter->first; if ( clonePar->blinder_ != 0 ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for a clone of this parameter - it will be replaced!" << std::endl; delete clonePar->blinder_; clonePar->blinder_ = 0; } clonePar->blinder_ = new LauBlind(*blinder_); } } void LauParameter::updatePull() { if (this->clone()) { parent_->updatePull(); return; } // calculate the bias bias_ = value_ - genValue_; // if we have errors calculated then calculate // the pull using the best error available if ((bias_ > 0.0) && (negError_ > 1e-10)) { pull_ = bias_ / negError_; } else if ((bias_ < 0.0) && (posError_ > 1e-10)) { pull_ = bias_ / posError_; } else if (error_ > 1e-10) { pull_ = bias_ / error_; } else { pull_ = 0.0; } this->updateClones(kFALSE); } void LauParameter::checkRange(Double_t val, Double_t minVal, Double_t maxVal) { // first check that min is less than max (or they are the same - this is allowed) if (minVal > maxVal) { cerr<<"ERROR in LauParameter::checkRange : minValue: "< maxValue_) { minValue_ = maxValue_; cerr<<" : Setting both to "< maxVal)) { if (name_ != "") { cerr<<"ERROR in LauParameter::checkRange : value: "<clone()) { LauParameter* clonePar = parent_->createClone(constFactor); clonePar->name(this->name()); return clonePar; } // clone ourselves using the copy-constructor LauParameter* clonePar = new LauParameter(*this); Double_t newValue = clonePar->value() * constFactor; clonePar->value( newValue ); clonePar->wipeClones(); clonePar->clone(this); clones_.insert( std::make_pair( clonePar, constFactor ) ); return clonePar; } LauParameter* LauParameter::createClone(const TString& newName, Double_t constFactor) { // self message to create the clone LauParameter* clonePar = this->createClone(constFactor); // set the new name clonePar->name(newName); // and return return clonePar; } void LauParameter::updateClones(Bool_t justValue) { // if we don't have any clones then there's nothing to do if ( clones_.empty() ) { return; } // we have to set the values directly rather than using member functions because otherwise we'd get into an infinite loop if (justValue) { for ( auto& [ clonePar, constFactor ] : clones_ ) { clonePar->value_ = constFactor * value_; } } else { for ( auto& [ clonePar, constFactor ] : clones_ ) { clonePar->value_ = constFactor * value_; clonePar->error_ = constFactor * error_; clonePar->negError_ = constFactor * negError_; clonePar->posError_ = constFactor * posError_; clonePar->genValue_ = constFactor * genValue_; clonePar->initValue_ = constFactor * initValue_; clonePar->minValue_ = constFactor * minValue_; clonePar->maxValue_ = constFactor * maxValue_; clonePar->fixed_ = fixed_; clonePar->secondStage_ = secondStage_; clonePar->gaussConstraint_ = gaussConstraint_; clonePar->constraintTrueMean_ = constraintTrueMean_; clonePar->constraintMean_ = constraintMean_; clonePar->constraintWidth_ = constraintWidth_; clonePar->gcc_ = gcc_; clonePar->bias_ = bias_; clonePar->pull_ = pull_; } } } void LauParameter::randomiseValue() { this->randomiseValue(this->minValue(), this->maxValue()); } void LauParameter::randomiseValue(Double_t minVal, Double_t maxVal) { // if we're fixed then do nothing if (this->fixed()) { return; } // check supplied values are sensible if (maxVal < minVal) { cerr<<"ERROR in LauParameter::randomiseValue : Supplied maximum value smaller than minimum value."< this->maxValue()) { maxVal = this->maxValue(); } if (minVal < this->minValue()) { minVal = this->minValue(); } // use the zero-seed random number generator to get values that are // uniformly distributed over the given range Double_t randNo = LauRandom::zeroSeedRandom()->Rndm(); Double_t val = randNo*(maxVal - minVal) + minVal; this->initValue(val); } // ostream operator std::ostream& operator << (std::ostream& stream, const LauParameter& par) { stream << par.value(); return stream; } diff --git a/src/LauParametricStepFuncPdf.cc b/src/LauParametricStepFuncPdf.cc index 3c9e1ed..c5cd27f 100644 --- a/src/LauParametricStepFuncPdf.cc +++ b/src/LauParametricStepFuncPdf.cc @@ -1,231 +1,230 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParametricStepFuncPdf.cc \brief File containing implementation of LauParametricStepFuncPdf class. */ /***************************************************************************** * Class based on RooFit/RooParametricStepFunction. * * Original copyright given below. * ***************************************************************************** * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauParametricStepFuncPdf.hh" -ClassImp(LauParametricStepFuncPdf) LauParametricStepFuncPdf::LauParametricStepFuncPdf(const TString& theVarName, const vector& params, const vector& limits, NormBin normalisationBin) : LauAbsPdf(theVarName, params, limits.front(), limits.back()), normBin_(normalisationBin), limits_(limits) { // Constructor for the PSF PDF. // // The parameters in params are the bin contents of all but the // normalisation bin, so has N_bins-1 entries. // The last argument specifies the limits of the bins and the range // as a whole, so has N_bins+1 entries. if (this->nParameters() != this->nBins()-1) { cerr<<"ERROR in LauParametricStepFuncPdf constructor: LauParametricStepFuncPdf requires N-1 parameters, where N is the number of bins."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauParametricStepFuncPdf::~LauParametricStepFuncPdf() { // Destructor } void LauParametricStepFuncPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the parameters const vector& pars = this->getParameters(); // Calculate value Double_t value(0.0); const UInt_t numBins = this->nBins(); if ( this->normBin() == Last ) { // the last bin is our normalisation bin for ( UInt_t i(1); i<=numBins; ++i ) { if ( abscissa < limits_[i] ) { // in bin i-1 (starting with bin 0) if ( i < numBins ) { // not in last bin value = pars[i-1]->unblindValue(); break; } else { // in last bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(1); junblindValue() * binSize ); } binSize = limits_[numBins] - limits_[numBins-1]; value = ( 1.0 - sum ) / binSize; break; } } } } else { // the first bin is our normalisation bin for ( UInt_t i(1); i<=numBins; ++i ) { if ( abscissa < limits_[i] ) { // in bin i-1 (starting with bin 0) if ( i > 1 ) { // not in first bin value = pars[i-2]->unblindValue(); break; } else { // in first bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(2); j<=numBins; ++j ) { binSize = limits_[j] - limits_[j-1]; sum += ( pars[j-2]->unblindValue() * binSize ); } binSize = limits_[1] - limits_[0]; value = ( 1.0 - sum ) / binSize; break; } } } } this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauParametricStepFuncPdf::calcNorm() { this->setNorm(1.0); } void LauParametricStepFuncPdf::calcPDFHeight( const LauKinematics* /*kinematics*/ ) { if (this->heightUpToDate()) { return; } // Get the parameters const vector& pars = this->getParameters(); // Find the PDF height Double_t height(0.0); Double_t value(0.0); const UInt_t numBins = this->nBins(); if ( this->normBin() == Last ) { // the last bin is our normalisation bin // Check through all the parameterised bins for ( UInt_t i(0); iunblindValue(); if ( height < value ) { height = value; } } // Check the last bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(1); junblindValue() * binSize ); } binSize = limits_[numBins] - limits_[numBins-1]; value = ( 1.0 - sum ) / binSize; if ( height < value ) { height = value; } } else { // the first bin is our normalisation bin // Check through all the parameterised bins for ( UInt_t i(1); iunblindValue(); if ( height < value ) { height = value; } } // Check the first bin Double_t sum(0.0); Double_t binSize(0.0); for ( UInt_t j(2); j<=numBins; ++j ) { binSize = limits_[j] - limits_[j-1]; sum += ( pars[j-2]->unblindValue() * binSize ); } binSize = limits_[1] - limits_[0]; value = ( 1.0 - sum ) / binSize; if ( height < value ) { height = value; } } this->setMaxHeight(height); } diff --git a/src/LauParticlePDG.cc b/src/LauParticlePDG.cc index c160f8a..18d22f2 100644 --- a/src/LauParticlePDG.cc +++ b/src/LauParticlePDG.cc @@ -1,149 +1,148 @@ /* Copyright 2008 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauParticlePDG.cc \brief File containing implementation of LauParticlePDG class. */ #include using std::cerr; using std::endl; #include "TMath.h" #include "TParticlePDG.h" #include "LauConstants.hh" #include "LauDatabasePDG.hh" #include "LauParticlePDG.hh" -ClassImp(LauParticlePDG) LauParticlePDG::LauParticlePDG(const TParticlePDG* particle) : theParticle_(particle), antiParticle_(0), mass_(0.0), kaon_(kFALSE), pion_(kFALSE), ks_(kFALSE), pi0_(kFALSE), D_(kFALSE), B_(kFALSE) { // store the mass and kaon? and pion? if ( TMath::Abs(this->code()) == 211 ) { // charged pion mass_ = LauConstants::mPi; pion_ = kTRUE; } else if ( this->code() == 111 ) { // neutral pion mass_ = LauConstants::mPi0; pion_ = kTRUE; pi0_ = kTRUE; } else if ( TMath::Abs(this->code()) == 321 ) { // charged kaon mass_ = LauConstants::mK; kaon_ = kTRUE; } else if ( this->code() == 130 || this->code() == 310 || TMath::Abs(this->code()) == 311 ) { // neutral kaon mass_ = LauConstants::mK0; kaon_ = kTRUE; if ( this->code() == 310 ) { ks_ = kTRUE; } } else if ( this->code() == 221 ) { // eta mass_ = LauConstants::mEta; } else if ( this->code() == 331 ) { // eta' mass_ = LauConstants::mEtaPrime; } else if ( TMath::Abs(this->code()) == 411 ) { // charged D mass_ = LauConstants::mD; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 421 ) { // neutral D mass_ = LauConstants::mD0; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 431) { // charged D_s mass_ = LauConstants::mDs; D_ = kTRUE; } else if ( TMath::Abs(this->code()) == 511 ) { // neutral B mass_ = LauConstants::mB0; B_ = kTRUE; } else if ( TMath::Abs(this->code()) == 521 ) { // charged B mass_ = LauConstants::mB; B_ = kTRUE; } else if ( TMath::Abs(this->code()) == 531 ) { // neutral B_s mass_ = LauConstants::mBs0; B_ = kTRUE; } } LauParticlePDG::~LauParticlePDG() { } Int_t LauParticlePDG::code() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::code : Null pointer."<PdgCode(); } Int_t LauParticlePDG::conjugateCode() const { if (antiParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::conjugateCode : Null pointer."<code(); } Int_t LauParticlePDG::charge() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::charge : Null pointer."<Charge(); Int_t theCharge = static_cast(chargeTimesThree/3.0); return theCharge; } TString LauParticlePDG::string() const { if (theParticle_ == 0) { cerr<<"ERROR in LauParticlePDG::string : Null pointer."<GetName(); } TString LauParticlePDG::stringAlphaNum() const { TString name = this->string(); name.ReplaceAll("*","st"); name.ReplaceAll("_",""); name.ReplaceAll("(",""); name.ReplaceAll(")",""); name.ReplaceAll("+","p"); name.ReplaceAll("-","m"); return name; } diff --git a/src/LauPolNR.cc b/src/LauPolNR.cc index 61b9088..ea4453a 100644 --- a/src/LauPolNR.cc +++ b/src/LauPolNR.cc @@ -1,96 +1,95 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolNR.cc \brief File containing implementation of LauPolNR class. */ #include #include "TMath.h" #include "LauPolNR.hh" #include "LauDaughters.hh" -ClassImp(LauPolNR) LauPolNR::LauPolNR(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), omega_(0.0), order_(0) { } LauPolNR::~LauPolNR() { } void LauPolNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauPolNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } // Make the spin term purely the Legendre polynomial of the cos(helicity angle) this->setSpinType( LauAbsResonance::Legendre ); Double_t omega = 0.5*(daughters->getMassParent()+(1.0/3.0)*(daughters->getMassDaug1()+daughters->getMassDaug2()+daughters->getMassDaug3())); this->setOmega( omega ); TString name = this->getResonanceName(); if (name.EndsWith("0",TString::kExact)){ order_ = 0; } else if (name.EndsWith("1",TString::kExact)){ order_ = 1; } else if (name.EndsWith("2",TString::kExact)){ order_ = 2; } else if (name.EndsWith("3",TString::kExact)){ order_ = 3; } else{ std::cerr << "ERROR in LauPolNR::initialise : Resonance order unknown (known orders : 0, 1, 2 and 3)" << std::endl; std::cerr << " : Defaulting to 0." << std::endl; } } LauComplex LauPolNR::resAmp(Double_t mass, Double_t spinTerm) { Double_t magnitude( spinTerm ); Double_t massDiff = mass - omega_; for ( UInt_t i(0); i < order_; ++i ) { magnitude *= massDiff; } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } diff --git a/src/LauPolarFormFactorNR.cc b/src/LauPolarFormFactorNR.cc index 682806a..932209f 100644 --- a/src/LauPolarFormFactorNR.cc +++ b/src/LauPolarFormFactorNR.cc @@ -1,148 +1,147 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorNR.cc \brief File containing implementation of LauPolarFormFactorNR class. */ #include #include "TMath.h" #include "LauConstants.hh" #include "LauPolarFormFactorNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauPolarFormFactorNR) LauPolarFormFactorNR::LauPolarFormFactorNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambda_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_lambda"; lambda_ = resInfo->getExtraParameter( parName ); if ( lambda_ == 0 ) { lambda_ = new LauParameter( parName, 1.0, 0.0, 10.0, kTRUE ); lambda_->secondStage(kTRUE); resInfo->addExtraParameter( lambda_ ); } } LauPolarFormFactorNR::~LauPolarFormFactorNR() { } void LauPolarFormFactorNR::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauPolarFormFactorNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } if ( model_ != LauAbsResonance::PolarFFNR) { std::cerr << "WARNING in LauPolarFormFactorNR::initialise : Unknown model requested, defaulting to Polar Form Factor." << std::endl; model_ = LauAbsResonance::PolarFFNR; } } LauComplex LauPolarFormFactorNR::resAmp(Double_t mass, Double_t) { Double_t magnitude(1.0); Double_t lambda = this->getLambda(); magnitude = 1.0/(1.0 + mass*mass /(lambda*lambda)); LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauPolarFormFactorNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambda() ) { this->addFloatingParameter( lambda_ ); } return this->getParameters(); } void LauPolarFormFactorNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambda") { this->setLambda(value); std::cout << "INFO in LauPolarFormFactorNR::setResonanceParameter : Setting parameter lambda = " << this->getLambda() << std::endl; } else { std::cerr << "WARNING in LauPolarFormFactorNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauPolarFormFactorNR::floatResonanceParameter(const TString& name) { if (name == "lambda") { if ( lambda_->fixed() ) { lambda_->fixed( kFALSE ); this->addFloatingParameter( lambda_ ); } else { std::cerr << "WARNING in LauPolarFormFactorNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauPolarFormFactorNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauPolarFormFactorNR::getResonanceParameter(const TString& name) { if (name == "lambda") { return lambda_; } else { std::cerr << "WARNING in LauPolarFormFactorNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauPolarFormFactorNR::setLambda(const Double_t lambda) { lambda_->value( lambda ); lambda_->genValue( lambda ); lambda_->initValue( lambda ); } diff --git a/src/LauPolarFormFactorSymNR.cc b/src/LauPolarFormFactorSymNR.cc index ea88f7a..0e4dc6e 100644 --- a/src/LauPolarFormFactorSymNR.cc +++ b/src/LauPolarFormFactorSymNR.cc @@ -1,185 +1,184 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarFormFactorSymNR.cc \brief File containing implementation of LauPolarFormFactorSymNR class. */ #include #include "TMath.h" #include "LauConstants.hh" #include "LauPolarFormFactorSymNR.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauPolarFormFactorSymNR) LauPolarFormFactorSymNR::LauPolarFormFactorSymNR(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambda_(0), model_(resType) { TString parName = this->getSanitisedName(); parName += "_lambda"; lambda_ = resInfo->getExtraParameter( parName ); if ( lambda_ == 0 ) { lambda_ = new LauParameter( parName, 1.0, 0.0, 10.0, kTRUE ); lambda_->secondStage(kTRUE); resInfo->addExtraParameter( lambda_ ); } } LauPolarFormFactorSymNR::~LauPolarFormFactorSymNR() { } void LauPolarFormFactorSymNR::initialise() { const LauDaughters* daughters = this->getDaughters(); if ( ! daughters->gotSymmetricalDP() ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; } Int_t resPairAmpInt = this->getPairInt(); if ( resPairAmpInt == 3 ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : This lineshape is intended to be on the symmetrised axes of the DP." << std::endl; } if ( (model_ != LauAbsResonance::PolarFFSymNR) && (model_ != LauAbsResonance::PolarFFSymNRNoInter)) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Unknown model requested, defaulting to Polar Form Factor." << std::endl; model_ = LauAbsResonance::PolarFFSymNR; } if ( (model_ != LauAbsResonance::PolarFFSymNR) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauPolarFormFactorSymNR::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::PolarFFSymNRNoInter instead" << std::endl; } // NB we do not need to call setSpinType(LauAbsResonance::Legendre) here (as is done in LauPolarFormFactorNR) since override the amplitude method and explicitly use calcLegendrePoly } LauComplex LauPolarFormFactorSymNR::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauPolarFormFactorSymNR : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } LauComplex LauPolarFormFactorSymNR::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Polar Form Factor Non-Resonant distribution // Calculate for symmetric DPs, e.g. 3pi or 3K, by using shapeNo = 1 or 2 // Have s<->t symmetry already done in Dynamics flip function. // For Kpipi or similar plots, one can use the separate terms // and consider them as two separate components with their own mag and phase. // For this shapeNo = 3 and shapeNo = 4 need to be used to create the two // individual amplitudes (with the same value of lambda). // Calculate Mandelstam variables. // s = m_13^2, t = m_23^2 const Double_t s = kinematics->getm13Sq(); const Double_t t = kinematics->getm23Sq(); Double_t magnitude(1.0); const Double_t lambda = this->getLambda(); if ( model_ == LauAbsResonance::PolarFFSymNR ) { magnitude = 1.0/(1.0 + s /(lambda*lambda)) + 1.0/(1.0 + t /(lambda*lambda)); } else if ( model_ == LauAbsResonance::PolarFFSymNRNoInter ) { magnitude = (s <= t) ? 1.0/(1.0 + s /(lambda*lambda)) : 1.0/(1.0 + t /(lambda*lambda)); } LauComplex resAmplitude(magnitude, 0.0); return resAmplitude; } const std::vector& LauPolarFormFactorSymNR::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambda() ) { this->addFloatingParameter( lambda_ ); } return this->getParameters(); } void LauPolarFormFactorSymNR::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambda") { this->setLambda(value); std::cout << "INFO in LauPolarFormFactorSymNR::setResonanceParameter : Setting parameter lambda = " << this->getLambda() << std::endl; } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauPolarFormFactorSymNR::floatResonanceParameter(const TString& name) { if (name == "lambda") { if ( lambda_->fixed() ) { lambda_->fixed( kFALSE ); this->addFloatingParameter( lambda_ ); } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauPolarFormFactorSymNR::getResonanceParameter(const TString& name) { if (name == "lambda") { return lambda_; } else { std::cerr << "WARNING in LauPolarFormFactorSymNR::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauPolarFormFactorSymNR::setLambda(const Double_t lambda) { lambda_->value( lambda ); lambda_->genValue( lambda ); lambda_->initValue( lambda ); } diff --git a/src/LauPolarGammaCPCoeffSet.cc b/src/LauPolarGammaCPCoeffSet.cc index edfd294..19d3e91 100644 --- a/src/LauPolarGammaCPCoeffSet.cc +++ b/src/LauPolarGammaCPCoeffSet.cc @@ -1,768 +1,767 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarGammaCPCoeffSet.cc \brief File containing implementation of LauPolarGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauPolarGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" LauParameter* LauPolarGammaCPCoeffSet::gammaGlobal_ = 0; LauParameter* LauPolarGammaCPCoeffSet::rDGlobal_ = 0; LauParameter* LauPolarGammaCPCoeffSet::deltaDGlobal_ = 0; -ClassImp(LauPolarGammaCPCoeffSet) LauPolarGammaCPCoeffSet::LauPolarGammaCPCoeffSet(const TString& compName, const DecayType decayType, const Double_t x, const Double_t y, const Double_t rB, const Double_t deltaB, const Double_t gamma, const Double_t rD, const Double_t deltaD, const Bool_t xFixed, const Bool_t yFixed, const Bool_t rBFixed, const Bool_t deltaBFixed, const Bool_t gammaFixed, const Bool_t rDFixed, const Bool_t deltaDFixed, const Bool_t rBSecondStage, const Bool_t deltaBSecondStage, const Bool_t gammaSecondStage, const Bool_t rDSecondStage, const Bool_t deltaDSecondStage, const Bool_t useGlobalGamma, const Bool_t useGlobalADSPars) : LauAbsCoeffSet(compName), decayType_(decayType), x_(0), y_(0), rB_(0), deltaB_(0), gamma_(0), rD_(0), deltaD_(0), useGlobalGamma_(useGlobalGamma), useGlobalADSPars_(useGlobalADSPars), nonCPPart_(x,y), cpPart_(0.0,0.0), cpAntiPart_(0.0,0.0), particleCoeff_(0.0,0.0), antiparticleCoeff_(0.0,0.0), acp_("ACP", 0.0, -1.0, 1.0) { // All of the possible D decay types need these two parameters x_ = new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed); y_ = new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed); // if we're using a global gamma, create it if it doesn't already exist then set gamma_ to point to it // otherwise create our individual copy of gamma if (useGlobalGamma_) { if (!gammaGlobal_) { gammaGlobal_ = new LauParameter("gamma", gamma, minPhase_, maxPhase_, gammaFixed); gamma_ = gammaGlobal_; } else { gamma_ = gammaGlobal_->createClone(); } } else { gamma_ = new LauParameter("gamma", gamma, minPhase_, maxPhase_, gammaFixed); } if (gammaSecondStage && !gammaFixed) { gamma_->secondStage(kTRUE); gamma_->initValue(0.0); } // which of the other parameter we need depends on the D-decay type if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = new LauParameter("rB", rB, minMagnitude_, maxMagnitude_, rBFixed); deltaB_ = new LauParameter("deltaB", deltaB, minPhase_, maxPhase_, deltaBFixed); if (rBSecondStage && !rBFixed) { rB_->secondStage(kTRUE); rB_->initValue(0.0); } if (deltaBSecondStage && !deltaBFixed) { deltaB_->secondStage(kTRUE); deltaB_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if (useGlobalADSPars_) { if ( !rDGlobal_ ) { rDGlobal_ = new LauParameter("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaDGlobal_ = new LauParameter("deltaD", deltaD, minPhase_, maxPhase_, deltaDFixed); rD_ = rDGlobal_; deltaD_ = deltaDGlobal_; } else { rD_ = rDGlobal_->createClone(); deltaD_ = deltaDGlobal_->createClone(); } } else { rD_ = new LauParameter("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaD_ = new LauParameter("deltaD", deltaD, minPhase_, maxPhase_, deltaDFixed); } if (rDSecondStage && !rDFixed) { rD_->secondStage(kTRUE); rD_->initValue(0.0); } if (deltaDSecondStage && !deltaDFixed) { deltaD_->secondStage(kTRUE); deltaD_->initValue(0.0); } } } LauPolarGammaCPCoeffSet::LauPolarGammaCPCoeffSet(const LauPolarGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), decayType_( rhs.decayType_ ), x_(0), y_(0), rB_(0), deltaB_(0), gamma_(0), rD_(0), deltaD_(0), useGlobalGamma_( rhs.useGlobalGamma_ ), useGlobalADSPars_( rhs.useGlobalADSPars_ ), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { gamma_ = rhs.gamma_->createClone(constFactor); if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = rhs.rB_->createClone(constFactor); deltaB_ = rhs.deltaB_->createClone(constFactor); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rD_ = rhs.rD_->createClone(constFactor); deltaD_ = rhs.deltaD_->createClone(constFactor); } } else { if (useGlobalGamma_) { gamma_ = gammaGlobal_->createClone(); } else { gamma_ = new LauParameter("gamma", rhs.gamma_->value(), minPhase_, maxPhase_, rhs.gamma_->fixed()); if ( rhs.gamma_->blind() ) { const LauBlind* blinder = rhs.gamma_->blinder(); gamma_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.gamma_->secondStage() && !rhs.gamma_->fixed() ) { gamma_->secondStage(kTRUE); gamma_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_ = new LauParameter("rB", rhs.rB_->value(), minMagnitude_, maxMagnitude_, rhs.rB_->fixed()); if ( rhs.rB_->blind() ) { const LauBlind* blinder = rhs.rB_->blinder(); rB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaB_ = new LauParameter("deltaB", rhs.deltaB_->value(), minPhase_, maxPhase_, rhs.deltaB_->fixed()); if ( rhs.deltaB_->blind() ) { const LauBlind* blinder = rhs.deltaB_->blinder(); deltaB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.rB_->secondStage() && !rhs.rB_->fixed() ) { rB_->secondStage(kTRUE); rB_->initValue(0.0); } if ( rhs.deltaB_->secondStage() && !rhs.deltaB_->fixed() ) { deltaB_->secondStage(kTRUE); deltaB_->initValue(0.0); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if ( useGlobalADSPars_ ) { rD_ = rDGlobal_->createClone(); deltaD_ = deltaDGlobal_->createClone(); } else { rD_ = new LauParameter("rD", rhs.rD_->value(), minMagnitude_, maxMagnitude_, rhs.rD_->fixed()); if ( rhs.rD_->blind() ) { const LauBlind* blinder = rhs.rD_->blinder(); rD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } deltaD_ = new LauParameter("deltaD", rhs.deltaD_->value(), minPhase_, maxPhase_, rhs.deltaD_->fixed()); if ( rhs.deltaD_->blind() ) { const LauBlind* blinder = rhs.deltaD_->blinder(); deltaD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.rD_->secondStage() && !rhs.rD_->fixed() ) { rD_->secondStage(kTRUE); rD_->initValue(0.0); } if ( rhs.deltaD_->secondStage() && !rhs.deltaD_->fixed() ) { deltaD_->secondStage(kTRUE); deltaD_->initValue(0.0); } } } } } void LauPolarGammaCPCoeffSet::adjustName(LauParameter* par, const TString& oldBaseName) { if ( ( par == gamma_ && useGlobalGamma_ ) || ( par == rD_ && useGlobalADSPars_ ) || ( par == deltaD_ && useGlobalADSPars_ ) ) { // for global parameters we do not want to adjust their names return; } else { LauAbsCoeffSet::adjustName(par,oldBaseName); } } std::vector LauPolarGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if ( !gamma_->fixed() ) { pars.push_back(gamma_); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if ( !rB_->fixed() ) { pars.push_back(rB_); } if ( !deltaB_->fixed() ) { pars.push_back(deltaB_); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if ( !rD_->fixed() ) { pars.push_back(rD_); } if ( !deltaD_->fixed() ) { pars.push_back(deltaD_); } } return pars; } void LauPolarGammaCPCoeffSet::printParValues() const { std::cout<<"INFO in LauPolarGammaCPCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"x = "<value()<<",\t"; std::cout<<"y = "<value()<<",\t"; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { std::cout<<"rB = "<value()<<",\t"; std::cout<<"deltaB = "<value()<<",\t"; } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { std::cout<<"rD = "<value()<<",\t"; std::cout<<"deltaD = "<value()<<",\t"; } std::cout<<"gamma = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { print.printFormat(stream, rB_->value()); stream<<" \\pm "; print.printFormat(stream, rB_->error()); stream<<"$ & $"; print.printFormat(stream, deltaB_->value()); stream<<" \\pm "; print.printFormat(stream, deltaB_->error()); stream<<"$ & $"; } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { print.printFormat(stream, rD_->value()); stream<<" \\pm "; print.printFormat(stream, rD_->error()); stream<<"$ & $"; print.printFormat(stream, deltaD_->value()); stream<<" \\pm "; print.printFormat(stream, deltaD_->error()); stream<<"$ & $"; } print.printFormat(stream, gamma_->value()); stream<<" \\pm "; print.printFormat(stream, gamma_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (gamma_->fixed() == kFALSE && gamma_->secondStage() == kFALSE) { // Choose a value for "gamma" between +-pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; gamma_->initValue(value); gamma_->value(value); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if (rB_->fixed() == kFALSE && rB_->secondStage() == kFALSE) { // Choose a value for "rB" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; rB_->initValue(value); rB_->value(value); } if (deltaB_->fixed() == kFALSE && deltaB_->secondStage() == kFALSE) { // Choose a value for "deltaB" between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; deltaB_->initValue(value); deltaB_->value(value); } } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { if (rD_->fixed() == kFALSE && rD_->secondStage() == kFALSE) { // Choose a value for "rD" between 0.0 and 2.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*2.0; rD_->initValue(value); rD_->value(value); } if (deltaD_->fixed() == kFALSE && deltaD_->secondStage() == kFALSE) { // Choose a value for "deltaD" between +- pi Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi; deltaD_->initValue(value); deltaD_->value(value); } } } void LauPolarGammaCPCoeffSet::finaliseValues() { // retrieve the current values from the parameters Double_t gammaVal = gamma_->value(); Double_t rBVal = 0.0; Double_t deltaBVal = 0.0; Double_t genDeltaB = 0.0; Double_t rDVal = 0.0; Double_t deltaDVal = 0.0; Double_t genDeltaD = 0.0; if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rBVal = rB_->value(); deltaBVal = deltaB_->value(); genDeltaB = deltaB_->genValue(); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rDVal = rD_->value(); deltaDVal = deltaD_->value(); genDeltaD = deltaD_->genValue(); } // Check whether we have a negative magnitude. // If so make it positive and add pi to the phases. if (rBVal < 0.0) { rBVal *= -1.0; deltaBVal += LauConstants::pi; } if (rDVal < 0.0) { rDVal *= -1.0; deltaDVal += LauConstants::pi; } // Check now whether the phases lie in the right range (-pi to pi). Bool_t deltaBWithinRange(kFALSE); Bool_t deltaDWithinRange(kFALSE); Bool_t gammaWithinRange(kFALSE); while ( deltaBWithinRange == kFALSE ) { if (deltaBVal > -LauConstants::pi && deltaBVal <= LauConstants::pi) { deltaBWithinRange = kTRUE; } else { // Not within the specified range if (deltaBVal > LauConstants::pi) { deltaBVal -= LauConstants::twoPi; } else if (deltaBVal <= -LauConstants::pi) { deltaBVal += LauConstants::twoPi; } } } while ( deltaDWithinRange == kFALSE ) { if (deltaDVal > -LauConstants::pi && deltaDVal <= LauConstants::pi) { deltaDWithinRange = kTRUE; } else { // Not within the specified range if (deltaDVal > LauConstants::pi) { deltaDVal -= LauConstants::twoPi; } else if (deltaDVal <= -LauConstants::pi) { deltaDVal += LauConstants::twoPi; } } } while ( gammaWithinRange == kFALSE ) { if (gammaVal > -LauConstants::pi && gammaVal <= LauConstants::pi) { gammaWithinRange = kTRUE; } else { // Not within the specified range if (gammaVal > LauConstants::pi) { gammaVal -= LauConstants::twoPi; } else if (gammaVal <= -LauConstants::pi) { gammaVal += LauConstants::twoPi; } } } // To resolve the two-fold ambiguity in gamma and deltaB we require gamma to be in the range 0-pi if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { if (gammaVal < 0.0) { if (deltaBVal <= 0.0) { gammaVal += LauConstants::pi; deltaBVal += LauConstants::pi; } else { gammaVal += LauConstants::pi; deltaBVal -= LauConstants::pi; } } } // A further problem can occur when the generated phase is close to -pi or pi. // The phase can wrap over to the other end of the scale - // this leads to artificially large pulls so we wrap it back. Double_t diff = deltaBVal - genDeltaB; if (diff > LauConstants::pi) { deltaBVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaBVal += LauConstants::twoPi; } diff = deltaDVal - genDeltaD; if (diff > LauConstants::pi) { deltaDVal -= LauConstants::twoPi; } else if (diff < -LauConstants::pi) { deltaDVal += LauConstants::twoPi; } // finally store the new values in the parameters // and update the pulls gamma_->value(gammaVal); gamma_->updatePull(); if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == GLW_CPOdd || decayType_ == GLW_CPEven ) { rB_->value(rBVal); rB_->updatePull(); deltaB_->value(deltaBVal); deltaB_->updatePull(); } if ( decayType_ == ADS_Favoured || decayType_ == ADS_Suppressed || decayType_ == ADS_Favoured_btouOnly ) { rD_->value(rDVal); rD_->updatePull(); deltaD_->value(deltaDVal); deltaD_->updatePull(); } } const LauComplex& LauPolarGammaCPCoeffSet::particleCoeff() { this->updateAmplitudes(); return particleCoeff_; } const LauComplex& LauPolarGammaCPCoeffSet::antiparticleCoeff() { this->updateAmplitudes(); return antiparticleCoeff_; } void LauPolarGammaCPCoeffSet::updateAmplitudes() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); const Double_t gammaVal = gamma_->unblindValue(); switch ( decayType_ ) { case GLW_CPOdd : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); cpPart_.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal + gammaVal), -rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal - gammaVal), -rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPEven : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); cpPart_.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal + gammaVal), rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal - gammaVal), rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case ADS_Favoured : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal + gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal + gammaVal) ); cpAntiPart_.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal - gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal - gammaVal) ); break; } case ADS_Suppressed : { const Double_t rBVal = rB_->unblindValue(); const Double_t deltaBVal = deltaB_->unblindValue(); const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal + gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart_.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal - gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPOdd_btouOnly : nonCPPart_.rescale(-1.0); cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case GLW_CPEven_btouOnly : cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case ADS_Favoured_btouOnly : { const Double_t rDVal = rD_->unblindValue(); const Double_t deltaDVal = deltaD_->unblindValue(); cpPart_.setRealImagPart( rDVal * TMath::Cos( -deltaDVal + gammaVal ), rDVal * TMath::Sin( -deltaDVal + gammaVal ) ); cpAntiPart_.setRealImagPart( rDVal * TMath::Cos( -deltaDVal - gammaVal ), rDVal * TMath::Sin( -deltaDVal - gammaVal ) ); break; } case ADS_Suppressed_btouOnly : cpPart_.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart_.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; } particleCoeff_ = nonCPPart_ * cpPart_; antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; } void LauPolarGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauPolarGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauPolarGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value LauComplex nonCPPart( x_->value(), y_->value() ); LauComplex cpPart; LauComplex cpAntiPart; const Double_t gammaVal = gamma_->value(); switch ( decayType_ ) { case GLW_CPOdd : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); cpPart.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal + gammaVal), -rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 - rBVal*TMath::Cos(deltaBVal - gammaVal), -rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPEven : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); cpPart.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal + gammaVal), rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 + rBVal*TMath::Cos(deltaBVal - gammaVal), rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case ADS_Favoured : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal + gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal + gammaVal) ); cpAntiPart.setRealImagPart( 1.0 + rBVal*rDVal*TMath::Cos(deltaBVal - deltaDVal - gammaVal), rBVal*rDVal*TMath::Sin(deltaBVal - deltaDVal - gammaVal) ); break; } case ADS_Suppressed : { const Double_t rBVal = rB_->value(); const Double_t deltaBVal = deltaB_->value(); const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal + gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal + gammaVal) ); cpAntiPart.setRealImagPart( rDVal*TMath::Cos(-deltaDVal) + rBVal*TMath::Cos(deltaBVal - gammaVal), rDVal*TMath::Sin(-deltaDVal) + rBVal*TMath::Sin(deltaBVal - gammaVal) ); break; } case GLW_CPOdd_btouOnly : nonCPPart.rescale(-1.0); cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case GLW_CPEven_btouOnly : cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; case ADS_Favoured_btouOnly : { const Double_t rDVal = rD_->value(); const Double_t deltaDVal = deltaD_->value(); cpPart.setRealImagPart( rDVal * TMath::Cos( -deltaDVal + gammaVal ), rDVal * TMath::Sin( -deltaDVal + gammaVal ) ); cpAntiPart.setRealImagPart( rDVal * TMath::Cos( -deltaDVal - gammaVal ), rDVal * TMath::Sin( -deltaDVal - gammaVal ) ); break; } case ADS_Suppressed_btouOnly : cpPart.setRealImagPart( 1.0 * TMath::Cos( gammaVal ), 1.0 * TMath::Sin( gammaVal ) ); cpAntiPart.setRealImagPart( 1.0 * TMath::Cos( -gammaVal ), 1.0 * TMath::Sin( -gammaVal ) ); break; } const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = gamma_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauPolarGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauPolarGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauPolarGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauPoleRes.cc b/src/LauPoleRes.cc index cc90887..8525415 100644 --- a/src/LauPoleRes.cc +++ b/src/LauPoleRes.cc @@ -1,77 +1,76 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPoleRes.cc \brief File containing implementation of LauPoleRes class. */ #include "LauPoleRes.hh" -ClassImp(LauPoleRes) LauPoleRes::LauPoleRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters) { } LauPoleRes::~LauPoleRes() { } void LauPoleRes::initialise() { } LauComplex LauPoleRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a pole. 1/((mpole*mpole)-m*m) // mpole==(m0-iw0)==(rePole-i*imPole), to use the already defined mass and width of the resonance Double_t rePole = this->getMass(); Double_t imPole = this->getWidth(); Double_t reTerm = rePole*rePole -imPole*imPole -mass*mass; Double_t imTerm = 2.0*rePole*imPole; LauComplex resAmplitude(reTerm, imTerm); resAmplitude.rescale(1./(reTerm*reTerm + imTerm*imTerm)); return resAmplitude.scale(spinTerm); } const std::vector& LauPoleRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } return this->getParameters(); } diff --git a/src/LauPrint.cc b/src/LauPrint.cc index 234a942..31f5e15 100644 --- a/src/LauPrint.cc +++ b/src/LauPrint.cc @@ -1,65 +1,64 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPrint.cc \brief File containing implementation of LauPrint class. */ #include #include "TMath.h" #include "LauPrint.hh" -ClassImp(LauPrint) LauPrint::LauPrint() { } LauPrint::~LauPrint() { } void LauPrint::printFormat(std::ostream& stream, Double_t value) const { // Print double value to a specified level of precision char* string = new char[100]; if (TMath::Abs(value) < 1e-30) { sprintf(string, "%5.3f", 0.0); } else if (TMath::Abs(value) < 0.01) { sprintf(string, "%5.3e", value); } else if (TMath::Abs(value) < 0.1) { sprintf(string, "%5.3f", value); } else { sprintf(string, "%5.3f", value); } stream< #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagCPCoeffSet) LauRealImagCPCoeffSet::LauRealImagCPCoeffSet(const TString& compName, Double_t x, Double_t y, Double_t xbar, Double_t ybar, Bool_t xFixed, Bool_t yFixed, Bool_t xbarFixed, Bool_t ybarFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xbar_(new LauParameter("Xbar", xbar, minRealImagPart_, maxRealImagPart_, xbarFixed)), ybar_(new LauParameter("Ybar", ybar, minRealImagPart_, maxRealImagPart_, ybarFixed)), particleCoeff_(x,y), antiparticleCoeff_(xbar,ybar), acp_("ACP", 0.0, -1.0, 1.0, kTRUE) { } LauRealImagCPCoeffSet::LauRealImagCPCoeffSet(const LauRealImagCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xbar_(0), ybar_(0), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); xbar_ = rhs.xbar_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } xbar_ = new LauParameter("Xbar", rhs.xbar_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbar_->fixed()); if ( rhs.xbar_->blind() ) { const LauBlind* blinder = rhs.xbar_->blinder(); xbar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); ybar_ = rhs.ybar_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } ybar_ = new LauParameter("Ybar", rhs.ybar_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybar_->fixed()); if ( rhs.ybar_->blind() ) { const LauBlind* blinder = rhs.ybar_->blinder(); ybar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); pars.push_back(xbar_); pars.push_back(ybar_); return pars; } void LauRealImagCPCoeffSet::printParValues() const { std::cout << "INFO in LauRealImagCPCoeffSet::printParValues : Component \"" << this->name() << "\" has "; std::cout << "x = " << x_->value() << ",\t"; std::cout << "y = " << y_->value() << ",\t"; std::cout << "xbar = " << xbar_->value() << ",\t"; std::cout << "ybar = " << ybar_->value() << "." << std::endl; } void LauRealImagCPCoeffSet::printTableHeading(std::ostream& stream) const { stream<<"\\begin{tabular}{|l|c|c|c|c|}"<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xbar_->value()); stream<<" \\pm "; print.printFormat(stream, xbar_->error()); stream<<"$ & $"; print.printFormat(stream, ybar_->value()); stream<<" \\pm "; print.printFormat(stream, ybar_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xbar_->fixed() == kFALSE) { // Choose a value for "Xbar" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xbar_->initValue(value); xbar_->value(value); } if (ybar_->fixed() == kFALSE) { // Choose a value for "Ybar" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; ybar_->initValue(value); ybar_->value(value); } } void LauRealImagCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xbar_->updatePull(); ybar_->updatePull(); } const LauComplex& LauRealImagCPCoeffSet::particleCoeff() { particleCoeff_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); return particleCoeff_; } const LauComplex& LauRealImagCPCoeffSet::antiparticleCoeff() { antiparticleCoeff_.setRealImagPart( xbar_->unblindValue(), ybar_->unblindValue() ); return antiparticleCoeff_; } void LauRealImagCPCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { Double_t xVal( coeff.re() ); Double_t yVal( coeff.im() ); Double_t xBarVal( coeffBar.re() ); Double_t yBarVal( coeffBar.im() ); x_->value( xVal ); y_->value( yVal ); xbar_->value( xBarVal ); ybar_->value( yBarVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); xbar_->genValue( xBarVal ); ybar_->genValue( yBarVal ); x_->initValue( xVal ); y_->initValue( yVal ); xbar_->initValue( xBarVal ); ybar_->initValue( yBarVal ); } } LauParameter LauRealImagCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value Double_t csq = x_->value()*x_->value() + y_->value()*y_->value(); Double_t cbarsq = xbar_->value()*xbar_->value() + ybar_->value()*ybar_->value(); Double_t numer = cbarsq - csq; Double_t denom = cbarsq + csq; Double_t value = numer/denom; // is it fixed? Bool_t fixed = x_->fixed() && y_->fixed() && xbar_->fixed() && ybar_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauRealImagCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart ) { clone = new LauRealImagCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRealImagCoeffSet.cc b/src/LauRealImagCoeffSet.cc index f107182..c10bbfc 100644 --- a/src/LauRealImagCoeffSet.cc +++ b/src/LauRealImagCoeffSet.cc @@ -1,185 +1,184 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagCoeffSet.cc \brief File containing implementation of LauRealImagCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauRealImagCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagCoeffSet) LauRealImagCoeffSet::LauRealImagCoeffSet(const TString& compName, Double_t x, Double_t y, Bool_t xFixed, Bool_t yFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X",x,minRealImagPart_,maxRealImagPart_,xFixed)), y_(new LauParameter("Y",y,minRealImagPart_,maxRealImagPart_,yFixed)), coeff_(x,y) { } LauRealImagCoeffSet::LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), coeff_( rhs.coeff_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); return pars; } void LauRealImagCoeffSet::printParValues() const { std::cout<<"INFO in LauRealImagCoeffSet::printParValues : Component \""<name()<<"\" has real part = "<value()<<" and imaginary part = "<value()<<"."<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value between -10.0 and 10.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*20.0 - 10.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value between -10.0 and 10.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*20.0 - 10.0; y_->initValue(value); y_->value(value); } } void LauRealImagCoeffSet::finaliseValues() { x_->updatePull(); y_->updatePull(); } const LauComplex& LauRealImagCoeffSet::particleCoeff() { coeff_.setRealImagPart(x_->unblindValue(), y_->unblindValue()); return coeff_; } const LauComplex& LauRealImagCoeffSet::antiparticleCoeff() { return this->particleCoeff(); } void LauRealImagCoeffSet::setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) { LauComplex average( coeff ); average += coeffBar; average.rescale( 0.5 ); Double_t xVal( average.re() ); Double_t yVal( average.im() ); x_->value( xVal ); y_->value( yVal ); if ( init ) { x_->genValue( xVal ); y_->genValue( yVal ); x_->initValue( xVal ); y_->initValue( yVal ); } } LauParameter LauRealImagCoeffSet::acp() { TString parName(this->baseName()); parName += "_ACP"; return LauParameter(parName,0.0); } LauAbsCoeffSet* LauRealImagCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart ) { clone = new LauRealImagCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRealImagGammaCPCoeffSet.cc b/src/LauRealImagGammaCPCoeffSet.cc index 9120410..1345e22 100644 --- a/src/LauRealImagGammaCPCoeffSet.cc +++ b/src/LauRealImagGammaCPCoeffSet.cc @@ -1,296 +1,295 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagGammaCPCoeffSet.cc \brief File containing implementation of LauRealImagGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" -ClassImp(LauRealImagGammaCPCoeffSet) LauRealImagGammaCPCoeffSet::LauRealImagGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t xbarCP, const Double_t ybarCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t xbarCPFixed, const Bool_t ybarCPFixed) : LauAbsCoeffSet(compName), x_(new LauParameter("X", x, minRealImagPart_, maxRealImagPart_, xFixed)), y_(new LauParameter("Y", y, minRealImagPart_, maxRealImagPart_, yFixed)), xCP_(new LauParameter("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed)), yCP_(new LauParameter("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed)), xbarCP_(new LauParameter("XbarCP", xbarCP, minRealImagPart_, maxRealImagPart_, xbarCPFixed)), ybarCP_(new LauParameter("YbarCP", ybarCP, minRealImagPart_, maxRealImagPart_, ybarCPFixed)), nonCPPart_( x, y), cpPart_( 1+xCP, yCP ), cpAntiPart_( 1+xbarCP, ybarCP ), particleCoeff_( nonCPPart_ * cpPart_ ), antiparticleCoeff_( nonCPPart_ * cpAntiPart_ ), acp_("ACP", (antiparticleCoeff_.abs2()-particleCoeff_.abs2())/(antiparticleCoeff_.abs2()+particleCoeff_.abs2()), -1.0, 1.0, xCPFixed&&yCPFixed&&xbarCPFixed&&ybarCPFixed) { } LauRealImagGammaCPCoeffSet::LauRealImagGammaCPCoeffSet(const LauRealImagGammaCPCoeffSet& rhs, CloneOption cloneOption, Double_t constFactor) : LauAbsCoeffSet(rhs.name()), x_(0), y_(0), xCP_(0), yCP_(0), xbarCP_(0), ybarCP_(0), nonCPPart_( rhs.nonCPPart_ ), cpPart_( rhs.cpPart_ ), cpAntiPart_( rhs.cpAntiPart_ ), particleCoeff_( rhs.particleCoeff_ ), antiparticleCoeff_( rhs.antiparticleCoeff_ ), acp_( rhs.acp_ ) { if ( cloneOption == All || cloneOption == TieRealPart ) { x_ = rhs.x_->createClone(constFactor); } else { x_ = new LauParameter("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); if ( rhs.x_->blind() ) { const LauBlind* blinder = rhs.x_->blinder(); x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieImagPart ) { y_ = rhs.y_->createClone(constFactor); } else { y_ = new LauParameter("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); if ( rhs.y_->blind() ) { const LauBlind* blinder = rhs.y_->blinder(); y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == All || cloneOption == TieCPPars ) { xCP_ = rhs.xCP_->createClone(constFactor); yCP_ = rhs.yCP_->createClone(constFactor); xbarCP_ = rhs.xbarCP_->createClone(constFactor); ybarCP_ = rhs.ybarCP_->createClone(constFactor); } else { xCP_ = new LauParameter("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); if ( rhs.xCP_->blind() ) { const LauBlind* blinder = rhs.xCP_->blinder(); xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } yCP_ = new LauParameter("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); if ( rhs.yCP_->blind() ) { const LauBlind* blinder = rhs.yCP_->blinder(); yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } xbarCP_ = new LauParameter("XbarCP", rhs.xbarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbarCP_->fixed()); if ( rhs.xbarCP_->blind() ) { const LauBlind* blinder = rhs.xbarCP_->blinder(); xbarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } ybarCP_ = new LauParameter("YbarCP", rhs.ybarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybarCP_->fixed()); if ( rhs.ybarCP_->blind() ) { const LauBlind* blinder = rhs.ybarCP_->blinder(); ybarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagGammaCPCoeffSet::getParameters() { std::vector pars; pars.push_back(x_); pars.push_back(y_); if(!xCP_->fixed()) pars.push_back(xCP_); if(!yCP_->fixed()) pars.push_back(yCP_); if(!xbarCP_->fixed()) pars.push_back(xbarCP_); if(!ybarCP_->fixed()) pars.push_back(ybarCP_); return pars; } void LauRealImagGammaCPCoeffSet::printParValues() const { std::cout << "INFO in LauRealImagGammaCPCoeffSet::printParValues : Component \"" << this->name() << "\" has "; std::cout << "x = " << x_->value() << ",\t"; std::cout << "y = " << y_->value() << ",\t"; std::cout << "xCP = " << xCP_->value() << ",\t"; std::cout << "yCP = " << yCP_->value() << ",\t"; std::cout << "xbarCP = " << xbarCP_->value() << ",\t"; std::cout << "ybarCP = " << ybarCP_->value() << "." << std::endl; } void LauRealImagGammaCPCoeffSet::printTableHeading(std::ostream& stream) const { stream<<"\\begin{tabular}{|l|c|c|c|c|c|c|}"<name(); resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, x_->error()); stream<<"$ & $"; print.printFormat(stream, y_->value()); stream<<" \\pm "; print.printFormat(stream, y_->error()); stream<<"$ & $"; print.printFormat(stream, xCP_->value()); stream<<" \\pm "; print.printFormat(stream, xCP_->error()); stream<<"$ & $"; print.printFormat(stream, yCP_->value()); stream<<" \\pm "; print.printFormat(stream, yCP_->error()); stream<<"$ & $"; print.printFormat(stream, xbarCP_->value()); stream<<" \\pm "; print.printFormat(stream, xbarCP_->error()); stream<<"$ & $"; print.printFormat(stream, ybarCP_->value()); stream<<" \\pm "; print.printFormat(stream, ybarCP_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; x_->initValue(value); x_->value(value); } if (y_->fixed() == kFALSE) { // Choose a value for "Y" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; y_->initValue(value); y_->value(value); } if (xCP_->fixed() == kFALSE) { // Choose a value for "XCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xCP_->initValue(value); xCP_->value(value); } if (yCP_->fixed() == kFALSE) { // Choose a value for "YCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; yCP_->initValue(value); yCP_->value(value); } if (xbarCP_->fixed() == kFALSE) { // Choose a value for "XbarCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; xbarCP_->initValue(value); xbarCP_->value(value); } if (ybarCP_->fixed() == kFALSE) { // Choose a value for "YbarCP" between -3.0 and 3.0 Double_t value = LauAbsCoeffSet::getRandomiser()->Rndm()*6.0 - 3.0; ybarCP_->initValue(value); ybarCP_->value(value); } } void LauRealImagGammaCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); xCP_->updatePull(); yCP_->updatePull(); xbarCP_->updatePull(); ybarCP_->updatePull(); } const LauComplex& LauRealImagGammaCPCoeffSet::particleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpPart_.setRealImagPart( 1.0+xCP_->unblindValue(), yCP_->unblindValue() ); particleCoeff_ = nonCPPart_ * cpPart_; return particleCoeff_; } const LauComplex& LauRealImagGammaCPCoeffSet::antiparticleCoeff() { nonCPPart_.setRealImagPart( x_->unblindValue(), y_->unblindValue() ); cpAntiPart_.setRealImagPart( 1.0+xbarCP_->unblindValue(), ybarCP_->unblindValue() ); antiparticleCoeff_ = nonCPPart_ * cpAntiPart_; return antiparticleCoeff_; } void LauRealImagGammaCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauRealImagGammaCPCoeffSet::acp() { // set the name TString parName(this->baseName()); parName += "_ACP"; acp_.name(parName); // work out the ACP value const LauComplex nonCPPart( x_->value(), y_->value() ); const LauComplex cpPart( 1.0+xCP_->value(), yCP_->value() ); const LauComplex cpAntiPart( 1.0+xbarCP_->value(), ybarCP_->value() ); const LauComplex partCoeff = nonCPPart * cpPart; const LauComplex antiCoeff = nonCPPart * cpAntiPart; const Double_t numer = antiCoeff.abs2() - partCoeff.abs2(); const Double_t denom = antiCoeff.abs2() + partCoeff.abs2(); const Double_t value = numer/denom; // is it fixed? const Bool_t fixed = xCP_->fixed() && yCP_->fixed() && xbarCP_->fixed() && ybarCP_->fixed(); acp_.fixed(fixed); // we can't work out the error without the covariance matrix const Double_t error(0.0); // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauAbsCoeffSet* LauRealImagGammaCPCoeffSet::createClone(const TString& newName, CloneOption cloneOption, Double_t constFactor) { LauAbsCoeffSet* clone(0); if ( cloneOption == All || cloneOption == TieRealPart || cloneOption == TieImagPart || cloneOption == TieCPPars ) { clone = new LauRealImagGammaCPCoeffSet( *this, cloneOption, constFactor ); clone->name( newName ); } else { std::cerr << "ERROR in LauRealImagGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; } return clone; } diff --git a/src/LauRelBreitWignerRes.cc b/src/LauRelBreitWignerRes.cc index d6f76a5..17e057f 100644 --- a/src/LauRelBreitWignerRes.cc +++ b/src/LauRelBreitWignerRes.cc @@ -1,253 +1,252 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRelBreitWignerRes.cc \brief File containing implementation of LauRelBreitWignerRes class. */ #include #include "LauConstants.hh" #include "LauRelBreitWignerRes.hh" -ClassImp(LauRelBreitWignerRes) LauRelBreitWignerRes::LauRelBreitWignerRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), q0_(0.0), resMass_(0.0), resMassSq_(0.0), resWidth_(0.0), resRadius_(0.0), parRadius_(0.0), mDaugSum_(0.0), mDaugSumSq_(0.0), mDaugDiff_(0.0), mDaugDiffSq_(0.0), mParentSq_(0.0), mBachSq_(0.0), FR0_(1.0) { } LauRelBreitWignerRes::~LauRelBreitWignerRes() { } void LauRelBreitWignerRes::initialise() { // Set-up various constants. This must be called again if the mass/width/spin // of a resonance changes... resMass_ = this->getMass(); resWidth_ = this->getWidth(); resRadius_ = this->getResRadius(); parRadius_ = this->getParRadius(); Double_t massDaug1 = this->getMassDaug1(); Double_t massDaug2 = this->getMassDaug2(); Double_t massBachelor = this->getMassBachelor(); Double_t massParent = this->getMassParent(); // Create the mass squares, sums, differences etc. resMassSq_ = resMass_*resMass_; mDaugSum_ = massDaug1 + massDaug2; mDaugSumSq_ = mDaugSum_*mDaugSum_; mDaugDiff_ = massDaug1 - massDaug2; mDaugDiffSq_ = mDaugDiff_*mDaugDiff_; mParentSq_ = massParent*massParent; mBachSq_ = massBachelor*massBachelor; // Create an effective resonance pole mass to protect against resonances // that are below threshold Double_t effResMass = resMass_; Double_t effResMassSq = resMassSq_; if ( resMassSq_ - mDaugSumSq_ < 0.0 ) { Double_t minMass = mDaugSum_; Double_t maxMass = massParent - massBachelor; Double_t tanhTerm = std::tanh( (resMass_ - ((minMass + maxMass)/2))/(maxMass-minMass)); effResMass = minMass + (maxMass-minMass)*(1+tanhTerm)/2; effResMassSq = effResMass*effResMass; } // Decay momentum of either daughter in the resonance rest frame // when resonance mass = rest-mass value, m_0 (PDG value) Double_t term1 = effResMassSq - mDaugSumSq_; Double_t term2 = effResMassSq - mDaugDiffSq_; Double_t term12 = term1*term2; if (term12 > 0.0) { q0_ = TMath::Sqrt(term12)/(2.0*effResMass); } else { q0_ = 0.0; } // Calculate the resonance Blatt-Weisskopf form factor for the case when m = m_0 FR0_ = 1.0; if ( this->getSpin() > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); if ( resBWFactor != nullptr ) { FR0_ = resBWFactor->calcFormFactor(q0_); } } } LauComplex LauRelBreitWignerRes::resAmp(Double_t mass, Double_t spinTerm) { // This function returns the complex dynamical amplitude for a Breit-Wigner resonance, // given the invariant mass and cos(helicity) values. LauComplex resAmplitude(0.0, 0.0); if (mass < 1e-10) { std::cerr << "WARNING in LauRelBreitWignerRes::amplitude : mass < 1e-10." << std::endl; return LauComplex(0.0, 0.0); } else if (q0_ < 1e-30) { return LauComplex(0.0, 0.0); } // Calculate the width of the resonance (as a function of mass) // First, calculate the various form factors. // NB // q is the momentum of either daughter in the resonance rest-frame, // p is the momentum of the bachelor in the resonance rest-frame, // pstar is the momentum of the bachelor in the parent rest-frame. // These quantities have been calculate in LauAbsResonance::amplitude(...) const Double_t resMass = this->getMass(); const Double_t resWidth = this->getWidth(); const Double_t resRadius = this->getResRadius(); const Double_t parRadius = this->getParRadius(); // If the mass is floating and its value has changed we need to // recalculate everything that assumes that value // Similarly for the BW radii if ( ( (!this->fixMass()) && resMass != resMass_ ) || ( (!this->fixResRadius()) && resRadius != resRadius_ ) || ( (!this->fixParRadius()) && parRadius != parRadius_ ) ) { this->initialise(); } const Int_t resSpin = this->getSpin(); const Double_t q = this->getQ(); const Double_t p = this->getP(); const Double_t pstar = this->getPstar(); // Get barrier scaling factors Double_t fFactorR(1.0); Double_t fFactorB(1.0); if ( resSpin > 0 ) { const LauBlattWeisskopfFactor* resBWFactor = this->getResBWFactor(); if ( resBWFactor != nullptr ) { fFactorR = resBWFactor->calcFormFactor(q); } const LauBlattWeisskopfFactor* parBWFactor = this->getParBWFactor(); if ( parBWFactor != nullptr ) { switch ( parBWFactor->getRestFrame() ) { case LauBlattWeisskopfFactor::ResonanceFrame: fFactorB = parBWFactor->calcFormFactor(p); break; case LauBlattWeisskopfFactor::ParentFrame: fFactorB = parBWFactor->calcFormFactor(pstar); break; case LauBlattWeisskopfFactor::Covariant: { Double_t covFactor = this->getCovFactor(); if ( resSpin > 2 ) { covFactor = TMath::Power( covFactor, 1.0/resSpin ); } else if ( resSpin == 2 ) { covFactor = TMath::Sqrt( covFactor ); } fFactorB = parBWFactor->calcFormFactor(pstar*covFactor); break; } } } } // If ignoreMomenta is set, set the total width simply as the pole width, and do // not include any momentum-dependent barrier factors (set them to unity) Double_t totWidth(resWidth); if (!this->ignoreMomenta()) { const Double_t qRatio = q/q0_; Double_t qTerm(0.0); if (resSpin == 0) { qTerm = qRatio; } else if (resSpin == 1) { qTerm = qRatio*qRatio*qRatio; } else if (resSpin == 2) { qTerm = qRatio*qRatio*qRatio*qRatio*qRatio; } else { qTerm = TMath::Power(qRatio, 2.0*resSpin + 1.0); } const Double_t fFactorRRatio = fFactorR/FR0_; totWidth = resWidth*qTerm*(resMass/mass)*fFactorRRatio*fFactorRRatio; } const Double_t massSq = mass*mass; const Double_t massSqTerm = resMassSq_ - massSq; // Compute the complex amplitude resAmplitude = LauComplex(massSqTerm, resMass*totWidth); // Scale by the denominator factor, as well as the spin term Double_t scale = spinTerm/(massSqTerm*massSqTerm + resMassSq_*totWidth*totWidth); // Include Blatt-Weisskopf barrier factors if (!this->ignoreBarrierScaling()) { scale *= fFactorR * fFactorB; } resAmplitude.rescale(scale); return resAmplitude; } const std::vector& LauRelBreitWignerRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } diff --git a/src/LauRescattering2Res.cc b/src/LauRescattering2Res.cc index 37fd6c5..396a45c 100644 --- a/src/LauRescattering2Res.cc +++ b/src/LauRescattering2Res.cc @@ -1,672 +1,671 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescattering2Res.cc \brief File containing implementation of LauRescattering2Res class. */ #include #include "LauConstants.hh" #include "LauRescattering2Res.hh" #include "LauResonanceInfo.hh" -ClassImp(LauRescattering2Res) LauRescattering2Res::LauRescattering2Res(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), B1_(0),B2_(0),B3_(0), C1_(0),C2_(0),C3_(0),C4_(0),C5_(0), D0_(0),D1_(0),D2_(0),D3_(0), F1_(0),F2_(0),F3_(0),F4_(0) { // Default values for parameters, taken from const Double_t B1Val(23.6); const Double_t B2Val(29.4); const Double_t B3Val(0.6); const Double_t C1Val(34.39); const Double_t C2Val(4.4); const Double_t C3Val(-32.9); const Double_t C4Val(-16.); const Double_t C5Val(7.4); const Double_t D0Val(0.59); const Double_t D1Val(-0.38); const Double_t D2Val(0.12); const Double_t D3Val(-0.09); const Double_t F1Val(-0.043); const Double_t F2Val(-0.008); const Double_t F3Val(-0.28); const Double_t F4Val(0.026); const TString& parNameBase = this->getSanitisedName(); TString B1Name(parNameBase); B1Name += "_B1"; B1_ = resInfo->getExtraParameter( B1Name ); if ( B1_ == 0 ) { B1_ = new LauParameter( B1Name, B1Val, -100.,100., kTRUE ); B1_->secondStage(kTRUE); resInfo->addExtraParameter( B1_ ); } TString B2Name(parNameBase); B2Name += "_B2"; B2_ = resInfo->getExtraParameter( B2Name ); if ( B2_ == 0 ) { B2_ = new LauParameter( B2Name, B2Val, -100.,100., kTRUE ); B2_->secondStage(kTRUE); resInfo->addExtraParameter( B2_ ); } TString B3Name(parNameBase); B3Name += "_B3"; B3_ = resInfo->getExtraParameter( B3Name ); if ( B3_ == 0 ) { B3_ = new LauParameter( B3Name, B3Val, -100.,100., kTRUE ); B3_->secondStage(kTRUE); resInfo->addExtraParameter( B3_ ); } TString C1Name(parNameBase); C1Name += "_C1"; C1_ = resInfo->getExtraParameter( C1Name ); if ( C1_ == 0 ) { C1_ = new LauParameter( C1Name, C1Val, -100.,100., kTRUE ); C1_->secondStage(kTRUE); resInfo->addExtraParameter( C1_ ); } TString C2Name(parNameBase); C2Name += "_C2"; C2_ = resInfo->getExtraParameter( C2Name ); if ( C2_ == 0 ) { C2_ = new LauParameter( C2Name, C2Val, -100.,100., kTRUE ); C2_->secondStage(kTRUE); resInfo->addExtraParameter( C2_ ); } TString C3Name(parNameBase); C3Name += "_C3"; C3_ = resInfo->getExtraParameter( C3Name ); if ( C3_ == 0 ) { C3_ = new LauParameter( C3Name, C3Val, -100.,100., kTRUE ); C3_->secondStage(kTRUE); resInfo->addExtraParameter( C3_ ); } TString C4Name(parNameBase); C4Name += "_C4"; C4_ = resInfo->getExtraParameter( C4Name ); if ( C4_ == 0 ) { C4_ = new LauParameter( C4Name, C4Val, -100.,100., kTRUE ); C4_->secondStage(kTRUE); resInfo->addExtraParameter( C4_ ); } TString C5Name(parNameBase); C5Name += "_C5"; C5_ = resInfo->getExtraParameter( C5Name ); if ( C5_ == 0 ) { C5_ = new LauParameter( C5Name, C5Val, -100.,100., kTRUE ); C5_->secondStage(kTRUE); resInfo->addExtraParameter( C5_ ); } TString D0Name(parNameBase); D0Name += "_D0"; D0_ = resInfo->getExtraParameter( D0Name ); if ( D0_ == 0 ) { D0_ = new LauParameter( D0Name, D0Val, -100.,100., kTRUE ); D0_->secondStage(kTRUE); resInfo->addExtraParameter( D0_ ); } TString D1Name(parNameBase); D1Name += "_D1"; D1_ = resInfo->getExtraParameter( D1Name ); if ( D1_ == 0 ) { D1_ = new LauParameter( D1Name, D1Val, -100.,100., kTRUE ); D1_->secondStage(kTRUE); resInfo->addExtraParameter( D1_ ); } TString D2Name(parNameBase); D2Name += "_D2"; D2_ = resInfo->getExtraParameter( D2Name ); if ( D2_ == 0 ) { D2_ = new LauParameter( D2Name, D2Val,-100.,100., kTRUE ); D2_->secondStage(kTRUE); resInfo->addExtraParameter( D2_ ); } TString D3Name(parNameBase); D3Name += "_D3"; D3_ = resInfo->getExtraParameter( D3Name ); if ( D3_ == 0 ) { D3_ = new LauParameter( D3Name, D3Val, -100.,100., kTRUE ); D3_->secondStage(kTRUE); resInfo->addExtraParameter( D3_ ); } TString F1Name(parNameBase); F1Name += "_F1"; F1_ = resInfo->getExtraParameter( F1Name ); if ( F1_ == 0 ) { F1_ = new LauParameter( F1Name, F1Val, -100.,100., kTRUE ); F1_->secondStage(kTRUE); resInfo->addExtraParameter( F1_ ); } TString F2Name(parNameBase); F2Name += "_F2"; F2_ = resInfo->getExtraParameter( F2Name ); if ( F2_ == 0 ) { F2_ = new LauParameter( F2Name, F2Val, -100.,100., kTRUE ); F2_->secondStage(kTRUE); resInfo->addExtraParameter( F2_ ); } TString F3Name(parNameBase); F3Name += "_F3"; F3_ = resInfo->getExtraParameter( F3Name ); if ( F3_ == 0 ) { F3_ = new LauParameter( F3Name, F3Val, -100.,100., kTRUE ); F3_->secondStage(kTRUE); resInfo->addExtraParameter( F3_ ); } TString F4Name(parNameBase); F4Name += "_F4"; F4_ = resInfo->getExtraParameter( F4Name ); if ( F4_ == 0 ) { F4_ = new LauParameter( F4Name, F4Val, -100.,100., kTRUE ); F4_->secondStage(kTRUE); resInfo->addExtraParameter( F4_ ); } } LauRescattering2Res::~LauRescattering2Res() { delete B1_;delete B2_;delete B3_; delete C1_;delete C2_;delete C3_;delete C4_;delete C5_; delete D0_;delete D1_;delete D2_;delete D3_; delete F1_;delete F2_;delete F3_;delete F4_; } void LauRescattering2Res::initialise() { sqr_tmin[1] = 2.00*LauConstants::mK; sqr_tmin[2] = 1.47; sqr_tmax[1] = 1.47; sqr_tmax[2] = 2.00; B0_ = 226.5*TMath::Pi()/180.0 + B1_->value() - B2_->value() + B3_->value(); C0_ = phi00(sqr_tmax[1]*sqr_tmax[1], 1) + C1_->value() - C2_->value() + C3_->value() - C4_->value() + C5_->value(); F0_ = g00(sqr_tmax[1]*sqr_tmax[1], 1) + F1_->value() - F2_->value() + F3_->value() - F4_->value(); std::cout << "##### B = " << this->B1_->value()<<", "<< this->B2_->value()<<", "<< this->B3_->value()<C2_->value()<<", "<< this->C3_->value()<<", "<< this->C4_->value()<<", "<< this->C5_->value()<D1_->value()<<", "<< this->D2_->value()<<", "<< this->D3_->value()<< std::endl; std::cout << "##### F = " << this->F1_->value()<<", "<< this->F2_->value()<<", "<< this->F3_->value()<<", "<< this->F4_->value()< sqr_tmax[1] && mass < sqr_tmax[2]) i = 2; if (i == 0) { std::cout << " ERROR MASS = " << mass <<" out of limmits mI, mII" << std::endl; return LauComplex(0,0); } Double_t sqr_t = mass; Double_t mag = this->g00(sqr_t, i); Double_t phase = this->phi00(sqr_t, i); return LauComplex(mag*TMath::Cos(phase), mag*TMath::Sin(phase)); } Double_t LauRescattering2Res::pn(const Double_t x_, const Double_t n) const { if (n==0) return 1.0; if (n==1) return x_; return 2*x_*pn(x_,n-1) - pn(x_,n-2); } Double_t LauRescattering2Res::x(const Double_t sqr_t, const Int_t i) const { return 2.0*(sqr_t-sqr_tmin[i])/(sqr_tmax[i]-sqr_tmin[i]) -1.0; } Double_t LauRescattering2Res::phi00(const Double_t sqr_t, const Int_t i) const { Double_t x_t = x(sqr_t, i); if (i==1) return B0_*this->pn(x_t,0)+ B1_->value()*this->pn(x_t,1)+ B2_->value()*this->pn(x_t,2)+ B3_->value()*this->pn(x_t,3); if (i==2) return C0_*this->pn(x_t,0)+ C1_->value()*this->pn(x_t,1)+ C2_->value()*this->pn(x_t,2)+ C3_->value()*this->pn(x_t,3)+ C4_->value()*this->pn(x_t,4)+ C5_->value()*this->pn(x_t,5); return 0; } Double_t LauRescattering2Res::g00(const Double_t sqr_t, const Int_t i) const { Double_t x_t = x(sqr_t, i); if (i==1) return D0_->value()*this->pn(x_t,0)+ D1_->value()*this->pn(x_t,1)+ D2_->value()*this->pn(x_t,2)+ D3_->value()*this->pn(x_t,3); if (i==2) return F0_*this->pn(x_t,0)+ F1_->value()*this->pn(x_t,1)+ F2_->value()*this->pn(x_t,2)+ F3_->value()*this->pn(x_t,3)+ F4_->value()*this->pn(x_t,4); return 0; } // TODO up to here! const std::vector& LauRescattering2Res::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Parameter() ) { this->addFloatingParameter( B1_ ); } if ( ! this->fixB2Parameter() ) { this->addFloatingParameter( B2_ ); } if ( ! this->fixB3Parameter() ) { this->addFloatingParameter( B3_ ); } if ( ! this->fixC1Parameter() ) { this->addFloatingParameter( C1_ ); } if ( ! this->fixC2Parameter() ) { this->addFloatingParameter( C2_ ); } if ( ! this->fixC3Parameter() ) { this->addFloatingParameter( C3_ ); } if ( ! this->fixC4Parameter() ) { this->addFloatingParameter( C4_ ); } if ( ! this->fixC5Parameter() ) { this->addFloatingParameter( C5_ ); } if ( ! this->fixD0Parameter() ) { this->addFloatingParameter( D0_ ); } if ( ! this->fixD1Parameter() ) { this->addFloatingParameter( D1_ ); } if ( ! this->fixD2Parameter() ) { this->addFloatingParameter( D2_ ); } if ( ! this->fixD3Parameter() ) { this->addFloatingParameter( D3_ ); } if ( ! this->fixF1Parameter() ) { this->addFloatingParameter( F1_ ); } if ( ! this->fixF2Parameter() ) { this->addFloatingParameter( F2_ ); } if ( ! this->fixF3Parameter() ) { this->addFloatingParameter( F3_ ); } if ( ! this->fixF4Parameter() ) { this->addFloatingParameter( F4_ ); } return this->getParameters(); } void LauRescattering2Res::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the NRAmplitude lineshape dynamics if (name == "B1") { this->setB1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B1 = " << this->getB1Parameter() << std::endl; } else if (name == "B2") { this->setB2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B2 = " << this->getB2Parameter() << std::endl; } else if (name == "B3") { this->setB3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude B3 = " << this->getB3Parameter() << std::endl; } else if (name == "C1") { this->setC1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C1 = " << this->getC1Parameter() << std::endl; } else if (name == "C2") { this->setC2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C2 = " << this->getC2Parameter() << std::endl; } else if (name == "C3") { this->setC3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C3 = " << this->getC3Parameter() << std::endl; } else if (name == "C4") { this->setC4Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C4 = " << this->getC4Parameter() << std::endl; } else if (name == "C5") { this->setC5Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude C5 = " << this->getC5Parameter() << std::endl; } else if (name == "D0") { this->setD0Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D0 = " << this->getD0Parameter() << std::endl; } else if (name == "D1") { this->setD1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D1 = " << this->getD1Parameter() << std::endl; } else if (name == "D2") { this->setD2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D2 = " << this->getD2Parameter() << std::endl; } else if (name == "D3") { this->setD3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude D3 = " << this->getD3Parameter() << std::endl; } else if (name == "F1") { this->setF1Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F1 = " << this->getF1Parameter() << std::endl; } else if (name == "F2") { this->setF2Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F2 = " << this->getF2Parameter() << std::endl; } else if (name == "F3") { this->setF3Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F3 = " << this->getF3Parameter() << std::endl; } else if (name == "F4") { this->setF4Parameter(value); std::cout << "INFO in LauRescattering2Res::setResonanceParameter : Setting NRAmplitude F4 = " << this->getF4Parameter() << std::endl; } else { std::cerr << "WARNING in LauRescattering2Res::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauRescattering2Res::floatResonanceParameter(const TString& name) { if (name == "B1") { if ( B1_->fixed() ) { B1_->fixed( kFALSE ); this->addFloatingParameter( B1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "B2") { if ( B2_->fixed() ) { B2_->fixed( kFALSE ); this->addFloatingParameter( B2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "B3") { if ( B3_->fixed() ) { B3_->fixed( kFALSE ); this->addFloatingParameter( B3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C1") { if ( C1_->fixed() ) { C1_->fixed( kFALSE ); this->addFloatingParameter( C1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C2") { if ( C2_->fixed() ) { C2_->fixed( kFALSE ); this->addFloatingParameter( C2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C3") { if ( C3_->fixed() ) { C3_->fixed( kFALSE ); this->addFloatingParameter( C3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C4") { if ( C4_->fixed() ) { C4_->fixed( kFALSE ); this->addFloatingParameter( C4_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C5") { if ( C5_->fixed() ) { C5_->fixed( kFALSE ); this->addFloatingParameter( C5_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D0") { if ( D0_->fixed() ) { D0_->fixed( kFALSE ); this->addFloatingParameter( D0_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D1") { if ( D1_->fixed() ) { D1_->fixed( kFALSE ); this->addFloatingParameter( D1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D2") { if ( D2_->fixed() ) { D2_->fixed( kFALSE ); this->addFloatingParameter( D2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "D3") { if ( D3_->fixed() ) { D3_->fixed( kFALSE ); this->addFloatingParameter( D3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F1") { if ( F1_->fixed() ) { F1_->fixed( kFALSE ); this->addFloatingParameter( F1_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F2") { if ( F2_->fixed() ) { F2_->fixed( kFALSE ); this->addFloatingParameter( F2_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "F3") { if ( F3_->fixed() ) { F3_->fixed( kFALSE ); this->addFloatingParameter( F3_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "4F") { if ( F4_->fixed() ) { F4_->fixed( kFALSE ); this->addFloatingParameter( F4_ ); } else { std::cerr << "WARNING in LauRescattering2Res::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauRescattering2Res::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauRescattering2Res::getResonanceParameter(const TString& name) { if (name == "B1") { return B1_; } else if (name == "B2") { return B2_; } else if (name == "B3") { return B3_; } else if (name == "C1") { return C1_; } else if (name == "C2") { return C2_; } else if (name == "C3") { return C3_; } else if (name == "C4") { return C4_; } else if (name == "C5") { return C5_; } else if (name == "D0") { return D0_; } else if (name == "D1") { return D1_; } else if (name == "D2") { return D2_; } else if (name == "D3") { return D3_; } else if (name == "F1") { return F1_; } else if (name == "F2") { return F2_; } else if (name == "F3") { return F3_; } else if (name == "F4") { return F4_; } else { std::cerr << "WARNING in LauRescattering2Res::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauRescattering2Res::setB1Parameter(const Double_t B1) { B1_->value( B1 ); B1_->genValue( B1 ); B1_->initValue( B1 ); } void LauRescattering2Res::setB2Parameter(const Double_t B2) { B2_->value( B2 ); B2_->genValue( B2 ); B2_->initValue( B2 ); } void LauRescattering2Res::setB3Parameter(const Double_t B3) { B3_->value( B3 ); B3_->genValue( B3 ); B3_->initValue( B3 ); } void LauRescattering2Res::setC1Parameter(const Double_t C1) { C1_->value( C1 ); C1_->genValue( C1 ); C1_->initValue( C1 ); } void LauRescattering2Res::setC2Parameter(const Double_t C2) { C2_->value( C2 ); C2_->genValue( C2 ); C2_->initValue( C2 ); } void LauRescattering2Res::setC3Parameter(const Double_t C3) { C3_->value( C3 ); C3_->genValue( C3 ); C3_->initValue( C3 ); } void LauRescattering2Res::setC4Parameter(const Double_t C4) { C4_->value( C4 ); C4_->genValue( C4 ); C4_->initValue( C4 ); } void LauRescattering2Res::setC5Parameter(const Double_t C5) { C5_->value( C5 ); C5_->genValue( C5 ); C5_->initValue( C5 ); } void LauRescattering2Res::setD0Parameter(const Double_t D0) { D0_->value( D0 ); D0_->genValue( D0 ); D0_->initValue( D0 ); } void LauRescattering2Res::setD1Parameter(const Double_t D1) { D1_->value( D1 ); D1_->genValue( D1 ); D1_->initValue( D1 ); } void LauRescattering2Res::setD2Parameter(const Double_t D2) { D2_->value( D2 ); D2_->genValue( D2 ); D2_->initValue( D2 ); } void LauRescattering2Res::setD3Parameter(const Double_t D3) { D3_->value( D3 ); D3_->genValue( D3 ); D3_->initValue( D3 ); } void LauRescattering2Res::setF1Parameter(const Double_t F1) { F1_->value( F1 ); F1_->genValue( F1 ); F1_->initValue( F1 ); } void LauRescattering2Res::setF2Parameter(const Double_t F2) { F2_->value( F2 ); F2_->genValue( F2 ); F2_->initValue( F2 ); } void LauRescattering2Res::setF3Parameter(const Double_t F3) { F3_->value( F3 ); F3_->genValue( F3 ); F3_->initValue( F3 ); } void LauRescattering2Res::setF4Parameter(const Double_t F4) { F4_->value( F4 ); F4_->genValue( F4 ); F4_->initValue( F4 ); } diff --git a/src/LauRescatteringRes.cc b/src/LauRescatteringRes.cc index f71bec5..bc503ee 100644 --- a/src/LauRescatteringRes.cc +++ b/src/LauRescatteringRes.cc @@ -1,454 +1,453 @@ /* Copyright 2018 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRescatteringRes.cc \brief File containing implementation of LauRescatteringRes class. */ #include #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauRescatteringRes.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauRescatteringRes) LauRescatteringRes::LauRescatteringRes(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), lambdaPiPi_(0), lambdaKK_(0), Mf_(0), Ms_(0), Mprime_(0), Eps1_(0), Eps2_(0), C0_(0), model_(resType) { TString parNameBase = this->getSanitisedName(); TString lambdaPiPiName(parNameBase); lambdaPiPiName += "_lambdaPiPi"; lambdaPiPi_ = resInfo->getExtraParameter( lambdaPiPiName ); if ( lambdaPiPi_ == 0 ) { lambdaPiPi_ = new LauParameter( lambdaPiPiName, 1.0, 0.0, 10.0, kTRUE ); lambdaPiPi_->secondStage(kTRUE); resInfo->addExtraParameter( lambdaPiPi_ ); } TString lambdaKKName(parNameBase); lambdaKKName += "_lambdaKK"; lambdaKK_ = resInfo->getExtraParameter( lambdaKKName ); if ( lambdaKK_ == 0 ) { lambdaKK_ = new LauParameter( lambdaKKName, 2.8, 0.0, 10.0, kTRUE ); lambdaKK_->secondStage(kTRUE); resInfo->addExtraParameter( lambdaKK_ ); } TString MfName(parNameBase); MfName += "_Mf"; Mf_ = resInfo->getExtraParameter( MfName ); if ( Mf_ == 0 ) { Mf_ = new LauParameter( MfName, 1.32, 0.0, 10.0, kTRUE ); Mf_->secondStage(kTRUE); resInfo->addExtraParameter( Mf_ ); } TString MsName(parNameBase); MsName += "_Ms"; Ms_ = resInfo->getExtraParameter( MsName ); if ( Ms_ == 0 ) { Ms_ = new LauParameter( MsName, 0.92, 0.0, 10.0, kTRUE ); Ms_->secondStage(kTRUE); resInfo->addExtraParameter( Ms_ ); } TString MprimeName(parNameBase); MprimeName += "_Mprime"; Mprime_ = resInfo->getExtraParameter( MprimeName ); if ( Mprime_ == 0 ) { Mprime_ = new LauParameter( MprimeName, 1.5, 0.0, 10.0, kTRUE ); Mprime_->secondStage(kTRUE); resInfo->addExtraParameter( Mprime_ ); } TString Eps1Name(parNameBase); Eps1Name += "_Eps1"; Eps1_ = resInfo->getExtraParameter( Eps1Name ); if ( Eps1_ == 0 ) { Eps1_ = new LauParameter( Eps1Name, 2.4, 0.0, 10.0, kTRUE ); Eps1_->secondStage(kTRUE); resInfo->addExtraParameter( Eps1_ ); } TString Eps2Name(parNameBase); Eps2Name += "_Eps2"; Eps2_ = resInfo->getExtraParameter( Eps2Name ); if ( Eps2_ == 0 ) { Eps2_ = new LauParameter( Eps2Name, -5.5, -10.0, 10.0, kTRUE ); Eps2_->secondStage(kTRUE); resInfo->addExtraParameter( Eps2_ ); } TString C0Name(parNameBase); C0Name += "_C0"; C0_ = resInfo->getExtraParameter( C0Name ); if ( C0_ == 0 ) { C0_ = new LauParameter( C0Name, 1.3, 0.0, 10.0, kTRUE ); C0_->secondStage(kTRUE); resInfo->addExtraParameter( C0_ ); } } LauRescatteringRes::~LauRescatteringRes() { } void LauRescatteringRes::initialise() { const LauDaughters* daughters = this->getDaughters(); Int_t resPairAmpInt = this->getPairInt(); if ( daughters->gotSymmetricalDP() && resPairAmpInt != 3 ) { std::cerr << "WARNING in LauRescatteringRes::initialise : Dalitz plot is symmetric - this lineshape is not appropriate." << std::endl; std::cerr << "WARNING I think that this warning is not appropiate because Laura Simetrize at LauIsobarModel level." << std::endl; } if ( (model_ != LauAbsResonance::Rescattering) && (model_ != LauAbsResonance::RescatteringNoInter)) { std::cerr << "WARNING in LauRescatteringRes::initialise : Unknown model requested, defaulting to exponential." << std::endl; model_ = LauAbsResonance::Rescattering; } if ( (model_ != LauAbsResonance::RescatteringNoInter) && (this->getSpin() != 0) ) { std::cerr << "WARNING in LauRescatteringRes::initialise : Non-zero spin will be ignored for this model - perhaps you should use LauAbsResonance::BelleSymNRNoInter instead" << std::endl; } } LauComplex LauRescatteringRes::amplitude(const LauKinematics* kinematics) { // This function returns the complex dynamical amplitude for a Reescatering distribution o original // pelaez paper parameters Eq 2.15a [Pelaez et Yndúrain: arXiv:hep-ph/0411334v2 Mar 2005] Double_t Mprime = this->getMprime(); Double_t Mf = this->getMf(); Double_t Ms = this->getMs(); Double_t eps1 = this->getEps1(); Double_t eps2 = this->getEps2(); Double_t c0 = this->getC0(); Double_t lambPiPi = this->getLambdaPiPi(); Double_t lambKK = this->getLambdaKK(); Double_t mk = LauConstants::mK; // Calculate Mandelstam variables: s = m_13^2, t = m_23^2, u = m_12^2. Double_t s = 0; Double_t t = 0; Int_t resPairAmpInt = getPairInt(); if (resPairAmpInt == 1) { s = kinematics->getm23Sq(); t = kinematics->getm12Sq(); } else if (resPairAmpInt == 2) { s = kinematics->getm13Sq(); t = kinematics->getm23Sq(); } else if (resPairAmpInt == 3) { s = kinematics->getm12Sq(); t = kinematics->getm13Sq(); } else { std::cerr << "ERROR in LauAbsResonance::amplitude : Nonsense setup of resPairAmp array." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Calculate amplitude for s variable. Double_t mass_s = TMath::Sqrt(s); Double_t k2Square_s = (s - 4.0*mk*mk)/4.0; Double_t k2Abs_s=0; if (k2Square_s > 0) k2Abs_s = TMath::Sqrt(k2Square_s); else k2Abs_s = TMath::Sqrt(-1.0*k2Square_s); Double_t cotdelta0_s = c0*(s - Ms*Ms)*(Mf*Mf - s)*k2Abs_s/(Mf*Mf*mass_s*k2Square_s); // Eq 2.15a Double_t delta0_s = TMath::ATan(1.0/cotdelta0_s); Double_t eta0_s = 1.0 - (eps1*k2Abs_s/mass_s + eps2*k2Square_s/s)*(Mprime*Mprime-s)/s; // Eq 2.15a if ((mass_s < 2.0*mk)||(mass_s > Mprime )) eta0_s = 1; Double_t mag_s = TMath::Sqrt( 1-eta0_s*eta0_s); Double_t tauRe_s = mag_s*TMath::Cos(2.0*delta0_s); Double_t tauIm_s = mag_s*TMath::Sin(2.0*delta0_s); Double_t NR1_s = 1.0/(1.0+s/(lambPiPi*lambPiPi)); Double_t NR2_s = 1.0/(1.0+s/(lambKK*lambKK)); //LauComplex resAmplitude(-tauIm_s*NR1_s*NR2_s - tauIm_t*NR1_t*NR2_t, tauRe_s*NR1_s*NR2_s + tauRe_t*NR1_t*NR2_t ); if ((model_ == LauAbsResonance::RescatteringNoInter)&&(t<=s)) { NR1_s=0.0; NR2_s=0.0; tauRe_s=0.0; tauIm_s=0.0; } LauComplex resAmplitude(-tauIm_s*NR1_s*NR2_s ,tauRe_s*NR1_s*NR2_s); return resAmplitude; } LauComplex LauRescatteringRes::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauRescatteringRes : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauRescatteringRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixLambdaPiPi() ) { this->addFloatingParameter( lambdaPiPi_ ); } if ( ! this->fixLambdaKK() ) { this->addFloatingParameter( lambdaKK_ ); } if ( ! this->fixMf() ) { this->addFloatingParameter( Mf_ ); } if ( ! this->fixMs() ) { this->addFloatingParameter( Ms_ ); } if ( ! this->fixMprime() ) { this->addFloatingParameter( Mprime_ ); } if ( ! this->fixEps1() ) { this->addFloatingParameter( Eps1_ ); } if ( ! this->fixEps2() ) { this->addFloatingParameter( Eps2_ ); } if ( ! this->fixC0() ) { this->addFloatingParameter( C0_ ); } return this->getParameters(); } void LauRescatteringRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "lambdaPiPi") { this->setLambdaPiPi(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter lambdaPiPi = " << this->getLambdaPiPi() << std::endl; } else if (name == "lambdaKK") { this->setLambdaKK(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter lambdaKK = " << this->getLambdaKK() << std::endl; } else if (name == "Mf") { this->setMf(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Mf = " << this->getMf() << std::endl; } else if (name == "Ms") { this->setMs(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Ms = " << this->getMs() << std::endl; } else if (name == "Mprime") { this->setMprime(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter Mprime = " << this->getMprime() << std::endl; } else if (name == "Eps1") { this->setEps1(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps1 = " << this->getEps1() << std::endl; } else if (name == "Eps2") { this->setEps2(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps2 = " << this->getEps2() << std::endl; } else if (name == "C0") { this->setC0(value); std::cout << "INFO in LauRescatteringRes::setResonanceParameter : Setting parameter eps2 = " << this->getC0() << std::endl; } else { std::cerr << "WARNING in LauRescatteringRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauRescatteringRes::floatResonanceParameter(const TString& name) { if (name == "lambdaPiPi") { if ( lambdaPiPi_->fixed() ) { lambdaPiPi_->fixed( kFALSE ); this->addFloatingParameter( lambdaPiPi_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "lambdaKK") { if ( lambdaKK_->fixed() ) { lambdaKK_->fixed( kFALSE ); this->addFloatingParameter( lambdaKK_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Mf") { if ( Mf_->fixed() ) { Mf_->fixed( kFALSE ); this->addFloatingParameter( Mf_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Ms") { if ( Ms_->fixed() ) { Ms_->fixed( kFALSE ); this->addFloatingParameter( Ms_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Mprime") { if ( Mprime_->fixed() ) { Mprime_->fixed( kFALSE ); this->addFloatingParameter( Mprime_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Eps1") { if ( Eps1_->fixed() ) { Eps1_->fixed( kFALSE ); this->addFloatingParameter( Eps1_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "Eps2") { if ( Eps2_->fixed() ) { Eps2_->fixed( kFALSE ); this->addFloatingParameter( Eps2_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "C0") { if ( C0_->fixed() ) { C0_->fixed( kFALSE ); this->addFloatingParameter( C0_ ); } else { std::cerr << "WARNING in LauRescatteringRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauRescatteringRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauRescatteringRes::getResonanceParameter(const TString& name) { if (name == "lambdaPiPi") { return lambdaPiPi_; } else if (name == "lambdaKK") { return lambdaKK_; } if (name == "Mf") { return Mf_; } else if (name == "Ms") { return Ms_; } if (name == "Mprime") { return Mprime_; } if (name == "Eps1") { return Eps1_; } if (name == "Eps2") { return Eps2_; } if (name == "C0") { return C0_; } else { std::cerr << "WARNING in LauRescatteringRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauRescatteringRes::setLambdaPiPi(const Double_t lambda) { lambdaPiPi_->value( lambda ); lambdaPiPi_->genValue( lambda ); lambdaPiPi_->initValue( lambda ); } void LauRescatteringRes::setLambdaKK(const Double_t lambda) { lambdaKK_->value( lambda ); lambdaKK_->genValue( lambda ); lambdaKK_->initValue( lambda ); } void LauRescatteringRes::setMf(const Double_t Mf) { Mf_->value( Mf ); Mf_->genValue( Mf ); Mf_->initValue( Mf ); } void LauRescatteringRes::setMs(const Double_t Ms) { Ms_->value( Ms ); Ms_->genValue( Ms ); Ms_->initValue( Ms ); } void LauRescatteringRes::setMprime(const Double_t Mprime) { Mprime_->value( Mprime ); Mprime_->genValue( Mprime); Mprime_->initValue( Mprime ); } void LauRescatteringRes::setEps1(const Double_t Eps1) { Eps1_->value( Eps1 ); Eps1_->genValue( Eps1 ); Eps1_->initValue( Eps1 ); } void LauRescatteringRes::setEps2(const Double_t Eps2) { Eps2_->value( Eps2 ); Eps2_->genValue( Eps2 ); Eps2_->initValue( Eps2 ); } void LauRescatteringRes::setC0(const Double_t C0) { C0_->value( C0 ); C0_->genValue( C0 ); C0_->initValue( C0 ); } diff --git a/src/LauResonanceInfo.cc b/src/LauResonanceInfo.cc index fbb9e59..b2b4504 100644 --- a/src/LauResonanceInfo.cc +++ b/src/LauResonanceInfo.cc @@ -1,212 +1,211 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceInfo.cc \brief File containing implementation of LauResonanceInfo class. */ #include #include "LauParameter.hh" #include "LauResonanceInfo.hh" -ClassImp(LauResonanceInfo) LauResonanceInfo::LauResonanceInfo(const TString& name, const Double_t mass, const Double_t width, const Int_t spin, const Int_t charge, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius) : name_(name), sanitisedName_(""), mass_(0), width_(0), spin_(spin), charge_(charge), bwCategory_(bwCategory), bwRadius_(bwRadius), conjugate_(0), extraPars_() { this->sanitiseName(); mass_ = new LauParameter(sanitisedName_+"_MASS",mass,0.0,3.0*mass,kTRUE); mass_->secondStage(kTRUE); width_ = new LauParameter(sanitisedName_+"_WIDTH",width,0.0,3.0*width,kTRUE); width_->secondStage(kTRUE); } LauResonanceInfo::~LauResonanceInfo() { delete mass_; mass_ = 0; delete width_; width_ = 0; for ( std::set::iterator iter = extraPars_.begin(); iter != extraPars_.end(); ++iter ) { delete (*iter); } extraPars_.clear(); } LauResonanceInfo::LauResonanceInfo( const LauResonanceInfo& other, const TString& newName, const Int_t newCharge ) : name_(newName), sanitisedName_(""), mass_(0), width_(0), spin_(other.spin_), charge_(newCharge), bwCategory_(other.bwCategory_), bwRadius_(other.bwRadius_), conjugate_(0), extraPars_() { this->sanitiseName(); mass_ = other.mass_->createClone( sanitisedName_+"_MASS" ); width_ = other.width_->createClone( sanitisedName_+"_WIDTH" ); for ( std::set::iterator iter = other.extraPars_.begin(); iter != other.extraPars_.end(); ++iter ) { TString parName = (*iter)->name(); parName.Remove(0, parName.Last('_')); parName.Prepend( sanitisedName_ ); LauParameter* par = (*iter)->createClone( parName ); extraPars_.insert( par ); } } LauResonanceInfo* LauResonanceInfo::createChargeConjugate() { Int_t newCharge = -charge_; TString newName( name_ ); Ssiz_t index = newName.Index("+"); if ( index != -1 ) { newName.Replace( index, 1, "-" ); } else { index = newName.Index("-"); if ( index != -1 ) { newName.Replace( index, 1, "+" ); } } LauResonanceInfo* conjugate = new LauResonanceInfo( *this, newName, newCharge ); conjugate->conjugate_ = this; this->conjugate_ = conjugate; return conjugate; } LauResonanceInfo* LauResonanceInfo::createSharedParameterRecord( const TString& name ) { LauResonanceInfo* newinfo = new LauResonanceInfo( *this, name, charge_ ); sharedParRecords_.push_back(newinfo); return newinfo; } LauParameter* LauResonanceInfo::getExtraParameter( const TString& parName ) { LauParameter* par(0); for ( std::set::iterator iter = extraPars_.begin(); iter != extraPars_.end(); ++iter ) { if ( (*iter)->name() == parName ) { par = (*iter); } } return par; } void LauResonanceInfo::addExtraParameter( LauParameter* param, const Bool_t independentPar ) { bool ok = extraPars_.insert( param ).second; if ( !ok ) { std::cerr << "WARNING in LauResonanceInfo::addExtraParameter : parameter already present, not adding again" << std::endl; return; } if ( conjugate_ != 0 ) { conjugate_->addCloneOfExtraParameter( param, independentPar ); } for ( std::vector::iterator iter = sharedParRecords_.begin(); iter != sharedParRecords_.end(); ++iter ) { (*iter)->addCloneOfExtraParameter( param, independentPar ); } } void LauResonanceInfo::addCloneOfExtraParameter( LauParameter* param, const Bool_t copyNotClone ) { TString parName = param->name(); parName.Remove(0, parName.Last('_')); parName.Prepend( sanitisedName_ ); LauParameter* cloneParam(0); if ( copyNotClone ) { cloneParam = new LauParameter( parName, param->unblindValue(), param->minValue(), param->maxValue(), param->fixed() ); cloneParam->secondStage(kTRUE); } else { cloneParam = param->createClone( parName ); } extraPars_.insert( cloneParam ); } std::ostream& operator<<( std::ostream& stream, const LauResonanceInfo& infoRecord ) { stream << infoRecord.getName() << ": "; stream << "mass = " << infoRecord.getMass()->value() << ", "; stream << "width = " << infoRecord.getWidth()->value() << ", "; stream << "spin = " << infoRecord.getSpin() << ", "; Int_t charge = infoRecord.getCharge(); if ( charge < 0 ) { stream << "charge = " << infoRecord.getCharge() << ", "; } else { stream << "charge = " << infoRecord.getCharge() << ", "; } stream << "BW radius = " << infoRecord.getBWRadius(); return stream; } void LauResonanceInfo::sanitiseName() { sanitisedName_ = name_; sanitisedName_ = sanitisedName_.ReplaceAll("+","p"); sanitisedName_ = sanitisedName_.ReplaceAll("-","m"); sanitisedName_ = sanitisedName_.ReplaceAll("*","st"); sanitisedName_ = sanitisedName_.ReplaceAll("(","_"); sanitisedName_ = sanitisedName_.ReplaceAll(")","_"); sanitisedName_ = sanitisedName_.ReplaceAll("[","_"); sanitisedName_ = sanitisedName_.ReplaceAll("]","_"); sanitisedName_ = sanitisedName_.ReplaceAll("<","_"); sanitisedName_ = sanitisedName_.ReplaceAll(">","_"); sanitisedName_ = sanitisedName_.ReplaceAll("{","_"); sanitisedName_ = sanitisedName_.ReplaceAll("}","_"); sanitisedName_ = sanitisedName_.ReplaceAll(" ","_"); sanitisedName_ = sanitisedName_.ReplaceAll("$",""); sanitisedName_ = sanitisedName_.ReplaceAll("%",""); sanitisedName_ = sanitisedName_.ReplaceAll("&",""); sanitisedName_ = sanitisedName_.ReplaceAll("/",""); sanitisedName_ = sanitisedName_.ReplaceAll(":",""); sanitisedName_ = sanitisedName_.ReplaceAll(";",""); sanitisedName_ = sanitisedName_.ReplaceAll("=",""); sanitisedName_ = sanitisedName_.ReplaceAll("\\",""); sanitisedName_ = sanitisedName_.ReplaceAll("^",""); sanitisedName_ = sanitisedName_.ReplaceAll("|",""); sanitisedName_ = sanitisedName_.ReplaceAll(",",""); sanitisedName_ = sanitisedName_.ReplaceAll(".",""); sanitisedName_.Remove(TString::kBoth,'_'); } diff --git a/src/LauResonanceMaker.cc b/src/LauResonanceMaker.cc index 31065e6..b264fb8 100644 --- a/src/LauResonanceMaker.cc +++ b/src/LauResonanceMaker.cc @@ -1,1043 +1,1042 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResonanceMaker.cc \brief File containing implementation of LauResonanceMaker class. */ #include #include "LauAbsResonance.hh" #include "LauBelleNR.hh" #include "LauBelleSymNR.hh" #include "LauBreitWignerRes.hh" #include "LauDabbaRes.hh" #include "LauDaughters.hh" #include "LauEFKLLMRes.hh" #include "LauFlatteRes.hh" #include "LauFlatNR.hh" #include "LauGaussIncohRes.hh" #include "LauGounarisSakuraiRes.hh" #include "LauKappaRes.hh" #include "LauLASSRes.hh" #include "LauLASSBWRes.hh" #include "LauLASSNRRes.hh" #include "LauModIndPartWaveMagPhase.hh" #include "LauModIndPartWaveRealImag.hh" #include "LauNRAmplitude.hh" #include "LauRescatteringRes.hh" #include "LauRescattering2Res.hh" #include "LauPolNR.hh" #include "LauPoleRes.hh" #include "LauPolarFormFactorNR.hh" #include "LauPolarFormFactorSymNR.hh" #include "LauRelBreitWignerRes.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" #include "LauRhoOmegaMix.hh" #include "LauSigmaRes.hh" -ClassImp(LauResonanceMaker); LauResonanceMaker* LauResonanceMaker::resonanceMaker_ = 0; LauResonanceMaker::LauResonanceMaker() : nResDefMax_(0), bwBarrierType_(LauBlattWeisskopfFactor::BWPrimeBarrier), bwRestFrame_(LauBlattWeisskopfFactor::ResonanceFrame), spinFormalism_(LauAbsResonance::Zemach_P), summaryPrinted_(kFALSE) { this->createResonanceVector(); this->setDefaultBWRadius( LauBlattWeisskopfFactor::Parent, 4.0 ); } LauResonanceMaker::~LauResonanceMaker() { for ( std::vector::iterator iter = bwIndepFactors_.begin(); iter != bwIndepFactors_.end(); ++iter ) { delete *iter; } bwIndepFactors_.clear(); for ( BWFactorCategoryMap::iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { delete iter->second.bwFactor_; } bwFactors_.clear(); } LauResonanceMaker& LauResonanceMaker::get() { if ( resonanceMaker_ == 0 ) { resonanceMaker_ = new LauResonanceMaker(); } return *resonanceMaker_; } void LauResonanceMaker::createResonanceVector() { // Function to create all possible resonances that this class supports. // Also add in the sigma and kappa - but a special paramterisation is used // instead of the PDG "pole mass and width" values. std::cout << "INFO in LauResonanceMaker::createResonanceVector : Setting up possible resonance states..." << std::endl; LauResonanceInfo* neutral(0); LauResonanceInfo* positve(0); LauResonanceInfo* negatve(0); // Define the resonance names and store them in the array resInfo_.clear(); resInfo_.reserve(100); // rho resonances name, mass, width, spin, charge, default BW category, BW radius parameter (defaults to 4.0) // rho(770) neutral = new LauResonanceInfo("rho0(770)", 0.77526, 0.1478, 1, 0, LauBlattWeisskopfFactor::Light, 5.3); positve = new LauResonanceInfo("rho+(770)", 0.77511, 0.1491, 1, 1, LauBlattWeisskopfFactor::Light, 5.3); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // The following two lines of code are placed here in order to allow the following, rather niche, scenario: // The LauRhoOmegaMix code permits (through the use of the optional independentPar argument of LauResonanceInfo::addExtraParameter) the magnitude and phase of the rho/omega mixing to potentially differ between the decay of the parent particle to rho0 X and the parent antiparticle to rho0 Xbar. // This can be acheived by using the rho0(770) record in one case and the rho0(770)_COPY record in the other. neutral = neutral->createSharedParameterRecord("rho0(770)_COPY"); resInfo_.push_back( neutral ); // rho(1450) neutral = new LauResonanceInfo("rho0(1450)", 1.465, 0.400, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1450)", 1.465, 0.400, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho_3(1690) neutral = new LauResonanceInfo("rho0_3(1690)", 1.686, 0.186, 3, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+_3(1690)", 1.686, 0.186, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho(1700) neutral = new LauResonanceInfo("rho0(1700)", 1.720, 0.250, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1700)", 1.720, 0.250, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho(1900) neutral = new LauResonanceInfo("rho0(1900)", 1.909, 0.130, 1, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+(1900)", 1.909, 0.130, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // rho_3(1990) neutral = new LauResonanceInfo("rho0_3(1990)", 1.982, 0.188, 3, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("rho+_3(1990)", 1.982, 0.188, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K* resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // K*(892) neutral = new LauResonanceInfo("K*0(892)", 0.89555, 0.0473, 1, 0, LauBlattWeisskopfFactor::Kstar, 3.0); positve = new LauResonanceInfo("K*+(892)", 0.89166, 0.0508, 1, 1, LauBlattWeisskopfFactor::Kstar, 3.0); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1410) neutral = new LauResonanceInfo("K*0(1410)", 1.414, 0.232, 1, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+(1410)", 1.414, 0.232, 1, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*_0(1430) neutral = new LauResonanceInfo("K*0_0(1430)", 1.425, 0.270, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_0(1430)", 1.425, 0.270, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // LASS nonresonant model neutral = neutral->createSharedParameterRecord("LASSNR0"); positve = positve->createSharedParameterRecord("LASSNR+"); negatve = negatve->createSharedParameterRecord("LASSNR-"); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*_2(1430) neutral = new LauResonanceInfo("K*0_2(1430)", 1.4324, 0.109, 2, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_2(1430)", 1.4273, 0.100, 2, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1680) neutral = new LauResonanceInfo("K*0(1680)", 1.718, 0.322, 1, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+(1680)", 1.718, 0.322, 1, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // K*(1950) neutral = new LauResonanceInfo("K*0_0(1950)", 1.945, 0.201, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("K*+_0(1950)", 1.945, 0.201, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // phi resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // phi(1020) neutral = new LauResonanceInfo("phi(1020)", 1.019461, 0.004249, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // phi(1680) neutral = new LauResonanceInfo("phi(1680)", 1.680, 0.150, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // f_0(980) neutral = new LauResonanceInfo("f_0(980)", 0.990, 0.070, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1270) neutral = new LauResonanceInfo("f_2(1270)", 1.2755, 0.1867, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(1370) neutral = new LauResonanceInfo("f_0(1370)", 1.370, 0.350, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f'_0(1300), from Belle's Kspipi paper neutral = new LauResonanceInfo("f'_0(1300)", 1.449, 0.126, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1430) neutral = new LauResonanceInfo("f_2(1430)", 1.430, 0.150, 2, 0, LauBlattWeisskopfFactor::Light ); // PDG width in the range 13 - 150 resInfo_.push_back( neutral ); // f_0(1500) neutral = new LauResonanceInfo("f_0(1500)", 1.506, 0.112, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f'_2(1525) neutral = new LauResonanceInfo("f'_2(1525)", 1.5174, 0.086, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1565) neutral = new LauResonanceInfo("f_2(1565)", 1.542, 0.122, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1640) neutral = new LauResonanceInfo("f_2(1640)", 1.639, 0.099, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(1710) neutral = new LauResonanceInfo("f_0(1710)", 1.704, 0.123, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1810) neutral = new LauResonanceInfo("f_2(1810)", 1.815, 0.197, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1910) neutral = new LauResonanceInfo("f_2(1910)", 1.900, 0.167, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(1950) neutral = new LauResonanceInfo("f_2(1950)", 1.936, 0.464, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_2(2010) neutral = new LauResonanceInfo("f_2(2010)", 2.011, 0.202, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(2020) neutral = new LauResonanceInfo("f_0(2020)", 1.992, 0.442, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_4(2050) neutral = new LauResonanceInfo("f_4(2050)", 2.018, 0.237, 4, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // f_0(2100) neutral = new LauResonanceInfo("f_0(2100)", 2.086, 0.284, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // omega resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // omega(782) neutral = new LauResonanceInfo("omega(782)", 0.78265, 0.00849, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // a resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // a_0(980) neutral = new LauResonanceInfo("a0_0(980)", 0.980, 0.092, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_0(980)", 0.980, 0.092, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // a_0(1450) neutral = new LauResonanceInfo("a0_0(1450)", 1.474, 0.265, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_0(1450)", 1.474, 0.265, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // a_2(1320) neutral = new LauResonanceInfo("a0_2(1320)", 1.3169, 0.1050, 2, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("a+_2(1320)", 1.3169, 0.1050, 2, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // charmonium resonances name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // chi_c0 neutral = new LauResonanceInfo("chi_c0", 3.41471, 0.0108, 0, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c1 neutral = new LauResonanceInfo("chi_c1", 3.51067, 0.00084, 0, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c2 neutral = new LauResonanceInfo("chi_c2", 3.55617, 0.00197, 2, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // psi(3770) neutral = new LauResonanceInfo("psi(3770)", 3.7737, 0.0272, 1, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // X(3872) neutral = new LauResonanceInfo("X(3872)", 3.87169, 0.0012, 1, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // chi_c2(2P) neutral = new LauResonanceInfo("chi_c2(2P)", 3.9222, 0.0353, 2, 0, LauBlattWeisskopfFactor::Charmonium ); resInfo_.push_back( neutral ); // unknown scalars name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // sigma neutral = new LauResonanceInfo("sigma0", 0.475, 0.550, 0, 0, LauBlattWeisskopfFactor::Light ); positve = new LauResonanceInfo("sigma+", 0.475, 0.550, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // kappa neutral = new LauResonanceInfo("kappa0", 0.824, 0.478, 0, 0, LauBlattWeisskopfFactor::Kstar ); positve = new LauResonanceInfo("kappa+", 0.824, 0.478, 0, 1, LauBlattWeisskopfFactor::Kstar ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // dabba neutral = new LauResonanceInfo("dabba0", 2.098, 0.520, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("dabba+", 2.098, 0.520, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited charm states name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // D* neutral = new LauResonanceInfo("D*0", 2.00685, 0.0021, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+", 2.01026, 83.4e-6, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D*_0 neutral = new LauResonanceInfo("D*0_0", 2.300, 0.274, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+_0", 2.349, 0.221, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D*_2 //AVERAGE--neutral = new LauResonanceInfo("D*0_2", 2.4618, 0.049, 2, 0 ); neutral = new LauResonanceInfo("D*0_2", 2.4607, 0.0475, 2, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D*+_2", 2.4654, 0.0467, 2, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D1(2420) neutral = new LauResonanceInfo("D0_1(2420)", 2.4208, 0.0317, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+_1(2420)", 2.4232, 0.025, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D(2600) //OLD--neutral = new LauResonanceInfo("D0(2600)", 2.6087, 0.093, 0, 0 ); //OLD--positve = new LauResonanceInfo("D+(2600)", 2.6213, 0.093, 0, 1 ); neutral = new LauResonanceInfo("D0(2600)", 2.623, 0.139, 0, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+(2600)", 2.623, 0.139, 0, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // D(2680) neutral = new LauResonanceInfo("D*0_1(2680)", 2.6811, 0.1867, 1, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // D(2760) //OLD-- neutral = new LauResonanceInfo("D0(2760)", 2.7633, 0.061, 1, 0 ); //OLD-- positve = new LauResonanceInfo("D+(2760)", 2.7697, 0.061, 1, 1 ); neutral = new LauResonanceInfo("D0(2760)", 2.761, 0.063, 1, 0, LauBlattWeisskopfFactor::Charm ); positve = new LauResonanceInfo("D+(2760)", 2.761, 0.063, 1, 1, LauBlattWeisskopfFactor::Charm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("D*0_3(2760)", 2.7755, 0.0953, 3, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // D(2900) neutral = new LauResonanceInfo("D0(3000)", 3.214, 0.186, 0, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // D(3400) neutral = new LauResonanceInfo("D0(3400)", 3.4, 0.15, 0, 0, LauBlattWeisskopfFactor::Charm ); resInfo_.push_back( neutral ); // excited strange charm name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Ds* positve = new LauResonanceInfo("Ds*+", 2.1121, 0.0019, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds0*(2317) positve = new LauResonanceInfo("Ds*+_0(2317)", 2.3178, 0.0038, 0, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds2*(2573) positve = new LauResonanceInfo("Ds*+_2(2573)", 2.5691, 0.0169, 2, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds1*(2700) positve = new LauResonanceInfo("Ds*+_1(2700)", 2.7083, 0.120, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds1*(2860) positve = new LauResonanceInfo("Ds*+_1(2860)", 2.859, 0.159, 1, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Ds3*(2860) positve = new LauResonanceInfo("Ds*+_3(2860)", 2.860, 0.053, 3, 1, LauBlattWeisskopfFactor::StrangeCharm ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited bottom states name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // B* neutral = new LauResonanceInfo("B*0", 5.3247, 0.00, 1, 0, LauBlattWeisskopfFactor::Beauty, 6.0); positve = new LauResonanceInfo("B*+", 5.3247, 0.00, 1, 1, LauBlattWeisskopfFactor::Beauty, 6.0); negatve = positve->createChargeConjugate(); resInfo_.push_back( neutral ); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // excited strange bottom name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Bs* neutral = new LauResonanceInfo("Bs*0", 5.4154, 0.00, 1, 0, LauBlattWeisskopfFactor::StrangeBeauty, 6.0); resInfo_.push_back( neutral ); // nonresonant models name, mass, width, spin, charge, BW category, BW radius parameter (defaults to 4.0) // Phase-space nonresonant model neutral = new LauResonanceInfo("NonReson", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Theory-based nonresonant model neutral = new LauResonanceInfo("NRModel", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Belle nonresonant models neutral = new LauResonanceInfo("BelleSymNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("BelleNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR+", 0.0, 0.0, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Swave", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Swave+",0.0, 0.0, 0, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Pwave", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Pwave+",0.0, 0.0, 1, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Dwave", 0.0, 0.0, 2, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Dwave+",0.0, 0.0, 2, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); neutral = new LauResonanceInfo("BelleNR_Fwave", 0.0, 0.0, 3, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); positve = new LauResonanceInfo("BelleNR_Fwave+",0.0, 0.0, 3, 1, LauBlattWeisskopfFactor::Light ); negatve = positve->createChargeConjugate(); resInfo_.push_back( positve ); resInfo_.push_back( negatve ); // Taylor expansion nonresonant model neutral = new LauResonanceInfo("NRTaylor", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Polynomial nonresonant models neutral = new LauResonanceInfo("PolNR_S0", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_S1", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_S2", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P0", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P1", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolNR_P2", 0.0, 0.0, 1, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Fake resonances for S-Wave splines neutral = new LauResonanceInfo("Spline_S0", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("Spline_S0_Bar", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // Polar Form Factor nonresonant model neutral = new LauResonanceInfo("PolarFFSymNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); neutral = new LauResonanceInfo("PolarFFNR", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); // PiPi-KK Inelastic Scattering neutral = new LauResonanceInfo("Rescattering", 0.0, 0.0, 0, 0, LauBlattWeisskopfFactor::Light ); resInfo_.push_back( neutral ); nResDefMax_ = resInfo_.size(); } void LauResonanceMaker::setBWType(const LauBlattWeisskopfFactor::BarrierType bwType) { // Check whether any BW factors have been created and bail out if so if ( ! bwIndepFactors_.empty() ) { std::cerr << "ERROR in LauResonanceMaker::setBWType : some barrier factors have already been created - cannot change the barrier type now!" << std::endl; return; } for ( BWFactorCategoryMap::const_iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { if ( iter->second.bwFactor_ != 0 ) { std::cerr << "ERROR in LauResonanceMaker::setBWType : some barrier factors have already been created - cannot change the barrier type now!" << std::endl; return; } } bwBarrierType_ = bwType; } void LauResonanceMaker::setBWBachelorRestFrame(const LauBlattWeisskopfFactor::RestFrame restFrame) { // Check whether any BW factors have been created and bail out if so if ( ! bwIndepFactors_.empty() ) { std::cerr << "ERROR in LauResonanceMaker::setBWBachelorRestFrame : some barrier factors have already been created - cannot change the rest frame now!" << std::endl; return; } for ( BWFactorCategoryMap::const_iterator iter = bwFactors_.begin(); iter != bwFactors_.end(); ++iter ) { if ( iter->second.bwFactor_ != 0 ) { std::cerr << "ERROR in LauResonanceMaker::setBWBachelorRestFrame : some barrier factors have already been created - cannot change the rest frame now!" << std::endl; return; } } bwRestFrame_ = restFrame; } void LauResonanceMaker::setSpinFormalism(const LauAbsResonance::LauSpinType spinType) { if ( summaryPrinted_ ) { std::cerr << "ERROR in LauResonanceMaker::setSpinFormalism : cannot redefine the spin formalism after creating one or more resonances" << std::endl; return; } spinFormalism_ = spinType; } void LauResonanceMaker::setDefaultBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Double_t bwRadius) { if ( bwCategory == LauBlattWeisskopfFactor::Default || bwCategory == LauBlattWeisskopfFactor::Indep ) { std::cerr << "WARNING in LauResonanceMaker::setDefaultBWRadius : cannot set radius values for Default or Indep categories" << std::endl; return; } // Check if we have an information object for this category BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter != bwFactors_.end() ) { // If so, we can set the value in the information object BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; categoryInfo.defaultRadius_ = bwRadius; // Then we can check if a LauBlattWeisskopfFactor object has been created for this category LauBlattWeisskopfFactor* bwFactor = categoryInfo.bwFactor_; if ( bwFactor != 0 ) { // If it has then we can also set its radius value directly LauParameter* radius = bwFactor->getRadiusParameter(); radius->value(bwRadius); radius->initValue(bwRadius); radius->genValue(bwRadius); } } else { // If not then we just store the value to be used later BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = 0; categoryInfo.defaultRadius_ = bwRadius; categoryInfo.radiusFixed_ = kTRUE; } } void LauResonanceMaker::fixBWRadius(const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const Bool_t fixRadius) { if ( bwCategory == LauBlattWeisskopfFactor::Default || bwCategory == LauBlattWeisskopfFactor::Indep ) { std::cerr << "WARNING in LauResonanceMaker::fixBWRadius : cannot fix/float radius values for Default or Indep categories" << std::endl; return; } // Check if we have an information object for this category BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter != bwFactors_.end() ) { // If so, we can set the value in the information object BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; categoryInfo.radiusFixed_ = fixRadius; // Then we can check if a LauBlattWeisskopfFactor object has been created for this category LauBlattWeisskopfFactor* bwFactor = categoryInfo.bwFactor_; if ( bwFactor != 0 ) { // If it has then we can also fix/float its radius value directly LauParameter* radius = bwFactor->getRadiusParameter(); radius->fixed(fixRadius); } } else { // If not then we just store the value to be used later BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = 0; categoryInfo.defaultRadius_ = -1.0; categoryInfo.radiusFixed_ = fixRadius; } } LauBlattWeisskopfFactor* LauResonanceMaker::getParentBWFactor(Int_t resSpin, LauBlattWeisskopfFactor::BarrierType barrierType) { LauBlattWeisskopfFactor* bwFactor(0); // Look up the category in the category information map BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( LauBlattWeisskopfFactor::Parent ); if ( factor_iter == bwFactors_.end() ) { // If the category is currently undefined we need to create it bwFactor = new LauBlattWeisskopfFactor( resSpin, 4.0, bwBarrierType_, bwRestFrame_, LauBlattWeisskopfFactor::Parent ); std::cerr<<"WARNING in LauResonanceMaker::getParentBWFactor : Default radius 4.0 set for Blatt-Weisskopf factor category: Parent"<getRadiusParameter()->value(); categoryInfo.radiusFixed_ = kTRUE; } else { // If it exists, we can check if the factor object has been created BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; if ( categoryInfo.bwFactor_ != 0 ) { // If so, simply clone it bwFactor = categoryInfo.bwFactor_->createClone( resSpin, barrierType ); } else { // Otherwise we need to create it, using the default value if it has been set if ( categoryInfo.defaultRadius_ >= 0.0 ) { bwFactor = new LauBlattWeisskopfFactor( resSpin, categoryInfo.defaultRadius_, bwBarrierType_, bwRestFrame_, LauBlattWeisskopfFactor::Parent ); } else { bwFactor = new LauBlattWeisskopfFactor( resSpin, 4.0, bwBarrierType_, bwRestFrame_, LauBlattWeisskopfFactor::Parent ); std::cerr<<"WARNING in LauResonanceMaker::getParentBWFactor : Default radius 4.0 set for Blatt-Weisskopf factor category: Parent"<getRadiusParameter(); radius->fixed( categoryInfo.radiusFixed_ ); } } return bwFactor; } LauBlattWeisskopfFactor* LauResonanceMaker::getBWFactor( const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory, const LauResonanceInfo* resInfo ) { LauBlattWeisskopfFactor* bwFactor(0); // If this is an independent factor, create it and add it to the list of independent factors, then return it if ( bwCategory == LauBlattWeisskopfFactor::Indep ) { bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); bwIndepFactors_.push_back(bwFactor); return bwFactor; } // Otherwise, look up the category in the category information map BWFactorCategoryMap::iterator factor_iter = bwFactors_.find( bwCategory ); if ( factor_iter == bwFactors_.end() ) { // If the category is currently undefined we need to create it bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); BlattWeisskopfCategoryInfo& categoryInfo = bwFactors_[bwCategory]; categoryInfo.bwFactor_ = bwFactor; categoryInfo.defaultRadius_ = bwFactor->getRadiusParameter()->value(); categoryInfo.radiusFixed_ = kTRUE; } else { // If it exists, we can check if the factor object has been created BlattWeisskopfCategoryInfo& categoryInfo = factor_iter->second; if ( categoryInfo.bwFactor_ != 0 ) { // If so, simply clone it const UInt_t resSpin = resInfo->getSpin(); bwFactor = categoryInfo.bwFactor_->createClone( resSpin, categoryInfo.bwFactor_->getBarrierType() ); } else { // Otherwise we need to create it, using the default value if it has been set if ( categoryInfo.defaultRadius_ >= 0.0 ) { bwFactor = new LauBlattWeisskopfFactor( *resInfo, categoryInfo.defaultRadius_, bwBarrierType_, bwRestFrame_, bwCategory ); } else { bwFactor = new LauBlattWeisskopfFactor( *resInfo, bwBarrierType_, bwRestFrame_, bwCategory ); } categoryInfo.bwFactor_ = bwFactor; // Set whether the radius should be fixed/floated LauParameter* radius = bwFactor->getRadiusParameter(); radius->fixed( categoryInfo.radiusFixed_ ); } } return bwFactor; } LauAbsResonance* LauResonanceMaker::getResonance(const LauDaughters* daughters, const TString& resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory) { // Routine to return the appropriate LauAbsResonance object given the resonance // name (resName), which daughter is the bachelor track (resPairAmpInt = 1,2 or 3), // and the resonance type ("BW" = Breit-Wigner, "Flatte" = Flatte distribution). // If this is the first resonance we are making, first print a summary of the formalism if ( ! summaryPrinted_ ) { std::cout << "INFO in LauResonanceMaker::getResonance : Freezing amplitude formalism:" << std::endl; switch ( spinFormalism_ ) { case LauAbsResonance::Zemach_P : std::cout << " : Spin factors use Zemach spin tensors, with bachelor momentum in resonance rest frame" << std::endl; break; case LauAbsResonance::Zemach_Pstar : std::cout << " : Spin factors use Zemach spin tensors, with bachelor momentum in parent rest frame" << std::endl; break; case LauAbsResonance::Covariant : std::cout << " : Spin factors use Covariant spin tensors" << std::endl; break; case LauAbsResonance::Legendre : std::cout << " : Spin factors are just Legendre polynomials" << std::endl; break; } switch ( bwBarrierType_ ) { case LauBlattWeisskopfFactor::BWBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the 'non-primed' form" << std::endl; break; case LauBlattWeisskopfFactor::BWPrimeBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the 'primed' form" << std::endl; break; case LauBlattWeisskopfFactor::ExpBarrier : std::cout << " : Blatt-Weisskopf barrier factors are the exponential form" << std::endl; break; } switch ( bwRestFrame_ ) { case LauBlattWeisskopfFactor::ParentFrame : std::cout << " : Blatt-Weisskopf barrier factors use bachelor momentum in parent rest frame" << std::endl; break; case LauBlattWeisskopfFactor::ResonanceFrame : std::cout << " : Blatt-Weisskopf barrier factors use bachelor momentum in resonance rest frame" << std::endl; break; case LauBlattWeisskopfFactor::Covariant : std::cout << " : Blatt-Weisskopf barrier factors use covariant expression" << std::endl; break; } summaryPrinted_ = kTRUE; } // Loop over all possible resonance states we have defined in // createResonanceVector() until we get a match with the name of the resonance LauResonanceInfo* resInfo(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (resName == (*iter)->getName()) { // We have recognised the resonance name. std::cout<<"INFO in LauResonanceMaker::getResonance : Creating resonance: "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } case LauAbsResonance::GS : { // Gounaris-Sakurai function to try and model the rho(770) better std::cout<<" : Using Gounaris-Sakurai lineshape. "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } case LauAbsResonance::Flatte : // Flatte distribution - coupled channel Breit-Wigner std::cout<<" : Using Flatte lineshape. "<getBWCategory(); } LauBlattWeisskopfFactor* resBWFactor = this->getBWFactor( resCategory, resInfo ); LauBlattWeisskopfFactor* parBWFactor = this->getBWFactor( parCategory, resInfo ); theResonance->setBarrierRadii( resBWFactor, parBWFactor ); break; } // Set the spin formalism choice theResonance->setSpinType( spinFormalism_ ); return theResonance; } Int_t LauResonanceMaker::resTypeInt(const TString& name) const { // Internal function that returns the resonance integer, specified by the // order of the resonance vector defined in createResonanceVector(), // for a given resonance name. Int_t resTypInt(-99); Int_t i(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (name.BeginsWith((*iter)->getName(), TString::kExact) == kTRUE) { // We have recognised the resonance from those that are available resTypInt = i; return resTypInt; } ++i; } return resTypInt; } void LauResonanceMaker::printAll( std::ostream& stream ) const { for ( std::vector::const_iterator iter = resInfo_.begin(); iter != resInfo_.end(); ++iter ) { stream << (**iter) << std::endl; } } LauResonanceInfo* LauResonanceMaker::getResInfo(const TString& resName) const { LauResonanceInfo* resInfo(0); for (std::vector::const_iterator iter=resInfo_.begin(); iter!=resInfo_.end(); ++iter) { if (resName == (*iter)->getName()) { // We have recognised the resonance name. resInfo = (*iter); // stop looping break; } } return resInfo; } diff --git a/src/LauResultsExtractor.cc b/src/LauResultsExtractor.cc index f4e424d..f10e0f0 100644 --- a/src/LauResultsExtractor.cc +++ b/src/LauResultsExtractor.cc @@ -1,296 +1,295 @@ /* Copyright 2005 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauResultsExtractor.cc \brief File containing implementation of LauResultsExtractor class. */ #include "LauResultsExtractor.hh" #include #include #include #include #include #include "TChain.h" #include "TFile.h" #include "TH1.h" #include "TLeaf.h" #include "TObjArray.h" #include "TSystem.h" -ClassImp(LauResultsExtractor) LauResultsExtractor::LauResultsExtractor(const TString& inputFileName, const TString& outputFileName, const TString& treeName) : inputFileName_(inputFileName), outputFileName_(outputFileName), treeName_(treeName), inputTree_(0), outputFile_(0), outputTree_(0), nEntries_(0) { } LauResultsExtractor::~LauResultsExtractor() { this->clearMaps(); delete inputTree_; inputTree_ = 0; if (outputFile_ && outputFile_->IsOpen()) { delete outputTree_; outputTree_ = 0; } delete outputFile_; outputFile_ = 0; } void LauResultsExtractor::setupInputTree() { TObjArray* leaves = inputTree_->GetListOfLeaves(); Int_t nLeaves = leaves->GetEntries(); std::cout<<"Setting branches for input tree \""<GetName()<<"\" with "<SetBranchAddress("iExpt",&iExpt_); inputTree_->SetBranchAddress("fitStatus",&fitStatus_); inputTree_->SetBranchAddress("NLL",&NLL_); inputTree_->SetBranchAddress("EDM",&EDM_); for (Int_t iLeaf(3); iLeaf((*leaves)[iLeaf]); TString type = leaf->GetTypeName(); TString name = leaf->GetName(); Int_t size = leaf->GetNdata(); if ((type != "Double_t") || (size != 1)) { continue; } std::pair::iterator,bool> result = otherVars_.insert(std::make_pair(name,0.0)); std::map::iterator iter = result.first; bool ok = result.second; if (ok) { inputTree_->SetBranchAddress(name,&(iter->second)); } } std::cout<<"Set branch addresses for "<GetName()<<"\"..."<Branch("iExpt",&iExpt_,"iExpt/I"); tree->Branch("fitStatus",&fitStatus_,"fitStatus/I"); tree->Branch("NLL",&NLL_,"NLL/D"); tree->Branch("EDM",&EDM_,"EDM/D"); for (std::map::iterator iter = otherVars_.begin(); iter != otherVars_.end(); ++iter) { TString name = iter->first; Double_t * address = &(iter->second); TString thirdBit = name; thirdBit += "/D"; tree->Branch(name,address,thirdBit); } std::cout<<"Created "<SetBranchStatus("iExpt",kTRUE); inputTree_->SetBranchStatus("fitStatus",kTRUE); inputTree_->SetBranchStatus("NLL",kTRUE); inputTree_->SetBranchStatus("EDM",kTRUE); for (std::map::iterator iter = otherVars_.begin(); iter != otherVars_.end(); ++iter) { TString name = iter->first; inputTree_->SetBranchStatus(name,status); } } void LauResultsExtractor::clearMaps() { for (std::map::iterator iter = nllHistos_.begin(); iter != nllHistos_.end(); ++iter) { delete (iter->second); } bestNLL_.clear(); worstNLL_.clear(); allNLLs_.clear(); nllHistos_.clear(); } void LauResultsExtractor::process(Int_t numExpts) { // open the text file std::cout << "\n" << "Chaining...\n" << std::endl; std::ifstream textFile(inputFileName_, std::ios::in); if (!textFile.good()) { std::cerr<<"Problem opening file: \""<Exit(EXIT_FAILURE); } if (inputTree_) { delete inputTree_; inputTree_ = 0; } inputTree_ = new TChain(treeName_); // Read the text file and add each valid entry to the chain TString inputFileName = ""; while(inputFileName.ReadLine(textFile) && (!inputFileName.IsNull())) { if (inputFileName.EndsWith(".root") && !inputFileName.BeginsWith("#")) { std::cout << inputFileName << std::endl; inputTree_->Add(inputFileName); } else { std::cout << inputFileName << "\t *** Skipped ***" << std::endl; } } textFile.close(); std::cout << "\n" << "... finished.\n" << std::endl; nEntries_ = inputTree_->GetEntries(); this->setupInputTree(); outputTree_ = new TTree(treeName_,""); this->setupOutputTree(outputTree_); // setup the map: // for each experiment there is a pair object holding // the best NLL and the tree entry for that NLL value // each expt starts out with NLL = 0.0 and entry = -1 std::cout<<"Setting up the map..."<clearMaps(); for (Int_t i(0); i())); allNLLs_[i].reserve(nEntries_); } std::cout<<" done.\n"<setInputTreeBranchStatus(kFALSE); // loop over the tree and store the best entries for each expt std::cout<<"Starting to store best entry info..."<GetEntry(j); if ( (fitStatus_ == 3) && (NLL_ > -DBL_MAX/10.0) ) { allNLLs_[iExpt_].push_back(NLL_); Double_t curBestNLL = bestNLL_[iExpt_].first; Int_t curBestEntry = bestNLL_[iExpt_].second; if ((NLL_ < curBestNLL) || (curBestEntry == -1)) { bestNLL_[iExpt_] = std::make_pair(NLL_,j); } Double_t curWorstNLL = worstNLL_[iExpt_].first; Int_t curWorstEntry = worstNLL_[iExpt_].second; if ((NLL_ > curWorstNLL) || (curWorstEntry == -1)) { worstNLL_[iExpt_] = std::make_pair(NLL_,j); } } } std::cout<<"Finished storing best entry info.\n"<::const_iterator iter = allNLLs_[i].begin(); iter != allNLLs_[i].end(); ++iter) { histo->Fill(*iter); } nllHistos_.insert(std::make_pair(i, histo)); } std::cout<<" done.\n"<setInputTreeBranchStatus(kTRUE); std::ofstream fout("best-fit.txt"); // loop over the experiments, grab the best entry and store it std::cout<<"Starting to retrieve best entries and fill output tree."<GetEntry(bestEntry); outputTree_->Fill(); } if ((numExpts<100) || (i%(numExpts/100)==0)) { std::cout<<"Writing out experiment "<GetCurrentFile()->GetName()); bestFit.Remove(0,3); Int_t index = bestFit.Index("_"); if ( index < 1 ) { index = bestFit.Index("."); } bestFit.Remove(index); fout<<"Experiment "<writeFile(); } void LauResultsExtractor::writeFile() { if (!outputFile_) { outputFile_ = new TFile(outputFileName_,"recreate"); } for (std::map::iterator iter = nllHistos_.begin(); iter != nllHistos_.end(); ++iter) { (iter->second)->SetDirectory(outputFile_); } outputTree_->SetDirectory(outputFile_); outputFile_->Write(); outputFile_->Close(); delete outputFile_; outputFile_ = 0; nllHistos_.clear(); } diff --git a/src/LauRhoOmegaMix.cc b/src/LauRhoOmegaMix.cc index a51691c..ea9f744 100644 --- a/src/LauRhoOmegaMix.cc +++ b/src/LauRhoOmegaMix.cc @@ -1,510 +1,509 @@ /* Copyright 2016 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRhoOmegaMix.cc \brief File containing implementation of LauRhoOmegaMix class. */ #include #include "LauBlattWeisskopfFactor.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauParameter.hh" #include "LauRhoOmegaMix.hh" #include "LauResonanceInfo.hh" #include "LauResonanceMaker.hh" -ClassImp(LauRhoOmegaMix) LauRhoOmegaMix::LauRhoOmegaMix(LauResonanceInfo* resInfo, const LauAbsResonance::LauResonanceModel resType, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), model_(resType), rhoMass_(0.0), rhoResRadius_(0.0), rhoParRadius_(0.0), mOmega_(0), mOmega0_(0.0), mOmegaCur_(0.0), wOmega_(0), wOmega0_(0.0), wOmegaCur_(0.0), magB_(0), phiB_(0), delta_(0), useDenom_(kTRUE), doneFirstInit_(kFALSE), rhoRes_(0), omegaRes_(0), whichAmpSq_(0) { // Create the rho and omega lineshapes depending on the resonance type enumeration. // The narrow omega is always a relativistic Breit-Wigner (RBW), but the broader rho // can either be a RBW or a Gounaris-Sakurai lineshape. The" _1" form for the resonance type // specifies that we want to assume the amplitude denominator correction term is set to 1. // In principle, the rho lineshape can be any resonance defined by the resInfo pointer, so we // use that to extract all relevant information about the first resonance. // We do not need the barrier nor spin factor terms for the components separately, since // they will be added after the lineshapes have been combined LauResonanceMaker& resMaker = LauResonanceMaker::get(); LauAbsResonance::LauResonanceModel rhoType = LauAbsResonance::RelBW; if (resType == LauAbsResonance::RhoOmegaMix_GS || resType == LauAbsResonance::RhoOmegaMix_GS_1) { rhoType = LauAbsResonance::GS; } rhoRes_ = resMaker.getResonance(daughters, resInfo->getName(), resPairAmpInt, rhoType, LauBlattWeisskopfFactor::Light); LauResonanceInfo* omegaInfo = resMaker.getResInfo("omega(782)"); omegaRes_ = resMaker.getResonance(daughters, omegaInfo->getName(), resPairAmpInt, LauAbsResonance::RelBW, LauBlattWeisskopfFactor::Light); // Check to see if we want to set the denominator factor to unity if (resType == LauAbsResonance::RhoOmegaMix_RBW_1 || resType == LauAbsResonance::RhoOmegaMix_GS_1) { useDenom_ = kFALSE; } // Initialise various parameters that can be used in the model const TString& parNameBase = this->getSanitisedName(); // Pole mass of the omega (2nd) resonance. Initialise using the resonance maker (PDG) info mOmega0_ = omegaInfo->getMass()->unblindValue(); // Also set the current internal value of the omega mass for initialisation logic mOmegaCur_ = mOmega0_; TString mOmegaName(parNameBase); mOmegaName += "_mOmega"; mOmega_ = resInfo->getExtraParameter(mOmegaName); if (!mOmega_) { mOmega_ = new LauParameter(mOmegaName, mOmega0_, 0.0, 100.0, kTRUE); mOmega_->secondStage(kTRUE); resInfo->addExtraParameter(mOmega_); } // Pole width of the omega (2nd) resonance. Initialise using the resonance maker (PDG) info wOmega0_ = omegaInfo->getWidth()->unblindValue(); // Also set the current internal value of the omega width for initialisation logic wOmegaCur_ = wOmega0_; TString wOmegaName(parNameBase); wOmegaName += "_wOmega"; wOmega_ = resInfo->getExtraParameter(wOmegaName); if (!wOmega_) { wOmega_ = new LauParameter(wOmegaName, wOmega0_, 0.0, 100.0, kTRUE); wOmega_->secondStage(kTRUE); resInfo->addExtraParameter(wOmega_); } // Set the magnitude and phase of the omega amplitude mixing term. // These should be fitted const Double_t magBVal = 1.0; const Double_t phiBVal = 0.0; TString magBName(parNameBase); magBName += "_magB"; magB_ = resInfo->getExtraParameter(magBName); if (!magB_) { magB_ = new LauParameter(magBName, magBVal, 0.0, 100.0, kTRUE); magB_->secondStage(kTRUE); resInfo->addExtraParameter(magB_, kTRUE); // the kTRUE here allows this value to vary between B and Bbar - TODO: maybe make this configurable? } TString phiBName(parNameBase); phiBName += "_phiB"; phiB_ = resInfo->getExtraParameter(phiBName); if (!phiB_) { phiB_ = new LauParameter(phiBName, phiBVal, -10.0, 10.0, kTRUE); phiB_->secondStage(kTRUE); resInfo->addExtraParameter(phiB_, kTRUE); // the kTRUE here allows this value to vary between B and Bbar - TODO: maybe make this configurable? } // Set the delta parameter for the omega amplitude mixing term. This // is usually fixed but should be varied for systematic error checks. // In theory, this parameter can be complex, but we only use its magnitude // in the mixing amplitude, since its usually very small: (2.15 +- 0.35) MeV/c^2 const Double_t deltaVal = 2.15e-3; TString deltaName(parNameBase); deltaName += "_delta"; delta_ = resInfo->getExtraParameter(deltaName); if (!delta_) { delta_ = new LauParameter(deltaName, deltaVal, 0.0, 100.0, kTRUE); delta_->secondStage(kTRUE); resInfo->addExtraParameter(delta_); } } LauRhoOmegaMix::~LauRhoOmegaMix() { } void LauRhoOmegaMix::initialise() { // Initialise the two resonances. This is done within each amplitude() function // call and so floating parameters are checked every time, although secondary // initialisation checks will be "skipped" since the parameters will be unchanged // for the given set of kinematic variables/parameters this->initialiseRho(); this->initialiseOmega(); } void LauRhoOmegaMix::initialiseRho() { // Propagate settings rhoRes_->setSpinType( this->getSpinType() ); rhoRes_->flipHelicity( this->flipHelicity() ); rhoRes_->ignoreMomenta( this->ignoreMomenta() ); rhoRes_->ignoreSpin( this->ignoreSpin() ); rhoRes_->ignoreBarrierScaling( this->ignoreBarrierScaling() ); // Do the initialisation rhoRes_->initialise(); // Keep track of the current pole mass and barrier factor terms so that // we can reinitialise the rho resonance if they change rhoMass_ = rhoRes_->getMass(); rhoResRadius_ = rhoRes_->getResRadius(); rhoParRadius_ = rhoRes_->getParRadius(); } void LauRhoOmegaMix::initialiseOmega() { // Set the pole mass and width of the omega resonance if this has changed // using the parameters mOmega_ and wOmega_ Double_t newOmegaM(-1.0), newOmegaW(-1.0); const Int_t newOmegaSpin(-1); // See if the new pole mass is different from the current value Double_t tmpOmegaM = mOmega_->unblindValue(); if (fabs(tmpOmegaM - mOmegaCur_) > 1e-10) { newOmegaM = tmpOmegaM; } // See if the new pole width is different from the current value Double_t tmpOmegaW = wOmega_->unblindValue(); if (fabs(tmpOmegaW - wOmegaCur_) > 1e-10) { newOmegaW = tmpOmegaW; } // If any parameter is negative, they are unchanged omegaRes_->changeResonance(newOmegaM, newOmegaW, newOmegaSpin); Bool_t changedOmegaM(kFALSE); if (newOmegaM > -1.0) { changedOmegaM = kTRUE; } if (doneFirstInit_ == kFALSE) { // Let the omega resonance pointer know if the mass or width are fixed or floating omegaRes_->fixMass(this->fixmOmegaValue()); omegaRes_->fixWidth(this->fixwOmegaValue()); // We do not need to use the spin terms for the omega lineshape, since we // use those from the rho for the full amplitude later on // (as such we do not need to propagate the flip helicity setting to the omega, just to the rho) omegaRes_->ignoreSpin(kTRUE); // We want to ignore momentum-dependent width effects: just use the constant pole width omegaRes_->ignoreMomenta(kTRUE); // And we also need to ignore barrier scaling omegaRes_->ignoreBarrierScaling(kTRUE); // Initialise the omega resonance pointer omegaRes_->initialise(); doneFirstInit_ = kTRUE; } else { // Reinitialise the omega resonance pointer only if we have changed // its pole mass. It has no barrier factor if (changedOmegaM == kTRUE) { omegaRes_->initialise(); } } // Keep track of the current values of the mass and width of the omega (floating/fixed) mOmegaCur_ = tmpOmegaM; wOmegaCur_ = tmpOmegaW; } LauComplex LauRhoOmegaMix::amplitude(const LauKinematics* kinematics) { // This function overrides and returns the complex dynamical amplitude for the // rho-omega mass mixing amplitude given the kinematics // Check to see if we need to reinitialise the rho resonance pointer const Double_t resMass = rhoRes_->getMass(); const Double_t resRadius = rhoRes_->getResRadius(); const Double_t parRadius = rhoRes_->getParRadius(); if ( ( (!this->fixMass()) && fabs(resMass - rhoMass_) > 1e-10) || ( (!this->fixResRadius()) && fabs(resRadius - rhoResRadius_) > 1e-10 ) || ( (!this->fixParRadius()) && fabs(parRadius - rhoParRadius_) > 1e-10 ) ) { this->initialiseRho(); } // Always check the initialisaton of the omega resonance in case we have varied // its mass/width via the fit parameters this->initialiseOmega(); // First, get the amplitude of the first (rho) resonance. // This will include the full barrier and spin terms const LauComplex rhoAmp = rhoRes_->amplitude(kinematics); // Next, get the amplitude of the second (omega) resonance. This ignores barrier // and spin terms, and uses the pole width only (no momentum dependence) const LauComplex omegaAmp = omegaRes_->amplitude(kinematics); // The Delta parameter, which we assume is purely real. Theoretically, delta can // be complex, but in practice we only use its (usually small) magnitude const Double_t Delta = (resMass + mOmegaCur_)*this->getdeltaValue(); // The B amplitude term const Double_t magBVal = this->getmagBValue()*Delta; const Double_t phiBVal = this->getphiBValue(); const LauComplex BTerm = LauComplex(magBVal*cos(phiBVal), magBVal*sin(phiBVal)); // The mass mixing term const LauComplex unity(1.0, 0.0); const LauComplex mixingTerm = BTerm*omegaAmp + unity; // Now form the full amplitude LauComplex resAmplitude = rhoAmp*mixingTerm; // Add the mixing correction denominator term if required if (useDenom_) { // Here, we need to disable the rho barrier & spin factors, since they are // only needed for the numerator term of the full amplitude. Note that we still // need to use the momentum-dependent width (with its resonance barrier term) // Disable barrier scaling factors for the amplitude (not width) rhoRes_->ignoreBarrierScaling(kTRUE); // Also ignore spin terms for now rhoRes_->ignoreSpin(kTRUE); const LauComplex rhoAmp2 = rhoRes_->amplitude(kinematics); // Reinstate barrier scaling and spin term flags rhoRes_->ignoreBarrierScaling(kFALSE); rhoRes_->ignoreSpin(kFALSE); // Denominator term const LauComplex DeltaSq = LauComplex(Delta*Delta, 0.0); const LauComplex denomTerm = unity - DeltaSq*rhoAmp2*omegaAmp; // Modify the full amplitude resAmplitude = resAmplitude/denomTerm; if (this->whichAmpSq_ == 1) { // For omega fit fraction return LauComplex(sqrt(omegaAmp.abs() * Delta * magBVal), 0.0); } else if (this->whichAmpSq_ == 2) { // For rho fit fraction return rhoAmp; } } return resAmplitude; } LauComplex LauRhoOmegaMix::resAmp(Double_t mass, Double_t spinTerm) { std::cerr << "ERROR in LauRhoOmegaMix : This method should never be called." << std::endl; std::cerr << " : Returning zero amplitude for mass = " << mass << " and spinTerm = " << spinTerm << "." << std::endl; return LauComplex(0.0, 0.0); } const std::vector& LauRhoOmegaMix::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixmOmegaValue() ) { this->addFloatingParameter( mOmega_ ); } if ( ! this->fixwOmegaValue() ) { this->addFloatingParameter( wOmega_ ); } if ( ! this->fixmagBValue() ) { this->addFloatingParameter( magB_ ); } if ( ! this->fixphiBValue() ) { this->addFloatingParameter( phiB_ ); } if ( ! this->fixdeltaValue() ) { this->addFloatingParameter( delta_ ); } if ( ! this->fixMass() ) { this->addFloatingParameter( this->getMassPar() ); } if ( ! this->fixWidth() ) { this->addFloatingParameter( this->getWidthPar() ); } if ( ! this->fixResRadius() ) { this->addFloatingParameter( this->getResBWFactor()->getRadiusParameter() ); } if ( ! this->fixParRadius() ) { this->addFloatingParameter( this->getParBWFactor()->getRadiusParameter() ); } return this->getParameters(); } void LauRhoOmegaMix::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "mOmega") { this->setmOmegaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter mOmega = " << this->getmOmegaValue() << std::endl; } else if (name == "wOmega") { this->setwOmegaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter wOmega = " << this->getwOmegaValue() << std::endl; } else if (name == "magB") { this->setmagBValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter magB = " << this->getmagBValue() << std::endl; } else if (name == "phiB") { this->setphiBValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter phiB = " << this->getphiBValue() << std::endl; } else if (name == "delta") { this->setdeltaValue(value); std::cout << "INFO in LauRhoOmegaMix::setResonanceParameter : Setting parameter delta = " << this->getdeltaValue() << std::endl; } else { std::cerr << "WARNING in LauSigmaRes::setResonanceParameter: Parameter name "<fixed() ) { mOmega_->fixed( kFALSE ); this->addFloatingParameter( mOmega_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { wOmega_->fixed( kFALSE ); this->addFloatingParameter( wOmega_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { magB_->fixed( kFALSE ); this->addFloatingParameter( magB_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { phiB_->fixed( kFALSE ); this->addFloatingParameter( phiB_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<fixed() ) { delta_->fixed( kFALSE ); this->addFloatingParameter( delta_ ); } else { std::cerr << "WARNING in LauRhoOmegaMix::floatResonanceParameter: Parameter "<value( mOmega ); mOmega_->genValue( mOmega ); mOmega_->initValue( mOmega ); } void LauRhoOmegaMix::setwOmegaValue(const Double_t wOmega) { wOmega_->value( wOmega ); wOmega_->genValue( wOmega ); wOmega_->initValue( wOmega ); } void LauRhoOmegaMix::setmagBValue(const Double_t magB) { magB_->value( magB ); magB_->genValue( magB ); magB_->initValue( magB ); } void LauRhoOmegaMix::setphiBValue(const Double_t phiB) { phiB_->value( phiB ); phiB_->genValue( phiB ); phiB_->initValue( phiB ); } void LauRhoOmegaMix::setdeltaValue(const Double_t delta) { delta_->value( delta ); delta_->genValue( delta ); delta_->initValue( delta ); } diff --git a/src/LauRooFitTask.cc b/src/LauRooFitTask.cc index a7d19e5..2313b24 100644 --- a/src/LauRooFitTask.cc +++ b/src/LauRooFitTask.cc @@ -1,394 +1,393 @@ /* Copyright 2017 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRooFitTask.cc \brief File containing implementation of LauRooFitTask class. */ #include #include #include "RooFormulaVar.h" #include "RooRealVar.h" #include "RooDataSet.h" #include "TFile.h" #include "TString.h" #include "TSystem.h" #include "TTree.h" #include "LauFitNtuple.hh" #include "LauParameter.hh" #include "LauSimFitTask.hh" #include "LauRooFitTask.hh" -ClassImp(LauRooFitTask) LauRooFitTask::LauRooFitTask( RooAbsPdf& model, const Bool_t extended, const RooArgSet& vars, const TString& weightVarName ) : LauSimFitTask(), model_(model), dataVars_(vars), weightVarName_(weightVarName), dataFile_(0), dataTree_(0), exptData_(0), extended_(extended), iExptSet_(), nllVar_(0) { } LauRooFitTask::~LauRooFitTask() { delete nllVar_; nllVar_ = 0; this->cleanData(); } void LauRooFitTask::cleanData() { if ( dataFile_ != 0 ) { dataFile_->Close(); delete dataFile_; dataTree_ = 0; dataFile_ = 0; } delete exptData_; exptData_ = 0; } void LauRooFitTask::initialise() { if ( weightVarName_ != "" ) { Bool_t weightVarFound = kFALSE; RooFIter argset_iter = dataVars_.fwdIterator(); RooAbsArg* param(0); while ( (param = argset_iter.next()) ) { TString name = param->GetName(); if ( name == weightVarName_ ) { weightVarFound = kTRUE; break; } } if ( ! weightVarFound ) { std::cerr << "ERROR in LauRooFitTask::initialise : The set of data variables does not contain the weighting variable \"" << weightVarName_ << std::endl; std::cerr << " : Weighting will be disabled." << std::endl; weightVarName_ = ""; } } } Bool_t LauRooFitTask::verifyFitData(const TString& dataFileName, const TString& dataTreeName) { // Clean-up from any previous runs if ( dataFile_ != 0 ) { this->cleanData(); } // Open the data file dataFile_ = TFile::Open( dataFileName ); if ( ! dataFile_ ) { std::cerr << "ERROR in LauRooFitTask::verifyFitData : Problem opening data file \"" << dataFileName << "\"" << std::endl; return kFALSE; } // Retrieve the tree dataTree_ = dynamic_cast( dataFile_->Get( dataTreeName ) ); if ( ! dataTree_ ) { std::cerr << "ERROR in LauRooFitTask::verifyFitData : Problem retrieving tree \"" << dataTreeName << "\" from data file \"" << dataFileName << "\"" << std::endl; dataFile_->Close(); delete dataFile_; dataFile_ = 0; return kFALSE; } // Check that the tree contains branches for all the fit variables RooFIter argset_iter = dataVars_.fwdIterator(); RooAbsArg* param(0); Bool_t allOK(kTRUE); while ( (param = argset_iter.next()) ) { TString name = param->GetName(); TBranch* branch = dataTree_->GetBranch( name ); if ( branch == 0 ) { std::cerr << "ERROR in LauRooFitTask::verifyFitData : The data tree does not contain a branch for fit variable \"" << name << std::endl; allOK = kFALSE; } } if ( ! allOK ) { return kFALSE; } // Check whether the tree has the branch iExpt TBranch* branch = dataTree_->GetBranch("iExpt"); if ( branch == 0 ) { std::cout << "WARNING in LauRooFitTask::verifyFitData : Cannot find branch \"iExpt\" in the tree, will treat all data as being from a single experiment" << std::endl; } else { // Define the valid values for iExpt iExptSet_.clear(); const UInt_t firstExp = dataTree_->GetMinimum("iExpt"); const UInt_t lastExp = dataTree_->GetMaximum("iExpt"); for ( UInt_t iExp = firstExp; iExp <= lastExp; ++iExp ) { iExptSet_.insert( iExp ); } } return kTRUE; } void LauRooFitTask::prepareInitialParArray( TObjArray& array ) { // Check that the NLL variable has been initialised if ( ! nllVar_ ) { std::cerr << "ERROR in LauRooFitTask::prepareInitialParArray : NLL var not initialised" << std::endl; return; } // If we already prepared the entries in the fitPars_ vector then we only need to add the contents to the array if ( ! fitPars_.empty() ) { for ( std::vector::iterator iter = fitPars_.begin(); iter != fitPars_.end(); ++iter ) { array.Add(*iter); } return; } // Store the set of parameters and the total number of parameters RooArgSet* varSet = nllVar_->getParameters( exptData_ ); UInt_t nFreePars(0); // Loop through the fit parameters RooFIter argset_iter = varSet->fwdIterator(); RooAbsArg* param(0); while ( (param = argset_iter.next()) ) { // Only consider the free parameters if ( ! param->isConstant() ) { // Add the parameter RooRealVar* rrvar = dynamic_cast( param ); if ( rrvar != 0 ) { // Count the number of free parameters ++nFreePars; // Do the conversion and add it to the array LauParameter* lpar = this->convertToLauParameter( rrvar ); fitVars_.push_back( rrvar ); fitPars_.push_back( lpar ); array.Add( lpar ); } else { RooFormulaVar* rfvar = dynamic_cast( param ); if ( rfvar == 0 ) { std::cerr << "ERROR in LauRooFitTask::prepareInitialParArray : The parameter is neither a RooRealVar nor a RooFormulaVar, don't know what to do" << std::endl; continue; } std::vector< std::pair > lpars = this->convertToLauParameters( rfvar ); for ( std::vector< std::pair >::iterator iter = lpars.begin(); iter != lpars.end(); ++iter ) { RooRealVar* rrv = iter->first; LauParameter* lpar = iter->second; if ( ! rrv->isConstant() ) { continue; } // Count the number of free parameters ++nFreePars; // Add the parameter to the array fitVars_.push_back( rrvar ); fitPars_.push_back( lpar ); array.Add( lpar ); } } } } delete varSet; this->startNewFit( nFreePars, nFreePars ); } LauParameter* LauRooFitTask::convertToLauParameter( const RooRealVar* rooParameter ) const { return new LauParameter( rooParameter->GetName(), rooParameter->getVal(), rooParameter->getMin(), rooParameter->getMax(), rooParameter->isConstant() ); } std::vector< std::pair > LauRooFitTask::convertToLauParameters( const RooFormulaVar* rooFormula ) const { // Create the empty vector std::vector< std::pair > lauParameters; Int_t parIndex(0); RooAbsArg* rabsarg(0); RooRealVar* rrvar(0); RooFormulaVar* rfvar(0); // Loop through all the parameters of the formula while ( (rabsarg = rooFormula->getParameter(parIndex)) ) { // First try converting to a RooRealVar rrvar = dynamic_cast( rabsarg ); if ( rrvar ) { // Do the conversion and add it to the array LauParameter* lpar = this->convertToLauParameter( rrvar ); lauParameters.push_back( std::make_pair(rrvar,lpar) ); continue; } // If that didn't work, try converting to a RooFormulaVar rfvar = dynamic_cast( rabsarg ); if ( rfvar ) { // Do the conversion and add these to the array std::vector< std::pair > lpars = this->convertToLauParameters( rfvar ); for ( std::vector< std::pair >::iterator iter = lpars.begin(); iter != lpars.end(); ++iter ) { lauParameters.push_back( *iter ); } continue; } // If neither of those worked we don't know what to do, so print an error message and continue std::cerr << "ERROR in LauRooFitTask::convertToLauParameters : One of the parameters is not a RooRealVar nor a RooFormulaVar, it is a: " << rabsarg->ClassName() << std::endl; std::cerr << " : Do not know how to process that - it will be skipped." << std::endl; } return lauParameters; } Double_t LauRooFitTask::getTotNegLogLikelihood() { Double_t nLL = (nllVar_ != 0) ? nllVar_->getVal() : 0.0; return nLL; } void LauRooFitTask::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check const UInt_t nFreePars = this->nFreeParams(); if ( ! this->withinAsymErrorCalc() ) { if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauRooFitTask::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the floating ones with their new values for (UInt_t i(0); ifixed()) { // Set both the RooRealVars and the LauParameters fitPars_[i]->value(par[i]); fitVars_[i]->setVal(par[i]); } } } UInt_t LauRooFitTask::readExperimentData() { // check that we're being asked to read a valid index const UInt_t exptIndex = this->iExpt(); if ( iExptSet_.empty() && exptIndex != 0 ) { std::cerr << "ERROR in LauRooFitTask::readExperimentData : Invalid experiment number " << exptIndex << ", data contains only one experiment" << std::endl; return 0; } else if ( iExptSet_.find( exptIndex ) == iExptSet_.end() ) { std::cerr << "ERROR in LauRooFitTask::readExperimentData : Invalid experiment number " << exptIndex << std::endl; return 0; } // cleanup the data from any previous experiment delete exptData_; // retrieve the data and find out how many events have been read if ( iExptSet_.empty() ) { exptData_ = new RooDataSet( TString::Format("expt%dData",exptIndex), "", dataTree_, dataVars_, "", (weightVarName_ != "") ? weightVarName_.Data() : 0 ); } else { const TString selectionString = TString::Format("iExpt==%d",exptIndex); TTree* exptTree = dataTree_->CopyTree(selectionString); exptData_ = new RooDataSet( TString::Format("expt%dData",exptIndex), "", exptTree, dataVars_, "", (weightVarName_ != "") ? weightVarName_.Data() : 0 ); delete exptTree; } const UInt_t nEvent = exptData_->numEntries(); this->eventsPerExpt( nEvent ); return nEvent; } void LauRooFitTask::cacheInputFitVars() { // cleanup the old NLL info delete nllVar_; // construct the new NLL variable for this dataset nllVar_ = new RooNLLVar("nllVar", "", model_, *exptData_, extended_); } void LauRooFitTask::finaliseExperiment( const LauAbsFitter::FitStatus& fitStat, const TObjArray* parsFromCoordinator, const TMatrixD* covMat, TObjArray& parsToCoordinator ) { // Copy the fit status information this->storeFitStatus( fitStat, *covMat ); // Now process the parameters const UInt_t nFreePars = this->nFreeParams(); UInt_t nPars = parsFromCoordinator->GetEntries(); if ( nPars != nFreePars ) { std::cerr << "ERROR in LauRooFitTask::finaliseExperiment : Unexpected number of parameters received from coordinator" << std::endl; std::cerr << " : Received " << nPars << " when expecting " << nFreePars << std::endl; gSystem->Exit( EXIT_FAILURE ); } for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*parsFromCoordinator)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauRooFitTask::finaliseExperiment : Error reading parameter from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } if ( parameter->name() != fitPars_[iPar]->name() ) { std::cerr << "ERROR in LauRooFitTask::finaliseExperiment : Error reading parameter from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } *(fitPars_[iPar]) = *parameter; RooRealVar* rrv = fitVars_[iPar]; rrv->setVal( parameter->value() ); rrv->setError( parameter->error() ); rrv->setAsymError( parameter->negError(), parameter->posError() ); } // Update the pulls and add each finalised fit parameter to the list to // send back to the coordinator for ( std::vector::iterator iter = fitPars_.begin(); iter != fitPars_.end(); ++iter ) { (*iter)->updatePull(); parsToCoordinator.Add( *iter ); } // Write the results into the ntuple std::vector extraVars; LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitPars_, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); } diff --git a/src/LauSPlot.cc b/src/LauSPlot.cc index 993a543..d761cd6 100644 --- a/src/LauSPlot.cc +++ b/src/LauSPlot.cc @@ -1,1303 +1,1302 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSPlot.cc \brief File containing implementation of LauSPlot class. Class for defining the SPlot technique based on TSplot from ROOT by the following authors: Muriel Pivk, Anna Kreshuk (10/2005). (Original copyright notice below) */ /********************************************************************** * * * Copyright (c) 2005 ROOT Foundation, CERN/PH-SFT * * * **********************************************************************/ #include #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TEventList.h" #include "TFile.h" #include "TLeaf.h" #include "TMath.h" #include "TObjArray.h" #include "TSystem.h" #include "TTree.h" #include "TVirtualFitter.h" #include "LauSPlot.hh" extern void Yields(Int_t &, Double_t *, Double_t &f, Double_t *x, Int_t iflag); -ClassImp(LauSPlot) LauSPlot::LauSPlot(const TString& fileName, const TString& treeName, Int_t firstExpt, Int_t nExpt, const NameSet& variableNames, const NumbMap& freeSpecies, const NumbMap& fixdSpecies, const TwoDMap& twodimPDFs, Bool_t sigSplit, Bool_t scfDPSmeared) : fileName_(fileName), inputTreeName_(treeName), cnTreeName_(""), sweightTreeName_(""), file_(0), inputTree_(0), cnTree_(0), sweightTree_(0), eventList_(0), variableNames_(variableNames), freeSpecies_(freeSpecies), fixdSpecies_(fixdSpecies), origFreeSpecies_(freeSpecies), origFixdSpecies_(fixdSpecies), twodimPDFs_(twodimPDFs), signalSplit_(sigSplit), scfDPSmear_(scfDPSmeared), readInput_(kFALSE), definedCNBranches_(kFALSE), definedSWeightBranches_(kFALSE), firstExpt_(firstExpt), nExpt_(nExpt), iExpt_(0), nEvents_(0), nDiscVars_(variableNames.size()), nFreeSpecies_(freeSpecies.size()), nFixdSpecies_(fixdSpecies.size()), nSpecies_(freeSpecies.size()+fixdSpecies.size()) { this->openInputFileAndTree(); this->readInputInfo(); this->createSWeightTree(); if (nFixdSpecies_>0) { this->createCNTree(); } } LauSPlot::~LauSPlot() { // seems that closing the file deletes the tree // so only delete if the file is still open if (file_ && file_->IsOpen()) { delete inputTree_; inputTree_ = 0; delete sweightTree_; sweightTree_ = 0; delete cnTree_; cnTree_ = 0; } delete file_; file_ = 0; } void LauSPlot::openInputFileAndTree() { // first check whether we've already opened up the file or not if (!file_) { // if not, first check the filename and if all ok create the file if (fileName_ == "") { cerr<<"ERROR in LauSPlot::createFileAndTree : Bad filename supplied, not creating file or tree."<IsZombie() || !file_->IsWritable()) { cerr<<"ERROR in LauSPlot::createFileAndTree : Problem opening file \""<cd(); inputTree_ = dynamic_cast(file_->Get(inputTreeName_)); inputTree_->SetDirectory(file_); } } void LauSPlot::readInputInfo() { // Read the tree and then setup the maps so we know which leaves to // read from the tree to get the various PDF values Bool_t inputOK = this->readInputLeaves(); if (!inputOK) { this->readInput(inputOK); return; } inputOK = this->checkLeaves(); this->readInput(inputOK); return; } Bool_t LauSPlot::readInputLeaves() { // Read all the leaves in the tree and store them in the leaves map if (!inputTree_) { cerr<<"ERROR in LauSPlot::readInputInfo : Invalid pointer to data tree."<(inputTree_->GetNbranches()) : 0; TObjArray* pLeaves = inputTree_->GetListOfLeaves(); if (!pLeaves) { cerr<<"ERROR in LauSPlot::readInputInfo : Problem retrieving leaves from the tree."< leaves.GetSize()) { cerr<<"ERROR in LauSPlot::readInputInfo : List of leaves is smaller than number of branches - this is strange!"<(leaves[iLeaf]); // we can't deal with arrays Int_t size = leaf->GetNdata(); if (size != 1) { cerr<<"ERROR in LauSPlot::readInputInfo : Tree has array branches, can't deal with those."<GetName(); // initialise an entry in the maps to hold the value leaves_[name] = leaf; } return kTRUE; } Bool_t LauSPlot::checkLeaves() const { // Analyse the names of the leaves to check that we have a leaf for // all bits of information we require, i.e. a likelihood value for // each combination of variable and species // If we have 2D PDFs then we have to look for some extra leaves for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { const TString& specName = twodim_iter->first; const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; TString expectedName(specName); expectedName += firstVarName; expectedName += secondVarName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<Like for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { const TString& specName = fixd_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<signalSplit() ) { // now need to search for the sigTM and sigSCF leaves for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName("sigTM"); expectedName += varName; expectedName += "Like"; Bool_t found(kFALSE); for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { found = kTRUE; break; } } if (!found) { cerr<<"ERROR in LauSPlot::checkLeaves : Could not find expected leaf \""<cd(); cnTree_ = new TTree(cnTreeName_, cnTreeName_); cnTree_->SetDirectory(file_); this->definedCNBranches(kFALSE); } } void LauSPlot::createSWeightTree() { // check whether we've already created the tree if (!sweightTree_) { // if not change to the file's directory and create the tree sweightTreeName_ = inputTreeName_; sweightTreeName_ += "_sWeights"; file_->cd(); sweightTree_ = new TTree(sweightTreeName_, sweightTreeName_); sweightTree_->SetDirectory(file_); this->definedSWeightBranches(kFALSE); } } void LauSPlot::defineCNBranches() { if (this->definedCNBranches()) { cerr<<"ERROR in LauSPlot::defineCNBranches : Already defined branches, not doing it again."<Branch("iExpt", &iExpt_, "iExpt/I"); for (std::map::iterator excl_iter = cN_.begin(); excl_iter != cN_.end(); ++excl_iter) { const TString& exclName = excl_iter->first; NumbMap& species = excl_iter->second; for (NumbMap::iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t * pointer = &(spec_iter->second); TString name(specName); name += "_cN"; if (exclName == "none") { name += "_all"; } else { name += "_no"; name += exclName; } TString thirdPart(name); thirdPart += "/D"; cnTree_->Branch(name, pointer, thirdPart); } } this->definedCNBranches(kTRUE); } void LauSPlot::defineSWeightBranches() { if (this->definedSWeightBranches()) { cerr<<"ERROR in LauSPlot::defineSWeightBranches : Already defined branches, not doing it again."<::iterator excl_iter = sWeightsCurrent_.begin(); excl_iter != sWeightsCurrent_.end(); ++excl_iter) { const TString& exclName = excl_iter->first; NumbMap& species = excl_iter->second; for (NumbMap::iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t * pointer = &(spec_iter->second); TString name(specName); name += "_sWeight"; if (exclName == "none") { name += "_all"; } else { name += "_no"; name += exclName; } TString thirdPart(name); thirdPart += "/D"; sweightTree_->Branch(name, pointer, thirdPart); } } this->definedSWeightBranches(kTRUE); } void LauSPlot::setExperiment(Int_t iExpt) { if (!inputTree_) { cerr<<"ERROR in LauSPlot::setExperiment : Invalid pointer to data tree."<SetDirectory(file_); } // fill the event list with this experiment's events TString listName(eventList_->GetName()); listName.Prepend(">>"); TString selection("iExpt=="); selection += iExpt; cout<<"LauSPlot::setExperiment : Setting tree to experiment number "<Draw(listName,selection); // find how many events there are nEvents_ = eventList_->GetN(); cout<<" Found "<readExpt(); } void LauSPlot::readExpt() { for (Int_t iEvt(0); iEvt < nEvents_; ++iEvt) { // Find which entry from the full tree contains the requested event Long64_t iEntry = eventList_ ? eventList_->GetEntry(iEvt) : iEvt; if (iEntry<0) { // this shouldn't happen, but just in case... cerr<<"ERROR in LauSPlot::readExpt : Problem retrieving event."<Exit(EXIT_FAILURE); } // Then retrieve that entry from the tree inputTree_->GetEntry(iEntry); // If needed retrieve the SCF fraction values if ( this->signalSplit() ) { for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == "sigSCFFrac") && (leaf != 0)) { scfFrac_[iEvt] = leaf->GetValue(); break; } } } // Copy the leaf values into discPdf_ for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { const TString& specName = twodim_iter->first; const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; TString varName = firstVarName + secondVarName; TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } Bool_t needSignalSearch(kFALSE); for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { const TString& specName = fixd_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } for (NumbMap::const_iterator free_iter = freeSpecies_.begin(); free_iter != freeSpecies_.end(); ++free_iter) { const TString& specName = free_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } if ( needSignalSearch ) { for (NameSet::const_iterator vars_iter = variableNames_.begin(); vars_iter != variableNames_.end(); ++vars_iter) { const TString& varName = (*vars_iter); TString specName("sigTM"); TString expectedName(specName); expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } specName = "sigSCF"; expectedName = specName; expectedName += varName; expectedName += "Like"; for (LeafMap::const_iterator leaf_iter = leaves_.begin(); leaf_iter != leaves_.end(); ++leaf_iter) { const TString& leafName = leaf_iter->first; const TLeaf* leaf = leaf_iter->second; if ((leafName == expectedName) && (leaf != 0)) { discPdf_[iEvt][specName][varName] = leaf->GetValue(); break; } } } } } } void LauSPlot::runCalculations(const TString& option) { // Calculates the sWeights and cN coeffs // The option controls the print level: // "Q" - no print out (default) // "V" - prints the estimated # of events in species // "VV" - as "V" + the MINUIT printing + sums of weights for control if (!this->readInput()) { cerr<<"ERROR in LauSPlot::runCalculations : The input ntuple has not been successfully read, can't calculate anything."<checkFitter(); // Loop over experiments for (iExpt_ = firstExpt_; iExpt_ < (firstExpt_+nExpt_); ++iExpt_) { this->setExperiment(iExpt_); if (nEvents_ < 1) { cerr<<"ERROR in LauSPlot::runCalculations : Zero events in experiment "<calcTotPDFValues(exclName); // Reset the fitter this->initialiseFitter(opt); // Set the parameters to their initial values this->setFitParameters(); // Run the fit this->runFit(); // Get the fitted parameter values back this->retrieveFittedParameters(opt); // Get the covariance matrix Bool_t covMatOK = this->calcCovMatrix(); Double_t * covmat(0); if (!covMatOK) { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); covmat = fitter->GetCovarianceMatrix(); } if (opt.Contains("W")) { this->printCovMatrixElements(covmat); } // calculate the cN and sWeights from the covariance matrix if (nFixdSpecies_ > 0) { this->calcCNCoeffs(exclName, covmat); } this->calcSWeights(exclName, covmat); // print verbose info if required if (opt.Contains("W")) { this->printSumOfWeights(exclName); } } // Finally fill all the branches for this experiment if (nFixdSpecies_ > 0) { this->fillCNBranches(); } this->fillSWeightBranches(); } } void LauSPlot::checkFitter() const { TString minuitName("TFitter"); TVirtualFitter * fitter = TVirtualFitter::GetFitter(); if (fitter) { TString fitterName(fitter->IsA()->GetName()); if (fitterName != minuitName) { delete fitter; fitter = 0; } } fitter = TVirtualFitter::Fitter(0); } void LauSPlot::initialiseFitter(const TString& opt) { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); fitter->Clear(); fitter->SetFCN(Yields); fitter->SetObjectFit(this); // Set the print level Double_t arglist[10]; if (opt.Contains("Q")) { arglist[0]=-1; } if (opt.Contains("V")) { arglist[0]=0; } if (opt.Contains("W")) { arglist[0]=1; } fitter->ExecuteCommand("SET PRINT", arglist, 1); // Need to set the "SET ERR" command to +0.5 for +/-1 sigma errors // for maximum likelihood fit. arglist[0] = 0.5; fitter->ExecuteCommand("SET ERR", arglist, 1); } void LauSPlot::setFitParameters() const { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); // must add the parameters in the same order as they are stored in pdfTot_ Int_t ispecies(0); const NumbMap& species = pdfTot_.front(); for (NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& name(spec_iter->first); // starting parameters should be the original values, // not those that came out of the last fit NumbMap::const_iterator free_iter = origFreeSpecies_.find(name); NumbMap::const_iterator fixd_iter = origFixdSpecies_.find(name); Bool_t fixed = fixd_iter != origFixdSpecies_.end(); Double_t value(0.0); if (fixed) { value = fixd_iter->second; } else { value = free_iter->second; } fitter->SetParameter(ispecies, name, value, 1, 0, 0); if (fixed) { fitter->FixParameter(ispecies); } ++ispecies; } } void LauSPlot::runFit() { TVirtualFitter * fitter = TVirtualFitter::GetFitter(); Double_t arglist[10]; arglist[0] = 1000*nFreeSpecies_; // maximum iterations arglist[1] = 0.05; // tolerance : min EDM = 0.001*tolerance // Execute MIGRAD Int_t fitStatus = fitter->ExecuteCommand("MIGRAD", arglist, 2); if (fitStatus != 0) { cerr<<"ERROR in LauSPlot::runFit : Error during MIGRAD minimisation."<ExecuteCommand("HESSE", arglist, 1); if (fitStatus != 0) { cerr<<"ERROR in LauSPlot::runFit : Error during HESSE error calculation."<first<<","<first<<"] = "<first<<","<first<<"] = "<first); NumbMap::iterator free_iter = freeSpecies_.find(name); if (free_iter != freeSpecies_.end()) { free_iter->second = fitter->GetParameter(ispecies); if (!opt.Contains("Q")) { cout<<"Estimated # of events in species "<second<first; Double_t sumweight(0.0); for (Int_t iEvt(0); iEvt < nEvents_; ++iEvt) { const NumbMap& specWeightMap = sWeights_[iEvt].find(exclName)->second; Double_t weight = specWeightMap.find(specName)->second; sumweight += weight; } cout<<"Sum of sWeights for species \""< denominator(nEvents_); for (Int_t iEvt(0); iEvtfirst; Double_t specNumEvents = spec_iter->second; denominator[iEvt] += specNumEvents * pdfTot_[iEvt][specName]; } for (NumbMap::const_iterator spec_iter = fixdSpecies_.begin(); spec_iter != fixdSpecies_.end(); ++spec_iter) { const TString& specName = spec_iter->first; Double_t specNumEvents = spec_iter->second; denominator[iEvt] += specNumEvents * pdfTot_[iEvt][specName]; } // Square to get the final denominator denominator[iEvt] *= denominator[iEvt]; } // Then calculate each element Int_t i(0); for (NumbMap::const_iterator spec_iter_i = freeSpecies_.begin(); spec_iter_i != freeSpecies_.end(); ++spec_iter_i) { const TString& specName_i = spec_iter_i->first; Int_t j(0); for (NumbMap::const_iterator spec_iter_j = freeSpecies_.begin(); spec_iter_j != freeSpecies_.end(); ++spec_iter_j) { const TString& specName_j = spec_iter_j->first; invMatrix(i,j) = 0.0; for (Int_t iEvt(0); iEvtfirst; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } pdfTot_[iEvt][specName] = 1.0; // loop through the 2D histo list NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } } } for (NumbMap::const_iterator spec_iter = freeSpecies_.begin(); spec_iter != freeSpecies_.end(); ++spec_iter) { const TString& specName = spec_iter->first; // if the signal is split we need to do a dedicated search // for sigTM and sigSCF, so skip the signal here if ( specName == "sig" && this->signalSplit() ) { needSignalSearch = kTRUE; continue; } pdfTot_[iEvt][specName] = 1.0; // loop through the 2D histo list NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value pdfTot_[iEvt][specName] *= discPdf_[iEvt][specName][varName]; } } } } if ( needSignalSearch ) { // loop through the 2D histo list TString specName("sigTM"); Double_t tmPDFVal(1.0); NameSet skipList; for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; tmPDFVal *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value tmPDFVal *= discPdf_[iEvt][specName][varName]; } } } tmPDFVal *= (1.0 - scfFrac_[iEvt]); // loop through the 2D histo list specName = "sigSCF"; Double_t scfPDFVal(1.0); skipList.clear(); for ( TwoDMap::const_iterator twodim_iter = twodimPDFs_.begin(); twodim_iter != twodimPDFs_.end(); ++twodim_iter ) { // if the entry doesn't refer to this // species then skip on if ( specName != twodim_iter->first ) { continue; } // retrieve the two variable names const TString& firstVarName = twodim_iter->second.first; const TString& secondVarName = twodim_iter->second.second; if ( firstVarName != exclName && secondVarName != exclName ) { // if neither name is the one being excluded then... // add them both to the skip list skipList.insert( firstVarName ); skipList.insert( secondVarName ); // and multiply the total by the combined PDF value TString varName = firstVarName + secondVarName; scfPDFVal *= discPdf_[iEvt][specName][varName]; } } // loop through all the variables for (NameSet::const_iterator var_iter = variableNames_.begin(); var_iter != variableNames_.end(); ++var_iter) { const TString& varName = (*var_iter); // if the variable isn't the one being excluded if (exclName != varName) { // and it's not involved in a 2D PDF if ( skipList.find(varName) == skipList.end() ) { // multiply the total by its PDF value scfPDFVal *= discPdf_[iEvt][specName][varName]; } } } if ( exclName == "DP" || !this->scfDPSmear() ) { scfPDFVal *= scfFrac_[iEvt]; } pdfTot_[iEvt]["sig"] = tmPDFVal + scfPDFVal; } } } void LauSPlot::calcCNCoeffs(const TString& exclName, const Double_t *covmat) { // Computes the cN for the extended sPlots from the covariance matrix if (nFixdSpecies_ <= 0) { return; } Int_t species_n(0); for (NumbMap::const_iterator iter_n = freeSpecies_.begin(); iter_n != freeSpecies_.end(); ++iter_n) { Int_t species_j(0); const TString& specName = iter_n->first; Double_t value = iter_n->second; cN_[exclName][specName] = value; for (NumbMap::const_iterator iter_j = freeSpecies_.begin(); iter_j != freeSpecies_.end(); ++iter_j) { if (covmat) { cN_[exclName][specName] -= covmat[species_n*nSpecies_+species_j]; } else { cN_[exclName][specName] -= covMat_(species_n,species_j); } ++species_j; } ++species_n; } } void LauSPlot::calcSWeights(const TString& exclName, Double_t *covmat) { // Computes the sWeights from the covariance matrix // NB for the extended sPlot the sum in the denominator is still over all species, // while that in the numerator is only over the free species. // Similarly the sWeights can only be calculated for the free species. Double_t numerator(0.0), denominator(0.0); for (Int_t iEvent = 0; iEvent < nEvents_; ++iEvent) { denominator = 0.0; for (NumbMap::const_iterator free_iter = freeSpecies_.begin(); free_iter != freeSpecies_.end(); ++free_iter) { denominator += free_iter->second * pdfTot_[iEvent][free_iter->first]; } for (NumbMap::const_iterator fixd_iter = fixdSpecies_.begin(); fixd_iter != fixdSpecies_.end(); ++fixd_iter) { denominator += fixd_iter->second * pdfTot_[iEvent][fixd_iter->first]; } Int_t species_n(0); for (NumbMap::const_iterator iter_n = freeSpecies_.begin(); iter_n != freeSpecies_.end(); ++iter_n) { numerator = 0.0; Int_t species_j(0); for (NumbMap::const_iterator iter_j = freeSpecies_.begin(); iter_j != freeSpecies_.end(); ++iter_j) { if (covmat) { numerator += covmat[species_n*nSpecies_+species_j] * pdfTot_[iEvent][iter_j->first]; } else { numerator += covMat_(species_n,species_j) * pdfTot_[iEvent][iter_j->first]; } ++species_j; } sWeights_[iEvent][exclName][iter_n->first] = numerator/denominator; ++species_n; } } } void LauSPlot::fillCNBranches() { if (!cnTree_) { cerr<<"ERROR in LauSPlot::fillCNBranches : Tree not created, cannot fill branches."<definedCNBranches()) { this->defineCNBranches(); } cnTree_->Fill(); } void LauSPlot::fillSWeightBranches() { if (!sweightTree_) { cerr<<"ERROR in LauSPlot::fillSWeightBranches : Tree not created, cannot fill branches."<definedSWeightBranches()) { this->copyEventWeights(0); this->defineSWeightBranches(); } for (Int_t iEvent = 0; iEvent < nEvents_; ++iEvent) { this->copyEventWeights(iEvent); sweightTree_->Fill(); } } void LauSPlot::copyEventWeights(Int_t iEvent) { for (std::map::const_iterator excl_iter = sWeights_[iEvent].begin(); excl_iter != sWeights_[iEvent].end(); ++excl_iter) { const TString& exclName = excl_iter->first; const NumbMap& species = excl_iter->second; for (NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { const TString& specName = spec_iter->first; sWeightsCurrent_[exclName][specName] = spec_iter->second; } } } void LauSPlot::writeOutResults() { // write out the results // remove the transient objects that we don't want (re-)written to the file if (eventList_) { delete eventList_; eventList_ = 0; } if (inputTree_) { delete inputTree_; inputTree_ = 0; } // first add the input tree as a friend of the output tree this->addFriendTree(); // then write everything to the file and clean up file_->cd(); file_->Write(); file_->Close(); delete file_; file_ = 0; } void LauSPlot::addFriendTree() { if (!sweightTree_) { cerr<<"ERROR in LauSPlot::addFriendTree : Tree not created, cannot add friend."<AddFriend(inputTreeName_,fileName_); } void Yields(Int_t &, Double_t *, Double_t &f, Double_t *x, Int_t /*iflag*/) { // FCN-function for Minuit f = 0.0; TVirtualFitter *fitter = TVirtualFitter::GetFitter(); LauSPlot* theModel = dynamic_cast(fitter->GetObjectFit()); const std::vector& pdfTot = theModel->totalPdf(); Double_t ntot(0.0); for (std::vector::const_iterator evt_iter = pdfTot.begin(); evt_iter != pdfTot.end(); ++evt_iter) { // loop over events const LauSPlot::NumbMap& species = (*evt_iter); Int_t ispecies(0); Double_t lik(0.0); ntot = 0.0; for (LauSPlot::NumbMap::const_iterator spec_iter = species.begin(); spec_iter != species.end(); ++spec_iter) { // loop over species lik += x[ispecies] * spec_iter->second; ntot += x[ispecies]; ++ispecies; } if (lik < 0.0) { // make f the worst possible value to force MINUIT // out of this region of parameter space f = -DBL_MAX; break; } else { f += TMath::Log(lik); } } // extended likelihood f = (ntot-f); } diff --git a/src/LauScfMap.cc b/src/LauScfMap.cc index eb1b6f0..6dabe2f 100644 --- a/src/LauScfMap.cc +++ b/src/LauScfMap.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauScfMap.cc \brief File containing implementation of LauScfMap class. */ #include #include #include #include using std::cout; using std::cerr; using std::flush; using std::endl; #include "TAxis.h" #include "TH2.h" #include "TSystem.h" #include "LauScfMap.hh" -ClassImp(LauScfMap) LauScfMap::LauScfMap(): nBinsX_(-1), nBinsY_(-1), numberOfBins_(-1) { } LauScfMap::~LauScfMap() { for (std::vector::iterator iter = histos_.begin(); iter != histos_.end(); ++iter) { delete (*iter); } } void LauScfMap::setHistos(const std::vector& histos) { // Check that we have enough histograms Int_t nBinsX = histos.front()->GetNbinsX(); Int_t nBinsY = histos.front()->GetNbinsY(); Int_t nHist = histos.size(); if (nHist != nBinsX*nBinsY) { cerr<<"ERROR in LauScfMap::setHistos : There should be as many histograms supplied as there are bins in each of them."<::iterator iter = histos_.begin(); iter != histos_.end(); ++iter) { delete (*iter); } histos_.clear(); // Make sure we have enough space for the new histograms histos_.reserve(nHist); // Loop through the supplied vector // Clone each histogram and store it for (std::vector::const_iterator iter = histos.begin(); iter != histos.end(); ++iter) { TH2* histo = dynamic_cast((*iter)->Clone()); if ( histo==0 ) { cerr<<"ERROR in LauScfMap::setHistos : Problem cloning one of the histograms."<Exit(EXIT_FAILURE); } histos_.push_back(histo); } if ( histos_.size() != histos.size() ) { cerr<<"ERROR in LauScfMap::setHistos : Problem cloning the histograms."<Exit(EXIT_FAILURE); } // Now we need to setup the map // First clear it contribs_.clear(); // Fill in the map that links, to each reco bin, a vector with the numbers of the tru bins // that have non-zero contributions in that reco bin // Loop over each histogram bin for (Int_t j(0); jGetBin(i+1,j+1); std::vector& truBins = contribs_[binNo]; truBins.reserve(nHist); for (Int_t k(0); kGetBinContent(binNo); if (content>0.0) { truBins.push_back(k); } } } } } void LauScfMap::listBinCentres( std::vector& xCoords, std::vector& yCoords) const { // Create the list of fake points, located at the centres of the // true bins, that we will add to the data points, so as to cache // the DP amplitudes, scfFractions and jacobians at those points. // that have non-zero contributions in that reco bin const TAxis* xAxis = histos_.front()->GetXaxis(); Double_t xMax = xAxis->GetXmax(); Double_t xMin = xAxis->GetXmin(); Double_t xIncrement = (Double_t)((xMax - xMin)/nBinsX_); const TAxis* yAxis = histos_.front()->GetYaxis(); Double_t yMax = yAxis->GetXmax(); Double_t yMin = yAxis->GetXmin(); Double_t yIncrement = (Double_t)((yMax - yMin)/nBinsY_); // Loop over each histogram bin Double_t yCoord = yMin + yIncrement/2; for (Int_t j(1); j<=nBinsY_; ++j) { Double_t xCoord = xMin + xIncrement/2; for (Int_t i(1); i<=nBinsX_; ++i) { xCoords.push_back(xCoord); yCoords.push_back(yCoord); xCoord += xIncrement; } yCoord += yIncrement; } } Int_t LauScfMap::binNumber(Double_t xCoord, Double_t yCoord) const { const TH2* histo = histos_.front(); if (histo != 0) { return histo->FindFixBin(xCoord,yCoord); } else { cerr<<"ERROR in LauScfMap::recoBin : No valid histograms found."<* LauScfMap::trueBins(Int_t recoBin) const { std::map< Int_t, std::vector >::const_iterator iter = contribs_.find(recoBin); if (iter != contribs_.end()) { return &(iter->second); } else { return 0; } } Double_t LauScfMap::prob(Int_t recoBin, Int_t trueBin) const { const TH2* histo = histos_[trueBin]; if (histo != 0) { return histo->GetBinContent(recoBin); } else { cerr<<"ERROR in LauScfMap::prob : No histogram found for true bin "<GetBinXYZ( trueBin, x, y, z ); Int_t theBin = nBinsX_*(y-1) + (x-1); if ( theBin < 0 || static_cast(theBin) >= histos_.size() ) { cerr<<"ERROR in LauScfMap::trueHist : No histogram found for true bin "<Exit(EXIT_FAILURE); } TH2* histo = histos_[theBin]; if ( histo == 0 ) { cerr<<"ERROR in LauScfMap::trueHist : Null histogram pointer found for true bin "<Exit(EXIT_FAILURE); } return histo; } diff --git a/src/LauSigmaRes.cc b/src/LauSigmaRes.cc index d7f5f30..8f2a852 100644 --- a/src/LauSigmaRes.cc +++ b/src/LauSigmaRes.cc @@ -1,306 +1,305 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmaRes.cc \brief File containing implementation of LauSigmaRes class. */ #include #include "LauConstants.hh" #include "LauSigmaRes.hh" #include "LauResonanceInfo.hh" -ClassImp(LauSigmaRes) LauSigmaRes::LauSigmaRes(LauResonanceInfo* resInfo, const Int_t resPairAmpInt, const LauDaughters* daughters) : LauAbsResonance(resInfo, resPairAmpInt, daughters), mPiSq4_(4.0*LauConstants::mPiSq), sAdler_(LauConstants::mPiSq*0.5), b1_(0), b2_(0), a_(0), m0_(0) { // Initialise various constants mPiSq4_ = 4.0*LauConstants::mPiSq; sAdler_ = LauConstants::mPiSq*0.5; // Adler zero at 0.5*(mpi)^2 // constant factors from BES data const Double_t b1Val = 0.5843; const Double_t b2Val = 1.6663; const Double_t aVal = 1.082; const Double_t m0Val = 0.9264; const TString& parNameBase = this->getSanitisedName(); TString b1Name(parNameBase); b1Name += "_b1"; b1_ = resInfo->getExtraParameter( b1Name ); if ( b1_ == 0 ) { b1_ = new LauParameter( b1Name, b1Val, 0.0, 100.0, kTRUE ); b1_->secondStage(kTRUE); resInfo->addExtraParameter( b1_ ); } TString b2Name(parNameBase); b2Name += "_b2"; b2_ = resInfo->getExtraParameter( b2Name ); if ( b2_ == 0 ) { b2_ = new LauParameter( b2Name, b2Val, 0.0, 100.0, kTRUE ); b2_->secondStage(kTRUE); resInfo->addExtraParameter( b2_ ); } TString aName(parNameBase); aName += "_A"; a_ = resInfo->getExtraParameter( aName ); if ( a_ == 0 ) { a_ = new LauParameter( aName, aVal, 0.0, 10.0, kTRUE ); a_->secondStage(kTRUE); resInfo->addExtraParameter( a_ ); } TString m0Name(parNameBase); m0Name += "_m0"; m0_ = resInfo->getExtraParameter( m0Name ); if ( m0_ == 0 ) { m0_ = new LauParameter( m0Name, m0Val, 0.0, 10.0, kTRUE ); m0_->secondStage(kTRUE); resInfo->addExtraParameter( m0_ ); } } LauSigmaRes::~LauSigmaRes() { } void LauSigmaRes::initialise() { this->checkDaughterTypes(); Double_t resSpin = this->getSpin(); if (resSpin != 0) { std::cerr << "WARNING in LauSigmaRes::initialise : Resonance spin is " << resSpin << "." << std::endl; std::cerr << " : Sigma amplitude is only for scalers, resetting spin to 0." << std::endl; this->changeResonance( -1.0, -1.0, 0 ); } } void LauSigmaRes::checkDaughterTypes() const { // Check that the daughter tracks are the same type. Otherwise issue a warning // and set the type to be pion for the Sigma distribution. Int_t resPairAmpInt = this->getPairInt(); if (resPairAmpInt < 1 || resPairAmpInt > 3) { std::cerr << "WARNING in LauSigmaRes::checkDaughterTypes : resPairAmpInt = " << resPairAmpInt << " is out of the range [1,2,3]." << std::endl; return; } const TString& nameDaug1 = this->getNameDaug1(); const TString& nameDaug2 = this->getNameDaug2(); if (!nameDaug1.CompareTo(nameDaug2, TString::kExact)) { // Daughter types agree. Find out if we have pion or kaon system if (!nameDaug1.Contains("pi")) { std::cerr << "ERROR in LauSigmaRes::checkDaughterTypes : Sigma model is using daughters \""< mPiSq4_) {rho = TMath::Sqrt(1.0 - mPiSq4_/s);} const Double_t m0Val = this->getM0Value(); const Double_t m0Sq = m0Val * m0Val; const Double_t aVal = this->getAValue(); const Double_t b1Val = this->getB1Value(); const Double_t b2Val = this->getB2Value(); Double_t f = b2Val*s + b1Val; // f(s) function Double_t numerator = s - sAdler_; Double_t denom = m0Sq - sAdler_; Double_t gamma(0.0); if (TMath::Abs(denom) > 1e-10 && TMath::Abs(aVal) > 1e-10) { // Decay width of the system gamma = rho*(numerator/denom)*f*TMath::Exp(-(s - m0Sq)/aVal); } // Now form the complex amplitude - use relativistic BW form (without barrier factors) // Note that the M factor in the denominator is not the "pole" at ~500 MeV, but is // m0_ = 0.9264, the mass when the phase shift goes through 90 degrees. Double_t dMSq = m0Sq - s; Double_t widthTerm = gamma*m0Val; LauComplex resAmplitude(dMSq, widthTerm); Double_t denomFactor = dMSq*dMSq + widthTerm*widthTerm; Double_t invDenomFactor = 0.0; if (denomFactor > 1e-10) {invDenomFactor = 1.0/denomFactor;} resAmplitude.rescale(spinTerm*invDenomFactor); return resAmplitude; } const std::vector& LauSigmaRes::getFloatingParameters() { this->clearFloatingParameters(); if ( ! this->fixB1Value() ) { this->addFloatingParameter( b1_ ); } if ( ! this->fixB2Value() ) { this->addFloatingParameter( b2_ ); } if ( ! this->fixAValue() ) { this->addFloatingParameter( a_ ); } if ( ! this->fixM0Value() ) { this->addFloatingParameter( m0_ ); } return this->getParameters(); } void LauSigmaRes::setResonanceParameter(const TString& name, const Double_t value) { // Set various parameters for the lineshape if (name == "b1") { this->setB1Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter b1 = " << this->getB1Value() << std::endl; } else if (name == "b2") { this->setB2Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter b2 = " << this->getB2Value() << std::endl; } else if (name == "A") { this->setAValue(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter A = " << this->getAValue() << std::endl; } else if (name == "m0") { this->setM0Value(value); std::cout << "INFO in LauSigmaRes::setResonanceParameter : Setting parameter m0 = " << this->getM0Value() << std::endl; } else { std::cerr << "WARNING in LauSigmaRes::setResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } void LauSigmaRes::floatResonanceParameter(const TString& name) { if (name == "b1") { if ( b1_->fixed() ) { b1_->fixed( kFALSE ); this->addFloatingParameter( b1_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "b2") { if ( b2_->fixed() ) { b2_->fixed( kFALSE ); this->addFloatingParameter( b2_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "A") { if ( a_->fixed() ) { a_->fixed( kFALSE ); this->addFloatingParameter( a_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else if (name == "m0") { if ( m0_->fixed() ) { m0_->fixed( kFALSE ); this->addFloatingParameter( m0_ ); } else { std::cerr << "WARNING in LauSigmaRes::floatResonanceParameter: Parameter already floating. No parameter changes made." << std::endl; } } else { std::cerr << "WARNING in LauSigmaRes::fixResonanceParameter: Parameter name not reconised. No parameter changes made." << std::endl; } } LauParameter* LauSigmaRes::getResonanceParameter(const TString& name) { if (name == "b1") { return b1_; } else if (name == "b2") { return b2_; } else if (name == "A") { return a_; } else if (name == "m0") { return m0_; } else { std::cerr << "WARNING in LauSigmaRes::getResonanceParameter: Parameter name not reconised." << std::endl; return 0; } } void LauSigmaRes::setB1Value(const Double_t b1) { b1_->value( b1 ); b1_->genValue( b1 ); b1_->initValue( b1 ); } void LauSigmaRes::setB2Value(const Double_t b2) { b2_->value( b2 ); b2_->genValue( b2 ); b2_->initValue( b2 ); } void LauSigmaRes::setAValue(const Double_t A) { a_->value( A ); a_->genValue( A ); a_->initValue( A ); } void LauSigmaRes::setM0Value(const Double_t m0) { m0_->value( m0 ); m0_->genValue( m0 ); m0_->initValue( m0 ); } diff --git a/src/LauSigmoidPdf.cc b/src/LauSigmoidPdf.cc index 886f474..0619de9 100644 --- a/src/LauSigmoidPdf.cc +++ b/src/LauSigmoidPdf.cc @@ -1,159 +1,158 @@ /* Copyright 2012 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSigmoidPdf.cc \brief File containing implementation of LauSigmoidPdf class. */ #include #include using std::cout; using std::cerr; using std::endl; using std::vector; #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauSigmoidPdf.hh" -ClassImp(LauSigmoidPdf) LauSigmoidPdf::LauSigmoidPdf(const TString& theVarName, const vector& params, Double_t minAbscissa, Double_t maxAbscissa) : LauAbsPdf(theVarName, params, minAbscissa, maxAbscissa), a_(0), b_(0) { // Constructor for the general form of a Sigmoid PDF. // // The parameters in params "a" and "b" define the steepness of the // slope and shift of the distribution (negative parameter "a" flips // the distribution around the y-axis). // The last two arguments specify the range in which the PDF is // defined, and the PDF will be normalised w.r.t. these limits. a_ = this->findParameter("a"); b_ = this->findParameter("b"); if ((this->nParameters() != 2) || (a_ == 0) || (b_ == 0)) { cerr<<"ERROR in LauSigmoidPdf constructor: LauSigmoidPdf requires 2 parameters: \"a\" and \"b\"."<Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauSigmoidPdf::~LauSigmoidPdf() { // Destructor } LauSigmoidPdf::LauSigmoidPdf(const LauSigmoidPdf& other) : LauAbsPdf(other.varName(), other.getParameters(), other.getMinAbscissa(), other.getMaxAbscissa()) { // Copy constructor this->setRandomFun(other.getRandomFun()); this->calcNorm(); } void LauSigmoidPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get our abscissa Double_t abscissa = abscissas[0]; // Get the up to date parameter values Double_t a = a_->unblindValue(); Double_t b = b_->unblindValue(); // Calculate the value of the exponent for the given value of the abscissa. Double_t exponent = -a*abscissa + b; Double_t value = 1.0/(1.0+ TMath::Exp(exponent)); this->setUnNormPDFVal(value); // if the parameters are floating then we // need to recalculate the normalisation if (!this->cachePDF() && !this->withinNormCalc() && !this->withinGeneration()) { this->calcNorm(); } } void LauSigmoidPdf::calcNorm() { // Get the up to date parameter values Double_t a = a_->unblindValue(); Double_t b = b_->unblindValue(); // Calculate the normalisation of the sigmoid and cache it. Double_t norm(0.0); if (TMath::Abs(a) > 1e-10) { Double_t expb = TMath::Exp(b); norm = TMath::Log( TMath::Exp(a * this->getMaxAbscissa()) + expb ) - TMath::Log( TMath::Exp(a * this->getMinAbscissa()) + expb ); norm /= a; } this->setNorm(norm); } void LauSigmoidPdf::calcPDFHeight(const LauKinematics* /*kinematics*/) { if (this->heightUpToDate()) { return; } // Get the up to date parameter values Double_t a = a_->unblindValue(); LauAbscissas maxPoint(1); maxPoint[0] = 0; // Calculate the PDF height for the Sigmoid function. if (a > 0.0) { maxPoint[0] = this->getMaxAbscissa(); } else { maxPoint[0] = this->getMinAbscissa(); } this->calcLikelihoodInfo(maxPoint); Double_t height = this->getUnNormLikelihood(); this->setMaxHeight(height); } diff --git a/src/LauSimFitCoordinator.cc b/src/LauSimFitCoordinator.cc index eddb02c..d6cb8b0 100644 --- a/src/LauSimFitCoordinator.cc +++ b/src/LauSimFitCoordinator.cc @@ -1,1065 +1,1064 @@ /* Copyright 2013 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitCoordinator.cc \brief File containing implementation of LauSimFitCoordinator class. */ #include #include #include #include "TMath.h" #include "TMatrixD.h" #include "TMessage.h" #include "TMonitor.h" #include "TObjArray.h" #include "TObjString.h" #include "TServerSocket.h" #include "TSocket.h" #include "TSystem.h" #include "LauAbsFitter.hh" #include "LauFitNtuple.hh" #include "LauFitter.hh" #include "LauFormulaPar.hh" #include "LauParameter.hh" #include "LauParamFixed.hh" #include "LauSimFitCoordinator.hh" -ClassImp(LauSimFitCoordinator) LauSimFitCoordinator::LauSimFitCoordinator( UInt_t numTasks, UInt_t port ) : nTasks_(numTasks), reqPort_(port), socketMonitor_(0), messageFromTask_(0), fitNtuple_(0) { messagesToTasks_.resize( nTasks_ ); for ( UInt_t iTask(0); iTask < nTasks_; ++iTask ) { messagesToTasks_[iTask] = new TMessage(); } } LauSimFitCoordinator::~LauSimFitCoordinator() { delete socketMonitor_; socketMonitor_ = 0; // Tell all tasks that they are finished and delete corresponding socket TString msgStr("Finish"); TMessage message( kMESS_STRING ); message.WriteTString(msgStr); for ( std::vector::iterator iter = socketTasks_.begin(); iter != socketTasks_.end(); ++iter ) { (*iter)->Send(message); (*iter)->Close(); delete (*iter); } socketTasks_.clear(); // Remove all fit parameters for ( std::vector::iterator iter = params_.begin(); iter != params_.end(); ++iter ) { delete *iter; } params_.clear(); for ( std::vector::iterator iter = vectorPar_.begin(); iter != vectorPar_.end(); ++iter ) { delete[] (*iter); } vectorPar_.clear(); delete messageFromTask_; messageFromTask_ = 0; for ( std::vector::iterator iter = messagesToTasks_.begin(); iter != messagesToTasks_.end(); ++iter ) { delete (*iter); } messagesToTasks_.clear(); delete fitNtuple_; } void LauSimFitCoordinator::initSockets() { if ( socketMonitor_ != 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::initSockets : Sockets already initialised." << std::endl; return; } //initialise socket connection, then accept a connection and return a full-duplex communication socket. socketMonitor_ = new TMonitor(); TServerSocket *ss = new TServerSocket( reqPort_, kFALSE ); UInt_t actual_port = ss->GetLocalPort(); std::cout << "INFO in LauSimFitCoordinator::initSockets : Waiting for connection with " << nTasks_ << " tasks on port " << actual_port << std::endl; socketTasks_.resize(nTasks_); for ( UInt_t iTask(0); iTaskAccept(); std::cout << " : Added task " << iTask << std::endl; } // tell the clients to start std::cout << "INFO in LauSimFitCoordinator::initSockets : Initialising tasks" << std::endl; for ( UInt_t iTask(0); iTaskuseAsymmFitErrors()); socketTasks_[iTask]->Send(message); socketMonitor_->Add(socketTasks_[iTask]); } std::cout << " : Now start fit\n" << std::endl; ss->Close(); delete ss; } /* * OLD VERSION THAT JUST GETS THE NAMES - COULD HAVE A SERIES OF EXCHANGES TO GET THE NAMES, INIT VALUES, RANGES, ETC. INSTEAD OF PASSING PARAMETERS * THIS INCREASES THE GENERALITY OF THE CODE, I.E. THERE IS NO NEED FOR THE TASKS TO KNOW ANY LAURA++ CLASS BUT THIS ONE, BUT MAKES IT RATHER MORE DENSE * FOR THE MOMENT I WILL STICK WITH THE METHOD OF PASSING LAUPARAMETER OBJECTS AROUND AND CONSIDER GOING BACK TO THIS GENERAL METHOD ONCE EVERYTHING IS WORKING * void LauSimFitCoordinator::getParametersFromTasksFirstTime() { taskIndices_.resize( nTasks_ ); TSocket* sActive(0); for ( UInt_t iTask(0); iTaskSend(message); // Wait to receive the response and check that it has come from the task we just requested from sActive = socketMonitor_->Select(); if ( sActive != socketTasks_[iTask] ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Received message from a different task than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names socketTasks_[iTask]->Recv( messageFromTask_ ); TObjArray * objarray = dynamic_cast( messageFromTask_->ReadObject( messageFromTask_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Error reading parameter names from task" << std::endl; gSystem->Exit(1); } Int_t nPars = objarray->GetEntries(); for ( Int_t iPar(0); iPar < nPars; ++iPar ) { TObjString* objstring = dynamic_cast( (*objarray)[iPar] ); if ( ! objstring ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Error reading parameter names from task" << std::endl; gSystem->Exit(1); } TString parname = objstring->GetString(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter != parIndices_.end() ) { UInt_t index = iter->second; taskIndices_[iTask].push_back( index ); } else { UInt_t index = parIndices_.size(); parIndices_.insert( std::make_pair( parname, index ) ); parNames_.insert( std::make_pair( index, parname ) ); taskIndices_[iTask].push_back( index ); } } delete objarray; objarray = 0; delete messageFromTask_; messageFromTask_ = 0; } UInt_t nPars = parNames_.size(); parValues_.resize( nPars ); } */ void LauSimFitCoordinator::getParametersFromTasks() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasks : Sockets not initialised." << std::endl; return; } if ( params_.empty() ) { this->getParametersFromTasksFirstTime(); // Add variables to Gaussian constrain to a list this->addConParameters(); } else { this->updateParametersFromTasks(); } } void LauSimFitCoordinator::updateParametersFromTasks() { TSocket* sActive(0); // Construct a message, requesting the list of parameter names TString msgStr = "Send Parameters"; TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iTask(0); iTaskSend(message); // Wait to receive the response and check that it has come from the task we just requested from sActive = socketMonitor_->Select(); if ( sActive != socketTasks_[iTask] ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Received message from a different task than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names socketTasks_[iTask]->Recv( messageFromTask_ ); TObjArray * objarray = dynamic_cast( messageFromTask_->ReadObject( messageFromTask_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Error reading parameter names from task" << std::endl; gSystem->Exit(1); } // We want to auto-delete the supplied parameters since we only copy their values in this case objarray->SetOwner(kTRUE); const UInt_t nPars = objarray->GetEntries(); if ( nPars != taskIndices_[iTask].size() ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Unexpected number of parameters received from task" << std::endl; gSystem->Exit(1); } for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Error reading parameter from task" << std::endl; gSystem->Exit(1); } TString parname = parameter->name(); Double_t parvalue = parameter->initValue(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter == parIndices_.end() ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Unexpected parameter name received from task" << std::endl; gSystem->Exit(1); } const UInt_t index = iter->second; if ( taskIndices_[iTask][iPar] != index ) { std::cerr << "ERROR in LauSimFitCoordinator::updateParametersFromTasks : Unexpected parameter received from task" << std::endl; gSystem->Exit(1); } params_[index]->initValue( parvalue ); parValues_[index] = parvalue; vectorPar_[iTask][iPar] = parvalue; this->checkParameter( parameter, index ); } delete objarray; objarray = 0; delete messageFromTask_; messageFromTask_ = 0; } } void LauSimFitCoordinator::getParametersFromTasksFirstTime() { taskIndices_.resize( nTasks_ ); taskFreeIndices_.resize( nTasks_ ); vectorPar_.resize( nTasks_ ); vectorRes_.resize( nTasks_ ); TSocket* sActive(0); // Construct a message, requesting the list of parameter names TString msgStr = "Send Parameters"; TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iTask(0); iTaskSend(message); // Wait to receive the response and check that it has come from the task we just requested from sActive = socketMonitor_->Select(); if ( sActive != socketTasks_[iTask] ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Received message from a different task than expected!" << std::endl; gSystem->Exit(1); } // Read the object and extract the parameter names socketTasks_[iTask]->Recv( messageFromTask_ ); TObjArray * objarray = dynamic_cast( messageFromTask_->ReadObject( messageFromTask_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Error reading parameters from task" << std::endl; gSystem->Exit(1); } const UInt_t nPars = objarray->GetEntries(); vectorPar_[iTask] = new Double_t[nPars]; for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitCoordinator::getParametersFromTasksFirstTime : Error reading parameter from task" << std::endl; gSystem->Exit(1); } TString parname = parameter->name(); Double_t parvalue = parameter->initValue(); Bool_t parfixed = parameter->fixed(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter != parIndices_.end() ) { UInt_t index = iter->second; taskIndices_[iTask].push_back( index ); if ( ! parfixed ) { taskFreeIndices_[iTask].push_back( index ); } this->checkParameter( parameter, index ); } else { UInt_t index = parIndices_.size(); parIndices_.insert( std::make_pair( parname, index ) ); parNames_.insert( std::make_pair( index, parname ) ); taskIndices_[iTask].push_back( index ); if ( ! parfixed ) { taskFreeIndices_[iTask].push_back( index ); } params_.push_back( parameter ); parValues_.push_back( parvalue ); } vectorPar_[iTask][iPar] = parvalue; } delete objarray; objarray = 0; delete messageFromTask_; messageFromTask_ = 0; } } void LauSimFitCoordinator::printParInfo() const { for ( UInt_t iTask(0); iTask& indices = taskIndices_[iTask]; std::cout << "INFO in LauSimFitCoordinator::printParInfo : Task " << iTask << " has the following parameters:\n"; for ( std::vector::const_iterator iter = indices.begin(); iter != indices.end(); ++iter ) { const TString& parName = parNames_.find(*iter)->second; Double_t parValue = parValues_[*iter]; const LauParameter* par = params_[*iter]; if ( par->name() != parName || par->initValue() != parValue ) { std::cerr << "ERROR in LauSimFitCoordinator::printParInfo : Discrepancy in parameter name and value records, this is very strange!!" << std::endl; } std::cout << " : " << parName << " = " << parValue << " and has index " << *iter << "\n"; } std::cout << std::endl; } std::cout << "INFO in LauSimFitCoordinator::printParInfo : " << "There are " << params_.size() << " parameters in total" << std::endl; } void LauSimFitCoordinator::checkParameter( const LauParameter* param, UInt_t index ) const { const LauParameter* storedPar = params_[index]; TString parName = storedPar->name(); if ( param->name() != parName ) { std::cerr << "ERROR in LauSimFitCoordinator::checkParameter : Parameter name is different!! This shouldn't happen!!" << std::endl; } if ( param->initValue() != storedPar->initValue() ) { std::cerr << "WARNING in LauSimFitCoordinator::checkParameter : Initial value for parameter " << parName << " is different, will use the value first set: " << storedPar->initValue() << std::endl; } if ( param->minValue() != storedPar->minValue() ) { std::cerr << "WARNING in LauSimFitCoordinator::checkParameter : Minimum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->minValue() << std::endl; } if ( param->maxValue() != storedPar->maxValue() ) { std::cerr << "WARNING in LauSimFitCoordinator::checkParameter : Maximum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->maxValue() << std::endl; } if ( param->fixed() != storedPar->fixed() ) { std::cerr << "WARNING in LauSimFitCoordinator::checkParameter : Fixed/floating property of parameter " << parName << " is different, will use the value first set: " << (storedPar->fixed() ? "fixed" : "floating") << std::endl; } if ( param->secondStage() != storedPar->secondStage() ) { std::cerr << "WARNING in LauSimFitCoordinator::checkParameter : Second stage property of parameter " << parName << " is different, will use the value first set: " << (storedPar->secondStage() ? "true" : "false") << std::endl; } } void LauSimFitCoordinator::initialise() { this->initSockets(); } void LauSimFitCoordinator::runSimFit( const TString& fitNtupleFileName, const UInt_t nExp, const UInt_t firstExp, const Bool_t useAsymmErrors, const Bool_t doTwoStageFit ) { // Routine to perform the total fit. // First, initialise this->useAsymmFitErrors(useAsymmErrors); this->twoStageFit(doTwoStageFit); this->initialise(); std::cout << "INFO in LauSimFitCoordinator::runSimFit : First experiment = " << firstExp << std::endl; std::cout << "INFO in LauSimFitCoordinator::runSimFit : Number of experiments = " << nExp << std::endl; // Start the cumulative timer cumulTimer_.Start(); this->resetFitCounters(); // Create and setup the fit results ntuple std::cout << "INFO in LauSimFitCoordinator::runSimFit : Creating fit ntuple." << std::endl; if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;} fitNtuple_ = new LauFitNtuple(fitNtupleFileName, useAsymmErrors); // Loop over the number of experiments for (UInt_t iExp = firstExp; iExp < (firstExp+nExp); ++iExp) { // Start the timer to see how long each fit takes timer_.Start(); this->setCurrentExperiment( iExp ); // Instruct the tasks to read the data for this experiment Bool_t readOK = this->readData(); if ( ! readOK ) { std::cerr << "ERROR in LauSimFitCoordinator::runSimFit : One or more tasks reported problems with reading data for experiment " << iExp << ", skipping..." << std::endl; timer_.Stop(); continue; } // Instruct the tasks to perform the caching this->cacheInputData(); // If we're fitting toy experiments then re-generate the means of any constraints this->generateConstraintMeans( conVars_ ); // Do the fit this->fitExpt(); // Stop the timer and see how long the program took so far timer_.Stop(); timer_.Print(); // Instruct the tasks to finalise the results this->finalise(); } // Print out total timing info. std::cout << "INFO in LauSimFitCoordinator::runSimFit : Cumulative timing:" << std::endl; cumulTimer_.Stop(); cumulTimer_.Print(); // Print out stats on OK fits. const UInt_t nOKFits = this->numberOKFits(); const UInt_t nBadFits = this->numberBadFits(); std::cout << "INFO in LauSimFitCoordinator::runSimFit : Number of OK Fits = " << nOKFits << std::endl; std::cout << "INFO in LauSimFitCoordinator::runSimFit : Number of Failed Fits = " << nBadFits << std::endl; Double_t fitEff(0.0); if (nExp != 0) {fitEff = nOKFits/(1.0*nExp);} std::cout << "INFO in LauSimFitCoordinator::runSimFit : Fit efficiency = " << fitEff*100.0 << "%." << std::endl; // Instruct the tasks to write out any fit results (ntuples etc...). this->writeOutResults(); } void LauSimFitCoordinator::withinAsymErrorCalc(const Bool_t inAsymErrCalc) { this->LauFitObject::withinAsymErrorCalc(inAsymErrCalc); if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::withinAsymErrorCalc : Sockets not initialised." << std::endl; return; } // Construct a message, informing the tasks whether or not we are now within the asymmetric error calculation TString msgStr("Asym Error Calc"); const Bool_t asymErrorCalc( this->withinAsymErrorCalc() ); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); message.WriteBool( asymErrorCalc ); // Send the message to the tasks for ( UInt_t iTask(0); iTaskSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); while ( responsesReceived != nTasks_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the task and the number of events read Bool_t response(kTRUE); UInt_t iTask(0); sActive->Recv( messageFromTask_ ); messageFromTask_->ReadUInt( iTask ); messageFromTask_->ReadBool( response ); if ( response != asymErrorCalc ) { std::cerr << "WARNING in LauSimFitCoordinator::withinAsymErrorCalc : Problem informing task " << iTask << std::endl; } ++responsesReceived; } } Bool_t LauSimFitCoordinator::readData() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::readData : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting to read the data for the given experiment TString msgStr("Read Expt"); const UInt_t iExp( this->iExpt() ); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); message.WriteUInt( iExp ); // Send the message to the tasks for ( UInt_t iTask(0); iTaskSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); Bool_t ok(kTRUE); while ( responsesReceived != nTasks_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the task and the number of events read sActive->Recv( messageFromTask_ ); UInt_t iTask(0); UInt_t nEvents(0); messageFromTask_->ReadUInt( iTask ); messageFromTask_->ReadUInt( nEvents ); if ( nEvents <= 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::readData : Task " << iTask << " reports no events found for experiment " << iExp << std::endl; ok = kFALSE; } else { std::cerr << "INFO in LauSimFitCoordinator::readData : Task " << iTask << " reports " << nEvents << " events found for experiment " << iExp << std::endl; } ++responsesReceived; } return ok; } Bool_t LauSimFitCoordinator::cacheInputData() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::cacheInputData : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting it to read the data for the given experiment TString msgStr("Cache"); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); for ( UInt_t iTask(0); iTaskSend(message); } TSocket* sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nTasks_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the task and the success/failure flag sActive->Recv( messageFromTask_ ); UInt_t iTask(0); Bool_t ok(kTRUE); messageFromTask_->ReadUInt( iTask ); messageFromTask_->ReadBool( ok ); if ( ! ok ) { std::cerr << "ERROR in LauSimFitCoordinator::cacheInputData : Task " << iTask << " reports an error performing caching" << std::endl; allOK = kFALSE; } ++responsesReceived; } return allOK; } void LauSimFitCoordinator::checkInitFitParams() { this->getParametersFromTasks(); this->printParInfo(); } void LauSimFitCoordinator::fitExpt() { // Routine to perform the actual fit for the given experiment // Instruct the tasks to update initial fit parameters if required (e.g. if using random numbers). this->checkInitFitParams(); // Initialise the fitter LauFitter::fitter().useAsymmFitErrors( this->useAsymmFitErrors() ); LauFitter::fitter().twoStageFit( this->twoStageFit() ); LauFitter::fitter().initialise( this, params_ ); this->startNewFit( LauFitter::fitter().nParameters(), LauFitter::fitter().nFreeParameters() ); // Now ready for minimisation step std::cout << "\nINFO in LauSimFitCoordinator::fitExpt : Start minimisation...\n"; LauAbsFitter::FitStatus fitResult = LauFitter::fitter().minimise(); // If we're doing a two stage fit we can now release (i.e. float) // the 2nd stage parameters and re-fit if (this->twoStageFit()) { if ( fitResult.status != 3 ) { std::cerr << "ERROR in LauSimFitCoordinator:fitExpt : Not running second stage fit since first stage failed." << std::endl; LauFitter::fitter().releaseSecondStageParameters(); } else { LauFitter::fitter().releaseSecondStageParameters(); this->startNewFit( LauFitter::fitter().nParameters(), LauFitter::fitter().nFreeParameters() ); fitResult = LauFitter::fitter().minimise(); } } const TMatrixD& covMat = LauFitter::fitter().covarianceMatrix(); this->storeFitStatus( fitResult, covMat ); // Store the final fit results and errors into protected internal vectors that // all sub-classes can use within their own finalFitResults implementation // used below (e.g. putting them into an ntuple in a root file) LauFitter::fitter().updateParameters(); } void LauSimFitCoordinator::setParsFromMinuit(Double_t* par, Int_t npar) { // This function sets the internal parameters based on the values // that Minuit is using when trying to minimise the total likelihood function. // MINOS reports different numbers of free parameters depending on the // situation, so disable this check if ( ! this->withinAsymErrorCalc() ) { const UInt_t nFreePars = this->nFreeParams(); if (static_cast(npar) != nFreePars) { std::cerr << "ERROR in LauSimFitCoordinator::setParsFromMinuit : Unexpected number of free parameters: " << npar << ".\n"; std::cerr << " Expected: " << nFreePars << ".\n" << std::endl; gSystem->Exit(EXIT_FAILURE); } } // Despite npar being the number of free parameters // the par array actually contains all the parameters, // free and floating... // Update all the parameters with their new values. // Change the value in the array to be sent out to the tasks and the // parameters themselves (so that constraints are correctly calculated) for (UInt_t i(0); inTotParams(); ++i) { if (!params_[i]->fixed()) { parValues_[i] = par[i]; params_[i]->value(par[i]); } } } Double_t LauSimFitCoordinator::getTotNegLogLikelihood() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::getTotNegLogLikelihood : Sockets not initialised." << std::endl; return 0.0; } // Send current values of the parameters to the tasks. for ( UInt_t iTask(0); iTask& indices = taskIndices_[iTask]; std::vector& freeIndices = taskFreeIndices_[iTask]; UInt_t nPars = indices.size(); UInt_t nFreePars = freeIndices.size(); for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { vectorPar_[iTask][iPar] = parValues_[ indices[iPar] ]; } TMessage* message = messagesToTasks_[iTask]; message->Reset( kMESS_ANY ); message->WriteUInt( nPars ); message->WriteUInt( nFreePars ); message->WriteFastArray( vectorPar_[iTask], nPars ); socketTasks_[iTask]->Send(*message); } Double_t negLogLike(0.0); TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nTasks_ ) { sActive = socketMonitor_->Select(); sActive->Recv(messageFromTask_); messageFromTask_->ReadDouble( vectorRes_[responsesReceived] ); Double_t& nLL = vectorRes_[responsesReceived]; if ( nLL == 0.0 || TMath::IsNaN(nLL) || !TMath::Finite(nLL) ) { allOK = kFALSE; } negLogLike += vectorRes_[responsesReceived]; ++responsesReceived; } // Calculate any penalty terms from Gaussian constrained variables const auto& multiDimCons = this->multiDimConstraints(); if ( ! conVars_.empty() || ! multiDimCons.empty() ){ negLogLike += this->getLogLikelihoodPenalty(); } const Double_t worstNegLogLike = -1.0*this->worstLogLike(); if ( ! allOK ) { std::cerr << "WARNING in LauSimFitCoordinator::getTotNegLogLikelihood : Strange NLL value returned by one or more tasks\n"; std::cerr << " : Returning worst NLL found so far to force MINUIT out of this region." << std::endl; negLogLike = worstNegLogLike; } else if ( negLogLike > worstNegLogLike ) { this->worstLogLike( -negLogLike ); } return negLogLike; } Double_t LauSimFitCoordinator::getLogLikelihoodPenalty() { Double_t penalty{0.0}; for ( LauAbsRValue* par : conVars_ ) { penalty += par->constraintPenalty(); } auto& multiDimCons = this->multiDimConstraints(); for ( auto& constraint : multiDimCons ) { penalty += constraint.constraintPenalty(); } return penalty; } void LauSimFitCoordinator::addConParameters() { // Add penalties from the constraints to fit parameters // First, constraints on the fit parameters themselves for ( LauParameter* param : params_ ) { if ( param->gaussConstraint() ) { conVars_.push_back( param ); std::cout << "INFO in LauSimFitCoordinator::addConParameters : Added Gaussian constraint to parameter "<< param->name() << std::endl; } } // Second, constraints on arbitrary combinations auto& conStore = this->formulaConstraints(); for ( auto& constraint : conStore ) { std::vector params; for ( const auto& name : constraint.conPars_ ) { for ( LauParameter* par : params_ ) { if ( par->name() == name ){ params.push_back( par ); } } } // If the parameters are not found, skip it if ( params.size() != constraint.conPars_.size() ) { std::cerr << "WARNING in LauSimFitCoordinator::addConParameters: Could not find parameters to constrain in the formula... skipping" << std::endl; continue; } constraint.formulaPar_ = std::make_unique( constraint.formula_, constraint.formula_, params ); constraint.formulaPar_->addGaussianConstraint( constraint.mean_, constraint.width_ ); conVars_.push_back( constraint.formulaPar_.get() ); std::cout << "INFO in LauSimFitCoordinator::addConParameters : Added Gaussian constraint to formula\n"; std::cout << " : Formula: " << constraint.formula_ << std::endl; for ( LauParameter* param : params ) { std::cout << " : Parameter: " << param->name() << std::endl; } } // Thirdly, add n-dimensional constraints auto& multiDimCons = this->multiDimConstraints(); for ( auto& constraint : multiDimCons ){ for ( auto& parname : constraint.conPars_ ){ for ( auto& fitPar : params_ ){ if ( parname == fitPar->name() ){ // Check parameters do not have a 1D Gaussian constraint applied if ( fitPar->gaussConstraint() ){ std::cerr << "ERROR in LauAbsFitModel::addConParameters: parameter in n-dimensional constraint already has a 1d constraint applied" << std::endl; gSystem->Exit(EXIT_FAILURE); } constraint.conLauPars_.push_back(fitPar); } } } if ( constraint.conLauPars_.size() != constraint.conPars_.size() ){ std::cerr << "Error in LauAbsFitModel::addConParameters : Could not match parameter names for n-dimensional constraint" << std::endl; gSystem->Exit(EXIT_FAILURE); } } } Bool_t LauSimFitCoordinator::finalise() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Sockets not initialised." << std::endl; return kFALSE; } // Prepare the covariance matrices const TMatrixD& covMatrix = this->covarianceMatrix(); covMatrices_.resize( nTasks_ ); LauParamFixed pred; std::map freeParIndices; UInt_t counter(0); for ( UInt_t iPar(0); iPar < this->nTotParams(); ++iPar ) { const LauParameter* par = params_[iPar]; if ( ! pred(par) ) { freeParIndices.insert( std::make_pair(iPar,counter) ); ++counter; } } for ( UInt_t iTask(0); iTask freeIndices; freeIndices.reserve( nPar ); for ( UInt_t iPar(0); iPar < nPar; ++iPar ) { UInt_t index = taskIndices_[iTask][iPar]; std::map::iterator freeIter = freeParIndices.find(index); if ( freeIter == freeParIndices.end() ) { continue; } UInt_t freeIndex = freeIter->second; freeIndices.push_back( freeIndex ); } const UInt_t nFreePars = freeIndices.size(); TMatrixD& covMat = covMatrices_[iTask]; covMat.ResizeTo( nFreePars, nFreePars ); for ( UInt_t iPar(0); iPar < nFreePars; ++iPar ) { for ( UInt_t jPar(0); jPar < nFreePars; ++jPar ) { UInt_t i = freeIndices[iPar]; UInt_t j = freeIndices[jPar]; covMat( iPar, jPar ) = covMatrix( i, j ); } } } // The array to hold the parameters TObjArray array; // Send messages to all tasks containing the final parameters and fit status, NLL for ( UInt_t iTask(0); iTask& indices = taskIndices_[iTask]; UInt_t nPars = indices.size(); for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { array.Add( params_[ indices[iPar] ] ); } const Int_t status = this->statusCode(); const Double_t NLL = this->nll(); const Double_t EDM = this->edm(); TMatrixD& covMat = covMatrices_[iTask]; TMessage* message = messagesToTasks_[iTask]; message->Reset( kMESS_OBJECT ); message->WriteInt( status ); message->WriteDouble( NLL ); message->WriteDouble( EDM ); message->WriteObject( &array ); message->WriteObject( &covMat ); socketTasks_[iTask]->Send(*message); } TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nTasks_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the task and the number of events read sActive->Recv( messageFromTask_ ); UInt_t iTask(0); Bool_t ok(kTRUE); messageFromTask_->ReadUInt( iTask ); messageFromTask_->ReadBool( ok ); if ( ok ) { TObjArray * objarray = dynamic_cast( messageFromTask_->ReadObject( messageFromTask_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Error reading finalised parameters from task" << std::endl; allOK = kFALSE; } else { // We want to auto-delete the supplied parameters since we only copy their values in this case objarray->SetOwner(kTRUE); const UInt_t nPars = objarray->GetEntries(); if ( nPars != taskIndices_[iTask].size() ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Unexpected number of finalised parameters received from task" << std::endl; allOK = kFALSE; } else { for ( UInt_t iPar(0); iPar < nPars; ++iPar ) { LauParameter* parameter = dynamic_cast( (*objarray)[iPar] ); if ( ! parameter ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Error reading parameter from task" << std::endl; allOK = kFALSE; continue; } TString parname = parameter->name(); std::map< TString, UInt_t >::iterator iter = parIndices_.find( parname ); if ( iter == parIndices_.end() ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Unexpected parameter name received from task" << std::endl; allOK = kFALSE; continue; } const UInt_t index = iter->second; if ( taskIndices_[iTask][iPar] != index ) { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Unexpected parameter received from task" << std::endl; allOK = kFALSE; continue; } Double_t parvalue = parameter->value(); params_[index]->value( parvalue ); parValues_[index] = parvalue; vectorPar_[iTask][iPar] = parvalue; } } delete objarray; } } else { std::cerr << "ERROR in LauSimFitCoordinator::finalise : Task " << iTask << " reports an error performing finalisation" << std::endl; allOK = kFALSE; } ++responsesReceived; } // Fill our ntuple as well if ( fitNtuple_ != 0 ) { for ( std::vector::iterator iter = params_.begin(); iter != params_.end(); ++iter ) { if (!(*iter)->fixed()) { (*iter)->updatePull(); } } std::vector extraVars; fitNtuple_->storeParsAndErrors( params_, extraVars ); fitNtuple_->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); fitNtuple_->updateFitNtuple(); } return allOK; } Bool_t LauSimFitCoordinator::writeOutResults() { if ( socketMonitor_ == 0 ) { std::cerr << "ERROR in LauSimFitCoordinator::writeOutResults : Sockets not initialised." << std::endl; return kFALSE; } // Construct a message, requesting to write out the fit results TString msgStr("Write Results"); TMessage message( kMESS_STRING ); message.WriteTString( msgStr ); // Send the message to the tasks for ( UInt_t iTask(0); iTaskSend(message); } TSocket *sActive(0); UInt_t responsesReceived(0); Bool_t allOK(kTRUE); while ( responsesReceived != nTasks_ ) { // Get the next queued response sActive = socketMonitor_->Select(); // Extract from the message the ID of the task and the number of events read sActive->Recv( messageFromTask_ ); UInt_t iTask(0); Bool_t ok(kTRUE); messageFromTask_->ReadUInt( iTask ); messageFromTask_->ReadBool( ok ); if ( ! ok ) { std::cerr << "ERROR in LauSimFitCoordinator::writeOutResults : Task " << iTask << " reports an error performing finalisation" << std::endl; allOK = kFALSE; } ++responsesReceived; } // Write out our ntuple as well if (fitNtuple_ != 0) { fitNtuple_->writeOutFitResults(); } return allOK; } diff --git a/src/LauSimFitTask.cc b/src/LauSimFitTask.cc index cf99836..6d7fd03 100644 --- a/src/LauSimFitTask.cc +++ b/src/LauSimFitTask.cc @@ -1,310 +1,309 @@ /* Copyright 2015 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimFitTask.cc \brief File containing implementation of LauSimFitTask class. */ #include #include #include "TMatrixD.h" #include "TMessage.h" #include "TObjArray.h" #include "TObjString.h" #include "TSocket.h" #include "TSystem.h" #include "LauSimFitTask.hh" #include "LauFitNtuple.hh" -ClassImp(LauSimFitTask) LauSimFitTask::LauSimFitTask() : socketCoordinator_(0), messageFromCoordinator_(0), taskId_(0), nTasks_(0), parValues_(0), fitNtuple_(0) { } LauSimFitTask::~LauSimFitTask() { delete socketCoordinator_; delete messageFromCoordinator_; delete[] parValues_; delete fitNtuple_; } void LauSimFitTask::runTask(const TString& dataFileName, const TString& dataTreeName, const TString& histFileName, const TString& tableFileName, const TString& addressCoordinator, const UInt_t portCoordinator) { // Establish the connection to the coordinator process this->connectToCoordinator( addressCoordinator, portCoordinator ); // Initialise the fit model this->initialise(); // NB call to addConParameters() is intentionally not included here cf. // LauAbsFitModel::run() since this has to be dealt with by the coordinator // to avoid multiple inclusions of each penalty term // Print a warning if constraints on combinations of parameters have been specified const auto& storeCon = this->formulaConstraints(); if ( ! storeCon.empty() ) { std::cerr << "WARNING in LauSimFitTask::runTask : Constraints have been added but these will be ignored - they should have been added to the coordinator process" << std::endl; } // Setup saving of fit results to ntuple/LaTeX table etc. this->setupResultsOutputs( histFileName, tableFileName ); // This reads in the given dataFile and creates an input // fit data tree that stores them for all events and experiments. Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName); if (!dataOK) { std::cerr << "ERROR in LauSimFitTask::runTask : Problem caching the fit data." << std::endl; return; } // Now process the various requests from the coordinator this->processCoordinatorRequests(); std::cout << "INFO in LauSimFitTask::runTask : Fit task " << this->taskId() << " has finished successfully" << std::endl; } void LauSimFitTask::setupResultsOutputs( const TString& histFileName, const TString& /*tableFileName*/ ) { // Create and setup the fit results ntuple std::cout << "INFO in LauSimFitTask::setupResultsOutputs : Creating fit ntuple." << std::endl; if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;} fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors()); } void LauSimFitTask::connectToCoordinator( const TString& addressCoordinator, const UInt_t portCoordinator ) { if ( socketCoordinator_ != 0 ) { std::cerr << "ERROR in LauSimFitTask::connectToCoordinator : coordinator socket already present" << std::endl; return; } // Open connection to coordinator socketCoordinator_ = new TSocket(addressCoordinator, portCoordinator); socketCoordinator_->Recv( messageFromCoordinator_ ); messageFromCoordinator_->ReadUInt( taskId_ ); messageFromCoordinator_->ReadUInt( nTasks_ ); Bool_t useAsymErrs(kFALSE); messageFromCoordinator_->ReadBool( useAsymErrs ); this->useAsymmFitErrors(useAsymErrs); delete messageFromCoordinator_; messageFromCoordinator_ = 0; std::cout << "INFO in LauSimFitTask::connectToCoordinator : Established connection to coordinator on port " << portCoordinator << std::endl; std::cout << " : We are task " << taskId_ << " of " << nTasks_ << std::endl; if ( useAsymErrs ) { std::cout << " : The fit will determine asymmetric errors" << std::endl; } } void LauSimFitTask::processCoordinatorRequests() { // Listen for requests from the coordinator and act accordingly TMessage messageToCoordinator(kMESS_ANY); while ( kTRUE ) { socketCoordinator_->Recv( messageFromCoordinator_ ); if ( messageFromCoordinator_->What() == kMESS_STRING ) { TString msgStr; messageFromCoordinator_->ReadTString( msgStr ); std::cout << "INFO in LauSimFitTask::processCoordinatorRequests : Received message from coordinator: " << msgStr << std::endl; if ( msgStr == "Send Parameters" ) { // Send the fit parameters TObjArray array; this->prepareInitialParArray( array ); // Create array to efficiently exchange parameter values with coordinator if ( parValues_ != 0 ) { delete[] parValues_; parValues_ = 0; } UInt_t nPar = array.GetEntries(); parValues_ = new Double_t[nPar]; messageToCoordinator.Reset( kMESS_OBJECT ); messageToCoordinator.WriteObject( &array ); socketCoordinator_->Send( messageToCoordinator ); } else if ( msgStr == "Read Expt" ) { // Read the data for this experiment UInt_t iExp(0); messageFromCoordinator_->ReadUInt( iExp ); this->setCurrentExperiment( iExp ); UInt_t nEvents = this->readExperimentData(); if ( nEvents < 1 ) { std::cerr << "WARNING in LauSimFitTask::processCoordinatorRequests : Zero events in experiment " << iExp << ", the coordinator should skip this experiment..." << std::endl; } messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteUInt( taskId_ ); messageToCoordinator.WriteUInt( nEvents ); socketCoordinator_->Send( messageToCoordinator ); } else if ( msgStr == "Cache" ) { // Perform the caching this->cacheInputFitVars(); messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteUInt( taskId_ ); messageToCoordinator.WriteBool( kTRUE ); socketCoordinator_->Send( messageToCoordinator ); } else if ( msgStr == "Asym Error Calc" ) { Bool_t asymErrorCalc(kFALSE); messageFromCoordinator_->ReadBool( asymErrorCalc ); this->withinAsymErrorCalc( asymErrorCalc ); messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteUInt( taskId_ ); messageToCoordinator.WriteBool( asymErrorCalc ); socketCoordinator_->Send( messageToCoordinator ); } else if ( msgStr == "Write Results" ) { this->writeOutAllFitResults(); messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteUInt( taskId_ ); messageToCoordinator.WriteBool( kTRUE ); socketCoordinator_->Send( messageToCoordinator ); } else if ( msgStr == "Finish" ) { std::cout << "INFO in LauSimFitTask::processCoordinatorRequests : Message from coordinator to finish" << std::endl; break; } else { std::cerr << "ERROR in LauSimFitTask::processCoordinatorRequests : Unexpected message from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } } else if ( messageFromCoordinator_->What() == kMESS_OBJECT ) { std::cout << "INFO in LauSimFitTask::processCoordinatorRequests : Received message from coordinator: Finalise" << std::endl; Int_t status(0); Double_t NLL(0.0); Double_t EDM(0.0); messageFromCoordinator_->ReadInt( status ); messageFromCoordinator_->ReadDouble( NLL ); messageFromCoordinator_->ReadDouble( EDM ); TObjArray * objarray = dynamic_cast( messageFromCoordinator_->ReadObject( messageFromCoordinator_->GetClass() ) ); if ( ! objarray ) { std::cerr << "ERROR in LauSimFitTask::processCoordinatorRequests : Error reading parameters from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } TMatrixD * covMat = dynamic_cast( messageFromCoordinator_->ReadObject( messageFromCoordinator_->GetClass() ) ); if ( ! covMat ) { std::cerr << "ERROR in LauSimFitTask::processCoordinatorRequests : Error reading covariance matrix from coordinator" << std::endl; gSystem->Exit( EXIT_FAILURE ); } TObjArray array; LauAbsFitter::FitStatus fitStat { status, NLL, EDM }; this->finaliseExperiment( fitStat, objarray, covMat, array ); delete objarray; objarray = 0; delete covMat; covMat = 0; // Send the finalised parameters back to the coordinator messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteUInt( taskId_ ); messageToCoordinator.WriteBool( kTRUE ); messageToCoordinator.WriteObject( &array ); socketCoordinator_->Send( messageToCoordinator ); } else if ( messageFromCoordinator_->What() == kMESS_ANY ) { UInt_t nPars(0); UInt_t nFreePars(0); messageFromCoordinator_->ReadUInt( nPars ); messageFromCoordinator_->ReadUInt( nFreePars ); if ( nPars != this->nTotParams() ) { std::cerr << "ERROR in LauSimFitTask::processCoordinatorRequests : Unexpected number of parameters received from coordinator" << std::endl; std::cerr << " : Received " << nPars << " when expecting " << this->nTotParams() << std::endl; gSystem->Exit( EXIT_FAILURE ); } messageFromCoordinator_->ReadFastArray( parValues_, nPars ); this->setParsFromMinuit( parValues_, nFreePars ); Double_t negLogLike = this->getTotNegLogLikelihood(); messageToCoordinator.Reset( kMESS_ANY ); messageToCoordinator.WriteDouble( negLogLike ); socketCoordinator_->Send( messageToCoordinator ); } else { std::cerr << "ERROR in LauSimFitTask::processCoordinatorRequests : Unexpected message type" << std::endl; gSystem->Exit( EXIT_FAILURE ); } delete messageFromCoordinator_; messageFromCoordinator_ = 0; } } void LauSimFitTask::writeOutAllFitResults() { // Write out histograms at end if (fitNtuple_ != 0) { fitNtuple_->writeOutFitResults(); } } diff --git a/src/LauSimpleFitModel.cc b/src/LauSimpleFitModel.cc index 687121f..ebf8d51 100644 --- a/src/LauSimpleFitModel.cc +++ b/src/LauSimpleFitModel.cc @@ -1,2365 +1,2364 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSimpleFitModel.cc \brief File containing implementation of LauSimpleFitModel class. */ #include #include #include #include #include "TFile.h" #include "TH2.h" #include "TMinuit.h" #include "TRandom.h" #include "TSystem.h" #include "TVirtualFitter.h" #include "LauAbsBkgndDPModel.hh" #include "LauAbsCoeffSet.hh" #include "LauIsobarDynamics.hh" #include "LauAbsPdf.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauDaughters.hh" #include "LauEmbeddedData.hh" #include "LauEffModel.hh" #include "LauFitNtuple.hh" #include "LauGenNtuple.hh" #include "LauKinematics.hh" #include "LauPrint.hh" #include "LauRandom.hh" #include "LauScfMap.hh" #include "LauSimpleFitModel.hh" #include "TGraph2D.h" #include "TGraph.h" #include "TStyle.h" #include "TCanvas.h" -ClassImp(LauSimpleFitModel) LauSimpleFitModel::LauSimpleFitModel(LauIsobarDynamics* sigModel) : LauAbsFitModel(), sigDPModel_(sigModel), kinematics_(sigModel ? sigModel->getKinematics() : 0), usingBkgnd_(kFALSE), nSigComp_(0), nSigDPPar_(0), nExtraPdfPar_(0), nNormPar_(0), meanEff_("meanEff",0.0,0.0,1.0), dpRate_("dpRate",0.0,0.0,100.0), //signalEvents_("signalEvents",1.0,0.0,1.0), signalEvents_(0), useSCF_(kFALSE), useSCFHist_(kFALSE), scfFrac_("scfFrac",0.0,0.0,1.0), scfFracHist_(0), scfMap_(0), compareFitData_(kFALSE), signalTree_(0), reuseSignal_(kFALSE), useReweighting_(kFALSE), sigDPLike_(0.0), scfDPLike_(0.0), sigExtraLike_(0.0), scfExtraLike_(0.0), sigTotalLike_(0.0), scfTotalLike_(0.0) { } LauSimpleFitModel::~LauSimpleFitModel() { delete signalTree_; for (LauBkgndEmbDataList::iterator iter = bkgndTree_.begin(); iter != bkgndTree_.end(); ++iter) { delete (*iter); } delete scfFracHist_; } void LauSimpleFitModel::setupBkgndVectors() { UInt_t nBkgnds = this->nBkgndClasses(); bkgndDPModels_.resize( nBkgnds ); bkgndPdfs_.resize( nBkgnds ); bkgndEvents_.resize( nBkgnds ); bkgndTree_.resize( nBkgnds ); reuseBkgnd_.resize( nBkgnds ); bkgndDPLike_.resize( nBkgnds ); bkgndExtraLike_.resize( nBkgnds ); bkgndTotalLike_.resize( nBkgnds ); } void LauSimpleFitModel::setNSigEvents(LauParameter* nSigEvents) { if ( nSigEvents == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNSigEvents : The signal yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( signalEvents_ != 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl; return; } signalEvents_ = nSigEvents; TString name = signalEvents_->name(); if ( ! name.Contains("signalEvents") && !( name.BeginsWith("signal") && name.EndsWith("Events") ) ) { signalEvents_->name("signalEvents"); } Double_t value = nSigEvents->value(); signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } void LauSimpleFitModel::setNBkgndEvents(LauAbsRValue* nBkgndEvents) { if ( nBkgndEvents == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : The background yield LauParameter pointer is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() ); if ( bkgndEvents_[bkgndID] != 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl; return; } nBkgndEvents->name( nBkgndEvents->name()+"Events" ); if ( nBkgndEvents->isLValue() ) { Double_t value = nBkgndEvents->value(); LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0)); } bkgndEvents_[bkgndID] = nBkgndEvents; } void LauSimpleFitModel::splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf, const Bool_t fluctuateBins, LauScfMap* scfMap ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } if ( dpHisto == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : The histogram pointer is null." << std::endl; return; } const LauDaughters* daughters = sigDPModel_->getDaughters(); scfFracHist_ = new LauEffModel( daughters, 0 ); scfFracHist_->setEffHisto( dpHisto, kTRUE, fluctuateBins, 0.0, 0.0, upperHalf, daughters->squareDP() ); scfMap_ = scfMap; useSCF_ = kTRUE; useSCFHist_ = kTRUE; } void LauSimpleFitModel::splitSignalComponent( const Double_t scfFrac, const Bool_t fixed ) { if ( useSCF_ == kTRUE ) { std::cerr << "ERROR in LauSimpleFitModel::splitSignalComponent : Have already setup SCF." << std::endl; return; } scfFrac_.range( 0.0, 1.0 ); scfFrac_.value( scfFrac ); scfFrac_.initValue( scfFrac ); scfFrac_.genValue( scfFrac ); scfFrac_.fixed( fixed ); useSCF_ = kTRUE; useSCFHist_ = kFALSE; } void LauSimpleFitModel::setBkgndDPModel(const TString& bkgndClass, LauAbsBkgndDPModel* bkgndDPModel) { if (bkgndDPModel == 0) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndDPModel : The model pointer is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndDPModel : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); bkgndDPModels_[bkgndID] = bkgndDPModel; usingBkgnd_ = kTRUE; } void LauSimpleFitModel::setSignalPdf(LauAbsPdf* pdf) { if (pdf==0) { std::cerr << "ERROR in LauSimpleFitModel::setSignalPdf : The PDF pointer is null." << std::endl; return; } signalPdfs_.push_back(pdf); } void LauSimpleFitModel::setSCFPdf(LauAbsPdf* pdf) { if (pdf==0) { std::cerr << "ERROR in LauSimpleFitModel::setSCFPdf : The PDF pointer is null." << std::endl; return; } scfPdfs_.push_back(pdf); } void LauSimpleFitModel::setBkgndPdf(const TString& bkgndClass, LauAbsPdf* pdf) { if (pdf == 0) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndPdf : The PDF pointer is null." << std::endl; return; } // check that this background name is valid if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::setBkgndPdf : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); bkgndPdfs_[bkgndID].push_back(pdf); usingBkgnd_ = kTRUE; } void LauSimpleFitModel::setAmpCoeffSet(LauAbsCoeffSet* coeffSet) { // Resize the coeffPars vector if not already done if ( coeffPars_.empty() ) { coeffPars_.resize( sigDPModel_->getnTotAmp() ); for (std::vector::iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) { (*iter) = 0; } } // Is there a component called compName in the signal model? TString compName(coeffSet->name()); const Int_t index = sigDPModel_->resonanceIndex(compName); if ( index < 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setAmpCoeffSet : Signal DP model doesn't contain component \"" << compName << "\"." << std::endl; return; } // Do we already have it in our list of names? if ( coeffPars_[index] != 0 && coeffPars_[index]->name() == compName) { std::cerr << "ERROR in LauSimpleFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl; return; } coeffSet->index(index); coeffPars_[index] = coeffSet; ++nSigComp_; std::cout << "INFO in LauSimpleFitModel::setAmpCoeffSet : Added coefficients for component A"<< index << ": \"" << compName << "\" to the fit model." << std::endl; coeffSet->printParValues(); } void LauSimpleFitModel::initialise() { // Initialisation if (!this->useDP() && signalPdfs_.empty()) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Signal model doesn't exist for any variable." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (this->useDP()) { // Check that we have all the Dalitz-plot models if ( sigDPModel_ == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::initialise : The pointer to the signal DP model is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); } if ( usingBkgnd_ ) { for (LauBkgndDPModelList::const_iterator dpmodel_iter = bkgndDPModels_.begin(); dpmodel_iter != bkgndDPModels_.end(); ++dpmodel_iter ) { if ( (*dpmodel_iter) == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::initialise : The pointer to one of the background DP models is null.\n"; std::cerr << " : Removing the Dalitz Plot from the model." << std::endl; this->useDP(kFALSE); break; } } } // Need to check that the number of components we have and that the dynamics has matches up UInt_t nAmp = sigDPModel_->getnTotAmp(); if (nAmp != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Number of signal DP components with magnitude and phase set not right." << std::endl; gSystem->Exit(EXIT_FAILURE); } // From the initial parameter values calculate the coefficients // so they can be passed to the signal model this->updateCoeffs(); // If all is well, go ahead and initialise them this->initialiseDPModels(); } // Next check that, if a given component is being used we've got the // right number of PDFs for all the variables involved // TODO - should probably check variable names and so on as well UInt_t nsigpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nsigpdfvars; } } } if (useSCF_) { UInt_t nscfpdfvars(0); for ( LauPdfList::const_iterator pdf_iter = scfPdfs_.begin(); pdf_iter != scfPdfs_.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nscfpdfvars; } } } if (nscfpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauSimpleFitModel::initialise : There are " << nsigpdfvars << " TM signal PDF variables but " << nscfpdfvars << " SCF signal PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } if (usingBkgnd_) { for (LauBkgndPdfsList::const_iterator bgclass_iter = bkgndPdfs_.begin(); bgclass_iter != bkgndPdfs_.end(); ++bgclass_iter) { UInt_t nbkgndpdfvars(0); const LauPdfList& pdfList = (*bgclass_iter); for ( LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter ) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nbkgndpdfvars; } } } if (nbkgndpdfvars != nsigpdfvars) { std::cerr << "ERROR in LauSimpleFitModel::initialise : There are " << nsigpdfvars << " signal PDF variables but " << nbkgndpdfvars << " bkgnd PDF variables." << std::endl; gSystem->Exit(EXIT_FAILURE); } } } // Clear the vectors of parameter information so we can start from scratch this->clearFitParVectors(); // Set the fit parameters for signal and background models this->setSignalDPParameters(); // Set the fit parameters for the various extra PDFs this->setExtraPdfParameters(); // Set the initial bg and signal events this->setFitNEvents(); // Check that we have the expected number of fit variables const LauParameterPList& fitVars = this->fitPars(); if (fitVars.size() != (nSigDPPar_ + nExtraPdfPar_ + nNormPar_)) { std::cerr << "ERROR in LauSimpleFitModel::initialise : Number of fit parameters not of expected size." << std::endl; gSystem->Exit(EXIT_FAILURE); } this->setExtraNtupleVars(); } void LauSimpleFitModel::initialiseDPModels() { std::cout << "INFO in LauSimpleFitModel::initialiseDPModels : Initialising DP models" << std::endl; sigDPModel_->initialise(coeffs_); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = bkgndDPModels_.begin(); iter != bkgndDPModels_.end(); ++iter) { (*iter)->initialise(); } } } void LauSimpleFitModel::recalculateNormalisation() { //std::cout << "INFO in LauSimpleFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl; sigDPModel_->recalculateNormalisation(); sigDPModel_->modifyDataTree(); } void LauSimpleFitModel::setSignalDPParameters() { // Set the fit parameters for the signal model. nSigDPPar_ = 0; if ( ! this->useDP() ) { return; } std::cout << "INFO in LauSimpleFitModel::setSignalDPParameters : Setting the initial fit parameters for the signal DP model." << std::endl; // Place isobar coefficient parameters in vector of fit variables LauParameterPList& fitVars = this->fitPars(); for (UInt_t i = 0; i < nSigComp_; i++) { LauParameterPList pars = coeffPars_[i]->getParameters(); for (LauParameterPList::iterator iter = pars.begin(); iter != pars.end(); ++iter) { if ( !(*iter)->clone() ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } // Obtain the resonance parameters and place them in the vector of fit variables and in a separate vector LauParameterPSet& resVars = this->resPars(); resVars.clear(); LauParameterPList& sigDPPars = sigDPModel_->getFloatingParameters(); for ( LauParameterPList::iterator iter = sigDPPars.begin(); iter != sigDPPars.end(); ++iter ) { if ( resVars.insert(*iter).second ) { fitVars.push_back(*iter); ++nSigDPPar_; } } } void LauSimpleFitModel::setExtraPdfParameters() { // Include all the parameters of the various PDFs in the fit // NB all of them are passed to the fit, even though some have been fixed through parameter.fixed(kTRUE) // With the new "cloned parameter" scheme only "original" parameters are passed to the fit. // Their clones are updated automatically when the originals are updated. nExtraPdfPar_ = 0; nExtraPdfPar_ += this->addFitParameters(signalPdfs_); if (useSCF_ == kTRUE) { nExtraPdfPar_ += this->addFitParameters(scfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { nExtraPdfPar_ += this->addFitParameters(*iter); } } } void LauSimpleFitModel::setFitNEvents() { if ( signalEvents_ == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setFitNEvents : Signal yield not defined." << std::endl; return; } nNormPar_ = 0; // initialise the total number of events to be the sum of all the hypotheses Double_t nTotEvts = signalEvents_->value(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { nTotEvts += (*iter)->value(); if ( (*iter) == 0 ) { std::cerr << "ERROR in LauSimpleFitModel::setFitNEvents : Background yield not defined." << std::endl; return; } } this->eventsPerExpt(TMath::FloorNint(nTotEvts)); LauParameterPList& fitVars = this->fitPars(); // if doing an extended ML fit add the number of signal events into the fit parameters if (this->doEMLFit()) { std::cout << "INFO in LauSimpleFitModel::setFitNEvents : Initialising number of events for signal and background components..." << std::endl; // add the signal events to the list of fit parameters fitVars.push_back(signalEvents_); ++nNormPar_; } else { std::cout << "INFO in LauSimpleFitModel::setFitNEvents : Initialising number of events for background components (and hence signal)..." << std::endl; } if (useSCF_ && !useSCFHist_) { fitVars.push_back(&scfFrac_); ++nNormPar_; } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { if ( ! parameter->clone() ) { fitVars.push_back(parameter); ++nNormPar_; } } } } } void LauSimpleFitModel::setExtraNtupleVars() { // Set-up other parameters derived from the fit results, e.g. fit fractions. if (this->useDP() != kTRUE) { return; } // First clear the vectors so we start from scratch this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Add a fit fraction for each signal component fitFrac_ = sigDPModel_->getFitFractions(); if (fitFrac_.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << fitFrac_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } // Add the fit fraction that has not been corrected for the efficiency for each signal component fitFracEffUnCorr_ = sigDPModel_->getFitFractionsEfficiencyUncorrected(); if (fitFracEffUnCorr_.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << fitFracEffUnCorr_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i = 0; i < nSigComp_; i++) { for (UInt_t j = i; j < nSigComp_; j++) { extraVars.push_back(fitFrac_[i][j]); extraVars.push_back(fitFracEffUnCorr_[i][j]); } } // Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions) std::vector extraParams = sigDPModel_->getExtraParameters(); std::vector::iterator extraIter; for (extraIter = extraParams.begin(); extraIter != extraParams.end(); ++extraIter) { LauParameter extraParameter = (*extraIter); extraVars.push_back(extraParameter); } // Now add in the DP efficiency value Double_t initMeanEff = sigDPModel_->getMeanEff().initValue(); meanEff_.value(initMeanEff); meanEff_.initValue(initMeanEff); meanEff_.genValue(initMeanEff); extraVars.push_back(meanEff_); // Also add in the DP rate Double_t initDPRate = sigDPModel_->getDPRate().initValue(); dpRate_.value(initDPRate); dpRate_.initValue(initDPRate); dpRate_.genValue(initDPRate); extraVars.push_back(dpRate_); } void LauSimpleFitModel::finaliseFitResults(const TString& tablePrefixName) { // Retrieve parameters from the fit results for calculations and toy generation // and eventually store these in output root ntuples/text files // Now take the fit parameters and update them as necessary // e.g. to make mag > 0.0 and phase in the right range. // This function will also calculate any other values, such as the // fit fractions, using any errors provided by fitParErrors as appropriate. // Also obtain the pull values: (measured - generated)/(average error) if (this->useDP() == kTRUE) { for (UInt_t i = 0; i < nSigComp_; i++) { // Check whether we have mag > 0.0, and phase in the right range coeffPars_[i]->finaliseValues(); } } // update the pulls on the events if (this->doEMLFit()) { signalEvents_->updatePull(); } if (useSCF_ && !useSCFHist_) { scfFrac_.updatePull(); } if (usingBkgnd_ == kTRUE) { for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { std::vector parameters = (*iter)->getPars(); for ( LauParameter* parameter : parameters ) { parameter->updatePull(); } } } // Update the pulls on all the extra PDFs' parameters this->updateFitParameters(signalPdfs_); if (useSCF_ == kTRUE) { this->updateFitParameters(scfPdfs_); } if (usingBkgnd_ == kTRUE) { for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->updateFitParameters(*iter); } } // Fill the fit results to the ntuple for current experiment // update the coefficients and then calculate the fit fractions if (this->useDP() == kTRUE) { this->updateCoeffs(); sigDPModel_->updateCoeffs(coeffs_); sigDPModel_->calcExtraInfo(); LauParArray fitFrac = sigDPModel_->getFitFractions(); if (fitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << fitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } LauParArray fitFracEffUnCorr = sigDPModel_->getFitFractionsEfficiencyUncorrected(); if (fitFracEffUnCorr.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << fitFracEffUnCorr.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); dpRate_.value(sigDPModel_->getDPRate().value()); this->clearExtraVarVectors(); LauParameterList& extraVars = this->extraPars(); // Then store the final fit parameters, and any extra parameters for // the signal model (e.g. fit fractions) for (UInt_t i(0); i extraParams = sigDPModel_->getExtraParameters(); std::vector::iterator extraIter; for (extraIter = extraParams.begin(); extraIter != extraParams.end(); ++extraIter) { LauParameter extraParameter = (*extraIter); extraVars.push_back(extraParameter); } // Now add in the DP efficiency value extraVars.push_back(meanEff_); // Also add in the DP rate extraVars.push_back(dpRate_); this->printFitFractions(std::cout); } const LauParameterPList& fitVars = this->fitPars(); const LauParameterList& extraVars = this->extraPars(); LauFitNtuple* ntuple = this->fitNtuple(); ntuple->storeParsAndErrors(fitVars, extraVars); // find out the correlation matrix for the parameters ntuple->storeCorrMatrix(this->iExpt(), this->fitStatus(), this->covarianceMatrix()); // Fill the data into ntuple ntuple->updateFitNtuple(); // Print out the partial fit fractions, phases and the // averaged efficiency, reweighted by the dynamics (and anything else) if (this->writeLatexTable()) { TString sigOutFileName(tablePrefixName); sigOutFileName += "_"; sigOutFileName += this->iExpt(); sigOutFileName += "Expt.tex"; this->writeOutTable(sigOutFileName); } } void LauSimpleFitModel::printFitFractions(std::ostream& output) { // Print out Fit Fractions, total DP rate and mean efficiency for (UInt_t i = 0; i < nSigComp_; i++) { output << "FitFraction for component " << i << " (" << coeffPars_[i]->name() << ") = " << fitFrac_[i][i] << std::endl; } output << "Overall DP rate (integral of matrix element squared) = " << dpRate_ << std::endl; output << "Average efficiency weighted by whole DP dynamics = " << meanEff_ << std::endl; } void LauSimpleFitModel::writeOutTable(const TString& outputFile) { // Write out the results of the fit to a tex-readable table // TODO - need to include the yields in this table std::ofstream fout(outputFile); LauPrint print; std::cout << "INFO in LauSimpleFitModel::writeOutTable : Writing out results of the fit to the tex file " << outputFile << std::endl; if (this->useDP() == kTRUE) { // print the fit coefficients in one table coeffPars_.front()->printTableHeading(fout); for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->printTableRow(fout); } fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; // print the fit fractions in another fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; fout << "Component & FitFraction \\\\" << std::endl; fout << "\\hline" << std::endl; Double_t fitFracSum(0.0); for (UInt_t i = 0; i < nSigComp_; i++) { TString resName = coeffPars_[i]->name(); resName = resName.ReplaceAll("_", "\\_"); fout << resName << " & $"; Double_t fitFrac = fitFrac_[i][i].value(); fitFracSum += fitFrac; print.printFormat(fout, fitFrac); fout << "$ \\\\" << std::endl; } fout << "\\hline" << std::endl; // Also print out sum of fit fractions fout << "Fit Fraction Sum & $"; print.printFormat(fout, fitFracSum); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "DP rate & $"; print.printFormat(fout, dpRate_.value()); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "$< \\varepsilon >$ & $"; print.printFormat(fout, meanEff_.value()); fout << "$ \\\\" << std::endl; fout << "\\hline" << std::endl; fout << "\\end{tabular}" << std::endl << std::endl; } if (!signalPdfs_.empty()) { fout << "\\begin{tabular}{|l|c|}" << std::endl; fout << "\\hline" << std::endl; if (useSCF_ == kTRUE) { fout << "\\Extra TM Signal PDFs' Parameters: & \\\\" << std::endl; } else { fout << "\\Extra Signal PDFs' Parameters: & \\\\" << std::endl; } this->printFitParameters(signalPdfs_, fout); if (useSCF_ == kTRUE && !scfPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra SCF Signal PDFs' Parameters: & \\\\" << std::endl; this->printFitParameters(scfPdfs_, fout); } if (usingBkgnd_ == kTRUE && !bkgndPdfs_.empty()) { fout << "\\hline" << std::endl; fout << "\\Extra Background PDFs' Parameters: & \\\\" << std::endl; for (LauBkgndPdfsList::const_iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->printFitParameters(*iter, fout); } } fout << "\\hline \n\\end{tabular}" << std::endl << std::endl; } } void LauSimpleFitModel::checkInitFitParams() { // Update the number of signal events to be total-sum(background events) this->updateSigEvents(); // Check whether we want to have randomised initial fit parameters for the signal model if (this->useRandomInitFitPars() == kTRUE) { std::cout << "INFO in LauSimpleFitModel::checkInitFitParams : Setting random parameters for the signal DP model" << std::endl; this->randomiseInitFitPars(); } } void LauSimpleFitModel::randomiseInitFitPars() { // Only randomise those parameters that are not fixed! std::cout << "INFO in LauSimpleFitModel::randomiseInitFitPars : Randomising the initial fit magnitudes and phases of the resonances..." << std::endl; for (UInt_t i = 0; i < nSigComp_; i++) { coeffPars_[i]->randomiseInitValues(); } } std::pair LauSimpleFitModel::eventsToGenerate() { // Determine the number of events to generate for each hypothesis // If we're smearing then smear each one individually LauGenInfo nEvtsGen; // Keep track of whether any yield or asymmetry parameters are blinded Bool_t blind = kFALSE; // Signal if ( signalEvents_->blind() ) { blind = kTRUE; } Double_t evtWeight(1.0); Double_t nEvts = signalEvents_->genValue(); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } Int_t nEvtsToGen { static_cast(nEvts) }; if (this->doPoissonSmearing()) { nEvtsToGen = LauRandom::randomFun()->Poisson(nEvts); } nEvtsGen["signal"] = std::make_pair( nEvtsToGen, evtWeight ); // Backgrounds const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { const LauAbsRValue* evtsPar = bkgndEvents_[bkgndID]; if ( evtsPar->blind() ) { blind = kTRUE; } evtWeight = 1.0; nEvts = evtsPar->genValue(); if ( nEvts < 0 ) { evtWeight = -1.0; nEvts = TMath::Abs( nEvts ); } nEvtsToGen = static_cast(nEvts); if (this->doPoissonSmearing()) { nEvtsToGen = LauRandom::randomFun()->Poisson(nEvts); } const TString& bkgndClass = this->bkgndClassName(bkgndID); nEvtsGen[bkgndClass] = std::make_pair( nEvtsToGen, evtWeight ); } return std::make_pair( nEvtsGen, blind ); } Bool_t LauSimpleFitModel::genExpt() { // Routine to generate toy Monte Carlo events according to the various models we have defined. // Determine the number of events to generate for each hypothesis std::pair info = this->eventsToGenerate(); LauGenInfo nEvts = info.first; const Bool_t blind = info.second; Bool_t genOK(kTRUE); Int_t evtNum(0); const UInt_t nBkgnds = this->nBkgndClasses(); std::vector bkgndClassNames(nBkgnds); std::vector bkgndClassNamesGen(nBkgnds); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); bkgndClassNames[iBkgnd] = name; bkgndClassNamesGen[iBkgnd] = "gen"+name; } const Bool_t storeSCFTruthInfo = ( useSCF_ || ( this->enableEmbedding() && signalTree_ != 0 && signalTree_->haveBranch("mcMatch") ) ); // Loop over the hypotheses and generate the requested number of events for each one for (LauGenInfo::const_iterator iter = nEvts.begin(); iter != nEvts.end(); ++iter) { const TString& type(iter->first); Int_t nEvtsGen( iter->second.first ); Double_t evtWeight( iter->second.second ); for (Int_t iEvt(0); iEvtsetGenNtupleDoubleBranchValue( "evtWeight", evtWeight ); // Add efficiency information this->setGenNtupleDoubleBranchValue( "efficiency", 1 ); if (type == "signal") { this->setGenNtupleIntegerBranchValue("genSig",1); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 ); } genOK = this->generateSignalEvent(); this->setGenNtupleDoubleBranchValue( "efficiency", sigDPModel_->getEvtEff() ); } else { this->setGenNtupleIntegerBranchValue("genSig",0); if ( storeSCFTruthInfo ) { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",0); } UInt_t bkgndID(0); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { Int_t gen(0); if ( bkgndClassNames[iBkgnd] == type ) { gen = 1; bkgndID = iBkgnd; } this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], gen ); } genOK = this->generateBkgndEvent(bkgndID); } if (!genOK) { // If there was a problem with the generation then break out and return. // The problem model will have adjusted itself so that all should be OK next time. break; } if (this->useDP() == kTRUE) { this->setDPBranchValues(); } // Store the event number (within this experiment) this->setGenNtupleIntegerBranchValue("iEvtWithinExpt",evtNum); // and then increment it ++evtNum; this->fillGenNtupleBranches(); if ( !blind && (iEvt%500 == 0) ) { std::cout << "INFO in LauSimpleFitModel::genExpt : Generated event number " << iEvt << " out of " << nEvtsGen << " " << type << " events." << std::endl; } } if (!genOK) { break; } } if (this->useDP() && genOK) { sigDPModel_->checkToyMC(kTRUE,kTRUE); // Get the fit fractions if they're to be written into the latex table if (this->writeLatexTable()) { LauParArray fitFrac = sigDPModel_->getFitFractions(); if (fitFrac.size() != nSigComp_) { std::cerr << "ERROR in LauSimpleFitModel::genExpt : Fit Fraction array of unexpected dimension: " << fitFrac.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } for (UInt_t i(0); iExit(EXIT_FAILURE); } } for (UInt_t i(0); igetMeanEff().value()); dpRate_.value(sigDPModel_->getDPRate().value()); } } // If we're reusing embedded events or if the generation is being // reset then clear the lists of used events if (reuseSignal_ || !genOK) { if (signalTree_) { signalTree_->clearUsedList(); } } for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { LauEmbeddedData* data = bkgndTree_[bkgndID]; if (reuseBkgnd_[bkgndID] || !genOK) { if (data) { data->clearUsedList(); } } } return genOK; } Bool_t LauSimpleFitModel::generateSignalEvent() { // Generate signal event Bool_t genOK(kTRUE); Bool_t genSCF(kFALSE); if (this->useDP()) { if (this->enableEmbedding() && signalTree_) { if (useReweighting_) { // Select a (random) event from the generated data. Then store the // reconstructed DP co-ords, together with other pdf information, // as the embedded data. genOK = signalTree_->getReweightedEvent(sigDPModel_); } else { signalTree_->getEmbeddedEvent(kinematics_); } if (signalTree_->haveBranch("mcMatch")) { Int_t match = static_cast(signalTree_->getValue("mcMatch")); if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } else { genOK = sigDPModel_->generate(); if ( genOK && useSCF_ ) { Double_t frac(0.0); if ( useSCFHist_ ) { frac = scfFracHist_->calcEfficiency( kinematics_ ); } else { frac = scfFrac_.genValue(); } if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; // Optionally smear the DP position // of the SCF event if ( scfMap_ != 0 ) { Double_t xCoord(0.0), yCoord(0.0); if ( kinematics_->squareDP() ) { xCoord = kinematics_->getmPrime(); yCoord = kinematics_->getThetaPrime(); } else { xCoord = kinematics_->getm13Sq(); yCoord = kinematics_->getm23Sq(); } // Find the bin number where this event is generated Int_t binNo = scfMap_->binNumber( xCoord, yCoord ); // Retrieve the migration histogram TH2* histo = scfMap_->trueHist( binNo ); const LauAbsEffModel * effModel = sigDPModel_->getEffModel(); do { // Get a random point from the histogram histo->GetRandom2( xCoord, yCoord ); // Update the kinematics if ( kinematics_->squareDP() ) { kinematics_->updateSqDPKinematics( xCoord, yCoord ); } else { kinematics_->updateKinematics( xCoord, yCoord ); } } while ( ! effModel->passVeto( kinematics_ ) ); } } } } } else { if (this->enableEmbedding() && signalTree_) { signalTree_->getEmbeddedEvent(0); if (signalTree_->haveBranch("mcMatch")) { Int_t match = static_cast(signalTree_->getValue("mcMatch")); if (match) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } else if ( useSCF_ ) { Double_t frac = scfFrac_.genValue(); if ( frac < LauRandom::randomFun()->Rndm() ) { this->setGenNtupleIntegerBranchValue("genTMSig",1); this->setGenNtupleIntegerBranchValue("genSCFSig",0); genSCF = kFALSE; } else { this->setGenNtupleIntegerBranchValue("genTMSig",0); this->setGenNtupleIntegerBranchValue("genSCFSig",1); genSCF = kTRUE; } } } if (genOK) { if ( useSCF_ ) { if ( genSCF ) { this->generateExtraPdfValues(&scfPdfs_, signalTree_); } else { this->generateExtraPdfValues(&signalPdfs_, signalTree_); } } else { this->generateExtraPdfValues(&signalPdfs_, signalTree_); } } // Check for problems with the embedding if (this->enableEmbedding() && signalTree_ && (signalTree_->nEvents() == signalTree_->nUsedEvents())) { std::cerr << "WARNING in LauSimpleFitModel::generateSignalEvent : Source of embedded signal events used up, clearing the list of used events." << std::endl; signalTree_->clearUsedList(); } return genOK; } Bool_t LauSimpleFitModel::generateBkgndEvent(UInt_t bkgndID) { // Generate background event Bool_t genOK(kTRUE); LauAbsBkgndDPModel* model = bkgndDPModels_[bkgndID]; LauEmbeddedData* embeddedData(0); if (this->enableEmbedding()) { embeddedData = bkgndTree_[bkgndID]; } LauPdfList* extraPdfs = &bkgndPdfs_[bkgndID]; if (this->useDP()) { if (embeddedData) { embeddedData->getEmbeddedEvent(kinematics_); } else { if (model == 0) { std::cerr << "ERROR in LauSimpleFitModel::generateBkgndEvent : Can't find the DP model for background class \"" << this->bkgndClassName(bkgndID) << "\"." << std::endl; gSystem->Exit(EXIT_FAILURE); } genOK = model->generate(); } } else { if (embeddedData) { embeddedData->getEmbeddedEvent(0); } } if (genOK) { this->generateExtraPdfValues(extraPdfs, embeddedData); } // Check for problems with the embedding if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) { std::cerr << "WARNING in LauSimpleFitModel::generateBkgndEvent : Source of embedded " << this->bkgndClassName(bkgndID) << " events used up, clearing the list of used events." << std::endl; embeddedData->clearUsedList(); } return genOK; } void LauSimpleFitModel::setupGenNtupleBranches() { // Setup the required ntuple branches this->addGenNtupleDoubleBranch("evtWeight"); this->addGenNtupleIntegerBranch("genSig"); this->addGenNtupleDoubleBranch("efficiency"); if ( useSCF_ || ( this->enableEmbedding() && signalTree_ != 0 && signalTree_->haveBranch("mcMatch") ) ) { this->addGenNtupleIntegerBranch("genTMSig"); this->addGenNtupleIntegerBranch("genSCFSig"); } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name.Prepend("gen"); this->addGenNtupleIntegerBranch(name); } if (this->useDP() == kTRUE) { this->addGenNtupleDoubleBranch("m12"); this->addGenNtupleDoubleBranch("m23"); this->addGenNtupleDoubleBranch("m13"); this->addGenNtupleDoubleBranch("m12Sq"); this->addGenNtupleDoubleBranch("m23Sq"); this->addGenNtupleDoubleBranch("m13Sq"); this->addGenNtupleDoubleBranch("cosHel12"); this->addGenNtupleDoubleBranch("cosHel23"); this->addGenNtupleDoubleBranch("cosHel13"); if (kinematics_->squareDP()) { this->addGenNtupleDoubleBranch("mPrime"); this->addGenNtupleDoubleBranch("thPrime"); } } for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { this->addGenNtupleDoubleBranch( (*var_iter) ); } } } } void LauSimpleFitModel::setDPBranchValues() { // Store all the DP information this->setGenNtupleDoubleBranchValue("m12", kinematics_->getm12()); this->setGenNtupleDoubleBranchValue("m23", kinematics_->getm23()); this->setGenNtupleDoubleBranchValue("m13", kinematics_->getm13()); this->setGenNtupleDoubleBranchValue("m12Sq", kinematics_->getm12Sq()); this->setGenNtupleDoubleBranchValue("m23Sq", kinematics_->getm23Sq()); this->setGenNtupleDoubleBranchValue("m13Sq", kinematics_->getm13Sq()); this->setGenNtupleDoubleBranchValue("cosHel12", kinematics_->getc12()); this->setGenNtupleDoubleBranchValue("cosHel23", kinematics_->getc23()); this->setGenNtupleDoubleBranchValue("cosHel13", kinematics_->getc13()); if (kinematics_->squareDP()) { this->setGenNtupleDoubleBranchValue("mPrime", kinematics_->getmPrime()); this->setGenNtupleDoubleBranchValue("thPrime", kinematics_->getThetaPrime()); } } void LauSimpleFitModel::generateExtraPdfValues(LauPdfList* extraPdfs, LauEmbeddedData* embeddedData) { // Generate from the extra PDFs if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { LauFitData genValues; if (embeddedData) { genValues = embeddedData->getValues( (*pdf_iter)->varNames() ); } else { genValues = (*pdf_iter)->generate(kinematics_); } for ( LauFitData::const_iterator var_iter = genValues.begin(); var_iter != genValues.end(); ++var_iter ) { TString varName = var_iter->first; if ( varName != "m13Sq" && varName != "m23Sq" ) { Double_t value = var_iter->second; this->setGenNtupleDoubleBranchValue(varName,value); } } } } } void LauSimpleFitModel::propagateParUpdates() { // Update the total normalisation for the signal likelihood if (this->useDP() == kTRUE) { this->updateCoeffs(); sigDPModel_->updateCoeffs(coeffs_); } // Update the signal events from the background events if not doing an extended fit if ( !this->doEMLFit() && !signalEvents_->fixed() ) { this->updateSigEvents(); } } void LauSimpleFitModel::updateSigEvents() { // The background parameters will have been set from Minuit. // We need to update the signal events using these. Double_t nTotEvts = this->eventsPerExpt(); signalEvents_->range(-2.0*nTotEvts,2.0*nTotEvts); for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { LauAbsRValue* nBkgndEvents = (*iter); if ( nBkgndEvents->isLValue() ) { LauParameter* yield = dynamic_cast( nBkgndEvents ); yield->range(-2.0*nTotEvts,2.0*nTotEvts); } } if ( signalEvents_->fixed() ) { return; } // Subtract background events (if any) from signal. Double_t signalEvents = nTotEvts; if ( usingBkgnd_ == kTRUE ) { for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { signalEvents -= (*iter)->value(); } } signalEvents_->value(signalEvents); } void LauSimpleFitModel::cacheInputFitVars() { // Fill the internal data trees of the signal and backgrond models. LauFitDataTree* inputFitData = this->fitData(); // First the Dalitz plot variables (m_ij^2) if (this->useDP() == kTRUE) { // need to append SCF smearing bins before caching DP amplitudes if ( scfMap_ != 0 ) { this->appendBinCentres( inputFitData ); } sigDPModel_->fillDataTree(*inputFitData); if (usingBkgnd_ == kTRUE) { for (LauBkgndDPModelList::iterator iter = bkgndDPModels_.begin(); iter != bkgndDPModels_.end(); ++iter) { (*iter)->fillDataTree(*inputFitData); } } } // ...and then the extra PDFs this->cacheInfo(signalPdfs_, *inputFitData); this->cacheInfo(scfPdfs_, *inputFitData); for (LauBkgndPdfsList::iterator iter = bkgndPdfs_.begin(); iter != bkgndPdfs_.end(); ++iter) { this->cacheInfo((*iter), *inputFitData); } // and finally the SCF fractions and jacobians if ( useSCF_ && useSCFHist_ ) { if ( !inputFitData->haveBranch( "m13Sq" ) || !inputFitData->haveBranch( "m23Sq" ) ) { std::cerr << "ERROR in LauSimpleFitModel::cacheInputFitVars : Input data does not contain DP branches and so can't cache the SCF fraction." << std::endl; gSystem->Exit(EXIT_FAILURE); } UInt_t nEvents = inputFitData->nEvents(); recoSCFFracs_.clear(); recoSCFFracs_.reserve( nEvents ); if ( kinematics_->squareDP() ) { recoJacobians_.clear(); recoJacobians_.reserve( nEvents ); } for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) { const LauFitData& dataValues = inputFitData->getData(iEvt); LauFitData::const_iterator m13_iter = dataValues.find("m13Sq"); LauFitData::const_iterator m23_iter = dataValues.find("m23Sq"); kinematics_->updateKinematics( m13_iter->second, m23_iter->second ); Double_t scfFrac = scfFracHist_->calcEfficiency( kinematics_ ); recoSCFFracs_.push_back( scfFrac ); if ( kinematics_->squareDP() ) { recoJacobians_.push_back( kinematics_->calcSqDPJacobian() ); } } } } void LauSimpleFitModel::appendBinCentres( LauFitDataTree* inputData ) { // We'll be caching the DP amplitudes and efficiencies of the centres of the true bins. // To do so, we attach some fake points at the end of inputData, the number of the entry // minus the total number of events corresponding to the number of the histogram for that // given true bin in the LauScfMap object. (What this means is that when Laura is provided with // the LauScfMap object by the user, it's the latter who has to make sure that it contains the // right number of histograms and in exactly the right order!) // Get the x and y co-ordinates of the bin centres std::vector binCentresXCoords; std::vector binCentresYCoords; scfMap_->listBinCentres(binCentresXCoords, binCentresYCoords); // The SCF histograms could be in square Dalitz plot histograms. // The dynamics takes normal Dalitz plot coords, so we might have to convert them back. Bool_t sqDP = kinematics_->squareDP(); UInt_t nBins = binCentresXCoords.size(); fakeSCFFracs_.clear(); fakeSCFFracs_.reserve( nBins ); if ( sqDP ) { fakeJacobians_.clear(); fakeJacobians_.reserve( nBins ); } for (UInt_t iBin = 0; iBin < nBins; ++iBin) { if ( sqDP ) { kinematics_->updateSqDPKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); binCentresXCoords[iBin] = kinematics_->getm13Sq(); binCentresYCoords[iBin] = kinematics_->getm23Sq(); fakeJacobians_.push_back( kinematics_->calcSqDPJacobian() ); } else { kinematics_->updateKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]); } fakeSCFFracs_.push_back( scfFracHist_->calcEfficiency( kinematics_ ) ); } // Set up inputFitVars_ object to hold the fake events inputData->appendFakePoints(binCentresXCoords,binCentresYCoords); } Double_t LauSimpleFitModel::getTotEvtLikelihood(UInt_t iEvt) { // Get the DP likelihood for signal and backgrounds this->getEvtDPLikelihood(iEvt); // Get the combined extra PDFs likelihood for signal and backgrounds this->getEvtExtraLikelihoods(iEvt); // If appropriate, combine the TM and SCF likelihoods Double_t sigLike = sigDPLike_ * sigExtraLike_; if ( useSCF_ ) { Double_t scfFrac(0.0); if (useSCFHist_) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } sigLike *= (1.0 - scfFrac); if ( (scfMap_ != 0) && (this->useDP() == kTRUE) ) { // if we're smearing the SCF DP PDF then the SCF frac // is already included in the SCF DP likelihood sigLike += (scfDPLike_ * scfExtraLike_); } else { sigLike += (scfFrac * scfDPLike_ * scfExtraLike_); } } // Construct the total event likelihood Double_t likelihood = signalEvents_->unblindValue() * sigLike; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { likelihood += (bkgndEvents_[bkgndID]->unblindValue() * bkgndDPLike_[bkgndID] * bkgndExtraLike_[bkgndID]); } return likelihood; } Double_t LauSimpleFitModel::getEventSum() const { Double_t eventSum(0.0); eventSum += signalEvents_->unblindValue(); for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) { eventSum += (*iter)->unblindValue(); } return eventSum; } void LauSimpleFitModel::getEvtDPLikelihood(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // Dalitz plot for the given event evtNo. if (this->useDP() == kTRUE) { sigDPModel_->calcLikelihoodInfo(iEvt); sigDPLike_ = sigDPModel_->getEvtLikelihood(); if ( useSCF_ == kTRUE ) { if ( scfMap_ == 0 ) { // we're not smearing the SCF DP position // so the likelihood is the same as the TM scfDPLike_ = sigDPLike_; } else { // calculate the smeared SCF DP likelihood scfDPLike_ = this->getEvtSCFDPLikelihood(iEvt); } } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = bkgndDPModels_[bkgndID]->getLikelihood(iEvt); } else { bkgndDPLike_[bkgndID] = 0.0; } } } else { // There's always going to be a term in the likelihood for the // signal, so we'd better not zero it. sigDPLike_ = 1.0; scfDPLike_ = 1.0; const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_ == kTRUE) { bkgndDPLike_[bkgndID] = 1.0; } else { bkgndDPLike_[bkgndID] = 0.0; } } } } Double_t LauSimpleFitModel::getEvtSCFDPLikelihood(UInt_t iEvt) { Double_t scfDPLike(0.0); Double_t recoJacobian(1.0); Double_t xCoord(0.0); Double_t yCoord(0.0); Bool_t squareDP = kinematics_->squareDP(); if ( squareDP ) { xCoord = sigDPModel_->getEvtmPrime(); yCoord = sigDPModel_->getEvtthPrime(); recoJacobian = recoJacobians_[iEvt]; } else { xCoord = sigDPModel_->getEvtm13Sq(); yCoord = sigDPModel_->getEvtm23Sq(); } // Find the bin that our reco event falls in Int_t recoBin = scfMap_->binNumber( xCoord, yCoord ); // Find out which true Bins contribute to the given reco bin const std::vector* trueBins = scfMap_->trueBins(recoBin); Int_t nDataEvents = this->eventsPerExpt(); // Loop over the true bins for (std::vector::const_iterator iter = trueBins->begin(); iter != trueBins->end(); ++iter) { Int_t trueBin = (*iter); // prob of a true event in the given true bin migrating to the reco bin Double_t pRecoGivenTrue = scfMap_->prob( recoBin, trueBin ); // We've cached the DP amplitudes and the efficiency for the // true bin centres, just after the data points sigDPModel_->calcLikelihoodInfo( nDataEvents + trueBin ); Double_t pTrue = sigDPModel_->getEvtLikelihood(); // Get the cached SCF fraction (and jacobian if we're using the square DP) Double_t scfFraction = fakeSCFFracs_[ trueBin ]; Double_t jacobian(1.0); if ( squareDP ) { jacobian = fakeJacobians_[ trueBin ]; } scfDPLike += pTrue * jacobian * scfFraction * pRecoGivenTrue; } // Divide by the reco jacobian scfDPLike /= recoJacobian; return scfDPLike; } void LauSimpleFitModel::getEvtExtraLikelihoods(UInt_t iEvt) { // Function to return the signal and background likelihoods for the // extra variables for the given event evtNo. sigExtraLike_ = 1.0; for (LauPdfList::iterator iter = signalPdfs_.begin(); iter != signalPdfs_.end(); ++iter) { (*iter)->calcLikelihoodInfo(iEvt); sigExtraLike_ *= (*iter)->getLikelihood(); } if (useSCF_) { scfExtraLike_ = 1.0; for (LauPdfList::iterator iter = scfPdfs_.begin(); iter != scfPdfs_.end(); ++iter) { (*iter)->calcLikelihoodInfo(iEvt); scfExtraLike_ *= (*iter)->getLikelihood(); } } const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) { if (usingBkgnd_) { bkgndExtraLike_[bkgndID] = 1.0; LauPdfList& pdfList = bkgndPdfs_[bkgndID]; for (LauPdfList::iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { (*pdf_iter)->calcLikelihoodInfo(iEvt); bkgndExtraLike_[bkgndID] *= (*pdf_iter)->getLikelihood(); } } else { bkgndExtraLike_[bkgndID] = 0.0; } } } void LauSimpleFitModel::updateCoeffs() { coeffs_.clear(); coeffs_.reserve(nSigComp_); for (UInt_t i = 0; i < nSigComp_; i++) { coeffs_.push_back(coeffPars_[i]->particleCoeff()); } } void LauSimpleFitModel::setupSPlotNtupleBranches() { // add branches for storing the experiment number and the number of // the event within the current experiment this->addSPlotNtupleIntegerBranch("iExpt"); this->addSPlotNtupleIntegerBranch("iEvtWithinExpt"); // Store the efficiency of the event (for inclusive BF calculations). if (this->storeDPEff()) { this->addSPlotNtupleDoubleBranch("efficiency"); if ( sigDPModel_->usingScfModel() ) { this->addSPlotNtupleDoubleBranch("scffraction"); } } // Store the total event likelihood for each species. if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFTotalLike"); this->addSPlotNtupleDoubleBranch("sigSCFFrac"); } else { this->addSPlotNtupleDoubleBranch("sigTotalLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "TotalLike"; this->addSPlotNtupleDoubleBranch(name); } } // Store the DP likelihoods if (this->useDP()) { if (useSCF_) { this->addSPlotNtupleDoubleBranch("sigTMDPLike"); this->addSPlotNtupleDoubleBranch("sigSCFDPLike"); } else { this->addSPlotNtupleDoubleBranch("sigDPLike"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name( this->bkgndClassName(iBkgnd) ); name += "DPLike"; this->addSPlotNtupleDoubleBranch(name); } } } // Store the likelihoods for each extra PDF if (useSCF_) { this->addSPlotNtupleBranches(&signalPdfs_, "sigTM"); this->addSPlotNtupleBranches(&scfPdfs_, "sigSCF"); } else { this->addSPlotNtupleBranches(&signalPdfs_, "sig"); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList* pdfList = &(bkgndPdfs_[iBkgnd]); this->addSPlotNtupleBranches(pdfList, bkgndClass); } } } void LauSimpleFitModel::addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix) { if (extraPdfs) { // Loop through each of the PDFs for (LauPdfList::const_iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply add one branch for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else if ( nVars == 2 ) { // If the PDF has two variables then we // need a branch for them both together and // branches for each TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; this->addSPlotNtupleDoubleBranch(name); } TString name(prefix); name += allVars; name += "Like"; this->addSPlotNtupleDoubleBranch(name); } else { std::cerr << "WARNING in LauSimpleFitModel::addSPlotNtupleBranches : Can't yet deal with 3D PDFs." << std::endl; } } } } Double_t LauSimpleFitModel::setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt) { // Store the PDF value for each variable in the list Double_t totalLike(1.0); Double_t extraLike(0.0); if (extraPdfs) { for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) { // calculate the likelihood for this event (*pdf_iter)->calcLikelihoodInfo(iEvt); extraLike = (*pdf_iter)->getLikelihood(); totalLike *= extraLike; // Count the number of input variables that are not // DP variables (used in the case where there is DP // dependence for e.g. MVA) UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 1 ) { // If the PDF only has one variable then // simply store the value for that variable TString varName = (*pdf_iter)->varName(); TString name(prefix); name += varName; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else if ( nVars == 2 ) { // If the PDF has two variables then we // store the value for them both together // and for each on their own TString allVars(""); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { allVars += (*var_iter); TString name(prefix); name += (*var_iter); name += "Like"; Double_t indivLike = (*pdf_iter)->getLikelihood( (*var_iter) ); this->setSPlotNtupleDoubleBranchValue(name, indivLike); } TString name(prefix); name += allVars; name += "Like"; this->setSPlotNtupleDoubleBranchValue(name, extraLike); } else { std::cerr << "WARNING in LauSimpleFitModel::setSPlotNtupleBranchValues : Can't yet deal with 3D PDFs." << std::endl; } } } return totalLike; } LauSPlot::NameSet LauSimpleFitModel::variableNames() const { LauSPlot::NameSet nameSet; if (this->useDP()) { nameSet.insert("DP"); } // Loop through all the signal PDFs for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { // Loop over the variables involved in each PDF std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { // If they are not DP coordinates then add them if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { nameSet.insert( (*var_iter) ); } } } return nameSet; } LauSPlot::NumbMap LauSimpleFitModel::freeSpeciesNames() const { LauSPlot::NumbMap numbMap; if (!signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (!par->fixed()) { numbMap[bkgndClass] = par->genValue(); if ( ! par->isLValue() ) { std::cerr << "WARNING in LauSimpleFitModel::freeSpeciesNames : \"" << par->name() << "\" is a LauFormulaPar, which implies it is perhaps not entirely free to float in the fit, so the sWeight calculation may not be reliable" << std::endl; } } } } return numbMap; } LauSPlot::NumbMap LauSimpleFitModel::fixdSpeciesNames() const { LauSPlot::NumbMap numbMap; if (signalEvents_->fixed() && this->doEMLFit()) { numbMap["sig"] = signalEvents_->genValue(); } if ( usingBkgnd_ ) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauAbsRValue* par = bkgndEvents_[iBkgnd]; if (par->fixed()) { numbMap[bkgndClass] = par->genValue(); } } } return numbMap; } LauSPlot::TwoDMap LauSimpleFitModel::twodimPDFs() const { LauSPlot::TwoDMap twodimMap; for (LauPdfList::const_iterator pdf_iter = signalPdfs_.begin(); pdf_iter != signalPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { if (useSCF_) { twodimMap.insert( std::make_pair( "sigTM", std::make_pair( varNames[0], varNames[1] ) ) ); } else { twodimMap.insert( std::make_pair( "sig", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if ( useSCF_ ) { for (LauPdfList::const_iterator pdf_iter = scfPdfs_.begin(); pdf_iter != scfPdfs_.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( "sigSCF", std::make_pair( varNames[0], varNames[1] ) ) ); } } } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); const LauPdfList& pdfList = bkgndPdfs_[iBkgnd]; for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) { // Count the number of input variables that are not DP variables UInt_t nVars(0); std::vector varNames = (*pdf_iter)->varNames(); for ( std::vector::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) { if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) { ++nVars; } } if ( nVars == 2 ) { twodimMap.insert( std::make_pair( bkgndClass, std::make_pair( varNames[0], varNames[1] ) ) ); } } } } return twodimMap; } void LauSimpleFitModel::storePerEvtLlhds() { std::cout << "INFO in LauSimpleFitModel::storePerEvtLlhds : Storing per-event likelihood values..." << std::endl; // if we've not been using the DP model then we need to cache all // the info here so that we can get the efficiency from it LauFitDataTree* inputFitData = this->fitData(); if (!this->useDP() && this->storeDPEff()) { sigDPModel_->initialise(coeffs_); sigDPModel_->fillDataTree(*inputFitData); } UInt_t evtsPerExpt(this->eventsPerExpt()); for (UInt_t iEvt = 0; iEvt < evtsPerExpt; ++iEvt) { this->setSPlotNtupleIntegerBranchValue("iExpt",this->iExpt()); this->setSPlotNtupleIntegerBranchValue("iEvtWithinExpt",iEvt); // the DP information this->getEvtDPLikelihood(iEvt); if (this->storeDPEff()) { if (!this->useDP()) { sigDPModel_->calcLikelihoodInfo(iEvt); } this->setSPlotNtupleDoubleBranchValue("efficiency",sigDPModel_->getEvtEff()); if ( sigDPModel_->usingScfModel() ) { this->setSPlotNtupleDoubleBranchValue("scffraction",sigDPModel_->getEvtScfFraction()); } } if (this->useDP()) { sigTotalLike_ = sigDPLike_; if (useSCF_) { scfTotalLike_ = scfDPLike_; this->setSPlotNtupleDoubleBranchValue("sigTMDPLike",sigDPLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFDPLike",scfDPLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigDPLike",sigDPLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "DPLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndDPLike_[iBkgnd]); } } } else { sigTotalLike_ = 1.0; if (useSCF_) { scfTotalLike_ = 1.0; } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { bkgndTotalLike_[iBkgnd] = 1.0; } } } // the signal PDF values if ( useSCF_ ) { sigTotalLike_ *= this->setSPlotNtupleBranchValues(&signalPdfs_, "sigTM", iEvt); scfTotalLike_ *= this->setSPlotNtupleBranchValues(&scfPdfs_, "sigSCF", iEvt); } else { sigTotalLike_ *= this->setSPlotNtupleBranchValues(&signalPdfs_, "sig", iEvt); } // the background PDF values if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { const TString& bkgndClass = this->bkgndClassName(iBkgnd); LauPdfList& pdfs = bkgndPdfs_[iBkgnd]; bkgndTotalLike_[iBkgnd] *= this->setSPlotNtupleBranchValues(&(pdfs), bkgndClass, iEvt); } } // the total likelihoods if (useSCF_) { Double_t scfFrac(0.0); if ( useSCFHist_ ) { scfFrac = recoSCFFracs_[iEvt]; } else { scfFrac = scfFrac_.unblindValue(); } this->setSPlotNtupleDoubleBranchValue("sigSCFFrac",scfFrac); sigTotalLike_ *= ( 1.0 - scfFrac ); if ( scfMap_ == 0 ) { scfTotalLike_ *= scfFrac; } this->setSPlotNtupleDoubleBranchValue("sigTMTotalLike",sigTotalLike_); this->setSPlotNtupleDoubleBranchValue("sigSCFTotalLike",scfTotalLike_); } else { this->setSPlotNtupleDoubleBranchValue("sigTotalLike",sigTotalLike_); } if (usingBkgnd_) { const UInt_t nBkgnds = this->nBkgndClasses(); for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) { TString name = this->bkgndClassName(iBkgnd); name += "TotalLike"; this->setSPlotNtupleDoubleBranchValue(name,bkgndTotalLike_[iBkgnd]); } } // fill the tree this->fillSPlotNtupleBranches(); } std::cout << "INFO in LauSimpleFitModel::storePerEvtLlhds : Finished storing per-event likelihood values." << std::endl; } void LauSimpleFitModel::embedSignal(const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment, Bool_t useReweighting) { if (signalTree_) { std::cerr << "ERROR in LauSimpleFitModel::embedSignal : Already embedding signal from a file." << std::endl; return; } signalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = signalTree_->findBranches(); if (!dataOK) { delete signalTree_; signalTree_ = 0; std::cerr << "ERROR in LauSimpleFitModel::embedSignal : Problem creating data tree for embedding." << std::endl; return; } reuseSignal_ = reuseEventsWithinEnsemble; useReweighting_ = useReweighting; if (this->enableEmbedding() == kFALSE) { this->enableEmbedding(kTRUE); } } void LauSimpleFitModel::embedBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment) { if ( ! this->validBkgndClass( bkgndClass ) ) { std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl; std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl; return; } UInt_t bkgndID = this->bkgndClassID( bkgndClass ); if (bkgndTree_[bkgndID]) { std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Already embedding background from a file." << std::endl; return; } bkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment); Bool_t dataOK = bkgndTree_[bkgndID]->findBranches(); if (!dataOK) { delete bkgndTree_[bkgndID]; bkgndTree_[bkgndID] = 0; std::cerr << "ERROR in LauSimpleFitModel::embedBkgnd : Problem creating data tree for embedding." << std::endl; return; } reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble; if (this->enableEmbedding() == kFALSE) { this->enableEmbedding(kTRUE); } } void LauSimpleFitModel::weightEvents( const TString& dataFileName, const TString& dataTreeName ) { // Routine to provide weights for events that are uniformly distributed // in the DP (or square DP) so as to reproduce the given DP model const Bool_t squareDP { kinematics_->squareDP() }; if ( squareDP ) { std::cout << "INFO in LauSimpleFitModel::weightEvents : will store DP model weights and the square DP jacobian\n"; std::cout << " : the DP model weights can be used on their own to weight events that were generated flat in phase space\n"; std::cout << " : or they can be multiplied by the jacobian to weight events that were generated flat in the square DP\n"; std::cout << " : or they can be multiplied by max(1.0, jacobian) to weight events that were generated quasi-flat in the square DP" << std::endl; } else { std::cout << "INFO in LauSimpleFitModel::weightEvents : will store DP model weights suitable for weighting events that 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. const Bool_t dataOK { this->verifyFitData( dataFileName, dataTreeName ) }; if ( ! dataOK ) { std::cerr << "ERROR in LauSimpleFitModel::weightEvents : Problem caching the data." << std::endl; return; } LauFitDataTree* inputFitData { this->fitData() }; if ( ! inputFitData->haveBranch( "m13Sq_MC" ) || ! inputFitData->haveBranch( "m23Sq_MC" ) ) { std::cerr << "ERROR 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 }; const Ssiz_t index { weightsFileName.Last( '.' ) }; weightsFileName.Insert( index, "_DPweights" ); LauGenNtuple weightsTuple{ weightsFileName, dataTreeName }; weightsTuple.addIntegerBranch( "iExpt" ); weightsTuple.addIntegerBranch( "iEvtWithinExpt" ); weightsTuple.addDoubleBranch( "dpModelWeight" ); if ( squareDP ) { weightsTuple.addDoubleBranch( "sqDPJacobian" ); } const UInt_t nExpmt { this->nExpt() }; const UInt_t firstExpmt { this->firstExpt() }; for (UInt_t iExpmt {firstExpmt}; iExpmt < (firstExpmt+nExpmt); ++iExpmt) { inputFitData->readExperimentData(iExpmt); const 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 ) }; const Double_t m13Sq_MC { evtData.at( "m13Sq_MC" ) }; const Double_t m23Sq_MC { evtData.at( "m23Sq_MC" ) }; Double_t dpModelWeight{0.0}; Double_t jacobian{1.0}; if ( kinematics_->withinDPLimits( m13Sq_MC, m23Sq_MC ) ) { kinematics_->updateKinematics( m13Sq_MC, m23Sq_MC ); dpModelWeight = sigDPModel_->getEventWeight(); if ( squareDP ) { jacobian = kinematics_->calcSqDPJacobian(); } dpModelWeight /= sigDPModel_->getDPNorm(); } weightsTuple.setDoubleBranchValue( "dpModelWeight", dpModelWeight ); if ( squareDP ) { weightsTuple.setDoubleBranchValue( "sqDPJacobian", jacobian ); } weightsTuple.fillBranches(); } } weightsTuple.buildIndex( "iExpt", "iEvtWithinExpt" ); weightsTuple.addFriendTree( dataFileName, dataTreeName ); weightsTuple.writeOutGenResults(); } void LauSimpleFitModel::savePDFPlots(const TString& label) { savePDFPlotsWave(label, 0); savePDFPlotsWave(label, 1); savePDFPlotsWave(label, 2); std::cout << "LauCPFitModel::plot" << std::endl; // ((LauIsobarDynamics*)sigDPModel_)->plot(); //Double_t minm13 = sigDPModel_->getKinematics()->getm13Min(); Double_t minm13 = 0.0; Double_t maxm13 = sigDPModel_->getKinematics()->getm13Max(); //Double_t minm23 = sigDPModel_->getKinematics()->getm23Min(); Double_t minm23 = 0.0; Double_t maxm23 = sigDPModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, chPdf; Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = sigDPModel_->getnCohAmp(); for (UInt_t resID = 0; resID <= nAmp; ++resID) { TGraph2D *dt = new TGraph2D(); TString resName = "TotalAmp"; if (resID != nAmp){ TString tStrResID = Form("%d", resID); const LauIsobarDynamics* model = sigDPModel_; const LauAbsResonance* resonance = model->getResonance(resID); resName = resonance->getResonanceName(); std::cout << "resName = " << resName << std::endl; } resName.ReplaceAll("(", ""); resName.ReplaceAll(")", ""); resName.ReplaceAll("*", "Star"); TCanvas *c = new TCanvas("c"+resName+label,resName+" ("+label+")",0,0,600,400); dt->SetName(resName+label); dt->SetTitle(resName+" ("+label+")"); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { //if (s13 > 4) continue; sigDPModel_->calcLikelihoodInfo(s13, s23); LauComplex chAmp = sigDPModel_->getEvtDPAmp(); if (resID != nAmp){ chAmp = sigDPModel_->getFullAmplitude(resID); } chPdf = chAmp.abs2(); //if ((z > 0.04)||(z < -0.03)) continue; //z = TMath::Log(z); if (sigDPModel_->getDaughters()->gotSymmetricalDP()){ Double_t sLow = s13; Double_t sHigh = s23; if (sLow>sHigh) { continue; //sLow = s23; //sHigh = s13; } //if (sLow > 3.5) continue; //if (i<10) std::cout << "SymmetricalDP" << std::endl; //if (z>0.02) z = 0.02; //if (z<-0.02) z = -0.02; dt->SetPoint(count,sHigh,sLow,chPdf); count++; } else { dt->SetPoint(count,s13,s23,chPdf); count++; } } } } gStyle->SetPalette(1); dt->GetXaxis()->SetTitle("m_{K#pi}(low)"); dt->GetYaxis()->SetTitle("m_{K#pi}(high)"); dt->Draw("SURF1"); dt->GetXaxis()->SetTitle("m_{K#pi}(low)"); dt->GetYaxis()->SetTitle("m_{K#pi}(high)"); c->SaveAs("plot_2D_"+resName + "_"+label+".C"); } } void LauSimpleFitModel::savePDFPlotsWave(const TString& label, const Int_t& spin) { std::cout << "label = "<< label << ", spin = "<< spin << std::endl; TString tStrResID = "S_Wave"; if (spin == 1) tStrResID = "P_Wave"; if (spin == 2) tStrResID = "D_Wave"; std::cout << "LauSimpleFitModel::savePDFPlotsWave: "<< tStrResID << std::endl; TCanvas *c = new TCanvas("c"+tStrResID+label,tStrResID+" ("+label+")",0,0,600,400); Double_t minm13 = 0.0; Double_t maxm13 = sigDPModel_->getKinematics()->getm13Max(); Double_t minm23 = 0.0; Double_t maxm23 = sigDPModel_->getKinematics()->getm23Max(); Double_t mins13 = minm13*minm13; Double_t maxs13 = maxm13*maxm13; Double_t mins23 = minm23*minm23; Double_t maxs23 = maxm23*maxm23; Double_t s13, s23, chPdf; TGraph2D *dt = new TGraph2D(); dt->SetName(tStrResID+label); dt->SetTitle(tStrResID+" ("+label+")"); Int_t n13=200.00, n23=200.00; Double_t delta13, delta23; delta13 = (maxs13 - mins13)/n13; delta23 = (maxs23 - mins23)/n23; UInt_t nAmp = sigDPModel_->getnCohAmp(); Int_t count=0; for (Int_t i=0; igetKinematics()->withinDPLimits2(s23, s13)) { //if (s13 > 4) continue; LauComplex chAmp(0,0); Bool_t noWaveRes = kTRUE; sigDPModel_->calcLikelihoodInfo(s13, s23); for (UInt_t resID = 0; resID < nAmp; ++resID) { const LauIsobarDynamics* model = sigDPModel_; const LauAbsResonance* resonance = model->getResonance(resID); Int_t spin_res = resonance->getSpin(); if (spin != spin_res) continue; noWaveRes = kFALSE; chAmp += sigDPModel_->getFullAmplitude(resID); } if (noWaveRes) return; chPdf = chAmp.abs2(); if (sigDPModel_->getDaughters()->gotSymmetricalDP()){ Double_t sLow = s13; Double_t sHigh = s23; if (sLow>sHigh) { continue; //sLow = s23; //sHigh = s13; } dt->SetPoint(count,sHigh,sLow,chPdf); count++; } else { dt->SetPoint(count,s13,s23,chPdf); count++; } } } } gStyle->SetPalette(1); dt->GetXaxis()->SetTitle("pipi"); dt->GetYaxis()->SetTitle("pipi"); dt->Draw("SURF1"); dt->GetXaxis()->SetTitle("pipi"); dt->GetYaxis()->SetTitle("pipi"); c->SaveAs("plot_2D_"+tStrResID+"_"+label+".C"); } diff --git a/src/LauSumPdf.cc b/src/LauSumPdf.cc index 4687d5f..0b93e83 100644 --- a/src/LauSumPdf.cc +++ b/src/LauSumPdf.cc @@ -1,211 +1,210 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauSumPdf.cc \brief File containing implementation of LauSumPdf class. */ #include #include #include "TMath.h" #include "TSystem.h" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauSumPdf.hh" -ClassImp(LauSumPdf) LauSumPdf::LauSumPdf(LauAbsPdf* pdf1, LauAbsPdf* pdf2, LauParameter* frac) : LauAbsPdf(pdf1 ? pdf1->varNames() : std::vector(), std::vector(), pdf1 ? pdf1->getMinAbscissas() : LauFitData(), pdf1 ? pdf1->getMaxAbscissas() : LauFitData()), pdf1_(pdf1), pdf2_(pdf2), frac_(frac) { // Constructor for the sum PDF. // We are defining the sum as: // f x (PDF1/S(PDF1)) + (1-f) x (PDF2/S(PDF2)) // where f is the fraction, x is multiplication, PDFi is the i'th PDF, // and S(PDFi) is the integral of the i'th PDF. // // The last two arguments specify the range in which the PDF is defined, and the PDF // will be normalised w.r.t. these limits. // So the first thing we have to do is check the pointers are all valid. if (!frac || !pdf1 || !pdf2) { std::cerr << "ERROR in LauSumPdf constructor : one of the 3 pointers is null." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Next check that the abscissa ranges are the same for each PDF if (pdf1->getMinAbscissa() != pdf2->getMinAbscissa()) { std::cerr << "ERROR in LauSumPdf constructor : minimum abscissa values not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } if (pdf1->getMaxAbscissa() != pdf2->getMaxAbscissa()) { std::cerr << "ERROR in LauSumPdf constructor : maximum abscissa values not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same number of input variables if (pdf1->nInputVars() != pdf2->nInputVars()) { std::cerr << "ERROR in LauSumPdf constructor : number of input variables not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Also check that both PDFs are expecting the same variable name if (pdf1->varNames() != pdf2->varNames()) { std::cerr << "ERROR in LauSumPdf constructor : variable name not the same for the two PDFs." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Then we need to grab all the parameters and pass them to the base class. // This is so that when we are asked for them they can be put into the fit. // The number of parameters is the number in PDF1 + the number in PDF2 + 1 for the fraction. UInt_t nPar(pdf1->nParameters()+pdf2->nParameters()+1); std::vector params; params.reserve(nPar); std::vector& pdf1pars = pdf1->getParameters(); std::vector& pdf2pars = pdf2->getParameters(); params.push_back(frac); for (std::vector::iterator iter = pdf1pars.begin(); iter != pdf1pars.end(); ++iter) { params.push_back(*iter); } for (std::vector::iterator iter = pdf2pars.begin(); iter != pdf2pars.end(); ++iter) { params.push_back(*iter); } this->addParameters(params); // Now check that we can find the fraction parameter ok frac_ = this->findParameter("frac"); if (frac_ == 0) { std::cerr << "ERROR in LauSumPdf constructor : parameter \"frac\" not found." << std::endl; gSystem->Exit(EXIT_FAILURE); } // Cache the normalisation factor this->calcNorm(); } LauSumPdf::~LauSumPdf() { // Destructor } void LauSumPdf::calcLikelihoodInfo(const LauAbscissas& abscissas) { // Check that the given abscissa is within the allowed range if (!this->checkRange(abscissas)) { gSystem->Exit(EXIT_FAILURE); } // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(abscissas); pdf2_->calcLikelihoodInfo(abscissas); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = frac * result1 + (1.0-frac) * result2; this->setUnNormPDFVal(result); } void LauSumPdf::calcNorm() { // Nothing to do here, since it is already normalized this->setNorm(1.0); } void LauSumPdf::calcPDFHeight( const LauKinematics* kinematics ) { if ( this->heightUpToDate() && ! this->isDPDependent() ) { return; } // This method gives you the maximum possible height of the PDF. // It combines the maximum heights of the two individual PDFs. // So it would give the true maximum if the two individual maxima coincided. // It is guaranteed to always be >= the true maximum. // Update the heights of the individual PDFs pdf1_->calcPDFHeight( kinematics ); pdf2_->calcPDFHeight( kinematics ); // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Find the (un-normalised) individual PDF maxima Double_t height1 = pdf1_->getMaxHeight(); Double_t height2 = pdf2_->getMaxHeight(); // Get the individual PDF normalisation factors Double_t norm1 = pdf1_->getNorm(); Double_t norm2 = pdf2_->getNorm(); // Calculate the normalised individual PDF maxima height1 /= norm1; height2 /= norm2; // Combine these heights together Double_t height = frac * height1 + (1-frac) * height2; this->setMaxHeight(height); } // Override the base class methods for cacheInfo and calcLikelihoodInfo(UInt_t iEvt). // For both of these we delegate to the two constituent PDFs. void LauSumPdf::cacheInfo(const LauFitDataTree& inputData) { pdf1_->cacheInfo(inputData); pdf2_->cacheInfo(inputData); // determine whether we are caching our PDF value Bool_t doCaching ( this->nFixedParameters() == this->nParameters() ); this->cachePDF( doCaching ); // Set whether the height is up-to-date only if it is true for both of the sub-PDFs Bool_t hutd = pdf1_->heightUpToDate() && pdf2_->heightUpToDate(); this->heightUpToDate(hutd); } void LauSumPdf::calcLikelihoodInfo(UInt_t iEvt) { // Get the up to date parameter values Double_t frac = frac_->unblindValue(); // Evaluate the normalised PDF values pdf1_->calcLikelihoodInfo(iEvt); pdf2_->calcLikelihoodInfo(iEvt); Double_t result1 = pdf1_->getLikelihood(); Double_t result2 = pdf2_->getLikelihood(); // Add them together Double_t result = frac * result1 + (1.0-frac) * result2; this->setUnNormPDFVal(result); } diff --git a/src/LauVetoes.cc b/src/LauVetoes.cc index 6dc7af4..5c9aabf 100644 --- a/src/LauVetoes.cc +++ b/src/LauVetoes.cc @@ -1,215 +1,214 @@ /* Copyright 2004 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauVetoes.cc \brief File containing implementation of LauVetoes class. */ #include #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauVetoes) LauVetoes::LauVetoes() : nVetoes_(0) { } LauVetoes::~LauVetoes() { } LauVetoes::LauVetoes(const LauVetoes& other) : nVetoes_(other.nVetoes_), vetoPair_(other.vetoPair_), vetoMinMass_(other.vetoMinMass_), vetoMaxMass_(other.vetoMaxMass_) { } LauVetoes& LauVetoes::operator=(const LauVetoes& other) { if ( &other != this ) { nVetoes_ = other.nVetoes_; vetoPair_ = other.vetoPair_; vetoMinMass_ = other.vetoMinMass_; vetoMaxMass_ = other.vetoMaxMass_; } return *this; } void LauVetoes::addMassVeto(const Int_t resPairAmpInt, const Double_t minMass, const Double_t maxMass) { const Double_t minMassSq = minMass*minMass; const Double_t maxMassSq = maxMass*maxMass; this->addMassSqVeto(resPairAmpInt, minMassSq, maxMassSq); } void LauVetoes::addMassSqVeto(const Int_t resPairAmpInt, const Double_t minMassSq, const Double_t maxMassSq) { // Routine to add a veto in the Dalitz plot. The function takes as input the // bachelor track number (1, 2 or 3) and the mass-squared range of the veto. if (resPairAmpInt == 1) { // The bachelor track is the first track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 1, with " << minMassSq << " < m^2_23 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 2) { // The bachelor track is the second track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 2, with " << minMassSq << " < m^2_13 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 3) { // The bachelor track is the third track std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 3, with " << minMassSq << " < m^2_12 < " << maxMassSq << std::endl; } else if (resPairAmpInt == 4) { // Special case for symmetric DPs - the veto will be applied on the minimum of m13Sq and m23Sq std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 4, with " << minMassSq << " < m^2_min < " << maxMassSq << std::endl; } else if (resPairAmpInt == 5) { // Special case for symmetric DPs - the veto will be applied on the maximum of m13Sq and m23Sq std::cout << "INFO in LauVetoes::addMassSqVeto : Adding the veto for resPairAmpInt = 5, with " << minMassSq << " < m^2_max < " << maxMassSq << std::endl; } else { std::cerr << "ERROR in LauVetoes::addMassSqVeto : Invalid resPairAmpInt. Please use 1, 2 or 3 to specify bachelor daughter track (or 4 or 5 to specify a veto on mMinSq or mMaxSq in a symmetric DP). Veto is not added." << std::endl; return; } // Set the veto limits vetoPair_.push_back(resPairAmpInt); vetoMinMass_.push_back(minMassSq); vetoMaxMass_.push_back(maxMassSq); // Keep track of how many vetoes we have ++nVetoes_; } Bool_t LauVetoes::passVeto(const LauKinematics* kinematics) const { // Routine to ask whether the given Dalitz plot point passes any specified vetoes. if (kinematics == 0) { std::cerr << "ERROR in LauVetoes::passVeto : LauKinematics object is null." << std::endl; return kFALSE; } const Double_t m12Sq = kinematics->getm12Sq(); const Double_t m23Sq = kinematics->getm23Sq(); const Double_t m13Sq = kinematics->getm13Sq(); const Bool_t symmetricDP = kinematics->gotSymmetricalDP(); const Bool_t fullySymmetricDP = kinematics->gotFullySymmetricDP(); return this->passVeto(m12Sq, m23Sq, m13Sq, symmetricDP, fullySymmetricDP); } Bool_t LauVetoes::passVeto(const Double_t m12Sq, const Double_t m23Sq, const Double_t m13Sq, const Bool_t symmetricDP, const Bool_t fullySymmetricDP) const { // Routine to ask whether the given Dalitz plot point passes any specified vetoes. // Loop over the number of possible vetoes for ( UInt_t i(0); i < nVetoes_; ++i) { if (vetoPair_[i] == 1) { // Veto m23 combination if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } // If the DP is symmetric we need to test m13 combination as well if ( symmetricDP || fullySymmetricDP ) { if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 2) { // Veto m13 combination if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } // If the DP is symmetric we need to test m23 combination as well if ( symmetricDP || fullySymmetricDP ) { if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 3) { // Veto m12 combination if (m12Sq > vetoMinMass_[i] && m12Sq < vetoMaxMass_[i]) { return kFALSE; } // If it's fully symmetric we need to check all 3 combinations if ( fullySymmetricDP ) { if (m13Sq > vetoMinMass_[i] && m13Sq < vetoMaxMass_[i]) { return kFALSE; } if (m23Sq > vetoMinMass_[i] && m23Sq < vetoMaxMass_[i]) { return kFALSE; } } } else if (vetoPair_[i] == 4) { if (!symmetricDP) { std::cerr << "WARNING in LauVetoes::passVeto : resPairAmpInt of 4 is only valid for symmetric DPs, will ignore this veto" << std::endl; continue; } // Veto mMin combination const Double_t mMinSq = TMath::Min( m13Sq, m23Sq ); if (mMinSq > vetoMinMass_[i] && mMinSq < vetoMaxMass_[i]) { return kFALSE; } } else if (vetoPair_[i] == 5) { if (!symmetricDP) { std::cerr << "WARNING in LauVetoes::passVeto : resPairAmpInt of 5 is only valid for symmetric DPs, will ignore this veto" << std::endl; continue; } // Veto mMax combination const Double_t mMaxSq = TMath::Max( m13Sq, m23Sq ); if (mMaxSq > vetoMinMass_[i] && mMaxSq < vetoMaxMass_[i]) { return kFALSE; } } } return kTRUE; } diff --git a/src/LauWeightedSumEffModel.cc b/src/LauWeightedSumEffModel.cc index 0fb5a28..99a6d21 100644 --- a/src/LauWeightedSumEffModel.cc +++ b/src/LauWeightedSumEffModel.cc @@ -1,123 +1,122 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauWeightedSumEffModel.cc \brief File containing implementation of LauWeightedSumEffModel class. */ #include #include #include "TSystem.h" #include "Lau2DHistDP.hh" #include "Lau2DSplineDP.hh" #include "LauDaughters.hh" #include "LauWeightedSumEffModel.hh" #include "LauKinematics.hh" #include "LauVetoes.hh" -ClassImp(LauWeightedSumEffModel) LauWeightedSumEffModel::LauWeightedSumEffModel(const LauDaughters* daughters) : daughters_( daughters ), effModel_( 0 ), fluctuateEffHisto_( kFALSE ), lowBinWarningIssued_( kFALSE ), highBinWarningIssued_( kFALSE ) { if ( daughters_ == 0 ) { std::cerr << "ERROR in LauWeightedSumEffModel Constructor : invalid pointer to daughters object supplied." << std::endl; gSystem->Exit(EXIT_FAILURE); } } void LauWeightedSumEffModel::addEffModel(const LauAbsEffModel* effModel, Double_t coeff) { const LauDaughters* otherDaughters = effModel->getDaughters(); if( otherDaughters->getTypeDaug1()!=daughters_->getTypeDaug1() || otherDaughters->getTypeDaug2()!=daughters_->getTypeDaug2() || otherDaughters->getTypeDaug3()!=daughters_->getTypeDaug3() || otherDaughters->getTypeParent()!=daughters_->getTypeParent() ) { std::cerr << "ERROR in LauWeightedSumEffModel::addEffModel : daughters of provided efficiency model do not match those expected." << std::endl; gSystem->Exit(EXIT_FAILURE); } effModel_.push_back(effModel); coeff_.push_back(coeff); if ( effModel->fluctuateEffHisto() ) { fluctuateEffHisto_ = kTRUE; } } Double_t LauWeightedSumEffModel::calcEfficiency( const LauKinematics* kinematics ) const { // Routine to calculate the efficiency for the given event/point in // the Dalitz plot. This routine uses the models set by the // addEffModel() function. Double_t eff(0.0); std::vector::const_iterator it = effModel_.begin(); std::vector::const_iterator end = effModel_.end(); std::vector::const_iterator coeffIt = coeff_.begin(); for( ; it!=end; ++it) { eff += (*coeffIt)*(*it)->calcEfficiency( kinematics ); ++coeffIt; } // Check that the efficiency is in the allowed range (0-1) // Out of range efficiencies could be caused by incorrect coefficients. if ( eff < 0.0 ) { if(!lowBinWarningIssued_) { std::cerr << "WARNING in LauWeightedSumEffModel::calcEfficiency : Efficiency " << eff << " is less than 0 - setting to 0. You may want to check your coefficients!" << std::endl << " : Further warnings will be suppressed." << std::endl; lowBinWarningIssued_=kTRUE; } eff = 0.0; } else if ( eff > 1.0 ) { if(!highBinWarningIssued_) { std::cerr << "WARNING in LauWeightedSumEffModel::calcEfficiency : Efficiency " << eff << " is greater than 1 - setting to 1. You may want to check your coefficients!" << std::endl << " : Further warnings will be suppressed." << std::endl; highBinWarningIssued_=kTRUE; } eff = 1.0; } return eff; } Bool_t LauWeightedSumEffModel::passVeto( const LauKinematics* kinematics ) const { std::vector::const_iterator it = effModel_.begin(); std::vector::const_iterator end = effModel_.end(); for( ; it!=end; ++it) { if(!(*it)->passVeto( kinematics )) return kFALSE; } return kTRUE; }