17 #include "analysis/OrcaKinFit/ParticleFitObject.h"
18 #include <framework/logging/Logger.h>
28 #include <gsl/gsl_matrix.h>
29 #include <gsl/gsl_linalg.h>
37 namespace OrcaKinFit {
40 : mass(0), fourMomentum(
FourVector(0, 0, 0, 0)), paramCycl{}
42 for (
double& i : paramCycl)
49 : BaseFitObject(rhs), mass(0), fourMomentum(
FourVector(0, 0, 0, 0)), paramCycl{}
65 if (!isfinite(mass_))
return false;
66 if (
mass == mass_)
return true;
68 mass = std::abs(mass_);
76 if (psource !=
this) {
77 BaseFitObject::assign(source);
79 for (
int i = 0; i < BaseDefs::MAXPAR; ++i)
80 paramCycl[i] = psource->paramCycl[i];
96 os <<
"[" <<
getE() <<
", " <<
getPx() <<
", "
101 FourVector ParticleFitObject::getFourMomentum()
const
103 if (!cachevalid) updateCache();
108 return getFourMomentum().
getE();
112 return getFourMomentum().
getPx();
116 return getFourMomentum().
getPy();
120 return getFourMomentum().
getPz();
124 return getFourMomentum().
getP();
128 return getFourMomentum().
getP2();
132 return getFourMomentum().
getPt();
136 return getFourMomentum().
getPt2();
143 if (!cachevalid) updateCache();
154 for (
int ilocal = 0; ilocal < getNPar(); ++ilocal) {
155 int iglobal = getGlobalParNum(ilocal);
156 assert(iglobal >= 0 && iglobal < idim);
164 for (
int ilocal1 = 0; ilocal1 < getNPar(); ++ilocal1) {
165 int iglobal1 = getGlobalParNum(ilocal1);
166 for (
int ilocal2 = ilocal1; ilocal2 < getNPar(); ++ilocal2) {
167 int iglobal2 = getGlobalParNum(ilocal2);
168 M[idim * iglobal1 + iglobal2] +=
num2ndDerivative(ilocal1, eps, ilocal2, eps);
173 void ParticleFitObject::getDerivatives(
double der[],
int idim)
const
175 for (
int ilocal = 0; ilocal < getNPar(); ++ilocal) {
176 assert(ilocal < idim);
177 der [4 * ilocal] =
getDE(ilocal);
178 der [4 * ilocal + 1] =
getDPx(ilocal);
179 der [4 * ilocal + 2] =
getDPy(ilocal);
180 der [4 * ilocal + 3] =
getDPz(ilocal);
184 void ParticleFitObject::test1stDerivatives()
186 B2INFO(
"ParticleFitObject::test1stDerivatives, object " << getName() <<
"\n");
187 double ycalc[100], ynum[100];
188 for (
int i = 0; i < 100; ++i) ycalc[i] = ynum[i] = 0;
189 addToGlobalChi2DerVector(ycalc, 100);
190 double eps = 0.00001;
192 for (
int ilocal = 0; ilocal < getNPar(); ++ilocal) {
193 int iglobal = getGlobalParNum(ilocal);
194 double calc = ycalc[iglobal];
195 double num = ynum[iglobal];
196 B2INFO(
"fo: " << getName() <<
" par " << ilocal <<
"/"
197 << iglobal <<
" (" << getParamName(ilocal)
198 <<
") calc: " << calc <<
" - num: " << num <<
" = " << calc - num);
202 void ParticleFitObject::test2ndDerivatives()
204 B2INFO(
"ParticleFitObject::test2ndDerivatives, object " <<
getName() <<
"\n");
205 const int idim = 100;
206 auto* Mnum =
new double[idim * idim];
207 auto* Mcalc =
new double[idim * idim];
208 for (
int i = 0; i < idim * idim; ++i) Mnum[i] = Mcalc[i] = 0;
209 addToGlobalChi2DerMatrix(Mcalc, idim);
211 B2INFO(
"eps=" << eps);
213 for (
int ilocal1 = 0; ilocal1 < getNPar(); ++ilocal1) {
214 int iglobal1 = getGlobalParNum(ilocal1);
215 for (
int ilocal2 = ilocal1; ilocal2 < getNPar(); ++ilocal2) {
216 int iglobal2 = getGlobalParNum(ilocal2);
217 double calc = Mcalc[idim * iglobal1 + iglobal2];
218 double num = Mnum[idim * iglobal1 + iglobal2];
219 B2INFO(
"fo: " <<
getName() <<
" par " << ilocal1 <<
"/"
220 << iglobal1 <<
" (" << getParamName(ilocal1)
221 <<
"), par " << ilocal2 <<
"/"
222 << iglobal2 <<
" (" << getParamName(ilocal2)
223 <<
") calc: " << calc <<
" - num: " << num <<
" = " << calc - num);
232 double save = getParam(ilocal);
233 setParam(ilocal, save + eps);
234 double v1 = getChi2();
235 setParam(ilocal, save - eps);
236 double v2 = getChi2();
237 double result = (v1 - v2) / (2 * eps);
238 setParam(ilocal, save);
243 int ilocal2,
double eeps2)
247 if (ilocal1 == ilocal2) {
248 double save = getParam(ilocal1);
249 double v0 = getChi2();
250 setParam(ilocal1, save + eeps1);
251 double v1 = getChi2();
252 setParam(ilocal1, save - eeps1);
253 double v2 = getChi2();
254 result = (v1 + v2 - 2 * v0) / (eeps1 * eeps1);
255 setParam(ilocal1, save);
257 double save1 = getParam(ilocal1);
258 double save2 = getParam(ilocal2);
259 setParam(ilocal1, save1 + eeps1);
260 setParam(ilocal2, save2 + eeps2);
261 double v11 = getChi2();
262 setParam(ilocal2, save2 - eeps2);
263 double v12 = getChi2();
264 setParam(ilocal1, save1 - eeps1);
265 double v22 = getChi2();
266 setParam(ilocal2, save2 + eeps2);
267 double v21 = getChi2();
268 result = (v11 + v22 - v12 - v21) / (4 * eeps1 * eeps2);
269 setParam(ilocal1, save1);
270 setParam(ilocal2, save2);
276 double ParticleFitObject::getChi2()
const
280 if (not covinvvalid and not calculateCovInv())
return 0;
282 double resid[BaseDefs::MAXPAR] = {0};
283 for (
int i = 0; i < getNPar(); i++) {
284 if (isParamMeasured(i) && !isParamFixed(i)) {
285 resid[i] = par[i] - mpar[i];
286 if (paramCycl[i] > 0) {
287 resid[i] = fmod(resid[i], paramCycl[i]);
288 if (resid[i] > paramCycl[i] / 2) resid[i] -= paramCycl[i];
289 if (resid[i] < -paramCycl[i] / 2) resid[i] += paramCycl[i];
296 for (
int i = 0; i < getNPar(); i++) {
297 if (isParamMeasured(i) && !isParamFixed(i)) {
298 for (
int j = 0; j < getNPar(); j++) {
299 if (isParamMeasured(j) && !isParamFixed(j)) {
300 chi2 += resid[i] * covinv[i][j] * resid[j];