source: Sophya/trunk/SophyaLib/NTools/fct2dfit.cc@ 896

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

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

File size: 40.0 KB
Line 
1#include "machdefs.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <iostream.h>
5#include <math.h>
6#include "fct2dfit.h"
7#include "perrors.h"
8#include "nbconst.h"
9#include "tabmath.h"
10
11// define SIMPSON4 c'etait la prod 91-95 rcecile
12#define SIMPSON9
13#include "simps2d.h"
14
15// define EXPO exp
16#define EXPO tabFExp
17#define MINEXPM (100.)
18
19//================================================================
20// GeneralFunction 2D pour PSF pixel taille 1x1
21//================================================================
22
23/////////////////////////////////////////////////////////////////
24//++
25// Class GeneralPSF2D
26// Lib Outils++
27// include fct2dfit.h
28//
29// Classe de definition d'une PSF 2D a nPar parametres
30// Pour definir une PSF, il faut creer une classe qui herite
31// de ``GeneralPSF2D'' (cf par exemple GauRho2D...).
32// La disposition des parametres definissant la PSF est indifferente,
33// toutefois il est conseille de suivre l'ordre:
34//--
35//++
36// - PSF 2D a NPar parametres:
37// p[0] = Volume (ou hauteur)
38// p[1] = centre X0, p[2] = centre Y0
39// p[3] = SigmaX , p[4] = SigmaY, p[5] = Rho
40// p[6],p[7],... = autres parametres (eventuels) definissant la PSF.
41// (ex: pour la Moffat p[6] = exposant Beta et NPar=8).
42// p[NPar-1] = Fond
43//--
44//++
45// L'emploi de certaines classes comme par exemple ``GenMultiPSF2D''
46// necessite de suivre rigoureusement l'ordre indique ci-dessus
47// pour les parametres.
48//--
49
50//++
51GeneralPSF2D::GeneralPSF2D(unsigned int nPar)
52//
53//--
54: GeneralFunction(2,nPar), VolEps(1.e-4)
55{
56ASSERT( nPar>0 );
57}
58
59GeneralPSF2D::~GeneralPSF2D()
60{
61}
62
63//++
64double GeneralPSF2D::ValueH(double const xp[], double const* parm)
65//
66//| ValueH = hauteur*forme(x,y)+fond tq forme(0,0)=1.
67//| alors que Value = volume*forme(x,y)+fond tq volume(forme)=1.
68//| Dans notre convention le dernier parametre est le fond,
69//| le premier le volume et les 2 suivants le centrage x0,y0
70//| ---> Ici parm[0] = hauteur
71//--
72{
73double x0[2];
74int mm1 = mNPar - 1;
75
76// point central en [x0,y0]
77x0[0] = parm[1]; x0[1] = parm[2];
78
79// retour avec hauteur = 1
80return (Value(xp,parm) - parm[mm1]) / (Value(x0,parm) - parm[mm1])
81 * parm[0] + parm[mm1];
82}
83
84//++
85double GeneralPSF2D::VolPSF(double const* parm)
86//
87//| Cette fonction calcule le volume d'une PSF de hauteur=1
88//| avec une precision de "VolEps"
89//| dans le but de connaitre le coefficient permettant
90//| de convertir le volume d'une PSF en son amplitude
91//| ou vice-versa: " volume = VolPSF * hauteur "
92//| L'integration se fait 1/4 de pixel par 1/4 de pixel
93//| ATTENTION: Il s'agit de PSF donc x,y,x0,y0,Sigma.. sont en pixels
94//--
95{
96 double x[2],step;
97 double vol,volprec;
98 int ecart,i,j,k;
99 int mm1 = mNPar-1;
100
101 step = 1. / 4.;
102 vol = volprec = 0.;
103 ecart = 1;
104
105 /* pixel central */
106 for(k=0;k<nd2d;k++) {
107 x[0] = parm[1] + dx2d[k]*step;
108 x[1] = parm[2] + dy2d[k]*step;
109 vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
110 }
111
112/* increment en couronnes carrees de 2*ecart+1 de cote */
113 while ( ecart < 2 || fabs((vol-volprec)/vol) > VolEps ) {
114 volprec = vol;
115 for (i= -ecart;i<=ecart;i++) for(k=0;k<nd2d;k++) {
116 x[0] = parm[1] + (i+dx2d[k])*step;
117 x[1] = parm[2] + (-ecart+dy2d[k])*step;
118 vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
119 x[1] = parm[2] + ( ecart+dy2d[k])*step;
120 vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
121 }
122 for (j= -ecart+1;j<=ecart-1;j++) for(k=0;k<nd2d;k++) {
123 x[1] = parm[2] + (j+dy2d[k])*step;
124 x[0] = parm[1] + (-ecart+dx2d[k])*step;
125 vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
126 x[0] = parm[1] + ( ecart+dx2d[k])*step;
127 vol += (ValueH(x,parm)-parm[mm1]) * w2d[k];
128 }
129 ecart++;
130 // printf("ec=%d v=%f prec=%f %f\n",ecart,vol,fabs((vol-volprec)/vol),VolEps);
131 }
132
133 vol *= step * step / parm[0];
134 return vol;
135}
136
137//++
138void GeneralPSF2D::DefaultParam(double *parm)
139//
140// Definition des defauts des parametres
141//--
142{
143 for (int i=0; i<mNPar; i++) parm[i] = 0.;
144 parm[3] = parm[4] = 1.; // Sigx Sigy
145}
146
147//++
148void GeneralPSF2D::SetVolEps(double const prec)
149//
150// Definition de la precision sur le calcul du volume
151//--
152{
153 VolEps = prec;
154}
155
156//================================================================
157// GeneralFunction 2D pour MULTI-PSF pixel taille 1x1
158//================================================================
159
160/////////////////////////////////////////////////////////////////
161//++
162// Class GenMultiPSF2D
163// Lib Outils++
164// include fct2dfit.h
165//
166// Classe de definition d'un ensemble de PSF2D
167// pour fiter simultanement plusieurs etoiles et un fond constant.
168// Les parametres de forme de la PSF (Sx, Sy, Rho etc... et Fond)
169// sont les memes pour toutes les etoiles, seuls le centre
170// (X0,Y0) et le volume (ou la hauteur) V varient pour chaque etoile.
171// La disposition des parametres definissant la PSF generique
172// est obligatoirement la suivante:
173//--
174//++
175//| - PSF 2D a NPar parametres:
176//| p[0] = Volume (ou hauteur)
177//| p[1] = centre X0, p[2] = centre Y0
178//| p[3] = SigmaX , p[4] = SigmaY, p[5] = Rho
179//| p[6],p[7],... = autres parametres (eventuels) definissant la PSF.
180//| (ex: pour la Moffat p[6] = exposant Beta et NPar=8).
181//| p[NPar-1] = Fond
182//|
183//--
184//++
185//| - La Multi-PSF a ses parametres arranges dans l'ordre suivant:
186//| Soit NStar le nombre d'etoiles a fiter simultanement
187//| NP = le nombre de parametres de la PSF 2D generique
188//| On a NF = NP-7 parametres de forme supplementaires
189//| (ex: nf=0 pour GauRho2D, nf=1 pour MofRho2D)
190//| p[0],p[1],p[2] = V0,X0,Y0 pour la premiere etoile
191//| p[3],p[4],p[5] = V1,X1,Y1 pour la deuxieme etoile
192//| ...
193//| p[3*i],p[3*i+1],p[3*i+2] = Vi,Xi,Yi pour la (i+1) ieme etoile
194//| ...
195//| p[m*i],p[m*i+1],p[m*i+2] = Vm,Xm,Ym ; m = NStar-1
196//| pour la NStar ieme et derniere etoile
197//| p[3*NStar],p[3*NStar+1],p[3*NStar+2] = SigmaX, SigmaY et Rho
198//| p[3*NStar+3],...,p[3*NStar+2+NF] = parametres de forme
199//| supplementaires pour definir la PSF 2D
200//| p[3*NStar+2+NF+1] = Fond
201//--
202
203//++
204GenMultiPSF2D::GenMultiPSF2D(GeneralPSF2D* psf2d,unsigned int nstar)
205//
206// Createur. ``psf2d'' est le nom de la PSF generique a utiliser,
207// et ``nstar'' est le nombre d'etoiles a fiter simultanement.
208//--
209 : GeneralPSF2D((psf2d!=NULL) ? 3*nstar+4+psf2d->NPar()-7: 0)
210 , mPsf2D(psf2d), mNStar(nstar)
211{
212ASSERT( nstar>0 && psf2d!=NULL );
213mNForme = mPsf2D->NPar() - 7;
214ASSERT( mNForme>=0 );
215mNParm = mPsf2D->NPar();
216mParm = new double[mNParm];
217mDer = new double[mNParm];
218mNParmTot = GeneralPSF2D::NPar();
219cout<<"mNStar="<<mNStar<<" mNParmTot="<<mNParmTot
220 <<" mNParm="<<mNParm<<" mNForme="<<mNForme<<endl;
221}
222
223GenMultiPSF2D::~GenMultiPSF2D()
224{
225delete [] mParm; mParm = NULL;
226delete [] mDer; mDer = NULL;
227}
228
229double GenMultiPSF2D::Value(double const xp[], double const* Par)
230{
231// Fond commun
232double val = Par[mNParmTot-1];
233
234// Remplissage le tableau des parametres pour la PSF generique
235// ... Communs a toutes les PSF individuelles: Sx,Sy,Rho,[Forme],Fond
236const double *pt = &Par[3*mNStar];
237double *p = &mParm[3];
238{for(int i=0;i<3+mNForme;i++) *(p++) = *(pt++);} // Sx,Sy,Rho,[Forme...]
239*(p++) = 0.; // Fond
240
241// ... Propres a chaque etoiles: Vi,Xi,Yi
242pt = Par;
243{for(int i=0;i<mNStar;i++) {
244 mParm[0] = *(pt++); // Vi (ou Hi)
245 mParm[1] = *(pt++); // Xi
246 mParm[2] = *(pt++); // Yi
247 val += mPsf2D->Value(xp,mParm);
248}}
249
250return val;
251}
252
253double GenMultiPSF2D::Val_Der(double const xp[], double const* Par
254 ,double *DgDpar)
255{
256{for(int i=3*mNStar;i<mNParmTot-1;i++) DgDpar[i] = 0.;}
257
258// Fond commun
259double val = Par[mNParmTot-1];
260DgDpar[mNParmTot-1] = 1.; // D./DFond
261
262// Remplissage le tableau des parametres pour la PSF generique
263// ... Communs a toutes les PSF individuelles: Sx,Sy,Rho,[Forme],Fond
264const double *pt = &Par[3*mNStar];
265double *p = &mParm[3];
266{for(int i=0;i<3+mNForme;i++) *(p++) = *(pt++);} // Sx,Sy,Rho,[Forme...]
267*(p++) = 0.; // Fond
268
269// ... Propres a chaque etoiles: Vi,Xi,Yi
270double *dpt = DgDpar, *dpt2 = &DgDpar[3*mNStar];
271pt = Par;
272{for(int i=0;i<mNStar;i++) {
273 mParm[0] = *(pt++); // Vi (ou Hi)
274 mParm[1] = *(pt++); // Xi
275 mParm[2] = *(pt++); // Yi
276 val += mPsf2D->Val_Der(xp,mParm,mDer);
277 {for(int j=0;j<3;j++) *(dpt++) = mDer[j];} // D./DVi,D./DXi,D./DYi
278 {for(int j=0;j<3+mNForme;j++) *(dpt2+j) += mDer[3+j];} // D./DSx,D./DSy,D./DRho,[D./DForme]
279}}
280
281return val;
282}
283
284//==============================================================================
285// CLASSES DE FONCTIONS 2D type PSF AVEC PARAMETRES POUR LE FIT pixel taille 1x1
286// la taille du pixel est importante quand on utilise les PSF integrees
287// (x,y x0,y0 sigmaX.... sont en unites de pixels !!!)
288//==============================================================================
289
290#define _x0_ Par[1]
291#define _y0_ Par[2]
292#define _sigx_ Par[3]
293#define _sigy_ Par[4]
294#define _rho_ Par[5]
295#define _Gm_ Par[6]
296#define _B4_ Par[6]
297#define _B6_ Par[7]
298#define _B2_ Par[8]
299
300/////////////////////////////////////////////////////////////////
301//++
302// Module Classes de PSF 2D
303// Lib Outils++
304// include fct2dfit.h
305//--
306/////////////////////////////////////////////////////////////////
307
308/////////////////////////////////////////////////////////////////
309//++
310// Titre GauRho2D
311// \index{GauRho2D}
312//
313//| gaussienne+fond 2D
314//| Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=fond
315//| sigx,sigy,rho = sigma et rho de la gaussienne
316//| x0,y0 = centre de la gaussienne
317//| PSF(x,y) = N * exp[ - 1/2 (X**2 + Y**2 -2*rho*X*Y) ]
318//| avec X = (x-x0)/sigx et Y = (y-y0)/sigy
319//| N = sqrt(1-rho**2)/(2*Pi*sigx*sigy)
320//| le volume de cette gaussienne est V=1.
321//| F(x,y) = Par[0]*PSF(x,y)+Par[6] (volume=Par[0],fond=Par[6])
322//--
323//++
324//| -*- Remarque: De la facon dont est ecrite la PSF gaussienne
325//| sigx,sigy representent les sigmas des gaussiennes 1D
326//| qui sont les coupes de la gaussienne 2D pour y=0 et x=0.
327//| Les moments centres d'ordre 2 sont
328//| sx = sigx/sqrt(1-ro^2) et sy = sigy/sqrt(1-ro^2)
329//--
330/////////////////////////////////////////////////////////////////
331
332//++
333GauRho2D::GauRho2D()
334//
335// Createur
336//--
337: GeneralPSF2D(7)
338{
339}
340
341GauRho2D::~GauRho2D()
342{
343}
344
345double GauRho2D::Value(double const xp[], double const* Par)
346{
347 double N = sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
348 double X = (xp[0]-_x0_)/_sigx_;
349 double Y = (xp[1]-_y0_)/_sigy_;
350 double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
351 if( z2<MINEXPM ) return Par[0] * N*EXPO(-z2) + Par[6];
352 else return Par[6];
353}
354
355double GauRho2D::ValueH(double const xp[], double const* Par)
356{
357 double X = (xp[0]-_x0_)/_sigx_;
358 double Y = (xp[1]-_y0_)/_sigy_;
359 //double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
360 double z2 = 0.5*(X-Y)*(X-Y) - (_rho_ - 1)*X*Y;
361 if( z2<MINEXPM ) return Par[0] * EXPO(-z2) + Par[6];
362 else return Par[6];
363}
364
365double GauRho2D::VolPSF(double const* Par)
366{
367 return DeuxPi * _sigx_ * _sigy_ / sqrt(1.-_rho_*_rho_);
368}
369
370double GauRho2D::Val_Der(double const xp[], double const* Par
371 , double *DgDpar)
372{
373 double unmr2 = 1.-_rho_*_rho_;
374 double N = sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
375 double X = (xp[0]-_x0_)/_sigx_;
376 double Y = (xp[1]-_y0_)/_sigy_;
377
378 double XmrY = X-_rho_*Y;
379 double YmrX = Y-_rho_*X;
380 double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
381
382 /* g(x,y) */
383 double PSF = 0.;
384 if( z2<MINEXPM ) PSF = N * EXPO(-z2);
385 /* dg(x,y)/d(x0) */
386 DgDpar[1] = Par[0]* PSF* XmrY/_sigx_;
387 /* dg(x,y)/d(y0) */
388 DgDpar[2] = Par[0]* PSF* YmrX/_sigy_;
389 /* dg(x,y)/d(sx)*/
390 DgDpar[3] = Par[0]* PSF* (X*XmrY-1.)/_sigx_;
391 /* dg(x,y)/d(sy) */
392 DgDpar[4] = Par[0]* PSF* (Y*YmrX-1.)/_sigy_;
393 /* dg(x,y)/d(rho) */
394 DgDpar[5] = Par[0]* PSF* (X*Y-2.*_rho_/unmr2);
395 /* dg(x,y)/d(Vol) */
396 DgDpar[0] = PSF;
397 /* dg(x,y)/d(Fond) */
398 DgDpar[6] = 1.;
399
400 return Par[0] * PSF + Par[6];
401}
402
403void GauRho2D::DefaultParam(double *parm)
404{
405 for (int i=0; i<mNPar; i++) parm[i] = 0.;
406 parm[3] = parm[4] = 1.; // Sigx Sigy
407}
408
409
410/////////////////////////////////////////////////////////////////
411//++
412// Titre GauRhInt2D
413// \index{GauRhInt2D}
414//
415//| Cette fonction calcule une approximation a l'integrale d'une
416//| gaussienne 2D sur un carre de longueur unite (x,y-05 -> x,y+0.5)
417//--
418/////////////////////////////////////////////////////////////////
419
420//++
421GauRhInt2D::GauRhInt2D()
422//
423// Createur
424//--
425: GeneralPSF2D(7)
426{
427}
428
429GauRhInt2D::~GauRhInt2D()
430{
431}
432
433double GauRhInt2D::Value(double const xp[], double const* Par)
434{
435 double N = sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
436 double x = xp[0] - _x0_;
437 double y = xp[1] - _y0_;
438 double SPSF = 0.;
439 double X,Y,z2;
440 for(int i=0; i<nd2d; i++) {
441 X = (x+dx2d[i])/_sigx_;
442 Y = (y+dy2d[i])/_sigy_;
443 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
444 if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
445 }
446 return Par[0]* N*SPSF + Par[6];
447}
448
449double GauRhInt2D::ValueH(double const xp[], double const* Par)
450{
451 double x = xp[0] - _x0_;
452 double y = xp[1] - _y0_;
453 double SPSF = 0.;
454 double X,Y,z2;
455 for(int i=0; i<nd2d; i++) {
456 X = (x+dx2d[i])/_sigx_;
457 Y = (y+dy2d[i])/_sigy_;
458 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
459 if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
460 }
461 return Par[0] *SPSF + Par[6];
462}
463
464double GauRhInt2D::VolPSF(double const* Par)
465{
466 return DeuxPi * _sigx_ * _sigy_ / sqrt(1.-_rho_*_rho_);
467}
468
469double GauRhInt2D::Val_Der(double const xp[], double const* Par
470 ,double *DgDpar)
471{
472 for(int i=0; i<=6; i++) DgDpar[i] = 0.;
473 double unmr2 = 1.-_rho_*_rho_;
474 double N = sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
475 double x = xp[0] - _x0_;
476 double y = xp[1] - _y0_;
477
478 double z2,PSF,X,Y,XmrY,YmrX;
479 double SPSF = 0.;
480 {
481 for(int i=0; i<nd2d; i++) {
482 X = (x+dx2d[i])/_sigx_;
483 Y = (y+dy2d[i])/_sigy_;
484 XmrY = X-_rho_*Y;
485 YmrX = Y-_rho_*X;
486 z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
487 /* g(x,y) */
488 if(z2<MINEXPM) PSF = N * EXPO(-z2) * w2d[i]; else PSF = 0.;
489 SPSF += PSF;
490 /* dg(x,y)/d(x0) */
491 DgDpar[1] += Par[0] * PSF* XmrY/_sigx_;
492 /* dg(x,y)/d(y0) */
493 DgDpar[2] += Par[0] * PSF* YmrX/_sigy_;
494 /* dg(x,y)/d(sx)*/
495 DgDpar[3] += Par[0] * PSF* (X*XmrY-1.)/_sigx_;
496 /* dg(x,y)/d(sy) */
497 DgDpar[4] += Par[0] * PSF* (Y*YmrX-1.)/_sigy_;
498 /* dg(x,y)/d(rho) */
499 DgDpar[5] += Par[0] * PSF* (X*Y-2.*_rho_/unmr2);
500 }
501 }
502 /* dg(x,y)/d(Vol) */
503 DgDpar[0] = SPSF;
504 /* dg(x,y)/d(Fond) */
505 DgDpar[6] = 1.;
506
507 return Par[0] *SPSF + Par[6];
508}
509
510void GauRhInt2D::DefaultParam(double *parm)
511{
512 for (int i=0; i<mNPar; i++) parm[i] = 0.;
513 parm[3] = parm[4] = 1.; // Sigx Sigy
514}
515
516#define B4 1.
517#define B6 1.
518#define KB4B6 0.136887
519
520/////////////////////////////////////////////////////////////////
521//++
522// Titre GdlRho2D
523// \index{GdlRho2D}
524//
525//| Cette fonction calcule une gaussienne 2D de volume 1 approchee
526//| par son developpement limite au 3ieme ordre (see dophot)
527//| Meme commentaire que GauRho2D, cf plus haut sauf que:
528//| Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=fond
529//| z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
530//| PSF(x,y) = N / [ 1 + z**2 + B4/2 *z**4 + B6/6 *z**6 ]
531//| N = KB4B6
532//| le coefficient KB4B6 etant trop dur a calculer analytiquement
533//| Il doit etre calcule numeriquement et entre dans ce programme
534//| ATTENTION: dans cette routine B4 et B6 sont imposes et pas fites!
535//| - DL de la gaussienne: B4=1., B6=1., KB4B6=0.13688679
536//| le volume de cette gaussienne est V=1.
537//| F(x,y) = Par[0]*PSF(x,y)+Par[6] (volume=Par[0],fond=Par[6])
538//--
539/////////////////////////////////////////////////////////////////
540
541//++
542GdlRho2D::GdlRho2D()
543//
544// Createur
545//--
546: GeneralPSF2D(7)
547{
548}
549
550GdlRho2D::~GdlRho2D()
551{
552}
553
554double GdlRho2D::Value(double const xp[], double const* Par)
555{
556 double N = KB4B6*sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_);
557 double X = (xp[0]-_x0_)/_sigx_;
558 double Y = (xp[1]-_y0_)/_sigy_;
559 double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
560 double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
561 return Par[0] *N/D + Par[6];
562}
563
564double GdlRho2D::ValueH(double const xp[], double const* Par)
565{
566 double X = (xp[0]-_x0_)/_sigx_;
567 double Y = (xp[1]-_y0_)/_sigy_;
568 double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
569 double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
570 return Par[0] /D + Par[6];
571}
572
573double GdlRho2D::VolPSF(double const* Par)
574{
575 return _sigx_*_sigy_/(KB4B6*sqrt(1.-_rho_*_rho_));
576}
577
578double GdlRho2D::Val_Der(double const xp[], double const* Par
579 , double *DgDpar)
580{
581 double unmr2 = 1.-_rho_*_rho_;
582 double N = KB4B6*sqrt(unmr2)/(_sigx_*_sigy_);
583 double X = (xp[0]-_x0_)/_sigx_;
584 double Y = (xp[1]-_y0_)/_sigy_;
585 double XmrY = X-_rho_*Y;
586 double YmrX = Y-_rho_*X;
587 double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
588 double D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
589 double dDsD = (1.+z2*(B4+B6/2.*z2))/D;
590
591 /* g(x,y) */
592 double PSF = N / D;
593 /* dg(x,y)/d(x0) */
594 DgDpar[1] = Par[0]* PSF* dDsD*XmrY/_sigx_;
595 /* dg(x,y)/d(y0) */
596 DgDpar[2] = Par[0]* PSF* dDsD*YmrX/_sigy_;
597 /* dg(x,y)/d(sx)*/
598 DgDpar[3] = Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
599 /* dg(x,y)/d(sy) */
600 DgDpar[4] = Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
601 /* dg(x,y)/d(rho) */
602 DgDpar[5] = Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
603 /* dg(x,y)/d(Vol) */
604 DgDpar[0] = PSF;
605 /* dg(x,y)/d(Fond) */
606 DgDpar[6] = 1.;
607
608 return Par[0] *PSF + Par[6];
609}
610
611void GdlRho2D::DefaultParam(double *parm)
612{
613 for (int i=0; i<mNPar; i++) parm[i] = 0.;
614 parm[3] = parm[4] = 1.; // Sigx Sigy
615}
616
617
618/////////////////////////////////////////////////////////////////
619//++
620// Titre GdlRhInt2D
621// \index{GdlRhInt2D}
622//
623// fonction integree de GdlRho2d
624//--
625/////////////////////////////////////////////////////////////////
626
627//++
628GdlRhInt2D::GdlRhInt2D()
629//
630// Createur
631//--
632: GeneralPSF2D(7)
633{
634}
635
636GdlRhInt2D::~GdlRhInt2D()
637{
638}
639
640double GdlRhInt2D::Value(double const xp[], double const* Par)
641{
642 double N = KB4B6*sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_);
643 double x = xp[0] - _x0_;
644 double y = xp[1] - _y0_;
645
646 double z2,X,Y,D;
647 double SPSF = 0.;
648 for(int i=0; i<nd2d; i++) {
649 X = (x+dx2d[i])/_sigx_;
650 Y = (y+dy2d[i])/_sigy_;
651 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
652 D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
653 SPSF += w2d[i] / D;
654 }
655 return Par[0] *N*SPSF + Par[6];
656}
657
658double GdlRhInt2D::ValueH(double const xp[], double const* Par)
659{
660 double x = xp[0] - _x0_;
661 double y = xp[1] - _y0_;
662
663 double z2,X,Y,D;
664 double SPSF = 0.;
665 for(int i=0; i<nd2d; i++) {
666 X = (x+dx2d[i])/_sigx_;
667 Y = (y+dy2d[i])/_sigy_;
668 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
669 D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
670 SPSF += w2d[i] / D;
671 }
672 return Par[0] *SPSF + Par[6];
673}
674
675double GdlRhInt2D::VolPSF(double const* Par)
676{
677 return _sigx_*_sigy_/(KB4B6*sqrt(1.-_rho_*_rho_));
678}
679
680double GdlRhInt2D::Val_Der(double const xp[], double const* Par
681 , double *DgDpar)
682{
683 for(int i=0; i<=6; i++) DgDpar[i] = 0.;
684 double unmr2 = 1.-_rho_*_rho_;
685 double N = KB4B6*sqrt(unmr2)/(_sigx_*_sigy_);
686 double x = xp[0] - _x0_;
687 double y = xp[1] - _y0_;
688
689 double z2,PSF,X,Y,XmrY,YmrX,D,dDsD;
690 double SPSF = 0.;
691 {
692 for(int i=0; i<nd2d; i++) {
693 X = (x+dx2d[i])/_sigx_;
694 Y = (y+dy2d[i])/_sigy_;
695 XmrY = X-_rho_*Y;
696 YmrX = Y-_rho_*X;
697 z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
698 D = 1.+z2*(1.+z2*(B4/2.+B6/6.*z2));
699 dDsD = (1.+z2*(B4+B6/2.*z2))/D;
700 /* g(x,y) */
701 PSF = N / D * w2d[i];
702 SPSF += PSF;
703 /* dg(x,y)/d(x0) */
704 DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
705 /* dg(x,y)/d(y0) */
706 DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
707 /* dg(x,y)/d(sx)*/
708 DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
709 /* dg(x,y)/d(sy) */
710 DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
711 /* dg(x,y)/d(rho) */
712 DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
713 }
714 }
715 /* dg(x,y)/d(Vol) */
716 DgDpar[0] = SPSF;
717 /* dg(x,y)/d(Fond) */
718 DgDpar[6] = 1.;
719
720 return Par[0] *SPSF + Par[6];
721}
722
723void GdlRhInt2D::DefaultParam(double *parm)
724{
725 for (int i=0; i<mNPar; i++) parm[i] = 0.;
726 parm[3] = parm[4] = 1.; // Sigx Sigy
727}
728
729#undef B4
730#undef B6
731#undef KB4B6
732
733/////////////////////////////////////////////////////////////////
734//++
735// Titre Gdl1Rho2D
736// \index{Gdl1Rho2D}
737//
738//| Cette fonction calcule une gaussienne 2D approchee
739//| par son developpement limite au 2sd ordre (see dophot)
740//| Meme commentaire que GauRho2D, cf plus haut sauf que:
741//| z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
742//| PSF(x,y) = N / [ 1 + z**2 + B4/2 *z**4 ]
743//| Le coefficient B4 est fitte (6ieme parametres)
744//| ATTENTION: les normalisations N dependent de B4
745//| 1-/ B4 est suppose etre toujours positif pour que la PSF tendent
746//| vers 0+ quand z2 tend vers l'infini
747//| 2-/ Il y a 3 cas de calcul de K(B4) = int(PSF(x,y)) de 0 a l'infini
748//| 0<B4<1/2, 1/2<B4, et B4=1/2
749//| mais pour des raisons d'analyse
750//| numerique j'ai pris 3 intervalles:
751//| 0.<B4<0.499, 0.501<B4, 0.499<=B4<=0.501
752//| dans le 3ieme intervalle, comme K est continue est derivable
753//| en B4=1/2, j'ai represente K par la droite tangeante
754//| ce qui, apres verification dans paw est une tres bonne approx.
755//| (je tiens les calculs a disposition.. me demander)
756//| Par [0]=vol [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho [6]=B4 [7]=fond
757//| F(x,y) = Par[0]*PSF(x,y)+Par[7]
758//--
759/////////////////////////////////////////////////////////////////
760
761//++
762Gdl1Rho2D::Gdl1Rho2D()
763//
764// Createur
765//--
766: GeneralPSF2D(8)
767{
768}
769
770Gdl1Rho2D::~Gdl1Rho2D()
771{
772}
773
774double Gdl1Rho2D::Value(double const xp[], double const* Par)
775{
776 double K,W,V,dKdB4;
777 if ( 0. < _B4_ && _B4_ < 0.499 ) {
778 V = 1.-2.*_B4_;
779 W = sqrt(V);
780 K = -log( (1.-W)/(1.+W) )/W;
781 dKdB4 = ( K-2./(1.-V) )/V;
782 } else if ( 0.501 < _B4_ ) {
783 V = 1./(2.*_B4_-1.);
784 W = sqrt(V);
785 K = 2.*W*( Pi/2.-atan(W) );
786 dKdB4 = V*( 2.*V/(1.+V) - K );
787 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
788 dKdB4 = -4./3.;
789 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
790 } else {
791 return(0.);
792 }
793 double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
794
795 double X = (xp[0] - _x0_)/_sigx_;
796 double Y = (xp[1] - _y0_)/_sigy_;
797 double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
798 double D = 1.+z2*(1.+z2*_B4_/2.);
799 return Par[0] *N/D + Par[7];
800}
801
802double Gdl1Rho2D::ValueH(double const xp[], double const* Par)
803{
804 double X = (xp[0] - _x0_)/_sigx_;
805 double Y = (xp[1] - _y0_)/_sigy_;
806 double z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
807 double D = 1.+z2*(1.+z2*_B4_/2.);
808 return Par[0] /D + Par[7];
809}
810
811double Gdl1Rho2D::VolPSF(double const* Par)
812{
813 double K,W,V,dKdB4;
814 if ( 0. < _B4_ && _B4_ < 0.499 ) {
815 V = 1.-2.*_B4_;
816 W = sqrt(V);
817 K = -log( (1.-W)/(1.+W) )/W;
818 dKdB4 = ( K-2./(1.-V) )/V;
819 } else if ( 0.501 < _B4_ ) {
820 V = 1./(2.*_B4_-1.);
821 W = sqrt(V);
822 K = 2.*W*( Pi/2.-atan(W) );
823 dKdB4 = V*( 2.*V/(1.+V) - K );
824 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
825 dKdB4 = -4./3.;
826 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
827 } else {
828 return(0.);
829 }
830 double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
831 return 1./N;
832}
833
834double Gdl1Rho2D::Val_Der(double const xp[], double const* Par
835 , double *DgDpar)
836{
837 double K,W,V,dKdB4;
838 if ( 0. < _B4_ && _B4_ < 0.499 ) {
839 V = 1.-2.*_B4_;
840 W = sqrt(V);
841 K = -log( (1.-W)/(1.+W) )/W;
842 dKdB4 = ( K-2./(1.-V) )/V;
843 } else if ( 0.501 < _B4_ ) {
844 V = 1./(2.*_B4_-1.);
845 W = sqrt(V);
846 K = 2.*W*( Pi/2.-atan(W) );
847 dKdB4 = V*( 2.*V/(1.+V) - K );
848 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
849 dKdB4 = -4./3.;
850 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
851 } else {
852 for(int i=0;i<=7;i++) DgDpar[i] = 0.;
853 return(0.);
854 }
855 double unmr2 = 1.-_rho_*_rho_;
856 double N = sqrt(unmr2)/(_sigx_*_sigy_*DeuxPi*K);
857
858 double X = (xp[0] - _x0_)/_sigx_;
859 double Y = (xp[1] - _y0_)/_sigy_;
860 double XmrY = X-_rho_*Y;
861 double YmrX = Y-_rho_*X;
862 double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
863 double D = 1.+z2*(1.+z2*_B4_/2.);
864 double dDsD = (1.+z2*_B4_)/D;
865
866 /* g(x,y) */
867 double PSF = N / D;
868 /* dg(x,y)/d(x0) */
869 DgDpar[1] = Par[0]* PSF* dDsD*XmrY/_sigx_;
870 /* dg(x,y)/d(y0) */
871 DgDpar[2] = Par[0]* PSF* dDsD*YmrX/_sigy_;
872 /* dg(x,y)/d(sx)*/
873 DgDpar[3] = Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
874 /* dg(x,y)/d(sy) */
875 DgDpar[4] = Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
876 /* dg(x,y)/d(rho) */
877 DgDpar[5] = Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
878 /* dg(x,y)/d(B4) */
879 DgDpar[6] = Par[0]* PSF* (-dKdB4/K-z2*z2/2./D);
880 /* dg(x,y)/d(Vol) */
881 DgDpar[0] = PSF;
882 /* dg(x,y)/d(Fond) */
883 DgDpar[7] = 1.;
884
885 return Par[0] *PSF + Par[7];
886}
887
888void Gdl1Rho2D::DefaultParam(double *parm)
889{
890 for (int i=0; i<mNPar; i++) parm[i] = 0.;
891 parm[3] = parm[4] = 1.; // Sigx Sigy
892 parm[6] = 1.;
893}
894
895/////////////////////////////////////////////////////////////////
896//++
897// Titre Gdl1RhInt2D
898// \index{Gdl1RhInt2D}
899//
900// fonction integree de Gdl1Rho2D
901//--
902/////////////////////////////////////////////////////////////////
903
904//++
905Gdl1RhInt2D::Gdl1RhInt2D()
906//
907// Createur
908//--
909: GeneralPSF2D(8)
910{
911}
912
913Gdl1RhInt2D::~Gdl1RhInt2D()
914{
915}
916
917double Gdl1RhInt2D::Value(double const xp[], double const* Par)
918{
919 double K,W,V,dKdB4;
920 if ( 0. < _B4_ && _B4_ < 0.499 ) {
921 V = 1.-2.*_B4_;
922 W = sqrt(V);
923 K = -log( (1.-W)/(1.+W) )/W;
924 dKdB4 = ( K-2./(1.-V) )/V;
925 } else if ( 0.501 < _B4_ ) {
926 V = 1./(2.*_B4_-1.);
927 W = sqrt(V);
928 K = 2.*W*( Pi/2.-atan(W) );
929 dKdB4 = V*( 2.*V/(1.+V) - K );
930 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
931 dKdB4 = -4./3.;
932 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
933 } else {
934 return(0.);
935 }
936 double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
937
938 double x = xp[0] - _x0_;
939 double y = xp[1] - _y0_;
940 double SPSF=0.;
941 double z2,X,Y,D;
942 for(int i=0; i<nd2d; i++) {
943 X = (x+dx2d[i])/_sigx_;
944 Y = (y+dy2d[i])/_sigy_;
945 z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
946 D = 1.+z2*(1.+z2*_B4_/2.);
947 SPSF += w2d[i] / D;
948 }
949 return Par[0] *N*SPSF + Par[7];
950}
951
952double Gdl1RhInt2D::ValueH(double const xp[], double const* Par)
953{
954 double x = xp[0] - _x0_;
955 double y = xp[1] - _y0_;
956 double SPSF=0.;
957 double z2,X,Y,D;
958 for(int i=0; i<nd2d; i++) {
959 X = (x+dx2d[i])/_sigx_;
960 Y = (y+dy2d[i])/_sigy_;
961 z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
962 D = 1.+z2*(1.+z2*_B4_/2.);
963 SPSF += w2d[i] / D;
964 }
965 return Par[0] *SPSF + Par[7];
966}
967
968double Gdl1RhInt2D::VolPSF(double const* Par)
969{
970 double K,W,V,dKdB4;
971 if ( 0. < _B4_ && _B4_ < 0.499 ) {
972 V = 1.-2.*_B4_;
973 W = sqrt(V);
974 K = -log( (1.-W)/(1.+W) )/W;
975 dKdB4 = ( K-2./(1.-V) )/V;
976 } else if ( 0.501 < _B4_ ) {
977 V = 1./(2.*_B4_-1.);
978 W = sqrt(V);
979 K = 2.*W*( Pi/2.-atan(W) );
980 dKdB4 = V*( 2.*V/(1.+V) - K );
981 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
982 dKdB4 = -4./3.;
983 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
984 } else {
985 return(0.);
986 }
987 double N = sqrt(1.-_rho_*_rho_)/(_sigx_*_sigy_*DeuxPi*K);
988 return 1./N;
989}
990
991double Gdl1RhInt2D::Val_Der(double const xp[], double const* Par
992 , double *DgDpar)
993{
994 for(int i=0; i<7; i++) DgDpar[i] = 0.;
995
996 double K,W,V,dKdB4;
997 if ( 0. < _B4_ && _B4_ < 0.499 ) {
998 V = 1.-2.*_B4_;
999 W = sqrt(V);
1000 K = -log( (1.-W)/(1.+W) )/W;
1001 dKdB4 = ( K-2./(1.-V) )/V;
1002 } else if ( 0.501 < _B4_ ) {
1003 V = 1./(2.*_B4_-1.);
1004 W = sqrt(V);
1005 K = 2.*W*( Pi/2.-atan(W) );
1006 dKdB4 = V*( 2.*V/(1.+V) - K );
1007 } else if ( 0.499 <= _B4_ && _B4_ <= 0.501 ) {
1008 dKdB4 = -4./3.;
1009 K = dKdB4 * ( _B4_ - 0.5 ) + 2.;
1010 } else {
1011 return(0.);
1012 }
1013 double unmr2 = 1.-_rho_*_rho_;
1014 double N = sqrt(unmr2)/(_sigx_*_sigy_*DeuxPi*K);
1015
1016 double x = xp[0] - _x0_;
1017 double y = xp[1] - _y0_;
1018 double z2,PSF,X,Y,XmrY,YmrX,D,dDsD;
1019 double SPSF=0.;
1020 {for(int i=0; i<nd2d; i++) {
1021 X = (x+dx2d[i])/_sigx_;
1022 Y = (y+dy2d[i])/_sigy_;
1023 XmrY = X-_rho_*Y;
1024 YmrX = Y-_rho_*X;
1025 z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
1026 D = 1.+z2*(1.+z2*_B4_/2.);
1027 dDsD = (1.+z2*_B4_)/D;
1028 /* dg(x,y) */
1029 PSF = N / D * w2d[i];
1030 SPSF += PSF;
1031 /* dg(x,y)/d(x0) */
1032 DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
1033 /* dg(x,y)/d(y0) */
1034 DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
1035 /* dg(x,y)/d(sx)*/
1036 DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
1037 /* dg(x,y)/d(sy) */
1038 DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
1039 /* dg(x,y)/d(rho) */
1040 DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
1041 /* dg(x,y)/d(B4) */
1042 DgDpar[6] += Par[0]* PSF* (-dKdB4/K-z2*z2/2./D);
1043 }}
1044 /* dg(x,y)/d(Vol) */
1045 DgDpar[0] = SPSF;
1046 /* dg(x,y)/d(Fond) */
1047 DgDpar[7] = 1.;
1048
1049 return Par[0] *SPSF + Par[7];
1050}
1051
1052void Gdl1RhInt2D::DefaultParam(double *parm)
1053{
1054 for (int i=0; i<mNPar; i++) parm[i] = 0.;
1055 parm[3] = parm[4] = 1.; // Sigx Sigy
1056 parm[6] = 1.;
1057}
1058
1059/////////////////////////////////////////////////////////////////
1060//++
1061// Titre Gdl2Rho2D
1062// \index{Gdl2Rho2D}
1063//
1064//| Cette fonction calcule une gaussienne 2D de hauteur 1 approchee
1065//| par son developpement limite ordre 3 (see dophot)
1066//| Meme commentaire que GauRho2D, cf plus haut sauf que:
1067//| z**2 = 1/2 (X**2 + Y**2 -2*rho*X*Y)
1068//| Z**2 = B2*z2
1069//| PSF(x,y) = h / [ 1 + Z**2 + B4**2/2 *Z**4 + B6**2/6 *Z**6 ]
1070//| B2,B4,B6 peuvent etre fittes
1071//| - DL de la gaussienne: B2=B4=B6=1.
1072//| Par [0]=hauteur [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho
1073//| [6]=B4 [7]=B6 [8]=B2 [9]= fond
1074//| F(x,y) = Par[0]*PSF(x,y)+Par[9]
1075//--
1076/////////////////////////////////////////////////////////////////
1077
1078
1079//++
1080Gdl2Rho2D::Gdl2Rho2D()
1081//
1082// Createur
1083//--
1084: GeneralPSF2D(10)
1085{
1086}
1087
1088Gdl2Rho2D::~Gdl2Rho2D()
1089{
1090}
1091
1092double Gdl2Rho2D::Value(double const xp[], double const* Par)
1093{
1094 double X = (xp[0]-_x0_)/_sigx_;
1095 double Y = (xp[1]-_y0_)/_sigy_;
1096 double z2 = (X*X + Y*Y - 2*_rho_*X*Y)/2.;
1097 double Z2 = _B2_ * _B2_ * z2;
1098 double Z4 = Z2*Z2;
1099 double Z6 = Z4*Z2;
1100 double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1101 return Par[0] /D + Par[9];
1102}
1103
1104double Gdl2Rho2D::ValueH(double const xp[], double const* Par)
1105{
1106 double X = (xp[0]-_x0_)/_sigx_;
1107 double Y = (xp[1]-_y0_)/_sigy_;
1108 double z2 = (X*X + Y*Y - 2*_rho_*X*Y)/2.;
1109 double Z2 = _B2_ * _B2_ * z2;
1110 double Z4 = Z2*Z2;
1111 double Z6 = Z4*Z2;
1112 double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1113 return Par[0] /D + Par[9];
1114}
1115
1116double Gdl2Rho2D::Val_Der(double const xp[], double const* Par
1117 , double *DgDpar)
1118{
1119 double unmr2 = 1.-_rho_*_rho_;
1120 double X = (xp[0]-_x0_)/_sigx_;
1121 double Y = (xp[1]-_y0_)/_sigy_;
1122 double XmrY = X-_rho_*Y;
1123 double YmrX = Y-_rho_*X;
1124 double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
1125 double Z2 = _B2_ * _B2_ * z2;
1126 double Z4 = Z2*Z2;
1127 double Z6 = Z4*Z2;
1128 double D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1129 double dDsDB2 = (1. + _B4_*_B4_*Z2 + _B6_*_B6_/2.*Z4 )/D;
1130 double dDsD = _B2_*_B2_ * dDsDB2;
1131 /* g(x,y) */
1132 double PSF = 1. / D;
1133 /* dg(x,y)/d(x0) */
1134 DgDpar[1] = Par[0]* PSF* dDsD*XmrY/_sigx_;
1135 /* dg(x,y)/d(y0) */
1136 DgDpar[2] = Par[0]* PSF* dDsD*YmrX/_sigy_;
1137 /* dg(x,y)/d(sx)*/
1138 DgDpar[3] = Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
1139 /* dg(x,y)/d(sy) */
1140 DgDpar[4] = Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
1141 /* dg(x,y)/d(rho) */
1142 DgDpar[5] = Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
1143 /* dg(x,y)/d(B4) */
1144 DgDpar[6] = Par[0]* PSF* (-_B4_*Z4/D);
1145 /* dg(x,y)/d(B6) */
1146 DgDpar[7] = Par[0]* PSF* (-_B6_*Z6/3./D);
1147 /* dg(x,y)/d(B2) */
1148 DgDpar[8] = Par[0]* PSF* (-2.*_B2_*z2*dDsDB2);
1149 /* dg(x,y)/d(hauteur) */
1150 DgDpar[0] = PSF;
1151 /* dg(x,y)/d(Fond) */
1152 DgDpar[9] = 1.;
1153
1154 return Par[0] *PSF + Par[9];
1155}
1156
1157void Gdl2Rho2D::DefaultParam(double *parm)
1158{
1159 for (int i=0; i<mNPar; i++) parm[i] = 0.;
1160 parm[3] = parm[4] = 1.; // Sigx Sigy
1161 parm[6] = parm[7] = parm[8] = 1.;
1162}
1163
1164/////////////////////////////////////////////////////////////////
1165//++
1166// Titre Gdl2RhInt2D
1167// \index{Gdl2RhInt2D}
1168//
1169// fonction integree de Gdl2Rho2d
1170//--
1171/////////////////////////////////////////////////////////////////
1172
1173//++
1174Gdl2RhInt2D::Gdl2RhInt2D()
1175//
1176// Createur
1177//--
1178: GeneralPSF2D(10)
1179{
1180}
1181
1182Gdl2RhInt2D::~Gdl2RhInt2D()
1183{
1184}
1185
1186double Gdl2RhInt2D::Value(double const xp[], double const* Par)
1187{
1188 double x = xp[0] - _x0_;
1189 double y = xp[1] - _y0_;
1190 double SPSF=0.;
1191 double X,Y,z2,Z2,Z4,Z6,D;
1192 for(int i=0; i<nd2d; i++) {
1193 X = (x+dx2d[i])/_sigx_;
1194 Y = (y+dy2d[i])/_sigy_;
1195 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
1196 Z2 = _B2_ * _B2_ * z2;
1197 Z4 = Z2*Z2;
1198 Z6 = Z4*Z2;
1199 D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1200 /* g(x,y) */
1201 SPSF += w2d[i] / D;
1202 }
1203 return Par[0] *SPSF + Par[9];
1204}
1205
1206double Gdl2RhInt2D::ValueH(double const xp[], double const* Par)
1207{
1208 double x = xp[0] - _x0_;
1209 double y = xp[1] - _y0_;
1210 double SPSF=0.;
1211 double X,Y,z2,Z2,Z4,Z6,D;
1212 for(int i=0; i<nd2d; i++) {
1213 X = (x+dx2d[i])/_sigx_;
1214 Y = (y+dy2d[i])/_sigy_;
1215 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
1216 Z2 = _B2_ * _B2_ * z2;
1217 Z4 = Z2*Z2;
1218 Z6 = Z4*Z2;
1219 D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1220 /* g(x,y) */
1221 SPSF += w2d[i] / D;
1222 }
1223 return Par[0] *SPSF + Par[9];
1224}
1225
1226double Gdl2RhInt2D::Val_Der(double const xp[], double const* Par
1227 , double *DgDpar)
1228{
1229 for(int i=0; i<=9; i++) DgDpar[i] = 0.;
1230
1231 double unmr2 = 1.-_rho_*_rho_;
1232 double x = xp[0] - _x0_;
1233 double y = xp[1] - _y0_;
1234 double SPSF=0.;
1235 double X,Y,XmrY,YmrX,z2,Z2,Z4,Z6,D,dDsD,dDsDB2,PSF;
1236 {for(int i=0; i<nd2d; i++) {
1237 X = (x+dx2d[i])/_sigx_;
1238 Y = (y+dy2d[i])/_sigy_;
1239 XmrY = X-_rho_*Y;
1240 YmrX = Y-_rho_*X;
1241 z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
1242 Z2 = _B2_ * _B2_ * z2;
1243 Z4 = Z2*Z2;
1244 Z6 = Z4*Z2;
1245 D = 1. + Z2 + _B4_*_B4_/2.*Z4 + _B6_*_B6_/6.*Z6;
1246 dDsDB2 = (1. + _B4_*_B4_*Z2 + _B6_*_B6_/2.*Z4 )/D;
1247 dDsD = _B2_*_B2_ * dDsDB2;
1248 /* dg(x,y) */
1249 PSF = w2d[i] / D;
1250 SPSF += PSF;
1251 /* dg(x,y)/d(x0) */
1252 DgDpar[1] += Par[0]* PSF* dDsD*XmrY/_sigx_;
1253 /* dg(x,y)/d(y0) */
1254 DgDpar[2] += Par[0]* PSF* dDsD*YmrX/_sigy_;
1255 /* dg(x,y)/d(sx)*/
1256 DgDpar[3] += Par[0]* PSF* (dDsD*X*XmrY-1.)/_sigx_;
1257 /* dg(x,y)/d(sy) */
1258 DgDpar[4] += Par[0]* PSF* (dDsD*Y*YmrX-1.)/_sigy_;
1259 /* dg(x,y)/d(rho) */
1260 DgDpar[5] += Par[0]* PSF* (dDsD*X*Y-2.*_rho_/unmr2);
1261 /* dg(x,y)/d(B4) */
1262 DgDpar[6] += Par[0]* PSF* (-_B4_*Z4/D);
1263 /* dg(x,y)/d(B6) */
1264 DgDpar[7] += Par[0]* PSF* (-_B6_*Z6/3./D);
1265 /* dg(x,y)/d(B2) */
1266 DgDpar[8] += Par[0]* PSF* (-2.*_B2_*z2*dDsDB2);
1267 }}
1268 /* dg(x,y)/d(hauteur) */
1269 DgDpar[0] = SPSF;
1270 /* dg(x,y)/d(Fond) */
1271 DgDpar[9] = 1.;
1272
1273 return Par[0] *SPSF + Par[9];
1274}
1275
1276void Gdl2RhInt2D::DefaultParam(double *parm)
1277{
1278 for (int i=0; i<mNPar; i++) parm[i] = 0.;
1279 parm[3] = parm[4] = 1.; // Sigx Sigy
1280 parm[6] = parm[7] = parm[8] = 1.;
1281}
1282
1283/////////////////////////////////////////////////////////////////
1284//++
1285// Titre MofRho2D
1286// \index{MofRho2D}
1287//
1288//| Cette fonction calcule une Moffat 2D
1289//| Par [0]=hauteur [1]=x0 [2]=y0 [3]=sigx [4]=sigy [5]=rho
1290//| [6]=Gm [7]= fond
1291//| PSF(x,y) = valeur de la Moffat normalisee a un volume = 1
1292//| PSF(x,y) = N / [ 1. + 0.5*(X**2 + Y**2 -2*rho*X*Y) ]**Gm
1293//| avec X = (x-x0)/sigx et Y = (y-y0)/sigy et Gm>1
1294//| N = (1-Gm)*sqrt(1-rho**2)/(2*Pi*sigx*sigy)
1295//| le volume de cette Moffat est V=1.
1296//| F(x,y) = Par[0]*PSF(x,y)+Par[7]
1297//--
1298/////////////////////////////////////////////////////////////////
1299
1300//++
1301MofRho2D::MofRho2D()
1302//
1303// Createur
1304//--
1305: GeneralPSF2D(8)
1306{
1307}
1308
1309MofRho2D::~MofRho2D()
1310{
1311}
1312
1313double MofRho2D::Value(double const xp[], double const* Par)
1314{
1315 double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
1316 double X = (xp[0] - _x0_)/_sigx_;
1317 double Y = (xp[1] - _y0_)/_sigy_;
1318 double z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
1319 z2 = _Gm_*log(1. + z2);
1320 if( z2<MINEXPM ) return Par[0] *N*EXPO(-z2) + Par[7];
1321 else return Par[7];
1322}
1323
1324double MofRho2D::ValueH(double const xp[], double const* Par)
1325{
1326 double X = (xp[0] - _x0_)/_sigx_;
1327 double Y = (xp[1] - _y0_)/_sigy_;
1328 double z2 = (X*X + Y*Y -2.*_rho_*X*Y)/2.;
1329 z2 = _Gm_*log(1. + z2);
1330 if( z2<MINEXPM ) return Par[0] *EXPO(-z2) + Par[7];
1331 else return Par[7];
1332}
1333
1334double MofRho2D::VolPSF(double const* Par)
1335{
1336 double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
1337 return 1./N;
1338}
1339
1340double MofRho2D::Val_Der(double const xp[], double const* Par
1341 , double *DgDpar)
1342{
1343 double unmr2 = 1.-_rho_*_rho_;
1344 double N = (_Gm_-1.)*sqrt(unmr2)/DeuxPi/_sigx_/_sigy_;
1345 double X = (xp[0] - _x0_)/_sigx_;
1346 double Y = (xp[1] - _y0_)/_sigy_;
1347 double XmrY = X-_rho_*Y;
1348 double YmrX = Y-_rho_*X;
1349 double z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
1350 double D = 1. + z2;
1351 double lD = log(D);
1352 /* g(x,y) */
1353 double PSF = _Gm_*lD;
1354 if( PSF<MINEXPM ) PSF = N * EXPO(-PSF); else PSF = 0.;
1355 /* dg(x,y)/d(x0) */
1356 DgDpar[1] = Par[0]* PSF* XmrY/_sigx_ * _Gm_/D;
1357 /* dg(x,y)/d(y0) */
1358 DgDpar[2] = Par[0]* PSF* YmrX/_sigy_ * _Gm_/D;
1359 /* dg(x,y)/d(sx)*/
1360 DgDpar[3] = Par[0]* PSF* (X*XmrY*_Gm_/D - 1.)/_sigx_;
1361 /* dg(x,y)/d(sy) */
1362 DgDpar[4] = Par[0]* PSF* (Y*YmrX*_Gm_/D - 1.)/_sigy_;
1363 /* dg(x,y)/d(rho) */
1364 DgDpar[5] = Par[0]* PSF* (X*Y*_Gm_/D - 2.*_rho_/unmr2);
1365 /* dg(x,y)/d(Gm) */
1366 DgDpar[6] = Par[0]* PSF* (1./(_Gm_-1.) - lD);
1367 /* dg(x,y)/d(Vol) */
1368 DgDpar[0] = PSF;
1369 /* dg(x,y)/d(Fond) */
1370 DgDpar[7] = 1.;
1371
1372 return Par[0] *PSF + Par[7];
1373}
1374
1375void MofRho2D::DefaultParam(double *parm)
1376{
1377 for (int i=0; i<mNPar; i++) parm[i] = 0.;
1378 parm[3] = parm[4] = 1.; // Sigx Sigy
1379 parm[6] = 3.;
1380}
1381
1382/////////////////////////////////////////////////////////////////
1383//++
1384// Titre MofRhInt2D
1385// \index{MofRhInt2D}
1386//
1387// fonction integree de MofRho2d
1388//--
1389/////////////////////////////////////////////////////////////////
1390
1391//++
1392MofRhInt2D::MofRhInt2D()
1393//
1394// Createur
1395//--
1396: GeneralPSF2D(8)
1397{
1398}
1399
1400MofRhInt2D::~MofRhInt2D()
1401{
1402}
1403
1404double MofRhInt2D::Value(double const xp[], double const* Par)
1405{
1406 double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
1407 double x = xp[0] - _x0_;
1408 double y = xp[1] - _y0_;
1409 double SPSF = 0.;
1410 double z2,X,Y;
1411 for(int i=0; i<nd2d; i++) {
1412 X = (x+dx2d[i])/_sigx_;
1413 Y = (y+dy2d[i])/_sigy_;
1414 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
1415 /* g(x,y) */
1416 z2 = _Gm_*log(1. + z2);
1417 if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
1418 }
1419 return Par[0] * N*SPSF + Par[7];
1420}
1421
1422double MofRhInt2D::ValueH(double const xp[], double const* Par)
1423{
1424 double x = xp[0] - _x0_;
1425 double y = xp[1] - _y0_;
1426 double SPSF = 0.;
1427 double z2,X,Y;
1428 for(int i=0; i<nd2d; i++) {
1429 X = (x+dx2d[i])/_sigx_;
1430 Y = (y+dy2d[i])/_sigy_;
1431 z2 = (X*X + Y*Y - 2.*_rho_*X*Y)/2.;
1432 /* g(x,y) */
1433 z2 = _Gm_*log(1. + z2);
1434 if( z2<MINEXPM ) SPSF += EXPO(-z2) * w2d[i];
1435 }
1436 return Par[0] *SPSF + Par[7];
1437}
1438
1439double MofRhInt2D::VolPSF(double const* Par)
1440{
1441 double N = (_Gm_-1.)*sqrt(1.-_rho_*_rho_)/(DeuxPi*_sigx_*_sigy_);
1442 return 1./N;
1443}
1444
1445double MofRhInt2D::Val_Der(double const xp[], double const* Par
1446 , double *DgDpar)
1447{
1448 for(int i=0; i<=7; i++) DgDpar[i] = 0.;
1449
1450 double unmr2 = 1.-_rho_*_rho_;
1451 double N = (_Gm_-1.)*sqrt(unmr2)/(DeuxPi*_sigx_*_sigy_);
1452 double x = xp[0] - _x0_;
1453 double y = xp[1] - _y0_;
1454 double SPSF = 0.;
1455 double X,Y,XmrY,YmrX,z2,D,lD,PSF;
1456 {for(int i=0; i<nd2d; i++) {
1457 X = (x+dx2d[i])/_sigx_;
1458 Y = (y+dy2d[i])/_sigy_;
1459 XmrY = X-_rho_*Y;
1460 YmrX = Y-_rho_*X;
1461 z2 = (X*(XmrY-_rho_*Y)+Y*Y)/2.;
1462 D = 1. + z2;
1463 lD = log(D);
1464 /* g(x,y) */
1465 PSF = _Gm_*lD;
1466 if( PSF<MINEXPM ) PSF = N * EXPO(-PSF) * w2d[i]; else PSF = 0.;
1467 SPSF += PSF;
1468 /* dg(x,y)/d(x0) */
1469 DgDpar[1] += Par[0]* PSF* XmrY/_sigx_ * _Gm_/D;
1470 /* dg(x,y)/d(y0) */
1471 DgDpar[2] += Par[0]* PSF* YmrX/_sigy_ * _Gm_/D;
1472 /* dg(x,y)/d(sx)*/
1473 DgDpar[3] += Par[0]* PSF* (X*XmrY*_Gm_/D - 1.)/_sigx_;
1474 /* dg(x,y)/d(sy) */
1475 DgDpar[4] += Par[0]* PSF* (Y*YmrX*_Gm_/D - 1.)/_sigy_;
1476 /* dg(x,y)/d(rho) */
1477 DgDpar[5] += Par[0]* PSF* (X*Y*_Gm_/D - 2.*_rho_/unmr2);
1478 /* dg(x,y)/d(Gm) */
1479 DgDpar[6] += Par[0]* PSF* (1./(_Gm_-1.) - lD);
1480 }}
1481 /* dg(x,y)/d(Vol) */
1482 DgDpar[0] = SPSF;
1483 /* dg(x,y)/d(Fond) */
1484 DgDpar[7] = 1.;
1485
1486 return Par[0] *SPSF + Par[7];
1487}
1488
1489void MofRhInt2D::DefaultParam(double *parm)
1490{
1491 for (int i=0; i<mNPar; i++) parm[i] = 0.;
1492 parm[3] = parm[4] = 1.; // Sigx Sigy
1493 parm[6] = 3.;
1494}
1495
1496
1497#undef _sigx_
1498#undef _sigy_
1499#undef _rho_
1500#undef _x0_
1501#undef _y0_
1502#undef _Gm_
1503#undef _B4_
1504#undef _B6_
1505#undef _B2_
1506
1507//==============================================================================
1508// CLASSES DE FONCTIONS 2D type Xi2 AVEC PARAMETRES POUR LE FIT pixel taille 1x1
1509// la taille du pixel est importante quand on utilise les PSF integrees
1510// (x,y x0,y0 sigmaX.... sont en unites de pixels !!!)
1511//==============================================================================
1512
1513/////////////////////////////////////////////////////////////////
1514//++
1515// Titre X2-GauRho2D
1516// \index{X2-GauRho2D}
1517//
1518// Chi2 pour une Gaussienne+fond 2D (voir detail dans GauRho2D).
1519//--
1520/////////////////////////////////////////////////////////////////
1521
1522//++
1523// X2-GauRho2D::X2-GauRho2D()
1524// Createur
1525//--
1526X2_GauRho2D::X2_GauRho2D()
1527: GeneralXi2(7)
1528{
1529 gaurho2d = new GauRho2D;
1530}
1531
1532X2_GauRho2D::~X2_GauRho2D()
1533{
1534 delete gaurho2d;
1535}
1536
1537double X2_GauRho2D::Value(GeneralFitData& data, double* parm, int& ndataused)
1538{
1539 ASSERT( data.NVar()==2 );
1540 double x[2],z;
1541
1542 double c2 = 0.;
1543 ndataused = 0;
1544 for(int k=0;k<data.NData();k++) {
1545 if( ! data.IsValid(k) ) continue;
1546 x[0] = data.X(k); x[1] = data.Y(k);
1547 z = (data.Val(k)-gaurho2d->Value(x,parm))/data.EVal(k);
1548 c2 += z*z;
1549 ndataused++;
1550 }
1551 return c2;
1552}
1553
1554double X2_GauRho2D::Derivee2(GeneralFitData& data, int i,int j, double* parm)
1555{
1556 ASSERT( data.NVar()==2 && i<7 && j<7);
1557 double x[2],dparm[7];
1558
1559 double d2c2 = 0.;
1560 for(int k=0;k<data.NData();k++) {
1561 if( ! data.IsValid(k) ) continue;
1562 x[0] = data.X(k); x[1] = data.Y(k);
1563 gaurho2d->Val_Der(x,parm,dparm);
1564 d2c2 += 2.*dparm[i]*dparm[j]/(data.EVal(k)*data.EVal(k));
1565 }
1566 return d2c2;
1567}
Note: See TracBrowser for help on using the repository browser.