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 #include <xsh_utils_wrappers.h>
00028 #include <xsh_utils_image.h>
00029 #include <xsh_error.h>
00030 #include <xsh_utils.h>
00031 #include <xsh_pfits_qc.h>
00032 #include <xsh_pfits.h>
00033 #include <xsh_dfs.h>
00034 #include <xsh_data_pre.h>
00035 #include <xsh_data_instrument.h>
00036 #include <math.h>
00037 #include <string.h>
00038 #define FLAG -1.e+9
00039
00040
00041
00042
00043
00044
00045
00046 static Stats *
00047 xsh_image_stats_on_rectangle ( cpl_image * im,
00048 float loReject,
00049 float hiReject,
00050 int llx,
00051 int lly,
00052 int urx,
00053 int ury );
00054
00055
00056
00057
00058
00059 static cpl_image*
00060 xsh_image_crop(const cpl_image *image,
00061 int xlo, int ylo,
00062 int xhi, int yhi);
00063
00064 static float
00065 xsh_clean_mean( float * array,
00066 int n_elements,
00067 float throwaway_low,
00068 float throwaway_high ) ;
00069
00070
00071 static cpl_error_code
00072 xsh_compute_geom_corr(
00073 const double dxdu,
00074 const double dydv,
00075 const double dxdv,
00076 const double dydu,
00077 const double du,
00078 const double dv,
00079 double* dA);
00080
00081
00082 static double xsh_sinc(double x);
00083 static void reverse_tanh_kernel(double * data, int nn);
00084
00085 static cpl_image *
00086 xsh_gen_lowpass(const int xs,
00087 const int ys,
00088 const double sigma_x,
00089 const double sigma_y);
00090
00107 static cpl_error_code
00108 xsh_compute_geom_corr(
00109 const double dxdu,
00110 const double dydv,
00111 const double dxdv,
00112 const double dydu,
00113 const double du,
00114 const double dv,
00115 double* dA)
00116 {
00117
00118
00119 *dA=fabs(dxdu*dydv-dxdv*dydu)*du*dv;
00120 return cpl_error_get_code();
00121
00122 }
00123
00124
00132 cpl_image*
00133 xsh_image_compute_geom_corr(cpl_image* in)
00134 {
00135
00136 cpl_image* out=NULL;
00137 float* pdata=NULL;
00138 int sx=0;
00139 int sy=0;
00140 register int i=0;
00141 register int j=0;
00142 double dxdu=0;
00143 double dydv=0;
00144 double dxdv=0;
00145 double dydu=0;
00146 double du=0;
00147 double dv=0;
00148 double dA=0;
00149
00150 assure (in != NULL, CPL_ERROR_NULL_INPUT,"NULL input frame");
00151 check(sx=cpl_image_get_size_x(in));
00152 check(sy=cpl_image_get_size_y(in));
00153
00154 pdata=cpl_image_get_data_float(out);
00155 for(j=0;j<sy;j++) {
00156 for(i=0;i<sx;i++) {
00157
00158
00159
00160 check(xsh_compute_geom_corr(dxdu,dydv,dxdv,dydu,du,dv,&dA));
00161 }
00162 }
00163
00164 cleanup:
00165
00166 if(cpl_error_get_code() != CPL_ERROR_NONE) {
00167 xsh_free_image(&out);
00168 return NULL;
00169 } else {
00170 return out;
00171 }
00172 }
00173
00174
00175
00176
00177
00201
00202
00203 double *
00204 xsh_generate_interpolation_kernel(const char * kernel_type)
00205 {
00206 double * tab ;
00207 int i ;
00208 double x ;
00209 double alpha ;
00210 double inv_norm ;
00211 int samples = KERNEL_SAMPLES ;
00212
00213 if (kernel_type==NULL) {
00214 tab = xsh_generate_interpolation_kernel("tanh") ;
00215 } else if (!strcmp(kernel_type, "default")) {
00216 tab = xsh_generate_interpolation_kernel("tanh") ;
00217 } else if (!strcmp(kernel_type, "sinc")) {
00218 tab = cpl_malloc(samples * sizeof(double)) ;
00219 tab[0] = 1.0 ;
00220 tab[samples-1] = 0.0 ;
00221 for (i=1 ; i<samples ; i++) {
00222 x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
00223 tab[i] = xsh_sinc(x) ;
00224 }
00225 } else if (!strcmp(kernel_type, "sinc2")) {
00226 tab = cpl_malloc(samples * sizeof(double)) ;
00227 tab[0] = 1.0 ;
00228 tab[samples-1] = 0.0 ;
00229 for (i=1 ; i<samples ; i++) {
00230 x = 2.0 * (double)i/(double)(samples-1) ;
00231 tab[i] = xsh_sinc(x) ;
00232 tab[i] *= tab[i] ;
00233 }
00234 } else if (!strcmp(kernel_type, "lanczos")) {
00235 tab = cpl_malloc(samples * sizeof(double)) ;
00236 for (i=0 ; i<samples ; i++) {
00237 x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
00238 if (fabs(x)<2) {
00239 tab[i] = xsh_sinc(x) * xsh_sinc(x/2) ;
00240 } else {
00241 tab[i] = 0.00 ;
00242 }
00243 }
00244 } else if (!strcmp(kernel_type, "hamming")) {
00245 tab = cpl_malloc(samples * sizeof(double)) ;
00246 alpha = 0.54 ;
00247 inv_norm = 1.00 / (double)(samples - 1) ;
00248 for (i=0 ; i<samples ; i++) {
00249 x = (double)i ;
00250 if (i<(samples-1)/2) {
00251 tab[i] = alpha + (1-alpha) * cos(2.0*M_PI*x*inv_norm) ;
00252 } else {
00253 tab[i] = 0.0 ;
00254 }
00255 }
00256 } else if (!strcmp(kernel_type, "hann")) {
00257 tab = cpl_malloc(samples * sizeof(double)) ;
00258 alpha = 0.50 ;
00259 inv_norm = 1.00 / (double)(samples - 1) ;
00260 for (i=0 ; i<samples ; i++) {
00261 x = (double)i ;
00262 if (i<(samples-1)/2) {
00263 tab[i] = alpha + (1-alpha) * cos(2.0*M_PI*x*inv_norm) ;
00264 } else {
00265 tab[i] = 0.0 ;
00266 }
00267 }
00268 } else if (!strcmp(kernel_type, "tanh")) {
00269 tab = xsh_generate_tanh_kernel(TANH_STEEPNESS) ;
00270 } else {
00271 xsh_msg_error("unrecognized kernel type [%s]: aborting generation",
00272 kernel_type) ;
00273 return NULL ;
00274 }
00275
00276 return tab ;
00277 }
00278
00279
00280
00291
00292
00293 static double
00294 xsh_sinc(double x)
00295 {
00296 if (fabs(x)<1e-4)
00297 return (double)1.00 ;
00298 else
00299 return ((sin(x * (double)M_PI)) / (x * (double)M_PI)) ;
00300 }
00301
00302
00303
00304
00340
00341
00342 cpl_image *
00343 xsh_warp_image_generic(
00344 cpl_image * image_in,
00345 char * kernel_type,
00346 cpl_polynomial * poly_u,
00347 cpl_polynomial * poly_v
00348 )
00349 {
00350 cpl_image * image_out ;
00351 int i, j, k ;
00352 int lx_out, ly_out ;
00353 double cur ;
00354 double neighbors[16] ;
00355 double rsc[8],
00356 sumrs ;
00357 double x, y ;
00358 int px, py ;
00359 int pos ;
00360 int tabx, taby ;
00361 double * kernel ;
00362 int leaps[16] ;
00363 int ilx=0;
00364 int ily=0;
00365 float* pidata=NULL;
00366 float* podata=NULL;
00367 cpl_vector* vx=NULL;
00368 if (image_in == NULL) return NULL ;
00369
00370
00371
00372 kernel = xsh_generate_interpolation_kernel(kernel_type) ;
00373 if (kernel == NULL) {
00374 xsh_msg_error("cannot generate kernel: aborting resampling") ;
00375 return NULL ;
00376 }
00377 ilx=cpl_image_get_size_x(image_in);
00378 ily=cpl_image_get_size_y(image_in);
00379 pidata=cpl_image_get_data_float(image_in);
00380
00381
00382 lx_out = (int)ilx ;
00383 ly_out = (int)ily ;
00384
00385 image_out = cpl_image_new(lx_out, ly_out,CPL_TYPE_FLOAT) ;
00386 podata=cpl_image_get_data_float(image_out);
00387
00388
00389
00390 leaps[0] = -1 - ilx ;
00391 leaps[1] = - ilx ;
00392 leaps[2] = 1 - ilx ;
00393 leaps[3] = 2 - ilx ;
00394
00395 leaps[4] = -1 ;
00396 leaps[5] = 0 ;
00397 leaps[6] = 1 ;
00398 leaps[7] = 2 ;
00399
00400 leaps[8] = -1 + ilx ;
00401 leaps[9] = ilx ;
00402 leaps[10]= 1 + ilx ;
00403 leaps[11]= 2 + ilx ;
00404
00405 leaps[12]= -1 + 2*ilx ;
00406 leaps[13]= 2*ilx ;
00407 leaps[14]= 1 + 2*ilx ;
00408 leaps[15]= 2 + 2*ilx ;
00409
00410 vx=cpl_vector_new(2);
00411
00412 for (j=0 ; j < ly_out ; j++) {
00413 for (i=0 ; i< lx_out ; i++) {
00414
00415 cpl_vector_set(vx,0,(double)i);
00416 cpl_vector_set(vx,1,(double)j);
00417 x = cpl_polynomial_eval(poly_u, vx);
00418 y = cpl_polynomial_eval(poly_v, vx);
00419
00420
00421 px = (int)x ;
00422 py = (int)y ;
00423
00424 if ((px < 1) ||
00425 (px > (ilx-3)) ||
00426 (py < 1) ||
00427 (py > (ily-3)))
00428 podata[i+j*lx_out] = (pixelvalue)0.0/0.0 ;
00429 else {
00430
00431 pos = px + py * ilx ;
00432 for (k=0 ; k<16 ; k++)
00433 neighbors[k] = (double)(pidata[(int)(pos+leaps[k])]) ;
00434
00435
00436 tabx = (x - (double)px) * (double)(TABSPERPIX) ;
00437 taby = (y - (double)py) * (double)(TABSPERPIX) ;
00438
00439
00440
00441
00442 rsc[0] = kernel[TABSPERPIX + tabx] ;
00443 rsc[1] = kernel[tabx] ;
00444 rsc[2] = kernel[TABSPERPIX - tabx] ;
00445 rsc[3] = kernel[2 * TABSPERPIX - tabx] ;
00446 rsc[4] = kernel[TABSPERPIX + taby] ;
00447 rsc[5] = kernel[taby] ;
00448 rsc[6] = kernel[TABSPERPIX - taby] ;
00449 rsc[7] = kernel[2 * TABSPERPIX - taby] ;
00450
00451 sumrs = (rsc[0]+rsc[1]+rsc[2]+rsc[3]) *
00452 (rsc[4]+rsc[5]+rsc[6]+rsc[7]) ;
00453
00454
00455 cur = rsc[4] * ( rsc[0]*neighbors[0] +
00456 rsc[1]*neighbors[1] +
00457 rsc[2]*neighbors[2] +
00458 rsc[3]*neighbors[3] ) +
00459 rsc[5] * ( rsc[0]*neighbors[4] +
00460 rsc[1]*neighbors[5] +
00461 rsc[2]*neighbors[6] +
00462 rsc[3]*neighbors[7] ) +
00463 rsc[6] * ( rsc[0]*neighbors[8] +
00464 rsc[1]*neighbors[9] +
00465 rsc[2]*neighbors[10] +
00466 rsc[3]*neighbors[11] ) +
00467 rsc[7] * ( rsc[0]*neighbors[12] +
00468 rsc[1]*neighbors[13] +
00469 rsc[2]*neighbors[14] +
00470 rsc[3]*neighbors[15] ) ;
00471
00472
00473 podata[i+j*lx_out] = (pixelvalue)(cur/sumrs) ;
00474
00475 }
00476 }
00477 }
00478 cpl_vector_delete(vx);
00479 cpl_free(kernel) ;
00480 return image_out ;
00481 }
00482
00483
00484 #define hk_gen(x,s) (((tanh(s*(x+0.5))+1)/2)*((tanh(s*(-x+0.5))+1)/2))
00485
00486
00507
00508
00509 double * xsh_generate_tanh_kernel(double steep)
00510 {
00511 double * kernel ;
00512 double * x ;
00513 double width ;
00514 double inv_np ;
00515 double ind ;
00516 int i ;
00517 int np ;
00518 int samples ;
00519
00520 width = (double)TABSPERPIX / 2.0 ;
00521 samples = KERNEL_SAMPLES ;
00522 np = 32768 ;
00523 inv_np = 1.00 / (double)np ;
00524
00525
00526
00527
00528
00529 x = cpl_malloc((2*np+1)*sizeof(double)) ;
00530 for (i=0 ; i<np/2 ; i++) {
00531 ind = (double)i * 2.0 * width * inv_np ;
00532 x[2*i] = hk_gen(ind, steep) ;
00533 x[2*i+1] = 0.00 ;
00534 }
00535 for (i=np/2 ; i<np ; i++) {
00536 ind = (double)(i-np) * 2.0 * width * inv_np ;
00537 x[2*i] = hk_gen(ind, steep) ;
00538 x[2*i+1] = 0.00 ;
00539 }
00540
00541
00542
00543
00544 reverse_tanh_kernel(x, np) ;
00545
00546
00547
00548
00549 kernel = cpl_malloc(samples * sizeof(double)) ;
00550 for (i=0 ; i<samples ; i++) {
00551 kernel[i] = 2.0 * width * x[2*i] * inv_np ;
00552 }
00553 cpl_free(x) ;
00554 return kernel ;
00555 }
00556
00557
00558 #define KERNEL_SW(a,b) tempr=(a);(a)=(b);(b)=tempr
00559
00571
00572
00573 static void
00574 reverse_tanh_kernel(double * data, int nn)
00575 {
00576 unsigned long n,
00577 mmax,
00578 m,
00579 i, j,
00580 istep ;
00581 double wtemp,
00582 wr,
00583 wpr,
00584 wpi,
00585 wi,
00586 theta;
00587 double tempr,
00588 tempi;
00589
00590 n = (unsigned long)nn << 1;
00591 j = 1;
00592 for (i=1 ; i<n ; i+=2) {
00593 if (j > i) {
00594 KERNEL_SW(data[j-1],data[i-1]);
00595 KERNEL_SW(data[j],data[i]);
00596 }
00597 m = n >> 1;
00598 while (m>=2 && j>m) {
00599 j -= m;
00600 m >>= 1;
00601 }
00602 j += m;
00603 }
00604 mmax = 2;
00605 while (n > mmax) {
00606 istep = mmax << 1;
00607 theta = 2 * M_PI / mmax;
00608 wtemp = sin(0.5 * theta);
00609 wpr = -2.0 * wtemp * wtemp;
00610 wpi = sin(theta);
00611 wr = 1.0;
00612 wi = 0.0;
00613 for (m=1 ; m<mmax ; m+=2) {
00614 for (i=m ; i<=n ; i+=istep) {
00615 j = i + mmax;
00616 tempr = wr * data[j-1] - wi * data[j];
00617 tempi = wr * data[j] + wi * data[j-1];
00618 data[j-1] = data[i-1] - tempr;
00619 data[j] = data[i] - tempi;
00620 data[i-1] += tempr;
00621 data[i] += tempi;
00622 }
00623 wr = (wtemp = wr) * wpr - wi * wpi + wr;
00624 wi = wi * wpr + wtemp * wpi + wi;
00625 }
00626 mmax = istep;
00627 }
00628 }
00629 #undef KERNEL_SW
00630
00631
00632
00633
00646
00647
00648 void xsh_show_interpolation_kernel(char * kernel_name)
00649 {
00650 double * ker ;
00651 int i ;
00652 double x ;
00653
00654
00655 ker = xsh_generate_interpolation_kernel(kernel_name) ;
00656 if (ker == NULL)
00657 return ;
00658
00659 (void)fprintf(stdout, "# Kernel is %s\n", kernel_name) ;
00660 x = 0.00 ;
00661 for (i=0 ; i<KERNEL_SAMPLES ; i++) {
00662 (void)fprintf(stdout, "%g %g\n", x, ker[i]) ;
00663 x += 1.00 / (double)TABSPERPIX ;
00664 }
00665 cpl_free(ker) ;
00666 return ;
00667 }
00668
00676 double
00677 xsh_image_get_stdev_robust(const cpl_image *image,
00678 double cut,
00679 double *dstdev)
00680 {
00681 cpl_mask *rejected = NULL;
00682 cpl_image *im = NULL;
00683 double median = 0;
00684 double robust_stdev = 0;
00685
00686 assure (image != NULL, CPL_ERROR_NULL_INPUT,"NULL input frame");
00687 assure( cut > 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal cut: %f", cut );
00688 assure( dstdev == NULL, CPL_ERROR_ILLEGAL_INPUT, "Unsupported");
00689
00690 median = cpl_image_get_median(image);
00691
00692 im = cpl_image_duplicate(image);
00693 cpl_image_subtract_scalar(im, median);
00694 cpl_image_power(im, 2);
00695
00696
00697 rejected = cpl_mask_threshold_image_create(image,median - cut,
00698 median + cut);
00699 cpl_mask_not(rejected);
00700 cpl_image_reject_from_mask(im, rejected);
00701
00702 robust_stdev = sqrt(cpl_image_get_mean(im));
00703
00704 cleanup:
00705 xsh_free_image(&im);
00706 xsh_free_mask(&rejected);
00707
00708 return robust_stdev;
00709 }
00710
00717 double xsh_image_get_stdev_clean(const cpl_image *image,
00718 double *dstdev)
00719 {
00720 cpl_mask *rejected = NULL;
00721 cpl_image *im = NULL;
00722 double median = 0;
00723 double stdev = 0;
00724 double robust_stdev = 0;
00725 double kappa=3.0;
00726 double cut=0;
00727
00728 assure (image != NULL, CPL_ERROR_NULL_INPUT,"NULL input frame");
00729 assure( dstdev == NULL, CPL_ERROR_ILLEGAL_INPUT, "Unsupported");
00730
00731 median = cpl_image_get_median(image);
00732 stdev=cpl_image_get_stdev(image);
00733 cut=kappa*stdev;
00734
00735 im = cpl_image_duplicate(image);
00736 cpl_image_subtract_scalar(im, median);
00737 cpl_image_power(im, 2);
00738
00739
00740 rejected = cpl_mask_threshold_image_create(image,median - cut,
00741 median + cut);
00742 cpl_mask_not(rejected);
00743 cpl_image_reject_from_mask(im, rejected);
00744
00745 robust_stdev = sqrt(cpl_image_get_mean(im));
00746
00747 cleanup:
00748 xsh_free_image(&im);
00749 xsh_free_mask(&rejected);
00750
00751 return robust_stdev;
00752 }
00753
00754
00755
00763 double
00764 xsh_fixed_pattern_noise(const cpl_image *master,
00765 double convert_ADU,
00766 double master_noise)
00767 {
00768 double master_fixed_pattern_noise=0;
00769 cpl_image *image1 = NULL;
00770 cpl_image *image2 = NULL;
00771
00772 assure (master != NULL, CPL_ERROR_NULL_INPUT,"NULL input frame");
00773
00774
00775
00776
00777 if (cpl_image_get_size_x(master) >= 121 &&
00778 cpl_image_get_size_y(master) >= 121) {
00779
00780 int mid_x = (cpl_image_get_size_x(master) + 1) / 2;
00781 int mid_y = (cpl_image_get_size_y(master) + 1) / 2;
00782
00783
00784 image1=xsh_image_crop(master,
00785 mid_x - 50, mid_y - 50,
00786 mid_x + 50, mid_y + 50);
00787
00788
00789 image2=xsh_image_crop(master,
00790 mid_x + 10 - 50, mid_y + 10 - 50,
00791 mid_x + 10 + 50, mid_y + 10 + 50);
00792
00793 cpl_image_subtract(image1, image2);
00794
00795 master_fixed_pattern_noise = cpl_image_get_stdev(image1) / sqrt(2);
00796
00797
00798 master_fixed_pattern_noise *= convert_ADU;
00799
00800
00801 if (master_fixed_pattern_noise >= master_noise) {
00802
00803 master_fixed_pattern_noise = sqrt(master_fixed_pattern_noise*
00804 master_fixed_pattern_noise
00805 -
00806 master_noise*
00807 master_noise);
00808 }
00809 else {
00810 cpl_msg_warning(cpl_func,
00811 "Zero-shift noise (%f ADU) is greater than "
00812 "accumulated zero-shift and fixed pattern noise (%f ADU), "
00813 "setting fixed pattern noise to zero",
00814 master_noise,
00815 master_fixed_pattern_noise);
00816 master_fixed_pattern_noise = 0;
00817 }
00818 }
00819 else {
00820 cpl_msg_warning(cpl_func,
00821 "Master flat too small (%dx%d), "
00822 "need size 121x121 to compute master flat "
00823 "fixed pattern noise",
00824 cpl_image_get_size_x(master),
00825 cpl_image_get_size_y(master));
00826 master_fixed_pattern_noise = -1;
00827 }
00828
00829 cleanup:
00830 xsh_free_image(&image1);
00831 xsh_free_image(&image2);
00832
00833 return master_fixed_pattern_noise;
00834 }
00835
00843 double
00844 xsh_fixed_pattern_noise_bias(const cpl_image *first_raw,
00845 const cpl_image *second_raw,
00846 double ron)
00847 {
00848 double bias_fixed_pattern_noise=0;
00849 cpl_image *image1 = NULL;
00850 cpl_image *image2 = NULL;
00851 int nx, ny;
00852
00853 assure (first_raw != NULL, CPL_ERROR_NULL_INPUT,"NULL input image");
00854 assure (second_raw != NULL, CPL_ERROR_NULL_INPUT,"NULL input image");
00855
00856
00857
00858
00859
00860 nx = cpl_image_get_size_x(first_raw);
00861 ny = cpl_image_get_size_y(first_raw);
00862
00863
00864 image1=xsh_image_crop(first_raw, 1, 1,nx - 10, ny - 10);
00865
00866
00867 image2=xsh_image_crop(second_raw, 11, 11,nx, ny);
00868
00869 cpl_image_subtract(image1, image2);
00870
00871 bias_fixed_pattern_noise = xsh_image_get_stdev_robust(image1, 50, NULL)
00872 / sqrt(2);
00873
00874
00875
00876
00877
00878 if (bias_fixed_pattern_noise > ron) {
00879
00880 bias_fixed_pattern_noise = sqrt(bias_fixed_pattern_noise *
00881 bias_fixed_pattern_noise
00882 -
00883 ron * ron);
00884 }
00885 else {
00886 cpl_msg_warning(cpl_func,
00887 "Zero-shift noise (%f ADU) is greater than "
00888 "accumulated zero-shift and fixed pattern "
00889 "noise (%f ADU), "
00890 "setting fixed pattern noise to zero",
00891 ron,
00892 bias_fixed_pattern_noise);
00893 bias_fixed_pattern_noise = 0;
00894 }
00895
00896 cleanup:
00897 xsh_free_image(&image1);
00898 xsh_free_image(&image2);
00899
00900 return bias_fixed_pattern_noise;
00901 }
00902
00903
00918 static cpl_image*
00919 xsh_image_crop(const cpl_image *image,
00920 int xlo, int ylo,
00921 int xhi, int yhi)
00922 {
00923
00924
00925 cpl_image *image_crop = NULL;
00926 assure( image != NULL, CPL_ERROR_ILLEGAL_INPUT, "Null input image" );
00927 assure( 1 <= xlo && xlo <= xhi && xhi <= cpl_image_get_size_x(image) &&
00928 1 <= ylo && ylo <= yhi && yhi <= cpl_image_get_size_y(image),
00929 CPL_ERROR_ILLEGAL_INPUT,
00930 "Cannot extraction region (%d, %d) - (%d, %d) of %dx%d image",
00931 xlo, ylo, xhi, yhi,
00932 cpl_image_get_size_x(image),
00933 cpl_image_get_size_y(image));
00934
00935
00936
00937 check(image_crop = cpl_image_extract(image,xlo, ylo,xhi, yhi));
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951 cleanup:
00952 if(cpl_error_get_code() != CPL_ERROR_NONE) {
00953 return NULL;
00954 } else {
00955 return image_crop;
00956 }
00957 }
00958
00959
00960
01011 cpl_error_code xsh_image_warp_polynomial_scale(cpl_image *out,
01012 const cpl_polynomial *poly_x,
01013 const cpl_polynomial *poly_y)
01014 {
01015 cpl_polynomial *dxdu=NULL;
01016 cpl_polynomial *dxdv=NULL;
01017 cpl_polynomial *dydu=NULL;
01018 cpl_polynomial *dydv=NULL;
01019
01020 cpl_vector *val=NULL;
01021 double *pval=NULL;
01022
01023 double *ddata=NULL;
01024 float *fdata=NULL;
01025
01026 int nx, ny;
01027 int i, j;
01028
01029
01030 if (out == NULL || poly_x == NULL || poly_y == NULL)
01031 return cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
01032
01033 if (cpl_polynomial_get_dimension(poly_x) != 2 ||
01034 cpl_polynomial_get_dimension(poly_y) != 2)
01035 return cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
01036
01037 if (cpl_image_get_type(out) != CPL_TYPE_FLOAT &&
01038 cpl_image_get_type(out) != CPL_TYPE_DOUBLE)
01039 return cpl_error_set(cpl_func, CPL_ERROR_INVALID_TYPE);
01040
01041
01042
01043
01044
01045
01046 dxdu = cpl_polynomial_duplicate(poly_x);
01047 dxdv = cpl_polynomial_duplicate(poly_x);
01048 dydu = cpl_polynomial_duplicate(poly_y);
01049 dydv = cpl_polynomial_duplicate(poly_y);
01050
01051 cpl_polynomial_derivative(dxdu, 0);
01052 cpl_polynomial_derivative(dxdv, 1);
01053 cpl_polynomial_derivative(dydu, 0);
01054 cpl_polynomial_derivative(dydv, 1);
01055
01056
01057
01058
01059
01060
01061
01062 nx = cpl_image_get_size_x(out);
01063 ny = cpl_image_get_size_y(out);
01064
01065 val = cpl_vector_new(2);
01066 pval = cpl_vector_get_data(val);
01067
01068 switch (cpl_image_get_type(out)) {
01069 case CPL_TYPE_FLOAT:
01070 fdata = cpl_image_get_data_float(out);
01071 for (j=0; j < ny; j++) {
01072 pval[1] = j + 1;
01073 for (i=0; i < nx; i++) {
01074 pval[0] = i + 1;
01075 *fdata++ = cpl_polynomial_eval(dxdu, val)
01076 * cpl_polynomial_eval(dydv, val)
01077 - cpl_polynomial_eval(dxdv, val)
01078 * cpl_polynomial_eval(dydu, val);
01079 }
01080 }
01081 break;
01082 case CPL_TYPE_DOUBLE:
01083 ddata = cpl_image_get_data_double(out);
01084 for (j=0; j < ny; j++) {
01085 pval[1] = j + 1;
01086 for (i=0; i < nx; i++) {
01087 pval[0] = i + 1;
01088 *ddata++ = cpl_polynomial_eval(dxdu, val)
01089 * cpl_polynomial_eval(dydv, val)
01090 - cpl_polynomial_eval(dxdv, val)
01091 * cpl_polynomial_eval(dydu, val);
01092 }
01093 }
01094 break;
01095 default:
01096
01097
01098
01099
01100
01101
01102 break;
01103 }
01104
01105 cpl_vector_delete(val);
01106 cpl_polynomial_delete(dxdu);
01107 cpl_polynomial_delete(dxdv);
01108 cpl_polynomial_delete(dydu);
01109 cpl_polynomial_delete(dydv);
01110
01111
01112
01113
01114
01115
01116 cpl_image_abs(out);
01117
01118 return CPL_ERROR_NONE;
01119
01120 }
01121
01122
01129 cpl_image*
01130 xsh_scharr_x(cpl_image* in) {
01131
01132 cpl_image* scharr_x=NULL;
01133 float* pscharr_x=NULL;
01134 float* pin=NULL;
01135 int sx=0;
01136 int sy=0;
01137 int i=0;
01138 int j=0;
01139
01140
01141 check(scharr_x=cpl_image_duplicate(in));
01142 check(pscharr_x=cpl_image_get_data_float(scharr_x));
01143 check(pin=cpl_image_get_data_float(in));
01144 check(sx=cpl_image_get_size_x(in));
01145 check(sy=cpl_image_get_size_y(in));
01146
01147 for(i=1;i<sx-1;i++) {
01148 for(j=1;j<sy-1;j++) {
01149 pscharr_x[i+j*sx]=3*pin[i-1+(j+1)*sx]-3*pin[i+1+(j+1)*sx]+
01150 10*pin[i-1+j*sx]-10*pin[i+1+j*sx]+
01151 3*pin[i-1+(j-1)*sx]-3*pin[i+1+(j-1)*sx];
01152 }
01153 }
01154
01155 cleanup:
01156 return scharr_x;
01157
01158 }
01159
01160
01161
01168 cpl_image*
01169 xsh_scharr_y(cpl_image* in) {
01170
01171 cpl_image* scharr_y=NULL;
01172 float* pscharr_y=NULL;
01173 float* pin=NULL;
01174 int sx=0;
01175 int sy=0;
01176 int i=0;
01177 int j=0;
01178
01179
01180 check(scharr_y=cpl_image_duplicate(in));
01181 check(pscharr_y=cpl_image_get_data_float(scharr_y));
01182 check(pin=cpl_image_get_data_float(in));
01183 check(sx=cpl_image_get_size_x(in));
01184 check(sy=cpl_image_get_size_y(in));
01185
01186 for(i=1;i<sx-1;i++) {
01187 for(j=1;j<sy-1;j++) {
01188 pscharr_y[i+j*sx]=3*pin[i-1+(j+1)*sx]+10*pin[i+(j+1)*sx]+3*pin[i+1+(j+1)*sx]+
01189 -3*pin[i-1+(j-1)*sx]-10*pin[i+(j-1)*sx]-3*pin[i+1+(j-1)*sx];
01190 }
01191 }
01192
01193 cleanup:
01194 return scharr_y;
01195
01196 }
01197
01198
01206 cpl_image*
01207 xsh_sobel_lx(cpl_image* in) {
01208
01209 cpl_image* lx=NULL;
01210 float* plx=NULL;
01211 float* pin=NULL;
01212 int sx=0;
01213 int sy=0;
01214 int i=0;
01215 int j=0;
01216
01217
01218 check(lx=cpl_image_duplicate(in));
01219 check(plx=cpl_image_get_data_float(lx));
01220 check(pin=cpl_image_get_data_float(in));
01221 check(sx=cpl_image_get_size_x(in));
01222 check(sy=cpl_image_get_size_y(in));
01223
01224 for(i=1;i<sx-1;i++) {
01225 for(j=1;j<sy-1;j++) {
01226 plx[i+j*sx]=pin[i-1+(j+1)*sx]-pin[i+1+(j+1)*sx]+
01227 2*pin[i-1+j*sx]-2*pin[i+1+j*sx]+
01228 pin[i-1+(j-1)*sx]-pin[i+1+(j-1)*sx];
01229 }
01230 }
01231
01232 cleanup:
01233 return lx;
01234
01235 }
01236
01237
01238
01246 cpl_image*
01247 xsh_sobel_ly(cpl_image* in) {
01248
01249
01250
01251 cpl_image* ly=NULL;
01252 float* ply=NULL;
01253 float* pin=NULL;
01254 int sx=0;
01255 int sy=0;
01256 int i=0;
01257 int j=0;
01258
01259
01260 check(ly=cpl_image_duplicate(in));
01261 check(ply=cpl_image_get_data_float(ly));
01262 check(pin=cpl_image_get_data_float(in));
01263 check(sx=cpl_image_get_size_x(in));
01264 check(sy=cpl_image_get_size_y(in));
01265
01266 for(i=1;i<sx-1;i++) {
01267 for(j=1;j<sy-1;j++) {
01268 ply[i+j*sx]=pin[i-1+(j+1)*sx]+2*pin[i+(j+1)*sx]+pin[i+1+(j+1)*sx]+
01269 -pin[i-1+(j-1)*sx]-2*pin[i+(j-1)*sx]-pin[i+1+(j-1)*sx];
01270 }
01271 }
01272 cleanup:
01273 return ly;
01274
01275 }
01276
01292 cpl_error_code
01293 xsh_compute_ron(cpl_frameset* frames,
01294 int llx,
01295 int lly,
01296 int urx,
01297 int ury,
01298 int nsampl,
01299 int hsize,
01300 const int reg_id,
01301 double* ron,
01302 double* ron_err)
01303 {
01304
01305 cpl_frame* bias1=NULL;
01306 cpl_frame* bias2=NULL;
01307
01308 cpl_image* ima1=NULL;
01309 cpl_image* ima2=NULL;
01310 cpl_image* imad=NULL;
01311
01312 const char* name1=NULL;
01313 const char* name2=NULL;
01314 int nx1=0;
01315 int ny1=0;
01316 int nx2=0;
01317 int ny2=0;
01318 int zone[4];
01319 int nfrm=0;
01320 cpl_propertylist* plist=NULL;
01321 const char* name_o="BIAS_PAIR_DIFF.fits";
01322
01323
01324 check(nfrm=cpl_frameset_get_size(frames));
01325
01326 if ( nfrm < 2 ) goto cleanup;
01327
01328 check(bias1=cpl_frameset_get_first(frames));
01329 check(bias2=cpl_frameset_get_next(frames));
01330 check(name1=cpl_frame_get_filename(bias1));
01331 check(name2=cpl_frame_get_filename(bias2));
01332 check(ima1=cpl_image_load(name1,CPL_TYPE_FLOAT,0,0));
01333 check(ima2=cpl_image_load(name2,CPL_TYPE_FLOAT,0,0));
01334
01335 check(nx1=cpl_image_get_size_x(ima1));
01336 check(nx2=cpl_image_get_size_x(ima2));
01337
01338 check(ny1=cpl_image_get_size_y(ima1));
01339 check(ny2=cpl_image_get_size_y(ima2));
01340
01341 if((nx1 != nx2) || (ny1 != ny2)) {
01342 xsh_error_msg("image1's size: [%d,%d] != from image2's size [%d,%d]",
01343 nx1,ny1,nx2,ny2);
01344 goto cleanup;
01345 }
01346
01347 check(plist=cpl_propertylist_load(name1,0));
01348
01349 if(llx == -1) llx=1;
01350 if(lly == -1) lly=1;
01351
01352 if(urx == -1) urx=nx1;
01353 if(ury == -1) ury=ny1;
01354
01355 zone[0]=llx;
01356 zone[1]=urx;
01357 zone[2]=lly;
01358 zone[3]=ury;
01359
01360 check(imad=cpl_image_duplicate(ima1));
01361 check(cpl_image_subtract(imad,ima2));
01362
01363 check(cpl_flux_get_noise_window(imad, zone,hsize,nsampl,ron,ron_err));
01364
01365
01366 *ron/=sqrt(2);
01367 *ron_err/=sqrt(2);
01368
01369
01370
01371 if(reg_id==1) {
01372 xsh_pfits_set_qc_ron1(plist,*ron);
01373 xsh_pfits_set_qc_ron1_err(plist,*ron_err);
01374 } else{
01375 xsh_pfits_set_qc_ron2(plist,*ron);
01376 xsh_pfits_set_qc_ron2_err(plist,*ron_err);
01377 }
01378 check(cpl_propertylist_append_string(plist,XSH_PCATG,"BIAS_PAIR_DIFF"));
01379 check(cpl_image_save(imad,name_o,CPL_BPP_IEEE_FLOAT,plist,CPL_IO_DEFAULT));
01380
01381 cleanup:
01382 xsh_free_image(&ima1);
01383 xsh_free_image(&ima2);
01384 xsh_free_image(&imad);
01385 xsh_free_propertylist(&plist);
01386
01387
01388
01389 if (cpl_error_get_code()) {
01390 return -1 ;
01391 } else {
01392 return 0 ;
01393 }
01394
01395
01396 }
01397
01427 cpl_image *
01428 xsh_image_search_bad_pixels_via_noise(cpl_imagelist * darks,
01429 float thresh_sigma_factor,
01430 float low_threshold,
01431 float high_threshold,
01432 int llx,
01433 int lly,
01434 int urx,
01435 int ury)
01436 {
01437 cpl_image * bp_map =NULL;
01438 int z, n, i ;
01439 int lx, ly ;
01440 int row, col ;
01441 int low_n, high_n ;
01442 float * spectrum =NULL;
01443 double pix_sum ;
01444 double sqr_sum ;
01445 Stats * stats =NULL;
01446 cpl_image* img_src=NULL;
01447
01448 float* psrcdata=NULL;
01449 float* pbpdata=NULL;
01450
01451 int lz=0;
01452
01453 if ( NULL == darks )
01454 {
01455 xsh_msg_error("no input cube given!\n") ;
01456 return NULL ;
01457 }
01458
01459 if ( thresh_sigma_factor <= 0. )
01460 {
01461 xsh_msg_error("factor is smaller or equal zero!\n") ;
01462 return NULL ;
01463 }
01464 if ( low_threshold < 0. || high_threshold < 0. || (low_threshold + high_threshold) >= 100. )
01465 {
01466 xsh_msg_error("wrong reject percentage values!\n") ;
01467 return NULL ;
01468 }
01469
01470 lz=cpl_imagelist_get_size(darks);
01471 if ( lz < 1 )
01472 {
01473 xsh_msg_error("not enough dark frames given for good statistics!") ;
01474 return NULL ;
01475 }
01476 img_src=cpl_imagelist_get(darks,0);
01477
01478 lx = cpl_image_get_size_x(img_src) ;
01479 ly = cpl_image_get_size_y(img_src) ;
01480
01481 if (llx == -1) llx=1;
01482 if (lly == -1) lly=1;
01483
01484 if (urx == -1) urx=lx;
01485 if (ury == -1) ury=ly;
01486
01487 llx = (llx<1) ? 1 : llx;
01488 lly = (lly<1) ? 1 : lly;
01489
01490 urx = (urx>lx) ? lx : urx;
01491 ury = (ury>ly) ? lx : ury;
01492
01493
01494
01495 low_n = (int)(low_threshold/100. *(float)lz) ;
01496 high_n = (int)(high_threshold/100. *(float)lz) ;
01497
01498 if (NULL == (bp_map = cpl_image_new (lx, ly,CPL_TYPE_FLOAT) ) )
01499 {
01500 xsh_msg_error("could not allocate new memory!\n") ;
01501 return NULL ;
01502 }
01503 pbpdata=cpl_image_get_data(bp_map);
01504 if (NULL == (spectrum = (float*) cpl_calloc(lz, sizeof(float)) ) )
01505 {
01506 xsh_msg_error("could not allocate new memory!\n") ;
01507 return NULL ;
01508 }
01509
01510
01511 for ( row = 0 ; row < ly ; row++ ) {
01512
01513 for ( col = 0 ; col < lx ; col++ ) {
01514
01515 for ( z = 0 ; z < lz ; z++ ) {
01516 img_src=cpl_imagelist_get(darks,z);
01517 psrcdata=cpl_image_get_data(img_src);
01518 spectrum[z] = psrcdata[col+lx*row] ;
01519 }
01520 xsh_pixel_qsort(spectrum, lz) ;
01521 n = 0 ;
01522 pix_sum = 0.;
01523 sqr_sum = 0.;
01524 for ( i = low_n ; i < lz - high_n ; i++ ) {
01525 pix_sum += (double)spectrum[i] ;
01526 sqr_sum += ((double)spectrum[i]*(double)spectrum[i]) ;
01527 n++ ;
01528 }
01529
01530 pix_sum /= (double)n ;
01531 sqr_sum /= (double)n ;
01532
01533 pbpdata[col+lx*row] = (float)sqrt(sqr_sum - pix_sum*pix_sum) ;
01534 }
01535 }
01536
01537 cpl_free(spectrum) ;
01538 if ( NULL == (stats = xsh_image_stats_on_rectangle(bp_map,
01539 low_threshold,
01540 high_threshold,
01541 llx, lly,urx,ury)))
01542 {
01543 xsh_msg_error("could not get image statistics!\n") ;
01544 cpl_image_delete (bp_map) ;
01545 return NULL ;
01546 }
01547
01548
01549
01550 for ( row = 0 ; row < ly ; row++ ) {
01551 for ( col = 0 ; col < lx ; col++ ) {
01552 if (pbpdata[col+lx*row] >
01553 stats->cleanmean+thresh_sigma_factor*stats->cleanstdev ||
01554 pbpdata[col+lx*row] <
01555 stats->cleanmean-thresh_sigma_factor*stats->cleanstdev)
01556 {
01557 pbpdata[col+lx*row] = 0. ;
01558 }
01559 else
01560 {
01561 pbpdata[col+lx*row] = QFLAG_HOT_PIXEL ;
01562 }
01563 }
01564 }
01565
01566 cpl_free (stats) ;
01567 return bp_map ;
01568 }
01569
01570
01587 Stats * xsh_image_stats_on_rectangle ( cpl_image * im,
01588 float loReject,
01589 float hiReject,
01590 int llx,
01591 int lly,
01592 int urx,
01593 int ury )
01594 {
01595 Stats * retstats=NULL;
01596 int i=0 ;
01597 int row=0;
01598 int col=0;
01599 int n=0;
01600 int npix=0;
01601 int lo_n=0;
01602 int hi_n=0;
01603 double pix_sum=0;
01604 double sqr_sum=0;
01605 float * pix_array=NULL;
01606 int im_lx=0;
01607 int im_ly=0;
01608 float* pim=NULL;
01609
01610 if ( NULL == im )
01611 {
01612 xsh_msg_error("sorry, no input image given!") ;
01613 return NULL ;
01614 }
01615 if ( loReject+hiReject >= 100. )
01616 {
01617 xsh_msg_error("sorry, too much pixels rejected!") ;
01618 return NULL ;
01619 }
01620 if ( loReject < 0. || loReject >= 100. ||
01621 hiReject < 0. || hiReject >= 100. )
01622 {
01623 xsh_msg_error("sorry, negative reject values!") ;
01624 return NULL ;
01625 }
01626
01627 im_lx=cpl_image_get_size_x(im);
01628 im_ly=cpl_image_get_size_y(im);
01629 if ( llx < 0 || lly < 0 ||
01630 urx < 0 || ury < 0 ||
01631 llx > im_lx || lly > im_ly ||
01632 urx > im_lx || ury > im_ly ||
01633 ury <= lly || urx <= llx )
01634 {
01635 xsh_msg_error("sorry, wrong pixel coordinates of rectangle!") ;
01636 return NULL ;
01637 }
01638
01639
01640 retstats = (Stats*) cpl_calloc(1, sizeof(Stats)) ;
01641 npix = (urx - llx + 1) * (ury - lly + 1) ;
01642 pix_array = (float*) cpl_calloc ( npix, sizeof(float) ) ;
01643
01644
01645
01646
01647 n = 0 ;
01648 pim = cpl_image_get_data_float(im);
01649 for ( row = lly ; row <= ury ; row++ )
01650 {
01651 for ( col = llx ; col <= urx ; col++ )
01652 {
01653 if ( !isnan(pim[col + row*im_lx]) )
01654 {
01655 pix_array[n] = pim[col + row*im_lx] ;
01656 n++ ;
01657 }
01658 }
01659 }
01660
01661 npix = n;
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672 if ( FLT_MAX == (retstats->cleanmean = xsh_clean_mean(pix_array,
01673 npix, loReject, hiReject)) )
01674 {
01675 xsh_msg_error("xsh_clean_mean() did not work!") ;
01676 cpl_free(retstats) ;
01677 cpl_free(pix_array) ;
01678 return NULL ;
01679 }
01680
01681
01682
01683 lo_n = (int) (loReject / 100. * (float)npix) ;
01684 hi_n = (int) (hiReject / 100. * (float)npix) ;
01685 pix_sum = 0. ;
01686 sqr_sum = 0. ;
01687 n = 0 ;
01688 for ( i = lo_n ; i <= npix - hi_n ; i++ )
01689 {
01690 pix_sum += (double)pix_array[i] ;
01691 sqr_sum += ((double)pix_array[i] * (double)pix_array[i]) ;
01692 n++ ;
01693 }
01694
01695 if ( n == 0 )
01696 {
01697 xsh_msg_error("number of clean pixels is zero!") ;
01698 cpl_free(retstats) ;
01699 cpl_free(pix_array) ;
01700 return NULL ;
01701 }
01702 retstats -> npix = n ;
01703 pix_sum /= (double) n ;
01704 sqr_sum /= (double) n ;
01705 retstats -> cleanstdev = (float)sqrt(sqr_sum - pix_sum * pix_sum) ;
01706 cpl_free (pix_array) ;
01707 return retstats ;
01708 }
01709
01710 #define PIX_SWAP(a,b) { pixelvalue temp=(a);(a)=(b);(b)=temp; }
01711 #define PIX_STACK_SIZE 50
01712
01724 void
01725 xsh_pixel_qsort(pixelvalue *pix_arr, int npix)
01726 {
01727 int i,
01728 ir,
01729 j,
01730 k,
01731 l;
01732 int i_stack[PIX_STACK_SIZE*sizeof(pixelvalue)] ;
01733 int j_stack ;
01734 pixelvalue a ;
01735
01736 ir = npix ;
01737 l = 1 ;
01738 j_stack = 0 ;
01739 for (;;) {
01740 if (ir-l < 7) {
01741 for (j=l+1 ; j<=ir ; j++) {
01742 a = pix_arr[j-1];
01743 for (i=j-1 ; i>=1 ; i--) {
01744 if (pix_arr[i-1] <= a) break;
01745 pix_arr[i] = pix_arr[i-1];
01746 }
01747 pix_arr[i] = a;
01748 }
01749 if (j_stack == 0) break;
01750 ir = i_stack[j_stack-- -1];
01751 l = i_stack[j_stack-- -1];
01752 } else {
01753 k = (l+ir) >> 1;
01754 PIX_SWAP(pix_arr[k-1], pix_arr[l])
01755 if (pix_arr[l] > pix_arr[ir-1]) {
01756 PIX_SWAP(pix_arr[l], pix_arr[ir-1])
01757 }
01758 if (pix_arr[l-1] > pix_arr[ir-1]) {
01759 PIX_SWAP(pix_arr[l-1], pix_arr[ir-1])
01760 }
01761 if (pix_arr[l] > pix_arr[l-1]) {
01762 PIX_SWAP(pix_arr[l], pix_arr[l-1])
01763 }
01764 i = l+1;
01765 j = ir;
01766 a = pix_arr[l-1];
01767 for (;;) {
01768 do i++; while (pix_arr[i-1] < a);
01769 do j--; while (pix_arr[j-1] > a);
01770 if (j < i) break;
01771 PIX_SWAP(pix_arr[i-1], pix_arr[j-1]);
01772 }
01773 pix_arr[l-1] = pix_arr[j-1];
01774 pix_arr[j-1] = a;
01775 j_stack += 2;
01776 if (j_stack > PIX_STACK_SIZE) {
01777 xsh_msg_error("stack too small : aborting");
01778 exit(-2001) ;
01779 }
01780 if (ir-i+1 >= j-l) {
01781 i_stack[j_stack-1] = ir;
01782 i_stack[j_stack-2] = i;
01783 ir = j-1;
01784 } else {
01785 i_stack[j_stack-1] = j-1;
01786 i_stack[j_stack-2] = l;
01787 l = i;
01788 }
01789 }
01790 }
01791 }
01792 #undef PIX_STACK_SIZE
01793 #undef PIX_SWAP
01794
01811 float xsh_clean_mean( float * array,
01812 int n_elements,
01813 float throwaway_low,
01814 float throwaway_high )
01815 {
01816 int i, n ;
01817 int lo_n, hi_n ;
01818 float sum ;
01819
01820 if ( array == NULL )
01821 {
01822 xsh_msg_error(" no array given in xsh_clean_mean!") ;
01823 return FLT_MAX ;
01824 }
01825
01826 if ( n_elements <= 0 )
01827 {
01828 xsh_msg_error("wrong number of elements given") ;
01829 return FLT_MAX ;
01830 }
01831
01832 if ( throwaway_low < 0. || throwaway_high < 0. ||
01833 throwaway_low + throwaway_high >= 100. )
01834 {
01835 xsh_msg_error("wrong throw away percentage given!") ;
01836 return FLT_MAX ;
01837 }
01838
01839 lo_n = (int) (throwaway_low * (float)n_elements / 100.) ;
01840 hi_n = (int) (throwaway_high * (float)n_elements / 100.) ;
01841
01842
01843 xsh_pixel_qsort( array, n_elements ) ;
01844
01845 n = 0 ;
01846 sum = 0. ;
01847 for ( i = lo_n ; i < n_elements - hi_n ; i++ )
01848 {
01849 if ( !isnan(array[i]) )
01850 {
01851 sum += array[i] ;
01852 n++ ;
01853 }
01854 }
01855 if ( n == 0 )
01856 {
01857 return FLAG ;
01858 }
01859 else
01860 {
01861 return sum/(float)n ;
01862 }
01863 }
01864
01865
01879
01880
01881 cpl_image *
01882 xsh_image_smooth_fft(cpl_image * inp, const int fx, const int fy)
01883 {
01884
01885 int sx=0;
01886 int sy=0;
01887
01888 cpl_image* out=NULL;
01889 cpl_image* im_re=NULL;
01890 cpl_image* im_im=NULL;
01891 cpl_image* ifft_re=NULL;
01892 cpl_image* ifft_im=NULL;
01893 cpl_image* filter=NULL;
01894
01895
01896 cknull_msg(inp,"Null in put image, exit");
01897 check(im_re = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
01898 check(im_im = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
01899
01900
01901 check(cpl_image_fft(im_re,im_im,CPL_FFT_DEFAULT));
01902 check(sx=cpl_image_get_size_x(inp));
01903 check(sy=cpl_image_get_size_y(inp));
01904
01905
01906
01907 check(filter = xsh_gen_lowpass(sx,sy,fx,fy));
01908
01909
01910 cpl_image_multiply(im_re,filter);
01911 cpl_image_multiply(im_im,filter);
01912
01913 xsh_free_image(&filter);
01914
01915 check(ifft_re = cpl_image_duplicate(im_re));
01916 check(ifft_im = cpl_image_duplicate(im_im));
01917
01918 xsh_free_image(&im_re);
01919 xsh_free_image(&im_im);
01920
01921
01922 check(cpl_image_fft(ifft_re,ifft_im,CPL_FFT_INVERSE));
01923 check(out = cpl_image_cast(ifft_re, CPL_TYPE_FLOAT));
01924
01925 cleanup:
01926
01927 xsh_free_image(&ifft_re);
01928 xsh_free_image(&ifft_im);
01929 xsh_free_image(&filter);
01930 xsh_free_image(&im_re);
01931 xsh_free_image(&im_im);
01932
01933 if(cpl_error_get_code() != CPL_ERROR_NONE) {
01934 return NULL;
01935 } else {
01936 return out;
01937 }
01938
01939 }
01940
01941
01957
01958 static cpl_image *
01959 xsh_gen_lowpass(const int xs,
01960 const int ys,
01961 const double sigma_x,
01962 const double sigma_y)
01963 {
01964
01965 int i= 0.0;
01966 int j= 0.0;
01967 int hlx= 0.0;
01968 int hly = 0.0;
01969 double x= 0.0;
01970 double y= 0.0;
01971 double gaussval= 0.0;
01972 double inv_sigma_x=1./sigma_x;
01973 double inv_sigma_y=1./sigma_y;
01974
01975 float *data;
01976
01977 cpl_image *lowpass_image=NULL;
01978 int err_no=0;
01979
01980
01981 lowpass_image = cpl_image_new (xs, ys, CPL_TYPE_FLOAT);
01982 if (lowpass_image == NULL) {
01983 xsh_msg_error("Cannot generate lowpass filter <%s>",
01984 cpl_error_get_message());
01985 return NULL;
01986 }
01987
01988 hlx = xs/2;
01989 hly = ys/2;
01990
01991 data = cpl_image_get_data_float(lowpass_image);
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003 data[0] = 1.0;
02004
02005
02006 for (i=1 ; i<=hlx ; i++) {
02007 x = i * inv_sigma_x;
02008 gaussval = exp(-0.5*x*x);
02009 data[i] = gaussval;
02010 data[xs-i] = gaussval;
02011 }
02012
02013 for (j=1; j<=hly ; j++) {
02014 y = j * inv_sigma_y;
02015
02016 data[j*xs] = exp(-0.5*y*y);
02017 data[(ys-j)*xs] = exp(-0.5*y*y);
02018
02019 for (i=1 ; i<=hlx ; i++) {
02020
02021 x = i * inv_sigma_x;
02022 gaussval = exp (-0.5*(x*x+y*y));
02023 data[j*xs+i] = gaussval;
02024 data[(j+1)*xs-i] = gaussval;
02025 data[(ys-j)*xs+i] = gaussval;
02026 data[(ys+1-j)*xs-i] = gaussval;
02027
02028 }
02029 }
02030
02031
02032
02033
02034
02035 if(err_no != 0)
02036 err_no = 0;
02037
02038 return lowpass_image;
02039 }
02040
02041
02042
02056
02057
02058 cpl_image *
02059 xsh_image_smooth_mean_y(cpl_image * inp, const int r)
02060 {
02061
02062
02063 double* pinp = NULL;
02064 double* pout = NULL;
02065 int sx = 0;
02066 int sy = 0;
02067 int i = 0;
02068 int j = 0;
02069 int k = 0;
02070
02071 cpl_image* out=NULL;
02072
02073 XSH_ASSURE_NOT_NULL( inp);
02074 check( out = cpl_image_cast( inp, CPL_TYPE_DOUBLE));
02075 check(sx = cpl_image_get_size_x(inp));
02076 check(sy = cpl_image_get_size_y(inp));
02077 check(pinp = cpl_image_get_data_double(inp));
02078 check(pout = cpl_image_get_data_double(out));
02079 for( j=r; j<sy-r; j++) {
02080 for( i=0; i<sx; i++) {
02081 for( k=-r; k<r; k++) {
02082 pout[j*sx+i] += pinp[(j+k)*sx+i];
02083 }
02084 pout[j*sx+i]/=2*r;
02085 }
02086 }
02087
02088 cleanup:
02089 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02090 xsh_free_image( &out);
02091 }
02092 return out;
02093 }
02094
02095
02096
02110
02111
02112 cpl_image *
02113 xsh_image_smooth_median_y(cpl_image * inp, const int r)
02114 {
02115
02116
02117 double* pout=NULL;
02118 int sx=0;
02119 int sy=0;
02120 int i=0;
02121 int j=0;
02122
02123 cpl_image* out=NULL;
02124
02125
02126 cknull_msg(inp,"Null in put image, exit");
02127
02128 check(out=cpl_image_cast(inp,CPL_TYPE_DOUBLE));
02129 check(sx=cpl_image_get_size_x(inp));
02130 check(sy=cpl_image_get_size_y(inp));
02131 check(pout=cpl_image_get_data_double(out));
02132
02133 for(j=r+1;j<sy-r;j++) {
02134 for(i=1;i<sx;i++) {
02135 pout[j*sx+i]=cpl_image_get_median_window(inp,i,j,i,j+r);
02136 }
02137 }
02138
02139 cleanup:
02140
02141 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02142 return NULL;
02143 } else {
02144 return out;
02145
02146 }
02147
02148 }
02149
02150
02151
02165
02166
02167 cpl_image *
02168 xsh_image_smooth_mean_x( cpl_image * inp, const int r)
02169 {
02170
02171 double* pinp=NULL;
02172 double* pout=NULL;
02173 int sx=0;
02174 int sy=0;
02175 int i=0;
02176 int j=0;
02177 int k=0;
02178
02179 cpl_image* out=NULL;
02180
02181
02182 XSH_ASSURE_NOT_NULL( inp);
02183 check( out = cpl_image_cast( inp, CPL_TYPE_DOUBLE));
02184 check( sx=cpl_image_get_size_x(inp));
02185 check( sy=cpl_image_get_size_y(inp));
02186 check( pinp=cpl_image_get_data_double(inp));
02187 check( pout=cpl_image_get_data_double(out));
02188 for(j=0;j<sy;j++) {
02189 for(i=r;i<sx-r;i++) {
02190 for(k=-r;k<r;k++) {
02191 pout[j*sx+i]+=pinp[j*sx+i+k];
02192 }
02193 pout[j*sx+i]/=2*r;
02194 }
02195 }
02196
02197 cleanup:
02198
02199 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02200 return NULL;
02201 } else {
02202 return out;
02203
02204 }
02205
02206 }
02207
02208
02209
02223
02224
02225 cpl_image *
02226 xsh_image_smooth_median_x(cpl_image * inp, const int r)
02227 {
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237 float* pout=NULL;
02238 int sx=0;
02239 int sy=0;
02240 int i=0;
02241 int j=0;
02242
02243 cpl_image* out=NULL;
02244
02245
02246 cknull_msg(inp,"Null in put image, exit");
02247
02248 check(out=cpl_image_cast(inp,CPL_TYPE_FLOAT));
02249 check(sx=cpl_image_get_size_x(inp));
02250 check(sy=cpl_image_get_size_y(inp));
02251 check(pout=cpl_image_get_data_float(out));
02252
02253 for(j=1;j<sy;j++) {
02254 for(i=r+1;i<sx-r;i++) {
02255 pout[j*sx+i]=cpl_image_get_median_window(inp,i,j,i+r,j);
02256 }
02257 }
02258
02259 cleanup:
02260
02261 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02262 return NULL;
02263 } else {
02264 return out;
02265
02266 }
02267
02268 }
02269
02270
02271
02272
02286
02287
02288 cpl_image *
02289 xsh_image_smooth_median_xy(cpl_image * inp, const int r)
02290 {
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300 double* pout=NULL;
02301 int sx=0;
02302 int sy=0;
02303 int i=0;
02304 int j=0;
02305
02306 cpl_image* out=NULL;
02307
02308
02309 cknull_msg(inp,"Null in put image, exit");
02310
02311 check(out=cpl_image_cast(inp,CPL_TYPE_DOUBLE));
02312 check(sx=cpl_image_get_size_x(inp));
02313 check(sy=cpl_image_get_size_y(inp));
02314 check(pout=cpl_image_get_data_double(out));
02315
02316 for(j=r+1;j<sy-r;j++) {
02317 for(i=r+1;i<sx-r;i++) {
02318 pout[j*sx+i]=cpl_image_get_median_window(inp,i,j,i+r,j+r);
02319 }
02320 }
02321
02322 cleanup:
02323
02324 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02325 return NULL;
02326 } else {
02327 return out;
02328
02329 }
02330
02331 }
02332
02333
02343
02344
02345 cpl_error_code
02346 xsh_image_clean_badpixel(cpl_frame* in)
02347 {
02348
02349
02350 cpl_image* ima=NULL;
02351 cpl_image* err=NULL;
02352 cpl_image* qua=NULL;
02353 cpl_propertylist* hima=NULL;
02354 cpl_propertylist* herr=NULL;
02355 cpl_propertylist* hqua=NULL;
02356
02357
02358 const char* name=NULL;
02359 double* pima=NULL;
02360 int* pqua=NULL;
02361 int nx=0;
02362 int ny=0;
02363 int i=0;
02364 int j=0;
02365 int rx=5;
02366 int ry=5;
02367 int ip=0;
02368 int jp=0;
02369
02370 name=cpl_frame_get_filename(in);
02371 hima=cpl_propertylist_load(name,0);
02372 herr=cpl_propertylist_load(name,1);
02373 hqua=cpl_propertylist_load(name,2);
02374 ima=cpl_image_load(name,CPL_TYPE_DOUBLE,0,0);
02375 err=cpl_image_load(name,CPL_TYPE_DOUBLE,0,1);
02376 qua=cpl_image_load(name,CPL_TYPE_INT,0,2);
02377
02378 nx=cpl_image_get_size_x(ima);
02379 ny=cpl_image_get_size_y(ima);
02380
02381 pima=cpl_image_get_data_double(ima);
02382 pqua=cpl_image_get_data_int(qua);
02383
02384 for(j=ry;j<ny-ry;j++) {
02385 jp=j++;
02386 for(i=rx;i<nx-rx;i++) {
02387 ip=i++;
02388 if(pqua[i+j*nx]!=0) {
02389 pima[i+j*nx]=cpl_image_get_median_window(ima,i-rx,j-ry,i+rx,j+ry);
02390 }
02391 }
02392 }
02393 check(cpl_image_save(ima,name,XSH_PRE_DATA_BPP,hima,CPL_IO_DEFAULT));
02394 check(cpl_image_save(err,name,XSH_PRE_ERRS_BPP,herr,CPL_IO_EXTEND));
02395 check(cpl_image_save(qua,name,XSH_PRE_QUAL_BPP,hqua,CPL_IO_EXTEND));
02396
02397 cleanup:
02398 xsh_free_image(&ima);
02399 xsh_free_image(&err);
02400 xsh_free_image(&qua);
02401 xsh_free_propertylist(&hima);
02402 xsh_free_propertylist(&herr);
02403 xsh_free_propertylist(&hqua);
02404
02405 return cpl_error_get_code();
02406
02407 }
02408
02409
02410
02424
02425
02426 double
02427 xsh_image_fit_gaussian_max_pos_x_window(const cpl_image* ima,
02428 const int llx,
02429 const int urx,
02430 const int ypos)
02431 {
02432
02433
02434 XSH_GAUSSIAN_FIT fit_res;
02435 int i=0;
02436 int nelem=0;
02437 int ix=0;
02438 int iy=ypos;
02439
02440 double dy=0;
02441 cpl_vector* pix_pos=NULL;
02442 cpl_vector* pix_val=NULL;
02443 double x_centroid=0;
02444
02445
02446 nelem=urx-llx+1;
02447 check( pix_pos = cpl_vector_new( nelem ) ) ;
02448 check( pix_val = cpl_vector_new( nelem ) ) ;
02449
02450
02451 for( i = 0, ix = llx ; ix <= urx ; ix++, i++, dy += 1. ) {
02452 int rej ;
02453 double value ;
02454
02455 cpl_error_reset() ;
02456 value = cpl_image_get(ima , ix, iy, &rej ) ;
02457 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
02458 xsh_msg_dbg_high( " *** X,Y out of range %d,%d", ix, iy ) ;
02459 cpl_error_reset() ;
02460 continue ;
02461 }
02462 cpl_vector_set( pix_val, i, value ) ;
02463 cpl_vector_set( pix_pos, i, dy ) ;
02464 }
02465
02466 xsh_vector_fit_gaussian( pix_pos, pix_val, &fit_res );
02467 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
02468 xsh_msg_dbg_high( " *** X,Y out of range %d,%d", ix, iy ) ;
02469 cpl_error_reset() ;
02470 x_centroid=cpl_image_get_centroid_x_window(ima,llx,ypos,urx,ypos);
02471
02472
02473 } else {
02474
02475 x_centroid=llx+fit_res.peakpos;
02476 }
02477
02478 cleanup:
02479 xsh_free_vector(&pix_pos);
02480 xsh_free_vector(&pix_val);
02481
02482 return x_centroid;
02483 }
02484
02485
02499
02500
02501 static double
02502 xsh_image_fit_gaussian_max_pos_y_window(const cpl_image* ima,
02503 const int lly,
02504 const int ury,
02505 const int xpos)
02506 {
02507
02508
02509 XSH_GAUSSIAN_FIT fit_res;
02510 int j=0;
02511 int nelem=0;
02512 int jy=0;
02513 int jx=xpos;
02514
02515 double dy=0;
02516 cpl_vector* pix_pos=NULL;
02517 cpl_vector* pix_val=NULL;
02518 double y_centroid=0;
02519
02520
02521 nelem=ury-lly+1;
02522 check( pix_pos = cpl_vector_new( nelem ) ) ;
02523 check( pix_val = cpl_vector_new( nelem ) ) ;
02524
02525
02526 for( j = 0, jy = lly ; jy <= ury ; jy++, j++, dy += 1. ) {
02527 int rej ;
02528 double value ;
02529
02530 cpl_error_reset() ;
02531 value = cpl_image_get(ima , jx, jy, &rej ) ;
02532 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
02533 xsh_msg_dbg_high( " *** X,Y out of range %d,%d", jx, jy ) ;
02534 cpl_error_reset() ;
02535 continue ;
02536 }
02537 cpl_vector_set( pix_val, j, value ) ;
02538 cpl_vector_set( pix_pos, j, dy ) ;
02539 }
02540
02541 xsh_vector_fit_gaussian( pix_pos, pix_val, &fit_res );
02542 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
02543 xsh_msg_dbg_high( " *** X,Y out of range %d,%d", jx, jy ) ;
02544 cpl_error_reset() ;
02545 y_centroid=cpl_image_get_centroid_y_window(ima,xpos,lly,xpos,ury);
02546
02547
02548 } else {
02549
02550 y_centroid=lly+fit_res.peakpos;
02551 }
02552
02553 cleanup:
02554 xsh_free_vector(&pix_pos);
02555 xsh_free_vector(&pix_val);
02556
02557 return y_centroid;
02558 }
02559
02560
02561
02578
02579
02580 static cpl_table*
02581 xsh_image_qc_trace_window(cpl_image* data_ima,cpl_propertylist* head,
02582 const int hsize, const int method)
02583 {
02584
02585 cpl_table* table=NULL;
02586 int i=0;
02587
02588 int naxis1=0;
02589 int naxis2=0;
02590 int mx=0;
02591 int my=0;
02592
02593 int lly=0;
02594 int ury=0;
02595 int llx=0;
02596 int* px=NULL;
02597 double* pcy=NULL;
02598 double* pwav=NULL;
02599 double crval1=0;
02600 double cdelt1=0;
02601
02602 crval1=xsh_pfits_get_crval1(head);
02603 cdelt1=xsh_pfits_get_cdelt1(head);
02604
02605 naxis1=cpl_image_get_size_x(data_ima);
02606 naxis2=cpl_image_get_size_y(data_ima);
02607
02608 table=cpl_table_new(naxis1);
02609 cpl_table_new_column(table,"X",CPL_TYPE_INT);
02610 cpl_table_new_column(table,"WAVELENGTH",CPL_TYPE_DOUBLE);
02611 cpl_table_new_column(table,"POS",CPL_TYPE_DOUBLE);
02612
02613 cpl_table_fill_column_window_int(table,"X",0,naxis1,0);
02614 cpl_table_fill_column_window_double(table,"WAVELENGTH",0,naxis1,0.);
02615 cpl_table_fill_column_window_double(table,"POS",0,naxis1,0.);
02616
02617 px=cpl_table_get_data_int(table,"X");
02618 pwav=cpl_table_get_data_double(table,"WAVELENGTH");
02619 pcy=cpl_table_get_data_double(table,"POS");
02620
02621 for(i=0;i<naxis1;i++) {
02622 px[i]=i;
02623 pwav[i]=crval1+cdelt1*i;
02624 llx=i+1;
02625 check(cpl_image_get_maxpos_window(data_ima,llx,1,llx,naxis2,&mx,&my));
02626 lly=(my-hsize>0) ? my-hsize:1;
02627 ury=(my+hsize<=naxis2) ? my+hsize:naxis2;
02628 if(method == 0 ) {
02629 pcy[i]=xsh_image_fit_gaussian_max_pos_y_window(data_ima,lly,ury,llx);
02630 } else {
02631 check(pcy[i]=cpl_image_get_centroid_y_window(data_ima,llx,lly,llx,ury));
02632 }
02633 }
02634
02635 cleanup:
02636
02637 return table;
02638 }
02639
02658
02659
02660 cpl_frame*
02661 xsh_frame_image_qc_trace_window(cpl_frame* frm_ima,xsh_instrument* instrument,
02662 const char* suffix,const int hsize, const int method)
02663 {
02664
02665 cpl_frame* result=NULL;
02666 cpl_table* table=NULL;
02667 cpl_image* data_ima=NULL;
02668 const char* name=NULL;
02669
02670 cpl_propertylist* plist=NULL;
02671 char fname[80];
02672 char tag[50];
02673
02674 check(name=cpl_frame_get_filename(frm_ima));
02675
02676 check(data_ima=cpl_image_load(name,CPL_TYPE_DOUBLE,0,0));
02677 plist=cpl_propertylist_load(name,0);
02678
02679
02680 check(table=xsh_image_qc_trace_window(data_ima,plist,hsize,method));
02681
02682 sprintf(tag,"MERGE3D_TRACE_OBJ_%s_%s",
02683 xsh_instrument_arm_tostring( instrument),suffix);
02684 sprintf(fname,"%s.fits",tag);
02685
02686 check(cpl_table_save(table,plist,NULL,fname,CPL_IO_DEFAULT));
02687
02688 result=xsh_frame_product(fname,tag,CPL_FRAME_TYPE_TABLE,
02689 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
02690
02691 cleanup:
02692
02693 xsh_free_propertylist(&plist);
02694 xsh_free_table(&table);
02695 xsh_free_image(&data_ima);
02696
02697 return result;
02698 }
02699
02718
02719
02720 cpl_frame*
02721 xsh_frame_image_ext_qc_trace_window(cpl_frame* frm_ima,
02722 xsh_instrument* instrument,
02723 const char* suffix,
02724 const int hsize,
02725 const int method)
02726 {
02727
02728 cpl_frame* result=NULL;
02729 cpl_table* table=NULL;
02730 cpl_table* table_tot=NULL;
02731
02732 cpl_image* data_ima=NULL;
02733 const char* name=NULL;
02734
02735 cpl_propertylist* phead=NULL;
02736 cpl_propertylist* xhead=NULL;
02737
02738 char fname[80];
02739 char tag[50];
02740 int nbext=0;
02741 int k=0;
02742 int nrow=0;
02743 xsh_msg("Trace object position");
02744 check(name=cpl_frame_get_filename(frm_ima));
02745 nbext=cpl_frame_get_nextensions( frm_ima);
02746
02747 table_tot=cpl_table_new(0);
02748 phead=cpl_propertylist_load(name,0);
02749 for(k=0;k<nbext;k+=3){
02750 nrow=cpl_table_get_nrow(table_tot);
02751
02752 check(data_ima=cpl_image_load(name,CPL_TYPE_DOUBLE,0,k));
02753 xhead=cpl_propertylist_load(name,k);
02754
02755 check(table=xsh_image_qc_trace_window(data_ima,xhead,hsize,method));
02756 if(k==0) check(cpl_table_copy_structure(table_tot,table));
02757 cpl_table_insert(table_tot,table,nrow);
02758 xsh_free_propertylist(&xhead);
02759 xsh_free_table(&table);
02760 xsh_free_image(&data_ima);
02761 }
02762 sprintf(tag,"OBJ_POS_ORD_%s_%s",
02763 xsh_instrument_arm_tostring( instrument),suffix);
02764 sprintf(fname,"%s.fits",tag);
02765
02766 check(cpl_table_save(table_tot,phead,NULL,fname,CPL_IO_DEFAULT));
02767
02768 result=xsh_frame_product(fname,tag,CPL_FRAME_TYPE_TABLE,
02769 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
02770
02771 cleanup:
02772
02773 xsh_free_propertylist(&phead);
02774 xsh_free_propertylist(&xhead);
02775 xsh_free_table(&table);
02776 xsh_free_table(&table_tot);
02777 xsh_free_image(&data_ima);
02778
02779 return result;
02780 }
02781
02782
02783
02784 static cpl_error_code
02785 xsh_util_compute_qc_residuals(cpl_table* table,
02786 xsh_instrument* instrument,
02787 cpl_propertylist* plist)
02788 {
02789 cpl_table* qc_table=NULL;
02790 double res_min=0;
02791 double res_max=0;
02792 double res_med=0;
02793 double res_avg=0;
02794 double res_rms=0;
02795 double wmin=0;
02796 double wmax=0;
02797 int nsel=0;
02798
02799 if( xsh_instrument_get_arm(instrument) == XSH_ARM_UVB) {
02800 wmin=350;
02801 wmax=540;
02802 } else if( xsh_instrument_get_arm(instrument) == XSH_ARM_VIS){
02803 wmin=580;
02804 wmax=950;
02805 } else {
02806 wmin=1000;
02807 wmax=2200;
02808 }
02809
02810 check(nsel=cpl_table_and_selected_double(table,"WAVELENGTH",CPL_GREATER_THAN,wmin));
02811 check(nsel=cpl_table_and_selected_double(table,"WAVELENGTH",CPL_LESS_THAN,wmax));
02812 check(qc_table=cpl_table_extract_selected(table));
02813 check(cpl_table_select_all(table));
02814
02815
02816 check(res_min=cpl_table_get_column_min(qc_table,"RES12"));
02817 check(res_max=cpl_table_get_column_max(qc_table,"RES12"));
02818 check(res_avg=cpl_table_get_column_mean(qc_table,"RES12"));
02819 check(res_med=cpl_table_get_column_median(qc_table,"RES12"));
02820 check(res_rms=cpl_table_get_column_stdev(qc_table,"RES12"));
02821
02822 cpl_propertylist_append_double(plist,XSH_QC_TRACE12_MIN,res_min);
02823 cpl_propertylist_set_comment(plist,XSH_QC_TRACE12_MIN,"Minimum residuals");
02824 cpl_propertylist_append_double(plist,XSH_QC_TRACE12_MAX,res_max);
02825 cpl_propertylist_set_comment(plist,XSH_QC_TRACE12_MAX,"Maximum residuals");
02826 cpl_propertylist_append_double(plist,XSH_QC_TRACE12_AVG,res_avg);
02827 cpl_propertylist_set_comment(plist,XSH_QC_TRACE12_AVG,"Mean residuals");
02828
02829 cpl_propertylist_append_double(plist,XSH_QC_TRACE12_MED,res_med);
02830 cpl_propertylist_set_comment(plist,XSH_QC_TRACE12_MED,"Median residuals");
02831 cpl_propertylist_append_double(plist,XSH_QC_TRACE12_RMS,res_rms);
02832 cpl_propertylist_set_comment(plist,XSH_QC_TRACE12_RMS,"Stdev residuals");
02833
02834 res_min=cpl_table_get_column_min(qc_table,"RES32");
02835 res_max=cpl_table_get_column_max(qc_table,"RES32");
02836 res_avg=cpl_table_get_column_mean(qc_table,"RES32");
02837 res_med=cpl_table_get_column_median(qc_table,"RES32");
02838 res_rms=cpl_table_get_column_stdev(qc_table,"RES32");
02839
02840 cpl_propertylist_append_double(plist,XSH_QC_TRACE32_MIN,res_min);
02841 cpl_propertylist_set_comment(plist,XSH_QC_TRACE32_MIN,"Minimum residuals");
02842 cpl_propertylist_append_double(plist,XSH_QC_TRACE32_MAX,res_max);
02843 cpl_propertylist_set_comment(plist,XSH_QC_TRACE32_MAX,"Maximum residuals");
02844 cpl_propertylist_append_double(plist,XSH_QC_TRACE32_AVG,res_avg);
02845 cpl_propertylist_set_comment(plist,XSH_QC_TRACE32_AVG,"Mean residuals");
02846
02847 cpl_propertylist_append_double(plist,XSH_QC_TRACE32_MED,res_med);
02848 cpl_propertylist_set_comment(plist,XSH_QC_TRACE32_MED,"Median residuals");
02849 cpl_propertylist_append_double(plist,XSH_QC_TRACE32_RMS,res_rms);
02850 cpl_propertylist_set_comment(plist,XSH_QC_TRACE32_RMS,"Stdev residuals");
02851
02852 res_min=cpl_table_get_column_min(qc_table,"RES13");
02853 res_max=cpl_table_get_column_max(qc_table,"RES13");
02854 res_avg=cpl_table_get_column_mean(qc_table,"RES13");
02855 res_med=cpl_table_get_column_median(qc_table,"RES13");
02856 res_rms=cpl_table_get_column_stdev(qc_table,"RES13");
02857
02858 cpl_propertylist_append_double(plist,XSH_QC_TRACE13_MIN,res_min);
02859 cpl_propertylist_set_comment(plist,XSH_QC_TRACE13_MIN,"Minimum residuals");
02860 cpl_propertylist_append_double(plist,XSH_QC_TRACE13_MAX,res_max);
02861 cpl_propertylist_set_comment(plist,XSH_QC_TRACE13_MAX,"Maximum residuals");
02862 cpl_propertylist_append_double(plist,XSH_QC_TRACE13_AVG,res_avg);
02863 cpl_propertylist_set_comment(plist,XSH_QC_TRACE13_AVG,"Mean residuals");
02864
02865 cpl_propertylist_append_double(plist,XSH_QC_TRACE13_MED,res_med);
02866 cpl_propertylist_set_comment(plist,XSH_QC_TRACE13_MED,"Median residuals");
02867 cpl_propertylist_append_double(plist,XSH_QC_TRACE13_RMS,res_rms);
02868 cpl_propertylist_set_comment(plist,XSH_QC_TRACE13_RMS,"Stdev residuals");
02869
02870 cleanup:
02871 xsh_free_table(&qc_table);
02872 return cpl_error_get_code();
02873
02874 }
02875
02876
02903
02904
02905
02906 cpl_frame*
02907 xsh_cube_qc_trace_window(cpl_frame* frm_cube,xsh_instrument* instrument,
02908 const char* suffix,const char* rec_prefix,
02909 const int win_min, const int win_max,
02910 const int hsize,
02911 const int method,const int compute_qc)
02912 {
02913 cpl_frame* result=NULL;
02914 cpl_table* table=NULL;
02915 cpl_image* data_ima=NULL;
02916 cpl_image* errs_ima=NULL;
02917 cpl_imagelist* data_iml=NULL;
02918 cpl_imagelist* errs_iml=NULL;
02919 cpl_imagelist* swap1=NULL;
02920 cpl_imagelist* swap2=NULL;
02921 cpl_imagelist* data_swap=NULL;
02922 cpl_imagelist* errs_swap=NULL;
02923
02924 const char* name=NULL;
02925
02926 int k=0;
02927
02928 int j=0;
02929
02930 int naxis1=0;
02931 int naxis2=0;
02932 int naxis3=0;
02933
02934
02935 int mx=0;
02936 int my=0;
02937 double cx=0;
02938
02939
02940
02941 int llx=0;
02942 int urx=0;
02943
02944 double* pcx1=NULL;
02945 double* pcx2=NULL;
02946 double* pcx3=NULL;
02947 double* pwav=NULL;
02948 double crval3=0;
02949 double cdelt3=0;
02950 cpl_propertylist* plist=NULL;
02951 char fname[80];
02952 char tag[80];
02953
02954 check(name=cpl_frame_get_filename(frm_cube));
02955
02956
02957 check(data_iml=cpl_imagelist_load(name,CPL_TYPE_DOUBLE,0));
02958 plist=cpl_propertylist_load(name,0);
02959 crval3=xsh_pfits_get_crval3(plist);
02960 cdelt3=xsh_pfits_get_cdelt3(plist);
02961
02962 swap1=cpl_imagelist_swap_axis_create(data_iml,CPL_SWAP_AXIS_XZ);
02963 xsh_free_imagelist(&data_iml);
02964 swap2=cpl_imagelist_swap_axis_create(swap1,CPL_SWAP_AXIS_YZ);
02965 xsh_free_imagelist(&swap1);
02966 data_swap=cpl_imagelist_swap_axis_create(swap2,CPL_SWAP_AXIS_XZ);
02967 xsh_free_imagelist(&swap2);
02968
02969
02970 check(errs_iml=cpl_imagelist_load(name,CPL_TYPE_DOUBLE,0));
02971
02972 swap1=cpl_imagelist_swap_axis_create(errs_iml,CPL_SWAP_AXIS_XZ);
02973 xsh_free_imagelist(&data_iml);
02974 swap2=cpl_imagelist_swap_axis_create(swap1,CPL_SWAP_AXIS_YZ);
02975 xsh_free_imagelist(&swap1);
02976 errs_swap=cpl_imagelist_swap_axis_create(swap2,CPL_SWAP_AXIS_XZ);
02977 xsh_free_imagelist(&swap2);
02978
02979
02980 check(naxis3=cpl_imagelist_get_size(data_swap));
02981 data_ima=cpl_imagelist_get(data_swap,0);
02982
02983 naxis1=cpl_image_get_size_x(data_ima);
02984 naxis2=cpl_image_get_size_y(data_ima);
02985
02986
02987 table=cpl_table_new(naxis3);
02988 cpl_table_new_column(table,"WAVELENGTH",CPL_TYPE_DOUBLE);
02989
02990 cpl_table_new_column(table,"POS_1",CPL_TYPE_DOUBLE);
02991 cpl_table_new_column(table,"POS_2",CPL_TYPE_DOUBLE);
02992 cpl_table_new_column(table,"POS_3",CPL_TYPE_DOUBLE);
02993
02994 pwav=cpl_table_get_data_double(table,"WAVELENGTH");
02995 pcx1=cpl_table_get_data_double(table,"POS_1");
02996 pcx2=cpl_table_get_data_double(table,"POS_2");
02997 pcx3=cpl_table_get_data_double(table,"POS_3");
02998
02999 cpl_table_fill_column_window_double(table,"WAVELENGTH",0,naxis3,0.);
03000 cpl_table_fill_column_window_double(table,"POS_1",0,naxis3,0.);
03001 cpl_table_fill_column_window_double(table,"POS_2",0,naxis3,0.);
03002 cpl_table_fill_column_window_double(table,"POS_3",0,naxis3,0.);
03003
03004
03005 for(k=0;k<naxis3;k++) {
03006
03007 check(data_ima=cpl_imagelist_get(data_swap,k));
03008 check(errs_ima=cpl_imagelist_get(data_swap,k));
03009 pwav[k]=crval3+cdelt3*k;
03010
03011 for(j=1;j<=naxis2;j++) {
03012 check(cpl_image_get_maxpos_window(data_ima,
03013 win_min,j,win_max,j,&mx,&my));
03014 llx=(mx-hsize>win_min) ? mx-hsize:win_min;
03015 urx=(mx+hsize<win_max) ? mx+hsize:win_max;
03016 if(method == 0 ) {
03017 cx=xsh_image_fit_gaussian_max_pos_x_window(data_ima,llx,urx,j);
03018 } else {
03019 check(cx=cpl_image_get_centroid_x_window(data_ima,llx,j,urx,j));
03020
03021 }
03022
03023 switch(j){
03024 case 1: pcx1[k]=cx;
03025 case 2: pcx2[k]=cx;
03026 case 3: pcx3[k]=cx;
03027 }
03028 }
03029
03030 }
03031
03032
03033 cpl_table_duplicate_column(table,"RES12",table,"POS_1");
03034 cpl_table_subtract_columns(table,"RES12","POS_2");
03035
03036 cpl_table_duplicate_column(table,"RES32",table,"POS_3");
03037 cpl_table_subtract_columns(table,"RES32","POS_2");
03038
03039 cpl_table_duplicate_column(table,"RES13",table,"POS_1");
03040 cpl_table_subtract_columns(table,"RES13","POS_3");
03041
03042 if(compute_qc) {
03043 check(xsh_util_compute_qc_residuals(table, instrument,plist));
03044 }
03045
03046 sprintf(tag,"%s_%s_TRACE_OBJ_%s",
03047 rec_prefix,suffix,xsh_instrument_arm_tostring( instrument));
03048 sprintf(fname,"%s.fits",tag);
03049 check(cpl_table_save(table,plist,NULL,fname,CPL_IO_DEFAULT));
03050 result=xsh_frame_product(fname,tag,CPL_FRAME_TYPE_TABLE,
03051 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
03052
03053
03054 cleanup:
03055
03056 xsh_free_table(&table);
03057 xsh_free_imagelist(&swap1);
03058 xsh_free_imagelist(&swap2);
03059 xsh_free_imagelist(&data_swap);
03060 xsh_free_imagelist(&errs_swap);
03061 xsh_free_imagelist(&data_iml);
03062 xsh_free_imagelist(&errs_iml);
03063 xsh_free_propertylist(&plist);
03064
03065 return result;
03066 }
03076 cpl_error_code
03077 xsh_iml_merge_avg(cpl_imagelist** data,
03078 cpl_imagelist** mask,
03079 const cpl_image* data_ima,
03080 const cpl_image* mask_ima,
03081 const int mk)
03082 {
03083 cpl_image* data_tmp=NULL;
03084 cpl_image* mask_tmp=NULL;
03085 int* pmsk=NULL;
03086 double norm=0;
03087 int naxis1=0;
03088 int naxis2=0;
03089
03090 int size=0;
03091 check(size=cpl_imagelist_get_size(*mask));
03092 if(mk<size) {
03093 check(data_tmp=cpl_imagelist_get(*data,mk));
03094 check(mask_tmp=cpl_imagelist_get(*mask,mk));
03095 check(pmsk=cpl_image_get_data_int(mask_tmp));
03096 check(naxis1=cpl_image_get_size_x(mask_tmp));
03097 check(naxis2=cpl_image_get_size_y(mask_tmp));
03098
03099 check(norm=pmsk[1]+1);
03100 check(cpl_image_add(data_tmp,data_ima));
03101 check(cpl_image_divide_scalar(data_tmp,norm));
03102 check(cpl_image_add_scalar(mask_tmp,1));
03103 check(cpl_imagelist_set(*mask,cpl_image_duplicate(mask_ima),mk));
03104 check(cpl_imagelist_set(*data,cpl_image_duplicate(data_tmp),mk));
03105
03106 } else {
03107 check(cpl_imagelist_set(*mask,cpl_image_duplicate(mask_ima),mk));
03108 check(cpl_imagelist_set(*data,cpl_image_duplicate(data_ima),mk));
03109 }
03110
03111 cleanup:
03112
03113
03114
03115
03116 return cpl_error_get_code();
03117
03118 }
03119
03120
03128
03129 cpl_image*
03130 xsh_image_mflat_detect_blemishes(cpl_frame* flat_frame,
03131 xsh_instrument* instrument)
03132 {
03133
03134 cpl_image* result=NULL;
03135 cpl_image* diff=NULL;
03136 cpl_image* flat_smooth=NULL;
03137 cpl_array* val=NULL;
03138 cpl_matrix* mx=NULL;
03139 cpl_image* flat_image=NULL;
03140 cpl_propertylist* head=NULL;
03141
03142 int binx=0;
03143 int biny=0;
03144 int sx=0;
03145 int sy=0;
03146 int size=0;
03147 int i=0;
03148 int j=0;
03149 int k=0;
03150 int niter=3;
03151 int filter_width_x=1;
03152 int filter_width_y=3;
03153
03154 double kappa=10.;
03155 double mean=0;
03156 double stdev=0;
03157 double stdev_x_kappa=0;
03158
03159 double med_flat=0;
03160
03161 double* pres=NULL;
03162 double* pima=NULL;
03163 double* pval=NULL;
03164 double* pdif=NULL;
03165 int npixs=0;
03166 const char* name=NULL;
03167 char filename[80];
03168
03169
03170 passure( flat_frame !=NULL , "NULL input flat ");
03171 name=cpl_frame_get_filename(flat_frame);
03172 flat_image=cpl_image_load(name,CPL_TYPE_DOUBLE,0,0);
03173 head=cpl_propertylist_load(name,0);
03174
03175 sx=cpl_image_get_size_x(flat_image);
03176 sy=cpl_image_get_size_y(flat_image);
03177 npixs=sx*sy;
03178 if ( xsh_instrument_get_arm(instrument) == XSH_ARM_NIR){
03179 binx=1;
03180 biny=1;
03181 } else {
03182 binx=xsh_pfits_get_binx(head);
03183 biny=xsh_pfits_get_biny(head);
03184 }
03185
03186 if (binx>1) filter_width_x=5;
03187 if (biny>1) filter_width_y=5;
03188
03189
03190
03191 check(mx=cpl_matrix_new(filter_width_x,filter_width_y));
03192
03193 for(j=0; j< filter_width_y; j++){
03194 for(i=0; i< filter_width_x; i++){
03195 cpl_matrix_set( mx, i,j,1.0);
03196 }
03197 }
03198
03199 check(diff=cpl_image_duplicate(flat_image));
03200
03201 check(flat_smooth=xsh_image_filter_median(flat_image,mx));
03202
03203
03204
03205
03206 check(cpl_image_subtract(diff,flat_smooth));
03207
03208
03209
03210
03211
03212 check(med_flat=cpl_image_get_median(flat_image));
03213
03214
03215 val=cpl_array_new(npixs,CPL_TYPE_DOUBLE);
03216 check(cpl_array_fill_window_double(val,0,npixs,0));
03217 check(pval=cpl_array_get_data_double(val));
03218 check(pima=cpl_image_get_data_double(flat_image));
03219 check(pdif=cpl_image_get_data_double(diff));
03220 k=0;
03221 for(i=0;i<npixs;i++) {
03222 if(pima[i]>med_flat) {
03223 pval[k]=pdif[i];
03224 k++;
03225 }
03226 }
03227
03228 check(cpl_array_set_size(val,k));
03229
03230
03231 check(mean=cpl_array_get_mean(val));
03232 check(stdev=cpl_array_get_stdev(val));
03233 stdev_x_kappa=stdev*kappa;
03234 check(size=cpl_array_get_size(val));
03235
03236 for(i=0;i<niter;i++) {
03237 for(k=0;k<size;k++) {
03238 if(fabs(pval[k]-mean)>stdev_x_kappa) {
03239 cpl_array_set_invalid(val,k);
03240 }
03241 }
03242 mean=cpl_array_get_mean(val);
03243 stdev=cpl_array_get_stdev(val);
03244 stdev_x_kappa=stdev*kappa;
03245 }
03246
03247
03248 result=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
03249 pres=cpl_image_get_data_double(result);
03250 for(i=0;i<npixs;i++) {
03251 if(fabs(pdif[i])<stdev_x_kappa) {
03252 pres[i]=1.;
03253 }
03254 }
03255
03256 sprintf(filename,"blemish_%s.fits",xsh_instrument_arm_tostring(instrument));
03257
03258 check(cpl_image_save(result,filename,CPL_BPP_IEEE_FLOAT,NULL,
03259 CPL_IO_DEFAULT));
03260
03261
03262 cleanup:
03263 xsh_free_array(&val);
03264 xsh_free_image(&diff);
03265 xsh_free_image(&flat_smooth);
03266 xsh_free_matrix(&mx);
03267 xsh_free_image(&flat_image);
03268 xsh_free_propertylist(&head);
03269 return result;
03270 }
03271
03272
03273
03282
03283 cpl_frame*
03284 xsh_image_mflat_detect_hotcold(cpl_frame* flat_frame,
03285 xsh_instrument* instrument,
03286 const int mode)
03287 {
03288 cpl_frame* msk_frm=NULL;
03289 cpl_image* mask=NULL;
03290 cpl_image* diff=NULL;
03291 cpl_image* flat_smooth=NULL;
03292 cpl_array* val=NULL;
03293 cpl_matrix* mx=NULL;
03294 cpl_image* flat_image=NULL;
03295 cpl_propertylist* head=NULL;
03296
03297 int binx=0;
03298 int biny=0;
03299 int sx=0;
03300 int sy=0;
03301 int size=0;
03302 int i=0;
03303 int j=0;
03304 int k=0;
03305 int niter=3;
03306 int filter_width_x=1;
03307 int filter_width_y=3;
03308
03309 double kappa=10.;
03310 double mean=0;
03311 double stdev=0;
03312 double stdev_x_kappa=0;
03313
03314 double med_flat=0;
03315
03316 double* pmsk=NULL;
03317 double* pima=NULL;
03318 double* pval=NULL;
03319 double* pdif=NULL;
03320 int npixs=0;
03321 const char* name=NULL;
03322 char filename[80];
03323 char tag[80];
03324
03325
03326 passure( flat_frame !=NULL , "NULL input flat ");
03327 name=cpl_frame_get_filename(flat_frame);
03328 flat_image=cpl_image_load(name,CPL_TYPE_DOUBLE,0,0);
03329 head=cpl_propertylist_load(name,0);
03330
03331 sx=cpl_image_get_size_x(flat_image);
03332 sy=cpl_image_get_size_y(flat_image);
03333 npixs=sx*sy;
03334 if ( xsh_instrument_get_arm(instrument) == XSH_ARM_NIR){
03335 binx=1;
03336 biny=1;
03337 } else {
03338 binx=xsh_pfits_get_binx(head);
03339 biny=xsh_pfits_get_biny(head);
03340 }
03341
03342 if (binx>1) filter_width_x=5;
03343 if (biny>1) filter_width_y=5;
03344
03345
03346
03347 check(mx=cpl_matrix_new(filter_width_x,filter_width_y));
03348
03349 for(j=0; j< filter_width_y; j++){
03350 for(i=0; i< filter_width_x; i++){
03351 cpl_matrix_set( mx, i,j,1.0);
03352 }
03353 }
03354
03355 check(diff=cpl_image_duplicate(flat_image));
03356
03357 check(flat_smooth=xsh_image_filter_median(flat_image,mx));
03358
03359
03360
03361
03362 check(cpl_image_subtract(diff,flat_smooth));
03363
03364
03365
03366
03367
03368 check(med_flat=cpl_image_get_median(flat_image));
03369
03370
03371 val=cpl_array_new(npixs,CPL_TYPE_DOUBLE);
03372 check(cpl_array_fill_window_double(val,0,npixs,0));
03373 check(pval=cpl_array_get_data_double(val));
03374 check(pima=cpl_image_get_data_double(flat_image));
03375 check(pdif=cpl_image_get_data_double(diff));
03376 k=0;
03377 for(i=0;i<npixs;i++) {
03378 if(pima[i]>med_flat) {
03379 pval[k]=pdif[i];
03380 k++;
03381 }
03382 }
03383
03384 check(cpl_array_set_size(val,k));
03385
03386
03387 check(mean=cpl_array_get_mean(val));
03388 check(stdev=cpl_array_get_stdev(val));
03389 stdev_x_kappa=stdev*kappa;
03390 check(size=cpl_array_get_size(val));
03391
03392 for(i=0;i<niter;i++) {
03393 for(k=0;k<size;k++) {
03394 if(fabs(pval[k]-mean)>stdev_x_kappa) {
03395 cpl_array_set_invalid(val,k);
03396 }
03397 }
03398 mean=cpl_array_get_mean(val);
03399 stdev=cpl_array_get_stdev(val);
03400 stdev_x_kappa=stdev*kappa;
03401 }
03402
03403
03404 mask=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
03405 pmsk=cpl_image_get_data_double(mask);
03406
03407 if(mode==1) {
03408 for(i=0;i<npixs;i++) {
03409 if(pdif[i]>stdev_x_kappa) {
03410 pmsk[i]=QFLAG_WELL_SATURATION;
03411 }
03412 }
03413 } else {
03414 for(i=0;i<npixs;i++) {
03415 if(pdif[i]<-stdev_x_kappa) {
03416 pmsk[i]=QFLAG_LOW_QE_PIXEL;
03417 }
03418 }
03419 }
03420
03421 if(mode==1) {
03422 sprintf(tag,"%s_%s",XSH_BP_MAP_SP,xsh_instrument_arm_tostring(instrument));
03423 sprintf(filename,"%s.fits",tag);
03424 } else {
03425 sprintf(tag,"%s_%s",XSH_BP_MAP_DP,xsh_instrument_arm_tostring(instrument));
03426 sprintf(filename,"%s.fits",tag);
03427 }
03428
03429 check(cpl_image_save(mask,filename,XSH_PRE_DATA_BPP,NULL,
03430 CPL_IO_DEFAULT));
03431
03432 check(msk_frm=xsh_frame_product(filename,tag,CPL_FRAME_TYPE_IMAGE,
03433 CPL_FRAME_GROUP_PRODUCT,
03434 CPL_FRAME_LEVEL_FINAL));
03435
03436 cleanup:
03437 xsh_free_array(&val);
03438 xsh_free_image(&mask);
03439 xsh_free_image(&diff);
03440 xsh_free_image(&flat_smooth);
03441 xsh_free_matrix(&mx);
03442 xsh_free_image(&flat_image);
03443 xsh_free_propertylist(&head);
03444 return msk_frm;
03445 }
03446
03447