mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2024-11-10 00:45:36 +00:00
XY datatypes: tools to get residuals or partial residuals from a fit
This commit is contained in:
parent
59bb3fb78c
commit
cebf2334fa
@ -29,7 +29,7 @@ using namespace Latan;
|
||||
******************************************************************************/
|
||||
// constructors ////////////////////////////////////////////////////////////////
|
||||
Chi2Function::Chi2Function(const XYStatData &data)
|
||||
: data_(data)
|
||||
: data_(&data)
|
||||
, buffer_(new Chi2FunctionBuffer)
|
||||
{
|
||||
resizeBuffer();
|
||||
@ -50,7 +50,7 @@ Index Chi2Function::getNArg(void) const
|
||||
LATAN_ERROR(Memory, "no model set");
|
||||
}
|
||||
|
||||
return nPar_ + data_.getStatXDim()*data_.getNFitPoint();
|
||||
return nPar_ + data_->getStatXDim()*data_->getNFitPoint();
|
||||
}
|
||||
|
||||
Index Chi2Function::getNDof(void) const
|
||||
@ -60,7 +60,7 @@ Index Chi2Function::getNDof(void) const
|
||||
LATAN_ERROR(Memory, "no model set");
|
||||
}
|
||||
|
||||
return data_.getYDim()*data_.getNFitPoint() - nPar_;
|
||||
return data_->getYDim()*data_->getNFitPoint() - nPar_;
|
||||
}
|
||||
|
||||
Index Chi2Function::getNPar(void) const
|
||||
@ -77,15 +77,15 @@ void Chi2Function::setModel(const DoubleModel &model, const Index j)
|
||||
{
|
||||
typedef decltype(model_.size()) size_type;
|
||||
|
||||
if (static_cast<Index>(model_.size()) != data_.getYDim())
|
||||
if (static_cast<Index>(model_.size()) != data_->getYDim())
|
||||
{
|
||||
model_.resize(static_cast<size_type>(data_.getYDim()));
|
||||
model_.resize(static_cast<size_type>(data_->getYDim()));
|
||||
}
|
||||
if (model.getNArg() != data_.getXDim())
|
||||
if (model.getNArg() != data_->getXDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "model number of arguments and x-dimension mismatch");
|
||||
}
|
||||
for (unsigned int l = 0; l < data_.getYDim(); ++l)
|
||||
for (unsigned int l = 0; l < data_->getYDim(); ++l)
|
||||
{
|
||||
if (model_[l]&&(l != j))
|
||||
{
|
||||
@ -103,11 +103,11 @@ void Chi2Function::setModel(const vector<const DoubleModel *> &modelVector)
|
||||
{
|
||||
typedef decltype(model_.size()) size_type;
|
||||
|
||||
if (static_cast<Index>(model_.size()) != data_.getYDim())
|
||||
if (static_cast<Index>(model_.size()) != data_->getYDim())
|
||||
{
|
||||
model_.resize(static_cast<size_type>(data_.getYDim()));
|
||||
model_.resize(static_cast<size_type>(data_->getYDim()));
|
||||
}
|
||||
if (modelVector.size() != static_cast<size_type>(data_.getYDim()))
|
||||
if (modelVector.size() != static_cast<size_type>(data_->getYDim()))
|
||||
{
|
||||
LATAN_ERROR(Size, "number of models and y-dimension mismatch");
|
||||
}
|
||||
@ -117,7 +117,7 @@ void Chi2Function::setModel(const vector<const DoubleModel *> &modelVector)
|
||||
{
|
||||
LATAN_ERROR(Memory, "trying to set a null model");
|
||||
}
|
||||
if (modelVector[j]->getNArg() != data_.getXDim())
|
||||
if (modelVector[j]->getNArg() != data_->getXDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "model number of arguments and x-dimension mismatch");
|
||||
}
|
||||
@ -139,24 +139,24 @@ void Chi2Function::resizeBuffer(void) const
|
||||
{
|
||||
Index size;
|
||||
|
||||
size = (data_.getYDim() + data_.getStatXDim())*data_.getNFitPoint();
|
||||
size = (data_->getYDim() + data_->getStatXDim())*data_->getNFitPoint();
|
||||
buffer_->v.setConstant(size, 0.0);
|
||||
buffer_->x.setConstant(data_.getXDim(), 0.0);
|
||||
buffer_->x.setConstant(data_->getXDim(), 0.0);
|
||||
buffer_->invVar.setConstant(size, size, 0.0);
|
||||
buffer_->xInd.setConstant(data_.getStatXDim(), 0);
|
||||
buffer_->dInd.setConstant(data_.getNFitPoint(), 0);
|
||||
buffer_->xInd.setConstant(data_->getStatXDim(), 0);
|
||||
buffer_->dInd.setConstant(data_->getNFitPoint(), 0);
|
||||
}
|
||||
|
||||
// compute variance matrix inverse /////////////////////////////////////////////
|
||||
void Chi2Function::setVarianceBlock(const Index l1, const Index l2,
|
||||
ConstBlock<MatBase<double>> m) const
|
||||
{
|
||||
const Index nPoint = data_.getNFitPoint();
|
||||
const Index nPoint = data_->getNFitPoint();
|
||||
|
||||
FOR_VEC(buffer_->dInd, k2)
|
||||
FOR_VEC(buffer_->dInd, k1)
|
||||
{
|
||||
if (data_.isDataCorrelated(buffer_->dInd(k1), buffer_->dInd(k2)))
|
||||
if (data_->isDataCorrelated(buffer_->dInd(k1), buffer_->dInd(k2)))
|
||||
{
|
||||
buffer_->invVar(l1*nPoint + k1, l2*nPoint + k2) =
|
||||
m(buffer_->dInd(k1), buffer_->dInd(k2));
|
||||
@ -166,11 +166,11 @@ void Chi2Function::setVarianceBlock(const Index l1, const Index l2,
|
||||
|
||||
void Chi2Function::initBuffer(void) const
|
||||
{
|
||||
const Index xDim = data_.getXDim();
|
||||
const Index statXDim = data_.getStatXDim();
|
||||
const Index yDim = data_.getYDim();
|
||||
const Index nData = data_.getNData();
|
||||
const Index nPoint = data_.getNFitPoint();
|
||||
const Index xDim = data_->getXDim();
|
||||
const Index statXDim = data_->getStatXDim();
|
||||
const Index yDim = data_->getYDim();
|
||||
const Index nData = data_->getNData();
|
||||
const Index nPoint = data_->getNFitPoint();
|
||||
Index is, kf;
|
||||
|
||||
// resize buffer
|
||||
@ -180,7 +180,7 @@ void Chi2Function::initBuffer(void) const
|
||||
is = 0;
|
||||
for (Index i = 0; i < xDim; ++i)
|
||||
{
|
||||
if (!data_.isXExact(i))
|
||||
if (!data_->isXExact(i))
|
||||
{
|
||||
buffer_->xInd(is) = i;
|
||||
is++;
|
||||
@ -189,7 +189,7 @@ void Chi2Function::initBuffer(void) const
|
||||
kf = 0;
|
||||
for (Index k = 0; k < nData; ++k)
|
||||
{
|
||||
if (data_.isFitPoint(k))
|
||||
if (data_->isFitPoint(k))
|
||||
{
|
||||
buffer_->dInd(kf) = k;
|
||||
kf++;
|
||||
@ -200,9 +200,9 @@ void Chi2Function::initBuffer(void) const
|
||||
for (Index j2 = 0; j2 < yDim; ++j2)
|
||||
for (Index j1 = 0; j1 < yDim; ++j1)
|
||||
{
|
||||
if (data_.isYYCorrelated(j1, j2))
|
||||
if (data_->isYYCorrelated(j1, j2))
|
||||
{
|
||||
setVarianceBlock(j1, j2, data_.yyVar(j1, j2));
|
||||
setVarianceBlock(j1, j2, data_->yyVar(j1, j2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,10 +210,10 @@ void Chi2Function::initBuffer(void) const
|
||||
FOR_VEC(buffer_->xInd, i2)
|
||||
FOR_VEC(buffer_->xInd, i1)
|
||||
{
|
||||
if (data_.isXXCorrelated(buffer_->xInd(i1), buffer_->xInd(i2)))
|
||||
if (data_->isXXCorrelated(buffer_->xInd(i1), buffer_->xInd(i2)))
|
||||
{
|
||||
setVarianceBlock(i1 + yDim, i2 + yDim,
|
||||
data_.xxVar(buffer_->xInd(i1), buffer_->xInd(i2)));
|
||||
data_->xxVar(buffer_->xInd(i1), buffer_->xInd(i2)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,9 +221,9 @@ void Chi2Function::initBuffer(void) const
|
||||
FOR_VEC(buffer_->xInd, i)
|
||||
for (Index j = 0; j < yDim; ++j)
|
||||
{
|
||||
if (data_.isYXCorrelated(j, buffer_->xInd(i)))
|
||||
if (data_->isYXCorrelated(j, buffer_->xInd(i)))
|
||||
{
|
||||
setVarianceBlock(j, i + yDim, data_.yxVar(j, buffer_->xInd(i)));
|
||||
setVarianceBlock(j, i + yDim, data_->yxVar(j, buffer_->xInd(i)));
|
||||
}
|
||||
}
|
||||
auto lowerYX = buffer_->invVar.block(yDim*nPoint, 0, yDim*statXDim,
|
||||
@ -247,9 +247,9 @@ double Chi2Function::operator()(const double *arg) const
|
||||
LATAN_ERROR(Memory, "null model");
|
||||
}
|
||||
|
||||
const Index xDim = data_.getXDim();
|
||||
const Index yDim = data_.getYDim();
|
||||
const Index nPoint = data_.getNFitPoint();
|
||||
const Index xDim = data_->getXDim();
|
||||
const Index yDim = data_->getYDim();
|
||||
const Index nPoint = data_->getNFitPoint();
|
||||
Index is;
|
||||
ConstMap<DVec> xi(arg + nPar_, getNArg() - nPar_, 1);
|
||||
double res;
|
||||
@ -265,7 +265,7 @@ double Chi2Function::operator()(const double *arg) const
|
||||
FOR_VEC(buffer_->dInd, k)
|
||||
{
|
||||
const DoubleModel *f = model_[static_cast<size_type>(j)];
|
||||
double f_jk, y_jk = data_.y(j, buffer_->dInd(k));
|
||||
double f_jk, y_jk = data_->y(j, buffer_->dInd(k));
|
||||
|
||||
if (!f)
|
||||
{
|
||||
@ -274,9 +274,9 @@ double Chi2Function::operator()(const double *arg) const
|
||||
is = 0;
|
||||
for (Index i = 0; i < xDim; ++i)
|
||||
{
|
||||
if (data_.isXExact(i))
|
||||
if (data_->isXExact(i))
|
||||
{
|
||||
buffer_->x(i) = data_.x(i, buffer_->dInd(k));
|
||||
buffer_->x(i) = data_->x(i, buffer_->dInd(k));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -293,7 +293,7 @@ double Chi2Function::operator()(const double *arg) const
|
||||
FOR_VEC(buffer_->xInd, i)
|
||||
FOR_VEC(buffer_->dInd, k)
|
||||
{
|
||||
double x_ik = data_.x(buffer_->xInd(i), buffer_->dInd(k));
|
||||
double x_ik = data_->x(buffer_->xInd(i), buffer_->dInd(k));
|
||||
double xi_ik = xi(i*nPoint + k);
|
||||
|
||||
buffer_->v(yDim*nPoint + i*nPoint + k) = xi_ik - x_ik;
|
||||
|
@ -69,7 +69,7 @@ private:
|
||||
ConstBlock<MatBase<double>> m) const;
|
||||
void initBuffer(void) const;
|
||||
private:
|
||||
const XYStatData &data_;
|
||||
const XYStatData *data_;
|
||||
std::shared_ptr<Chi2FunctionBuffer> buffer_;
|
||||
std::vector<const DoubleModel *> model_;
|
||||
Index nPar_{-1};
|
||||
|
@ -64,6 +64,22 @@ const DoubleFunctionSample & SampleFitResult::getModel(
|
||||
return model_[static_cast<unsigned int>(j)];
|
||||
}
|
||||
|
||||
FitResult SampleFitResult::getFitResult(const Index s) const
|
||||
{
|
||||
FitResult fit;
|
||||
|
||||
fit = (*this)[s];
|
||||
fit.chi2_ = getChi2();
|
||||
fit.nDof_ = static_cast<Index>(getNDof());
|
||||
fit.model_.resize(model_.size());
|
||||
for (unsigned int k = 0; k < model_.size(); ++k)
|
||||
{
|
||||
fit.model_[k] = model_[k][s];
|
||||
}
|
||||
|
||||
return fit;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* XYSampleData implementation *
|
||||
******************************************************************************/
|
||||
@ -294,3 +310,58 @@ void XYSampleData::setDataToSample(const Index s)
|
||||
data_.x() = x_[s];
|
||||
data_.y() = y_[s];
|
||||
}
|
||||
|
||||
// residuals ///////////////////////////////////////////////////////////////////
|
||||
XYSampleData XYSampleData::getResiduals(const SampleFitResult &fit) const
|
||||
{
|
||||
const Index nSample = x_.size();
|
||||
XYSampleData res(*this);
|
||||
DMatSample xBuf(nSample, getXDim(), 1), tmp(nSample, 1, 1);
|
||||
|
||||
for (Index j = 0; j < res.getYDim(); ++j)
|
||||
{
|
||||
const DoubleFunctionSample &f = fit.getModel(_, j);
|
||||
|
||||
for (Index k = 0; k < res.getNData(); ++k)
|
||||
{
|
||||
xBuf = this->x(_, k);
|
||||
tmp = this->y(j, k);
|
||||
FOR_STAT_ARRAY(xBuf, s)
|
||||
{
|
||||
tmp[s](0) -= f[s](xBuf[s].transpose());
|
||||
}
|
||||
res.y(j, k) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
XYSampleData XYSampleData::getPartialResiduals(const SampleFitResult &fit,
|
||||
const DVec &x,
|
||||
const Index i) const
|
||||
{
|
||||
const Index nSample = x_.size();
|
||||
XYSampleData res(*this);
|
||||
DMatSample xBuf(nSample, getXDim(), 1), tmp(nSample, 1, 1);
|
||||
DVec buf(x);
|
||||
|
||||
for (Index j = 0; j < res.getYDim(); ++j)
|
||||
{
|
||||
const DoubleFunctionSample &f = fit.getModel(_, j);
|
||||
|
||||
for (Index k = 0; k < res.getNData(); ++k)
|
||||
{
|
||||
xBuf = this->x(_, k);
|
||||
tmp = this->y(j, k);
|
||||
FOR_STAT_ARRAY(xBuf, s)
|
||||
{
|
||||
buf(i) = xBuf[s](i);
|
||||
tmp[s](0) -= f[s](xBuf[s].transpose()) - f[s](buf);
|
||||
}
|
||||
res.y(j, k) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
const Index j = 0) const;
|
||||
const DoubleFunctionSample & getModel(const PlaceHolder ph,
|
||||
const Index j = 0) const;
|
||||
FitResult getFitResult(const Index s = central) const;
|
||||
private:
|
||||
DSample chi2_;
|
||||
double nDof_{0.};
|
||||
@ -59,7 +60,9 @@ private:
|
||||
|
||||
/******************************************************************************
|
||||
* XYSampleData *
|
||||
******************************************************************************/
|
||||
******************************************************************************
|
||||
* index convention: i: X, j: Y, k: data
|
||||
*/
|
||||
class XYSampleData: public FitInterface
|
||||
{
|
||||
public:
|
||||
@ -88,18 +91,22 @@ public:
|
||||
SampleBlock y(const PlaceHolder ph1 = _, const PlaceHolder ph2 = _);
|
||||
ConstSampleBlock y(const PlaceHolder ph1 = _,
|
||||
const PlaceHolder ph2 = _) const;
|
||||
SampleBlock y(const Index i, const PlaceHolder ph2 = _);
|
||||
ConstSampleBlock y(const Index i, const PlaceHolder ph2 = _) const;
|
||||
SampleBlock y(const Index j, const PlaceHolder ph2 = _);
|
||||
ConstSampleBlock y(const Index j, const PlaceHolder ph2 = _) const;
|
||||
SampleBlock y(const PlaceHolder ph1, const Index k);
|
||||
ConstSampleBlock y(const PlaceHolder ph1, const Index k) const;
|
||||
SampleBlock y(const Index i, const Index k);
|
||||
ConstSampleBlock y(const Index i, const Index k) const;
|
||||
SampleBlock y(const Index j, const Index k);
|
||||
ConstSampleBlock y(const Index j, const Index k) const;
|
||||
// fit
|
||||
SampleFitResult fit(Minimizer &minimizer, const DVec &init,
|
||||
const std::vector<const DoubleModel *> &modelVector);
|
||||
template <typename... Mods>
|
||||
SampleFitResult fit(Minimizer &minimizer, const DVec &init,
|
||||
const DoubleModel &model, const Mods... models);
|
||||
// residuals
|
||||
XYSampleData getResiduals(const SampleFitResult &fit) const;
|
||||
XYSampleData getPartialResiduals(const SampleFitResult &fit, const DVec &x,
|
||||
const Index j) const;
|
||||
private:
|
||||
void setDataToSample(const Index s);
|
||||
private:
|
||||
|
@ -268,3 +268,41 @@ FitResult XYStatData::fit(Minimizer &minimizer, const DVec &init,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// residuals ///////////////////////////////////////////////////////////////////
|
||||
XYStatData XYStatData::getResiduals(const FitResult &fit) const
|
||||
{
|
||||
XYStatData res(*this);
|
||||
|
||||
for (Index j = 0; j < res.getYDim(); ++j)
|
||||
{
|
||||
const DoubleFunction &f = fit.getModel(j);
|
||||
|
||||
for (Index k = 0; k < res.getNData(); ++k)
|
||||
{
|
||||
res.y(j, k) -= f(res.x(_, k).transpose());
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
XYStatData XYStatData::getPartialResiduals(const FitResult &fit, const DVec &x,
|
||||
const Index i) const
|
||||
{
|
||||
XYStatData res(*this);
|
||||
DVec buf(x), xk;
|
||||
|
||||
for (Index j = 0; j < res.getYDim(); ++j)
|
||||
{
|
||||
const DoubleFunction &f = fit.getModel(j);
|
||||
|
||||
for (Index k = 0; k < res.getNData(); ++k)
|
||||
{
|
||||
buf(i) = res.x(i, k);
|
||||
res.y(j, k) -= f(res.x(_, k).transpose()) - f(buf);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ BEGIN_LATAN_NAMESPACE
|
||||
class FitResult: public DVec
|
||||
{
|
||||
friend class XYStatData;
|
||||
friend class SampleFitResult;
|
||||
public:
|
||||
// constructors
|
||||
FitResult(void) = default;
|
||||
@ -56,7 +57,9 @@ private:
|
||||
|
||||
/******************************************************************************
|
||||
* object for X vs. Y statistical data *
|
||||
******************************************************************************/
|
||||
******************************************************************************
|
||||
* index convention: i: X, j: Y, k: data
|
||||
*/
|
||||
class XYStatData: public FitInterface
|
||||
{
|
||||
public:
|
||||
@ -112,6 +115,10 @@ public:
|
||||
template <typename... Ts>
|
||||
FitResult fit(Minimizer &minimizer, const DVec &init,
|
||||
const DoubleModel &model, const Ts... models);
|
||||
// residuals
|
||||
XYStatData getResiduals(const FitResult &fit) const;
|
||||
XYStatData getPartialResiduals(const FitResult &fit, const DVec &x,
|
||||
const Index j) const;
|
||||
|
||||
private:
|
||||
DMat x_, y_;
|
||||
|
Loading…
Reference in New Issue
Block a user