/*
|
/*
|
* psf.c
|
* psf.c
|
*
|
*
|
* Fit a PSF model to an image.
|
* Fit a PSF model to an image.
|
*
|
*
|
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
*
|
*
|
* This file part of: SExtractor
|
* This file part of: SExtractor
|
*
|
*
|
* Copyright: (C) 1998-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
|
* Copyright: (C) 1998-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
|
*
|
*
|
* License: GNU General Public License
|
* License: GNU General Public License
|
*
|
*
|
* SExtractor is free software: you can redistribute it and/or modify
|
* SExtractor is free software: you can redistribute it and/or modify
|
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
* (at your option) any later version.
|
* (at your option) any later version.
|
* SExtractor is distributed in the hope that it will be useful,
|
* SExtractor is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
* along with SExtractor. If not, see <http://www.gnu.org/licenses/>.
|
* along with SExtractor. If not, see <http://www.gnu.org/licenses/>.
|
*
|
*
|
* Last modified: 23/06/2011
|
* Last modified: 06/10/2011
|
*
|
*
|
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
|
|
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
#include "config.h"
|
#include "config.h"
|
#endif
|
#endif
|
|
|
#include <math.h>
|
#include <math.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
|
|
#include "define.h"
|
#include "define.h"
|
#include "globals.h"
|
#include "globals.h"
|
#include "prefs.h"
|
#include "prefs.h"
|
#include "fits/fitscat.h"
|
#include "fits/fitscat.h"
|
#include "check.h"
|
#include "check.h"
|
#include "field.h"
|
#include "field.h"
|
#include "filter.h"
|
#include "filter.h"
|
#include "image.h"
|
#include "image.h"
|
#include "wcs/poly.h"
|
#include "wcs/poly.h"
|
#include "psf.h"
|
#include "psf.h"
|
|
|
/*------------------------------- variables ---------------------------------*/
|
/*------------------------------- variables ---------------------------------*/
|
|
|
|
|
extern keystruct objkey[];
|
extern keystruct objkey[];
|
extern objstruct outobj;
|
extern objstruct outobj;
|
|
|
/********************************* psf_init **********************************/
|
/********************************* psf_init **********************************/
|
/*
|
/*
|
Allocate memory and stuff for the PSF-fitting.
|
Allocate memory and stuff for the PSF-fitting.
|
*/
|
*/
|
void psf_init(psfstruct *psf)
|
void psf_init(psfstruct *psf)
|
{
|
{
|
QMALLOC(thepsfit, psfitstruct, 1);
|
QMALLOC(thepsfit, psfitstruct, 1);
|
QMALLOC(thepsfit->x, double, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->x, double, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->y, double, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->y, double, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->flux, float, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->flux, float, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->fluxerr, float, prefs.psf_npsfmax);
|
QMALLOC(thepsfit->fluxerr, float, prefs.psf_npsfmax);
|
QMALLOC(ppsfit, psfitstruct, 1); /*?*/
|
QMALLOC(ppsfit, psfitstruct, 1); /*?*/
|
QMALLOC(ppsfit->x, double, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->x, double, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->y, double, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->y, double, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->flux, float, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->flux, float, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->fluxerr, float, prefs.psf_npsfmax);
|
QMALLOC(ppsfit->fluxerr, float, prefs.psf_npsfmax);
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/********************************* psf_end ***********************************/
|
/********************************* psf_end ***********************************/
|
/*
|
/*
|
Free memory occupied by the PSF-fitting stuff.
|
Free memory occupied by the PSF-fitting stuff.
|
*/
|
*/
|
void psf_end(psfstruct *psf, psfitstruct *psfit)
|
void psf_end(psfstruct *psf, psfitstruct *psfit)
|
{
|
{
|
int d, ndim;
|
int d, ndim;
|
|
|
if (psf->pc)
|
|
pc_end(psf->pc);
|
|
|
|
ndim = psf->poly->ndim;
|
ndim = psf->poly->ndim;
|
for (d=0; d<ndim; d++)
|
for (d=0; d<ndim; d++)
|
free(psf->contextname[d]);
|
free(psf->contextname[d]);
|
free(psf->context);
|
free(psf->context);
|
free(psf->contextname);
|
free(psf->contextname);
|
free(psf->contextoffset);
|
free(psf->contextoffset);
|
free(psf->contextscale);
|
free(psf->contextscale);
|
free(psf->contexttyp);
|
free(psf->contexttyp);
|
poly_end(psf->poly);
|
poly_end(psf->poly);
|
free(psf->maskcomp);
|
free(psf->maskcomp);
|
free(psf->maskloc);
|
free(psf->maskloc);
|
free(psf->masksize);
|
free(psf->masksize);
|
free(psf);
|
free(psf);
|
|
|
if (psfit)
|
if (psfit)
|
{
|
{
|
free(psfit->x);
|
free(psfit->x);
|
free(psfit->y);
|
free(psfit->y);
|
free(psfit->flux);
|
free(psfit->flux);
|
free(psfit->fluxerr);
|
free(psfit->fluxerr);
|
free(psfit);
|
free(psfit);
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/********************************* psf_load *********************************/
|
/********************************* psf_load *********************************/
|
/*
|
/*
|
Read the PSF data from a FITS file.
|
Read the PSF data from a FITS file.
|
*/
|
*/
|
psfstruct *psf_load(char *filename)
|
psfstruct *psf_load(char *filename)
|
{
|
{
|
static objstruct saveobj;
|
|
static obj2struct saveobj2;
|
static obj2struct saveobj2;
|
psfstruct *psf;
|
psfstruct *psf;
|
catstruct *cat;
|
catstruct *cat;
|
tabstruct *tab;
|
tabstruct *tab;
|
keystruct *key;
|
keystruct *key;
|
char *head, *ci,*co;
|
char *head, *ci,*co;
|
int deg[POLY_MAXDIM], group[POLY_MAXDIM], ndim, ngroup,
|
int deg[POLY_MAXDIM], group[POLY_MAXDIM], ndim, ngroup,
|
i,k;
|
i,k;
|
|
|
/* Open the cat (well it is not a "cat", but simply a FITS file */
|
/* Open the cat (well it is not a "cat", but simply a FITS file */
|
if (!(cat = read_cat(filename)))
|
if (!(cat = read_cat(filename)))
|
error(EXIT_FAILURE, "*Error*: PSF file not found: ", filename);
|
error(EXIT_FAILURE, "*Error*: PSF file not found: ", filename);
|
|
|
/* OK, we now allocate memory for the PSF structure itself */
|
/* OK, we now allocate memory for the PSF structure itself */
|
QCALLOC(psf, psfstruct, 1);
|
QCALLOC(psf, psfstruct, 1);
|
|
|
/* Store a short copy of the PSF filename */
|
/* Store a short copy of the PSF filename */
|
if ((ci=strrchr(filename, '/')))
|
if ((ci=strrchr(filename, '/')))
|
strcpy(psf->name, ci+1);
|
strcpy(psf->name, ci+1);
|
else
|
else
|
strcpy(psf->name, filename);
|
strcpy(psf->name, filename);
|
|
|
if (!(tab = name_to_tab(cat, "PSF_DATA", 0)))
|
if (!(tab = name_to_tab(cat, "PSF_DATA", 0)))
|
error(EXIT_FAILURE, "*Error*: PSF_DATA table not found in catalog ",
|
error(EXIT_FAILURE, "*Error*: PSF_DATA table not found in catalog ",
|
filename);
|
filename);
|
|
|
head = tab->headbuf;
|
head = tab->headbuf;
|
|
|
/*-- Dimension of the polynomial */
|
/*-- Dimension of the polynomial */
|
if (fitsread(head, "POLNAXIS", &ndim, H_INT,T_LONG) == RETURN_OK
|
if (fitsread(head, "POLNAXIS", &ndim, H_INT,T_LONG) == RETURN_OK
|
&& ndim)
|
&& ndim)
|
{
|
{
|
/*-- So we have a polynomial description of the PSF variations */
|
/*-- So we have a polynomial description of the PSF variations */
|
if (ndim > POLY_MAXDIM)
|
if (ndim > POLY_MAXDIM)
|
{
|
{
|
sprintf(gstr, "*Error*: The POLNAXIS parameter in %s exceeds %d",
|
sprintf(gstr, "*Error*: The POLNAXIS parameter in %s exceeds %d",
|
psf->name, POLY_MAXDIM);
|
psf->name, POLY_MAXDIM);
|
error(EXIT_FAILURE, gstr, "");
|
error(EXIT_FAILURE, gstr, "");
|
}
|
}
|
|
|
QMALLOC(psf->contextname, char *, ndim);
|
QMALLOC(psf->contextname, char *, ndim);
|
QMALLOC(psf->context, double *, ndim);
|
QMALLOC(psf->context, double *, ndim);
|
QMALLOC(psf->contexttyp, t_type, ndim);
|
QMALLOC(psf->contexttyp, t_type, ndim);
|
QMALLOC(psf->contextoffset, double, ndim);
|
QMALLOC(psf->contextoffset, double, ndim);
|
QMALLOC(psf->contextscale, double, ndim);
|
QMALLOC(psf->contextscale, double, ndim);
|
|
|
/*-- We will have to use the outobj structs, so we first save their content */
|
/*-- We will have to use the flagobj2 struct, so we first save its content */
|
saveobj = outobj;
|
saveobj2 = flagobj2;
|
saveobj2 = outobj2;
|
/*-- flagobj2 is used as a FLAG array, so we initialize it to 0 */
|
/*-- outobj's are used as FLAG arrays, so we initialize them to 0 */
|
memset(&flagobj2, 0, sizeof(flagobj2));
|
memset(&outobj, 0, sizeof(outobj));
|
|
memset(&outobj2, 0, sizeof(outobj2));
|
|
for (i=0; i<ndim; i++)
|
for (i=0; i<ndim; i++)
|
{
|
{
|
/*---- Polynomial groups */
|
/*---- Polynomial groups */
|
sprintf(gstr, "POLGRP%1d", i+1);
|
sprintf(gstr, "POLGRP%1d", i+1);
|
if (fitsread(head, gstr, &group[i], H_INT,T_LONG) != RETURN_OK)
|
if (fitsread(head, gstr, &group[i], H_INT,T_LONG) != RETURN_OK)
|
goto headerror;
|
goto headerror;
|
|
|
/*---- Contexts */
|
/*---- Contexts */
|
QMALLOC(psf->contextname[i], char, 80);
|
QMALLOC(psf->contextname[i], char, 80);
|
sprintf(gstr, "POLNAME%1d", i+1);
|
sprintf(gstr, "POLNAME%1d", i+1);
|
if (fitsread(head,gstr,psf->contextname[i],H_STRING,T_STRING)!=RETURN_OK)
|
if (fitsread(head,gstr,psf->contextname[i],H_STRING,T_STRING)!=RETURN_OK)
|
goto headerror;
|
goto headerror;
|
if (*psf->contextname[i]==(char)':')
|
if (*psf->contextname[i]==(char)':')
|
/*------ It seems we're facing a FITS header parameter */
|
/*------ It seems we're facing a FITS header parameter */
|
psf->context[i] = NULL; /* This is to tell we'll have to load */
|
psf->context[i] = NULL; /* This is to tell we'll have to load */
|
/* a FITS header context later on */
|
/* a FITS header context later on */
|
else
|
else
|
/*------ The context element is a dynamic object parameter */
|
/*------ The context element is a dynamic object parameter */
|
{
|
{
|
if ((k = findkey(psf->contextname[i], (char *)objkey,
|
if ((k = findkey(psf->contextname[i], (char *)objkey,
|
sizeof(keystruct)))==RETURN_ERROR)
|
sizeof(keystruct)))==RETURN_ERROR)
|
{
|
{
|
sprintf(gstr, "*Error*: %s CONTEXT parameter in %s unknown",
|
sprintf(gstr, "*Error*: %s CONTEXT parameter in %s unknown",
|
psf->contextname[i], psf->name);
|
psf->contextname[i], psf->name);
|
error(EXIT_FAILURE, gstr, "");
|
error(EXIT_FAILURE, gstr, "");
|
}
|
}
|
key = objkey+k;
|
key = objkey+k;
|
psf->context[i] = key->ptr;
|
psf->context[i] = key->ptr;
|
psf->contexttyp[i] = key->ttype;
|
psf->contexttyp[i] = key->ttype;
|
/*------ Declare the parameter "active" to trigger computation by SExtractor */
|
/*------ Declare the parameter "active" to trigger computation by SExtractor */
|
*((char *)key->ptr) = (char)'\1';
|
*((char *)key->ptr) = (char)'\1';
|
}
|
}
|
/*---- Scaling of the context parameter */
|
/*---- Scaling of the context parameter */
|
sprintf(gstr, "POLZERO%1d", i+1);
|
sprintf(gstr, "POLZERO%1d", i+1);
|
if (fitsread(head, gstr, &psf->contextoffset[i], H_EXPO, T_DOUBLE)
|
if (fitsread(head, gstr, &psf->contextoffset[i], H_EXPO, T_DOUBLE)
|
!=RETURN_OK)
|
!=RETURN_OK)
|
goto headerror;
|
goto headerror;
|
sprintf(gstr, "POLSCAL%1d", i+1);
|
sprintf(gstr, "POLSCAL%1d", i+1);
|
if (fitsread(head, gstr, &psf->contextscale[i], H_EXPO, T_DOUBLE)
|
if (fitsread(head, gstr, &psf->contextscale[i], H_EXPO, T_DOUBLE)
|
!=RETURN_OK)
|
!=RETURN_OK)
|
goto headerror;
|
goto headerror;
|
}
|
}
|
|
|
/*-- Number of groups */
|
/*-- Number of groups */
|
if (fitsread(head, "POLNGRP ", &ngroup, H_INT, T_LONG) != RETURN_OK)
|
if (fitsread(head, "POLNGRP ", &ngroup, H_INT, T_LONG) != RETURN_OK)
|
goto headerror;
|
goto headerror;
|
|
|
for (i=0; i<ngroup; i++)
|
for (i=0; i<ngroup; i++)
|
{
|
{
|
/*---- Polynomial degree for each group */
|
/*---- Polynomial degree for each group */
|
sprintf(gstr, "POLDEG%1d", i+1);
|
sprintf(gstr, "POLDEG%1d", i+1);
|
if (fitsread(head, gstr, °[i], H_INT,T_LONG) != RETURN_OK)
|
if (fitsread(head, gstr, °[i], H_INT,T_LONG) != RETURN_OK)
|
goto headerror;
|
goto headerror;
|
}
|
}
|
|
|
psf->poly = poly_init(group, ndim, deg, ngroup);
|
psf->poly = poly_init(group, ndim, deg, ngroup);
|
|
|
/*-- Update the permanent FLAG arrays (that is, perform an "OR" on them) */
|
/*-- Restore previous flagobj2 content */
|
for (ci=(char *)&outobj,co=(char *)&flagobj,i=sizeof(objstruct); i--;)
|
flagobj2 = saveobj2;
|
*(co++) |= *(ci++);
|
|
for (ci=(char *)&outobj2,co=(char *)&flagobj2,i=sizeof(obj2struct); i--;)
|
|
*(co++) |= *(ci++);
|
|
|
|
/*-- Restore previous outobj contents */
|
|
outobj = saveobj;
|
|
outobj2 = saveobj2;
|
|
}
|
}
|
else
|
else
|
{
|
{
|
/*-- This is a simple, constant PSF */
|
/*-- This is a simple, constant PSF */
|
psf->poly = poly_init(group, 0, deg, 0);
|
psf->poly = poly_init(group, 0, deg, 0);
|
psf->context = NULL;
|
psf->context = NULL;
|
}
|
}
|
|
|
/* Dimensionality of the PSF mask */
|
/* Dimensionality of the PSF mask */
|
if (fitsread(head, "PSFNAXIS", &psf->maskdim, H_INT, T_LONG) != RETURN_OK)
|
if (fitsread(head, "PSFNAXIS", &psf->maskdim, H_INT, T_LONG) != RETURN_OK)
|
goto headerror;
|
goto headerror;
|
if (psf->maskdim<2 || psf->maskdim>3)
|
if (psf->maskdim<2 || psf->maskdim>3)
|
error(EXIT_FAILURE, "*Error*: wrong dimensionality for the PSF "
|
error(EXIT_FAILURE, "*Error*: wrong dimensionality for the PSF "
|
"mask in ", filename);
|
"mask in ", filename);
|
QMALLOC(psf->masksize, int, psf->maskdim);
|
QMALLOC(psf->masksize, int, psf->maskdim);
|
for (i=0; i<psf->maskdim; i++)
|
for (i=0; i<psf->maskdim; i++)
|
psf->masksize[i] = 1;
|
psf->masksize[i] = 1;
|
psf->masknpix = 1;
|
psf->masknpix = 1;
|
for (i=0; i<psf->maskdim; i++)
|
for (i=0; i<psf->maskdim; i++)
|
{
|
{
|
sprintf(gstr, "PSFAXIS%1d", i+1);
|
sprintf(gstr, "PSFAXIS%1d", i+1);
|
if (fitsread(head, gstr, &psf->masksize[i], H_INT,T_LONG) != RETURN_OK)
|
if (fitsread(head, gstr, &psf->masksize[i], H_INT,T_LONG) != RETURN_OK)
|
goto headerror;
|
goto headerror;
|
psf->masknpix *= psf->masksize[i];
|
psf->masknpix *= psf->masksize[i];
|
}
|
}
|
|
|
/* PSF FWHM: defaulted to 3 pixels */
|
/* PSF FWHM: defaulted to 3 pixels */
|
if (fitsread(head, "PSF_FWHM", &psf->fwhm, H_FLOAT,T_DOUBLE) != RETURN_OK)
|
if (fitsread(head, "PSF_FWHM", &psf->fwhm, H_FLOAT,T_DOUBLE) != RETURN_OK)
|
psf->fwhm = 3.0;
|
psf->fwhm = 3.0;
|
|
|
/* PSF oversampling: defaulted to 1 */
|
/* PSF oversampling: defaulted to 1 */
|
if (fitsread(head, "PSF_SAMP", &psf->pixstep,H_FLOAT,T_FLOAT) != RETURN_OK
|
if (fitsread(head, "PSF_SAMP", &psf->pixstep,H_FLOAT,T_FLOAT) != RETURN_OK
|
|| psf->pixstep <= 0.0)
|
|| psf->pixstep <= 0.0)
|
psf->pixstep = 1.0;
|
psf->pixstep = 1.0;
|
|
|
/* Load the PSF mask data */
|
/* Load the PSF mask data */
|
key = read_key(tab, "PSF_MASK");
|
key = read_key(tab, "PSF_MASK");
|
psf->maskcomp = key->ptr;
|
psf->maskcomp = key->ptr;
|
|
|
psf->pc = pc_load(cat);
|
|
|
|
QMALLOC(psf->maskloc, float, psf->masksize[0]*psf->masksize[1]);
|
QMALLOC(psf->maskloc, float, psf->masksize[0]*psf->masksize[1]);
|
|
|
/* But don't touch my arrays!! */
|
/* But don't touch my arrays!! */
|
blank_keys(tab);
|
blank_keys(tab);
|
|
|
free_cat(&cat, 1);
|
free_cat(&cat, 1);
|
|
|
return psf;
|
return psf;
|
|
|
headerror:
|
headerror:
|
error(EXIT_FAILURE, "*Error*: Incorrect or obsolete PSF data in ", filename);
|
error(EXIT_FAILURE, "*Error*: Incorrect or obsolete PSF data in ", filename);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
|
|
/***************************** psf_readcontext *******************************/
|
/***************************** psf_readcontext *******************************/
|
/*
|
/*
|
Read the PSF context parameters in the FITS header.
|
Read the PSF context parameters in the FITS header.
|
*/
|
*/
|
void psf_readcontext(psfstruct *psf, picstruct *field)
|
void psf_readcontext(psfstruct *psf, picstruct *field)
|
{
|
{
|
static double contextval[POLY_MAXDIM];
|
static double contextval[POLY_MAXDIM];
|
int i, ndim;
|
int i, ndim;
|
|
|
ndim = psf->poly->ndim;
|
ndim = psf->poly->ndim;
|
for (i=0; i<ndim; i++)
|
for (i=0; i<ndim; i++)
|
if (!psf->context[i])
|
if (!psf->context[i])
|
{
|
{
|
psf->context[i] = &contextval[i];
|
psf->context[i] = &contextval[i];
|
psf->contexttyp[i] = T_DOUBLE;
|
psf->contexttyp[i] = T_DOUBLE;
|
if (fitsread(field->tab->headbuf, psf->contextname[i]+1, &contextval[i],
|
if (fitsread(field->tab->headbuf, psf->contextname[i]+1, &contextval[i],
|
H_FLOAT,T_DOUBLE) == RETURN_ERROR)
|
H_FLOAT,T_DOUBLE) == RETURN_ERROR)
|
{
|
{
|
sprintf(gstr, "*Error*: %s parameter not found in the header of ",
|
sprintf(gstr, "*Error*: %s parameter not found in the header of ",
|
psf->contextname[i]+1);
|
psf->contextname[i]+1);
|
error(EXIT_FAILURE, gstr, field->rfilename);
|
error(EXIT_FAILURE, gstr, field->rfilename);
|
}
|
}
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/******************************** psf_fit ***********************************/
|
/******************************** psf_fit ***********************************/
|
/* standard PSF fit for one component */
|
/* standard PSF fit for one component */
|
/****************************************************************************/
|
/****************************************************************************/
|
|
|
void psf_fit(psfstruct *psf, picstruct *field, picstruct *wfield,
|
void psf_fit(psfstruct *psf, picstruct *field, picstruct *wfield,
|
objstruct *obj, obj2struct *obj2)
|
obj2struct *obj2)
|
{
|
{
|
checkstruct *check;
|
checkstruct *check;
|
static double x2[PSF_NPSFMAX],y2[PSF_NPSFMAX],xy[PSF_NPSFMAX],
|
static double x2[PSF_NPSFMAX],y2[PSF_NPSFMAX],xy[PSF_NPSFMAX],
|
deltax[PSF_NPSFMAX],
|
deltax[PSF_NPSFMAX],
|
deltay[PSF_NPSFMAX],
|
deltay[PSF_NPSFMAX],
|
flux[PSF_NPSFMAX],fluxerr[PSF_NPSFMAX],
|
flux[PSF_NPSFMAX],fluxerr[PSF_NPSFMAX],
|
deltaxb[PSF_NPSFMAX],deltayb[PSF_NPSFMAX],
|
deltaxb[PSF_NPSFMAX],deltayb[PSF_NPSFMAX],
|
fluxb[PSF_NPSFMAX],fluxerrb[PSF_NPSFMAX],
|
fluxb[PSF_NPSFMAX],fluxerrb[PSF_NPSFMAX],
|
sol[PSF_NTOT], covmat[PSF_NTOT*PSF_NTOT],
|
sol[PSF_NTOT], covmat[PSF_NTOT*PSF_NTOT],
|
vmat[PSF_NTOT*PSF_NTOT], wmat[PSF_NTOT];
|
vmat[PSF_NTOT*PSF_NTOT], wmat[PSF_NTOT];
|
float *data, *data2, *data3, *weight, *d, *w;
|
float *data, *data2, *data3, *weight, *d, *w;
|
double *mat,
|
double *mat,
|
*m, *var,
|
*m, *var,
|
dx,dy,
|
dx,dy,
|
pix,pix2, wthresh,val,
|
pix,pix2, wthresh,val,
|
backnoise2, gain, radmin2,radmax2,satlevel,chi2,
|
backnoise2, gain, radmin2,radmax2,satlevel,chi2,
|
r2, valmax, psf_fwhm;
|
r2, valmax, psf_fwhm;
|
float **psfmasks, **psfmaskx,**psfmasky,
|
float **psfmasks, **psfmaskx,**psfmasky,
|
*ps, *dh, *wh, pixstep;
|
*ps, *dh, *wh, pixstep;
|
PIXTYPE *datah, *weighth;
|
PIXTYPE *datah, *weighth;
|
int i,j,p, npsf,npsfmax, npix, nppix, ix,iy,niter,
|
int i,j,p, npsf,npsfmax, npix, nppix, ix,iy,niter,
|
width, height, pwidth,pheight, x,y,
|
width, height, pwidth,pheight, x,y,
|
xmax,ymax, wbad, gainflag, convflag, npsfflag,
|
xmax,ymax, wbad, gainflag, convflag, npsfflag,
|
ival,kill=0;
|
ival,kill=0;
|
|
|
dx = dy = 0.0;
|
dx = dy = 0.0;
|
niter = 0;
|
niter = 0;
|
npsfmax = prefs.psf_npsfmax;
|
npsfmax = prefs.psf_npsfmax;
|
pixstep = 1.0/psf->pixstep;
|
pixstep = 1.0/psf->pixstep;
|
gain = (field->gain >0.0? field->gain: 1e30);
|
gain = (field->gain >0.0? field->gain: 1e30);
|
backnoise2 = field->backsig*field->backsig;
|
backnoise2 = field->backsig*field->backsig;
|
satlevel = field->satur_level - obj->bkg;
|
satlevel = field->satur_level - obj2->bkg;
|
wthresh = wfield?wfield->weight_thresh:BIG;
|
wthresh = wfield?wfield->weight_thresh:BIG;
|
gainflag = prefs.weightgain_flag;
|
gainflag = prefs.weightgain_flag;
|
psf_fwhm = psf->fwhm*psf->pixstep;
|
psf_fwhm = psf->fwhm*psf->pixstep;
|
|
|
|
|
/* Initialize outputs */
|
/* Initialize outputs */
|
thepsfit->niter = 0;
|
thepsfit->niter = 0;
|
thepsfit->npsf = 0;
|
thepsfit->npsf = 0;
|
for (j=0; j<npsfmax; j++)
|
for (j=0; j<npsfmax; j++)
|
{
|
{
|
thepsfit->x[j] = obj2->posx;
|
thepsfit->x[j] = obj2->posx;
|
thepsfit->y[j] = obj2->posy;
|
thepsfit->y[j] = obj2->posy;
|
thepsfit->flux[j] = 0.0;
|
thepsfit->flux[j] = 0.0;
|
thepsfit->fluxerr[j] = 0.0;
|
thepsfit->fluxerr[j] = 0.0;
|
}
|
}
|
|
|
/* Scale data area with object "size" */
|
/* Scale data area with object "size" */
|
ix = (obj->xmax+obj->xmin+1)/2;
|
ix = (obj2->xmax+obj2->xmin+1)/2;
|
iy = (obj->ymax+obj->ymin+1)/2;
|
iy = (obj2->ymax+obj2->ymin+1)/2;
|
width = obj->xmax-obj->xmin+1+psf_fwhm;
|
width = obj2->xmax-obj2->xmin+1+psf_fwhm;
|
if (width < (ival=(int)(psf_fwhm*2)))
|
if (width < (ival=(int)(psf_fwhm*2)))
|
width = ival;
|
width = ival;
|
height = obj->ymax-obj->ymin+1+psf_fwhm;
|
height = obj2->ymax-obj2->ymin+1+psf_fwhm;
|
if (height < (ival=(int)(psf_fwhm*2)))
|
if (height < (ival=(int)(psf_fwhm*2)))
|
height = ival;
|
height = ival;
|
npix = width*height;
|
npix = width*height;
|
radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
|
radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
|
radmax2 = npix/2.0;
|
radmax2 = npix/2.0;
|
|
|
/* Scale total area with PSF FWHM */
|
/* Scale total area with PSF FWHM */
|
pwidth = (int)(psf->masksize[0]*psf->pixstep)+width;;
|
pwidth = (int)(psf->masksize[0]*psf->pixstep)+width;;
|
pheight = (int)(psf->masksize[1]*psf->pixstep)+height;
|
pheight = (int)(psf->masksize[1]*psf->pixstep)+height;
|
nppix = pwidth*pheight;
|
nppix = pwidth*pheight;
|
|
|
QMALLOC(weighth, PIXTYPE, npix);
|
QMALLOC(weighth, PIXTYPE, npix);
|
QMALLOC(weight, float, npix);
|
QMALLOC(weight, float, npix);
|
QMALLOC(datah, PIXTYPE, npix);
|
QMALLOC(datah, PIXTYPE, npix);
|
QMALLOC(data, float, npix);
|
QMALLOC(data, float, npix);
|
QMALLOC(data2, float, npix);
|
QMALLOC(data2, float, npix);
|
QMALLOC(data3, float, npix);
|
QMALLOC(data3, float, npix);
|
QMALLOC(mat, double, npix*PSF_NTOT);
|
QMALLOC(mat, double, npix*PSF_NTOT);
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS]
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
|
|| prefs.check[CHECK_SUBPCPROTOS] || prefs.check[CHECK_PCPROTOS]
|
|
|| prefs.check[CHECK_PCOPROTOS])
|
|
{
|
{
|
QMALLOC(checkmask, PIXTYPE, nppix);
|
QMALLOC(checkmask, PIXTYPE, nppix);
|
}
|
}
|
|
|
QMALLOC(psfmasks, float *, npsfmax);
|
QMALLOC(psfmasks, float *, npsfmax);
|
QMALLOC(psfmaskx, float *, npsfmax);
|
QMALLOC(psfmaskx, float *, npsfmax);
|
QMALLOC(psfmasky, float *, npsfmax);
|
QMALLOC(psfmasky, float *, npsfmax);
|
for (i=0; i<npsfmax; i++)
|
for (i=0; i<npsfmax; i++)
|
{
|
{
|
QMALLOC(psfmasks[i], float, npix);
|
QMALLOC(psfmasks[i], float, npix);
|
QMALLOC(psfmaskx[i], float, npix);
|
QMALLOC(psfmaskx[i], float, npix);
|
QMALLOC(psfmasky[i], float, npix);
|
QMALLOC(psfmasky[i], float, npix);
|
}
|
}
|
|
|
/* Compute weights */
|
/* Compute weights */
|
wbad = 0;
|
wbad = 0;
|
if (wfield)
|
if (wfield)
|
{
|
{
|
psf_copyobjpix(datah, weighth, width, height, ix,iy, obj2,
|
psf_copyobjpix(datah, weighth, width, height, ix,iy, obj2,
|
!(field->flags&MEASURE_FIELD));
|
!(field->flags&MEASURE_FIELD));
|
for (wh=weighth, w=weight, dh=datah,p=npix; p--;)
|
for (wh=weighth, w=weight, dh=datah,p=npix; p--;)
|
if ((pix=*(wh++)) < wthresh && pix>0
|
if ((pix=*(wh++)) < wthresh && pix>0
|
&& (pix2=*(dh++))>-BIG
|
&& (pix2=*(dh++))>-BIG
|
&& pix2<satlevel)
|
&& pix2<satlevel)
|
*(w++) = 1/sqrt(pix+(pix2>0.0?
|
*(w++) = 1/sqrt(pix+(pix2>0.0?
|
(gainflag? pix2*pix/backnoise2:pix2)/gain
|
(gainflag? pix2*pix/backnoise2:pix2)/gain
|
:0.0));
|
:0.0));
|
else
|
else
|
{
|
{
|
*(w++) = 0.0;
|
*(w++) = 0.0;
|
wbad++;
|
wbad++;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
psf_copyobjpix(datah, NULL, width, height, ix,iy, obj2,
|
psf_copyobjpix(datah, NULL, width, height, ix,iy, obj2,
|
!(field->flags&MEASURE_FIELD));
|
!(field->flags&MEASURE_FIELD));
|
for (w=weight, dh=datah, p=npix; p--;)
|
for (w=weight, dh=datah, p=npix; p--;)
|
if ((pix=*(dh++))>-BIG && pix<satlevel)
|
if ((pix=*(dh++))>-BIG && pix<satlevel)
|
*(w++) = 1.0/sqrt(backnoise2+(pix>0.0?pix/gain:0.0));
|
*(w++) = 1.0/sqrt(backnoise2+(pix>0.0?pix/gain:0.0));
|
else
|
else
|
{
|
{
|
*(w++) = 0.0;
|
*(w++) = 0.0;
|
wbad++;
|
wbad++;
|
}
|
}
|
}
|
}
|
|
|
/* Special action if most of the weights are zero!! */
|
/* Special action if most of the weights are zero!! */
|
if (wbad>=npix-3)
|
if (wbad>=npix-3)
|
return;
|
return;
|
|
|
/* Weight the data */
|
/* Weight the data */
|
dh = datah;
|
dh = datah;
|
val = obj->dbkg; /* Take into account a local background change */
|
val = obj2->dbkg; /* Take into account a local background change */
|
d = data;
|
d = data;
|
w = weight;
|
w = weight;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(d++) = (*(dh++)-val)**(w++);
|
*(d++) = (*(dh++)-val)**(w++);
|
|
|
/* Get the local PSF */
|
/* Get the local PSF */
|
psf_build(psf);
|
psf_build(psf, obj2);
|
|
|
npsfflag = 1;
|
npsfflag = 1;
|
r2 = psf_fwhm*psf_fwhm/2.0;
|
r2 = psf_fwhm*psf_fwhm/2.0;
|
fluxb[0] = fluxerrb[0] = deltaxb[0] = deltayb[0] = 0.0;
|
fluxb[0] = fluxerrb[0] = deltaxb[0] = deltayb[0] = 0.0;
|
|
|
for (npsf=1; npsf<=npsfmax && npsfflag; npsf++)
|
for (npsf=1; npsf<=npsfmax && npsfflag; npsf++)
|
{
|
{
|
kill=0;
|
kill=0;
|
/*-- First compute an optimum initial guess for the positions of components */
|
/*-- First compute an optimum initial guess for the positions of components */
|
if (npsf>1)
|
if (npsf>1)
|
{
|
{
|
/*---- Subtract previously fitted components */
|
/*---- Subtract previously fitted components */
|
d = data2;
|
d = data2;
|
dh = datah;
|
dh = datah;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(d++) = (double)*(dh++);
|
*(d++) = (double)*(dh++);
|
for (j=0; j<npsf-1; j++)
|
for (j=0; j<npsf-1; j++)
|
{
|
{
|
d = data2;
|
d = data2;
|
ps = psfmasks[j];
|
ps = psfmasks[j];
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(d++) -= flux[j]**(ps++);
|
*(d++) -= flux[j]**(ps++);
|
}
|
}
|
convolve_image(field, data2, data3, width,height);
|
convolve_image(field, data2, data3, width,height);
|
/*---- Ignore regions too close to stellar cores */
|
/*---- Ignore regions too close to stellar cores */
|
for (j=0; j<npsf-1; j++)
|
for (j=0; j<npsf-1; j++)
|
{
|
{
|
d = data3;
|
d = data3;
|
dy = -((double)(height/2)+deltay[j]);
|
dy = -((double)(height/2)+deltay[j]);
|
for (y=height; y--; dy += 1.0)
|
for (y=height; y--; dy += 1.0)
|
{
|
{
|
dx = -((double)(width/2)+deltax[j]);
|
dx = -((double)(width/2)+deltax[j]);
|
for (x=width; x--; dx+= 1.0, d++)
|
for (x=width; x--; dx+= 1.0, d++)
|
if (dx*dx+dy*dy<r2)
|
if (dx*dx+dy*dy<r2)
|
*d = -BIG;
|
*d = -BIG;
|
}
|
}
|
}
|
}
|
/*---- Now find the brightest pixel (poor man's guess, to be refined later) */
|
/*---- Now find the brightest pixel (poor man's guess, to be refined later) */
|
d = data3;
|
d = data3;
|
valmax = -BIG;
|
valmax = -BIG;
|
xmax = width/2;
|
xmax = width/2;
|
ymax = height/2;
|
ymax = height/2;
|
for (y=0; y<height; y++)
|
for (y=0; y<height; y++)
|
for (x=0; x<width; x++)
|
for (x=0; x<width; x++)
|
{
|
{
|
if ((val = *(d++))>valmax)
|
if ((val = *(d++))>valmax)
|
{
|
{
|
valmax = val;
|
valmax = val;
|
xmax = x;
|
xmax = x;
|
ymax = y;
|
ymax = y;
|
}
|
}
|
}
|
}
|
deltax[npsf-1] = (double)(xmax - width/2);
|
deltax[npsf-1] = (double)(xmax - width/2);
|
deltay[npsf-1] = (double)(ymax - height/2);
|
deltay[npsf-1] = (double)(ymax - height/2);
|
}
|
}
|
else
|
else
|
{
|
{
|
/*---- Only one component to fit: simply use the barycenter as a guess */
|
/*---- Only one component to fit: simply use the barycenter as a guess */
|
deltax[npsf-1] = obj->mx - ix;
|
deltax[npsf-1] = obj2->mx - ix;
|
deltay[npsf-1] = obj->my - iy;
|
deltay[npsf-1] = obj2->my - iy;
|
}
|
}
|
|
|
niter = 0;
|
niter = 0;
|
convflag = 1;
|
convflag = 1;
|
for (i=0; i<PSF_NITER && convflag; i++)
|
for (i=0; i<PSF_NITER && convflag; i++)
|
{
|
{
|
convflag = 0,niter++,m=mat;
|
convflag = 0,niter++,m=mat;
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
/*------ Resample the PSFs here for the 1st iteration */
|
/*------ Resample the PSFs here for the 1st iteration */
|
vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
|
vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
|
psfmasks[j], width, height,
|
psfmasks[j], width, height,
|
-deltax[j]*pixstep, -deltay[j]*pixstep,
|
-deltax[j]*pixstep, -deltay[j]*pixstep,
|
pixstep);
|
pixstep);
|
m=compute_gradient(weight,width,height,
|
m=compute_gradient(weight,width,height,
|
psfmasks[j],psfmaskx[j],psfmasky[j],m);
|
psfmasks[j],psfmaskx[j],psfmasky[j],m);
|
}
|
}
|
|
|
|
|
svdfit(mat, data, npix, npsf*PSF_NA, sol, vmat, wmat);
|
svdfit(mat, data, npix, npsf*PSF_NA, sol, vmat, wmat);
|
|
|
compute_pos( &npsf, &convflag, &npsfflag,radmin2,radmax2,
|
compute_pos( &npsf, &convflag, &npsfflag,radmin2,radmax2,
|
r2, sol,flux, deltax, deltay,&dx,&dy);
|
r2, sol,flux, deltax, deltay,&dx,&dy);
|
}
|
}
|
|
|
/*-- Compute variances and covariances */
|
/*-- Compute variances and covariances */
|
svdvar(vmat, wmat, npsf*PSF_NA, covmat);
|
svdvar(vmat, wmat, npsf*PSF_NA, covmat);
|
var = covmat;
|
var = covmat;
|
for (j=0; j<npsf; j++, var += (npsf*PSF_NA+1)*PSF_NA)
|
for (j=0; j<npsf; j++, var += (npsf*PSF_NA+1)*PSF_NA)
|
{
|
{
|
/*---- First, the error on the flux estimate */
|
/*---- First, the error on the flux estimate */
|
fluxerr[j] = sqrt(*var)>0.0? sqrt(*var):999999.0;
|
fluxerr[j] = sqrt(*var)>0.0? sqrt(*var):999999.0;
|
//if (flux[j]<12*fluxerr && j>0)
|
//if (flux[j]<12*fluxerr && j>0)
|
// npsfmax--,flux[j]=0;
|
// npsfmax--,flux[j]=0;
|
if (flux[j]<12*fluxerr[j] && j>0)
|
if (flux[j]<12*fluxerr[j] && j>0)
|
{
|
{
|
flux[j]=0,kill++,npsfmax--;
|
flux[j]=0,kill++,npsfmax--;
|
//if(j==npsfmax-1)
|
//if(j==npsfmax-1)
|
// kill++;
|
// kill++;
|
}
|
}
|
}
|
}
|
if (npsfflag)
|
if (npsfflag)
|
{
|
{
|
/*--- If we reach this point we know the data are worth backuping */
|
/*--- If we reach this point we know the data are worth backuping */
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
deltaxb[j] = deltax[j];
|
deltaxb[j] = deltax[j];
|
deltayb[j] = deltay[j];
|
deltayb[j] = deltay[j];
|
fluxb[j] = flux[j];
|
fluxb[j] = flux[j];
|
fluxerrb[j]=fluxerr[j];
|
fluxerrb[j]=fluxerr[j];
|
}
|
}
|
}
|
}
|
}
|
}
|
npsf=npsf-1-kill;
|
npsf=npsf-1-kill;
|
|
|
/* Now keep only fitted stars that fall within the current detection area */
|
/* Now keep only fitted stars that fall within the current detection area */
|
i = 0;
|
i = 0;
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
x = (int)(deltaxb[j]+0.4999)+width/2;
|
x = (int)(deltaxb[j]+0.4999)+width/2;
|
y = (int)(deltayb[j]+0.4999)+height/2;
|
y = (int)(deltayb[j]+0.4999)+height/2;
|
if (x<0 || x>=width || y<0 || y>=height)
|
if (x<0 || x>=width || y<0 || y>=height)
|
continue;
|
continue;
|
if (weight[y*width+x] < 1/BIG)
|
if (weight[y*width+x] < 1/BIG)
|
continue;
|
continue;
|
if (10*fluxb[j]<fluxb[0] )
|
if (10*fluxb[j]<fluxb[0] )
|
continue;
|
continue;
|
if (fluxb[j]<=0 )
|
if (fluxb[j]<=0 )
|
continue;
|
continue;
|
|
|
if (FLAG(obj2.poserrmx2_psf))
|
if (FLAG(obj2.poserrmx2_psf))
|
compute_poserr(j,covmat,sol,obj2,x2,y2,xy, npsf);
|
compute_poserr(j,covmat,sol,obj2,x2,y2,xy, npsf);
|
|
|
deltax[i] = deltaxb[j];
|
deltax[i] = deltaxb[j];
|
deltay[i] = deltayb[j];
|
deltay[i] = deltayb[j];
|
flux[i] = fluxb[j];
|
flux[i] = fluxb[j];
|
fluxerr[i++] = fluxerrb[j];
|
fluxerr[i++] = fluxerrb[j];
|
}
|
}
|
|
|
npsf = i;
|
npsf = i;
|
|
|
/* Compute chi2 if asked to
|
/* Compute chi2 if asked to
|
if (FLAG(obj2.chi2_psf))
|
if (FLAG(obj2.chi2_psf))
|
{
|
{
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
chi2 = 0.0;
|
chi2 = 0.0;
|
for (d=data,w=weight,p=0; p<npix; w++,p++)
|
for (d=data,w=weight,p=0; p<npix; w++,p++)
|
{
|
{
|
pix = *(d++);
|
pix = *(d++);
|
pix -= psfmasks[j][p]*flux[j]**w;
|
pix -= psfmasks[j][p]*flux[j]**w;
|
chi2 += pix*pix;
|
chi2 += pix*pix;
|
if (chi2>1E29) chi2=1E28;
|
if (chi2>1E29) chi2=1E28;
|
}
|
}
|
obj2->chi2_psf = obj->sigbkg>0.?
|
obj2->chi2_psf = obj2->sigbkg>0.?
|
chi2/((npix - 3*npsf)*obj->sigbkg*obj->sigbkg):999999;
|
chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
|
|
|
}
|
}
|
|
|
}*/
|
}*/
|
/* Compute relative chi2 if asked to */
|
/* Compute relative chi2 if asked to */
|
if (FLAG(obj2.chi2_psf))
|
if (FLAG(obj2.chi2_psf))
|
{
|
{
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
chi2 = 0.0;
|
chi2 = 0.0;
|
for (d=data,w=weight,p=0; p<npix; w++,p++)
|
for (d=data,w=weight,p=0; p<npix; w++,p++)
|
{
|
{
|
pix = *(d++)/flux[j];
|
pix = *(d++)/flux[j];
|
pix -= psfmasks[j][p]**w;
|
pix -= psfmasks[j][p]**w;
|
chi2 += pix*pix;
|
chi2 += pix*pix;
|
if (chi2>1E29) chi2=1E28;
|
if (chi2>1E29) chi2=1E28;
|
}
|
}
|
obj2->chi2_psf = flux[j]>0?
|
obj2->chi2_psf = flux[j]>0?
|
chi2/((npix - 3*npsf)*obj->sigbkg*obj->sigbkg):999999;
|
chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
|
|
|
}
|
}
|
|
|
}
|
}
|
/* CHECK images */
|
/* CHECK images */
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
|
vignet_resample(psf->maskloc, psf->masksize[0], psf->masksize[1],
|
checkmask, pwidth, pheight,
|
checkmask, pwidth, pheight,
|
-deltax[j]*pixstep, -deltay[j]*pixstep, pixstep);
|
-deltax[j]*pixstep, -deltay[j]*pixstep, pixstep);
|
if ((check = prefs.check[CHECK_SUBPSFPROTOS]))
|
if ((check = prefs.check[CHECK_SUBPSFPROTOS]))
|
addcheck(check, checkmask, pwidth,pheight, ix,iy,-flux[j]);
|
addcheck(check, checkmask, pwidth,pheight, ix,iy,-flux[j]);
|
if ((check = prefs.check[CHECK_PSFPROTOS]))
|
if ((check = prefs.check[CHECK_PSFPROTOS]))
|
addcheck(check, checkmask, pwidth,pheight, ix,iy,flux[j]);
|
addcheck(check, checkmask, pwidth,pheight, ix,iy,flux[j]);
|
}
|
}
|
|
|
thepsfit->niter = niter;
|
thepsfit->niter = niter;
|
thepsfit->npsf = npsf;
|
thepsfit->npsf = npsf;
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
thepsfit->x[j] = ix+deltax[j]+1.0;
|
thepsfit->x[j] = ix+deltax[j]+1.0;
|
thepsfit->y[j] = iy+deltay[j]+1.0;
|
thepsfit->y[j] = iy+deltay[j]+1.0;
|
thepsfit->flux[j] = flux[j];
|
thepsfit->flux[j] = flux[j];
|
thepsfit->fluxerr[j] = fluxerr[j];
|
thepsfit->fluxerr[j] = fluxerr[j];
|
}
|
}
|
|
|
|
|
|
|
|
|
/* Now the morphology stuff */
|
|
if (prefs.pc_flag)
|
|
{
|
|
width = pwidth-1;
|
|
height = pheight-1;
|
|
npix = width*height;
|
|
|
|
/*-- Re-compute weights */
|
|
if (wfield)
|
|
{
|
|
psf_copyobjpix(datah, weighth, width, height, ix,iy, obj2,
|
|
!(field->flags&MEASURE_FIELD));
|
|
for (wh=weighth ,w=weight, p=npix; p--;)
|
|
*(w++) = (pix=*(wh++))<wthresh? sqrt(pix): 0.0;
|
|
}
|
|
else
|
|
{
|
|
psf_copyobjpix(datah, NULL, width, height, ix,iy, obj2,
|
|
!(field->flags&MEASURE_FIELD));
|
|
for (w=weight, dh=datah, p=npix; p--;)
|
|
*(w++) = ((pix = *(dh++))>-BIG && pix<satlevel)?
|
|
1.0/sqrt(backnoise2+(pix>0.0?pix/gain:0.0))
|
|
:0.0;
|
|
}
|
|
|
|
/*-- Weight the data */
|
|
dh = datah;
|
|
d = data;
|
|
w = weight;
|
|
for (p=npix; p--;)
|
|
*(d++) = *(dh++)*(*(w++));
|
|
|
|
pc_fit(psf, data, weight, width, height, ix,iy, dx,dy, npix,
|
|
field->backsig);
|
|
}
|
|
|
|
|
|
for (i=0; i<prefs.psf_npsfmax; i++)
|
for (i=0; i<prefs.psf_npsfmax; i++)
|
{
|
{
|
QFREE(psfmasks[i]);
|
QFREE(psfmasks[i]);
|
QFREE(psfmaskx[i]);
|
QFREE(psfmaskx[i]);
|
QFREE(psfmasky[i]);
|
QFREE(psfmasky[i]);
|
}
|
}
|
|
|
QFREE(psfmasks);
|
QFREE(psfmasks);
|
QFREE(psfmaskx);
|
QFREE(psfmaskx);
|
QFREE(psfmasky);
|
QFREE(psfmasky);
|
QFREE(datah);
|
QFREE(datah);
|
QFREE(data);
|
QFREE(data);
|
QFREE(data2);
|
QFREE(data2);
|
QFREE(data3);
|
QFREE(data3);
|
QFREE(weighth);
|
QFREE(weighth);
|
QFREE(weight);
|
QFREE(weight);
|
QFREE(data);
|
QFREE(data);
|
QFREE(mat);
|
QFREE(mat);
|
|
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS]
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
|
|| prefs.check[CHECK_SUBPCPROTOS] || prefs.check[CHECK_PCPROTOS]
|
|
|| prefs.check[CHECK_PCOPROTOS])
|
|
{
|
|
QFREE(checkmask);
|
QFREE(checkmask);
|
}
|
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/****************************** double_psf_fit ******************************/
|
/****************************** double_psf_fit ******************************/
|
/* double fit to make psf detection on one image and photometry on another */
|
/* double fit to make psf detection on one image and photometry on another */
|
/****************************************************************************/
|
/****************************************************************************/
|
|
|
void double_psf_fit(psfstruct *ppsf, picstruct *pfield, picstruct *pwfield,
|
void double_psf_fit(psfstruct *ppsf, picstruct *pfield, picstruct *pwfield,
|
objstruct *obj, obj2struct *obj2,
|
obj2struct *obj2,
|
psfstruct *psf, picstruct *field, picstruct *wfield)
|
psfstruct *psf, picstruct *field, picstruct *wfield)
|
{
|
{
|
static double /* sum[PSF_NPSFMAX]*/ pdeltax[PSF_NPSFMAX],
|
static double /* sum[PSF_NPSFMAX]*/ pdeltax[PSF_NPSFMAX],
|
pdeltay[PSF_NPSFMAX],psol[PSF_NPSFMAX], pcovmat[PSF_NPSFMAX*PSF_NPSFMAX],
|
pdeltay[PSF_NPSFMAX],psol[PSF_NPSFMAX], pcovmat[PSF_NPSFMAX*PSF_NPSFMAX],
|
pvmat[PSF_NPSFMAX*PSF_NPSFMAX], pwmat[PSF_NPSFMAX],pflux[PSF_NPSFMAX],
|
pvmat[PSF_NPSFMAX*PSF_NPSFMAX], pwmat[PSF_NPSFMAX],pflux[PSF_NPSFMAX],
|
pfluxerr[PSF_NPSFMAX];
|
pfluxerr[PSF_NPSFMAX];
|
|
|
double *pmat,
|
double *pmat,
|
*pm, /* *pps, *px, *py,*/
|
*pm, /* *pps, *px, *py,*/
|
dx,dy,pdx,pdy, /* x1,y1, mx,my,mflux, */
|
dx,dy,pdx,pdy, /* x1,y1, mx,my,mflux, */
|
val, ppix,ppix2, /* dflux, */
|
val, ppix,ppix2, /* dflux, */
|
gain, radmin2,radmax2,satlevel
|
gain, radmin2,radmax2,satlevel
|
,chi2,pwthresh,pbacknoise2, /* mr, */
|
,chi2,pwthresh,pbacknoise2, /* mr, */
|
r2=0, psf_fwhm,ppsf_fwhm ;
|
r2=0, psf_fwhm,ppsf_fwhm ;
|
float **ppsfmasks, **ppsfmaskx,**ppsfmasky, *pps;
|
float **ppsfmasks, **ppsfmaskx,**ppsfmasky, *pps;
|
float *pdata, *pdata2, *pdata3, *pweight, *pd, *pw,
|
float *pdata, *pdata2, *pdata3, *pweight, *pd, *pw,
|
*pdh, *pwh, pixstep,ppixstep;
|
*pdh, *pwh, pixstep,ppixstep;
|
PIXTYPE *pdatah, *pweighth;
|
PIXTYPE *pdatah, *pweighth;
|
int i,j,k,p, npsf, npix,ix,iy,
|
int i,j,k,p, npsf, npix,ix,iy,
|
width, height, /* hw,hh, */
|
width, height, /* hw,hh, */
|
x,y, /* yb, */
|
x,y, /* yb, */
|
wbad, gainflag,
|
wbad, gainflag,
|
ival,npsfmax;
|
ival,npsfmax;
|
double *pvar;
|
double *pvar;
|
|
|
pdx = pdy =dx = dy = 0.0;
|
pdx = pdy =dx = dy = 0.0;
|
ppixstep = 1.0/ppsf->pixstep;
|
ppixstep = 1.0/ppsf->pixstep;
|
pixstep = 1.0/psf->pixstep;
|
pixstep = 1.0/psf->pixstep;
|
gain = (field->gain >0.0? field->gain: 1e30);
|
gain = (field->gain >0.0? field->gain: 1e30);
|
npsfmax=prefs.psf_npsfmax;
|
npsfmax=prefs.psf_npsfmax;
|
pbacknoise2 = pfield->backsig*pfield->backsig;
|
pbacknoise2 = pfield->backsig*pfield->backsig;
|
satlevel = field->satur_level - obj->bkg;
|
satlevel = field->satur_level - obj2->bkg;
|
gainflag = prefs.weightgain_flag;
|
gainflag = prefs.weightgain_flag;
|
psf_fwhm = psf->fwhm*psf->pixstep;
|
psf_fwhm = psf->fwhm*psf->pixstep;
|
ppsf_fwhm = ppsf->fwhm*ppsf->pixstep;
|
ppsf_fwhm = ppsf->fwhm*ppsf->pixstep;
|
pwthresh = pwfield?pwfield->weight_thresh:BIG;
|
pwthresh = pwfield?pwfield->weight_thresh:BIG;
|
|
|
/* Initialize outputs */
|
/* Initialize outputs */
|
ppsfit->niter = 0;
|
ppsfit->niter = 0;
|
ppsfit->npsf = 0;
|
ppsfit->npsf = 0;
|
for (j=0; j<npsfmax; j++)
|
for (j=0; j<npsfmax; j++)
|
{
|
{
|
ppsfit->x[j] = 999999.0;
|
ppsfit->x[j] = 999999.0;
|
ppsfit->y[j] = 999999.0;
|
ppsfit->y[j] = 999999.0;
|
ppsfit->flux[j] = 0.0;
|
ppsfit->flux[j] = 0.0;
|
ppsfit->fluxerr[j] = 0.0;
|
ppsfit->fluxerr[j] = 0.0;
|
pdeltax[j]= pdeltay[j]=psol[j]= pwmat[j]=pflux[j]=pfluxerr[j]=0.0;
|
pdeltax[j]= pdeltay[j]=psol[j]= pwmat[j]=pflux[j]=pfluxerr[j]=0.0;
|
|
|
}
|
}
|
|
|
ix = (obj->xmax+obj->xmin+1)/2;
|
ix = (obj2->xmax+obj2->xmin+1)/2;
|
iy = (obj->ymax+obj->ymin+1)/2;
|
iy = (obj2->ymax+obj2->ymin+1)/2;
|
width = obj->xmax-obj->xmin+1+psf_fwhm;
|
width = obj2->xmax-obj2->xmin+1+psf_fwhm;
|
if (width < (ival=(int)(psf_fwhm*2)))
|
if (width < (ival=(int)(psf_fwhm*2)))
|
width = ival;
|
width = ival;
|
height = obj->ymax-obj->ymin+1+psf_fwhm;
|
height = obj2->ymax-obj2->ymin+1+psf_fwhm;
|
if (height < (ival=(int)(psf_fwhm*2)))
|
if (height < (ival=(int)(psf_fwhm*2)))
|
height = ival;
|
height = ival;
|
npix = width*height;
|
npix = width*height;
|
radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
|
radmin2 = PSF_MINSHIFT*PSF_MINSHIFT;
|
radmax2 = npix/2.0;
|
radmax2 = npix/2.0;
|
psf_fit(psf, field, wfield, obj, obj2);
|
psf_fit(psf, field, wfield, obj2);
|
npsf=thepsfit->npsf;
|
npsf=thepsfit->npsf;
|
|
|
QMALLOC(ppsfmasks,float *,npsfmax);
|
QMALLOC(ppsfmasks,float *,npsfmax);
|
QMALLOC(ppsfmaskx,float *,npsfmax);
|
QMALLOC(ppsfmaskx,float *,npsfmax);
|
QMALLOC(ppsfmasky,float *,npsfmax);
|
QMALLOC(ppsfmasky,float *,npsfmax);
|
|
|
for (i=0; i<npsfmax; i++)
|
for (i=0; i<npsfmax; i++)
|
{
|
{
|
QMALLOC(ppsfmasks[i],float,npix);
|
QMALLOC(ppsfmasks[i],float,npix);
|
QMALLOC(ppsfmaskx[i],float,npix);
|
QMALLOC(ppsfmaskx[i],float,npix);
|
QMALLOC(ppsfmasky[i],float,npix);
|
QMALLOC(ppsfmasky[i],float,npix);
|
}
|
}
|
|
|
QMALLOC(pweighth, PIXTYPE, npix);
|
QMALLOC(pweighth, PIXTYPE, npix);
|
QMALLOC(pweight, float, npix);
|
QMALLOC(pweight, float, npix);
|
QMALLOC(pdatah, PIXTYPE, npix);
|
QMALLOC(pdatah, PIXTYPE, npix);
|
QMALLOC(pdata, float, npix);
|
QMALLOC(pdata, float, npix);
|
QMALLOC(pdata2, float, npix);
|
QMALLOC(pdata2, float, npix);
|
QMALLOC(pdata3, float, npix);
|
QMALLOC(pdata3, float, npix);
|
QMALLOC(pmat, double, npix*npsfmax);
|
QMALLOC(pmat, double, npix*npsfmax);
|
|
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
pdeltax[j] =thepsfit->x[j]-ix-1 ;
|
pdeltax[j] =thepsfit->x[j]-ix-1 ;
|
pdeltay[j] =thepsfit->y[j]-iy-1 ;
|
pdeltay[j] =thepsfit->y[j]-iy-1 ;
|
ppsfit->flux[j] = 0;
|
ppsfit->flux[j] = 0;
|
ppsfit->fluxerr[j] = 0;
|
ppsfit->fluxerr[j] = 0;
|
}
|
}
|
|
|
/*------------------- Now the photometry fit ---------------------*/
|
/*------------------- Now the photometry fit ---------------------*/
|
/* Compute photometry weights */
|
/* Compute photometry weights */
|
wbad = 0;
|
wbad = 0;
|
if (pwfield)
|
if (pwfield)
|
{
|
{
|
psf_copyobjpix(pdatah, pweighth, width, height, ix,iy, obj2, 0);
|
psf_copyobjpix(pdatah, pweighth, width, height, ix,iy, obj2, 0);
|
for (pwh=pweighth, pw=pweight, pdh=pdatah,p=npix; p--;)
|
for (pwh=pweighth, pw=pweight, pdh=pdatah,p=npix; p--;)
|
{
|
{
|
if ((ppix=*(pwh++)) < pwthresh && ppix>0
|
if ((ppix=*(pwh++)) < pwthresh && ppix>0
|
&& (ppix2=*(pdh++))>-BIG && ppix2<satlevel)
|
&& (ppix2=*(pdh++))>-BIG && ppix2<satlevel)
|
*(pw++) = 1/sqrt(ppix+(ppix2>0.0?
|
*(pw++) = 1/sqrt(ppix+(ppix2>0.0?
|
(gainflag? ppix2*ppix/pbacknoise2:ppix2)/gain : 0.0));
|
(gainflag? ppix2*ppix/pbacknoise2:ppix2)/gain : 0.0));
|
else
|
else
|
{
|
{
|
*(pw++) = 0.0;
|
*(pw++) = 0.0;
|
wbad++;
|
wbad++;
|
}
|
}
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
psf_copyobjpix(pdatah, NULL, width, height, ix,iy, obj2, 0);
|
psf_copyobjpix(pdatah, NULL, width, height, ix,iy, obj2, 0);
|
for (pw=pweight, pdh=pdatah, p=npix; p--;)
|
for (pw=pweight, pdh=pdatah, p=npix; p--;)
|
if ((ppix=*(pdh++))>-BIG && ppix<satlevel)
|
if ((ppix=*(pdh++))>-BIG && ppix<satlevel)
|
*(pw++) = 1.0/sqrt(pbacknoise2+(ppix>0.0?ppix/gain:0.0));
|
*(pw++) = 1.0/sqrt(pbacknoise2+(ppix>0.0?ppix/gain:0.0));
|
else
|
else
|
{
|
{
|
*(pw++) = 0.0;
|
*(pw++) = 0.0;
|
wbad++;
|
wbad++;
|
}
|
}
|
}
|
}
|
|
|
/* Special action if most of the weights are zero!! */
|
/* Special action if most of the weights are zero!! */
|
if (wbad>=npix-3)
|
if (wbad>=npix-3)
|
return;
|
return;
|
|
|
/* Weight the data */
|
/* Weight the data */
|
pdh = pdatah;
|
pdh = pdatah;
|
pd = pdata;
|
pd = pdata;
|
pw = pweight;
|
pw = pweight;
|
val = obj->dbkg;
|
val = obj2->dbkg;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(pd++) = (*(pdh++)-val)**(pw++);
|
*(pd++) = (*(pdh++)-val)**(pw++);
|
|
|
|
|
/* Get the photmetry PSF */
|
/* Get the photmetry PSF */
|
psf_build(ppsf);
|
psf_build(ppsf, obj2);
|
for (j=1; j<=npsf; j++)
|
for (j=1; j<=npsf; j++)
|
{
|
{
|
if (j>1)
|
if (j>1)
|
{
|
{
|
/*---- Subtract //previously fitted components in photometry image */
|
/*---- Subtract //previously fitted components in photometry image */
|
pd = pdata2;
|
pd = pdata2;
|
pdh = pdatah;
|
pdh = pdatah;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(pd++) = (double)*(pdh++);
|
*(pd++) = (double)*(pdh++);
|
for (k=0; k<j-1; k++)
|
for (k=0; k<j-1; k++)
|
{
|
{
|
pd = pdata2;
|
pd = pdata2;
|
pps = ppsfmasks[k];
|
pps = ppsfmasks[k];
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(pd++) -= pflux[k]**(pps++);
|
*(pd++) -= pflux[k]**(pps++);
|
}
|
}
|
convolve_image(pfield, pdata2, pdata3, width,height);
|
convolve_image(pfield, pdata2, pdata3, width,height);
|
/*---- Ignore regions too close to stellar cores */
|
/*---- Ignore regions too close to stellar cores */
|
for (k=0; k<j-1; k++)
|
for (k=0; k<j-1; k++)
|
{
|
{
|
pd = pdata3;
|
pd = pdata3;
|
dy = -((double)(height/2)+pdeltay[k]);
|
dy = -((double)(height/2)+pdeltay[k]);
|
for (y=height; y--; dy += 1.0)
|
for (y=height; y--; dy += 1.0)
|
{
|
{
|
dx = -((double)(width/2)+pdeltax[k]);
|
dx = -((double)(width/2)+pdeltax[k]);
|
for (x=width; x--; dx+= 1.0, pd++)
|
for (x=width; x--; dx+= 1.0, pd++)
|
if (dx*dx+dy*dy<r2) /*?*/
|
if (dx*dx+dy*dy<r2) /*?*/
|
*pd = -BIG;
|
*pd = -BIG;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
pm=pmat;
|
pm=pmat;
|
for (k=0; k<j; k++)
|
for (k=0; k<j; k++)
|
{
|
{
|
/*------ Resample the PSFs here for the 1st iteration */
|
/*------ Resample the PSFs here for the 1st iteration */
|
vignet_resample(ppsf->maskloc,
|
vignet_resample(ppsf->maskloc,
|
ppsf->masksize[0], ppsf->masksize[1],
|
ppsf->masksize[0], ppsf->masksize[1],
|
ppsfmasks[k], width, height,
|
ppsfmasks[k], width, height,
|
-pdeltax[k]*ppixstep, -pdeltay[k]*ppixstep,
|
-pdeltax[k]*ppixstep, -pdeltay[k]*ppixstep,
|
ppixstep);
|
ppixstep);
|
pm=compute_gradient_phot(pweight,width,height, ppsfmasks[k],pm);
|
pm=compute_gradient_phot(pweight,width,height, ppsfmasks[k],pm);
|
}
|
}
|
|
|
svdfit(pmat, pdata, npix, j, psol, pvmat, pwmat);
|
svdfit(pmat, pdata, npix, j, psol, pvmat, pwmat);
|
compute_pos_phot( &j, psol,pflux);
|
compute_pos_phot( &j, psol,pflux);
|
|
|
for (k=0; k<j; k++)
|
for (k=0; k<j; k++)
|
{
|
{
|
svdvar(pvmat, pwmat, j, pcovmat);
|
svdvar(pvmat, pwmat, j, pcovmat);
|
pvar = pcovmat;
|
pvar = pcovmat;
|
pfluxerr[k]= sqrt(*pvar)>0.0 && sqrt(*pvar)<99?
|
pfluxerr[k]= sqrt(*pvar)>0.0 && sqrt(*pvar)<99?
|
sqrt(*pvar):99;
|
sqrt(*pvar):99;
|
}
|
}
|
}
|
}
|
/* Compute chi2 if asked to
|
/* Compute chi2 if asked to
|
if (FLAG(obj2.chi2_psf))
|
if (FLAG(obj2.chi2_psf))
|
{
|
{
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
chi2 = 0.0;
|
chi2 = 0.0;
|
for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
|
for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
|
{
|
{
|
ppix = *(pd++);
|
ppix = *(pd++);
|
ppix -= ppsfmasks[j][p]*pflux[j]**pw;
|
ppix -= ppsfmasks[j][p]*pflux[j]**pw;
|
chi2 += ppix*ppix;
|
chi2 += ppix*ppix;
|
if (chi2>1E29) chi2=1E28;
|
if (chi2>1E29) chi2=1E28;
|
}
|
}
|
obj2->chi2_psf = obj->sigbkg>0.?
|
obj2->chi2_psf = obj2->sigbkg>0.?
|
chi2/((npix - 3*npsf)*obj->sigbkg*obj->sigbkg):999999;
|
chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
|
|
|
}
|
}
|
|
|
}
|
}
|
*/
|
*/
|
/* Compute relative error if asked to */
|
/* Compute relative error if asked to */
|
if (FLAG(obj2.chi2_psf))
|
if (FLAG(obj2.chi2_psf))
|
{
|
{
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
chi2 = 0.0;
|
chi2 = 0.0;
|
for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
|
for (pd=pdata,pw=pweight,p=0; p<npix; pw++,p++)
|
{
|
{
|
ppix = *(pd++)/pflux[j];
|
ppix = *(pd++)/pflux[j];
|
ppix -= ppsfmasks[j][p]**pw;
|
ppix -= ppsfmasks[j][p]**pw;
|
chi2 += ppix*ppix;
|
chi2 += ppix*ppix;
|
if (chi2>1E29) chi2=1E28;
|
if (chi2>1E29) chi2=1E28;
|
}
|
}
|
obj2->chi2_psf = pflux[j]>0?
|
obj2->chi2_psf = pflux[j]>0?
|
chi2/((npix - 3*npsf)*obj->sigbkg*obj->sigbkg):999999;
|
chi2/((npix - 3*npsf)*obj2->sigbkg*obj2->sigbkg):999999;
|
|
|
}
|
}
|
|
|
}
|
}
|
ppsfit->niter = thepsfit->niter;
|
ppsfit->niter = thepsfit->niter;
|
ppsfit->npsf = npsf;
|
ppsfit->npsf = npsf;
|
|
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
thepsfit->x[j] = ix+pdeltax[j]+1.0;
|
thepsfit->x[j] = ix+pdeltax[j]+1.0;
|
thepsfit->y[j] = iy+pdeltay[j]+1.0;
|
thepsfit->y[j] = iy+pdeltay[j]+1.0;
|
thepsfit->flux[j] = pflux[j];
|
thepsfit->flux[j] = pflux[j];
|
thepsfit->fluxerr[j] = pfluxerr[j];
|
thepsfit->fluxerr[j] = pfluxerr[j];
|
ppsfit->x[j] = ix+pdeltax[j]+1.0;
|
ppsfit->x[j] = ix+pdeltax[j]+1.0;
|
ppsfit->y[j] = iy+pdeltay[j]+1.0;
|
ppsfit->y[j] = iy+pdeltay[j]+1.0;
|
ppsfit->flux[j] = pflux[j];
|
ppsfit->flux[j] = pflux[j];
|
ppsfit->fluxerr[j] = pfluxerr[j];
|
ppsfit->fluxerr[j] = pfluxerr[j];
|
}
|
}
|
|
|
|
|
for (i=0; i<npsfmax; i++)
|
for (i=0; i<npsfmax; i++)
|
{
|
{
|
QFREE(ppsfmasks[i]);
|
QFREE(ppsfmasks[i]);
|
QFREE(ppsfmaskx[i]);
|
QFREE(ppsfmaskx[i]);
|
QFREE(ppsfmasky[i]);
|
QFREE(ppsfmasky[i]);
|
}
|
}
|
|
|
|
|
QFREE(ppsfmasks);
|
QFREE(ppsfmasks);
|
QFREE(ppsfmaskx);
|
QFREE(ppsfmaskx);
|
QFREE(ppsfmasky);
|
QFREE(ppsfmasky);
|
QFREE(pdatah);
|
QFREE(pdatah);
|
QFREE(pdata);
|
QFREE(pdata);
|
QFREE(pdata2);
|
QFREE(pdata2);
|
QFREE(pdata3);
|
QFREE(pdata3);
|
QFREE(pweighth);
|
QFREE(pweighth);
|
QFREE(pweight);
|
QFREE(pweight);
|
QFREE(pdata);
|
QFREE(pdata);
|
QFREE(pmat);
|
QFREE(pmat);
|
|
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS]
|
if (prefs.check[CHECK_SUBPSFPROTOS] || prefs.check[CHECK_PSFPROTOS])
|
|| prefs.check[CHECK_SUBPCPROTOS] || prefs.check[CHECK_PCPROTOS]
|
|
|| prefs.check[CHECK_PCOPROTOS])
|
|
{
|
{
|
QFREE(checkmask);
|
QFREE(checkmask);
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/****** psf_copyobjpix ******************************************************
|
/****** psf_copyobjpix ******************************************************
|
PROTO int psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
|
PROTO int psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
|
int wout, int hout, int ix, int iy,
|
int wout, int hout, int ix, int iy,
|
obj2struct *obj2, int detect_flag);
|
obj2struct *obj2, int detect_flag);
|
PURPOSE Copy a piece of the input object image/weights to local arrays.
|
PURPOSE Copy a piece of the input object image/weights to local arrays.
|
INPUT Pointer to the output data array,
|
INPUT Pointer to the output data array,
|
pointer to the output weight array,
|
pointer to the output weight array,
|
output frame width,
|
output frame width,
|
output frame height,
|
output frame height,
|
integer x coordinate,
|
integer x coordinate,
|
integer y coordinate,
|
integer y coordinate,
|
pointer to the obj2 structure,
|
pointer to the obj2 structure,
|
detection field flag (non 0 only for pure detection images).
|
detection field flag (non 0 only for pure detection images).
|
OUTPUT RETURN_ERROR if the coordinates are outside object image,
|
OUTPUT RETURN_ERROR if the coordinates are outside object image,
|
RETURN_OK otherwise.
|
RETURN_OK otherwise.
|
NOTES -.
|
NOTES -.
|
AUTHOR E. Bertin (IAP)
|
AUTHOR E. Bertin (IAP)
|
VERSION 23/06/2011
|
VERSION 23/06/2011
|
***/
|
***/
|
int psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
|
int psf_copyobjpix(PIXTYPE *data, PIXTYPE *weight,
|
int wout, int hout, int ix, int iy,
|
int wout, int hout, int ix, int iy,
|
obj2struct *obj2, int detect_flag)
|
obj2struct *obj2, int detect_flag)
|
{
|
{
|
PIXTYPE *datat,*weightt, *imagein,*weightin;
|
PIXTYPE *datat,*weightt, *imagein,*weightin;
|
int i,y, win,hin, w2, xmin,xmax,ymin,ymax;
|
int i,y, win,hin, w2, xmin,xmax,ymin,ymax;
|
|
|
/* Set output to -BIG */
|
/* Set output to -BIG */
|
datat = data;
|
datat = data;
|
for (i=wout*hout; i--;)
|
for (i=wout*hout; i--;)
|
*(datat++) = -BIG;
|
*(datat++) = -BIG;
|
if (weight)
|
if (weight)
|
memset(weight, 0, wout*hout*sizeof(PIXTYPE));
|
memset(weight, 0, wout*hout*sizeof(PIXTYPE));
|
|
|
ix -= obj2->immin[0];
|
ix -= obj2->immin[0];
|
iy -= obj2->immin[1];
|
iy -= obj2->immin[1];
|
win = obj2->imsize[0];
|
win = obj2->imsize[0];
|
hin = obj2->imsize[1];
|
hin = obj2->imsize[1];
|
|
|
/* Don't go further if out of frame!! */
|
/* Don't go further if out of frame!! */
|
if (ix<0 || ix>=win || iy<0 || iy>=hin)
|
if (ix<0 || ix>=win || iy<0 || iy>=hin)
|
return RETURN_ERROR;
|
return RETURN_ERROR;
|
|
|
/* Set the image boundaries */
|
/* Set the image boundaries */
|
w2 = wout;
|
w2 = wout;
|
ymin = iy-hout/2;
|
ymin = iy-hout/2;
|
ymax = ymin + hout;
|
ymax = ymin + hout;
|
if (ymin<0)
|
if (ymin<0)
|
{
|
{
|
data -= ymin*wout;
|
data -= ymin*wout;
|
if (weight)
|
if (weight)
|
weight -= ymin*wout;
|
weight -= ymin*wout;
|
ymin = 0;
|
ymin = 0;
|
}
|
}
|
if (ymax>hin)
|
if (ymax>hin)
|
ymax = hin;
|
ymax = hin;
|
|
|
xmin = ix-wout/2;
|
xmin = ix-wout/2;
|
xmax = xmin + wout;
|
xmax = xmin + wout;
|
if (xmax>win)
|
if (xmax>win)
|
{
|
{
|
w2 -= xmax-win;
|
w2 -= xmax-win;
|
xmax = win;
|
xmax = win;
|
}
|
}
|
if (xmin<0)
|
if (xmin<0)
|
{
|
{
|
data -= xmin;
|
data -= xmin;
|
if (weight)
|
if (weight)
|
weight -= xmin;
|
weight -= xmin;
|
w2 += xmin;
|
w2 += xmin;
|
xmin = 0;
|
xmin = 0;
|
}
|
}
|
|
|
/* Copy the right pixels to the destination */
|
/* Copy the right pixels to the destination */
|
imagein = detect_flag? obj2->dimage:obj2->image;
|
imagein = detect_flag? obj2->dimage:obj2->image;
|
for (y=ymin; y<ymax; y++, data += wout)
|
for (y=ymin; y<ymax; y++, data += wout)
|
memcpy(data, imagein + xmin+y*win, w2*sizeof(PIXTYPE));
|
memcpy(data, imagein + xmin+y*win, w2*sizeof(PIXTYPE));
|
if (weight)
|
if (weight)
|
{
|
{
|
weightin = detect_flag? obj2->dweight:obj2->weight;
|
weightin = detect_flag? obj2->dweight:obj2->weight;
|
for (y=ymin; y<ymax; y++, data += wout)
|
for (y=ymin; y<ymax; y++, data += wout)
|
memcpy(weight, weightin + xmin+y*win, w2*sizeof(PIXTYPE));
|
memcpy(weight, weightin + xmin+y*win, w2*sizeof(PIXTYPE));
|
}
|
}
|
|
|
|
|
return RETURN_OK;
|
return RETURN_OK;
|
}
|
}
|
|
|
|
|
|
|
/******************************* psf_build **********************************/
|
/******************************* psf_build **********************************/
|
/*
|
/*
|
Build the local PSF (function of "context").
|
Build the local PSF (function of "context").
|
*/
|
*/
|
void psf_build(psfstruct *psf)
|
void psf_build(psfstruct *psf, obj2struct *obj2)
|
{
|
{
|
static double pos[POLY_MAXDIM];
|
static double pos[POLY_MAXDIM];
|
double *basis, fac;
|
double *basis, fac;
|
float *ppc, *pl;
|
float *ppc, *pl;
|
int i,n,p, ndim, npix;
|
int i,n,p, ndim, npix;
|
|
|
if (psf->build_flag)
|
if (psf->build_flag)
|
return;
|
return;
|
|
|
npix = psf->masksize[0]*psf->masksize[1];
|
npix = psf->masksize[0]*psf->masksize[1];
|
|
|
/* Reset the Local PSF mask */
|
/* Reset the Local PSF mask */
|
memset(psf->maskloc, 0, npix*sizeof(float));
|
memset(psf->maskloc, 0, npix*sizeof(float));
|
|
|
/* Grab the context vector */
|
/* Grab the context vector */
|
ndim = psf->poly->ndim;
|
ndim = psf->poly->ndim;
|
for (i=0; i<ndim; i++)
|
for (i=0; i<ndim; i++)
|
{
|
{
|
ttypeconv(psf->context[i], &pos[i], psf->contexttyp[i],T_DOUBLE);
|
ttypeconv((char *)obj2 + ((void *)psf->context[i]-(void *)&flagobj2),
|
|
&pos[i], psf->contexttyp[i],T_DOUBLE);
|
pos[i] = (pos[i] - psf->contextoffset[i]) / psf->contextscale[i];
|
pos[i] = (pos[i] - psf->contextoffset[i]) / psf->contextscale[i];
|
}
|
}
|
poly_func(psf->poly, pos);
|
poly_func(psf->poly, pos);
|
|
|
basis = psf->poly->basis;
|
basis = psf->poly->basis;
|
|
|
ppc = psf->maskcomp;
|
ppc = psf->maskcomp;
|
/* Sum each component */
|
/* Sum each component */
|
for (n = (psf->maskdim>2?psf->masksize[2]:1); n--;)
|
for (n = (psf->maskdim>2?psf->masksize[2]:1); n--;)
|
{
|
{
|
pl = psf->maskloc;
|
pl = psf->maskloc;
|
fac = *(basis++);
|
fac = *(basis++);
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
*(pl++) += fac**(ppc++);
|
*(pl++) += fac**(ppc++);
|
}
|
}
|
|
|
psf->build_flag = 1;
|
psf->build_flag = 1;
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/******************************** psf_fwhm **********************************/
|
/******************************** psf_fwhm **********************************/
|
/*
|
/*
|
Return the local PSF FWHM.
|
Return the local PSF FWHM.
|
*/
|
*/
|
double psf_fwhm(psfstruct *psf)
|
double psf_fwhm(psfstruct *psf, obj2struct *obj2)
|
{
|
{
|
float *pl,
|
float *pl,
|
val, max;
|
val, max;
|
int n,p, npix;
|
int n,p, npix;
|
|
|
if (!psf->build_flag)
|
if (!psf->build_flag)
|
psf_build(psf);
|
psf_build(psf, obj2);
|
|
|
npix = psf->masksize[0]*psf->masksize[1];
|
npix = psf->masksize[0]*psf->masksize[1];
|
max = -BIG;
|
max = -BIG;
|
pl = psf->maskloc;
|
pl = psf->maskloc;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
if ((val=*(pl++)) > max)
|
if ((val=*(pl++)) > max)
|
max = val;
|
max = val;
|
pl = psf->maskloc;
|
pl = psf->maskloc;
|
max /= 2.0;
|
max /= 2.0;
|
n = 0;
|
n = 0;
|
for (p=npix; p--;)
|
for (p=npix; p--;)
|
if (*(pl++) >= max)
|
if (*(pl++) >= max)
|
n++;
|
n++;
|
|
|
return 2.0*sqrt(n/PI)*psf->pixstep;
|
return 2.0*sqrt(n/PI)*psf->pixstep;
|
}
|
}
|
|
|
|
|
/*****************************compute_gradient*********************************/
|
/*****************************compute_gradient*********************************/
|
|
|
double *compute_gradient(float *weight,int width, int height,
|
double *compute_gradient(float *weight,int width, int height,
|
float *masks,float *maskx,float *masky
|
float *masks,float *maskx,float *masky
|
,double *m)
|
,double *m)
|
{
|
{
|
int x,y;
|
int x,y;
|
float *w, *ps,*px,*py;
|
float *w, *ps,*px,*py;
|
|
|
/*------ copy of the (weighted) PSF, with outer ring set to zero */
|
/*------ copy of the (weighted) PSF, with outer ring set to zero */
|
ps = masks;
|
ps = masks;
|
w = weight;
|
w = weight;
|
for (y=0; y<height; y++)
|
for (y=0; y<height; y++)
|
for (x=0; x<width; x++, ps++, w++)
|
for (x=0; x<width; x++, ps++, w++)
|
*(m++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*ps**w):0)):0;
|
*(m++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*ps**w):0)):0;
|
/*------ (weighted) PSF gradient in x (kernel for first moment in x) */
|
/*------ (weighted) PSF gradient in x (kernel for first moment in x) */
|
ps = masks;
|
ps = masks;
|
px = maskx;
|
px = maskx;
|
w = weight;
|
w = weight;
|
for (y=0; y<height; y++)
|
for (y=0; y<height; y++)
|
for (x=0; x<width; x++, ps++, w++)
|
for (x=0; x<width; x++, ps++, w++)
|
*(m++) = ((*px++) = (x?(x>=(width-1)?0:*(ps+1)-*(ps-1)):0))**w/2;
|
*(m++) = ((*px++) = (x?(x>=(width-1)?0:*(ps+1)-*(ps-1)):0))**w/2;
|
/*------ (weighted) PSF gradient in y (kernel for first moment in y) */
|
/*------ (weighted) PSF gradient in y (kernel for first moment in y) */
|
ps = masks;
|
ps = masks;
|
py = masky;
|
py = masky;
|
w = weight;
|
w = weight;
|
for (y=0; y<height; y++)
|
for (y=0; y<height; y++)
|
for (x=0; x<width; x++, ps++, w++)
|
for (x=0; x<width; x++, ps++, w++)
|
*(m++) = (*(py++)=(y?(y>=(height-1)?0:*(ps+width)-*(ps-width)):0))
|
*(m++) = (*(py++)=(y?(y>=(height-1)?0:*(ps+width)-*(ps-width)):0))
|
**w/2;
|
**w/2;
|
return m;
|
return m;
|
}
|
}
|
|
|
/*****************************compute_gradient_phot*****************************
|
/*****************************compute_gradient_phot*****************************
|
****/
|
****/
|
|
|
double *compute_gradient_phot(float *pweight,int width, int height,
|
double *compute_gradient_phot(float *pweight,int width, int height,
|
float *pmasks,double *pm)
|
float *pmasks,double *pm)
|
|
|
{
|
{
|
int x,y;
|
int x,y;
|
float *pw, *pps;
|
float *pw, *pps;
|
|
|
/*------ copy of the (weighted) PSF, with outer ring set to zero */
|
/*------ copy of the (weighted) PSF, with outer ring set to zero */
|
pps = pmasks;
|
pps = pmasks;
|
pw = pweight;
|
pw = pweight;
|
for (y=0; y<height; y++)
|
for (y=0; y<height; y++)
|
for (x=0; x<width; x++, pps++, pw++)
|
for (x=0; x<width; x++, pps++, pw++)
|
*(pm++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*pps**pw):0)):0;
|
*(pm++) = y?(y>=(height-1)?0:(x?(x>=(width-1)?0:*pps**pw):0)):0;
|
|
|
return pm;
|
return pm;
|
}
|
}
|
|
|
/**************************compute_pos********************************/
|
/**************************compute_pos********************************/
|
|
|
void compute_pos(int *pnpsf,int *pconvflag,int *pnpsfflag,double radmin2,
|
void compute_pos(int *pnpsf,int *pconvflag,int *pnpsfflag,double radmin2,
|
double radmax2,double r2,double *sol,double *flux
|
double radmax2,double r2,double *sol,double *flux
|
,double *deltax,double *deltay,double *pdx,double *pdy)
|
,double *deltax,double *deltay,double *pdx,double *pdy)
|
{
|
{
|
int j,k,convflag,npsfflag,npsf;
|
int j,k,convflag,npsfflag,npsf;
|
double dx,dy;
|
double dx,dy;
|
|
|
dx=*pdx;
|
dx=*pdx;
|
dy=*pdy;
|
dy=*pdy;
|
convflag=*pconvflag;
|
convflag=*pconvflag;
|
npsfflag=*pnpsfflag;
|
npsfflag=*pnpsfflag;
|
npsf=*pnpsf;
|
npsf=*pnpsf;
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
flux[j] = sol[j*PSF_NA];
|
flux[j] = sol[j*PSF_NA];
|
/*------ Update the PSF shifts */
|
/*------ Update the PSF shifts */
|
if (fabs(flux[j])>0.0)
|
if (fabs(flux[j])>0.0)
|
{
|
{
|
dx = -sol[j*PSF_NA+1]/((npsf>1?2:1)*flux[j]);
|
dx = -sol[j*PSF_NA+1]/((npsf>1?2:1)*flux[j]);
|
dy = -sol[j*PSF_NA+2]/((npsf>1?2:1)*flux[j]);
|
dy = -sol[j*PSF_NA+2]/((npsf>1?2:1)*flux[j]);
|
}
|
}
|
|
|
deltax[j] += dx;
|
deltax[j] += dx;
|
deltay[j] += dy;
|
deltay[j] += dy;
|
/*------ Continue until all PSFs have come to a complete stop */
|
/*------ Continue until all PSFs have come to a complete stop */
|
if ((dx*dx+dy*dy) > radmin2)
|
if ((dx*dx+dy*dy) > radmin2)
|
convflag = 1;
|
convflag = 1;
|
}
|
}
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
/*------ Exit if too much decentering or negative flux */
|
/*------ Exit if too much decentering or negative flux */
|
for (k=j+1; k<npsf; k++)
|
for (k=j+1; k<npsf; k++)
|
{
|
{
|
dx = deltax[j]-deltax[k];
|
dx = deltax[j]-deltax[k];
|
dy = deltay[j]-deltay[k];
|
dy = deltay[j]-deltay[k];
|
if (dx*dx+dy*dy<r2/4.0)
|
if (dx*dx+dy*dy<r2/4.0)
|
{
|
{
|
flux[j] = -BIG;
|
flux[j] = -BIG;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
if (flux[j]<0.0
|
if (flux[j]<0.0
|
|| (deltax[j]*deltax[j] + deltay[j]*deltay[j]) > radmax2)
|
|| (deltax[j]*deltax[j] + deltay[j]*deltay[j]) > radmax2)
|
{
|
{
|
npsfflag = 0;
|
npsfflag = 0;
|
convflag = 0;
|
convflag = 0;
|
npsf--;
|
npsf--;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
*pdx=dx;
|
*pdx=dx;
|
*pdy=dy;
|
*pdy=dy;
|
*pconvflag=convflag;
|
*pconvflag=convflag;
|
*pnpsfflag= npsfflag;
|
*pnpsfflag= npsfflag;
|
*pnpsf=npsf;
|
*pnpsf=npsf;
|
return;
|
return;
|
}
|
}
|
|
|
/**************************compute_pos_phot********************************/
|
/**************************compute_pos_phot********************************/
|
|
|
void compute_pos_phot(int *pnpsf,double *sol,double *flux)
|
void compute_pos_phot(int *pnpsf,double *sol,double *flux)
|
{
|
{
|
int j,npsf;
|
int j,npsf;
|
npsf=*pnpsf;
|
npsf=*pnpsf;
|
for (j=0; j<npsf; j++)
|
for (j=0; j<npsf; j++)
|
{
|
{
|
flux[j] = sol[j];
|
flux[j] = sol[j];
|
}
|
}
|
*pnpsf=npsf;
|
*pnpsf=npsf;
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/************************************compute_poserr*****************************
|
/************************************compute_poserr*****************************
|
*********/
|
*********/
|
|
|
void compute_poserr( int j,double *var,double *sol,obj2struct *obj2,double *x2,
|
void compute_poserr( int j,double *var,double *sol,obj2struct *obj2,double *x2,
|
double *y2,double *xy, int npsf)
|
double *y2,double *xy, int npsf)
|
{
|
{
|
double vara,covab,varb, f2;
|
double vara,covab,varb, f2;
|
|
|
/*------ Variances and covariance along x and y */
|
/*------ Variances and covariance along x and y */
|
vara = *(var += (PSF_NA*npsf+1)*(j*PSF_NA+1));
|
vara = *(var += (PSF_NA*npsf+1)*(j*PSF_NA+1));
|
covab = *(++var);
|
covab = *(++var);
|
varb = *(var += PSF_NA*npsf);
|
varb = *(var += PSF_NA*npsf);
|
f2 = sol[PSF_NA*j];
|
f2 = sol[PSF_NA*j];
|
f2 *= f2;
|
f2 *= f2;
|
obj2->poserrmx2_psf = vara/f2;
|
obj2->poserrmx2_psf = vara/f2;
|
obj2->poserrmy2_psf = varb/f2;
|
obj2->poserrmy2_psf = varb/f2;
|
obj2->poserrmxy_psf = covab/f2;
|
obj2->poserrmxy_psf = covab/f2;
|
|
|
/*------ If requested, translate variances to major and minor error axes... */
|
/*------ If requested, translate variances to major and minor error axes... */
|
if (FLAG(obj2.poserra_psf))
|
if (FLAG(obj2.poserra_psf))
|
{
|
{
|
double pmx2,pmy2,temp,theta;
|
double pmx2,pmy2,temp,theta;
|
|
|
if (fabs(temp=obj2->poserrmx2_psf-obj2->poserrmy2_psf) > 0.0)
|
if (fabs(temp=obj2->poserrmx2_psf-obj2->poserrmy2_psf) > 0.0)
|
theta = atan2(2.0 * obj2->poserrmxy_psf,temp) / 2.0;
|
theta = atan2(2.0 * obj2->poserrmxy_psf,temp) / 2.0;
|
else
|
else
|
theta = PI/4.0;
|
theta = PI/4.0;
|
|
|
temp = sqrt(0.25*temp*temp+obj2->poserrmxy_psf*obj2->poserrmxy_psf);
|
temp = sqrt(0.25*temp*temp+obj2->poserrmxy_psf*obj2->poserrmxy_psf);
|
pmy2 = pmx2 = 0.5*(obj2->poserrmx2_psf+obj2->poserrmy2_psf);
|
pmy2 = pmx2 = 0.5*(obj2->poserrmx2_psf+obj2->poserrmy2_psf);
|
pmx2+=temp;
|
pmx2+=temp;
|
pmy2-=temp;
|
pmy2-=temp;
|
|
|
obj2->poserra_psf = (float)sqrt(pmx2);
|
obj2->poserra_psf = (float)sqrt(pmx2);
|
obj2->poserrb_psf = (float)sqrt(pmy2);
|
obj2->poserrb_psf = (float)sqrt(pmy2);
|
obj2->poserrtheta_psf = theta*180.0/PI;
|
obj2->poserrtheta_psf = theta*180.0/PI;
|
}
|
}
|
|
|
/*------ ...Or ellipse parameters */
|
/*------ ...Or ellipse parameters */
|
if (FLAG(obj2.poserr_cxx))
|
if (FLAG(obj2.poserr_cxx))
|
{
|
{
|
double xm2,ym2, xym, temp;
|
double xm2,ym2, xym, temp;
|
|
|
xm2 = obj2->poserrmx2_psf;
|
xm2 = obj2->poserrmx2_psf;
|
ym2 = obj2->poserrmy2_psf;
|
ym2 = obj2->poserrmy2_psf;
|
xym = obj2->poserrmxy_psf;
|
xym = obj2->poserrmxy_psf;
|
obj2->poserrcxx_psf = (float)(ym2/(temp=xm2*ym2-xym*xym));
|
obj2->poserrcxx_psf = (float)(ym2/(temp=xm2*ym2-xym*xym));
|
obj2->poserrcyy_psf = (float)(xm2/temp);
|
obj2->poserrcyy_psf = (float)(xm2/temp);
|
obj2->poserrcxy_psf = (float)(-2*xym/temp);
|
obj2->poserrcxy_psf = (float)(-2*xym/temp);
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
|
|
/******************************** svdfit ************************************/
|
/******************************** svdfit ************************************/
|
/*
|
/*
|
General least-square fit A.x = b, based on Singular Value Decomposition (SVD).
|
General least-square fit A.x = b, based on Singular Value Decomposition (SVD).
|
Loosely adapted from Numerical Recipes in C, 2nd Ed. (p. 671).
|
Loosely adapted from Numerical Recipes in C, 2nd Ed. (p. 671).
|
Note: the a and v matrices are transposed with respect to the N.R. convention.
|
Note: the a and v matrices are transposed with respect to the N.R. convention.
|
*/
|
*/
|
void svdfit(double *a, float *b, int m, int n, double *sol,
|
void svdfit(double *a, float *b, int m, int n, double *sol,
|
double *vmat, double *wmat)
|
double *vmat, double *wmat)
|
{
|
{
|
#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
|
#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
|
(maxarg1) : (maxarg2))
|
(maxarg1) : (maxarg2))
|
#define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
|
#define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
|
(ct=bt/at,at*sqrt(1.0+ct*ct)) \
|
(ct=bt/at,at*sqrt(1.0+ct*ct)) \
|
: (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
|
: (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
|
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
|
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
|
#define TOL 1.0e-11
|
#define TOL 1.0e-11
|
|
|
int flag,i,its,j,jj,k,l,nm,mmi,nml;
|
int flag,i,its,j,jj,k,l,nm,mmi,nml;
|
double c,f,h,s,x,y,z,
|
double c,f,h,s,x,y,z,
|
anorm, g, scale,
|
anorm, g, scale,
|
at,bt,ct,maxarg1,maxarg2,
|
at,bt,ct,maxarg1,maxarg2,
|
thresh, wmax,
|
thresh, wmax,
|
*w,*ap,*ap0,*ap1,*ap10,*rv1p,*vp,*vp0,*vp1,*vp10,
|
*w,*ap,*ap0,*ap1,*ap10,*rv1p,*vp,*vp0,*vp1,*vp10,
|
*tmpp, *rv1,*tmp;
|
*tmpp, *rv1,*tmp;
|
float *bp;
|
float *bp;
|
|
|
anorm = g = scale = 0.0;
|
anorm = g = scale = 0.0;
|
if (m < n)
|
if (m < n)
|
error(EXIT_FAILURE, "*Error*: Not enough rows for solving the system ",
|
error(EXIT_FAILURE, "*Error*: Not enough rows for solving the system ",
|
"in svdfit()");
|
"in svdfit()");
|
|
|
QMALLOC(rv1, double, n);
|
QMALLOC(rv1, double, n);
|
QMALLOC(tmp, double, n);
|
QMALLOC(tmp, double, n);
|
l = nm = nml = 0; /* To avoid gcc -Wall warnings */
|
l = nm = nml = 0; /* To avoid gcc -Wall warnings */
|
for (i=0;i<n;i++)
|
for (i=0;i<n;i++)
|
{
|
{
|
l = i+1;
|
l = i+1;
|
nml = n-l;
|
nml = n-l;
|
rv1[i] = scale*g;
|
rv1[i] = scale*g;
|
g = s = scale = 0.0;
|
g = s = scale = 0.0;
|
if ((mmi = m - i) > 0)
|
if ((mmi = m - i) > 0)
|
{
|
{
|
ap = ap0 = a+i*(m+1);
|
ap = ap0 = a+i*(m+1);
|
for (k=mmi;k--;)
|
for (k=mmi;k--;)
|
scale += fabs(*(ap++));
|
scale += fabs(*(ap++));
|
if (scale)
|
if (scale)
|
{
|
{
|
for (ap=ap0,k=mmi; k--; ap++)
|
for (ap=ap0,k=mmi; k--; ap++)
|
{
|
{
|
*ap /= scale;
|
*ap /= scale;
|
s += *ap**ap;
|
s += *ap**ap;
|
}
|
}
|
f = *ap0;
|
f = *ap0;
|
g = -SIGN(sqrt(s),f);
|
g = -SIGN(sqrt(s),f);
|
h = f*g-s;
|
h = f*g-s;
|
*ap0 = f-g;
|
*ap0 = f-g;
|
ap10 = a+l*m+i;
|
ap10 = a+l*m+i;
|
for (j=nml;j--; ap10+=m)
|
for (j=nml;j--; ap10+=m)
|
{
|
{
|
for (s=0.0,ap=ap0,ap1=ap10,k=mmi; k--;)
|
for (s=0.0,ap=ap0,ap1=ap10,k=mmi; k--;)
|
s += *(ap1++)**(ap++);
|
s += *(ap1++)**(ap++);
|
f = s/h;
|
f = s/h;
|
for (ap=ap0,ap1=ap10,k=mmi; k--;)
|
for (ap=ap0,ap1=ap10,k=mmi; k--;)
|
*(ap1++) += f**(ap++);
|
*(ap1++) += f**(ap++);
|
}
|
}
|
for (ap=ap0,k=mmi; k--;)
|
for (ap=ap0,k=mmi; k--;)
|
*(ap++) *= scale;
|
*(ap++) *= scale;
|
}
|
}
|
}
|
}
|
wmat[i] = scale*g;
|
wmat[i] = scale*g;
|
g = s = scale = 0.0;
|
g = s = scale = 0.0;
|
if (i < m && i+1 != n)
|
if (i < m && i+1 != n)
|
{
|
{
|
ap = ap0 = a+i+m*l;
|
ap = ap0 = a+i+m*l;
|
for (k=nml;k--; ap+=m)
|
for (k=nml;k--; ap+=m)
|
scale += fabs(*ap);
|
scale += fabs(*ap);
|
if (scale)
|
if (scale)
|
{
|
{
|
for (ap=ap0,k=nml;k--; ap+=m)
|
for (ap=ap0,k=nml;k--; ap+=m)
|
{
|
{
|
*ap /= scale;
|
*ap /= scale;
|
s += *ap**ap;
|
s += *ap**ap;
|
}
|
}
|
f=*ap0;
|
f=*ap0;
|
g = -SIGN(sqrt(s),f);
|
g = -SIGN(sqrt(s),f);
|
h=f*g-s;
|
h=f*g-s;
|
*ap0=f-g;
|
*ap0=f-g;
|
rv1p = rv1+l;
|
rv1p = rv1+l;
|
for (ap=ap0,k=nml;k--; ap+=m)
|
for (ap=ap0,k=nml;k--; ap+=m)
|
*(rv1p++) = *ap/h;
|
*(rv1p++) = *ap/h;
|
ap10 = a+l+m*l;
|
ap10 = a+l+m*l;
|
for (j=m-l; j--; ap10++)
|
for (j=m-l; j--; ap10++)
|
{
|
{
|
for (s=0.0,ap=ap0,ap1=ap10,k=nml; k--; ap+=m,ap1+=m)
|
for (s=0.0,ap=ap0,ap1=ap10,k=nml; k--; ap+=m,ap1+=m)
|
s += *ap1**ap;
|
s += *ap1**ap;
|
rv1p = rv1+l;
|
rv1p = rv1+l;
|
for (ap1=ap10,k=nml;k--; ap1+=m)
|
for (ap1=ap10,k=nml;k--; ap1+=m)
|
*ap1 += s**(rv1p++);
|
*ap1 += s**(rv1p++);
|
}
|
}
|
for (ap=ap0,k=nml;k--; ap+=m)
|
for (ap=ap0,k=nml;k--; ap+=m)
|
*ap *= scale;
|
*ap *= scale;
|
}
|
}
|
}
|
}
|
anorm=MAX(anorm,(fabs(wmat[i])+fabs(rv1[i])));
|
anorm=MAX(anorm,(fabs(wmat[i])+fabs(rv1[i])));
|
}
|
}
|
|
|
for (i=n-1;i>=0;i--)
|
for (i=n-1;i>=0;i--)
|
{
|
{
|
if (i < n-1)
|
if (i < n-1)
|
{
|
{
|
if (g)
|
if (g)
|
{
|
{
|
ap0 = a+l*m+i;
|
ap0 = a+l*m+i;
|
vp0 = vmat+i*n+l;
|
vp0 = vmat+i*n+l;
|
vp10 = vmat+l*n+l;
|
vp10 = vmat+l*n+l;
|
g *= *ap0;
|
g *= *ap0;
|
for (ap=ap0,vp=vp0,j=nml; j--; ap+=m)
|
for (ap=ap0,vp=vp0,j=nml; j--; ap+=m)
|
*(vp++) = *ap/g;
|
*(vp++) = *ap/g;
|
for (j=nml; j--; vp10+=n)
|
for (j=nml; j--; vp10+=n)
|
{
|
{
|
for (s=0.0,ap=ap0,vp1=vp10,k=nml; k--; ap+=m)
|
for (s=0.0,ap=ap0,vp1=vp10,k=nml; k--; ap+=m)
|
s += *ap**(vp1++);
|
s += *ap**(vp1++);
|
for (vp=vp0,vp1=vp10,k=nml; k--;)
|
for (vp=vp0,vp1=vp10,k=nml; k--;)
|
*(vp1++) += s**(vp++);
|
*(vp1++) += s**(vp++);
|
}
|
}
|
}
|
}
|
vp = vmat+l*n+i;
|
vp = vmat+l*n+i;
|
vp1 = vmat+i*n+l;
|
vp1 = vmat+i*n+l;
|
for (j=nml; j--; vp+=n)
|
for (j=nml; j--; vp+=n)
|
*vp = *(vp1++) = 0.0;
|
*vp = *(vp1++) = 0.0;
|
}
|
}
|
vmat[i*n+i]=1.0;
|
vmat[i*n+i]=1.0;
|
g=rv1[i];
|
g=rv1[i];
|
l=i;
|
l=i;
|
nml = n-l;
|
nml = n-l;
|
}
|
}
|
|
|
for (i=(m<n?m:n); --i>=0;)
|
for (i=(m<n?m:n); --i>=0;)
|
{
|
{
|
l=i+1;
|
l=i+1;
|
nml = n-l;
|
nml = n-l;
|
mmi=m-i;
|
mmi=m-i;
|
g=wmat[i];
|
g=wmat[i];
|
ap0 = a+i*m+i;
|
ap0 = a+i*m+i;
|
ap10 = ap0 + m;
|
ap10 = ap0 + m;
|
for (ap=ap10,j=nml;j--;ap+=m)
|
for (ap=ap10,j=nml;j--;ap+=m)
|
*ap=0.0;
|
*ap=0.0;
|
if (g)
|
if (g)
|
{
|
{
|
g=1.0/g;
|
g=1.0/g;
|
for (j=nml;j--; ap10+=m)
|
for (j=nml;j--; ap10+=m)
|
{
|
{
|
for (s=0.0,ap=ap0,ap1=ap10,k=mmi; --k;)
|
for (s=0.0,ap=ap0,ap1=ap10,k=mmi; --k;)
|
s += *(++ap)**(++ap1);
|
s += *(++ap)**(++ap1);
|
f = (s/(*ap0))*g;
|
f = (s/(*ap0))*g;
|
for (ap=ap0,ap1=ap10,k=mmi;k--;)
|
for (ap=ap0,ap1=ap10,k=mmi;k--;)
|
*(ap1++) += f**(ap++);
|
*(ap1++) += f**(ap++);
|
}
|
}
|
for (ap=ap0,j=mmi;j--;)
|
for (ap=ap0,j=mmi;j--;)
|
*(ap++) *= g;
|
*(ap++) *= g;
|
}
|
}
|
else
|
else
|
for (ap=ap0,j=mmi;j--;)
|
for (ap=ap0,j=mmi;j--;)
|
*(ap++)=0.0;
|
*(ap++)=0.0;
|
++(*ap0);
|
++(*ap0);
|
}
|
}
|
|
|
for (k=n; --k>=0;)
|
for (k=n; --k>=0;)
|
{
|
{
|
for (its=0;its<100;its++)
|
for (its=0;its<100;its++)
|
{
|
{
|
flag=1;
|
flag=1;
|
for (l=k;l>=0;l--)
|
for (l=k;l>=0;l--)
|
{
|
{
|
nm=l-1;
|
nm=l-1;
|
if (fabs(rv1[l])+anorm == anorm)
|
if (fabs(rv1[l])+anorm == anorm)
|
{
|
{
|
flag=0;
|
flag=0;
|
break;
|
break;
|
}
|
}
|
if (fabs(wmat[nm])+anorm == anorm)
|
if (fabs(wmat[nm])+anorm == anorm)
|
break;
|
break;
|
}
|
}
|
if (flag)
|
if (flag)
|
{
|
{
|
c=0.0;
|
c=0.0;
|
s=1.0;
|
s=1.0;
|
ap0 = a+nm*m;
|
ap0 = a+nm*m;
|
ap10 = a+l*m;
|
ap10 = a+l*m;
|
for (i=l; i<=k; i++,ap10+=m)
|
for (i=l; i<=k; i++,ap10+=m)
|
{
|
{
|
f=s*rv1[i];
|
f=s*rv1[i];
|
if (fabs(f)+anorm == anorm)
|
if (fabs(f)+anorm == anorm)
|
break;
|
break;
|
g=wmat[i];
|
g=wmat[i];
|
h=PYTHAG(f,g);
|
h=PYTHAG(f,g);
|
wmat[i]=h;
|
wmat[i]=h;
|
h=1.0/h;
|
h=1.0/h;
|
c=g*h;
|
c=g*h;
|
s=(-f*h);
|
s=(-f*h);
|
for (ap=ap0,ap1=ap10,j=m; j--;)
|
for (ap=ap0,ap1=ap10,j=m; j--;)
|
{
|
{
|
z = *ap1;
|
z = *ap1;
|
y = *ap;
|
y = *ap;
|
*(ap++) = y*c+z*s;
|
*(ap++) = y*c+z*s;
|
*(ap1++) = z*c-y*s;
|
*(ap1++) = z*c-y*s;
|
}
|
}
|
}
|
}
|
}
|
}
|
z=wmat[k];
|
z=wmat[k];
|
if (l == k)
|
if (l == k)
|
{
|
{
|
if (z < 0.0)
|
if (z < 0.0)
|
{
|
{
|
wmat[k] = -z;
|
wmat[k] = -z;
|
vp = vmat+k*n;
|
vp = vmat+k*n;
|
for (j=n; j--; vp++)
|
for (j=n; j--; vp++)
|
*vp = (-*vp);
|
*vp = (-*vp);
|
}
|
}
|
break;
|
break;
|
}
|
}
|
if (its == 99)
|
if (its == 99)
|
error(EXIT_FAILURE, "*Error*: No convergence in 100 SVD iterations ",
|
error(EXIT_FAILURE, "*Error*: No convergence in 100 SVD iterations ",
|
"in svdfit()");
|
"in svdfit()");
|
x=wmat[l];
|
x=wmat[l];
|
nm=k-1;
|
nm=k-1;
|
y=wmat[nm];
|
y=wmat[nm];
|
g=rv1[nm];
|
g=rv1[nm];
|
h=rv1[k];
|
h=rv1[k];
|
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
|
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
|
g=PYTHAG(f,1.0);
|
g=PYTHAG(f,1.0);
|
f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
|
f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
|
c=s=1.0;
|
c=s=1.0;
|
ap10 = a+l*m;
|
ap10 = a+l*m;
|
vp10 = vmat+l*n;
|
vp10 = vmat+l*n;
|
for (j=l;j<=nm;j++,ap10+=m,vp10+=n)
|
for (j=l;j<=nm;j++,ap10+=m,vp10+=n)
|
{
|
{
|
i=j+1;
|
i=j+1;
|
g=rv1[i];
|
g=rv1[i];
|
y=wmat[i];
|
y=wmat[i];
|
h=s*g;
|
h=s*g;
|
g=c*g;
|
g=c*g;
|
z=PYTHAG(f,h);
|
z=PYTHAG(f,h);
|
rv1[j]=z;
|
rv1[j]=z;
|
c=f/z;
|
c=f/z;
|
s=h/z;
|
s=h/z;
|
f=x*c+g*s;
|
f=x*c+g*s;
|
g=g*c-x*s;
|
g=g*c-x*s;
|
h=y*s;
|
h=y*s;
|
y=y*c;
|
y=y*c;
|
for (vp=(vp1=vp10)+n,jj=n; jj--;)
|
for (vp=(vp1=vp10)+n,jj=n; jj--;)
|
{
|
{
|
z = *vp;
|
z = *vp;
|
x = *vp1;
|
x = *vp1;
|
*(vp1++) = x*c+z*s;
|
*(vp1++) = x*c+z*s;
|
*(vp++) = z*c-x*s;
|
*(vp++) = z*c-x*s;
|
}
|
}
|
z=PYTHAG(f,h);
|
z=PYTHAG(f,h);
|
wmat[j]=z;
|
wmat[j]=z;
|
if (z)
|
if (z)
|
{
|
{
|
z=1.0/z;
|
z=1.0/z;
|
c=f*z;
|
c=f*z;
|
s=h*z;
|
s=h*z;
|
}
|
}
|
f=c*g+s*y;
|
f=c*g+s*y;
|
x=c*y-s*g;
|
x=c*y-s*g;
|
for (ap=(ap1=ap10)+m,jj=m; jj--;)
|
for (ap=(ap1=ap10)+m,jj=m; jj--;)
|
{
|
{
|
z = *ap;
|
z = *ap;
|
y = *ap1;
|
y = *ap1;
|
*(ap1++) = y*c+z*s;
|
*(ap1++) = y*c+z*s;
|
*(ap++) = z*c-y*s;
|
*(ap++) = z*c-y*s;
|
}
|
}
|
}
|
}
|
rv1[l]=0.0;
|
rv1[l]=0.0;
|
rv1[k]=f;
|
rv1[k]=f;
|
wmat[k]=x;
|
wmat[k]=x;
|
}
|
}
|
}
|
}
|
|
|
wmax=0.0;
|
wmax=0.0;
|
w = wmat;
|
w = wmat;
|
for (j=n;j--; w++)
|
for (j=n;j--; w++)
|
if (*w > wmax)
|
if (*w > wmax)
|
wmax=*w;
|
wmax=*w;
|
thresh=TOL*wmax;
|
thresh=TOL*wmax;
|
w = wmat;
|
w = wmat;
|
for (j=n;j--; w++)
|
for (j=n;j--; w++)
|
if (*w < thresh)
|
if (*w < thresh)
|
*w = 0.0;
|
*w = 0.0;
|
|
|
w = wmat;
|
w = wmat;
|
ap = a;
|
ap = a;
|
tmpp = tmp;
|
tmpp = tmp;
|
for (j=n; j--; w++)
|
for (j=n; j--; w++)
|
{
|
{
|
s=0.0;
|
s=0.0;
|
if (*w)
|
if (*w)
|
{
|
{
|
bp = b;
|
bp = b;
|
for (i=m; i--;)
|
for (i=m; i--;)
|
s += *(ap++)**(bp++);
|
s += *(ap++)**(bp++);
|
s /= *w;
|
s /= *w;
|
}
|
}
|
else
|
else
|
ap += m;
|
ap += m;
|
*(tmpp++) = s;
|
*(tmpp++) = s;
|
}
|
}
|
|
|
vp0 = vmat;
|
vp0 = vmat;
|
for (j=0; j<n; j++,vp0++)
|
for (j=0; j<n; j++,vp0++)
|
{
|
{
|
s=0.0;
|
s=0.0;
|
tmpp = tmp;
|
tmpp = tmp;
|
for (vp=vp0,jj=n; jj--; vp+=n)
|
for (vp=vp0,jj=n; jj--; vp+=n)
|
s += *vp**(tmpp++);
|
s += *vp**(tmpp++);
|
sol[j]=s;
|
sol[j]=s;
|
}
|
}
|
|
|
/* Free temporary arrays */
|
/* Free temporary arrays */
|
free(tmp);
|
free(tmp);
|
free(rv1);
|
free(rv1);
|
|
|
return;
|
return;
|
}
|
}
|
|
|
#undef SIGN
|
#undef SIGN
|
#undef MAX
|
#undef MAX
|
#undef PYTHAG
|
#undef PYTHAG
|
#undef TOL
|
#undef TOL
|
|
|
/******************************** svdvar ************************************/
|
/******************************** svdvar ************************************/
|
/*
|
/*
|
Computation of the covariance matrix from the SVD vmat and wmat matrices.A
|
Computation of the covariance matrix from the SVD vmat and wmat matrices.A
|
dapted from Numerical Recipes in C, 2nd Ed. (p. 679).
|
dapted from Numerical Recipes in C, 2nd Ed. (p. 679).
|
*/
|
*/
|
void svdvar(double *v, double *w, int n, double *cov)
|
void svdvar(double *v, double *w, int n, double *cov)
|
{
|
{
|
static double wti[PSF_NTOT];
|
static double wti[PSF_NTOT];
|
double sum;
|
double sum;
|
int i,j,k;
|
int i,j,k;
|
|
|
for (i=0; i<n; i++)
|
for (i=0; i<n; i++)
|
wti[i] = w[i]? 1.0/(w[i]*w[i]) : 0.0;
|
wti[i] = w[i]? 1.0/(w[i]*w[i]) : 0.0;
|
|
|
for (i=0; i<n; i++)
|
for (i=0; i<n; i++)
|
for (j=0; j<=i; j++)
|
for (j=0; j<=i; j++)
|
{
|
{
|
for (sum=0.0,k=0; k<n; k++)
|
for (sum=0.0,k=0; k<n; k++)
|
sum += v[k*n+i]*v[k*n+j]*wti[k];
|
sum += v[k*n+i]*v[k*n+j]*wti[k];
|
cov[j*n+i] = cov[i*n+j] = sum;
|
cov[j*n+i] = cov[i*n+j] = sum;
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
|