FORS Pipeline Reference Manual  4.12.5
fors/fors_extract.c
1 /* $Id: fors_extract.c,v 1.45 2011-10-13 14:29:24 cgarcia Exp $
2  *
3  * This file is part of the FORS Library
4  * Copyright (C) 2002-2010 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2011-10-13 14:29:24 $
24  * $Revision: 1.45 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <fors_extract.h>
33 #include <fors_star.h>
34 
35 #include <fors_tools.h>
36 #include <fors_dfs.h>
37 #include <fors_pfits.h>
38 #include <fors_utils.h>
39 
40 #include <cpl.h>
41 
42 #include <string.h>
43 #include <stdbool.h>
44 #include <math.h>
45 
52 /*-----------------------------------------------------------------------------
53  (Proto)types
54  -----------------------------------------------------------------------------*/
55 
57 {
58  enum {SEX, TEST} method;
59  const char *sex_exe;
60  const char *sex_config;
61  const char *sex_mag;
62  const char *sex_magerr;
63  int sex_radius;
64 };
65 
66 static fors_star_list *
67 extract_sex( const fors_image *image,
68  const fors_setting *setting,
69  const char *sex_exe,
70  const char *sex_config,
71  const char *sex_mag,
72  const char *sex_magerr,
73  int radius,
74  double magsyserr,
75  fors_extract_sky_stats *sky_stats,
76  cpl_image **background,
77  cpl_table **extracted_sources);
78 
79 static fors_star_list *
81  cpl_image **background,
82  cpl_table **extracted_sources);
83 
84 /*-----------------------------------------------------------------------------
85  Implementation
86  -----------------------------------------------------------------------------*/
87 
88 /*----------------------------------------------------------------------------*/
98 /*----------------------------------------------------------------------------*/
99 bool
100 fors_extract_check_sex_flag( unsigned int sex_flag)
101 {
102  return (sex_flag == 0x0);
103 }
104 
105 /*----------------------------------------------------------------------------*/
120 /*----------------------------------------------------------------------------*/
121 bool
123  const cpl_image *ref_img)
124 {
125  bool success = 1;
126 
127  if (star == NULL)
128  return 0;
129 
130  success &= fors_star_check_values(star);
131 
132  success &= (star->magnitude < 98);
133 
134  if (ref_img != NULL)
135  {
136  success &= star->pixel->x >= 1;
137  success &= star->pixel->x <= cpl_image_get_size_x(ref_img);
138  success &= star->pixel->y >= 1;
139  success &= star->pixel->y <= cpl_image_get_size_y(ref_img);
140  }
141 
142  return success;
143 }
144 
145 /*----------------------------------------------------------------------------*/
151 /*----------------------------------------------------------------------------*/
152 void
153 fors_extract_define_parameters( cpl_parameterlist *parameters,
154  const char *context)
155 {
156  cpl_parameter *p;
157  const char *full_name = NULL;
158  const char *name;
159 
160  /*
161  name = "extract_method";
162  full_name = cpl_sprintf("%s.%s", context, name);
163  p = cpl_parameter_new_enum(full_name,
164  CPL_TYPE_STRING,
165  "Source extraction method",
166  context,
167  "sex", 2,
168  "sex", "test");
169  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
170  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
171  cpl_parameterlist_append(parameters, p);
172  cpl_free((void *)full_name);
173  */
174 
175  name = "sex_exe";
176  full_name = cpl_sprintf("%s.%s", context, name);
177  p = cpl_parameter_new_value(full_name,
178  CPL_TYPE_STRING,
179  "SExtractor executable",
180  context,
181  FORS_SEXTRACTOR_PATH "/sex");
182  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
183  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
184  cpl_parameterlist_append(parameters, p);
185  cpl_free((void *)full_name);
186 
187  name = "sex_config";
188  full_name = cpl_sprintf("%s.%s", context, name);
189  p = cpl_parameter_new_value(full_name,
190  CPL_TYPE_STRING,
191  "SExtractor configuration file",
192  context,
193  FORS_SEXTRACTOR_CONFIG "/fors.sex");
194  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
195  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
196  cpl_parameterlist_append(parameters, p);
197  cpl_free((void *)full_name);
198 
199 
200  name = "sex_mag";
201  full_name = cpl_sprintf("%s.%s", context, name);
202  p = cpl_parameter_new_value(full_name,
203  CPL_TYPE_STRING,
204  "SExtractor magnitude",
205  context,
206  "MAG_APER");
207  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
208  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
209  cpl_parameterlist_append(parameters, p);
210  cpl_free((void *)full_name);
211 
212  name = "sex_magerr";
213  full_name = cpl_sprintf("%s.%s", context, name);
214  p = cpl_parameter_new_value(full_name,
215  CPL_TYPE_STRING,
216  "SExtractor magnitude error",
217  context,
218  "MAGERR_APER");
219  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
220  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221  cpl_parameterlist_append(parameters, p);
222  cpl_free((void *)full_name);
223 
224  name = "sex_radius";
225  full_name = cpl_sprintf("%s.%s", context, name);
226  p = cpl_parameter_new_value(full_name,
227  CPL_TYPE_INT,
228  "Background error map median filter "
229  "radius (unbinned pixels)",
230  context,
231  64);
232  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
233  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
234  cpl_parameterlist_append(parameters, p);
235  cpl_free((void *)full_name); full_name = NULL;
236 
237  return;
238 }
239 
240 /*----------------------------------------------------------------------------*/
241 #undef cleanup
242 #define cleanup \
243 do { \
244  cpl_free((void *)name); \
245  cpl_free((void *)method); \
246 } while (0)
247 
256 /*----------------------------------------------------------------------------*/
257 extract_method *
258 fors_extract_method_new( const cpl_parameterlist *parameters,
259  const char *context)
260 {
261  extract_method *em = cpl_malloc(sizeof(*em));
262  const char *name = NULL;
263  const char *method = NULL;
264 
265  cpl_msg_info(cpl_func, "Extraction method:");
266 
267  cpl_msg_indent_more();
268  //"sex" method is the default. The parameter won't appear when calling
269  //the recipe from esorex, but it will in the unit tests fors_zeropoint-test,
270  //fors_img_science-test.
271  name = cpl_sprintf("%s.%s", context, "extract_method");
272  if(cpl_parameterlist_find_const(parameters, name) == NULL)
273  method = cpl_sprintf("%s", "sex");
274  else
275  method = cpl_sprintf("%s",dfs_get_parameter_string_const(parameters, name));
276  cpl_free((void *)name); name = NULL;
277  cpl_msg_indent_less();
278 
279  assure( !cpl_error_get_code(), return NULL, NULL );
280  assure( method != NULL, return NULL, NULL );
281 
282  if (strcmp(method, "sex") == 0) {
283  em->method = SEX;
284 
285  cpl_msg_indent_more();
286  name = cpl_sprintf("%s.%s", context, "sex_exe");
287  em->sex_exe = dfs_get_parameter_string_const(parameters,
288  name);
289  cpl_free((void *)name); name = NULL;
290  cpl_msg_indent_less();
291 
292 
293  cpl_msg_indent_more();
294  name = cpl_sprintf("%s.%s", context, "sex_config");
295  em->sex_config = dfs_get_parameter_string_const(parameters,
296  name);
297  cpl_free((void *)name); name = NULL;
298  cpl_msg_indent_less();
299 
300 
301 
302  cpl_msg_indent_more();
303  name = cpl_sprintf("%s.%s", context, "sex_mag");
304  em->sex_mag = dfs_get_parameter_string_const(parameters,
305  name);
306  cpl_free((void *)name); name = NULL;
307  cpl_msg_indent_less();
308 
309 
310  cpl_msg_indent_more();
311  name = cpl_sprintf("%s.%s", context, "sex_magerr");
312  em->sex_magerr = dfs_get_parameter_string_const(parameters,
313  name);
314  cpl_free((void *)name); name = NULL;
315  cpl_msg_indent_less();
316 
317 
318  cpl_msg_indent_more();
319  name = cpl_sprintf("%s.%s", context, "sex_radius");
320  em->sex_radius = dfs_get_parameter_int_const(parameters,
321  name);
322  cpl_free((void *)name); name = NULL;
323  cpl_msg_indent_less();
324  }
325  else if (strcmp(method, "test") == 0) {
326  em->method = TEST;
327  }
328  else {
329  assure( false, return NULL, "Unknown extraction method '%s'", method);
330  }
331 
332  cleanup;
333  return em;
334 }
335 
336 /*----------------------------------------------------------------------------*/
340 /*----------------------------------------------------------------------------*/
341 void
342 fors_extract_method_delete( extract_method **em)
343 {
344  if (em && *em) {
345  cpl_free(*em); *em = NULL;
346  }
347  return;
348 }
349 
350 /*----------------------------------------------------------------------------*/
351 #undef cleanup
352 #define cleanup
353 
363 /*----------------------------------------------------------------------------*/
364 fors_star_list *
365 fors_extract( const fors_image *image,
366  const fors_setting *setting,
367  const extract_method *em,
368  double magsyserr,
369  fors_extract_sky_stats *sky_stats,
370  cpl_image **background,
371  cpl_table **extracted_sources)
372 {
373  assure( em != NULL, return NULL, NULL );
374 
375  cpl_msg_info(cpl_func, "Extracting sources");
376 
377  switch (em->method ) {
378  case SEX: return extract_sex(image, setting,
379  em->sex_exe,
380  em->sex_config,
381  em->sex_mag,
382  em->sex_magerr,
383  em->sex_radius,
384  magsyserr,
385  sky_stats,
386  background,
387  extracted_sources); break;
388  case TEST: return extract_test(sky_stats, background, extracted_sources); break;
389  default:
390  assure( false, return NULL, "Unknown method %d", em->method );
391  break;
392  }
393 }
394 
395 /*----------------------------------------------------------------------------*/
396 #undef cleanup
397 #define cleanup \
398 do { \
399  cpl_table_delete(out); out = NULL; \
400  cpl_free((void *)command); \
401  cpl_image_delete(work_back); work_back = NULL; \
402  cpl_image_delete(bmaxsigma); bmaxsigma = NULL; \
403  cpl_image_delete(bsigma); bsigma = NULL; \
404  fors_image_delete(&fbsigma); \
405 } while (0)
406 
429 /*----------------------------------------------------------------------------*/
430 static fors_star_list *
431 extract_sex( const fors_image *image,
432  const fors_setting *setting,
433  const char *sex_exe,
434  const char *sex_config,
435  const char *sex_mag,
436  const char *sex_magerr,
437  int radius,
438  double magsyserr,
439  fors_extract_sky_stats *sky_stats,
440  cpl_image **background,
441  cpl_table **extracted_sources)
442 {
443  const char *const filename_data = "sextract_data.fits";
444  const char *const filename_sigma = "sextract_bkg_sigma.fits";
445  const char *const filename_cat = "sextract_cat.fits";
446  const char *const filename_bkg = "sextract_bkg.fits";
447  cpl_table *out = NULL;
448  const char *command = NULL;
449  fors_star_list *stars = NULL;
450  cpl_image *work_back = NULL;
451  cpl_image *bmaxsigma = NULL;
452  cpl_image *bsigma = NULL;
453  fors_image *fbsigma = NULL;
454  fors_image *cropped = NULL;
455  int croplx, croply, cropux, cropuy;
456  const char *const filename_data_full = "sextract_data_full.fits";
457  const char *const filename_sigma_full = "sextract_bkg_sigma_full.fits";
458  int vignetted = 1;
459 
460  assure( setting != NULL, return NULL, NULL );
461 
462  assure( image != NULL, return NULL, NULL );
463 
464  assure( sky_stats != NULL, return NULL, NULL );
465  assure( background != NULL, return NULL, NULL );
466 
467 
468  /*
469  * In case of new chips, crop
470  */
471 
472  if (strcmp(setting->chip_id, "CCID20-14-5-6") == 0) {
473  croplx = 380 / setting->binx;
474  croply = 626 / setting->biny;
475  cropux = 3714 / setting->binx;
476  cropuy = 2048 / setting->biny;
477  }
478  else if (strcmp(setting->chip_id, "CCID20-14-5-3") == 0) {
479  croplx = 380 / setting->binx;
480  croply = 2 / setting->biny;
481  cropux = 3714 / setting->binx;
482  cropuy = 1920 / setting->biny;
483  }
484  else if (strncmp(setting->chip_id, "Marl", 4) == 0) {
485  croplx = 380 / setting->binx;
486  croply = 694 / setting->biny;
487  cropux = 3690 / setting->binx;
488  cropuy = 2048 / setting->biny;
489  }
490  else if (strncmp(setting->chip_id, "Norm", 4) == 0) {
491  croplx = 380 / setting->binx;
492  croply = 2 / setting->biny;
493  cropux = 3690 / setting->binx;
494  cropuy = 1894 / setting->biny;
495  }
496  else {
497  vignetted = 0;
498  }
499 
500  cropped = (fors_image *)image; /* As a default.... */
501 
502  if (vignetted) {
503  fors_image_save_sex(image, NULL,
504  filename_data_full,
505  filename_sigma_full,
506  radius);
507 
508  assure( !cpl_error_get_code(), return NULL,
509  "Could not save image to %s and %s",
510  filename_data_full, filename_sigma_full);
511 
512  cropped = fors_image_duplicate(image);
513  fors_image_crop(cropped, croplx, croply, cropux, cropuy);
514  }
515 
516  /* provide data and error bars in separate files,
517  pass to sextractor */
518 
519  fors_image_save_sex(cropped, NULL,
520  filename_data,
521  filename_sigma,
522  radius);
523  assure( !cpl_error_get_code(), return NULL,
524  "Could not save image to %s and %s",
525  filename_data, filename_sigma);
526 
527  if (vignetted)
528  fors_image_delete(&cropped);
529 
530 
531  /*
532  * A = load filename_sigma
533  *
534  * M = fors_image_max_filter(A)
535  *
536  * |A-M|
537  */
538 
539  command = cpl_sprintf("%s %s,%s "
540  "-c %s "
541  /* Use SExtractor's double mode which is probably
542  more tested and more bugfree than the
543  single image mode */
544  "-GAIN %f " /* Different terminology here:
545  SExtractor-gain == ESO-conad,
546  unit = e- / ADU
547  */
548  "-PIXEL_SCALE %f "
549  "-CHECKIMAGE_TYPE BACKGROUND "
550  "-CHECKIMAGE_NAME %s "
551  "-WEIGHT_TYPE MAP_RMS "
552  "-WEIGHT_IMAGE %s,%s "
553  "-CATALOG_TYPE FITS_1.0 "
554  "-CATALOG_NAME %s",
555  sex_exe,
556  filename_data, filename_data,
557  sex_config,
558  1.0/setting->average_gain,
559  setting->pixel_scale,
560  filename_bkg,
561  filename_sigma, filename_sigma,
562  filename_cat);
563 
564  cpl_msg_info(cpl_func, "Running '%s'", command);
565 
566  assure( system(command) == 0, return stars, "'%s' failed", command);
567 
568  /*
569  * The background map is here used just to evaluate a QC parameter,
570  * and is also returned to the caller.
571  */
572  {
573  int plane = 0;
574  int extension = 0;
575 
576  *background = cpl_image_load(filename_bkg,
577  CPL_TYPE_FLOAT, plane, extension);
578 
579  assure( !cpl_error_get_code(), return NULL,
580  "Could not load SExtractor background image %s",
581  filename_bkg );
582 
583  if (vignetted) {
584  work_back = cpl_image_new(fors_image_get_size_x(image),
585  fors_image_get_size_y(image),
586  CPL_TYPE_FLOAT);
587  cpl_image_copy(work_back, *background, croplx, croply);
588 
589  assure( !cpl_error_get_code(), return NULL,
590  "Could not insert background image %s",
591  filename_bkg );
592 
593  cpl_image_delete(*background);
594  *background = work_back;
595  work_back = NULL;
596  }
597 
598  /*
599  * To avoid using the non-illuminated parts, use only the central
600  * 100x100 window.
601  *
602  * It does not make too much sense to trend these QC parameters
603  * anyway because they mostly describe the individual science
604  * exposures.
605  */
606 
607  int nx = cpl_image_get_size_x(*background);
608  int ny = cpl_image_get_size_y(*background);
609  int xlo = nx/2 - 50;
610  int xhi = nx/2 + 50;
611  int ylo = ny/2 - 50;
612  int yhi = ny/2 + 50;
613 
614  if (xlo < 0) xlo = 0; /* Just in case... */
615  if (xhi >= nx) xhi = nx - 1;
616  if (ylo < 0) ylo = 0;
617  if (yhi >= ny) yhi = ny - 1;
618 
619  work_back = cpl_image_duplicate(*background);
620 
621  sky_stats->mean = cpl_image_get_mean_window(work_back,
622  xlo, ylo, xhi, yhi);
623  sky_stats->median = cpl_image_get_median_window(work_back,
624  xlo, ylo, xhi, yhi);
625  cpl_image_subtract_scalar(work_back, sky_stats->median);
626  cpl_image_abs(work_back);
627  sky_stats->rms = cpl_image_get_median_window(work_back,
628  xlo, ylo, xhi, yhi)
629  * STDEV_PR_MAD;
630 
631  cpl_image_delete(work_back); work_back = NULL;
632 
633  assure( !cpl_error_get_code(), return NULL,
634  "Could not calculate sky statistics" );
635 
636  }
637 
638  cpl_msg_info(cpl_func, "Background = %f +- %f ADU",
639  sky_stats->median, sky_stats->rms);
640 
641  /*
642  * SExtractors background estimation is not reliable near
643  * non-illuminated areas. The underestimated background
644  * leads to false detections.
645  * Therefore, reject sources which are too close to the
646  * illumination edge. The edge is masked using a max filter
647  * on the smoothed variance image of the background map.
648  * The filter must have comparable size to the SExtractor
649  * BACK_SIZE parameter. The discrimination level is half-way
650  * between the high-variance and low-variance regions.
651  */
652 
653  float level;
654  {
655  int xradius = 64;
656  int yradius = 64;
657  int plane = 0;
658  int extension = 0;
659  float maxima;
660  float minima;
661 
662  if (vignetted) {
663  bsigma = cpl_image_load(filename_sigma_full,
664  CPL_TYPE_FLOAT, plane, extension);
665  }
666  else {
667  bsigma = cpl_image_load(filename_sigma,
668  CPL_TYPE_FLOAT, plane, extension);
669  }
670 
671  assure( !cpl_error_get_code(), return NULL,
672  "Could not load SExtractor background error image %s",
673  filename_sigma );
674 
675  /*
676  * Duplication is necessary for creating the fors_image
677  * to be passed to fors_image_filter_max_create()
678  */
679 
680  /* this wraps the fors_image around the cpl images,
681  * so set them to NULL */
682 
683  fbsigma = fors_image_new(cpl_image_duplicate(bsigma), bsigma);
684  bsigma = NULL;
685 
686  {
687  bool use_variance = true;
688  bmaxsigma = fors_image_filter_max_create(fbsigma, xradius,
689  yradius, use_variance);
690 
691  /* cpl_image_save(bmaxsigma, "/tmp/test.fits", CPL_BPP_IEEE_FLOAT, NULL,
692  CPL_IO_DEFAULT); */
693 
694  }
695 
696  fors_image_delete(&fbsigma);
697 
698  /*
699  This is not robust if there are no non-illuminated areas.
700 
701  maxima = cpl_image_get_max(bmaxsigma);
702  minima = cpl_image_get_min(bmaxsigma);
703  level = (maxima + minima) / 2;
704  */
705 
706  /* 5 sigma rejection */
707  level = cpl_image_get_median(bmaxsigma) * 5;
708 
709  cpl_msg_debug(cpl_func, "Threshold level = %f",
710  level);
711 
712  }
713 
714  out = cpl_table_load(filename_cat, 1, 1);
715 
716  assure( !cpl_error_get_code(), return NULL,
717  "Could not load SExtractor output table %s",
718  filename_cat);
719 
720  /* Validate sextractor output */
721  assure( cpl_table_has_column(out, "FLAGS"), return NULL,
722  "%s: Missing column: %s", filename_cat, "FLAGS");
723 
724  assure( cpl_table_has_column(out, "CLASS_STAR"), return NULL,
725  "%s: Missing column: %s", filename_cat, "CLASS_STAR");
726 
727  assure( cpl_table_has_column(out, "BACKGROUND"), return NULL,
728  "%s: Missing column: %s", filename_cat, "BACKGROUND");
729 
730  assure( cpl_table_has_column(out, "X_IMAGE"), return NULL,
731  "%s: Missing column: %s", filename_cat, "X_IMAGE");
732 
733  assure( cpl_table_has_column(out, "Y_IMAGE"), return NULL,
734  "%s: Missing column: %s", filename_cat, "Y_IMAGE");
735 
736  assure( cpl_table_has_column(out, "FWHM_IMAGE"), return NULL,
737  "%s: Missing column: %s", filename_cat, "FWHM_IMAGE");
738 
739  assure( cpl_table_has_column(out, "A_IMAGE"), return NULL,
740  "%s: Missing column: %s", filename_cat, "A_IMAGE");
741 
742  assure( cpl_table_has_column(out, "B_IMAGE"), return NULL,
743  "%s: Missing column: %s", filename_cat, "B_IMAGE");
744 
745  assure( cpl_table_has_column(out, "THETA_IMAGE"), return NULL,
746  "%s: Missing column: %s", filename_cat, "THETA_IMAGE");
747 
748  assure( cpl_table_has_column(out, sex_mag), return NULL,
749  "%s: Missing column: %s", filename_cat, sex_mag);
750 
751  assure( cpl_table_has_column(out, sex_magerr), return NULL,
752  "%s: Missing column: %s", filename_cat, sex_magerr);
753 
754 
755  /* cpl_table_dump_structure(out, stdout); */
756 
757  if (vignetted) {
758  cpl_table_add_scalar(out, "X_IMAGE", croplx - 1);
759  cpl_table_add_scalar(out, "Y_IMAGE", croply - 1);
760  }
761 
762  stars = fors_star_list_new();
763 
764  {
765  int i;
766  int bkg_rejected = 0;
767  int rejected = 0;
768  float *bdata = cpl_image_get_data(bmaxsigma);
769  int nx = cpl_image_get_size_x(bmaxsigma);
770  int ny = cpl_image_get_size_y(bmaxsigma);
771 
772  for (i = 0; i < cpl_table_get_nrow(out); i++) {
773  fors_star *s = NULL;
774  unsigned int flags = 0x0;
775  int x, y, tmp;
776  double bg_err;
777 
778  s = fors_star_new_from_table( out,
779  i,
780  "X_IMAGE",
781  "Y_IMAGE",
782  "FWHM_IMAGE",
783  "A_IMAGE",
784  "B_IMAGE",
785  "THETA_IMAGE",
786  sex_mag,
787  sex_magerr,
788  "CLASS_STAR");
789  (*s).orientation *= M_PI/180;
790  (*s).semi_major *= setting->binx;
791  (*s).semi_minor *= setting->binx;
792  (*s).fwhm *= setting->binx;
793  (*s).dmagnitude = sqrt((*s).dmagnitude * (*s).dmagnitude + magsyserr * magsyserr);
794 
795  flags = cpl_table_get_int( out, "FLAGS", i, NULL);
796 
797  x = (int)(s->pixel->x + 0.5);
798  y = (int)(s->pixel->y + 0.5);
799  if (x >= 1 && x <= nx && y >= 1 && y <= ny)
800  bg_err = cpl_image_get(bmaxsigma, x, y, &tmp);
801  else
802  bg_err = -1.0;
803 
804  if (fors_extract_check_sex_flag(flags)
805  && fors_extract_check_sex_star(s, bmaxsigma)
806  && bg_err < level)
807  {
808  cpl_msg_debug( cpl_func,
809  "Source at (%f, %f): fwhm = %f px",
810  s->pixel->x, s->pixel->y, s->fwhm);
811  assure( !cpl_error_get_code(), return NULL,
812  "Could not read SExtractor "
813  "output table %s",
814  filename_cat);
815  fors_star_list_insert(stars, s);
816  }
817  else
818  {
819  cpl_msg_debug( cpl_func,
820  "Rejecting source at (%f, %f): "
821  "flags = 0x%x; fwhm = %f pix; "
822  "background error = %f; "
823  "level = %f; "
824  "background = %f",
825  s->pixel->x, s->pixel->y,
826  flags, s->fwhm,
827  bg_err, level,
828  cpl_table_get_float(
829  out, "BACKGROUND", i, NULL));
830  fors_star_delete(&s);
831  rejected++;
832  if (bg_err >= level)
833  bkg_rejected++;
834  }
835  }
836 
837  cpl_msg_info(cpl_func, "%d sources sextracted, %d rejected",
838  fors_star_list_size(stars) + rejected,
839  rejected);
840  }
841 
842  if (extracted_sources != NULL) {
843  *extracted_sources = cpl_table_duplicate(out);
844  }
845 
846  cleanup;
847  return stars;
848 }
849 
850 /*----------------------------------------------------------------------------*/
851 #undef cleanup
852 #define cleanup
853 
865 /*----------------------------------------------------------------------------*/
866 static fors_star_list *
868  cpl_image **background,
869  cpl_table **extracted_sources)
870 {
871  assure( sky_stats != NULL, return NULL, NULL );
872  assure( background != NULL, return NULL, NULL );
873 
874  sky_stats->mean = 1;
875  sky_stats->median = 2;
876  sky_stats->rms = 3;
877 
878  *background = cpl_image_new(10, 20, CPL_TYPE_FLOAT); /* Zero, wrong size */
879 
880  fors_star_list *stars = fors_star_list_new();
881 
882  struct {
883  double x, y, magnitude, dmagnitude;
884  }
885  data[] = {
886  {100 , 200, -10, 0.01},
887  {1100, 200, -11, 0.01},
888  {1 , 5 , -10, 0.01},
889  {100 , 1200, -12, 0.01},
890  {1100, 1200, -13, 0.01}
891  };
892 
893  int N = sizeof(data) / sizeof(*data);
894  int i;
895  double a = 2;
896  double b = 1;
897  double fwhm = 1.5;
898  double orientation = 1.0; /* radians */
899 
900  for (i = 0; i < N; i++) {
901  fors_star_list_insert(stars,
902  fors_star_new(data[i].x,
903  data[i].y,
904  fwhm,
905  a, b, orientation,
906  data[i].magnitude,
907  data[i].dmagnitude,
908  1.0));
909  }
910 
911  if (extracted_sources != NULL) {
912  *extracted_sources = fors_create_sources_table(stars);
913 
914  assure (!cpl_error_get_code(), return NULL,
915  "Could not create extracted sources table");
916  }
917 
918  return stars;
919 }
920 
fors_image * fors_image_new(cpl_image *data, cpl_image *variance)
Create image.
Definition: fors_image.c:102
static fors_star_list * extract_test(fors_extract_sky_stats *sky_stats, cpl_image **background, cpl_table **extracted_sources)
Extract sources.
void fors_image_save_sex(const fors_image *image, const cpl_propertylist *header, const char *filename_dat, const char *filename_var, int radius)
Save image in format useable by SExtractor.
Definition: fors_image.c:432
void fors_star_delete(fors_star **star)
Delete object and set pointer to NULL.
Definition: fors_star.c:273
void fors_image_crop(fors_image *image, int xlo, int ylo, int xhi, int yhi)
Crop image.
Definition: fors_image.c:1012
void fors_image_delete(fors_image **image)
Deallocate image and set pointer to NULL.
Definition: fors_image.c:162
cpl_size fors_image_get_size_y(const fors_image *image)
Get image height.
Definition: fors_image.c:518
static fors_star_list * extract_sex(const fors_image *image, const fors_setting *setting, const char *sex_exe, const char *sex_config, const char *sex_mag, const char *sex_magerr, int radius, double magsyserr, fors_extract_sky_stats *sky_stats, cpl_image **background, cpl_table **extracted_sources)
Extract sources using SExtractor.
#define assure(EXPR)
Definition: list.c:101
int dfs_get_parameter_int_const(const cpl_parameterlist *parlist, const char *name)
Definition: fors_dfs.c:791
void fors_extract_method_delete(extract_method **em)
Deallocate extraction method and set the pointer to NULL.
cpl_image * fors_image_filter_max_create(const fors_image *image, int xradius, int yradius, bool use_data)
Max filter image.
Definition: fors_image.c:1302
fors_star * fors_star_new(double x, double y, double fwhm, double smajor, double sminor, double orientation, double m, double dm, double si)
Constructor.
Definition: fors_star.c:114
void fors_extract_define_parameters(cpl_parameterlist *parameters, const char *context)
Define recipe parameters.
bool fors_extract_check_sex_flag(unsigned int sex_flag)
Check SExtractor object feature: FLAG.
cpl_size fors_image_get_size_x(const fors_image *image)
Get image width.
Definition: fors_image.c:505
bool fors_star_check_values(const fors_star *star)
Copy constructor.
Definition: fors_star.c:227
const char * dfs_get_parameter_string_const(const cpl_parameterlist *parlist, const char *name)
Definition: fors_dfs.c:811
cpl_table * fors_create_sources_table(fors_star_list *sources)
Create product.
Definition: fors_tools.c:130
fors_star_list * fors_extract(const fors_image *image, const fors_setting *setting, const extract_method *em, double magsyserr, fors_extract_sky_stats *sky_stats, cpl_image **background, cpl_table **extracted_sources)
Extract sources.
fors_image * fors_image_duplicate(const fors_image *image)
Copy constructor.
Definition: fors_image.c:149
extract_method * fors_extract_method_new(const cpl_parameterlist *parameters, const char *context)
Get extraction method from parameter list.
bool fors_extract_check_sex_star(const fors_star *star, const cpl_image *ref_img)
Check a sextracted star for validity.
fors_star * fors_star_new_from_table(const cpl_table *tab, unsigned int row, const char *x_col, const char *y_col, const char *fwhm_col, const char *smaj_col, const char *smin_col, const char *theta_col, const char *mag_col, const char *dmag_col, const char *stlndx_col)
Create a star from a table WITHOUT checking.
Definition: fors_star.c:170