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