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_image.h>
00033
00034 #include <fors_dfs.h>
00035 #include <fors_utils.h>
00036 #include <fors_pfits.h>
00037 #include <fors_double.h>
00038 #include <fors_saturation.h>
00039 #include <fors_subtract_bias.h>
00040 #include <moses.h>
00041
00042 #include <cpl.h>
00043
00044 #include <math.h>
00045 #include <stdbool.h>
00046 #include <stdio.h>
00047
00048
00052 const cpl_type FORS_IMAGE_TYPE = CPL_TYPE_FLOAT;
00053 #define FORS_IMAGE_TYPE_MAX FLT_MAX
00054
00055
00056 #undef cleanup
00057
00058
00059
00060
00061
00062
00063
00064
00065 static int
00066 max_filter(const float *ibuffer, float *obuffer, int length, int size)
00067 {
00068 float max;
00069 int start = size / 2;
00070 int end = length - size / 2;
00071 int i, j;
00072
00073
00074 for (i = start; i < end; i++) {
00075 max = ibuffer[i-start];
00076 for (j = i - start + 1; j <= i + start; j++)
00077 if (max < ibuffer[j])
00078 max = ibuffer[j];
00079 obuffer[i] = max;
00080 }
00081
00082 for (i = 0; i < start; i++)
00083 obuffer[i] = obuffer[start];
00084
00085 for (i = end; i < length; i++)
00086 obuffer[i] = obuffer[end-1];
00087
00088 return 0;
00089 }
00090
00091 #define cleanup
00092
00101 fors_image *
00102 fors_image_new(cpl_image *data, cpl_image *variance)
00103 {
00104 fors_image *image = NULL;
00105
00106 assure( data != NULL, return NULL, NULL );
00107 assure( variance != NULL, return NULL, NULL );
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 assure( cpl_image_get_size_x(data) == cpl_image_get_size_x(variance) &&
00121 cpl_image_get_size_y(data) == cpl_image_get_size_y(variance),
00122 return NULL,
00123 "Incompatible data and weight image sizes: "
00124 "%"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT
00125 " and %"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT,
00126 cpl_image_get_size_x(data), cpl_image_get_size_y(data),
00127 cpl_image_get_size_x(variance), cpl_image_get_size_y(variance));
00128
00129 assure( cpl_image_get_min(variance) >= 0, return NULL,
00130 "Variances must be non-negative, minimum is %g. \n"
00131 "This is most likely a software bug. "
00132 "You may contact usd-help@eso.org which can provide a workaround.",
00133 cpl_image_get_min(variance));
00134
00135 image = cpl_malloc(sizeof(*image));
00136
00137 image->data = data;
00138 image->variance = variance;
00139
00140 return image;
00141 }
00142
00143 #undef cleanup
00144 #define cleanup
00145
00150 fors_image *
00151 fors_image_duplicate(const fors_image *image)
00152 {
00153 assure( image != NULL, return NULL, NULL );
00154
00155 return fors_image_new(cpl_image_duplicate(image->data),
00156 cpl_image_duplicate(image->variance));
00157 }
00158
00163 void
00164 fors_image_delete(fors_image **image)
00165 {
00166 if (image && *image) {
00167 cpl_image_delete((*image)->data);
00168 cpl_image_delete((*image)->variance);
00169 cpl_free(*image); *image = NULL;
00170 }
00171 return;
00172 }
00173
00178 void
00179 fors_image_delete_const(const fors_image **image)
00180 {
00181 fors_image_delete((fors_image **)image);
00182
00183 return;
00184 }
00185
00186
00187 #if 0
00188
00192 static void
00193 fors_image_dump(const fors_image *image, FILE *file)
00194 {
00195 if (image == NULL) {
00196 fprintf(file, "Null image\n");
00197 }
00198 else {
00199 cpl_stats *stats;
00200
00201 fprintf(file, "Data:\n");
00202 stats = cpl_stats_new_from_image(image->data, CPL_STATS_ALL);
00203 cpl_stats_dump(stats, CPL_STATS_ALL, file);
00204 cpl_stats_delete(stats);
00205
00206 fprintf(file, "Variance:\n");
00207 stats = cpl_stats_new_from_image(image->variance, CPL_STATS_ALL);
00208 cpl_stats_dump(stats, CPL_STATS_ALL, file);
00209 cpl_stats_delete(stats);
00210 }
00211
00212 return;
00213 }
00214 #endif
00215
00216 #undef cleanup
00217 #define cleanup \
00218 do { \
00219 double_list_delete(&sat_percent, double_delete); \
00220 } while (0)
00221
00235 fors_image_list *
00236 fors_image_load_list(const cpl_frameset *frames)
00237 {
00238 fors_image_list *ilist = fors_image_list_new();
00239 double_list *sat_percent = double_list_new();
00240
00241 assure( frames != NULL, return ilist, NULL );
00242 assure( !cpl_frameset_is_empty(frames), return ilist, "Empty frameset");
00243
00244 {
00245 const cpl_frame *f;
00246
00247 for (int i =0; i< cpl_frameset_get_size(frames); i ++)
00248 {
00249 f = cpl_frameset_get_position_const(frames, i);
00250
00251 fors_image *ima = fors_image_load(f);
00252
00253 fors_image_list_insert(ilist, ima);
00254 }
00255 }
00256
00257 cleanup;
00258 return ilist;
00259 }
00260
00272 const fors_image_list *
00273 fors_image_load_list_const(const cpl_frameset *frames)
00274 {
00275 return (const fors_image_list *)
00276 fors_image_load_list(frames);
00277 }
00278
00279 #undef cleanup
00280 #define cleanup \
00281 do { \
00282 } while (0)
00283
00290 fors_image *
00291 fors_image_load(const cpl_frame *frame)
00292 {
00293 fors_image *image = NULL;
00294 cpl_image *data = NULL;
00295 cpl_image *variance = NULL;
00296 const char *filename;
00297 int extension= 0;
00298 const int plane = 0;
00299
00300 assure( frame != NULL, return image, NULL );
00301
00302 filename = cpl_frame_get_filename(frame);
00303 assure( filename != NULL, return image,
00304 "NULL filename received");
00305
00306 cpl_msg_info(cpl_func, "Loading %s: %s",
00307
00308 (cpl_frame_get_tag(frame) != NULL) ?
00309 cpl_frame_get_tag(frame) : "NULL",
00310 filename);
00311
00312
00313 data = cpl_image_load(filename,
00314 FORS_IMAGE_TYPE, plane, extension);
00315
00316 assure( data != NULL, return image,
00317 "Could not load image from %s extension %d",
00318 filename, extension);
00319
00320
00321
00322 if (cpl_frame_get_nextensions(frame) == 0) {
00323
00324
00325 variance = cpl_image_new(
00326 cpl_image_get_size_x(data),
00327 cpl_image_get_size_y(data),
00328 FORS_IMAGE_TYPE);
00329
00330 }
00331 else {
00332
00333 extension = 1;
00334
00335
00336 variance = cpl_image_load(filename,
00337 FORS_IMAGE_TYPE, plane, extension);
00338
00339 assure( variance != NULL, return image,
00340 "Could not load image from %s extension %d",
00341 filename, extension);
00342
00343 cpl_image_power(variance, 2);
00344
00345 assure( cpl_image_get_min(variance) >= 0,
00346 cpl_image_delete(variance); return image,
00347 "Illegal minimum variance: %g",
00348 cpl_image_get_min(variance));
00349
00350 }
00351
00352 image = fors_image_new(data, variance);
00353
00354 cleanup;
00355 return image;
00356 }
00357
00358
00359 #undef cleanup
00360 #define cleanup \
00361 do { \
00362 cpl_image_delete(sigma); \
00363 cpl_propertylist_delete(extension_header); \
00364 } while(0)
00365
00374 void
00375 fors_image_save(const fors_image *image, const cpl_propertylist *header,
00376 const cpl_propertylist *err_header,
00377 const char *filename)
00378 {
00379 cpl_propertylist *extension_header = NULL;
00380 cpl_image *sigma = NULL;
00381
00382 assure( image != NULL, return, NULL );
00383
00384 assure( filename != NULL, return, NULL );
00385
00386 cpl_image_save(image->data, filename, CPL_BPP_IEEE_FLOAT, header,
00387 CPL_IO_DEFAULT);
00388 assure( !cpl_error_get_code(), return,
00389 "Cannot save product %s", filename);
00390
00391 sigma = cpl_image_power_create(image->variance, 0.5);
00392
00393 if(err_header != NULL)
00394 extension_header = cpl_propertylist_duplicate(err_header);
00395 else
00396 extension_header = cpl_propertylist_new();
00397 cpl_propertylist_append_string(extension_header,
00398 "EXTNAME", "IMAGE.ERR");
00399
00400 cpl_image_save(sigma, filename, CPL_BPP_IEEE_FLOAT, extension_header,
00401 CPL_IO_EXTEND);
00402 assure( !cpl_error_get_code(), return,
00403 "Cannot save product %s", filename);
00404
00405 cleanup;
00406 return;
00407 }
00408
00409
00410 #undef cleanup
00411 #define cleanup \
00412 do { \
00413 cpl_image_delete(var_bkg); \
00414 cpl_image_delete(sigma_bkg); \
00415 } while(0)
00416
00427 void
00428 fors_image_save_sex(const fors_image *image, const cpl_propertylist *header,
00429 const char *filename_dat,
00430 const char *filename_var,
00431 int radius)
00432 {
00433 cpl_propertylist *extension_header = NULL;
00434 cpl_image *sigma_bkg = NULL;
00435 cpl_image *var_bkg = NULL;
00436
00437 assure( image != NULL, return, NULL );
00438
00439 assure( filename_dat != NULL, return, NULL );
00440 assure( filename_var != NULL, return, NULL );
00441
00442 cpl_image_save(image->data, filename_dat, CPL_BPP_IEEE_FLOAT, header,
00443 CPL_IO_DEFAULT);
00444 assure( !cpl_error_get_code(), return,
00445 "Cannot save product %s", filename_dat);
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 cpl_msg_info(cpl_func, "Creating background error map");
00456
00457 bool filter_data = false;
00458 int xstep = radius/2;
00459
00460
00461
00462
00463
00464
00465 int ystep = radius/2;
00466 int xstart = 1;
00467 int ystart = 1;
00468 int xend = fors_image_get_size_x(image);
00469 int yend = fors_image_get_size_y(image);
00470
00471
00472 var_bkg = fors_image_filter_median_create(image,
00473 radius,
00474 radius,
00475 xstart, ystart,
00476 xend, yend,
00477 xstep, ystep,
00478 filter_data);
00479 assure( !cpl_error_get_code(), return,
00480 "Median filtering failed");
00481
00482 sigma_bkg = cpl_image_power_create(var_bkg, 0.5);
00483
00484 cpl_image_save(sigma_bkg, filename_var,
00485 CPL_BPP_IEEE_FLOAT, extension_header,
00486 CPL_IO_DEFAULT);
00487 assure( !cpl_error_get_code(), return,
00488 "Cannot save product %s", filename_var);
00489
00490 cleanup;
00491 return;
00492 }
00493
00494 #undef cleanup
00495 #define cleanup
00496
00501 cpl_size fors_image_get_size_x(const fors_image *image)
00502 {
00503 assure( image != NULL, return -1, NULL );
00504 return cpl_image_get_size_x(image->data);
00505 }
00506
00507 #undef cleanup
00508 #define cleanup
00509
00514 cpl_size fors_image_get_size_y(const fors_image *image)
00515 {
00516 assure( image != NULL, return -1, NULL );
00517 return cpl_image_get_size_y(image->data);
00518 }
00519
00520 #undef cleanup
00521 #define cleanup
00522
00526 const float *fors_image_get_data_const(const fors_image *image)
00527 {
00528 assure( image != NULL, return NULL, NULL );
00529
00530 assure( FORS_IMAGE_TYPE == CPL_TYPE_FLOAT, return NULL, NULL );
00531
00532
00533
00534 return cpl_image_get_data_float(image->data);
00535 }
00536
00537 #undef cleanup
00538 #define cleanup
00539
00546 void
00547 fors_image_abs(fors_image *image)
00548 {
00549 assure( image != NULL, return, NULL );
00550
00551 cpl_image_abs(image->data);
00552
00553 return;
00554 }
00555
00556 #undef cleanup
00557 #define cleanup
00558
00565 void
00566 fors_image_square(fors_image *image)
00567 {
00568 assure( image != NULL, return, NULL );
00569
00570 cpl_image_multiply(image->data, image->data);
00571
00572
00573
00574
00575 cpl_image_multiply_scalar(image->variance, 2);
00576
00577 return;
00578 }
00579
00580
00581 #undef cleanup
00582 #define cleanup \
00583 do { \
00584 cpl_image_delete(temp); \
00585 } while(0)
00586
00594 void
00595 fors_image_subtract(fors_image *left, const fors_image *right)
00596 {
00597 cpl_image *temp = NULL;
00598 assure( left != NULL, return, NULL );
00599 assure( right != NULL, return, NULL );
00600
00601 cpl_image_subtract(left->data, right->data);
00602
00603
00604 cpl_image_add(left->variance, right->variance);
00605
00606 cleanup;
00607 return;
00608 }
00609
00610 #undef cleanup
00611 #define cleanup
00612
00622 void
00623 fors_image_multiply_noerr(fors_image *left, const cpl_image *right)
00624 {
00625 assure( left != NULL, return, NULL );
00626 assure( right != NULL, return, NULL );
00627 assure( cpl_image_get_size_x(left->data) == cpl_image_get_size_x(right) &&
00628 cpl_image_get_size_y(left->data) == cpl_image_get_size_y(right),
00629 return,
00630 "Incompatible data and weight image sizes: "
00631 "%"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT
00632 " and %"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT,
00633 cpl_image_get_size_x(left->data),
00634 cpl_image_get_size_y(left->data),
00635 cpl_image_get_size_x(right),
00636 cpl_image_get_size_y(right));
00637
00638 cpl_image_multiply(left->data, right);
00639 cpl_image_multiply(left->variance, right);
00640 cpl_image_multiply(left->variance, right);
00641
00642 return;
00643 }
00644
00645 #undef cleanup
00646 #define cleanup
00647
00663 void
00664 fors_image_divide_noerr(fors_image *left, cpl_image *right)
00665 {
00666 assure( left != NULL, return, NULL );
00667 assure( right != NULL, return, NULL );
00668 assure( cpl_image_get_size_x(left->data) == cpl_image_get_size_x(right) &&
00669 cpl_image_get_size_y(left->data) == cpl_image_get_size_y(right),
00670 return,
00671 "Incompatible data and weight image sizes: "
00672 "%"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT
00673 " and %"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT,
00674 cpl_image_get_size_x(left->data),
00675 cpl_image_get_size_y(left->data),
00676 cpl_image_get_size_x(right),
00677 cpl_image_get_size_y(right));
00678
00679 int x, y;
00680 int nx = cpl_image_get_size_x(right);
00681 int ny = cpl_image_get_size_y(right);
00682 float *datal = cpl_image_get_data_float(left->data);
00683 float *datav = cpl_image_get_data_float(left->variance);
00684 float *datar = cpl_image_get_data_float(right);
00685 for (y = 0; y < ny; y++) {
00686 for (x = 0; x < nx; x++) {
00687 if (datar[x + nx*y] == 0) {
00688 datar[x + nx*y] = 1;
00689 datal[x + nx*y] = 1;
00690
00691 datav[x + nx*y] = FORS_IMAGE_TYPE_MAX;
00692 }
00693 }
00694 }
00695
00696 cpl_image_divide(left->data, right);
00697 cpl_image_divide(left->variance, right);
00698 cpl_image_divide(left->variance, right);
00699
00700 return;
00701 }
00702
00703 #undef cleanup
00704 #define cleanup \
00705 do { \
00706 fors_image_delete(&dupl); \
00707 } while(0)
00708
00728 void
00729 fors_image_divide(fors_image *left, const fors_image *right)
00730 {
00731 fors_image *dupl = NULL;
00732
00733 assure( left != NULL, return, NULL );
00734 assure( right != NULL, return, NULL );
00735
00736 dupl = fors_image_duplicate(right);
00737
00738 cpl_image_divide(left->data, dupl->data);
00739
00740
00741 cpl_image_multiply(dupl->variance, left->data);
00742 cpl_image_multiply(dupl->variance, left->data);
00743
00744
00745
00746 cpl_image_add(left->variance, dupl->variance);
00747
00748
00749
00750 cpl_image_divide(left->variance, dupl->data);
00751 cpl_image_divide(left->variance, dupl->data);
00752
00753
00754
00755 int x, y;
00756 int nx = cpl_image_get_size_x(left->data);
00757 int ny = cpl_image_get_size_y(left->data);
00758 float *datal = cpl_image_get_data_float(left->data);
00759 float *datav = cpl_image_get_data_float(left->variance);
00760 float *datar = cpl_image_get_data_float(right->data);
00761 for (y = 0; y < ny; y++) {
00762 for (x = 0; x < nx; x++) {
00763 if (datar[x + nx*y] == 0) {
00764 datal[x + nx*y] = 1;
00765 datav[x + nx*y] = FORS_IMAGE_TYPE_MAX;
00766 }
00767 }
00768 }
00769
00770 cleanup;
00771 return;
00772 }
00773
00774 #undef cleanup
00775 #define cleanup \
00776 do { \
00777 cpl_image_delete(s22d12); \
00778 } while(0)
00779
00790 void
00791 fors_image_multiply(fors_image *left, const fors_image *right)
00792 {
00793 cpl_image *s22d12 = NULL;
00794
00795 assure( left != NULL, return, NULL );
00796 assure( right != NULL, return, NULL );
00797
00798 s22d12 = cpl_image_duplicate(right->variance);
00799 cpl_image_multiply(s22d12, left->data);
00800 cpl_image_multiply(s22d12, left->data);
00801
00802 cpl_image_multiply(left->variance, right->data);
00803 cpl_image_multiply(left->variance, right->data);
00804 cpl_image_add(left->variance, s22d12);
00805
00806 cpl_image_multiply(left->data, right->data);
00807
00808 cleanup;
00809 return;
00810 }
00811
00812
00813 #undef cleanup
00814 #define cleanup
00815
00827 void fors_image_subtract_scalar(fors_image *image, double s, double ds)
00828 {
00829 assure( image != NULL, return, NULL );
00830 assure( ds <= 0, return, "Unsupported");
00831
00832 cpl_image_subtract_scalar(image->data, s);
00833
00834 return;
00835 }
00836
00837
00838 #undef cleanup
00839 #define cleanup
00840
00852 void fors_image_divide_scalar(fors_image *image, double s, double ds)
00853 {
00854 assure( image != NULL, return, NULL );
00855 assure( s != 0, return, "Division by zero");
00856 assure( ds <= 0, return, "Unsupported");
00857
00858 cpl_image_divide_scalar(image->data, s);
00859 cpl_image_divide_scalar(image->variance, s*s);
00860
00861 return;
00862 }
00863
00864 #undef cleanup
00865 #define cleanup
00866
00878 void fors_image_multiply_scalar(fors_image *image, double s, double ds)
00879 {
00880 assure( image != NULL, return, NULL );
00881 assure( ds <= 0, return, "Unsupported");
00882
00883 cpl_image_multiply_scalar(image->data, s);
00884 cpl_image_multiply_scalar(image->variance, s*s);
00885
00886 return;
00887 }
00888
00889 #undef cleanup
00890 #define cleanup \
00891 do { \
00892 cpl_image_delete(temp); \
00893 } while(0)
00894
00907 void fors_image_exponential(fors_image *image, double b, double db)
00908 {
00909 cpl_image *temp = NULL;
00910
00911 assure( image != NULL, return, NULL );
00912 assure( b >= 0, return, "Negative base: %f", b);
00913 assure( db <= 0, return, "Unsupported");
00914
00915 cpl_image_exponential(image->data, b);
00916
00917 double lnb = log(b);
00918
00919 cpl_image_multiply_scalar(image->variance, lnb*lnb);
00920 cpl_image_multiply(image->variance, image->data);
00921 cpl_image_multiply(image->variance, image->data);
00922
00923 return;
00924 }
00925
00926
00927 #undef cleanup
00928 #define cleanup
00929
00934 double
00935 fors_image_get_min(const fors_image *image)
00936 {
00937 assure( image != NULL, return 0, NULL );
00938
00939 return cpl_image_get_min(image->data);
00940 }
00941
00942 #undef cleanup
00943 #define cleanup
00944
00949 double
00950 fors_image_get_max(const fors_image *image)
00951 {
00952 assure( image != NULL, return 0, NULL );
00953
00954 return cpl_image_get_max(image->data);
00955 }
00956
00957 #undef cleanup
00958 #define cleanup
00959
00965 double
00966 fors_image_get_mean(const fors_image *image, double *dmean)
00967 {
00968 assure( image != NULL, return 0, NULL );
00969 assure( dmean == NULL, return 0, "Unsupported");
00970
00971 return cpl_image_get_mean(image->data);
00972 }
00973
00974 #undef cleanup
00975 #define cleanup
00976
00982 double
00983 fors_image_get_median(const fors_image *image, double *dmedian)
00984 {
00985 assure( image != NULL, return 0, NULL );
00986 assure( dmedian == NULL, return 0, "Unsupported");
00987
00988 return cpl_image_get_median(image->data);
00989 }
00990
00991
00992 #undef cleanup
00993 #define cleanup
00994
01008 void fors_image_crop(fors_image *image,
01009 int xlo, int ylo,
01010 int xhi, int yhi)
01011 {
01012
01013
01014 assure( image != NULL, return, NULL );
01015 assure( 1 <= xlo && xlo <= xhi && xhi <= fors_image_get_size_x(image) &&
01016 1 <= ylo && ylo <= yhi && yhi <= fors_image_get_size_y(image),
01017 return, "Cannot extraction region (%d, %d) - (%d, %d) of "
01018 "%"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT" image",
01019 xlo, ylo, xhi, yhi,
01020 fors_image_get_size_x(image),
01021 fors_image_get_size_y(image));
01022
01023 cpl_image *new_data = cpl_image_extract(image->data,
01024 xlo, ylo,
01025 xhi, yhi);
01026 cpl_image_delete(image->data);
01027
01028 cpl_image* new_variance = cpl_image_extract(image->variance,
01029 xlo, ylo,
01030 xhi, yhi);
01031 cpl_image_delete(image->variance);
01032
01033 image->data = new_data;
01034 image->variance = new_variance;
01035
01036 return;
01037 }
01038
01064 cpl_image *
01065 fors_image_filter_median_create(const fors_image *image,
01066 int xradius,
01067 int yradius,
01068 int xstart,
01069 int ystart,
01070 int xend,
01071 int yend,
01072 int xstep,
01073 int ystep,
01074 bool use_data)
01075 {
01076 const cpl_image *input = NULL;
01077 cpl_image *smooth = NULL;
01078 int nx, ny;
01079
01080 assure( image != NULL, return smooth, NULL );
01081 passure( image->data != NULL, return smooth );
01082 passure( image->variance != NULL, return smooth );
01083
01084 input = (use_data) ? image->data : image->variance;
01085
01086 nx = cpl_image_get_size_x(input);
01087 ny = cpl_image_get_size_y(input);
01088
01089 if (xstep < 1) xstep = 1;
01090 if (ystep < 1) ystep = 1;
01091
01092 assure( 1 <= xstart && xstart <= xend && xend <= nx &&
01093 1 <= ystart && ystart <= yend && yend <= ny, return smooth,
01094 "Illegal region (%d, %d) - (%d, %d) of %dx%d image",
01095 xstart, ystart,
01096 xend, yend,
01097 nx, ny);
01098
01099 smooth = cpl_image_duplicate(input);
01100
01101
01102 assure( FORS_IMAGE_TYPE == CPL_TYPE_FLOAT, return smooth, NULL );
01103
01104 const float *input_data = cpl_image_get_data_float_const(input);
01105 float *smooth_data = cpl_image_get_data_float(smooth);
01106 float *data = cpl_malloc((2*yradius + 1)*(2*xradius + 1)*sizeof(*data));
01107
01108 int y;
01109 for (y = ystart; y < yend; y++) {
01110
01111
01112
01113
01114
01115
01116 int ylo = y - (yradius/ystep) * ystep;
01117 int yhi = y + (yradius/ystep) * ystep;
01118
01119 while (ylo < ystart) ylo += ystep;
01120 while (yhi > yend ) yhi -= ystep;
01121
01122 int x;
01123 for (x = xstart; x < xend; x++) {
01124 int xlo = x - (xradius/xstep) * xstep;
01125 int xhi = x + (xradius/xstep) * xstep;
01126
01127 while (xlo < xstart) xlo += xstep;
01128 while (xhi > xend ) xhi -= xstep;
01129
01130
01131 int k = 0;
01132 int j, i;
01133 for (j = ylo; j <= yhi; j += ystep) {
01134 for (i = xlo; i <= xhi; i += xstep) {
01135 data[k++] = input_data[ (i-1) + (j-1)*nx ];
01136 }
01137 }
01138
01139
01140 smooth_data[ (x-1) + (y-1)*nx ] =
01141 fors_tools_get_median_float(data, k);
01142 }
01143 }
01144
01145 cpl_free(data);
01146 return smooth;
01147 }
01148
01149 #undef cleanup
01150 #define cleanup \
01151 do { \
01152 cpl_image_delete(input); \
01153 } while(0)
01154 cpl_image *
01155 fors_image_flat_fit_create(fors_image *image,
01156 int step,
01157 int degree,
01158 float level)
01159 {
01160 cpl_image *temp = NULL;
01161 cpl_image *input = NULL;
01162 cpl_image *smooth = NULL;
01163 int nx, ny;
01164
01165 assure( image != NULL, return smooth, NULL );
01166 passure( image->data != NULL, return smooth );
01167 assure( step > 0, return smooth, NULL );
01168 assure( degree >= 0, return smooth, NULL );
01169
01170
01171 temp = image->data;
01172
01173 nx = cpl_image_get_size_x(temp);
01174 ny = cpl_image_get_size_y(temp);
01175
01176
01177
01178
01179
01180 assure( FORS_IMAGE_TYPE == CPL_TYPE_FLOAT, return smooth, NULL );
01181
01182
01183
01184
01185
01186 input = mos_image_filter_median(image->data, 3, 3);
01187
01188 const float *input_data = cpl_image_get_data_float_const(input);
01189
01190
01191
01192
01193
01194 int x, y, pos;
01195 int count = 0;
01196 for (y = 0; y < ny; y += step) {
01197 pos = y*nx;
01198 for (x = 0; x < nx; x += step, pos += step) {
01199 if (input_data[pos] > level) {
01200 count++;
01201 }
01202 }
01203 }
01204
01205 if (count < (degree+1)*(degree+2)) {
01206 step = sqrt((nx*nx)/((degree+1)*(degree+2))) / 2;
01207 if (step == 0)
01208 step = 1;
01209 cpl_msg_error(cpl_func, "Flat field image too small (%dx%d). "
01210 "Please provide a smaller resampling step (a good "
01211 "value would be %d)", nx, ny, step);
01212 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
01213 cleanup;
01214 return NULL;
01215 }
01216
01217
01218
01219
01220
01221
01222 cpl_bivector *positions = cpl_bivector_new(count);
01223 double *xpos = cpl_bivector_get_x_data(positions);
01224 double *ypos = cpl_bivector_get_y_data(positions);
01225 cpl_vector *fluxes = cpl_vector_new(count);
01226 double *flux = cpl_vector_get_data(fluxes);
01227
01228 count = 0;
01229 for (y = 0; y < ny; y += step) {
01230 pos = y*nx;
01231 for (x = 0; x < nx; x += step, pos += step) {
01232 if (input_data[pos] > level) {
01233 xpos[count] = x;
01234 ypos[count] = y;
01235 flux[count] = input_data[pos];
01236 count++;
01237 }
01238 }
01239 }
01240
01241 cpl_image_delete(input); input = NULL;
01242
01243
01244
01245
01246
01247
01248 cpl_polynomial *model = cpl_polynomial_fit_2d_create(positions,
01249 fluxes,
01250 degree,
01251 NULL);
01252
01253 cpl_bivector_delete(positions);
01254 cpl_vector_delete(fluxes);
01255
01256 smooth = cpl_image_new(nx, ny, FORS_IMAGE_TYPE);
01257 float *smooth_data = cpl_image_get_data_float(smooth);
01258
01259 cpl_vector *point = cpl_vector_new(2);
01260 double *dpoint = cpl_vector_get_data(point);
01261
01262 for (y = 0; y < ny; y++) {
01263 pos = y*nx;
01264 dpoint[1] = y;
01265 for (x = 0; x < nx; x++, pos++) {
01266 dpoint[0] = x;
01267 smooth_data[pos] = cpl_polynomial_eval(model, point);
01268 }
01269 }
01270
01271 cpl_polynomial_delete(model);
01272 cpl_vector_delete(point);
01273
01274 cleanup;
01275 return smooth;
01276
01277 }
01278
01279 #undef cleanup
01280 #define cleanup
01281
01297 cpl_image *
01298 fors_image_filter_max_create(const fors_image *image,
01299 int xradius,
01300 int yradius,
01301 bool use_data)
01302 {
01303 const cpl_image *input = NULL;
01304 cpl_image *hmaxima = NULL;
01305 cpl_image *maxima = NULL;
01306 int nx, ny;
01307
01308 assure( image != NULL, return maxima, NULL );
01309 passure( image->data != NULL, return maxima );
01310 passure( image->variance != NULL, return maxima );
01311
01312 input = (use_data) ? image->data : image->variance;
01313
01314 nx = cpl_image_get_size_x(input);
01315 ny = cpl_image_get_size_y(input);
01316
01317
01318
01319
01320
01321 hmaxima = cpl_image_duplicate(input);
01322
01323
01324 assure( FORS_IMAGE_TYPE == CPL_TYPE_FLOAT, return maxima, NULL );
01325
01326 float *input_data = (float *)cpl_image_get_data_float_const(input);
01327 float *maxima_data = cpl_image_get_data_float(hmaxima);
01328
01329 int y;
01330 for (y = 0; y < ny; y++) {
01331 const float *irow = input_data + y * nx;
01332 float *orow = maxima_data + y * nx;
01333 max_filter(irow, orow, nx, 2*xradius+1);
01334 }
01335
01336 cpl_image_turn(hmaxima, 1);
01337
01338
01339
01340
01341
01342 maxima = cpl_image_duplicate(hmaxima);
01343 input_data = cpl_image_get_data_float(hmaxima);
01344 maxima_data = cpl_image_get_data_float(maxima);
01345
01346
01347
01348
01349
01350 int x;
01351 for (x = 0; x < nx; x++) {
01352 const float *irow = input_data + x * ny;
01353 float *orow = maxima_data + x * ny;
01354 max_filter(irow, orow, ny, 2*yradius+1);
01355 }
01356
01357 cpl_image_delete(hmaxima);
01358
01359 cpl_image_turn(maxima, -1);
01360
01361 return maxima;
01362 }
01363
01364 #undef cleanup
01365 #define cleanup
01366
01372 double
01373 fors_image_get_stdev(const fors_image *image, double *dstdev)
01374 {
01375 assure( image != NULL, return 0, NULL );
01376 assure( dstdev == NULL, return 0, "Unsupported");
01377
01378 return cpl_image_get_stdev(image->data);
01379 }
01380 #undef cleanup
01381 #define cleanup \
01382 do { \
01383 cpl_mask_delete(rejected); \
01384 cpl_image_delete(im); \
01385 } while (0)
01386
01394 double fors_image_get_stdev_robust(const fors_image *image,
01395 double cut,
01396 double *dstdev)
01397 {
01398 cpl_mask *rejected = NULL;
01399 cpl_image *im = NULL;
01400
01401 assure( image != NULL, return 0, NULL );
01402 assure( cut > 0, return 0, "Illegal cut: %f", cut );
01403 assure( dstdev == NULL, return 0, "Unsupported");
01404
01405 double median = fors_image_get_median(image, NULL);
01406
01407 im = cpl_image_duplicate(image->data);
01408 cpl_image_subtract_scalar(im, median);
01409 cpl_image_power(im, 2);
01410
01411
01412 rejected = cpl_mask_threshold_image_create(image->data,
01413 median - cut,
01414 median + cut);
01415 cpl_mask_not(rejected);
01416 cpl_image_reject_from_mask(im, rejected);
01417
01418 double robust_stdev = sqrt(cpl_image_get_mean(im));
01419
01420 cleanup;
01421 return robust_stdev;
01422 }
01423
01424 #undef cleanup
01425 #define cleanup
01426
01436 double
01437 fors_image_get_error_mean(const fors_image *image, double *dmean)
01438 {
01439 double avg;
01440
01441 assure( image != NULL, return 0, NULL );
01442 assure( dmean == NULL, return 0, "Unsupported");
01443
01444 avg = cpl_image_get_mean(image->variance);
01445
01446
01447 assure( avg >= 0, return -1, "Average variance is %f", avg);
01448
01449 return sqrt(avg);
01450 }
01451
01452
01453 #undef cleanup
01454 #define cleanup \
01455 do { \
01456 cpl_imagelist_delete(datlist); \
01457 cpl_imagelist_delete(varlist); \
01458 } while (0)
01459
01468 fors_image *
01469 fors_image_collapse_create(const fors_image_list *images)
01470 {
01471 cpl_imagelist *datlist = NULL;
01472 cpl_imagelist *varlist = NULL;
01473 cpl_image *data = NULL;
01474 cpl_image *variance = NULL;
01475 const fors_image *i;
01476 int N = 0;
01477
01478 assure( images != NULL, return NULL, NULL );
01479 assure( fors_image_list_size(images) > 0, return NULL,
01480 "Cannot stack zero images");
01481
01482 i = fors_image_list_first_const(images);
01483
01484 datlist = cpl_imagelist_new();
01485 varlist = cpl_imagelist_new();
01486
01487 while(i != NULL) {
01488
01489
01490 cpl_imagelist_set(datlist,
01491 cpl_image_duplicate(i->data),
01492 cpl_imagelist_get_size(datlist));
01493 cpl_imagelist_set(varlist,
01494 cpl_image_duplicate(i->variance),
01495 cpl_imagelist_get_size(varlist));
01496 i = fors_image_list_next_const(images);
01497 N++;
01498 }
01499
01500 #ifdef CPL_IS_NOT_CRAP
01501 data = cpl_imagelist_collapse_create(datlist);
01502
01503 variance = cpl_imagelist_collapse_create(varlist);
01504 #else
01505 data = fors_imagelist_collapse_create(datlist);
01506
01507 variance = fors_imagelist_collapse_create(varlist);
01508 #endif
01509
01510 cpl_image_divide_scalar(variance, N);
01511
01512 cleanup;
01513 return fors_image_new(data, variance);
01514 }
01515
01516
01517 #undef cleanup
01518 #define cleanup \
01519 do { \
01520 cpl_imagelist_delete(datlist); \
01521 cpl_imagelist_delete(varlist); \
01522 } while (0)
01523
01534 fors_image *
01535 fors_image_collapse_minmax_create(const fors_image_list *images,
01536 int low, int high)
01537 {
01538 cpl_imagelist *datlist = NULL;
01539 cpl_imagelist *varlist = NULL;
01540 cpl_image *data = NULL;
01541 cpl_image *variance = NULL;
01542 const fors_image *i;
01543 int N = 0;
01544
01545 assure( images != NULL, return NULL, NULL );
01546 assure( fors_image_list_size(images) > low + high, return NULL,
01547 "Cannot reject more images than there are");
01548 assure( low*high >= 0 && low+high > 0, return NULL,
01549 "Invalid minmax rejection criteria");
01550
01551 i = fors_image_list_first_const(images);
01552
01553 datlist = cpl_imagelist_new();
01554 varlist = cpl_imagelist_new();
01555
01556 while(i != NULL) {
01557
01558
01559 cpl_imagelist_set(datlist,
01560 cpl_image_duplicate(i->data),
01561 cpl_imagelist_get_size(datlist));
01562 cpl_imagelist_set(varlist,
01563 cpl_image_duplicate(i->variance),
01564 cpl_imagelist_get_size(varlist));
01565 i = fors_image_list_next_const(images);
01566 N++;
01567 }
01568
01569 data = cpl_imagelist_collapse_minmax_create(datlist, low, high);
01570 variance = cpl_imagelist_collapse_minmax_create(varlist, low, high);
01571
01572 cpl_image_divide_scalar(variance, N);
01573
01574 cleanup;
01575 return fors_image_new(data, variance);
01576 }
01577
01590 fors_image *
01591 fors_image_collapse_ksigma_create(const fors_image_list *images,
01592 int low, int high, int iter)
01593 {
01594 cpl_imagelist *datlist = NULL;
01595 cpl_imagelist *varlist = NULL;
01596 cpl_image *data = NULL;
01597 cpl_image *variance = NULL;
01598 cpl_image *ngood = NULL;
01599 const fors_image *i;
01600
01601 assure( images != NULL, return NULL, NULL );
01602
01603 i = fors_image_list_first_const(images);
01604
01605 datlist = cpl_imagelist_new();
01606 varlist = cpl_imagelist_new();
01607
01608 while(i != NULL) {
01609
01610
01611 cpl_imagelist_set(datlist,
01612 cpl_image_duplicate(i->data),
01613 cpl_imagelist_get_size(datlist));
01614 cpl_imagelist_set(varlist,
01615 cpl_image_duplicate(i->variance),
01616 cpl_imagelist_get_size(varlist));
01617 i = fors_image_list_next_const(images);
01618 }
01619
01620 data = mos_ksigma_stack(datlist, low, high, iter, &ngood);
01621 variance = cpl_imagelist_collapse_create(varlist);
01622
01623 cpl_image_divide(variance, ngood);
01624
01625 cpl_image_delete(ngood);
01626 cleanup;
01627
01628 return fors_image_new(data, variance);
01629 }
01630
01642 fors_image *
01643 fors_image_collapse_median_create(const fors_image_list *images)
01644 {
01645 cpl_imagelist *datlist = NULL;
01646 cpl_imagelist *varlist = NULL;
01647 cpl_image *data = NULL;
01648 cpl_image *variance = NULL;
01649 const fors_image *i;
01650 int N = 0;
01651
01652 assure( images != NULL, return NULL, NULL );
01653 assure( fors_image_list_size(images) > 0, return NULL,
01654 "Cannot stack zero images");
01655
01656 i = fors_image_list_first_const(images);
01657
01658 datlist = cpl_imagelist_new();
01659 varlist = cpl_imagelist_new();
01660 while(i != NULL) {
01661
01662 cpl_imagelist_set(datlist,
01663 cpl_image_duplicate(i->data),
01664 cpl_imagelist_get_size(datlist));
01665 cpl_imagelist_set(varlist,
01666 cpl_image_duplicate(i->variance),
01667 cpl_imagelist_get_size(varlist));
01668
01669 i = fors_image_list_next_const(images);
01670 N++;
01671 }
01672
01673 #ifdef CPL_IS_NOT_CRAP
01674 data = cpl_imagelist_collapse_median_create(datlist);
01675
01676 variance = cpl_imagelist_collapse_create(varlist);
01677 #else
01678 data = fors_imagelist_collapse_median_create(datlist);
01679
01680 variance = fors_imagelist_collapse_create(varlist);
01681 #endif
01682
01683 cpl_image_divide_scalar(variance, N);
01684
01685 cpl_image_multiply_scalar(variance,
01686 fors_utils_median_corr(N) *
01687 fors_utils_median_corr(N));
01688
01689 cleanup;
01690 return fors_image_new(data, variance);
01691 }
01692
01693 #undef cleanup
01694 #define cleanup
01695
01712 void fors_image_draw(fors_image *image, int type,
01713 double x, double y,
01714 int radius, double color)
01715 {
01716 assure( image != NULL, return, NULL );
01717
01718 assure( type == 0 || type == 1 || type == 2,
01719 return , "Unsupported type %d", type);
01720
01721 assure( radius > 0, return, NULL );
01722
01723 if (type == 2) {
01724 int i;
01725 for (i = 0; i < 360; i++) {
01726
01727
01728 int px = x + radius*cos(i/(2*M_PI));
01729 int py = y + radius*sin(i/(2*M_PI));
01730
01731 if (1 <= px && px <= cpl_image_get_size_x(image->data) &&
01732 1 <= py && py <= cpl_image_get_size_y(image->data)) {
01733 cpl_image_set(image->data, px, py, color);
01734 cpl_image_set(image->variance, px, py, color > 0 ? color : 0);
01735 }
01736 }
01737 }
01738 else {
01739 int i;
01740
01741 for (i = -radius; i <= radius; i++) {
01742
01743 int px, py;
01744
01745 if (type == 0) {
01746 px = x + i;
01747 py = y;
01748 }
01749 else {
01750 px = x;
01751 py = y + i;
01752 }
01753
01754 if (1 <= px && px <= cpl_image_get_size_x(image->data) &&
01755 1 <= py && py <= cpl_image_get_size_y(image->data)) {
01756 cpl_image_set(image->data , px, py, color);
01757 cpl_image_set(image->variance, px, py, color > 0 ? color : 0);
01758 }
01759 }
01760 }
01761
01762 return;
01763 }
01764
01765 hdrl_imagelist * fors_image_list_to_hdrl(const fors_image_list * imalist)
01766 {
01767 int i;
01768 hdrl_imagelist * images_hdrl = hdrl_imagelist_new();
01769 const fors_image * target = fors_image_list_first_const(imalist);
01770 for(i = 0 ; i < fors_image_list_size(imalist); ++i)
01771 {
01772 const cpl_image * ima_data = target->data;
01773 cpl_image * ima_error = cpl_image_power_create(target->variance, 0.5);
01774 cpl_mask * old_bpm = cpl_image_set_bpm(ima_error,
01775 cpl_mask_duplicate(cpl_image_get_bpm_const(ima_data)));
01776 cpl_mask_delete(old_bpm);
01777 hdrl_image * ima_hdrl = hdrl_image_create(ima_data, ima_error);
01778 hdrl_imagelist_set(images_hdrl, ima_hdrl,
01779 hdrl_imagelist_get_size(images_hdrl));
01780 target = fors_image_list_next_const(imalist);
01781 cpl_image_delete(ima_error);
01782 }
01783
01784 return images_hdrl;
01785 }
01786
01787 fors_image * fors_image_from_hdrl(const hdrl_image * image)
01788 {
01789 const cpl_image * data = hdrl_image_get_image_const(image);
01790 cpl_image * variance = cpl_image_power_create
01791 (hdrl_image_get_error_const(image), 2);
01792 fors_image * ima = fors_image_new(cpl_image_duplicate(data), variance);
01793 return ima;
01794 }
01795
01796
01797 #define LIST_DEFINE
01798 #undef LIST_ELEM
01799 #define LIST_ELEM fors_image
01800 #include <list.h>
01801