SINFONI Pipeline Reference Manual  2.6.0
sinfo_detlin.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 /*******************************************************************************
20  * E.S.O. - VLT project
21  *
22  *
23  *
24  * who when what
25  * -------- -------- ----------------------------------------------
26  * amodigli 18/04/02 created
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32 #define POSIX_SOURCE 1
33 #include "sinfo_vltPort.h"
34 
35 /*
36  * System Headers
37  */
38 
39 /*
40  * Local Headers
41  */
42 
43 #include "sinfo_detlin.h"
44 #include "sinfo_recipes.h"
45 #include "sinfo_fit_curve.h"
46 
54 /*----------------------------------------------------------------------------
55  * Function codes
56  *--------------------------------------------------------------------------*/
57 
79 cpl_imagelist *
80 sinfo_new_fit_intensity_course(cpl_imagelist * flatStack,
81  int order,
82  float loReject,
83  float hiReject )
84 {
85  cpl_imagelist * ret_iml ;
86 
87  int i, z ;
88  double * coeffs ;
89  Stats ** stats=NULL ;
90  int sx;
91  int sy;
92  int sz;
93  float* psrcdata;
94  float* presdata;
95  cpl_image* img_tmp=NULL;
96  sx=cpl_image_get_size_x(cpl_imagelist_get(flatStack,0));
97  sy=cpl_image_get_size_y(cpl_imagelist_get(flatStack,0));
98  sz=cpl_imagelist_get_size(flatStack);
99 
100  stats=(Stats**) cpl_calloc(sz,sizeof(Stats*)) ;
101 
102  if ( NULL == flatStack )
103  {
104  sinfo_msg_error("no input cube given!") ;
105  cpl_free(stats);
106  return NULL ;
107  }
108  if ( order <= 0 )
109  {
110  sinfo_msg_error("wrong order of polynomial given!") ;
111  cpl_free(stats);
112  return NULL ;
113  }
114  /* allocate memory for returned cube */
115  ret_iml = cpl_imagelist_new();
116  for ( z = 0 ; z < order+1 ; z++ )
117  {
118  img_tmp=cpl_image_new(sx,sy,CPL_TYPE_FLOAT);
119  cpl_imagelist_set(ret_iml,img_tmp,z);
120  }
121 
122  for ( z = 0 ; z < sz ; z++ )
123  {
124  stats[z]=
125  sinfo_new_image_stats_on_rectangle(cpl_imagelist_get(flatStack,z),
126  loReject,
127  hiReject,
128  0,
129  0,
130  sx-1,
131  sy-1) ;
132  if ( stats[z] == NULL )
133  {
134  sinfo_msg_error("could not compute image statistics "
135  "in plane: %d", z) ;
136  cpl_imagelist_delete(ret_iml) ;
137  return NULL ;
138  }
139  }
140 
141  /* go through the image plane and store the spectra in a double
142  points data structure */
143 
144  for ( i = 0 ; i < sx*sy ; i++ )
145  {
146  /* allocate dpoint object */
147  dpoint * points ;
148  if ( NULL == ( points = (dpoint*) cpl_calloc(sz, sizeof(dpoint)) ) )
149  {
150  sinfo_msg_error("could not allocate memory!\n") ;
151  cpl_imagelist_delete(ret_iml) ;
152  return NULL ;
153  }
154 
155  for ( z = 0 ; z < sz ; z++ )
156  {
157  if(NULL==(img_tmp = cpl_imagelist_get(flatStack,z))) {
158  sinfo_msg_error("could not get image!");
159  cpl_imagelist_delete(ret_iml) ;
160  cpl_free(points) ;
161  return NULL;
162  } else {
163  psrcdata=cpl_image_get_data_float(img_tmp);
164  points[z].x = (double)stats[z]->cleanmean ;
165  points[z].y = (double)psrcdata[i] ;
166  }
167  }
168 
169 
170  if ( NULL == ( coeffs = sinfo_fit_1d_poly(order, points, sz, NULL) ) )
171  {
172  sinfo_msg_warning("could not fit spectrum of pixel: %d\n", i) ;
173  for ( z = 0 ; z < order+1 ; z++ )
174  {
175  presdata=cpl_image_get_data_float(cpl_imagelist_get(ret_iml,z));
176  presdata[i] = ZERO ;
177  }
178  }
179  else
180  {
181  for ( z = 0 ; z < order+1 ; z++ )
182  {
183  if(NULL==(img_tmp = cpl_imagelist_get(ret_iml,z))) {
184  sinfo_msg_error("could not get image!");
185  cpl_imagelist_delete(ret_iml) ;
186  return NULL;
187  } else {
188  presdata=cpl_image_get_data_float(img_tmp);
189  presdata[i] = coeffs[z] ;
190  }
191  }
192  }
193  cpl_free(points) ;
194  cpl_free(coeffs) ;
195  }
196 
197  for ( z = 0 ; z < sz ; z++ )
198  {
199  cpl_free (stats[z]) ;
200  }
201  cpl_free(stats);
202  return ret_iml ;
203 }
204 
205 
229 cpl_image * sinfo_new_search_bad_pixels( cpl_imagelist * coeffs,
230  double threshSigmaFactor,
231  double nonlinearThresh,
232  float loReject,
233  float hiReject )
234 {
235  int i ;
236  Stats * stats ;
237  int sx=0;
238  int sy=0;
239  int sz=0;
240 
241  cpl_image * img_res ;
242  cpl_image* img_src=NULL;
243 
244  float* psrcdata=NULL;
245  float* presdata=NULL;
246 
247  if ( NULL == coeffs )
248  {
249  sinfo_msg_error("no input cube given!\n") ;
250  return NULL ;
251  }
252  if ( threshSigmaFactor <= 0. )
253  {
254  sinfo_msg_error("wrong sigma factor given, 0 or negativ!\n") ;
255  return NULL ;
256  }
257  if ( nonlinearThresh <= 0. )
258  {
259  sinfo_msg_error("wrong nonlinear threshold value given, "
260  "0 or negative!") ;
261  return NULL ;
262  }
263 
264  sz=cpl_imagelist_get_size(coeffs);
265 
266  if ( sz <= 1 )
267  {
268  sinfo_msg_error("no cube given, only one plane!\n") ;
269  return NULL ;
270  }
271 
272  /* Note that we refer to image #1! */
273  img_src=cpl_imagelist_get(coeffs,1);
274  sx=cpl_image_get_size_x(img_src);
275  sy=cpl_image_get_size_y(img_src);
276 
277  /* allocate memory for return image */
278  if ( NULL == (img_res = cpl_image_new(sx, sy,CPL_TYPE_FLOAT)) )
279  {
280  sinfo_msg_error("could not allocate memory!\n") ;
281  return NULL ;
282  }
283 
284 
285  /* first test the sensitivity deviations of each pixel */
286  /* determine the clean mean and clean standard deviation
287  in the whole image frame */
288 
289  stats = sinfo_new_image_stats_on_rectangle(img_src,
290  loReject,
291  hiReject, 0, 0,
292  sx-1, sy-1) ;
293  if ( NULL == stats )
294  {
295  sinfo_msg_error("could not determine image statistics!\n") ;
296  cpl_image_delete(img_res) ;
297  return NULL ;
298  }
299 
300 
301  psrcdata=cpl_image_get_data_float(img_src);
302  presdata=cpl_image_get_data_float(img_res);
303  for ( i = 0 ; i < (int) sx*sy ; i++ )
304  {
305 
306  if ( isnan(psrcdata[i]) )
307  {
308  presdata[i] = 0. ;
309  }
310  else if ( stats->cleanmean - psrcdata[i] >
311  threshSigmaFactor*stats->cleanstdev )
312  {
313  presdata[i] = 0. ;
314  }
315  else
316  {
317  presdata[i] = 1. ;
318  }
319  }
320  cpl_free(stats) ;
321 
322 
323  /* -----------------------------------------------------
324  * now test additionally the non-linearity if available.
325  * if a strong non-linearity occurs for pixels which are
326  * declared "good" so far (normal linear coefficients)
327  * these pixels will be declared bad.
328  */
329  if (sz > 1)
330  {
331  int z;
332  for ( z = 2 ; z < sz ; z++ )
333  {
334  img_src=cpl_imagelist_get(coeffs,z);
335  sx=cpl_image_get_size_x(img_src);
336  sy=cpl_image_get_size_y(img_src);
337 
338  psrcdata=cpl_image_get_data_float(img_src);
339  stats = sinfo_new_image_stats_on_rectangle(img_src, loReject,
340  hiReject, 0, 0, sx-1, sy-1) ;
341  if ( NULL == stats )
342  {
343  sinfo_msg_error("could not determine image statistics!\n") ;
344  cpl_image_delete(img_res) ;
345  return NULL ;
346  }
347  presdata=cpl_image_get_data_float(img_res);
348  for ( i = 0 ; i < (int) sx*sy ; i++ )
349  {
350  if ( presdata[i] == 1. &&
351  (fabs(psrcdata[i] - stats->cleanmean) >
352  threshSigmaFactor*stats->cleanstdev ||
353  fabs(psrcdata[i]) > nonlinearThresh ) )
354  {
355  presdata[i] = 0. ;
356  }
357  }
358  cpl_free(stats) ;
359  }
360  }
361 
362  return img_res ;
363 }
364 
365 
366 
367 
388 cpl_image * sinfo_new_search_bad_pixels_via_noise(cpl_imagelist * darks,
389  float threshSigmaFactor,
390  float loReject,
391  float hiReject )
392 {
393  cpl_image * bp_map ;
394  int z, n, i ;
395  int lx, ly ;
396  int row, col ;
397  int low_n, high_n ;
398  float * spectrum ;
399  double pix_sum ;
400  double sqr_sum ;
401  Stats * stats ;
402  cpl_image* img_src=NULL;
403 
404  float* psrcdata=NULL;
405  float* pbpdata=NULL;
406 
407  int lz=0;
408 
409  if ( NULL == darks )
410  {
411  sinfo_msg_error("no input cube given!\n") ;
412  return NULL ;
413  }
414 
415  if ( threshSigmaFactor <= 0. )
416  {
417  sinfo_msg_error("factor is smaller or equal zero!\n") ;
418  return NULL ;
419  }
420  if ( loReject < 0. || hiReject < 0. || (loReject + hiReject) >= 100. )
421  {
422  sinfo_msg_error("wrong reject percentage values!\n") ;
423  return NULL ;
424  }
425 
426  lz=cpl_imagelist_get_size(darks);
427  if ( lz < 1 )
428  {
429  sinfo_msg_error("not enough dark frames given for good statistics!") ;
430  return NULL ;
431  }
432  img_src=cpl_imagelist_get(darks,0);
433 
434  lx = cpl_image_get_size_x(img_src) ;
435  ly = cpl_image_get_size_y(img_src) ;
436 
437  low_n = (int)(loReject/100. *(float)lz) ;
438  high_n = (int)(hiReject/100. *(float)lz) ;
439  if (NULL == (bp_map = cpl_image_new (lx, ly,CPL_TYPE_FLOAT) ) )
440  {
441  sinfo_msg_error("could not allocate new memory!\n") ;
442  return NULL ;
443  }
444  pbpdata=cpl_image_get_data(bp_map);
445  if (NULL == (spectrum = (float*) cpl_calloc(lz, sizeof(float)) ) )
446  {
447  sinfo_msg_error("could not allocate new memory!\n") ;
448  return NULL ;
449  }
450  for ( row = 0 ; row < ly ; row++ ) {
451 
452  for ( col = 0 ; col < lx ; col++ ) {
453 
454  for ( z = 0 ; z < lz ; z++ ) {
455  img_src=cpl_imagelist_get(darks,z);
456  psrcdata=cpl_image_get_data(img_src);
457  spectrum[z] = psrcdata[col+lx*row] ;
458  }
459  sinfo_pixel_qsort(spectrum, lz) ;
460  n = 0 ;
461  pix_sum = 0.;
462  sqr_sum = 0.;
463  for ( i = low_n ; i < lz - high_n ; i++ ) {
464  pix_sum += (double)spectrum[i] ;
465  sqr_sum += ((double)spectrum[i]*(double)spectrum[i]) ;
466  n++ ;
467  }
468  /* compute the noise in each pixel */
469  pix_sum /= (double)n ;
470  sqr_sum /= (double)n ;
471 
472  pbpdata[col+lx*row] = (float)sqrt(sqr_sum - pix_sum*pix_sum) ;
473  }
474  }
475  cpl_free(spectrum) ;
476  if ( NULL == (stats = sinfo_new_image_stats_on_rectangle (bp_map, loReject,
477  hiReject, 200, 200, 800, 800) ) )
478  {
479  sinfo_msg_error("could not get image statistics!\n") ;
480  cpl_image_delete (bp_map) ;
481  return NULL ;
482  }
483 
484 
485  /* now build the bad pixel mask */
486  for ( row = 0 ; row < ly ; row++ ) {
487  for ( col = 0 ; col < lx ; col++ ) {
488  if (pbpdata[col+lx*row] >
489  stats->cleanmean+threshSigmaFactor*stats->cleanstdev ||
490  pbpdata[col+lx*row] <
491  stats->cleanmean-threshSigmaFactor*stats->cleanstdev)
492  {
493  pbpdata[col+lx*row] = 0. ;
494  }
495  else
496  {
497  pbpdata[col+lx*row] = 1. ;
498  }
499  }
500  }
501  cpl_free (stats) ;
502  return bp_map ;
503 }
504 
505 
506 
515 int sinfo_new_count_bad_pixels (cpl_image * bad )
516 {
517  int i, n ;
518  int sx=cpl_image_get_size_x(bad);
519  int sy=cpl_image_get_size_y(bad);
520  float* pbpdata=cpl_image_get_data(bad);
521 
522  n = 0 ;
523  for ( i = 0 ; i < (int) sx*sy ; i++ )
524  {
525  if ( pbpdata[i] == 0 || isnan(pbpdata[i]) )
526  {
527  n++ ;
528  }
529  }
530  return n ;
531 }
532 
533 
561 cpl_image * sinfo_new_abs_dist_image(cpl_image * im, float fmedian )
562 {
563 
564  cpl_image * image ;
565  pixelvalue * value ;
566  pixelvalue dist ;
567  pixelvalue median_dist ;
568  pixelvalue* pix_dist=NULL ;
569  int * position ;
570  int nposition ;
571  int n, m, i, j ;
572  double sum, sum2 ;
573  double stdev ;
574  float* pdata=NULL;
575  int lx=0;
576  int ly=0;
577 
578  if ( im == NULL )
579  {
580  sinfo_msg_error ("no image input\n") ;
581  return NULL ;
582  }
583 
584  image = cpl_image_duplicate ( im ) ;
585 
586  /*----------------------------------------------------------------------
587  * go through all pixels
588  */
589 
590  sum = 0. ;
591  sum2 = 0. ;
592  m = 0 ;
593 
594  pdata = cpl_image_get_data(im);
595  lx=cpl_image_get_size_x(im);
596  ly=cpl_image_get_size_y(im);
597  pix_dist=(pixelvalue*)cpl_calloc(lx*ly,sizeof(pixelvalue)) ;
598 
599  for ( i = 0 ; i < (int) lx*ly ; i++ )
600  {
601  /* blank pixels are not replaced */
602  if ( isnan(pdata[i]) )
603  {
604  continue ;
605  }
606 
607  /* initialize the buffer variables for the 8 nearest neighbors */
608  value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
609  position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
610 
611  /*--------------------------------------------------------------------
612  * determine the pixel position of the 8 nearest neighbors
613  */
614 
615  position[0] = i + lx - 1 ; /* upper left */
616  position[1] = i + lx ; /* upper */
617  position[2] = i + lx + 1 ; /* upper right */
618  position[3] = i + 1 ; /* right */
619  position[4] = i - lx + 1 ; /* lower right */
620  position[5] = i - lx ; /* lower */
621  position[6] = i - lx - 1 ; /* lower left */
622  position[7] = i - 1 ; /* left */
623 
624  /*--------------------------------------------------------------------
625  * determine the positions of the image margins, top positions are
626  * changed to low positions and vice versa. Right positions are
627  * changed to left positions and vice versa.
628  */
629 
630  if ( i >= 0 && i < lx ) /* bottom line */
631  {
632  position[4] += 2 * lx ;
633  position[5] += 2 * lx ;
634  position[6] += 2 * lx ;
635  }
636  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
637  {
638  position[0] -= 2 * lx ;
639  position[1] -= 2 * lx ;
640  position[2] -= 2 * lx ;
641  }
642  else if ( i % lx == 0 ) /* left side */
643  {
644  position[0] += 2 ;
645  position[6] += 2 ;
646  position[7] += 2 ;
647  }
648  else if ( i % lx == lx - 1 ) /* right side */
649  {
650  position[2] -= 2 ;
651  position[3] -= 2 ;
652  position[4] -= 2 ;
653  }
654 
655  /* -------------------------------------------------------------------
656  * read the pixel values of the neighboring pixels,
657  * blanks are not considered
658  */
659 
660  nposition = 8 ;
661  n = 0 ;
662  for ( j = 0 ; j < nposition ; j ++ )
663  {
664  if ( !isnan(pdata[position[j]]) )
665  {
666  value[n] = pdata[position[j]] ;
667  n ++ ;
668  }
669  }
670  nposition = n ;
671 
672  if ( nposition <= 1 ) /* almost all neighbors are blank */
673  {
674  pdata[i] = ZERO ;
675  cpl_free(value) ;
676  cpl_free(position) ;
677  continue ;
678  }
679 
680  /* determine the absolute distances */
681  dist = 0. ;
682  for ( n = 0 ; n < nposition ; n++ )
683  {
684  dist += (pdata[i] - value[n])*(pdata[i] - value[n]) ;
685  }
686  dist = sqrt(dist)/(float) nposition ;
687  pix_dist[m] = dist ;
688  m++ ;
689  sum += (double)dist ;
690  sum2 += (double)dist * (double)dist ;
691  cpl_free(value) ;
692  cpl_free(position) ;
693  }
694  sum /= (double)m ;
695  sum2 /= (double)m ;
696  stdev = sqrt(sum2 - sum*sum) ;
697 
698  median_dist = sinfo_new_median(pix_dist, m) ;
699 
700  for ( i = 0 ; i < (int) lx*ly ; i++ )
701  {
702  /* blank pixels are not replaced */
703  if ( isnan(pdata[i]) )
704  {
705  continue ;
706  }
707 
708  /* initialize the buffer variables for the 8 nearest neighbors */
709  value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
710  position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
711 
712  /*-------------------------------------------------------------------
713  * determine the pixel position of the 8 nearest neighbors
714  */
715 
716  position[0] = i + lx - 1 ; /* upper left */
717  position[1] = i + lx ; /* upper */
718  position[2] = i + lx + 1 ; /* upper right */
719  position[3] = i + 1 ; /* right */
720  position[4] = i - lx + 1 ; /* lower right */
721  position[5] = i - lx ; /* lower */
722  position[6] = i - lx - 1 ; /* lower left */
723  position[7] = i - 1 ; /* left */
724 
725  /*-------------------------------------------------------------
726  * determine the positions of the image margins, top positions are
727  * changed to low positions and vice versa. Right positions are
728  * changed to left positions and vice versa.
729  */
730 
731  if ( i >= 0 && i < lx ) /* bottom line */
732  {
733  position[4] += 2 * lx ;
734  position[5] += 2 * lx ;
735  position[6] += 2 * lx ;
736  }
737  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
738  {
739  position[0] -= 2 * lx ;
740  position[1] -= 2 * lx ;
741  position[2] -= 2 * lx ;
742  }
743  else if ( i % lx == 0 ) /* left side */
744  {
745  position[0] += 2 ;
746  position[6] += 2 ;
747  position[7] += 2 ;
748  }
749  else if ( i % lx == lx - 1 ) /* right side */
750  {
751  position[2] -= 2 ;
752  position[3] -= 2 ;
753  position[4] -= 2 ;
754  }
755 
756  /* -------------------------------------------------------------------
757  * read the pixel values of the neighboring pixels,
758  * blanks are not considered
759  */
760 
761  nposition = 8 ;
762  n = 0 ;
763  for ( j = 0 ; j < nposition ; j ++ )
764  {
765  if ( !isnan(pdata[position[j]]) )
766  {
767  value[n] = pdata[position[j]] ;
768  n ++ ;
769  }
770  }
771  nposition = n ;
772 
773  if ( nposition <= 1 ) /* almost all neighbors are blank */
774  {
775  pdata[i] = ZERO ;
776  cpl_free(value) ;
777  cpl_free(position) ;
778  continue ;
779  }
780 
781  /* determine the absolute distances */
782  dist = 0. ;
783  for ( n = 0 ; n < nposition ; n++ )
784  {
785  dist += (pdata[i] - value[n])*(pdata[i] - value[n]) ;
786  }
787  dist = sqrt(dist)/(float) nposition ;
788 
789 
790  /* -----------------------------------------------------------------
791  * replace the pixel value by the sinfo_median on conditions:
792  * fmedian = 0: always replace with sinfo_median.
793  * fmedian < 0: interpret as absolute condition:
794  * if |pixel - sinfo_median| > -fmedian
795  * replace with sinfo_median.
796  * fmedian > 0: replace by sinfo_median (fmedian as a factor of
797  * the square root of the sinfo_median itself)
798  * if |pixel - median| >= fmedian * sqrt ( median )
799  * considers a dependence on the pixel value.
800  * This can be used to consider photon noise.
801  */
802 
803  if ( fmedian == 0 )
804  {
805  pdata[i] = dist ;
806  }
807  else if ( fmedian < 0 &&
808  fabs ( median_dist - dist ) >= -fmedian*stdev )
809  {
810  pdata[i] = dist ;
811  }
812  else if ( fmedian > 0 &&
813  fabs ( median_dist - dist ) >=
814  fmedian*stdev * sqrt(fabs(dist)) )
815  {
816  pdata[i] = dist ;
817  }
818  else
819  {
820  cpl_free (value) ;
821  cpl_free (position) ;
822  continue ;
823  }
824 
825  cpl_free (value) ;
826  cpl_free (position) ;
827  }
828  cpl_free(pix_dist);
829  return image ;
830 }
831 
832 
833 
834 
835 
836 
837 /*----------------------------------------------------------------------------
838  Function: sinfo_new_local_median_image()
839  In : im: input image
840  fmedian: a factor to the local standard deviation
841  loReject, hiReject: fraction of rejected values to determine
842  a clean standard deviation
843  half_box_size: integer half size of the running box to
844  determine the local clean standard deviation
845  Out : resulting image
846  Job : filter, calculates the local stdev in a moving box
847  Then it calculates the difference of the pixel to the median
848  of the nearest neighbors
849  by using the 8 closest pixels of every pixel.
850  The values in the output image are determined according
851  to the values of the input parameter.
852  If fmedian = 0: always replace by median
853  if fmedian < 0: replace median if |median_dist - dist| >
854  fmedian * stdev
855  if fmedian > 0: replace by median (fmedian as a factor of
856  the square root of the median itself)
857  if |pixel - median| >= fmedian*sqrt(median)
858  This can be used to consider photon noise.
859  This considers a dependence of the differences on the
860  pixel values themselves.
861  Notice : it is assumed that most of the 8 nearest neighbor pixels
862  are not bad pixels!
863  blank pixels are not replaced!
864  ---------------------------------------------------------------------------*/
865 
866 cpl_image * sinfo_new_local_median_image( cpl_image * im,
867  float fmedian,
868  float loReject,
869  float hiReject,
870  int half_box_size )
871 {
872  cpl_image * image ;
873  pixelvalue * value ;
874  pixelvalue median ;
875  int * position ;
876  int nposition ;
877  int n, i, j ;
878  int llx, lly, urx, ury ;
879  Stats * stats ;
880  int lx=0;
881  int ly=0;
882  float* pidata=NULL;
883  float* podata=NULL;
884 
885  if ( im == NULL )
886  {
887  sinfo_msg_error ("no image input") ;
888  return NULL ;
889  }
890  if ( half_box_size < 0 )
891  {
892  sinfo_msg_error ("negativ box_size given") ;
893  return NULL ;
894  }
895 
896  image = cpl_image_duplicate ( im ) ;
897  lx=cpl_image_get_size_x(im);
898  ly=cpl_image_get_size_y(im);
899  pidata=cpl_image_get_data(im);
900  podata=cpl_image_get_data(image);
901  /*----------------------------------------------------------------------
902  * go through all pixels
903  */
904 
905  for ( i = 0 ; i < (int) lx*ly ; i++ )
906  {
907  /* blank pixels are not replaced */
908  if ( isnan(pidata[i]) )
909  {
910  continue ;
911  }
912 
913  /* compute the image statistics in the box area */
914  llx = i%lx - half_box_size ;
915  if ( llx < 0 ) llx = 0 ;
916  lly = i%ly - half_box_size ;
917  if ( lly < 0 ) lly = 0 ;
918  urx = i%lx + half_box_size ;
919  if ( urx >= lx ) urx = lx - 1 ;
920  ury = i%ly + half_box_size ;
921  if ( ury >= ly ) ury = ly - 1 ;
922 
923  if ( NULL == (stats = sinfo_new_image_stats_on_rectangle (im, loReject,
924  hiReject, llx, lly, urx, ury)) )
925  {
926  sinfo_msg_warning("could not determine image statistics ");
927  sinfo_msg_warning("in pixel %d", i) ;
928  continue ;
929  }
930 
931  /* initialize the buffer variables for the 8 nearest neighbors */
932  value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
933  position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
934 
935  /*----------------------------------------------------------------------
936  * determine the pixel position of the 8 nearest neighbors
937  */
938 
939  position[0] = i + lx - 1 ; /* upper left */
940  position[1] = i + lx ; /* upper */
941  position[2] = i + lx + 1 ; /* upper right */
942  position[3] = i + 1 ; /* right */
943  position[4] = i - lx + 1 ; /* lower right */
944  position[5] = i - lx ; /* lower */
945  position[6] = i - lx - 1 ; /* lower left */
946  position[7] = i - 1 ; /* left */
947 
948  /*---------------------------------------------------------------------
949  * determine the positions of the image margins, top positions are
950  * changed to low positions and vice versa. Right positions are
951  * changed to left positions and vice versa.
952  */
953 
954  if ( i >= 0 && i < lx ) /* bottom line */
955  {
956  position[4] += 2 * lx ;
957  position[5] += 2 * lx ;
958  position[6] += 2 * lx ;
959  }
960  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
961  {
962  position[0] -= 2 * lx ;
963  position[1] -= 2 * lx ;
964  position[2] -= 2 * lx ;
965  }
966  else if ( i % lx == 0 ) /* left side */
967  {
968  position[0] += 2 ;
969  position[6] += 2 ;
970  position[7] += 2 ;
971  }
972  else if ( i % lx == lx - 1 ) /* right side */
973  {
974  position[2] -= 2 ;
975  position[3] -= 2 ;
976  position[4] -= 2 ;
977  }
978 
979  /* ------------------------------------------------------------------
980  * read the pixel values of the neighboring pixels,
981  * blanks are not considered
982  */
983 
984  nposition = 8 ;
985  n = 0 ;
986  for ( j = 0 ; j < nposition ; j ++ )
987  {
988  if ( !isnan(pidata[position[j]]) )
989  {
990  value[n] = pidata[position[j]] ;
991  n ++ ;
992  }
993  }
994  nposition = n ;
995 
996  if ( nposition <= 1 ) /* almost all neighbors are blank */
997  {
998  podata[i] = ZERO ;
999  cpl_free(value) ;
1000  cpl_free(position) ;
1001  cpl_free(stats) ;
1002  continue ;
1003  }
1004 
1005  /* sort the values and determine the median */
1006 
1007  sinfo_pixel_qsort( value, nposition ) ;
1008  if ( nposition % 2 == 1 )
1009  {
1010  median = value [ nposition/2 ] ;
1011  }
1012  else
1013  {
1014  median = ( value [nposition/2 - 1] + value [nposition/2] ) / 2. ;
1015  }
1016 
1017  /* -----------------------------------------------------------------
1018  * replace the pixel value by the median on conditions:
1019  * fmedian = 0: always replace with median.
1020  * fmedian > 0: replace by median (fmedian as a factor of
1021  * the square root of the median itself)
1022  * if |pixel - median| >= fmedian * sqrt ( median )
1023  * considers a dependence on the pixel value.
1024  * This can be used to consider photon noise.
1025  */
1026 
1027  if ( fmedian == 0 )
1028  {
1029  podata[i] = median ;
1030  }
1031  else if ( fmedian < 0 &&
1032  fabs ( median - pidata[i] ) >= -fmedian * stats->cleanstdev)
1033  {
1034  podata[i] = median ;
1035  }
1036  else if ( fmedian > 0 &&
1037  fabs ( median - pidata[i] ) >= fmedian * sqrt(fabs(median)) )
1038  {
1039  podata[i] = median ;
1040  }
1041  else
1042  {
1043  cpl_free (value) ;
1044  cpl_free (position) ;
1045  cpl_free (stats) ;
1046  continue ;
1047  }
1048 
1049  cpl_free (value) ;
1050  cpl_free (position) ;
1051  cpl_free (stats) ;
1052  }
1053  return image ;
1054 }
1055 
1056 
1057 
1058 /*----------------------------------------------------------------------------
1059  Function: sinfo_new_mean_image_in_spec()
1060  In : image, a threshold parameter
1061  Out : resulting image
1062  Job : mean filter, calculates the mean for an image
1063  by using the 4 closest pixels of every pixel in spectral
1064  direction (column).
1065  The values in the output image are determined according
1066  to the values of the input parameter.
1067  If fmedian = 0: always replace by mean
1068  if fmedian < 0: replace by mean if |pixel - mean| >
1069  -fmedian
1070  if fmedian > 0: replace by mean (fmedian as a factor of
1071  the square root of the mean itself)
1072  if |pixel - mean| >= fmedian * sqrt ( mean )
1073  This can be used to consider photon noise.
1074  This considers a dependence of the differences on the
1075  pixel values themselves.
1076  Notice : it is assumed that most of the 4 nearest neighbor pixels
1077  are not bad pixels!
1078  blank pixels are not replaced!
1079  ---------------------------------------------------------------------------*/
1080 
1081 cpl_image * sinfo_new_mean_image_in_spec( cpl_image * im, float fmedian )
1082 {
1083  cpl_image * image ;
1084  pixelvalue * value ;
1085  pixelvalue mean ;
1086  int * position ;
1087  int nposition ;
1088  int n, i, j ;
1089  int lx=0;
1090  int ly=0;
1091  float* pidata=NULL;
1092  float* podata=NULL;
1093 
1094  if ( im == NULL )
1095  {
1096  sinfo_msg_error ("no image input") ;
1097  return NULL ;
1098  }
1099 
1100  image = cpl_image_duplicate ( im ) ;
1101  lx=cpl_image_get_size_x(im);
1102  ly=cpl_image_get_size_y(im);
1103  pidata=cpl_image_get_data(im);
1104  podata=cpl_image_get_data(image);
1105 
1106  /*----------------------------------------------------------------------
1107  * go through all pixels
1108  */
1109 
1110  for ( i = 0 ; i < (int) lx*ly ; i++ )
1111  {
1112  /* blank pixels are not replaced */
1113  if ( isnan(pidata[i]) )
1114  {
1115  continue ;
1116  }
1117 
1118  /* initialize the buffer variables for the 2 nearest
1119  spectral neighbors */
1120  value = (pixelvalue * )cpl_calloc ( 4, sizeof ( pixelvalue * ) ) ;
1121  position = ( int * ) cpl_calloc ( 4, sizeof ( int * ) ) ;
1122 
1123  /*--------------------------------------------------------------------
1124  * determine the pixel position of the 8 nearest neighbors
1125  */
1126 
1127  position[0] = i + lx ; /* upper */
1128  position[1] = i + 2*lx ; /* upper */
1129  position[2] = i - lx ; /* lower */
1130  position[3] = i - 2*lx ; /* lower */
1131 
1132  /*-------------------------------------------------------------------
1133  * determine the positions of the image margins, top positions are
1134  * changed to low positions and vice versa. Right positions are changed
1135  * to left positions and vice versa.
1136  */
1137 
1138  if ( i >= 0 && i < lx ) /* bottom line */
1139  {
1140  position[2] += 2 * lx ;
1141  position[3] += 4 * lx ;
1142  }
1143  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
1144  {
1145  position[0] -= 2 * lx ;
1146  position[1] -= 4 * lx ;
1147  }
1148 
1149  /* -------------------------------------------------------------------
1150  * read the pixel values of the neighboring pixels,
1151  * blanks are not considered
1152  */
1153 
1154  nposition = 4 ;
1155  n = 0 ;
1156  for ( j = 0 ; j < nposition ; j ++ )
1157  {
1158  if ( !isnan(pidata[position[j]]) )
1159  {
1160  value[n] = pidata[position[j]] ;
1161  n ++ ;
1162  }
1163  }
1164  nposition = n ;
1165 
1166  if ( nposition < 1 ) /* all neighbors are blank */
1167  {
1168  podata[i] = ZERO ;
1169  cpl_free(value) ;
1170  cpl_free(position) ;
1171  continue ;
1172  }
1173 
1174  /* determine the mean */
1175  mean = 0. ;
1176  for ( n = 0 ; n < nposition ; n++ )
1177  {
1178  mean += value[n] ;
1179  }
1180  mean /= (float) nposition ;
1181 
1182  /* -----------------------------------------------------------------
1183  * replace the pixel value by the median on conditions:
1184  * fmedian = 0:","always replace with mean.
1185  * fmedian < 0: interpret as absolute condition:
1186  * if |pixel - mean| > -fmedian
1187  * replace with mean.
1188  */
1189 
1190  if ( fmedian == 0 )
1191  {
1192  podata[i] = mean ;
1193  }
1194  else if ( fmedian < 0 &&
1195  fabs ( mean - pidata[i] ) >= -fmedian )
1196  {
1197  podata[i] = mean ;
1198  }
1199  else if ( fmedian > 0 &&
1200  fabs ( mean - pidata[i] ) >= fmedian * sqrt(fabs(mean)) )
1201  {
1202  podata[i] = mean ;
1203  }
1204  else
1205  {
1206  cpl_free (value) ;
1207  cpl_free (position) ;
1208  continue ;
1209  }
1210 
1211  cpl_free (value) ;
1212  cpl_free (position) ;
1213  }
1214  return image ;
1215 }
1216 
1217 
1218 
1219 
1220 
1221 
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69
#define sinfo_msg_warning(...)
Print an warning message.
Definition: sinfo_msg.h:93