FORS Pipeline Reference Manual 4.9.20
|
00001 /* $Id: fors_extract.c,v 1.45 2011/10/13 14:29:24 cgarcia Exp $ 00002 * 00003 * This file is part of the FORS Library 00004 * Copyright (C) 2002-2010 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 /* 00022 * $Author: cgarcia $ 00023 * $Date: 2011/10/13 14:29:24 $ 00024 * $Revision: 1.45 $ 00025 * $Name: fors-4_9_20 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <fors_extract.h> 00033 #include <fors_star.h> 00034 00035 #include <fors_tools.h> 00036 #include <fors_dfs.h> 00037 #include <fors_pfits.h> 00038 #include <fors_utils.h> 00039 00040 #include <cpl.h> 00041 00042 #include <string.h> 00043 #include <stdbool.h> 00044 #include <math.h> 00045 00052 /*----------------------------------------------------------------------------- 00053 (Proto)types 00054 -----------------------------------------------------------------------------*/ 00055 00056 struct _extract_method 00057 { 00058 enum {SEX, TEST} method; 00059 const char *sex_exe; 00060 const char *sex_config; 00061 const char *sex_mag; 00062 const char *sex_magerr; 00063 int sex_radius; 00064 }; 00065 00066 static fors_star_list * 00067 extract_sex( const fors_image *image, 00068 const fors_setting *setting, 00069 const char *sex_exe, 00070 const char *sex_config, 00071 const char *sex_mag, 00072 const char *sex_magerr, 00073 int radius, 00074 double magsyserr, 00075 fors_extract_sky_stats *sky_stats, 00076 cpl_image **background, 00077 cpl_table **extracted_sources); 00078 00079 static fors_star_list * 00080 extract_test( fors_extract_sky_stats *sky_stats, 00081 cpl_image **background, 00082 cpl_table **extracted_sources); 00083 00084 /*----------------------------------------------------------------------------- 00085 Implementation 00086 -----------------------------------------------------------------------------*/ 00087 00088 /*----------------------------------------------------------------------------*/ 00098 /*----------------------------------------------------------------------------*/ 00099 bool 00100 fors_extract_check_sex_flag( unsigned int sex_flag) 00101 { 00102 return (sex_flag == 0x0); 00103 } 00104 00105 /*----------------------------------------------------------------------------*/ 00120 /*----------------------------------------------------------------------------*/ 00121 bool 00122 fors_extract_check_sex_star( const fors_star *star, 00123 const cpl_image *ref_img) 00124 { 00125 bool success = 1; 00126 00127 if (star == NULL) 00128 return 0; 00129 00130 success &= fors_star_check_values(star); 00131 00132 success &= (star->magnitude < 98); 00133 00134 if (ref_img != NULL) 00135 { 00136 success &= star->pixel->x >= 1; 00137 success &= star->pixel->x <= cpl_image_get_size_x(ref_img); 00138 success &= star->pixel->y >= 1; 00139 success &= star->pixel->y <= cpl_image_get_size_y(ref_img); 00140 } 00141 00142 return success; 00143 } 00144 00145 /*----------------------------------------------------------------------------*/ 00151 /*----------------------------------------------------------------------------*/ 00152 void 00153 fors_extract_define_parameters( cpl_parameterlist *parameters, 00154 const char *context) 00155 { 00156 cpl_parameter *p; 00157 const char *full_name = NULL; 00158 const char *name; 00159 00160 /* 00161 name = "extract_method"; 00162 full_name = cpl_sprintf("%s.%s", context, name); 00163 p = cpl_parameter_new_enum(full_name, 00164 CPL_TYPE_STRING, 00165 "Source extraction method", 00166 context, 00167 "sex", 2, 00168 "sex", "test"); 00169 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00170 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00171 cpl_parameterlist_append(parameters, p); 00172 cpl_free((void *)full_name); 00173 */ 00174 00175 name = "sex_exe"; 00176 full_name = cpl_sprintf("%s.%s", context, name); 00177 p = cpl_parameter_new_value(full_name, 00178 CPL_TYPE_STRING, 00179 "SExtractor executable", 00180 context, 00181 FORS_SEXTRACTOR_PATH "/sex"); 00182 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00183 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00184 cpl_parameterlist_append(parameters, p); 00185 cpl_free((void *)full_name); 00186 00187 name = "sex_config"; 00188 full_name = cpl_sprintf("%s.%s", context, name); 00189 p = cpl_parameter_new_value(full_name, 00190 CPL_TYPE_STRING, 00191 "SExtractor configuration file", 00192 context, 00193 FORS_SEXTRACTOR_CONFIG "/fors.sex"); 00194 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00195 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00196 cpl_parameterlist_append(parameters, p); 00197 cpl_free((void *)full_name); 00198 00199 00200 name = "sex_mag"; 00201 full_name = cpl_sprintf("%s.%s", context, name); 00202 p = cpl_parameter_new_value(full_name, 00203 CPL_TYPE_STRING, 00204 "SExtractor magnitude", 00205 context, 00206 "MAG_APER"); 00207 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00208 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00209 cpl_parameterlist_append(parameters, p); 00210 cpl_free((void *)full_name); 00211 00212 name = "sex_magerr"; 00213 full_name = cpl_sprintf("%s.%s", context, name); 00214 p = cpl_parameter_new_value(full_name, 00215 CPL_TYPE_STRING, 00216 "SExtractor magnitude error", 00217 context, 00218 "MAGERR_APER"); 00219 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00220 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00221 cpl_parameterlist_append(parameters, p); 00222 cpl_free((void *)full_name); 00223 00224 name = "sex_radius"; 00225 full_name = cpl_sprintf("%s.%s", context, name); 00226 p = cpl_parameter_new_value(full_name, 00227 CPL_TYPE_INT, 00228 "Background error map median filter " 00229 "radius (unbinned pixels)", 00230 context, 00231 64); 00232 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00233 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00234 cpl_parameterlist_append(parameters, p); 00235 cpl_free((void *)full_name); full_name = NULL; 00236 00237 return; 00238 } 00239 00240 /*----------------------------------------------------------------------------*/ 00241 #undef cleanup 00242 #define cleanup \ 00243 do { \ 00244 cpl_free((void *)name); \ 00245 cpl_free((void *)method); \ 00246 } while (0) 00247 00256 /*----------------------------------------------------------------------------*/ 00257 extract_method * 00258 fors_extract_method_new( const cpl_parameterlist *parameters, 00259 const char *context) 00260 { 00261 extract_method *em = cpl_malloc(sizeof(*em)); 00262 const char *name = NULL; 00263 const char *method = NULL; 00264 00265 cpl_msg_info(cpl_func, "Extraction method:"); 00266 00267 cpl_msg_indent_more(); 00268 //"sex" method is the default. The parameter won't appear when calling 00269 //the recipe from esorex, but it will in the unit tests fors_zeropoint-test, 00270 //fors_img_science-test. 00271 name = cpl_sprintf("%s.%s", context, "extract_method"); 00272 if(cpl_parameterlist_find_const(parameters, name) == NULL) 00273 method = cpl_sprintf("%s", "sex"); 00274 else 00275 method = cpl_sprintf("%s",dfs_get_parameter_string_const(parameters, name)); 00276 cpl_free((void *)name); name = NULL; 00277 cpl_msg_indent_less(); 00278 00279 assure( !cpl_error_get_code(), return NULL, NULL ); 00280 assure( method != NULL, return NULL, NULL ); 00281 00282 if (strcmp(method, "sex") == 0) { 00283 em->method = SEX; 00284 00285 cpl_msg_indent_more(); 00286 name = cpl_sprintf("%s.%s", context, "sex_exe"); 00287 em->sex_exe = dfs_get_parameter_string_const(parameters, 00288 name); 00289 cpl_free((void *)name); name = NULL; 00290 cpl_msg_indent_less(); 00291 00292 00293 cpl_msg_indent_more(); 00294 name = cpl_sprintf("%s.%s", context, "sex_config"); 00295 em->sex_config = dfs_get_parameter_string_const(parameters, 00296 name); 00297 cpl_free((void *)name); name = NULL; 00298 cpl_msg_indent_less(); 00299 00300 00301 00302 cpl_msg_indent_more(); 00303 name = cpl_sprintf("%s.%s", context, "sex_mag"); 00304 em->sex_mag = dfs_get_parameter_string_const(parameters, 00305 name); 00306 cpl_free((void *)name); name = NULL; 00307 cpl_msg_indent_less(); 00308 00309 00310 cpl_msg_indent_more(); 00311 name = cpl_sprintf("%s.%s", context, "sex_magerr"); 00312 em->sex_magerr = dfs_get_parameter_string_const(parameters, 00313 name); 00314 cpl_free((void *)name); name = NULL; 00315 cpl_msg_indent_less(); 00316 00317 00318 cpl_msg_indent_more(); 00319 name = cpl_sprintf("%s.%s", context, "sex_radius"); 00320 em->sex_radius = dfs_get_parameter_int_const(parameters, 00321 name); 00322 cpl_free((void *)name); name = NULL; 00323 cpl_msg_indent_less(); 00324 } 00325 else if (strcmp(method, "test") == 0) { 00326 em->method = TEST; 00327 } 00328 else { 00329 assure( false, return NULL, "Unknown extraction method '%s'", method); 00330 } 00331 00332 cleanup; 00333 return em; 00334 } 00335 00336 /*----------------------------------------------------------------------------*/ 00340 /*----------------------------------------------------------------------------*/ 00341 void 00342 fors_extract_method_delete( extract_method **em) 00343 { 00344 if (em && *em) { 00345 cpl_free(*em); *em = NULL; 00346 } 00347 return; 00348 } 00349 00350 /*----------------------------------------------------------------------------*/ 00351 #undef cleanup 00352 #define cleanup 00353 00363 /*----------------------------------------------------------------------------*/ 00364 fors_star_list * 00365 fors_extract( const fors_image *image, 00366 const fors_setting *setting, 00367 const extract_method *em, 00368 double magsyserr, 00369 fors_extract_sky_stats *sky_stats, 00370 cpl_image **background, 00371 cpl_table **extracted_sources) 00372 { 00373 assure( em != NULL, return NULL, NULL ); 00374 00375 cpl_msg_info(cpl_func, "Extracting sources"); 00376 00377 switch (em->method ) { 00378 case SEX: return extract_sex(image, setting, 00379 em->sex_exe, 00380 em->sex_config, 00381 em->sex_mag, 00382 em->sex_magerr, 00383 em->sex_radius, 00384 magsyserr, 00385 sky_stats, 00386 background, 00387 extracted_sources); break; 00388 case TEST: return extract_test(sky_stats, background, extracted_sources); break; 00389 default: 00390 assure( false, return NULL, "Unknown method %d", em->method ); 00391 break; 00392 } 00393 } 00394 00395 /*----------------------------------------------------------------------------*/ 00396 #undef cleanup 00397 #define cleanup \ 00398 do { \ 00399 cpl_table_delete(out); out = NULL; \ 00400 cpl_free((void *)command); \ 00401 cpl_image_delete(work_back); work_back = NULL; \ 00402 cpl_image_delete(bmaxsigma); bmaxsigma = NULL; \ 00403 cpl_image_delete(bsigma); bsigma = NULL; \ 00404 fors_image_delete(&fbsigma); \ 00405 } while (0) 00406 00429 /*----------------------------------------------------------------------------*/ 00430 static fors_star_list * 00431 extract_sex( const fors_image *image, 00432 const fors_setting *setting, 00433 const char *sex_exe, 00434 const char *sex_config, 00435 const char *sex_mag, 00436 const char *sex_magerr, 00437 int radius, 00438 double magsyserr, 00439 fors_extract_sky_stats *sky_stats, 00440 cpl_image **background, 00441 cpl_table **extracted_sources) 00442 { 00443 const char *const filename_data = "sextract_data.fits"; 00444 const char *const filename_sigma = "sextract_bkg_sigma.fits"; 00445 const char *const filename_cat = "sextract_cat.fits"; 00446 const char *const filename_bkg = "sextract_bkg.fits"; 00447 cpl_table *out = NULL; 00448 const char *command = NULL; 00449 fors_star_list *stars = NULL; 00450 cpl_image *work_back = NULL; 00451 cpl_image *bmaxsigma = NULL; 00452 cpl_image *bsigma = NULL; 00453 fors_image *fbsigma = NULL; 00454 fors_image *cropped = NULL; 00455 int croplx, croply, cropux, cropuy; 00456 const char *const filename_data_full = "sextract_data_full.fits"; 00457 const char *const filename_sigma_full = "sextract_bkg_sigma_full.fits"; 00458 int vignetted = 1; 00459 00460 assure( setting != NULL, return NULL, NULL ); 00461 00462 assure( image != NULL, return NULL, NULL ); 00463 00464 assure( sky_stats != NULL, return NULL, NULL ); 00465 assure( background != NULL, return NULL, NULL ); 00466 00467 00468 /* 00469 * In case of new chips, crop 00470 */ 00471 00472 if (strcmp(setting->chip_id, "CCID20-14-5-6") == 0) { 00473 croplx = 380 / setting->binx; 00474 croply = 626 / setting->biny; 00475 cropux = 3714 / setting->binx; 00476 cropuy = 2048 / setting->biny; 00477 } 00478 else if (strcmp(setting->chip_id, "CCID20-14-5-3") == 0) { 00479 croplx = 380 / setting->binx; 00480 croply = 2 / setting->biny; 00481 cropux = 3714 / setting->binx; 00482 cropuy = 1920 / setting->biny; 00483 } 00484 else if (strncmp(setting->chip_id, "Marl", 4) == 0) { 00485 croplx = 380 / setting->binx; 00486 croply = 694 / setting->biny; 00487 cropux = 3690 / setting->binx; 00488 cropuy = 2048 / setting->biny; 00489 } 00490 else if (strncmp(setting->chip_id, "Norm", 4) == 0) { 00491 croplx = 380 / setting->binx; 00492 croply = 2 / setting->biny; 00493 cropux = 3690 / setting->binx; 00494 cropuy = 1894 / setting->biny; 00495 } 00496 else { 00497 vignetted = 0; 00498 } 00499 00500 cropped = (fors_image *)image; /* As a default.... */ 00501 00502 if (vignetted) { 00503 fors_image_save_sex(image, NULL, 00504 filename_data_full, 00505 filename_sigma_full, 00506 radius); 00507 00508 assure( !cpl_error_get_code(), return NULL, 00509 "Could not save image to %s and %s", 00510 filename_data_full, filename_sigma_full); 00511 00512 cropped = fors_image_duplicate(image); 00513 fors_image_crop(cropped, croplx, croply, cropux, cropuy); 00514 } 00515 00516 /* provide data and error bars in separate files, 00517 pass to sextractor */ 00518 00519 fors_image_save_sex(cropped, NULL, 00520 filename_data, 00521 filename_sigma, 00522 radius); 00523 assure( !cpl_error_get_code(), return NULL, 00524 "Could not save image to %s and %s", 00525 filename_data, filename_sigma); 00526 00527 if (vignetted) 00528 fors_image_delete(&cropped); 00529 00530 00531 /* 00532 * A = load filename_sigma 00533 * 00534 * M = fors_image_max_filter(A) 00535 * 00536 * |A-M| 00537 */ 00538 00539 command = cpl_sprintf("%s %s,%s " 00540 "-c %s " 00541 /* Use SExtractor's double mode which is probably 00542 more tested and more bugfree than the 00543 single image mode */ 00544 "-GAIN %f " /* Different terminology here: 00545 SExtractor-gain == ESO-conad, 00546 unit = e- / ADU 00547 */ 00548 "-PIXEL_SCALE %f " 00549 "-CHECKIMAGE_TYPE BACKGROUND " 00550 "-CHECKIMAGE_NAME %s " 00551 "-WEIGHT_TYPE MAP_RMS " 00552 "-WEIGHT_IMAGE %s,%s " 00553 "-CATALOG_TYPE FITS_1.0 " 00554 "-CATALOG_NAME %s", 00555 sex_exe, 00556 filename_data, filename_data, 00557 sex_config, 00558 1.0/setting->average_gain, 00559 setting->pixel_scale, 00560 filename_bkg, 00561 filename_sigma, filename_sigma, 00562 filename_cat); 00563 00564 cpl_msg_info(cpl_func, "Running '%s'", command); 00565 00566 assure( system(command) == 0, return stars, "'%s' failed", command); 00567 00568 /* 00569 * The background map is here used just to evaluate a QC parameter, 00570 * and is also returned to the caller. 00571 */ 00572 { 00573 int plane = 0; 00574 int extension = 0; 00575 00576 *background = cpl_image_load(filename_bkg, 00577 CPL_TYPE_FLOAT, plane, extension); 00578 00579 assure( !cpl_error_get_code(), return NULL, 00580 "Could not load SExtractor background image %s", 00581 filename_bkg ); 00582 00583 if (vignetted) { 00584 work_back = cpl_image_new(fors_image_get_size_x(image), 00585 fors_image_get_size_y(image), 00586 CPL_TYPE_FLOAT); 00587 cpl_image_copy(work_back, *background, croplx, croply); 00588 00589 assure( !cpl_error_get_code(), return NULL, 00590 "Could not insert background image %s", 00591 filename_bkg ); 00592 00593 cpl_image_delete(*background); 00594 *background = work_back; 00595 work_back = NULL; 00596 } 00597 00598 /* 00599 * To avoid using the non-illuminated parts, use only the central 00600 * 100x100 window. 00601 * 00602 * It does not make too much sense to trend these QC parameters 00603 * anyway because they mostly describe the individual science 00604 * exposures. 00605 */ 00606 00607 int nx = cpl_image_get_size_x(*background); 00608 int ny = cpl_image_get_size_y(*background); 00609 int xlo = nx/2 - 50; 00610 int xhi = nx/2 + 50; 00611 int ylo = ny/2 - 50; 00612 int yhi = ny/2 + 50; 00613 00614 if (xlo < 0) xlo = 0; /* Just in case... */ 00615 if (xhi >= nx) xhi = nx - 1; 00616 if (ylo < 0) ylo = 0; 00617 if (yhi >= ny) yhi = ny - 1; 00618 00619 work_back = cpl_image_duplicate(*background); 00620 00621 sky_stats->mean = cpl_image_get_mean_window(work_back, 00622 xlo, ylo, xhi, yhi); 00623 sky_stats->median = cpl_image_get_median_window(work_back, 00624 xlo, ylo, xhi, yhi); 00625 cpl_image_subtract_scalar(work_back, sky_stats->median); 00626 cpl_image_abs(work_back); 00627 sky_stats->rms = cpl_image_get_median_window(work_back, 00628 xlo, ylo, xhi, yhi) 00629 * STDEV_PR_MAD; 00630 00631 cpl_image_delete(work_back); work_back = NULL; 00632 00633 assure( !cpl_error_get_code(), return NULL, 00634 "Could not calculate sky statistics" ); 00635 00636 } 00637 00638 cpl_msg_info(cpl_func, "Background = %f +- %f ADU", 00639 sky_stats->median, sky_stats->rms); 00640 00641 /* 00642 * SExtractors background estimation is not reliable near 00643 * non-illuminated areas. The underestimated background 00644 * leads to false detections. 00645 * Therefore, reject sources which are too close to the 00646 * illumination edge. The edge is masked using a max filter 00647 * on the smoothed variance image of the background map. 00648 * The filter must have comparable size to the SExtractor 00649 * BACK_SIZE parameter. The discrimination level is half-way 00650 * between the high-variance and low-variance regions. 00651 */ 00652 00653 float level; 00654 { 00655 int xradius = 64; 00656 int yradius = 64; 00657 int plane = 0; 00658 int extension = 0; 00659 float maxima; 00660 float minima; 00661 00662 if (vignetted) { 00663 bsigma = cpl_image_load(filename_sigma_full, 00664 CPL_TYPE_FLOAT, plane, extension); 00665 } 00666 else { 00667 bsigma = cpl_image_load(filename_sigma, 00668 CPL_TYPE_FLOAT, plane, extension); 00669 } 00670 00671 assure( !cpl_error_get_code(), return NULL, 00672 "Could not load SExtractor background error image %s", 00673 filename_sigma ); 00674 00675 /* 00676 * Duplication is necessary for creating the fors_image 00677 * to be passed to fors_image_filter_max_create() 00678 */ 00679 00680 /* this wraps the fors_image around the cpl images, 00681 * so set them to NULL */ 00682 00683 fbsigma = fors_image_new(cpl_image_duplicate(bsigma), bsigma); 00684 bsigma = NULL; 00685 00686 { 00687 bool use_variance = true; 00688 bmaxsigma = fors_image_filter_max_create(fbsigma, xradius, 00689 yradius, use_variance); 00690 00691 /* cpl_image_save(bmaxsigma, "/tmp/test.fits", CPL_BPP_IEEE_FLOAT, NULL, 00692 CPL_IO_DEFAULT); */ 00693 00694 } 00695 00696 fors_image_delete(&fbsigma); 00697 00698 /* 00699 This is not robust if there are no non-illuminated areas. 00700 00701 maxima = cpl_image_get_max(bmaxsigma); 00702 minima = cpl_image_get_min(bmaxsigma); 00703 level = (maxima + minima) / 2; 00704 */ 00705 00706 /* 5 sigma rejection */ 00707 level = cpl_image_get_median(bmaxsigma) * 5; 00708 00709 cpl_msg_debug(cpl_func, "Threshold level = %f", 00710 level); 00711 00712 } 00713 00714 out = cpl_table_load(filename_cat, 1, 1); 00715 00716 assure( !cpl_error_get_code(), return NULL, 00717 "Could not load SExtractor output table %s", 00718 filename_cat); 00719 00720 /* Validate sextractor output */ 00721 assure( cpl_table_has_column(out, "FLAGS"), return NULL, 00722 "%s: Missing column: %s", filename_cat, "FLAGS"); 00723 00724 assure( cpl_table_has_column(out, "CLASS_STAR"), return NULL, 00725 "%s: Missing column: %s", filename_cat, "CLASS_STAR"); 00726 00727 assure( cpl_table_has_column(out, "BACKGROUND"), return NULL, 00728 "%s: Missing column: %s", filename_cat, "BACKGROUND"); 00729 00730 assure( cpl_table_has_column(out, "X_IMAGE"), return NULL, 00731 "%s: Missing column: %s", filename_cat, "X_IMAGE"); 00732 00733 assure( cpl_table_has_column(out, "Y_IMAGE"), return NULL, 00734 "%s: Missing column: %s", filename_cat, "Y_IMAGE"); 00735 00736 assure( cpl_table_has_column(out, "FWHM_IMAGE"), return NULL, 00737 "%s: Missing column: %s", filename_cat, "FWHM_IMAGE"); 00738 00739 assure( cpl_table_has_column(out, "A_IMAGE"), return NULL, 00740 "%s: Missing column: %s", filename_cat, "A_IMAGE"); 00741 00742 assure( cpl_table_has_column(out, "B_IMAGE"), return NULL, 00743 "%s: Missing column: %s", filename_cat, "B_IMAGE"); 00744 00745 assure( cpl_table_has_column(out, "THETA_IMAGE"), return NULL, 00746 "%s: Missing column: %s", filename_cat, "THETA_IMAGE"); 00747 00748 assure( cpl_table_has_column(out, sex_mag), return NULL, 00749 "%s: Missing column: %s", filename_cat, sex_mag); 00750 00751 assure( cpl_table_has_column(out, sex_magerr), return NULL, 00752 "%s: Missing column: %s", filename_cat, sex_magerr); 00753 00754 00755 /* cpl_table_dump_structure(out, stdout); */ 00756 00757 if (vignetted) { 00758 cpl_table_add_scalar(out, "X_IMAGE", croplx - 1); 00759 cpl_table_add_scalar(out, "Y_IMAGE", croply - 1); 00760 } 00761 00762 stars = fors_star_list_new(); 00763 00764 { 00765 int i; 00766 int bkg_rejected = 0; 00767 int rejected = 0; 00768 float *bdata = cpl_image_get_data(bmaxsigma); 00769 int nx = cpl_image_get_size_x(bmaxsigma); 00770 int ny = cpl_image_get_size_y(bmaxsigma); 00771 00772 for (i = 0; i < cpl_table_get_nrow(out); i++) { 00773 fors_star *s = NULL; 00774 unsigned int flags = 0x0; 00775 int x, y, tmp; 00776 double bg_err; 00777 00778 s = fors_star_new_from_table( out, 00779 i, 00780 "X_IMAGE", 00781 "Y_IMAGE", 00782 "FWHM_IMAGE", 00783 "A_IMAGE", 00784 "B_IMAGE", 00785 "THETA_IMAGE", 00786 sex_mag, 00787 sex_magerr, 00788 "CLASS_STAR"); 00789 (*s).orientation *= M_PI/180; 00790 (*s).semi_major *= setting->binx; 00791 (*s).semi_minor *= setting->binx; 00792 (*s).fwhm *= setting->binx; 00793 (*s).dmagnitude = sqrt((*s).dmagnitude * (*s).dmagnitude + magsyserr * magsyserr); 00794 00795 flags = cpl_table_get_int( out, "FLAGS", i, NULL); 00796 00797 x = (int)(s->pixel->x + 0.5); 00798 y = (int)(s->pixel->y + 0.5); 00799 if (x >= 1 && x <= nx && y >= 1 && y <= ny) 00800 bg_err = cpl_image_get(bmaxsigma, x, y, &tmp); 00801 else 00802 bg_err = -1.0; 00803 00804 if (fors_extract_check_sex_flag(flags) 00805 && fors_extract_check_sex_star(s, bmaxsigma) 00806 && bg_err < level) 00807 { 00808 cpl_msg_debug( cpl_func, 00809 "Source at (%f, %f): fwhm = %f px", 00810 s->pixel->x, s->pixel->y, s->fwhm); 00811 assure( !cpl_error_get_code(), return NULL, 00812 "Could not read SExtractor " 00813 "output table %s", 00814 filename_cat); 00815 fors_star_list_insert(stars, s); 00816 } 00817 else 00818 { 00819 cpl_msg_debug( cpl_func, 00820 "Rejecting source at (%f, %f): " 00821 "flags = 0x%x; fwhm = %f pix; " 00822 "background error = %f; " 00823 "level = %f; " 00824 "background = %f", 00825 s->pixel->x, s->pixel->y, 00826 flags, s->fwhm, 00827 bg_err, level, 00828 cpl_table_get_float( 00829 out, "BACKGROUND", i, NULL)); 00830 fors_star_delete(&s); 00831 rejected++; 00832 if (bg_err >= level) 00833 bkg_rejected++; 00834 } 00835 } 00836 00837 cpl_msg_info(cpl_func, "%d sources sextracted, %d rejected", 00838 fors_star_list_size(stars) + rejected, 00839 rejected); 00840 } 00841 00842 if (extracted_sources != NULL) { 00843 *extracted_sources = cpl_table_duplicate(out); 00844 } 00845 00846 cleanup; 00847 return stars; 00848 } 00849 00850 /*----------------------------------------------------------------------------*/ 00851 #undef cleanup 00852 #define cleanup 00853 00865 /*----------------------------------------------------------------------------*/ 00866 static fors_star_list * 00867 extract_test( fors_extract_sky_stats *sky_stats, 00868 cpl_image **background, 00869 cpl_table **extracted_sources) 00870 { 00871 assure( sky_stats != NULL, return NULL, NULL ); 00872 assure( background != NULL, return NULL, NULL ); 00873 00874 sky_stats->mean = 1; 00875 sky_stats->median = 2; 00876 sky_stats->rms = 3; 00877 00878 *background = cpl_image_new(10, 20, CPL_TYPE_FLOAT); /* Zero, wrong size */ 00879 00880 fors_star_list *stars = fors_star_list_new(); 00881 00882 struct { 00883 double x, y, magnitude, dmagnitude; 00884 } 00885 data[] = { 00886 {100 , 200, -10, 0.01}, 00887 {1100, 200, -11, 0.01}, 00888 {1 , 5 , -10, 0.01}, 00889 {100 , 1200, -12, 0.01}, 00890 {1100, 1200, -13, 0.01} 00891 }; 00892 00893 int N = sizeof(data) / sizeof(*data); 00894 int i; 00895 double a = 2; 00896 double b = 1; 00897 double fwhm = 1.5; 00898 double orientation = 1.0; /* radians */ 00899 00900 for (i = 0; i < N; i++) { 00901 fors_star_list_insert(stars, 00902 fors_star_new(data[i].x, 00903 data[i].y, 00904 fwhm, 00905 a, b, orientation, 00906 data[i].magnitude, 00907 data[i].dmagnitude, 00908 1.0)); 00909 } 00910 00911 if (extracted_sources != NULL) { 00912 *extracted_sources = fors_create_sources_table(stars); 00913 00914 assure (!cpl_error_get_code(), return NULL, 00915 "Could not create extracted sources table"); 00916 } 00917 00918 return stars; 00919 } 00920