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

Last change on this file since 753 was 514, checked in by ansari, 26 years ago

elimination des OVector/OMatrix au profit des TVector/TMatrix cmv 25/10/99

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