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

Last change on this file since 1242 was 926, checked in by ansari, 25 years ago

documentation cmv 13/4/00

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