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