1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sim/Fitting/ObjectiveMetric.h
//! @brief Defines class ObjectiveMetrices.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_SIM_FITTING_OBJECTIVEMETRIC_H
#define BORNAGAIN_SIM_FITTING_OBJECTIVEMETRIC_H
#include "Base/Type/ICloneable.h"
#include <functional>
#include <memory>
#include <vector>
class SimDataPair;
//! Base class for metric implementations
class ObjectiveMetric : public ICloneable {
public:
ObjectiveMetric(const std::function<double(double)>& norm);
#ifndef SWIG
ObjectiveMetric* clone() const override = 0;
#endif // SWIG
//! Computes metric value from SimDataPair object. Calls computeFromArrays internally.
//! @param data_pair: SimDataPair object. Can optionally contain data uncertainties
//! @param use_weights: boolean, defines if data uncertainties should be taken into account
virtual double computeMetric(const SimDataPair& data_pair, bool use_weights) const;
//! Computes metric value from data arrays. Negative values in exp_data
//! are ignored as well as non-positive uncertainties.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
//! @param exp_stdv: array with experimental data uncertainties.
virtual double computeFromArrays(std::vector<double> sim_data, std::vector<double> exp_data,
std::vector<double> exp_stdv) const = 0;
//! Computes metric value from data arrays. Negative values in exp_data are ignored.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
virtual double computeFromArrays(std::vector<double> sim_data,
std::vector<double> exp_data) const = 0;
void setNorm(std::function<double(double)> norm);
//! Returns a copy of the normalization function used.
auto norm() const { return m_norm; }
private:
std::function<double(double)> m_norm; //! normalization function.
};
//! Implementation of the standard \f$ \chi^2 \f$ metric
//! derived from maximum likelihood with Gaussian uncertainties.
//! With default L2 norm corresponds to the formula
//! \f[\chi^2 = \sum \frac{(I - D)^2}{\delta_D^2}\f]
class Chi2Metric : public ObjectiveMetric {
public:
Chi2Metric();
#ifndef SWIG
Chi2Metric* clone() const override;
#endif // SWIG
//! Computes metric value from data arrays. Negative values in exp_data
//! are ignored as well as non-positive uncertainties.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
//! @param exp_stdv: array with experimental data uncertainties.
double computeFromArrays(std::vector<double> sim_data, std::vector<double> exp_data,
std::vector<double> exp_stdv) const override;
//! Computes metric value from data arrays. Negative values in exp_data are ignored.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
double computeFromArrays(std::vector<double> sim_data,
std::vector<double> exp_data) const override;
};
//! Implementation of \f$ \chi^2 \f$ metric
//! with standard deviation\f$\sigma = max(\sqrt{I}, 1)\f$,
//! where \f$I\f$ is the simulated intensity.
//! With default L2 norm corresponds to the formula
//! \f[\chi^2 = \sum \frac{(I - D)^2}{max(I, 1)}\f]
//! for unweighted experimental data. Falls to standard
//! Chi2Metric when data uncertainties are taken into account.
class PoissonLikeMetric : public Chi2Metric {
public:
PoissonLikeMetric();
#ifndef SWIG
PoissonLikeMetric* clone() const override;
#endif // SWIG
using Chi2Metric::computeFromArrays;
//! Computes metric value from data arrays. Negative values in exp_data are ignored.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
double computeFromArrays(std::vector<double> sim_data,
std::vector<double> exp_data) const override;
};
//! Implementation of the standard \f$ \chi^2 \f$ metric with intensity \f$I\f$
//! and experimental data \f$D\f$
//! being replaced by \f$ \log_{10} I \f$ and \f$\log_{10} D\f$ accordingly.
//! With default L2 norm corresponds to the formula
//! \f[\chi^2 = \sum \frac{(\log_{10} I - log_{10} D)^2 D^2 \ln^2{10}}{\delta_D^2}\f]
class LogMetric : public ObjectiveMetric {
public:
LogMetric();
#ifndef SWIG
LogMetric* clone() const override;
#endif // SWIG
//! Computes metric value from data arrays. Negative values in exp_data
//! are ignored as well as non-positive uncertainties.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
//! @param exp_stdv: array with experimental data uncertainties.
double computeFromArrays(std::vector<double> sim_data, std::vector<double> exp_data,
std::vector<double> exp_stdv) const override;
//! Computes metric value from data arrays. Negative values in exp_data are ignored.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
double computeFromArrays(std::vector<double> sim_data,
std::vector<double> exp_data) const override;
};
//! Implementation of relative difference metric.
//! With default L2 norm and weighting off corresponds to the formula
//! \f[Result = \sum \frac{(I - D)^2}{(I + D)^2}\f]
//! where \f$I\f$ is the simulated intensity, \f$D\f$ - experimental data.
//! If weighting is on, falls back to the standard \f$\chi^2\f$ metric.
class meanRelativeDifferenceMetric : public Chi2Metric {
public:
meanRelativeDifferenceMetric();
#ifndef SWIG
meanRelativeDifferenceMetric* clone() const override;
#endif // SWIG
using Chi2Metric::computeFromArrays;
//! Computes metric value from data arrays. Negative values in exp_data are ignored.
//! All arrays involved in the computation must be of the same size.
//! @param sim_data: array with simulated intensities.
//! @param exp_data: array with intensity values obtained from an experiment.
double computeFromArrays(std::vector<double> sim_data,
std::vector<double> exp_data) const override;
};
//! Implementation of relative difference metric.
//! With default L2 norm and weighting off corresponds to the formula
//! \f[Result = \sum (I \cdot Q^4 - D \cdot Q^4)^2\f]
//! where \f$Q\f$ is the scattering vector magnitude. If weighting is on,
//! coincides with the metric provided by Chi2Metric class.
class RQ4Metric : public Chi2Metric {
public:
RQ4Metric();
#ifndef SWIG
RQ4Metric* clone() const override;
#endif // SWIG
//! Computes metric value from SimDataPair object. Calls computeFromArrays internally.
//! @param data_pair: SimDataPair object. Can optionally contain data uncertainties
//! @param use_weights: boolean, defines if data uncertainties should be taken into account
double computeMetric(const SimDataPair& data_pair, bool use_weights) const override;
};
#endif // BORNAGAIN_SIM_FITTING_OBJECTIVEMETRIC_H
|