00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <fors_utils.h>
00033
00034 #include <fors_pfits.h>
00035
00036 #include <math.h>
00037 #include <stdbool.h>
00038
00039
00043
00044
00047
00048 #define REQ_CPL_MAJOR 4
00049 #define REQ_CPL_MINOR 0
00050 #define REQ_CPL_MICRO 0
00051
00052 const double STDEV_PR_MAD = 1/0.6744897;
00053
00054
00055
00056
00064
00065 const char * fors_get_license(void)
00066 {
00067 const char *const fors_license =
00068 "This file is currently part of the FORS Instrument Pipeline\n"
00069 "Copyright (C) 2002-2011 European Southern Observatory\n"
00070 "\n"
00071 "This program is free software; you can redistribute it and/or modify\n"
00072 "it under the terms of the GNU General Public License as published by\n"
00073 "the Free Software Foundation; either version 2 of the License, or\n"
00074 "(at your option) any later version.\n"
00075 "\n"
00076 "This program is distributed in the hope that it will be useful,\n"
00077 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00078 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00079 "GNU General Public License for more details.\n"
00080 "\n"
00081 "You should have received a copy of the GNU General Public License\n"
00082 "along with this program; if not, write to the Free Software Foundation,\n"
00083 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n";
00084 return fors_license ;
00085 }
00086
00087
00091
00092 void fors_print_banner(void)
00093 {
00094 cpl_msg_info(__func__, "*****************************************");
00095 cpl_msg_info(__func__, "Welcome to FORS Pipeline release %s",
00096 PACKAGE_VERSION);
00097 cpl_msg_info(__func__, "*****************************************");
00098 }
00099
00100
00105
00106 int
00107 fors_get_version_binary(void)
00108 {
00109
00110
00111
00112
00113
00114 #ifdef CPL_VERSION_CODE
00115 #if CPL_VERSION_CODE >= CPL_VERSION(REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO)
00116 cpl_msg_debug(cpl_func,
00117 "Compile time CPL version code was %d. "
00118 "Required is version %d.%d.%d, code %d",
00119 CPL_VERSION_CODE, REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO,
00120 CPL_VERSION(REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO));
00121 #else
00122 #error CPL version too old
00123 #endif
00124 #else
00125 #error CPL_VERSION_CODE not defined. CPL version too old
00126 #endif
00127
00128 if (cpl_version_get_major() < REQ_CPL_MAJOR ||
00129 (cpl_version_get_major() == REQ_CPL_MAJOR &&
00130 (int) cpl_version_get_minor() < REQ_CPL_MINOR) ||
00131
00132 (cpl_version_get_major() == REQ_CPL_MAJOR &&
00133 cpl_version_get_minor() == REQ_CPL_MINOR &&
00134 (int) cpl_version_get_micro() < REQ_CPL_MICRO)
00135 ) {
00136
00137
00138 cpl_msg_warning(cpl_func,
00139 "Runtime CPL version %s (%d.%d.%d) "
00140 "is not supported. "
00141 "Please update to CPL version %d.%d.%d or later",
00142 cpl_version_get_version(),
00143 cpl_version_get_major(),
00144 cpl_version_get_minor(),
00145 cpl_version_get_micro(),
00146 REQ_CPL_MAJOR,
00147 REQ_CPL_MINOR,
00148 REQ_CPL_MICRO);
00149 }
00150 else {
00151 cpl_msg_debug(cpl_func,
00152 "Runtime CPL version %s (%d.%d.%d) detected, "
00153 "%d.%d.%d or later required",
00154 cpl_version_get_version(),
00155 cpl_version_get_major(),
00156 cpl_version_get_minor(),
00157 cpl_version_get_micro(),
00158 REQ_CPL_MAJOR,
00159 REQ_CPL_MINOR,
00160 REQ_CPL_MICRO);
00161 }
00162
00163
00164
00165
00166
00167
00168 return FORS_BINARY_VERSION;
00169 }
00170
00171
00172
00180
00181 double fors_rand_gauss(void)
00182 {
00183 static double V1, V2, S;
00184 static int phase = 0;
00185 double X;
00186
00187 if(phase == 0) {
00188 do {
00189 double U1 = (double)rand() / RAND_MAX;
00190 double U2 = (double)rand() / RAND_MAX;
00191
00192 V1 = 2 * U1 - 1;
00193 V2 = 2 * U2 - 1;
00194 S = V1 * V1 + V2 * V2;
00195 } while(S >= 1 || S == 0);
00196
00197 X = V1 * sqrt(-2 * log(S) / S);
00198 } else
00199 X = V2 * sqrt(-2 * log(S) / S);
00200
00201 phase = 1 - phase;
00202
00203 return X;
00204 }
00205
00206
00210
00211 double fors_tools_get_kth_double(
00212 double * a,
00213 int n,
00214 int k)
00215 {
00216 double x ;
00217 int i, j, l, m ;
00218
00219 cpl_ensure(a, CPL_ERROR_NULL_INPUT, 0.00) ;
00220
00221 l=0 ; m=n-1 ;
00222 while (l<m) {
00223 x=a[k] ;
00224 i=l ;
00225 j=m ;
00226 do {
00227 while (a[i]<x) i++ ;
00228 while (x<a[j]) j-- ;
00229 if (i<=j) {
00230
00231 double temp = a[i];
00232 a[i] = a[j];
00233 a[j] = temp;
00234 i++ ; j-- ;
00235 }
00236 } while (i<=j) ;
00237 if (j<k) l=i ;
00238 if (k<i) m=j ;
00239 }
00240 return a[k] ;
00241 }
00242
00243 #undef cleanup
00244 #define cleanup
00245
00249
00250 float fors_tools_get_median_float(float *a, int n)
00251 {
00252 return (n % 2 == 0) ?
00253 (fors_tools_get_kth_float(a, n, (n-1)/2) +
00254 fors_tools_get_kth_float(a, n, (n/2))) / 2.0
00255 : fors_tools_get_kth_float(a, n, n/2);
00256 }
00257
00258 #undef cleanup
00259 #define cleanup
00260
00264
00265 float fors_tools_get_median_fast_float(float *a, int n)
00266 {
00267 return fors_tools_get_kth_float(a, n, n/2);
00268 }
00269
00270 #undef cleanup
00271 #define cleanup
00272
00276
00277 float fors_tools_get_kth_float(
00278 float * a,
00279 int n,
00280 int k)
00281 {
00282 float x ;
00283 int i, j, l, m ;
00284
00285 cpl_ensure(a, CPL_ERROR_NULL_INPUT, 0.00) ;
00286
00287 l=0 ; m=n-1 ;
00288 while (l<m) {
00289 x=a[k] ;
00290 i=l ;
00291 j=m ;
00292 do {
00293 while (a[i]<x) i++ ;
00294 while (x<a[j]) j-- ;
00295 if (i<=j) {
00296
00297 float temp = a[i];
00298 a[i] = a[j];
00299 a[j] = temp;
00300 i++ ; j-- ;
00301 }
00302 } while (i<=j) ;
00303 if (j<k) l=i ;
00304 if (k<i) m=j ;
00305 }
00306 return a[k] ;
00307 }
00308
00309 #undef cleanup
00310 #define cleanup
00311
00317
00318 const char *
00319 fors_frame_get_type_string(const cpl_frame *f)
00320 {
00321 assure( f != NULL, return NULL, "Null frame" );
00322
00323 switch (cpl_frame_get_type(f)) {
00324 case CPL_FRAME_TYPE_NONE: return "NONE"; break;
00325 case CPL_FRAME_TYPE_IMAGE: return "IMAGE"; break;
00326 case CPL_FRAME_TYPE_MATRIX: return "MATRIX"; break;
00327 case CPL_FRAME_TYPE_TABLE: return "TABLE"; break;
00328 default:
00329 return "unrecognized frame type";
00330 break;
00331 }
00332 }
00333
00334 #undef cleanup
00335 #define cleanup
00336
00342
00343 const char *
00344 fors_frame_get_group_string(const cpl_frame *f)
00345 {
00346 assure( f != NULL, return NULL, "Null frame" );
00347
00348 switch (cpl_frame_get_group(f)) {
00349 case CPL_FRAME_GROUP_NONE: return "NONE"; break;
00350 case CPL_FRAME_GROUP_RAW: return CPL_FRAME_GROUP_RAW_ID; break;
00351 case CPL_FRAME_GROUP_CALIB: return CPL_FRAME_GROUP_CALIB_ID; break;
00352 case CPL_FRAME_GROUP_PRODUCT: return CPL_FRAME_GROUP_PRODUCT_ID; break;
00353 default:
00354 return "unrecognized frame group";
00355 break;
00356 }
00357 }
00358
00359 #undef cleanup
00360 #define cleanup
00361
00367
00368 const char *
00369 fors_frame_get_level_string(const cpl_frame *f)
00370 {
00371 assure( f != NULL, return NULL, "Null frame" );
00372
00373 switch (cpl_frame_get_level(f)) {
00374 case CPL_FRAME_LEVEL_NONE: return "NONE"; break;
00375 case CPL_FRAME_LEVEL_TEMPORARY: return "TEMPORARY"; break;
00376 case CPL_FRAME_LEVEL_INTERMEDIATE:return "INTERMEDIATE"; break;
00377 case CPL_FRAME_LEVEL_FINAL: return "FINAL"; break;
00378 default:
00379 return "unrecognized frame level";
00380 break;
00381 }
00382 }
00383
00384
00391
00392 void
00393 fors_frameset_print(const cpl_frameset *frames)
00394 {
00395
00396
00397 if (frames == NULL) {
00398 cpl_msg_info(cpl_func, "NULL");
00399 }
00400 else {
00401 const cpl_frame *f = NULL;
00402 f = cpl_frameset_get_first_const(frames);
00403
00404 if (f == NULL) {
00405 cpl_msg_info(cpl_func, "[Empty frame set]");
00406 }
00407 else {
00408 while(f != NULL) {
00409 fors_frame_print(f);
00410 f = cpl_frameset_get_next_const(frames);
00411 }
00412 }
00413 }
00414
00415 return;
00416 }
00417
00418
00425
00426 void
00427 fors_frame_print(const cpl_frame *f)
00428 {
00429 if (f == NULL) {
00430 cpl_msg_info(cpl_func, "NULL");
00431 }
00432 else {
00433 const char *filename = cpl_frame_get_filename(f);
00434 const char *tag = cpl_frame_get_tag(f);
00435
00436 if (filename == NULL) {
00437 filename = "NULL";
00438 }
00439 if (tag == NULL) {
00440 tag = "NULL";
00441 }
00442
00443 cpl_msg_info(cpl_func, "%-7s %-20s %s",
00444 fors_frame_get_group_string(f),
00445 tag,
00446 filename);
00447
00448 cpl_msg_debug(cpl_func, "type \t= %s", fors_frame_get_type_string(f));
00449 cpl_msg_debug(cpl_func, "group \t= %s", fors_frame_get_group_string(f));
00450 cpl_msg_debug(cpl_func, "level \t= %s", fors_frame_get_level_string(f));
00451 }
00452
00453 return;
00454 }
00455
00456
00457 #undef cleanup
00458 #define cleanup
00459
00466
00467 cpl_frameset *
00468 fors_frameset_extract(const cpl_frameset *frames,
00469 const char *tag)
00470 {
00471 cpl_frameset *subset = NULL;
00472 const cpl_frame *f;
00473
00474 assure( frames != NULL, return NULL, "Null frameset" );
00475 assure( tag != NULL, return NULL, "Null tag" );
00476
00477 subset = cpl_frameset_new();
00478
00479 for (f = cpl_frameset_find_const(frames, tag);
00480 f != NULL;
00481 f = cpl_frameset_find_const(frames, NULL)) {
00482
00483 cpl_frameset_insert(subset, cpl_frame_duplicate(f));
00484 }
00485
00486 return subset;
00487 }
00488
00489
00495
00496 const char *fors_type_get_string(cpl_type t)
00497 {
00498
00499
00500
00501 if (!(t & CPL_TYPE_FLAG_ARRAY))
00502 switch(t & (~CPL_TYPE_FLAG_ARRAY)) {
00503 case CPL_TYPE_CHAR: return "char"; break;
00504 case CPL_TYPE_UCHAR: return "uchar"; break;
00505 case CPL_TYPE_BOOL: return "boolean"; break;
00506 case CPL_TYPE_INT: return "int"; break;
00507 case CPL_TYPE_UINT: return "uint"; break;
00508 case CPL_TYPE_LONG: return "long"; break;
00509 case CPL_TYPE_ULONG: return "ulong"; break;
00510 case CPL_TYPE_FLOAT: return "float"; break;
00511 case CPL_TYPE_DOUBLE: return "double"; break;
00512 case CPL_TYPE_POINTER: return "pointer"; break;
00513 case CPL_TYPE_INVALID: return "invalid"; break;
00514 default:
00515 return "unrecognized type";
00516 }
00517 else
00518 switch(t & (~CPL_TYPE_FLAG_ARRAY)) {
00519 case CPL_TYPE_CHAR: return "string (char array)"; break;
00520 case CPL_TYPE_UCHAR: return "uchar array"; break;
00521 case CPL_TYPE_BOOL: return "boolean array"; break;
00522 case CPL_TYPE_INT: return "int array"; break;
00523 case CPL_TYPE_UINT: return "uint array"; break;
00524 case CPL_TYPE_LONG: return "long array"; break;
00525 case CPL_TYPE_ULONG: return "ulong array"; break;
00526 case CPL_TYPE_FLOAT: return "float array"; break;
00527 case CPL_TYPE_DOUBLE: return "double array"; break;
00528 case CPL_TYPE_POINTER: return "pointer array"; break;
00529 case CPL_TYPE_INVALID: return "invalid (array)"; break;
00530 default:
00531 return "unrecognized type";
00532 }
00533 }
00534
00535
00543
00544 void
00545 fors_parameterlist_set_defaults(cpl_parameterlist *parlist)
00546 {
00547 cpl_parameter *p = NULL;
00548 bool parameter_is_set;
00549
00550 p = cpl_parameterlist_get_first(parlist);
00551 while (p != NULL) {
00552
00553
00554
00555
00556 parameter_is_set = cpl_parameter_get_default_flag(p);
00557
00558 if (!parameter_is_set) {
00559 cpl_type ptype = cpl_parameter_get_type(p);
00560 switch (ptype) {
00561 case CPL_TYPE_BOOL:
00562 cpl_parameter_set_bool(p, cpl_parameter_get_default_bool(p));
00563 break;
00564 case CPL_TYPE_INT:
00565 cpl_parameter_set_int(p, cpl_parameter_get_default_int(p));
00566 break;
00567 case CPL_TYPE_DOUBLE:
00568 cpl_parameter_set_double(p, cpl_parameter_get_default_double(p));
00569 break;
00570 case CPL_TYPE_STRING:
00571 cpl_parameter_set_string(p, cpl_parameter_get_default_string(p));
00572 break;
00573 default:
00574 assure( false, return, "Unknown type of parameter '%s'",
00575 cpl_parameter_get_name(p));
00576 }
00577 }
00578 p = cpl_parameterlist_get_next(parlist);
00579 }
00580
00581 return;
00582 }
00583
00584 #ifdef CPL_IS_NOT_CRAP
00585 #else
00586
00597 cpl_image *fors_imagelist_collapse_create(const cpl_imagelist *ilist)
00598 {
00599 cpl_image *result = cpl_imagelist_collapse_create(ilist);
00600
00601 if (result != NULL && cpl_image_count_rejected(result) == 0) {
00602 cpl_image_accept_all(result);
00603 }
00604
00605 return result;
00606 }
00607
00608
00616 cpl_image *fors_imagelist_collapse_median_create(const cpl_imagelist *ilist)
00617 {
00618 cpl_image *result = cpl_imagelist_collapse_median_create(ilist);
00619
00620 if (result != NULL && cpl_image_count_rejected(result) == 0) {
00621 cpl_image_accept_all(result);
00622 }
00623
00624 return result;
00625 }
00626 #endif
00627
00628 #undef cleanup
00629 #define cleanup
00630
00636 double fors_angle_diff(const double *a1, const double *a2)
00637 {
00638 assure( a1 != NULL, return -1, NULL );
00639 assure( a2 != NULL, return -1, NULL );
00640
00641 double d = *a1 - *a2;
00642
00643 while (d < -M_PI) d += 2*M_PI;
00644 while (d > M_PI) d -= 2*M_PI;
00645
00646 return fabs(d);
00647 }
00648
00649 #define MAX_MESSAGE_LENGTH 1024
00650 #undef cleanup
00651 #define cleanup
00652
00660 void fors_msg_macro(cpl_msg_severity level, const char *fct, const char *format, ...)
00661 {
00662 char message[MAX_MESSAGE_LENGTH];
00663 va_list al;
00664
00665 va_start(al, format);
00666 vsnprintf(message, MAX_MESSAGE_LENGTH - 1, format, al);
00667 va_end(al);
00668
00669 message[MAX_MESSAGE_LENGTH - 1] = '\0';
00670
00671 switch(level) {
00672 case CPL_MSG_DEBUG: cpl_msg_debug (fct, "%s", message); break;
00673 case CPL_MSG_INFO: cpl_msg_info (fct, "%s", message); break;
00674 case CPL_MSG_WARNING: cpl_msg_warning(fct, "%s", message); break;
00675 case CPL_MSG_ERROR: cpl_msg_error (fct, "%s", message); break;
00676 default:
00677 cpl_msg_error(fct, "Unknown message level: %d", level);
00678 cpl_msg_error(fct, "%s", message);
00679 break;
00680 }
00681 return;
00682 }
00683
00684
00685 #undef cleanup
00686 #define cleanup
00687
00696 double fors_utils_median_corr(int n)
00697 {
00698 assure( n > 0, return -1, "Illegal number: %d", n);
00699
00700 const double c[] = {
00701
00702
00703
00704
00705
00706
00707 1, 0.999892, 0.000405,
00708 2, 0.999868, 0.000413,
00709 3, 1.159685, 0.000467,
00710 4, 1.091738, 0.000431,
00711 5, 1.197186, 0.000473,
00712 6, 1.134358, 0.000454,
00713 7, 1.213364, 0.000481,
00714 8, 1.159116, 0.000466,
00715 9, 1.223264, 0.000487,
00716 10, 1.176252, 0.000468,
00717 11, 1.228136, 0.000491,
00718 12, 1.187431, 0.000476,
00719 13, 1.231643, 0.000498,
00720 14, 1.195670, 0.000488,
00721 15, 1.235724, 0.000491,
00722 16, 1.201223, 0.000482,
00723 17, 1.237393, 0.000487,
00724 18, 1.207451, 0.000487,
00725 19, 1.239745, 0.000502,
00726 20, 1.212639, 0.000490,
00727 21, 1.241837, 0.000498,
00728 22, 1.216330, 0.000492,
00729 23, 1.244426, 0.000508,
00730 24, 1.221290, 0.000493,
00731 25, 1.246456, 0.000507,
00732 26, 1.224591, 0.000498,
00733 27, 1.248254, 0.000500,
00734 28, 1.227300, 0.000498,
00735 29, 1.248467, 0.000503,
00736 30, 1.229101, 0.000485,
00737 31, 1.248270, 0.000498,
00738 32, 1.231945, 0.000493,
00739 33, 1.249087, 0.000509,
00740 34, 1.231960, 0.000486,
00741 35, 1.249525, 0.000500,
00742 36, 1.231679, 0.000496,
00743 37, 1.249156, 0.000510,
00744 38, 1.233630, 0.000494,
00745 39, 1.249173, 0.000483,
00746 40, 1.233669, 0.000492,
00747 41, 1.248756, 0.000510,
00748 42, 1.235170, 0.000493,
00749 43, 1.248498, 0.000497,
00750 44, 1.235864, 0.000501,
00751 45, 1.248986, 0.000487,
00752 46, 1.236148, 0.000495,
00753 47, 1.248720, 0.000507,
00754 48, 1.236461, 0.000499,
00755 49, 1.248677, 0.000500,
00756 50, 1.236832, 0.000499,
00757 51, 1.249143, 0.000510,
00758 52, 1.237251, 0.000497,
00759 53, 1.248619, 0.000510,
00760 54, 1.237826, 0.000490,
00761 55, 1.249292, 0.000499,
00762 56, 1.238721, 0.000492,
00763 57, 1.248719, 0.000502,
00764 58, 1.238830, 0.000482,
00765 59, 1.248869, 0.000491,
00766 60, 1.239892, 0.000501,
00767 61, 1.248980, 0.000505,
00768 62, 1.239435, 0.000506,
00769 63, 1.249534, 0.000506,
00770 64, 1.240748, 0.000507,
00771 65, 1.249158, 0.000501,
00772 66, 1.240053, 0.000503,
00773 67, 1.248843, 0.000500,
00774 68, 1.241417, 0.000499,
00775 69, 1.249386, 0.000506,
00776 70, 1.241106, 0.000499,
00777 71, 1.249540, 0.000509,
00778 72, 1.240998, 0.000491,
00779 73, 1.250202, 0.000502,
00780 74, 1.241989, 0.000491,
00781 75, 1.249485, 0.000497,
00782 76, 1.242218, 0.000503,
00783 77, 1.249733, 0.000506,
00784 78, 1.240815, 0.000517,
00785 79, 1.250652, 0.000494,
00786 80, 1.241356, 0.000501,
00787 81, 1.250115, 0.000511,
00788 82, 1.241610, 0.000506,
00789 83, 1.249751, 0.000504,
00790 84, 1.242905, 0.000485,
00791 85, 1.249906, 0.000512,
00792 86, 1.243211, 0.000502,
00793 87, 1.250671, 0.000503,
00794 88, 1.242750, 0.000489,
00795 89, 1.249779, 0.000502,
00796 90, 1.243191, 0.000507,
00797 91, 1.250325, 0.000494,
00798 92, 1.243411, 0.000493,
00799 93, 1.250774, 0.000508,
00800 94, 1.244007, 0.000492,
00801 95, 1.249777, 0.000503,
00802 96, 1.243910, 0.000507,
00803 97, 1.250147, 0.000503,
00804 98, 1.243634, 0.000501,
00805 99, 1.250931, 0.000504,
00806 100, 1.243948, 0.000504};
00807
00808 if (n <= 100) {
00809 return c[(n-1)*3 + 1];
00810 }
00811 else {
00812 return sqrt(M_PI/2);
00813 }
00814 }
00815