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