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