source: Sophya/trunk/SophyaLib/NTools/fct1dfit.cc@ 3840

Last change on this file since 3840 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 11.9 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <stdio.h>
4#include <stdlib.h>
5#include <iostream>
6#include <math.h>
7#include "fct1dfit.h"
8#include "perrors.h"
9#include "nbconst.h"
10#include "tabmath.h"
11
12//define EXPO exp
13#define EXPO tabFExp
14#define MINEXPM (100.)
15
16//================================================================
17// CLASSES DE FONCTIONS 1D AVEC PARAMETRES POUR LE FIT
18//================================================================
19
20/////////////////////////////////////////////////////////////////
21/*!
22 \class SOPHYA::Gauss1DPol
23 \ingroup NTools
24 \anchor Gauss1DPol
25 \verbatim
26 Gaussienne+polynome:
27 Si polcenter=true: xc=(x-par[1]), sinon xc=x
28 f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ]
29 +par[3] + par[4]*xc + .... + par[3+NDegPol]*xc**NDegPol
30 NDegPol = degre du polynome, si <0 pas de polynome
31 \endverbatim
32*/
33Gauss1DPol::Gauss1DPol(unsigned int ndegpol,bool polcenter)
34: GeneralFunction(1,ndegpol+4), NDegPol(ndegpol), PolCenter(polcenter)
35{
36}
37
38Gauss1DPol::Gauss1DPol(bool polcenter)
39: GeneralFunction(1,3), NDegPol(-1), PolCenter(polcenter)
40{
41}
42
43Gauss1DPol::~Gauss1DPol()
44{
45}
46
47double Gauss1DPol::Value(double const xp[], double const* Par)
48{
49double xc = (xp[0]-Par[1])/Par[2];
50double e = 0.5*xc*xc;
51if( e<MINEXPM ) e = EXPO(-e); else e = 0.;
52double f = Par[0]*e;
53
54if(NDegPol>=0) {
55 double xcp = (PolCenter) ? Par[1] : 0.;
56 double xpow = 1.;
57 for(int i=0;i<=NDegPol;i++) {
58 f += Par[3+i]*xpow;
59 xpow *= xp[0]-xcp;
60 }
61}
62return (f);
63}
64
65double Gauss1DPol::Val_Der(double const xp[],double const* Par
66 ,double *DgDpar)
67{
68
69 double xc = (xp[0]-Par[1])/Par[2];
70 double xc2 = xc*xc;
71 double e = 0.5*xc2;
72 if( e<MINEXPM ) e = EXPO(-e); else e = 0.;
73 double f = Par[0]*e;
74
75 DgDpar[0] = e;
76 DgDpar[1] = xc / Par[2] *f;
77 DgDpar[2] = xc2/ Par[2] *f;
78
79 if(NDegPol>=0) {
80 double xcp = (PolCenter) ? Par[1] : 0.;
81 double xpow = 1.;
82 for(int i=0;i<=NDegPol;i++) {
83 DgDpar[3+i] = xpow;
84 f += Par[3+i]*xpow;
85 if(PolCenter && i<NDegPol) DgDpar[2] += -(i+1)*xpow*Par[4+i];
86 xpow *= xp[0]-xcp;
87 }
88 }
89return f;
90}
91
92
93/////////////////////////////////////////////////////////////////
94/*!
95 \class SOPHYA::GaussN1DPol
96 \ingroup NTools
97 \anchor GaussN1DPol
98 \verbatim
99 Gaussienne_Normalisee+polynome (par[0]=Volume:
100 Si polcenter=true: xc=(x-par[1]), sinon xc=x
101 f(x) = par[0]/(sqrt(2*Pi)*par[2])*exp[-0.5*((x-par[1])/par[2])**2 ]
102 +par[3] + par[4]*xc + .... + par[3+NDegPol]*xc**NDegPol
103 NDegPol = degre du polynome, si <0 pas de polynome
104 \endverbatim
105*/
106GaussN1DPol::GaussN1DPol(unsigned int ndegpol,bool polcenter)
107: GeneralFunction(1,ndegpol+4), NDegPol(ndegpol), PolCenter(polcenter)
108{
109}
110
111GaussN1DPol::GaussN1DPol(bool polcenter)
112: GeneralFunction(1,3), NDegPol(-1), PolCenter(polcenter)
113{
114}
115
116GaussN1DPol::~GaussN1DPol()
117{
118}
119
120double GaussN1DPol::Value(double const xp[], double const* Par)
121{
122 double xc = (xp[0]-Par[1])/Par[2];
123 double xc2 = xc*xc;
124 double e = 0.5*xc2;
125 if( e<MINEXPM ) e = EXPO(-e)/(S2Pi*Par[2]); else e = 0.;
126 double f = Par[0]*e;
127
128 if(NDegPol>=0) {
129 double xcp = (PolCenter) ? Par[1] : 0.;
130 double xpow = 1.;
131 for(int i=0;i<=NDegPol;i++) {
132 f += Par[3+i]*xpow;
133 xpow *= xp[0]-xcp;
134 }
135 }
136
137return (f);
138}
139
140double GaussN1DPol::Val_Der(double const xp[], double const* Par
141 , double *DgDpar)
142{
143 double xc = (xp[0]-Par[1])/Par[2];
144 double xc2 = xc*xc;
145 double e = 0.5*xc2;
146 if( e<MINEXPM ) e = EXPO(-e)/(S2Pi*Par[2]); else e = 0.;
147 double f = Par[0]*e;
148
149 DgDpar[0] = e;
150 DgDpar[1] = xc / Par[2] *f;
151 DgDpar[2] = (xc2-1.)/ Par[2] *f;
152
153 if(NDegPol>=0) {
154 double xcp = (PolCenter) ? Par[1] : 0.;
155 double xpow = 1.;
156 for(int i=0;i<=NDegPol;i++) {
157 DgDpar[3+i] = xpow;
158 f += Par[3+i]*xpow;
159 if(PolCenter && i<NDegPol) DgDpar[2] += -(i+1)*xpow*Par[4+i];
160 xpow *= xp[0]-xcp;
161 }
162 }
163
164 return f;
165}
166
167/////////////////////////////////////////////////////////////////
168/*!
169 \class SOPHYA::Exp1DPol
170 \ingroup NTools
171 \anchor Exp1DPol
172 \verbatim
173 Exponentielle+polynome:
174 xx = x - X_Center
175 f(x) = exp[par[0]+par[1]*xx]
176 +par[2] + par[3]*xx + .... + par[2+NDegPol]*xx**NDegPol
177 NDegPol = degre du polynome, si <0 pas de polynome
178 \endverbatim
179*/
180Exp1DPol::Exp1DPol(unsigned int ndegpol,double x0)
181: GeneralFunction(1,ndegpol+3), NDegPol(ndegpol), X_Center(x0)
182{
183}
184
185Exp1DPol::Exp1DPol(double x0)
186: GeneralFunction(1,2), NDegPol(-1), X_Center(x0)
187{
188}
189
190Exp1DPol::~Exp1DPol()
191{
192}
193
194double Exp1DPol::Value(double const xp[], double const* Par)
195{
196double xc = Par[0]+Par[1]*(xp[0]-X_Center);
197double f = ( xc>-MINEXPM ) ? EXPO(xc): 0.;
198
199if(NDegPol>=0) {
200 double xpow = 1.;
201 for(int i=0;i<=NDegPol;i++) {
202 f += Par[2+i]*xpow;
203 xpow *= xp[0]-X_Center;
204 }
205}
206return (f);
207}
208
209double Exp1DPol::Val_Der(double const xp[],double const* Par
210 ,double *DgDpar)
211{
212double xc = Par[0]+Par[1]*(xp[0]-X_Center);
213double f = ( xc>-MINEXPM ) ? EXPO(xc): 0.;
214
215DgDpar[0] = f;
216DgDpar[1] = (xp[0]-X_Center) * f;
217
218if(NDegPol>=0) {
219 double xpow = 1.;
220 for(int i=0;i<=NDegPol;i++) {
221 DgDpar[2+i] = xpow;
222 f += Par[2+i]*xpow;
223 xpow *= xp[0]-X_Center;
224 }
225}
226return f;
227}
228
229/////////////////////////////////////////////////////////////////
230/*!
231 \class SOPHYA::Polyn1D
232 \ingroup NTools
233 \anchor Polyn1D
234 \verbatim
235 polynome 1D:
236 xx = x - X_Center
237 f(x) = par[0] + par[1]*xx + .... + par[NDegPol+1]*xx**NDegPol
238 NDegPol = degre du polynome
239 \endverbatim
240*/
241Polyn1D::Polyn1D(unsigned int ndegpol,double x0)
242: GeneralFunction(1,ndegpol+1), NDegPol(ndegpol), X_Center(x0)
243{
244}
245
246Polyn1D::~Polyn1D()
247{
248}
249
250double Polyn1D::Value(double const xp[], double const* Par)
251{
252 double xpow = 1.;
253 double f = 0.;
254 for(int i=0;i<=NDegPol;i++) {
255 f += Par[i]*xpow;
256 xpow *= xp[0]-X_Center;
257 }
258 return (f);
259}
260
261double Polyn1D::Val_Der(double const xp[], double const* Par
262 , double *DgDpar)
263{
264 double xpow = 1.;
265 double f = 0.;
266 for(int i=0;i<=NDegPol;i++) {
267 DgDpar[i] = xpow;
268 f += Par[i]*xpow;
269 xpow *= xp[0]-X_Center;
270 }
271 return f;
272}
273
274
275/////////////////////////////////////////////////////////////////
276/*!
277 \class SOPHYA::HarmonieNu
278 \ingroup NTools
279 \anchor HarmonieNu
280 \verbatim
281 Analyse harmonique:
282 f(t) = par(1) + Sum[par(2k) *cos(2*pi*k*par(0)*(t-t0)]
283 + Sum[par(2k+1)*sin(2*pi*k*par(0)*(t-t0)]
284 la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1]
285 avec la convention k=1 pour le fondamental
286 k>1 pour le (k-1)ieme harmonique
287 par(0) = inverse de la periode (frequence)
288 par(1) = terme constant
289 par(2), par(3) = termes devant le cosinus et le sinus
290 du fondamental
291 par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus
292 et le sinus de l'harmonique m (m>=1).
293 NHarm() = nombre d'harmoniques a fitter.
294 T0() = centrage des temps, ce n'est pas un parametre du fit.
295 `Conseil:' Avant de faire un fit avec les `NHarm()'
296 harmoniques, il est preferable de faire un pre-fit
297 ou seuls les parametres 1,2 et 3 sont libres et d'injecter
298 le resultat du fit sur ces 3 parametres comme valeurs
299 de depart pour le fit global avec les `NHarm()' harmoniques.
300 De toute facon, le fit ne marchera que si la periode
301 est initialisee de facon tres precise.
302 \endverbatim
303*/
304HarmonieNu::HarmonieNu(unsigned int nharm,double t0)
305: GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0)
306{
307}
308
309HarmonieNu::~HarmonieNu()
310{
311}
312
313double HarmonieNu::Value(double const xp[], double const* Par)
314{
315 double a = 2.*Pi*(xp[0]-T0)*Par[0];
316 double f = Par[1];
317 for(int k=1;k<=NHarm+1;k++) {
318 // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm
319 f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a);
320 }
321 return f;
322}
323
324double HarmonieNu::Val_Der(double const xp[], double const* Par
325 , double *DgDpar)
326{
327 double cs,sn;
328 double dadp0 = 2.*Pi*(xp[0]-T0);
329 double a = dadp0*Par[0];
330 double f = Par[1];
331 DgDpar[0] = 0.;
332 DgDpar[1] = 1.;
333 for(int k=1;k<=NHarm+1;k++) {
334 cs = cos(k*a); sn = sin(k*a);
335 f += Par[2*k]*cs + Par[2*k+1]*sn;
336 DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs);
337 DgDpar[2*k] = cs;
338 DgDpar[2*k+1] = sn;
339 }
340 return f;
341}
342
343
344/////////////////////////////////////////////////////////////////
345/*!
346 \class SOPHYA::HarmonieT
347 \ingroup NTools
348 \anchor HarmonieT
349 \verbatim
350 Analyse harmonique:
351 f(t) = par(1) + Sum[par(2k) *cos(2*pi*k*(t-t0)/par(0)]
352 + Sum[par(2k+1)*sin(2*pi*k*(t-t0)/par(0)]
353 la somme Sum porte sur l'indice k qui varie de [1,NHarm()+1]
354 avec la convention k=1 pour le fondamental
355 k>1 pour le (k-1)ieme harmonique
356 par(0) = periode
357 par(1) = terme constant
358 par(2), par(3) = termes devant le cosinus et le sinus
359 du fondamental
360 par(2(m+1)), par(2(m+1)+1) = termes devant le cosinus
361 et le sinus de l'harmonique m (m>=1).
362 NHarm() = nombre d'harmoniques a fitter.
363 T0() = centrage des temps, ce n'est pas un parametre du fit.
364 \endverbatim
365*/
366HarmonieT::HarmonieT(unsigned int nharm,double t0)
367: GeneralFunction(1,4+2*nharm), NHarm(nharm), T0(t0)
368{
369}
370
371HarmonieT::~HarmonieT()
372{
373}
374
375double HarmonieT::Value(double const xp[], double const* Par)
376{
377 double a = 2.*Pi*(xp[0]-T0)/Par[0];
378 double f = Par[1];
379 for(int k=1;k<=NHarm+1;k++) {
380 // k=1 fondamental, k=2 a NHarm+1 harmoniques numero 1 a NHarm
381 f += Par[2*k]*cos(k*a) + Par[2*k+1]*sin(k*a);
382 }
383 return f;
384}
385
386double HarmonieT::Val_Der(double const xp[], double const* Par
387 , double *DgDpar)
388{
389 double cs,sn;
390 double dadp0 = 2.*Pi*(xp[0]-T0);
391 double a = dadp0/Par[0];
392 double f = Par[1];
393 DgDpar[0] = 0.;
394 DgDpar[1] = 1.;
395 for(int k=1;k<=NHarm+1;k++) {
396 cs = cos(k*a); sn = sin(k*a);
397 f += Par[2*k]*cs + Par[2*k+1]*sn;
398 DgDpar[0] += k*dadp0*(-Par[2*k]*sn+Par[2*k+1]*cs)/(-Par[0]*Par[0]);
399 DgDpar[2*k] = cs;
400 DgDpar[2*k+1] = sn;
401 }
402 return f;
403}
404
405//================================================================
406// CLASSES DE FONCTIONS 2D AVEC PARAMETRES POUR LE FIT
407//================================================================
408
409/////////////////////////////////////////////////////////////////
410/*!
411 \class SOPHYA::Polyn2D
412 \ingroup NTools
413 \anchor Polyn2D
414 \verbatim
415 polynome 2D de degre total degre:
416 NDegPol = degre du polynome (note N dans la suite)
417 x = x - X_Center, y = y - Y_Center
418 f(x,y) = p[0] +sum(k=1,n){ sum(i=0,k){ p[ki]*x^i*y^(k-i) }}
419 Il y a k+1 termes de degre k (ex: x^i*y^(k-i))
420 terme de degre k avec x^i: p[ki] avec ki = k*(k+1)/2 + i
421 C'est a dire:
422 deg0: p0
423 deg1: + p1*y + p2*x
424 deg2: + p3*y^2 + p4*x*y + p5*x^2
425 deg3: + p6*y^3 + p7*x*y^2 + p8*x^2*y + p9*x^3
426 deg4: + p10*y^4 + p11*x*y^3 + p12*x^2*y^2 + p13*x^3*y + p14*x^4
427 deg5: + p15*y^5 + ... ... + ... + p20*x^5
428 ...
429 degk: + p[k*(k+1)/2]*y^k + ... ... + p[k*(k+3)/2]*x^k
430 ...
431 degn: + p[n*(n+1)/2]*y^n + ... ... + p[n*(n+3)/2]*x^n
432 \endverbatim
433*/
434Polyn2D::Polyn2D(unsigned int ndegpol,double x0,double y0)
435: GeneralFunction(2,ndegpol*(ndegpol+3)/2+1), NDegPol(ndegpol), X_Center(x0), Y_Center(y0)
436{
437}
438
439Polyn2D::~Polyn2D()
440{
441}
442
443double Polyn2D::Value(double const xp[], double const* Par)
444{
445 double f = 0.;
446 double xpow = 1.;
447 for(int i=0;i<=NDegPol;i++) { // On gere la puissance x^i i<ndeg
448 int ip;
449 double ypow = 1.;
450 for(int j=0;j<=NDegPol-i;j++) { // On gere la puissance x^j tq degre=i+j<=ndeg
451 ip = (i+j)*(i+j+1)/2+i;
452 f += Par[ip]*xpow*ypow;
453 ypow *= xp[1]-Y_Center;
454 }
455 xpow *= xp[0]-X_Center;
456 }
457 return f;
458}
459
460double Polyn2D::Val_Der(double const xp[], double const* Par
461 , double *DgDpar)
462{
463 double f = 0.;
464 double xpow = 1.;
465 for(int i=0;i<=NDegPol;i++) { // On gere la puissance x^i i<ndeg
466 int ip;
467 double ypow = 1.;
468 for(int j=0;j<=NDegPol-i;j++) { // On gere la puissance x^j tq degre=i+j<=ndeg
469 ip = (i+j)*(i+j+1)/2+i;
470 DgDpar[ip] = xpow*ypow;
471 f += Par[ip]*DgDpar[ip];
472 ypow *= xp[1]-Y_Center;
473 }
474 xpow *= xp[0]-X_Center;
475 }
476 return f;
477}
Note: See TracBrowser for help on using the repository browser.