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
00033
00034
00035
00036 #include <math.h>
00037
00038 #include <string.h>
00039 #include <assert.h>
00040
00041 #include <cpl.h>
00042
00043 #include "irplib_utils.h"
00044
00045
00046
00047
00048
00049 #ifndef inline
00050 #define inline
00051 #endif
00052
00053
00054
00055
00056
00057 #if defined HAVE_ISNAN && HAVE_ISNAN != 0
00058 #if !defined isnan && defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 0
00059
00060
00061 int isnan(double);
00062 #endif
00063 #endif
00064
00065
00066
00067
00068
00069 inline static double irplib_data_get_double(const void *, cpl_type, int)
00070 #ifdef CPL_HAVE_GNUC_NONNULL
00071 __attribute__((nonnull))
00072 #endif
00073 ;
00074
00075 inline static void irplib_data_set_double(void *, cpl_type, int, double)
00076 #ifdef CPL_HAVE_GNUC_NONNULL
00077 __attribute__((nonnull))
00078 #endif
00079 ;
00080
00081
00085
00090
00145
00146 cpl_error_code irplib_image_split(const cpl_image * self,
00147 cpl_image * im_low,
00148 cpl_image * im_mid,
00149 cpl_image * im_high,
00150 double th_low,
00151 cpl_boolean isleq_low,
00152 double th_high,
00153 cpl_boolean isgeq_high,
00154 double alt_low,
00155 double alt_high,
00156 cpl_boolean isbad_low,
00157 cpl_boolean isbad_mid,
00158 cpl_boolean isbad_high)
00159 {
00160
00161 const void * selfdata = cpl_image_get_data_const(self);
00162
00163
00164
00165 const cpl_boolean hasbpm
00166 = cpl_image_count_rejected(self) ? CPL_TRUE : CPL_FALSE;
00167 const cpl_binary * selfbpm = hasbpm
00168 ? cpl_mask_get_data_const(cpl_image_get_bpm_const(self)) : NULL;
00169 const cpl_type selftype = cpl_image_get_type(self);
00170 const int nx = cpl_image_get_size_x(self);
00171 const int ny = cpl_image_get_size_y(self);
00172 const int npix = nx * ny;
00173 const cpl_boolean do_low = im_low != NULL;
00174 const cpl_boolean do_mid = im_mid != NULL;
00175 const cpl_boolean do_high = im_high != NULL;
00176 void * lowdata = NULL;
00177 void * middata = NULL;
00178 void * highdata = NULL;
00179 cpl_binary * lowbpm = NULL;
00180 cpl_binary * midbpm = NULL;
00181 cpl_binary * highbpm = NULL;
00182 const cpl_type lowtype
00183 = do_low ? cpl_image_get_type(im_low) : CPL_TYPE_INVALID;
00184 const cpl_type midtype
00185 = do_mid ? cpl_image_get_type(im_mid) : CPL_TYPE_INVALID;
00186 const cpl_type hightype
00187 = do_high ? cpl_image_get_type(im_high) : CPL_TYPE_INVALID;
00188 int i;
00189
00190
00191 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00192 cpl_ensure_code(do_low || do_mid || do_high, CPL_ERROR_NULL_INPUT);
00193 cpl_ensure_code(th_low <= th_high, CPL_ERROR_ILLEGAL_INPUT);
00194
00195 if (do_low) {
00196 cpl_ensure_code(cpl_image_get_size_x(im_low) == nx,
00197 CPL_ERROR_INCOMPATIBLE_INPUT);
00198 cpl_ensure_code(cpl_image_get_size_y(im_low) == ny,
00199 CPL_ERROR_INCOMPATIBLE_INPUT);
00200 lowdata = cpl_image_get_data(im_low);
00201 }
00202
00203 if (do_mid) {
00204 cpl_ensure_code(cpl_image_get_size_x(im_mid) == nx,
00205 CPL_ERROR_INCOMPATIBLE_INPUT);
00206 cpl_ensure_code(cpl_image_get_size_y(im_mid) == ny,
00207 CPL_ERROR_INCOMPATIBLE_INPUT);
00208 middata = cpl_image_get_data(im_mid);
00209 }
00210
00211 if (do_high) {
00212 cpl_ensure_code(cpl_image_get_size_x(im_high) == nx,
00213 CPL_ERROR_INCOMPATIBLE_INPUT);
00214 cpl_ensure_code(cpl_image_get_size_y(im_high) == ny,
00215 CPL_ERROR_INCOMPATIBLE_INPUT);
00216 highdata = cpl_image_get_data(im_high);
00217 }
00218
00219
00220
00221 for (i = 0; i < npix; i++) {
00222 const double value = irplib_data_get_double(selfdata, selftype, i);
00223 cpl_boolean isalt_low = do_low;
00224 cpl_boolean isalt_mid = do_mid;
00225 cpl_boolean isalt_high = do_high;
00226 cpl_boolean setbad_low = do_low;
00227 cpl_boolean setbad_mid = do_mid;
00228 cpl_boolean setbad_high = do_high;
00229 const void * setdata = NULL;
00230 double alt_mid;
00231
00232 if (isleq_low ? value <= th_low : value < th_low) {
00233 if (do_low) {
00234 isalt_low = CPL_FALSE;
00235 irplib_data_set_double(lowdata, lowtype, i, value);
00236 setbad_low = hasbpm && selfbpm[i];
00237 setdata = lowdata;
00238 }
00239 alt_mid = alt_low;
00240 } else if (isgeq_high ? value >= th_high : value > th_high) {
00241 if (do_high) {
00242 isalt_high = CPL_FALSE;
00243 irplib_data_set_double(highdata, hightype, i, value);
00244 setbad_high = hasbpm && selfbpm[i];
00245 setdata = highdata;
00246 }
00247 alt_mid = alt_high;
00248 } else if (do_mid) {
00249 isalt_mid = CPL_FALSE;
00250 irplib_data_set_double(middata, midtype, i, value);
00251 setbad_mid = hasbpm && selfbpm[i];
00252 setdata = middata;
00253 }
00254
00255 if (isalt_low && lowdata != setdata) {
00256 irplib_data_set_double(lowdata, lowtype, i, alt_low);
00257 setbad_low = isbad_low;
00258 }
00259 if (isalt_mid && middata != setdata) {
00260 irplib_data_set_double(middata, midtype, i, alt_mid);
00261 setbad_mid = isbad_mid;
00262 }
00263 if (isalt_high && highdata != setdata) {
00264 irplib_data_set_double(highdata, hightype, i, alt_high);
00265 setbad_high = isbad_high;
00266 }
00267
00268 if (setbad_low) {
00269 if (lowbpm == NULL) lowbpm
00270 = cpl_mask_get_data(cpl_image_get_bpm(im_low));
00271 lowbpm[i] = CPL_BINARY_1;
00272 }
00273 if (setbad_mid) {
00274 if (midbpm == NULL) midbpm
00275 = cpl_mask_get_data(cpl_image_get_bpm(im_mid));
00276 midbpm[i] = CPL_BINARY_1;
00277 }
00278 if (setbad_high) {
00279 if (highbpm == NULL) highbpm
00280 = cpl_mask_get_data(cpl_image_get_bpm(im_high));
00281 highbpm[i] = CPL_BINARY_1;
00282 }
00283 }
00284
00285 return CPL_ERROR_NONE;
00286
00287 }
00288
00289
00290
00338
00339
00340 cpl_error_code
00341 irplib_dfs_table_convert(cpl_table * self,
00342 cpl_frameset * allframes,
00343 const cpl_frameset * useframes,
00344 int maxlinelen,
00345 char commentchar,
00346 const char * product_name,
00347 const char * procatg,
00348 const cpl_parameterlist * parlist,
00349 const char * recipe_name,
00350 const cpl_propertylist * mainlist,
00351 const cpl_propertylist * extlist,
00352 const char * remregexp,
00353 const char * instrume,
00354 const char * pipe_id,
00355 cpl_boolean (*table_set_row)
00356 (cpl_table *, const char *, int,
00357 const cpl_frame *,
00358 const cpl_parameterlist *),
00359 cpl_error_code (*table_check)
00360 (cpl_table *,
00361 const cpl_frameset *,
00362 const cpl_parameterlist *))
00363 {
00364
00365 const char * filename;
00366 cpl_propertylist * applist = NULL;
00367 cpl_errorstate prestate = cpl_errorstate_get();
00368 cpl_error_code error;
00369
00370 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00371 cpl_ensure_code(allframes != NULL, CPL_ERROR_NULL_INPUT);
00372 cpl_ensure_code(useframes != NULL, CPL_ERROR_NULL_INPUT);
00373 cpl_ensure_code(procatg != NULL, CPL_ERROR_NULL_INPUT);
00374 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
00375 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
00376 cpl_ensure_code(instrume != NULL, CPL_ERROR_NULL_INPUT);
00377 cpl_ensure_code(pipe_id != NULL, CPL_ERROR_NULL_INPUT);
00378
00379 cpl_ensure_code(!irplib_table_read_from_frameset(self, useframes,
00380 maxlinelen,
00381 commentchar,
00382 parlist,
00383 table_set_row),
00384 cpl_error_get_code());
00385
00386 if (table_check != NULL && (table_check(self, useframes, parlist) ||
00387 !cpl_errorstate_is_equal(prestate))) {
00388 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
00389 "Consistency check of table failed");
00390 }
00391
00392 filename = product_name != NULL
00393 ? product_name : cpl_sprintf("%s" CPL_DFS_FITS, recipe_name);
00394
00395 applist = mainlist == NULL
00396 ? cpl_propertylist_new() : cpl_propertylist_duplicate(mainlist);
00397
00398 error = cpl_propertylist_append_string(applist, "INSTRUME", instrume);
00399
00400 if (!error)
00401 error = cpl_dfs_save_table(allframes, parlist, useframes, self,
00402 extlist, recipe_name, procatg, applist,
00403 remregexp, pipe_id, filename);
00404
00405 cpl_propertylist_delete(applist);
00406 if (filename != product_name) cpl_free((char*)filename);
00407
00408
00409 cpl_ensure_code(!error, error);
00410
00411 return CPL_ERROR_NONE;
00412
00413 }
00414
00415
00416
00417
00466
00467
00468 cpl_error_code
00469 irplib_table_read_from_frameset(cpl_table * self,
00470 const cpl_frameset * useframes,
00471 int maxlinelen,
00472 char commentchar,
00473 const cpl_parameterlist * parlist,
00474 cpl_boolean (*table_set_row)
00475 (cpl_table *, const char *, int,
00476 const cpl_frame *,
00477 const cpl_parameterlist *))
00478 {
00479
00480 const cpl_frame * rawframe;
00481 char * linebuffer = NULL;
00482 FILE * stream = NULL;
00483 int nfiles = 0;
00484 int nrow = cpl_table_get_nrow(self);
00485 int irow = 0;
00486 cpl_errorstate prestate = cpl_errorstate_get();
00487
00488 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00489 cpl_ensure_code(useframes != NULL, CPL_ERROR_NULL_INPUT);
00490 cpl_ensure_code(maxlinelen > 0, CPL_ERROR_ILLEGAL_INPUT);
00491 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
00492 cpl_ensure_code(table_set_row != NULL, CPL_ERROR_NULL_INPUT);
00493
00494 linebuffer = cpl_malloc(maxlinelen);
00495
00496 for (rawframe = cpl_frameset_get_first_const(useframes);
00497 rawframe != NULL;
00498 rawframe = cpl_frameset_get_next_const(useframes), nfiles++) {
00499
00500 const char * rawfile = cpl_frame_get_filename(rawframe);
00501 const char * done;
00502 const int irowpre = irow;
00503 int iirow = 0;
00504 int ierror;
00505
00506 if (rawfile == NULL) break;
00507
00508 stream = fopen(rawfile, "r");
00509
00510 if (stream == NULL) {
00511 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO, "Could not "
00512 "open %s for reading", rawfile);
00513 break;
00514 }
00515
00516 for (;(done = fgets(linebuffer, maxlinelen, stream)) != NULL; iirow++) {
00517
00518 if (linebuffer[0] != commentchar) {
00519 cpl_boolean didset;
00520 const int prerow = irow;
00521
00522 if (irow == nrow) {
00523 nrow += nrow ? nrow : 1;
00524 if (cpl_table_set_size(self, nrow)) break;
00525 }
00526
00527 didset = table_set_row(self, linebuffer, irow, rawframe,
00528 parlist);
00529 if (didset) irow++;
00530
00531 if (!cpl_errorstate_is_equal(prestate)) {
00532 if (didset)
00533 cpl_error_set_message(cpl_func, cpl_error_get_code(),
00534 "Failed to set table row %d "
00535 "using line %d from %d. file %s",
00536 1+prerow, iirow+1,
00537 nfiles+1, rawfile);
00538 else
00539 cpl_error_set_message(cpl_func, cpl_error_get_code(),
00540 "Failure with line %d from %d. "
00541 "file %s", iirow+1,
00542 nfiles+1, rawfile);
00543
00544 break;
00545 }
00546 }
00547 }
00548 if (done != NULL) break;
00549
00550 ierror = fclose(stream);
00551 stream = NULL;
00552 if (ierror) break;
00553
00554
00555 if (irow == irowpre)
00556 cpl_msg_warning(cpl_func, "No usable lines in the %d. file: %s",
00557 1+nfiles, rawfile);
00558 }
00559
00560 cpl_free(linebuffer);
00561 if (stream != NULL) fclose(stream);
00562
00563
00564 cpl_ensure_code(rawframe == NULL, cpl_error_get_code());
00565
00566 if (irow == 0) {
00567 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
00568 "No usable lines in the %d input "
00569 "frame(s)", nfiles);
00570 }
00571
00572
00573 cpl_ensure_code(!cpl_table_set_size(self, irow), cpl_error_get_code());
00574
00575 return CPL_ERROR_NONE;
00576 }
00577
00578
00579
00580
00592
00593 void irplib_reset(void)
00594 {
00595 return;
00596 }
00597
00598
00605
00606 int irplib_compare_tags(
00607 cpl_frame * frame1,
00608 cpl_frame * frame2)
00609 {
00610 char * v1 ;
00611 char * v2 ;
00612
00613
00614 if (frame1==NULL || frame2==NULL) return -1 ;
00615
00616
00617 if ((v1 = (char*)cpl_frame_get_tag(frame1)) == NULL) return -1 ;
00618 if ((v2 = (char*)cpl_frame_get_tag(frame2)) == NULL) return -1 ;
00619
00620
00621 if (strcmp(v1, v2)) return 0 ;
00622 else return 1 ;
00623 }
00624
00625
00641
00642 const char * irplib_frameset_find_file(const cpl_frameset * self,
00643 const char * tag)
00644 {
00645 const cpl_frame * frame = cpl_frameset_find_const(self, tag);
00646
00647
00648 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00649
00650 if (frame == NULL) return NULL;
00651
00652 if (cpl_frameset_find_const(self, NULL))
00653 cpl_msg_warning(cpl_func,
00654 "Frameset has more than one file with tag: %s",
00655 tag);
00656
00657 return cpl_frame_get_filename(frame);
00658
00659 }
00660
00661
00671
00672 cpl_frame * irplib_frameset_get_first_from_group(
00673 const cpl_frameset * self,
00674 cpl_frame_group group)
00675 {
00676 const cpl_frame * frame;
00677 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00678
00679 for (frame = cpl_frameset_get_first_const(self); frame != NULL ;
00680 frame = cpl_frameset_get_next_const(self)) {
00681 if (cpl_frame_get_group(frame) == group) break;
00682 }
00683 return (cpl_frame*)frame;
00684 }
00685
00686
00705
00706 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures * self,
00707 int * ind, int nfind)
00708 {
00709 const int nsize = cpl_apertures_get_size(self);
00710 int ifind;
00711
00712
00713 cpl_ensure_code(nsize > 0, cpl_error_get_code());
00714 cpl_ensure_code(ind, CPL_ERROR_NULL_INPUT);
00715 cpl_ensure_code(nfind > 0, CPL_ERROR_ILLEGAL_INPUT);
00716 cpl_ensure_code(nfind <= nsize, CPL_ERROR_ILLEGAL_INPUT);
00717
00718 for (ifind=0; ifind < nfind; ifind++) {
00719 double maxflux = -1;
00720 int maxind = -1;
00721 int i;
00722 for (i=1; i <= nsize; i++) {
00723 int k;
00724
00725
00726 for (k=0; k < ifind; k++) if (ind[k] == i) break;
00727
00728 if (k == ifind) {
00729
00730 const double flux = cpl_apertures_get_flux(self, i);
00731
00732 if (maxind < 0 || flux > maxflux) {
00733 maxind = i;
00734 maxflux = flux;
00735 }
00736 }
00737 }
00738 ind[ifind] = maxind;
00739 }
00740
00741 return CPL_ERROR_NONE;
00742
00743 }
00744
00745
00749
00750 int irplib_isinf(double value)
00751 {
00752 #if defined HAVE_ISINF && HAVE_ISINF
00753 return isinf(value);
00754 #else
00755 return value != 0 && value == 2 * value;
00756 #endif
00757 }
00758
00759
00763
00764 int irplib_isnan(double value)
00765 {
00766 #if defined HAVE_ISNAN && HAVE_ISNAN
00767 return isnan(value);
00768 #else
00769 return value != value;
00770 #endif
00771 }
00772
00773
00774
00775
00786
00787 void irplib_errorstate_warning(unsigned self, unsigned first, unsigned last)
00788 {
00789
00790 const cpl_boolean is_reverse = first > last ? CPL_TRUE : CPL_FALSE;
00791 const unsigned newest = is_reverse ? first : last;
00792 const unsigned oldest = is_reverse ? last : first;
00793 const char * revmsg = is_reverse ? " in reverse order" : "";
00794
00795
00796 assert( oldest <= self );
00797 assert( newest >= self );
00798
00799 if (newest == 0) {
00800 cpl_msg_info(cpl_func, "No error(s) to dump");
00801 assert( oldest == 0);
00802 } else {
00803 assert( oldest > 0);
00804 assert( newest >= oldest);
00805 if (self == first) {
00806 if (oldest == 1) {
00807 cpl_msg_warning(cpl_func, "Dumping all %u error(s)%s:", newest,
00808 revmsg);
00809 } else {
00810 cpl_msg_warning(cpl_func, "Dumping the %u most recent error(s) "
00811 "out of a total of %u errors%s:",
00812 newest - oldest + 1, newest, revmsg);
00813 }
00814 cpl_msg_indent_more();
00815 }
00816
00817 cpl_msg_warning(cpl_func, "[%u/%u] '%s' (%u) at %s", self, newest,
00818 cpl_error_get_message(), cpl_error_get_code(),
00819 cpl_error_get_where());
00820
00821 if (self == last) cpl_msg_indent_less();
00822 }
00823 }
00824
00825
00828
00839
00840 inline static
00841 double irplib_data_get_double(const void * self, cpl_type type, int i)
00842 {
00843
00844 double value;
00845
00846
00847 switch (type) {
00848 case CPL_TYPE_FLOAT:
00849 {
00850 const float * pself = (const float*)self;
00851 value = (double)pself[i];
00852 break;
00853 }
00854 case CPL_TYPE_INT:
00855 {
00856 const int * pself = (const int*)self;
00857 value = (double)pself[i];
00858 break;
00859 }
00860 default:
00861 {
00862 const double * pself = (const double*)self;
00863 value = pself[i];
00864 break;
00865 }
00866 }
00867
00868 return value;
00869
00870 }
00871
00872
00873
00884
00885 inline static
00886 void irplib_data_set_double(void * self, cpl_type type, int i, double value)
00887 {
00888
00889 switch (type) {
00890 case CPL_TYPE_FLOAT:
00891 {
00892 float * pself = (float*)self;
00893 pself[i] = (float)value;
00894 break;
00895 }
00896 case CPL_TYPE_INT:
00897 {
00898 int * pself = (int*)self;
00899 pself[i] = (int)value;
00900 break;
00901 }
00902 default:
00903 {
00904 double * pself = (double*)self;
00905 pself[i] = value;
00906 break;
00907 }
00908 }
00909 }