20#include "hdrl_cat_classify.h"
22#include "hdrl_cat_casu.h"
23#include "hdrl_cat_table.h"
24#include "hdrl_cat_utils_sort.h"
40static cpl_size g_nrows;
41static double g_thresh;
42static double g_skylevel;
43static double g_skynoise;
47static cpl_size g_poor;
48static double g_sigell, g_fitell, g_elllim, g_sigellf, g_fitellf, g_sigpa, g_fitpa;
49static double g_blim, g_flim, g_cmin, g_cmax;
50static double g_fit1, g_fit2, g_fit3, g_fit4, g_fit5, g_fit6, g_fit7;
51static double g_fit_final, g_sigma_final;
52static double *g_lower1, *g_lower2, *g_lower3, *g_upper1, *g_upper2, *g_upper3, *g_uppere;
53static double g_avsig1, g_avsig2, g_avsig3, g_wt1, g_wt2, g_wt3;
56static cpl_size g_nstar, g_ngal, g_njunk, g_ncmp;
59static double g_avsat, g_corlim, g_cormin, g_apcpkht;
60static double g_apcor1, g_apcor2, g_apcor3, g_apcor4, g_apcor5;
61static double g_apcor6, g_apcor7;
64static double *g_workspace = NULL;
65static cpl_table *g_catcopy = NULL;
66static double *g_areal[NAREAL];
67static double *g_core_flux, *g_core1_flux, *g_core2_flux, *g_core3_flux;
68static double *g_core4_flux, *g_core5_flux, *g_core6_flux;
69static double *g_peak_height, *g_peak_mag, *g_ellipticity, *g_iso_flux;
70static double *g_total_flux, *g_cls, *g_sig, *g_xpos, *g_ypos, *g_pa, *g_skylev;
73static double g_xmin, g_xmax, g_ymin, g_ymax;
74static double g_pixlim;
75static const char *g_colsfull[NCOLFULL] = {
76 "Aper_flux_3",
"Aper_flux_1",
"Aper_flux_4",
"Aper_flux_5",
"Aper_flux_6",
77 "Peak_height",
"Ellipticity",
"Isophotal_flux",
"Isophotal_flux",
78 "Aper_flux_7",
"X_coordinate",
"Y_coordinate",
"Position_angle",
"Sky_level",
84static void anhist(
double *data, cpl_size n,
double *medval,
double *sigma);
86static void boundaries(
double *core1,
double *core2,
double *core3,
double medval1,
87 double sigma1,
double medval2,
double sigma2, cpl_size small,
88 double area1,
double area2,
89 double *wt,
double *avsig,
double *lower,
double *upper);
90static void boundpk(
double *core,
double *pkht,
double medval,
double sigma,
91 double *wt,
double *avsig,
double *lower,
double *upper);
93static void classify_run(
void);
95static void classstats(
double *core1,
double *core2, cpl_size small,
double cutlev,
96 double *medval,
double *sigma);
97static void classstats_ap0(
double *medval,
double *sigma);
98static void classstats_ap67(
double *mag1,
double *mag2,
double *medval,
double *sigma);
99static void classstats_el(
void);
100static void classstats_pa(
void);
101static void classstats_ellf(
double);
102static void classstats_final(
void);
104static void medstat(
double *array, cpl_size n,
double *medval,
double *sigval);
157 if (cpl_table_get_ncol(cat) != NCOLS) {
158 return CPL_ERROR_INCOMPATIBLE_INPUT;
164 double fwhm = cpl_propertylist_get_double(extra,
"ESO DRS SEEING" );
165 cpl_size nxout = cpl_propertylist_get_int( extra,
"ESO DRS NXOUT" );
166 cpl_size nyout = cpl_propertylist_get_int( extra,
"ESO DRS NYOUT" );
168 g_thresh = cpl_propertylist_get_double(extra,
"ESO DRS THRESHOL");
169 g_skylevel = cpl_propertylist_get_double(extra,
"ESO QC MEAN_SKY" );
170 g_skynoise = cpl_propertylist_get_double(extra,
"ESO QC SKY_NOISE");
171 g_rcore = cpl_propertylist_get_double(extra,
"ESO DRS RCORE" );
173 g_xmin = FRAMECUT * (double)nxout;
174 g_xmax = (1. - FRAMECUT) * (
double)nxout;
175 g_ymin = FRAMECUT * (double)nyout;
176 g_ymax = (1. - FRAMECUT) * (
double)nyout;
181 g_catcopy = cpl_table_duplicate(cat);
182 g_nrows = cpl_table_get_nrow(cat);
184 g_cls = cpl_table_get_data_double(cat,
"Classification");
185 g_sig = cpl_table_get_data_double(cat,
"Statistic");
187 const char *cols[ NCOLFULL];
188 for (cpl_size i = 0; i < NCOLFULL; i++) {
189 cols[ i] = g_colsfull[ i];
192 g_core_flux = cpl_table_get_data_double(g_catcopy, cols[ 0]);
193 g_core1_flux = cpl_table_get_data_double(g_catcopy, cols[ 1]);
194 g_core2_flux = cpl_table_get_data_double(g_catcopy, cols[ 2]);
195 g_core3_flux = cpl_table_get_data_double(g_catcopy, cols[ 3]);
196 g_core4_flux = cpl_table_get_data_double(g_catcopy, cols[ 4]);
197 g_peak_height = cpl_table_get_data_double(g_catcopy, cols[ 5]);
198 g_ellipticity = cpl_table_get_data_double(g_catcopy, cols[ 6]);
199 g_iso_flux = cpl_table_get_data_double(g_catcopy, cols[ 7]);
200 g_total_flux = cpl_table_get_data_double(g_catcopy, cols[ 8]);
201 g_core5_flux = cpl_table_get_data_double(g_catcopy, cols[ 9]);
202 g_xpos = cpl_table_get_data_double(g_catcopy, cols[10]);
203 g_ypos = cpl_table_get_data_double(g_catcopy, cols[11]);
204 g_pa = cpl_table_get_data_double(g_catcopy, cols[12]);
205 g_skylev = cpl_table_get_data_double(g_catcopy, cols[13]);
206 g_core6_flux = cpl_table_get_data_double(g_catcopy, cols[14]);
209 g_workspace = cpl_malloc(2 * g_nrows *
sizeof(*g_workspace));
210 g_peak_mag = g_workspace;
212 double *work = g_workspace + g_nrows;
215 for (cpl_size i = 0; i < g_nrows; i++) {
217 g_core_flux[i] = 2.5 * log10(CPL_MAX(g_core_flux[i], 1.));
218 g_core1_flux[i] = 2.5 * log10(CPL_MAX(g_core1_flux[i], 1.));
219 g_core2_flux[i] = 2.5 * log10(CPL_MAX(g_core2_flux[i], 1.));
220 g_core3_flux[i] = 2.5 * log10(CPL_MAX(g_core3_flux[i], 1.));
221 g_core4_flux[i] = 2.5 * log10(CPL_MAX(g_core4_flux[i], 1.));
222 g_core5_flux[i] = 2.5 * log10(CPL_MAX(g_core5_flux[i], 1.));
224 double moff = 1. / (1. - pow((g_thresh / CPL_MAX(g_peak_height[i] ,g_thresh)), 0.6));
225 g_iso_flux[i] = 2.5 * log10(CPL_MAX(moff *g_iso_flux[i], 1.));
227 g_peak_mag[i] = 2.5 * log10(CPL_MAX(g_peak_height[i] - g_skynoise, 0.1));
230 if (g_core6_flux != NULL) {
231 for (cpl_size i = 0; i < g_nrows; i++) {
232 g_core6_flux[i] = 2.5 * log10(CPL_MAX(g_core6_flux[i], 1.));
237 for (cpl_size i = 0; i < NAREAL; i++) {
239 sprintf(colname,
"Areal_%ld_profile", (
long int)i + 1);
240 g_areal[i] = cpl_table_get_data_double(g_catcopy, colname);
245 if (fwhm > CPL_MAX(5., g_rcore * sqrt(2.))) g_poor = 1;
252 for (cpl_size i = 0; i < g_nrows; i++) {
254 double ell = g_ellipticity[i];
255 double core = g_core_flux[ i];
256 double pkht = g_peak_height[i];
258 if (g_cls[i] == -1. && ell < g_elllim && core < g_corlim && pkht > 10. * g_thresh) {
260 double ap = log(0.5 * pkht / g_thresh) / log(2.) + 1.;
261 cpl_size iap = (cpl_size)ap;
262 double delap = ap - (double)iap;
264 if (iap > 0 && iap < NAREAL && g_areal[1][i] > 0.) {
266 double area = g_areal[iap - 1][i]*(1. - delap) + g_areal[iap][i] * delap;
267 work[n++] = 2. * sqrt(area / CPL_MATH_PI);
275 medstat(work, n, &fwhm, &junk);
278 double arg = (0.25 * CPL_MATH_PI * fwhm * fwhm) - 1;
279 fwhm = 2. * sqrt(CPL_MAX(0., arg / CPL_MATH_PI));
285 if (g_catcopy != NULL) {
286 cpl_table_delete(g_catcopy);
292 cpl_propertylist_update_double(extra,
"ESO QC IMAGE_SIZE", fwhm);
293 cpl_propertylist_update_double(extra,
"ESO QC ELLIPTICITY", g_fitell);
294 cpl_propertylist_update_double(extra,
"ESO QC POSANG", g_fitpa);
295 cpl_propertylist_update_double(extra,
"ESO QC APERTURE_CORR", g_apcor3);
296 cpl_propertylist_update_int( extra,
"ESO QC NOISE_OBJ", g_njunk);
297 cpl_propertylist_update_double(extra,
"ESO QC SATURATION", g_avsat);
299 cpl_propertylist_set_comment( extra,
"ESO QC IMAGE_SIZE",
"[pixels] Average FWHM of stellar objects");
300 cpl_propertylist_set_comment( extra,
"ESO QC ELLIPTICITY",
"Average stellar ellipticity (1-b/a)");
301 cpl_propertylist_set_comment( extra,
"ESO QC POSANG",
"[degrees] Median position angle");
302 cpl_propertylist_set_comment( extra,
"ESO QC APERTURE_CORR",
"Stellar ap-corr 1x core flux");
303 cpl_propertylist_set_comment( extra,
"ESO QC NOISE_OBJ",
"Number of noise objects");
307 cpl_propertylist_update_bool( extra,
"ESO DRS CLASSIFD", 1);
309 cpl_propertylist_set_comment( extra,
"ESO DRS CLASSIFD",
"Catalogue has been classified");
313 cpl_propertylist_update_double(extra,
"APCORPK", g_apcpkht);
314 cpl_propertylist_update_double(extra,
"APCOR1", g_apcor1);
315 cpl_propertylist_update_double(extra,
"APCOR2", g_apcor2);
316 cpl_propertylist_update_double(extra,
"APCOR3", g_apcor3);
317 cpl_propertylist_update_double(extra,
"APCOR4", g_apcor4);
318 cpl_propertylist_update_double(extra,
"APCOR5", g_apcor5);
319 cpl_propertylist_update_double(extra,
"APCOR6", g_apcor6);
320 cpl_propertylist_update_double(extra,
"APCOR7", g_apcor7);
322 cpl_propertylist_set_comment( extra,
"APCORPK",
"Stellar aperture correction - peak height");
323 cpl_propertylist_set_comment( extra,
"APCOR1",
"Stellar aperture correction - 1/2x core flux");
324 cpl_propertylist_set_comment( extra,
"APCOR2",
"Stellar aperture correction - core/sqrt(2) flux");
325 cpl_propertylist_set_comment( extra,
"APCOR3",
"Stellar aperture correction - 1x core flux");
326 cpl_propertylist_set_comment( extra,
"APCOR4",
"Stellar aperture correction - sqrt(2)x core flux");
327 cpl_propertylist_set_comment( extra,
"APCOR5",
"Stellar aperture correction - 2x core flux");
328 cpl_propertylist_set_comment( extra,
"APCOR6",
"Stellar aperture correction - 2*sqrt(2)x core flux");
329 cpl_propertylist_set_comment( extra,
"APCOR7",
"Stellar aperture correction - 4x core flux");
333 cpl_propertylist_update_string(extra,
"SYMBOL1",
"{Ellipticity Position_angle Areal_1_profile Classification} {el");
334 cpl_propertylist_update_string(extra,
"SYMBOL2",
"lipse blue (1.0-$Ellipticity) $Position_angle+90 {} $Classific");
335 cpl_propertylist_update_string(extra,
"SYMBOL3",
"ation==1} {sqrt($Areal_1_profile*(1.0-$Ellipticity)/3.142)} : {");
336 cpl_propertylist_update_string(extra,
"SYMBOL4",
"Ellipticity Position_angle Areal_1_profile Classification} {el");
337 cpl_propertylist_update_string(extra,
"SYMBOL5",
"lipse red (1.0-$Ellipticity) $Position_angle+90 {} $Classific");
338 cpl_propertylist_update_string(extra,
"SYMBOL6",
"ation==-1} {sqrt($Areal_1_profile*(1.0-$Ellipticity)/3.142)} :");
339 cpl_propertylist_update_string(extra,
"SYMBOL7",
"{Ellipticity Position_angle Areal_1_profile Classification} {el");
340 cpl_propertylist_update_string(extra,
"SYMBOL8",
"lipse green (1.0-$Ellipticity) $Position_angle+90 {} $Classifi");
341 cpl_propertylist_update_string(extra,
"SYMBOL9",
"cation==0} {sqrt($Areal_1_profile*(1.0-$Ellipticity)/3.142)}");
345 if (g_workspace != NULL) {
346 cpl_free(g_workspace);
350 return CPL_ERROR_NONE;
371static void anhist(
double *data, cpl_size n,
double *medval,
double *sigma)
373 #define MAXHIST 66536
376 cpl_size *histo = cpl_calloc(MAXHIST,
sizeof(cpl_size));
377 double *sval = cpl_calloc(MAXHIST,
sizeof(
double));
380 for (cpl_size i = 0; i < n; i++) {
382 double aux = data[i] / STEP;
383 cpl_size ilev = (cpl_size)(aux + (aux < 0. ? -0.5 : 0.5));
385 if (ilev >= -10 && ilev <= 100) {
394 for (cpl_size i = 0; i < MAXHIST; i++) {
395 if (histo[i] > hmax) {
396 hmax = (double)(histo[i]);
405 *medval = data[(n+1)/2-1];
406 *sigma = CPL_MATH_STD_MAD * 0.5 * (data[(3 * n + 3) / 4 - 1] - data[(n + 3) / 4 - 1]);
417 for (cpl_size i = 1; i < MAXHIST-1; i++) {
418 sval[i] = (histo[i - 1] + histo[i] + histo[i + 1]) / 3.;
419 if (sval[i] > smax) {
427 hmax = (double)(histo[imax]);
431 for (cpl_size i = imax-1; i > 0; i--) {
432 if (sval[i] >= sval[i + 1] && sval[i] >= sval[i - 1]) {
433 if (sval[i] > 0.5 * smax)
440 hmax = (double)(histo[imax]);
444 *medval = CPL_MIN((
double)(imax - 10) * STEP, data[(n + 1) / 2 - 1]);
446 double aux = 0.5 * hmax;
447 double hlim = (cpl_size)(aux + (aux < 0. ? -0.5 : 0.5));
450 while (imax - i > 1 && histo[imax - i] > hlim) {
455 double ratio = hmax / CPL_MAX(1., (
double)(histo[imax - i]));
456 *sigma = (double)i * STEP / (sqrt(2.) * CPL_MAX(1., log(ratio)));
457 *sigma = CPL_MAX(*sigma, 0.5 * STEP);
464 if (histo) cpl_free(histo);
465 if (sval) cpl_free(sval);
493static void boundaries(
double *core1,
double *core2,
double *core3,
double medval1,
494 double sigma1,
double medval2,
double sigma2, cpl_size small,
495 double area1,
double area2,
496 double *wt,
double *avsig,
double *lower,
double *upper)
499 double *work = cpl_malloc(g_nrows *
sizeof(
double));
505 double asign = (small == 1 ? -1. : 1.);
509 for (cpl_size i = 0; i < g_nrows; i++) {
511 double c1 = core1[i];
515 double c2 = core2[i];
516 double dc = asign * (c2 - c1);
518 if (dc > medval1 - 3. * sigma1 && c1 < g_blim - 3.) {
519 work[n++] = dc - medval1;
524 double c2 = core3[i];
527 if (dc > medval2 - 3. * sigma2 && c1 < g_blim - 3.) {
528 work[n++] = dc - medval2;
535 medstat(work, n, avsig, &junk);
541 *wt = CPL_MIN(5., CPL_MAX(1., * avsig / sigma1));
542 xnoise = sqrt(area1) * g_skynoise;
544 *wt = CPL_MIN(2.5, CPL_MAX(1., * avsig / sigma2));
545 xnoise = sqrt(area2) * g_skynoise;
550 for (cpl_size i = 0; i < NSAMPLE; i++) {
552 double xmag = 5. + (double)(i + 1) * 0.1;
553 double xflux = pow(10., (
double)(0.4 * xmag));
554 double ratio = 2.5 * log10(CPL_MAX(1. + xnoise / xflux, 0.));
557 lower[i] = medval1 - 3. * sqrt(sigma1 * sigma1 + ratio * ratio);
558 upper[i] = medval1 + 3. * sqrt(sigma1 * sigma1 + 0.5 * ratio * ratio);
560 lower[i] = medval2 - 3. * sqrt(sigma2 * sigma2 + ratio * ratio);
561 upper[i] = medval2 + 3. * sqrt(sigma2 * sigma2 + 0.5 * ratio * ratio);
565 upper[0] = (g_poor == 0 ? medval1 : medval2);
588static void boundpk(
double *core,
double *pkht,
double medval,
double sigma,
589 double *wt,
double *avsig,
double *lower,
double *upper)
592 double *work = cpl_malloc(g_nrows *
sizeof(
double));
596 for (cpl_size i = 0; i < g_nrows; i++) {
601 if (c - p > medval - 3. * sigma && c < g_blim - 3.) {
602 work[n++] = c - p - medval;
608 medstat(work, n, avsig, &junk);
611 *wt = CPL_MIN(5., CPL_MAX(1., *avsig / sigma));
614 double xnoise = sqrt(CPL_MATH_PI * g_rcore * g_rcore) * g_skynoise;
615 for (cpl_size i = 0; i < NSAMPLE; i++) {
617 double xmag = 5.0 + (double)(i + 1) * 0.1;
618 double pmag = xmag - medval;
621 double xflux = pow(10., (
double)(0.4 * xmag));
622 double pflux = pow(10., (
double)(0.4 * pmag));
625 double ratio = 2.5 * log10((
double)(1. + CPL_MAX(xnoise / xflux, g_skynoise / pflux)));
627 lower[i] = medval - 3. * sqrt(sigma * sigma + ratio * ratio);
628 upper[i] = medval + 3. * sqrt(sigma * sigma + 0.5 * ratio * ratio);
646static void classify_run(
void)
658 double fluxlim = 2.5 * log10((
double)(5. * sqrt(CPL_MATH_PI * g_rcore * g_rcore) * g_skynoise));
660 g_flim = CPL_MIN(g_flim, CPL_MAX( 6., fluxlim + 3.));
661 g_corlim = CPL_MIN(g_blim, CPL_MAX(12.5, fluxlim + 5.));
662 g_cormin = CPL_MIN(g_blim, CPL_MAX(12.5, fluxlim + 5.));
667 for (cpl_size i = 0; i < g_nrows; i++) {
668 double xflux = g_core_flux[i];
669 g_cmin = CPL_MIN(g_cmin, xflux);
670 g_cmax = CPL_MAX(g_cmax, xflux);
672 g_cmin = CPL_MAX(fluxlim - 0.5, g_cmin);
674 g_cmax = CPL_MIN(g_cmax, 20.);
680 double sigma1, sigma2, sigma3, sigma4, sigma5, sigma6, sigma7;
681 classstats(g_core_flux, g_core1_flux, 1, 0.2, &g_fit1, &sigma1);
682 classstats(g_core_flux, g_core3_flux, 0, 0.1, &g_fit2, &sigma2);
683 classstats(g_core_flux, g_core2_flux, 0, 0.0, &g_fit4, &sigma4);
684 classstats(g_core_flux, g_core4_flux, 0, 0.1, &g_fit5, &sigma5);
685 classstats(g_core_flux, g_peak_mag, 1, 0.2, &g_fit3, &sigma3);
688 classstats_ellf(fluxlim);
694 g_lower1 = cpl_malloc(NSAMPLE *
sizeof(*g_lower1));
695 g_lower2 = cpl_malloc(NSAMPLE *
sizeof(*g_lower2));
696 g_lower3 = cpl_malloc(NSAMPLE *
sizeof(*g_lower3));
697 g_upper1 = cpl_malloc(NSAMPLE *
sizeof(*g_upper1));
698 g_upper2 = cpl_malloc(NSAMPLE *
sizeof(*g_upper2));
699 g_upper3 = cpl_malloc(NSAMPLE *
sizeof(*g_upper3));
702 boundaries(g_core_flux, g_core1_flux, g_core2_flux, g_fit1,
703 sigma1, g_fit4, sigma4, 1,
704 CPL_MATH_PI * g_rcore * g_rcore, 2. * CPL_MATH_PI * g_rcore * g_rcore,
705 &g_wt1, &g_avsig1, g_lower1, g_upper1);
708 boundaries(g_core_flux, g_core3_flux, g_core4_flux, g_fit2,
709 sigma2, g_fit5, sigma5, 0,
710 4. * CPL_MATH_PI * g_rcore * g_rcore, 8. * CPL_MATH_PI * g_rcore * g_rcore,
711 &g_wt2, &g_avsig2, g_lower2, g_upper2);
714 boundpk(g_core_flux, g_peak_mag, g_fit3, sigma3, &g_wt3, &g_avsig3, g_lower3, g_upper3);
720 double *lower = cpl_malloc(NSAMPLE *
sizeof(
double));
721 double *upper = cpl_malloc(NSAMPLE *
sizeof(
double));
722 g_uppere = cpl_malloc(NSAMPLE *
sizeof(*g_uppere));
724 double xnoise = sqrt(CPL_MATH_PI * g_rcore * g_rcore) * g_skynoise;
727 ratell = xnoise / pow(10., 0.4 * (fluxlim + 1.5));
728 ratell = 2.5 * log10(CPL_MAX(1. + ratell, 0.));
731 ratscl = (pow((g_fitellf + 2. * g_sigellf - g_fitell), 2.) - 4. * g_sigell * g_sigell) / (4. * ratell * ratell);
732 ratscl = CPL_MAX(0.25, CPL_MIN(10., ratscl));
734 for (cpl_size i = 0; i < NSAMPLE; i++) {
736 double xmag = 5. + 0.1 * (double)(i + 1);
737 double xflux = pow(10., 0.4 * xmag);
738 double ratio = 2.5 * log10(1. + xnoise / xflux);
741 lower[i] = g_fit_final - 5. * sqrt( g_sigma_final * g_sigma_final + ratio * ratio);
742 upper[i] = g_fit_final + sqrt(9. * g_sigma_final * g_sigma_final + 0. * ratio * ratio);
744 g_uppere[i] = g_fitell + 2. * sqrt(g_sigell * g_sigell + ratscl * ratio * ratio);
745 g_uppere[i] = CPL_MIN(0.5, g_uppere[i]);
748 g_elllim = CPL_MIN(0.5, CPL_MAX(0.2, g_fitell + 2. * g_sigell));
749 fluxlim = 2.5 * log10((
double)(2.5 * sqrt(CPL_MATH_PI * g_rcore * g_rcore) * g_skynoise));
756 for (cpl_size i = 0; i < g_nrows; i++) {
758 double ell = g_ellipticity[i];
759 double core = g_core_flux[i];
760 double pkht = g_peak_mag[i];
762 double aux1 = 10. * (core - 5.);
764 cpl_size iarg = CPL_MAX(1, CPL_MIN(NSAMPLE, (cpl_size)(aux1 + (aux1 < 0. ? -0.5 : 0.5)))) - 1;
769 sig1 = CPL_MAX(0.01, (g_fit1 - g_lower1[iarg]) / 3.);
770 sig2 = CPL_MAX(0.01, (g_fit2 - g_lower2[iarg]) / 3.);
772 sig1 = CPL_MAX(0.01, (g_fit4 - g_lower1[iarg]) / 3.);
773 sig2 = CPL_MAX(0.01, (g_fit5 - g_lower2[iarg]) / 3.);
775 double sig3 = CPL_MAX(0.01, (g_fit3 - g_lower3[iarg]) / 3.);
777 double denom = (g_wt1 / sig1 + g_wt2 / sig2 + g_wt3 / sig3);
779 double w1 = (g_wt1 / sig1) / denom;
780 double w2 = (g_wt2 / sig2) / denom;
781 double w3 = (g_wt3 / sig3) / denom;
786 double core_small = g_core1_flux[i];
787 double core_large = g_core3_flux[i];
789 statistic = ( core - core_small - g_fit1 ) * w1
790 + (CPL_MAX(core_large - core - g_fit2, -3. * sig2)) * w2
791 + ( core - pkht - g_fit3 ) * w3;
794 double core_midd = g_core2_flux[i];
795 double core_large = g_core4_flux[i];
797 statistic = ( core_midd - core - g_fit4 ) * w1
798 + (CPL_MAX(core_large - core - g_fit5, -3. * sig2)) * w2
799 + ( core - pkht - g_fit3 ) * w3;
803 double aux2 = exp(CPL_MAX(0., core - g_corlim + 1.));
804 double statcut = upper[iarg] + 3. * g_sigma_final * (aux2 - 1.);
805 if (statistic >= statcut) {
807 }
else if (statistic <= lower[iarg]) {
812 g_sig[i] = (statistic - g_fit_final) / ((g_fit_final - lower[iarg]) / 5.);
817 if (core - pkht - g_fit3 < -4. * sig3) g_cls[i] = 0.;
820 double ellbound = CPL_MAX(g_elllim, g_uppere[iarg]);
821 if (ell > ellbound && g_cls[i] == -1. && core < g_flim && g_sig[i] > -2.) g_cls[i] = -2.;
824 if (core > g_corlim && statistic >= lower[iarg]) g_cls[i] = -1.;
827 if (ell > 0.9 && core < g_corlim) g_cls[i] = 0.;
830 if (core < fluxlim) g_cls[i] = 0.;
834 if (g_cls[i] == -1.) {
836 }
else if (g_cls[i] == 1.) {
838 }
else if (g_cls[i] == -2.) {
848 classstats_ap67(g_core5_flux, g_core3_flux, &g_fit6, &sigma6);
849 classstats_ap67(g_core_flux, g_core6_flux, &g_fit7, &sigma7);
854 classstats_ap0(&fit0, &sigma0);
855 fit0 = CPL_MAX(g_fit6, fit0);
858 g_apcpkht = fit0 + g_fit3;
860 g_apcor1 = fit0 + g_fit1;
861 g_apcor2 = fit0 + g_fit7;
863 g_apcor4 = fit0 - g_fit4;
864 g_apcor5 = fit0 - g_fit2;
865 g_apcor6 = fit0 - g_fit5;
866 g_apcor7 = fit0 - g_fit6;
869 double *work = cpl_malloc(g_nrows *
sizeof(
double));
872 for (cpl_size i = 0; i < g_nrows; i++) {
874 double ell = g_ellipticity[i];
875 double core = g_core_flux[i];
876 double pkht = CPL_MAX(g_thresh, g_peak_height[i]) + g_skylev[i];
878 if ( ( ( ell < g_elllim
882 && g_areal[0][i] >= g_pixlim
884 || pkht >= 0.9 * g_avsat
886 && g_xpos[i] >= g_xmin
887 && g_xpos[i] <= g_xmax
888 && g_ypos[i] >= g_ymin
889 && g_ypos[i] <= g_ymax
898 medstat(work,ii,&avsatnew,&junk);
899 avsatnew = CPL_MAX(10000.0+g_skylevel,avsatnew);
901 avsatnew = 10000.0 + g_skylevel;
909 if (g_lower1 != NULL) {cpl_free(g_lower1); g_lower1 = NULL;}
910 if (g_lower2 != NULL) {cpl_free(g_lower2); g_lower2 = NULL;}
911 if (g_lower3 != NULL) {cpl_free(g_lower3); g_lower3 = NULL;}
913 if (g_upper1 != NULL) {cpl_free(g_upper1); g_upper1 = NULL;}
914 if (g_upper2 != NULL) {cpl_free(g_upper2); g_upper2 = NULL;}
915 if (g_upper3 != NULL) {cpl_free(g_upper3); g_upper3 = NULL;}
917 if (g_uppere != NULL) {cpl_free(g_uppere); g_uppere = NULL;}
936static void classstats(
double *core1,
double *core2, cpl_size small,
double cutlev,
937 double *medval,
double *sigma) {
943 double amult = (small == 1 ? -1. : 1.);
946 double *work = cpl_malloc(g_nrows *
sizeof(
double));
947 double *dc = cpl_malloc(g_nrows *
sizeof(
double));
950 for (cpl_size i = 0; i < g_nrows; i++) {
951 dc[i] = amult * (core2[i] - core1[i]);
955 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
957 double sigmaold = *sigma;
961 for (cpl_size i = 0; i < g_nrows; i++) {
964 if ( g_ellipticity[i] < g_elllim
967 && fabs(dc[i] - *medval) < 3.*(*sigma)
968 && g_xpos[i] >= g_xmin
969 && g_xpos[i] <= g_xmax
970 && g_ypos[i] >= g_ymin
971 && g_ypos[i] <= g_ymax
972 && g_areal[0][i] >= g_pixlim)
974 if (iloop > 0 || (iloop == 0 && dc[i] >= cutlev)) {
983 sort_array(work, n,
sizeof(*work), HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
987 anhist( work, n, medval, sigma);
991 medstat(work, n, medval, sigma);
993 *sigma = CPL_MIN(sigmaold, *sigma);
1003 *sigma = CPL_MAX(*sigma, 0.01);
1019static void classstats_el(
void)
1026 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1029 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1032 for (cpl_size i = 0; i < g_nrows; i++) {
1033 if ( g_ellipticity[i] < 0.5
1034 && g_core_flux[i] < g_blim
1035 && g_core_flux[i] > g_flim
1036 && fabs(g_ellipticity[i] - g_fitell) < 2. * g_sigell
1037 && g_xpos[i] >= g_xmin
1038 && g_xpos[i] <= g_xmax
1039 && g_ypos[i] >= g_ymin
1040 && g_ypos[i] <= g_ymax
1041 && g_areal[0][i] >= g_pixlim)
1043 work[n++] = g_ellipticity[i];
1048 medstat(work, n, &g_fitell, &g_sigell);
1055 g_elllim = CPL_MIN(0.5, CPL_MAX(0.2, g_fitell + 2. * g_sigell));
1069static void classstats_pa(
void)
1076 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1079 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1082 for (cpl_size i = 0; i < g_nrows; i++) {
1084 if ( g_core_flux[i] < g_blim
1085 && g_core_flux[i] > g_flim
1086 && fabs(g_pa[i] - g_fitpa) < 2. * g_sigpa
1087 && g_xpos[i] >= g_xmin
1088 && g_xpos[i] <= g_xmax
1089 && g_ypos[i] >= g_ymin
1090 && g_ypos[i] <= g_ymax
1091 && g_areal[0][i] >= g_pixlim)
1093 work[n++] = g_pa[i];
1098 medstat(work, n, &g_fitpa, &g_sigpa);
1120static void classstats_ellf(
double fluxlim)
1127 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1130 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1133 for (cpl_size i = 0; i < g_nrows; i++) {
1135 if ( g_ellipticity[i] < 0.75
1136 && g_core_flux[i] > fluxlim + 1.
1137 && g_core_flux[i] < fluxlim + 2.
1138 && fabs(g_ellipticity[i] - g_fitellf) < 2. * g_sigellf)
1140 work[n++] = g_ellipticity[i];
1145 medstat(work, n, &g_fitellf, &g_sigellf);
1168static void classstats_ap0(
double *medval,
double *sigma)
1173 g_elllim = CPL_MIN(0.5, CPL_MAX(0.2, g_fitell + 2. * g_sigell));
1176 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1177 double *dc = cpl_malloc(g_nrows *
sizeof(
double));
1180 for (cpl_size i = 0; i < g_nrows; i++) {
1181 dc[i] = CPL_MAX(0., CPL_MAX(g_iso_flux[i], g_core5_flux[i])) - g_core_flux[i];
1185 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1189 for (cpl_size i = 0; i < g_nrows; i++) {
1192 if ( g_ellipticity[i] < g_elllim
1193 && g_core_flux[i] < g_blim
1194 && g_core_flux[i] > g_flim
1195 && fabs(dc[i] - *medval) < 3. * (*sigma)
1198 && g_xpos[i] >= g_xmin
1199 && g_xpos[i] <= g_xmax
1200 && g_ypos[i] >= g_ymin
1201 && g_ypos[i] <= g_ymax
1202 && g_areal[0][i] >= g_pixlim)
1204 if (iloop > 0 || (iloop == 0 && dc[i] >= 0.)) {
1213 sort_array(work, n,
sizeof(*work), HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
1217 anhist(work, n, medval, sigma);
1219 *sigma = CPL_MATH_STD_MAD * (*medval - work[(cpl_size)(0.25 * (
double)(n + 3)) - 1]);
1220 *sigma = CPL_MAX(0.025, *sigma);
1225 medstat(work, n, medval, &sigmanew);
1227 *sigma = CPL_MIN(*sigma, sigmanew);
1228 *sigma = CPL_MAX(0.01, *sigma);
1238 *sigma = CPL_MAX(*sigma, 0.01);
1259static void classstats_ap67(
double *mag1,
double *mag2,
double *medval,
double *sigma)
1264 g_elllim = CPL_MIN(0.5, CPL_MAX(0.2, g_fitell + 2. * g_sigell));
1267 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1268 double *dc = cpl_malloc(g_nrows *
sizeof(
double));
1271 for (cpl_size i = 0; i < g_nrows; i++) {
1272 dc[i] = mag1[i] - mag2[i];
1276 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1280 for (cpl_size i = 0; i < g_nrows; i++) {
1283 if ( g_ellipticity[i] < g_elllim
1284 && g_core_flux[i] < g_blim
1285 && g_core_flux[i] > g_flim
1286 && fabs(dc[i] - *medval) < 3. * (*sigma)
1287 && g_cls[i] == -1. && g_sig[i] < 5.
1288 && g_xpos[i] >= g_xmin
1289 && g_xpos[i] <= g_xmax
1290 && g_ypos[i] >= g_ymin
1291 && g_ypos[i] <= g_ymax
1292 && g_areal[0][i] >= g_pixlim)
1294 if (iloop > 0 || (iloop == 0 && dc[i] >= 0.)) {
1303 sort_array(work, n,
sizeof(*work), HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
1307 anhist(work, n, medval, sigma);
1309 *sigma = CPL_MATH_STD_MAD * (*medval - work[(cpl_size)(0.25 * (
double)(n + 3)) - 1]);
1310 *sigma = CPL_MAX(0.025, *sigma);
1315 medstat(work, n, medval, &sigmanew);
1317 *sigma = CPL_MIN(*sigma, sigmanew);
1318 *sigma = CPL_MAX(0.01, *sigma);
1327 *sigma = CPL_MAX(*sigma, 0.01);
1345static void classstats_final(
void)
1348 g_sigma_final = 1.e6;
1354 double *work = cpl_malloc(g_nrows *
sizeof(
double));
1355 double *work1 = cpl_malloc(g_nrows *
sizeof(
double));
1356 double *statistic = cpl_malloc(g_nrows *
sizeof(
double));
1359 for (cpl_size i = 0; i < g_nrows; i++) {
1361 double pkht = g_peak_mag[i];
1362 double core = g_core_flux[i];
1364 double aux = 10. * (core - 5.);
1365 cpl_size iarg = CPL_MAX(1, CPL_MIN(NSAMPLE, (cpl_size)(aux + (aux < 0. ? -0.5 : 0.5)))) - 1;
1370 sig1 = CPL_MAX(0.01, (g_fit1 - g_lower1[iarg]) / 3.);
1371 sig2 = CPL_MAX(0.01, (g_fit2 - g_lower2[iarg]) / 3.);
1373 sig1 = CPL_MAX(0.01, (g_fit4 - g_lower1[iarg]) / 3.);
1374 sig2 = CPL_MAX(0.01, (g_fit5 - g_lower2[iarg]) / 3.);
1376 double sig3 = CPL_MAX(0.01, (g_fit3 - g_lower3[iarg]) / 3.);
1378 double denom = (g_wt1 / sig1 + g_wt2 / sig2 + g_wt3 / sig3);
1380 double w1 = (g_wt1 / sig1) / denom;
1381 double w2 = (g_wt2 / sig2) / denom;
1382 double w3 = (g_wt3 / sig3) / denom;
1386 double core_small = g_core1_flux[i];
1387 double core_large = g_core3_flux[i];
1389 statistic[i] = (core - core_small - g_fit1) * w1
1390 + (core_large - core - g_fit2) * w2
1391 + (core - pkht - g_fit3) * w3;
1395 double core_midd = g_core2_flux[i];
1396 double core_large = g_core4_flux[i];
1398 statistic[i] = (core_midd - core - g_fit4) * w1
1399 + (core_large - core - g_fit5) * w2
1400 + (core - pkht - g_fit3) * w3;
1405 for (cpl_size iloop = 0; iloop < MAXLOOP; iloop++) {
1407 double sigmaold = g_sigma_final;
1410 for (cpl_size i = 0; i < g_nrows ; i++) {
1412 double ell = g_ellipticity[i];
1413 double core = g_core_flux[i];
1418 && fabs((
double)(statistic[i] - g_fit_final)) < 3. * g_sigma_final
1419 && g_areal[0][i] >= g_pixlim)
1421 work[n++] = statistic[i];
1425 if (core > g_corlim && iloop == MAXLOOP - 2) {
1426 g_cls[ncls] = statistic[i];
1427 g_sig[ncls++] = core;
1434 sort_array(work, n,
sizeof(*work), HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
1436 if (iloop == 0 && n > 10) {
1437 anhist( work, n, &g_fit_final, &g_sigma_final);
1439 medstat(work, n, &g_fit_final, &g_sigma_final);
1442 g_sigma_final = CPL_MAX(0.01, CPL_MIN(sigmaold, g_sigma_final));
1447 g_sigma_final = 0.01;
1452 sort_array_index(g_sig, ncls, g_cls, HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
1459 double corlim1 = 0.;
1460 double corlim2 = 0.;
1461 double corval1 = 0.;
1462 double corval2 = 0.;
1464 while (iend == 0 && idx < ncls-1) {
1467 if (g_sig[idx] > xcor+0.25 && ii >= 3) {
1471 medstat(work, ii, &cfit, &csig);
1473 for (cpl_size iloop = 0; iloop < 3; iloop++) {
1476 for (cpl_size k = 0; k < ii; k++) {
1477 if (work[k] <= cfit + 3. * csig)
1478 work1[kk++] = work[k];
1482 medstat(work1, kk, &cfit, &junk);
1485 if (cfit <= g_fit_final + 3. * g_sigma_final) {
1500 work[ii++] = g_cls[idx];
1506 g_corlim = corlim2 - 0.5 * (corval2 - g_fit_final - 3. * g_sigma_final) / (corval2 - corval1);
1510 g_corlim = CPL_MAX(g_cormin, g_corlim);
1513 for (cpl_size i = 0; i < g_nrows; i++) {
1515 double core = g_core_flux[i];
1516 if (core >= g_corlim) {
1517 work[kk++] = g_peak_height[i] + g_skylevel;
1524 medstat(work, kk, &g_avsat, &junk);
1526 g_avsat = CPL_MAX(10000. + g_skylevel, g_avsat);
1529 g_avsat = 10000. + g_skylevel;
1535 cpl_free(statistic);
1553static void medstat(
double *array, cpl_size n,
double *medval,
double *sigval)
1566 sort_array(array, n,
sizeof(*array), HDRL_SORT_DOUBLE, CPL_SORT_ASCENDING);
1568 cpl_size lev1 = ( n + 1) / 2;
1569 cpl_size lev2 = (3 * n + 3) / 4;
1570 cpl_size lev3 = ( n + 3) / 4;
1572 *medval = array[lev1 - 1];
1573 *sigval = CPL_MATH_STD_MAD * 0.5 * (array[lev2 - 1] - array[lev3 - 1]);
cpl_propertylist * hdrl_casu_tfits_get_ehu(hdrl_casu_tfits *p)
Get the propertylist for the extension header for a given hdrl_casu_tfits image.
cpl_table * hdrl_casu_tfits_get_table(hdrl_casu_tfits *p)
Get the CPL table from the hdrl_casu_tfits object.
cpl_error_code hdrl_classify(hdrl_casu_tfits *catalogue, double minsize)
Do star/galaxy classification.
cpl_error_code sort_array(void *a, cpl_size nE, cpl_size sE, hdrl_sort_type type, cpl_sort_direction dir)
sort_array hdrl function for order arrays with know types. Using the type parameter for select the co...
cpl_error_code sort_array_index(double *a, cpl_size nE, void *b, hdrl_sort_type type, cpl_sort_direction dir)
sort_array_index hdrl function for sort two arrays The alghorithm sort 'a' and in the same way sort t...