SINFONI Pipeline Reference Manual  2.6.0
sinfo_merge.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 * schreib 04/07/00 created
27 */
28 
29 /************************************************************************
30 * NAME
31 * sinfo_merge.c - merges the rows of two image data frames into
32 * one frame with doubled column length
33 *
34 * SYNOPSIS
35 * #include "merge.h"
36 *
37 * a) cpl_image * sinfo_sinfo_merge_images ( cpl_image * im1,
38 * cpl_image * im2,
39 * cpl_image * res_image )
40 *
41 * 1) cpl_image * sinfo_new_remove_general_offset( cpl_image * im1,
42 * cpl_image * im2,
43 * cpl_image * res_image,
44 * int n )
45 *
46 * 2) cpl_image * sinfo_new_remove_regional_tilt ( cpl_image * im1,
47 * cpl_image * im2,
48 * cpl_image * res_image )
49 *
50 * 3) cpl_image * sinfo_new_remove_column_offset ( cpl_image * im1,
51 * cpl_image * im2,
52 * cpl_image * res_image )
53 *
54 * 4) cpl_image * sinfo_new_remove_residual_tilt ( cpl_image * im2,
55  cpl_image * res_image )
56 *
57 * 5) cpl_image * sinfo_new_remove_residual_offset( cpl_image * im2,
58  cpl_image * res_image )
59 *
60 * DESCRIPTION
61 * a) merges the rows of two image frames in a way that the resulting
62 * image has double length in y-direction
63 *
64 * The procedures are used in the SPIFFI data reduction to merge two
65 * data frames. In order to fully match the two input frames there
66 * are five steps (procedures) foreseen:
67 * 1) remove general offset between the frames, created by e.g. different
68 * air masses.
69 * 2) remove regional tilt between frames, created by e.g. different
70 * emissivities.
71 * 3) remove individual column offsets, created e.g. by imperfect
72 * guiding, offset is divided out.
73 * 4) remove residual individual column tilts, created by previous
74 * operations.
75 * 5) remove residual column offsets by subtracting the sinfo_median.
76 *
77 * FILES
78 *
79 * ENVIRONMENT
80 *
81 * RETURN VALUES
82 * always the pointer to the image data structure cpl_image
83 *
84 * CAUTIONS
85 *
86 * EXAMPLES
87 *
88 * SEE ALSO
89 * Python script merging.py
90 *
91 * BUGS
92 *
93 *------------------------------------------------------------------------
94 */
95 
96 #ifdef HAVE_CONFIG_H
97 # include <config.h>
98 #endif
99 #include "sinfo_vltPort.h"
100 
101 /*
102  * System Headers
103  */
104 
105 /*
106  * Local Headers
107  */
108 
109 #include "sinfo_merge.h"
110 #include "sinfo_globals.h"
130 cpl_image * sinfo_sinfo_merge_images ( cpl_image * im1,
131  cpl_image * im2,
132  cpl_image * res_image )
133 {
134  cpl_image * out_image ;
135  cpl_image * residual ;
136  int i, j ;
137 
138  int lx1=0;
139  int ly1=0;
140  int lx2=0;
141  int ly2=0;
142 
143 
144  float* pi1data=NULL;
145  float* pi2data=NULL;
146  float* pirdata=NULL;
147  float* poutdata=NULL;
148  float* ptmpdata=NULL;
149 
150 
151 
152  if ( im1 == NULL || im2 == NULL || res_image == NULL)
153  {
154  sinfo_msg_error (" null image as input") ;
155  return NULL ;
156  }
157  lx1=cpl_image_get_size_x(im1);
158  ly1=cpl_image_get_size_y(im1);
159 
160  lx2=cpl_image_get_size_x(im2);
161  ly2=cpl_image_get_size_y(im2);
162 
163 
164 
165  pi1data=cpl_image_get_data_float(im1);
166  pi2data=cpl_image_get_data_float(im2);
167  pirdata=cpl_image_get_data_float(res_image);
168 
169 
170  if ( lx1 != lx2 || ly1 != ly2 )
171  {
172  sinfo_msg_error ("input images are not compatible in size") ;
173  return NULL ;
174  }
175 
176  /* allocate memory */
177  if ( NULL == (out_image = cpl_image_new (lx1, 2 * ly1,CPL_TYPE_FLOAT)) )
178  {
179  sinfo_msg_error (" cannot allocate new image") ;
180  return NULL ;
181  }
182  poutdata=cpl_image_get_data_float(out_image);
183 
184  if ( NULL == (residual = cpl_image_new (lx1, ly1,CPL_TYPE_FLOAT)) )
185  {
186  sinfo_msg_error (" cannot allocate new image ") ;
187  return NULL ;
188  }
189  ptmpdata=cpl_image_get_data_float(residual);
190 
191  /* now compute the final residual image */
192  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
193  {
194  if ( isnan(pi1data[i]) || isnan(pi2data[i]) )
195  {
196  ptmpdata[i] = ZERO ;
197  }
198  else
199  {
200  ptmpdata[i] = pi1data[i] - pi2data[i] ;
201  }
202  pirdata[i] = ptmpdata[i] ;
203  }
204 
205  /* now merge the two images */
206  for ( i = 0 ; i < ly1 ; i ++ )
207  {
208  for ( j = 0 ; j < lx1 ; j ++ )
209  {
210  /* transfer rows to output */
211  poutdata[2*i*lx1 + j] = pi1data[i*lx1 + j] ;
212  poutdata[(2*i+1) * lx1 + j] = pi2data[i*lx1 + j] ;
213  }
214  }
215 
216  cpl_image_delete (residual) ;
217 
218  return out_image ;
219 }
220 
221 
238 cpl_image * sinfo_new_remove_general_offset( cpl_image * im1,
239  cpl_image * im2,
240  cpl_image * res_image,
241  int n )
242 {
243  cpl_image * out_image ;
244  cpl_image * residual ;
245  pixelvalue sum, sqr_sum ;
246  pixelvalue mean, stdev ;
247  int i, npix ;
248 
249  int lx1=0;
250  int ly1=0;
251  int lx2=0;
252  int ly2=0;
253  /*
254  int lxr=0;
255  int lyr=0;
256  */
257  int lxt=0;
258  int lyt=0;
259 
260  float* pi1data=NULL;
261  float* pi2data=NULL;
262 
263  float* poutdata=NULL;
264  float* ptmpdata=NULL;
265 
266 
267 
268  if ( im1 == NULL || im2 == NULL )
269  {
270  sinfo_msg_error (" null image as input") ;
271  return NULL ;
272  }
273  lx1=cpl_image_get_size_x(im1);
274  ly1=cpl_image_get_size_y(im1);
275 
276  lx2=cpl_image_get_size_x(im2);
277  ly2=cpl_image_get_size_y(im2);
278 
279 
280 
281  pi1data=cpl_image_get_data_float(im1);
282  pi2data=cpl_image_get_data_float(im2);
283 
284 
285  if ( lx1 != lx2 || ly1 != ly2 )
286  {
287  sinfo_msg_error (" input images are not compatible in size") ;
288  return NULL ;
289  }
290 
291  if ( n <= 0 )
292  {
293  sinfo_msg_error("number of rows for offset determination "
294  "is 0 or smaller ") ;
295  return NULL ;
296  }
297 
298  /* allocate memory */
299  if ( NULL == (residual = cpl_image_new (lx1, ly1, CPL_TYPE_FLOAT)) )
300  {
301  sinfo_msg_error (" cannot allocate new image ") ;
302  return NULL ;
303  }
304 
305  out_image = cpl_image_duplicate( im2 ) ;
306  poutdata=cpl_image_get_data_float(out_image);
307  ptmpdata=cpl_image_get_data_float(residual);
308  lxt=cpl_image_get_size_x(residual);
309  lyt=cpl_image_get_size_y(residual);
310 
311  /* ---------------------------------------------------------------------
312  * first we determine the "good" pixels and subtract the two images
313  * then we determine the mean and 3 sigma
314  */
315 
316  sum = 0. ;
317  sqr_sum = 0. ;
318  npix = 0 ;
319  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
320  {
321  if ( isnan(pi1data[i]) || isnan(pi2data[i]) )
322  {
323  ptmpdata[i] = ZERO ;
324  continue ;
325  }
326  else
327  {
328  ptmpdata[i] = pi1data[i] - pi2data[i] ;
329  }
330 
331  sum += ptmpdata[i] ;
332  sqr_sum += (ptmpdata[i]) * (ptmpdata[i]) ;
333  npix ++ ;
334  }
335  if ( npix <= 1 )
336  {
337  mean = 0. ;
338  stdev = 0. ;
339  }
340  else
341  {
342  mean = sum / (pixelvalue) npix ;
343  /* stdev is 3 sigma */
344  stdev = 3 * sqrt(( sqr_sum - sum*mean ) / (pixelvalue)(npix - 1)) ;
345  }
346 
347  /* exclude everything > 3 sigma */
348 
349  for ( i = 0 ; i < (int) lxt*lyt ; i++ )
350  {
351  if ( fabs( ptmpdata[i] - mean ) > stdev )
352  {
353  ptmpdata[i] = ZERO ;
354  }
355  }
356 
357  /* now subtract the general offset which is determined
358  as mean of the first n rows */
359 
360  sum = 0. ;
361  npix = 0 ;
362  for ( i = 0 ; i < n * lxt ; i++ )
363  {
364  if ( isnan(ptmpdata[i]) )
365  {
366  continue ;
367  }
368 
369  sum += ptmpdata[i] ;
370  npix ++ ;
371  }
372  if ( npix == 0 )
373  {
374  mean = 0. ;
375  }
376  else
377  {
378  mean = sum / (pixelvalue) npix ;
379  }
380 
381  /* now apply this to the second input image */
382  for ( i = 0 ; i < (int) lx2*ly2 ; i++ )
383  {
384  if ( isnan(pi2data[i]) )
385  {
386  poutdata[i] = ZERO ;
387  continue ;
388  }
389  poutdata[i] = pi2data[i] + mean ;
390  }
391 
392  /* now determine the residual image if available */
393  if ( res_image != NULL )
394  {
395  /*
396  lxr=cpl_image_get_size_x(res_image);
397  lyr=cpl_image_get_size_y(res_image);
398  */
399  float* pirdata=cpl_image_get_data_float(res_image);
400 
401 
402  for ( i = 0 ; i < (int) lxt*lyt ; i++ )
403  {
404  if ( isnan(ptmpdata[i]) )
405  {
406  pirdata[i] = ZERO ;
407  continue ;
408  }
409  pirdata[i] = ptmpdata[i] - mean ;
410  }
411  }
412 
413  cpl_image_delete (residual) ;
414 
415  return out_image ;
416 }
417 
430 cpl_image * sinfo_new_remove_regional_tilt ( cpl_image * im1,
431  cpl_image * im2,
432  cpl_image * res_image )
433 {
434  cpl_image * out_image ;
435  cpl_image * filtered ;
436  int i, j, k, npix, nrunning ;
437  pixelvalue a, b, sum;
438  int lx1=0;
439  int ly1=0;
440  int lx2=0;
441  int ly2=0;
442  int lxr=0;
443  int lyr=0;
444  int lxf=0;
445  int lyf=0;
446 
447  float* pi1data=NULL;
448  /* float* pi2data=NULL; */
449 
450  float* pirdata=NULL;
451  float* poutdata=NULL;
452  float* pfildata=NULL;
453 
454 
455  if ( im1 == NULL || im2 == NULL || res_image == NULL )
456  {
457  sinfo_msg_error ("null image as input") ;
458  return NULL ;
459  }
460  lx1=cpl_image_get_size_x(im1);
461  ly1=cpl_image_get_size_y(im1);
462 
463  lx2=cpl_image_get_size_x(im2);
464  ly2=cpl_image_get_size_y(im2);
465 
466  lxr=cpl_image_get_size_x(res_image);
467  lyr=cpl_image_get_size_y(res_image);
468 
469 
470  pi1data=cpl_image_get_data_float(im1);
471  /* pi2data=cpl_image_get_data_float(im2); */
472 
473  pirdata=cpl_image_get_data_float(res_image);
474 
475  if ( lx1 != lx2 || ly1 != ly2 ||
476  lx2 != lxr || ly2 != lyr )
477  {
478  sinfo_msg_error ("input images are not compatible in size") ;
479  return NULL ;
480  }
481 
482  /* allocate memory */
483  if ( NULL == ( filtered = cpl_image_new (lx2, ly2,CPL_TYPE_FLOAT)) )
484  {
485  sinfo_msg_error ("cannot allocate new image ") ;
486  return NULL ;
487  }
488 
489  out_image = cpl_image_duplicate( im2 ) ;
490  poutdata=cpl_image_get_data_float(out_image);
491  pfildata=cpl_image_get_data_float(filtered);
492  lxf=cpl_image_get_size_x(filtered);
493  lyf=cpl_image_get_size_y(filtered);
494 
495  /*-------------------------------------------------------------------------
496  * Now work in the given difference image res_image on each
497  column separately. This image is first smoothed columnwise
498  by a running box
499  */
500 
501  nrunning = 31 ; /* # of points in the running box, odd number required */
502 
503  for ( j = 0 ; j < lyr ; j ++ ) /* select a row */
504  {
505  for ( i = 0 ; i < lxr ; i ++ ) /* go through one row */
506  {
507  npix = 0 ;
508  sum = 0. ;
509  for (k = i - (nrunning-1)/2 ; k < i + (nrunning+1)/2; k ++ )
510  {
511  /* marginal pixels are not considered */
512  if ( k < 2 )
513  {
514  continue ;
515  }
516  if ( k > (lxr) - 2 )
517  {
518  break ;
519 
520  }
521  if ( isnan(pirdata[j*lxr + k]) )
522  {
523  continue ;
524  }
525  npix ++ ;
526  sum += pirdata[j*lxr + k] ;
527  }
528  if ( npix != 0 )
529  {
530  pfildata[j*lxr + i] = sum/npix ;
531  }
532  else
533  {
534  pfildata[j*lxr + i] = ZERO ;
535  }
536  }
537  }
538 
539  /*------------------------------------------------------------------
540  * now determine the tilt in each column and remove it in such a way
541  * that the first rows are used as references that are not changed
542  * a free regression fit is (index i means the sum over i):
543  * ax + b: a = [<xiyi>-<xi><yi>]/[<xi^2>-<xi>^2]
544  * => : a = [xiyi - xi<yi>]/[xi^2 - xi<xi>]
545  * b = <yi> - a<xi>
546  */
547 
548  for ( i = 0 ; i < lxf ; i ++ ) /* one column selected */
549  {
550  pixelvalue sumy = 0. ; /* yi */
551  pixelvalue sumc = 0. ; /* xiyi */
552  pixelvalue sumx = 0. ; /* xi */
553  pixelvalue sum2 = 0. ; /* xi^2 */
554  npix = 0 ;
555 
556  for ( j = 0 ; j < lyf ; j ++ )
557  {
558  if ( isnan(pfildata[i + j*lxf]) )
559  {
560  continue ;
561  }
562  sumy += pfildata[i + j*lxf] ;
563  sumc += (pfildata[i + j*lxf]) * j ;
564  sum2 += j*j ;
565  sumx += j ;
566  npix ++ ;
567  }
568  if ( npix > 2 && fabs(sum2 - sumx*sumx/npix) >= 1e-6 )
569  {
570  a = ( sumc - sumx*sumy/npix ) / ( sum2 - sumx*sumx/npix ) ;
571  b = ( sumy - a*sumx ) / npix ;
572  }
573  else
574  {
575  a = ZERO ;
576  b = ZERO ;
577  }
578 
579  /*-----------------------------------------------------------
580  * now correct the second input image im2 and the res_image.
581  */
582 
583  if ( !isnan(a) && !isnan(b) && fabs(a) < 1e8 && fabs(b) < 1e8 )
584  {
585  for ( j = 0 ; j < lyf ; j ++ ) /* the same column */
586  {
587  if ( !isnan(poutdata[i + j*lxf]) )
588  {
589  poutdata[i + j*lxf] += a*j+b ;
590  }
591  }
592  }
593  }
594 
595  /* now compute the final residual image */
596  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
597  {
598  if ( isnan(pi1data[i]) || isnan(poutdata[i]) )
599  {
600  pirdata[i] = ZERO ;
601  }
602  else
603  {
604  pirdata[i] = pi1data[i] - poutdata[i] ;
605  }
606  }
607 
608  cpl_image_delete (filtered) ;
609 
610  return out_image ;
611 }
612 
613 
626 cpl_image * sinfo_new_remove_column_offset ( cpl_image * im1,
627  cpl_image * im2,
628  cpl_image * res_image )
629 {
630  cpl_image * out_image ;
631  int i, j, nrunning ;
632  pixelvalue mean, stdev, median1, median2, ratio ;
633  pixelvalue * column1, * column2 ;
634  int lx1=0;
635  int ly1=0;
636  int lx2=0;
637  int ly2=0;
638  int lxr=0;
639  int lyr=0;
640  float* pi1data=NULL;
641  float* pi2data=NULL;
642  float* pirdata=NULL;
643  float* poutdata=NULL;
644 
645  if ( im1 == NULL || im2 == NULL || res_image == NULL )
646  {
647  sinfo_msg_error ("null image as input") ;
648  return NULL ;
649  }
650  lx1=cpl_image_get_size_x(im1);
651  ly1=cpl_image_get_size_y(im1);
652 
653  lx2=cpl_image_get_size_x(im2);
654  ly2=cpl_image_get_size_y(im2);
655 
656  lxr=cpl_image_get_size_x(res_image);
657  lyr=cpl_image_get_size_y(res_image);
658 
659 
660  pi1data=cpl_image_get_data_float(im1);
661  pi2data=cpl_image_get_data_float(im2);
662  pirdata=cpl_image_get_data_float(res_image);
663 
664  if ( lx1 != lx2 || ly1 != ly2 ||
665  lx2 != lxr || ly2 != lyr )
666  {
667  sinfo_msg_error ("input images are not compatible in size") ;
668  return NULL ;
669  }
670 
671  out_image = cpl_image_duplicate( im2 ) ;
672  poutdata=cpl_image_get_data_float(out_image);
673 
674  /*-------------------------------------------------------------------------
675  * now we deal with a constant offset in every column. We assume that it
676  is due to redistribution of the flux. So we should divide the offset
677  out. The ratio is derived from the medians of the contributions
678  rather than the means.
679  */
680 
681  for ( i = 0 ; i < lx2 ; i ++ ) /* select a column */
682  {
683  /* statistics on columns */
684  pixelvalue sum = 0. ;
685  pixelvalue sum2 = 0. ;
686  int npix = 0 ;
687  for ( j = 0 ; j < ly2 ; j ++ )
688  {
689  /* first select only the good pixels */
690  if ( isnan(pirdata[i + j*lxr]) )
691  {
692  continue ;
693  }
694  sum += pirdata[i + j*lxr] ;
695  sum2 += pirdata[i + j*lxr] *
696  pirdata[i + j*lxr] ;
697  npix ++ ;
698  }
699  if ( npix <= 1 )
700  {
701  continue ;
702  }
703  else
704  {
705  mean = sum/(pixelvalue) npix ;
706  if ( (sum2 - sum * mean) < 0 )
707  {
708  sinfo_msg_error ("variance is negative") ;
709  continue ;
710  }
711  else
712  {
713  /* 2 sigma */
714  stdev = 2 * sqrt ( (sum2 - sum*mean)/(pixelvalue)(npix - 1) ) ;
715  }
716  }
717 
718  /* do it only if the S/N is high enough */
719  if ( fabs(mean)/stdev < 0.5 )
720  {
721  continue ;
722  }
723 
724  /* exclude everything > 2 sigma */
725  for ( j = 0 ; j < lyr ; j ++ )
726  {
727  if ( pirdata[i + j*lxr] < mean - stdev ||
728  pirdata[i + j*lxr] > mean + stdev )
729  {
730  pirdata[i + j*lxr] = ZERO ;
731  }
732  }
733 
734  /* now deal with the offset */
735  median1 = 0. ;
736  median2 = 0. ;
737  nrunning = 0 ;
738  /* allocate memory for the column buffers */
739  column1 = (pixelvalue *) cpl_calloc ( ly1 , sizeof (pixelvalue *) ) ;
740  column2 = (pixelvalue *) cpl_calloc ( ly2 , sizeof (pixelvalue *) ) ;
741 
742  for ( j = 0 ; j < lyr ; j++ ) /* go through one column */
743  {
744  if ( isnan(pirdata[i + j*lxr]) )
745  {
746  continue ;
747  }
748  if ( isnan(pi1data[i+j*lx1]) || isnan(pi2data[i+j*lx2]) )
749  {
750  continue ;
751  }
752  column1[nrunning] = pi1data[i + j*lx1] ;
753  column2[nrunning] = pi2data[i + j*lx2] ;
754  nrunning ++ ;
755  }
756 
757  /* change the second input image only if there are more then
758  10 % good pixels in a column */
759  if ( nrunning > 0.1*lyr )
760  {
761  /* --------------------------------------------------------------
762  * determine the medians of the columns of both images and compute
763  the ratio, the columns of the second input image are multiplied
764  by this ratio to adjust the column offsets.
765  */
766  median2 = sinfo_new_median( column2, nrunning ) ;
767  if ( median2 != 0. )
768  {
769  median1 = sinfo_new_median( column1, nrunning ) ;
770  ratio = median1 / median2 ;
771  if ( ratio > 0 )
772  {
773  for ( j = 0 ; j < ly2 ; j++ ) /* go through one column */
774  {
775  if ( !isnan(pi2data[i + j*lx2]) )
776  {
777  poutdata[i + j*lx2] = pi2data[i + j*lx2] * ratio ;
778  }
779  else
780  {
781  poutdata[i + j*lx2] = ZERO ;
782  }
783  }
784  }
785  }
786  }
787  cpl_free ( column1 ) ;
788  cpl_free ( column2 ) ;
789  }
790 
791  /* now compute the final residual image */
792  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
793  {
794  if ( isnan(pi1data[i]) || isnan(poutdata[i]) )
795  {
796  pirdata[i] = ZERO ;
797  }
798  else
799  {
800  pirdata[i] = pi1data[i] - poutdata[i] ;
801  }
802  }
803 
804  return out_image ;
805 }
806 
807 
817 cpl_image *
818 sinfo_new_remove_residual_tilt ( cpl_image * im2, cpl_image * res_image )
819 {
820  cpl_image * out_image ;
821  cpl_image * residual ;
822  int i, j ;
823  pixelvalue a, b, sumx, sumy, sumc, mean, stdev ;
824  int lx2=0;
825  int ly2=0;
826  int rlx=0;
827  int rly=0;
828  /* float* pi2data=NULL; */
829  float* pirdata=NULL;
830  float* poutdata=NULL;
831  float* ptmpdata=NULL;
832 
833 
834 
835 
836  if ( im2 == NULL || res_image == NULL )
837  {
838  sinfo_msg_error ("null image as input") ;
839  return NULL ;
840  }
841  lx2=cpl_image_get_size_x(im2);
842  ly2=cpl_image_get_size_y(im2);
843  rlx=cpl_image_get_size_x(res_image);
844  rly=cpl_image_get_size_y(res_image);
845  /* pi2data=cpl_image_get_data_float(im2); */
846  pirdata=cpl_image_get_data_float(res_image);
847 
848  if ( lx2 != rlx || ly2 != rly )
849  {
850  sinfo_msg_error ("input images are not compatible in size") ;
851  return NULL ;
852  }
853 
854  out_image = cpl_image_duplicate( im2 ) ;
855  residual = cpl_image_duplicate( res_image ) ;
856  poutdata=cpl_image_get_data_float(out_image);
857  ptmpdata=cpl_image_get_data_float(residual);
858 
859  for ( i = 0 ; i < lx2; i++ ) /* select one column */
860  {
861  pixelvalue sum = 0. ;
862  pixelvalue sum2 = 0. ;
863  int npix = 0 ;
864  for ( j = 0 ; j < ly2 ; j++ )
865  {
866  /* first select good pixels and derive the mean
867  and sigma of each column */
868  if ( isnan(pirdata[i + j*rlx]) )
869  {
870  continue ;
871  }
872  sum += pirdata[i + j*rlx] ;
873  sum2 += pirdata[i + j*rlx] *
874  pirdata[i + j*rlx] ;
875  npix ++ ;
876  }
877 
878  if ( npix <= 1 )
879  {
880  continue ;
881  }
882  else
883  {
884  mean = sum / (pixelvalue) npix ;
885  stdev = 1.5 * sqrt( (sum2 - sum*mean) / (pixelvalue)(npix - 1) ) ;
886  }
887 
888  /* exclude everything > 1.5 sigma */
889  for ( j = 0 ; j < ly2 ; j++ )
890  {
891  if ( pirdata[i + j*rlx] < mean - stdev ||
892  pirdata[i + j*rlx] > mean + stdev )
893  {
894  pirdata[i + j*rlx] = ZERO ;
895  }
896  }
897 
898  /* now determine the tilt, see function sinfo_removeRegionalTilt
899  for explanation */
900  sumy = 0. ; /* yi */
901  sumc = 0. ; /* xiyi */
902  sumx = 0. ; /* xi */
903  sum2 = 0. ; /* xi^2 */
904  npix = 0 ;
905 
906  for ( j = 0 ; j < rly ; j ++ )
907  {
908  if ( isnan(pirdata[i + j*rlx]) )
909  {
910  continue ;
911  }
912  sumy += pirdata[i + j*rlx] ;
913  sumc += (pirdata[i + j*rlx]) * j ;
914  sum2 += j*j ;
915  sumx += j ;
916  npix ++ ;
917  }
918  if ( npix > 2 && fabs(sum2 - sumx*sumx/npix) >= 1e-6 )
919  {
920  a = ( sumc - sumx*sumy/npix ) / ( sum2 - sumx*sumx/npix ) ;
921  b = ( sumy - a*sumx ) / npix ;
922  }
923  else
924  {
925  a = ZERO ;
926  b = ZERO ;
927  }
928 
929  /*-------------------------------------------------------------------
930  * now correct the second input image im2 and the res_image.
931  */
932 
933  if ( !isnan(a) && !isnan(b) && fabs(a) < 1e8 && fabs(b) < 1e8 )
934  {
935  for ( j = 0 ; j < ly2 ; j ++ ) /* the same column */
936  {
937  if ( !isnan(poutdata[i+j*lx2]) )
938  {
939  poutdata[i + j*lx2] += a*j+b ;
940  pirdata[i + j*lx2] = ptmpdata[i + j*lx2] -(a*j+b) ;
941  }
942  }
943  }
944  }
945 
946  cpl_image_delete (residual) ;
947 
948  return out_image ;
949 }
950 
951 
962 cpl_image *
963 sinfo_new_remove_residual_offset( cpl_image * im2, cpl_image * res_image )
964 {
965  cpl_image * out_image ;
966  int i, j;
967  pixelvalue res_median ;
968  pixelvalue * column ;
969  int lx2=0;
970  int ly2=0;
971  int rlx=0;
972  int rly=0;
973  /*
974  int olx=0;
975  int oly=0;
976  */
977  float* pi2data=NULL;
978  float* pirdata=NULL;
979  float* poudata=NULL;
980 
981 
982  if ( im2 == NULL || res_image == NULL )
983  {
984  sinfo_msg_error ("null image as input") ;
985  return NULL ;
986  }
987  lx2=cpl_image_get_size_x(im2);
988  ly2=cpl_image_get_size_y(im2);
989  rlx=cpl_image_get_size_x(res_image);
990  rly=cpl_image_get_size_y(res_image);
991  pi2data=cpl_image_get_data_float(im2);
992  pirdata=cpl_image_get_data_float(res_image);
993 
994 
995  if ( lx2 != rlx || ly2 != rly )
996  {
997  sinfo_msg_error ("input images are not compatible in size") ;
998  return NULL ;
999  }
1000 
1001  out_image = cpl_image_duplicate( im2 ) ;
1002  poudata=cpl_image_get_data_float(res_image);
1003  /*
1004  olx=cpl_image_get_size_x(res_image);
1005  oly=cpl_image_get_size_y(res_image);
1006  */
1007  column = (pixelvalue *) cpl_calloc ( ly2 , sizeof (pixelvalue *) ) ;
1008 
1009  for ( i = 0 ; i < lx2 ; i++ ) /* select one column */
1010  {
1011  int npix = 0 ;
1012  for (j=0;j<ly2;j++)
1013  column[j]=0;
1014 
1015  for ( j = 0 ; j < rly ; j++ ) /* go through one column */
1016  {
1017  if ( isnan(pirdata[i + j*rlx]) )
1018  {
1019  continue ;
1020  }
1021 
1022  column[npix] = pirdata[i + j*rlx] ;
1023  npix ++ ;
1024  }
1025 
1026  /* determine the sinfo_median of a column of the residual image */
1027  if ( npix > 0.1 * rly )
1028  {
1029  res_median = sinfo_new_median( column, npix ) ;
1030  }
1031  else
1032  {
1033  continue ;
1034  }
1035 
1036  for ( j = 0 ; j < ly2 ; j++ ) /* go through one column */
1037  {
1038  if ( !isnan(pi2data[i+j*lx2]))
1039  {
1040  poudata[i + j*lx2] = pi2data[i + j*lx2] + res_median ;
1041  }
1042  else
1043  {
1044  poudata[i + j*lx2] = ZERO ;
1045  }
1046  if ( !isnan(pirdata[i + j*rlx]) )
1047  {
1048  pirdata[i + j*rlx] -= res_median ;
1049  }
1050  }
1051  }
1052  cpl_free ( column ) ;
1053  return out_image ;
1054 }
1056 /*___oOo___*/
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69