00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029
00037
00040
00041
00042
00043
00044 #include <math.h>
00045 #include <xsh_drl.h>
00046 #include <xsh_data_order.h>
00047 #include <xsh_data_spectralformat.h>
00048 #include <xsh_error.h>
00049 #include <xsh_utils.h>
00050 #include <xsh_msg.h>
00051 #include <xsh_data_pre.h>
00052 #include <xsh_pfits.h>
00053 #include <xsh_parameters.h>
00054
00055 #include <cpl.h>
00056
00057 typedef struct {
00058 int order ;
00059 int pos_x ;
00060 int pos_y ;
00061 double flux ;
00062 } CENTER_ORDER ;
00063
00064 typedef struct {
00065 int absorder ;
00066 int start_x ;
00067 } START_ORDER ;
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static void compute_dist_pixel( int * xdisp, int * pdist, int dist_order,
00087 int first, int last )
00088 {
00089 int i, nb ;
00090
00091 nb = last - first ;
00092 memset( pdist, 0, nb*sizeof(int) ) ;
00093
00094 for( i = 0 ; (i+dist_order) < nb ; i++, pdist++ ) {
00095 *pdist = xdisp[i] - xdisp[i+dist_order] ;
00096 xsh_msg( " Order: %d, Distance: %d\n", first+i, *pdist ) ;
00097 }
00098
00099 }
00100
00101 static int compute_abs_order( START_ORDER * start_x, int nb,
00102 cpl_frame * spectral_frame,
00103 xsh_detect_continuum_param * detect_param,
00104 xsh_instrument * instrument )
00105 {
00106 int dist_order ;
00107 xsh_spectralformat_list * spectral_list = NULL ;
00108 int * abs_orders = NULL ;
00109 int * dist_pixel = NULL ;
00110 int * xdisp_cen = NULL ;
00111 int spec_size=0 ;
00112 int i=0 ;
00113 int * distances = NULL, * delta = NULL, * the_absorder = NULL ;
00114 int ndist=0;
00115 int good_order=0;
00116 int ngood=0 ;
00117 int first_order=0;
00118 int last_order=0 ;
00119 int min_idx=0 ;
00120 XSH_ARM the_arm ;
00121
00122 xsh_msg( ">>>> Entering compute_abs_order" ) ;
00123 the_arm = xsh_instrument_get_arm( instrument ) ;
00124
00125
00126 check( spectral_list = xsh_spectralformat_list_load(spectral_frame,
00127 instrument)) ;
00128 spec_size = spectral_list->size ;
00129 xsh_msg( " Nb of Orders in Spectral Format: %d", spec_size ) ;
00130
00131
00132 XSH_CALLOC(dist_pixel, int, spec_size ) ;
00133 XSH_CALLOC(xdisp_cen, int, spec_size ) ;
00134 XSH_CALLOC(abs_orders, int, spec_size ) ;
00135 check(xsh_spectralformat_list_get_xdisp_cen( spectral_list,
00136 abs_orders, xdisp_cen));
00137 if ( detect_param->dist_order == 0 ) dist_order = spectral_list->dist_order ;
00138 else dist_order = detect_param->dist_order ;
00139 xsh_msg( " DIST_ORDER = %d", dist_order ) ;
00140 first_order = abs_orders[0] ;
00141 last_order = abs_orders[spec_size-1]+1 ;
00142 compute_dist_pixel( xdisp_cen, dist_pixel, dist_order, first_order,
00143 last_order ) ;
00144
00145 xsh_msg( "First Order: %d, Last Order: %d", first_order, last_order ) ;
00146
00147 XSH_CALLOC( distances, int, nb ) ;
00148 xsh_msg( "Calcul Distances" ) ;
00149 for( ndist = 0, i = 0 ; i<nb ; i++, ndist++ ) {
00150 int j ;
00151
00152 j = i+dist_order ;
00153 if ( j >= nb ) break ;
00154 distances[i] = abs((start_x+i)->start_x - (start_x+j)->start_x ) ;
00155 xsh_msg( "distances[%d] = %d", i, distances[i] ) ;
00156 }
00157
00158
00159
00160
00161
00162
00163 {
00164 float min_avg = 9999999. ;
00165
00166 for( i = 0 ; i<ndist ; i++ ) {
00167 int j, k ;
00168 float sdelta = 0., avg = 0. ;
00169
00170 if ( distances[i] <= 0 ) break ;
00171 xsh_msg( " Start order %d", i ) ;
00172 for( k = i, j = 0 ; j<spec_size; j++, k++ ) {
00173 if ( dist_pixel[j] <= 0 ) break ;
00174 sdelta += abs(distances[k] - dist_pixel[j]) ;
00175 xsh_msg( " found: %d, spec: %d, delta: %d (%d,%d)", k, j,
00176 abs(distances[k] - dist_pixel[j]), distances[k],
00177 dist_pixel[j] ) ;
00178 }
00179 if ( j == 0 ) continue ;
00180 avg = sdelta/(float)j ;
00181 xsh_msg( " ===> avg: %.3lf", avg ) ;
00182
00183 if ( avg < min_avg ) {
00184 min_avg = avg ;
00185 min_idx = i ;
00186 }
00187 }
00188 xsh_msg( " Best first absolute order found: %d (%d)", min_idx,
00189 abs_orders[0] ) ;
00190 }
00191
00192 good_order = abs_orders[0] ;
00193 xsh_msg( "First good order: index %d, absorder %d, Position %d",
00194 min_idx, good_order, (start_x+min_idx)->start_x ) ;
00195
00196
00197 for( ngood=0, i=min_idx ; i<nb && good_order<last_order ; i++, ngood++ ) {
00198 (start_x+i)->absorder = good_order++ ;
00199 xsh_msg( "Center[%d]: Absorder %d, Position %d", i, (start_x+i)->absorder,
00200 (start_x+i)->start_x) ;
00201 }
00202
00203
00204 if ( min_idx != 0 ) {
00205 xsh_msg( "Remove spurious orders" ) ;
00206 memmove( start_x, start_x+min_idx, sizeof(START_ORDER)*ngood ) ;
00207 }
00208
00209 {
00210 int expected ;
00211 expected = instrument->config->orders ;
00212 xsh_msg( " ===== Orders Found: %d (should be %d)", ngood, expected ) ;
00213 XSH_ASSURE_NOT_ILLEGAL_MSG( ngood == expected,
00214 "\n***** NOT ENOUGH ORDERS FOUND. STOP *****\n" ) ;
00215 }
00216
00217 cleanup:
00218 XSH_FREE( distances ) ;
00219 XSH_FREE( dist_pixel ) ;
00220 XSH_FREE( abs_orders ) ;
00221 XSH_FREE( delta ) ;
00222 XSH_FREE( the_absorder ) ;
00223 xsh_spectralformat_list_free( &spectral_list ) ;
00224
00225 return ngood ;
00226 }
00227
00228 static void invert_startx( START_ORDER * pstart, int nb )
00229 {
00230 int i, j ;
00231 START_ORDER * nstart = NULL;
00232
00233 XSH_CALLOC( nstart, START_ORDER, nb ) ;
00234
00235 for( j = 0, i = (nb-1) ; i>=0 ; i--, j++ )
00236 *(nstart+j) = *(pstart+i) ;
00237
00238 memcpy( pstart, nstart, nb*sizeof(START_ORDER) ) ;
00239
00240 cleanup:
00241 return ;
00242 }
00243
00244 static int comp_center( const void * one, const void * two )
00245 {
00246 CENTER_ORDER * first = (CENTER_ORDER *)one ;
00247 CENTER_ORDER * secnd = (CENTER_ORDER *)two ;
00248
00249 if ( first->order < secnd->order ) return -1 ;
00250 else if ( first->order > secnd->order ) return 1 ;
00251 else return 0 ;
00252 }
00253
00266 static int find_maximum( int * found, double * pos_x, int ix0, int max,
00267 double thresh )
00268 {
00269 int ix ;
00270 double * ppos ;
00271
00272 xsh_msg_dbg_high( "Find_maximum: Start at %d, thresh=%lf", ix0, thresh ) ;
00273 if ( thresh < 0 ) thresh = 0. ;
00274 for( ppos = pos_x+ix0, ix = ix0 ; ix < max ; ix++, ppos++ ) {
00275 double flux0 ;
00276
00277 if ( *ppos < thresh ) continue ;
00278
00279
00280
00281 for( flux0 = 0., ppos++, ix++ ; ix < max ; ix++, ppos++ ) {
00282 if ( *ppos > flux0 ) {
00283 flux0 = *ppos ;
00284 *found = ix ;
00285 continue ;
00286 }
00287 else {
00288
00289
00290
00291 xsh_msg_dbg_high( " Max X: %d, %lf", *found, flux0 ) ;
00292 for( ; ix < max ; ix++, ppos++ ) {
00293 if ( *ppos < thresh ) {
00294
00295 return ix ;
00296 }
00297 xsh_msg_dbg_high( " X: %d, %lf", ix, *ppos ) ;
00298 }
00299 }
00300 }
00301 }
00302 xsh_msg( " NOT FOUND !" ) ;
00303 return -1 ;
00304 }
00305
00317 static int search_max( xsh_pre * pre, int iy, int ix0, int ix1 )
00318 {
00319 int ix, ixmax ;
00320 double max = -9999999. ;
00321
00322 for( ixmax = 0, ix = ix0 ; ix<ix1 ; ix++ ) {
00323 int rej ;
00324 double flux ;
00325
00326 flux = cpl_image_get( pre->data, ix, iy, &rej ) ;
00327
00328 if ( rej != 0 ) continue ;
00329 if ( flux > max ) {
00330 ixmax = ix ;
00331 max = flux ;
00332 }
00333 }
00334
00335 return ixmax ;
00336 }
00337
00338 static void save_centers(CENTER_ORDER * pcent, int fpos, int npos,
00339 const char * arm )
00340 {
00341 static FILE * fgnu = NULL, * freg = NULL ;
00342 static const char * gnuname ;
00343 int first_call ;
00344 FILE *fout ;
00345 char fname[32] ;
00346 int i, order ;
00347 CENTER_ORDER * ppcent ;
00348
00349 if ( fgnu == NULL ) {
00350 gnuname = xsh_stringcat_any( "all_orders_", arm, ".gnu", NULL ) ;
00351 fgnu = fopen( gnuname, "w" ) ;
00352 fprintf( fgnu, "set term x11\nplot " ) ;
00353 first_call = 1 ;
00354 }
00355 else first_call = 0 ;
00356 ppcent = pcent + fpos ;
00357 order = ppcent->order ;
00358 sprintf( fname, "order_%s_%02d.dat", arm, order ) ;
00359 fout = fopen( fname, "w" ) ;
00360
00361 if ( !first_call ) fprintf( fgnu, "," ) ;
00362 fprintf( fgnu, "'%s' u 1:2 w points pt 5 t''", fname ) ;
00363
00364 for( i = fpos ; i<npos; i++, ppcent++ )
00365 fprintf( fout, "%d %d %.3lf\n",
00366 ppcent->pos_x, ppcent->pos_y, ppcent->flux ) ;
00367
00368 fclose( fout ) ;
00369 if ( order == 0 ) {
00370 fprintf( fgnu, "\n" ) ;
00371 fclose( fgnu ) ;
00372 }
00373
00374
00375 if ( freg == NULL )
00376 freg = fopen( "order_create.reg", "w" ) ;
00377 fprintf( freg, "# Region file format: DS9 version 4.0\n" ) ;
00378 fprintf( freg, "global color=red font=\"helvetica 4 normal\"select=1 highlite=1 edit=1 move=1 delete=1 include=1 fixed=0 source\n" ) ;
00379 fprintf( freg, "image\n# RED center_x center_y (pixels)\n" ) ;
00380 for( ppcent = pcent+fpos, i = fpos ; i <npos ; i++, ppcent++ ) {
00381 fprintf( freg, "point(%d.,%d.) #point=cross color=red font=\"helvetica 4 normal\"\n", ppcent->pos_x, ppcent->pos_y ) ;
00382 }
00383 if ( order == 0 ) fclose( freg ) ;
00384 }
00385
00386 static void save_pos_x( double * posx, int size, const char * arm )
00387 {
00388 FILE * fout ;
00389 char fname[32] ;
00390 int i ;
00391
00392 sprintf( fname, "histo_%s.dat", arm ) ;
00393 fout = fopen( fname, "w" ) ;
00394
00395 for( i = 0 ; i<size ; i++ )
00396 fprintf( fout, "%d %lf\n", i, *(posx+i) ) ;
00397
00398 fclose( fout ) ;
00399 }
00400
00401 static void fit_order_list( xsh_order_list * list,
00402 int npos, CENTER_ORDER * pcent, int degree)
00403 {
00404 double * vorder = NULL, * po ;
00405 double * pos_x = NULL, * px ;
00406 double * pos_y = NULL, * py ;
00407 int i ;
00408
00409 XSH_CALLOC( vorder, double, npos ) ;
00410 XSH_CALLOC( pos_x, double, npos ) ;
00411 XSH_CALLOC( pos_y, double, npos ) ;
00412
00413 po = vorder ;
00414 px = pos_x ;
00415 py = pos_y ;
00416 for( i = 0 ; i<npos ; i++, po++, px++, py++, pcent++ ) {
00417 *po = pcent->order ;
00418 *px = pcent->pos_x ;
00419 *py = pcent->pos_y ;
00420 }
00421
00422 xsh_order_list_fit(list, npos, vorder, pos_x, pos_y, degree) ;
00423
00424 cleanup:
00425 XSH_FREE( vorder ) ;
00426 XSH_FREE( pos_x ) ;
00427 XSH_FREE( pos_y ) ;
00428 return ;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 cpl_frame *
00454 xsh_order_table_from_fmtchk( xsh_pre * pre,
00455 cpl_frame * spectral_frame,
00456 xsh_detect_continuum_param * detect_param,
00457 xsh_instrument * instrument )
00458 {
00459 xsh_order_list * res_list = NULL ;
00460 cpl_frame * result = NULL ;
00461 int nx, ny, iy0, iy=0, ix, ix0, ix1, step_y ;
00462 int degree ;
00463 int norders ;
00464 int imax=0, found=0;
00465 double * pos_x = NULL ;
00466 double med, stdev ;
00467 int nfound, iord, npos, fpos ;
00468 CENTER_ORDER * centers = NULL ;
00469 START_ORDER * order_startx = NULL ;
00470 const char* tag=NULL;
00471 const char* fname=NULL;
00472
00473 xsh_msg( " ======= xsh_order_table_from_fmtchk" ) ;
00474 xsh_msg( " Window: %d, Step: %d, Search S/N; %.1lf, Follow S/N: %.1lf",
00475 detect_param->fmtchk_window, detect_param->fmtchk_step,
00476 detect_param->fmtchk_search_sn,
00477 detect_param->fmtchk_follow_sn ) ;
00478
00479 XSH_ASSURE_NOT_NULL( pre ) ;
00480 XSH_ASSURE_NOT_NULL( spectral_frame ) ;
00481 XSH_ASSURE_NOT_NULL( detect_param ) ;
00482 XSH_ASSURE_NOT_NULL( instrument ) ;
00483
00484
00485
00486
00487
00488 if ( instrument->config == NULL )
00489 xsh_instrument_get_config( instrument ) ;
00490
00491 norders = instrument->config->orders ;
00492 xsh_msg( " Expected Orders: %d", norders ) ;
00493
00494
00495 XSH_CALLOC( order_startx, START_ORDER, norders*2 ) ;
00496
00497 nx = xsh_pre_get_nx( pre ) ;
00498 ny = xsh_pre_get_ny( pre ) ;
00499
00500 if ( instrument->arm == XSH_ARM_VIS ) iy0 = 0.75*ny ;
00501 else iy0 = ny/2 ;
00502
00503 degree = detect_param->poly_degree ;
00504 step_y = detect_param->fmtchk_step ;
00505
00506 XSH_CALLOC( centers, CENTER_ORDER, ((norders*2)*(ny/step_y))+10 ) ;
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 XSH_CALLOC( pos_x, double, nx ) ;
00521
00522
00523 check( res_list=xsh_order_list_create( instrument ) ) ;
00524
00525
00526
00527
00528 med = cpl_image_get_median_window( pre->data, 1, iy0, nx, iy0 ) ;
00529 stdev = cpl_image_get_stdev_window( pre->data, 1, iy0, nx, iy0 ) ;
00530 xsh_msg( " ===> Y=%d, median = %lf, stdev = %lf", iy, med, stdev ) ;
00531
00532 for( ix = 1; ix <= nx ; ix++ ) {
00533 double flux ;
00534 int rej ;
00535
00536 flux = cpl_image_get( pre->data, ix, iy0, &rej ) ;
00537 *(pos_x+ix-1) = flux ;
00538 }
00539 if ( xsh_debug_level_get() >= XSH_DEBUG_LEVEL_LOW )
00540 save_pos_x( pos_x, nx,
00541 xsh_instrument_arm_tostring( instrument ) ) ;
00542
00543
00544 for( ix = 0, imax = 0, nfound = 0 ; nfound < (norders*2) ; ) {
00545 ix = find_maximum( &found, pos_x, ix, nx-1,
00546 med*detect_param->fmtchk_search_sn ) ;
00547 if ( ix == -1 ) break ;
00548 xsh_msg( "Found Order %d at %d,%d, value: %lf", nfound, found, iy0,
00549 *(pos_x+found) ) ;
00550 (order_startx+nfound)->start_x = found+1 ;
00552 nfound++ ;
00553 }
00554 if (nfound ==0) {
00555 xsh_msg("Found only 0 orders!");
00556 xsh_msg("Try to decrease drecoverformat-search-min-sn parameter value");
00557 }
00558
00559
00560 check(invert_startx( order_startx, nfound ) );
00561
00562
00563
00564
00565
00566
00567
00568 check(norders = compute_abs_order( order_startx, nfound,
00569 spectral_frame, detect_param,
00570 instrument )) ;
00571
00572
00573
00574 for( fpos = 0, npos = 0, iord = 0 ; iord < norders ; iord++ ) {
00575 double max ;
00576 int dum ;
00577 int low_y = 0, up_y = ny-1 ;
00578 int the_ord ;
00579
00580 xsh_msg( " Seaching for Order %d (window: %d)", iord,
00581 detect_param->fmtchk_window ) ;
00582 xsh_msg( " Starting position: %d,%d",
00583 (order_startx+iord)->start_x, iy0 );
00584
00585 ix = (order_startx+iord)->start_x ;
00586 the_ord = (order_startx+iord)->absorder ;
00587 centers[npos].order = the_ord ;
00588 centers[npos].pos_x = ix ;
00589 centers[npos].pos_y = iy0 ;
00590 centers[npos].flux = *(pos_x+ix) ;
00591 npos++ ;
00592 for( iy = (iy0+step_y) ; iy <= ny ; iy+= step_y, npos++ ) {
00593
00594 ix0 = ix - detect_param->fmtchk_window ;
00595 ix1 = ix + detect_param->fmtchk_window ;
00596 if ( ix0 < 1 ) ix0 = 1 ;
00597 if ( ix1 >= nx ) ix1 = nx ;
00598
00599 ix = search_max( pre, iy, ix0, ix1 ) ;
00600 max = cpl_image_get( pre->data, ix, iy, &dum ) ;
00601 if ( dum != 0 ) continue ;
00602 if ( max <= 0 || max < med*detect_param->fmtchk_follow_sn ) break ;
00603 up_y = iy ;
00604 centers[npos].order = the_ord ;
00605 centers[npos].pos_x = ix ;
00606 centers[npos].pos_y = iy ;
00607 centers[npos].flux = max ;
00608 xsh_msg_dbg_high( " Max at %d,%d: %lf", ix, iy, max ) ;
00609 }
00610 ix = (order_startx+iord)->start_x ;
00611 for( iy = (iy0-step_y) ; iy > 0 ; iy -= step_y, npos++ ) {
00612 ix0 = ix - detect_param->fmtchk_window ;
00613 ix1 =ix + detect_param->fmtchk_window ;
00614 if ( ix0 < 1 ) break ;
00615 if ( ix1 > nx ) break ;
00616
00617 ix = search_max( pre, iy, ix0, ix1 ) ;
00618 max = cpl_image_get( pre->data, ix, iy, &dum ) ;
00619 if ( max <= 0 || max < med*detect_param->fmtchk_follow_sn ) {
00620 xsh_msg( " Stop Following at %d,%d (value = %.2lf)", ix, iy, max ) ;
00621 break ;
00622 }
00623 low_y = iy ;
00624 centers[npos].order = the_ord ;
00625 centers[npos].pos_x = ix ;
00626 centers[npos].pos_y = iy ;
00627 centers[npos].flux = max ;
00628 xsh_msg_dbg_high( " Max at %d,%d: %lf", ix, iy, max ) ;
00629 }
00630 if ( xsh_debug_level_get() >= XSH_DEBUG_LEVEL_LOW )
00631 save_centers( centers, fpos, npos,
00632 xsh_instrument_arm_tostring( instrument ) ) ;
00633 fpos = npos ;
00634 res_list->list[iord].starty = low_y ;
00635 res_list->list[iord].endy = up_y ;
00636 res_list->list[iord].absorder = the_ord ;
00637 }
00638
00639
00640 qsort( centers, npos, sizeof( CENTER_ORDER ), comp_center ) ;
00641 fit_order_list(res_list, npos, centers, degree);
00642
00643
00644
00645
00646
00647 tag=XSH_GET_TAG_FROM_ARM( XSH_ORDER_TAB_GUESS,instrument);
00648 fname="ORDER_TAB_FROM_FMTCHK.fits";
00649 check(result=xsh_order_list_save(res_list,instrument,fname,tag,pre->ny)) ;
00650
00651 cleanup:
00652 XSH_FREE( pos_x ) ;
00653 XSH_FREE( centers ) ;
00654 XSH_FREE( order_startx ) ;
00655
00656 return result ;
00657 }