diff --git a/inc/Lau1DCubicSpline.hh b/inc/Lau1DCubicSpline.hh index 374411a..6f73b51 100644 --- a/inc/Lau1DCubicSpline.hh +++ b/inc/Lau1DCubicSpline.hh @@ -1,313 +1,313 @@ /* 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 #include #include #include "Rtypes.h" #include "TF1.h" #include "TFitResultPtr.h" #include "LauPrint.hh" class TH1; class LauAbsRValue; class LauParameter; class Lau1DCubicSpline final { public: //! Define the allowed interpolation types enum class SplineType { 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 class BoundaryType { 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] type the type of spline (Standard, Akima, Linear) \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, const SplineType type = SplineType::StandardSpline, const BoundaryType leftBound = BoundaryType::NotAKnot, const BoundaryType rightBound = BoundaryType::NotAKnot, const Double_t dydx0 = 0.0, const Double_t dydxn = 0.0); //! Evaluate the function at given point /*! \param [in] x the x-coordinate \return the value of the spline at x */ Double_t evaluate(const 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 y-values of the knots /*! \param [in] ys the y-values of the knots */ void updateYValues(const std::vector& ys); //! 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(const SplineType 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(const BoundaryType leftBound, const BoundaryType rightBound, const Double_t dydx0 = 0.0, const Double_t dydxn = 0.0); //! Get the number of knots std::size_t getnKnots() const {return nKnots_;} //! Get y values const std::vector& getYValues() const {return y_;} //! Get x values const std::vector& getXValues() const {return x_;} //! Get the coefficients of a given spline segment in the form a + bx + cx^2 + dx^3 /*! \param [in] segIndex refers to the index of the knot at the left end of the segment (segIndex = 0 gets the coefficients of the the segment between x_0 and x_1) \param [in] normalise if true, the coefficients returned will be normalised by the integral of the complete spline (defaults to false) \return coefficients {a, b, c, d} */ std::array getCoefficients(const std::size_t segIndex, const bool normalise = false) const; //! Get the integral over all the spline segments Double_t integral() const; //! Make a TF1 showing the spline with its current knot values /*! \param [in] normalise whether or not you want the spline normalised \return 1D function object */ TF1* makeTF1(const bool normalise = false) const; //! Fit the the normalisation of the spline to a TH1 /*! \param [in] hist the histogram to be fitted \param [in] printLevel the level of printout desired from fit \return a TF1 fit to the histogram */ TF1* normaliseToTH1(TH1* hist, const LauOutputLevel printLevel = LauOutputLevel::Standard) const; //! Fit the spline to a TH1 /*! \param [in] hist the histogram to be fitted \param [in] printLevel the level of printout desired from fit \param [in] doWL If true do a weighted likelihood fit, else chi2 \param [in] fixedParams Provide a map of knots to be fixed and to what values \return a shared-ownership smart pointer to the fit results */ TFitResultPtr fitToTH1(TH1* hist, const LauOutputLevel printLevel = LauOutputLevel::Standard, const bool doWL = false, std::map fixedParams = {}); //! Write the spline to a json file /*! \param [in] fileName the name of the file to which the JSON should be written \param [in] splineName the (optional) name of the entry in the JSON to which the spline should be written \param [in] append if true, append the spline to the existing JSON within the file - if using this option it is then mandatory to provide splineName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4) */ void writeToJson(const TString& fileName, const TString& splineName = "", const bool append = false, const int indent = 4) const; //! Construct a new Lau1DCubicSpline object based on values read from a json file /*! \param [in] fileName the name of the file from which the JSON should be read \param [in] splineName the (optional) name of the entry in the JSON from which the spline should be read \return the newly constructed spline */ static std::unique_ptr readFromJson(const TString& fileName, const TString& splineName = ""); //! Find the maximum of the spline /*! \return the maximum of the spline */ Double_t findMaximum() const; private: //! Default constructor - only for use in readFromJson Lau1DCubicSpline() = default; //! 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 std::size_t nKnots_{0}; //! 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 SplineType type_{SplineType::StandardSpline}; //! The left-hand boundary condition on the spline BoundaryType leftBound_{BoundaryType::NotAKnot}; //! The right-hand boundary condition on the spline BoundaryType rightBound_{BoundaryType::NotAKnot}; //! The gradient at the left boundary for a clamped spline Double_t dydx0_{0.0}; //! The gradient at the right boundary for a clamped spline Double_t dydxn_{0.0}; // enable JSON serialisation of this class NLOHMANN_DEFINE_TYPE_INTRUSIVE(Lau1DCubicSpline, nKnots_, x_, y_, type_, leftBound_, rightBound_, dydx0_, dydxn_) ClassDef(Lau1DCubicSpline, 0) // Class for defining a 1D cubic spline }; //! \cond DOXYGEN_IGNORE // map Lau1DCubicSpline::SplineType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( Lau1DCubicSpline::SplineType, { {Lau1DCubicSpline::SplineType::StandardSpline, "StandardSpline"}, {Lau1DCubicSpline::SplineType::AkimaSpline, "AkimaSpline"}, {Lau1DCubicSpline::SplineType::LinearInterpolation, "LinearInterpolation"}, }) // map Lau1DCubicSpline::BoundaryType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( Lau1DCubicSpline::BoundaryType, { {Lau1DCubicSpline::BoundaryType::Clamped, "Clamped"}, {Lau1DCubicSpline::BoundaryType::Natural, "Natural"}, {Lau1DCubicSpline::BoundaryType::NotAKnot, "NotAKnot"}, }) std::ostream& operator<<(std::ostream& out, const Lau1DCubicSpline::SplineType type); std::ostream& operator<<(std::ostream& out, const Lau1DCubicSpline::BoundaryType type); -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauAbsCoeffSet.hh b/inc/LauAbsCoeffSet.hh index 7c661a4..f68a109 100644 --- a/inc/LauAbsCoeffSet.hh +++ b/inc/LauAbsCoeffSet.hh @@ -1,542 +1,542 @@ /* 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. */ #ifndef LAU_ABS_COEFF_SET #define LAU_ABS_COEFF_SET #include "LauJsonTools.hh" #include "TString.h" #include #include #include #include #include class TRandom; class LauComplex; class LauParameter; /*! \brief Types of coefficient sets The different forms that are implemented for the complex coefficients. Each form is represented by a class that inherits from LauAbsCoeffSet. The corresponding class is named in a simlar manner, replacing "Abs" with the enum label. */ enum class LauCoeffType { MagPhase, /*!< \see LauMagPhaseCoeffSet */ RealImag, /*!< \see LauRealImagCoeffSet */ BelleCP, /*!< \see LauBelleCPCoeffSet */ CartesianCP, /*!< \see LauCartesianCPCoeffSet */ CartesianGammaCP, /*!< \see LauCartesianGammaCPCoeffSet */ CleoCP, /*!< \see LauCleoCPCoeffSet */ MagPhaseCP, /*!< \see LauMagPhaseCPCoeffSet */ NSCCartesianCP, /*!< \see LauNSCCartesianCPCoeffSet */ PolarGammaCP, /*!< \see LauPolarGammaCPCoeffSet */ RealImagCP, /*!< \see LauRealImagCPCoeffSet */ RealImagGammaCP /*!< \see LauRealImagGammaCPCoeffSet */ }; //! Output stream operator std::ostream& operator<<( std::ostream& os, const LauCoeffType type ); /*! \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. */ class LauAbsCoeffSet { public: //! Options for cloning operation enum class 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 */ }; //! Construct a collection of coefficient objects based on values read from a JSON file /*! \param [in] fileName the name of the file from which the JSON should be read \param [in] elementName the optional name of the JSON element that contains the coefficient definitions (defaults to using the root record) \return the collection of newly constructed coefficients */ static std::vector> readFromJson( const TString& fileName, const TString& elementName = "" ); //! Write a collection of coefficient objects to a JSON file /*! \tparam Collection the type of the collection, which should contain either smart or raw pointers to LauAbsCoeffSet or derived types \param [in] coeffs the collection of coefficients to be written out \param [in] fileName the name of the file to which the JSON should be written \param [in] elementName the (optional) name of the JSON element to which the coefficients should be written \param [in] append if true, append the spline to the existing JSON within the file - if using this option it is then mandatory to provide elementName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4) */ template static void writeToJson( const Collection& coeffs, const TString& fileName, const TString& elementName = "", const bool append = false, const int indent = 4 ); //! Destructor virtual ~LauAbsCoeffSet() = default; //! Determine the type of the coefficient /*! \return the type of the coefficient */ virtual LauCoeffType type() const = 0; //! 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; //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient */ virtual std::vector getParameters() const = 0; //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names */ virtual std::vector getParNames() const = 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, const Bool_t init ) = 0; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ virtual LauParameter acp() = 0; //! Write state to a JSON record /*! \param [in,out] j the JSON record to write to */ virtual void serialiseToJson( nlohmann::json& j ) const; //! Apply the blinding information in the JSON record to all parameters /*! \param [in] j the JSON record to read from */ virtual void applyBlinding( const nlohmann::json& j ); //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } //! 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 */ 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 */ 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 */ 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 */ void baseName(const TString& theBasename) {basename_ = theBasename;} //! Retrieve the index number of the coefficient set /*! \return the index number of the coefficient set */ UInt_t index() const {return index_;} //! Set the index number of the coefficient set /*! \param [in] newIndex the new index */ void index(const UInt_t newIndex); //! Is this coefficient set a clone of another? /*! \return whether this coefficient set is a clone */ Bool_t clone() const {return parent_ != nullptr;} //! From which coefficient set was this one cloned? /*! \return the parent of this coefficient set, or nullptr if this isn't a clone */ const LauAbsCoeffSet* parent() const {return parent_;} //! What clone option was this cloned with? /*! \return the clone option with which this was cloned */ CloneOption cloneOption() const {return cloneOption_;} //! What constant factor was this cloned with? /*! \return the constant factor with which this was cloned */ Double_t constFactor() const {return constFactor_;} //! 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 */ void setParameterValue(const TString& parName, const Double_t value, const 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 */ void setParameterError(const TString& parName, const Double_t error); //! Set the named parameter to be fixed in the fit /*! \param [in] parName the name of the parameter to adjust */ void fixParameter(const TString& parName); //! Set the named parameter to float in the fit /*! \param [in] parName the name of the parameter to adjust */ 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 */ 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 */ 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 */ 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(const Double_t minMag, const 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(const Double_t minPhase, const 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(const Double_t minPar, const 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(const Double_t minPar, const 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 \param [in] parent the coefficient set from which this one has been cloned (or nullptr if we are not a clone) \param [in] cloneOption the cloning option that was used (if applicable) \param [in] constFactor the constant factor that was used when cloning (if applicable) */ LauAbsCoeffSet(const TString& theName, const TString& theBaseName = "A", const LauAbsCoeffSet* parent = nullptr, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0); //! Copy constructor /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet(const LauAbsCoeffSet& rhs) = default; //! Move constructor /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet(LauAbsCoeffSet&& rhs) = default; //! Copy assignment operator /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet& operator=(const LauAbsCoeffSet& rhs) = delete; //! Move assignment operator /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet& operator=(LauAbsCoeffSet&& rhs) = delete; //! 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 the parameter to be renamed \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_; private: //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ virtual LauAbsCoeffSet* createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const = 0; //! 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_{0}; //! The parent of this coefficient set, if this is a clone const LauAbsCoeffSet* const parent_{nullptr}; //! The clone option used, if applicable const CloneOption cloneOption_{CloneOption::All}; //! The constant factor used, if applicable const Double_t constFactor_{1.0}; ClassDef(LauAbsCoeffSet, 0) }; template void LauAbsCoeffSet::writeToJson( const Collection& coeffs, const TString& fileName, const TString& elementName, const bool append, const int indent ) { using nlohmann::json; json j; j["nCoeffs"] = coeffs.size(); j["coeffs"] = json::array(); for ( auto& coeffset : coeffs ) { j["coeffs"].push_back( *coeffset ); } const bool writeOK { LauJsonTools::writeJsonFile( j, fileName.Data(), elementName.Data(), append, indent ) }; if ( ! writeOK ) { std::cerr << "ERROR in LauAbsCoeffSet::writeToJson : could not successfully write to file \"" << fileName << std::endl; } } //! \cond DOXYGEN_IGNORE // map LauCoeffType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauCoeffType, { {LauCoeffType::MagPhase, "MagPhase"}, {LauCoeffType::RealImag, "RealImag"}, {LauCoeffType::BelleCP, "BelleCP"}, {LauCoeffType::CartesianCP, "CartesianCP"}, {LauCoeffType::CartesianGammaCP, "CartesianGammaCP"}, {LauCoeffType::CleoCP, "CleoCP"}, {LauCoeffType::MagPhaseCP, "MagPhaseCP"}, {LauCoeffType::NSCCartesianCP, "NSCCartesianCP"}, {LauCoeffType::PolarGammaCP, "PolarGammaCP"}, {LauCoeffType::RealImagCP, "RealImagCP"}, {LauCoeffType::RealImagGammaCP, "RealImagGammaCP"}, }) // map Lau1DCubicSpline::BoundaryType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauAbsCoeffSet::CloneOption, { {LauAbsCoeffSet::CloneOption::All, "All"}, {LauAbsCoeffSet::CloneOption::TiePhase, "TiePhase"}, {LauAbsCoeffSet::CloneOption::TieMagnitude, "TieMagnitude"}, {LauAbsCoeffSet::CloneOption::TieRealPart, "TieRealPart"}, {LauAbsCoeffSet::CloneOption::TieImagPart, "TieImagPart"}, {LauAbsCoeffSet::CloneOption::TieCPPars, "TieCPPars"}, }) // exceptions to be thrown in case of JSON type issues class LauWrongCoeffType : public std::runtime_error { public: LauWrongCoeffType(const std::string& what) : std::runtime_error(what) {} }; class LauClonedCoeff : public std::runtime_error { public: LauClonedCoeff(const std::string& what) : std::runtime_error(what) {} }; namespace nlohmann { template <> struct adl_serializer { static void to_json(json& j, const LauAbsCoeffSet& t) { t.serialiseToJson(j); } }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauAbsRValue.hh b/inc/LauAbsRValue.hh index d8c21a5..8725c1f 100644 --- a/inc/LauAbsRValue.hh +++ b/inc/LauAbsRValue.hh @@ -1,215 +1,215 @@ /* 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 LauAbsRValue.hh \brief File containing declaration of LauAbsRValue class. */ /*! \class LauAbsRValue \brief Pure abstract base class for defining a parameter containing an R value Pure abstract base class for defining a parameter containing an R value, either a LauParameter or a LauFormulaPar */ #ifndef LAU_ABSRVALUE #define LAU_ABSRVALUE #include "LauJsonTools.hh" #include "Rtypes.h" #include "TString.h" #include #include #include class LauParameter; class LauAbsRValue { public: //! Constructor LauAbsRValue() = default; //! Destructor virtual ~LauAbsRValue() = default; //! Copy constructor LauAbsRValue(const LauAbsRValue& rhs) = default; //! Copy assignment operator LauAbsRValue& operator=(const LauAbsRValue& rhs) = default; //! Move constructor LauAbsRValue(LauAbsRValue&& rhs) = default; //! Move assignment operator LauAbsRValue& operator=(LauAbsRValue&& rhs) = default; //! Return the name of the parameter /*! \return the name of the parameter */ virtual const TString& name() const =0; //! Set the parameter name /*! \param [in] newName the name of the parameter */ virtual void name(const TString& newName) =0; //! Return the value of the parameter /*! \return the value of the parameter */ virtual Double_t value() const =0; //! The unblinded value of the parameter /*! \return the unblinded value of the parameter */ virtual Double_t unblindValue() const =0; //! The value generated for the parameter /*! \return the value generated for the parameter */ virtual Double_t genValue() const =0; //! The initial value of the parameter /*! \return the initial value of the parameter given to the fitter */ virtual Double_t initValue() const =0; //! Check whether a Gaussian constraints is applied /*! \return the boolean flag true/false whether a Gaussian constraint is applied */ virtual Bool_t gaussConstraint() const =0; //! The mean of the Gaussian constraint /*! \return the mean value of the Gaussian constraint */ virtual Double_t constraintMean() const =0; //! The width of the Gaussian constraint /*! \return the width of the Gaussian constraint */ virtual Double_t constraintWidth() const =0; //! Return the list of LauParameters on which the LauAbsRValue depends /*! \return the list of LauParameters */ virtual std::vector getPars() =0; //! Is the parameter also an L value or not /*! \return whether the parameter is also an L value */ virtual Bool_t isLValue() const =0; //! Check is the parameter is fixed or floated /*! \return the boolean flag whether the parameter is fixed */ virtual Bool_t fixed() const =0; //! The blinding state /*! \return the blinding state: kTRUE means that it is blinded, kFALSE that it is not blinded */ virtual Bool_t blind() const =0; //! Write state to a JSON record /*! \param [in,out] j the JSON record to write to */ virtual void serialiseToJson( nlohmann::json& j ) const; //! Construct a collection of parameter objects based on values read from a JSON array /*! \param [in] array the JSON array \return the collection of newly constructed parameters */ static std::vector> readFromJson( const nlohmann::json& array ); //! Construct a collection of parameter objects based on values read from a JSON file /*! \param [in] fileName the name of the file from which the JSON should be read \param [in] elementName the optional name of the JSON element that contains the array of parameter definitions (defaults to using the root record) \return the collection of newly constructed parameters */ static std::vector> readFromJson( const TString& fileName, const TString& elementName = "" ); //! Write a collection of parameter objects to a JSON file /*! \param [in] params the collection of parameters to be written out (the collection should contain either smart or raw pointers to LauAbsRValue or derived types) \param [in] fileName the name of the file to which the JSON should be written \param [in] elementName the (optional) name of the JSON element to which the parameters should be written \param [in] append if true, append the spline to the existing JSON within the file - if using this option it is then mandatory to provide elementName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4) */ template static void writeToJson( const Collection& params, const TString& fileName, const TString& elementName = "", const bool append = false, const int indent = 4 ); private: ClassDef(LauAbsRValue,1) // Abstract base class for R parameters }; template void LauAbsRValue::writeToJson( const Collection& params, const TString& fileName, const TString& elementName, const bool append, const int indent ) { using nlohmann::json; json j = json::array(); for ( auto& param : params ) { j.push_back( *param ); } const bool writeOK { LauJsonTools::writeJsonFile( j, fileName.Data(), elementName.Data(), append, indent ) }; if ( ! writeOK ) { std::cerr << "ERROR in LauAbsRValue::writeToJson : could not successfully write to file \"" << fileName << std::endl; } } //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static void to_json(json& j, const LauAbsRValue& t) { t.serialiseToJson(j); } }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauAbsResonance.hh b/inc/LauAbsResonance.hh index 05c8f7e..f0931a9 100644 --- a/inc/LauAbsResonance.hh +++ b/inc/LauAbsResonance.hh @@ -1,650 +1,650 @@ /* 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 "LauBlattWeisskopfFactor.hh" #include "LauComplex.hh" #include "LauParameter.hh" #include "TString.h" #include class LauDaughters; class LauKinematics; class LauResonanceInfo; class LauAbsResonance { public: //! Define the allowed resonance types enum class ResonanceModel { 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) */ Bugg, /*!< 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_Pole, /*!< description using K-matrix and P-vector */ KMatrix_SVP, /*!< 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 */ LHCbNR, /*!< an empirical exponential nonresonant amplitude with phase */ 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 class SpinType { 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, bachelor momentum in parent rest frame */ Covariant_P, /*!< Covariant tensor formalism, bachelor momentum in resonance rest frame */ 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(ResonanceModel 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 ResonanceModel getResonanceModel() const = 0; //! Get the spin type /*! \return the spin formalism */ SpinType 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_!=nullptr) ? resMass_->unblindValue() : -1.0;} //! Get the width of the resonance /*! \return the resonance width */ Double_t getWidth() const {return (resWidth_!=nullptr) ? 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_!=nullptr) { resMass_->fixed(parFixed); } } //! Fix or release the resonance width /*! \param [in] parFixed new status of width */ void fixWidth(const Bool_t parFixed) { if (resWidth_!=nullptr) { 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_!=nullptr) ? 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_!=nullptr) ? resWidth_->fixed() : kTRUE; } //! Set the spin formalism to be used /*! \param [in] spinType the spin formalism */ void setSpinType(const SpinType 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; //! Access the resonance info object const LauResonanceInfo* getResInfo() const {return resInfo_;} //! Get the centrifugal barrier for the parent decay const LauBlattWeisskopfFactor* getParBWFactor() const {return parBWFactor_;} //! Get the centrifugal barrier for the resonance decay const LauBlattWeisskopfFactor* getResBWFactor() const {return resBWFactor_;} //! Create a JSON object containing the current settings virtual nlohmann::json writeSettingsToJson() 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_;} //! Get the centrifugal barrier for the resonance decay LauBlattWeisskopfFactor* getResBWFactor() {return resBWFactor_;} //! Access the resonance info object LauResonanceInfo* getResInfo() {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_; } //! Retrieve all resonance parameters (excluding mass and width), so that they can be saved to JSON virtual std::vector getResonanceParameters() const { return {}; } 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_{nullptr}; //! 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_{nullptr}; //! Resonance width LauParameter* resWidth_{nullptr}; //! 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_{nullptr}; //! Blatt Weisskopf barrier for resonance decay LauBlattWeisskopfFactor* resBWFactor_{nullptr}; //! Spin formalism SpinType spinType_{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 }; //! \cond DOXYGEN_IGNORE // map LauAbsResonance::ResonanceModel values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauAbsResonance::ResonanceModel, { {LauAbsResonance::ResonanceModel::BW, "BW"}, {LauAbsResonance::ResonanceModel::RelBW, "RelBW"}, {LauAbsResonance::ResonanceModel::GS, "GS"}, {LauAbsResonance::ResonanceModel::Flatte, "Flatte"}, {LauAbsResonance::ResonanceModel::Sigma, "Sigma"}, {LauAbsResonance::ResonanceModel::Bugg, "Bugg"}, {LauAbsResonance::ResonanceModel::Kappa, "Kappa"}, {LauAbsResonance::ResonanceModel::Dabba, "Dabba"}, {LauAbsResonance::ResonanceModel::LASS, "LASS"}, {LauAbsResonance::ResonanceModel::LASS_BW, "LASS_BW"}, {LauAbsResonance::ResonanceModel::LASS_NR, "LASS_NR"}, {LauAbsResonance::ResonanceModel::EFKLLM, "EFKLLM"}, {LauAbsResonance::ResonanceModel::KMatrix_Pole, "KMatrix_Pole"}, {LauAbsResonance::ResonanceModel::KMatrix_SVP, "KMatrix_SVP"}, {LauAbsResonance::ResonanceModel::FlatNR, "FlatNR"}, {LauAbsResonance::ResonanceModel::NRModel, "NRModel"}, {LauAbsResonance::ResonanceModel::BelleNR, "BelleNR"}, {LauAbsResonance::ResonanceModel::PowerLawNR, "PowerLawNR"}, {LauAbsResonance::ResonanceModel::BelleSymNR, "BelleSymNR"}, {LauAbsResonance::ResonanceModel::BelleSymNRNoInter, "BelleSymNRNoInter"}, {LauAbsResonance::ResonanceModel::LHCbNR, "LHCbNR"}, {LauAbsResonance::ResonanceModel::TaylorNR, "TaylorNR"}, {LauAbsResonance::ResonanceModel::PolNR, "PolNR"}, {LauAbsResonance::ResonanceModel::Pole, "Pole"}, {LauAbsResonance::ResonanceModel::PolarFFNR, "PolarFFNR"}, {LauAbsResonance::ResonanceModel::PolarFFSymNR, "PolarFFSymNR"}, {LauAbsResonance::ResonanceModel::PolarFFSymNRNoInter, "PolarFFSymNRNoInter"}, {LauAbsResonance::ResonanceModel::Rescattering, "Rescattering"}, {LauAbsResonance::ResonanceModel::Rescattering2, "Rescattering2"}, {LauAbsResonance::ResonanceModel::RescatteringNoInter, "RescatteringNoInter"}, {LauAbsResonance::ResonanceModel::MIPW_MagPhase, "MIPW_MagPhase"}, {LauAbsResonance::ResonanceModel::MIPW_RealImag, "MIPW_RealImag"}, {LauAbsResonance::ResonanceModel::GaussIncoh, "GaussIncoh"}, {LauAbsResonance::ResonanceModel::RhoOmegaMix_GS, "RhoOmegaMix_GS"}, {LauAbsResonance::ResonanceModel::RhoOmegaMix_RBW, "RhoOmegaMix_RBW"}, {LauAbsResonance::ResonanceModel::RhoOmegaMix_GS_1, "RhoOmegaMix_GS_1"}, {LauAbsResonance::ResonanceModel::RhoOmegaMix_RBW_1, "RhoOmegaMix_RBW_1"}, }) // map LauAbsResonance::SpinType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauAbsResonance::SpinType, { {LauAbsResonance::SpinType::Zemach_P, "Zemach_P"}, {LauAbsResonance::SpinType::Zemach_Pstar, "Zemach_Pstar"}, {LauAbsResonance::SpinType::Covariant, "Covariant"}, {LauAbsResonance::SpinType::Covariant_P, "Covariant_P"}, {LauAbsResonance::SpinType::Legendre, "Legendre"}, }) -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauBelleCPCoeffSet.hh b/inc/LauBelleCPCoeffSet.hh index b8fb217..946f3e9 100644 --- a/inc/LauBelleCPCoeffSet.hh +++ b/inc/LauBelleCPCoeffSet.hh @@ -1,246 +1,246 @@ /* 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. */ #ifndef LAU_BELLECP_COEFF_SET #define LAU_BELLECP_COEFF_SET #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" #include "Rtypes.h" #include #include #include /*! \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] */ 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, const Double_t a, const Double_t delta, const Double_t b, const Double_t phi, const Bool_t aFixed, const Bool_t deltaFixed, const Bool_t bFixed, const Bool_t phiFixed, const Bool_t bSecondStage = kFALSE, const Bool_t phiSecondStage = kFALSE); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet(LauBelleCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet& operator=(LauBelleCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::BelleCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ A, Delta, B, Phi ] */ std::vector getParameters() override { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ A, Delta, B, Phi ] */ std::vector getParameters() const override { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ A, Delta, B, Phi ] */ std::vector getParNames() const override { return { "A", "Delta", "B", "Phi" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauBelleCPCoeffSet(const LauBelleCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet(const LauBelleCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet& operator=(const LauBelleCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauBelleCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude a std::unique_ptr a_; //! The magnitude b std::unique_ptr b_; //! The strong phase std::unique_ptr delta_; //! The weak phase std::unique_ptr phi_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauBelleCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauBelleCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauBlattWeisskopfFactor.hh b/inc/LauBlattWeisskopfFactor.hh index 84f2d78..4c516eb 100644 --- a/inc/LauBlattWeisskopfFactor.hh +++ b/inc/LauBlattWeisskopfFactor.hh @@ -1,236 +1,236 @@ /* 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" #include #include #include class LauParameter; class LauResonanceInfo; class LauBlattWeisskopfFactor final { public: //! Define the allowed types of barrier factors enum class 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 class 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 class Category { 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 Category category ); //! Constructor LauBlattWeisskopfFactor( const LauResonanceInfo& resInfo, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const Category category ); //! Constructor LauBlattWeisskopfFactor( const UInt_t spin, const Double_t resRadius, const BarrierType barrierType, const RestFrame restFrame, const Category category ); //! Copy constructor (deleted) LauBlattWeisskopfFactor( const LauBlattWeisskopfFactor& other ) = delete; //! Move constructor (deleted) LauBlattWeisskopfFactor( LauBlattWeisskopfFactor&& other ) = delete; //! Copy assignment operator (deleted) LauBlattWeisskopfFactor& operator=( const LauBlattWeisskopfFactor& other ) = delete; //! Move assignment operator (deleted) LauBlattWeisskopfFactor& operator=( LauBlattWeisskopfFactor&& other ) = delete; //! Destructor ~LauBlattWeisskopfFactor() noexcept; //! 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 ); //! Check whether is a clone or not Bool_t clone() const { return parent_ != nullptr; } //! Get the parent factor const LauBlattWeisskopfFactor* getParent() const { return parent_; } //! Get the parent factor LauBlattWeisskopfFactor* getParent() { return parent_; } //! Retrieve the radius parameter const LauParameter* getRadiusParameter() const { return radius_.get(); } //! Retrieve the radius parameter LauParameter* getRadiusParameter() { return radius_.get(); } //! 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 (with options) LauBlattWeisskopfFactor( LauBlattWeisskopfFactor& other, const UInt_t newSpin, const BarrierType newBarrierType ); //! Mark this as a clone of the given parent /*! \param theparent the parent parameter */ void setParent(LauBlattWeisskopfFactor* theparent) { parent_ = theparent; } //! Method to remove a clone from the list of clones /*! This is used in the destructor to allow a clone to inform its parent it is no longer around \param [in] clone the clone to be removed from the list */ void removeFromCloneList(LauBlattWeisskopfFactor* clone) { auto iter = clones_.find( clone ); if ( iter != clones_.end() ) { clones_.erase( iter ); } } //! Set the name of the radius parameter TString setRadiusName( const LauResonanceInfo& resInfo, const Category category ); //! Set the name of the radius parameter TString setRadiusName( const Category category ); //! Set the name of the radius parameter TString setRadiusName( const TString& categoryName ); //! The parent factor (nullptr if this is not a clone) LauBlattWeisskopfFactor* parent_{nullptr}; //! The clones of this factor std::set clones_; //! Resonance spin const UInt_t spin_; //! Radius parameter std::unique_ptr radius_; //! Barrier type const BarrierType barrierType_; //! Rest frame const RestFrame restFrame_; ClassDef(LauBlattWeisskopfFactor, 0) }; //! \cond DOXYGEN_IGNORE // map LauBlattWeisskopfFactor::BarrierType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauBlattWeisskopfFactor::BarrierType, { {LauBlattWeisskopfFactor::BarrierType::BWPrimeBarrier, "BWPrimeBarrier"}, {LauBlattWeisskopfFactor::BarrierType::BWBarrier, "BWBarrier"}, {LauBlattWeisskopfFactor::BarrierType::ExpBarrier, "ExpBarrier"}, }) // map LauBlattWeisskopfFactor::RestFrame values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauBlattWeisskopfFactor::RestFrame, { {LauBlattWeisskopfFactor::RestFrame::ResonanceFrame, "ResonanceFrame"}, {LauBlattWeisskopfFactor::RestFrame::Covariant, "Covariant"}, {LauBlattWeisskopfFactor::RestFrame::ParentFrame, "ParentFrame"}, }) // map LauBlattWeisskopfFactor::Category values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauBlattWeisskopfFactor::Category, { {LauBlattWeisskopfFactor::Category::Default, "Default"}, {LauBlattWeisskopfFactor::Category::Parent, "Parent"}, {LauBlattWeisskopfFactor::Category::Indep, "Indep"}, {LauBlattWeisskopfFactor::Category::Light, "Light"}, {LauBlattWeisskopfFactor::Category::Kstar, "Kstar"}, {LauBlattWeisskopfFactor::Category::Charm, "Charm"}, {LauBlattWeisskopfFactor::Category::StrangeCharm, "StrangeCharm"}, {LauBlattWeisskopfFactor::Category::Charmonium, "Charmonium"}, {LauBlattWeisskopfFactor::Category::Beauty, "Beauty"}, {LauBlattWeisskopfFactor::Category::StrangeBeauty, "StrangeBeauty"}, {LauBlattWeisskopfFactor::Category::CharmBeauty, "CharmBeauty"}, {LauBlattWeisskopfFactor::Category::Custom1, "Custom1"}, {LauBlattWeisskopfFactor::Category::Custom2, "Custom2"}, {LauBlattWeisskopfFactor::Category::Custom3, "Custom3"}, {LauBlattWeisskopfFactor::Category::Custom4, "Custom4"}, }) -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauCartesianCPCoeffSet.hh b/inc/LauCartesianCPCoeffSet.hh index 9f0b16a..ff96eb4 100644 --- a/inc/LauCartesianCPCoeffSet.hh +++ b/inc/LauCartesianCPCoeffSet.hh @@ -1,242 +1,242 @@ /* 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 #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, const Double_t x, const Double_t y, const Double_t deltaX, const Double_t deltaY, const Bool_t xFixed, const Bool_t yFixed, const Bool_t deltaXFixed, const Bool_t deltaYFixed, const Bool_t deltaXSecondStage = kFALSE, const Bool_t deltaYSecondStage = kFALSE); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet(LauCartesianCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet& operator=(LauCartesianCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::CartesianCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, DeltaX, DeltaY ] */ std::vector getParameters() override { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, DeltaX, DeltaY ] */ std::vector getParameters() const override { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, DeltaX, DeltaY ] */ std::vector getParNames() const override { return { "X", "Y", "DeltaX", "DeltaY" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauCartesianCPCoeffSet(const LauCartesianCPCoeffSet& rhs, CloneOption cloneOption = CloneOption::All, Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet(const LauCartesianCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet& operator=(const LauCartesianCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauCartesianCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The average real part std::unique_ptr x_; //! The average imaginary part std::unique_ptr y_; //! The asymmetric real part std::unique_ptr deltaX_; //! The asymmetric imaginary part std::unique_ptr deltaY_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauCartesianCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauCartesianCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauCartesianGammaCPCoeffSet.hh b/inc/LauCartesianGammaCPCoeffSet.hh index 1b00bbc..b00d9ce 100644 --- a/inc/LauCartesianGammaCPCoeffSet.hh +++ b/inc/LauCartesianGammaCPCoeffSet.hh @@ -1,258 +1,258 @@ /* 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 #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); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet(LauCartesianGammaCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet& operator=(LauCartesianGammaCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::CartesianGammaCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, XCP, YCP, DeltaXCP, DeltaYCP ] */ std::vector getParameters() override { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), deltaXCP_.get(), deltaYCP_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, XCP, YCP, DeltaXCP, DeltaYCP ] */ std::vector getParameters() const override { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), deltaXCP_.get(), deltaYCP_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, XCP, YCP, DeltaXCP, DeltaYCP ] */ std::vector getParNames() const override { return { "X", "Y", "XCP", "YCP", "DeltaXCP", "DeltaYCP" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauCartesianGammaCPCoeffSet(const LauCartesianGammaCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet(const LauCartesianGammaCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet& operator=(const LauCartesianGammaCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauCartesianGammaCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The nonCP real part std::unique_ptr x_; //! The nonCP imaginary part std::unique_ptr y_; //! The average CP real part std::unique_ptr xCP_; //! The average CP imaginary part std::unique_ptr yCP_; //! The asymmetric CP real part std::unique_ptr deltaXCP_; //! The asymmetric CP imaginary part std::unique_ptr 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_; ClassDefOverride(LauCartesianGammaCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauCartesianGammaCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauCleoCPCoeffSet.hh b/inc/LauCleoCPCoeffSet.hh index 24fd5d5..058b004 100644 --- a/inc/LauCleoCPCoeffSet.hh +++ b/inc/LauCleoCPCoeffSet.hh @@ -1,246 +1,246 @@ /* 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 #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, const Double_t a, const Double_t delta, const Double_t b, const Double_t phi, const Bool_t aFixed, const Bool_t deltaFixed, const Bool_t bFixed, const Bool_t phiFixed, const Bool_t bSecondStage = kFALSE, const Bool_t phiSecondStage = kFALSE); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet(LauCleoCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet& operator=(LauCleoCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::CleoCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ A, Delta, B, Phi ] */ std::vector getParameters() override { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ A, Delta, B, Phi ] */ std::vector getParameters() const override { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ A, Delta, B, Phi ] */ std::vector getParNames() const override { return { "A", "Delta", "B", "Phi" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauCleoCPCoeffSet(const LauCleoCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet(const LauCleoCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet& operator=(const LauCleoCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauCleoCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude a std::unique_ptr a_; //! The magnitude b std::unique_ptr b_; //! The strong phase std::unique_ptr delta_; //! The weak phase std::unique_ptr phi_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauCleoCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauCleoCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauDecayTime.hh b/inc/LauDecayTime.hh index 7fe4ac4..e789397 100644 --- a/inc/LauDecayTime.hh +++ b/inc/LauDecayTime.hh @@ -1,88 +1,88 @@ /* Copyright 2021 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDecayTime.hh \brief File containing declaration of utilities for decay time modelling */ #ifndef LAU_DECAYTIME_UTILS #define LAU_DECAYTIME_UTILS #include /*! \namespace LauDecayTime \brief Namespace to contain various definitions that are common to the description of the decay time dependence of the amplitudes */ namespace LauDecayTime { // TODO - can we think of better names? //! The functional form of the decay time PDF enum class FuncType { Hist, //< Hist PDF for fixed background Delta, //< Delta function - for prompt background Exp, //< Exponential function - for non-prompt background or charged B's DeltaExp, //< Delta + Exponential function - for background with prompt and non-prompt parts ExpTrig, //< Exponential function with Delta m driven mixing - for neutral B_d's ExpHypTrig //< Exponential function with both Delta m and Delta Gamma driven mixing - for neutral B_s's }; //! How is the decay time measured - absolute or difference? enum class TimeMeasurementMethod { DecayTime, //< Absolute measurement of decay time, e.g. LHCb scenario DecayTimeDiff //< Measurement of the difference of two decay times, e.g. BaBar/Belle(II) scenario }; //! How is the TD efficiency information going to be given? enum class EfficiencyMethod { Uniform, //< As a uniform distribution (constant) Binned, //< As a histogram (TH1D/TH1F) Spline //< As a cubic spline (or products thereof) }; //! \cond DOXYGEN_IGNORE // map FuncType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( FuncType, { {FuncType::Hist, "Hist"}, {FuncType::Delta, "Delta"}, {FuncType::Exp, "Exp"}, {FuncType::DeltaExp, "DeltaExp"}, {FuncType::ExpTrig, "ExpTrig"}, {FuncType::ExpHypTrig, "ExpHypTrig"}, }) // map TimeMeasurementMethod values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( TimeMeasurementMethod, { {TimeMeasurementMethod::DecayTime, "DecayTime"}, {TimeMeasurementMethod::DecayTimeDiff, "DecayTimeDiff"}, }) // map EfficiencyMethod values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( EfficiencyMethod, { {EfficiencyMethod::Uniform, "Uniform"}, {EfficiencyMethod::Binned, "Binned"}, {EfficiencyMethod::Spline, "Spline"}, }) - //! \endcond DOXYGEN_IGNORE + //! \endcond } #endif diff --git a/inc/LauDecayTimeResolution.hh b/inc/LauDecayTimeResolution.hh index ead1ff1..d102e53 100644 --- a/inc/LauDecayTimeResolution.hh +++ b/inc/LauDecayTimeResolution.hh @@ -1,327 +1,327 @@ /* Copyright 2021 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauDecayTimeResolution.hh \brief File containing declaration of LauDecayTimeResolution class. */ #ifndef LAU_DECAYTIME_RESOLUTION #define LAU_DECAYTIME_RESOLUTION #include "LauAbsRValue.hh" #include "LauJsonTools.hh" #include "Rtypes.h" #include "TString.h" #include #include #include #include #include /*! \class LauDecayTimeResolution \brief Class for defining the model for decay time resolution */ class LauDecayTimeResolution final { public: /*! \enum ScalingType \brief Define the types of per-event error scaling that can be performed */ enum class ScalingType { None, //!< No scaling is performed Global, //!< All means and widths are scaled PerGaussian, //!< Scaling is enabled/disabled for each Gaussian PerParameter //!< Scaling is enabled/disabled for individual parameters }; //! Constructor /*! \param nGauss the number of Gaussians in the resolution model \param resolutionParams the parameters of the resolution model \param scale if true all means and widths are scaled by per-event decay time error, if false none are scaled */ LauDecayTimeResolution( const std::size_t nGauss, std::vector> resolutionParams, const bool scale = false ); //! Constructor /*! \param nGauss the number of Gaussians in the resolution model \param resolutionParams the parameters of the resolution model \param scale for each Gaussian, if true its mean and width are both scaled by per-event decay time error, if false neither are scaled */ LauDecayTimeResolution( const std::size_t nGauss, std::vector> resolutionParams, const std::vector& scale ); //! Constructor /*! \param nGauss the number of Gaussians in the resolution model \param resolutionParams the parameters of the resolution model \param scaleMeans for each Gaussian, if true its mean is scaled by per-event decay time error, if false its mean is not scaled \param scaleWidths for each Gaussian, if true its width is scaled by per-event decay time error, if false its width is not scaled */ LauDecayTimeResolution( const std::size_t nGauss, std::vector> resolutionParams, const std::vector& scaleMeans, const std::vector& scaleWidths ); //! Retrieve the parameters of the resolution model so that they can be loaded into a fit /*! \return the parameters of the resolution model */ std::vector getParameters() { return params_; } //! Retrieve the number of Gaussians in the model /*! \return the number of Gaussians */ const std::size_t& nGauss() const { return nGauss_; } //! Retrieve the scaling type /*! \return the scaling type */ ScalingType getScalingType() const { return scalingType_; } //! Retrieve whether any of the parameters of the resolution function scaled by the per-event error /*! \return whether scaling or not */ bool scaleWithPerEventError() const { return scaleWithPerEventError_; } //! Retrieve whether the mean of each Gaussian is scaled by the per-event decay time error /*! \return the mean scaling flags */ const std::vector& scaleMeans() const { return scaleMeans_; } //! Retrieve whether the width of each Gaussian is scaled by the per-event decay time error /*! \return the width scaling flags */ const std::vector& scaleWidths() const { return scaleWidths_; } //! Retrieve the up-to-date values of the means /*! \return the mean values */ const std::vector& getMeanValues() const { return meanVals_; } //! Retrieve the up-to-date values of the widths /*! \return the width values */ const std::vector& getWidthValues() const { return widthVals_; } //! Retrieve the up-to-date values of the fractions /*! \return the fraction values */ const std::vector& getFractionValues() const { return fractionVals_; } //! Retrieve whether any of the parameter values have changed in the last fit iteration /*! \return the any param changed flag */ const bool& anythingChanged() const { return anythingChanged_; } //! Initialise the parameter cache /*! Must be called prior to starting fitting or generation */ void initialise(); //! Propagate any updates to parameters and recalculate information as neeeded /*! Should be called at each fit iteration */ void propagateParUpdates(); //! Construct a collection of resolution model objects based on values read from a JSON value /*! The JSON value should be an Object, which must contain the following elements: - "parameters", an Array, which contains an Object for each parameter of the models to be constructed - "signalModel", an Object, which contains: + "nGauss", a Number_Unsigned to specify the number of Gaussian functions in the model + "scalingType", a String to specify the scaling type (must match a state of ScalingType) + "parameters", an Array of Strings that specifies the parameters from the top-level "parameters" Array to be used to build the signal model - "backgroundModels", an Array, which contains Objects for each background component, each of which contain: + "name", a String specifying the background component name + "model", an Object to define the model (definition as per the "signalModel" entry above) \param [in] j the JSON value to deserialise \return the collection of newly constructed models */ static std::map> readFromJson( const nlohmann::json& j ); //! Construct a collection of resolution model objects based on values read from a JSON file /*! The JSON value structure is as defined in readFromJson(nlohmann::json) \param [in] fileName the name of the file from which the JSON should be read \param [in] elementName the optional name of the JSON element that contains the definitions (defaults to using the root record) \return the collection of newly constructed models */ static std::map> readFromJson( const TString& fileName, const TString& elementName = "" ); //! Write a collection of physics model objects to a JSON file /*! \tparam ResModelPtr a pointer-like type that points to LauDecayTimeResolution objects \param [in] models the collection of models to be written out \param [in] fileName the name of the file to which the JSON should be written \param [in] elementName the (optional) name of the JSON element to which the coefficients should be written \param [in] append if true, append the spline to the existing JSON within the file - if using this option it is then mandatory to provide elementName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4) */ template static void writeToJson( const std::map& models, const TString& fileName, const TString& elementName = "", const bool append = false, const int indent = 4 ); //! Retrieve the specified parameter /*! \param [in] parName the parameter to retrieve */ const LauAbsRValue* findParameter(const TString& parName) const; //! Retrieve the specified parameter /*! \param [in] parName the parameter to retrieve */ LauAbsRValue* findParameter(const TString& parName); private: //! Resize the internal vectors to match nGauss_ void resizeVectors(); //! Do an initial sanity check of our setup void checkSetup(); //! Update the cached parameter values void updateParameterCache(); //! Read the resolution model part of the JSON serialisation /*! \param [in] j the JSON value from which to read the model \param [in] parameters the collection of parameters, some of which should be used to construct the model \return the newly constructed signal model */ static std::unique_ptr readResolutionModelFromJson( const nlohmann::json& j, std::vector>& parameters ); //! Read the background models part of the JSON serialisation /*! \param [in] j the JSON value from which to read the model \param [in] parameters the collection of parameters, which should be used to construct the models \return the newly constructed background models */ static std::map> readBackgroundModelsFromJson( const nlohmann::json& j, std::vector>& parameters ); //! Write this model to JSON objects /*! \param [in,out] model the JSON record to which to write this model \param [in,out] parameters the JSON record to which to write the parameters */ void serialiseToJson( nlohmann::json& model, nlohmann::json& parameters ) const; //! The number of Gaussians in the resolution function const std::size_t nGauss_; //! Are any of the parameters of the resolution function scaled by the per-event error? const bool scaleWithPerEventError_{false}; //! Scale the mean of each Gaussian by the per-event decay time error? const std::vector scaleMeans_; //! Scale the width of each Gaussian by the per-event decay time error? const std::vector scaleWidths_; //! Scaling type const ScalingType scalingType_{ScalingType::None}; //! Store of all parameters of the resolution function std::vector> paramsOwned_; //! Store of all parameters of the resolution function std::vector params_; //! Fraction parameter for each Gaussian in the resolution function std::vector fractions_; //! Mean parameter for each Gaussian in the resolution function std::vector means_; //! Width parameter for each Gaussian in the resolution function std::vector widths_; //! Fraction of each Gaussian in the resolution function std::vector fractionVals_; //! Mean of each Gaussian in the resolution function std::vector meanVals_; //! Width of each Gaussian in the resolution function std::vector widthVals_; //! Is any parameter floating in the fit? bool anythingFloating_{false}; //! Has any floating parameter changed in the last fit iteration? bool anythingChanged_{false}; ClassDef(LauDecayTimeResolution, 0) }; //! \cond DOXYGEN_IGNORE // map LauDecayTimeResolution::ScalingType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauDecayTimeResolution::ScalingType, { {LauDecayTimeResolution::ScalingType::None, "None"}, {LauDecayTimeResolution::ScalingType::Global, "Global"}, {LauDecayTimeResolution::ScalingType::PerGaussian, "PerGaussian"}, {LauDecayTimeResolution::ScalingType::PerParameter, "PerParameter"}, }) -//! \endcond DOXYGEN_IGNORE +//! \endcond template void LauDecayTimeResolution::writeToJson( const std::map& models, const TString& fileName, const TString& elementName, const bool append, const int indent ) { using nlohmann::json; // Check for a signal model auto iter { models.find("signal") }; if ( iter == models.end() ) { std::cerr << "ERROR in LauDecayTimeResolution::writeToJson : cannot locate the signal model in the collection, aborting" << std::endl; return; } json j; json& parameters = j["parameters"] = json::array(); json& signalModel = j["signalModel"] = json::object(); json& backgroundModels = j["backgroundModels"] = json::array(); for ( const auto& [ name, model ] : models ) { if ( name == "signal" ) { model->serialiseToJson( signalModel, parameters ); } else { json modelDef = json::object(); modelDef["name"] = name; json& bkgndModel = modelDef["model"] = json::object(); model->serialiseToJson( bkgndModel, parameters ); backgroundModels.push_back( modelDef ); } } const bool writeOK { LauJsonTools::writeJsonFile( j, fileName.Data(), elementName.Data(), append, indent ) }; if ( ! writeOK ) { std::cerr << "ERROR in LauDecayTimePhysicsModel::writeToJson : could not successfully write to file \"" << fileName << std::endl; } } #endif diff --git a/inc/LauJsonTools.hh b/inc/LauJsonTools.hh index 5cd9eb2..2f43067 100644 --- a/inc/LauJsonTools.hh +++ b/inc/LauJsonTools.hh @@ -1,181 +1,181 @@ /* Copyright 2023 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ #ifndef LAU_JSON_TOOLS_HH #define LAU_JSON_TOOLS_HH #include "TString.h" #include #include #include /*! \file LauJsonTools.hh \brief File containing LauJsonTools namespace */ /*! \namespace LauJsonTools \brief Namespace containing tools for reading/writing JSON files */ namespace LauJsonTools { /*! \enum JsonType \brief Define types that can be found in JSON fields and that we can handle */ enum class JsonType { Null, //!< JSON value is null Object, //!< JSON value is an object Array, //!< JSON value is an array String, //!< JSON value is a string Boolean, //!< JSON value is a boolean Number_Integer, //!< JSON value is an integer (signed or unsigned) Number_Unsigned, //!< JSON value is an unsigned integer Number_Float, //!< JSON value is a floating point value Number, //!< JSON value is any number (integer, unsigned or float) Primitive, //!< JSON value is any primative type (null, string, boolean, integer, unsigned, float) Structured, //!< JSON value is any structured type (object, array) Any //!< JSON value is any of the above }; //! Typedef to define a combination of a JSON element's name and type using ElementNameType = std::pair< std::string, JsonType >; //! Exception object to be thrown in case of a missing element class MissingJsonElement : public std::runtime_error { public: //! Constructor /*! \param [in] what the message explaining the precise error that has occurred */ MissingJsonElement(const std::string& what) : std::runtime_error(what) {} }; //! Exception object to be thrown in case of malformed JSON class InvalidJson : public std::runtime_error { public: //! Constructor /*! \param [in] what the message explaining the precise error that has occurred */ InvalidJson(const std::string& what) : std::runtime_error(what) {} }; //! Deserialise a JSON file to a JSON value /*! \param [in] fileName the name of the file to read \param [in] elementName the optional name of the element within the root object to retrieve - by default retrieve the root structure \param [in] expectedType the expected type of the value */ nlohmann::json readJsonFile(const std::string& fileName, const std::string& elementName = "", const JsonType expectedType = JsonType::Any); //! Serialise a JSON value to a JSON file /*! \param [in] value the JSON value to serialise \param [in] fileName the name of the file to be written \param [in] elementName the (optional) name of the JSON element to which the coefficients should be written \param [in] append if true, append the spline to the existing JSON within the file - if using this option it is then mandatory to provide elementName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4)\n From the nlohmann::json::dump documentation:\n If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of 0 will only insert newlines. A value of -1 selects the most compact representation. \return true if file successfully written, false otherwise */ bool writeJsonFile(const nlohmann::json& value, const std::string& fileName, const std::string& elementName = "", const bool append = false, const int indent = 4); //! Check that the type of a JSON value is as expected /*! \param [in] value the JSON value to check \param [in] expectedType the expected type of the value */ bool checkValueType(const nlohmann::json& value, const JsonType expectedType); //! Check that the expected JSON elements are present in the supplied object /*! \param [in] obj the JSON object to check \param [in] expectedElements the elements (names and types) that are expected \return true if all expected elements are present, false otherwise */ bool checkObjectElements( const nlohmann::json& obj, const std::vector& expectedElements ); //! Access the value of an element that should be present in an object (no checking is done) /*! \tparam T the type of the element to be retrieved \param [in] obj the JSON object to access \param [in] elementName the name of the element within the object to retrieve \return the value of the element */ template T getValue( const nlohmann::json& obj, const std::string& elementName ) { return obj.at( elementName ).get(); } //! Access an element that may or may not be present in an object /*! \param [in] obj the JSON object to access \param [in] elementName the name of the element within the object to retrieve \param [in] expectedType the expected type of the element \return a pointer to the element, or nullptr if it is not present */ const nlohmann::json* getOptionalElement( const nlohmann::json& obj, const std::string& elementName, const JsonType expectedType = JsonType::Any ); //! Access the value of an element that may or may not be present in an object /*! \tparam T the type of the element to be retrieved \param [in] obj the JSON object to access \param [in] elementName the name of the element within the object to retrieve \param [in] expectedType the expected type of the element \return the value of the element as a std::optional */ template std::optional getOptionalValue( const nlohmann::json& obj, const std::string& elementName, const JsonType expectedType = JsonType::Any ); } template std::optional LauJsonTools::getOptionalValue( const nlohmann::json& obj, const std::string& elementName, const JsonType expectedType ) { auto elem { getOptionalElement( obj, elementName, expectedType ) }; if ( ! elem ) { return {}; } return elem->get(); } //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static void to_json(json& j, const TString& t) { j = t.Data(); } static TString from_json(const json& j) { return j.get(); } }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauMagPhaseCPCoeffSet.hh b/inc/LauMagPhaseCPCoeffSet.hh index 3267719..ed385eb 100644 --- a/inc/LauMagPhaseCPCoeffSet.hh +++ b/inc/LauMagPhaseCPCoeffSet.hh @@ -1,242 +1,242 @@ /* 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 #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, const Double_t mag, const Double_t phase, const Double_t magBar, const Double_t phaseBar, const Bool_t magFixed, const Bool_t phaseFixed, const Bool_t magBarFixed, const Bool_t phaseBarFixed); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet(LauMagPhaseCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet& operator=(LauMagPhaseCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::MagPhaseCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ Mag, Phase, MagBar, PhaseBar ] */ std::vector getParameters() override { return { mag_.get(), phase_.get(), magBar_.get(), phaseBar_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ Mag, Phase, MagBar, PhaseBar ] */ std::vector getParameters() const override { return { mag_.get(), phase_.get(), magBar_.get(), phaseBar_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ Mag, Phase, MagBar, PhaseBar ] */ std::vector getParNames() const override { return { "Mag", "Phase", "MagBar", "PhaseBar" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs, CloneOption cloneOption = CloneOption::All, Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet& operator=(const LauMagPhaseCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauMagPhaseCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude for particles std::unique_ptr mag_; //! The phase for particles std::unique_ptr phase_; //! The magnitude for antiparticles std::unique_ptr magBar_; //! The phase for antiparticles std::unique_ptr phaseBar_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauMagPhaseCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauMagPhaseCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauMagPhaseCoeffSet.hh b/inc/LauMagPhaseCoeffSet.hh index ad8aa10..f1d8b1f 100644 --- a/inc/LauMagPhaseCoeffSet.hh +++ b/inc/LauMagPhaseCoeffSet.hh @@ -1,225 +1,225 @@ /* 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 #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, const Double_t magnitude, const Double_t phase, const Bool_t magFixed, const Bool_t phaseFixed); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet(LauMagPhaseCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet& operator=(LauMagPhaseCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::MagPhase; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ Mag, Phase ] */ std::vector getParameters() override { return { magnitude_.get(), phase_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ Mag, Phase ] */ std::vector getParameters() const override { return { magnitude_.get(), phase_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ Mag, Phase ] */ std::vector getParNames() const override { return { "Mag", "Phase" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry (zero by design) */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet& operator=(const LauMagPhaseCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauMagPhaseCoeffSet* createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The magnitude std::unique_ptr magnitude_; //! The phase std::unique_ptr phase_; //! The complex coefficient LauComplex coeff_; ClassDefOverride(LauMagPhaseCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauMagPhaseCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauNSCCartesianCPCoeffSet.hh b/inc/LauNSCCartesianCPCoeffSet.hh index 07eb58b..61dba56 100644 --- a/inc/LauNSCCartesianCPCoeffSet.hh +++ b/inc/LauNSCCartesianCPCoeffSet.hh @@ -1,291 +1,291 @@ /* 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 LauNSCCartesianCPCoeffSet.hh \brief File containing declaration of LauNSCCartesianCPCoeffSet class. */ /*! \class LauNSCCartesianCPCoeffSet \brief Class for defining complex coefficients using the Cartesian CP convention for two linked Dalitz plots. Holds a set of real values that define the complex coefficients for an amplitude component in two DPs. The amplitudes have the form: A_f = ( x + Delta_x ) + i ( y + Delta_y ) Abar_f = ( x' - Delta_x' ) + i ( y' - Delta_y' ) A_fbar = ( x' + Delta_x' ) + i ( y' + Delta_y' ) Abar_fbar = ( x - Delta_x ) + i ( y - Delta_y ) */ #ifndef LAU_BSCARTESIANCP_COEFF_SET #define LAU_BSCARTESIANCP_COEFF_SET #include #include #include #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauNSCCartesianCPCoeffSet : public LauAbsCoeffSet { public: //! Constructor /*! \param [in] compName the name of the coefficient set \param [in] finalStateIsF kTRUE if the final state being considered is f, kFALSE if the final state being considered is fbar \param [in] x the CP-conserving parameter for the real part of A_f and Abar_fbar \param [in] y the CP-conserving parameter for the imaginary part of A_f and Abar_fbar \param [in] deltaX the CP-violating parameter for the real part of A_f and Abar_fbar \param [in] deltaY the CP-violating parameter for the imaginary part of A_f and Abar_fbar \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 \param [in] xPrime the CP-conserving parameter for the real part of A_fbar and Abar_f \param [in] yPrime the CP-conserving parameter for the imaginary part of A_fbar and Abar_f \param [in] deltaXPrime the CP-violating parameter for the real part of A_fbar and Abar_f \param [in] deltaYPrime the CP-violating parameter for the imaginary part of A_fbar and Abar_f \param [in] xPrimeFixed whether xPrime is fixed \param [in] yPrimeFixed whether yPrime is fixed \param [in] deltaXPrimeFixed whether deltaXPrime is fixed \param [in] deltaYPrimeFixed whether deltaYPrime is fixed \param [in] deltaXPrimeSecondStage whether deltaXPrime should be floated only in the second stage of the fit \param [in] deltaYPrimeSecondStage whether deltaYPrime should be floated only in the second stage of the fit */ LauNSCCartesianCPCoeffSet(const TString& compName, const Bool_t finalStateIsF, const Double_t x, const Double_t y, const Double_t deltaX, const Double_t deltaY, const Bool_t xFixed, const Bool_t yFixed, const Bool_t deltaXFixed, const Bool_t deltaYFixed, const Bool_t deltaXSecondStage, const Bool_t deltaYSecondStage, const Double_t xPrime, const Double_t yPrime, const Double_t deltaXPrime, const Double_t deltaYPrime, const Bool_t xPrimeFixed, const Bool_t yPrimeFixed, const Bool_t deltaXPrimeFixed, const Bool_t deltaYPrimeFixed, const Bool_t deltaXPrimeSecondStage, const Bool_t deltaYPrimeSecondStage); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauNSCCartesianCPCoeffSet(LauNSCCartesianCPCoeffSet&& rhs) = default; //! Move assignment operator (deleted) /*! The const field finalStateIsF implicitly deletes this anyway \param [in] rhs the coefficient to clone */ LauNSCCartesianCPCoeffSet& operator=(LauNSCCartesianCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::NSCCartesianCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, DeltaX, DeltaY, XPrime, YPrime, DeltaXPrime, DeltaYPrime ] */ std::vector getParameters() override { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get(), xPrime_.get(), yPrime_.get(), deltaXPrime_.get(), deltaYPrime_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, DeltaX, DeltaY, XPrime, YPrime, DeltaXPrime, DeltaYPrime ] */ std::vector getParameters() const override { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get(), xPrime_.get(), yPrime_.get(), deltaXPrime_.get(), deltaYPrime_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, DeltaX, DeltaY, XPrime, YPrime, DeltaXPrime, DeltaYPrime ] */ std::vector getParNames() const override { return { "X", "Y", "DeltaX", "DeltaY", "XPrime", "YPrime", "DeltaXPrime", "DeltaYPrime" }; } //! Determine whether this is the f or fbar final state /*! \return kTRUE if the final state is f, kFALSE if fbar */ Bool_t finalStateIsF() const { return finalStateIsF_; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } //! Write state to a JSON record /*! \param [in,out] j the JSON record to write to */ void serialiseToJson( nlohmann::json& j ) const override; private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauNSCCartesianCPCoeffSet(const LauNSCCartesianCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauNSCCartesianCPCoeffSet(const LauNSCCartesianCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauNSCCartesianCPCoeffSet& operator=(const LauNSCCartesianCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauNSCCartesianCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; //! Boolean controlling which final state information should be returned const Bool_t finalStateIsF_; // the actual fit parameters (need to be pointers so they can be cloned) //! The CP-conserving parameter for the real part of A_f and Abar_fbar std::unique_ptr x_; //! The CP-conserving parameter for the imaginary part of A_f and Abar_fbar std::unique_ptr y_; //! The CP-violating parameter for the real part of A_f and Abar_fbar std::unique_ptr deltaX_; //! The CP-violating parameter for the imaginary part of A_f and Abar_fbar std::unique_ptr deltaY_; //! The CP-conserving parameter for the real part of A_fbar and Abar_f std::unique_ptr xPrime_; //! The CP-conserving parameter for the imaginary part of A_fbar and Abar_f std::unique_ptr yPrime_; //! The CP-violating parameter for the real part of A_fbar and Abar_f std::unique_ptr deltaXPrime_; //! The CP-violating parameter for the imaginary part of A_fbar and Abar_f std::unique_ptr deltaYPrime_; //! The complex coefficient for A_f LauComplex coeffAf_; //! The complex coefficient for A_fbar LauComplex coeffAfbar_; //! The complex coefficient for Abar_f LauComplex coeffAbarf_; //! The complex coefficient for Abar_fbar LauComplex coeffAbarfbar_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauNSCCartesianCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauNSCCartesianCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauParameter.hh b/inc/LauParameter.hh index b7a0787..ba862c0 100644 --- a/inc/LauParameter.hh +++ b/inc/LauParameter.hh @@ -1,601 +1,601 @@ /* 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.hh \brief File containing declaration of LauParameter class. */ #ifndef LAU_PARAMETER #define LAU_PARAMETER #include "LauAbsRValue.hh" #include "LauBlind.hh" #include "TObject.h" #include "TString.h" #include #include #include #include /*! \class LauParameter \brief Class for defining the fit parameter objects. Holds all relevant information for the parameters for both generation and fitting step: current, initial and generated value, maximum and minimum range, error, asymmetric error, fix and float and etc. */ class LauParameter final : public TObject, public LauAbsRValue { public: //! Default constructor LauParameter() = default; //! Constructor for named parameter /*! \param [in] parName the parameter name */ explicit LauParameter(const TString& parName); //! Constructor for parameter value /*! \param [in] parValue the parameter value */ explicit LauParameter(const Double_t parValue); //! Constructor double limit parameter /*! \param [in] parValue the parameter value \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter */ LauParameter(const Double_t parValue, const Double_t min, const Double_t max); //! Constructor double limit fixed parameter /*! \param [in] parValue the parameter value \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter \param [in] parFixed boolean flag to fix or float parameter */ LauParameter(const Double_t parValue, const Double_t min, const Double_t max, const Bool_t parFixed); //! Constructor for double error and limit parameter /*! \param [in] parValue the parameter value \param [in] parError the parameter error \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter */ LauParameter(const Double_t parValue, const Double_t parError, const Double_t min, const Double_t max); //! Constructor for parameter value and name /*! \param [in] parName the parameter name \param [in] parValue the parameter value */ LauParameter(const TString& parName, const Double_t parValue); //! Constructor double limit parameter and name /*! \param [in] parName the parameter name \param [in] parValue the parameter value \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter */ LauParameter(const TString& parName, const Double_t parValue, const Double_t min, const Double_t max); //! Constructor double limit fixed parameter and name /*! \param [in] parName the parameter name \param [in] parValue the parameter value \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter \param [in] parFixed boolean flag to fix (kTRUE) or float (kFALSE) the parameter */ LauParameter(const TString& parName, const Double_t parValue, const Double_t min, const Double_t max, const Bool_t parFixed); //! Constructor double error and limit parameter and name /*! \param [in] parName the parameter name \param [in] parValue the parameter value \param [in] parError the parameter error \param [in] min the minimum value of the parameter \param [in] max the maximum value of the parameter */ LauParameter(const TString& parName, const Double_t parValue, const Double_t parError, const Double_t min, const Double_t max); // Destructor virtual ~LauParameter() noexcept; //! Copy constructor /*! \param [in] rhs the parameter to be copied */ LauParameter(const LauParameter& rhs) = default; //! Copy assignment operator /*! \param [in] rhs the parameter to be copied */ LauParameter& operator=(const LauParameter& rhs) = default; //! Move constructor /*! \param [in] rhs the parameter to be moved from */ LauParameter(LauParameter&& rhs) = default; //! Move assignment operator /*! \param [in] rhs the parameter to be moved from */ LauParameter& operator=(LauParameter&& rhs) = default; // the simple accessor functions //! The parameter name /*! \return the name of the parameter */ const TString& name() const override {return name_;} //! The blinding state /*! \return the blinding state: kTRUE means that it is blinded, kFALSE that it is not blinded */ Bool_t blind() const override {return blinder_.active();} //! Access the blinder object /*! \return the blinder */ const LauBlind* blinder() const {return blinder_.active() ? &blinder_ : nullptr;} //! The value of the parameter /*! \return the value of the parameter */ Double_t value() const override {return value_;} //! The unblinded value of the parameter /*! \return the unblinded value of the parameter */ Double_t unblindValue() const override {return blinder_.active() ? blinder_.unblind(value_) : value_;} //! The error on the parameter /*! \return the error on the parameter */ Double_t error() const {return error_;} //! The lower error on the parameter /*! \return the lower error on the parameter */ Double_t negError() const {return negError_;} //! The upper error on the parameter /*! \return the upper error on the parameter */ Double_t posError() const {return posError_;} //! The value generated for the parameter /*! \return the value generated for the parameter */ Double_t genValue() const override {return genValue_;} //! The initial value of the parameter /*! \return the initial value of the parameter given to the fitter */ Double_t initValue() const override {return initValue_;} //! The minimum value allowed for the parameter /*! \return the minimum value allowed for the parameter */ Double_t minValue() const {return minValue_;} //! The maximum value allowed for the parameter /*! \return the maximum value allowed for the parameter */ Double_t maxValue() const {return maxValue_;} //! The range allowed for the parameter /*! \return the range allowed for the parameters, defined as the difference between the max and min value */ Double_t range() const {return this->maxValue() - this->minValue();} //! Check whether the parameter is fixed or floated /*! \return the boolean flag true/false whether the parameter is fixed */ Bool_t fixed() const override {return fixed_;} //! Check whether the parameter should be floated only in the second stage of a two stage fit /*! \return the boolean flag true/false whether it floats only in the second stage */ Bool_t secondStage() const {return secondStage_;} //! Check whether a Gaussian constraints is applied /*! \return the boolean flag true/false whether a Gaussian constraint is applied */ Bool_t gaussConstraint() const override {return gaussConstraint_;} //! The mean of the Gaussian constraint /*! \return the mean value of the Gaussian constraint */ Double_t constraintMean() const override {return constraintMean_;} //! The width of the Gaussian constraint /*! \return the width of the Gaussian constraint */ Double_t constraintWidth() const override {return constraintWidth_;} //! The parameter global correlation coefficient /*! \return the global correlation coefficient */ Double_t globalCorrelationCoeff() const {return gcc_;} //! The bias in the parameter /*! \return the bias in the parameter, defined as the difference between the value and the generated value */ Double_t bias() const {return bias_;} //! The pull value for the parameter /*! \return the pull value for the parameter, defined as the bias divided by the error */ Double_t pull() const {return pull_;} //! Boolean to say it is an L value /*! \return kTRUE, LauParameters are L values */ Bool_t isLValue() const override {return kTRUE;} //! Get the LauParameter itself /*! \return a vector of the LauParameter */ std::vector getPars() override; // the simple "setter" functions //! Set the parameter name /*! \param [in] newName the name of the parameter */ void name(const TString& newName) override; //! Set the value of the parameter /*! \param [in] newValue the value of the parameter */ void value(const Double_t newValue); //! Set the error on the parameter /*! \param [in] newError the error on the parameter */ void error(const Double_t newError); //! Set the lower error on the parameter /*! \param [in] newNegError the lower error on the parameter */ void negError(const Double_t newNegError); //! Set the upper error on the parameter /*! \param [in] newPosError the upper error on the parameter */ void posError(const Double_t newPosError); //! Set the error values on the parameter /*! \param [in] newError the error on the parameter \param [in] newNegError the lower error on the parameter \param [in] newPosError the upper error on the parameter */ void errors(const Double_t newError, const Double_t newNegError, const Double_t newPosError); //! Set the value and errors on the parameter /*! \param [in] newValue the value of the parameter \param [in] newError the error on the parameter \param [in] newNegError the lower error on the parameter (default set to zero) \param [in] newPosError the upper error on the parameter (default set to zero) */ void valueAndErrors(const Double_t newValue, const Double_t newError, const Double_t newNegError = 0.0, const Double_t newPosError = 0.0); //! Set the global correlation coefficient /*! \param [in] newGCCValue the value of the coefficient */ void globalCorrelationCoeff(const Double_t newGCCValue); //! Set the generated value for the parameter /*! \param [in] newGenValue the generated value for the parameter */ void genValue(const Double_t newGenValue); //! Set the inital value for the parameter /*! \param [in] newInitValue the initial value for the parameter */ void initValue(const Double_t newInitValue); //! Set the minimum value for the parameter /*! \param [in] newMinValue the minimum value for the parameter */ void minValue(const Double_t newMinValue); //! Set the maximum value for the parameter /*! \param [in] newMaxValue the maximum value for the parameter */ void maxValue(const Double_t newMaxValue); //! Set the range for the parameter /*! \param [in] newMinValue the minimum value for the parameter \param [in] newMaxValue the maximum value for the parameter */ void range(const Double_t newMinValue, const Double_t newMaxValue); //! Set the value and range for the parameter /*! \param [in] newValue the value of the parameter \param [in] newMinValue the minimum value for the parameter \param [in] newMaxValue the maximum value for the parameter */ void valueAndRange(const Double_t newValue, const Double_t newMinValue, const Double_t newMaxValue); //! Fix or float the given parameter /*! \param [in] parFixed boolean flag to fix or float the parameter */ void fixed(const Bool_t parFixed); //! Set parameter as second-stage or not of the fit /*! \param [in] secondStagePar boolean flag to check whether is a second-stage parameter */ void secondStage(const Bool_t secondStagePar); //! 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(const Double_t newGaussMean, const Double_t newGaussWidth); //! Remove the Gaussian constraint void removeGaussianConstraint(); //! Blind the parameter /*! See LauBlind documentation for details of blinding procedure \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 \param [in] flipSign activate possible random sign flip (off by default) */ void blindParameter(const TString& blindingString, const Double_t width, const Bool_t flipSign = kFALSE); // functions for the cloning mechanism //! Check whether is a clone or not /*! \return true/false whether is a clone */ Bool_t clone() const {return (parent_ != nullptr);} //! Method to create a clone from the parent parameter using the copy constructor /*! \param [in] constFactor the optional constant factor by which the clone shold be multiplied \return the cloned parameter */ LauParameter* createClone(const Double_t constFactor = 1.0); //! Method to create a clone from the parent parameter using the copy constructor and setting a new name /*! \param [in] newName the new name of the cloned parameter \param [in] constFactor the optional constant factor by which the clone shold be multiplied \return the cloned parameter */ LauParameter* createClone(const TString& newName, const Double_t constFactor = 1.0); //! The parent parameter /*! \return the parent parameter */ LauParameter* parent() const {return parent_;} //! Call to update the bias and pull values void updatePull(); //! Randomise the value of the parameter (if it is floating). /*! The pre-defined parameter range is used as the randomisation range. */ void randomiseValue(); //! Randomise the value of the parameter (if it is floating). /*! Use the given range unless either of the given values are outside the range of the parameter, in which case that value will be altered to the current max or min. \param [in] minVal the minimum value for the parameter \param [in] maxVal the maximum value for the parameter */ void randomiseValue(const Double_t minVal, const Double_t maxVal); //! Write state to a JSON record /*! \param [in,out] j the JSON record to write to */ void serialiseToJson( nlohmann::json& j ) const override; protected: //! Method to check whether value provided is within the range and that the minimum and maximum limits make sense /*! \param [in] val the value of the parameter \param [in] minVal the minimum value allowed \param [in] maxVal the maximum value allowed */ void checkRange(const Double_t val, const Double_t minVal, const Double_t maxVal); //! Method to check whether value provided is whithin the range and that the minimum and maximum limits make sense void checkRange() { this->checkRange(this->value(),this->minValue(),this->maxValue()); } //! Mark this as a clone of the given parent /*! \param theparent the parent parameter */ void clone(LauParameter* theparent) { parent_ = theparent; } //! Method to remove a clone from the list of clones /*! This is used in the destructor to allow a clone to inform its parent it is no longer around \param [in] clone the clone to be removed from the list */ void removeFromCloneList(LauParameter* clone) { auto iter = clones_.find( clone ); if ( iter != clones_.end() ) { clones_.erase( iter ); } } //! Method to clear the clone parameters void wipeClones() {clones_.clear();} //! Method to update clone values /*! \param [in] justValue boolean flag to determine whether it is necessary to update all the parameter settings or only its value. */ void updateClones(const Bool_t justValue); private: //! LauFitNtuple is a friend class friend class LauFitNtuple; //! The parameter name TString name_; //! The parameter value Double_t value_{0.0}; //! The error on the parameter Double_t error_{0.0}; //! The lower error on the parameter Double_t negError_{0.0}; //! The upper error on the parameter Double_t posError_{0.0}; //! Toy generation value Double_t genValue_{0.0}; //! Initial fit value Double_t initValue_{0.0}; //! Minimum value for the parameter Double_t minValue_{0.0}; //! Maximum value for the parameter Double_t maxValue_{0.0}; //! Fix/float option for parameter Bool_t fixed_{kTRUE}; //! Flag whether it is floated only in the second stage of the fit Bool_t secondStage_{kFALSE}; //! Choice to use Gaussian constraint Bool_t gaussConstraint_{kFALSE}; //! Mean value of the Gaussian constraint Double_t constraintMean_{0.0}; //! Width of the Gaussian constraint Double_t constraintWidth_{0.0}; //! Global correlation coefficient Double_t gcc_{0.0}; //! Parameter bias Double_t bias_{0.0}; //! Parameter pull Double_t pull_{0.0}; //! The parent parameter LauParameter* parent_{nullptr}; //! The clones of this parameter std::map clones_; //! The blinding engine LauBlind blinder_; ClassDefOverride(LauParameter, 5) }; //! Output stream operator std::ostream& operator << (std::ostream& stream, const LauParameter& par); //! Type to define an array of parameters typedef std::vector< std::vector > LauParArray; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauParameter from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauPolarGammaCPCoeffSet.hh b/inc/LauPolarGammaCPCoeffSet.hh index b088885..5d53f7d 100644 --- a/inc/LauPolarGammaCPCoeffSet.hh +++ b/inc/LauPolarGammaCPCoeffSet.hh @@ -1,357 +1,357 @@ /* 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 #include "Rtypes.h" #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" class LauPolarGammaCPCoeffSet : public LauAbsCoeffSet { public: //! The possible D decay modes enum class 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); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauPolarGammaCPCoeffSet(LauPolarGammaCPCoeffSet&& rhs) = default; //! Move assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauPolarGammaCPCoeffSet& operator=(LauPolarGammaCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::PolarGammaCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, gamma, [rB, deltaB, rD, deltaD] ] */ std::vector getParameters() override; //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, gamma, [rB, deltaB, rD, deltaD] ] */ std::vector getParameters() const override; //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, gamma, [rB, deltaB, rD, deltaD] ] */ std::vector getParNames() const override; //! Determine the decay type of the coefficient /*! \return the decay type of the coefficient */ DecayType decayType() const { return decayType_; } //! Determine whether the global value of gamma is used for this coefficient /*! \return kTRUE if the global value of gamma is used, false otherwise */ Bool_t useGlobalGamma() const { return useGlobalGamma_; } //! Determine whether the global values of the ADS parameter are used for this coefficient /*! \return kTRUE if the global values are used, false otherwise */ Bool_t useGlobalADSPars() const { return useGlobalADSPars_; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, const Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } //! Write state to a JSON record /*! \param [in,out] j the JSON record to write to */ void serialiseToJson( nlohmann::json& j ) const override; 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauPolarGammaCPCoeffSet(const LauPolarGammaCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauPolarGammaCPCoeffSet(const LauPolarGammaCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauPolarGammaCPCoeffSet& operator=(const LauPolarGammaCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauPolarGammaCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; //! Prepend the base name and index to the name of a parameter /*! \param [in,out] par the parameter to be renamed \param [in] oldBaseName the old base name, which might need to be removed before adding the new one */ void adjustName(LauParameter& par, const TString& oldBaseName) override; //! 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 std::unique_ptr x_; //! The imaginary part of the b -> c amplitude std::unique_ptr y_; //! the magnitude of the ratio of the b -> u and b -> c amplitudes std::unique_ptr rB_; //! the relative CP-conserving (strong) phase of the b -> u and b -> c amplitudes std::unique_ptr deltaB_; //! the relative CP-violating (weak) phase of the b -> u and b -> c amplitudes std::shared_ptr gamma_; //! the magnitude of the ratio of the favoured and suppressed D-decay amplitudes std::shared_ptr rD_; //! the relative strong phase of the favoured and suppressed D-decay amplitudes std::shared_ptr deltaD_; //! The CP-violating phase (shared by multiple resonances) static std::shared_ptr gammaGlobal_; //! the magnitude of the ratio of the favoured and suppressed D-decay amplitudes (shared by multiple resonances) static std::shared_ptr rDGlobal_; //! the relative strong phase of the favoured and suppressed D-decay amplitudes (shared by multiple resonances) static std::shared_ptr 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_; ClassDefOverride(LauPolarGammaCPCoeffSet, 0) }; //! Output stream operator std::ostream& operator<<( std::ostream& os, const LauPolarGammaCPCoeffSet::DecayType type ); //! \cond DOXYGEN_IGNORE // map LauPolarGammaCPCoeffSet::DecayType values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( LauPolarGammaCPCoeffSet::DecayType, { {LauPolarGammaCPCoeffSet::DecayType::GLW_CPOdd, "GLW_CPOdd"}, {LauPolarGammaCPCoeffSet::DecayType::GLW_CPEven, "GLW_CPEven"}, {LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured, "ADS_Favoured"}, {LauPolarGammaCPCoeffSet::DecayType::ADS_Suppressed, "ADS_Suppressed"}, {LauPolarGammaCPCoeffSet::DecayType::GLW_CPOdd_btouOnly, "GLW_CPOdd_btouOnly"}, {LauPolarGammaCPCoeffSet::DecayType::GLW_CPEven_btouOnly, "GLW_CPEven_btouOnly"}, {LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured_btouOnly, "ADS_Favoured_btouOnly"}, {LauPolarGammaCPCoeffSet::DecayType::ADS_Suppressed_btouOnly, "ADS_Suppressed_btouOnly"}, }) namespace nlohmann { template <> struct adl_serializer { static LauPolarGammaCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauRealImagCPCoeffSet.hh b/inc/LauRealImagCPCoeffSet.hh index 56affef..4794c55 100644 --- a/inc/LauRealImagCPCoeffSet.hh +++ b/inc/LauRealImagCPCoeffSet.hh @@ -1,241 +1,241 @@ /* 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 #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, const Double_t x, const Double_t y, const Double_t xbar, const Double_t ybar, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xbarFixed, const Bool_t ybarFixed); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet(LauRealImagCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet& operator=(LauRealImagCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::RealImagCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, XBar, YBar ] */ std::vector getParameters() override { return { x_.get(), y_.get(), xbar_.get(), ybar_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, XBar, YBar ] */ std::vector getParameters() const override { return { x_.get(), y_.get(), xbar_.get(), ybar_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, XBar, YBar ] */ std::vector getParNames() const override { return { "X", "Y", "XBar", "YBar" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauRealImagCPCoeffSet(const LauRealImagCPCoeffSet& rhs, CloneOption cloneOption = CloneOption::All, Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet(const LauRealImagCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet& operator=(const LauRealImagCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauRealImagCPCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The real part for the particle std::unique_ptr x_; //! The imaginary part for the particle std::unique_ptr y_; //! The real part for the antiparticle std::unique_ptr xbar_; //! The imaginary part for the antiparticle std::unique_ptr ybar_; //! The particle complex coefficient LauComplex particleCoeff_; //! The antiparticle complex coefficient LauComplex antiparticleCoeff_; //! The CP asymmetry LauParameter acp_; ClassDefOverride(LauRealImagCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauRealImagCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauRealImagCoeffSet.hh b/inc/LauRealImagCoeffSet.hh index 4f2945c..7377722 100644 --- a/inc/LauRealImagCoeffSet.hh +++ b/inc/LauRealImagCoeffSet.hh @@ -1,227 +1,227 @@ /* 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. */ #ifndef LAU_REALIMAG_COEFF_SET #define LAU_REALIMAG_COEFF_SET #include "LauAbsCoeffSet.hh" #include "LauComplex.hh" #include "LauParameter.hh" #include "Rtypes.h" #include #include #include #include /*! \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. */ 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, const Double_t x, const Double_t y, const Bool_t xFixed, const Bool_t yFixed); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet(LauRealImagCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet& operator=(LauRealImagCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::RealImag; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y ] */ std::vector getParameters() override { return { x_.get(), y_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y ] */ std::vector getParameters() const override { return { x_.get(), y_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y ] */ std::vector getParNames() const override { return { "X", "Y" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry (zero by design) */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet& operator=(const LauRealImagCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauRealImagCoeffSet* createClone_impl(const TString& newName, const LauAbsCoeffSet::CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The real part std::unique_ptr x_; //! The imaginary part std::unique_ptr y_; //! The complex coefficient LauComplex coeff_; ClassDefOverride(LauRealImagCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauRealImagCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauRealImagGammaCPCoeffSet.hh b/inc/LauRealImagGammaCPCoeffSet.hh index 5759c5e..35f9580 100644 --- a/inc/LauRealImagGammaCPCoeffSet.hh +++ b/inc/LauRealImagGammaCPCoeffSet.hh @@ -1,278 +1,278 @@ /* 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 #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); //! Move constructor (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet(LauRealImagGammaCPCoeffSet&& rhs) = default; //! Move assignment operator (delete) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet& operator=(LauRealImagGammaCPCoeffSet&& rhs) = delete; //! Determine the type of the coefficient /*! \return the type of the coefficient */ LauCoeffType type() const override { return LauCoeffType::RealImagGammaCP; } //! Retrieve the parameters of the coefficient, e.g. so that they can be loaded into a fit /*! \return the parameters of the coefficient [ X, Y, XCP, YCP, XBarCP, YBarCP ] */ std::vector getParameters() override { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), xbarCP_.get(), ybarCP_.get() }; } //! Retrieve the (const) parameters of the coefficient, e.g. so that they can be queried /*! \return the (const) parameters of the coefficient [ X, Y, XCP, YCP, XBarCP, YBarCP ] */ std::vector getParameters() const override { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), xbarCP_.get(), ybarCP_.get() }; } //! Retrieve the names of the parameters of the coefficient (in the same order as the parameters in getParameters) /*! \return the parameter names [ X, Y, XCP, YCP, XBarCP, YBarCP ] */ std::vector getParNames() const override { return { "X", "Y", "XCP", "YCP", "XBarCP", "YBarCP" }; } //! Print the current values of the parameters void printParValues() const override; //! Print the column headings for a results table /*! \param [out] stream the stream to print to */ void printTableHeading(std::ostream& stream) const override; //! Print the parameters of the complex coefficient as a row in the results table /*! \param [out] stream the stream to print to */ void printTableRow(std::ostream& stream) const override; //! Randomise the starting values of the parameters for a fit void randomiseInitValues() override; //! Make sure values are in "standard" ranges, e.g. phases should be between -pi and pi void finaliseValues() override; //! Retrieve the complex coefficient for a particle /*! \return the complex coefficient for a particle */ const LauComplex& particleCoeff() override; //! Retrieve the complex coefficient for an antiparticle /*! \return the complex coefficient for an antiparticle */ const LauComplex& antiparticleCoeff() override; //! 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 */ void setCoeffValues( const LauComplex& coeff, const LauComplex& coeffBar, Bool_t init ) override; //! Calculate the CP asymmetry /*! \return the CP asymmetry */ LauParameter acp() override; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ std::unique_ptr createClone(const TString& newName, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}) const { return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } private: //! Copy constructor (with options) /*! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) */ LauRealImagGammaCPCoeffSet(const LauRealImagGammaCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0, const nlohmann::json& coeffInfo = {}); //! Copy constructor (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet(const LauRealImagGammaCPCoeffSet& rhs) = delete; //! Copy assignment operator (deleted) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet& operator=(const LauRealImagGammaCPCoeffSet& rhs) = delete; //! 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 \param [in] coeffInfo an optional JSON entry that contains the values of any non-cloned parameters (depending on the CloneOption) \return a clone of the coefficient set */ LauRealImagGammaCPCoeffSet* createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const override; // the actual fit parameters // (need to be pointers so they can be cloned) //! The real nonCP part std::unique_ptr x_; //! The imaginary nonCP part std::unique_ptr y_; //! The real CP part for the particle std::unique_ptr xCP_; //! The imaginary CP part for the particle std::unique_ptr yCP_; //! The real CP part for the antiparticle std::unique_ptr xbarCP_; //! The imaginary CP part for the antiparticle std::unique_ptr 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_; ClassDefOverride(LauRealImagGammaCPCoeffSet, 0) }; //! \cond DOXYGEN_IGNORE namespace nlohmann { template <> struct adl_serializer { static LauRealImagGammaCPCoeffSet from_json(const json& j); }; } -//! \endcond DOXYGEN_IGNORE +//! \endcond #endif diff --git a/inc/LauVetoes.hh b/inc/LauVetoes.hh index 987ac65..131959f 100644 --- a/inc/LauVetoes.hh +++ b/inc/LauVetoes.hh @@ -1,144 +1,144 @@ /* 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 "Rtypes.h" #include "TString.h" #include #include #include class LauKinematics; class LauVetoes final { public: //! Constructor LauVetoes() = default; //! 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 UInt_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 UInt_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; //! Write the set of vetoes to a JSON file /*! \param [in] fileName the name of the file to which the JSON should be written \param [in] elementName the (optional) name of the element in the JSON to which to write \param [in] append if true, append to the existing JSON within the file - if using this option it is then mandatory to provide elementName \param [in] indent the indentation level to use in the output in number of spaces (defaults to 4) */ - void writeToJson(const TString& fileName, const TString& splineName = "", const bool append = false, const int indent = 4) const; + void writeToJson(const TString& fileName, const TString& elementName = "", const bool append = false, const int indent = 4) const; //! Construct a new LauVetoes object based on values read from a json file /*! \param [in] fileName the name of the file from which the JSON should be read \param [in] elementName the (optional) name of the element in the JSON from which to read \return the newly constructed object */ static std::unique_ptr readFromJson(const TString& fileName, const TString& elementName = ""); private: //! 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; //! Check the validity of a veto /*! \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 */ Bool_t checkVeto(const UInt_t resPairAmpInt, const Double_t minMassSq, const Double_t maxMassSq) const; //! Print the veto info at a given index /*! \param [in] index the index of the veto */ void printVeto(const std::size_t index) const; //! Routine to check validity of all vetoes after loading from JSON void checkValidity(); //! 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_; // enable JSON serialisation of this class NLOHMANN_DEFINE_TYPE_INTRUSIVE(LauVetoes, vetoPair_, vetoMinMass_, vetoMaxMass_) ClassDef(LauVetoes,0) // Vetoes in the Dalitz plot }; #endif diff --git a/src/Lau1DCubicSpline.cc b/src/Lau1DCubicSpline.cc index 0183b6d..c9e5cb3 100644 --- a/src/Lau1DCubicSpline.cc +++ b/src/Lau1DCubicSpline.cc @@ -1,721 +1,721 @@ /* 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 #include #include #include "Lau1DCubicSpline.hh" #include "LauAbsRValue.hh" #include "LauJsonTools.hh" #include "LauParameter.hh" ClassImp(Lau1DCubicSpline) Lau1DCubicSpline::Lau1DCubicSpline(const std::vector& xs, const std::vector& ys, const SplineType type, const BoundaryType leftBound, const BoundaryType rightBound, const Double_t dydx0, const Double_t dydxn) : nKnots_{xs.size()}, x_{xs}, y_{ys}, type_{type}, leftBound_{leftBound}, rightBound_{rightBound}, dydx0_{dydx0}, dydxn_{dydxn} { init(); } std::unique_ptr Lau1DCubicSpline::readFromJson(const TString& fileName, const TString& splineName) { // NB deliberately not using uniform initialisation here because of this issue: // https://json.nlohmann.me/home/faq/#brace-initialization-yields-arrays const nlohmann::json j = LauJsonTools::readJsonFile( fileName.Data(), splineName.Data(), LauJsonTools::JsonType::Object ); if ( j.is_null() ) { if ( splineName != "" ) { std::cerr << "ERROR in Lau1DCubicSpline::readFromJson : unable to retrieve JSON object from element \"" << splineName << "\" in file \"" << fileName << "\"" << std::endl; } else { std::cerr << "ERROR in Lau1DCubicSpline::readFromJson : unable to retrieve JSON object from root element of file \"" << fileName << "\"" << std::endl; } return {}; } // NB can't use std::make_unique here because the default constructor is private std::unique_ptr spline{ new Lau1DCubicSpline }; j.get_to(*spline); spline->init(); return spline; } void Lau1DCubicSpline::writeToJson(const TString& fileName, const TString& splineName, const bool append, const int indent) const { const nlohmann::json j = *this; const bool writeOK { LauJsonTools::writeJsonFile( j, fileName.Data(), splineName.Data(), append, indent ) }; if ( ! writeOK ) { std::cerr << "ERROR in Lau1DCubicSpline::writeToJson : could not successfully write to file \"" << fileName << std::endl; } } Double_t Lau1DCubicSpline::evaluate(const Double_t x) const { // do not attempt to extrapolate the spline if( xx_[nKnots_-1] ) { std::cerr << "WARNING in Lau1DCubicSpline::evaluate : function is only defined between " << x_[0] << " and " << x_[nKnots_-1] << std::endl; std::cerr << " 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 std::size_t cell{0}; while( x > x_[cell+1] ) { ++cell; } // obtain x- and y-values of the neighbouring knots const Double_t xLow { x_[cell] }; const Double_t xHigh { x_[cell+1] }; const Double_t yLow { y_[cell] }; const Double_t yHigh { y_[cell+1] }; if(type_ == SplineType::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 const Double_t t { (x - xLow) / (xHigh - xLow) }; const Double_t a { dydx_[cell] * (xHigh - xLow) - (yHigh - yLow) }; const Double_t b { -1.*dydx_[cell+1] * (xHigh - xLow) + (yHigh - yLow) }; const 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::updateYValues(const std::vector& ys) { for (std::size_t i{0}; iunblindValue(); } this->calcDerivatives(); } void Lau1DCubicSpline::updateYValues(const std::vector& ys) { for (std::size_t i{0}; iunblindValue(); } this->calcDerivatives(); } void Lau1DCubicSpline::updateType(const SplineType type) { if(type_ != type) { type_ = type; this->calcDerivatives(); } } void Lau1DCubicSpline::updateBoundaryConditions(const BoundaryType leftBound, const BoundaryType rightBound, const Double_t dydx0, const Double_t dydxn) { bool updateDerivatives{false}; if(leftBound_ != leftBound || rightBound_ != rightBound) { leftBound_ = leftBound; rightBound_ = rightBound; updateDerivatives = true; } if(dydx0_ != dydx0) { dydx0_ = dydx0; if(leftBound_ == BoundaryType::Clamped) updateDerivatives = true; } if(dydxn_ != dydxn) { dydxn_ = dydxn; if(rightBound_ == BoundaryType::Clamped) updateDerivatives = true; } if(updateDerivatives) { this->calcDerivatives(); } } std::array Lau1DCubicSpline::getCoefficients(const std::size_t segIndex, const bool normalise) const { std::array result = {0.,0.,0.,0.}; if(segIndex >= nKnots_-1) { std::cerr << "ERROR in Lau1DCubicSpline::getCoefficients requested for too high a knot value" << std::endl; return result; } Double_t xL = x_[segIndex] , xH = x_[segIndex+1]; Double_t yL = y_[segIndex] , yH = y_[segIndex+1]; Double_t h = xH-xL; //This number comes up a lot switch(type_) { case SplineType::StandardSpline: case SplineType::AkimaSpline: { Double_t kL = dydx_[segIndex], kH = dydx_[segIndex+1]; //a and b based on definitions from https://en.wikipedia.org/wiki/Spline_interpolation#Algorithm_to_find_the_interpolating_cubic_spline Double_t a = kL*h-(yH-yL); Double_t b =-kH*h+(yH-yL); Double_t denom = -h*h*h;//The terms have a common demoninator result[0] = -b*xL*xL*xH + a*xL*xH*xH + h*h*(xL*yH - xH*yL); result[1] = -a*xH*(2*xL+xH) + b*xL*(xL+2*xH) + h*h*(yL-yH); result[2] = -b*(2*xL+xH) + a*(xL+2*xH); result[3] = -a+b; for(auto& res : result){res /= denom;} break; } /* case SplineType::AkimaSpline: // Double check the Akima description of splines (in evaluate) right now they're the same except for the first derivatives { //using fomulae from https://asmquantmacro.com/2015/09/01/akima-spline-interpolation-in-excel/ std::function m = [&](Int_t j) //formula to get the straight line gradient { if(j < 0){return 2*m(j+1)-m(j+2);} if(j >= nKnots_){return 2*m(j-1)-m(j-2);} return (y_[j+1]-y_[j]) / (x_[j+1]-x_[j]); }; auto t = [&](Int_t j) { Double_t res = 0.; //originally res was called 't' but that produced a shadow warning Double_t denom = TMath::Abs(m(j+1)-m(j)) + TMath::Abs(m(j-1)-m(j-2)); if(denom == 0){res = (m(j)-m(j-1))/2;} //Special case for when denom = 0 else { res = TMath::Abs(m(j+1)-m(j))*m(j-1) + TMath::Abs(m(j-1)-m(j-2))*m(j); res /= denom; } return res; }; //These are the p's to get the spline in the form p_k(x-xL)^k Double_t pDenom = x_[segIndex+1]/x_[segIndex]; //a denominator used for p[2] and p[3] std::array p = {y_[segIndex],t(segIndex),0.,0.}; //we'll do the last 2 below p[2] = 3*m(segIndex)-2*t(segIndex)-t(segIndex+1); p[2]/= pDenom; p[3] = t(segIndex)+t(segIndex+1)-2*m(segIndex); p[3]/= pDenom*pDenom; //Now finally rearranging the p's into the desired results result[0] = p[0]-p[1]*xL+p[2]*xL*xL-p[3]*xL*xL*xL; result[1] = p[1]-2*p[2]*xL+3*p[3]*xL*xL; result[2] = p[2]-3*p[3]*xL; result[3] = p[3]; break; }*/ case SplineType::LinearInterpolation: { result[0] = xH*yL-xL*yH; result[1] = yH-yL; for(auto& res : result){res /= h;} break; } } if (normalise) { const Double_t integral { this->integral() }; for(auto& res : result){res /= integral;} } return result; } Double_t Lau1DCubicSpline::integral() const { Double_t integral{0.0}; for(std::size_t iKnot{0}; iKnot < nKnots_ -1; ++iKnot) { const Double_t minAbs { x_[iKnot] }; const Double_t maxAbs { x_[iKnot+1] }; const std::array coeffs { this->getCoefficients(iKnot, false) }; auto integralFunc = [&coeffs](Double_t x){return coeffs[0]*x + coeffs[1]*x*x/2.0 + coeffs[2]*x*x*x/3.0 + coeffs[3]*x*x*x*x/4.0;}; integral += integralFunc(maxAbs); integral -= integralFunc(minAbs); } return integral; } TF1* Lau1DCubicSpline::makeTF1(const bool normalise) const { auto fitf = [this](Double_t* x, Double_t* par) {//there is only 1 x (the abscissa) and 1 par (a scaling of the entire thing for normalisation) return this->evaluate( x[0] ) * par[0]; }; //Make the function TF1* func = new TF1("FittedFunc",fitf,x_.front(),x_.back(),1); func -> SetParNames("Normalisation"); if(normalise) { func->SetParameter(0, 1./func->Integral(x_.front(),x_.back())); } else{func->SetParameter(0,1.);} return func; } TF1* Lau1DCubicSpline::normaliseToTH1(TH1* hist, const LauOutputLevel printLevel) const { //first define the fit function auto fitf = [this](Double_t* x, Double_t* par) {//there is only 1 x (the abscissa) and 1 par (a scaling of the entire thing) return this->evaluate( x[0] ) * par[0]; }; //Make the function TF1* FittedFunc = new TF1("FittedFunc",fitf,x_.front(),x_.back(),1); //Set the parameter name FittedFunc -> SetParNames("Constant"); //Set the parameter limits and default value FittedFunc -> SetParLimits(0,0.,10.); FittedFunc -> SetParameter(0,1.); // Options to: // - N = do not store the graphics function // - 0 = do not plot the fit result TString fitOptions {"N 0"}; switch ( printLevel ) { case LauOutputLevel::Verbose : fitOptions += " V"; break; case LauOutputLevel::Quiet : fitOptions += " Q"; break; case LauOutputLevel::Standard : break; } hist->Fit( "FittedFunc", fitOptions ); return FittedFunc; } TFitResultPtr Lau1DCubicSpline::fitToTH1(TH1* hist, const LauOutputLevel printLevel, const bool doWL, std::map fixedParams) { auto fitf = [this](Double_t* x, Double_t* par) { this -> updateYValues( std::vector(par, par + nKnots_) ); return this -> evaluate( x[0] ); }; TF1 FittedFunc("FittedFunc",fitf,x_.front(),x_.back(),nKnots_); const Double_t knotMax { hist->GetMaximum() * 1.5 }; for(std::size_t knot{0}; knot <= nKnots_ ; ++knot) { FittedFunc.SetParName(knot, Form("Knot%lu",knot)); FittedFunc.SetParLimits(knot, 0., knotMax); FittedFunc.SetParameter(knot, y_[knot]); } for(auto& [knot, val] : fixedParams) { FittedFunc.FixParameter(knot, val); } // Options to: // - N = do not store the graphics function // - 0 = do not plot the fit result // - S = save the result of the fit // - WL= do a weighted likelihood fit (not chi2) TString fitOptions {"N 0 S"}; if(doWL){fitOptions += " WL";} switch ( printLevel ) { case LauOutputLevel::Verbose : fitOptions += " V"; break; case LauOutputLevel::Quiet : fitOptions += " Q"; break; case LauOutputLevel::Standard : break; } return hist->Fit( "FittedFunc", fitOptions ); } void Lau1DCubicSpline::init() { if( y_.size() != x_.size()) { std::cerr << "ERROR in Lau1DCubicSpline::init : The number of y-values given does not match the number of x-values" << std::endl; std::cerr << " Found " << y_.size() << ", expected " << x_.size() << std::endl; gSystem->Exit(EXIT_FAILURE); } if( nKnots_ < 3 ) { std::cerr << "ERROR in Lau1DCubicSpline::init : The number of knots is too small" << std::endl; std::cerr << " Found " << nKnots_ << ", expected at least 3 (to have at least 1 internal knot)" << std::endl; gSystem->Exit(EXIT_FAILURE); } dydx_.assign(nKnots_,0.0); a_.assign(nKnots_,0.0); b_.assign(nKnots_,0.0); c_.assign(nKnots_,0.0); d_.assign(nKnots_,0.0); this->calcDerivatives(); } void Lau1DCubicSpline::calcDerivatives() { switch ( type_ ) { case SplineType::StandardSpline : this->calcDerivativesStandard(); break; case SplineType::AkimaSpline : this->calcDerivativesAkima(); break; case SplineType::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 switch ( leftBound_ ) { case BoundaryType::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])); break; } case BoundaryType::NotAKnot : { // define the width, h, and the 'slope', delta, of the first cell const Double_t h1{x_[1]-x_[0]}; const Double_t h2{x_[2]-x_[0]}; const Double_t delta1{(y_[1]-y_[0])/h1}; const Double_t 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); break; } case BoundaryType::Clamped : { b_[0] = 1.; c_[0] = 0.; d_[0] = dydx0_; break; } } // set right boundary condition switch ( rightBound_ ) { case BoundaryType::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])); break; } case BoundaryType::NotAKnot : { // define the width, h, and the 'slope', delta, of the last cell const Double_t hnm1{x_[nKnots_-1]-x_[nKnots_-2]}; const Double_t hnm2(x_[nKnots_-2]-x_[nKnots_-3]); const Double_t deltanm1{(y_[nKnots_-1]-y_[nKnots_-2])/hnm1}; const Double_t 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); break; } case BoundaryType::Clamped : { a_[nKnots_-1] = 0.; b_[nKnots_-1] = 1.; d_[nKnots_-1] = dydxn_; break; } } // the remaining equations ensure that f_i-1''(x_i) = f''_i(x_i) for all internal knots for(std::size_t i{1}; i(nKnots_-2)}; 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.0}, an{0.0}, anp1{0.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(std::size_t i{1}; i coeffs { this->getCoefficients(iSegment, false) }; // first derivative is a parabola const Double_t a { coeffs[3]*3.0 }; const Double_t b { coeffs[2]*2.0 }; const Double_t c { coeffs[1] }; const Double_t discriminant { b*b - 4.0*a*c }; // if no real roots, skip this segment if ( discriminant < 0.0) { continue; } const Double_t x1 { (-b + TMath::Sqrt(discriminant))/(2.0*a) }; if ( x1 > x_[iSegment] and x1 < x_[iSegment+1] ) { // this root is within the segment - check the 2nd derivative const Double_t secondDeriv { 2.0 * a * x1 + b }; if ( secondDeriv < 0.0 ) { // evaluate the function and update max if appropriate const Double_t y1 { this->evaluate(x1) }; if ( y1 > max ) { max = y1; } } } const Double_t x2 { (-b - TMath::Sqrt(discriminant))/(2.0*a) }; if ( x2 > x_[iSegment] and x2 < x_[iSegment+1] ) { // this root is within the segment - check the 2nd derivative const Double_t secondDeriv { 2.0 * a * x2 + b }; if ( secondDeriv < 0.0 ) { // evaluate the function and update max if appropriate const Double_t y2 { this->evaluate(x2) }; if ( y2 > max ) { max = y2; } } } } return max; } //! \cond DOXYGEN_IGNORE std::ostream& operator<<(std::ostream& out, const Lau1DCubicSpline::SplineType type) { switch (type) { case Lau1DCubicSpline::SplineType::StandardSpline : out << "StandardSpline"; break; case Lau1DCubicSpline::SplineType::AkimaSpline : out << "AkimaSpline"; break; case Lau1DCubicSpline::SplineType::LinearInterpolation : out << "LinearInterpolation"; break; } return out; } std::ostream& operator<<(std::ostream& out, const Lau1DCubicSpline::BoundaryType type) { switch (type) { case Lau1DCubicSpline::BoundaryType::Clamped: out << "Clamped"; break; case Lau1DCubicSpline::BoundaryType::Natural : out << "Natural"; break; case Lau1DCubicSpline::BoundaryType::NotAKnot : out << "NotAKnot"; break; } return out; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauBelleCPCoeffSet.cc b/src/LauBelleCPCoeffSet.cc index b4ef146..c78a44f 100644 --- a/src/LauBelleCPCoeffSet.cc +++ b/src/LauBelleCPCoeffSet.cc @@ -1,439 +1,439 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauBelleCPCoeffSet) LauBelleCPCoeffSet::LauBelleCPCoeffSet(const TString& compName, const Double_t a, const Double_t delta, const Double_t b, const Double_t phi, const Bool_t aFixed, const Bool_t deltaFixed, const Bool_t bFixed, const Bool_t phiFixed, const Bool_t bSecondStage, const Bool_t phiSecondStage) : LauAbsCoeffSet{ compName }, a_{ std::make_unique("A", a, minMagnitude_, maxMagnitude_, aFixed) }, b_{ std::make_unique("B", b, minMagnitude_, maxMagnitude_, bFixed) }, delta_{ std::make_unique("Delta", delta, minPhase_, maxPhase_, deltaFixed) }, phi_{ std::make_unique("Phi", phi, minPhase_, maxPhase_, phiFixed) }, 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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { a_.reset( rhs.a_->createClone(constFactor) ); } else { const auto aVal { getOptionalValue( coeffInfo, "A", JsonType::Number ).value_or( rhs.a_->value() ) }; const auto aFixed { getOptionalValue( coeffInfo, "AFixed", JsonType::Boolean ).value_or( rhs.a_->fixed() ) }; a_ = std::make_unique("A", aVal, minMagnitude_, maxMagnitude_, aFixed); if ( getOptionalValue( coeffInfo, "ABlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "ABlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "ABlindingWidth" ) }; a_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.a_->blind() ) { const LauBlind* blinder { rhs.a_->blinder() }; a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { b_.reset( rhs.b_->createClone(constFactor) ); } else { const auto bVal { getOptionalValue( coeffInfo, "B", JsonType::Number ).value_or( rhs.b_->value() ) }; const auto bFixed { getOptionalValue( coeffInfo, "BFixed", JsonType::Boolean ).value_or( rhs.b_->fixed() ) }; const auto bSecondStage { getOptionalValue( coeffInfo, "BSecondStage", JsonType::Boolean ).value_or( rhs.b_->secondStage() ) }; b_ = std::make_unique("B", bVal, minMagnitude_, maxMagnitude_, bFixed); if (bSecondStage && !bFixed) { b_->secondStage(kTRUE); b_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "BBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "BBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "BBlindingWidth" ) }; b_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.b_->blind() ) { const LauBlind* blinder { rhs.b_->blinder() }; b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase ) { delta_.reset( rhs.delta_->createClone(constFactor) ); } else { const auto deltaVal { getOptionalValue( coeffInfo, "Delta", JsonType::Number ).value_or( rhs.delta_->value() ) }; const auto deltaFixed { getOptionalValue( coeffInfo, "DeltaFixed", JsonType::Boolean ).value_or( rhs.delta_->fixed() ) }; delta_ = std::make_unique("Delta", deltaVal, minPhase_, maxPhase_, deltaFixed); if ( getOptionalValue( coeffInfo, "DeltaBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaBlindingWidth" ) }; delta_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.delta_->blind() ) { const LauBlind* blinder { rhs.delta_->blinder() }; delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { phi_.reset( rhs.phi_->createClone(constFactor) ); } else { const auto phiVal { getOptionalValue( coeffInfo, "Phi", JsonType::Number ).value_or( rhs.phi_->value() ) }; const auto phiFixed { getOptionalValue( coeffInfo, "PhiFixed", JsonType::Boolean ).value_or( rhs.phi_->fixed() ) }; const auto phiSecondStage { getOptionalValue( coeffInfo, "PhiSecondStage", JsonType::Boolean ).value_or( rhs.phi_->secondStage() ) }; phi_ = std::make_unique("Phi", phiVal, minPhase_, maxPhase_, phiFixed); if (phiSecondStage && !phiFixed) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "PhiBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "PhiBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "PhiBlindingWidth" ) }; phi_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.phi_->blind() ) { const LauBlind* blinder { rhs.phi_->blinder() }; phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const 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 const Double_t mag { LauAbsCoeffSet::getRandomiser()->Rndm()*0.1 }; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi const 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 const 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() }; // 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. const Double_t genDelta { delta_->genValue() }; const Double_t genPhi { phi_->genValue() }; 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() { const LauComplex aTerm{a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())}; const 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() { const LauComplex aTerm{a_->unblindValue()*TMath::Cos(delta_->unblindValue()), a_->unblindValue()*TMath::Sin(delta_->unblindValue())}; const 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, const Bool_t init ) { const LauComplex sum { coeff + coeffBar }; const LauComplex diff { coeff - coeffBar }; const LauComplex ratio { diff / sum }; const Double_t aVal{ 0.5 * sum.abs() }; const Double_t deltaVal{ sum.arg() }; const Double_t bVal{ ratio.abs() }; const 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 const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // work out the ACP value const Double_t value { (-2.0*b_->value()*TMath::Cos(phi_->value()))/(1.0+b_->value()*b_->value()) }; // is it fixed? const Bool_t fixed { b_->fixed() && phi_->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_; } LauBelleCPCoeffSet* LauBelleCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase || cloneOption == CloneOption::TieMagnitude || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauBelleCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauBelleCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauBelleCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::BelleCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauBelleCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauBelleCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("A", JsonType::Number), std::make_pair("Delta", JsonType::Number), std::make_pair("B", JsonType::Number), std::make_pair("Phi", JsonType::Number), std::make_pair("AFixed", JsonType::Boolean), std::make_pair("DeltaFixed", JsonType::Boolean), std::make_pair("BFixed", JsonType::Boolean), std::make_pair("PhiFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauBelleCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto a { getValue( j, "A" ) }; const auto delta { getValue( j, "Delta" ) }; const auto b { getValue( j, "B" ) }; const auto phi { getValue( j, "Phi" ) }; const auto aFixed { getValue( j, "AFixed" ) }; const auto deltaFixed { getValue( j, "DeltaFixed" ) }; const auto bFixed { getValue( j, "BFixed" ) }; const auto phiFixed { getValue( j, "PhiFixed" ) }; const auto bSecondStage { getOptionalValue( j, "BSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto phiSecondStage { getOptionalValue( j, "PhiSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; LauBelleCPCoeffSet coeff{ name, a, delta, b, phi, aFixed, deltaFixed, bFixed, phiFixed, bSecondStage, phiSecondStage }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauCartesianCPCoeffSet.cc b/src/LauCartesianCPCoeffSet.cc index 5591328..66c49f8 100644 --- a/src/LauCartesianCPCoeffSet.cc +++ b/src/LauCartesianCPCoeffSet.cc @@ -1,361 +1,361 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauCartesianCPCoeffSet) LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t deltaX, const Double_t deltaY, const Bool_t xFixed, const Bool_t yFixed, const Bool_t deltaXFixed, const Bool_t deltaYFixed, const Bool_t deltaXSecondStage, const Bool_t deltaYSecondStage) : LauAbsCoeffSet{ compName }, x_{ std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed) }, y_{ std::make_unique("Y", y, minRealImagPart_, maxRealImagPart_, yFixed) }, deltaX_{ std::make_unique("DeltaX", deltaX, minDelta_, maxDelta_, deltaXFixed) }, deltaY_{ std::make_unique("DeltaY", deltaY, minDelta_, maxDelta_, deltaYFixed) }, 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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { deltaX_.reset( rhs.deltaX_->createClone(constFactor) ); deltaY_.reset( rhs.deltaY_->createClone(constFactor) ); } else { const auto deltaXVal { getOptionalValue( coeffInfo, "DeltaX", JsonType::Number ).value_or( rhs.deltaX_->value() ) }; const auto deltaXFixed { getOptionalValue( coeffInfo, "DeltaXFixed", JsonType::Boolean ).value_or( rhs.deltaX_->fixed() ) }; const auto deltaXSecondStage { getOptionalValue( coeffInfo, "DeltaXSecondStage", JsonType::Boolean ).value_or( rhs.deltaX_->secondStage() ) }; const auto deltaYVal { getOptionalValue( coeffInfo, "DeltaY", JsonType::Number ).value_or( rhs.deltaY_->value() ) }; const auto deltaYFixed { getOptionalValue( coeffInfo, "DeltaYFixed", JsonType::Boolean ).value_or( rhs.deltaY_->fixed() ) }; const auto deltaYSecondStage { getOptionalValue( coeffInfo, "DeltaYSecondStage", JsonType::Boolean ).value_or( rhs.deltaY_->secondStage() ) }; deltaX_ = std::make_unique("DeltaX", deltaXVal, minDelta_, maxDelta_, deltaXFixed); deltaY_ = std::make_unique("DeltaY", deltaYVal, minDelta_, maxDelta_, deltaYFixed); if ( deltaXSecondStage && !deltaXFixed ) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if ( deltaYSecondStage && !deltaYFixed ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "DeltaXBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaXBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaXBlindingWidth" ) }; deltaX_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaX_->blind() ) { const LauBlind* blinder { rhs.deltaX_->blinder() }; deltaX_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( getOptionalValue( coeffInfo, "DeltaYBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaYBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaYBlindingWidth" ) }; deltaY_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaY_->blind() ) { const LauBlind* blinder { rhs.deltaY_->blinder() }; deltaY_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const 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 const 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 const 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 const 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, const Bool_t init ) { LauComplex average{ coeff }; average += coeffBar; average.rescale( 0.5 ); const Double_t xVal{ average.re() }; const Double_t yVal{ average.im() }; const Double_t deltaXVal{ coeff.re() - average.re() }; const 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 const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // work out the ACP value const Double_t numer { x_->value()*deltaX_->value() + y_->value()*deltaY_->value() }; const Double_t denom { x_->value()*x_->value() + deltaX_->value()*deltaX_->value() + y_->value()*y_->value() + deltaY_->value()*deltaY_->value() }; const Double_t value { -2.0*numer/denom }; // is it fixed? const Bool_t fixed { deltaX_->fixed() && deltaY_->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_; } LauCartesianCPCoeffSet* LauCartesianCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauCartesianCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauCartesianCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauCartesianCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::CartesianCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCartesianCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauCartesianCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("DeltaX", JsonType::Number), std::make_pair("DeltaY", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("DeltaXFixed", JsonType::Boolean), std::make_pair("DeltaYFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauCartesianCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto deltaX { getValue( j, "DeltaX" ) }; const auto deltaY { getValue( j, "DeltaY" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto deltaXFixed { getValue( j, "DeltaXFixed" ) }; const auto deltaYFixed { getValue( j, "DeltaYFixed" ) }; const auto deltaXSecondStage { getOptionalValue( j, "DeltaXSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto deltaYSecondStage { getOptionalValue( j, "DeltaYSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; LauCartesianCPCoeffSet coeff{ name, x, y, deltaX, deltaY, xFixed, yFixed, deltaXFixed, deltaYFixed, deltaXSecondStage, deltaYSecondStage }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauCartesianGammaCPCoeffSet.cc b/src/LauCartesianGammaCPCoeffSet.cc index 802f653..2423aa8 100644 --- a/src/LauCartesianGammaCPCoeffSet.cc +++ b/src/LauCartesianGammaCPCoeffSet.cc @@ -1,417 +1,417 @@ /* 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 "LauJsonTools.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_{ std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed) }, y_{ std::make_unique("Y", y, minRealImagPart_, maxRealImagPart_, yFixed) }, xCP_{ std::make_unique("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed) }, yCP_{ std::make_unique("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed) }, deltaXCP_{ std::make_unique("DeltaXCP", deltaXCP, minDelta_, maxDelta_, deltaXCPFixed) }, deltaYCP_{ std::make_unique("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, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, nonCPPart_{ rhs.nonCPPart_ }, cpPart_{ rhs.cpPart_ }, cpAntiPart_{ rhs.cpAntiPart_ }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { xCP_.reset( rhs.xCP_->createClone(constFactor) ); yCP_.reset( rhs.yCP_->createClone(constFactor) ); deltaXCP_.reset( rhs.deltaXCP_->createClone(constFactor) ); deltaYCP_.reset( rhs.deltaYCP_->createClone(constFactor) ); } else { const auto xCPVal { getOptionalValue( coeffInfo, "XCP", JsonType::Number ).value_or( rhs.xCP_->value() ) }; const auto xCPFixed { getOptionalValue( coeffInfo, "XCPFixed", JsonType::Boolean ).value_or( rhs.xCP_->fixed() ) }; xCP_ = std::make_unique("XCP", xCPVal, minRealImagPart_, maxRealImagPart_, xCPFixed); if ( getOptionalValue( coeffInfo, "XCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XCPBlindingWidth" ) }; xCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.xCP_->blind() ) { const LauBlind* blinder { rhs.xCP_->blinder() }; xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto yCPVal { getOptionalValue( coeffInfo, "YCP", JsonType::Number ).value_or( rhs.yCP_->value() ) }; const auto yCPFixed { getOptionalValue( coeffInfo, "YCPFixed", JsonType::Boolean ).value_or( rhs.yCP_->fixed() ) }; yCP_ = std::make_unique("YCP", yCPVal, minRealImagPart_, maxRealImagPart_, yCPFixed); if ( getOptionalValue( coeffInfo, "YCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YCPBlindingWidth" ) }; yCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.yCP_->blind() ) { const LauBlind* blinder { rhs.yCP_->blinder() }; yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto deltaXCPVal { getOptionalValue( coeffInfo, "DeltaXCP", JsonType::Number ).value_or( rhs.deltaXCP_->value() ) }; const auto deltaXCPFixed { getOptionalValue( coeffInfo, "DeltaXCPFixed", JsonType::Boolean ).value_or( rhs.deltaXCP_->fixed() ) }; const auto deltaXCPSecondStage { getOptionalValue( coeffInfo, "DeltaXCPSecondStage", JsonType::Boolean ).value_or( rhs.deltaXCP_->secondStage() ) }; const auto deltaYCPVal { getOptionalValue( coeffInfo, "DeltaYCP", JsonType::Number ).value_or( rhs.deltaYCP_->value() ) }; const auto deltaYCPFixed { getOptionalValue( coeffInfo, "DeltaYCPFixed", JsonType::Boolean ).value_or( rhs.deltaYCP_->fixed() ) }; const auto deltaYCPSecondStage { getOptionalValue( coeffInfo, "DeltaYCPSecondStage", JsonType::Boolean ).value_or( rhs.deltaYCP_->secondStage() ) }; deltaXCP_ = std::make_unique("DeltaXCP", deltaXCPVal, minDelta_, maxDelta_, deltaXCPFixed); deltaYCP_ = std::make_unique("DeltaYCP", deltaYCPVal, minDelta_, maxDelta_, deltaYCPFixed); if ( deltaXCPSecondStage && !deltaXCPFixed ) { deltaXCP_->secondStage(kTRUE); deltaXCP_->initValue(0.0); } if ( deltaYCPSecondStage && !deltaYCPFixed ) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "DeltaXCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaXCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaXCPBlindingWidth" ) }; deltaXCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaXCP_->blind() ) { const LauBlind* blinder { rhs.deltaXCP_->blinder() }; deltaXCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( getOptionalValue( coeffInfo, "DeltaYCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaYCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaYCPBlindingWidth" ) }; deltaYCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaYCP_->blind() ) { const LauBlind* blinder { rhs.deltaYCP_->blinder() }; deltaYCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const 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 const 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 const 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 const 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 const 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 const 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&, const 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 const TString parName{ this->baseName() + "_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_; } LauCartesianGammaCPCoeffSet* LauCartesianGammaCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauCartesianGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauCartesianGammaCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauCartesianGammaCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::CartesianGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCartesianGammaCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauCartesianGammaCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("XCP", JsonType::Number), std::make_pair("YCP", JsonType::Number), std::make_pair("DeltaXCP", JsonType::Number), std::make_pair("DeltaYCP", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("XCPFixed", JsonType::Boolean), std::make_pair("YCPFixed", JsonType::Boolean), std::make_pair("DeltaXCPFixed", JsonType::Boolean), std::make_pair("DeltaYCPFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauCartesianGammaCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto xCP { getValue( j, "XCP" ) }; const auto yCP { getValue( j, "YCP" ) }; const auto deltaXCP { getValue( j, "DeltaXCP" ) }; const auto deltaYCP { getValue( j, "DeltaYCP" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto xCPFixed { getValue( j, "XCPFixed" ) }; const auto yCPFixed { getValue( j, "YCPFixed" ) }; const auto deltaXCPFixed { getValue( j, "DeltaXCPFixed" ) }; const auto deltaYCPFixed { getValue( j, "DeltaYCPFixed" ) }; const auto deltaXCPSecondStage { getOptionalValue( j, "DeltaXCPSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto deltaYCPSecondStage { getOptionalValue( j, "DeltaYCPSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; LauCartesianGammaCPCoeffSet coeff{ name, x, y, xCP, yCP, deltaXCP, deltaYCP, xFixed, yFixed, xCPFixed, yCPFixed, deltaXCPFixed, deltaYCPFixed, deltaXCPSecondStage, deltaYCPSecondStage }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauCleoCPCoeffSet.cc b/src/LauCleoCPCoeffSet.cc index 62b46f1..4e29d8a 100644 --- a/src/LauCleoCPCoeffSet.cc +++ b/src/LauCleoCPCoeffSet.cc @@ -1,432 +1,432 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauCleoCPCoeffSet) LauCleoCPCoeffSet::LauCleoCPCoeffSet(const TString& compName, const Double_t a, const Double_t delta, const Double_t b, const Double_t phi, const Bool_t aFixed, const Bool_t deltaFixed, const Bool_t bFixed, const Bool_t phiFixed, const Bool_t bSecondStage, const Bool_t phiSecondStage) : LauAbsCoeffSet{ compName }, a_{ std::make_unique("A", a, minMagnitude_, maxMagnitude_, aFixed) }, b_{ std::make_unique("B", b, minMagnitude_, maxMagnitude_, bFixed) }, delta_{ std::make_unique("Delta", delta, minPhase_, maxPhase_, deltaFixed) }, phi_{ std::make_unique("Phi", phi, minPhase_, maxPhase_, phiFixed) }, 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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { a_.reset( rhs.a_->createClone(constFactor) ); } else { const auto aVal { getOptionalValue( coeffInfo, "A", JsonType::Number ).value_or( rhs.a_->value() ) }; const auto aFixed { getOptionalValue( coeffInfo, "AFixed", JsonType::Boolean ).value_or( rhs.a_->fixed() ) }; a_ = std::make_unique("A", aVal, minMagnitude_, maxMagnitude_, aFixed); if ( getOptionalValue( coeffInfo, "ABlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "ABlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "ABlindingWidth" ) }; a_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.a_->blind() ) { const LauBlind* blinder { rhs.a_->blinder() }; a_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { b_.reset( rhs.b_->createClone(constFactor) ); } else { const auto bVal { getOptionalValue( coeffInfo, "B", JsonType::Number ).value_or( rhs.b_->value() ) }; const auto bFixed { getOptionalValue( coeffInfo, "BFixed", JsonType::Boolean ).value_or( rhs.b_->fixed() ) }; const auto bSecondStage { getOptionalValue( coeffInfo, "BSecondStage", JsonType::Boolean ).value_or( rhs.b_->secondStage() ) }; b_ = std::make_unique("B", bVal, minMagnitude_, maxMagnitude_, bFixed); if ( bSecondStage && !bFixed ) { b_->secondStage(kTRUE); b_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "BBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "BBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "BBlindingWidth" ) }; b_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.b_->blind() ) { const LauBlind* blinder { rhs.b_->blinder() }; b_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase ) { delta_.reset( rhs.delta_->createClone(constFactor) ); } else { const auto deltaVal { getOptionalValue( coeffInfo, "Delta", JsonType::Number ).value_or( rhs.delta_->value() ) }; const auto deltaFixed { getOptionalValue( coeffInfo, "DeltaFixed", JsonType::Boolean ).value_or( rhs.delta_->fixed() ) }; delta_ = std::make_unique("Delta", deltaVal, minPhase_, maxPhase_, deltaFixed); if ( getOptionalValue( coeffInfo, "DeltaBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaBlindingWidth" ) }; delta_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.delta_->blind() ) { const LauBlind* blinder { rhs.delta_->blinder() }; delta_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { phi_.reset( rhs.phi_->createClone(constFactor) ); } else { const auto phiVal { getOptionalValue( coeffInfo, "Phi", JsonType::Number ).value_or( rhs.phi_->value() ) }; const auto phiFixed { getOptionalValue( coeffInfo, "PhiFixed", JsonType::Boolean ).value_or( rhs.phi_->fixed() ) }; const auto phiSecondStage { getOptionalValue( coeffInfo, "PhiSecondStage", JsonType::Boolean ).value_or( rhs.phi_->secondStage() ) }; phi_ = std::make_unique("Phi", phiVal, minPhase_, maxPhase_, phiFixed); if ( phiSecondStage && !phiFixed ) { phi_->secondStage(kTRUE); phi_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "PhiBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "PhiBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "PhiBlindingWidth" ) }; phi_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.phi_->blind() ) { const LauBlind* blinder { rhs.phi_->blinder() }; phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const 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 const Double_t mag { LauAbsCoeffSet::getRandomiser()->Rndm()*0.1 }; b_->initValue(mag); b_->value(mag); } if (delta_->fixed() == kFALSE) { // Choose a phase between +- pi const 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 const 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() }; // 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. const Double_t genDelta { delta_->genValue() }; const Double_t genPhi { phi_->genValue() }; 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() { const Double_t magnitude { a_->unblindValue() + b_->unblindValue() }; const Double_t phase { delta_->unblindValue() + phi_->unblindValue() }; particleCoeff_.setRealImagPart(magnitude*TMath::Cos(phase), magnitude*TMath::Sin(phase)); return particleCoeff_; } const LauComplex& LauCleoCPCoeffSet::antiparticleCoeff() { const Double_t magnitude { a_->unblindValue() - b_->unblindValue() }; const 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, const Bool_t init ) { const Double_t mag { coeff.abs() }; const Double_t magBar { coeffBar.abs() }; const Double_t phase { coeff.arg() }; const Double_t phaseBar { coeffBar.arg() }; const Double_t aVal{ 0.5 * ( mag + magBar ) }; const Double_t deltaVal{ 0.5 * ( phase + phaseBar ) }; const Double_t bVal{ 0.5 * ( mag - magBar ) }; const 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 const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // work out the ACP value const Double_t numer { -2.0*a_->value()*b_->value() }; const Double_t denom { a_->value()*a_->value() + b_->value()*b_->value() }; const Double_t value { numer/denom }; // is it fixed? const Bool_t fixed { a_->fixed() && b_->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_; } LauCleoCPCoeffSet* LauCleoCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase || cloneOption == CloneOption::TieMagnitude || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauCleoCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauCleoCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauCleoCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::CleoCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCleoCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauCleoCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("A", JsonType::Number), std::make_pair("Delta", JsonType::Number), std::make_pair("B", JsonType::Number), std::make_pair("Phi", JsonType::Number), std::make_pair("AFixed", JsonType::Boolean), std::make_pair("DeltaFixed", JsonType::Boolean), std::make_pair("BFixed", JsonType::Boolean), std::make_pair("PhiFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauCleoCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto a { getValue( j, "A" ) }; const auto delta { getValue( j, "Delta" ) }; const auto b { getValue( j, "B" ) }; const auto phi { getValue( j, "Phi" ) }; const auto aFixed { getValue( j, "AFixed" ) }; const auto deltaFixed { getValue( j, "DeltaFixed" ) }; const auto bFixed { getValue( j, "BFixed" ) }; const auto phiFixed { getValue( j, "PhiFixed" ) }; const auto bSecondStage { getOptionalValue( j, "BSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto phiSecondStage { getOptionalValue( j, "PhiSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; LauCleoCPCoeffSet coeff{ name, a, delta, b, phi, aFixed, deltaFixed, bFixed, phiFixed, bSecondStage, phiSecondStage }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauMagPhaseCPCoeffSet.cc b/src/LauMagPhaseCPCoeffSet.cc index 6a768f3..7843852 100644 --- a/src/LauMagPhaseCPCoeffSet.cc +++ b/src/LauMagPhaseCPCoeffSet.cc @@ -1,395 +1,395 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauMagPhaseCPCoeffSet) LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const TString& compName, const Double_t mag, const Double_t phase, const Double_t magBar, const Double_t phaseBar, const Bool_t magFixed, const Bool_t phaseFixed, const Bool_t magBarFixed, const Bool_t phaseBarFixed) : LauAbsCoeffSet{ compName }, mag_{ std::make_unique("Mag", mag, minMagnitude_, maxMagnitude_, magFixed) }, phase_{ std::make_unique("Phase", phase, minPhase_, maxPhase_, phaseFixed) }, magBar_{ std::make_unique("MagBar", magBar, minMagnitude_, maxMagnitude_, magBarFixed) }, phaseBar_{ std::make_unique("PhaseBar", phaseBar, minPhase_, maxPhase_, phaseBarFixed) }, acp_{ "ACP", (magBar*magBar - mag*mag)/(magBar*magBar + mag*mag), -1.0, 1.0 } { } LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const LauMagPhaseCPCoeffSet& rhs, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { mag_.reset( rhs.mag_->createClone(constFactor) ); magBar_.reset( rhs.magBar_->createClone(constFactor) ); } else { const auto magVal { getOptionalValue( coeffInfo, "Mag", JsonType::Number ).value_or( rhs.mag_->value() ) }; const auto magFixed { getOptionalValue( coeffInfo, "MagFixed", JsonType::Boolean ).value_or( rhs.mag_->fixed() ) }; mag_ = std::make_unique("Mag", magVal, minMagnitude_, maxMagnitude_, magFixed); if ( getOptionalValue( coeffInfo, "MagBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "MagBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "MagBlindingWidth" ) }; mag_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.mag_->blind() ) { const LauBlind* blinder { rhs.mag_->blinder() }; mag_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto magBarVal { getOptionalValue( coeffInfo, "MagBar", JsonType::Number ).value_or( rhs.magBar_->value() ) }; const auto magBarFixed { getOptionalValue( coeffInfo, "MagBarFixed", JsonType::Boolean ).value_or( rhs.magBar_->fixed() ) }; magBar_ = std::make_unique("MagBar", magBarVal, minMagnitude_, maxMagnitude_, magBarFixed); if ( getOptionalValue( coeffInfo, "MagBarBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "MagBarBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "MagBarBlindingWidth" ) }; magBar_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.magBar_->blind() ) { const LauBlind* blinder { rhs.magBar_->blinder() }; magBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase ) { phase_.reset( rhs.phase_->createClone(constFactor) ); phaseBar_.reset( rhs.phaseBar_->createClone(constFactor) ); } else { const auto phaseVal { getOptionalValue( coeffInfo, "Phase", JsonType::Number ).value_or( rhs.phase_->value() ) }; const auto phaseFixed { getOptionalValue( coeffInfo, "PhaseFixed", JsonType::Boolean ).value_or( rhs.phase_->fixed() ) }; phase_ = std::make_unique("Phase", phaseVal, minPhase_, maxPhase_, phaseFixed); if ( getOptionalValue( coeffInfo, "PhaseBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "PhaseBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "PhaseBlindingWidth" ) }; phase_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.phase_->blind() ) { const LauBlind* blinder { rhs.phase_->blinder() }; phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto phaseBarVal { getOptionalValue( coeffInfo, "PhaseBar", JsonType::Number ).value_or( rhs.phaseBar_->value() ) }; const auto phaseBarFixed { getOptionalValue( coeffInfo, "PhaseBarFixed", JsonType::Boolean ).value_or( rhs.phaseBar_->fixed() ) }; phaseBar_ = std::make_unique("PhaseBar", phaseBarVal, minPhase_, maxPhase_, phaseBarFixed); if ( getOptionalValue( coeffInfo, "PhaseBarBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "PhaseBarBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "PhaseBarBlindingWidth" ) }; phaseBar_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.phaseBar_->blind() ) { const LauBlind* blinder { rhs.phaseBar_->blinder() }; phaseBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const Double_t value { LauAbsCoeffSet::getRandomiser()->Rndm()*2.0 }; mag_->initValue(value); mag_->value(value); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi const 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 const Double_t value { LauAbsCoeffSet::getRandomiser()->Rndm()*2.0 }; magBar_->initValue(value); magBar_->value(value); } if (phaseBar_->fixed() == kFALSE) { // Choose a phase between +- pi const 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() }; // 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. const Double_t genPhase { phase_->genValue() }; const Double_t genPhaseBar { phaseBar_->genValue() }; 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 ) { const Double_t magVal{ coeff.abs() }; const Double_t phaseVal{ coeff.arg() }; const Double_t magBarVal{ coeffBar.abs() }; const 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 const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // work out the ACP value const Double_t value { (magBar_->value()*magBar_->value() - mag_->value()*mag_->value())/(magBar_->value()*magBar_->value() + mag_->value()*mag_->value()) }; // is it fixed? const Bool_t fixed { magBar_->fixed() && mag_->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_; } LauMagPhaseCPCoeffSet* LauMagPhaseCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase || cloneOption == CloneOption::TieMagnitude ) ) { std::cerr << "ERROR in LauMagPhaseCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauMagPhaseCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauMagPhaseCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::MagPhaseCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauMagPhaseCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauMagPhaseCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("Mag", JsonType::Number), std::make_pair("Phase", JsonType::Number), std::make_pair("MagBar", JsonType::Number), std::make_pair("PhaseBar", JsonType::Number), std::make_pair("MagFixed", JsonType::Boolean), std::make_pair("PhaseFixed", JsonType::Boolean), std::make_pair("MagBarFixed", JsonType::Boolean), std::make_pair("PhaseBarFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauMagPhaseCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto mag { getValue( j, "Mag" ) }; const auto phase { getValue( j, "Phase" ) }; const auto magBar { getValue( j, "MagBar" ) }; const auto phaseBar { getValue( j, "PhaseBar" ) }; const auto magFixed { getValue( j, "MagFixed" ) }; const auto phaseFixed { getValue( j, "PhaseFixed" ) }; const auto magBarFixed { getValue( j, "MagBarFixed" ) }; const auto phaseBarFixed { getValue( j, "PhaseBarFixed" ) }; LauMagPhaseCPCoeffSet coeff{ name, mag, phase, magBar, phaseBar, magFixed, phaseFixed, magBarFixed, phaseBarFixed }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauMagPhaseCoeffSet.cc b/src/LauMagPhaseCoeffSet.cc index 5898f63..8474a75 100644 --- a/src/LauMagPhaseCoeffSet.cc +++ b/src/LauMagPhaseCoeffSet.cc @@ -1,278 +1,278 @@ /* 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 "LauJsonTools.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauMagPhaseCoeffSet) LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const TString& compName, const Double_t magnitude, const Double_t phase, const Bool_t magFixed, const Bool_t phaseFixed) : LauAbsCoeffSet{ compName }, magnitude_{ std::make_unique("Mag", magnitude, minMagnitude_, maxMagnitude_, magFixed) }, phase_{ std::make_unique("Phase", phase, minPhase_, maxPhase_, phaseFixed) } { } LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, coeff_{ rhs.coeff_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { magnitude_.reset( rhs.magnitude_->createClone(constFactor) ); } else { const auto magVal { getOptionalValue( coeffInfo, "Mag", JsonType::Number ).value_or( rhs.magnitude_->value() ) }; const auto magFixed { getOptionalValue( coeffInfo, "MagFixed", JsonType::Boolean ).value_or( rhs.magnitude_->fixed() ) }; magnitude_ = std::make_unique("Mag", magVal, minMagnitude_, maxMagnitude_, magFixed); if ( getOptionalValue( coeffInfo, "MagBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "MagBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "MagBlindingWidth" ) }; magnitude_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.magnitude_->blind() ) { const LauBlind* blinder { rhs.magnitude_->blinder() }; magnitude_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase ) { phase_.reset( rhs.phase_->createClone(constFactor) ); } else { const auto phaseVal { getOptionalValue( coeffInfo, "Phase", JsonType::Number ).value_or( rhs.phase_->value() ) }; const auto phaseFixed { getOptionalValue( coeffInfo, "PhaseFixed", JsonType::Boolean ).value_or( rhs.phase_->fixed() ) }; phase_ = std::make_unique("Phase", phaseVal, minPhase_, maxPhase_, phaseFixed); if ( getOptionalValue( coeffInfo, "PhaseBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "PhaseBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "PhaseBlindingWidth" ) }; phase_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.phase_->blind() ) { const LauBlind* blinder { rhs.phase_->blinder() }; phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } void LauMagPhaseCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCoeffSet::printParValues : Component \""<name()<<"\" has "; std::cout<<"Mag = "<value()<<",\t"; std::cout<<"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 const Double_t mag { LauAbsCoeffSet::getRandomiser()->Rndm()*2.0 }; magnitude_->initValue(mag); magnitude_->value(mag); } if (phase_->fixed() == kFALSE) { // Choose a phase between +- pi const 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() }; // 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. const Double_t genPhase { phase_->genValue() }; const 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, const Bool_t init ) { LauComplex average{ coeff }; average += coeffBar; average.rescale( 0.5 ); const Double_t magVal{ average.abs() }; const 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() { const TString parName{ this->baseName() + "_ACP" }; return LauParameter{ parName, 0.0 }; } LauMagPhaseCoeffSet* LauMagPhaseCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TiePhase || cloneOption == CloneOption::TieMagnitude ) ) { std::cerr << "ERROR in LauMagPhaseCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauMagPhaseCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauMagPhaseCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::MagPhase ) { throw LauWrongCoeffType{"Wrong coefficient type given to construct LauMagPhaseCoeffSet"}; } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauMagPhaseCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("Mag", JsonType::Number), std::make_pair("Phase", JsonType::Number), std::make_pair("MagFixed", JsonType::Boolean), std::make_pair("PhaseFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauMagPhaseCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto mag { getValue( j, "Mag" ) }; const auto phase { getValue( j, "Phase" ) }; const auto magFixed { getValue( j, "MagFixed" ) }; const auto phaseFixed { getValue( j, "PhaseFixed" ) }; LauMagPhaseCoeffSet coeff{ name, mag, phase, magFixed, phaseFixed }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauNSCCartesianCPCoeffSet.cc b/src/LauNSCCartesianCPCoeffSet.cc index 766f788..1503be7 100644 --- a/src/LauNSCCartesianCPCoeffSet.cc +++ b/src/LauNSCCartesianCPCoeffSet.cc @@ -1,511 +1,511 @@ /* 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 LauNSCCartesianCPCoeffSet.cc \brief File containing implementation of LauNSCCartesianCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauNSCCartesianCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" #include "LauRandom.hh" ClassImp(LauNSCCartesianCPCoeffSet) LauNSCCartesianCPCoeffSet::LauNSCCartesianCPCoeffSet(const TString& compName, const Bool_t finalStateIsF, const Double_t x, const Double_t y, const Double_t deltaX, const Double_t deltaY, const Bool_t xFixed, const Bool_t yFixed, const Bool_t deltaXFixed, const Bool_t deltaYFixed, const Bool_t deltaXSecondStage, const Bool_t deltaYSecondStage, const Double_t xPrime, const Double_t yPrime, const Double_t deltaXPrime, const Double_t deltaYPrime, const Bool_t xPrimeFixed, const Bool_t yPrimeFixed, const Bool_t deltaXPrimeFixed, const Bool_t deltaYPrimeFixed, const Bool_t deltaXPrimeSecondStage, const Bool_t deltaYPrimeSecondStage ) : LauAbsCoeffSet{ compName }, finalStateIsF_{ finalStateIsF }, x_{ std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed) }, y_{ std::make_unique("Y", y, minRealImagPart_, maxRealImagPart_, yFixed) }, deltaX_{ std::make_unique("DeltaX", deltaX, minDelta_, maxDelta_, deltaXFixed) }, deltaY_{ std::make_unique("DeltaY", deltaY, minDelta_, maxDelta_, deltaYFixed) }, xPrime_{ std::make_unique("XPrime", xPrime, minRealImagPart_, maxRealImagPart_, xPrimeFixed) }, yPrime_{ std::make_unique("YPrime", yPrime, minRealImagPart_, maxRealImagPart_, yPrimeFixed) }, deltaXPrime_{ std::make_unique("DeltaXPrime", deltaXPrime, minDelta_, maxDelta_, deltaXPrimeFixed) }, deltaYPrime_{ std::make_unique("DeltaYPrime", deltaYPrime, minDelta_, maxDelta_, deltaYPrimeFixed) }, acp_{ "ACP", 0.0, -1.0, 1.0, kTRUE } { if (deltaXSecondStage && !deltaXFixed) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if (deltaYSecondStage && !deltaYFixed) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } if (deltaXPrimeSecondStage && !deltaXPrimeFixed) { deltaXPrime_->secondStage(kTRUE); deltaXPrime_->initValue(0.0); } if (deltaYPrimeSecondStage && !deltaYPrimeFixed) { deltaYPrime_->secondStage(kTRUE); deltaYPrime_->initValue(0.0); } } LauNSCCartesianCPCoeffSet::LauNSCCartesianCPCoeffSet(const LauNSCCartesianCPCoeffSet& rhs, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, finalStateIsF_{ rhs.finalStateIsF_ }, coeffAf_{ rhs.coeffAf_ }, coeffAfbar_{ rhs.coeffAfbar_ }, coeffAbarf_{ rhs.coeffAbarf_ }, coeffAbarfbar_{ rhs.coeffAbarfbar_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); xPrime_.reset( rhs.xPrime_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto xPrimeVal { getOptionalValue( coeffInfo, "XPrime", JsonType::Number ).value_or( rhs.xPrime_->value() ) }; const auto xPrimeFixed { getOptionalValue( coeffInfo, "XPrimeFixed", JsonType::Boolean ).value_or( rhs.xPrime_->fixed() ) }; xPrime_ = std::make_unique("XPrime", xPrimeVal, minRealImagPart_, maxRealImagPart_, xPrimeFixed); if ( getOptionalValue( coeffInfo, "XPrimeBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XPrimeBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XPrimeBlindingWidth" ) }; xPrime_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.xPrime_->blind() ) { const LauBlind* blinder { rhs.xPrime_->blinder() }; xPrime_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); yPrime_.reset( rhs.yPrime_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto yPrimeVal { getOptionalValue( coeffInfo, "YPrime", JsonType::Number ).value_or( rhs.yPrime_->value() ) }; const auto yPrimeFixed { getOptionalValue( coeffInfo, "YPrimeFixed", JsonType::Boolean ).value_or( rhs.yPrime_->fixed() ) }; yPrime_ = std::make_unique("YPrime", yPrimeVal, minRealImagPart_, maxRealImagPart_, yPrimeFixed); if ( getOptionalValue( coeffInfo, "YPrimeBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YPrimeBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YPrimeBlindingWidth" ) }; yPrime_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.yPrime_->blind() ) { const LauBlind* blinder { rhs.yPrime_->blinder() }; yPrime_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { deltaX_.reset( rhs.deltaX_->createClone(constFactor) ); deltaY_.reset( rhs.deltaY_->createClone(constFactor) ); deltaXPrime_.reset( rhs.deltaXPrime_->createClone(constFactor) ); deltaYPrime_.reset( rhs.deltaYPrime_->createClone(constFactor) ); } else { const auto deltaXVal { getOptionalValue( coeffInfo, "DeltaX", JsonType::Number ).value_or( rhs.deltaX_->value() ) }; const auto deltaXFixed { getOptionalValue( coeffInfo, "DeltaXFixed", JsonType::Boolean ).value_or( rhs.deltaX_->fixed() ) }; const auto deltaXSecondStage { getOptionalValue( coeffInfo, "DeltaXSecondStage", JsonType::Boolean ).value_or( rhs.deltaX_->secondStage() ) }; const auto deltaYVal { getOptionalValue( coeffInfo, "DeltaY", JsonType::Number ).value_or( rhs.deltaY_->value() ) }; const auto deltaYFixed { getOptionalValue( coeffInfo, "DeltaYFixed", JsonType::Boolean ).value_or( rhs.deltaY_->fixed() ) }; const auto deltaYSecondStage { getOptionalValue( coeffInfo, "DeltaYSecondStage", JsonType::Boolean ).value_or( rhs.deltaY_->secondStage() ) }; deltaX_ = std::make_unique("DeltaX", deltaXVal, minDelta_, maxDelta_, deltaXFixed); deltaY_ = std::make_unique("DeltaY", deltaYVal, minDelta_, maxDelta_, deltaYFixed); if ( getOptionalValue( coeffInfo, "DeltaXBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaXBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaXBlindingWidth" ) }; deltaX_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaX_->blind() ) { const LauBlind* blinder { rhs.deltaX_->blinder() }; deltaX_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( getOptionalValue( coeffInfo, "DeltaYBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaYBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaYBlindingWidth" ) }; deltaY_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaY_->blind() ) { const LauBlind* blinder { rhs.deltaY_->blinder() }; deltaY_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto deltaXPrimeVal { getOptionalValue( coeffInfo, "DeltaXPrime", JsonType::Number ).value_or( rhs.deltaXPrime_->value() ) }; const auto deltaXPrimeFixed { getOptionalValue( coeffInfo, "DeltaXPrimeFixed", JsonType::Boolean ).value_or( rhs.deltaXPrime_->fixed() ) }; const auto deltaXPrimeSecondStage { getOptionalValue( coeffInfo, "DeltaXPrimeSecondStage", JsonType::Boolean ).value_or( rhs.deltaXPrime_->secondStage() ) }; const auto deltaYPrimeVal { getOptionalValue( coeffInfo, "DeltaYPrime", JsonType::Number ).value_or( rhs.deltaYPrime_->value() ) }; const auto deltaYPrimeFixed { getOptionalValue( coeffInfo, "DeltaYPrimeFixed", JsonType::Boolean ).value_or( rhs.deltaYPrime_->fixed() ) }; const auto deltaYPrimeSecondStage { getOptionalValue( coeffInfo, "DeltaYPrimeSecondStage", JsonType::Boolean ).value_or( rhs.deltaYPrime_->secondStage() ) }; deltaXPrime_ = std::make_unique("DeltaXPrime", deltaXPrimeVal, minDelta_, maxDelta_, deltaXPrimeFixed); deltaYPrime_ = std::make_unique("DeltaYPrime", deltaYPrimeVal, minDelta_, maxDelta_, deltaYPrimeFixed); if ( getOptionalValue( coeffInfo, "DeltaXPrimeBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaXPrimeBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaXPrimeBlindingWidth" ) }; deltaXPrime_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaXPrime_->blind() ) { const LauBlind* blinder { rhs.deltaXPrime_->blinder() }; deltaXPrime_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( getOptionalValue( coeffInfo, "DeltaYPrimeBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "DeltaYPrimeBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "DeltaYPrimeBlindingWidth" ) }; deltaYPrime_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaYPrime_->blind() ) { const LauBlind* blinder { rhs.deltaYPrime_->blinder() }; deltaYPrime_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( deltaXSecondStage && !deltaXFixed ) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } if ( deltaYSecondStage && !deltaYFixed ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } if ( deltaXPrimeSecondStage && !deltaXPrimeFixed ) { deltaXPrime_->secondStage(kTRUE); deltaXPrime_->initValue(0.0); } if ( deltaYPrimeSecondStage && !deltaYPrimeFixed ) { deltaYPrime_->secondStage(kTRUE); deltaYPrime_->initValue(0.0); } } } void LauNSCCartesianCPCoeffSet::printParValues() const { std::cout<<"INFO in LauNSCCartesianCPCoeffSet::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()<<",\t"; std::cout<<"XPrime = "<value()<<",\t"; std::cout<<"YPrime = "<value()<<",\t"; std::cout<<"Delta xPrime = "<value()<<",\t"; std::cout<<"Delta yPrime = "<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<<"$ & $"; print.printFormat(stream, xPrime_->value()); stream<<" \\pm "; print.printFormat(stream, xPrime_->error()); stream<<"$ & $"; print.printFormat(stream, yPrime_->value()); stream<<" \\pm "; print.printFormat(stream, yPrime_->error()); stream<<"$ & $"; print.printFormat(stream, deltaXPrime_->value()); stream<<" \\pm "; print.printFormat(stream, deltaXPrime_->error()); stream<<"$ & $"; print.printFormat(stream, deltaYPrime_->value()); stream<<" \\pm "; print.printFormat(stream, deltaYPrime_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a value for "X" between -3.0 and 3.0 const Double_t value { LauRandom::zeroSeedRandom()->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 const Double_t value { LauRandom::zeroSeedRandom()->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 const Double_t value { LauRandom::zeroSeedRandom()->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 const Double_t value { LauRandom::zeroSeedRandom()->Rndm()*1.0 - 0.5 }; deltaY_->initValue(value); deltaY_->value(value); } if (xPrime_->fixed() == kFALSE) { // Choose a value for "XPrime" between -3.0 and 3.0 const Double_t value { LauRandom::zeroSeedRandom()->Rndm()*6.0 - 3.0 }; xPrime_->initValue(value); xPrime_->value(value); } if (yPrime_->fixed() == kFALSE) { // Choose a value for "YPrime" between -3.0 and 3.0 const Double_t value { LauRandom::zeroSeedRandom()->Rndm()*6.0 - 3.0 }; yPrime_->initValue(value); yPrime_->value(value); } if (deltaXPrime_->fixed() == kFALSE && deltaXPrime_->secondStage() == kFALSE) { // Choose a value for "Delta XPrime" between -0.5 and 0.5 const Double_t value { LauRandom::zeroSeedRandom()->Rndm()*1.0 - 0.5 }; deltaXPrime_->initValue(value); deltaXPrime_->value(value); } if (deltaYPrime_->fixed() == kFALSE && deltaYPrime_->secondStage() == kFALSE) { // Choose a value for "Delta YPrime" between -0.5 and 0.5 const Double_t value { LauRandom::zeroSeedRandom()->Rndm()*1.0 - 0.5 }; deltaYPrime_->initValue(value); deltaYPrime_->value(value); } } void LauNSCCartesianCPCoeffSet::finaliseValues() { // update the pulls x_->updatePull(); y_->updatePull(); deltaX_->updatePull(); deltaY_->updatePull(); xPrime_->updatePull(); yPrime_->updatePull(); deltaXPrime_->updatePull(); deltaYPrime_->updatePull(); } const LauComplex& LauNSCCartesianCPCoeffSet::particleCoeff() { if ( finalStateIsF_ ) { coeffAf_.setRealImagPart( x_->value() + deltaX_->value(), y_->value() + deltaY_->value() ); return coeffAf_; } else { coeffAfbar_.setRealImagPart( xPrime_->value() + deltaXPrime_->value(), yPrime_->value() + deltaYPrime_->value() ); return coeffAfbar_; } } const LauComplex& LauNSCCartesianCPCoeffSet::antiparticleCoeff() { if ( finalStateIsF_ ) { coeffAbarf_.setRealImagPart( xPrime_->value() - deltaXPrime_->value(), yPrime_->value() - deltaYPrime_->value() ); return coeffAbarf_; } else { coeffAbarfbar_.setRealImagPart( x_->value() - deltaX_->value(), y_->value() - deltaY_->value() ); return coeffAbarfbar_; } } void LauNSCCartesianCPCoeffSet::setCoeffValues( const LauComplex&, const LauComplex&, Bool_t ) { std::cerr << "ERROR in LauNSCCartesianCPCoeffSet::setCoeffValues : Method not supported by this class - too many parameters" << std::endl; } LauParameter LauNSCCartesianCPCoeffSet::acp() { // set the name const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // a single ACP parameter doesn't really make much sense here const Double_t value{0.0}; const Double_t error{0.0}; // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauNSCCartesianCPCoeffSet* LauNSCCartesianCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauNSCCartesianCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauNSCCartesianCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } void LauNSCCartesianCPCoeffSet::serialiseToJson( nlohmann::json& j ) const { // Call the base class method to do most of the work LauAbsCoeffSet::serialiseToJson(j); j["finalStateIsF"] = this->finalStateIsF(); } //! \cond DOXYGEN_IGNORE LauNSCCartesianCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::NSCCartesianCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauNSCCartesianCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauNSCCartesianCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("DeltaX", JsonType::Number), std::make_pair("DeltaY", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("DeltaXFixed", JsonType::Boolean), std::make_pair("DeltaYFixed", JsonType::Boolean), std::make_pair("XPrime", JsonType::Number), std::make_pair("YPrime", JsonType::Number), std::make_pair("DeltaXPrime", JsonType::Number), std::make_pair("DeltaYPrime", JsonType::Number), std::make_pair("XPrimeFixed", JsonType::Boolean), std::make_pair("YPrimeFixed", JsonType::Boolean), std::make_pair("DeltaXPrimeFixed", JsonType::Boolean), std::make_pair("DeltaYPrimeFixed", JsonType::Boolean), }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauNSCCartesianCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto finalStateIsF { getValue( j, "finalStateIsF" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto deltaX { getValue( j, "DeltaX" ) }; const auto deltaY { getValue( j, "DeltaY" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto deltaXFixed { getValue( j, "DeltaXFixed" ) }; const auto deltaYFixed { getValue( j, "DeltaYFixed" ) }; const auto deltaXSecondStage { getOptionalValue( j, "DeltaXSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto deltaYSecondStage { getOptionalValue( j, "DeltaYSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto xPrime { getValue( j, "XPrime" ) }; const auto yPrime { getValue( j, "YPrime" ) }; const auto deltaXPrime { getValue( j, "DeltaXPrime" ) }; const auto deltaYPrime { getValue( j, "DeltaYPrime" ) }; const auto xPrimeFixed { getValue( j, "XPrimeFixed" ) }; const auto yPrimeFixed { getValue( j, "YPrimeFixed" ) }; const auto deltaXPrimeFixed { getValue( j, "DeltaXPrimeFixed" ) }; const auto deltaYPrimeFixed { getValue( j, "DeltaYPrimeFixed" ) }; const auto deltaXPrimeSecondStage { getOptionalValue( j, "DeltaXPrimeSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; const auto deltaYPrimeSecondStage { getOptionalValue( j, "DeltaYPrimeSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; LauNSCCartesianCPCoeffSet coeff{ name, finalStateIsF, x, y, deltaX, deltaY, xFixed, yFixed, deltaXFixed, deltaYFixed, deltaXSecondStage, deltaYSecondStage, xPrime, yPrime, deltaXPrime, deltaYPrime, xPrimeFixed, yPrimeFixed, deltaXPrimeFixed, deltaYPrimeFixed, deltaXPrimeSecondStage, deltaYPrimeSecondStage }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauParameter.cc b/src/LauParameter.cc index d7bc17f..0142ed6 100644 --- a/src/LauParameter.cc +++ b/src/LauParameter.cc @@ -1,685 +1,685 @@ /* 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 "LauParameter.hh" #include "LauJsonTools.hh" #include "LauRandom.hh" #include "TRandom.h" #include #include ClassImp(LauParameter) LauParameter::LauParameter(const TString& parName) : name_{parName} { } LauParameter::LauParameter(const Double_t parValue) : value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{parValue-1e-6}, maxValue_{parValue+1e-6} { } LauParameter::LauParameter(const TString& parName, const Double_t parValue) : name_{parName}, value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{parValue-1e-6}, maxValue_{parValue+1e-6} { } LauParameter::LauParameter(const Double_t parValue, const Double_t min, const Double_t max) : value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max} { this->checkRange(); } LauParameter::LauParameter(const Double_t parValue, const Double_t parError, const Double_t min, const Double_t max) : value_{parValue}, error_{parError}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max} { this->checkRange(); } LauParameter::LauParameter(const Double_t parValue, const Double_t min, const Double_t max, const Bool_t parFixed) : value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max}, fixed_{parFixed} { this->checkRange(); } LauParameter::LauParameter(const TString& parName, const Double_t parValue, const Double_t min, const Double_t max) : name_{parName}, value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max} { this->checkRange(); } LauParameter::LauParameter(const TString& parName, const Double_t parValue, const Double_t min, const Double_t max, const Bool_t parFixed) : name_{parName}, value_{parValue}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max}, fixed_{parFixed} { this->checkRange(); } LauParameter::LauParameter(const TString& parName, const Double_t parValue, const Double_t parError, const Double_t min, const Double_t max) : name_{parName}, value_{parValue}, error_{parError}, genValue_{parValue}, initValue_{parValue}, minValue_{min}, maxValue_{max} { this->checkRange(); } LauParameter::~LauParameter() noexcept { // if we're a clone, we just need to inform our parent of our demise if ( this->clone() ) { parent_->removeFromCloneList(this); return; } // if we have no clones there's nothing to do if ( clones_.empty() ) { return; } // otherwise if we have clones we need to make one of them the new parent and inform the rest of the change // let's (arbitrarily) make the first parameter in the map the new parent auto iter = clones_.begin(); auto [ newParent, constFactor ] { *iter }; // remove that entry in the map clones_.erase(iter); // for all the other entries, we need to tell them they are clones of the new parent // and also rescale the constants so that they are relative to the new parent for ( auto& [ theClone, theFactor ] : clones_ ) { theClone->clone(newParent); theFactor /= constFactor; } // transfer the list of clones to the new parent newParent->clones_ = std::move(clones_); // finally, the new parent has to be told that it isn't a clone anymore newParent->clone(nullptr); } std::vector LauParameter::getPars() { std::vector list; list.push_back(this); return list; } void LauParameter::value(const Double_t newValue) { if (this->clone()) { parent_->value(newValue); } else { this->checkRange(newValue,this->minValue(),this->maxValue()); this->updateClones(kTRUE); } } void LauParameter::error(const Double_t newError) { if (this->clone()) { parent_->error(newError); } else { error_ = TMath::Abs(newError); this->updateClones(kFALSE); } } void LauParameter::negError(const Double_t newNegError) { if (this->clone()) { parent_->negError(newNegError); } else { negError_ = TMath::Abs(newNegError); this->updateClones(kFALSE); } } void LauParameter::posError(const Double_t newPosError) { if (this->clone()) { parent_->posError(newPosError); } else { posError_ = TMath::Abs(newPosError); this->updateClones(kFALSE); } } void LauParameter::errors(const Double_t newError, const Double_t newNegError, const 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(const Double_t newValue, const Double_t newError, const Double_t newNegError, const 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(const Double_t newGCCValue) { if (this->clone()) { parent_->globalCorrelationCoeff(newGCCValue); } else { gcc_ = newGCCValue; this->updateClones(kFALSE); } } void LauParameter::genValue(const Double_t newGenValue) { if (this->clone()) { parent_->genValue(newGenValue); } else { genValue_ = newGenValue; this->updateClones(kFALSE); } } void LauParameter::initValue(const Double_t newInitValue) { if (this->clone()) { parent_->initValue(newInitValue); } else { initValue_ = newInitValue; this->updateClones(kFALSE); } } void LauParameter::minValue(const Double_t newMinValue) { if (this->clone()) { parent_->minValue(newMinValue); } else { this->checkRange(this->value(),newMinValue,this->maxValue()); this->updateClones(kFALSE); } } void LauParameter::maxValue(const Double_t newMaxValue) { if (this->clone()) { parent_->maxValue(newMaxValue); } else { this->checkRange(this->value(),this->minValue(),newMaxValue); this->updateClones(kFALSE); } } void LauParameter::range(const Double_t newMinValue, const Double_t newMaxValue) { if (this->clone()) { parent_->range(newMinValue,newMaxValue); } else { this->checkRange(this->value(),newMinValue,newMaxValue); this->updateClones(kFALSE); } } void LauParameter::valueAndRange(const Double_t newValue, const Double_t newMinValue, const 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(const Bool_t parFixed) { if (this->clone()) { parent_->fixed(parFixed); } else { fixed_ = parFixed; this->updateClones(kFALSE); } } void LauParameter::secondStage(const Bool_t secondStagePar) { if (this->clone()) { parent_->secondStage(secondStagePar); } else { secondStage_ = secondStagePar; this->updateClones(kFALSE); } } void LauParameter::addGaussianConstraint(const Double_t newGaussMean, const Double_t newGaussWidth) { if (this->clone()) { parent_->addGaussianConstraint(newGaussMean,newGaussWidth); } else { gaussConstraint_ = kTRUE; constraintMean_ = newGaussMean; constraintWidth_ = newGaussWidth; this->updateClones(kFALSE); } } void LauParameter::removeGaussianConstraint() { if (this->clone()) { parent_->removeGaussianConstraint(); } else { gaussConstraint_ = kFALSE; this->updateClones(kFALSE); } } void LauParameter::blindParameter(const TString& blindingString, const Double_t width, const Bool_t flipSign) { if (this->clone()) { parent_->blindParameter(blindingString,width,flipSign); return; } if ( blinder_.active() ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for this parameter" << std::endl; return; } blinder_ = LauBlind{ blindingString, width, flipSign }; for ( auto& [ clonePar, _ ] : clones_ ) { if ( clonePar->blinder_.active() ) { std::cerr << "WARNING in LauParameter::blindParameter : blinding has already been set up for a clone of this parameter - it will be replaced!" << std::endl; } clonePar->blinder_ = 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(const Double_t val, const Double_t minVal, const Double_t maxVal) { // first check that min is less than max (or they are the same - this is allowed) if (minVal > maxVal) { std::cerr<<"ERROR in LauParameter::checkRange : minValue: "< maxValue_) { minValue_ = maxValue_; std::cerr<<" : Setting both to "< maxVal)) { if (name_ != "") { std::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, const 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(const 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->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(const Double_t minVal, const Double_t maxVal) { // if we're fixed then do nothing if (this->fixed()) { return; } // check supplied values are sensible if (maxVal < minVal) { std::cerr<<"ERROR in LauParameter::randomiseValue : Supplied maximum value smaller than minimum value."<Uniform( TMath::Max( minVal, this->minValue() ), TMath::Min( maxVal, this->maxValue() ) ) }; this->initValue(val); } void LauParameter::serialiseToJson( nlohmann::json& j ) const { using nlohmann::json; LauAbsRValue::serialiseToJson( j ); // First check whether this is a clone because there's much less to do if it is const Bool_t cloned { this->clone() }; j["clone"] = cloned; if ( cloned ) { j["parent"] = parent_->name(); auto me {const_cast(this)}; j["constFactor"] = parent_->clones_.at(me); return; } // TODO - do we need to write this? // - I guess it's maybe useful for a human reader but we don't use it at all in deserialisation if ( ! clones_.empty() ) { j["clones"] = json::array(); for ( auto& [ par, factor ] : clones_ ) { json obj = json::object( { {"name", par->name()}, {"factor", factor} } ); j["clones"].push_back( obj ); } } j["value"] = value_; j["genValue"] = genValue_; j["initValue"] = initValue_; j["error"] = error_; j["negError"] = negError_; j["posError"] = posError_; j["minValue"] = minValue_; j["maxValue"] = maxValue_; j["secondStage"] = secondStage_; j["gcc"] = gcc_; j["bias"] = bias_; j["pull"] = pull_; j["fixed"] = fixed_; const Bool_t blind { this->blind() }; j["blind"] = blind; if ( blind ) { j["blindingString"] = blinder_.blindingString(); j["blindingWidth"] = blinder_.blindingWidth(); j["blindingFlip"] = blinder_.flipSign(); } const Bool_t gaussCons { this->gaussConstraint() }; j["gaussConstraint"] = gaussCons; if ( gaussCons ) { j["constraintMean"] = this->constraintMean(); j["constraintWidth"] = this->constraintWidth(); } } // ostream operator std::ostream& operator<<(std::ostream& stream, const LauParameter& par) { stream << par.name() << " : "; stream << par.value(); if ( par.negError() > 1e-10 && par.posError() > 1e-10 ) { stream << " +/- (" << par.negError() << ", " << par.posError() << ")"; } else if ( par.error() > 1e-10 ) { stream << " +/- " << par.error(); } if ( par.fixed() ) { stream << " C"; } stream << " L(" << par.minValue() << ", " << par.maxValue() << ")"; if ( par.blind() ) { stream << " BLIND(" << par.blinder()->blindingString() << ", " << par.blinder()->blindingWidth() << ", " << std::boolalpha << par.blinder()->flipSign() << ")"; } return stream; } //! \cond DOXYGEN_IGNORE LauParameter nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::getValue; const auto isLValue { getValue( j, "isLValue" ) }; if ( ! isLValue ) { throw LauJsonTools::InvalidJson{"Cannot create LauParameter from non L-value"}; } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauJsonTools::InvalidJson{"Cannot create cloned LauParameter standalone"}; } // Get everything we need to construct the parameter const auto name { getValue( j, "name" ) }; const auto value { getValue( j, "value" ) }; const auto minValue { getValue( j, "minValue" ) }; const auto maxValue { getValue( j, "maxValue" ) }; const auto fixed { getValue( j, "fixed" ) }; LauParameter par { name, value, minValue, maxValue, fixed }; // Then get any additional information and use the appropriate functions to set the values const auto genValue { getValue( j, "genValue" ) }; par.genValue( genValue ); const auto initValue { getValue( j, "initValue" ) }; par.initValue( initValue ); const auto error { getValue( j, "error" ) }; const auto negError { getValue( j, "negError" ) }; const auto posError { getValue( j, "posError" ) }; par.errors( error, negError, posError ); par.updatePull(); const auto secondStage { getValue( j, "secondStage" ) }; par.secondStage( secondStage ); const auto gcc { getValue( j, "gcc" ) }; par.globalCorrelationCoeff( gcc ); const auto gaussCons { getValue( j, "gaussConstraint" ) }; if ( gaussCons ) { const auto mean { getValue( j, "constraintMean" ) }; const auto width { getValue( j, "constraintWidth" ) }; par.addGaussianConstraint( mean, width ); } const auto blind { getValue( j, "blind" ) }; if ( blind ) { const auto blindingStr { getValue( j, "blindingString" ) }; const auto blindingWidth { getValue( j, "blindingWidth" ) }; const auto blindingFlip { getValue( j, "blindingFlip" ) }; par.blindParameter( blindingStr, blindingWidth, blindingFlip ); } return par; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauPolarGammaCPCoeffSet.cc b/src/LauPolarGammaCPCoeffSet.cc index 6c44d06..7c237a9 100644 --- a/src/LauPolarGammaCPCoeffSet.cc +++ b/src/LauPolarGammaCPCoeffSet.cc @@ -1,1042 +1,1042 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" std::shared_ptr LauPolarGammaCPCoeffSet::gammaGlobal_; std::shared_ptr LauPolarGammaCPCoeffSet::rDGlobal_; std::shared_ptr LauPolarGammaCPCoeffSet::deltaDGlobal_; 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 }, useGlobalGamma_{ useGlobalGamma }, useGlobalADSPars_{ useGlobalADSPars }, acp_{ "ACP", 0.0, -1.0, 1.0 } { // All of the possible D decay types need these two parameters x_ = std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed); y_ = std::make_unique("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_ = std::make_shared("gamma", gamma, minPhase_, maxPhase_, gammaFixed); gamma_ = gammaGlobal_; } else { gamma_.reset( gammaGlobal_->createClone() ); } } else { gamma_ = std::make_shared("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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { rB_ = std::make_unique("rB", rB, minMagnitude_, maxMagnitude_, rBFixed); deltaB_ = std::make_unique("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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { if (useGlobalADSPars_) { if ( !rDGlobal_ ) { rDGlobal_ = std::make_shared("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaDGlobal_ = std::make_shared("deltaD", deltaD, minPhase_, maxPhase_, deltaDFixed); rD_ = rDGlobal_; deltaD_ = deltaDGlobal_; } else { rD_.reset( rDGlobal_->createClone() ); deltaD_.reset( deltaDGlobal_->createClone() ); } } else { rD_ = std::make_shared("rD", rD, minMagnitude_, maxMagnitude_, rDFixed); deltaD_ = std::make_shared("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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, decayType_{ rhs.decayType_ }, useGlobalGamma_{ rhs.useGlobalGamma_ }, useGlobalADSPars_{ rhs.useGlobalADSPars_ }, nonCPPart_{ rhs.nonCPPart_ }, cpPart_{ rhs.cpPart_ }, cpAntiPart_{ rhs.cpAntiPart_ }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { gamma_.reset( rhs.gamma_->createClone(constFactor) ); if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { rB_.reset( rhs.rB_->createClone(constFactor) ); deltaB_.reset( rhs.deltaB_->createClone(constFactor) ); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { rD_.reset( rhs.rD_->createClone(constFactor) ); deltaD_.reset( rhs.deltaD_->createClone(constFactor) ); } } else { if (useGlobalGamma_) { gamma_.reset( gammaGlobal_->createClone() ); } else { const auto gammaVal { getOptionalValue( coeffInfo, "gamma", JsonType::Number ).value_or( rhs.gamma_->value() ) }; const auto gammaFixed { getOptionalValue( coeffInfo, "gammaFixed", JsonType::Boolean ).value_or( rhs.gamma_->fixed() ) }; const auto gammaSecondStage { getOptionalValue( coeffInfo, "gammaSecondStage", JsonType::Boolean ).value_or( rhs.gamma_->secondStage() ) }; gamma_ = std::make_shared("gamma", gammaVal, minPhase_, maxPhase_, gammaFixed); if ( gammaSecondStage && !gammaFixed ) { gamma_->secondStage(kTRUE); gamma_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "gammaBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "gammaBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "gammaBlindingWidth" ) }; gamma_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.gamma_->blind() ) { const LauBlind* blinder { rhs.gamma_->blinder() }; gamma_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { const auto rBVal { getOptionalValue( coeffInfo, "rB", JsonType::Number ).value_or( rhs.rB_->value() ) }; const auto rBFixed { getOptionalValue( coeffInfo, "rBFixed", JsonType::Boolean ).value_or( rhs.rB_->fixed() ) }; const auto rBSecondStage { getOptionalValue( coeffInfo, "rBSecondStage", JsonType::Boolean ).value_or( rhs.rB_->secondStage() ) }; rB_ = std::make_unique("rB", rBVal, minMagnitude_, maxMagnitude_, rBFixed); if ( rBSecondStage && !rBFixed ) { rB_->secondStage(kTRUE); rB_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "rBBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "rBBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "rBBlindingWidth" ) }; rB_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.rB_->blind() ) { const LauBlind* blinder { rhs.rB_->blinder() }; rB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto deltaBVal { getOptionalValue( coeffInfo, "deltaB", JsonType::Number ).value_or( rhs.deltaB_->value() ) }; const auto deltaBFixed { getOptionalValue( coeffInfo, "deltaBFixed", JsonType::Boolean ).value_or( rhs.deltaB_->fixed() ) }; const auto deltaBSecondStage { getOptionalValue( coeffInfo, "deltaBSecondStage", JsonType::Boolean ).value_or( rhs.deltaB_->secondStage() ) }; deltaB_ = std::make_unique("deltaB", deltaBVal, minPhase_, maxPhase_, deltaBFixed); if ( deltaBSecondStage && !deltaBFixed ) { deltaB_->secondStage(kTRUE); deltaB_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "deltaBBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "deltaBBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "deltaBBlindingWidth" ) }; deltaB_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaB_->blind() ) { const LauBlind* blinder { rhs.deltaB_->blinder() }; deltaB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { if ( useGlobalADSPars_ ) { rD_.reset( rDGlobal_->createClone() ); deltaD_.reset( deltaDGlobal_->createClone() ); } else { const auto rDVal { getOptionalValue( coeffInfo, "rD", JsonType::Number ).value_or( rhs.rD_->value() ) }; const auto rDFixed { getOptionalValue( coeffInfo, "rDFixed", JsonType::Boolean ).value_or( rhs.rD_->fixed() ) }; const auto rDSecondStage { getOptionalValue( coeffInfo, "rDSecondStage", JsonType::Boolean ).value_or( rhs.rD_->secondStage() ) }; rD_ = std::make_unique("rD", rDVal, minMagnitude_, maxMagnitude_, rDFixed); if ( rDSecondStage && !rDFixed ) { rD_->secondStage(kTRUE); rD_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "rDBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "rDBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "rDBlindingWidth" ) }; rD_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.rD_->blind() ) { const LauBlind* blinder { rhs.rD_->blinder() }; rD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto deltaDVal { getOptionalValue( coeffInfo, "deltaD", JsonType::Number ).value_or( rhs.deltaD_->value() ) }; const auto deltaDFixed { getOptionalValue( coeffInfo, "deltaDFixed", JsonType::Boolean ).value_or( rhs.deltaD_->fixed() ) }; const auto deltaDSecondStage { getOptionalValue( coeffInfo, "deltaDSecondStage", JsonType::Boolean ).value_or( rhs.deltaD_->secondStage() ) }; deltaD_ = std::make_unique("deltaD", deltaDVal, minPhase_, maxPhase_, deltaDFixed); if ( deltaDSecondStage && !deltaDFixed ) { deltaD_->secondStage(kTRUE); deltaD_->initValue(0.0); } if ( getOptionalValue( coeffInfo, "deltaDBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "deltaDBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "deltaDBlindingWidth" ) }; deltaD_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.deltaD_->blind() ) { const LauBlind* blinder { rhs.deltaD_->blinder() }; deltaD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } } } void LauPolarGammaCPCoeffSet::adjustName(LauParameter& par, const TString& oldBaseName) { if ( ( &par == gamma_.get() && useGlobalGamma_ ) || ( &par == rD_.get() && useGlobalADSPars_ ) || ( &par == deltaD_.get() && 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.reserve(7); pars.push_back(x_.get()); pars.push_back(y_.get()); pars.push_back(gamma_.get()); if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { pars.push_back(rB_.get()); pars.push_back(deltaB_.get()); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { pars.push_back(rD_.get()); pars.push_back(deltaD_.get()); } return pars; } std::vector LauPolarGammaCPCoeffSet::getParameters() const { std::vector pars; pars.reserve(7); pars.push_back(x_.get()); pars.push_back(y_.get()); pars.push_back(gamma_.get()); if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { pars.push_back(rB_.get()); pars.push_back(deltaB_.get()); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { pars.push_back(rD_.get()); pars.push_back(deltaD_.get()); } return pars; } std::vector LauPolarGammaCPCoeffSet::getParNames() const { std::vector pars; pars.reserve(7); pars.push_back("X"); pars.push_back("Y"); pars.push_back("gamma"); if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { pars.push_back("rB"); pars.push_back("deltaB"); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { pars.push_back("rD"); 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { std::cout<<"rB = "<value()<<",\t"; std::cout<<"deltaB = "<value()<<",\t"; } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == 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 const 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 const 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 const Double_t value { LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi }; gamma_->initValue(value); gamma_->value(value); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { if (rB_->fixed() == kFALSE && rB_->secondStage() == kFALSE) { // Choose a value for "rB" between 0.0 and 2.0 const 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 const Double_t value { LauAbsCoeffSet::getRandomiser()->Rndm()*LauConstants::twoPi - LauConstants::pi }; deltaB_->initValue(value); deltaB_->value(value); } } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { if (rD_->fixed() == kFALSE && rD_->secondStage() == kFALSE) { // Choose a value for "rD" between 0.0 and 2.0 const 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 const 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { rBVal = rB_->value(); deltaBVal = deltaB_->value(); genDeltaB = deltaB_->genValue(); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == 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_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { rB_->value(rBVal); rB_->updatePull(); deltaB_->value(deltaBVal); deltaB_->updatePull(); } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == 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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 const TString parName{ this->baseName() + "_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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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 DecayType::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_; } LauPolarGammaCPCoeffSet* LauPolarGammaCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauPolarGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauPolarGammaCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } std::ostream& operator<<( std::ostream& os, const LauPolarGammaCPCoeffSet::DecayType type ) { using DecayType = LauPolarGammaCPCoeffSet::DecayType; switch ( type ) { case DecayType::GLW_CPOdd : os << "GLW_CPOdd"; break; case DecayType::GLW_CPEven : os << "GLW_CPEven"; break; case DecayType::ADS_Favoured : os << "ADS_Favoured"; break; case DecayType::ADS_Suppressed : os << "ADS_Suppressed"; break; case DecayType::GLW_CPOdd_btouOnly : os << "GLW_CPOdd_btouOnly"; break; case DecayType::GLW_CPEven_btouOnly : os << "GLW_CPEven_btouOnly"; break; case DecayType::ADS_Favoured_btouOnly : os << "ADS_Favoured_btouOnly"; break; case DecayType::ADS_Suppressed_btouOnly : os << "ADS_Suppressed_btouOnly"; break; } return os; } void LauPolarGammaCPCoeffSet::serialiseToJson( nlohmann::json& j ) const { // Call the base class method to do most of the work LauAbsCoeffSet::serialiseToJson(j); const LauPolarGammaCPCoeffSet::DecayType decayType { this->decayType() }; j["decayType"] = decayType; j["useGlobalGamma"] = this->useGlobalGamma(); j["useGlobalADSPars"] = this->useGlobalADSPars(); if ( this->useGlobalGamma() && gamma_->clone() ) { j["gamma"] = gamma_->value(); j["gammaFixed"] = gamma_->fixed(); j["gammaSecondStage"] = gamma_->secondStage(); } if ( this->useGlobalADSPars() && rD_ && rD_->clone() ) { j["rD"] = rD_->value(); j["rDFixed"] = rD_->fixed(); j["rDSecondStage"] = rD_->secondStage(); } if ( this->useGlobalADSPars() && deltaD_ && deltaD_->clone() ) { j["deltaD"] = deltaD_->value(); j["deltaDFixed"] = deltaD_->fixed(); j["deltaDSecondStage"] = deltaD_->secondStage(); } } //! \cond DOXYGEN_IGNORE LauPolarGammaCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; using DecayType = LauPolarGammaCPCoeffSet::DecayType; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::PolarGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauPolarGammaCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauPolarGammaCPCoeffSet standalone"}; } const auto decayType { getValue( j, "decayType" ) }; std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("Y", JsonType::Number), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("gamma", JsonType::Number), std::make_pair("gammaFixed", JsonType::Boolean) }; if ( decayType == DecayType::ADS_Favoured || decayType == DecayType::ADS_Suppressed || decayType == DecayType::GLW_CPOdd || decayType == DecayType::GLW_CPEven ) { mandatoryElements.push_back( std::make_pair( "rB", JsonType::Number ) ); mandatoryElements.push_back( std::make_pair( "rBFixed", JsonType::Boolean ) ); mandatoryElements.push_back( std::make_pair( "deltaB", JsonType::Number ) ); mandatoryElements.push_back( std::make_pair( "deltaBFixed", JsonType::Boolean ) ); } if ( decayType == DecayType::ADS_Favoured || decayType == DecayType::ADS_Suppressed || decayType == DecayType::ADS_Favoured_btouOnly ) { mandatoryElements.push_back( std::make_pair( "rD", JsonType::Number ) ); mandatoryElements.push_back( std::make_pair( "rDFixed", JsonType::Boolean ) ); mandatoryElements.push_back( std::make_pair( "deltaD", JsonType::Number ) ); mandatoryElements.push_back( std::make_pair( "deltaDFixed", JsonType::Boolean ) ); } if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauPolarGammaCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto useGlobalGamma { getOptionalValue( j, "useGlobalGamma", JsonType::Boolean ).value_or( kFALSE ) }; const auto useGlobalADSPars { getOptionalValue( j, "useGlobalADSPars", JsonType::Boolean ).value_or( kFALSE ) }; const auto x { getValue( j, "X" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto y { getValue( j, "Y" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto gamma { getValue( j, "gamma" ) }; const auto gammaFixed { getValue( j, "gammaFixed" ) }; const auto gammaSecondStage { getOptionalValue( j, "gammaSecondStage", JsonType::Boolean ).value_or( kFALSE ) }; Double_t rB{0.0}; Bool_t rBFixed{kTRUE}; Bool_t rBSecondStage{kFALSE}; Double_t deltaB{0.0}; Bool_t deltaBFixed{kTRUE}; Bool_t deltaBSecondStage{kFALSE}; Double_t rD{0.0}; Bool_t rDFixed{kTRUE}; Bool_t rDSecondStage{kFALSE}; Double_t deltaD{0.0}; Bool_t deltaDFixed{kTRUE}; Bool_t deltaDSecondStage{kFALSE}; if ( decayType == DecayType::ADS_Favoured || decayType == DecayType::ADS_Suppressed || decayType == DecayType::GLW_CPOdd || decayType == DecayType::GLW_CPEven ) { rB = getValue( j, "rB" ); rBFixed = getValue( j, "rBFixed" ); rBSecondStage = getOptionalValue( j, "rBSecondStage", JsonType::Boolean ).value_or(kFALSE); deltaB = getValue( j, "deltaB" ); deltaBFixed = getValue( j, "deltaBFixed" ); deltaBSecondStage = getOptionalValue( j, "deltaBSecondStage", JsonType::Boolean ).value_or(kFALSE); } if ( decayType == DecayType::ADS_Favoured || decayType == DecayType::ADS_Suppressed || decayType == DecayType::ADS_Favoured_btouOnly ) { rD = getValue( j, "rD" ); rDFixed = getValue( j, "rDFixed" ); rDSecondStage = getOptionalValue( j, "rDSecondStage", JsonType::Boolean ).value_or(kFALSE); deltaD = getValue( j, "deltaD" ); deltaDFixed = getValue( j, "deltaDFixed" ); deltaDSecondStage = getOptionalValue( j, "deltaDSecondStage", JsonType::Boolean ).value_or(kFALSE); } LauPolarGammaCPCoeffSet coeff{ name, decayType, x, y, rB, deltaB, gamma, rD, deltaD, xFixed, yFixed, rBFixed, deltaBFixed, gammaFixed, rDFixed, deltaDFixed, rBSecondStage, deltaBSecondStage, gammaSecondStage, rDSecondStage, deltaDSecondStage, useGlobalGamma, useGlobalADSPars }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauRealImagCPCoeffSet.cc b/src/LauRealImagCPCoeffSet.cc index cef9c28..16dc604 100644 --- a/src/LauRealImagCPCoeffSet.cc +++ b/src/LauRealImagCPCoeffSet.cc @@ -1,335 +1,335 @@ /* 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.cc \brief File containing implementation of LauRealImagCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauRealImagCPCoeffSet) LauRealImagCPCoeffSet::LauRealImagCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xbar, const Double_t ybar, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xbarFixed, const Bool_t ybarFixed) : LauAbsCoeffSet{ compName }, x_{ std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed) }, y_{ std::make_unique("Y", y, minRealImagPart_, maxRealImagPart_, yFixed) }, xbar_{ std::make_unique("XBar", xbar, minRealImagPart_, maxRealImagPart_, xbarFixed) }, ybar_{ std::make_unique("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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); xbar_.reset( rhs.xbar_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto xbarVal { getOptionalValue( coeffInfo, "XBar", JsonType::Number ).value_or( rhs.xbar_->value() ) }; const auto xbarFixed { getOptionalValue( coeffInfo, "XBarFixed", JsonType::Boolean ).value_or( rhs.xbar_->fixed() ) }; xbar_ = std::make_unique("XBar", xbarVal, minRealImagPart_, maxRealImagPart_, xbarFixed); if ( getOptionalValue( coeffInfo, "XBarBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBarBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBarBlindingWidth" ) }; xbar_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.xbar_->blind() ) { const LauBlind* blinder { rhs.xbar_->blinder() }; xbar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); ybar_.reset( rhs.ybar_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto ybarVal { getOptionalValue( coeffInfo, "YBar", JsonType::Number ).value_or( rhs.ybar_->value() ) }; const auto ybarFixed { getOptionalValue( coeffInfo, "YBarFixed", JsonType::Boolean ).value_or( rhs.ybar_->fixed() ) }; ybar_ = std::make_unique("YBar", ybarVal, minRealImagPart_, maxRealImagPart_, ybarFixed); if ( getOptionalValue( coeffInfo, "YBarBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBarBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBarBlindingWidth" ) }; ybar_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.ybar_->blind() ) { const LauBlind* blinder { rhs.ybar_->blinder() }; ybar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 ) { const Double_t xVal{ coeff.re() }; const Double_t yVal{ coeff.im() }; const Double_t xBarVal{ coeffBar.re() }; const 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 const TString parName{ this->baseName() + "_ACP" }; acp_.name(parName); // work out the ACP value const Double_t csq { x_->value()*x_->value() + y_->value()*y_->value() }; const Double_t cbarsq { xbar_->value()*xbar_->value() + ybar_->value()*ybar_->value() }; const Double_t numer { cbarsq - csq }; const Double_t denom { cbarsq + csq }; const Double_t value { numer/denom }; // is it fixed? const 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 const Double_t error{0.0}; // set the value and error acp_.valueAndErrors(value,error); return acp_; } LauRealImagCPCoeffSet* LauRealImagCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart ) ) { std::cerr << "ERROR in LauRealImagCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauRealImagCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauRealImagCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::RealImagCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauRealImagCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("XBar", JsonType::Number), std::make_pair("YBar", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("XBarFixed", JsonType::Boolean), std::make_pair("YBarFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauRealImagCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto xbar { getValue( j, "XBar" ) }; const auto ybar { getValue( j, "YBar" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto xbarFixed { getValue( j, "XBarFixed" ) }; const auto ybarFixed { getValue( j, "YBarFixed" ) }; LauRealImagCPCoeffSet coeff{ name, x, y, xbar, ybar, xFixed, yFixed, xbarFixed, ybarFixed }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauRealImagCoeffSet.cc b/src/LauRealImagCoeffSet.cc index efcad1e..77a7fad 100644 --- a/src/LauRealImagCoeffSet.cc +++ b/src/LauRealImagCoeffSet.cc @@ -1,239 +1,239 @@ /* 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 "LauJsonTools.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauRealImagCoeffSet) LauRealImagCoeffSet::LauRealImagCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Bool_t xFixed, const Bool_t yFixed) : LauAbsCoeffSet{ compName }, x_{ std::make_unique("X",x,minRealImagPart_,maxRealImagPart_,xFixed) }, y_{ std::make_unique("Y",y,minRealImagPart_,maxRealImagPart_,yFixed) }, coeff_{ x,y } { } LauRealImagCoeffSet::LauRealImagCoeffSet(const LauRealImagCoeffSet& rhs, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, coeff_{ rhs.coeff_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 ); const Double_t xVal{ average.re() }; const 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() { const TString parName{ this->baseName() + "_ACP" }; return LauParameter{parName,0.0}; } LauRealImagCoeffSet* LauRealImagCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart ) ) { std::cerr << "ERROR in LauRealImagCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauRealImagCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauRealImagCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::RealImag ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauRealImagCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauRealImagCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; LauRealImagCoeffSet coeff{ name, x, y, xFixed, yFixed }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond diff --git a/src/LauRealImagGammaCPCoeffSet.cc b/src/LauRealImagGammaCPCoeffSet.cc index 10238a9..0fd33c0 100644 --- a/src/LauRealImagGammaCPCoeffSet.cc +++ b/src/LauRealImagGammaCPCoeffSet.cc @@ -1,398 +1,398 @@ /* 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 "LauJsonTools.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_{ std::make_unique("X", x, minRealImagPart_, maxRealImagPart_, xFixed) }, y_{ std::make_unique("Y", y, minRealImagPart_, maxRealImagPart_, yFixed) }, xCP_{ std::make_unique("XCP", xCP, minRealImagPart_, maxRealImagPart_, xCPFixed) }, yCP_{ std::make_unique("YCP", yCP, minRealImagPart_, maxRealImagPart_, yCPFixed) }, xbarCP_{ std::make_unique("XBarCP", xbarCP, minRealImagPart_, maxRealImagPart_, xbarCPFixed) }, ybarCP_{ std::make_unique("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, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) : LauAbsCoeffSet{ rhs.name(), rhs.baseName(), &rhs, cloneOption, constFactor }, nonCPPart_{ rhs.nonCPPart_ }, cpPart_{ rhs.cpPart_ }, cpAntiPart_{ rhs.cpAntiPart_ }, particleCoeff_{ rhs.particleCoeff_ }, antiparticleCoeff_{ rhs.antiparticleCoeff_ }, acp_{ rhs.acp_ } { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { const auto xVal { getOptionalValue( coeffInfo, "X", JsonType::Number ).value_or( rhs.x_->value() ) }; const auto xFixed { getOptionalValue( coeffInfo, "XFixed", JsonType::Boolean ).value_or( rhs.x_->fixed() ) }; x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); if ( getOptionalValue( coeffInfo, "XBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBlindingWidth" ) }; x_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); } else { const auto yVal { getOptionalValue( coeffInfo, "Y", JsonType::Number ).value_or( rhs.y_->value() ) }; const auto yFixed { getOptionalValue( coeffInfo, "YFixed", JsonType::Boolean ).value_or( rhs.y_->fixed() ) }; y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); if ( getOptionalValue( coeffInfo, "YBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBlindingWidth" ) }; y_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieCPPars ) { xCP_.reset( rhs.xCP_->createClone(constFactor) ); yCP_.reset( rhs.yCP_->createClone(constFactor) ); xbarCP_.reset( rhs.xbarCP_->createClone(constFactor) ); ybarCP_.reset( rhs.ybarCP_->createClone(constFactor) ); } else { const auto xCPVal { getOptionalValue( coeffInfo, "XCP", JsonType::Number ).value_or( rhs.xCP_->value() ) }; const auto xCPFixed { getOptionalValue( coeffInfo, "XCPFixed", JsonType::Boolean ).value_or( rhs.xCP_->fixed() ) }; xCP_ = std::make_unique("XCP", xCPVal, minRealImagPart_, maxRealImagPart_, xCPFixed); if ( getOptionalValue( coeffInfo, "XCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XCPBlindingWidth" ) }; xCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.xCP_->blind() ) { const LauBlind* blinder { rhs.xCP_->blinder() }; xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto yCPVal { getOptionalValue( coeffInfo, "YCP", JsonType::Number ).value_or( rhs.yCP_->value() ) }; const auto yCPFixed { getOptionalValue( coeffInfo, "YCPFixed", JsonType::Boolean ).value_or( rhs.yCP_->fixed() ) }; yCP_ = std::make_unique("YCP", yCPVal, minRealImagPart_, maxRealImagPart_, yCPFixed); if ( getOptionalValue( coeffInfo, "YCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YCPBlindingWidth" ) }; yCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.yCP_->blind() ) { const LauBlind* blinder { rhs.yCP_->blinder() }; yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto xbarCPVal { getOptionalValue( coeffInfo, "XBarCP", JsonType::Number ).value_or( rhs.xbarCP_->value() ) }; const auto xbarCPFixed { getOptionalValue( coeffInfo, "XBarCPFixed", JsonType::Boolean ).value_or( rhs.xbarCP_->fixed() ) }; xbarCP_ = std::make_unique("XBarCP", xbarCPVal, minRealImagPart_, maxRealImagPart_, xbarCPFixed); if ( getOptionalValue( coeffInfo, "XBarCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "XBarCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "XBarCPBlindingWidth" ) }; xbarCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.xbarCP_->blind() ) { const LauBlind* blinder { rhs.xbarCP_->blinder() }; xbarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } const auto ybarCPVal { getOptionalValue( coeffInfo, "YBarCP", JsonType::Number ).value_or( rhs.ybarCP_->value() ) }; const auto ybarCPFixed { getOptionalValue( coeffInfo, "YBarCPFixed", JsonType::Boolean ).value_or( rhs.ybarCP_->fixed() ) }; ybarCP_ = std::make_unique("YBarCP", ybarCPVal, minRealImagPart_, maxRealImagPart_, ybarCPFixed); if ( getOptionalValue( coeffInfo, "YBarCPBlind", JsonType::Boolean ).value_or( kFALSE ) ) { const auto blindingString { getValue( coeffInfo, "YBarCPBlindingString" ) }; const auto blindingWidth { getValue( coeffInfo, "YBarCPBlindingWidth" ) }; ybarCP_->blindParameter( blindingString, blindingWidth ); } else if ( rhs.ybarCP_->blind() ) { const LauBlind* blinder { rhs.ybarCP_->blinder() }; ybarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } 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 const 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 const 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 const 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 const 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 const 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 const 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 const TString parName{ this->baseName() + "_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_; } LauRealImagGammaCPCoeffSet* LauRealImagGammaCPCoeffSet::createClone_impl(const TString& newName, const CloneOption cloneOption, const Double_t constFactor, const nlohmann::json& coeffInfo) const { if ( ! ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart || cloneOption == CloneOption::TieImagPart || cloneOption == CloneOption::TieCPPars ) ) { std::cerr << "ERROR in LauRealImagGammaCPCoeffSet::createClone : Invalid clone option" << std::endl; return nullptr; } auto clone = new LauRealImagGammaCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauRealImagGammaCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { using LauJsonTools::JsonType; using LauJsonTools::getValue; using LauJsonTools::getOptionalValue; const auto type { getValue( j, "type" ) }; if ( type != LauCoeffType::RealImagGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagGammaCPCoeffSet"); } const auto clone { getValue( j, "clone" ) }; if ( clone ) { throw LauClonedCoeff{"Cannot build a cloned LauRealImagGammaCPCoeffSet standalone"}; } const std::vector mandatoryElements { std::make_pair("X", JsonType::Number), std::make_pair("Y", JsonType::Number), std::make_pair("XCP", JsonType::Number), std::make_pair("YCP", JsonType::Number), std::make_pair("XBarCP", JsonType::Number), std::make_pair("YBarCP", JsonType::Number), std::make_pair("XFixed", JsonType::Boolean), std::make_pair("YFixed", JsonType::Boolean), std::make_pair("XCPFixed", JsonType::Boolean), std::make_pair("YCPFixed", JsonType::Boolean), std::make_pair("XBarCPFixed", JsonType::Boolean), std::make_pair("YBarCPFixed", JsonType::Boolean) }; if ( ! LauJsonTools::checkObjectElements( j, mandatoryElements ) ) { throw LauJsonTools::MissingJsonElement{"Missing elements needed to construct LauRealImagGammaCPCoeffSet"}; } const auto name { getValue( j, "name" ) }; const auto x { getValue( j, "X" ) }; const auto y { getValue( j, "Y" ) }; const auto xCP { getValue( j, "XCP" ) }; const auto yCP { getValue( j, "YCP" ) }; const auto xbarCP { getValue( j, "XBarCP" ) }; const auto ybarCP { getValue( j, "YBarCP" ) }; const auto xFixed { getValue( j, "XFixed" ) }; const auto yFixed { getValue( j, "YFixed" ) }; const auto xCPFixed { getValue( j, "XCPFixed" ) }; const auto yCPFixed { getValue( j, "YCPFixed" ) }; const auto xbarCPFixed { getValue( j, "XBarCPFixed" ) }; const auto ybarCPFixed { getValue( j, "YBarCPFixed" ) }; LauRealImagGammaCPCoeffSet coeff{ name, x, y, xCP, yCP, xbarCP, ybarCP, xFixed, yFixed, xCPFixed, yCPFixed, xbarCPFixed, ybarCPFixed }; coeff.applyBlinding( j ); return coeff; } -//! \endcond DOXYGEN_IGNORE +//! \endcond