public software.sextractor

[/] [branches/] [multi/] [src/] [psf.c] - Blame information for rev 285

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 233 bertin
/*
2
*                               psf.c
3 2 bertin
*
4 233 bertin
* Fit a PSF model to an image.
5 2 bertin
*
6 233 bertin
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 2 bertin
*
8 233 bertin
*       This file part of:      SExtractor
9 2 bertin
*
10 282 bertin
*       Copyright:              (C) 1998-2012 Emmanuel Bertin -- IAP/CNRS/UPMC
11 2 bertin
*
12 233 bertin
*       License:                GNU General Public License
13
*
14
*       SExtractor is free software: you can redistribute it and/or modify
15
*       it under the terms of the GNU General Public License as published by
16
*       the Free Software Foundation, either version 3 of the License, or
17
*       (at your option) any later version.
18
*       SExtractor is distributed in the hope that it will be useful,
19
*       but WITHOUT ANY WARRANTY; without even the implied warranty of
20
*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
*       GNU General Public License for more details.
22
*       You should have received a copy of the GNU General Public License
23
*       along with SExtractor. If not, see <http://www.gnu.org/licenses/>.
24
*
25 285 bertin
*       Last modified:          05/05/2012
26 233 bertin
*
27
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
28 2 bertin
 
29
#ifdef HAVE_CONFIG_H
30
#include        "config.h"
31
#endif
32
 
33
#include        <math.h>
34
#include        <stdio.h>
35
#include        <stdlib.h>
36
#include        <string.h>
37
 
38
#include        "define.h"
39
#include        "globals.h"
40
#include        "prefs.h"
41
#include        "fits/fitscat.h"
42
#include        "check.h"
43 248 bertin
#include        "field.h"
44 2 bertin
#include        "filter.h"
45
#include        "image.h"
46 173 bertin
#include        "wcs/poly.h"
47 2 bertin
#include        "psf.h"
48 283 bertin
#include        "subimage.h"
49 2 bertin
 
50
/*------------------------------- variables ---------------------------------*/
51
 
52
 
53 272 bertin
extern keystruct        obj2key[];
54 2 bertin
extern objstruct        outobj;
55
 
56
/********************************* psf_init **********************************/
57
/*
58
Allocate memory and stuff for the PSF-fitting.
59
*/
60
void    psf_init(psfstruct *psf)
61
  {
62
  QMALLOC(thepsfit, psfitstruct, 1);
63 218 bertin
  QMALLOC(thepsfit->x, double, prefs.psf_npsfmax);
64
  QMALLOC(thepsfit->y, double, prefs.psf_npsfmax);
65 2 bertin
  QMALLOC(thepsfit->flux, float, prefs.psf_npsfmax);
66 218 bertin
  QMALLOC(thepsfit->fluxerr, float, prefs.psf_npsfmax);
67 5 bertin
  QMALLOC(ppsfit, psfitstruct, 1); /*?*/
68 218 bertin
  QMALLOC(ppsfit->x, double, prefs.psf_npsfmax);
69
  QMALLOC(ppsfit->y, double, prefs.psf_npsfmax);
70 5 bertin
  QMALLOC(ppsfit->flux, float, prefs.psf_npsfmax);
71 218 bertin
  QMALLOC(ppsfit->fluxerr, float, prefs.psf_npsfmax);
72 2 bertin
 
73
  return;
74
  }
75
 
76
 
77
/********************************* psf_end ***********************************/
78
/*
79
Free memory occupied by the PSF-fitting stuff.
80
*/
81 5 bertin
void    psf_end(psfstruct *psf, psfitstruct *psfit)
82 2 bertin
  {
83
   int  d, ndim;
84
 
85
  ndim = psf->poly->ndim;
86
  for (d=0; d<ndim; d++)
87
    free(psf->contextname[d]);
88
  free(psf->context);
89
  free(psf->contextname);
90
  free(psf->contextoffset);
91
  free(psf->contextscale);
92
  free(psf->contexttyp);
93
  poly_end(psf->poly);
94
  free(psf->maskcomp);
95
  free(psf->maskloc);
96
  free(psf->masksize);
97
  free(psf);
98
 
99 173 bertin
  if (psfit)
100
    {
101
    free(psfit->x);
102
    free(psfit->y);
103
    free(psfit->flux);
104 218 bertin
    free(psfit->fluxerr);
105 173 bertin
    free(psfit);
106
    }
107 2 bertin
 
108
  return;
109
  }
110
 
111
 
112
/********************************* psf_load *********************************/
113
/*
114
Read the PSF data from a FITS file.
115
*/
116
psfstruct       *psf_load(char *filename)
117
  {
118
   static obj2struct    saveobj2;
119
   psfstruct            *psf;
120
   catstruct            *cat;
121
   tabstruct            *tab;
122
   keystruct            *key;
123
   char                 *head, *ci,*co;
124
   int                  deg[POLY_MAXDIM], group[POLY_MAXDIM], ndim, ngroup,
125
                        i,k;
126
 
127
/* Open the cat (well it is not a "cat", but simply a FITS file */
128
  if (!(cat = read_cat(filename)))
129
    error(EXIT_FAILURE, "*Error*: PSF file not found: ", filename);
130
 
131
/* OK, we now allocate memory for the PSF structure itself */
132
  QCALLOC(psf, psfstruct, 1);
133
 
134
/* Store a short copy of the PSF filename */
135
  if ((ci=strrchr(filename, '/')))
136
    strcpy(psf->name, ci+1);
137
  else
138
    strcpy(psf->name, filename);
139
 
140
  if (!(tab = name_to_tab(cat, "PSF_DATA", 0)))
141
    error(EXIT_FAILURE, "*Error*: PSF_DATA table not found in catalog ",
142
        filename);
143
 
144
  head = tab->headbuf;
145
 
146
/*-- Dimension of the polynomial */
147
  if (fitsread(head, "POLNAXIS", &ndim, H_INT,T_LONG) == RETURN_OK
148
        && ndim)
149
    {
150
/*-- So we have a polynomial description of the PSF variations */
151
    if (ndim > POLY_MAXDIM)
152
        {
153
        sprintf(gstr, "*Error*: The POLNAXIS parameter in %s exceeds %d",
154
                psf->name, POLY_MAXDIM);
155
        error(EXIT_FAILURE, gstr, "");
156
        }
157
 
158
    QMALLOC(psf->contextname, char *, ndim);
159
    QMALLOC(psf->context, double *, ndim);
160
    QMALLOC(psf->contexttyp, t_type, ndim);
161
    QMALLOC(psf->contextoffset, double, ndim);
162
    QMALLOC(psf->contextscale, double, ndim);
163
 
164 267 bertin
/*-- We will have to use the flagobj2 struct, so we first save its content */
165
    saveobj2 = flagobj2;
166
/*-- flagobj2 is used as a FLAG array, so we initialize it to 0 */
167
    memset(&flagobj2, 0, sizeof(flagobj2));
168 2 bertin
    for (i=0; i<ndim; i++)
169
      {
170
/*---- Polynomial groups */
171
      sprintf(gstr, "POLGRP%1d", i+1);
172
      if (fitsread(head, gstr, &group[i], H_INT,T_LONG) != RETURN_OK)
173
        goto headerror;
174
 
175
/*---- Contexts */
176
      QMALLOC(psf->contextname[i], char, 80);
177
      sprintf(gstr, "POLNAME%1d", i+1);
178
      if (fitsread(head,gstr,psf->contextname[i],H_STRING,T_STRING)!=RETURN_OK)
179
        goto headerror;
180
      if (*psf->contextname[i]==(char)':')
181
/*------ It seems we're facing a FITS header parameter */
182
        psf->context[i] = NULL; /* This is to tell we'll have to load */
183
                                /* a FITS header context later on */
184
      else
185
/*------ The context element is a dynamic object parameter */
186
        {
187 272 bertin
        if ((k = findkey(psf->contextname[i], (char *)obj2key,
188 2 bertin
                sizeof(keystruct)))==RETURN_ERROR)
189
          {
190
          sprintf(gstr, "*Error*: %s CONTEXT parameter in %s unknown",
191
                psf->contextname[i], psf->name);
192
          error(EXIT_FAILURE, gstr, "");
193
          }
194 272 bertin
        key = obj2key+k;
195 285 bertin
        psf->context[i] = key->ptr;     /* !CHECK should depend on channel */
196 2 bertin
        psf->contexttyp[i] = key->ttype;
197
/*------ Declare the parameter "active" to trigger computation by SExtractor */
198
        *((char *)key->ptr) = (char)'\1';
199
        }
200
/*---- Scaling of the context parameter */
201
      sprintf(gstr, "POLZERO%1d", i+1);
202
      if (fitsread(head, gstr, &psf->contextoffset[i], H_EXPO, T_DOUBLE)
203
                !=RETURN_OK)
204
        goto headerror;
205
      sprintf(gstr, "POLSCAL%1d", i+1);
206
      if (fitsread(head, gstr, &psf->contextscale[i], H_EXPO, T_DOUBLE)
207
                !=RETURN_OK)
208
        goto headerror;
209
      }
210
 
211
/*-- Number of groups */
212
    if (fitsread(head, "POLNGRP ", &ngroup, H_INT, T_LONG) != RETURN_OK)
213
      goto headerror;
214
 
215
    for (i=0; i<ngroup; i++)
216
      {
217
/*---- Polynomial degree for each group */
218
      sprintf(gstr, "POLDEG%1d", i+1);
219
      if (fitsread(head, gstr, &deg[i], H_INT,T_LONG) != RETURN_OK)
220
        goto headerror;
221
      }
222
 
223
    psf->poly = poly_init(group, ndim, deg, ngroup);
224
 
225 267 bertin
/*-- Restore previous flagobj2 content */
226
    flagobj2 = saveobj2;
227 2 bertin
    }
228
  else
229
    {
230
/*-- This is a simple, constant PSF */
231
    psf->poly = poly_init(group, 0, deg, 0);
232
    psf->context = NULL;
233
    }
234
 
235
/* Dimensionality of the PSF mask */
236
  if (fitsread(head, "PSFNAXIS", &psf->maskdim, H_INT, T_LONG) != RETURN_OK)
237
    goto headerror;
238
  if (psf->maskdim<2 || psf->maskdim>3)
239
    error(EXIT_FAILURE, "*Error*: wrong dimensionality for the PSF "
240
        "mask in ", filename);
241
  QMALLOC(psf->masksize, int, psf->maskdim);
242
  for (i=0; i<psf->maskdim; i++)
243
    psf->masksize[i] = 1;
244
  psf->masknpix = 1;
245
  for (i=0; i<psf->maskdim; i++)
246
    {
247
    sprintf(gstr, "PSFAXIS%1d", i+1);
248
    if (fitsread(head, gstr, &psf->masksize[i], H_INT,T_LONG) != RETURN_OK)
249
      goto headerror;
250
    psf->masknpix *= psf->masksize[i];
251
    }
252
 
253
/* PSF FWHM: defaulted to 3 pixels */
254
 if (fitsread(head, "PSF_FWHM", &psf->fwhm, H_FLOAT,T_DOUBLE) != RETURN_OK)
255
    psf->fwhm = 3.0;
256
 
257
/* PSF oversampling: defaulted to 1 */
258 221 bertin
  if (fitsread(head, "PSF_SAMP", &psf->pixstep,H_FLOAT,T_FLOAT) != RETURN_OK
259
        || psf->pixstep <= 0.0)
260 2 bertin
    psf->pixstep = 1.0;
261
 
262
/* Load the PSF mask data */
263
  key = read_key(tab, "PSF_MASK");
264
  psf->maskcomp = key->ptr;
265
 
266 206 bertin
  QMALLOC(psf->maskloc, float, psf->masksize[0]*psf->masksize[1]);
267 2 bertin
 
268
/* But don't touch my arrays!! */
269
  blank_keys(tab);
270
 
271
  free_cat(&cat, 1);
272
 
273
  return psf;
274
 
275
headerror:
276
  error(EXIT_FAILURE, "*Error*: Incorrect or obsolete PSF data in ", filename);
277
  return NULL;
278
  }
279
 
280
 
281
/***************************** psf_readcontext *******************************/
282
/*
283
Read the PSF context parameters in the FITS header.
284
*/
285 275 bertin
void    psf_readcontext(psfstruct *psf, fieldstruct *field)
286 2 bertin
  {
287
   static double        contextval[POLY_MAXDIM];
288
   int                  i, ndim;
289
 
290
  ndim = psf->poly->ndim;
291
  for (i=0; i<ndim; i++)
292
    if (!psf->context[i])
293
      {
294
      psf->context[i] = &contextval[i];
295
      psf->contexttyp[i] = T_DOUBLE;
296 173 bertin
      if (fitsread(field->tab->headbuf, psf->contextname[i]+1, &contextval[i],
297 2 bertin
                H_FLOAT,T_DOUBLE) == RETURN_ERROR)
298
        {
299
        sprintf(gstr, "*Error*: %s parameter not found in the header of ",
300
                psf->contextname[i]+1);
301
        error(EXIT_FAILURE, gstr, field->rfilename);
302
        }
303
      }
304
 
305
  return;
306
  }
307
 
308
 
309
/******************************** psf_fit ***********************************/
310 234 bertin
/*                   standard PSF fit for one component                     */
311 5 bertin
/****************************************************************************/
312
 
313 275 bertin
void    psf_fit(psfstruct *psf, fieldstruct *field, fieldstruct *wfield,
314 267 bertin
                obj2struct *obj2)
315 5 bertin
{
316
  checkstruct           *check;
317 248 bertin
  static double x2[PSF_NPSFMAX],y2[PSF_NPSFMAX],xy[PSF_NPSFMAX],
318 5 bertin
                        deltax[PSF_NPSFMAX],
319 218 bertin
                        deltay[PSF_NPSFMAX],
320
                        flux[PSF_NPSFMAX],fluxerr[PSF_NPSFMAX],
321 2 bertin
                        deltaxb[PSF_NPSFMAX],deltayb[PSF_NPSFMAX],
322 218 bertin
                        fluxb[PSF_NPSFMAX],fluxerrb[PSF_NPSFMAX],
323 5 bertin
                        sol[PSF_NTOT], covmat[PSF_NTOT*PSF_NTOT],
324 2 bertin
                        vmat[PSF_NTOT*PSF_NTOT], wmat[PSF_NTOT];
325 206 bertin
  float                 *data, *data2, *data3, *weight, *d, *w;
326
  double                *mat,
327
                        *m, *var,
328 5 bertin
                        dx,dy,
329
                        pix,pix2, wthresh,val,
330
                        backnoise2, gain, radmin2,radmax2,satlevel,chi2,
331 2 bertin
                        r2, valmax, psf_fwhm;
332 206 bertin
  float                 **psfmasks, **psfmaskx,**psfmasky,
333 218 bertin
                        *ps, *dh, *wh, pixstep;
334 217 bertin
  PIXTYPE               *datah, *weighth;
335 5 bertin
  int                   i,j,p, npsf,npsfmax, npix, nppix, ix,iy,niter,
336
                        width, height, pwidth,pheight, x,y,
337 2 bertin
                        xmax,ymax, wbad, gainflag, convflag, npsfflag,
338 18 bertin
                        ival,kill=0;
339 5 bertin
 
340 2 bertin
  dx = dy = 0.0;
341
  niter = 0;
342
  npsfmax = prefs.psf_npsfmax;
343
  pixstep = 1.0/psf->pixstep;
344 200 bertin
  gain = (field->gain >0.0? field->gain: 1e30);
345 2 bertin
  backnoise2 = field->backsig*field->backsig;
346 278 bertin
  satlevel = field->satur_level - obj2->bkg[0];
347 2 bertin
  wthresh = wfield?wfield->weight_thresh:BIG;
348 282 bertin
  gainflag = prefs.weightgain_flag[0];
349 2 bertin
  psf_fwhm = psf->fwhm*psf->pixstep;
350
 
351 5 bertin
 
352
  /* Initialize outputs */
353 2 bertin
  thepsfit->niter = 0;
354
  thepsfit->npsf = 0;
355 5 bertin
  for (j=0; j<npsfmax; j++)
356 2 bertin
    {
357 278 bertin
      thepsfit->x[j] = obj2->posx[0];
358
      thepsfit->y[j] = obj2->posy[0];
359 5 bertin
      thepsfit->flux[j] = 0.0;
360 218 bertin
      thepsfit->fluxerr[j] = 0.0;
361 2 bertin
    }
362
 
363 5 bertin
  /* Scale data area with object "size" */
364 267 bertin
  ix = (obj2->xmax+obj2->xmin+1)/2;
365
  iy = (obj2->ymax+obj2->ymin+1)/2;
366
  width = obj2->xmax-obj2->xmin+1+psf_fwhm;
367 2 bertin
  if (width < (ival=(int)(psf_fwhm*2)))
368
    width = ival;
369 267 bertin
  height = obj2->ymax-obj2->ymin+1+psf_fwhm;
370 2 bertin
  if (height < (ival=(int)(psf_fwhm*2)))
371
    height = ival;
372
  npix = width*height;
373
  radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
374
  radmax2 = npix/2.0;
375
 
376 5 bertin
  /* Scale total area with PSF FWHM */
377 2 bertin
  pwidth = (int)(psf->masksize[0]*psf->pixstep)+width;;
378
  pheight = (int)(psf->masksize[1]*psf->pixstep)+height;
379
  nppix = pwidth*pheight;
380
 
381
  QMALLOC(weighth, PIXTYPE, npix);
382 206 bertin
  QMALLOC(weight, float, npix);
383 2 bertin
  QMALLOC(datah, PIXTYPE, npix);
384 206 bertin
  QMALLOC(data, float, npix);
385
  QMALLOC(data2, float, npix);
386
  QMALLOC(data3, float, npix);
387 2 bertin
  QMALLOC(mat, double, npix*PSF_NTOT);
388 267 bertin
  if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
389 2 bertin
    {
390 5 bertin
      QMALLOC(checkmask, PIXTYPE, nppix);
391 2 bertin
    }
392
 
393 206 bertin
  QMALLOC(psfmasks, float *, npsfmax);
394
  QMALLOC(psfmaskx, float *, npsfmax);
395
  QMALLOC(psfmasky, float *, npsfmax);
396 2 bertin
  for (i=0; i<npsfmax; i++)
397
    {
398 206 bertin
      QMALLOC(psfmasks[i], float, npix);
399
      QMALLOC(psfmaskx[i], float, npix);
400
      QMALLOC(psfmasky[i], float, npix);
401 2 bertin
    }
402
 
403 5 bertin
  /* Compute weights */
404 2 bertin
  wbad = 0;
405
  if (wfield)
406
    {
407 249 bertin
    psf_copyobjpix(datah, weighth, width, height, ix,iy, obj2,
408 248 bertin
                !(field->flags&MEASURE_FIELD));
409
    for (wh=weighth, w=weight, dh=datah,p=npix; p--;)
410
      if ((pix=*(wh++)) < wthresh && pix>0
411
        && (pix2=*(dh++))>-BIG
412
        && pix2<satlevel)
413
        *(w++) = 1/sqrt(pix+(pix2>0.0?
414
                        (gainflag? pix2*pix/backnoise2:pix2)/gain
415
                        :0.0));
416 5 bertin
        else
417
          {
418 248 bertin
          *(w++) = 0.0;
419
          wbad++;
420 5 bertin
          }
421 2 bertin
    }
422
  else
423 248 bertin
    {
424 249 bertin
    psf_copyobjpix(datah, NULL, width, height, ix,iy, obj2,
425 248 bertin
                !(field->flags&MEASURE_FIELD));
426 2 bertin
    for (w=weight, dh=datah, p=npix; p--;)
427
      if ((pix=*(dh++))>-BIG && pix<satlevel)
428
        *(w++) = 1.0/sqrt(backnoise2+(pix>0.0?pix/gain:0.0));
429
      else
430
        {
431 5 bertin
          *(w++) = 0.0;
432
          wbad++;
433 2 bertin
        }
434 248 bertin
    }
435 2 bertin
 
436 5 bertin
  /* Special action if most of the weights are zero!! */
437 2 bertin
  if (wbad>=npix-3)
438
    return;
439
 
440 5 bertin
  /* Weight the data */
441 2 bertin
  dh = datah;
442 278 bertin
  val = obj2->dbkg[0];      /* Take into account a local background change */
443 2 bertin
  d = data;
444
  w = weight;
445
  for (p=npix; p--;)
446
    *(d++) = (*(dh++)-val)**(w++);
447
 
448 5 bertin
  /* Get the local PSF */
449 267 bertin
  psf_build(psf, obj2);
450 2 bertin
 
451
  npsfflag = 1;
452
  r2 = psf_fwhm*psf_fwhm/2.0;
453 218 bertin
  fluxb[0] = fluxerrb[0] = deltaxb[0] = deltayb[0] = 0.0;
454 5 bertin
 
455 2 bertin
  for (npsf=1; npsf<=npsfmax && npsfflag; npsf++)
456
    {
457 5 bertin
      kill=0;
458 2 bertin
/*-- First compute an optimum initial guess for the positions of components */
459 5 bertin
      if (npsf>1)
460
        {
461 2 bertin
/*---- Subtract previously fitted components */
462 5 bertin
          d = data2;
463
          dh = datah;
464
          for (p=npix; p--;)
465
            *(d++) = (double)*(dh++);
466
          for (j=0; j<npsf-1; j++)
467
            {
468
              d = data2;
469
              ps = psfmasks[j];
470
              for (p=npix; p--;)
471
                *(d++) -= flux[j]**(ps++);
472
            }
473
          convolve_image(field, data2, data3, width,height);
474 2 bertin
/*---- Ignore regions too close to stellar cores */
475 5 bertin
          for (j=0; j<npsf-1; j++)
476 2 bertin
            {
477 5 bertin
              d = data3;
478
              dy = -((double)(height/2)+deltay[j]);
479
              for (y=height; y--; dy += 1.0)
480
                {
481
                  dx = -((double)(width/2)+deltax[j]);
482
                  for (x=width; x--; dx+= 1.0, d++)
483
                    if (dx*dx+dy*dy<r2)
484
                      *d = -BIG;
485
                }
486 2 bertin
            }
487 5 bertin
/*---- Now find the brightest pixel (poor man's guess, to be refined later) */
488
          d = data3;
489
          valmax = -BIG;
490
          xmax = width/2;
491
          ymax = height/2;
492
          for (y=0; y<height; y++)
493
            for (x=0; x<width; x++)
494
              {
495
                if ((val = *(d++))>valmax)
496
                  {
497
                    valmax = val;
498
                    xmax = x;
499
                    ymax = y;
500
                  }
501
              }
502
          deltax[npsf-1] = (double)(xmax - width/2);
503
          deltay[npsf-1] = (double)(ymax - height/2);
504
        }
505
      else
506
        {
507 2 bertin
/*---- Only one component to fit: simply use the barycenter as a guess */
508 267 bertin
          deltax[npsf-1] = obj2->mx - ix;
509
          deltay[npsf-1] = obj2->my - iy;
510 2 bertin
        }
511
 
512 5 bertin
      niter = 0;
513
      convflag = 1;
514
      for (i=0; i<PSF_NITER && convflag; i++)
515 2 bertin
        {
516 5 bertin
          convflag = 0,niter++,m=mat;
517
          for (j=0; j<npsf; j++)
518 2 bertin
            {
519 5 bertin
/*------ Resample the PSFs here for the 1st iteration */
520
              vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
521
                              psfmasks[j], width, height,
522
                              -deltax[j]*pixstep, -deltay[j]*pixstep,
523
                              pixstep);
524
              m=compute_gradient(weight,width,height,
525
                                 psfmasks[j],psfmaskx[j],psfmasky[j],m);
526 2 bertin
            }
527 5 bertin
 
528
 
529
          svdfit(mat, data, npix, npsf*PSF_NA, sol, vmat, wmat);
530
 
531
          compute_pos( &npsf, &convflag, &npsfflag,radmin2,radmax2,
532
                       r2, sol,flux, deltax, deltay,&dx,&dy);
533 2 bertin
        }
534 218 bertin
 
535 5 bertin
/*-- Compute variances and covariances */
536 218 bertin
      svdvar(vmat, wmat, npsf*PSF_NA, covmat);
537
      var = covmat;
538
      for (j=0; j<npsf; j++, var += (npsf*PSF_NA+1)*PSF_NA)
539
        {
540 5 bertin
/*---- First, the error on the flux estimate */
541 218 bertin
          fluxerr[j] = sqrt(*var)>0.0?  sqrt(*var):999999.0;
542 5 bertin
          //if (flux[j]<12*fluxerr && j>0)
543
          //  npsfmax--,flux[j]=0;
544 218 bertin
          if (flux[j]<12*fluxerr[j] && j>0)
545 5 bertin
                 {
546
                   flux[j]=0,kill++,npsfmax--;
547
                   //if(j==npsfmax-1)
548
                   //  kill++;             
549
                 }
550 2 bertin
        }
551 5 bertin
      if (npsfflag)
552
        {
553
/*--- If we reach this point we know the data are worth backuping */
554
          for (j=0; j<npsf; j++)
555
            {
556
              deltaxb[j] = deltax[j];
557
              deltayb[j] = deltay[j];
558
              fluxb[j] = flux[j];
559 218 bertin
              fluxerrb[j]=fluxerr[j];
560 5 bertin
            }
561
        }
562 2 bertin
    }
563 5 bertin
  npsf=npsf-1-kill;
564 2 bertin
 
565
/* Now keep only fitted stars that fall within the current detection area */
566
  i = 0;
567
  for (j=0; j<npsf; j++)
568 5 bertin
    {
569
      x = (int)(deltaxb[j]+0.4999)+width/2;
570
      y = (int)(deltayb[j]+0.4999)+height/2;
571
      if (x<0 || x>=width || y<0 || y>=height)
572
        continue;
573
      if (weight[y*width+x] < 1/BIG)
574
        continue;
575
      if (10*fluxb[j]<fluxb[0] )
576
        continue;
577
      if (fluxb[j]<=0 )
578
        continue;
579
 
580
      if (FLAG(obj2.poserrmx2_psf))
581 218 bertin
        compute_poserr(j,covmat,sol,obj2,x2,y2,xy, npsf);
582 5 bertin
 
583
      deltax[i] = deltaxb[j];
584
      deltay[i] = deltayb[j];
585 218 bertin
      flux[i] = fluxb[j];
586
      fluxerr[i++] = fluxerrb[j];
587 2 bertin
    }
588 218 bertin
 
589 2 bertin
  npsf = i;
590
 
591 5 bertin
  /* Compute chi2 if asked to
592 2 bertin
  if (FLAG(obj2.chi2_psf))
593
    {
594
      for (j=0; j<npsf; j++)
595 5 bertin
        {
596
          chi2 = 0.0;
597
          for (d=data,w=weight,p=0; p<npix; w++,p++)
598
            {
599
              pix = *(d++);
600
              pix -=  psfmasks[j][p]*flux[j]**w;
601
              chi2 += pix*pix;
602
              if (chi2>1E29) chi2=1E28;
603
            }
604 267 bertin
          obj2->chi2_psf = obj2->sigbkg>0.?
605
            chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
606 5 bertin
 
607
        }
608
 
609
    }*/
610
 /* Compute relative chi2 if asked to */
611
    if (FLAG(obj2.chi2_psf))
612 2 bertin
    {
613 5 bertin
      for (j=0; j<npsf; j++)
614 2 bertin
        {
615 5 bertin
          chi2 = 0.0;
616
          for (d=data,w=weight,p=0; p<npix; w++,p++)
617
            {
618
              pix = *(d++)/flux[j];
619
              pix -=  psfmasks[j][p]**w;
620
              chi2 += pix*pix;
621
              if (chi2>1E29) chi2=1E28;
622
            }
623
          obj2->chi2_psf = flux[j]>0?
624 278 bertin
                chi2/((npix - 3*npsf)*obj2->sigbkg[0]*obj2->sigbkg[0]):999999;
625 2 bertin
 
626
        }
627 5 bertin
 
628 2 bertin
    }
629 5 bertin
  /* CHECK images */
630 2 bertin
  if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
631
    for (j=0; j<npsf; j++)
632
      {
633 5 bertin
        vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
634 206 bertin
                        checkmask, pwidth, pheight,
635 5 bertin
                        -deltax[j]*pixstep, -deltay[j]*pixstep, pixstep);
636
        if ((check = prefs.check[CHECK_SUBPSFPROTOS]))
637 275 bertin
          check_add(check, checkmask, pwidth,pheight, ix,iy,-flux[j]);
638 5 bertin
        if ((check = prefs.check[CHECK_PSFPROTOS]))
639 275 bertin
          check_add(check, checkmask, pwidth,pheight, ix,iy,flux[j]);
640 2 bertin
      }
641
 
642
  thepsfit->niter = niter;
643
  thepsfit->npsf = npsf;
644
  for (j=0; j<npsf; j++)
645
    {
646 5 bertin
      thepsfit->x[j] = ix+deltax[j]+1.0;
647
      thepsfit->y[j] = iy+deltay[j]+1.0;
648
      thepsfit->flux[j] = flux[j];
649 218 bertin
      thepsfit->fluxerr[j] = fluxerr[j];
650 267 bertin
    }
651 5 bertin
 
652
  for (i=0; i<prefs.psf_npsfmax; i++)
653 2 bertin
    {
654 5 bertin
      QFREE(psfmasks[i]);
655
      QFREE(psfmaskx[i]);
656
      QFREE(psfmasky[i]);
657 2 bertin
    }
658
 
659
  QFREE(psfmasks);
660
  QFREE(psfmaskx);
661
  QFREE(psfmasky);
662
  QFREE(datah);
663
  QFREE(data);
664
  QFREE(data2);
665
  QFREE(data3);
666
  QFREE(weighth);
667
  QFREE(weight);
668
  QFREE(data);
669 5 bertin
  QFREE(mat);
670 2 bertin
 
671 267 bertin
  if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
672
    QFREE(checkmask);
673 2 bertin
 
674
  return;
675 5 bertin
}
676 2 bertin
 
677
 
678 248 bertin
/****************************** double_psf_fit ******************************/
679
/* double fit to make psf detection on one image and photometry on another  */
680
/****************************************************************************/
681 5 bertin
 
682 275 bertin
void    double_psf_fit(psfstruct *ppsf, fieldstruct *pfield, fieldstruct *pwfield,
683 267 bertin
                       obj2struct *obj2,
684 275 bertin
                        psfstruct *psf, fieldstruct *field, fieldstruct *wfield)
685 5 bertin
{
686
  static double      /* sum[PSF_NPSFMAX]*/ pdeltax[PSF_NPSFMAX],
687
    pdeltay[PSF_NPSFMAX],psol[PSF_NPSFMAX], pcovmat[PSF_NPSFMAX*PSF_NPSFMAX],
688 218 bertin
    pvmat[PSF_NPSFMAX*PSF_NPSFMAX], pwmat[PSF_NPSFMAX],pflux[PSF_NPSFMAX],
689
    pfluxerr[PSF_NPSFMAX];
690 5 bertin
 
691 206 bertin
    double *pmat,
692
     *pm, /* *pps,  *px, *py,*/
693 5 bertin
    dx,dy,pdx,pdy, /* x1,y1, mx,my,mflux, */
694
    val, ppix,ppix2, /* dflux, */
695
    gain, radmin2,radmax2,satlevel
696
    ,chi2,pwthresh,pbacknoise2, /* mr, */
697 18 bertin
    r2=0, psf_fwhm,ppsf_fwhm ;
698 206 bertin
  float         **ppsfmasks, **ppsfmaskx,**ppsfmasky, *pps;
699
  float         *pdata, *pdata2, *pdata3, *pweight, *pd, *pw,
700
                *pdh, *pwh, pixstep,ppixstep;
701 5 bertin
  PIXTYPE       *pdatah, *pweighth;
702
  int                   i,j,k,p, npsf, npix,ix,iy,
703
    width, height, /* hw,hh, */
704
    x,y, /* yb, */
705
    wbad, gainflag,
706
    ival,npsfmax;
707
  double *pvar;
708
 
709
  pdx = pdy =dx = dy = 0.0;
710
  ppixstep = 1.0/ppsf->pixstep;
711
  pixstep = 1.0/psf->pixstep;
712 200 bertin
  gain = (field->gain >0.0? field->gain: 1e30);
713 5 bertin
  npsfmax=prefs.psf_npsfmax;
714
  pbacknoise2 = pfield->backsig*pfield->backsig;
715 278 bertin
  satlevel = field->satur_level - obj2->bkg[0];
716 282 bertin
  gainflag = prefs.weightgain_flag[0];
717 5 bertin
  psf_fwhm = psf->fwhm*psf->pixstep;
718
  ppsf_fwhm = ppsf->fwhm*ppsf->pixstep;
719
  pwthresh = pwfield?pwfield->weight_thresh:BIG;
720
 
721
  /* Initialize outputs */
722
  ppsfit->niter = 0;
723
  ppsfit->npsf = 0;
724
  for (j=0; j<npsfmax; j++)
725
    {
726
      ppsfit->x[j] = 999999.0;
727
      ppsfit->y[j] = 999999.0;
728
      ppsfit->flux[j] = 0.0;
729 218 bertin
      ppsfit->fluxerr[j] = 0.0;
730
      pdeltax[j]= pdeltay[j]=psol[j]= pwmat[j]=pflux[j]=pfluxerr[j]=0.0;
731 5 bertin
 
732
    }
733
 
734 267 bertin
  ix = (obj2->xmax+obj2->xmin+1)/2;
735
  iy = (obj2->ymax+obj2->ymin+1)/2;
736
  width = obj2->xmax-obj2->xmin+1+psf_fwhm;
737 5 bertin
  if (width < (ival=(int)(psf_fwhm*2)))
738
    width = ival;
739 267 bertin
  height = obj2->ymax-obj2->ymin+1+psf_fwhm;
740 5 bertin
  if (height < (ival=(int)(psf_fwhm*2)))
741
    height = ival;
742
  npix = width*height;
743
  radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
744
  radmax2 = npix/2.0;
745 267 bertin
  psf_fit(psf, field, wfield, obj2);
746 5 bertin
  npsf=thepsfit->npsf;
747
 
748 206 bertin
  QMALLOC(ppsfmasks,float *,npsfmax);
749
  QMALLOC(ppsfmaskx,float *,npsfmax);
750
  QMALLOC(ppsfmasky,float *,npsfmax);
751 5 bertin
 
752
  for (i=0; i<npsfmax; i++)
753
    {
754 206 bertin
      QMALLOC(ppsfmasks[i],float,npix);
755
      QMALLOC(ppsfmaskx[i],float,npix);
756
      QMALLOC(ppsfmasky[i],float,npix);
757 5 bertin
    }
758
 
759
  QMALLOC(pweighth, PIXTYPE, npix);
760 206 bertin
  QMALLOC(pweight, float, npix);
761 5 bertin
  QMALLOC(pdatah, PIXTYPE, npix);
762 206 bertin
  QMALLOC(pdata, float, npix);
763
  QMALLOC(pdata2, float, npix);
764
  QMALLOC(pdata3, float, npix);
765 5 bertin
  QMALLOC(pmat, double, npix*npsfmax);
766
 
767
   for (j=0; j<npsf; j++)
768
    {
769
      pdeltax[j] =thepsfit->x[j]-ix-1 ;
770
      pdeltay[j] =thepsfit->y[j]-iy-1 ;
771
      ppsfit->flux[j] = 0;
772 218 bertin
      ppsfit->fluxerr[j] = 0;
773 5 bertin
    }
774
 
775
/*-------------------  Now the photometry fit ---------------------*/
776
   /* Compute photometry weights */
777
  wbad = 0;
778
  if (pwfield)
779
    {
780 249 bertin
    psf_copyobjpix(pdatah, pweighth, width, height, ix,iy, obj2, 0);
781 248 bertin
    for (pwh=pweighth, pw=pweight, pdh=pdatah,p=npix; p--;)
782
      {
783
      if ((ppix=*(pwh++)) < pwthresh && ppix>0
784
                && (ppix2=*(pdh++))>-BIG  && ppix2<satlevel)
785
        *(pw++) = 1/sqrt(ppix+(ppix2>0.0?
786 5 bertin
                        (gainflag? ppix2*ppix/pbacknoise2:ppix2)/gain : 0.0));
787
      else
788 248 bertin
        {
789
        *(pw++) = 0.0;
790
        wbad++;
791 5 bertin
        }
792 248 bertin
      }
793 5 bertin
    }
794
  else
795 248 bertin
    {
796 249 bertin
    psf_copyobjpix(pdatah, NULL, width, height, ix,iy, obj2, 0);
797 5 bertin
    for (pw=pweight, pdh=pdatah, p=npix; p--;)
798
      if ((ppix=*(pdh++))>-BIG && ppix<satlevel)
799 248 bertin
        *(pw++) = 1.0/sqrt(pbacknoise2+(ppix>0.0?ppix/gain:0.0));
800 5 bertin
      else
801
        {
802 248 bertin
        *(pw++) = 0.0;
803
        wbad++;
804 5 bertin
        }
805 248 bertin
    }
806
 
807 5 bertin
  /* Special action if most of the weights are zero!! */
808
  if (wbad>=npix-3)
809
    return;
810
 
811
  /* Weight the data */
812
  pdh = pdatah;
813
  pd = pdata;
814
  pw = pweight;
815 278 bertin
  val = obj2->dbkg[0];
816 5 bertin
  for (p=npix; p--;)
817
    *(pd++) = (*(pdh++)-val)**(pw++);
818
 
819
 
820
  /* Get the photmetry PSF */
821 267 bertin
   psf_build(ppsf, obj2);
822 5 bertin
  for (j=1; j<=npsf; j++)
823
    {
824
      if (j>1)
825
        {
826
          /*---- Subtract //previously fitted components in photometry image */
827
          pd = pdata2;
828
          pdh = pdatah;
829
          for (p=npix; p--;)
830
            *(pd++) = (double)*(pdh++);
831
          for (k=0; k<j-1; k++)
832
            {
833
              pd = pdata2;
834
              pps = ppsfmasks[k];
835
              for (p=npix; p--;)
836
                *(pd++) -= pflux[k]**(pps++);
837
            }
838
          convolve_image(pfield, pdata2, pdata3, width,height);
839
         /*---- Ignore regions too close to stellar cores */
840
          for (k=0; k<j-1; k++)
841
            {
842
              pd = pdata3;
843
              dy = -((double)(height/2)+pdeltay[k]);
844
              for (y=height; y--; dy += 1.0)
845
                {
846
                  dx = -((double)(width/2)+pdeltax[k]);
847
                  for (x=width; x--; dx+= 1.0, pd++)
848
                    if (dx*dx+dy*dy<r2) /*?*/
849
                      *pd = -BIG;
850
                }
851
            }
852
        }
853
 
854
      pm=pmat;
855
      for (k=0; k<j; k++)
856
            {
857
              /*------ Resample the PSFs here for the 1st iteration */
858
              vignet_resample(ppsf->maskloc,
859
                        ppsf->masksize[0], ppsf->masksize[1],
860
                        ppsfmasks[k], width, height,
861
                        -pdeltax[k]*ppixstep, -pdeltay[k]*ppixstep,
862
                        ppixstep);
863
              pm=compute_gradient_phot(pweight,width,height, ppsfmasks[k],pm);
864
            }
865
 
866
      svdfit(pmat, pdata, npix, j, psol, pvmat, pwmat);
867
      compute_pos_phot( &j, psol,pflux);
868
 
869
  for (k=0; k<j; k++)
870
        {
871
          svdvar(pvmat, pwmat, j, pcovmat);
872
          pvar = pcovmat;
873 218 bertin
          pfluxerr[k]= sqrt(*pvar)>0.0 && sqrt(*pvar)<99?
874 5 bertin
            sqrt(*pvar):99;
875
        }
876
    }
877
  /* Compute chi2 if asked to
878
  if (FLAG(obj2.chi2_psf))
879
    {
880
      for (j=0; j<npsf; j++)
881
        {
882
          chi2 = 0.0;
883
          for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
884
            {
885
              ppix = *(pd++);
886
              ppix -=  ppsfmasks[j][p]*pflux[j]**pw;
887
              chi2 += ppix*ppix;
888
              if (chi2>1E29) chi2=1E28;
889
            }
890 267 bertin
          obj2->chi2_psf = obj2->sigbkg>0.?
891
            chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
892 5 bertin
 
893
        }
894
 
895
    }
896
 */
897
 /* Compute relative error if asked to */
898
  if (FLAG(obj2.chi2_psf))
899
  {
900
      for (j=0; j<npsf; j++)
901
        {
902
          chi2 = 0.0;
903
          for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
904
            {
905
              ppix = *(pd++)/pflux[j];
906
              ppix -=  ppsfmasks[j][p]**pw;
907
              chi2 += ppix*ppix;
908
              if (chi2>1E29) chi2=1E28;
909
            }
910
          obj2->chi2_psf = pflux[j]>0?
911 278 bertin
                chi2/((npix - 3*npsf)*obj2->sigbkg[0]*obj2->sigbkg[0]):999999;
912 5 bertin
 
913
        }
914
 
915
    }
916
  ppsfit->niter = thepsfit->niter;
917
  ppsfit->npsf = npsf;
918
 
919
  for (j=0; j<npsf; j++)
920
    {
921
      thepsfit->x[j] = ix+pdeltax[j]+1.0;
922
      thepsfit->y[j] = iy+pdeltay[j]+1.0;
923
      thepsfit->flux[j] = pflux[j];
924 218 bertin
      thepsfit->fluxerr[j] = pfluxerr[j];
925 5 bertin
      ppsfit->x[j] = ix+pdeltax[j]+1.0;
926
      ppsfit->y[j] = iy+pdeltay[j]+1.0;
927
      ppsfit->flux[j] = pflux[j];
928 218 bertin
      ppsfit->fluxerr[j] = pfluxerr[j];
929 5 bertin
    }
930
 
931
 
932
  for (i=0; i<npsfmax; i++)
933
    {
934
      QFREE(ppsfmasks[i]);
935
      QFREE(ppsfmaskx[i]);
936
      QFREE(ppsfmasky[i]);
937
    }
938
 
939
 
940
  QFREE(ppsfmasks);
941
  QFREE(ppsfmaskx);
942
  QFREE(ppsfmasky);
943
  QFREE(pdatah);
944
  QFREE(pdata);
945
  QFREE(pdata2);
946
  QFREE(pdata3);
947
  QFREE(pweighth);
948
  QFREE(pweight);
949
  QFREE(pdata);
950
  QFREE(pmat);
951
 
952 267 bertin
  if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
953 5 bertin
    {
954
      QFREE(checkmask);
955
    }
956
  return;
957 249 bertin
  }
958 5 bertin
 
959 248 bertin
 
960
/****** psf_copyobjpix ******************************************************
961
PROTO   int psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
962
                        int wout, int hout, int ix, int iy,
963
                        obj2struct *obj2, int detect_flag);
964
PURPOSE Copy a piece of the input object image/weights to local arrays.
965
INPUT   Pointer to the output data array,
966
        pointer to the output weight array,
967
        output frame width,
968
        output frame height,
969
        integer x coordinate,
970
        integer y coordinate,
971
        pointer to the obj2 structure,
972
        detection field flag (non 0 only for pure detection images).
973
OUTPUT  RETURN_ERROR if the coordinates are outside object image,
974
        RETURN_OK otherwise.
975
NOTES   -.
976
AUTHOR  E. Bertin (IAP)
977 283 bertin
VERSION 30/03/2012
978 248 bertin
 ***/
979
int     psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
980
                        int wout, int hout, int ix, int iy,
981 249 bertin
                        obj2struct *obj2, int detect_flag)
982 248 bertin
  {
983 283 bertin
   subimagestruct       *subimage;
984
   PIXTYPE              *datat,*weightt, *imagein,*weightin;
985
   int                  i,y, win,hin, w2, xmin,xmax,ymin,ymax;
986 249 bertin
 
987 248 bertin
/* Set output to -BIG */
988 249 bertin
  datat = data;
989 248 bertin
  for (i=wout*hout; i--;)
990 249 bertin
    *(datat++) = -BIG;
991 248 bertin
  if (weight)
992
    memset(weight, 0, wout*hout*sizeof(PIXTYPE));
993
 
994 283 bertin
  ix -= subimage->immin[0];
995
  iy -= subimage->immin[1];
996
  win = subimage->imsize[0];
997
  hin = subimage->imsize[1];
998 248 bertin
 
999
/* Don't go further if out of frame!! */
1000
  if (ix<0 || ix>=win || iy<0 || iy>=hin)
1001
    return RETURN_ERROR;
1002
 
1003
/* Set the image boundaries */
1004
  w2 = wout;
1005
  ymin = iy-hout/2;
1006
  ymax = ymin + hout;
1007
  if (ymin<0)
1008
    {
1009
    data -= ymin*wout;
1010
    if (weight)
1011
      weight -= ymin*wout;
1012
    ymin = 0;
1013
    }
1014
  if (ymax>hin)
1015
    ymax = hin;
1016
 
1017
  xmin = ix-wout/2;
1018
  xmax = xmin + wout;
1019
  if (xmax>win)
1020
    {
1021
    w2 -= xmax-win;
1022
    xmax = win;
1023
    }
1024
  if (xmin<0)
1025
    {
1026
    data -= xmin;
1027
    if (weight)
1028
      weight -= xmin;
1029
    w2 += xmin;
1030
    xmin = 0;
1031
    }
1032
 
1033
/* Copy the right pixels to the destination */
1034 283 bertin
  imagein = subimage->image;
1035 248 bertin
  for (y=ymin; y<ymax; y++, data += wout)
1036
    memcpy(data, imagein + xmin+y*win, w2*sizeof(PIXTYPE));
1037
  if (weight)
1038
    {
1039 283 bertin
    weightin = subimage->weight;
1040 248 bertin
    for (y=ymin; y<ymax; y++, data += wout)
1041
      memcpy(weight, weightin + xmin+y*win, w2*sizeof(PIXTYPE));
1042
    }
1043
 
1044
 
1045
  return RETURN_OK;
1046
  }
1047
 
1048
 
1049
 
1050 2 bertin
/******************************* psf_build **********************************/
1051
/*
1052
Build the local PSF (function of "context").
1053
*/
1054 267 bertin
void    psf_build(psfstruct *psf, obj2struct *obj2)
1055 2 bertin
  {
1056 285 bertin
   double       pos[POLY_MAXDIM];
1057 201 bertin
   double       *basis, fac;
1058
   float        *ppc, *pl;
1059 2 bertin
   int          i,n,p, ndim, npix;
1060
 
1061 221 bertin
  if (psf->build_flag)
1062
    return;
1063
 
1064 2 bertin
  npix = psf->masksize[0]*psf->masksize[1];
1065
 
1066
/* Reset the Local PSF mask */
1067 206 bertin
  memset(psf->maskloc, 0, npix*sizeof(float));
1068 2 bertin
 
1069
/* Grab the context vector */
1070
  ndim = psf->poly->ndim;
1071
  for (i=0; i<ndim; i++)
1072
    {
1073 267 bertin
    ttypeconv((char *)obj2 + ((void *)psf->context[i]-(void *)&flagobj2),
1074
                &pos[i], psf->contexttyp[i],T_DOUBLE);
1075 2 bertin
    pos[i] = (pos[i] - psf->contextoffset[i]) / psf->contextscale[i];
1076
    }
1077
  poly_func(psf->poly, pos);
1078
 
1079
  basis = psf->poly->basis;
1080
 
1081
  ppc = psf->maskcomp;
1082
/* Sum each component */
1083
  for (n = (psf->maskdim>2?psf->masksize[2]:1); n--;)
1084
    {
1085
    pl = psf->maskloc;
1086
    fac = *(basis++);
1087
    for (p=npix; p--;)
1088
      *(pl++) +=  fac**(ppc++);
1089
    }
1090
 
1091 221 bertin
  psf->build_flag = 1;
1092
 
1093 2 bertin
  return;
1094
  }
1095
 
1096
 
1097 221 bertin
/******************************** psf_fwhm **********************************/
1098
/*
1099
Return the local PSF FWHM.
1100
*/
1101 267 bertin
double  psf_fwhm(psfstruct *psf, obj2struct *obj2)
1102 221 bertin
  {
1103
   float        *pl,
1104
                val, max;
1105
   int          n,p, npix;
1106
 
1107
  if (!psf->build_flag)
1108 267 bertin
    psf_build(psf, obj2);
1109 221 bertin
 
1110
  npix = psf->masksize[0]*psf->masksize[1];
1111
  max = -BIG;
1112
  pl = psf->maskloc;
1113
  for (p=npix; p--;)
1114
    if ((val=*(pl++)) > max)
1115
      max = val;
1116
  pl = psf->maskloc;
1117
  max /= 2.0;
1118
  n = 0;
1119
  for (p=npix; p--;)
1120
    if (*(pl++) >= max)
1121
      n++;
1122
 
1123
  return 2.0*sqrt(n/PI)*psf->pixstep;
1124
  }
1125
 
1126
 
1127 5 bertin
/*****************************compute_gradient*********************************/
1128
 
1129 206 bertin
double *compute_gradient(float *weight,int width, int height,
1130
                         float *masks,float *maskx,float *masky
1131 5 bertin
                        ,double *m)
1132
{
1133
  int x,y;
1134 206 bertin
  float *w, *ps,*px,*py;
1135 5 bertin
 
1136
  /*------ copy of the (weighted) PSF, with outer ring set to zero */
1137
      ps = masks;
1138
      w = weight;
1139
      for (y=0; y<height; y++)
1140
        for (x=0; x<width; x++, ps++, w++)
1141
          *(m++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*ps**w):0)):0;
1142
      /*------ (weighted) PSF gradient in x (kernel for first moment in x) */
1143
      ps = masks;
1144
      px = maskx;
1145
      w = weight;
1146
      for (y=0; y<height; y++)
1147
        for (x=0; x<width; x++, ps++, w++)
1148
          *(m++) = ((*px++) = (x?(x>=(width-1)?0:*(ps+1)-*(ps-1)):0))**w/2;
1149
      /*------ (weighted) PSF gradient in y (kernel for first moment in y) */
1150
      ps = masks;
1151
      py = masky;
1152
      w = weight;
1153
      for (y=0; y<height; y++)
1154
        for (x=0; x<width; x++, ps++, w++)
1155
          *(m++) = (*(py++)=(y?(y>=(height-1)?0:*(ps+width)-*(ps-width)):0))
1156
            **w/2;
1157
  return m;
1158
}
1159
 
1160
/*****************************compute_gradient_phot*****************************
1161
****/
1162
 
1163 206 bertin
double *compute_gradient_phot(float  *pweight,int width, int height,
1164
                         float *pmasks,double *pm)
1165 5 bertin
 
1166
{
1167
  int x,y;
1168 206 bertin
  float  *pw, *pps;
1169 5 bertin
 
1170
  /*------ copy of the (weighted) PSF, with outer ring set to zero */
1171
      pps = pmasks;
1172
      pw = pweight;
1173
      for (y=0; y<height; y++)
1174
        for (x=0; x<width; x++, pps++, pw++)
1175
          *(pm++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*pps**pw):0)):0;
1176
 
1177
  return pm;
1178
}
1179
 
1180
/**************************compute_pos********************************/
1181
 
1182
void compute_pos(int *pnpsf,int *pconvflag,int *pnpsfflag,double radmin2,
1183
                         double radmax2,double r2,double *sol,double *flux
1184
                        ,double *deltax,double *deltay,double *pdx,double *pdy)
1185
{
1186
  int j,k,convflag,npsfflag,npsf;
1187
  double dx,dy;
1188
 
1189
  dx=*pdx;
1190
  dy=*pdy;
1191
  convflag=*pconvflag;
1192
  npsfflag=*pnpsfflag;
1193
  npsf=*pnpsf;
1194
  for (j=0; j<npsf; j++)
1195
    {
1196
      flux[j] = sol[j*PSF_NA];
1197
      /*------ Update the PSF shifts */
1198
      if (fabs(flux[j])>0.0)
1199
        {
1200
          dx = -sol[j*PSF_NA+1]/((npsf>1?2:1)*flux[j]);
1201
          dy = -sol[j*PSF_NA+2]/((npsf>1?2:1)*flux[j]);
1202
        }
1203
 
1204
      deltax[j] += dx;
1205
      deltay[j] += dy;
1206
      /*------ Continue until all PSFs have come to a complete stop */
1207
      if ((dx*dx+dy*dy) > radmin2)
1208
        convflag = 1;
1209
    }
1210
  for (j=0; j<npsf; j++)
1211
    {
1212
      /*------ Exit if too much decentering or negative flux */
1213
      for (k=j+1; k<npsf; k++)
1214
        {
1215
          dx = deltax[j]-deltax[k];
1216
          dy = deltay[j]-deltay[k];
1217
          if (dx*dx+dy*dy<r2/4.0)
1218
            {
1219
              flux[j] = -BIG;
1220
              break;
1221
            }
1222
        }
1223
      if (flux[j]<0.0
1224
          || (deltax[j]*deltax[j] + deltay[j]*deltay[j]) > radmax2)
1225
        {
1226
          npsfflag = 0;
1227
          convflag = 0;
1228
          npsf--;
1229
          break;
1230
        }
1231
    }
1232
  *pdx=dx;
1233
  *pdy=dy;
1234
  *pconvflag=convflag;
1235
  *pnpsfflag= npsfflag;
1236
  *pnpsf=npsf;
1237
  return;
1238
}
1239
 
1240
/**************************compute_pos_phot********************************/
1241
 
1242
void compute_pos_phot(int *pnpsf,double *sol,double *flux)
1243
{
1244
  int j,npsf;
1245
  npsf=*pnpsf;
1246
  for (j=0; j<npsf; j++)
1247
    {
1248
      flux[j] = sol[j];
1249
    }
1250
  *pnpsf=npsf;
1251
  return;
1252
}
1253
 
1254
 
1255
/************************************compute_poserr*****************************
1256
*********/
1257
 
1258
void compute_poserr( int j,double *var,double *sol,obj2struct *obj2,double *x2,
1259 218 bertin
                    double *y2,double *xy, int npsf)
1260 5 bertin
{
1261 218 bertin
  double vara,covab,varb, f2;
1262 5 bertin
 
1263
  /*------ Variances and covariance along x and y */
1264 218 bertin
  vara = *(var += (PSF_NA*npsf+1)*(j*PSF_NA+1));
1265 5 bertin
  covab = *(++var);
1266 218 bertin
  varb = *(var += PSF_NA*npsf);
1267
  f2 = sol[PSF_NA*j];
1268
  f2 *= f2;
1269
  obj2->poserrmx2_psf = vara/f2;
1270
  obj2->poserrmy2_psf = varb/f2;
1271
  obj2->poserrmxy_psf = covab/f2;
1272
 
1273 5 bertin
  /*------ If requested, translate variances to major and minor error axes... */
1274
  if (FLAG(obj2.poserra_psf))
1275
    {
1276
      double    pmx2,pmy2,temp,theta;
1277
 
1278
      if (fabs(temp=obj2->poserrmx2_psf-obj2->poserrmy2_psf) > 0.0)
1279
        theta = atan2(2.0 * obj2->poserrmxy_psf,temp) / 2.0;
1280
      else
1281
        theta = PI/4.0;
1282
 
1283
      temp = sqrt(0.25*temp*temp+obj2->poserrmxy_psf*obj2->poserrmxy_psf);
1284
      pmy2 = pmx2 = 0.5*(obj2->poserrmx2_psf+obj2->poserrmy2_psf);
1285
      pmx2+=temp;
1286
      pmy2-=temp;
1287 218 bertin
 
1288 5 bertin
      obj2->poserra_psf = (float)sqrt(pmx2);
1289
      obj2->poserrb_psf = (float)sqrt(pmy2);
1290
      obj2->poserrtheta_psf = theta*180.0/PI;
1291
    }
1292
 
1293
  /*------ ...Or ellipse parameters */
1294
  if (FLAG(obj2.poserr_cxx))
1295
    {
1296
      double    xm2,ym2, xym, temp;
1297
 
1298
      xm2 = obj2->poserrmx2_psf;
1299
      ym2 = obj2->poserrmy2_psf;
1300
      xym = obj2->poserrmxy_psf;
1301
      obj2->poserrcxx_psf = (float)(ym2/(temp=xm2*ym2-xym*xym));
1302
      obj2->poserrcyy_psf = (float)(xm2/temp);
1303
      obj2->poserrcxy_psf = (float)(-2*xym/temp);
1304
    }
1305
  return;
1306
}
1307
 
1308
 
1309 2 bertin
/******************************** svdfit ************************************/
1310
/*
1311
General least-square fit A.x = b, based on Singular Value Decomposition (SVD).
1312
Loosely adapted from Numerical Recipes in C, 2nd Ed. (p. 671).
1313
Note: the a and v matrices are transposed with respect to the N.R. convention.
1314
*/
1315 206 bertin
void svdfit(double *a, float *b, int m, int n, double *sol,
1316 2 bertin
        double *vmat, double *wmat)
1317
  {
1318
#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
1319
        (maxarg1) : (maxarg2))
1320
#define PYTHAG(a,b)     ((at=fabs(a)) > (bt=fabs(b)) ? \
1321
                                  (ct=bt/at,at*sqrt(1.0+ct*ct)) \
1322
                                : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
1323
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
1324
#define TOL             1.0e-11
1325
 
1326
   int                  flag,i,its,j,jj,k,l,nm,mmi,nml;
1327
   double               c,f,h,s,x,y,z,
1328
                        anorm, g, scale,
1329
                        at,bt,ct,maxarg1,maxarg2,
1330
                        thresh, wmax,
1331
                        *w,*ap,*ap0,*ap1,*ap10,*rv1p,*vp,*vp0,*vp1,*vp10,
1332 206 bertin
                        *tmpp, *rv1,*tmp;
1333
   float                *bp;
1334 2 bertin
 
1335
  anorm = g = scale = 0.0;
1336
  if (m < n)
1337
    error(EXIT_FAILURE, "*Error*: Not enough rows for solving the system ",
1338
        "in svdfit()");
1339
 
1340
  QMALLOC(rv1, double, n);
1341
  QMALLOC(tmp, double, n);
1342
  l = nm = nml = 0;                      /* To avoid gcc -Wall warnings */
1343
  for (i=0;i<n;i++)
1344
    {
1345
    l = i+1;
1346
    nml = n-l;
1347
    rv1[i] = scale*g;
1348
    g = s = scale = 0.0;
1349
    if ((mmi = m - i) > 0)
1350
      {
1351
      ap = ap0 = a+i*(m+1);
1352
      for (k=mmi;k--;)
1353
        scale += fabs(*(ap++));
1354
      if (scale)
1355
        {
1356
        for (ap=ap0,k=mmi; k--; ap++)
1357
          {
1358
          *ap /= scale;
1359
          s += *ap**ap;
1360
          }
1361
        f = *ap0;
1362
        g = -SIGN(sqrt(s),f);
1363
        h = f*g-s;
1364
        *ap0 = f-g;
1365
        ap10 = a+l*m+i;
1366
        for (j=nml;j--; ap10+=m)
1367
          {
1368
          for (s=0.0,ap=ap0,ap1=ap10,k=mmi; k--;)
1369
            s += *(ap1++)**(ap++);
1370
          f = s/h;
1371
          for (ap=ap0,ap1=ap10,k=mmi; k--;)
1372
            *(ap1++) += f**(ap++);
1373
          }
1374
        for (ap=ap0,k=mmi; k--;)
1375
          *(ap++) *= scale;
1376
        }
1377
      }
1378
    wmat[i] = scale*g;
1379
    g = s = scale = 0.0;
1380
    if (i < m && i+1 != n)
1381
      {
1382
      ap = ap0 = a+i+m*l;
1383
      for (k=nml;k--; ap+=m)
1384
        scale += fabs(*ap);
1385
      if (scale)
1386
        {
1387
        for (ap=ap0,k=nml;k--; ap+=m)
1388
          {
1389
          *ap /= scale;
1390
          s += *ap**ap;
1391
          }
1392
        f=*ap0;
1393
        g = -SIGN(sqrt(s),f);
1394
        h=f*g-s;
1395
        *ap0=f-g;
1396
        rv1p = rv1+l;
1397
        for (ap=ap0,k=nml;k--; ap+=m)
1398
          *(rv1p++) = *ap/h;
1399
        ap10 = a+l+m*l;
1400
        for (j=m-l; j--; ap10++)
1401
          {
1402
          for (s=0.0,ap=ap0,ap1=ap10,k=nml; k--; ap+=m,ap1+=m)
1403
            s += *ap1**ap;
1404
          rv1p = rv1+l;
1405
          for (ap1=ap10,k=nml;k--; ap1+=m)
1406
            *ap1 += s**(rv1p++);
1407
          }
1408
        for (ap=ap0,k=nml;k--; ap+=m)
1409
          *ap *= scale;
1410
        }
1411
      }
1412
    anorm=MAX(anorm,(fabs(wmat[i])+fabs(rv1[i])));
1413
    }
1414
 
1415
  for (i=n-1;i>=0;i--)
1416
    {
1417
    if (i < n-1)
1418
      {
1419
      if (g)
1420
        {
1421
        ap0 = a+l*m+i;
1422
        vp0 = vmat+i*n+l;
1423
        vp10 = vmat+l*n+l;
1424
        g *= *ap0;
1425
        for (ap=ap0,vp=vp0,j=nml; j--; ap+=m)
1426
          *(vp++) = *ap/g;
1427
        for (j=nml; j--; vp10+=n)
1428
          {
1429
          for (s=0.0,ap=ap0,vp1=vp10,k=nml; k--; ap+=m)
1430
            s += *ap**(vp1++);
1431
          for (vp=vp0,vp1=vp10,k=nml; k--;)
1432
            *(vp1++) += s**(vp++);
1433
          }
1434
        }
1435
      vp = vmat+l*n+i;
1436
      vp1 = vmat+i*n+l;
1437
      for (j=nml; j--; vp+=n)
1438
        *vp = *(vp1++) = 0.0;
1439
      }
1440
    vmat[i*n+i]=1.0;
1441
    g=rv1[i];
1442
    l=i;
1443
    nml = n-l;
1444
    }
1445
 
1446
  for (i=(m<n?m:n); --i>=0;)
1447
    {
1448
    l=i+1;
1449
    nml = n-l;
1450
    mmi=m-i;
1451
    g=wmat[i];
1452
    ap0 = a+i*m+i;
1453
    ap10 = ap0 + m;
1454
    for (ap=ap10,j=nml;j--;ap+=m)
1455
      *ap=0.0;
1456
    if (g)
1457
      {
1458
      g=1.0/g;
1459
      for (j=nml;j--; ap10+=m)
1460
        {
1461
        for (s=0.0,ap=ap0,ap1=ap10,k=mmi; --k;)
1462
              s += *(++ap)**(++ap1);
1463
        f = (s/(*ap0))*g;
1464
        for (ap=ap0,ap1=ap10,k=mmi;k--;)
1465
          *(ap1++) += f**(ap++);
1466
        }
1467
      for (ap=ap0,j=mmi;j--;)
1468
        *(ap++) *= g;
1469
      }
1470
    else
1471
      for (ap=ap0,j=mmi;j--;)
1472
        *(ap++)=0.0;
1473
    ++(*ap0);
1474
    }
1475
 
1476
  for (k=n; --k>=0;)
1477
      {
1478
      for (its=0;its<100;its++)
1479
        {
1480
        flag=1;
1481
        for (l=k;l>=0;l--)
1482
          {
1483
          nm=l-1;
1484
          if (fabs(rv1[l])+anorm == anorm)
1485
            {
1486
            flag=0;
1487
            break;
1488
            }
1489
          if (fabs(wmat[nm])+anorm == anorm)
1490
            break;
1491
          }
1492
        if (flag)
1493
          {
1494
          c=0.0;
1495
          s=1.0;
1496
          ap0 = a+nm*m;
1497
          ap10 = a+l*m;
1498
          for (i=l; i<=k; i++,ap10+=m)
1499
            {
1500
            f=s*rv1[i];
1501
            if (fabs(f)+anorm == anorm)
1502
              break;
1503
            g=wmat[i];
1504
            h=PYTHAG(f,g);
1505
            wmat[i]=h;
1506
            h=1.0/h;
1507
            c=g*h;
1508
            s=(-f*h);
1509
            for (ap=ap0,ap1=ap10,j=m; j--;)
1510
              {
1511
              z = *ap1;
1512
              y = *ap;
1513
              *(ap++) = y*c+z*s;
1514
              *(ap1++) = z*c-y*s;
1515
              }
1516
            }
1517
          }
1518
        z=wmat[k];
1519
        if (l == k)
1520
          {
1521
          if (z < 0.0)
1522
            {
1523
            wmat[k] = -z;
1524
            vp = vmat+k*n;
1525
            for (j=n; j--; vp++)
1526
              *vp = (-*vp);
1527
            }
1528
          break;
1529
          }
1530
        if (its == 99)
1531
          error(EXIT_FAILURE, "*Error*: No convergence in 100 SVD iterations ",
1532
                "in svdfit()");
1533
        x=wmat[l];
1534
        nm=k-1;
1535
        y=wmat[nm];
1536
        g=rv1[nm];
1537
        h=rv1[k];
1538
        f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
1539
        g=PYTHAG(f,1.0);
1540
        f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
1541
        c=s=1.0;
1542
        ap10 = a+l*m;
1543
        vp10 = vmat+l*n;
1544
        for (j=l;j<=nm;j++,ap10+=m,vp10+=n)
1545
          {
1546
          i=j+1;
1547
          g=rv1[i];
1548
          y=wmat[i];
1549
          h=s*g;
1550
          g=c*g;
1551
          z=PYTHAG(f,h);
1552
          rv1[j]=z;
1553
          c=f/z;
1554
          s=h/z;
1555
          f=x*c+g*s;
1556
          g=g*c-x*s;
1557
          h=y*s;
1558
          y=y*c;
1559
          for (vp=(vp1=vp10)+n,jj=n; jj--;)
1560
            {
1561
            z = *vp;
1562
            x = *vp1;
1563
            *(vp1++) = x*c+z*s;
1564
            *(vp++) = z*c-x*s;
1565
            }
1566
          z=PYTHAG(f,h);
1567
          wmat[j]=z;
1568
          if (z)
1569
            {
1570
            z=1.0/z;
1571
            c=f*z;
1572
            s=h*z;
1573
            }
1574
          f=c*g+s*y;
1575
          x=c*y-s*g;
1576
          for (ap=(ap1=ap10)+m,jj=m; jj--;)
1577
            {
1578
            z = *ap;
1579
            y = *ap1;
1580
            *(ap1++) = y*c+z*s;
1581
            *(ap++) = z*c-y*s;
1582
            }
1583
          }
1584
        rv1[l]=0.0;
1585
        rv1[k]=f;
1586
        wmat[k]=x;
1587
        }
1588
      }
1589
 
1590
  wmax=0.0;
1591
  w = wmat;
1592
  for (j=n;j--; w++)
1593
    if (*w > wmax)
1594
      wmax=*w;
1595
  thresh=TOL*wmax;
1596
  w = wmat;
1597
  for (j=n;j--; w++)
1598
    if (*w < thresh)
1599
      *w = 0.0;
1600
 
1601
  w = wmat;
1602
  ap = a;
1603
  tmpp = tmp;
1604
  for (j=n; j--; w++)
1605
    {
1606
    s=0.0;
1607
    if (*w)
1608
      {
1609
      bp = b;
1610
      for (i=m; i--;)
1611
        s += *(ap++)**(bp++);
1612
      s /= *w;
1613
      }
1614
    else
1615
      ap += m;
1616
    *(tmpp++) = s;
1617
    }
1618
 
1619
  vp0 = vmat;
1620
  for (j=0; j<n; j++,vp0++)
1621
    {
1622
    s=0.0;
1623
    tmpp = tmp;
1624
    for (vp=vp0,jj=n; jj--; vp+=n)
1625
      s += *vp**(tmpp++);
1626
    sol[j]=s;
1627
    }
1628
 
1629
/* Free temporary arrays */
1630
  free(tmp);
1631
  free(rv1);
1632
 
1633
  return;
1634
  }
1635
 
1636
#undef SIGN
1637
#undef MAX
1638
#undef PYTHAG
1639
#undef TOL
1640
 
1641
/******************************** svdvar ************************************/
1642
/*
1643
Computation of the covariance matrix from the SVD vmat and wmat matrices.A
1644
dapted from Numerical Recipes in C, 2nd Ed. (p. 679).
1645
*/
1646
void svdvar(double *v, double *w, int n, double *cov)
1647
  {
1648
   static double        wti[PSF_NTOT];
1649
   double               sum;
1650
   int                  i,j,k;
1651
 
1652
  for (i=0; i<n; i++)
1653
    wti[i] = w[i]? 1.0/(w[i]*w[i]) : 0.0;
1654
 
1655
  for (i=0; i<n; i++)
1656
    for (j=0; j<=i; j++)
1657
      {
1658
      for (sum=0.0,k=0; k<n; k++)
1659
        sum += v[k*n+i]*v[k*n+j]*wti[k];
1660
      cov[j*n+i] = cov[i*n+j] = sum;
1661
      }
1662
 
1663
  return;
1664
  }
1665