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

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

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

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