diff --git a/inc/LauAbsCoeffSet.hh b/inc/LauAbsCoeffSet.hh index 932d14a..b6ad73f 100644 --- a/inc/LauAbsCoeffSet.hh +++ b/inc/LauAbsCoeffSet.hh @@ -1,449 +1,492 @@ /* 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 "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 \return the collection of newly constructed coefficients */ static std::vector> readFromJson( const TString& fileName ); //! Write a collection of coefficient objects to a json file /*! \param[in] fileName the name of the file to which the JSON should be written \param[in] coeffs the collection of coefficients to be written out */ static void writeToJson( const TString& fileName, const std::vector>& coeffs ); //! 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; //! 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; //! 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) + 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)}; + 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 */ - virtual TString name() const {return name_;} + TString name() const {return name_;} //! Set the name of the coefficient set /*! The name should correspond to the name of the resonance in the model. \param [in] theName the name to set */ - virtual void name(const TString& theName) {name_ = theName;} + void name(const TString& theName) {name_ = theName;} //! Retrieve the base name of the coefficient set /*! The base name is generally of the form "Ai", where i is an integer. This is used in the fit results ntuple. \return the base name of the coefficient set */ - virtual const TString& baseName() const {return basename_;} + const TString& baseName() const {return basename_;} //! Set the base name of the coefficient set /*! The base name is generally of the form "Ai", where i is an integer. This is used in the fit results ntuple. \param [in] theBasename the base name to set */ - virtual void baseName(const TString& theBasename) {basename_ = theBasename;} + void baseName(const TString& theBasename) {basename_ = theBasename;} //! Retrieve the index number of the coefficient set /*! \return the index number of the coefficient set */ - virtual UInt_t index() const {return index_;} + UInt_t index() const {return index_;} //! Set the index number of the coefficient set /*! \param [in] newIndex the new index */ - virtual void index(const UInt_t newIndex); + 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 */ - virtual void setParameterValue(const TString& parName, const Double_t value, const Bool_t init); + 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 */ - virtual void setParameterError(const TString& parName, const Double_t error); + 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 */ - virtual void fixParameter(const TString& parName); + void fixParameter(const TString& parName); //! Set the named parameter to float in the fit /*! \param [in] parName the name of the parameter to adjust */ - virtual void floatParameter(const TString& parName); + void floatParameter(const TString& parName); //! Blind the named parameter /*! See LauBlind documentation for details of blinding procedure \param [in] parName the name of the parameter to adjust \param [in] blindingString the unique blinding string used to seed the random number generator \param [in] width the width of the Gaussian from which the offset should be sampled */ - virtual void blindParameter(const TString& parName, const TString& blindingString, const Double_t width); + void blindParameter(const TString& parName, const TString& blindingString, const Double_t width); //! Add Gaussian constraint to the named parameter /*! \param [in] parName the name of the parameter to adjust \param [in] mean the mean of the Gaussian constraint \param [in] width the width of the Gaussian constraint */ - virtual void addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width); + void addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width); //! Add suffix to the name of the given parameter /*! \param [in] parName the name of the parameter to adjust \param [in] suffix the suffix to add to the parameter name */ - virtual void addSuffixToParameterName(const TString& parName, const TString& suffix); + 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"); + 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) = default; //! Move assignment operator /*! \param [in] rhs the coefficient to clone */ LauAbsCoeffSet& operator=(LauAbsCoeffSet&& rhs) = default; //! 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) = 0; + 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* parent_{nullptr}; + + //! The clone option used, if applicable + CloneOption cloneOption_{CloneOption::All}; + + //! The constant factor used, if applicable + Double_t constFactor_{1.0}; + ClassDef(LauAbsCoeffSet, 0) }; //! \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"}, }) // exception 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); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauBelleCPCoeffSet.hh b/inc/LauBelleCPCoeffSet.hh index ffaf0ab..8c7d869 100644 --- a/inc/LauBelleCPCoeffSet.hh +++ b/inc/LauBelleCPCoeffSet.hh @@ -1,235 +1,238 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauBelleCPCoeffSet& operator=(LauBelleCPCoeffSet&& rhs) = default; //! 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() }; } //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauBelleCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauCartesianCPCoeffSet.hh b/inc/LauCartesianCPCoeffSet.hh index dc37de5..d3d8272 100644 --- a/inc/LauCartesianCPCoeffSet.hh +++ b/inc/LauCartesianCPCoeffSet.hh @@ -1,225 +1,228 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauCartesianCPCoeffSet& operator=(LauCartesianCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauCartesianCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauCartesianGammaCPCoeffSet.hh b/inc/LauCartesianGammaCPCoeffSet.hh index 3919e50..f7428c7 100644 --- a/inc/LauCartesianGammaCPCoeffSet.hh +++ b/inc/LauCartesianGammaCPCoeffSet.hh @@ -1,241 +1,244 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauCartesianGammaCPCoeffSet& operator=(LauCartesianGammaCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauCartesianGammaCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauCleoCPCoeffSet.hh b/inc/LauCleoCPCoeffSet.hh index 9e8d0b0..d561ae5 100644 --- a/inc/LauCleoCPCoeffSet.hh +++ b/inc/LauCleoCPCoeffSet.hh @@ -1,229 +1,232 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauCleoCPCoeffSet& operator=(LauCleoCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauCleoCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauMagPhaseCPCoeffSet.hh b/inc/LauMagPhaseCPCoeffSet.hh index e24ab00..a98a12c 100644 --- a/inc/LauMagPhaseCPCoeffSet.hh +++ b/inc/LauMagPhaseCPCoeffSet.hh @@ -1,225 +1,228 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCPCoeffSet& operator=(LauMagPhaseCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauMagPhaseCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauMagPhaseCoeffSet.hh b/inc/LauMagPhaseCoeffSet.hh index 9fb3ed5..029deba 100644 --- a/inc/LauMagPhaseCoeffSet.hh +++ b/inc/LauMagPhaseCoeffSet.hh @@ -1,208 +1,211 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file 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 (default) /*! \param [in] rhs the coefficient to clone */ LauMagPhaseCoeffSet& operator=(LauMagPhaseCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauMagPhaseCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauNSCCartesianCPCoeffSet.hh b/inc/LauNSCCartesianCPCoeffSet.hh index 0330cc1..0657830 100644 --- a/inc/LauNSCCartesianCPCoeffSet.hh +++ b/inc/LauNSCCartesianCPCoeffSet.hh @@ -1,268 +1,271 @@ /* 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, x', y', deltaX', deltaY' ] */ 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, deltaX, deltaY, x', y', deltaX', deltaY' ] */ std::vector getParameters() const override; //! 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) + 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)}; + 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) */ - LauNSCCartesianCPCoeffSet(const LauNSCCartesianCPCoeffSet& rhs, const CloneOption cloneOption = CloneOption::All, const Double_t constFactor = 1.0); + 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) override; + 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); static void to_json(json& j, const LauNSCCartesianCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauPolarGammaCPCoeffSet.hh b/inc/LauPolarGammaCPCoeffSet.hh index dd6adc8..e97a5c2 100644 --- a/inc/LauPolarGammaCPCoeffSet.hh +++ b/inc/LauPolarGammaCPCoeffSet.hh @@ -1,340 +1,343 @@ /* 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; //! 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) + 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)}; + return std::unique_ptr{this->createClone_impl(newName,cloneOption,constFactor,coeffInfo)}; } 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); + 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) override; + 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) }; //! \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); static void to_json(json& j, const LauPolarGammaCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauRealImagCPCoeffSet.hh b/inc/LauRealImagCPCoeffSet.hh index 5498ae6..cd488af 100644 --- a/inc/LauRealImagCPCoeffSet.hh +++ b/inc/LauRealImagCPCoeffSet.hh @@ -1,224 +1,227 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagCPCoeffSet& operator=(LauRealImagCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauRealImagCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauRealImagCoeffSet.hh b/inc/LauRealImagCoeffSet.hh index 9a5ed59..fed8da8 100644 --- a/inc/LauRealImagCoeffSet.hh +++ b/inc/LauRealImagCoeffSet.hh @@ -1,216 +1,219 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagCoeffSet& operator=(LauRealImagCoeffSet&& rhs) = default; //! 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() }; } //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauRealImagCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/inc/LauRealImagGammaCPCoeffSet.hh b/inc/LauRealImagGammaCPCoeffSet.hh index 0783962..26f7e7e 100644 --- a/inc/LauRealImagGammaCPCoeffSet.hh +++ b/inc/LauRealImagGammaCPCoeffSet.hh @@ -1,240 +1,243 @@ /* 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 (default) /*! \param [in] rhs the coefficient to clone */ LauRealImagGammaCPCoeffSet& operator=(LauRealImagGammaCPCoeffSet&& rhs) = default; //! 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; //! 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; //! 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) + 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)}; + 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); + 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) override; + 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); static void to_json(json& j, const LauRealImagGammaCPCoeffSet& t); }; } //! \endcond DOXYGEN_IGNORE #endif diff --git a/src/LauAbsCoeffSet.cc b/src/LauAbsCoeffSet.cc index da9acbe..32e41e9 100644 --- a/src/LauAbsCoeffSet.cc +++ b/src/LauAbsCoeffSet.cc @@ -1,368 +1,402 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauAbsCoeffSet.cc \brief File containing implementation of LauAbsCoeffSet class. */ #include #include #include "TString.h" #include "LauAbsCoeffSet.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauRandom.hh" ClassImp(LauAbsCoeffSet); TRandom* LauAbsCoeffSet::randomiser_ = nullptr; Double_t LauAbsCoeffSet::minMagnitude_ = -10.0; Double_t LauAbsCoeffSet::maxMagnitude_ = 10.0; Double_t LauAbsCoeffSet::minPhase_ = -LauConstants::threePi; Double_t LauAbsCoeffSet::maxPhase_ = LauConstants::threePi; Double_t LauAbsCoeffSet::minRealImagPart_ = -10.0; Double_t LauAbsCoeffSet::maxRealImagPart_ = 10.0; Double_t LauAbsCoeffSet::minDelta_ = -2.0; Double_t LauAbsCoeffSet::maxDelta_ = 2.0; -LauAbsCoeffSet::LauAbsCoeffSet(const TString& theName, const TString& theBaseName) : +LauAbsCoeffSet::LauAbsCoeffSet(const TString& theName, const TString& theBaseName, const LauAbsCoeffSet* parent, const CloneOption cloneOption, const Double_t constFactor) : name_{theName}, - basename_{theBaseName} + basename_{theBaseName}, + parent_{parent}, + cloneOption_{cloneOption}, + constFactor_{constFactor} { } TRandom* LauAbsCoeffSet::getRandomiser() { if ( randomiser_ == nullptr ) { randomiser_ = LauRandom::zeroSeedRandom(); } return randomiser_; } void LauAbsCoeffSet::index(const UInt_t newIndex) { index_ = newIndex; const TString oldBaseName{ this->baseName() }; TString basename{ oldBaseName }; basename += newIndex; basename += "_"; this->baseName(basename); std::vector pars { this->getParameters() }; for ( LauParameter* par : pars ) { this->adjustName( *par, oldBaseName ); } } void LauAbsCoeffSet::adjustName(LauParameter& par, const TString& oldBaseName) { TString theName{ par.name() }; if ( theName.BeginsWith( oldBaseName ) && theName != oldBaseName ) { theName.Remove(0,oldBaseName.Length()); } theName.Prepend(this->baseName()); par.name(theName); } void LauAbsCoeffSet::setParameterValue(const TString& parName, const Double_t value, const Bool_t init) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterValue : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->value( value ); if ( init ) { par->genValue( value ); par->initValue( value ); } } void LauAbsCoeffSet::setParameterError(const TString& parName, const Double_t error) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::setParameterError : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->error( error ); } void LauAbsCoeffSet::fixParameter(const TString& parName) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::fixParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kTRUE ); } void LauAbsCoeffSet::floatParameter(const TString& parName) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::floatParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->fixed( kFALSE ); } void LauAbsCoeffSet::blindParameter(const TString& parName, const TString& blindingString, const Double_t width) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::blindParameter : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->blindParameter( blindingString, width ); } void LauAbsCoeffSet::addGaussianConstraint(const TString& parName, const Double_t mean, const Double_t width) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::addGaussianConstraint : Unable to find parameter \"" << parName << "\"" << std::endl; return; } par->addGaussianConstraint( mean, width ); } void LauAbsCoeffSet::addSuffixToParameterName(const TString& parName, const TString& suffix) { LauParameter* par { this->findParameter( parName ) }; if ( par == nullptr ) { std::cerr << "ERROR in LauAbsCoeffSet::addSuffixToParameterName : Unable to find parameter \"" << parName << "\"" << std::endl; return; } TString newName{ par->name() }; if ( ! suffix.BeginsWith('_') ) { newName += "_"; } newName += suffix; par->name( newName ); } LauParameter* LauAbsCoeffSet::findParameter(const TString& parName) { std::vector pars { this->getParameters() }; for ( LauParameter* par : pars ) { const TString& iName { par->name() }; if ( iName.EndsWith( parName ) ) { return par; } } return nullptr; } #include "LauBelleCPCoeffSet.hh" #include "LauCartesianCPCoeffSet.hh" #include "LauCartesianGammaCPCoeffSet.hh" #include "LauCleoCPCoeffSet.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauMagPhaseCPCoeffSet.hh" #include "LauNSCCartesianCPCoeffSet.hh" #include "LauPolarGammaCPCoeffSet.hh" #include "LauRealImagCoeffSet.hh" #include "LauRealImagCPCoeffSet.hh" #include "LauRealImagGammaCPCoeffSet.hh" //! \cond DOXYGEN_IGNORE void nlohmann::adl_serializer::to_json( json& j, const LauAbsCoeffSet& t ) { switch ( t.type() ) { case LauCoeffType::MagPhase : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::RealImag : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::BelleCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::CartesianCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::CartesianGammaCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::CleoCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::MagPhaseCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::NSCCartesianCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::PolarGammaCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::RealImagCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; case LauCoeffType::RealImagGammaCP : nlohmann::adl_serializer::to_json( j, static_cast(t)); break; } } //! \endcond DOXYGEN_IGNORE std::vector> LauAbsCoeffSet::readFromJson( const TString& fileName ) { using nlohmann::json; std::ifstream in(fileName, std::ios_base::in); if ( ! in ) { std::cerr << "ERROR in LauAbsCoeffSet::readFromJson : couldn't open file \"" << fileName << "\"" << std::endl; return {}; } json j; in >> j; const auto nCoeffs { j.at("nCoeffs").get() }; + std::vector> coeffs; coeffs.reserve( nCoeffs ); + std::vector clonedCoeffs; + clonedCoeffs.reserve( nCoeffs ); + for ( auto& coeff : j.at("coeffs") ) { + // If it's a cloned coeff, we save it for later + const Bool_t clone { coeff.at("clone").get() }; + if ( clone ) { + clonedCoeffs.emplace_back( coeff ); + continue; + } + const LauCoeffType type { coeff.at("type").get() }; switch ( type ) { case LauCoeffType::MagPhase : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::RealImag : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::BelleCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::CartesianCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::CartesianGammaCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::CleoCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::MagPhaseCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::NSCCartesianCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::PolarGammaCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::RealImagCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; case LauCoeffType::RealImagGammaCP : coeffs.emplace_back( std::make_unique( coeff.get() ) ); break; } } + for ( auto& coeff : clonedCoeffs ) { + const std::string name { coeff.at("name").get() }; + const std::string parentName { coeff.at("parent").get() }; + + // Find the parent of this coefficient set + auto parent = std::find_if( coeffs.begin(), coeffs.end(), [&parentName](const std::unique_ptr& c){ return c->name() == parentName; } ); + if ( parent == coeffs.end() ) { + throw LauClonedCoeff{"Cannot locate parent (" + parentName + ") for cloned coefficient set " + name}; + } + + const CloneOption cloneOption { coeff.at("cloneOption").get() }; + const Double_t constFactor { coeff.at("constFactor").get() }; + + // Create a clone from the parent, passing the json + // entry for this coeffset to allow any parameters that + // are not cloned (depending on the CloneOption) to + // have their values etc. set correctly + coeffs.emplace_back( (*parent)->createClone( name, cloneOption, constFactor, coeff ) ); + } + return coeffs; } void LauAbsCoeffSet::writeToJson( const TString& fileName, const std::vector>& coeffs ) { using nlohmann::json; json j; j["nCoeffs"] = coeffs.size(); j["coeffs"] = json::array(); for ( auto& coeffset : coeffs ) { j["coeffs"].push_back( *coeffset ); } std::ofstream out{fileName, std::ios_base::out}; if ( ! out ) { std::cerr << "ERROR in LauAbsCoeffSet::writeToJson : couldn't open file \"" << fileName << "\" for writing. No file will be written!" << std::endl; return; } out << j.dump(4); out << std::endl; } std::ostream& operator<<( std::ostream& os, const LauCoeffType type ) { switch ( type ) { case LauCoeffType::MagPhase : os << "MagPhase"; break; case LauCoeffType::RealImag : os << "RealImag"; break; case LauCoeffType::BelleCP : os << "BelleCP"; break; case LauCoeffType::CartesianCP : os << "CartesianCP"; break; case LauCoeffType::CartesianGammaCP : os << "CartesianGammaCP"; break; case LauCoeffType::CleoCP : os << "CleoCP"; break; case LauCoeffType::MagPhaseCP : os << "MagPhaseCP"; break; case LauCoeffType::NSCCartesianCP : os << "NSCCartesianCP"; break; case LauCoeffType::PolarGammaCP : os << "PolarGammaCP"; break; case LauCoeffType::RealImagCP : os << "RealImagCP"; break; case LauCoeffType::RealImagGammaCP : os << "RealImagGammaCP"; break; } return os; } diff --git a/src/LauBelleCPCoeffSet.cc b/src/LauBelleCPCoeffSet.cc index 45ffc23..ea0c921 100644 --- a/src/LauBelleCPCoeffSet.cc +++ b/src/LauBelleCPCoeffSet.cc @@ -1,388 +1,436 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauBelleCPCoeffSet.cc \brief File containing implementation of LauBelleCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauBelleCPCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauBelleCPCoeffSet) LauBelleCPCoeffSet::LauBelleCPCoeffSet(const TString& compName, 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { a_.reset( rhs.a_->createClone(constFactor) ); } else { - a_ = std::make_unique("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); + const Double_t aVal { ( coeffInfo.contains("a") ) ? coeffInfo.at("a").get() : rhs.a_->value() }; + const Bool_t aFixed { ( coeffInfo.contains("aFixed") ) ? coeffInfo.at("aFixed").get() : rhs.a_->fixed() }; + + a_ = std::make_unique("A", aVal, minMagnitude_, maxMagnitude_, aFixed); + 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 { - b_ = std::make_unique("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); + const Double_t bVal { ( coeffInfo.contains("b") ) ? coeffInfo.at("b").get() : rhs.b_->value() }; + const Bool_t bFixed { ( coeffInfo.contains("bFixed") ) ? coeffInfo.at("bFixed").get() : rhs.b_->fixed() }; + const Bool_t bSecondStage { ( coeffInfo.contains("bSecondStage") ) ? coeffInfo.at("bSecondStage").get() : rhs.b_->secondStage() }; + + b_ = std::make_unique("B", bVal, minMagnitude_, maxMagnitude_, bFixed); + + if (bSecondStage && !bFixed) { + b_->secondStage(kTRUE); + b_->initValue(0.0); + } + 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 { - delta_ = std::make_unique("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); + const Double_t deltaVal { ( coeffInfo.contains("delta") ) ? coeffInfo.at("delta").get() : rhs.delta_->value() }; + const Bool_t deltaFixed { ( coeffInfo.contains("deltaFixed") ) ? coeffInfo.at("deltaFixed").get() : rhs.delta_->fixed() }; + + delta_ = std::make_unique("Delta", deltaVal, minPhase_, maxPhase_, deltaFixed); + 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 { - phi_ = std::make_unique("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); + const Double_t phiVal { ( coeffInfo.contains("phi") ) ? coeffInfo.at("phi").get() : rhs.phi_->value() }; + const Bool_t phiFixed { ( coeffInfo.contains("phiFixed") ) ? coeffInfo.at("phiFixed").get() : rhs.phi_->fixed() }; + const Bool_t phiSecondStage { ( coeffInfo.contains("phiSecondStage") ) ? coeffInfo.at("phiSecondStage").get() : rhs.phi_->secondStage() }; + + phi_ = std::make_unique("Phi", phiVal, minPhase_, maxPhase_, phiFixed); + + if (phiSecondStage && !phiFixed) { + phi_->secondStage(kTRUE); + phi_->initValue(0.0); + } + 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) +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 }; + if ( this->clone() ) { + const LauBelleCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::BelleCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauBelleCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t a { j.at("a").get() }; const Double_t delta { j.at("delta").get() }; const Double_t b { j.at("b").get() }; const Double_t phi { j.at("phi").get() }; const Bool_t aFixed { j.at("aFixed").get() }; const Bool_t deltaFixed { j.at("deltaFixed").get() }; const Bool_t bFixed { j.at("bFixed").get() }; const Bool_t phiFixed { j.at("phiFixed").get() }; - // TODO - these should be optional? - const Bool_t bSecondStage { j.at("bSecondStage").get() }; - const Bool_t phiSecondStage { j.at("phiSecondStage").get() }; + const Bool_t bSecondStage { j.contains("bSecondStage") ? j.at("bSecondStage").get() : kFALSE }; + const Bool_t phiSecondStage { j.contains("phiSecondStage") ? j.at("phiSecondStage").get() : kFALSE }; return { name, a, delta, b, phi, aFixed, deltaFixed, bFixed, phiFixed, bSecondStage, phiSecondStage }; } void nlohmann::adl_serializer::to_json(json& j, const LauBelleCPCoeffSet& t) { j["type"] = LauCoeffType::BelleCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["a"] = pars[0]->value(); - j["delta"] = pars[1]->value(); - j["b"] = pars[2]->value(); - j["phi"] = pars[3]->value(); - - j["aFixed"] = pars[0]->fixed(); - j["deltaFixed"] = pars[1]->fixed(); - j["bFixed"] = pars[2]->fixed(); - j["phiFixed"] = pars[3]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["bSecondStage"] = pars[2]->secondStage(); - j["phiSecondStage"] = pars[3]->secondStage(); + if ( ! pars[0]->clone() ) { + j["a"] = pars[0]->value(); + j["aFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["delta"] = pars[1]->value(); + j["deltaFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["b"] = pars[2]->value(); + j["bFixed"] = pars[2]->fixed(); + j["bSecondStage"] = pars[2]->secondStage(); + } + if ( ! pars[3]->clone() ) { + j["phi"] = pars[3]->value(); + j["phiFixed"] = pars[3]->fixed(); + j["phiSecondStage"] = pars[3]->secondStage(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauCartesianCPCoeffSet.cc b/src/LauCartesianCPCoeffSet.cc index 0c30dec..f06bdf2 100644 --- a/src/LauCartesianCPCoeffSet.cc +++ b/src/LauCartesianCPCoeffSet.cc @@ -1,327 +1,365 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianCPCoeffSet.cc \brief File containing implementation of LauCartesianCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauCartesianCPCoeffSet) LauCartesianCPCoeffSet::LauCartesianCPCoeffSet(const TString& compName, 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); 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 { - deltaX_ = std::make_unique("DeltaX", rhs.deltaX_->value(), minDelta_, maxDelta_, rhs.deltaX_->fixed()); - deltaY_ = std::make_unique("DeltaY", rhs.deltaY_->value(), minDelta_, maxDelta_, rhs.deltaY_->fixed()); - if ( rhs.deltaX_->secondStage() && !rhs.deltaX_->fixed() ) { + const Double_t deltaXVal { ( coeffInfo.contains("deltaX") ) ? coeffInfo.at("deltaX").get() : rhs.deltaX_->value() }; + const Bool_t deltaXFixed { ( coeffInfo.contains("deltaXFixed") ) ? coeffInfo.at("deltaXFixed").get() : rhs.deltaX_->fixed() }; + const Bool_t deltaXSecondStage { ( coeffInfo.contains("deltaXSecondStage") ) ? coeffInfo.at("deltaXSecondStage").get() : rhs.deltaX_->secondStage() }; + + const Double_t deltaYVal { ( coeffInfo.contains("deltaY") ) ? coeffInfo.at("deltaY").get() : rhs.deltaY_->value() }; + const Bool_t deltaYFixed { ( coeffInfo.contains("deltaYFixed") ) ? coeffInfo.at("deltaYFixed").get() : rhs.deltaY_->fixed() }; + const Bool_t deltaYSecondStage { ( coeffInfo.contains("deltaYSecondStage") ) ? coeffInfo.at("deltaYSecondStage").get() : 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 ( rhs.deltaY_->secondStage() && !rhs.deltaY_->fixed() ) { + if ( deltaYSecondStage && !deltaYFixed ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } + if ( rhs.deltaX_->blind() ) { const LauBlind* blinder { rhs.deltaX_->blinder() }; deltaX_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaY_->blind() ) { const LauBlind* blinder { rhs.deltaY_->blinder() }; deltaY_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianCPCoeffSet::getParameters() { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get() }; } std::vector LauCartesianCPCoeffSet::getParameters() const { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauCartesianCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::CartesianCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCartesianCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauCartesianCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t deltaX { j.at("deltaX").get() }; const Double_t deltaY { j.at("deltaY").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t deltaXFixed { j.at("deltaXFixed").get() }; const Bool_t deltaYFixed { j.at("deltaYFixed").get() }; const Bool_t deltaXSecondStage { j.at("deltaXSecondStage").get() }; const Bool_t deltaYSecondStage { j.at("deltaYSecondStage").get() }; return { name, x, y, deltaX, deltaY, xFixed, yFixed, deltaXFixed, deltaYFixed, deltaXSecondStage, deltaYSecondStage }; } void nlohmann::adl_serializer::to_json(json& j, const LauCartesianCPCoeffSet& t) { j["type"] = LauCoeffType::CartesianCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["deltaX"] = pars[2]->value(); - j["deltaY"] = pars[3]->value(); - - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["deltaXFixed"] = pars[2]->fixed(); - j["deltaYFixed"] = pars[3]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["deltaXSecondStage"] = pars[2]->secondStage(); - j["deltaYSecondStage"] = pars[3]->secondStage(); + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["deltaX"] = pars[2]->value(); + j["deltaXFixed"] = pars[2]->fixed(); + j["deltaXSecondStage"] = pars[2]->secondStage(); + } + if ( ! pars[3]->clone() ) { + j["deltaY"] = pars[3]->value(); + j["deltaYFixed"] = pars[3]->fixed(); + j["deltaYSecondStage"] = pars[3]->secondStage(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauCartesianGammaCPCoeffSet.cc b/src/LauCartesianGammaCPCoeffSet.cc index 8e5d182..c62fd18 100644 --- a/src/LauCartesianGammaCPCoeffSet.cc +++ b/src/LauCartesianGammaCPCoeffSet.cc @@ -1,379 +1,432 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauCartesianGammaCPCoeffSet.cc \brief File containing implementation of LauCartesianGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCartesianGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauCartesianGammaCPCoeffSet) LauCartesianGammaCPCoeffSet::LauCartesianGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t deltaXCP, const Double_t deltaYCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t deltaXCPFixed, const Bool_t deltaYCPFixed, const Bool_t deltaXCPSecondStage, const Bool_t deltaYCPSecondStage) : LauAbsCoeffSet{ compName }, x_{ 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + 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 { - xCP_ = std::make_unique("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); + const Double_t xCPVal { ( coeffInfo.contains("xCP") ) ? coeffInfo.at("xCP").get() : rhs.xCP_->value() }; + const Bool_t xCPFixed { ( coeffInfo.contains("xCPFixed") ) ? coeffInfo.at("xCPFixed").get() : rhs.xCP_->fixed() }; + + xCP_ = std::make_unique("XCP", xCPVal, minRealImagPart_, maxRealImagPart_, xCPFixed); + if ( rhs.xCP_->blind() ) { const LauBlind* blinder { rhs.xCP_->blinder() }; xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - yCP_ = std::make_unique("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); + + const Double_t yCPVal { ( coeffInfo.contains("yCP") ) ? coeffInfo.at("yCP").get() : rhs.yCP_->value() }; + const Bool_t yCPFixed { ( coeffInfo.contains("yCPFixed") ) ? coeffInfo.at("yCPFixed").get() : rhs.yCP_->fixed() }; + + yCP_ = std::make_unique("YCP", yCPVal, minRealImagPart_, maxRealImagPart_, yCPFixed); + if ( rhs.yCP_->blind() ) { const LauBlind* blinder { rhs.yCP_->blinder() }; yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - deltaXCP_ = std::make_unique("DeltaXCP", rhs.deltaXCP_->value(), minDelta_, maxDelta_, rhs.deltaXCP_->fixed()); - deltaYCP_ = std::make_unique("DeltaYCP", rhs.deltaYCP_->value(), minDelta_, maxDelta_, rhs.deltaYCP_->fixed()); - if ( rhs.deltaXCP_->secondStage() && !rhs.deltaXCP_->fixed() ) { + + const Double_t deltaXCPVal { ( coeffInfo.contains("deltaXCP") ) ? coeffInfo.at("deltaXCP").get() : rhs.deltaXCP_->value() }; + const Bool_t deltaXCPFixed { ( coeffInfo.contains("deltaXCPFixed") ) ? coeffInfo.at("deltaXCPFixed").get() : rhs.deltaXCP_->fixed() }; + const Bool_t deltaXCPSecondStage { ( coeffInfo.contains("deltaXCPSecondStage") ) ? coeffInfo.at("deltaXCPSecondStage").get() : rhs.deltaXCP_->secondStage() }; + + const Double_t deltaYCPVal { ( coeffInfo.contains("deltaYCP") ) ? coeffInfo.at("deltaYCP").get() : rhs.deltaYCP_->value() }; + const Bool_t deltaYCPFixed { ( coeffInfo.contains("deltaYCPFixed") ) ? coeffInfo.at("deltaYCPFixed").get() : rhs.deltaYCP_->fixed() }; + const Bool_t deltaYCPSecondStage { ( coeffInfo.contains("deltaYCPSecondStage") ) ? coeffInfo.at("deltaYCPSecondStage").get() : 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 ( rhs.deltaYCP_->secondStage() && !rhs.deltaYCP_->fixed() ) { + if ( deltaYCPSecondStage && !deltaYCPFixed ) { deltaYCP_->secondStage(kTRUE); deltaYCP_->initValue(0.0); } + if ( rhs.deltaXCP_->blind() ) { const LauBlind* blinder { rhs.deltaXCP_->blinder() }; deltaXCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } if ( rhs.deltaYCP_->blind() ) { const LauBlind* blinder { rhs.deltaYCP_->blinder() }; deltaYCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCartesianGammaCPCoeffSet::getParameters() { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), deltaXCP_.get(), deltaYCP_.get() }; } std::vector LauCartesianGammaCPCoeffSet::getParameters() const { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), deltaXCP_.get(), deltaYCP_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauCartesianGammaCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::CartesianGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCartesianGammaCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauCartesianGammaCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t xCP { j.at("xCP").get() }; const Double_t yCP { j.at("yCP").get() }; const Double_t deltaXCP { j.at("deltaXCP").get() }; const Double_t deltaYCP { j.at("deltaYCP").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t xCPFixed { j.at("xCPFixed").get() }; const Bool_t yCPFixed { j.at("yCPFixed").get() }; const Bool_t deltaXCPFixed { j.at("deltaXCPFixed").get() }; const Bool_t deltaYCPFixed { j.at("deltaYCPFixed").get() }; const Bool_t deltaXCPSecondStage { j.at("deltaXCPSecondStage").get() }; const Bool_t deltaYCPSecondStage { j.at("deltaYCPSecondStage").get() }; return { name, x, y, xCP, yCP, deltaXCP, deltaYCP, xFixed, yFixed, xCPFixed, yCPFixed, deltaXCPFixed, deltaYCPFixed, deltaXCPSecondStage, deltaYCPSecondStage }; } void nlohmann::adl_serializer::to_json(json& j, const LauCartesianGammaCPCoeffSet& t) { j["type"] = LauCoeffType::CartesianGammaCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["xCP"] = pars[2]->value(); - j["yCP"] = pars[3]->value(); - j["deltaXCP"] = pars[4]->value(); - j["deltaYCP"] = pars[5]->value(); - - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["xCPFixed"] = pars[2]->fixed(); - j["yCPFixed"] = pars[3]->fixed(); - j["deltaXCPFixed"] = pars[4]->fixed(); - j["deltaYCPFixed"] = pars[5]->fixed(); - - j["deltaXCPSecondStage"] = pars[4]->secondStage(); - j["deltaYCPSecondStage"] = pars[5]->secondStage(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } + + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["xCP"] = pars[2]->value(); + j["xCPFixed"] = pars[2]->fixed(); + } + if ( ! pars[3]->clone() ) { + j["yCP"] = pars[3]->value(); + j["yCPFixed"] = pars[3]->fixed(); + } + if ( ! pars[4]->clone() ) { + j["deltaXCP"] = pars[4]->value(); + j["deltaXCPFixed"] = pars[4]->fixed(); + j["deltaXCPSecondStage"] = pars[4]->secondStage(); + } + if ( ! pars[5]->clone() ) { + j["deltaYCP"] = pars[5]->value(); + j["deltaYCPFixed"] = pars[5]->fixed(); + j["deltaYCPSecondStage"] = pars[5]->secondStage(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauCleoCPCoeffSet.cc b/src/LauCleoCPCoeffSet.cc index 5436911..e4ca8a2 100644 --- a/src/LauCleoCPCoeffSet.cc +++ b/src/LauCleoCPCoeffSet.cc @@ -1,391 +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 LauCleoCPCoeffSet.cc \brief File containing implementation of LauCleoCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauCleoCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauCleoCPCoeffSet) LauCleoCPCoeffSet::LauCleoCPCoeffSet(const TString& compName, 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { a_.reset( rhs.a_->createClone(constFactor) ); } else { - a_ = std::make_unique("A", rhs.a_->value(), minMagnitude_, maxMagnitude_, rhs.a_->fixed()); + const Double_t aVal { ( coeffInfo.contains("a") ) ? coeffInfo.at("a").get() : rhs.a_->value() }; + const Bool_t aFixed { ( coeffInfo.contains("aFixed") ) ? coeffInfo.at("aFixed").get() : rhs.a_->fixed() }; + + a_ = std::make_unique("A", aVal, minMagnitude_, maxMagnitude_, aFixed); + 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 { - b_ = std::make_unique("B", rhs.b_->value(), minMagnitude_, maxMagnitude_, rhs.b_->fixed()); + const Double_t bVal { ( coeffInfo.contains("b") ) ? coeffInfo.at("b").get() : rhs.b_->value() }; + const Bool_t bFixed { ( coeffInfo.contains("bFixed") ) ? coeffInfo.at("bFixed").get() : rhs.b_->fixed() }; + const Bool_t bSecondStage { ( coeffInfo.contains("bSecondStage") ) ? coeffInfo.at("bSecondStage").get() : rhs.b_->secondStage() }; + + b_ = std::make_unique("B", bVal, minMagnitude_, maxMagnitude_, bFixed); + + if ( bSecondStage && !bFixed ) { + b_->secondStage(kTRUE); + b_->initValue(0.0); + } + 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 { - delta_ = std::make_unique("Delta", rhs.delta_->value(), minPhase_, maxPhase_, rhs.delta_->fixed()); + const Double_t deltaVal { ( coeffInfo.contains("delta") ) ? coeffInfo.at("delta").get() : rhs.delta_->value() }; + const Bool_t deltaFixed { ( coeffInfo.contains("deltaFixed") ) ? coeffInfo.at("deltaFixed").get() : rhs.delta_->fixed() }; + + delta_ = std::make_unique("Delta", deltaVal, minPhase_, maxPhase_, deltaFixed); + 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 { - phi_ = std::make_unique("Phi", rhs.phi_->value(), minPhase_, maxPhase_, rhs.phi_->fixed()); + const Double_t phiVal { ( coeffInfo.contains("phi") ) ? coeffInfo.at("phi").get() : rhs.phi_->value() }; + const Bool_t phiFixed { ( coeffInfo.contains("phiFixed") ) ? coeffInfo.at("phiFixed").get() : rhs.phi_->fixed() }; + const Bool_t phiSecondStage { ( coeffInfo.contains("phiSecondStage") ) ? coeffInfo.at("phiSecondStage").get() : rhs.phi_->secondStage() }; + + phi_ = std::make_unique("Phi", phiVal, minPhase_, maxPhase_, phiFixed); + + if ( phiSecondStage && !phiFixed ) { + phi_->secondStage(kTRUE); + phi_->initValue(0.0); + } + if ( rhs.phi_->blind() ) { const LauBlind* blinder { rhs.phi_->blinder() }; phi_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauCleoCPCoeffSet::getParameters() { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } std::vector LauCleoCPCoeffSet::getParameters() const { return { a_.get(), delta_.get(), b_.get(), phi_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauCleoCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::CleoCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauCleoCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauCleoCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t a { j.at("a").get() }; const Double_t delta { j.at("delta").get() }; const Double_t b { j.at("b").get() }; const Double_t phi { j.at("phi").get() }; const Bool_t aFixed { j.at("aFixed").get() }; const Bool_t deltaFixed { j.at("deltaFixed").get() }; const Bool_t bFixed { j.at("bFixed").get() }; const Bool_t phiFixed { j.at("phiFixed").get() }; - // TODO - these should be optional? - const Bool_t bSecondStage { j.at("bSecondStage").get() }; - const Bool_t phiSecondStage { j.at("phiSecondStage").get() }; + const Bool_t bSecondStage { j.contains("bSecondStage") ? j.at("bSecondStage").get() : kFALSE }; + const Bool_t phiSecondStage { j.contains("phiSecondStage") ? j.at("phiSecondStage").get() : kFALSE }; return { name, a, delta, b, phi, aFixed, deltaFixed, bFixed, phiFixed, bSecondStage, phiSecondStage }; } void nlohmann::adl_serializer::to_json(json& j, const LauCleoCPCoeffSet& t) { j["type"] = LauCoeffType::CleoCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["a"] = pars[0]->value(); - j["delta"] = pars[1]->value(); - j["b"] = pars[2]->value(); - j["phi"] = pars[3]->value(); - - j["aFixed"] = pars[0]->fixed(); - j["deltaFixed"] = pars[1]->fixed(); - j["bFixed"] = pars[2]->fixed(); - j["phiFixed"] = pars[3]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["bSecondStage"] = pars[2]->secondStage(); - j["phiSecondStage"] = pars[3]->secondStage(); + if ( ! pars[0]->clone() ) { + j["a"] = pars[0]->value(); + j["aFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["delta"] = pars[1]->value(); + j["deltaFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["b"] = pars[2]->value(); + j["bFixed"] = pars[2]->fixed(); + j["bSecondStage"] = pars[2]->secondStage(); + } + if ( ! pars[3]->clone() ) { + j["phi"] = pars[3]->value(); + j["phiFixed"] = pars[3]->fixed(); + j["phiSecondStage"] = pars[3]->secondStage(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauMagPhaseCPCoeffSet.cc b/src/LauMagPhaseCPCoeffSet.cc index 9ad75c0..6d648f8 100644 --- a/src/LauMagPhaseCPCoeffSet.cc +++ b/src/LauMagPhaseCPCoeffSet.cc @@ -1,360 +1,400 @@ /* Copyright 2011 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCPCoeffSet.cc \brief File containing implementation of LauMagPhaseCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauMagPhaseCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauMagPhaseCPCoeffSet) LauMagPhaseCPCoeffSet::LauMagPhaseCPCoeffSet(const TString& compName, 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, CloneOption cloneOption, Double_t constFactor) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { mag_.reset( rhs.mag_->createClone(constFactor) ); magBar_.reset( rhs.magBar_->createClone(constFactor) ); } else { - mag_ = std::make_unique("Mag", rhs.mag_->value(), minMagnitude_, maxMagnitude_, rhs.mag_->fixed()); + const Double_t magVal { ( coeffInfo.contains("mag") ) ? coeffInfo.at("mag").get() : rhs.mag_->value() }; + const Bool_t magFixed { ( coeffInfo.contains("magFixed") ) ? coeffInfo.at("magFixed").get() : rhs.mag_->fixed() }; + + mag_ = std::make_unique("Mag", magVal, minMagnitude_, maxMagnitude_, magFixed); + if ( rhs.mag_->blind() ) { const LauBlind* blinder { rhs.mag_->blinder() }; mag_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - magBar_ = std::make_unique("MagBar", rhs.magBar_->value(), minMagnitude_, maxMagnitude_, rhs.magBar_->fixed()); + + const Double_t magBarVal { ( coeffInfo.contains("magBar") ) ? coeffInfo.at("magBar").get() : rhs.magBar_->value() }; + const Bool_t magBarFixed { ( coeffInfo.contains("magBarFixed") ) ? coeffInfo.at("magBarFixed").get() : rhs.magBar_->fixed() }; + + magBar_ = std::make_unique("MagBar", magBarVal, minMagnitude_, maxMagnitude_, magBarFixed); + 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 { - phase_ = std::make_unique("Phase", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); + const Double_t phaseVal { ( coeffInfo.contains("phase") ) ? coeffInfo.at("phase").get() : rhs.phase_->value() }; + const Bool_t phaseFixed { ( coeffInfo.contains("phaseFixed") ) ? coeffInfo.at("phaseFixed").get() : rhs.phase_->fixed() }; + + phase_ = std::make_unique("Phase", phaseVal, minPhase_, maxPhase_, phaseFixed); + if ( rhs.phase_->blind() ) { const LauBlind* blinder { rhs.phase_->blinder() }; phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - phaseBar_ = std::make_unique("PhaseBar", rhs.phaseBar_->value(), minPhase_, maxPhase_, rhs.phaseBar_->fixed()); + + const Double_t phaseBarVal { ( coeffInfo.contains("phaseBar") ) ? coeffInfo.at("phaseBar").get() : rhs.phaseBar_->value() }; + const Bool_t phaseBarFixed { ( coeffInfo.contains("phaseBarFixed") ) ? coeffInfo.at("phaseBarFixed").get() : rhs.phaseBar_->fixed() }; + + phaseBar_ = std::make_unique("PhaseBar", phaseBarVal, minPhase_, maxPhase_, phaseBarFixed); + if ( rhs.phaseBar_->blind() ) { const LauBlind* blinder { rhs.phaseBar_->blinder() }; phaseBar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCPCoeffSet::getParameters() { return { mag_.get(), phase_.get(), magBar_.get(), phaseBar_.get() }; } std::vector LauMagPhaseCPCoeffSet::getParameters() const { return { mag_.get(), phase_.get(), magBar_.get(), phaseBar_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauMagPhaseCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::MagPhaseCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauMagPhaseCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauMagPhaseCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t mag { j.at("mag").get() }; const Double_t phase { j.at("phase").get() }; const Double_t magBar { j.at("magBar").get() }; const Double_t phaseBar { j.at("phaseBar").get() }; const Bool_t magFixed { j.at("magFixed").get() }; const Bool_t phaseFixed { j.at("phaseFixed").get() }; const Bool_t magBarFixed { j.at("magBarFixed").get() }; const Bool_t phaseBarFixed { j.at("phaseBarFixed").get() }; return { name, mag, phase, magBar, phaseBar, magFixed, phaseFixed, magBarFixed, phaseBarFixed }; } void nlohmann::adl_serializer::to_json(json& j, const LauMagPhaseCPCoeffSet& t) { j["type"] = LauCoeffType::MagPhaseCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["mag"] = pars[0]->value(); - j["phase"] = pars[1]->value(); - j["magBar"] = pars[2]->value(); - j["phaseBar"] = pars[3]->value(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["magFixed"] = pars[0]->fixed(); - j["phaseFixed"] = pars[1]->fixed(); - j["magBarFixed"] = pars[2]->fixed(); - j["phaseBarFixed"] = pars[3]->fixed(); + if ( ! pars[0]->clone() ) { + j["mag"] = pars[0]->value(); + j["magFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["phase"] = pars[1]->value(); + j["phaseFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["magBar"] = pars[2]->value(); + j["magBarFixed"] = pars[2]->fixed(); + } + if ( ! pars[3]->clone() ) { + j["phaseBar"] = pars[3]->value(); + j["phaseBarFixed"] = pars[3]->fixed(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauMagPhaseCoeffSet.cc b/src/LauMagPhaseCoeffSet.cc index 1d1e4ee..4513484 100644 --- a/src/LauMagPhaseCoeffSet.cc +++ b/src/LauMagPhaseCoeffSet.cc @@ -1,259 +1,286 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauMagPhaseCoeffSet.cc \brief File containing implementation of LauMagPhaseCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauMagPhaseCoeffSet) LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const TString& compName, const Double_t magnitude, const Double_t phase, const Bool_t magFixed, const Bool_t phaseFixed) : LauAbsCoeffSet{ compName }, magnitude_{ std::make_unique("A",magnitude,minMagnitude_,maxMagnitude_,magFixed) }, phase_{ std::make_unique("Delta",phase,minPhase_,maxPhase_,phaseFixed) } { } -LauMagPhaseCoeffSet::LauMagPhaseCoeffSet(const LauMagPhaseCoeffSet& rhs, const CloneOption cloneOption, const Double_t constFactor) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieMagnitude ) { magnitude_.reset( rhs.magnitude_->createClone(constFactor) ); } else { - magnitude_ = std::make_unique("A", rhs.magnitude_->value(), minMagnitude_, maxMagnitude_, rhs.magnitude_->fixed()); + const Double_t magVal { ( coeffInfo.contains("mag") ) ? coeffInfo.at("mag").get() : rhs.magnitude_->value() }; + const Bool_t magFixed { ( coeffInfo.contains("magFixed") ) ? coeffInfo.at("magFixed").get() : rhs.magnitude_->fixed() }; + + magnitude_ = std::make_unique("A", magVal, minMagnitude_, maxMagnitude_, magFixed); + 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 { - phase_ = std::make_unique("Delta", rhs.phase_->value(), minPhase_, maxPhase_, rhs.phase_->fixed()); + const Double_t phaseVal { ( coeffInfo.contains("phase") ) ? coeffInfo.at("phase").get() : rhs.phase_->value() }; + const Bool_t phaseFixed { ( coeffInfo.contains("phaseFixed") ) ? coeffInfo.at("phaseFixed").get() : rhs.phase_->fixed() }; + + phase_ = std::make_unique("Delta", phaseVal, minPhase_, maxPhase_, phaseFixed); + if ( rhs.phase_->blind() ) { const LauBlind* blinder { rhs.phase_->blinder() }; phase_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauMagPhaseCoeffSet::getParameters() { return { magnitude_.get(), phase_.get() }; } std::vector LauMagPhaseCoeffSet::getParameters() const { return { magnitude_.get(), phase_.get() }; } void LauMagPhaseCoeffSet::printParValues() const { std::cout<<"INFO in LauMagPhaseCoeffSet::printParValues : Component \""<name()<<"\" has magnitude = "<value()<<" and phase = "<value()<<"."<name() }; resName = resName.ReplaceAll("_", "\\_"); stream<value()); stream<<" \\pm "; print.printFormat(stream, magnitude_->error()); stream<<"$ & $"; print.printFormat(stream, phase_->value()); stream<<" \\pm "; print.printFormat(stream, phase_->error()); stream<<"$ \\\\"<fixed() == kFALSE) { // Choose a magnitude between 0.0 and 2.0 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) +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 }; + if ( this->clone() ) { + const LauMagPhaseCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::MagPhase ) { - throw LauWrongCoeffType("Wrong coefficient type given to construct LauMagPhaseCoeffSet"); + throw LauWrongCoeffType{"Wrong coefficient type given to construct LauMagPhaseCoeffSet"}; } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauMagPhaseCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t mag { j.at("mag").get() }; const Double_t phase { j.at("phase").get() }; const Bool_t magFixed { j.at("magFixed").get() }; const Bool_t phaseFixed { j.at("phaseFixed").get() }; return { name, mag, phase, magFixed, phaseFixed }; } void nlohmann::adl_serializer::to_json(json& j, const LauMagPhaseCoeffSet& t) { j["type"] = LauCoeffType::MagPhase; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["mag"] = pars[0]->value(); - j["phase"] = pars[1]->value(); - j["magFixed"] = pars[0]->fixed(); - j["phaseFixed"] = pars[1]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } + + if ( ! pars[0]->clone() ) { + j["mag"] = pars[0]->value(); + j["magFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["phase"] = pars[1]->value(); + j["phaseFixed"] = pars[1]->fixed(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauNSCCartesianCPCoeffSet.cc b/src/LauNSCCartesianCPCoeffSet.cc index 0338f9a..bd916e3 100644 --- a/src/LauNSCCartesianCPCoeffSet.cc +++ b/src/LauNSCCartesianCPCoeffSet.cc @@ -1,407 +1,465 @@ /* 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 "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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); xPrime_.reset( rhs.xPrime_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); - xPrime_ = std::make_unique("XPrime", rhs.xPrime_->value(), minRealImagPart_, maxRealImagPart_, rhs.xPrime_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + + const Double_t xPrimeVal { ( coeffInfo.contains("xPrime") ) ? coeffInfo.at("xPrime").get() : rhs.xPrime_->value() }; + const Bool_t xPrimeFixed { ( coeffInfo.contains("xPrimeFixed") ) ? coeffInfo.at("xPrimeFixed").get() : rhs.xPrime_->fixed() }; + + xPrime_ = std::make_unique("XPrime", xPrimeVal, minRealImagPart_, maxRealImagPart_, xPrimeFixed); } if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieImagPart ) { y_.reset( rhs.y_->createClone(constFactor) ); yPrime_.reset( rhs.yPrime_->createClone(constFactor) ); } else { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); - yPrime_ = std::make_unique("YPrime", rhs.yPrime_->value(), minRealImagPart_, maxRealImagPart_, rhs.yPrime_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + + const Double_t yPrimeVal { ( coeffInfo.contains("yPrime") ) ? coeffInfo.at("yPrime").get() : rhs.yPrime_->value() }; + const Bool_t yPrimeFixed { ( coeffInfo.contains("yPrimeFixed") ) ? coeffInfo.at("yPrimeFixed").get() : rhs.yPrime_->fixed() }; + + yPrime_ = std::make_unique("YPrime", yPrimeVal, minRealImagPart_, maxRealImagPart_, yPrimeFixed); } 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 { - deltaX_ = std::make_unique("DeltaX", rhs.deltaX_->value(), minDelta_, maxDelta_, rhs.deltaX_->fixed()); - deltaY_ = std::make_unique("DeltaY", rhs.deltaY_->value(), minDelta_, maxDelta_, rhs.deltaY_->fixed()); - deltaXPrime_ = std::make_unique("DeltaXPrime", rhs.deltaXPrime_->value(), minDelta_, maxDelta_, rhs.deltaXPrime_->fixed()); - deltaYPrime_ = std::make_unique("DeltaYPrime", rhs.deltaYPrime_->value(), minDelta_, maxDelta_, rhs.deltaYPrime_->fixed()); - if ( rhs.deltaX_->secondStage() && !rhs.deltaX_->fixed() ) { + const Double_t deltaXVal { ( coeffInfo.contains("deltaX") ) ? coeffInfo.at("deltaX").get() : rhs.deltaX_->value() }; + const Bool_t deltaXFixed { ( coeffInfo.contains("deltaXFixed") ) ? coeffInfo.at("deltaXFixed").get() : rhs.deltaX_->fixed() }; + const Bool_t deltaXSecondStage { ( coeffInfo.contains("deltaXSecondStage") ) ? coeffInfo.at("deltaXSecondStage").get() : rhs.deltaX_->secondStage() }; + + const Double_t deltaYVal { ( coeffInfo.contains("deltaY") ) ? coeffInfo.at("deltaY").get() : rhs.deltaY_->value() }; + const Bool_t deltaYFixed { ( coeffInfo.contains("deltaYFixed") ) ? coeffInfo.at("deltaYFixed").get() : rhs.deltaY_->fixed() }; + const Bool_t deltaYSecondStage { ( coeffInfo.contains("deltaYSecondStage") ) ? coeffInfo.at("deltaYSecondStage").get() : rhs.deltaY_->secondStage() }; + + deltaX_ = std::make_unique("DeltaX", deltaXVal, minDelta_, maxDelta_, deltaXFixed); + deltaY_ = std::make_unique("DeltaY", deltaYVal, minDelta_, maxDelta_, deltaYFixed); + + const Double_t deltaXPrimeVal { ( coeffInfo.contains("deltaXPrime") ) ? coeffInfo.at("deltaXPrime").get() : rhs.deltaXPrime_->value() }; + const Bool_t deltaXPrimeFixed { ( coeffInfo.contains("deltaXPrimeFixed") ) ? coeffInfo.at("deltaXPrimeFixed").get() : rhs.deltaXPrime_->fixed() }; + const Bool_t deltaXPrimeSecondStage { ( coeffInfo.contains("deltaXPrimeSecondStage") ) ? coeffInfo.at("deltaXPrimeSecondStage").get() : rhs.deltaXPrime_->secondStage() }; + + const Double_t deltaYPrimeVal { ( coeffInfo.contains("deltaYPrime") ) ? coeffInfo.at("deltaYPrime").get() : rhs.deltaYPrime_->value() }; + const Bool_t deltaYPrimeFixed { ( coeffInfo.contains("deltaYPrimeFixed") ) ? coeffInfo.at("deltaYPrimeFixed").get() : rhs.deltaYPrime_->fixed() }; + const Bool_t deltaYPrimeSecondStage { ( coeffInfo.contains("deltaYPrimeSecondStage") ) ? coeffInfo.at("deltaYPrimeSecondStage").get() : rhs.deltaYPrime_->secondStage() }; + + deltaXPrime_ = std::make_unique("DeltaXPrime", deltaXPrimeVal, minDelta_, maxDelta_, deltaXPrimeFixed); + deltaYPrime_ = std::make_unique("DeltaYPrime", deltaYPrimeVal, minDelta_, maxDelta_, deltaYPrimeFixed); + + if ( deltaXSecondStage && !deltaXFixed ) { deltaX_->secondStage(kTRUE); deltaX_->initValue(0.0); } - if ( rhs.deltaY_->secondStage() && !rhs.deltaY_->fixed() ) { + if ( deltaYSecondStage && !deltaYFixed ) { deltaY_->secondStage(kTRUE); deltaY_->initValue(0.0); } - if ( rhs.deltaXPrime_->secondStage() && !rhs.deltaXPrime_->fixed() ) { + if ( deltaXPrimeSecondStage && !deltaXPrimeFixed ) { deltaXPrime_->secondStage(kTRUE); deltaXPrime_->initValue(0.0); } - if ( rhs.deltaYPrime_->secondStage() && !rhs.deltaYPrime_->fixed() ) { + if ( deltaYPrimeSecondStage && !deltaYPrimeFixed ) { deltaYPrime_->secondStage(kTRUE); deltaYPrime_->initValue(0.0); } } } std::vector LauNSCCartesianCPCoeffSet::getParameters() { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get(), xPrime_.get(), yPrime_.get(), deltaXPrime_.get(), deltaYPrime_.get() }; } std::vector LauNSCCartesianCPCoeffSet::getParameters() const { return { x_.get(), y_.get(), deltaX_.get(), deltaY_.get(), xPrime_.get(), yPrime_.get(), deltaXPrime_.get(), deltaYPrime_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauNSCCartesianCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + auto clone = new LauNSCCartesianCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauNSCCartesianCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::NSCCartesianCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauNSCCartesianCPCoeffSet"); } + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauNSCCartesianCPCoeffSet standalone"}; + } + const TString name { j.at("name").get().c_str() }; const Bool_t finalStateIsF { j.at("finalStateIsF").get() }; - // TODO - handle cloned coeffs - const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t deltaX { j.at("deltaX").get() }; const Double_t deltaY { j.at("deltaY").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t deltaXFixed { j.at("deltaXFixed").get() }; const Bool_t deltaYFixed { j.at("deltaYFixed").get() }; const Bool_t deltaXSecondStage { j.at("deltaXSecondStage").get() }; const Bool_t deltaYSecondStage { j.at("deltaYSecondStage").get() }; const Double_t xPrime { j.at("xPrime").get() }; const Double_t yPrime { j.at("yPrime").get() }; const Double_t deltaXPrime { j.at("deltaXPrime").get() }; const Double_t deltaYPrime { j.at("deltaYPrime").get() }; const Bool_t xPrimeFixed { j.at("xPrimeFixed").get() }; const Bool_t yPrimeFixed { j.at("yPrimeFixed").get() }; const Bool_t deltaXPrimeFixed { j.at("deltaXPrimeFixed").get() }; const Bool_t deltaYPrimeFixed { j.at("deltaYPrimeFixed").get() }; const Bool_t deltaXPrimeSecondStage { j.at("deltaXPrimeSecondStage").get() }; const Bool_t deltaYPrimeSecondStage { j.at("deltaYPrimeSecondStage").get() }; return { name, finalStateIsF, x, y, deltaX, deltaY, xFixed, yFixed, deltaXFixed, deltaYFixed, deltaXSecondStage, deltaYSecondStage, xPrime, yPrime, deltaXPrime, deltaYPrime, xPrimeFixed, yPrimeFixed, deltaXPrimeFixed, deltaYPrimeFixed, deltaXPrimeSecondStage, deltaYPrimeSecondStage }; } void nlohmann::adl_serializer::to_json(json& j, const LauNSCCartesianCPCoeffSet& t) { j["type"] = LauCoeffType::NSCCartesianCP; j["name"] = t.name(); j["finalStateIsF"] = t.finalStateIsF(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["deltaX"] = pars[2]->value(); - j["deltaY"] = pars[3]->value(); - - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["deltaXFixed"] = pars[2]->fixed(); - j["deltaYFixed"] = pars[3]->fixed(); - - j["deltaXSecondStage"] = pars[2]->secondStage(); - j["deltaYSecondStage"] = pars[3]->secondStage(); - - j["xPrime"] = pars[4]->value(); - j["yPrime"] = pars[5]->value(); - j["deltaXPrime"] = pars[6]->value(); - j["deltaYPrime"] = pars[7]->value(); - - j["xPrimeFixed"] = pars[4]->fixed(); - j["yPrimeFixed"] = pars[5]->fixed(); - j["deltaXPrimeFixed"] = pars[6]->fixed(); - j["deltaYPrimeFixed"] = pars[7]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["deltaXPrimeSecondStage"] = pars[6]->secondStage(); - j["deltaYPrimeSecondStage"] = pars[7]->secondStage(); + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["deltaX"] = pars[2]->value(); + j["deltaXFixed"] = pars[2]->fixed(); + j["deltaXSecondStage"] = pars[2]->secondStage(); + } + if ( ! pars[3]->clone() ) { + j["deltaY"] = pars[3]->value(); + j["deltaYFixed"] = pars[3]->fixed(); + j["deltaYSecondStage"] = pars[3]->secondStage(); + } + if ( ! pars[4]->clone() ) { + j["xPrime"] = pars[4]->value(); + j["xPrimeFixed"] = pars[4]->fixed(); + } + if ( ! pars[5]->clone() ) { + j["yPrime"] = pars[5]->value(); + j["yPrimeFixed"] = pars[5]->fixed(); + } + if ( ! pars[6]->clone() ) { + j["deltaXPrime"] = pars[6]->value(); + j["deltaXPrimeFixed"] = pars[6]->fixed(); + j["deltaXPrimeSecondStage"] = pars[6]->secondStage(); + } + if ( ! pars[7]->clone() ) { + j["deltaYPrime"] = pars[7]->value(); + j["deltaYPrimeFixed"] = pars[7]->fixed(); + j["deltaYPrimeSecondStage"] = pars[7]->secondStage(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauPolarGammaCPCoeffSet.cc b/src/LauPolarGammaCPCoeffSet.cc index 3e80b78..fb3e660 100644 --- a/src/LauPolarGammaCPCoeffSet.cc +++ b/src/LauPolarGammaCPCoeffSet.cc @@ -1,892 +1,961 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauPolarGammaCPCoeffSet.cc \brief File containing implementation of LauPolarGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauPolarGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + 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 { - gamma_ = std::make_shared("gamma", rhs.gamma_->value(), minPhase_, maxPhase_, rhs.gamma_->fixed()); + const Double_t gammaVal { ( coeffInfo.contains("gamma") ) ? coeffInfo.at("gamma").get() : rhs.gamma_->value() }; + const Bool_t gammaFixed { ( coeffInfo.contains("gammaFixed") ) ? coeffInfo.at("gammaFixed").get() : rhs.gamma_->fixed() }; + const Bool_t gammaSecondStage { ( coeffInfo.contains("gammaSecondStage") ) ? coeffInfo.at("gammaSecondStage").get() : rhs.gamma_->secondStage() }; + + gamma_ = std::make_shared("gamma", gammaVal, minPhase_, maxPhase_, gammaFixed); + + if ( gammaSecondStage && !gammaFixed ) { + gamma_->secondStage(kTRUE); + gamma_->initValue(0.0); + } + if ( rhs.gamma_->blind() ) { const LauBlind* blinder { rhs.gamma_->blinder() }; gamma_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - if ( rhs.gamma_->secondStage() && !rhs.gamma_->fixed() ) { - gamma_->secondStage(kTRUE); - gamma_->initValue(0.0); - } } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::GLW_CPOdd || decayType_ == DecayType::GLW_CPEven ) { - rB_ = std::make_unique("rB", rhs.rB_->value(), minMagnitude_, maxMagnitude_, rhs.rB_->fixed()); + const Double_t rBVal { ( coeffInfo.contains("rB") ) ? coeffInfo.at("rB").get() : rhs.rB_->value() }; + const Bool_t rBFixed { ( coeffInfo.contains("rBFixed") ) ? coeffInfo.at("rBFixed").get() : rhs.rB_->fixed() }; + const Bool_t rBSecondStage { ( coeffInfo.contains("rBSecondStage") ) ? coeffInfo.at("rBSecondStage").get() : rhs.rB_->secondStage() }; + + rB_ = std::make_unique("rB", rBVal, minMagnitude_, maxMagnitude_, rBFixed); + + if ( rBSecondStage && !rBFixed ) { + rB_->secondStage(kTRUE); + rB_->initValue(0.0); + } + if ( rhs.rB_->blind() ) { const LauBlind* blinder { rhs.rB_->blinder() }; rB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - deltaB_ = std::make_unique("deltaB", rhs.deltaB_->value(), minPhase_, maxPhase_, rhs.deltaB_->fixed()); + + const Double_t deltaBVal { ( coeffInfo.contains("deltaB") ) ? coeffInfo.at("deltaB").get() : rhs.deltaB_->value() }; + const Bool_t deltaBFixed { ( coeffInfo.contains("deltaBFixed") ) ? coeffInfo.at("deltaBFixed").get() : rhs.deltaB_->fixed() }; + const Bool_t deltaBSecondStage { ( coeffInfo.contains("deltaBSecondStage") ) ? coeffInfo.at("deltaBSecondStage").get() : rhs.deltaB_->secondStage() }; + + deltaB_ = std::make_unique("deltaB", deltaBVal, minPhase_, maxPhase_, deltaBFixed); + + if ( deltaBSecondStage && !deltaBFixed ) { + deltaB_->secondStage(kTRUE); + deltaB_->initValue(0.0); + } + if ( rhs.deltaB_->blind() ) { const LauBlind* blinder { rhs.deltaB_->blinder() }; deltaB_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - if ( rhs.rB_->secondStage() && !rhs.rB_->fixed() ) { - rB_->secondStage(kTRUE); - rB_->initValue(0.0); - } - if ( rhs.deltaB_->secondStage() && !rhs.deltaB_->fixed() ) { - deltaB_->secondStage(kTRUE); - deltaB_->initValue(0.0); - } } if ( decayType_ == DecayType::ADS_Favoured || decayType_ == DecayType::ADS_Suppressed || decayType_ == DecayType::ADS_Favoured_btouOnly ) { if ( useGlobalADSPars_ ) { rD_.reset( rDGlobal_->createClone() ); deltaD_.reset( deltaDGlobal_->createClone() ); } else { - rD_ = std::make_shared("rD", rhs.rD_->value(), minMagnitude_, maxMagnitude_, rhs.rD_->fixed()); + const Double_t rDVal { ( coeffInfo.contains("rD") ) ? coeffInfo.at("rD").get() : rhs.rD_->value() }; + const Bool_t rDFixed { ( coeffInfo.contains("rDFixed") ) ? coeffInfo.at("rDFixed").get() : rhs.rD_->fixed() }; + const Bool_t rDSecondStage { ( coeffInfo.contains("rDSecondStage") ) ? coeffInfo.at("rDSecondStage").get() : rhs.rD_->secondStage() }; + + rD_ = std::make_unique("rD", rDVal, minMagnitude_, maxMagnitude_, rDFixed); + + if ( rDSecondStage && !rDFixed ) { + rD_->secondStage(kTRUE); + rD_->initValue(0.0); + } + if ( rhs.rD_->blind() ) { const LauBlind* blinder { rhs.rD_->blinder() }; rD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - deltaD_ = std::make_shared("deltaD", rhs.deltaD_->value(), minPhase_, maxPhase_, rhs.deltaD_->fixed()); + + const Double_t deltaDVal { ( coeffInfo.contains("deltaD") ) ? coeffInfo.at("deltaD").get() : rhs.deltaD_->value() }; + const Bool_t deltaDFixed { ( coeffInfo.contains("deltaDFixed") ) ? coeffInfo.at("deltaDFixed").get() : rhs.deltaD_->fixed() }; + const Bool_t deltaDSecondStage { ( coeffInfo.contains("deltaDSecondStage") ) ? coeffInfo.at("deltaDSecondStage").get() : rhs.deltaD_->secondStage() }; + + deltaD_ = std::make_unique("deltaD", deltaDVal, minPhase_, maxPhase_, deltaDFixed); + + if ( deltaDSecondStage && !deltaDFixed ) { + deltaD_->secondStage(kTRUE); + deltaD_->initValue(0.0); + } + if ( rhs.deltaD_->blind() ) { const LauBlind* blinder { rhs.deltaD_->blinder() }; deltaD_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - if ( rhs.rD_->secondStage() && !rhs.rD_->fixed() ) { - rD_->secondStage(kTRUE); - rD_->initValue(0.0); - } - if ( rhs.deltaD_->secondStage() && !rhs.deltaD_->fixed() ) { - deltaD_->secondStage(kTRUE); - deltaD_->initValue(0.0); - } } } } } void LauPolarGammaCPCoeffSet::adjustName(LauParameter& par, const TString& oldBaseName) { if ( ( &par == gamma_.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; } 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) +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 ); + if ( this->clone() ) { + const LauPolarGammaCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + auto clone = new LauPolarGammaCPCoeffSet{ *this, cloneOption, constFactor, coeffInfo }; clone->name( newName ); return clone; } //! \cond DOXYGEN_IGNORE LauPolarGammaCPCoeffSet nlohmann::adl_serializer::from_json(const json& j) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::PolarGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauPolarGammaCPCoeffSet"); } + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauPolarGammaCPCoeffSet standalone"}; + } + const TString name { j.at("name").get().c_str() }; const LauPolarGammaCPCoeffSet::DecayType decayType { j.at("decayType").get() }; - // TODO - handle cloned coeffs - const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t rB { j.at("rB").get() }; const Double_t deltaB { j.at("deltaB").get() }; const Double_t gamma { j.at("gamma").get() }; const Double_t rD { j.at("rD").get() }; const Double_t deltaD { j.at("deltaD").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t rBFixed { j.at("rBFixed").get() }; const Bool_t deltaBFixed { j.at("deltaBFixed").get() }; const Bool_t gammaFixed { j.at("gammaFixed").get() }; const Bool_t rDFixed { j.at("rDFixed").get() }; const Bool_t deltaDFixed { j.at("deltaDFixed").get() }; const Bool_t rBSecondStage { j.at("rBSecondStage").get() }; const Bool_t deltaBSecondStage { j.at("deltaBSecondStage").get() }; const Bool_t gammaSecondStage { j.at("gammaSecondStage").get() }; const Bool_t rDSecondStage { j.at("rDSecondStage").get() }; const Bool_t deltaDSecondStage { j.at("deltaDSecondStage").get() }; const Bool_t useGlobalGamma { j.at("useGlobalGamma").get() }; const Bool_t useGlobalADSPars { j.at("useGlobalADSPars").get() }; return { name, decayType, x, y, rB, deltaB, gamma, rD, deltaD, xFixed, yFixed, rBFixed, deltaBFixed, gammaFixed, rDFixed, deltaDFixed, rBSecondStage, deltaBSecondStage, gammaSecondStage, rDSecondStage, deltaDSecondStage, useGlobalGamma, useGlobalADSPars }; } void nlohmann::adl_serializer::to_json(json& j, const LauPolarGammaCPCoeffSet& t) { j["type"] = LauCoeffType::PolarGammaCP; j["name"] = t.name(); const LauPolarGammaCPCoeffSet::DecayType decayType { t.decayType() }; j["decayType"] = decayType; j["useGlobalGamma"] = t.useGlobalGamma(); j["useGlobalADSPars"] = t.useGlobalADSPars(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["gamma"] = pars[2]->value(); - - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["gammaFixed"] = pars[2]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["gammaSecondStage"] = pars[2]->secondStage(); + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["gamma"] = pars[2]->value(); + j["gammaFixed"] = pars[2]->fixed(); + j["gammaSecondStage"] = pars[2]->secondStage(); + } switch ( decayType ) { case LauPolarGammaCPCoeffSet::DecayType::GLW_CPOdd : case LauPolarGammaCPCoeffSet::DecayType::GLW_CPEven : - j["rB"] = pars[3]->value(); - j["deltaB"] = pars[4]->value(); - - j["rBFixed"] = pars[3]->fixed(); - j["deltaBFixed"] = pars[4]->fixed(); - - j["rBSecondStage"] = pars[3]->secondStage(); - j["deltaBSecondStage"] = pars[4]->secondStage(); + if ( ! pars[3]->clone() ) { + j["rB"] = pars[3]->value(); + j["rBFixed"] = pars[3]->fixed(); + j["rBSecondStage"] = pars[3]->secondStage(); + } + if ( ! pars[4]->clone() ) { + j["deltaB"] = pars[4]->value(); + j["deltaBFixed"] = pars[4]->fixed(); + j["deltaBSecondStage"] = pars[4]->secondStage(); + } break; case LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured : case LauPolarGammaCPCoeffSet::DecayType::ADS_Suppressed : - j["rB"] = pars[3]->value(); - j["deltaB"] = pars[4]->value(); - j["rD"] = pars[5]->value(); - j["deltaD"] = pars[6]->value(); - - j["rBFixed"] = pars[3]->fixed(); - j["deltaBFixed"] = pars[4]->fixed(); - j["rDFixed"] = pars[5]->fixed(); - j["deltaDFixed"] = pars[6]->fixed(); - - j["rBSecondStage"] = pars[3]->secondStage(); - j["deltaBSecondStage"] = pars[4]->secondStage(); - j["rDSecondStage"] = pars[5]->secondStage(); - j["deltaDSecondStage"] = pars[6]->secondStage(); + if ( ! pars[3]->clone() ) { + j["rB"] = pars[3]->value(); + j["rBFixed"] = pars[3]->fixed(); + j["rBSecondStage"] = pars[3]->secondStage(); + } + if ( ! pars[4]->clone() ) { + j["deltaB"] = pars[4]->value(); + j["deltaBFixed"] = pars[4]->fixed(); + j["deltaBSecondStage"] = pars[4]->secondStage(); + } + if ( ! pars[5]->clone() ) { + j["rD"] = pars[5]->value(); + j["rDFixed"] = pars[5]->fixed(); + j["rDSecondStage"] = pars[5]->secondStage(); + } + if ( ! pars[6]->clone() ) { + j["deltaD"] = pars[6]->value(); + j["deltaDFixed"] = pars[6]->fixed(); + j["deltaDSecondStage"] = pars[6]->secondStage(); + } break; case LauPolarGammaCPCoeffSet::DecayType::GLW_CPOdd_btouOnly : case LauPolarGammaCPCoeffSet::DecayType::GLW_CPEven_btouOnly : case LauPolarGammaCPCoeffSet::DecayType::ADS_Suppressed_btouOnly : break; case LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured_btouOnly : - j["rD"] = pars[3]->value(); - j["deltaD"] = pars[4]->value(); - - j["rDFixed"] = pars[3]->fixed(); - j["deltaDFixed"] = pars[4]->fixed(); - - j["rDSecondStage"] = pars[3]->secondStage(); - j["deltaDSecondStage"] = pars[4]->secondStage(); + if ( ! pars[3]->clone() ) { + j["rD"] = pars[3]->value(); + j["rDFixed"] = pars[3]->fixed(); + j["rDSecondStage"] = pars[3]->secondStage(); + } + if ( ! pars[4]->clone() ) { + j["deltaD"] = pars[4]->value(); + j["deltaDFixed"] = pars[4]->fixed(); + j["deltaDSecondStage"] = pars[4]->secondStage(); + } break; }; } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauRealImagCPCoeffSet.cc b/src/LauRealImagCPCoeffSet.cc index 9375e91..a1f8306 100644 --- a/src/LauRealImagCPCoeffSet.cc +++ b/src/LauRealImagCPCoeffSet.cc @@ -1,300 +1,340 @@ /* 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 "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, CloneOption cloneOption, Double_t constFactor) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); xbar_.reset( rhs.xbar_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + if ( rhs.x_->blind() ) { const LauBlind* blinder { rhs.x_->blinder() }; x_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - xbar_ = std::make_unique("Xbar", rhs.xbar_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbar_->fixed()); + + const Double_t xbarVal { ( coeffInfo.contains("xbar") ) ? coeffInfo.at("xbar").get() : rhs.xbar_->value() }; + const Bool_t xbarFixed { ( coeffInfo.contains("xbarFixed") ) ? coeffInfo.at("xbarFixed").get() : rhs.xbar_->fixed() }; + + xbar_ = std::make_unique("Xbar", xbarVal, minRealImagPart_, maxRealImagPart_, xbarFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + if ( rhs.y_->blind() ) { const LauBlind* blinder { rhs.y_->blinder() }; y_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - ybar_ = std::make_unique("Ybar", rhs.ybar_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybar_->fixed()); + + const Double_t ybarVal { ( coeffInfo.contains("ybar") ) ? coeffInfo.at("ybar").get() : rhs.ybar_->value() }; + const Bool_t ybarFixed { ( coeffInfo.contains("ybarFixed") ) ? coeffInfo.at("ybarFixed").get() : rhs.ybar_->fixed() }; + + ybar_ = std::make_unique("Ybar", ybarVal, minRealImagPart_, maxRealImagPart_, ybarFixed); + if ( rhs.ybar_->blind() ) { const LauBlind* blinder { rhs.ybar_->blinder() }; ybar_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagCPCoeffSet::getParameters() { return { x_.get(), y_.get(), xbar_.get(), ybar_.get() }; } std::vector LauRealImagCPCoeffSet::getParameters() const { return { x_.get(), y_.get(), xbar_.get(), ybar_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauRealImagCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::RealImagCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauRealImagCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t xbar { j.at("xbar").get() }; const Double_t ybar { j.at("ybar").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t xbarFixed { j.at("xbarFixed").get() }; const Bool_t ybarFixed { j.at("ybarFixed").get() }; return { name, x, y, xbar, ybar, xFixed, yFixed, xbarFixed, ybarFixed }; } void nlohmann::adl_serializer::to_json(json& j, const LauRealImagCPCoeffSet& t) { j["type"] = LauCoeffType::RealImagCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["xbar"] = pars[2]->value(); - j["ybar"] = pars[3]->value(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["xbarFixed"] = pars[2]->fixed(); - j["ybarFixed"] = pars[3]->fixed(); + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["xbar"] = pars[2]->value(); + j["xbarFixed"] = pars[2]->fixed(); + } + if ( ! pars[3]->clone() ) { + j["ybar"] = pars[3]->value(); + j["ybarFixed"] = pars[3]->fixed(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauRealImagCoeffSet.cc b/src/LauRealImagCoeffSet.cc index f41e462..33b44e1 100644 --- a/src/LauRealImagCoeffSet.cc +++ b/src/LauRealImagCoeffSet.cc @@ -1,211 +1,238 @@ /* Copyright 2006 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagCoeffSet.cc \brief File containing implementation of LauRealImagCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauRealImagCoeffSet.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauRealImagCoeffSet) LauRealImagCoeffSet::LauRealImagCoeffSet(const TString& compName, 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, CloneOption cloneOption, Double_t constFactor) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + 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) +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 }; + if ( this->clone() ) { + const LauRealImagCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::RealImag ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauRealImagCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; return { name, x, y, xFixed, yFixed }; } void nlohmann::adl_serializer::to_json(json& j, const LauRealImagCoeffSet& t) { j["type"] = LauCoeffType::RealImag; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } + + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/src/LauRealImagGammaCPCoeffSet.cc b/src/LauRealImagGammaCPCoeffSet.cc index c0050b7..e83bd23 100644 --- a/src/LauRealImagGammaCPCoeffSet.cc +++ b/src/LauRealImagGammaCPCoeffSet.cc @@ -1,359 +1,412 @@ /* Copyright 2014 University of Warwick Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Laura++ package authors: John Back Paul Harrison Thomas Latham */ /*! \file LauRealImagGammaCPCoeffSet.cc \brief File containing implementation of LauRealImagGammaCPCoeffSet class. */ #include #include #include #include "TMath.h" #include "TRandom.h" #include "LauRealImagGammaCPCoeffSet.hh" #include "LauComplex.hh" #include "LauConstants.hh" #include "LauParameter.hh" #include "LauPrint.hh" ClassImp(LauRealImagGammaCPCoeffSet) LauRealImagGammaCPCoeffSet::LauRealImagGammaCPCoeffSet(const TString& compName, const Double_t x, const Double_t y, const Double_t xCP, const Double_t yCP, const Double_t xbarCP, const Double_t ybarCP, const Bool_t xFixed, const Bool_t yFixed, const Bool_t xCPFixed, const Bool_t yCPFixed, const Bool_t xbarCPFixed, const Bool_t ybarCPFixed) : LauAbsCoeffSet{ compName }, x_{ 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) : - LauAbsCoeffSet{ rhs.name() }, +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_ } { if ( cloneOption == CloneOption::All || cloneOption == CloneOption::TieRealPart ) { x_.reset( rhs.x_->createClone(constFactor) ); } else { - x_ = std::make_unique("X", rhs.x_->value(), minRealImagPart_, maxRealImagPart_, rhs.x_->fixed()); + const Double_t xVal { ( coeffInfo.contains("x") ) ? coeffInfo.at("x").get() : rhs.x_->value() }; + const Bool_t xFixed { ( coeffInfo.contains("xFixed") ) ? coeffInfo.at("xFixed").get() : rhs.x_->fixed() }; + + x_ = std::make_unique("X", xVal, minRealImagPart_, maxRealImagPart_, xFixed); + 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 { - y_ = std::make_unique("Y", rhs.y_->value(), minRealImagPart_, maxRealImagPart_, rhs.y_->fixed()); + const Double_t yVal { ( coeffInfo.contains("y") ) ? coeffInfo.at("y").get() : rhs.y_->value() }; + const Bool_t yFixed { ( coeffInfo.contains("yFixed") ) ? coeffInfo.at("yFixed").get() : rhs.y_->fixed() }; + + y_ = std::make_unique("Y", yVal, minRealImagPart_, maxRealImagPart_, yFixed); + 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 { - xCP_ = std::make_unique("XCP", rhs.xCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xCP_->fixed()); + const Double_t xCPVal { ( coeffInfo.contains("xCP") ) ? coeffInfo.at("xCP").get() : rhs.xCP_->value() }; + const Bool_t xCPFixed { ( coeffInfo.contains("xCPFixed") ) ? coeffInfo.at("xCPFixed").get() : rhs.xCP_->fixed() }; + + xCP_ = std::make_unique("XCP", xCPVal, minRealImagPart_, maxRealImagPart_, xCPFixed); + if ( rhs.xCP_->blind() ) { const LauBlind* blinder { rhs.xCP_->blinder() }; xCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - yCP_ = std::make_unique("YCP", rhs.yCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.yCP_->fixed()); + + const Double_t yCPVal { ( coeffInfo.contains("yCP") ) ? coeffInfo.at("yCP").get() : rhs.yCP_->value() }; + const Bool_t yCPFixed { ( coeffInfo.contains("yCPFixed") ) ? coeffInfo.at("yCPFixed").get() : rhs.yCP_->fixed() }; + + yCP_ = std::make_unique("YCP", yCPVal, minRealImagPart_, maxRealImagPart_, yCPFixed); + if ( rhs.yCP_->blind() ) { const LauBlind* blinder { rhs.yCP_->blinder() }; yCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - xbarCP_ = std::make_unique("XbarCP", rhs.xbarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.xbarCP_->fixed()); + + const Double_t xbarCPVal { ( coeffInfo.contains("xbarCP") ) ? coeffInfo.at("xbarCP").get() : rhs.xbarCP_->value() }; + const Bool_t xbarCPFixed { ( coeffInfo.contains("xbarCPFixed") ) ? coeffInfo.at("xbarCPFixed").get() : rhs.xbarCP_->fixed() }; + + xbarCP_ = std::make_unique("XbarCP", xbarCPVal, minRealImagPart_, maxRealImagPart_, xbarCPFixed); + if ( rhs.xbarCP_->blind() ) { const LauBlind* blinder { rhs.xbarCP_->blinder() }; xbarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } - ybarCP_ = std::make_unique("YbarCP", rhs.ybarCP_->value(), minRealImagPart_, maxRealImagPart_, rhs.ybarCP_->fixed()); + + const Double_t ybarCPVal { ( coeffInfo.contains("ybarCP") ) ? coeffInfo.at("ybarCP").get() : rhs.ybarCP_->value() }; + const Bool_t ybarCPFixed { ( coeffInfo.contains("ybarCPFixed") ) ? coeffInfo.at("ybarCPFixed").get() : rhs.ybarCP_->fixed() }; + + ybarCP_ = std::make_unique("YbarCP", ybarCPVal, minRealImagPart_, maxRealImagPart_, ybarCPFixed); + if ( rhs.ybarCP_->blind() ) { const LauBlind* blinder { rhs.ybarCP_->blinder() }; ybarCP_->blindParameter( blinder->blindingString(), blinder->blindingWidth() ); } } } std::vector LauRealImagGammaCPCoeffSet::getParameters() { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), xbarCP_.get(), ybarCP_.get() }; } std::vector LauRealImagGammaCPCoeffSet::getParameters() const { return { x_.get(), y_.get(), xCP_.get(), yCP_.get(), xbarCP_.get(), ybarCP_.get() }; } 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) +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 }; + if ( this->clone() ) { + const LauRealImagGammaCPCoeffSet* parent { static_cast(this->parent()) }; + return parent->createClone_impl( newName, cloneOption, constFactor, coeffInfo ); + } + + 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) { const LauCoeffType type { j.at("type").get() }; if ( type != LauCoeffType::RealImagGammaCP ) { throw LauWrongCoeffType("Wrong coefficient type given to construct LauRealImagGammaCPCoeffSet"); } - const TString name { j.at("name").get().c_str() }; + const Bool_t clone { j.at("clone").get() }; + if ( clone ) { + throw LauClonedCoeff{"Cannot build a cloned LauRealImagGammaCPCoeffSet standalone"}; + } - // TODO - handle cloned coeffs + const TString name { j.at("name").get().c_str() }; const Double_t x { j.at("x").get() }; const Double_t y { j.at("y").get() }; const Double_t xCP { j.at("xCP").get() }; const Double_t yCP { j.at("yCP").get() }; const Double_t xbarCP { j.at("xbarCP").get() }; const Double_t ybarCP { j.at("ybarCP").get() }; const Bool_t xFixed { j.at("xFixed").get() }; const Bool_t yFixed { j.at("yFixed").get() }; const Bool_t xCPFixed { j.at("xCPFixed").get() }; const Bool_t yCPFixed { j.at("yCPFixed").get() }; const Bool_t xbarCPFixed { j.at("xbarCPFixed").get() }; const Bool_t ybarCPFixed { j.at("ybarCPFixed").get() }; return { name, x, y, xCP, yCP, xbarCP, ybarCP, xFixed, yFixed, xCPFixed, yCPFixed, xbarCPFixed, ybarCPFixed }; } void nlohmann::adl_serializer::to_json(json& j, const LauRealImagGammaCPCoeffSet& t) { j["type"] = LauCoeffType::RealImagGammaCP; j["name"] = t.name(); - // TODO - handle cloned coeffs - auto pars = t.getParameters(); - j["x"] = pars[0]->value(); - j["y"] = pars[1]->value(); - j["xCP"] = pars[2]->value(); - j["yCP"] = pars[3]->value(); - j["xbarCP"] = pars[4]->value(); - j["ybarCP"] = pars[5]->value(); - - j["xFixed"] = pars[0]->fixed(); - j["yFixed"] = pars[1]->fixed(); - j["xCPFixed"] = pars[2]->fixed(); - j["yCPFixed"] = pars[3]->fixed(); - j["xbarCPFixed"] = pars[4]->fixed(); - j["ybarCPFixed"] = pars[5]->fixed(); + if ( t.clone() ) { + j["clone"] = true; + j["parent"] = t.parent()->name(); + j["cloneOption"] = t.cloneOption(); + j["constFactor"] = t.constFactor(); + } else { + j["clone"] = false; + } + + if ( ! pars[0]->clone() ) { + j["x"] = pars[0]->value(); + j["xFixed"] = pars[0]->fixed(); + } + if ( ! pars[1]->clone() ) { + j["y"] = pars[1]->value(); + j["yFixed"] = pars[1]->fixed(); + } + if ( ! pars[2]->clone() ) { + j["xCP"] = pars[2]->value(); + j["xCPFixed"] = pars[2]->fixed(); + } + if ( ! pars[3]->clone() ) { + j["yCP"] = pars[3]->value(); + j["yCPFixed"] = pars[3]->fixed(); + } + if ( ! pars[4]->clone() ) { + j["xbarCP"] = pars[4]->value(); + j["xbarCPFixed"] = pars[4]->fixed(); + } + if ( ! pars[5]->clone() ) { + j["ybarCP"] = pars[5]->value(); + j["ybarCPFixed"] = pars[5]->fixed(); + } } //! \endcond DOXYGEN_IGNORE diff --git a/test/TestReadCoeffSetFromJson.cc b/test/TestReadCoeffSetFromJson.cc index 0aff43d..e0436a0 100644 --- a/test/TestReadCoeffSetFromJson.cc +++ b/test/TestReadCoeffSetFromJson.cc @@ -1,38 +1,49 @@ #include "LauAbsCoeffSet.hh" +#include "LauParameter.hh" #include #include #include #include int main() { /* const std::string filename {"coeffset.json"}; std::ifstream in(filename, std::ios_base::in); if ( not in ) { std::cerr << "ERROR : couldn't open file \"" << filename << "\"" << std::endl; return 1; } nlohmann::json j; in >> j; std::cout << j.dump(4) << std::endl; auto coeffset = j.get(); for ( const LauParameter* par : coeffset.getParameters() ) { std::cout << *par << std::endl; } */ + std::cout << std::boolalpha; std::vector> coeffs { LauAbsCoeffSet::readFromJson( "coeffset.json" ) }; - std::cout << "Read " << coeffs.size() << " coeffs from file" << std::endl; + std::cout << "Read " << coeffs.size() << " coeffs from file\n" << std::endl; for ( const auto& coeff : coeffs ) { - std::cout << coeff->type() << std::endl; + if ( coeff->name() == "K*0(892)" ) { + coeff->setParameterValue("B", 0.1, kTRUE); + } + std::cout << coeff->name() << "\n"; + std::cout << coeff->type() << "\n"; + std::cout << coeff->clone() << "\n"; + for ( const auto& par : coeff->getParameters() ) { + std::cout << *par << "\n"; + } + std::cout << std::endl; } } diff --git a/test/TestWriteCoeffSetToJson.cc b/test/TestWriteCoeffSetToJson.cc index 283e19d..a4c5599 100644 --- a/test/TestWriteCoeffSetToJson.cc +++ b/test/TestWriteCoeffSetToJson.cc @@ -1,53 +1,56 @@ #include "LauAbsCoeffSet.hh" #include "LauBelleCPCoeffSet.hh" #include "LauCartesianCPCoeffSet.hh" #include "LauCartesianGammaCPCoeffSet.hh" #include "LauCleoCPCoeffSet.hh" #include "LauMagPhaseCoeffSet.hh" #include "LauMagPhaseCPCoeffSet.hh" #include "LauNSCCartesianCPCoeffSet.hh" #include "LauPolarGammaCPCoeffSet.hh" #include "LauRealImagCoeffSet.hh" #include "LauRealImagCPCoeffSet.hh" #include "LauRealImagGammaCPCoeffSet.hh" #include #include #include #include int main() { std::vector> coeffs; coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 1.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", kTRUE, 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured, 1.00, 0.00, 0.10, 0.00, 1.20, 0.10, 1.60, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 1.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE) ); - coeffs.push_back( std::make_unique("K*0(892)", 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( coeffs.back()->createClone("K*0_0(1430)", LauAbsCoeffSet::CloneOption::TieCPPars) ); + coeffs.back()->setParameterValue( "A", 2.0, kTRUE ); + coeffs.back()->setParameterValue( "Delta", 3.1415926, kTRUE ); + coeffs.push_back( std::make_unique("rho0(770)", 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("rho+(770)", 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("rho0_3(1690)", 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("rho0(1450)", 1.00, 0.00, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("rho0(1700)", 1.00, 0.00, 1.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("K*0(1410)", kTRUE, 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, 1.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("K*0_2(1430)", LauPolarGammaCPCoeffSet::DecayType::ADS_Favoured, 1.00, 0.00, 0.10, 0.00, 1.20, 0.10, 1.60, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("K*0(1680)", 1.00, 0.00, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("phi(1020)", 1.00, 0.00, 1.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE) ); + coeffs.push_back( std::make_unique("f_0(980)", 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE, kTRUE) ); LauAbsCoeffSet::writeToJson( "coeffset.json", coeffs ); for ( auto& coeffset : coeffs ) { nlohmann::json j; j = *coeffset; - const std::string filename {j.at("type").get()+".json"}; + const std::string filename {j.at("type").get()+(coeffset->clone() ? "_clone.json" : ".json")}; std::ofstream out{filename, std::ios_base::out}; if ( ! out ) { std::cerr << "ERROR : couldn't open file \"" << filename << "\" for writing. No file will be written!" << std::endl; return 1; } out << j.dump(4); out << std::endl; } }