/*
* assoc.c
*
* Associate catalogues.
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* This file part of: SExtractor
*
* Copyright: (C) 1997-2010 Emmanuel Bertin -- IAP/CNRS/UPMC
*
* License: GNU General Public License
*
* SExtractor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* SExtractor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with SExtractor. If not, see .
*
* Last modified: 11/10/2010
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include "define.h"
#include "globals.h"
#include "prefs.h"
#include "assoc.h"
/********************************* comp_assoc ********************************/
/*
Comparison function for sort_assoc().
*/
int comp_assoc(const void *i1, const void *i2)
{
float *f1,*f2;
f1 = (float *)i1 + 1;
f2 = (float *)i2 + 1;
if (*f1<*f2)
return -1;
else return (*f1==*f2)?0:1;
}
/********************************* sort_assoc ********************************/
/*
Make the presentation histogram, order the assoc-list and build the hash-table.
*/
void sort_assoc(picstruct *field, assocstruct *assoc)
{
int comp_assoc(const void *i1, const void *i2);
float *list, rad;
int i,j, step,nobj, *hash;
step = assoc->ncol;
nobj = assoc->nobj;
list = assoc->list;
qsort(assoc->list, assoc->nobj, step*sizeof(float), comp_assoc);
/* Build the hash table that contains the first object in the sorted list */
/* which may be in reach from the current scanline */
QMALLOC(assoc->hash, int, field->height);
list = assoc->list+1; /* This is where the 1st y coordinate is stored */
hash = assoc->hash;
rad = assoc->radius;
for (i=0, j=0; iheight; i++)
{
/*-- For safety, we keep a 1-pixel margin */
for (;ji) ? -1 : j;
}
return;
}
/********************************* load_assoc ********************************/
/*
Read an assoc-list, and returns a pointer to the new assoc struct (or NULL if
no list was found).
*/
assocstruct *load_assoc(char *filename)
{
assocstruct *assoc;
FILE *file;
float *list, val;
char str[MAXCHAR], str2[MAXCHAR], *sstr;
int *data,
i,ispoon,j,k,l, ncol, ndata, nlist, size,spoonsize,
xindex,yindex,mindex;
if (!(file = fopen(filename, "r")))
return NULL;
assoc = NULL; /* To avoid gcc -Wall warnings */
list = NULL; /* To avoid gcc -Wall warnings */
data = NULL; /* To avoid gcc -Wall warnings */
ispoon = ncol = ndata = nlist = size = spoonsize = xindex = yindex
= mindex = 0;
NFPRINTF(OUTPUT, "Reading ASSOC input-list...");
for (i=0; fgets(str, MAXCHAR, file);)
{
/*-- Examine current input line (discard empty and comment lines) */
if (!*str || strchr("#\t\n",*str))
continue;
if (!i)
{
strcpy(str2, str);
/*---- Let's count the number of columns in the first line */
for (ncol=0; strtok(ncol?NULL:str2, " \t\v\n\r\f"); ncol++);
if (!ncol)
error(EXIT_FAILURE, "*Error*: empty line in ", filename);
/*---- Build a look-up table containing the ordering of column data */
QCALLOC(data, int, ncol);
k = 1;
for (j=0; j= ncol)
error(EXIT_FAILURE, "*Error*: ASSOC_PARAMS #1 exceeds the number of ",
"fields in the ASSOC file");
if ((yindex = prefs.assoc_param[1]-1) >= ncol)
error(EXIT_FAILURE, "*Error*: ASSOC_PARAMS #2 exceeds the number of ",
"fields in the ASSOC file");
if (prefs.nassoc_param>2)
{
if ((mindex = prefs.assoc_param[2]-1) >= ncol)
error(EXIT_FAILURE,"*Error*: ASSOC_PARAMS #3 exceeds the number of ",
"fields in the ASSOC file");
}
else
{
mindex = -1;
prefs.assoc_type = ASSOC_FIRST;
}
nlist = ndata+3;
/*---- Allocate memory for the ASSOC struct and the filtered list */
QMALLOC(assoc, assocstruct, 1);
ispoon = ASSOC_BUFINC/(nlist*sizeof(float));
spoonsize = ispoon*nlist;
QMALLOC(assoc->list, float, size = spoonsize);
list = assoc->list;
}
else if (!(i%ispoon))
{
QREALLOC(assoc->list, float, size += spoonsize);
list = assoc->list + i*nlist;
}
if (!(++i%1000))
{
sprintf(str2, "Reading input list... (%d objects)", i);
NFPRINTF(OUTPUT, str2);
}
/*-- Read the data normally */
*(list+2) = 0.0;
for (sstr = str, j=0; jlist, float, i*nlist);
assoc->nobj = i;
assoc->radius = prefs.assoc_radius;
assoc->ndata = ndata;
assoc->ncol = nlist;
return assoc;
}
/********************************* init_assoc ********************************/
/*
Initialize the association procedure.
*/
void init_assoc(picstruct *field)
{
assocstruct *assoc;
/* Load the assoc-list */
if (!(assoc = field->assoc = load_assoc(prefs.assoc_name)))
error(EXIT_FAILURE, "*Error*: Assoc-list file not found: ",
prefs.assoc_name);
/* Sort the assoc-list by y coordinates, and build the hash table */
sort_assoc(field, assoc);
/* Where data go for the current output pattern*/
assoc->data = outobj2.assoc;
return;
}
/********************************** end_assoc ********************************/
/*
Free memory related to the assoc operations.
*/
void end_assoc(picstruct *field)
{
/* Free the assoc-list */
if (field->assoc)
{
free((field->assoc)->list);
free((field->assoc)->hash);
free(field->assoc);
}
return;
}
/********************************** do_assoc *********************************/
/*
Perform the association task for a source and return the number of IDs.
*/
int do_assoc(picstruct *field, float x, float y)
{
assocstruct *assoc;
double aver;
float dx,dy, dist, rad, rad2, comp, wparam,
*list, *input, *data;
int h, step, i, flag, iy, nobj;
assoc = field->assoc;
/* Need to initialize the array */
memset(assoc->data, 0, prefs.assoc_size*sizeof(float));
aver = 0.0;
if (prefs.assoc_type == ASSOC_MIN || prefs.assoc_type == ASSOC_NEAREST)
comp = BIG;
else
comp = -BIG;
iy = (int)(y+0.499999);
if (iy<0 || iy>=field->height)
return 0;
/* If there is already no candidate in hash table, no need to go further */
if ((h=assoc->hash[iy])<0)
return 0;
/* Now loop over possible candidates */
nobj = assoc->nobj;
step = assoc->ncol;
list = assoc->list + step*h;
rad = assoc->radius;
rad2 = rad*rad;
for (flag = 0; (h++data, input, assoc->ndata*sizeof(float));
return 1;
}
wparam = *(list+2);
data = assoc->data;
switch(prefs.assoc_type)
{
case ASSOC_NEAREST:
if (distndata*sizeof(float));
comp = dist;
}
break;
case ASSOC_MEAN:
aver += wparam;
for (i=assoc->ndata; i--;)
*(data++) += *(input++)*wparam;
break;
case ASSOC_MAGMEAN:
wparam = fabs(wparam)<99.0?DEXP(-0.4*wparam): 0.0;
aver += wparam;
for (i=assoc->ndata; i--;)
*(data++) += *(input++)*wparam;
break;
case ASSOC_SUM:
for (i=assoc->ndata; i--;)
*(data++) += *(input++);
break;
case ASSOC_MAGSUM:
for (i=assoc->ndata; i--;)
*(data++) += fabs(wparam=*(input++))<99.0? DEXP(-0.4*wparam):0.0;
break;
case ASSOC_MIN:
if (wparamndata*sizeof(float));
comp = wparam;
}
break;
case ASSOC_MAX:
if (wparam>comp)
{
memcpy(data, input, assoc->ndata*sizeof(float));
comp = wparam;
}
break;
default:
error(EXIT_FAILURE, "*Internal Error*: unknown ASSOC type in ",
"pixlearn()");
}
}
}
/* No candidate found? exit! */
if (!flag)
return 0;
/* Terminate the computation of the mean */
if (prefs.assoc_type == ASSOC_MEAN || prefs.assoc_type == ASSOC_MAGMEAN)
{
if (aver<1e-30)
return 0;
data = assoc->data;
for (i=assoc->ndata; i--;)
*(data++) /= aver;
}
if (prefs.assoc_type == ASSOC_MAGSUM)
{
data = assoc->data;
for (i=assoc->ndata; i--; data++)
*data = *data>0.0? -2.5*log10(*data):99.0;
}
return flag;
}