SINFONI Pipeline Reference Manual  2.5.2
sinfo_absolute.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 14/11/00 created
27  */
29 /*---------------------------------------------------------------------------*/
34 /*---------------------------------------------------------------------------*/
35 
36 
37 /************************************************************************
38  * NAME
39  * sinfo_absolute.c - routines to determine the absolute positions
40  * of the slitlets out of an emission line frame
41  *
42  * SYNOPSIS
43  * #include "absolute.h"
44  *
45  * 1) float sinfo_new_edge( float * xdat, float * parlist,
46  int * npar, int * ndat )
47  * 2) void sinfo_new_edge_deriv( float * xdat, float * parlist,
48  float * dervs, int * npar )
49  * 3) static int sinfo_new_inv_mat_edge (void)
50  * 4) static new_void sinfo_get_mat_edge ( float * xdat,
51  * int * xdim,
52  * float * ydat,
53  * float * wdat,
54  * int * ndat,
55  * float * fpar,
56  * float * epar,
57  * int * npar )
58  * 5) static int sinfo_new_get_vec_edge ( float * xdat,
59  * int * xdim,
60  * float * ydat,
61  * float * wdat,
62  * int * ndat,
63  * float * fpar,
64  * float * epar,
65  * int * npar )
66  * 6) int sinfo_new_lsqfit_edge ( float * xdat,
67  * int * xdim,
68  * float * ydat,
69  * float * wdat,
70  * int * ndat,
71  * float * fpar,
72  * float * epar,
73  * int * mpar,
74  * int * npar,
75  * float * tol ,
76  * int * its ,
77  * float * lab )
78  * 7) int sinfo_new_fit_slits_edge( cpl_image * lineImage,
79  * FitParams ** par,
80  * float ** sinfo_slit_pos,
81  * int box_length,
82  * float y_box,
83  * float diff_tol )
84  * 8) int sinfo_new_fit_slits_edge_with_estimate ( cpl_image * lineImage,
85  * float ** sinfo_slit_pos,
86  * int box_length,
87  * float y_box,
88  * float diff_tol,
89  * int low_pos,
90  * int high_pos )
91  *
92  * DESCRIPTION
93  * 1) calculates the value of a slope function with parameters
94  * parlist at the position xdat
95  * 2) calculates the partial derivatives for a slope function with
96  * parameters parlist at position xdat
97  * 3) calculates the inverse of matrix2. The algorithm used
98  * is the Gauss-Jordan algorithm described in Stoer,
99  * Numerische Mathematik, 1. Teil.
100  * 4) builds the sinfo_matrix
101  * 5) calculates the correction sinfo_vector. The sinfo_matrix has been
102  * built by get_mat_edge(), we only have to rescale it for the
103  * current value of labda. The sinfo_matrix is rescaled so that
104  * the diagonal gets the value 1 + labda.
105  * Next we calculate the inverse of the sinfo_matrix and then
106  * the correction sinfo_vector.
107  * 6) this is a routine for making a least-squares fit of a
108  * function to a set of data points. The method used is
109  * described in: Marquardt, J.Soc.Ind.Appl.Math. 11. 431 (1963).
110  * This method is a mixture of the steepest descent method
111  * and the Taylor method.
112  * 7) fits the beginning and end position of the slitlets
113  * by using non-linear least square fitting of a step function
114  * fits a step function to the slitlet edges exposed and indicated
115  * by the brightest emission lines. To achieve this, the fit
116  * parameters are used to find the brightest emission line
117  * and to get its position for each column.
118  * The least squares fit is done by using a box smaller than
119  * the size of two slitlets
120  * 8) fits the beginning and end position of the slitlets
121  * by using non-linear least square fitting of an sinfo_edge function
122  * fits a linear edge function to the slitlet edges exposed and indicated
123  * by the brightest emission lines. The slitlet is searched within
124  * user given positions.
125  * The least squares fit is done by using a box smaller than
126  * the size of two slitlets
127  *
128  * FILES
129  *
130  * ENVIRONMENT
131  *
132  * RETURN VALUES
133  *
134  * CAUTIONS
135  *
136  * EXAMPLES
137  *
138  * SEE ALSO
139  *
140  * BUGS
141  *
142  *------------------------------------------------------------------------
143  */
144 #ifdef HAVE_CONFIG_H
145 # include <config.h>
146 #endif
147 #include "sinfo_vltPort.h"
148 /*
149  * System Headers
150  */
151 
152 /*
153  * Local Headers
154  */
155 
156 #include "sinfo_absolute.h"
157 #include "sinfo_recipes.h"
158 /*----------------------------------------------------------------------------
159  * Defines
160  *--------------------------------------------------------------------------*/
161 static float sqrarg ;
162 #define SQR(a) (sqrarg = (a) , sqrarg*sqrarg)
163 
164 #define XDIMA 1 /* dimension of the x values */
165 #define TOLA 0.001 /* fitting tolerance */
166 #define LABA 0.1 /* labda parameter */
167 #define ITSA 200 /* maximum number of iterations */
168 #define LABFACA 10.0 /* labda step factor */
169 #define LABMAXA 1.0e+10 /* maximum value for labda */
170 #define LABMINA 1.0e-10 /* minimum value for labda */
171 #define NPAR 4 /* number of fit parameters */
172 
173 /*----------------------------------------------------------------------------
174  * Local variables
175  *--------------------------------------------------------------------------*/
176 
177 static double chi1 ; /* old reduced chi-squared */
178 static double chi2 ; /* new reduced chi-squared */
179 static double labda ; /* mixing parameter */
180 static double vec[NPAR] ; /* correction sinfo_vector */
181 static double matrix1[NPAR][NPAR] ; /* original sinfo_matrix */
182 static double matrix2[NPAR][NPAR] ; /* inverse of matrix1 */
183 static int nfree ; /* number of free parameters */
184 static int parptr[NPAR] ; /* parameter pointer */
185 static float slopewidth ; /* initial value for fit parameter 5:
186  width of linear slope */
187 
188 /*----------------------------------------------------------------------------
189  * Functions private to this module
190  *--------------------------------------------------------------------------*/
191 static int sinfo_new_inv_mat_edge (void) ;
192 
193 static void sinfo_new_get_mat_edge ( float * xdat,
194  int * xdim,
195  float * ydat,
196  float * wdat,
197  int * ndat,
198  float * fpar,
199  float * epar/*,
200  int * npar*/ ) ;
201 
202 static int sinfo_new_get_vec_edge ( float * xdat,
203  int * xdim,
204  float * ydat,
205  float * wdat,
206  int * ndat,
207  float * fpar,
208  float * epar,
209  int * npar ) ;
210 float
211 sinfo_new_hat2 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ );
212 
213 float
214 sinfo_new_hat1 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ );
215 
216 void
217 sinfo_new_hat_deriv2(float * xdat, float * parlist,
218  float * dervs/*, int * npar*/ );
219 
220 void
221 sinfo_new_hat_deriv1( float * xdat, float * parlist,
222  float * dervs/*, int * npar*/ );
223 
224 int
225 sinfo_new_fit_slits1( cpl_image * lineImage,
226  FitParams ** par,
227  float ** sinfo_slit_pos,
228  int box_length,
229  float y_box );
230 
231 int
232 sinfo_new_fit_slits( cpl_image * lineImage,
233  FitParams ** par,
234  float ** sinfo_slit_pos,
235  int box_length,
236  float y_box,
237  float slope_width );
238 
239 
240 
241 int
242 sinfo_new_fit_slits2( cpl_image * lineImage,
243  FitParams ** par,
244  float ** sinfo_slit_pos,
245  int box_length,
246  float y_box,
247  float diff_tol );
248 /*----------------------------------------------------------------------------
249  * Function codes
250  *--------------------------------------------------------------------------*/
251 
270 float
271 sinfo_new_edge ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
272 {
273  float return_value ;
274  float slope1 ;
275 
276  /* compute the slopes */
277  slope1 = ( parlist[3] - parlist[2] ) / ( parlist[1] - parlist[0] ) ;
278 
279  /* now build the hat function out of the parameters */
280  if ( xdat[0] <= parlist[0] )
281  {
282  return_value = parlist[2] ;
283  }
284  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
285  {
286  return_value = (xdat[0] - parlist[0]) * slope1 + parlist[2] ;
287  }
288  else if ( xdat[0] > parlist[1] )
289  {
290  return_value = parlist[3] ;
291  }
292  else
293  {
294  return_value = 0. ;
295  }
296 
297  return return_value ;
298 }
299 
329 float
330 sinfo_new_hat2 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
331 {
332  float return_value ;
333  float slope1, slope2, slope3 ;
334 
335  /* compute the slopes */
336  slope1 = ( parlist[6] - parlist[4] ) / ( parlist[1] - parlist[0] ) ;
337  slope2 = ( parlist[7] - parlist[5] ) / ( parlist[3] - parlist[2] ) ;
338  slope3 = ( parlist[7] - parlist[6] ) / ( parlist[2] - parlist[1] ) ;
339 
340  /* now build the hat function out of the parameters */
341  if ( xdat[0] <= parlist[0] )
342  {
343  return_value = parlist[4] ;
344  }
345  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
346  {
347  return_value = (xdat[0] - parlist[0]) * slope1 + parlist[4] ;
348  }
349  else if ( xdat[0] > parlist[1] && xdat[0] <= parlist[2] )
350  {
351  return_value = (xdat[0] - parlist[1]) * slope3 + parlist[6] ;
352  }
353  else if ( xdat[0] > parlist[2] && xdat[0] <= parlist[3] )
354  {
355  return_value = (parlist[3] - xdat[0]) * slope2 + parlist[5] ;
356  }
357  else if ( xdat[0] > parlist[3] )
358  {
359  return_value = parlist[5] ;
360  }
361  else
362  {
363  return_value = 0. ;
364  }
365 
366  return return_value ;
367 }
368 
369 
399 float
400 sinfo_new_hat1 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
401 {
402  float return_value=0 ;
403  float slope1, slope2 ;
404 
405  /* take only positive values for the fit parameters */
406 
407  /* compute the slopes */
408  slope1 = (parlist[4] - parlist[2]) / slopewidth ;
409  slope2 = (parlist[4] - parlist[3]) / slopewidth ;
410 
411  /* now build the hat function out of the parameters */
412  if ( xdat[0] <= parlist[0] )
413  {
414  return_value = parlist[2] ;
415  }
416  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[0] + slopewidth )
417  {
418  return_value = (xdat[0] - parlist[0]) * slope1 + parlist[2] ;
419  }
420  else if ( xdat[0] > parlist[0] + slopewidth &&
421  xdat[0] <= parlist[1] - slopewidth )
422  {
423  return_value = parlist[4] ;
424  }
425  else if ( xdat[0] > parlist[1] - slopewidth && xdat[0] <= parlist[1] )
426  {
427  return_value = (parlist[1] - xdat[0]) * slope2 + parlist[3] ;
428  }
429  else if ( xdat[0] > parlist[1] )
430  {
431  return_value = parlist[3] ;
432  }
433 
434  return return_value ;
435 }
436 
437 
464 void
465 sinfo_new_edge_deriv( float * xdat, float * parlist,
466  float * dervs/*, int * npar*/ )
467 {
468  float deriv1_slope1 ;
469 
470  /* compute the slopes */
471  deriv1_slope1 =( parlist[3] - parlist[2] ) / SQR(parlist[1] - parlist[0]) ;
472 
473  /* now build the hat derivatives out of the parameters */
474  if ( xdat[0] <= parlist[0] )
475  {
476  dervs[0] = 0. ;
477  dervs[1] = 0. ;
478  dervs[2] = 1. ;
479  dervs[3] = 0. ;
480  }
481  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
482  {
483  dervs[0] = ( xdat[0] - parlist[1] ) * deriv1_slope1 ;
484  dervs[1] = ( parlist[0] - xdat[0] ) * deriv1_slope1 ;
485  dervs[2] = ( parlist[0] - xdat[0] ) / ( parlist[1] - parlist[0] ) + 1.;
486  dervs[3] = ( xdat[0] - parlist[0] ) / ( parlist[1] - parlist[0] ) ;
487  }
488  else if ( xdat[0] > parlist[1] )
489  {
490  dervs[0] = 0. ;
491  dervs[1] = 0. ;
492  dervs[2] = 0. ;
493  dervs[3] = 1. ;
494  }
495 }
530 void
531 sinfo_new_hat_deriv2(float * xdat, float * parlist,
532  float * dervs/*, int * npar*/ )
533 {
534  float deriv1_slope1 ;
535  float deriv1_slope2 ;
536  float deriv1_slope3 ;
537 
538  /* compute the slopes */
539  deriv1_slope1 = ( parlist[6] - parlist[4] ) / SQR(parlist[1] - parlist[0]);
540  deriv1_slope2 = ( parlist[7] - parlist[5] ) / SQR(parlist[3] - parlist[2]);
541  deriv1_slope3 = ( parlist[7] - parlist[6] ) / SQR(parlist[2] - parlist[1]);
542 
543  /* now build the hat derivatives out of the parameters */
544  if ( xdat[0] <= parlist[0] )
545  {
546  dervs[0] = 0. ;
547  dervs[1] = 0. ;
548  dervs[2] = 0. ;
549  dervs[3] = 0. ;
550  dervs[4] = 1. ;
551  dervs[5] = 0. ;
552  dervs[6] = 0. ;
553  dervs[7] = 0. ;
554  }
555  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
556  {
557  dervs[0] = ( xdat[0] - parlist[1] ) * deriv1_slope1 ;
558  dervs[1] = ( parlist[0] - xdat[0] ) * deriv1_slope1 ;
559  dervs[2] = 0. ;
560  dervs[3] = 0. ;
561  dervs[4] = ( parlist[0] - xdat[0] ) / ( parlist[1] - parlist[0] ) + 1.;
562  dervs[5] = 0. ;
563  dervs[6] = ( xdat[0] - parlist[0] ) / ( parlist[1] - parlist[0] ) ;
564  dervs[7] = 0. ;
565  }
566  else if ( xdat[0] > parlist[1] && xdat[0] <= parlist[2] )
567  {
568  dervs[0] = 0. ;
569  dervs[1] = (xdat[0] - parlist[2]) * deriv1_slope3 ;
570  dervs[2] = (parlist[1] - xdat[0]) * deriv1_slope3 ;
571  dervs[3] = 0. ;
572  dervs[4] = 0. ;
573  dervs[5] = 0. ;
574  dervs[6] = (parlist[1] - xdat[0]) / (parlist[2] - parlist[1]) + 1. ;
575  dervs[7] = (xdat[0] - parlist[1]) / (parlist[2] - parlist[1]) ;
576  }
577  else if ( xdat[0] > parlist[2] && xdat[0] <= parlist[3] )
578  {
579  dervs[0] = 0. ;
580  dervs[1] = 0. ;
581  dervs[2] = ( parlist[3] - xdat[0] ) * deriv1_slope2 ;
582  dervs[3] = ( xdat[0] - parlist[2] ) * deriv1_slope2 ;
583  dervs[4] = 0. ;
584  dervs[5] = ( xdat[0] - parlist[3] ) / ( parlist[3] - parlist[2] ) + 1.;
585  dervs[6] = 0. ;
586  dervs[7] = ( parlist[3] - xdat[0] ) / ( parlist[3] - parlist[2] ) ;
587  }
588  else if ( xdat[0] > parlist[3] )
589  {
590  dervs[0] = 0. ;
591  dervs[1] = 0. ;
592  dervs[2] = 0. ;
593  dervs[3] = 0. ;
594  dervs[4] = 0. ;
595  dervs[5] = 1. ;
596  dervs[6] = 0. ;
597  dervs[7] = 0. ;
598  }
599 }
600 
629 void
630 sinfo_new_hat_deriv1( float * xdat, float * parlist,
631  float * dervs/*, int * npar*/ )
632 {
633  /* now build the hat derivatives out of the parameters */
634  if ( xdat[0] <= parlist[0] )
635  {
636  dervs[0] = 0. ;
637  dervs[1] = 0. ;
638  dervs[2] = 1. ;
639  dervs[3] = 0. ;
640  dervs[4] = 0. ;
641  }
642  else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[0] + slopewidth )
643  {
644  dervs[0] = ( parlist[2] - parlist[4] ) / slopewidth ;
645  dervs[1] = 0. ;
646  dervs[2] = (( parlist[0] - xdat[0] ) / slopewidth ) + 1. ;
647  dervs[3] = 0. ;
648  dervs[4] = ( xdat[0] - parlist[0] ) / slopewidth ;
649  }
650  else if ( xdat[0] > parlist[0] + slopewidth && xdat[0] <=
651  parlist[1] - slopewidth )
652  {
653  dervs[0] = 0. ;
654  dervs[1] = 0. ;
655  dervs[2] = 0. ;
656  dervs[3] = 0. ;
657  dervs[4] = 1. ;
658  }
659  else if ( xdat[0] > parlist[1] - slopewidth && xdat[0] <= parlist[1] )
660  {
661  dervs[0] = 0. ;
662  dervs[1] = ( parlist[4] - parlist[3] ) / slopewidth ;
663  dervs[2] = 0. ;
664  dervs[3] = (( xdat[0] - parlist[1] ) / slopewidth ) + 1. ;
665  dervs[4] = ( parlist[1] - xdat[0] ) / slopewidth ;
666  }
667  else if ( xdat[0] > parlist[1] )
668  {
669  dervs[0] = 0. ;
670  dervs[1] = 0. ;
671  dervs[2] = 0. ;
672  dervs[3] = 1. ;
673  dervs[4] = 0. ;
674  }
675 }
676 
688 static int
689 sinfo_new_inv_mat_edge (void)
690 {
691  double even ;
692  double hv[NPAR] ;
693  double mjk ;
694  double rowmax ;
695  int evin ;
696  int i, j, k, row ;
697  int per[NPAR] ;
698 
699  /* set permutation array */
700  for ( i = 0 ; i < nfree ; i++ )
701  {
702  per[i] = i ;
703  }
704 
705  for ( j = 0 ; j < nfree ; j++ ) /* in j-th column */
706  {
707  /* determine largest element of a row */
708  rowmax = fabs ( matrix2[j][j] ) ;
709  row = j ;
710 
711  for ( i = j + 1 ; i < nfree ; i++ )
712  {
713  if ( fabs ( matrix2[i][j] ) > rowmax )
714  {
715  rowmax = fabs( matrix2[i][j] ) ;
716  row = i ;
717  }
718  }
719 
720  /* determinant is zero! */
721  if ( matrix2[row][j] == 0.0 )
722  {
723  return -6 ;
724  }
725 
726  /* if the largest element is not on the diagonal, then permutate rows */
727  if ( row > j )
728  {
729  for ( k = 0 ; k < nfree ; k++ )
730  {
731  even = matrix2[j][k] ;
732  matrix2[j][k] = matrix2[row][k] ;
733  matrix2[row][k] = even ;
734  }
735  /* keep track of permutation */
736  evin = per[j] ;
737  per[j] = per[row] ;
738  per[row] = evin ;
739  }
740 
741  /* modify column */
742  even = 1.0 / matrix2[j][j] ;
743  for ( i = 0 ; i < nfree ; i++ )
744  {
745  matrix2[i][j] *= even ;
746  }
747  matrix2[j][j] = even ;
748 
749  for ( k = 0 ; k < j ; k++ )
750  {
751  mjk = matrix2[j][k] ;
752  for ( i = 0 ; i < j ; i++ )
753  {
754  matrix2[i][k] -= matrix2[i][j] * mjk ;
755  }
756  for ( i = j + 1 ; i < nfree ; i++ )
757  {
758  matrix2[i][k] -= matrix2[i][j] * mjk ;
759  }
760  matrix2[j][k] = -even * mjk ;
761  }
762 
763  for ( k = j + 1 ; k < nfree ; k++ )
764  {
765  mjk = matrix2[j][k] ;
766  for ( i = 0 ; i < j ; i++ )
767  {
768  matrix2[i][k] -= matrix2[i][j] * mjk ;
769  }
770  for ( i = j + 1 ; i < nfree ; i++ )
771  {
772  matrix2[i][k] -= matrix2[i][j] * mjk ;
773  }
774  matrix2[j][k] = -even * mjk ;
775  }
776  }
777 
778  /* finally, repermute the columns */
779  for ( i = 0 ; i < nfree ; i++ )
780  {
781  for ( k = 0 ; k < nfree ; k++ )
782  {
783  hv[per[k]] = matrix2[i][k] ;
784  }
785  for ( k = 0 ; k < nfree ; k++ )
786  {
787  matrix2[i][k] = hv[k] ;
788  }
789  }
790 
791  /* all is well */
792  return 0 ;
793 }
794 
813 static void
814 sinfo_new_get_mat_edge ( float * xdat,
815  int * xdim,
816  float * ydat,
817  float * wdat,
818  int * ndat,
819  float * fpar,
820  float * epar/*,
821  int * npar*/ )
822 {
823  double wd ;
824  double wn ;
825  double yd ;
826  int i, j, n ;
827 
828  for ( j = 0 ; j < nfree ; j++ )
829  {
830  vec[j] = 0.0 ; /* zero sinfo_vector */
831  for ( i = 0 ; i<= j ; i++ ) /* zero matrix only on and
832  below diagonal */
833  {
834  matrix1[j][i] = 0.0 ;
835  }
836  }
837  chi2 = 0.0 ; /* reset reduced chi-squared */
838 
839  /* loop through data points */
840  for ( n = 0 ; n < (*ndat) ; n++ )
841  {
842  wn = wdat[n] ;
843  if ( wn > 0.0 ) /* legal weight ? */
844  {
845  yd = ydat[n] - sinfo_new_edge( &xdat[(*xdim) * n],
846  fpar/*, npar, ndat*/ ) ;
847  sinfo_new_edge_deriv( &xdat[(*xdim) * n], fpar, epar/*, npar */) ;
848  chi2 += yd * yd * wn ; /* add to chi-squared */
849  for ( j = 0 ; j < nfree ; j++ )
850  {
851  wd = epar[parptr[j]] * wn ; /* weighted derivative */
852  vec[j] += yd * wd ; /* fill sinfo_vector */
853  for ( i = 0 ; i <= j ; i++ ) /* fill sinfo_matrix */
854  {
855  matrix1[j][i] += epar[parptr[i]] * wd ;
856  }
857  }
858  }
859  }
860 }
861 
862 
863 
893 static int
894 sinfo_new_get_vec_edge ( float * xdat,
895  int * xdim,
896  float * ydat,
897  float * wdat,
898  int * ndat,
899  float * fpar,
900  float * epar,
901  int * npar )
902 {
903  double dj ;
904  double dy ;
905  double mii ;
906  double mji ;
907  double mjj ;
908  double wn ;
909  int i, j, n, r ;
910 
911  /* loop to modify and scale the sinfo_matrix */
912  for ( j = 0 ; j < nfree ; j++ )
913  {
914  mjj = matrix1[j][j] ;
915  if ( mjj <= 0.0 ) /* diagonal element wrong */
916  {
917  return -5 ;
918  }
919  mjj = sqrt( mjj ) ;
920  for ( i = 0 ; i < j ; i++ )
921  {
922  mji = matrix1[j][i] / mjj / sqrt( matrix1[i][i] ) ;
923  matrix2[i][j] = matrix2[j][i] = mji ;
924  }
925  matrix2[j][j] = 1.0 + labda ; /* scaled value on diagonal */
926  }
927 
928  if ( (r = sinfo_new_inv_mat_edge()) ) /* sinfo_invert sinfo_matrix inlace */
929  {
930  return r ;
931  }
932 
933  for ( i = 0 ; i < (*npar) ; i ++ )
934  {
935  epar[i] = fpar[i] ;
936  }
937 
938  /* loop to calculate correction sinfo_vector */
939  for ( j = 0 ; j < nfree ; j++ )
940  {
941  dj = 0.0 ;
942  mjj = matrix1[j][j] ;
943  if ( mjj <= 0.0) /* not allowed */
944  {
945  return -7 ;
946  }
947  mjj = sqrt ( mjj ) ;
948  for ( i = 0 ; i < nfree ; i++ )
949  {
950  mii = matrix1[i][i] ;
951  if ( mii <= 0.0 )
952  {
953  return -7 ;
954  }
955  mii = sqrt( mii ) ;
956  dj += vec[i] * matrix2[j][i] / mjj / mii ;
957  }
958  epar[parptr[j]] += dj ; /* new parameters */
959  }
960  chi1 = 0.0 ; /* reset reduced chi-squared */
961 
962  /* loop through the data points */
963  for ( n = 0 ; n < (*ndat) ; n++ )
964  {
965  wn = wdat[n] ; /* get weight */
966  if ( wn > 0.0 ) /* legal weight */
967  {
968  dy = ydat[n] - sinfo_new_edge( &xdat[(*xdim) * n], epar
969  /*, npar, ndat*/) ;
970  chi1 += wdat[n] * dy * dy ;
971  }
972  }
973  return 0 ;
974 }
975 
976 
1030 int
1031 sinfo_new_lsqfit_edge ( float * xdat,
1032  int * xdim,
1033  float * ydat,
1034  float * wdat,
1035  int * ndat,
1036  float * fpar,
1037  float * epar,
1038  int * mpar,
1039  int * npar,
1040  float * tol ,
1041  int * its ,
1042  float * lab )
1043 {
1044  int i, n, r ;
1045  int itc ; /* fate of fit */
1046  int found ; /* fit converged: 1, not yet converged: 0 */
1047  int nuse ; /* number of useable data points */
1048  double tolerance ; /* accuracy */
1049 
1050  itc = 0 ; /* fate of fit */
1051  found = 0 ; /* reset */
1052  nfree = 0 ; /* number of free parameters */
1053  nuse = 0 ; /* number of legal data points */
1054 
1055  if ( *tol < (FLT_EPSILON * 10.0 ) )
1056  {
1057  tolerance = FLT_EPSILON * 10.0 ; /* default tolerance */
1058  }
1059  else
1060  {
1061  tolerance = *tol ; /* tolerance */
1062  }
1063 
1064  labda = fabs( *lab ) * LABFACA ; /* start value for mixing parameter */
1065  for ( i = 0 ; i < (*npar) ; i++ )
1066  {
1067  if ( mpar[i] )
1068  {
1069  if ( nfree > NPAR ) /* too many free parameters */
1070  {
1071  return -1 ;
1072  }
1073  parptr[nfree++] = i ; /* a free parameter */
1074  }
1075  }
1076 
1077  if (nfree == 0) /* no free parameters */
1078  {
1079  return -2 ;
1080  }
1081 
1082  for ( n = 0 ; n < (*ndat) ; n++ )
1083  {
1084  if ( wdat[n] > 0.0 ) /* legal weight */
1085  {
1086  nuse ++ ;
1087  }
1088  }
1089 
1090  if ( nfree >= nuse )
1091  {
1092  return -3 ; /* no degrees of freedom */
1093  }
1094  if ( labda == 0.0 ) /* linear fit */
1095  {
1096  /* initialize fpar array */
1097  for ( i = 0 ; i < nfree ; fpar[parptr[i++]] = 0.0 ) ;
1098  sinfo_new_get_mat_edge(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar */) ;
1099  r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, ndat,
1100  fpar, epar, npar ) ;
1101  if ( r ) /* error */
1102  {
1103  return r ;
1104  }
1105  for ( i = 0 ; i < (*npar) ; i++ )
1106  {
1107  fpar[i] = epar[i] ; /* save new parameters */
1108  epar[i] = 0.0 ; /* and set errors to zero */
1109  }
1110  chi1 = sqrt( chi1 / (double) (nuse - nfree) ) ;
1111  for ( i = 0 ; i < nfree ; i++ )
1112  {
1113  if ( (matrix1[i][i] <= 0.0 ) || (matrix2[i][i] <= 0.0) )
1114  {
1115  return -7 ;
1116  }
1117  epar[parptr[i]] = chi1 * sqrt( matrix2[i][i] ) /
1118  sqrt( matrix1[i][i] ) ;
1119  }
1120  }
1121  else /* non-linear fit */
1122  {
1123  /*----------------------------------------------------------------
1124  * the non-linear fit uses the steepest descent method in combination
1125  * with the Taylor method. The mixing of these methods is controlled
1126  * by labda. In the outer loop ( called the iteration loop ) we build
1127  * the sinfo_matrix and calculate the correction sinfo_vector. In the
1128  * inner loop
1129  * (called the interpolation loop) we check whether we have obtained a
1130  * better solution than the previous one. If so, we leave the inner loop
1131  * else we increase labda ( give more weight to the steepest descent
1132  * method) calculate the correction sinfo_vector and check again.
1133  * After the inner loop
1134  * we do a final check on the goodness of the fit and if this satisfies
1135  * the tolerance we calculate the errors of the fitted parameters.
1136  */
1137  while ( !found ) /* iteration loop */
1138  {
1139  if ( itc++ == (*its) ) /* increase iteration counter */
1140  {
1141  return -4 ;
1142  }
1143  sinfo_new_get_mat_edge( xdat, xdim, ydat, wdat, ndat,
1144  fpar, epar/*, npar*/ ) ;
1145 
1146  /*-------------------------------------------------------------
1147  * here we decrease labda since we may assume that each iteration
1148  * brings us closer to the answer.
1149  */
1150  if ( labda > LABMINA )
1151  {
1152  labda = labda / LABFACA ; /* decrease labda */
1153  }
1154  r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, ndat,
1155  fpar, epar, npar ) ;
1156  if ( (int)fpar[1] - (int)fpar[0] <= 0 && fpar[1] / fpar[0] > 0. )
1157  {
1158  fpar[1] += 1. ;
1159  continue ;
1160  }
1161  if ( r ) /* error */
1162  {
1163  return r ;
1164  }
1165 
1166  while ( chi1 >= chi2 ) /* interpolation loop */
1167  {
1168  /*-----------------------------------------------------------
1169  * The next statement is based on experience, not on the
1170  * mathematics of the problem. It is assumed that we have
1171  * reached convergence when the pure steepest descent method
1172  * does not produce a better solution.
1173  */
1174  if ( labda > LABMAXA ) /* assume solution found */
1175  {
1176  break ;
1177  }
1178  labda = labda * LABFACA ; /* increase mixing parameter */
1179  r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat,
1180  ndat, fpar, epar, npar ) ;
1181  if ( (int)fpar[1] - (int)fpar[0] <= 0 &&
1182  fpar[1] / fpar[0] > 0. )
1183  {
1184  fpar[1] += 1. ;
1185  continue ;
1186  }
1187  if ( r ) /* error */
1188  {
1189  return r ;
1190  }
1191  }
1192 
1193  if ( labda <= LABMAXA ) /* save old parameters */
1194  {
1195  for ( i = 0 ; i < *npar ; i++ )
1196  {
1197  fpar[i] = epar[i] ;
1198  }
1199  }
1200  if ( (fabs( chi2 - chi1 ) <= (tolerance * chi1)) ||
1201  (labda > LABMAXA) )
1202  {
1203  /*------------------------------------------------------------
1204  * we have a satisfying solution, so now we need to calculate
1205  * the correct errors of the fitted parameters. This we do by
1206  * using the pure Taylor method because we are very close to
1207  * the real solution.
1208  */
1209  labda = LABMINA ; /* for Taylor solution */
1210  sinfo_new_get_mat_edge ( xdat, xdim, ydat, wdat, ndat,
1211  fpar, epar/*, npar */) ;
1212  r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat,
1213  ndat, fpar, epar, npar ) ;
1214 
1215  if ( r ) /* error */
1216  {
1217  return r ;
1218  }
1219  for ( i = 0 ; i < (*npar) ; i++ )
1220  {
1221  epar[i] = 0.0 ; /* set error to zero */
1222  }
1223  chi2 = sqrt ( chi2 / (double) (nuse - nfree) ) ;
1224 
1225  for ( i = 0 ; i < nfree ; i++ )
1226  {
1227  if ( (matrix1[i][i] <= 0.0) || (matrix2[i][i] <= 0.0) )
1228  {
1229  return -7 ;
1230  }
1231  epar[parptr[i]] = chi2 * sqrt( matrix2[i][i] ) /
1232  sqrt( matrix1[i][i] ) ;
1233  }
1234  found = 1 ; /* we found a solution */
1235  }
1236  }
1237  }
1238  return itc ; /* return number of iterations */
1239 }
1268 int
1269 sinfo_new_fit_slits1( cpl_image * lineImage,
1270  FitParams ** par,
1271  float ** sinfo_slit_pos,
1272  int box_length,
1273  float y_box )
1274 {
1275  float* position=NULL ;
1276  int * sinfo_edge, * edgeclean ;
1277  int * dummyedge ;
1278  int * pos_row, * pos_rowclean ;
1279  Vector * box_buffer ;
1280  float max_intensity ;
1281  float row_pos ;
1282  int col ;
1283  int i, j, k, m, n, ed ;
1284  int found;
1285  /*
1286  int init1;
1287  int init2 ;
1288  */
1289  int line ;
1290  int column ;
1291  int slit_length ;
1292  int agreed ;
1293  int bad_line ;
1294  int margin ;
1295  int iters, xdim, ndat ;
1296  int numpar, its ;
1297  int * mpar ;
1298  float * xdat, * wdat ;
1299  float tol, lab ;
1300  float fitpar[2*NPAR] ;
1301  float dervpar[NPAR] ;
1302  float minval, maxval ;
1303  int ilx=0;
1304  //int ily=0;
1305  float* pidata=NULL;
1306 
1307 
1308  if ( NULL == lineImage )
1309  {
1310  sinfo_msg_error("no line image given!" ) ;
1311  return -1 ;
1312  }
1313  ilx=cpl_image_get_size_x(lineImage);
1314  //ily=cpl_image_get_size_y(lineImage);
1315  pidata=cpl_image_get_data_float(lineImage);
1316 
1317  slit_length = (int) sqrt (ilx) ;
1318  if ( NULL == par )
1319  {
1320  sinfo_msg_error("no line fit parameters given!") ;
1321  return -2 ;
1322  }
1323 
1324  if ( NULL == sinfo_slit_pos )
1325  {
1326  sinfo_msg_error("no position array allocated!") ;
1327  return -3 ;
1328  }
1329 
1330  if ( box_length < slit_length ||
1331  box_length >= 3*slit_length )
1332  {
1333  sinfo_msg_error("wrong fitting box length given!" ) ;
1334  return -4 ;
1335  }
1336 
1337  if ( y_box <= 0. || y_box > 3. )
1338  {
1339  sinfo_msg_error("wrong y box length given!" ) ;
1340  return -5 ;
1341  }
1342 
1343  /* allocate memory for the edges and the row positon of the slitlets */
1344  sinfo_edge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1345  dummyedge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1346  edgeclean = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
1347  pos_row = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1348  pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
1349 
1350  /* ------------------------------------------------------------------------
1351  * go through the first image columns and the fit parameters and find
1352  * the line with the highest intensity
1353  */
1354  agreed = -1 ;
1355  bad_line = -1 ;
1356  while( agreed == -1 )
1357  {
1358  found = -1 ;
1359  max_intensity = -FLT_MAX ;
1360  for ( col = 0 ; col < box_length ; col++ )
1361  {
1362  for ( i = 0 ; i < par[0]->n_params ; i++ )
1363  {
1364  if ( par[i]->column == col && par[i]->line != bad_line )
1365  {
1366  if ( par[i]->fit_par[0] > max_intensity )
1367  {
1368  if ( par[i]->fit_par[1] > 0. )
1369  {
1370  max_intensity = par[i]->fit_par[0] ;
1371  found = i ;
1372  }
1373  }
1374  }
1375  }
1376  }
1377 
1378  /* --------------------------------------------------------------------
1379  * check if the found line is usable and if the neighbouring line
1380  * have intensity on near rows in neighbouring slitlets
1381  */
1382  line = par[found]->line ;
1383  column = par[found]->column ;
1384  row_pos = par[found]->fit_par[2] ;
1385  if ( found >= 0 && max_intensity > 0. )
1386  {
1387  for ( i = 0 ; i < par[0]->n_params ; i++ )
1388  {
1389  if ( par[i]->line == line-1 &&
1390  par[i]->column == column + slit_length )
1391  {
1392  if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
1393  par[i]->fit_par[2] >= (row_pos - y_box) )
1394  {
1395  bad_line = line ;
1396  }
1397  }
1398  }
1399  if ( bad_line != line )
1400  {
1401  agreed = 1 ;
1402  break ;
1403  }
1404  }
1405  else
1406  {
1407  sinfo_msg_error("no emission line found in the first image columns");
1408  return -6 ;
1409  }
1410  }
1411 
1412 
1413  if ( agreed == -1 )
1414  {
1415  sinfo_msg_error("no emission line found in the first image columns") ;
1416  return -6 ;
1417  }
1418 
1419  /* now find and store the raw sinfo_edge positions of the found slitlet */
1420  n = 0 ;
1421  ed = 0 ;
1422 
1423 
1424  position=cpl_calloc(ilx,sizeof(float));
1425  for ( col = 0 ; col < ilx ; col++ )
1426  {
1427  for ( i = 0 ; i < par[0]->n_params ; i++ )
1428  {
1429  if ( par[i]->column == col && par[i] -> line == line )
1430  {
1431  if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
1432  {
1433  position[n] = par[i]->fit_par[2] ;
1434  if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
1435  {
1436  sinfo_edge[ed] = col ;
1437  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
1438  ed++ ;
1439  if ( col >= ilx - slit_length - 5 )
1440  {
1441  pos_row[ed] = sinfo_new_nint( position[n] ) ;
1442  }
1443  }
1444  n++ ;
1445  }
1446  }
1447  }
1448  }
1449  if ( ed < (slit_length - 1) )
1450  {
1451  sinfo_msg_error("not enough slitlets found") ;
1452  return -7 ;
1453  }
1454 
1455  /* now find the clean sinfo_edge and row positions of the slitlets */
1456  for ( i = 1 ; i <= ed ; i ++ )
1457  {
1458  if (dummyedge[i-1] != -1)
1459  {
1460  dummyedge[i-1] = sinfo_edge[i-1] ;
1461  }
1462  if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
1463  (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
1464  {
1465  dummyedge[i] = -1 ;
1466  }
1467  if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
1468  (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
1469  {
1470  dummyedge[i+1] = -1 ;
1471  }
1472  }
1473 
1474  k = 0 ;
1475  for ( i = 0 ; i < ed ; i++ )
1476  {
1477  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
1478  {
1479  edgeclean[k] = dummyedge[i] ;
1480  pos_rowclean[k] = pos_row[i] ;
1481  k++ ;
1482  if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
1483  {
1484  pos_rowclean[k] = pos_row[ed] ;
1485  }
1486  }
1487  }
1488 
1489  if ( k != slit_length - 1 )
1490  {
1491  sinfo_msg_error("not enough clean slitlets found") ;
1492  return -7 ;
1493  }
1494 
1495  /* determine the margins of the fitting box outside the slitlets */
1496  margin = ( box_length - slit_length ) / 2 ;
1497 
1498  /* now go through the slitlets and store the intensity in a
1499  buffer sinfo_vector */
1500  for ( j = 0 ; j < k ; j++ )
1501  {
1502  m = 0 ;
1503  if ( j == 0 )
1504  {
1505  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
1506  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
1507  {
1508  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[0]] ;
1509  m++ ;
1510  }
1511  fitpar[0] = 3. ;
1512  fitpar[1] = 5. ;
1513  fitpar[2] = (float) edgeclean[0] - 1. ;
1514  fitpar[3] = (float) edgeclean[0] + 1. ;
1515 
1516  }
1517  else if ( j < k - 1 )
1518  {
1519  box_buffer = sinfo_new_vector( edgeclean[j] -
1520  edgeclean[j-1] + 2*margin ) ;
1521  for ( col = edgeclean[j - 1] - margin ;
1522  col < edgeclean[j] + margin ; col++ )
1523  {
1524  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
1525  m++ ;
1526  }
1527  fitpar[0] = (float) margin - 1. ;
1528  fitpar[1] = (float) margin + 1. ;
1529  fitpar[2] = (float) (edgeclean[j] - edgeclean[j-1] + margin) - 1. ;
1530  fitpar[3] = (float) (edgeclean[j] - edgeclean[j-1] + margin) + 1. ;
1531  }
1532  /*else if ( j == k - 1 )*/
1533  else
1534  {
1535  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
1536  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
1537  {
1538  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
1539  m++ ;
1540  }
1541  fitpar[0] = (float) margin - 1. ;
1542  fitpar[1] = (float) margin + 1. ;
1543  fitpar[2] = (float) (ilx - edgeclean[k-1] + margin) - 3. ;
1544  fitpar[3] = (float) (ilx - edgeclean[k-1] + margin) - 1. ;
1545  }
1546 
1547  xdat = (float *) cpl_calloc(box_buffer -> n_elements,sizeof (float) ) ;
1548  wdat = (float *) cpl_calloc(box_buffer -> n_elements,sizeof (float) ) ;
1549  mpar = (int *) cpl_calloc(NPAR, sizeof (int) ) ;
1550 
1551  /* set initial values for the fitting routine */
1552  minval = FLT_MAX ;
1553  maxval = -FLT_MAX ;
1554  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
1555  {
1556  xdat[i] = i ;
1557  wdat[i] = 1.0 ;
1558  if ( box_buffer -> data[i] < minval )
1559  {
1560  minval = box_buffer -> data[i] ;
1561  }
1562  if ( box_buffer -> data[i] > maxval )
1563  {
1564  maxval = box_buffer -> data[i] ;
1565  }
1566  }
1567 
1568  fitpar[4] = minval ;
1569  fitpar[5] = minval ;
1570  fitpar[6] = maxval ;
1571  fitpar[7] = maxval ;
1572 
1573  /* search for both positions of the half intensity of the
1574  hat within the buffer */
1575  /*
1576  init1 = -1 ;
1577  init2 = -1 ;
1578  */
1579  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
1580  {
1581  if ( box_buffer -> data[i] >= ( maxval - minval ) / 2. )
1582  {
1583  //init1 = i ;
1584  break ;
1585  }
1586  }
1587 
1588  for ( i = box_buffer->n_elements - 1 ; i >= 0 ; i-- )
1589  {
1590  if ( box_buffer -> data[i] >= ( maxval + minval ) / 2. )
1591  {
1592  //init2 = i ;
1593  break ;
1594  }
1595  }
1596 
1597  /* determine the initial positions from the found values */
1598  /* if ( init1 != -1 )
1599  {
1600  fitpar[0] = init1 - 1. ;
1601  fitpar[1] = init1 + 1. ;
1602  }
1603  if ( init2 != -1 )
1604  {
1605  fitpar[2] = init2 - 1. ;
1606  fitpar[3] = init2 + 1. ;
1607  } */
1608 
1609  for ( i = 0 ; i < NPAR ; i++ )
1610  {
1611  mpar[i] = 1 ;
1612  dervpar[i] = 0. ;
1613  }
1614 
1615  xdim = XDIMA ;
1616  ndat = box_buffer -> n_elements ;
1617  numpar = NPAR ;
1618  tol = TOLA ;
1619  lab = LABA ;
1620  its = ITSA ;
1621 
1622  /* finally, do the least squares fit over the buffer data */
1623  if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim,
1624  box_buffer -> data,
1625  wdat, &ndat, fitpar,
1626  dervpar, mpar,
1627  &numpar, &tol,
1628  &its, &lab )) )
1629  {
1630  sinfo_msg_warning("least squares fit failed, error no.: %d",
1631  iters) ;
1632  return -8 ;
1633  }
1634 
1635 
1636  /* take care of the column position of the fit boxes to get
1637  the absolute positions */
1638  if ( j == 0 )
1639  {
1640  sinfo_slit_pos[0][0] = (fitpar[0] + fitpar[1]) / 2. ;
1641  sinfo_slit_pos[0][1] = (fitpar[2] + fitpar[3]) / 2. ;
1642  }
1643  else
1644  {
1645  sinfo_slit_pos[j][0] = (fitpar[0] + fitpar[1]) / 2. +
1646  (float)edgeclean[j-1] - (float)margin ;
1647  sinfo_slit_pos[j][1] = (fitpar[2] + fitpar[3]) / 2. +
1648  (float)edgeclean[j-1] - (float)margin ;
1649  }
1650 
1651  sinfo_slit_pos[k][0] = (fitpar[0] + fitpar[1]) / 2. +
1652  (float)edgeclean[k-1] - (float)margin ;
1653  sinfo_slit_pos[k][1] = (fitpar[2] + fitpar[3]) / 2. +
1654  (float)edgeclean[k-1] - (float)margin ;
1655 
1656  sinfo_new_destroy_vector ( box_buffer ) ;
1657  cpl_free( xdat ) ;
1658  cpl_free( wdat ) ;
1659  cpl_free( mpar ) ;
1660  }
1661 
1662  cpl_free( sinfo_edge ) ;
1663  cpl_free( pos_row ) ;
1664  cpl_free( edgeclean ) ;
1665  cpl_free( dummyedge ) ;
1666  cpl_free( pos_rowclean ) ;
1667  cpl_free( position );
1668 
1669  return 0 ;
1670 }
1671 
1703 int
1704 sinfo_new_fit_slits( cpl_image * lineImage,
1705  FitParams ** par,
1706  float ** sinfo_slit_pos,
1707  int box_length,
1708  float y_box,
1709  float slope_width )
1710 {
1711  float* position=NULL ;
1712 
1713  int * sinfo_edge, * edgeclean ;
1714  int * dummyedge ;
1715  int * pos_row, * pos_rowclean ;
1716  Vector * box_buffer ;
1717  float max_intensity ;
1718  float row_pos ;
1719  int col ;
1720  int i, j, k, m, n, ed ;
1721  int found ;
1722  int line ;
1723  int column ;
1724  int slit_length ;
1725  int agreed ;
1726  int bad_line ;
1727  int margin ;
1728  int iters, xdim, ndat ;
1729  int numpar, its ;
1730  int * mpar ;
1731  float * xdat, * wdat ;
1732  float tol, lab ;
1733  float fitpar[NPAR] ;
1734  float dervpar[NPAR] ;
1735  float minval, maxval ;
1736  int ilx=0;
1737  //int ily=0;
1738  float* pidata=NULL;
1739 
1740 
1741  if ( NULL == lineImage )
1742  {
1743  sinfo_msg_error("no line image given!" ) ;
1744  return -1 ;
1745  }
1746  ilx=cpl_image_get_size_x(lineImage);
1747  //ily=cpl_image_get_size_y(lineImage);
1748  pidata=cpl_image_get_data_float(lineImage);
1749 
1750  slit_length = (int) sqrt (ilx) ;
1751  if ( NULL == par )
1752  {
1753  sinfo_msg_error("no line fit parameters given!" ) ;
1754  return -2 ;
1755  }
1756 
1757  if ( NULL == sinfo_slit_pos )
1758  {
1759  sinfo_msg_error("no position array allocated!" ) ;
1760  return -3 ;
1761  }
1762 
1763  if ( box_length < slit_length ||
1764  box_length >= 3*slit_length )
1765  {
1766  sinfo_msg_error("wrong fitting box length given!" ) ;
1767  return -4 ;
1768  }
1769 
1770  if ( y_box <= 0. || y_box > 3. )
1771  {
1772  sinfo_msg_error("wrong y box length given!" ) ;
1773  return -5 ;
1774  }
1775 
1776  if ( slope_width <= 0. )
1777  {
1778  sinfo_msg_error("wrong width of linear slope given!") ;
1779  return -6 ;
1780  }
1781 
1782  /* initialize module global variable slopewidth */
1783  slopewidth = slope_width ;
1784 
1785  /* allocate memory for the edges and the row positon of the slitlets */
1786  sinfo_edge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1787  dummyedge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1788  edgeclean = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
1789  pos_row = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
1790  pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
1791 
1792  /* ------------------------------------------------------------------------
1793  * go through the first image columns and the fit parameters and find
1794  * the line with the highest intensity
1795  */
1796  agreed = -1 ;
1797  bad_line = -1 ;
1798  while( agreed == -1 )
1799  {
1800  found = -1 ;
1801  max_intensity = -FLT_MAX ;
1802  for ( col = 0 ; col < box_length ; col++ )
1803  {
1804  for ( i = 0 ; i < par[0]->n_params ; i++ )
1805  {
1806  if ( par[i]->column == col && par[i]->line != bad_line )
1807  {
1808  if ( par[i]->fit_par[0] > max_intensity )
1809  {
1810  if ( par[i]->fit_par[1] > 0. )
1811  {
1812  max_intensity = par[i]->fit_par[0] ;
1813  found = i ;
1814  }
1815  }
1816  }
1817  }
1818  }
1819 
1820  /* --------------------------------------------------------------------
1821  * check if the found line is usable and if the neighbouring line
1822  * have intensity on near rows in neighbouring slitlets
1823  */
1824  line = par[found]->line ;
1825  column = par[found]->column ;
1826  row_pos = par[found]->fit_par[2] ;
1827  if ( found >= 0 && max_intensity > 0. )
1828  {
1829  for ( i = 0 ; i < par[0]->n_params ; i++ )
1830  {
1831  if ( par[i]->line == line-1 &&
1832  par[i]->column == column + slit_length )
1833  {
1834  if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
1835  par[i]->fit_par[2] >= (row_pos - y_box) )
1836  {
1837  bad_line = line ;
1838  }
1839  }
1840  }
1841  if ( bad_line != line )
1842  {
1843  agreed = 1 ;
1844  break ;
1845  }
1846  }
1847  else
1848  {
1849  sinfo_msg_error("no emission line found in the first image columns");
1850  return -7 ;
1851  }
1852  }
1853 
1854 
1855  if ( agreed == -1 )
1856  {
1857  sinfo_msg_error("no emission line found in the first image columns") ;
1858  return -7 ;
1859  }
1860 
1861  /* now find and store the raw sinfo_edge positions of the found slitlet */
1862  n = 0 ;
1863  ed = 0 ;
1864  position=cpl_calloc(ilx,sizeof(float)) ;
1865 
1866  for ( col = 0 ; col < ilx ; col++ )
1867  {
1868  for ( i = 0 ; i < par[0]->n_params ; i++ )
1869  {
1870  if ( par[i]->column == col && par[i] -> line == line )
1871  {
1872  if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
1873  {
1874  position[n] = par[i]->fit_par[2] ;
1875  if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
1876  {
1877  sinfo_edge[ed] = col ;
1878  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
1879  ed++ ;
1880  if ( col >= ilx - slit_length - 5 )
1881  {
1882  pos_row[ed] = sinfo_new_nint( position[n] ) ;
1883  }
1884  }
1885  n++ ;
1886  }
1887  }
1888  }
1889  }
1890  if ( ed < (slit_length - 1) )
1891  {
1892  sinfo_msg_error("not enough slitlets found") ;
1893  return -8 ;
1894  }
1895 
1896  /* now find the clean sinfo_edge and row positions of the slitlets */
1897  for ( i = 1 ; i <= ed ; i ++ )
1898  {
1899  if (dummyedge[i-1] != -1)
1900  {
1901  dummyedge[i-1] = sinfo_edge[i-1] ;
1902  }
1903  if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
1904  (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
1905  {
1906  dummyedge[i] = -1 ;
1907  }
1908  if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
1909  (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
1910  {
1911  dummyedge[i+1] = -1 ;
1912  }
1913  }
1914 
1915  k = 0 ;
1916  for ( i = 0 ; i < ed ; i++ )
1917  {
1918  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
1919  {
1920  edgeclean[k] = dummyedge[i] ;
1921  pos_rowclean[k] = pos_row[i] ;
1922  k++ ;
1923  if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
1924  {
1925  pos_rowclean[k] = pos_row[ed] ;
1926  }
1927  }
1928  }
1929 
1930  if ( k != slit_length - 1 )
1931  {
1932  sinfo_msg_error ("not enough clean slitlets found") ;
1933  return -7 ;
1934  }
1935 
1936  /* determine the margins of the fitting box outside the slitlets */
1937  margin = ( box_length - slit_length ) / 2 ;
1938 
1939  /* now go through the slitlets and store the intensity in a buffer
1940  sinfo_vector */
1941  for ( j = 0 ; j < k ; j++ )
1942  {
1943  m = 0 ;
1944  if ( j == 0 )
1945  {
1946  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
1947  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
1948  {
1949  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[0]] ;
1950  m++ ;
1951  }
1952  /* initial values for the fitted positions */
1953  fitpar[0] = 1. ;
1954  fitpar[1] = (float)edgeclean[0] ;
1955 
1956  }
1957  else if ( j < k - 1 )
1958  {
1959  box_buffer = sinfo_new_vector( edgeclean[j] -
1960  edgeclean[j-1] + 2*margin ) ;
1961  for ( col = edgeclean[j - 1] - margin ;
1962  col < edgeclean[j] + margin ; col++ )
1963  {
1964  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
1965  m++ ;
1966  }
1967  /* initial values for the fitted positions */
1968  fitpar[0] = (float)margin ;
1969  fitpar[1] = (float)(edgeclean[j] - edgeclean[j-1] + margin ) ;
1970  }
1971  /*else if ( j == k - 1 )*/
1972  else
1973  {
1974  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
1975  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
1976  {
1977  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
1978  m++ ;
1979  }
1980  /* initial values for the fitted positions */
1981  fitpar[0] = (float)margin ;
1982  fitpar[1] = (float)(m - 1) ;
1983  }
1984 
1985  xdat=(float *) cpl_calloc( box_buffer -> n_elements, sizeof (float) ) ;
1986  wdat=(float *) cpl_calloc( box_buffer -> n_elements, sizeof (float) ) ;
1987  mpar=(int *) cpl_calloc( NPAR, sizeof (int) ) ;
1988 
1989  /* set initial values for the fitting routine */
1990  minval = FLT_MAX ;
1991  maxval = -FLT_MAX ;
1992  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
1993  {
1994  xdat[i] = i ;
1995  wdat[i] = 1.0 ;
1996  if ( box_buffer -> data[i] < minval )
1997  {
1998  minval = box_buffer -> data[i] ;
1999  }
2000  if ( box_buffer -> data[i] > maxval )
2001  {
2002  maxval = box_buffer -> data[i] ;
2003  }
2004  }
2005 
2006  for ( i = 0 ; i < NPAR ; i++ )
2007  {
2008  mpar[i] = 1 ;
2009  dervpar[i] = 0. ;
2010  }
2011 
2012  xdim = XDIMA ;
2013  ndat = box_buffer -> n_elements ;
2014  numpar = NPAR ;
2015  tol = TOLA ;
2016  lab = LABA ;
2017  its = ITSA ;
2018 
2019  fitpar[2] = minval ;
2020  fitpar[3] = minval ;
2021  fitpar[4] = maxval ;
2022 
2023  /* finally, do the least squares fit over the buffer data */
2024  if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim,
2025  box_buffer -> data,
2026  wdat, &ndat, fitpar,
2027  dervpar, mpar, &numpar,
2028  &tol, &its, &lab )) )
2029  {
2030  sinfo_msg_warning("least squares fit failed, error no.: %d",
2031  iters) ;
2032  return -9 ;
2033  }
2034 
2035 
2036  /* take care of the column position of the fit boxes
2037  to get the absolute positions */
2038  if ( j == 0 )
2039  {
2040  sinfo_slit_pos[0][0] = fitpar[0] + slopewidth/2. ;
2041  sinfo_slit_pos[0][1] = fitpar[1] - slopewidth/2. ;
2042  }
2043  else
2044  {
2045  sinfo_slit_pos[j][0] = fitpar[0] + slopewidth/2. +
2046  (float)edgeclean[j-1] - (float)margin ;
2047  sinfo_slit_pos[j][1] = fitpar[1] - slopewidth/2. +
2048  (float)edgeclean[j-1] - (float)margin ;
2049  }
2050 
2051  sinfo_slit_pos[k][0] = fitpar[0] + slopewidth/2. +
2052  (float)edgeclean[k-1] - (float)margin ;
2053  sinfo_slit_pos[k][1] = fitpar[1] - slopewidth/2. +
2054  (float)edgeclean[k-1] - (float)margin ;
2055 
2056  sinfo_new_destroy_vector ( box_buffer ) ;
2057  cpl_free( xdat ) ;
2058  cpl_free( wdat ) ;
2059  cpl_free( mpar ) ;
2060  }
2061 
2062 
2063  cpl_free( sinfo_edge ) ;
2064  cpl_free( pos_row ) ;
2065  cpl_free( edgeclean ) ;
2066  cpl_free( dummyedge ) ;
2067  cpl_free( pos_rowclean ) ;
2068  cpl_free( position );
2069  return 0 ;
2070 }
2071 
2116 int
2117 sinfo_new_fit_slits2( cpl_image * lineImage,
2118  FitParams ** par,
2119  float ** sinfo_slit_pos,
2120  int box_length,
2121  float y_box,
2122  float diff_tol )
2123 {
2124  float* position=NULL ;
2125  int * sinfo_edge, * edgeclean ;
2126  int * dummyedge ;
2127  int * pos_row, * pos_rowclean ;
2128  Vector * box_buffer ;
2129  Vector * half_buffer ;
2130  float max_intensity ;
2131  float row_pos ;
2132  int col ;
2133  int i, j, k, m, n, ed ;
2134  int found, init1 ;
2135  int line ;
2136  int nel, n_right, left_right ;
2137  int column ;
2138  int slit_length ;
2139  int agreed ;
2140  int bad_line ;
2141  int margin ;
2142  int iters, xdim, ndat ;
2143  int numpar, its ;
2144  int * mpar ;
2145  float * xdat, * wdat ;
2146  float tol, lab ;
2147  float fitpar[NPAR] ;
2148  float dervpar[NPAR] ;
2149  float minval, maxval ;
2150  float pos, last_pos ;
2151  int ilx=0;
2152  //int ily=0;
2153  float* pidata=NULL;
2154 
2155 
2156  if ( NULL == lineImage )
2157  {
2158  sinfo_msg_error("no line image given!" ) ;
2159  return -1 ;
2160  }
2161  ilx=cpl_image_get_size_x(lineImage);
2162  //ily=cpl_image_get_size_y(lineImage);
2163  pidata=cpl_image_get_data_float(lineImage);
2164 
2165  slit_length = (int) sqrt (ilx) ;
2166 
2167  if ( NULL == par )
2168  {
2169  sinfo_msg_error("no line fit parameters given!" ) ;
2170  return -2 ;
2171  }
2172 
2173  if ( NULL == sinfo_slit_pos )
2174  {
2175  sinfo_msg_error("no position array allocated!" ) ;
2176  return -3 ;
2177  }
2178 
2179  if ( box_length < slit_length ||
2180  box_length >= 3*slit_length )
2181  {
2182  sinfo_msg_error("wrong fitting box length given!" ) ;
2183  return -4 ;
2184  }
2185 
2186  if ( y_box <= 0. || y_box > 3. )
2187  {
2188  sinfo_msg_error("wrong y box length given!" ) ;
2189  return -5 ;
2190  }
2191 
2192  if ( diff_tol < 1. )
2193  {
2194  sinfo_msg_error("diff_tol too small!" ) ;
2195  return -6 ;
2196  }
2197 
2198  /* allocate memory for the edges and the row positon of the slitlets */
2199  sinfo_edge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2200  dummyedge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2201  edgeclean = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
2202  pos_row = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2203  pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
2204 
2205  /* ------------------------------------------------------------------------
2206  * go through the first image columns and the fit parameters and find
2207  * the line with the highest intensity
2208  */
2209  agreed = -1 ;
2210  bad_line = -1 ;
2211  while( agreed == -1 )
2212  {
2213  found = -1 ;
2214  max_intensity = -FLT_MAX ;
2215  for ( col = 0 ; col < box_length ; col++ )
2216  {
2217  for ( i = 0 ; i < par[0]->n_params ; i++ )
2218  {
2219  if ( par[i]->column == col && par[i]->line != bad_line )
2220  {
2221  if ( par[i]->fit_par[0] > max_intensity )
2222  {
2223  if ( par[i]->fit_par[1] > 0. )
2224  {
2225  max_intensity = par[i]->fit_par[0] ;
2226  found = i ;
2227  }
2228  }
2229  }
2230  }
2231  }
2232 
2233  /* --------------------------------------------------------------------
2234  * check if the found line is usable and if the neighbouring line
2235  * have intensity on near rows in neighbouring slitlets
2236  */
2237  line = par[found]->line ;
2238  column = par[found]->column ;
2239  row_pos = par[found]->fit_par[2] ;
2240  if ( found >= 0 && max_intensity > 0. )
2241  {
2242  for ( i = 0 ; i < par[0]->n_params ; i++ )
2243  {
2244  if ( par[i]->line == line-1 &&
2245  par[i]->column == column + slit_length )
2246  {
2247  if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
2248  par[i]->fit_par[2] >= (row_pos - y_box) )
2249  {
2250  bad_line = line ;
2251  }
2252  }
2253  }
2254  if ( bad_line != line )
2255  {
2256  agreed = 1 ;
2257  break ;
2258  }
2259  }
2260  else
2261  {
2262  sinfo_msg_error("no emission line found in the first image columns");
2263  return -7 ;
2264  }
2265  }
2266 
2267 
2268  if ( agreed == -1 )
2269  {
2270  sinfo_msg_error("no emission line found in the first image columns") ;
2271  return -7 ;
2272  }
2273 
2274  /* now find and store the raw sinfo_edge positions of the found slitlet */
2275  n = 0 ;
2276  ed = 0 ;
2277  position=cpl_calloc(ilx,sizeof(float)) ;
2278 
2279  for ( col = 0 ; col < ilx ; col++ )
2280  {
2281  for ( i = 0 ; i < par[0]->n_params ; i++ )
2282  {
2283  if ( par[i]->column == col && par[i]->line == line )
2284  {
2285  if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
2286  {
2287  position[n] = par[i]->fit_par[2] ;
2288  if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
2289  {
2290  sinfo_edge[ed] = col ;
2291  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
2292  ed++ ;
2293  if ( col >= ilx - slit_length - 5 )
2294  {
2295  pos_row[ed] = sinfo_new_nint( position[n] ) ;
2296  }
2297  }
2298  n++ ;
2299  }
2300  }
2301  }
2302  }
2303  if ( ed < (slit_length - 1) )
2304  {
2305  sinfo_msg_error("not enough slitlets found") ;
2306  return -8 ;
2307  }
2308 
2309  /* now find the clean sinfo_edge and row positions of the slitlets */
2310  for ( i = 1 ; i <= ed ; i ++ )
2311  {
2312  if (dummyedge[i-1] != -1)
2313  {
2314  dummyedge[i-1] = sinfo_edge[i-1] ;
2315  }
2316  if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
2317  (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
2318  {
2319  dummyedge[i] = -1 ;
2320  }
2321  if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
2322  (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
2323  {
2324  dummyedge[i+1] = -1 ;
2325  }
2326  }
2327 
2328  k = 0 ;
2329  for ( i = 0 ; i < ed ; i++ )
2330  {
2331  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
2332  {
2333  edgeclean[k] = dummyedge[i] ;
2334  pos_rowclean[k] = pos_row[i] ;
2335  k++ ;
2336  if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
2337  {
2338  pos_rowclean[k] = pos_row[ed] ;
2339  }
2340  }
2341  }
2342 
2343  if ( k != slit_length - 1 )
2344  {
2345  sinfo_msg_error("not enough clean slitlets found") ;
2346  return -7 ;
2347  }
2348 
2349  /* determine the margins of the fitting box outside the slitlets */
2350  margin = ( box_length - slit_length ) / 2 ;
2351 
2352  /* now go through the slitlets and store the intensity in a
2353  buffer sinfo_vector */
2354  for ( j = 0 ; j <= k ; j++ )
2355  {
2356  m = 0 ;
2357  if ( j == 0 )
2358  {
2359  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
2360  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
2361  {
2362  box_buffer->data[m] = pidata[col +ilx*pos_rowclean[0]] ;
2363  m++ ;
2364  }
2365  }
2366  else if ( j < k )
2367  {
2368  box_buffer = sinfo_new_vector( edgeclean[j] -
2369  edgeclean[j-1] + 2*margin ) ;
2370  for ( col = edgeclean[j - 1] - margin ;
2371  col < edgeclean[j] + margin ; col++ )
2372  {
2373  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
2374  m++ ;
2375  }
2376  }
2377  else
2378  {
2379  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
2380  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
2381  {
2382  box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
2383  m++ ;
2384  }
2385  }
2386 
2387  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
2388  {
2389  nel = 0 ;
2390  if ( left_right == 0 )
2391  {
2392  nel = box_buffer -> n_elements / 2 ;
2393  }
2394  else
2395  {
2396  if ( box_buffer -> n_elements % 2 == 0 )
2397  {
2398  nel = box_buffer -> n_elements / 2 ;
2399  }
2400  else
2401  {
2402  nel = box_buffer -> n_elements / 2 + 1 ;
2403  }
2404  }
2405 
2406  /* now split the buffer in the midth in a left and right
2407  part for fitting */
2408  half_buffer = sinfo_new_vector( nel ) ;
2409  if ( left_right == 0 )
2410  {
2411  for ( i = 0 ; i < nel ; i++ )
2412  {
2413  half_buffer -> data[i] = box_buffer -> data[i] ;
2414  }
2415  }
2416  else
2417  {
2418  n_right = 0 ;
2419  for ( i = box_buffer -> n_elements - 1 ;
2420  i >= box_buffer -> n_elements - nel ; i-- )
2421  {
2422  half_buffer -> data[n_right] = box_buffer -> data[i] ;
2423  n_right++ ;
2424  }
2425  }
2426 
2427  xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
2428  wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
2429  mpar = (int *) cpl_calloc( NPAR, sizeof (int) ) ;
2430 
2431  /* set initial values for the fitting routine */
2432  minval = FLT_MAX ;
2433  maxval = -FLT_MAX ;
2434  for ( i = 0 ; i < nel ; i++ )
2435  {
2436  xdat[i] = i ;
2437  wdat[i] = 1.0 ;
2438  if ( half_buffer -> data[i] < minval )
2439  {
2440  minval = half_buffer -> data[i] ;
2441  }
2442  if ( half_buffer -> data[i] > maxval )
2443  {
2444  maxval = half_buffer -> data[i] ;
2445  }
2446  }
2447 
2448  fitpar[2] = minval ;
2449  fitpar[3] = maxval ;
2450 
2451  /* search for both positions of the half intensity of
2452  the hat within the buffer */
2453  init1 = -1 ;
2454  for ( i = 0 ; i < nel ; i++ )
2455  {
2456  if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
2457  {
2458  init1 = i ;
2459  break ;
2460  }
2461  }
2462 
2463  /* determine the initial positions from the found values */
2464  if ( init1 != -1 )
2465  {
2466  fitpar[0] = ((float)init1 - 1.) ;
2467  fitpar[1] = ((float)init1 + 1.) ;
2468  }
2469 
2470  for ( i = 0 ; i < NPAR ; i++ )
2471  {
2472  mpar[i] = 1 ;
2473  dervpar[i] = 0. ;
2474  }
2475 
2476  xdim = XDIMA ;
2477  ndat = nel ;
2478  numpar = NPAR ;
2479  tol = TOLA ;
2480  lab = LABA ;
2481  its = ITSA ;
2482 
2483  /* finally, do the least squares fit over the buffer data */
2484  if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim,
2485  half_buffer -> data,
2486  wdat, &ndat, fitpar,
2487  dervpar, mpar, &numpar,
2488  &tol, &its, &lab )) )
2489  {
2490  /* if the fit doesn't succeed the initial values are taken */
2491  sinfo_msg_warning (" least squares fit failed, error"
2492  " no.: %d in slitlet: %d\n", iters, j) ;
2493  fitpar[0] = ((float)init1 - 1.) ;
2494  fitpar[1] = ((float)init1 + 1.) ;
2495  }
2496 
2497  pos = (fitpar[0] + fitpar[1]) / 2. ;
2498 
2499  /*----------------------------------------------------------------
2500  * now discern the left and the right sinfo_edge fit of the
2501  * slitlets and associate the fit results with the absolute
2502  * positions in the image consider the difference of the fitted
2503  * slit position to the expected position and decide wether the
2504  * fit is taken or the expected value is taken.
2505  */
2506  if ( left_right == 0 )
2507  {
2508  /* take care of the column position of the fit boxes
2509  to get the absolute positions */
2510  if ( j == 0 )
2511  {
2512  if ( fabs(pos - ((float)edgeclean[0] - 1. -
2513  (float)slit_length)) < diff_tol )
2514  {
2515  sinfo_slit_pos[0][0] = pos ;
2516  }
2517  else
2518  {
2519  sinfo_msg_warning("something wrong with fitted left"
2520  " position of slitlet 0") ;
2521  if ( (float) edgeclean[0] - 1. -
2522  (float)slit_length < 0. )
2523  {
2524  sinfo_slit_pos[0][0] = 0. ;
2525  }
2526  else
2527  {
2528  sinfo_slit_pos[0][0] = (float)edgeclean[0] - 1. -
2529  (float)slit_length ;
2530  }
2531  }
2532  }
2533  else if ( j < k )
2534  {
2535  if ( fabs( pos - (float)margin ) < diff_tol )
2536  {
2537  sinfo_slit_pos[j][0] = pos + (float)edgeclean[j-1] -
2538  (float)margin ;
2539  }
2540  else
2541  {
2542  sinfo_msg_warning("something wrong with fitted left"
2543  " position of slitlet %d", j) ;
2544  sinfo_slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
2545  }
2546  }
2547  else
2548  {
2549  if ( fabs( pos - (float)margin ) < diff_tol )
2550  {
2551  sinfo_slit_pos[k][0] = pos + (float)edgeclean[k-1] -
2552  (float)margin ;
2553  }
2554  else
2555  {
2556  sinfo_msg_warning("something wrong with fitted left"
2557  " position of slitlet %d", j) ;
2558  sinfo_slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
2559  }
2560  }
2561  }
2562  else
2563  {
2564  /* take care of the column position of the fit boxes
2565  to get the absolute positions */
2566  if ( j == 0 )
2567  {
2568  if ( fabs( (float)box_buffer->n_elements - pos -
2569  (float)edgeclean[0] ) < diff_tol )
2570  {
2571  sinfo_slit_pos[0][1] = (float)(box_buffer->n_elements -
2572  1) - pos ;
2573  }
2574  else
2575  {
2576  sinfo_msg_warning("something wrong with fitted "
2577  "right position of slitlet 0") ;
2578  sinfo_slit_pos[0][1] = (float)edgeclean[0] - 1. ;
2579  }
2580  }
2581  else if ( j < k )
2582  {
2583  if ( fabs( (float)box_buffer->n_elements - pos
2584  + (float)edgeclean[j-1] - (float)margin -
2585  (float)edgeclean[j] ) < diff_tol )
2586  {
2587  sinfo_slit_pos[j][1] = (float)(box_buffer->n_elements -
2588  1) - pos
2589  + (float)edgeclean[j-1] - (float)margin ;
2590  }
2591  else
2592  {
2593  sinfo_msg_warning("something wrong with fitted right "
2594  "position of slitlet %d", j) ;
2595  sinfo_slit_pos[j][1] = (float)edgeclean[j] - 1. ;
2596  }
2597  }
2598  else
2599  {
2600  if ( edgeclean[k-1] + slit_length > ilx )
2601  {
2602  last_pos = (float)(ilx - 1) ;
2603  }
2604  else
2605  {
2606  last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
2607  }
2608  if ( fabs( (float)(box_buffer->n_elements - 1) - pos
2609  + (float)edgeclean[k-1] - (float)margin -
2610  last_pos ) < diff_tol )
2611  {
2612  sinfo_slit_pos[k][1] = (float)(box_buffer->n_elements -
2613  1) - pos
2614  + (float)edgeclean[k-1] - (float)margin ;
2615  }
2616  else
2617  {
2618  sinfo_msg_warning("something wrong with fitted right "
2619  "position of slitlet %d\n", j) ;
2620  sinfo_slit_pos[k][1] = last_pos ;
2621  }
2622  }
2623  }
2624 
2625  sinfo_new_destroy_vector ( half_buffer ) ;
2626  cpl_free( xdat ) ;
2627  cpl_free( wdat ) ;
2628  cpl_free( mpar ) ;
2629  }
2630  sinfo_new_destroy_vector ( box_buffer ) ;
2631  }
2632 
2633  cpl_free( sinfo_edge ) ;
2634  cpl_free( pos_row ) ;
2635  cpl_free( edgeclean ) ;
2636  cpl_free( dummyedge ) ;
2637  cpl_free( pos_rowclean ) ;
2638  cpl_free(position);
2639  return 0 ;
2640 }
2641 
2676 int
2677 sinfo_new_fit_slits_edge( cpl_image * lineImage,
2678  FitParams ** par,
2679  float ** sinfo_slit_pos,
2680  int box_length,
2681  float y_box,
2682  float diff_tol )
2683 {
2684  float* position=NULL ;
2685  int * sinfo_edge, * edgeclean ;
2686  int * dummyedge ;
2687  int * pos_row, * pos_rowclean ;
2688  Vector * box_buffer ;
2689  Vector * half_buffer ;
2690  float max_intensity ;
2691  float row_pos ;
2692  int row, col ;
2693  int i, j, k, m, n, ed ;
2694  int found, init1 ;
2695  int line ;
2696  int nel, n_right, left_right ;
2697  int column ;
2698  int slit_length ;
2699  int agreed ;
2700  int bad_line ;
2701  int margin ;
2702  int iters, xdim, ndat ;
2703  int numpar, its ;
2704  int * mpar ;
2705  float * xdat, * wdat ;
2706  float tol, lab ;
2707  float fitpar[NPAR] ;
2708  float dervpar[NPAR] ;
2709  float minval, maxval ;
2710  float pos, last_pos ;
2711  int ilx=0;
2712  //int ily=0;
2713  float* pidata=NULL;
2714 
2715 
2716  if ( NULL == lineImage )
2717  {
2718  sinfo_msg_error(" no line image given!" ) ;
2719  return -1 ;
2720  }
2721  ilx=cpl_image_get_size_x(lineImage);
2722  //ily=cpl_image_get_size_y(lineImage);
2723  pidata=cpl_image_get_data_float(lineImage);
2724 
2725  slit_length = (int) sqrt (ilx) ;
2726 
2727  if ( NULL == par )
2728  {
2729  sinfo_msg_error(" no line fit parameters given!" ) ;
2730  return -2 ;
2731  }
2732 
2733  if ( NULL == sinfo_slit_pos )
2734  {
2735  sinfo_msg_error(" no position array allocated!" ) ;
2736  return -3 ;
2737  }
2738 
2739  if ( box_length < 4 ||
2740  box_length >= 2*slit_length )
2741  {
2742  sinfo_msg_error(" wrong fitting box length given!" ) ;
2743  sinfo_msg_error(" Must be 4 <= box_length < %d ",2*slit_length ) ;
2744  sinfo_msg_error(" You have chosen box_length = %d ",box_length);
2745  return -4 ;
2746  }
2747 
2748  if ( y_box <= 0. || y_box > 3. )
2749  {
2750  sinfo_msg_error(" wrong y box length given!" ) ;
2751  sinfo_msg_error(" y_box=%f not in range (0,3]!",y_box);
2752  return -5 ;
2753  }
2754 
2755  if ( diff_tol < 1. )
2756  {
2757  sinfo_msg_error(" diff_tol too small!" ) ;
2758  return -6 ;
2759  }
2760 
2761  /* allocate memory for the edges and the row positon of the slitlets */
2762  sinfo_edge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2763  dummyedge = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2764  edgeclean = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
2765  pos_row = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
2766  pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
2767 
2768  /* ------------------------------------------------------------------------
2769  * go through the first image columns and the fit parameters and find
2770  * the line with the highest intensity
2771  */
2772  agreed = -1 ;
2773  bad_line = -1 ;
2774  while( agreed == -1 )
2775  {
2776  found = -1 ;
2777  max_intensity = -FLT_MAX ;
2778  for ( col = 0 ; col < slit_length ; col++ )
2779  {
2780  for ( i = 0 ; i < par[0]->n_params ; i++ )
2781  {
2782  if ( par[i]->column == col && par[i] -> line != bad_line )
2783  {
2784  if ( par[i]->fit_par[0] > max_intensity )
2785  {
2786  if ( par[i]->fit_par[1] >= 1. &&
2787  par[i]->fit_par[2] > 0. )
2788  {
2789  max_intensity = par[i]->fit_par[0] ;
2790  found = i ;
2791  }
2792  }
2793  }
2794  }
2795  }
2796 
2797  /* --------------------------------------------------------------------
2798  * check if the found line is usable and if the neighbouring line
2799  * have intensity on near rows in neighbouring slitlets
2800  */
2801  line = par[found]->line ;
2802  column = par[found]->column ;
2803  row_pos = par[found]->fit_par[2] ;
2804  if ( found >= 0 && max_intensity > 0. )
2805  {
2806  for ( i = 0 ; i < par[0]->n_params ; i++ )
2807  {
2808  if ( par[i]->line == line-1 &&
2809  par[i]->column == column + slit_length )
2810  {
2811  if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
2812  par[i]->fit_par[2] >= (row_pos - y_box) )
2813  {
2814  bad_line = line ;
2815  }
2816  }
2817  }
2818  if ( bad_line != line )
2819  {
2820  agreed = 1 ;
2821  break ;
2822  }
2823  }
2824  else
2825  {
2826  sinfo_msg_error("no emission line found in "
2827  "the first image columns") ;
2828  cpl_free( sinfo_edge ) ;
2829  cpl_free( pos_row ) ;
2830  cpl_free( edgeclean ) ;
2831  cpl_free( dummyedge ) ;
2832  cpl_free( pos_rowclean ) ;
2833  return -7 ;
2834  }
2835  }
2836 
2837 
2838  if ( agreed == -1 )
2839  {
2840  sinfo_msg_error(" no emission line found in the first image columns") ;
2841  cpl_free( sinfo_edge ) ;
2842  cpl_free( pos_row ) ;
2843  cpl_free( edgeclean ) ;
2844  cpl_free( dummyedge ) ;
2845  cpl_free( pos_rowclean ) ;
2846  return -7 ;
2847  }
2848 
2849  /* now find and store the raw sinfo_edge positions of the found slitlet */
2850  n = 0 ;
2851  ed = 0 ;
2852  position=cpl_calloc(ilx,sizeof(float)) ;
2853 
2854  for ( col = 0 ; col < ilx ; col++ )
2855  {
2856  for ( i = 0 ; i < par[0]->n_params ; i++ )
2857  {
2858  if ( par[i]->column == col && par[i]->line == line )
2859  {
2860  if ( par[i]->fit_par[0] > 0. &&
2861  par[i]->fit_par[1] >= 1. &&
2862  par[i]->fit_par[2] > 0. )
2863  {
2864  position[n] = par[i]->fit_par[2] ;
2865  if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
2866  {
2867  sinfo_edge[ed] = col ;
2868  pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
2869  ed++ ;
2870  if ( col >= ilx - slit_length - 5 )
2871  {
2872  pos_row[ed] = sinfo_new_nint( position[n] ) ;
2873  }
2874  }
2875  n++ ;
2876  }
2877  }
2878  }
2879  }
2880  if ( ed < (slit_length - 1) )
2881  {
2882  sinfo_msg_error(" not enough slitlets found") ;
2883  cpl_free( sinfo_edge ) ;
2884  cpl_free( pos_row ) ;
2885  cpl_free( edgeclean ) ;
2886  cpl_free( dummyedge ) ;
2887  cpl_free( pos_rowclean ) ;
2888  return -8 ;
2889  }
2890 
2891  /* now find the clean sinfo_edge and row positions of the slitlets */
2892  for ( i = 1 ; i <= ed ; i ++ )
2893  {
2894  if ( i == ed )
2895  {
2896  if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) < slit_length - 3 ||
2897  (sinfo_edge[i-1] - sinfo_edge[i-2]) > slit_length + 3 )
2898  {
2899  dummyedge[i-1] = -1 ;
2900  }
2901 
2902  }
2903  if (dummyedge[i-1] != -1)
2904  {
2905  dummyedge[i-1] = sinfo_edge[i-1] ;
2906  }
2907  else
2908  {
2909  continue ;
2910  }
2911  if ( i < ed )
2912  {
2913  if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
2914  (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
2915  {
2916  dummyedge[i] = -1 ;
2917  }
2918  }
2919  if ( i + 1 < ed && dummyedge[i] != -1 )
2920  {
2921  if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
2922  (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
2923  {
2924  dummyedge[i+1] = -1 ;
2925  }
2926  }
2927  }
2928 
2929  k = 0 ;
2930  for ( i = 0 ; i < ed ; i++ )
2931  {
2932  if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
2933  {
2934  edgeclean[k] = dummyedge[i] ;
2935  pos_rowclean[k] = pos_row[i] ;
2936  k++ ;
2937  if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
2938  {
2939  pos_rowclean[k] = pos_row[ed] ;
2940  }
2941  }
2942  }
2943 
2944  if ( k != slit_length - 1 )
2945  {
2946  sinfo_msg_error(" not enough clean slitlets found") ;
2947  cpl_free( sinfo_edge ) ;
2948  cpl_free( pos_row ) ;
2949  cpl_free( edgeclean ) ;
2950  cpl_free( dummyedge ) ;
2951  cpl_free( pos_rowclean ) ;
2952  return -8 ;
2953  }
2954 
2955  /* determine the margins of the fitting box outside the slitlets */
2956  margin = box_length / 2 ;
2957 
2958  /* ------------------------------------------------------------------------
2959  * now go through the slitlets, search along each column within a box with
2960  * half width y_box the maximum value and store these found values in a
2961  * buffer
2962  */
2963  for ( j = 0 ; j <= k ; j++ )
2964  {
2965  m = 0 ;
2966  if ( j == 0 )
2967  {
2968  box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
2969  for( col = 0 ; col < edgeclean[0] + margin ; col++ )
2970  {
2971  maxval = -FLT_MAX ;
2972  for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ;
2973  row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
2974  {
2975  if ( maxval < pidata[col + ilx*row] )
2976  {
2977  maxval = pidata[col + ilx*row] ;
2978  }
2979  }
2980  box_buffer->data[m] = maxval ;
2981  m++ ;
2982  }
2983  }
2984  else if ( j < k )
2985  {
2986  box_buffer = sinfo_new_vector( edgeclean[j] -
2987  edgeclean[j-1] + 2*margin ) ;
2988  for ( col = edgeclean[j - 1] - margin ;
2989  col < edgeclean[j] + margin ; col++ )
2990  {
2991  maxval = -FLT_MAX ;
2992  for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ;
2993  row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
2994  {
2995  if ( maxval < pidata[col + ilx*row] )
2996  {
2997  maxval = pidata[col + ilx*row] ;
2998  }
2999  }
3000  box_buffer->data[m] = maxval ;
3001  m++ ;
3002  }
3003  }
3004  else
3005  {
3006  box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
3007  for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
3008  {
3009  maxval = -FLT_MAX ;
3010  for ( row = pos_rowclean[k] - sinfo_new_nint(y_box) ;
3011  row <= pos_rowclean[k] + sinfo_new_nint(y_box) ; row++ )
3012  {
3013  if ( maxval < pidata[col + ilx*row] )
3014  {
3015  maxval = pidata[col + ilx*row] ;
3016  }
3017  }
3018  box_buffer->data[m] = maxval ;
3019  m++ ;
3020  }
3021  }
3022 
3023  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
3024  {
3025  nel = 0 ;
3026  if ( left_right == 0 )
3027  {
3028  nel = box_buffer -> n_elements / 2 ;
3029  }
3030  else
3031  {
3032  if ( box_buffer -> n_elements % 2 == 0 )
3033  {
3034  nel = box_buffer -> n_elements / 2 ;
3035  }
3036  else
3037  {
3038  nel = box_buffer -> n_elements / 2 + 1 ;
3039  }
3040  }
3041 
3042  /* now split the buffer in the midth in a left and right
3043  part for fitting */
3044  half_buffer = sinfo_new_vector( nel ) ;
3045  if ( left_right == 0 )
3046  {
3047  for ( i = 0 ; i < nel ; i++ )
3048  {
3049  half_buffer -> data[i] = box_buffer -> data[i] ;
3050  }
3051  }
3052  else
3053  {
3054  n_right = 0 ;
3055  for ( i = box_buffer -> n_elements - 1 ;
3056  i >= box_buffer -> n_elements - nel ; i-- )
3057  {
3058  half_buffer -> data[n_right] = box_buffer -> data[i] ;
3059  n_right++ ;
3060  }
3061  }
3062 
3063  xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
3064  wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
3065  mpar = (int *) cpl_calloc( NPAR, sizeof (int) ) ;
3066 
3067  /* set initial values for the fitting routine */
3068  minval = FLT_MAX ;
3069  maxval = -FLT_MAX ;
3070  for ( i = 0 ; i < nel ; i++ )
3071  {
3072  xdat[i] = i ;
3073  wdat[i] = 1.0 ;
3074  if ( half_buffer -> data[i] < minval )
3075  {
3076  minval = half_buffer -> data[i] ;
3077  }
3078  if ( half_buffer -> data[i] > maxval )
3079  {
3080  maxval = half_buffer -> data[i] ;
3081  }
3082  }
3083 
3084  fitpar[2] = minval ;
3085  fitpar[3] = maxval ;
3086 
3087  /* search for both positions of the half intensity of
3088  the hat within the buffer */
3089  init1 = -1 ;
3090  for ( i = 0 ; i < nel ; i++ )
3091  {
3092  if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
3093  {
3094  init1 = i ;
3095  break ;
3096  }
3097  }
3098 
3099  /* determine the initial positions from the found values */
3100  if ( init1 != -1 )
3101  {
3102  fitpar[0] = ((float)init1 - 1.) ;
3103  fitpar[1] = ((float)init1 + 1.) ;
3104  }
3105 
3106  for ( i = 0 ; i < NPAR ; i++ )
3107  {
3108  mpar[i] = 1 ;
3109  dervpar[i] = 0. ;
3110  }
3111 
3112  xdim = XDIMA ;
3113  ndat = nel ;
3114  numpar = NPAR ;
3115  tol = TOLA ;
3116  lab = LABA ;
3117  its = ITSA ;
3118 
3119  /* finally, do the least squares fit over the buffer data */
3120  if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim,
3121  half_buffer -> data,
3122  wdat, &ndat, fitpar,
3123  dervpar, mpar, &numpar,
3124  &tol, &its, &lab )) )
3125  {
3126  /* if the fit doesn't succeed the initial values are taken */
3127  sinfo_msg_warning ("least squares fit failed, error "
3128  "no.: %d in slitlet: %d", iters, j) ;
3129  fitpar[0] = ((float)init1 - 1.) ;
3130  fitpar[1] = ((float)init1 + 1.) ;
3131  }
3132 
3133  pos = (fitpar[0] + fitpar[1]) / 2. ;
3134 
3135  /*-----------------------------------------------------------------
3136  * now discern the left and the right sinfo_edge fit of the
3137  * slitlets and associate the fit results with the absolute
3138  * positions in the image consider the difference of the fitted
3139  * slit position to the expected position and decide wether the
3140  * fit is taken or the expected value is taken.
3141  */
3142  if ( left_right == 0 )
3143  {
3144  /* take care of the column position of the fit boxes to get
3145  the absolute positions */
3146  if ( j == 0 )
3147  {
3148  if ( fabs(pos - ((float)edgeclean[0] - 1. -
3149  (float)slit_length)) < diff_tol )
3150  {
3151  sinfo_slit_pos[0][0] = pos ;
3152  }
3153  else
3154  {
3155  sinfo_msg_warning("something wrong with fitted "
3156  "left position of slitlet 0") ;
3157  if ((float) edgeclean[0] - 1. -
3158  (float)slit_length < 0. )
3159  {
3160  sinfo_slit_pos[0][0] = 0. ;
3161  }
3162  else
3163  {
3164  sinfo_slit_pos[0][0] = (float)edgeclean[0] - 1. -
3165  (float)slit_length ;
3166  }
3167  }
3168  }
3169  else if ( j < k )
3170  {
3171  if ( fabs( pos - (float)margin ) < diff_tol )
3172  {
3173  sinfo_slit_pos[j][0] = pos + (float)edgeclean[j-1] -
3174  (float)margin ;
3175  }
3176  else
3177  {
3178  sinfo_msg_warning("something wrong with fitted "
3179  "left position of slitlet %d", j) ;
3180  sinfo_slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
3181  }
3182  }
3183  else
3184  {
3185  if ( fabs( pos - (float)margin ) < diff_tol )
3186  {
3187  sinfo_slit_pos[k][0] = pos + (float)edgeclean[k-1] -
3188  (float)margin ;
3189  }
3190  else
3191  {
3192  sinfo_msg_warning("something wrong with fitted left "
3193  "position of slitlet %d", j) ;
3194  sinfo_slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
3195  }
3196  }
3197  }
3198  else
3199  {
3200  /* take care of the column position of the fit boxes to
3201  get the absolute positions */
3202  if ( j == 0 )
3203  {
3204  if ( fabs( (float)box_buffer->n_elements - pos -
3205  (float)edgeclean[0] ) < diff_tol )
3206  {
3207  sinfo_slit_pos[0][1] = (float)(box_buffer->n_elements -
3208  1) - pos ;
3209  }
3210  else
3211  {
3212  sinfo_msg_warning("something wrong with fitted "
3213  "right position of slitlet 0") ;
3214  sinfo_slit_pos[0][1] = (float)edgeclean[0] - 1. ;
3215  }
3216  }
3217  else if ( j < k )
3218  {
3219  if ( fabs( (float)box_buffer->n_elements - pos
3220  + (float)edgeclean[j-1] - (float)margin -
3221  (float)edgeclean[j] ) < diff_tol )
3222  {
3223  sinfo_slit_pos[j][1] = (float)(box_buffer->n_elements -
3224  1) - pos
3225  + (float)edgeclean[j-1] - (float)margin;
3226  }
3227  else
3228  {
3229  sinfo_msg_warning("something wrong with fitted "
3230  "right position of slitlet %d", j) ;
3231  sinfo_slit_pos[j][1] = (float)edgeclean[j] - 1. ;
3232  }
3233  }
3234  else
3235  {
3236  if ( edgeclean[k-1] + slit_length > ilx )
3237  {
3238  last_pos = (float)(ilx - 1) ;
3239  }
3240  else
3241  {
3242  last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
3243  }
3244  if ( fabs( (float)(box_buffer->n_elements - 1) - pos
3245  + (float)edgeclean[k-1] - (float)margin -
3246  last_pos ) < diff_tol )
3247  {
3248  sinfo_slit_pos[k][1] = (float)(box_buffer->n_elements -
3249  1) - pos
3250  + (float)edgeclean[k-1] - (float)margin ;
3251  }
3252  else
3253  {
3254  sinfo_msg_warning("something wrong with fitted "
3255  "right position of slitlet %d", j) ;
3256  sinfo_slit_pos[k][1] = last_pos ;
3257  }
3258  }
3259  }
3260 
3261  sinfo_new_destroy_vector ( half_buffer ) ;
3262  cpl_free( xdat ) ;
3263  cpl_free( wdat ) ;
3264  cpl_free( mpar ) ;
3265  }
3266  sinfo_new_destroy_vector ( box_buffer ) ;
3267  }
3268 
3269  cpl_free( sinfo_edge ) ;
3270  cpl_free( pos_row ) ;
3271  cpl_free( edgeclean ) ;
3272  cpl_free( dummyedge ) ;
3273  cpl_free( pos_rowclean ) ;
3274  cpl_free( position );
3275  return 0 ;
3276 }
3277 
3300 int
3301 sinfo_new_fit_slits_edge_with_estimate ( cpl_image * lineImage,
3302  float ** sinfo_slit_pos,
3303  int box_length,
3304  float y_box,
3305  float diff_tol,
3306  int low_pos,
3307  int high_pos )
3308 {
3309  int* position=NULL ;
3310  Vector * box_buffer ;
3311  Vector * in_buffer ;
3312  int found_row ;
3313  int row, col ;
3314  int col_first, col_last ;
3315  int row_first, row_last ;
3316  int i, j, m, n ;
3317  int init1 ;
3318  int left_right ;
3319  int n_buf, shift ;
3320  int slit_length ;
3321  int iters, xdim, ndat ;
3322  int numpar, its ;
3323  int * mpar ;
3324  float * xdat, * wdat ;
3325  float tol, lab ;
3326  float fitpar[NPAR] ;
3327  float dervpar[NPAR] ;
3328  float minval, maxval ;
3329  float pos ;
3330  float new_pos ;
3331  int slitposition[SLITLENGTH] ;
3332  pixelvalue rowpos[SLITLENGTH] ;
3333  int ilx=0;
3334  int ily=0;
3335  float* pidata=NULL;
3336 
3337  slit_length = SLITLENGTH ; /* this is too high: 64 */
3338  slit_length = N_SLITLETS ; /* this is better: 32 */
3339 
3340 
3341  if ( NULL == lineImage )
3342  {
3343  sinfo_msg_error(" no line image given!" ) ;
3344  return -1 ;
3345  }
3346  ilx=cpl_image_get_size_x(lineImage);
3347  ily=cpl_image_get_size_y(lineImage);
3348  pidata=cpl_image_get_data_float(lineImage);
3349 
3350  if ( NULL == sinfo_slit_pos )
3351  {
3352  sinfo_msg_error(" no position array allocated!" ) ;
3353  return -1 ;
3354  }
3355 
3356  if ( box_length < 4 ||
3357  box_length > 2*slit_length )
3358  {
3359  sinfo_msg_error(" wrong fitting box length given!" ) ;
3360  sinfo_msg_error(" Must be 4 <= box_length < %d ",2*slit_length ) ;
3361  sinfo_msg_error(" You have chosen box_length = %d",box_length);
3362 
3363 
3364  return -1 ;
3365  }
3366 
3367  if ( y_box <= 0. || y_box > 6. )
3368  {
3369  sinfo_msg_error("wrong y box length given!" ) ;
3370  sinfo_msg_error("You have chosen y_box=%f not in range (0,6]!",y_box);
3371  return -1 ;
3372  }
3373  if ( diff_tol <= 0. )
3374  {
3375  sinfo_msg_error(" wrong diff_tol given!" ) ;
3376  return -1 ;
3377  }
3378 
3379  if ( low_pos >= high_pos || low_pos < 0 ||
3380  high_pos <= 0 || high_pos > ily )
3381  {
3382  sinfo_msg_error(" wrong user given search positions!" ) ;
3383  return -1 ;
3384  }
3385 
3386  /* now search for the maximum between the given positions for each col */
3387  position=cpl_calloc(ilx,sizeof(int)) ;
3388 
3389  for ( col = 0 ; col < ilx ; col++ )
3390  {
3391  found_row = -1 ;
3392  maxval = -FLT_MAX ;
3393  for ( row = low_pos ; row <= high_pos ; row++ )
3394  {
3395  if ( maxval < pidata[col+row*ilx] )
3396  {
3397  maxval = pidata[col+row*ilx] ;
3398  found_row = row ;
3399  }
3400  }
3401  if ( maxval > -FLT_MAX && found_row > low_pos )
3402  {
3403  position[col] = found_row ;
3404  }
3405  else
3406  {
3407  position[col] = 0 ;
3408  }
3409  }
3410 
3411  /* ------------------------------------------------------------------------
3412  * now go through the slitlets, search along each column within a box with
3413  * half width y_box the maximum value and store these found values in a
3414  * buffer
3415  */
3416  for ( j = 0 ; j < slit_length ; j++ )
3417  {
3418  /* now go through the columns and determine the slitlet positions by
3419  * calculating the sinfo_median of the found positions
3420  */
3421  n = 0 ;
3422  for ( col = sinfo_new_nint(sinfo_slit_pos[j][0])+ 1 ;
3423  col < sinfo_new_nint(sinfo_slit_pos[j][1]) -1 ; col++ )
3424  {
3425  rowpos[n] = (pixelvalue)position[col] ;
3426  n++ ;
3427  }
3428  slitposition[j] = (int)sinfo_new_median(rowpos, n) ;
3429  for ( left_right = 0 ; left_right <= 1 ; left_right++ )
3430 
3431  {
3432  init1 = 0 ;
3433  col_first = sinfo_new_nint( sinfo_slit_pos[j][left_right] ) -
3434  box_length/2 ;
3435  col_last = sinfo_new_nint( sinfo_slit_pos[j][left_right] ) +
3436  box_length/2 ;
3437  if ( col_first < 0 )
3438  {
3439  col_first = 0 ;
3440  init1 = 1 ;
3441  }
3442  if ( col_last > ilx )
3443  {
3444  col_last = ilx ;
3445  init1 = 1 ;
3446  }
3447  if ( col_last - col_first <= 0 )
3448  {
3449  sinfo_msg_error(" first and last column wrong!" ) ;
3450  return -1 ;
3451  }
3452  box_buffer = sinfo_new_vector( col_last - col_first ) ;
3453  m = 0 ;
3454  if ( left_right == 0 )
3455  {
3456  for( col = col_first ; col < col_last ; col++ )
3457  {
3458  row_first = slitposition[j] - sinfo_new_nint(y_box) ;
3459  row_last = slitposition[j] + sinfo_new_nint(y_box) ;
3460  if ( row_first < 0 )
3461  {
3462  row_first = 0 ;
3463  }
3464  if ( row_last >= ily )
3465  {
3466  row_last = ily - 1 ;
3467  }
3468  maxval = -FLT_MAX ;
3469  for ( row = row_first ; row <= row_last ; row++ )
3470  {
3471  if ( maxval < pidata[col + ilx*row] )
3472  {
3473  maxval = pidata[col + ilx*row] ;
3474  }
3475  }
3476  box_buffer->data[m] = maxval ;
3477  m++ ;
3478  }
3479  }
3480  else
3481  {
3482  for( col = col_last-1 ; col >= col_first ; col-- )
3483  {
3484  row_first = slitposition[j] - sinfo_new_nint(y_box) ;
3485  row_last = slitposition[j] + sinfo_new_nint(y_box) ;
3486  if ( row_first < 0 )
3487  {
3488  row_first = 0 ;
3489  }
3490  if ( row_last >= ily )
3491  {
3492  row_last = ily - 1 ;
3493  }
3494  maxval = -FLT_MAX ;
3495  for ( row = row_first ; row <= row_last ; row++ )
3496  {
3497  if ( maxval < pidata[col + ilx*row] )
3498  {
3499  maxval = pidata[col + ilx*row] ;
3500  }
3501  }
3502  box_buffer->data[m] = maxval ;
3503  m++ ;
3504  }
3505  }
3506 
3507  xdat=(float *)cpl_calloc( box_buffer->n_elements, sizeof (float));
3508  wdat=(float *)cpl_calloc( box_buffer->n_elements, sizeof (float));
3509  mpar=(int *) cpl_calloc( NPAR, sizeof (int) ) ;
3510 
3511  /* set initial values for the fitting routine */
3512  minval = FLT_MAX ;
3513  maxval = -FLT_MAX ;
3514  for ( i = 0 ; i < box_buffer->n_elements ; i++ )
3515  {
3516  xdat[i] = i ;
3517  wdat[i] = 1.0 ;
3518  if ( box_buffer -> data[i] < minval )
3519  {
3520  minval = box_buffer -> data[i] ;
3521  }
3522  if ( box_buffer -> data[i] > maxval )
3523  {
3524  maxval = box_buffer -> data[i] ;
3525  }
3526  }
3527  fitpar[2] = minval ;
3528  fitpar[3] = maxval ;
3529  /*----------------------------------------------------------------
3530  * if we have too few left background values (at the image edges)
3531  * the left margin of the buffer to fit is filled with the minimal
3532  * values in order to get a good fit
3533  */
3534 
3535  if ( init1 == 1 )
3536  {
3537  n_buf = box_buffer->n_elements + box_length/2 ;
3538  in_buffer = sinfo_new_vector( n_buf ) ;
3539  for ( i = 0 ; i < box_length/2 ; i++ )
3540  {
3541  in_buffer -> data[i] = minval ;
3542  }
3543  shift = 0 ;
3544  for ( i = box_length/2 ; i < n_buf ; i++ )
3545  {
3546  in_buffer -> data[i] = box_buffer -> data[shift] ;
3547  shift++ ;
3548  }
3549  sinfo_new_destroy_vector ( box_buffer ) ;
3550  box_buffer = sinfo_new_vector ( n_buf ) ;
3551  for ( i = 0 ; i < n_buf ; i++ )
3552  {
3553  box_buffer -> data[i] = in_buffer -> data[i] ;
3554  }
3555  sinfo_new_destroy_vector ( in_buffer ) ;
3556  }
3557  /* determine the initial positions from the found values */
3558  fitpar[0] = (float)box_buffer->n_elements/2. - 1. ;
3559  fitpar[1] = (float)box_buffer->n_elements/2. + 1. ;
3560 
3561  for ( i = 0 ; i < NPAR ; i++ )
3562  {
3563  mpar[i] = 1 ;
3564  dervpar[i] = 0. ;
3565  }
3566 
3567  xdim = XDIMA ;
3568  ndat = box_buffer->n_elements ;
3569  numpar = NPAR ;
3570  tol = TOLA ;
3571  lab = LABA ;
3572  its = ITSA ;
3573 
3574  /* finally, do the least squares fit over the buffer data */
3575  if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim,
3576  box_buffer -> data,
3577  wdat, &ndat, fitpar,
3578  dervpar, mpar, &numpar,
3579  &tol, &its, &lab )) )
3580  {
3581  sinfo_msg_warning (" least squares fit failed, error "
3582  "no.: %d in slitlet: %d\n", iters, j) ;
3583  sinfo_new_destroy_vector(box_buffer) ;
3584  cpl_free( xdat ) ;
3585  cpl_free( wdat ) ;
3586  cpl_free( mpar ) ;
3587  continue ;
3588  }
3589  if ( fitpar[1] <= fitpar[0] )
3590  {
3591  sinfo_msg_warning ("fit failed due to negative slope of "
3592  "sinfo_new_edge function in slitlet: %d",j);
3593  sinfo_new_destroy_vector(box_buffer) ;
3594  cpl_free( xdat ) ;
3595  cpl_free( wdat ) ;
3596  cpl_free( mpar ) ;
3597  continue ;
3598  }
3599 
3600  pos = (fitpar[0] + fitpar[1])/2. ;
3601  if ( init1 == 1 )
3602  {
3603  pos -= (float)box_length/2. ;
3604  }
3605 
3606  /*-------------------------------------------------------------
3607  * now compute the real slit positions using the guess positions
3608  * if the fit did not work the guess positions are taken
3609  * the same is done if the deviations are too big.
3610  */
3611  if ( pos != 0. )
3612  {
3613  if ( left_right == 0 )
3614  {
3615  new_pos = (float)col_first + pos ;
3616  }
3617  else
3618  {
3619  new_pos = (float)col_last-1 - pos ;
3620  }
3621  if ( fabs(new_pos - sinfo_slit_pos[j][left_right]) < diff_tol )
3622  {
3623  sinfo_slit_pos[j][left_right] = new_pos ;
3624  }
3625  else
3626  {
3627  sinfo_msg_warning (" deviation bigger than tolerance,"
3628  " take the estimated slitlet positiona"
3629  " in slitlet: %d\n", j) ;
3630  }
3631  }
3632 
3633  cpl_free( xdat ) ;
3634  cpl_free( wdat ) ;
3635  cpl_free( mpar ) ;
3636  sinfo_new_destroy_vector ( box_buffer ) ;
3637  }
3638  }
3639  cpl_free(position);
3640  return 0 ;
3641 }
3642 
3643