#include "sopnamsp.h" #include "machdefs.h" #include #include #include #include #include "fct1dfit.h" #include "perrors.h" #include "nbconst.h" #include "tabmath.h" //define EXPO exp #define EXPO tabFExp #define MINEXPM (100.) //================================================================ // CLASSES DE FONCTIONS 1D AVEC PARAMETRES POUR LE FIT //================================================================ ///////////////////////////////////////////////////////////////// /*! \class SOPHYA::Gauss1DPol \ingroup NTools \anchor Gauss1DPol \verbatim Gaussienne+polynome: Si polcenter=true: xc=(x-par[1]), sinon xc=x f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ] +par[3] + par[4]*xc + .... + par[3+NDegPol]*xc**NDegPol NDegPol = degre du polynome, si <0 pas de polynome \endverbatim */ Gauss1DPol::Gauss1DPol(unsigned int ndegpol,bool polcenter) : GeneralFunction(1,ndegpol+4), NDegPol(ndegpol), PolCenter(polcenter) { } Gauss1DPol::Gauss1DPol(bool polcenter) : GeneralFunction(1,3), NDegPol(-1), PolCenter(polcenter) { } Gauss1DPol::~Gauss1DPol() { } double Gauss1DPol::Value(double const xp[], double const* Par) { double xc = (xp[0]-Par[1])/Par[2]; double e = 0.5*xc*xc; if( e=0) { double xcp = (PolCenter) ? Par[1] : 0.; double xpow = 1.; for(int i=0;i<=NDegPol;i++) { f += Par[3+i]*xpow; xpow *= xp[0]-xcp; } } return (f); } double Gauss1DPol::Val_Der(double const xp[],double const* Par ,double *DgDpar) { double xc = (xp[0]-Par[1])/Par[2]; double xc2 = xc*xc; double e = 0.5*xc2; if( e=0) { double xcp = (PolCenter) ? Par[1] : 0.; double xpow = 1.; for(int i=0;i<=NDegPol;i++) { DgDpar[3+i] = xpow; f += Par[3+i]*xpow; if(PolCenter && i=0) { double xcp = (PolCenter) ? Par[1] : 0.; double xpow = 1.; for(int i=0;i<=NDegPol;i++) { f += Par[3+i]*xpow; xpow *= xp[0]-xcp; } } return (f); } double GaussN1DPol::Val_Der(double const xp[], double const* Par , double *DgDpar) { double xc = (xp[0]-Par[1])/Par[2]; double xc2 = xc*xc; double e = 0.5*xc2; if( e=0) { double xcp = (PolCenter) ? Par[1] : 0.; double xpow = 1.; for(int i=0;i<=NDegPol;i++) { DgDpar[3+i] = xpow; f += Par[3+i]*xpow; if(PolCenter && i-MINEXPM ) ? EXPO(xc): 0.; if(NDegPol>=0) { double xpow = 1.; for(int i=0;i<=NDegPol;i++) { f += Par[2+i]*xpow; xpow *= xp[0]-X_Center; } } return (f); } double Exp1DPol::Val_Der(double const xp[],double const* Par ,double *DgDpar) { double xc = Par[0]+Par[1]*(xp[0]-X_Center); double f = ( xc>-MINEXPM ) ? EXPO(xc): 0.; DgDpar[0] = f; DgDpar[1] = (xp[0]-X_Center) * f; if(NDegPol>=0) { double xpow = 1.; for(int i=0;i<=NDegPol;i++) { DgDpar[2+i] = xpow; f += Par[2+i]*xpow; xpow *= xp[0]-X_Center; } } return f; } ///////////////////////////////////////////////////////////////// /*! \class SOPHYA::Polyn1D \ingroup NTools \anchor Polyn1D \verbatim polynome 1D: xx = x - X_Center f(x) = par[0] + par[1]*xx + .... + par[NDegPol+1]*xx**NDegPol NDegPol = degre du polynome \endverbatim */ Polyn1D::Polyn1D(unsigned int ndegpol,double x0) : GeneralFunction(1,ndegpol+1), NDegPol(ndegpol), X_Center(x0) { } Polyn1D::~Polyn1D() { } double Polyn1D::Value(double const xp[], double const* Par) { double xpow = 1.; double f = 0.; for(int i=0;i<=NDegPol;i++) { f += Par[i]*xpow; xpow *= xp[0]-X_Center; } return (f); } double Polyn1D::Val_Der(double const xp[], double const* Par , double *DgDpar) { double xpow = 1.; double f = 0.; for(int i=0;i<=NDegPol;i++) { DgDpar[i] = xpow; f += Par[i]*xpow; xpow *= xp[0]-X_Center; } return f; } ///////////////////////////////////////////////////////////////// /*! \class SOPHYA::HarmonieNu \ingroup NTools \anchor HarmonieNu \verbatim Analyse harmonique: f(t) = par(1) + Sum[par(2k) *cos(2*pi*k*par(0)*(t-t0)] + Sum[par(2k+1)*sin(2*pi*k*par(0)*(t-t0)] la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1] avec la convention k=1 pour le fondamental k>1 pour le (k-1)ieme harmonique par(0) = inverse de la periode (frequence) par(1) = terme constant par(2), par(3) = termes devant le cosinus et le sinus du fondamental par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus et le sinus de l'harmonique m (m>=1). NHarm() = nombre d'harmoniques a fitter. T0() = centrage des temps, ce n'est pas un parametre du fit. `Conseil:' Avant de faire un fit avec les `NHarm()' harmoniques, il est preferable de faire un pre-fit ou seuls les parametres 1,2 et 3 sont libres et d'injecter le resultat du fit sur ces 3 parametres comme valeurs de depart pour le fit global avec les `NHarm()' harmoniques. De toute facon, le fit ne marchera que si la periode est initialisee de facon tres precise. \endverbatim */ HarmonieNu::HarmonieNu(unsigned int nharm,double t0) : GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0) { } HarmonieNu::~HarmonieNu() { } double HarmonieNu::Value(double const xp[], double const* Par) { double a = 2.*Pi*(xp[0]-T0)*Par[0]; double f = Par[1]; for(int k=1;k<=NHarm+1;k++) { // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a); } return f; } double HarmonieNu::Val_Der(double const xp[], double const* Par , double *DgDpar) { double cs,sn; double dadp0 = 2.*Pi*(xp[0]-T0); double a = dadp0*Par[0]; double f = Par[1]; DgDpar[0] = 0.; DgDpar[1] = 1.; for(int k=1;k<=NHarm+1;k++) { cs = cos(k*a); sn = sin(k*a); f += Par[2*k]*cs + Par[2*k+1]*sn; DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs); DgDpar[2*k] = cs; DgDpar[2*k+1] = sn; } return f; } ///////////////////////////////////////////////////////////////// /*! \class SOPHYA::HarmonieT \ingroup NTools \anchor HarmonieT \verbatim Analyse harmonique: f(t) = par(1) + Sum[par(2k) *cos(2*pi*k*(t-t0)/par(0)] + Sum[par(2k+1)*sin(2*pi*k*(t-t0)/par(0)] la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1] avec la convention k=1 pour le fondamental k>1 pour le (k-1)ieme harmonique par(0) = periode par(1) = terme constant par(2), par(3) = termes devant le cosinus et le sinus du fondamental par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus et le sinus de l'harmonique m (m>=1). NHarm() = nombre d'harmoniques a fitter. T0() = centrage des temps, ce n'est pas un parametre du fit. \endverbatim */ HarmonieT::HarmonieT(unsigned int nharm,double t0) : GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0) { } HarmonieT::~HarmonieT() { } double HarmonieT::Value(double const xp[], double const* Par) { double a = 2.*Pi*(xp[0]-T0)/Par[0]; double f = Par[1]; for(int k=1;k<=NHarm+1;k++) { // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a); } return f; } double HarmonieT::Val_Der(double const xp[], double const* Par , double *DgDpar) { double cs,sn; double dadp0 = 2.*Pi*(xp[0]-T0); double a = dadp0/Par[0]; double f = Par[1]; DgDpar[0] = 0.; DgDpar[1] = 1.; for(int k=1;k<=NHarm+1;k++) { cs = cos(k*a); sn = sin(k*a); f += Par[2*k]*cs + Par[2*k+1]*sn; DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs)/(-Par[0]*Par[0]); DgDpar[2*k] = cs; DgDpar[2*k+1] = sn; } return f; } //================================================================ // CLASSES DE FONCTIONS 2D AVEC PARAMETRES POUR LE FIT //================================================================ ///////////////////////////////////////////////////////////////// /*! \class SOPHYA::Polyn2D \ingroup NTools \anchor Polyn2D \verbatim polynome 2D de degre total degre: NDegPol = degre du polynome (note N dans la suite) x = x - X_Center, y = y - Y_Center f(x,y) = p[0] +sum(k=1,n){ sum(i=0,k){ p[ki]*x^i*y^(k-i) }} Il y a k+1 termes de degre k (ex: x^i*y^(k-i)) terme de degre k avec x^i: p[ki] avec ki = k*(k+1)/2 + i C'est a dire: deg0: p0 deg1: + p1*y + p2*x deg2: + p3*y^2 + p4*x*y + p5*x^2 deg3: + p6*y^3 + p7*x*y^2 + p8*x^2*y + p9*x^3 deg4: + p10*y^4 + p11*x*y^3 + p12*x^2*y^2 + p13*x^3*y + p14*x^4 deg5: + p15*y^5 + ... ... + ... + p20*x^5 ... degk: + p[k*(k+1)/2]*y^k + ... ... + p[k*(k+3)/2]*x^k ... degn: + p[n*(n+1)/2]*y^n + ... ... + p[n*(n+3)/2]*x^n \endverbatim */ Polyn2D::Polyn2D(unsigned int ndegpol,double x0,double y0) : GeneralFunction(2,ndegpol*(ndegpol+3)/2+1), NDegPol(ndegpol), X_Center(x0), Y_Center(y0) { } Polyn2D::~Polyn2D() { } double Polyn2D::Value(double const xp[], double const* Par) { double f = 0.; double xpow = 1.; for(int i=0;i<=NDegPol;i++) { // On gere la puissance x^i i