SINFONI Pipeline Reference Manual  2.6.0
sinfo_boltzmann.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  * who when what
23  * -------- -------- ----------------------------------------------
24  * schreib 27/02/01 created
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30 #include "sinfo_vltPort.h"
31 
32 /*
33  * System Headers
34  */
35 
36 /*
37  * Local Headers
38  */
39 
40 #include "sinfo_absolute.h"
41 #include "sinfo_recipes.h"
42 
43 /*----------------------------------------------------------------------------
44  * Defines
45  *--------------------------------------------------------------------------*/
46 
47 #define XDIMA 1 /* dimension of the x values */
48 #define TOLA 0.001 /* fitting tolerance */
49 #define LABA 0.1 /* labda parameter */
50 #define ITSA 200 /* maximum number of iterations */
51 #define LABFACA 10.0 /* labda step factor */
52 #define LABMAXA 1.0e+10 /* maximum value for labda */
53 #define LABMINA 1.0e-10 /* minimum value for labda */
54 #define NPAR 4 /* number of fit parameters */
55 
56 /*----------------------------------------------------------------------------
57  * Local variables
58  *--------------------------------------------------------------------------*/
59 
60 static double chi1 ; /* old reduced chi-squared */
61 static double chi2 ; /* new reduced chi-squared */
62 static double labda ; /* mixing parameter */
63 static double vec[NPAR] ; /* correction sinfo_vector */
64 static double matrix1[NPAR][NPAR] ; /* original sinfo_matrix */
65 static double matrix2[NPAR][NPAR] ; /* inverse of matrix1 */
66 static int nfree ; /* number of free parameters */
67 static int parptr[NPAR] ; /* parameter pointer */
68 
69 /*----------------------------------------------------------------------------
70  * Functions private to this module
71  *--------------------------------------------------------------------------*/
72 
73 static int sinfo_new_inv_mat (void) ;
74 
75 static void sinfo_new_get_mat ( float * xdat,
76  int * xdim,
77  float * ydat,
78  float * wdat,
79  int * ndat,
80  float * fpar,
81  float * epar/*,
82  int * npar*/ ) ;
83 
84 static int sinfo_new_get_vec ( float * xdat,
85  int * xdim,
86  float * ydat,
87  float * wdat,
88  int * ndat,
89  float * fpar,
90  float * epar,
91  int * npar ) ;
100 /*----------------------------------------------------------------------------
101  * Function codes
102  *--------------------------------------------------------------------------*/
103 
125 float sinfo_new_boltz ( float * xdat, float * parlist )
126 {
127  float return_value ;
128 
129  /* now build the boltzman function out of the parameters */
130  return_value =
131  (parlist[0] - parlist[1]) / (1 + exp(( xdat[0] - parlist[2] ) /
132  parlist[3])) + parlist[1] ;
133 
134  return return_value ;
135 }
136 
159 void sinfo_new_boltz_deriv( float * xdat, float * parlist, float * dervs )
160 {
161  float subst ;
162 
163  subst = (xdat[0] - parlist[2]) / parlist[3] ;
164 
165  dervs[0] = 1. / ( 1. + exp(subst) ) ;
166 
167  dervs[1] = -1. / ( 1. + exp(subst) ) + 1. ;
168 
169  dervs[2] = ( (parlist[0] - parlist[1]) / parlist[3] * exp(subst) ) /
170  ( (1. + exp(subst)) * (1. + exp(subst)) ) ;
171 
172  dervs[3] = ( (parlist[0] - parlist[1]) * (xdat[0] - parlist[2]) /
173  (parlist[3]*parlist[3]) * exp(subst) ) /
174  ( (1. + exp(subst)) * (1. + exp(subst)) ) ;
175 }
176 
188 static int sinfo_new_inv_mat (void)
189 {
190  double even ;
191  double hv[NPAR] ;
192  double mjk ;
193 
194  int evin ;
195  int i, j, k;
196  int per[NPAR] ;
197 
198  /* set permutation array */
199  for ( i = 0 ; i < nfree ; i++ )
200  {
201  per[i] = i ;
202  }
203 
204  for ( j = 0 ; j < nfree ; j++ ) /* in j-th column */
205  {
206  /* determine largest element of a row */
207  double rowmax = fabs ( matrix2[j][j] ) ;
208  int row = j ;
209 
210  for ( i = j + 1 ; i < nfree ; i++ )
211  {
212  if ( fabs ( matrix2[i][j] ) > rowmax )
213  {
214  rowmax = fabs( matrix2[i][j] ) ;
215  row = i ;
216  }
217  }
218 
219  /* determinant is zero! */
220  if ( matrix2[row][j] == 0.0 )
221  {
222  return -6 ;
223  }
224 
225  /* if the largest element is not on the diagonal, then permutate rows */
226  if ( row > j )
227  {
228  for ( k = 0 ; k < nfree ; k++ )
229  {
230  even = matrix2[j][k] ;
231  matrix2[j][k] = matrix2[row][k] ;
232  matrix2[row][k] = even ;
233  }
234  /* keep track of permutation */
235  evin = per[j] ;
236  per[j] = per[row] ;
237  per[row] = evin ;
238  }
239 
240  /* modify column */
241  even = 1.0 / matrix2[j][j] ;
242  for ( i = 0 ; i < nfree ; i++ )
243  {
244  matrix2[i][j] *= even ;
245  }
246  matrix2[j][j] = even ;
247 
248  for ( k = 0 ; k < j ; k++ )
249  {
250  mjk = matrix2[j][k] ;
251  for ( i = 0 ; i < j ; i++ )
252  {
253  matrix2[i][k] -= matrix2[i][j] * mjk ;
254  }
255  for ( i = j + 1 ; i < nfree ; i++ )
256  {
257  matrix2[i][k] -= matrix2[i][j] * mjk ;
258  }
259  matrix2[j][k] = -even * mjk ;
260  }
261 
262  for ( k = j + 1 ; k < nfree ; k++ )
263  {
264  mjk = matrix2[j][k] ;
265  for ( i = 0 ; i < j ; i++ )
266  {
267  matrix2[i][k] -= matrix2[i][j] * mjk ;
268  }
269  for ( i = j + 1 ; i < nfree ; i++ )
270  {
271  matrix2[i][k] -= matrix2[i][j] * mjk ;
272  }
273  matrix2[j][k] = -even * mjk ;
274  }
275  }
276 
277  /* finally, repermute the columns */
278  for ( i = 0 ; i < nfree ; i++ )
279  {
280  for ( k = 0 ; k < nfree ; k++ )
281  {
282  hv[per[k]] = matrix2[i][k] ;
283  }
284  for ( k = 0 ; k < nfree ; k++ )
285  {
286  matrix2[i][k] = hv[k] ;
287  }
288  }
289 
290  /* all is well */
291  return 0 ;
292 }
293 
309 static void sinfo_new_get_mat ( float * xdat,
310  int * xdim,
311  float * ydat,
312  float * wdat,
313  int * ndat,
314  float * fpar,
315  float * epar/*,
316  int * npar*/ )
317 {
318  double wd ;
319  double yd ;
320  int i, j, n ;
321 
322  for ( j = 0 ; j < nfree ; j++ )
323  {
324  vec[j] = 0.0 ; /* zero sinfo_vector */
325  for ( i = 0 ; i<= j ; i++ ) /* zero sinfo_matrix only
326  on and below diagonal */
327  {
328  matrix1[j][i] = 0.0 ;
329  }
330  }
331  chi2 = 0.0 ; /* reset reduced chi-squared */
332 
333  /* loop through data points */
334  for ( n = 0 ; n < (*ndat) ; n++ )
335  {
336  double wn = wdat[n] ;
337  if ( wn > 0.0 ) /* legal weight ? */
338  {
339  yd = ydat[n] - sinfo_new_boltz( &xdat[(*xdim) * n], fpar ) ;
340  sinfo_new_boltz_deriv( &xdat[(*xdim) * n], fpar, epar ) ;
341  chi2 += yd * yd * wn ; /* add to chi-squared */
342  for ( j = 0 ; j < nfree ; j++ )
343  {
344  wd = epar[parptr[j]] * wn ; /* weighted derivative */
345  vec[j] += yd * wd ; /* fill sinfo_vector */
346  for ( i = 0 ; i <= j ; i++ ) /* fill sinfo_matrix */
347  {
348  matrix1[j][i] += epar[parptr[i]] * wd ;
349  }
350  }
351  }
352  }
353 }
354 
355 
379 static int sinfo_new_get_vec ( float * xdat,
380  int * xdim,
381  float * ydat,
382  float * wdat,
383  int * ndat,
384  float * fpar,
385  float * epar,
386  int * npar )
387 {
388 
389  double dy ;
390  double mii ;
391  double mji ;
392  double mjj ;
393 
394  int i, j, n, r ;
395 
396  /* loop to modify and scale the sinfo_matrix */
397  for ( j = 0 ; j < nfree ; j++ )
398  {
399  mjj = matrix1[j][j] ;
400  if ( mjj <= 0.0 ) /* diagonal element wrong */
401  {
402  return -5 ;
403  }
404  mjj = sqrt( mjj ) ;
405  for ( i = 0 ; i < j ; i++ )
406  {
407  mji = matrix1[j][i] / mjj / sqrt( matrix1[i][i] ) ;
408  matrix2[i][j] = matrix2[j][i] = mji ;
409  }
410  matrix2[j][j] = 1.0 + labda ; /* scaled value on diagonal */
411  }
412 
413  if ( (r = sinfo_new_inv_mat()) ) /* sinfo_invert sinfo_matrix inlace */
414  {
415  return r ;
416  }
417 
418  for ( i = 0 ; i < (*npar) ; i ++ )
419  {
420  epar[i] = fpar[i] ;
421  }
422 
423  /* loop to calculate correction sinfo_vector */
424  for ( j = 0 ; j < nfree ; j++ )
425  {
426  double dj = 0.0 ;
427  mjj = matrix1[j][j] ;
428  if ( mjj <= 0.0) /* not allowed */
429  {
430  return -7 ;
431  }
432  mjj = sqrt ( mjj ) ;
433  for ( i = 0 ; i < nfree ; i++ )
434  {
435  mii = matrix1[i][i] ;
436  if ( mii <= 0.0 )
437  {
438  return -7 ;
439  }
440  mii = sqrt( mii ) ;
441  dj += vec[i] * matrix2[j][i] / mjj / mii ;
442  }
443  epar[parptr[j]] += dj ; /* new parameters */
444  }
445  chi1 = 0.0 ; /* reset reduced chi-squared */
446 
447  /* loop through the data points */
448  for ( n = 0 ; n < (*ndat) ; n++ )
449  {
450  double wn = wdat[n] ; /* get weight */
451  if ( wn > 0.0 ) /* legal weight */
452  {
453  dy = ydat[n] - sinfo_new_boltz( &xdat[(*xdim) * n], epar) ;
454  chi1 += wdat[n] * dy * dy ;
455  }
456  }
457  return 0 ;
458 }
459 
460 
461 
516 int sinfo_new_lsqfit ( float * xdat,
517  int * xdim,
518  float * ydat,
519  float * wdat,
520  int * ndat,
521  float * fpar,
522  float * epar,
523  int * mpar,
524  int * npar,
525  float * tol ,
526  int * its ,
527  float * lab )
528 {
529  int i, n, r ;
530  int itc ; /* fate of fit */
531  int found ; /* fit converged: 1, not yet converged: 0 */
532  int nuse ; /* number of useable data points */
533  double tolerance ; /* accuracy */
534 
535  itc = 0 ; /* fate of fit */
536  found = 0 ; /* reset */
537  nfree = 0 ; /* number of free parameters */
538  nuse = 0 ; /* number of legal data points */
539 
540  if ( *tol < (FLT_EPSILON * 10.0 ) )
541  {
542  tolerance = FLT_EPSILON * 10.0 ; /* default tolerance */
543  }
544  else
545  {
546  tolerance = *tol ; /* tolerance */
547  }
548 
549  labda = fabs( *lab ) * LABFACA ; /* start value for mixing parameter */
550  for ( i = 0 ; i < (*npar) ; i++ )
551  {
552  if ( mpar[i] )
553  {
554  if ( nfree > NPAR ) /* too many free parameters */
555  {
556  return -1 ;
557  }
558  parptr[nfree++] = i ; /* a free parameter */
559  }
560  }
561 
562  if (nfree == 0) /* no free parameters */
563  {
564  return -2 ;
565  }
566 
567  for ( n = 0 ; n < (*ndat) ; n++ )
568  {
569  if ( wdat[n] > 0.0 ) /* legal weight */
570  {
571  nuse ++ ;
572  }
573  }
574 
575  if ( nfree >= nuse )
576  {
577  return -3 ; /* no degrees of freedom */
578  }
579  if ( labda == 0.0 ) /* linear fit */
580  {
581  /* initialize fpar array */
582  for ( i = 0 ; i < nfree ; fpar[parptr[i++]] = 0.0 ) ;
583  sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar*/ ) ;
584  r = sinfo_new_get_vec(xdat,xdim,ydat,wdat,ndat,fpar,epar,npar) ;
585  if ( r ) /* error */
586  {
587  return r ;
588  }
589  for ( i = 0 ; i < (*npar) ; i++ )
590  {
591  fpar[i] = epar[i] ; /* save new parameters */
592  epar[i] = 0.0 ; /* and set errors to zero */
593  }
594  chi1 = sqrt( chi1 / (double) (nuse - nfree) ) ;
595  for ( i = 0 ; i < nfree ; i++ )
596  {
597  if ( (matrix1[i][i] <= 0.0 ) || (matrix2[i][i] <= 0.0) )
598  {
599  return -7 ;
600  }
601  epar[parptr[i]] = chi1 * sqrt( matrix2[i][i] ) /
602  sqrt( matrix1[i][i] ) ;
603  }
604  }
605  else /* non-linear fit */
606  {
607  /*----------------------------------------------------------------
608  * the non-linear fit uses the steepest descent method in combination
609  * with the Taylor method. The mixing of these methods is controlled
610  * by labda. In the outer loop ( called the iteration loop ) we build
611  * the sinfo_matrix and calculate the correction sinfo_vector.
612  * In the inner loop
613  * (called the interpolation loop) we check whether we have obtained a
614  * better solution than the previous one. If so, we leave the inner
615  * loop
616  * else we increase labda ( give more weight to the steepest descent
617  * method) calculate the correction sinfo_vector and check again.
618  * After the inner loop
619  * we do a final check on the goodness of the fit and if this satisfies
620  * the tolerance we calculate the errors of the fitted parameters.
621  */
622  while ( !found ) /* iteration loop */
623  {
624  if ( itc++ == (*its) ) /* increase iteration counter */
625  {
626  return -4 ;
627  }
628  sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar */) ;
629 
630  /*-------------------------------------------------------------
631  * here we decrease labda since we may assume that each iteration
632  * brings us closer to the answer.
633  */
634  if ( labda > LABMINA )
635  {
636  labda = labda / LABFACA ; /* decrease labda */
637  }
638  r = sinfo_new_get_vec ( xdat, xdim, ydat, wdat,
639  ndat, fpar, epar, npar ) ;
640 
641  if ( r ) /* error */
642  {
643  return r ;
644  }
645 
646  while ( chi1 >= chi2 ) /* interpolation loop */
647  {
648  /*-----------------------------------------------------------
649  * The next statement is based on experience, not on the
650  * mathematics of the problem. It is assumed that we have
651  * reached convergence when the pure steepest descent method
652  * does not produce a better solution.
653  */
654  if ( labda > LABMAXA ) /* assume solution found */
655  {
656  break ;
657  }
658  labda = labda * LABFACA ; /* increase mixing parameter */
659  r = sinfo_new_get_vec ( xdat, xdim, ydat, wdat,
660  ndat, fpar, epar, npar ) ;
661 
662  if ( r ) /* error */
663  {
664  return r ;
665  }
666  }
667 
668  if ( labda <= LABMAXA ) /* save old parameters */
669  {
670  for ( i = 0 ; i < *npar ; i++ )
671  {
672  fpar[i] = epar[i] ;
673  }
674  }
675  if ( (fabs( chi2 - chi1 ) <= (tolerance * chi1)) ||
676  (labda > LABMAXA) )
677  {
678  /*---------------------------------------------------------
679  * we have a satisfying solution, so now we need to calculate
680  * the correct errors of the fitted parameters. This we do by
681  * using the pure Taylor method because we are very close to
682  * the real solution.
683  */
684  labda = LABMINA ; /* for Taylor solution */
685  sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*,npar*/);
686  r = sinfo_new_get_vec(xdat,xdim,ydat,wdat,ndat,fpar,epar,npar);
687 
688  if ( r ) /* error */
689  {
690  return r ;
691  }
692  for ( i = 0 ; i < (*npar) ; i++ )
693  {
694  epar[i] = 0.0 ; /* set error to zero */
695  }
696  chi2 = sqrt ( chi2 / (double) (nuse - nfree) ) ;
697 
698  for ( i = 0 ; i < nfree ; i++ )
699  {
700  if ( (matrix1[i][i] <= 0.0) || (matrix2[i][i] <= 0.0) )
701  {
702  return -7 ;
703  }
704  epar[parptr[i]] = chi2 * sqrt( matrix2[i][i] ) /
705  sqrt( matrix1[i][i] ) ;
706  }
707  found = 1 ; /* we found a solution */
708  }
709  }
710  }
711  return itc ; /* return number of iterations */
712 }
713 
757 int sinfo_new_fit_slits_boltz ( cpl_image * lineImage,
758  FitParams ** par,
759  float ** slit_pos,
760  int box_length,
761  float y_box,
762  float diff_tol )
763 {
764  float* position=NULL ;
765  int * sinfo_edge, * edgeclean ;
766  int * dummyedge ;
767  int * pos_row, * pos_rowclean ;
768  Vector * box_buffer ;
769  Vector * half_buffer ;
770  Vector * in_buffer ;
771 
772 
773  int row, col ;
774  int i, j, k, n, ed ;
775  int init1 ;
776  int line ;
777  int nel, n_right, left_right ;
778  int n_buf, edge_ind, shift ;
779 
780  int slit_length ;
781  int agreed ;
782  int bad_line ;
783  int margin ;
784  int iters, xdim, ndat ;
785  int numpar, its ;
786  int * mpar ;
787  float * xdat, * wdat ;
788  float tol, lab ;
789  float fitpar[NPAR] ;
790  float dervpar[NPAR] ;
791  float minval, maxval ;
792 
793  float pos, last_pos ;
794  int old_col=0;
795  int old_pos=0;
796  int ilx=0;
797  int ily=0;
798  float* pidata=NULL;
799 
800 
801  slit_length = SLITLENGTH ;
802  if ( NULL == lineImage )
803  {
804  sinfo_msg_error(" no line image given!" ) ;
805  return -1 ;
806  }
807 
808  if ( NULL == par )
809  {
810  sinfo_msg_error(" no line fit parameters given!" ) ;
811  return -2 ;
812  }
813 
814  if ( NULL == slit_pos )
815  {
816  sinfo_msg_error(" no position array allocated!" ) ;
817  return -3 ;
818  }
819 
820  if ( box_length < 4 ||
821  box_length > 2*slit_length )
822  {
823  sinfo_msg_error(" wrong fitting box length given!" ) ;
824  return -4 ;
825  }
826 
827  if ( y_box <= 0. || y_box > 6. )
828  {
829  sinfo_msg_error(" wrong y box length given!" ) ;
830  return -5 ;
831  }
832 
833  if ( diff_tol < 1. )
834  {
835  sinfo_msg_error(" diff_tol too small!" ) ;
836  return -6 ;
837  }
838 
839  /* allocate memory for the edges and the row positon of the slitlets */
840  sinfo_edge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
841  dummyedge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
842  edgeclean = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
843  pos_row = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
844  pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
845 
846 
847  /* -----------------------------------------------------------------------
848  * go through the first image columns and the fit parameters and find the
849  line with the highest intensity
850  */
851  agreed = -1 ;
852  bad_line = -1 ;
853  while( agreed == -1 )
854  {
855  int found = -1 ;
856  float max_intensity = -FLT_MAX ;
857  for ( col = 0 ; col < slit_length ; col++ )
858  {
859  for ( i = 0 ; i < par[0]->n_params ; i++ )
860  {
861  if ( par[i]->column == col && par[i]->line != bad_line )
862  {
863  if ( par[i]->fit_par[0] > max_intensity )
864  {
865  if ( par[i]->fit_par[1] >= 1. &&
866  par[i]->fit_par[2] > 0. )
867  {
868  max_intensity = par[i]->fit_par[0] ;
869  found = i ;
870  }
871  }
872  }
873  }
874  }
875 
876  /* --------------------------------------------------------------------
877  * check if the found line is usable and if the neighbouring line
878  * have intensity on near rows in neighbouring slitlets
879  */
880  line = par[found]->line ;
881  int column = par[found]->column ;
882  double row_pos = par[found]->fit_par[2] ;
883  if ( found >= 0 && max_intensity > 0. )
884  {
885  for ( i = 0 ; i < par[0]->n_params ; i++ )
886  {
887  if ( par[i]->line == line-1 &&
888  par[i]->column == column + slit_length )
889  {
890  if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
891  par[i]->fit_par[2] >= (row_pos - y_box) )
892  {
893  bad_line = line ;
894  }
895  }
896  }
897  if ( bad_line != line )
898  {
899  agreed = 1 ;
900  break ;
901  }
902  }
903  else
904  {
905  sinfo_msg_error("no emission line found in the first image columns") ;
906  cpl_free( sinfo_edge ) ;
907  cpl_free( pos_row ) ;
908  cpl_free( edgeclean ) ;
909  cpl_free( dummyedge ) ;
910  cpl_free( pos_rowclean ) ;
911  return -7 ;
912  }
913  }
914 
915 
916 
917  if ( agreed == -1 )
918  {
919  sinfo_msg_error(" no emission line found in the first image columns") ;
920  cpl_free( sinfo_edge ) ;
921  cpl_free( pos_row ) ;
922  cpl_free( edgeclean ) ;
923  cpl_free( dummyedge ) ;
924  cpl_free( pos_rowclean ) ;
925  return -7 ;
926  }
927 
928  ilx=cpl_image_get_size_x(lineImage);
929  ily=cpl_image_get_size_y(lineImage);
930  pidata=cpl_image_get_data_float(lineImage);
931 
932  /* now find and store the raw sinfo_edge positions of the found slitlet */
933  n = 0 ;
934  ed = 0 ;
935  position=cpl_calloc(ilx,sizeof(float)) ;
936 
937  /* was for ( col = 0 ; col < ilx - slit_length/2 ; col++ ) */
938  for ( col = slit_length/2 ; col < ilx - slit_length/2 ; col++ )
939  {
940  for ( i = 0 ; i < par[0]->n_params ; i++ )
941  {
942  /*
943  printf("p1=%f p2=%f p3=%f\n",
944  par[i]->fit_par[0],par[i]->fit_par[1],par[i]->fit_par[2]);
945  */
946  if ( par[i]->column == col && par[i]->line == line )
947  {
948  if ( par[i]->fit_par[0] > 0. &&
949  par[i]->fit_par[1] >= 1. &&
950  par[i]->fit_par[2] > 0. )
951  {
952  position[n] = par[i]->fit_par[2] ;
953  old_pos=position[n];
954  if ( n > 0 &&
955  fabs(position[n] - position[n-1]) > y_box &&
956  (col-old_col) > (slit_length-SLIT_POS_ERR) )
957  {
958 
959  old_col=col;
960  sinfo_edge[ed] = col ;
961  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
962  /* printf("sinfo_edge[%d]=%d , pos_row=%d\n",
963  ed,sinfo_edge[ed],pos_row[ed]); */
964  ed++ ;
965  if ( col >= ilx - slit_length - SLIT_POS_ERR ) {
966  pos_row[ed] = sinfo_new_nint( position[n] ) ;
967  }
968  } else if ( ((col-old_col) >
969  (slit_length+SLIT_POS_ERR)) &&
970  (col>120) ) {
971  old_col=col;
972  sinfo_edge[ed] = col ;
973  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
974  sinfo_msg_warning("add1 slitlet edge[%d]=%d, pos_row=%d",
975  ed,sinfo_edge[ed],pos_row[ed]);
976  ed++ ;
977  if ( col >= ilx - slit_length - SLIT_POS_ERR ) {
978  pos_row[ed] = sinfo_new_nint( position[n] ) ;
979  }
980  }
981  n++ ;
982  }
983  } else if ( ((col-old_col) > (slit_length+SLIT_POS_ERR)) &&
984  (col>120) ) {
985  /*
986  printf("check col=%d col-old_col=%d check=%d\n",
987  col,(col-old_col),(slit_length+SLIT_POS_ERR));
988  */
989  position[n] = old_pos ;
990 
991  old_col+=slit_length;
992  sinfo_edge[ed] = old_col; ;
993  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
994 
995 
996  sinfo_msg_warning("added2 slitlet sinfo_edge[%d]=%d, pos_row=%d",
997  ed,sinfo_edge[ed],pos_row[ed]);
998  ed++ ;
999  if ( old_col >= ilx - slit_length - SLIT_POS_ERR ) {
1000  pos_row[ed] = old_pos ;
1001  }
1002  n++;
1003  }
1004  }
1005  }
1006 
1007 
1008  if ( ed < (N_SLITLETS - 1) )
1009  {
1010  sinfo_msg_error(" not enough slitlets, found: %d", ed) ;
1011  cpl_free( sinfo_edge ) ;
1012  cpl_free( pos_row ) ;
1013  cpl_free( edgeclean ) ;
1014  cpl_free( dummyedge ) ;
1015  cpl_free( pos_rowclean ) ;
1016  cpl_free( position );
1017  return -8 ;
1018  }
1019 
1020  /* now find the clean sinfo_edge and row positions of the slitlets */
1021  /* printf("ed=%d\n",ed); */
1022  for ( i = 1 ; i <= ed ; i ++ )
1023  {
1024  if ( i == ed )
1025  {
1026  if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) <
1027  slit_length - SLIT_LEN_ERR ||
1028  (sinfo_edge[i-1] - sinfo_edge[i-2]) >
1029  slit_length + SLIT_LEN_ERR )
1030  {
1031  /* printf("e(i-1)=%d e(i-2)=%d i=%d\n",
1032  edge[i-1], edge[i-2],i); */
1033  dummyedge[i-1] = -1 ;
1034  }
1035  }
1036  if (dummyedge[i-1] != -1)
1037  {
1038  dummyedge[i-1] = sinfo_edge[i-1] ;
1039  }
1040  else
1041  {
1042  continue ;
1043  }
1044  if ( i < ed )
1045  {
1046  if ( (sinfo_edge[i] - sinfo_edge[i-1]) <
1047  slit_length - SLIT_LEN_ERR ||
1048  (sinfo_edge[i] - sinfo_edge[i-1]) >
1049  slit_length + SLIT_LEN_ERR )
1050  {
1051  /* printf("e(i)=%d e(i-1)=%d i=%d\n",edge[i], edge[i-1],i); */
1052  dummyedge[i] = -1 ;
1053  }
1054  }
1055  if ( i+1 < ed && dummyedge[i] != -1 )
1056  {
1057  if ( (sinfo_edge[i+1] - sinfo_edge[i]) <
1058  slit_length - SLIT_LEN_ERR ||
1059  (sinfo_edge[i+1] - sinfo_edge[i]) >
1060  slit_length + SLIT_LEN_ERR )
1061  {
1062  /* printf("e(i+1)=%d e(i)=%d i=%d\n",edge[i+1], edge[i],i); */
1063  dummyedge[i+1] = -1 ;
1064  }
1065  }
1066  }
1067 
1068  k = 0 ;
1069  for ( i = 0 ; i < ed ; i++ )
1070  {
1071  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
1072  {
1073  edgeclean[k] = dummyedge[i] ;
1074  pos_rowclean[k] = pos_row[i] ;
1075  k++ ;
1076  if( edgeclean[k-1] > (ilx - slit_length -2*SLIT_LEN_ERR ) )
1077  {
1078  pos_rowclean[k] = pos_row[ed] ;
1079  }
1080  }
1081  }
1082  /*
1083  for ( i = 0 ; i < k ; i++ )
1084  {
1085  sinfo_msg_warning("%d %d", edgeclean[i], pos_rowclean[i]);
1086  }
1087  */
1088  if ( k != N_SLITLETS - 1 )
1089  {
1090  sinfo_msg_error(" wrong number of clean slitlets found: %d", k+1) ;
1091  cpl_free( sinfo_edge ) ;
1092  cpl_free( pos_row ) ;
1093  cpl_free( edgeclean ) ;
1094  cpl_free( dummyedge ) ;
1095  cpl_free( pos_rowclean ) ;
1096  return -7 ;
1097  }
1098 
1099  /* determine the margins of the fitting box outside the slitlets */
1100  margin = box_length / 2 ;
1101 
1102  /* ----------------------------------------------------------------------
1103  * now go through the slitlets, search along each column within a box with
1104  * half width y_box the maximum value and store these found values
1105  * in a buffer
1106  */
1107  if(
1108  ( (pos_rowclean[0]-sinfo_new_nint(y_box)) < 0 ) ||
1109  ( (pos_rowclean[0]+sinfo_new_nint(y_box)) >ily )
1110  ) {
1111 
1112  sinfo_msg_error("pos_rowclean[0] <0 something wrong!") ;
1113  cpl_free( sinfo_edge ) ;
1114  cpl_free( pos_row ) ;
1115  cpl_free( edgeclean ) ;
1116  cpl_free( dummyedge ) ;
1117  cpl_free( pos_rowclean ) ;
1118  return -7 ;
1119 
1120  }
1121 
1122  for ( j = 0 ; j <= k ; j++ )
1123  {
1124  int m = 0 ;
1125  if ( j == 0 )
1126  {
1127  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
1128  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
1129  {
1130  maxval = -FLT_MAX ;
1131  for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ;
1132  row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
1133  {
1134  if ( maxval < pidata[col + ilx*row] )
1135  {
1136  maxval = pidata[col + ilx*row] ;
1137  }
1138  }
1139  box_buffer->data[m] = maxval ;
1140  m++ ;
1141  }
1142  }
1143  else if ( j < k )
1144  {
1145  box_buffer = sinfo_new_vector( edgeclean[j] -
1146  edgeclean[j-1] + 2*margin ) ;
1147  for ( col = edgeclean[j - 1] - margin ;
1148  col < edgeclean[j] + margin ; col++ )
1149  {
1150  maxval = -FLT_MAX ;
1151  for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ;
1152  row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
1153  {
1154  if ( maxval < pidata[col + ilx*row] )
1155  {
1156  maxval = pidata[col + ilx*row] ;
1157  }
1158  }
1159  box_buffer->data[m] = maxval ;
1160  m++ ;
1161  }
1162  }
1163  else
1164  {
1165  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
1166  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
1167  {
1168  maxval = -FLT_MAX ;
1169  for ( row = pos_rowclean[k-2] - sinfo_new_nint(y_box) ;
1170  row <= pos_rowclean[k-2] + sinfo_new_nint(y_box) ; row++ )
1171  {
1172  if ( maxval < pidata[col + ilx*row] )
1173  {
1174  maxval = pidata[col + ilx*row] ;
1175  }
1176  }
1177  if(maxval>0) box_buffer->data[m] = maxval ;
1178  else box_buffer->data[m] = 0;
1179  m++ ;
1180  }
1181  }
1182 
1183  /* determine the minimum value in the box to get background1
1184  value for the sinfo_edge slitlets */
1185  double min = FLT_MAX ;
1186  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
1187  {
1188  if ( box_buffer -> data[i] < min )
1189  {
1190  min = box_buffer -> data[i] ;
1191  }
1192  }
1193 
1194  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
1195  {
1196  nel = 0 ;
1197  if ( left_right == 0 )
1198  {
1199  nel = box_buffer -> n_elements / 2 ;
1200  }
1201  else
1202  {
1203  if ( box_buffer -> n_elements % 2 == 0 )
1204  {
1205  nel = box_buffer -> n_elements / 2 ;
1206  }
1207  else
1208  {
1209  nel = box_buffer -> n_elements / 2 + 1 ;
1210  }
1211  }
1212 
1213  /* now split the buffer in the midth in a left and right
1214  part for fitting */
1215  half_buffer = sinfo_new_vector( nel ) ;
1216  if ( left_right == 0 )
1217  {
1218  for ( i = 0 ; i < nel ; i++ )
1219  {
1220  half_buffer -> data[i] = box_buffer -> data[i] ;
1221  }
1222  }
1223  else
1224  {
1225  n_right = 0 ;
1226  for ( i = box_buffer -> n_elements - 1 ;
1227  i >= box_buffer -> n_elements - nel ; i-- )
1228  {
1229  half_buffer -> data[n_right] = box_buffer -> data[i] ;
1230  n_right++ ;
1231  }
1232  }
1233 
1234  xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
1235  wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
1236  mpar = (int *) cpl_calloc( NPAR, sizeof (int) ) ;
1237 
1238  /* set initial values for the fitting routine */
1239  minval = FLT_MAX ;
1240  maxval = -FLT_MAX ;
1241  for ( i = 0 ; i < nel ; i++ )
1242  {
1243  xdat[i] = i ;
1244  wdat[i] = 1.0 ;
1245  if ( half_buffer -> data[i] < minval )
1246  {
1247  minval = half_buffer -> data[i] ;
1248  }
1249  if ( half_buffer -> data[i] > maxval )
1250  {
1251  maxval = half_buffer -> data[i] ;
1252  }
1253  }
1254 
1255  fitpar[0] = minval ;
1256  fitpar[1] = maxval ;
1257 
1258  /* search for both positions of the half intensity
1259  of the hat within the buffer */
1260  init1 = -1 ;
1261  for ( i = 0 ; i < nel ; i++ )
1262  {
1263  if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
1264  {
1265  init1 = i ;
1266  break ;
1267  }
1268  }
1269 
1270  /*----------------------------------------------------------------
1271  * if we have too few left background values (at the image edges)
1272  * the left margin of the buffer to fit is filled with the minimal
1273  * values in order to get a good fit
1274  */
1275 
1276  edge_ind = 0 ;
1277  if ( init1 < 3 )
1278  {
1279  n_buf = half_buffer->n_elements + margin ;
1280  in_buffer = sinfo_new_vector( n_buf ) ;
1281  for ( i = 0 ; i < margin ; i++ )
1282  {
1283  in_buffer -> data[i] = min ;
1284  }
1285  shift = 0 ;
1286  for ( i = margin ; i < n_buf ; i++ )
1287  {
1288  in_buffer -> data[i] = half_buffer -> data[shift] ;
1289  shift++ ;
1290  }
1291  sinfo_new_destroy_vector ( half_buffer ) ;
1292  half_buffer = sinfo_new_vector ( n_buf ) ;
1293  for ( i = 0 ; i < n_buf ; i++ )
1294  {
1295  half_buffer -> data[i] = in_buffer -> data[i] ;
1296  }
1297  edge_ind = 1 ;
1298  init1 += margin ;
1299  sinfo_new_destroy_vector ( in_buffer ) ;
1300  }
1301 
1302  /* determine the initial positions from the found values */
1303  if ( init1 != -1 )
1304  {
1305  fitpar[2] = (float)init1 ;
1306  }
1307  fitpar[3] = 1. ;
1308 
1309  for ( i = 0 ; i < NPAR ; i++ )
1310  {
1311  mpar[i] = 1 ;
1312  dervpar[i] = 0. ;
1313  }
1314 
1315  xdim = XDIMA ;
1316  ndat = nel ;
1317  numpar = NPAR ;
1318  tol = TOLA ;
1319  lab = LABA ;
1320  its = ITSA ;
1321 
1322  /* finally, do the least squares fit over the buffer data */
1323  if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim,
1324  half_buffer -> data,
1325  wdat, &ndat, fitpar,
1326  dervpar, mpar, &numpar,
1327  &tol, &its, &lab )) )
1328  {
1329  /* if the fit doesn't succeed the initial values are taken */
1330  sinfo_msg_warning (" least squares fit failed,"
1331  " error no.: %d in slitlet: %d", iters, j) ;
1332  fitpar[2] = (float)init1 ;
1333  }
1334 
1335  pos = fitpar[2] ;
1336  if ( edge_ind == 1 )
1337  {
1338  pos -= (float)margin ;
1339  }
1340 
1341  /*----------------------------------------------------------------
1342  * now discern the left and the right sinfo_edge fit of the
1343  * slitlets and associate the fit results with the absolute
1344  * positions in the image consider the difference of the fitted
1345  * slit position to the expected position and decide wether the
1346  * fit is taken or the expected value is taken.
1347  */
1348  if ( left_right == 0 )
1349  {
1350  /* take care of the column position of the fit boxes to get
1351  the absolute positions */
1352  if ( j == 0 )
1353  {
1354  if ( fabs(pos - ((float)edgeclean[0] - 1. -
1355  (float)slit_length)) < diff_tol )
1356  {
1357  slit_pos[0][0] = pos ;
1358  }
1359  else
1360  {
1361  sinfo_msg_warning("something wrong with fitted "
1362  "left position of slitlet 0") ;
1363  if ( (float) edgeclean[0] - 1. -
1364  (float)slit_length < 0. )
1365  {
1366  slit_pos[0][0] = 0. ;
1367  }
1368  else
1369  {
1370  slit_pos[0][0] = (float)edgeclean[0] - 1. -
1371  (float)slit_length ;
1372  }
1373  }
1374  }
1375  else if ( j < k )
1376  {
1377  if ( fabs( pos - (float)margin ) < diff_tol )
1378  {
1379  slit_pos[j][0] = pos + (float)edgeclean[j-1] -
1380  (float)margin ;
1381  }
1382  else
1383  {
1384  sinfo_msg_warning("something wrong with fitted "
1385  "left position of slitlet %d", j) ;
1386  slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
1387  }
1388  }
1389  else
1390  {
1391  if ( fabs( pos - (float)margin ) < diff_tol )
1392  {
1393  slit_pos[k][0] = pos + (float)edgeclean[k-1] -
1394  (float)margin ;
1395  }
1396  else
1397  {
1398  sinfo_msg_warning("something wrong with fitted "
1399  "left position of slitlet %d", j) ;
1400  slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
1401  }
1402  }
1403  }
1404  else
1405  {
1406  /* take care of the column position of the fit boxes to
1407  get the absolute positions */
1408  if ( j == 0 )
1409  {
1410  if ( fabs( (float)box_buffer->n_elements - pos -
1411  (float)edgeclean[0] ) < diff_tol )
1412  {
1413  slit_pos[0][1] = (float)(box_buffer->n_elements - 1) -
1414  pos ;
1415  }
1416  else
1417  {
1418  sinfo_msg_warning("something wrong with fitted "
1419  "right position of slitlet 0") ;
1420  slit_pos[0][1] = (float)edgeclean[0] - 1. ;
1421  }
1422  }
1423  else if ( j < k )
1424  {
1425  if ( fabs( (float)box_buffer->n_elements - pos
1426  + (float)edgeclean[j-1] - (float)margin -
1427  (float)edgeclean[j] ) < diff_tol )
1428  {
1429  slit_pos[j][1] = (float)(box_buffer->n_elements - 1) -
1430  pos
1431  + (float)edgeclean[j-1] - (float)margin ;
1432  }
1433  else
1434  {
1435  sinfo_msg_warning("something wrong with fitted "
1436  "right position of slitlet %d", j) ;
1437  slit_pos[j][1] = (float)edgeclean[j] - 1. ;
1438  }
1439  }
1440  else
1441  {
1442  if ( edgeclean[k-1] + slit_length > ilx )
1443  {
1444  last_pos = (float)(ilx - 1) ;
1445  }
1446  else
1447  {
1448  last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
1449  }
1450  if ( fabs( (float)(box_buffer->n_elements - 1) - pos
1451  + (float)edgeclean[k-1] - (float)margin -
1452  last_pos ) < diff_tol )
1453  {
1454  slit_pos[k][1] = (float)(box_buffer->n_elements - 1) -
1455  pos
1456  + (float)edgeclean[k-1] - (float)margin ;
1457  }
1458  else
1459  {
1460  sinfo_msg_warning("something wrong with fitted "
1461  "right position of slitlet %d", j) ;
1462  slit_pos[k][1] = last_pos ;
1463  }
1464  }
1465  }
1466 
1467  sinfo_new_destroy_vector ( half_buffer ) ;
1468  cpl_free( xdat ) ;
1469  cpl_free( wdat ) ;
1470  cpl_free( mpar ) ;
1471  }
1472  sinfo_new_destroy_vector ( box_buffer ) ;
1473  }
1474 
1475 
1476  cpl_free( sinfo_edge ) ;
1477  cpl_free( pos_row ) ;
1478  cpl_free( edgeclean ) ;
1479  cpl_free( dummyedge ) ;
1480  cpl_free( pos_rowclean ) ;
1481  cpl_free( position);
1482  return 0 ;
1483 }
1484 
1514 int
1515 sinfo_new_fit_slits_boltz_single_line ( cpl_image * lineImage,
1516  float ** slit_pos,
1517  int box_length,
1518  float y_box,
1519  int low_pos,
1520  int high_pos )
1521 {
1522  int* position=NULL ;
1523  int * sinfo_edge, * edgeclean ;
1524  int * dummyedge ;
1525  int * pos_row, * pos_rowclean ;
1526  Vector * box_buffer ;
1527  Vector * half_buffer ;
1528  Vector * in_buffer ;
1529 
1530  int row, col ;
1531  int i, j, k, ed ;
1532  int init1 ;
1533  int nel, n_right, left_right ;
1534  int n_buf, edge_ind, shift ;
1535  int slit_length ;
1536  int margin ;
1537  int iters, xdim, ndat ;
1538  int numpar, its ;
1539  int * mpar ;
1540  float * xdat, * wdat ;
1541  float tol, lab ;
1542  float fitpar[NPAR] ;
1543  float dervpar[NPAR] ;
1544  float minval, maxval ;
1545  float min ;
1546  float pos;
1547  //float last_pos ;
1548  int ilx=0;
1549  //int ily=0;
1550  float* pidata=NULL;
1551 
1552  slit_length = SLITLENGTH ;
1553 
1554  if ( NULL == lineImage )
1555  {
1556  sinfo_msg_error(" no line image given!" ) ;
1557  return -1 ;
1558  }
1559 
1560  if ( NULL == slit_pos )
1561  {
1562  sinfo_msg_error(" no position array allocated!" ) ;
1563  return -1 ;
1564  }
1565 
1566  if ( box_length < 4 ||
1567  box_length > 2*slit_length )
1568  {
1569  sinfo_msg_error(" wrong fitting box length given!" ) ;
1570  return -1 ;
1571  }
1572 
1573  if ( y_box <= 0. || y_box > 6. )
1574  {
1575  sinfo_msg_error(" wrong y box length given!" ) ;
1576  return -1 ;
1577  }
1578 
1579  ilx=cpl_image_get_size_x(lineImage);
1580  //ily=cpl_image_get_size_y(lineImage);
1581  pidata=cpl_image_get_data_float(lineImage);
1582 
1583  if ( low_pos >= high_pos || low_pos < 0 ||
1584  high_pos <= 0 || high_pos >= ilx )
1585  {
1586  sinfo_msg_error(" wrong user given search positions!" ) ;
1587  return -1 ;
1588  }
1589 
1590  /* allocate memory for the edges and the row position of the slitlets */
1591  sinfo_edge = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
1592  dummyedge = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
1593  edgeclean = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
1594  pos_row = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
1595  pos_rowclean = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
1596 
1597  /* now search for the maximum between the given positions for each col */
1598  position=cpl_calloc(ilx,sizeof(int)); ;
1599 
1600  for ( col = 0 ; col < ilx ; col++ )
1601  {
1602  int found_row = -1 ;
1603  maxval = -FLT_MAX ;
1604  for ( row = low_pos ; row <= high_pos ; row++ )
1605  {
1606  if ( maxval < pidata[col+row*ilx] )
1607  {
1608  maxval = pidata[col+row*ilx] ;
1609  found_row = row ;
1610  }
1611  }
1612  if ( maxval > -FLT_MAX && found_row > low_pos )
1613  {
1614  position[col] = found_row ;
1615  }
1616  else
1617  {
1618  position[col] = 0 ;
1619  }
1620  }
1621 
1622  /* now find and store the raw sinfo_edge positions of the found slitlet */
1623  ed = 0 ;
1624  for ( col = 0 ; col < (ilx) - 1 ; col++ )
1625  {
1626  if ( position[col] > 0 && position[col+1] > 0 &&
1627  abs(position[col+1] - position[col]) > 10 )
1628  {
1629  sinfo_edge[ed] = col ;
1630  pos_row[ed] = position[col] ;
1631  ed++ ;
1632  }
1633 
1634  }
1635  if (ed <= 1)
1636  {
1637  sinfo_msg_error(" no slitlets found!" ) ;
1638  cpl_free( sinfo_edge ) ;
1639  cpl_free( pos_row ) ;
1640  cpl_free( edgeclean ) ;
1641  cpl_free( dummyedge ) ;
1642  cpl_free( pos_rowclean ) ;
1643  cpl_free( position );
1644  return -1 ;
1645  }
1646 
1647  /* now find the clean sinfo_edge and row positions of the slitlets */
1648  for ( i = 1 ; i <= ed ; i ++ )
1649  {
1650  if ( i == ed )
1651  {
1652  if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) <
1653  slit_length - SLIT_LEN_ERR ||
1654  (sinfo_edge[i-1] - sinfo_edge[i-2]) >
1655  slit_length + SLIT_LEN_ERR )
1656  {
1657  dummyedge[i-1] = -1 ;
1658  }
1659  }
1660  if (dummyedge[i-1] != -1)
1661  {
1662  dummyedge[i-1] = sinfo_edge[i-1] ;
1663  }
1664  else
1665  {
1666  continue ;
1667  }
1668  if ( i < ed )
1669  {
1670  if ( (sinfo_edge[i] - sinfo_edge[i-1]) <
1671  slit_length - SLIT_LEN_ERR ||
1672  (sinfo_edge[i] - sinfo_edge[i-1]) >
1673  slit_length + SLIT_LEN_ERR )
1674  {
1675  dummyedge[i] = -1 ;
1676  }
1677  }
1678  if ( i+1 < ed && dummyedge[i] != -1 )
1679  {
1680  if ( (sinfo_edge[i+1] - sinfo_edge[i]) <
1681  slit_length - SLIT_LEN_ERR ||
1682  (sinfo_edge[i+1] - sinfo_edge[i]) >
1683  slit_length + SLIT_LEN_ERR )
1684  {
1685  dummyedge[i+1] = -1 ;
1686  }
1687  }
1688  }
1689 
1690  k = 0 ;
1691  for ( i = 0 ; i < ed ; i++ )
1692  {
1693  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
1694  {
1695  edgeclean[k] = dummyedge[i] ;
1696  pos_rowclean[k] = pos_row[i] ;
1697  k++ ;
1698  if( edgeclean[k-1] > (ilx - slit_length - 2*SLIT_LEN_ERR ) )
1699  {
1700  pos_rowclean[k] = pos_row[ed] ;
1701  }
1702  }
1703  }
1704 
1705  /* determine the margins of the fitting box outside the slitlets */
1706  margin = box_length / 2 ;
1707 
1708  /* ------------------------------------------------------------------------
1709  * now go through the slitlets, search along each column within a box with
1710  * half width y_box the maximum value and store these found values in a
1711  * buffer
1712  */
1713  for ( j = 0 ; j <= k ; j++ )
1714  {
1715  int m = 0 ;
1716  if ( j == 0 )
1717  {
1718  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
1719  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
1720  {
1721  maxval = -FLT_MAX ;
1722  for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ;
1723  row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
1724  {
1725  if ( maxval < pidata[col + ilx*row] )
1726  {
1727  maxval = pidata[col + ilx*row] ;
1728  }
1729  }
1730  box_buffer->data[m] = maxval ;
1731  m++ ;
1732  }
1733  }
1734  else if ( j < k )
1735  {
1736  box_buffer = sinfo_new_vector( edgeclean[j] -
1737  edgeclean[j-1] + 2*margin ) ;
1738  for ( col = edgeclean[j - 1] - margin ;
1739  col < edgeclean[j] + margin ; col++ )
1740  {
1741  maxval = -FLT_MAX ;
1742  for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ;
1743  row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
1744  {
1745  if ( maxval < pidata[col + ilx*row] )
1746  {
1747  maxval = pidata[col + ilx*row] ;
1748  }
1749  }
1750  box_buffer->data[m] = maxval ;
1751  m++ ;
1752  }
1753  }
1754  else
1755  {
1756  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
1757  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
1758  {
1759  if ( col < 0 )
1760  {
1761  col = 0 ;
1762  }
1763 
1764  maxval = -FLT_MAX ;
1765  for ( row = pos_rowclean[k] - sinfo_new_nint(y_box) ;
1766  row <= pos_rowclean[k] + sinfo_new_nint(y_box) ; row++ )
1767  {
1768  if ( row < 0 )
1769  {
1770  continue ;
1771  }
1772  if ( maxval < pidata[col + row * ilx] )
1773  {
1774  maxval = pidata[col + row * ilx] ;
1775  }
1776  }
1777  box_buffer->data[m] = maxval ;
1778  m++ ;
1779  }
1780  }
1781 
1782  /* determine the minimum value in the box to get background1
1783  value for the sinfo_edge slitlets */
1784  min = FLT_MAX ;
1785  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
1786  {
1787  if ( box_buffer -> data[i] < min )
1788  {
1789  min = box_buffer -> data[i] ;
1790  }
1791  }
1792 
1793  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
1794  {
1795  nel = 0 ;
1796  if ( left_right == 0 )
1797  {
1798  nel = box_buffer -> n_elements / 2 ;
1799  }
1800  else
1801  {
1802  if ( box_buffer -> n_elements % 2 == 0 )
1803  {
1804  nel = box_buffer -> n_elements / 2 ;
1805  }
1806  else
1807  {
1808  nel = box_buffer -> n_elements / 2 + 1 ;
1809  }
1810  }
1811 
1812  /* now split the buffer in the midth in a left and
1813  right part for fitting */
1814  half_buffer = sinfo_new_vector( nel ) ;
1815  if ( left_right == 0 )
1816  {
1817  for ( i = 0 ; i < nel ; i++ )
1818  {
1819  half_buffer -> data[i] = box_buffer -> data[i] ;
1820  }
1821  }
1822  else
1823  {
1824  n_right = 0 ;
1825  for ( i = box_buffer -> n_elements - 1 ;
1826  i >= box_buffer -> n_elements - nel ; i-- )
1827  {
1828  half_buffer -> data[n_right] = box_buffer -> data[i] ;
1829  n_right++ ;
1830  }
1831  }
1832 
1833  xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
1834  wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
1835  mpar = (int *) cpl_calloc( NPAR, sizeof (int) ) ;
1836 
1837  /* set initial values for the fitting routine */
1838  minval = FLT_MAX ;
1839  maxval = -FLT_MAX ;
1840  for ( i = 0 ; i < nel ; i++ )
1841  {
1842  xdat[i] = i ;
1843  wdat[i] = 1.0 ;
1844  if ( half_buffer -> data[i] < minval )
1845  {
1846  minval = half_buffer -> data[i] ;
1847  }
1848  if ( half_buffer -> data[i] > maxval )
1849  {
1850  maxval = half_buffer -> data[i] ;
1851  }
1852  }
1853  fitpar[0] = minval ;
1854  fitpar[1] = maxval ;
1855 
1856  /* search for both positions of the half intensity of
1857  the hat within the buffer */
1858  init1 = -1 ;
1859  for ( i = 0 ; i < nel ; i++ )
1860  {
1861  if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
1862  {
1863  init1 = i ;
1864  break ;
1865  }
1866  }
1867 
1868  /*---------------------------------------------------------------
1869  * if we have too few left background values (at the image edges)
1870  * the left margin of the buffer to fit is filled with the minimal
1871  * values in order to get a good fit
1872  */
1873 
1874  edge_ind = 0 ;
1875  if ( init1 < 3 )
1876  {
1877  n_buf = half_buffer->n_elements + margin ;
1878  in_buffer = sinfo_new_vector( n_buf ) ;
1879  for ( i = 0 ; i < margin ; i++ )
1880  {
1881  in_buffer -> data[i] = min ;
1882  }
1883  shift = 0 ;
1884  for ( i = margin ; i < n_buf ; i++ )
1885  {
1886  in_buffer -> data[i] = half_buffer -> data[shift] ;
1887  shift++ ;
1888  }
1889  sinfo_new_destroy_vector ( half_buffer ) ;
1890  half_buffer = sinfo_new_vector ( n_buf ) ;
1891  for ( i = 0 ; i < n_buf ; i++ )
1892  {
1893  half_buffer -> data[i] = in_buffer -> data[i] ;
1894  }
1895  edge_ind = 1 ;
1896  init1 += margin ;
1897  sinfo_new_destroy_vector ( in_buffer ) ;
1898  }
1899 
1900  /* determine the initial positions from the found values */
1901  if ( init1 != -1 )
1902  {
1903  fitpar[2] = (float)init1 ;
1904  }
1905  fitpar[3] = 1. ;
1906 
1907  for ( i = 0 ; i < NPAR ; i++ )
1908  {
1909  mpar[i] = 1 ;
1910  dervpar[i] = 0. ;
1911  }
1912 
1913  xdim = XDIMA ;
1914  ndat = nel ;
1915  numpar = NPAR ;
1916  tol = TOLA ;
1917  lab = LABA ;
1918  its = ITSA ;
1919 
1920  /* finally, do the least squares fit over the buffer data */
1921  if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim,
1922  half_buffer -> data,
1923  wdat, &ndat, fitpar,
1924  dervpar, mpar, &numpar,
1925  &tol, &its, &lab )) )
1926  {
1927  sinfo_msg_warning (" least squares fit failed, error "
1928  "no.: %d in slitlet: %d", iters, j) ;
1929  fitpar[2] = 0. ;
1930  }
1931  if ( fitpar[3] <=0. )
1932  {
1933  sinfo_msg_warning(" fit failed due to negative width"
1934  " of boltzmann function in slitlet: %d", j) ;
1935  fitpar[2] = 0. ;
1936  }
1937 
1938  pos = fitpar[2] ;
1939  if ( edge_ind == 1 )
1940  {
1941  pos -= (float)margin ;
1942  }
1943 
1944  /*-------------------------------------------------------------
1945  * now discern the left and the right sinfo_edge fit of the
1946  * slitlets and associate the fit results with the absolute
1947  * positions in the image consider the difference of the fitted
1948  * slit position to the expected position and decide wether the
1949  * fit is taken or the expected value is taken.
1950  */
1951  if ( left_right == 0 )
1952  {
1953  /* take care of the column position of the fit boxes to
1954  get the absolute positions */
1955  if ( j == 0 )
1956  {
1957  slit_pos[0][0] = pos ;
1958  if ( slit_pos[0][0] - (int) slit_pos[0][0] == 0.)
1959  {
1960  slit_pos[0][0] = 0. ;
1961  }
1962  }
1963  else if ( j < k )
1964  {
1965  slit_pos[j][0] = pos + (float)edgeclean[j-1] -
1966  (float)margin ;
1967  if ( slit_pos[j][0] - (int) slit_pos[j][0] == 0.)
1968  {
1969  slit_pos[j][0] = 0. ;
1970  }
1971  }
1972  else
1973  {
1974  slit_pos[k][0] = pos + (float)edgeclean[k-1] -
1975  (float)margin ;
1976  if ( slit_pos[k][0] - (int) slit_pos[k][0] == 0.)
1977  {
1978  slit_pos[k][0] = 0. ;
1979  }
1980  }
1981  }
1982  else
1983  {
1984  /* take care of the column position of the fit boxes to
1985  get the absolute positions */
1986  if ( j == 0 )
1987  {
1988  slit_pos[0][1] = (float)(box_buffer->n_elements - 1) - pos;
1989  if ( slit_pos[0][1] - (int) slit_pos[0][1] == 0.)
1990  {
1991  slit_pos[0][1] = 0. ;
1992  }
1993  }
1994  else if ( j < k )
1995  {
1996  slit_pos[j][1] = (float)(box_buffer->n_elements - 1) - pos
1997  + (float)edgeclean[j-1] - (float)margin ;
1998  if ( slit_pos[j][1] - (int) slit_pos[j][1] == 0.)
1999  {
2000  slit_pos[j][1] = 0. ;
2001  }
2002  }
2003  else
2004  {
2005  //last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
2006  slit_pos[k][1] = (float)(box_buffer->n_elements - 1) - pos
2007  + (float)edgeclean[k-1] - (float)margin ;
2008  if ( slit_pos[k][1] - (int) slit_pos[k][1] == 0.)
2009  {
2010  slit_pos[k][1] = 0. ;
2011  }
2012  }
2013  }
2014 
2015  sinfo_new_destroy_vector ( half_buffer ) ;
2016  cpl_free( xdat ) ;
2017  cpl_free( wdat ) ;
2018  cpl_free( mpar ) ;
2019  }
2020  sinfo_new_destroy_vector ( box_buffer ) ;
2021  }
2022 
2023  cpl_free( sinfo_edge ) ;
2024  cpl_free( pos_row ) ;
2025  cpl_free( edgeclean ) ;
2026  cpl_free( dummyedge ) ;
2027  cpl_free( pos_rowclean ) ;
2028  cpl_free( position );
2029  return 0 ;
2030 }
2031 
2062 int
2063 sinfo_new_fit_slits_boltz_with_estimate ( cpl_image * lineImage,
2064  float ** slit_pos,
2065  int box_length,
2066  float y_box,
2067  float diff_tol,
2068  int low_pos,
2069  int high_pos )
2070 {
2071  int* position=NULL ;
2072  Vector * box_buffer ;
2073  Vector * in_buffer ;
2074 
2075  int row, col ;
2076  int col_first, col_last ;
2077  int row_first, row_last ;
2078  int i, j, m;
2079  int init1 ;
2080  int left_right ;
2081  int n_buf, shift ;
2082  int slit_length ;
2083  int iters, xdim, ndat ;
2084  int numpar, its ;
2085  int * mpar ;
2086  float * xdat, * wdat ;
2087  float tol, lab ;
2088  float fitpar[NPAR] ;
2089  float dervpar[NPAR] ;
2090  float minval, maxval ;
2091  float pos ;
2092  float new_pos ;
2093  int slitposition[SLITLENGTH] ;
2094  pixelvalue rowpos[SLITLENGTH] ;
2095 
2096  int ilx=0;
2097  int ily=0;
2098  float* pidata=NULL;
2099 
2100  /* slit_length = SLITLENGTH ; this setting is too much 64 */
2101  slit_length = N_SLITLETS ; /* this setting is better: 32 */
2102 
2103  if ( NULL == lineImage )
2104  {
2105  sinfo_msg_error(" no line image given!" ) ;
2106  return -1 ;
2107  }
2108 
2109  if ( NULL == slit_pos )
2110  {
2111  sinfo_msg_error(" no position array allocated!" ) ;
2112  return -1 ;
2113  }
2114 
2115  if ( box_length < 4 ||
2116  box_length > 2*slit_length )
2117  {
2118  sinfo_msg_error(" wrong fitting box length given!" ) ;
2119  return -1 ;
2120  }
2121 
2122  if ( y_box <= 0. || y_box > 6. )
2123  {
2124  sinfo_msg_error(" wrong y box length given!" ) ;
2125  return -1 ;
2126  }
2127  if ( diff_tol <= 0. )
2128  {
2129  sinfo_msg_error(" wrong diff_tol given!" ) ;
2130  return -1 ;
2131  }
2132 
2133  ilx=cpl_image_get_size_x(lineImage);
2134  ily=cpl_image_get_size_y(lineImage);
2135  pidata=cpl_image_get_data_float(lineImage);
2136 
2137  if ( low_pos >= high_pos || low_pos < 0 ||
2138  high_pos <= 0 || high_pos > ily )
2139  {
2140  sinfo_msg_error(" wrong user given search positions!" ) ;
2141  return -1 ;
2142  }
2143 
2144  /* now search for the maximum between the given positions for each col */
2145  position=cpl_calloc(ilx,sizeof(int)) ;
2146  for ( col = 0 ; col < ilx ; col++ )
2147  {
2148  int found_row = -1 ;
2149  maxval = -FLT_MAX ;
2150  for ( row = low_pos ; row <= high_pos ; row++ )
2151  {
2152  if ( maxval < pidata[col+row*ilx] )
2153  {
2154  maxval = pidata[col+row*ilx] ;
2155  found_row = row ;
2156  }
2157  }
2158  if ( maxval > -FLT_MAX && found_row > low_pos )
2159  {
2160  position[col] = found_row ;
2161  }
2162  else
2163  {
2164  position[col] = 0 ;
2165  }
2166  }
2167 
2168  /* ------------------------------------------------------------------------
2169  * now go through the slitlets, search along each column within a box with
2170  * half width y_box the maximum value and store these found values in a
2171  * buffer
2172  */
2173  for ( j = 0 ; j < slit_length ; j++ )
2174  {
2175  /* now go through the columns and determine the slitlet positions by
2176  * calculating the median of the found positions
2177  */
2178  int n = 0 ;
2179 
2180  for ( col = sinfo_new_nint(slit_pos[j][0])+ 1 ;
2181  col < sinfo_new_nint(slit_pos[j][1]) -1 ; col++ )
2182  {
2183  rowpos[n] = (pixelvalue)position[col] ;
2184  n++ ;
2185  }
2186 
2187  slitposition[j] = (int)sinfo_new_median(rowpos, n) ;
2188  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
2189  {
2190  init1 = 0 ;
2191  col_first = sinfo_new_nint( slit_pos[j][left_right] ) -
2192  box_length/2 ;
2193  col_last = sinfo_new_nint( slit_pos[j][left_right] ) +
2194  box_length/2 ;
2195  if ( col_first < 0 )
2196  {
2197  col_first = 0 ;
2198  init1 = 1 ;
2199  }
2200  if ( col_last > ilx )
2201  {
2202  col_last = ilx ;
2203  init1 = 1 ;
2204  }
2205  if ( col_last - col_first <= 0 )
2206  {
2207  sinfo_msg_error(" first and last column wrong!" ) ;
2208  return -1 ;
2209  }
2210  box_buffer = sinfo_new_vector( col_last - col_first ) ;
2211  m = 0 ;
2212 
2213 
2214  if ( left_right == 0 )
2215  {
2216  for( col = col_first ; col < col_last ; col++ )
2217  {
2218  row_first = slitposition[j] - sinfo_new_nint(y_box) ;
2219  row_last = slitposition[j] + sinfo_new_nint(y_box) ;
2220  if ( row_first < 0 )
2221  {
2222  row_first = 0 ;
2223  }
2224  if ( row_last >= ily )
2225  {
2226  row_last = ily - 1 ;
2227  }
2228  maxval = -FLT_MAX ;
2229  for ( row = row_first ; row <= row_last ; row++ )
2230  {
2231  if ( maxval < pidata[col + ilx*row] )
2232  {
2233  maxval = pidata[col + ilx*row] ;
2234  }
2235  }
2236  box_buffer->data[m] = maxval ;
2237  m++ ;
2238  }
2239 
2240  }
2241  else
2242  {
2243 
2244  for( col = col_last-1 ; col >= col_first ; col-- )
2245  {
2246  row_first = slitposition[j] - sinfo_new_nint(y_box) ;
2247  row_last = slitposition[j] + sinfo_new_nint(y_box) ;
2248  if ( row_first < 0 )
2249  {
2250  row_first = 0 ;
2251  }
2252  if ( row_last >= ily )
2253  {
2254  row_last = ily - 1 ;
2255  }
2256  maxval = -FLT_MAX ;
2257  for ( row = row_first ; row <= row_last ; row++ )
2258  {
2259  if ( maxval < pidata[col + ilx*row] )
2260  {
2261  maxval = pidata[col + ilx*row] ;
2262  }
2263  }
2264  box_buffer->data[m] = maxval ;
2265  m++ ;
2266  }
2267 
2268  }
2269 
2270  xdat=(float *) cpl_calloc(box_buffer->n_elements, sizeof (float) );
2271  wdat=(float *) cpl_calloc(box_buffer->n_elements, sizeof (float) );
2272  mpar=(int *) cpl_calloc(NPAR, sizeof (int) ) ;
2273 
2274  /* set initial values for the fitting routine */
2275  minval = FLT_MAX ;
2276  maxval = -FLT_MAX ;
2277 
2278  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
2279  {
2280  xdat[i] = i ;
2281  wdat[i] = 1.0 ;
2282  if ( box_buffer -> data[i] < minval )
2283  {
2284  minval = box_buffer -> data[i] ;
2285  }
2286  if ( box_buffer -> data[i] > maxval )
2287  {
2288  maxval = box_buffer -> data[i] ;
2289  }
2290  }
2291  fitpar[0] = minval ;
2292  fitpar[1] = maxval ;
2293 
2294  /*-----------------------------------------------------------------
2295  * if we have too few left background values (at the image edges)
2296  * the left margin of the buffer to fit is filled with the minimal
2297  * values in order to get a good fit
2298  */
2299 
2300 
2301  if ( init1 == 1 )
2302  {
2303  n_buf = box_buffer->n_elements + box_length/2 ;
2304  in_buffer = sinfo_new_vector( n_buf ) ;
2305  for ( i = 0 ; i < box_length/2 ; i++ )
2306  {
2307  in_buffer -> data[i] = minval ;
2308  }
2309  shift = 0 ;
2310  for ( i = box_length/2 ; i < n_buf ; i++ )
2311  {
2312  in_buffer -> data[i] = box_buffer -> data[shift] ;
2313  shift++ ;
2314  }
2315  sinfo_new_destroy_vector ( box_buffer ) ;
2316  box_buffer = sinfo_new_vector ( n_buf ) ;
2317  for ( i = 0 ; i < n_buf ; i++ )
2318  {
2319  box_buffer -> data[i] = in_buffer -> data[i] ;
2320  }
2321  sinfo_new_destroy_vector ( in_buffer ) ;
2322  }
2323 
2324  /* determine the initial positions from the found values */
2325  fitpar[2] = (float)box_buffer->n_elements/2. ;
2326  fitpar[3] = 1. ;
2327 
2328  for ( i = 0 ; i < NPAR ; i++ )
2329  {
2330  mpar[i] = 1 ;
2331  dervpar[i] = 0. ;
2332  }
2333 
2334  xdim = XDIMA ;
2335  ndat = box_buffer->n_elements ;
2336  numpar = NPAR ;
2337  tol = TOLA ;
2338  lab = LABA ;
2339  its = ITSA ;
2340 
2341  /* finally, do the least squares fit over the buffer data */
2342  if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim,
2343  box_buffer -> data,
2344  wdat, &ndat, fitpar,
2345  dervpar, mpar, &numpar,
2346  &tol, &its, &lab )) )
2347  {
2348  sinfo_msg_warning ("least squares fit failed, error "
2349  "no.: %d in slitlet: %d\n", iters, j) ;
2350  sinfo_new_destroy_vector(box_buffer) ;
2351  cpl_free( xdat ) ;
2352  cpl_free( wdat ) ;
2353  cpl_free( mpar ) ;
2354  continue ;
2355  }
2356 
2357  if ( fitpar[3] <=0. )
2358  {
2359  sinfo_msg_warning ("fit failed due to negative width of "
2360  "boltzmann function in slitlet: %d\n", j) ;
2361  sinfo_new_destroy_vector(box_buffer) ;
2362  cpl_free( xdat ) ;
2363  cpl_free( wdat ) ;
2364  cpl_free( mpar ) ;
2365  continue ;
2366  }
2367  pos = fitpar[2] ;
2368  if ( init1 == 1 )
2369  {
2370  pos -= (float)box_length/2. ;
2371  }
2372 
2373  /*-------------------------------------------------------------
2374  * now compute the real slit positions using the guess positions
2375  * if the fit did not work the guess positions are taken
2376  * the same is done if the deviations are too big.
2377  */
2378  if ( pos != 0. )
2379  {
2380  if ( left_right == 0 )
2381  {
2382  new_pos = (float)col_first + pos ;
2383  }
2384  else
2385  {
2386  new_pos = (float)col_last-1 - pos ;
2387  }
2388  if ( fabs(new_pos - slit_pos[j][left_right]) < diff_tol )
2389  {
2390  slit_pos[j][left_right] = new_pos ;
2391  }
2392  else
2393  {
2394  sinfo_msg_warning (" deviation bigger than tolerance,"
2395  " take the estimated slitlet position "
2396  " in slitlet: %d\n", j) ;
2397  }
2398  }
2399 
2400  cpl_free( xdat ) ;
2401  cpl_free( wdat ) ;
2402  cpl_free( mpar ) ;
2403  sinfo_new_destroy_vector ( box_buffer ) ;
2404 
2405  }
2406  }
2407  cpl_free(position);
2408  return 0 ;
2409 }
2410 
2411 /*--------------------------------------------------------------------------*/
#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