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

Last change on this file since 2423 was 2322, checked in by cmv, 23 years ago
  • passage xxstream.h en xxstream
  • compile avec gcc_3.2, gcc_2.96 et cxx En 3.2 le seek from ::end semble marcher (voir Eval/COS/pbseekios.cc)

rz+cmv 11/2/2003

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