1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2024-11-10 00:45:36 +00:00

XYStatData (new): fit implemented (TO BE TESTED)

This commit is contained in:
Antonin Portelli 2016-03-15 19:13:20 +00:00
parent b165a98a93
commit 9f67ead605
3 changed files with 324 additions and 73 deletions

View File

@ -395,6 +395,8 @@ void FitInterface::updateLayout(void)
{
Index size, ifit;
layout.nXFitDim = 0;
layout.nYFitDim = 0;
layout.totalSize = 0;
layout.totalXSize = 0;
layout.totalYSize = 0;
@ -413,6 +415,7 @@ void FitInterface::updateLayout(void)
{
if (!xIsExact_[i])
{
layout.nXFitDim++;
size = getXFitSize(i);
layout.xSize.push_back(size);
layout.totalXSize += size;
@ -448,6 +451,7 @@ void FitInterface::updateLayout(void)
{
Index s = 0;
layout.nYFitDim++;
size = getYFitSize(j);
layout.ySize.push_back(size);
layout.totalYSize += size;

View File

@ -19,63 +19,49 @@
#include <LatAnalyze/XYStatData.hpp>
#include <LatAnalyze/includes.hpp>
#include <LatAnalyze/Math.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* FitResult implementation *
******************************************************************************/
// access //////////////////////////////////////////////////////////////////////
double FitResult::getChi2(void) const
{
return chi2_;
}
double FitResult::getChi2PerDof(void) const
{
return chi2_/getNDof();
}
double FitResult::getNDof(void) const
{
return static_cast<double>(nDof_);
}
double FitResult::getPValue(void) const
{
return Math::chi2PValue(getChi2(), getNDof());;
}
const DoubleFunction & FitResult::getModel(const Index j) const
{
return model_[static_cast<unsigned int>(j)];
}
/******************************************************************************
* XYStatData implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
XYStatData::XYStatData(void)
{}
// schedule fit var matrix update //////////////////////////////////////////////
void XYStatData::scheduleFitVarMatInit(void)
{
initVarMat_ = true;
}
// create data /////////////////////////////////////////////////////////////////
void XYStatData::createXData(const Index nData)
{
xData_.push_back(DVec::Zero(nData));
resizeVarMat();
}
void XYStatData::createYData(void)
{
yData_.push_back(map<Index, double>());
resizeVarMat();
}
void XYStatData::resizeVarMat(void)
{
xxVar_.conservativeResize(getNXDim(), getNXDim());
for (Index i1 = 0; i1 < getNXDim(); ++i1)
for (Index i2 = 0; i2 < getNXDim(); ++i2)
{
xxVar_(i1, i2).conservativeResize(getXSize(i1), getXSize(i2));
}
yyVar_.conservativeResize(getNYDim(), getNYDim());
for (Index j1 = 0; j1 < getNYDim(); ++j1)
for (Index j2 = 0; j2 < getNYDim(); ++j2)
{
yyVar_(j1, j2).conservativeResize(getYSize(j1), getYSize(j2));
}
xyVar_.conservativeResize(getNXDim(), getNYDim());
for (Index i = 0; i < getNXDim(); ++i)
for (Index j = 0; j < getNYDim(); ++j)
{
xyVar_(i, j).conservativeResize(getXSize(i), getYSize(j));
}
}
// data access /////////////////////////////////////////////////////////////////
double & XYStatData::x(const Index vi, const Index i)
{
checkXIndex(vi, i);
scheduleFitVarMatInit();
scheduleXMapInit();
scheduleChi2DataVecInit();
return xData_[i](vi);
}
@ -94,8 +80,9 @@ double & XYStatData::y(const Index k, const Index j)
{
registerDataPoint(k, j);
resizeVarMat();
scheduleFitVarMatInit();
}
scheduleXMapInit();
scheduleChi2DataVecInit();
return yData_[j][k];
}
@ -107,15 +94,6 @@ const double & XYStatData::y(const Index k, const Index j) const
return yData_[j].at(k);
}
#define checkVarMat(m, var)\
if (((m).rows() != (var).rows()) or ((m).cols() != (var).cols()))\
{\
LATAN_ERROR(Size, "provided variance matrix has a wrong size"\
" (expected " + strFrom((var).rows()) + "x"\
+ strFrom((var).cols()) + ", got " + strFrom((m).rows())\
+ "x" + strFrom((m).cols()) + ")");\
}
void XYStatData::setXXVar(const Index i1, const Index i2, const DMat &m)
{
checkXDim(i1);
@ -151,14 +129,6 @@ void XYStatData::setXYVar(const Index i, const Index j, const DMat &m)
scheduleFitVarMatInit();
}
#define checkErrVec(err, var)\
if ((err).size() != (var).rows())\
{\
LATAN_ERROR(Size, "provided error vector has a wrong size"\
" (expected " + strFrom((var).rows()) + ", got "\
+ strFrom((err).size()) + ")");\
}
void XYStatData::setXError(const Index i, const DVec &err)
{
checkXDim(i);
@ -214,14 +184,118 @@ DVec XYStatData::getYError(const Index j) const
}
// get total fit variance matrix ///////////////////////////////////////////////
const DMat & XYStatData::getFitVar(void)
const DMat & XYStatData::getFitVarMat(void)
{
updateFitVarMat();
return fitVar_;
}
// make total fit variance matrix //////////////////////////////////////////////
const DMat & XYStatData::getFitVarMatPInv(void)
{
updateFitVarMat();
return fitVarInv_;
}
// fit /////////////////////////////////////////////////////////////////////////
FitResult XYStatData::fit(Minimizer &minimizer, const DVec &init,
const vector<const DoubleModel *> &v)
{
// check model consistency
checkModelVec(v);
// get number of parameters
Index nPar = v[0]->getNPar();
Index totalNPar = nPar + layout.totalXSize;
// chi^2 function
auto chi2Func = [this, totalNPar, &v](const double *x)->double
{
ConstMap<DVec> p(x, totalNPar);
updateChi2ModVec(p, v);
chi2Vec_ = (chi2ModVec_ - chi2DataVec_);
return (chi2Vec_.transpose()*fitVarInv_).dot(chi2Vec_);
};
DoubleFunction chi2(chi2Func, totalNPar);
// minimization
FitResult result;
DVec totalInit(totalNPar);
updateFitVarMat();
updateChi2DataVec();
totalInit.segment(0, nPar) = init;
totalInit.segment(nPar, layout.totalXSize) =
chi2DataVec_.segment(layout.totalYSize, layout.totalXSize);
minimizer.setInit(totalInit);
result = minimizer(chi2);
result.chi2_ = chi2(result);
result.nDof_ = layout.totalYSize - nPar;
result.model_.resize(v.size());
for (unsigned int j = 0; j < v.size(); ++j)
{
result.model_[j] = v[j]->fixPar(result);
}
return result;
}
// create data /////////////////////////////////////////////////////////////////
void XYStatData::createXData(const Index nData)
{
xData_.push_back(DVec::Zero(nData));
resizeVarMat();
}
void XYStatData::createYData(void)
{
yData_.push_back(map<Index, double>());
resizeVarMat();
}
void XYStatData::resizeVarMat(void)
{
xxVar_.conservativeResize(getNXDim(), getNXDim());
for (Index i1 = 0; i1 < getNXDim(); ++i1)
for (Index i2 = 0; i2 < getNXDim(); ++i2)
{
xxVar_(i1, i2).conservativeResize(getXSize(i1), getXSize(i2));
}
yyVar_.conservativeResize(getNYDim(), getNYDim());
for (Index j1 = 0; j1 < getNYDim(); ++j1)
for (Index j2 = 0; j2 < getNYDim(); ++j2)
{
yyVar_(j1, j2).conservativeResize(getYSize(j1), getYSize(j2));
}
xyVar_.conservativeResize(getNXDim(), getNYDim());
for (Index i = 0; i < getNXDim(); ++i)
for (Index j = 0; j < getNYDim(); ++j)
{
xyVar_(i, j).conservativeResize(getXSize(i), getYSize(j));
}
scheduleFitVarMatInit();
}
// schedule buffer computation /////////////////////////////////////////////////
void XYStatData::scheduleFitVarMatInit(void)
{
initVarMat_ = true;
}
void XYStatData::scheduleXMapInit(void)
{
initXMap_ = true;
}
void XYStatData::scheduleChi2DataVecInit(void)
{
initChi2DataVec_ = true;
}
// buffer total fit variance matrix ////////////////////////////////////////////
void XYStatData::updateFitVarMat(void)
{
if (initVarMat_)
@ -301,6 +375,86 @@ void XYStatData::updateFitVarMat(void)
}
roffs += layout.xSize[ifit];
}
chi2DataVec_.resize(layout.totalSize);
chi2ModVec_.resize(layout.totalSize);
chi2Vec_.resize(layout.totalSize);
fitVarInv_ = fitVar_.pInverse();
initVarMat_ = false;
}
}
// buffer list of x vectors ////////////////////////////////////////////////////
void XYStatData::updateXMap(void)
{
if (initXMap_)
{
vector<Index> v;
set<Index> indSet;
for (Index j = 0; j < getNYDim(); ++j)
{
for (auto &p: yData_[j])
{
indSet.insert(p.first);
}
}
xMap_.clear();
for (auto k: indSet)
{
xMap_[k] = DVec(getNXDim());
v = dataCoord(k);
for (Index i = 0; i < getNXDim(); ++i)
{
xMap_[k](i) = xData_[i](v[i]);
}
}
initXMap_ = false;
}
}
// buffer chi^2 vectors ////////////////////////////////////////////////////////
void XYStatData::updateChi2DataVec(void)
{
if (initChi2DataVec_)
{
Index a = 0, j, k, i, r;
for (Index jfit = 0; jfit < layout.nYFitDim; ++jfit)
for (Index sfit = 0; sfit < layout.ySize[jfit]; ++sfit)
{
j = layout.yDim[jfit];
k = layout.data[jfit][sfit];
chi2DataVec_(a) = yData_[j][k];
a++;
}
for (Index ifit = 0; ifit < layout.nXFitDim; ++ifit)
for (Index rfit = 0; rfit < layout.xSize[ifit]; ++rfit)
{
i = layout.xDim[ifit];
r = layout.x[ifit][rfit];
chi2DataVec_(a) = xData_[i](r);
a++;
}
initChi2DataVec_ = false;
}
}
void XYStatData::updateChi2ModVec(const DVec p,
const vector<const DoubleModel *> &v)
{
Index nPar = v[0]->getNPar(), a = 0, j, k;
auto &par = p.segment(0, nPar), &xsi = p.segment(nPar, layout.totalXSize);
updateXMap();
for (Index jfit = 0; jfit < layout.nYFitDim; ++jfit)
for (Index sfit = 0; sfit < layout.ySize[jfit]; ++sfit)
{
j = layout.yDim[jfit];
k = layout.data[jfit][sfit];
chi2ModVec_(a) = (*v[j])(xMap_[k].data(), par.data());
a++;
}
chi2ModVec_.segment(a, layout.totalSize) = xsi;
}

View File

@ -22,9 +22,36 @@
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/FitInterface.hpp>
#include <LatAnalyze/Minimizer.hpp>
#include <LatAnalyze/Model.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* object for fit result *
******************************************************************************/
class FitResult: public DVec
{
friend class XYStatData;
friend class SampleFitResult;
public:
// constructors
FitResult(void) = default;
EIGEN_EXPR_CTOR(FitResult, FitResult, Base, MatExpr)
// destructor
virtual ~FitResult(void) = default;
// access
double getChi2(void) const;
double getChi2PerDof(void) const;
double getNDof(void) const;
double getPValue(void) const;
const DoubleFunction & getModel(const Index j = 0) const;
private:
double chi2_{0.0};
Index nDof_{0};
std::vector<DoubleFunction> model_;
};
/******************************************************************************
* class for X vs. Y statistical data *
******************************************************************************/
@ -32,11 +59,9 @@ class XYStatData: public FitInterface
{
public:
// constructor
XYStatData(void);
XYStatData(void) = default;
// destructor
virtual ~XYStatData(void) = default;
// schedule fit var matrix update
void scheduleFitVarMatInit(void);
// data access
double & x(const Index vi, const Index i = 0);
const double & x(const Index vi, const Index i = 0) const;
@ -52,24 +77,92 @@ public:
const DMat & getXYVar(const Index i, const Index j) const;
DVec getXError(const Index i) const;
DVec getYError(const Index j) const;
// get total fit variance matrix
const DMat & getFitVar(void);
// get total fit variance matrix and its pseudo-inverse
const DMat & getFitVarMat(void);
const DMat & getFitVarMatPInv(void);
// fit
FitResult fit(Minimizer &minimizer, const DVec &init,
const std::vector<const DoubleModel *> &v);
protected:
// create data
virtual void createXData(const Index nData);
virtual void createYData(void);
void resizeVarMat(void);
private:
// make total fit variance matrix
// schedule buffer computation
void scheduleFitVarMatInit(void);
void scheduleXMapInit(void);
void scheduleChi2DataVecInit(void);
// buffer total fit variance matrix
void updateFitVarMat(void);
// buffer list of x vectors
void updateXMap(void);
// buffer chi^2 vectors
void updateChi2DataVec(void);
void updateChi2ModVec(const DVec p,
const std::vector<const DoubleModel *> &v);
private:
std::vector<std::map<Index, double>> yData_;
std::vector<DVec> xData_;
std::map<Index, DVec> xMap_;
Mat<DMat> xxVar_, yyVar_, xyVar_;
DMat fitVar_;
DMat fitVar_, fitVarInv_;
DVec chi2DataVec_, chi2ModVec_, chi2Vec_;
bool initVarMat_{true};
bool initXMap_{true};
bool initChi2DataVec_{true};
};
/******************************************************************************
* error check macros *
******************************************************************************/
#define checkVarMat(m, var)\
if (((m).rows() != (var).rows()) or ((m).cols() != (var).cols()))\
{\
LATAN_ERROR(Size, "provided variance matrix has a wrong size"\
" (expected " + strFrom((var).rows()) + "x"\
+ strFrom((var).cols()) + ", got " + strFrom((m).rows())\
+ "x" + strFrom((m).cols()) + ")");\
}
#define checkErrVec(err, var)\
if ((err).size() != (var).rows())\
{\
LATAN_ERROR(Size, "provided error vector has a wrong size"\
" (expected " + strFrom((var).rows()) + ", got "\
+ strFrom((err).size()) + ")");\
}
#define checkModelVec(v)\
if (static_cast<Index>((v).size()) != getNYDim())\
{\
LATAN_ERROR(Size, "provided model vector has a wrong size"\
" (expected " + strFrom(getNYDim()) + ", got "\
+ strFrom((v).size()) + ")");\
}\
for (unsigned int _i = 1; _i < (v).size(); ++_i)\
{\
if ((v)[_i]->getNArg() != getNXDim())\
{\
LATAN_ERROR(Size, "model " + strFrom(_i) + " has a wrong"\
+ " number of argument (expected " + strFrom(getNXDim())\
+ ", got " + strFrom((v)[_i]->getNArg()));\
}\
}\
{\
Index _nPar = (v)[0]->getNPar();\
for (unsigned int _i = 1; _i < (v).size(); ++_i)\
{\
if ((v)[_i]->getNPar() != _nPar)\
{\
LATAN_ERROR(Size, "model " + strFrom(_i) + " has a wrong"\
+ " number of parameter (expected " + strFrom(_nPar)\
+ ", got " + strFrom((v)[_i]->getNPar()));\
}\
}\
}
END_LATAN_NAMESPACE
#endif // Latan_XYStatData_hpp_