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

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

Merge avec PEIDA++ (~V 3.8) et nettoyage pour nouveau PPersist Reza+cmv 21/10/99

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