X-shooter Pipeline Reference Manual 3.8.15
xsh_detect_order.c
Go to the documentation of this file.
1/* *
2 * This file is part of the ESO X-shooter Pipeline *
3 * Copyright (C) 2006 European Southern Observatory *
4 * *
5 * This library 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/*
21 * $Author: amodigli $
22 * $Date: 2012-12-16 14:07:08 $
23 * $Revision: 1.106 $
24 * $Name: not supported by cvs2svn $
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------
41 Includes
42 ----------------------------------------------------------------------------*/
43
44#include <math.h>
45#include <xsh_drl.h>
46#include <xsh_utils_wrappers.h>
47#include <xsh_data_order.h>
48#include <xsh_error.h>
49#include <xsh_utils.h>
50#include <xsh_utils_image.h>
51#include <xsh_msg.h>
52#include <xsh_data_pre.h>
53#include <cpl.h>
54
55/*---------------------------------------------------------------------------
56 Typedefs
57 ---------------------------------------------------------------------------*/
58#define HALF_SLIC_WINDOW 5
59
60/*---------------------------------------------------------------------------
61 Functions prototypes
62 ---------------------------------------------------------------------------*/
63
64/*---------------------------------------------------------------------------
65 Implementation
66 ---------------------------------------------------------------------------*/
67
68
78static cpl_table*
79xsh_compute_flat_edges(cpl_frame* frame,
80 xsh_order_list* list,
82 const char* method)
83{
84
85 cpl_image* mflat=NULL;
86 const char* name=NULL;
87 const char* name_o=NULL;
88 char name_t[256];
89 cpl_image* filter_x=NULL;
90 cpl_propertylist* plist=NULL;
91
92 cpl_table* tbl=NULL;
93 cpl_table* res=NULL;
94
95 cpl_vector* vsliclo=NULL;
96 cpl_vector* vslicup=NULL;
97 cpl_vector* vedgelo=NULL;
98 cpl_vector* vedgeup=NULL;
99 cpl_vector* vypos=NULL;
100
101 int* porder=NULL;
102 int* pabsorder=NULL;
103
104 double* pcenterx=NULL;
105 double* pcentery=NULL;
106
107
108 double* pedgelo=NULL;
109 double* pedgeup=NULL;
110 double* psliceup=NULL;
111 double* pslicelo=NULL;
112 double* psliceup_resx=NULL;
113 double* pslicelo_resx=NULL;
114
115 double* pedgeup_resx=NULL;
116 double* pedgelo_resx=NULL;
117
118
119 double* pedgelof=NULL;
120 double* pedgeupf=NULL;
121 double* psliceupf=NULL;
122 double* pslicelof=NULL;
123 double* psliceupthresf=NULL;
124 double* pslicelothresf=NULL;
125
126 double* ypos=NULL;
127
128
129 double* edgelo=NULL;
130 double* edgeup=NULL;
131 double* sliclo=NULL;
132 double* slicup=NULL;
133
134 double max=0;
135 int img_starty=0;
136 int img_endy=0;
137 int i=0;
138 int is_ifu=0;
139 int sx=0;
140 int sy=0;
141 int rad=6;
142 int y=0;
143 int llx=0;
144 int urx=0;
145 int nrows=0;
146 int k=0;
147 int num=0;
148 int nsel=0;
149
150 cpl_polynomial* sliclopoly=NULL;
151 cpl_polynomial* slicuppoly=NULL;
152 cpl_polynomial* edgelopoly=NULL;
153 cpl_polynomial* edgeuppoly=NULL;
154 //cpl_image* sbias=NULL;
155
156 check(name=cpl_frame_get_filename(frame));
157 check(mflat=cpl_image_load(name,CPL_TYPE_FLOAT,0,0));
158 /* one may smooth the image to remove bad columns
159 check(sbias=xsh_image_smooth_median_x(mflat,2));
160 check(cpl_image_save(sbias,"smooth.fits",CPL_BPP_IEEE_FLOAT,
161 NULL,CPL_IO_DEFAULT));
162 */
163
164 check(sx=cpl_image_get_size_x(mflat));
165 check(sy=cpl_image_get_size_y(mflat));
166
167 if(strcmp(method,"sobel") == 0) {
168 check(filter_x=xsh_sobel_lx(mflat));
169 } else {
170 check(filter_x=xsh_scharr_x(mflat));
171 }
172
173 //xsh_free_image(&sbias);
174
175 check(max=cpl_image_get_max(filter_x));
176 check(cpl_image_divide_scalar(filter_x,max));
177 check(cpl_image_abs(filter_x));
178
180 if(strcmp(method,"sobel") == 0) {
181 check(cpl_image_save(filter_x,"sobel_lx_n.fits",CPL_BPP_IEEE_FLOAT,
182 NULL,CPL_IO_DEFAULT));
183 } else {
184 check(cpl_image_save(filter_x,"scharr_x_n.fits",CPL_BPP_IEEE_FLOAT,
185 NULL,CPL_IO_DEFAULT));
186 }
187 }
188
189 nrows=sy*list->size;
190 check(tbl=cpl_table_new(nrows));
191 check(cpl_table_new_column(tbl,"ORDER",CPL_TYPE_INT));
192 check(cpl_table_new_column(tbl,"ABSORDER",CPL_TYPE_INT));
193
194 check(cpl_table_new_column(tbl,"CENTERX",CPL_TYPE_DOUBLE));
195 check(cpl_table_new_column(tbl,"CENTERY",CPL_TYPE_DOUBLE));
196 check(cpl_table_new_column(tbl,"EDGELOX",CPL_TYPE_DOUBLE));
197 check(cpl_table_new_column(tbl,"EDGEUPX",CPL_TYPE_DOUBLE));
198
199 check(cpl_table_fill_column_window_int(tbl,"ORDER",0,nrows,-1));
200 check(cpl_table_fill_column_window_int(tbl,"ABSORDER",0,nrows,-1));
201
202 check(cpl_table_fill_column_window_double(tbl,"CENTERX",0,nrows,-1));
203 check(cpl_table_fill_column_window_double(tbl,"CENTERY",0,nrows,-1));
204 check(cpl_table_fill_column_window_double(tbl,"EDGELOX",0,nrows,-1));
205 check(cpl_table_fill_column_window_double(tbl,"EDGEUPX",0,nrows,-1));
206
207
208 check(porder=cpl_table_get_data_int(tbl,"ORDER"));
209 check(pabsorder=cpl_table_get_data_int(tbl,"ABSORDER"));
210
211 check(pcenterx=cpl_table_get_data_double(tbl,"CENTERX"));
212 check(pcentery=cpl_table_get_data_double(tbl,"CENTERY"));
213 check(pedgelo=cpl_table_get_data_double(tbl,"EDGELOX"));
214 check(pedgeup=cpl_table_get_data_double(tbl,"EDGEUPX"));
215
216
218 if ( is_ifu){
219 xsh_msg( "Detect Order Edges in IFU mode");
220 check(cpl_table_new_column(tbl,"SLICELOX",CPL_TYPE_DOUBLE));
221 check(cpl_table_new_column(tbl,"SLICEUPX",CPL_TYPE_DOUBLE));
222 check(cpl_table_new_column(tbl,"SLICELOTHRESFX",CPL_TYPE_DOUBLE));
223 check(cpl_table_new_column(tbl,"SLICEUPTHRESFX",CPL_TYPE_DOUBLE));
224
225 check(pslicelothresf=cpl_table_get_data_double(tbl,"SLICELOTHRESFX"));
226 check(psliceupthresf=cpl_table_get_data_double(tbl,"SLICEUPTHRESFX"));
227 check(cpl_table_fill_column_window_double(tbl,"SLICELOTHRESFX",0,nrows,-1));
228 check(cpl_table_fill_column_window_double(tbl,"SLICEUPTHRESFX",0,nrows,-1));
229
230 check(pslicelo=cpl_table_get_data_double(tbl,"SLICELOX"));
231 check(psliceup=cpl_table_get_data_double(tbl,"SLICEUPX"));
232 check(cpl_table_fill_column_window_double(tbl,"SLICELOX",0,nrows,-1));
233 check(cpl_table_fill_column_window_double(tbl,"SLICEUPX",0,nrows,-1));
234
235 }
236 else {
237 xsh_msg( "Detect Order Edges in SLIT mode");
238 }
239
240 /* find centroids using previous constrained solutions */
241 for(i=0; i< list->size; i++){
242 porder[k]=list->list[i].order;
243 pabsorder[k]=list->list[i].absorder;
244
245 img_starty = list->list[i].starty/list->bin_y;
246 img_endy=list->list[i].endy/list->bin_y;
247
248 /*
249 -999 can occur only in QC mode and is used as flag to skip
250 edge detection on a given order. This was explicitly asked by QC.
251 Normal user mode should never have this behaviour.
252 */
253 if((list->list[i].starty == -999) ||
254 (list->list[i].endy==-999)){
255 xsh_msg("PROBLEMS tracing order %d",list->list[i].absorder);
256 method="fixed";
257 break;
258 }
259
260 xsh_msg_dbg_medium("start=%d end=%d",img_starty,img_endy);
261 for(y=img_starty; y<img_endy; y++){
262 double xl = 0, xu = 0, xc=0, xsl=0, xsu=0;
263 cpl_size px, py;
264 int yb=y*list->bin_y;
265
266 check( xu = xsh_order_list_eval_int( list, list->list[i].edguppoly, y));
267 check( xl = xsh_order_list_eval_int( list, list->list[i].edglopoly, y));
268
269 llx=(int)xl-rad;
270 urx=(int)xl+rad;
271 if((llx>0) && (urx< sx)) {
272 //check(pedgelo[k]=cpl_image_get_centroid_x_window(filter_x,llx,y,urx,y));
273 check( cpl_image_get_maxpos_window( filter_x, llx, y, urx, y, &px, &py));
274 pedgelo[k] = px;
275 pedgelo[k]*=list->bin_x;
276 porder[k]=list->list[i].order;
277 pabsorder[k]=list->list[i].absorder;
278 }
279 /* xsh_msg("y=%d xl=%g llx=%d lly=%d max=%g",y,xl,llx,urx,pedgelo[i]); */
280 llx=(int)xu-rad;
281 urx=(int)xu+rad;
282
283 if((llx>0) && (urx< sx)) {
284 //check(pedgeup[k]=cpl_image_get_centroid_x_window(filter_x,llx,y,urx,y));
285 check( cpl_image_get_maxpos_window( filter_x, llx,y,urx,y, &px, &py));
286 pedgeup[k] = px;
287 pedgeup[k]*=list->bin_x;
288 porder[k]=list->list[i].order;
289 pabsorder[k]=list->list[i].absorder;
290 }
291 /* xsh_msg("y=%d xu=%g llx=%d lly=%d max=%g",y,xu,llx,urx,pedgeup[i]); */
292
293 check( xc = xsh_order_list_eval( list, list->list[i].cenpoly, y));
294 pcenterx[k]=xc*list->bin_y;
295 pcentery[k]=yb;
296
297 /* xsh_msg("xu=%f xl=%f xc=%f y=%d i=%d\n",xl, xu, xc, y, i); */
298 if ( is_ifu) {
299 if ( list->list[i].sliclopoly != NULL ) {
300 check(xsl=cpl_polynomial_eval_1d(list->list[i].sliclopoly,yb,NULL));
301
302 xsl /= list->bin_x;
303 pslicelothresf[k] = xsl;
304 llx=(int)xsl-rad;
305 urx=(int)xsl+rad;
306
307 if((llx>0) && (urx)< sx) {
308 /*check(pslicelo[k]=cpl_image_get_centroid_x_window(filter_x,
309 llx,y,urx,y));*/
310 check( cpl_image_get_maxpos_window( filter_x, llx, y, urx, y, &px, &py));
311 pslicelo[k]=px;
312 pslicelo[k]*=list->bin_x;
313 porder[k]=list->list[i].order;
314 pabsorder[k]=list->list[i].absorder;
315 }
316 }
317
318 if ( list->list[i].slicuppoly != NULL ) {
319 check(xsu=cpl_polynomial_eval_1d(list->list[i].slicuppoly,yb,NULL));
320 xsu /= list->bin_x;
321 psliceupthresf[k] = xsu;
322 llx=(int)xsu-rad;
323 urx=(int)xsu+rad;
324
325 if((llx>0) && (urx)< sx) {
326 /*check(psliceup[k]=cpl_image_get_centroid_x_window(filter_x,
327 llx,y,urx,y));*/
328 check( cpl_image_get_maxpos_window( filter_x, llx, y, urx, y, &px, &py));
329 psliceup[k]=px;
330 psliceup[k]*=list->bin_x;
331 porder[k]=list->list[i].order;
332 pabsorder[k]=list->list[i].absorder;
333 }
334 }
335
336
337 } /* end check ifu */
338
339 k++;
340 } /* end loop over y */
341
342 } /* end loop over orders */
343
344 //check(cpl_table_save(res,plist,NULL,"pippo.fits",CPL_IO_DEFAULT));
345 check(num=cpl_table_and_selected_int(tbl,"ORDER",CPL_GREATER_THAN,-1));
346 check(res=cpl_table_extract_selected(tbl));
347 //check(cpl_table_save(res,plist,NULL,"pippo.fits",CPL_IO_DEFAULT));
348
349 xsh_free_table(&tbl);
350 cpl_table_select_all(res);
351
352 /* fit the edge column values */
353 check(cpl_table_new_column(res,"EDGELOFX",CPL_TYPE_DOUBLE));
354 check(cpl_table_new_column(res,"EDGEUPFX",CPL_TYPE_DOUBLE));
355 check(cpl_table_fill_column_window_double(res,"EDGELOFX",0,num,-1));
356 check(cpl_table_fill_column_window_double(res,"EDGEUPFX",0,num,-1));
357
358 check(cpl_table_new_column(res,"EDGELO_RESX",CPL_TYPE_DOUBLE));
359 check(cpl_table_new_column(res,"EDGEUP_RESX",CPL_TYPE_DOUBLE));
360 check(cpl_table_fill_column_window_double(res,"EDGELO_RESX",0,num,-1));
361 check(cpl_table_fill_column_window_double(res,"EDGEUP_RESX",0,num,-1));
362
363 check(pedgelof=cpl_table_get_data_double(res,"EDGELOFX"));
364 check(pedgeupf=cpl_table_get_data_double(res,"EDGEUPFX"));
365 check(pedgelo_resx=cpl_table_get_data_double(res,"EDGELO_RESX"));
366 check(pedgeup_resx=cpl_table_get_data_double(res,"EDGEUP_RESX"));
367
368 if ( is_ifu ) {
369 check(cpl_table_new_column(res,"SLICELOFX",CPL_TYPE_DOUBLE));
370 check(cpl_table_new_column(res,"SLICEUPFX",CPL_TYPE_DOUBLE));
371
372 check(cpl_table_fill_column_window_double(res,"SLICELOFX",0,num,-1));
373 check(cpl_table_fill_column_window_double(res,"SLICEUPFX",0,num,-1));
374 check(pslicelof=cpl_table_get_data_double(res,"SLICELOFX"));
375 check(psliceupf=cpl_table_get_data_double(res,"SLICEUPFX"));
376
377 check(cpl_table_new_column(res,"SLICELO_RESX",CPL_TYPE_DOUBLE));
378 check(cpl_table_new_column(res,"SLICEUP_RESX",CPL_TYPE_DOUBLE));
379 check(cpl_table_fill_column_window_double(res,"SLICELO_RESX",0,num,-1));
380 check(cpl_table_fill_column_window_double(res,"SLICEUP_RESX",0,num,-1));
381 check(pslicelo_resx=cpl_table_get_data_double(res,"SLICELO_RESX"));
382 check(psliceup_resx=cpl_table_get_data_double(res,"SLICEUP_RESX"));
383
384
385 }
386
387 k=0;
388 for(i=0; i< list->size; i++){
389
390 /*
391 -999 can occur only in QC mode and is used as flag to skip
392 edge detection on a given order. This was explicitly asked by QC.
393 Normal user mode should never have this behaviour.
394 */
395 if((list->list[i].starty == -999) ||
396 (list->list[i].endy==-999)){
397 xsh_msg("PROBLEMS");
398 method="fixed";
399 break;
400 }
401
402 check(nsel=cpl_table_and_selected_int(res,"ABSORDER",CPL_EQUAL_TO,
403 list->list[i].absorder));
404 if(nsel>0) {
405 check(tbl=cpl_table_extract_selected(res));
406
407 check(ypos=cpl_table_get_data_double(tbl,"CENTERY"));
408 check(vypos = cpl_vector_wrap( nsel, ypos ));
409
410 /* begin commented region */
411 check(edgelo=cpl_table_get_data_double(tbl,"EDGELOX"));
412 check(edgeup=cpl_table_get_data_double(tbl,"EDGEUPX"));
413
414 check(vedgelo = cpl_vector_wrap( nsel, edgelo ));
415 check(vedgeup = cpl_vector_wrap( nsel, edgeup ));
416
417 check( xsh_free_polynomial( &edgelopoly));
418 check(edgelopoly=xsh_polynomial_fit_1d_create( vypos, vedgelo,
419 list->list[i].pol_degree,
420 NULL));
421
422 check( xsh_free_polynomial( &edgeuppoly));
423 check(edgeuppoly=xsh_polynomial_fit_1d_create( vypos, vedgeup,
424 list->list[i].pol_degree,
425 NULL));
426
427
428
429
430 //Overwrite flat edges polynomial coefficients values
432 check(list->list[i].edglopoly=xsh_polynomial_fit_1d_create( vypos, vedgelo,
433 list->list[i].pol_degree,
434 NULL));
435
437 check(list->list[i].edguppoly=xsh_polynomial_fit_1d_create( vypos, vedgeup,
438 list->list[i].pol_degree,
439 NULL));
440
441
442
443 for(y=0; y< nsel; y++){
444 check( pedgelof[k+y] = cpl_polynomial_eval_1d(edgelopoly,ypos[y],NULL));
445 check( pedgeupf[k+y] = cpl_polynomial_eval_1d(edgeuppoly,ypos[y],NULL));
446
447 pedgelo_resx[k+y] = pedgelof[k+y] - edgelo[y];
448 pedgeup_resx[k+y] = pedgeupf[k+y] - edgeup[y];
449 //xsh_msg_debug("edge: lo=%g up=%g",pedgelof[k+y],pedgeupf[k+y]);
450 }
451 check( cpl_vector_unwrap(vedgeup )) ;
452 check( cpl_vector_unwrap(vedgelo )) ;
453 /* end commented region */
454
455 if ( is_ifu ) {
456 check(sliclo=cpl_table_get_data_double(tbl,"SLICELOX"));
457 check(slicup=cpl_table_get_data_double(tbl,"SLICEUPX"));
458 check( vslicup = cpl_vector_wrap( nsel, slicup )) ;
459 check( vsliclo = cpl_vector_wrap( nsel, sliclo )) ;
460
461 check( xsh_free_polynomial( &sliclopoly));
462 check(sliclopoly=xsh_polynomial_fit_1d_create( vypos, vsliclo,
463 list->list[i].pol_degree,
464 NULL));
465
466 check( xsh_free_polynomial( &slicuppoly));
467 check(slicuppoly=xsh_polynomial_fit_1d_create( vypos, vslicup,
468 list->list[i].pol_degree,
469 NULL));
470
471
472
473 //Overwrite IFU slices edges polynomial coefficients values
475 check(list->list[i].sliclopoly=xsh_polynomial_fit_1d_create( vypos, vsliclo,
476 list->list[i].pol_degree,
477 NULL));
478
480 check(list->list[i].slicuppoly=xsh_polynomial_fit_1d_create( vypos, vslicup,
481 list->list[i].pol_degree,
482 NULL));
483
484
485
486 for(y=0; y< nsel; y++){
487 check( pslicelof[k+y] = cpl_polynomial_eval_1d(sliclopoly,ypos[y],NULL));
488 check( psliceupf[k+y] = cpl_polynomial_eval_1d(slicuppoly,ypos[y],NULL));
489 pslicelo_resx[k+y] = pslicelof[k+y] - sliclo[y];
490 psliceup_resx[k+y] = psliceupf[k+y] - slicup[y];
491 }
492 check( cpl_vector_unwrap(vslicup )) ;
493 check( cpl_vector_unwrap(vsliclo )) ;
494 }
495 k+=nsel;
496 xsh_free_table(&tbl);
497 cpl_vector_unwrap(vypos );
498
499 }
500 cpl_table_select_all(res);
501 }
502
504
505 /* save results */
506 if ( instrument->mode == XSH_MODE_IFU) {
507 if (instrument->arm != XSH_ARM_UVB) {
509 } else {
512 } else {
514 }
515 }
516 } else {
517 if (instrument->arm != XSH_ARM_UVB) {
519 } else {
522 } else {
524 }
525 }
526 }
527 sprintf(name_t,"%s%s",name_o,".fits");
528 check(plist=cpl_propertylist_load(name,0));
529 check(cpl_table_save(res,plist,NULL,name_t,CPL_IO_DEFAULT));
530 }
531
532 cleanup:
533 check( xsh_free_polynomial( &sliclopoly));
534 check( xsh_free_polynomial( &slicuppoly));
535 check( xsh_free_polynomial( &edgelopoly));
536 check( xsh_free_polynomial( &edgeuppoly));
537 xsh_free_propertylist(&plist);
538 xsh_free_image(&mflat);
539 xsh_free_image(&filter_x);
540 xsh_free_table(&tbl);
541 return res;
542
543}
544
545
546
567static void xsh_eval_y_avg_chunk(xsh_pre* pre, int xc, int yc,
568 int chunk_y_hsize, int x_hsize, const int decode_bp, double *flux, double *noise)
569{
570 int nx, ny;
571 float *data = NULL, *errs = NULL;
572 int *qual = NULL;
573 int res_size=0;
574 int i,j;
575 int nb_good_pixels=0;
576
577 /* Check parameters */
579 XSH_ASSURE_NOT_NULL( flux);
580 XSH_ASSURE_NOT_NULL( noise);
581
582 nx = pre->nx;
583 ny = pre->ny;
584 res_size = x_hsize*2+1;
585
586 XSH_ASSURE_NOT_ILLEGAL( xc-x_hsize >= 0);
587 XSH_ASSURE_NOT_ILLEGAL( xc+x_hsize < nx);
588 XSH_ASSURE_NOT_ILLEGAL( yc-chunk_y_hsize >= 0);
589 XSH_ASSURE_NOT_ILLEGAL( yc+chunk_y_hsize < ny);
590
591 /* Get data,errs, qual*/
592 check( data = cpl_image_get_data_float( pre->data));
593 check( errs = cpl_image_get_data_float( pre->errs));
594 check( qual = cpl_image_get_data_int( pre->qual));
595
596 /* init vectors */
597 for(i=0; i< res_size; i++){
598 flux[i]=0;
599 noise[i]=0;
600
601 }
602 /* calculate flux and noise */
603 for(i=xc-x_hsize; i <= (xc+x_hsize); i++){
604 nb_good_pixels = 0;
605 int pix_val=i-xc+x_hsize;
606
607 for(j=yc-chunk_y_hsize; j <= (yc+chunk_y_hsize); j++){
608 int j_nx_plus_i=j*nx+i;
609 if ( (qual[j_nx_plus_i] & decode_bp) == 0){
610 flux[pix_val]+=data[j_nx_plus_i];
611 noise[pix_val]+=errs[j_nx_plus_i]*errs[j_nx_plus_i];
612 nb_good_pixels++;
613 }
614 }
615 if(nb_good_pixels>0) {
616 flux[pix_val] /= nb_good_pixels;
617 noise[pix_val]= sqrt(noise[pix_val])/nb_good_pixels;
618 } else {
619 noise[pix_val] = 1;
620 }
621 }
622
623 cleanup:
624 return;
625}
626
639static void
641 int chunk_hsize,
642 cpl_polynomial *cen_poly,
643 int cen_start,
644 int cen_end,
645 xsh_pre *pre,
646 const int decode_bp,
647 int* maxy)
648{
649 int y;
650 float flux_max;
651 int *qual = NULL;
652
653 /* check parameters */
654 XSH_ASSURE_NOT_NULL( cen_poly);
656 XSH_ASSURE_NOT_NULL( maxy);
657 XSH_ASSURE_NOT_ILLEGAL( cen_start >=1);
658 XSH_ASSURE_NOT_ILLEGAL( cen_end <= pre->ny);
659
660 check( qual = cpl_image_get_data_int( pre->qual));
661 flux_max = 0.0;
662 for(y=cen_start+chunk_hsize; y<= cen_end-chunk_hsize; y++){
663 int x;
664 double flux, noise;
665
666 check( x = xsh_order_list_eval_int( list, cen_poly, y));
667 /* computes mean signal and noise evaluating all (good) pixels in a box of
668 chunk_hsize half X size and 1 pix Y size */
669 check( xsh_eval_y_avg_chunk( pre, x-1, y-1, chunk_hsize, 0,decode_bp,
670 &flux, &noise));
671 if ( flux > flux_max ){
672 if ( (qual[x-1+(y-1)*pre->nx] & decode_bp) == 0 ){
673
674 flux_max = flux;
675 *maxy = y;
676 }
677 }
678 }
679
680 cleanup:
681 return;
682}
706static void
708 int y,
709 cpl_polynomial *cen_poly,
710 xsh_pre* pre,
711 int window_hsize,
712 double* res_flux,
713 double* res_noise,
714 int chunk_hsize,
715 double min_snr,
716 double flux_frac,
717 int min_size_x,
718 const int decode_bp,
719 int *x_min,
720 float *x_cen_sdivn,
721 int *xup,
722 int *xlow,
723 float *min_low,
724 float *min_up)
725{
726 int x = 0;
727 float min = 0.0, noise = 0.0, sdivn = 0.0;
728 float threshold = 0.0;
729 int j = 0, xmin = 0,xmax = 0;
730 int window_size;
731 //int pos_min=0;
732 //int min_order_size_x =0;
733
734 /* check Parameters */
735 XSH_ASSURE_NOT_NULL( cen_poly);
737 XSH_ASSURE_NOT_NULL( res_flux);
738 XSH_ASSURE_NOT_NULL( res_noise);
739
740 XSH_ASSURE_NOT_NULL( x_min);
741 XSH_ASSURE_NOT_NULL( x_cen_sdivn);
743 XSH_ASSURE_NOT_NULL( xlow);
744 XSH_ASSURE_NOT_NULL( min_low);
745 XSH_ASSURE_NOT_NULL( min_up);
746
747 window_size = window_hsize*2+1;
748 //min_order_size_x = floor(0.5*min_size_x);
749
750 check( x = xsh_order_list_eval_int( list, cen_poly, y));
751 xmin = x-window_hsize;
752 *x_min= xmin;
753 xmax = x+window_hsize;
754
755 /* VALID X,Y coordinate*/
756 if (xmin >= 1 && xmax <= pre->nx) {
757 /* compute mean flux and corresponding error summing up pixel signal in
758 a rectangular box of (2*window_half_hsize+1) X size and (2*chunk_hsize+1)
759 Y size */
760 check( xsh_eval_y_avg_chunk( pre, x-1, y-1, chunk_hsize, window_hsize,decode_bp,
761 res_flux, res_noise));
762 /* compute the Signal / Noise at center */
763 noise = res_noise[window_hsize+1];
764 sdivn = res_flux[window_hsize+1]/noise;
765 *x_cen_sdivn = sdivn;
766 /* Measure edges only for regions of sufficiently high S/N ratio */
767 if ( sdivn > min_snr ){
768
769 /* get the (order right) edge upper limit */
770 /* find the MIN flux level along the X window size */
771 min = res_flux[window_hsize+1];
772 for(j = window_hsize+1; j<window_size; j++) {
773 if (min > res_flux[j]){
774 min = res_flux[j];
775 }
776 }
777 /* compute the minimum flux THRESHOLD at a given Y pixel:
778
779 ---------<----flux max
780 <-----order edge
781 \
782 |
783 |
784 |
785 |
786 \
787 \--------threshold(min)
788 <-----this position
789 ----------- min (inter-order background)
790
791 */
792 threshold = (res_flux[window_hsize+1]-min) * flux_frac;
793
794 j = window_hsize+1;
795 while( (j < window_size-1) && ((res_flux[j]-min) >= threshold)){
796 j++;
797 }
798 *xup = j;
799 *min_up = min;
800
801 if ( (res_flux[j]-min) >= threshold){
802 xsh_msg("WARNING UP edge not detected. Increase window size");
803 *x_cen_sdivn = -1;
804 }
805 /* get the (order left) edge lower limits */
806 /* find the MIN flux level along the X window size */
807 min = res_flux[window_hsize+1];
808 //pos_min = window_hsize+1;
809
810 for(j=0; j<=window_hsize+1; j++) {
811 if (min > res_flux[j]){
812 min = res_flux[j];
813 //pos_min = j;
814 }
815 }
816
817 /* compute the minimum flux THRESHOLD at a given Y pixel:
818
819 flux max ----> /----------------
820 order edge ---> /
821 /
822 |
823 |
824 |
825 |
826 /
827 threshold(min) ---/
828 look for this pos---> /
829 inter-ord bkg(min)---/
830
831 */
832
833
834 threshold = (res_flux[window_hsize+1]-min) * flux_frac;
835 j = window_hsize+1;
836 while( (j > 0) && ( (res_flux[j]-min) >= threshold)){
837 j--;
838 }
839 *xlow = (double)j;
840 *min_low = min;
841 if ( (res_flux[j]-min) >= threshold){
842 xsh_msg("WARNING LOW edge not detected. Increase window size");
843 *x_cen_sdivn = -1;
844 }
845 if ( (*xup-*xlow) < min_size_x){
846 xsh_msg_dbg_medium("y %d : Size of order in cross dispersion "\
847 "to small %d < %d", y, *xup-*xlow, min_size_x);
848 *x_cen_sdivn = -1;
849 }
850 }
851 else{
852 xsh_msg_dbg_medium("y %d Invalid s/n : %f > %f", y, sdivn, min_snr);
853 }
854 }
855 else{
856 xsh_msg_dbg_medium("y %d Invalid xmin %d or xmax %d", y, xmin, xmax);
857 *x_cen_sdivn = -1;
858 }
859 cleanup:
860 return;
861}
862/* Measure a flux ratio at lower and upper edges with respect to flux at center */
863static void xsh_detect_slitlet_ratio( double* res_flux, int window_hsize,
864 double min_low, double min_up, int xlow, int xup,
865 double *ratio_low, double *ratio_up)
866{
867 double avg_cen = 0., avg_lo=0., avg_up=0.;
868 int j;
869 int size;
870 int center;
871
872
873 /* Check Parameters */
874 XSH_ASSURE_NOT_NULL( res_flux);
875 XSH_ASSURE_NOT_NULL( ratio_up);
876 XSH_ASSURE_NOT_NULL( ratio_low);
877
878 size = (xup-xlow)/3;
879
880 center = window_hsize+1;
881 /* evaluate average flux level for each IFU slitlet: */
882 /* evaluate average flux level for central IFU slitlet */
883 for( j=center-HALF_SLIC_WINDOW;
884 j <= center+HALF_SLIC_WINDOW ; j++ ){
885 avg_cen += res_flux[j];
886 }
887 avg_cen /= (HALF_SLIC_WINDOW*2)+1;
888
889 /* evaluate average flux level for low (left) IFU slitlet */
890 center = window_hsize+1-size;
891 for( j=center-HALF_SLIC_WINDOW;
892 j <= center+HALF_SLIC_WINDOW ; j++ ){
893 avg_lo += res_flux[j];
894 }
895 avg_lo /= (HALF_SLIC_WINDOW*2)+1;
896
897 /* evaluate average flux level for up (right) IFU slitlet */
898 center = window_hsize+1+size;
899 for( j=center-HALF_SLIC_WINDOW;
900 j <= center+HALF_SLIC_WINDOW ; j++ ){
901 avg_up += res_flux[j];
902 }
903 avg_up /= (HALF_SLIC_WINDOW*2)+1;
904 /* finally determines the slitlet flux ratio for upper and lower slitlet
905 as fraction of average flux above the min slitlet background as compared
906 to the mean central slitlet flux */
907 *ratio_up = (avg_up-min_up)/(avg_cen-min_up);
908 *ratio_low = (avg_lo-min_low)/(avg_cen-min_low);
909 cleanup:
910 return;
911}
928cpl_frame* xsh_detect_order_edge(cpl_frame *frame,
929 cpl_frame *cen_order_tab_frame, xsh_detect_order_param *detectorder_par,
931 /* MUST BE DEALLOCATED in caller */
932 cpl_frame * result = NULL;
933 /* ALLOCATED locally */
934 xsh_pre* pre = NULL;
935 xsh_order_list* list = NULL;
936 double* positions = NULL;
937 double* uppervalues = NULL;
938 double* lowervalues = NULL;
939 double * slicup = NULL;
940 double * sliclow = NULL;
941 cpl_vector* xpos = NULL;
942 cpl_vector* upper = NULL;
943 cpl_vector* lower = NULL;
944 cpl_vector * vslicup = NULL;
945 cpl_vector * vsliclow = NULL;
946
947 /* Others */
948 int y = 0;
949 int size = 0, i = 0, k = 0;
950 int is_ifu = 0;
951 char *fname = NULL;
952 const char * tag = NULL;
953 //const char * arm_name = NULL;
954
955 int window_size, min_order_size_x, chunk_hsize, window_hsize;
956 double min_snr, slitlet_up_factor, slitlet_low_factor;
957 double *res_flux = NULL, *res_noise = NULL;
958 double flux_frac;
959 int fixed_slice = 0;
960 const char* method = NULL;
961
962 cpl_table* tab_edges_res = NULL;
963 int bad_points = 0;
964
965 /* check input */
966 XSH_ASSURE_NOT_NULL(frame);
967 XSH_ASSURE_NOT_NULL(cen_order_tab_frame);
968 XSH_ASSURE_NOT_NULL(detectorder_par);
969
970 /* stores relevant recipe parameters in local variable */
971 window_hsize = detectorder_par->search_window_hsize;
972 window_size = window_hsize * 2 + 1;
973 min_order_size_x = detectorder_par->min_order_size_x;
974
975 flux_frac = detectorder_par->flux_thresh;
976 min_snr = detectorder_par->min_sn;
977 slitlet_low_factor = detectorder_par->slitlet_low_factor;
978 slitlet_up_factor = detectorder_par->slitlet_up_factor;
979 chunk_hsize = detectorder_par->chunk_hsize;
980 fixed_slice = detectorder_par->fixed_slice;
981 method = detectorder_par->method;
982
983 /* make initial check and suggest solution if not satisfied */
984 assure(window_size > 0, CPL_ERROR_ILLEGAL_INPUT,
985 "window_size=%d (window_size=window_hsize*2+1) < 0 "
986 "parameter detectorder-edges-search-window-half-size=%d "
987 "may have been set to a too large value", window_size, window_hsize);
988
989 /* Monitor values of relevant parameters */
990 xsh_msg_dbg_medium("Parameters");
992 " Window: %d,flux-Thresh: %.2f, S/N: %.2f", window_size, flux_frac, min_snr);
994 " min-size-x: %d, Slitlet-low-factor: %.2f\
995 Slitlet-up-factor: %.2f chunk-half-size %d", min_order_size_x, slitlet_low_factor, slitlet_up_factor, chunk_hsize);
996 xsh_msg_dbg_medium(" fixed-slice = %s", BOOLEAN_TO_STRING(fixed_slice));
997
998 /* load the frames */
999 check( pre = xsh_pre_load( frame, instrument));
1000
1001 check(list = xsh_order_list_load( cen_order_tab_frame, instrument));
1002
1003 assure(
1004 min_order_size_x > 0 && min_order_size_x < (floor) (pre->nx / list->size),
1005 CPL_ERROR_ILLEGAL_INPUT, "parameter detectorder-min-order-size-x=%d "
1006 "has been set to a too small or too large value", min_order_size_x);
1007
1008 //xsh_order_list_set_bin_x( list, pre->binx);
1009 //xsh_order_list_set_bin_y( list, pre->biny);
1010
1011 XSH_REGDEBUG("binning %dx%d", list->bin_x, list->bin_y);
1012 /* clean header */
1013 xsh_free_propertylist(&(list->header));
1015
1016 /* get the data */
1017 //arm_name = xsh_instrument_arm_tostring(instrument);
1018
1020 if (is_ifu) {
1021 xsh_msg( "Detect Order Edges in IFU mode");
1022 } else {
1023 xsh_msg( "Detect Order Edges in SLIT mode");
1024 }
1025
1026 /* allocate memory on variable storing intermediate results */
1027 /* detect order edge */
1028 /* TODO: is the size of this array ok? should not be pre->ny/list->bin_y? */
1029 XSH_CALLOC( positions, double, pre->ny*list->bin_y); /* y pos */
1030 XSH_CALLOC ( uppervalues,double,pre->ny*list->bin_y); /* right edge x pos */
1031 XSH_CALLOC( lowervalues, double,pre->ny*list->bin_y); /* left edge x pos */
1032 XSH_CALLOC ( res_flux, double, window_size); /* flux level */
1033 XSH_CALLOC( res_noise, double,window_size); /* noise level */
1034 /* In case of IFU */
1035 XSH_CALLOC ( slicup,double,pre->ny*list->bin_y); /* IFU upp slice (right) pos */
1036 XSH_CALLOC( sliclow, double,pre->ny*list->bin_y); /* IFU low slice (left) pos */
1037
1038 /* slitlet init factor */
1039 int decode_bp = instrument->decode_bp;
1040 /* for all orders */
1041 for (i = 0; i < list->size; i++) {
1042 int mean_size_up = 0;
1043 int mean_size_low = 0;
1044 int mean_size_slic_low = 0;
1045 int mean_size_slic_up = 0;
1046 double ratio_low = 0., ratio_up = 0.;
1047 int bin_starty;
1048 int bin_endy;
1049
1050 size = 0;
1051 check( bin_starty = xsh_order_list_get_starty( list, i));
1052 check( bin_endy = xsh_order_list_get_endy( list, i));
1053 xsh_msg_dbg_medium( "***** Order %d (%d-->%d)", i, bin_starty, bin_endy);
1054
1055 if (is_ifu && !fixed_slice) {
1056 int max_y = 0;
1057 float min_lo = 0.0, min_up = 0.0, sdivn = 0.0;
1058 int xmin = 0;
1059 int upperval = 0, lowval = 0;
1060
1061 /* Scan the whole order and detect y position at which its flux is
1062 maximum. The pixel must be a good pixel (we use also pixel code to
1063 specify which pixel codes are good/bad) */
1064 check(
1065 xsh_detect_max_y( list, chunk_hsize, list->list[i].cenpoly, bin_starty, bin_endy, pre,decode_bp, &max_y));
1066 xsh_msg("Max at %d", max_y);
1067
1068 /* detect order low (left) and upper (right) edge positions */
1069 check(
1070 xsh_detect_edges( list, max_y, list->list[i].cenpoly, pre, window_hsize, res_flux, res_noise, chunk_hsize, min_snr, flux_frac, min_order_size_x,decode_bp, &xmin, &sdivn, &upperval, &lowval, &min_lo, &min_up));
1071
1072 /* estimate size of order along X */
1073 xsh_msg_dbg_medium("order size at center %d", upperval-lowval);
1074 /* estimate slitlet ratio at order center */
1075 /* estimate the slitlet flux ratio for upper and lower IFU slitlets
1076 as fraction of average flux above the min slitlet background as
1077 compared to the mean central slitlet flux */
1078 check(
1079 xsh_detect_slitlet_ratio( res_flux, window_hsize, min_lo, min_up, lowval, upperval, &ratio_low, &ratio_up));
1080 xsh_msg_dbg_medium("ratio low %f up %f", ratio_low, ratio_up);
1081 }
1082 /* for all Y */
1083 bad_points = 0;
1084 for (y = 1 + chunk_hsize; y <= pre->ny - chunk_hsize; y++) {
1085 //if((y>= list->list[i].starty) &&
1086 // (y<=list->list[i].endy)) {
1087 float min_lo = 0.0, min_up = 0.0, sdivn = 0.0;
1088 int j = 0, xmin = 0;
1089 int upperval = 0, lowval = 0;
1090 double xslicup = 0.;
1091 double xsliclow = 0.;
1092 /* detect order low (left) and upper (right) edge positions */
1093
1094 check(
1095 xsh_detect_edges( list, y, list->list[i].cenpoly, pre, window_hsize, res_flux, res_noise, chunk_hsize, min_snr, flux_frac, min_order_size_x,decode_bp, &xmin, &sdivn, &upperval, &lowval, &min_lo, &min_up));
1096
1097 /* IFU - PRELIMINARY
1098 Starting from x (center of the order) calculate mean flux
1099 value using +-2 pixels
1100 Then find the slicup (from x toward nx): the edge is where
1101 the signal becomes lower than 90% of the avg signal at the
1102 center.
1103 Same for sliclow
1104 */
1105 /* limit edge detection to good S/N regions */
1106 if ((sdivn > min_snr) && is_ifu) {
1107 if (fixed_slice) {
1108 int slit_size = ceil((upperval - lowval + 1) / 3.0);
1109
1110 xsliclow = lowval + slit_size;
1111 xslicup = upperval - slit_size;
1112 } else {
1113 double avg = 0.;
1114 double max;
1115
1116 for (j = window_hsize + 1 - HALF_SLIC_WINDOW;
1117 j <= window_hsize + 1 + HALF_SLIC_WINDOW; j++) {
1118 avg += res_flux[j];
1119 }
1120 avg /= (HALF_SLIC_WINDOW * 2) + 1;
1121 max = (avg - min_up) * slitlet_up_factor * ratio_up;
1122 xslicup = 0;
1123 for (j = window_hsize + 1; j <= upperval; j++) {
1124 if ((res_flux[j] - min_up) < max) {
1125 /* Found position of slicup */
1126 xslicup = j - 1;
1127 break;
1128 }
1129 }
1130 xsliclow = 0;
1131 max = (avg - min_lo) * slitlet_low_factor * ratio_low;
1132 for (j = window_hsize + 1; j >= lowval; j--) {
1133 if ((res_flux[j] - min_lo) < max) {
1134 /* Found position of slicup */
1135 xsliclow = j + 1;
1136 break;
1137 }
1138 }
1139 }
1140 }
1141 /* store detect order edge */
1142 if ((sdivn > min_snr) && (upperval - lowval) >= min_order_size_x) {
1143 if (!is_ifu) {
1144 positions[size] = y;
1145 lowervalues[size] = lowval + xmin;
1146 uppervalues[size] = upperval + xmin;
1147 mean_size_low += window_hsize + 1 - lowval;
1148 mean_size_up += upperval - (window_hsize + 1);
1149 size++;
1150 } else if (xslicup != 0 && xsliclow != 0) {
1151
1152 positions[size] = y;
1153 lowervalues[size] = lowval + xmin;
1154 uppervalues[size] = upperval + xmin;
1155 mean_size_low += window_hsize + 1 - lowval;
1156 mean_size_up += upperval - (window_hsize + 1);
1157 slicup[size] = xslicup + xmin;
1158 sliclow[size] = xsliclow + xmin;
1159 mean_size_slic_low += window_hsize + 1 - xsliclow;
1160 mean_size_slic_up += xslicup - (window_hsize + 1);
1161 size++;
1162 }
1163 } else {
1165 "Order %d edge detection: sn (%g) < sn_threshold (%g) or order size (%d) < min order size min (%d)", list->list[i].absorder, sdivn, min_snr, (upperval - lowval), min_order_size_x);
1166 bad_points++;
1167 }
1168 /* END VALID THRESH*/
1169 //}//end check starty < y < endy
1170 } // end loop over y
1171 if (bad_points > 1) {
1173 "Order %d edge detection summary: ", list->list[i].absorder);
1175 "%d out of %d not matching user defined min S/N (%g), or minimum order size", bad_points, pre->ny-2*chunk_hsize, min_snr);
1176 }
1177
1178 /* put the start and end of order in Y */
1179 if (size <= 3 && detectorder_par->qc_mode == CPL_TRUE) {
1180 /* Set dummy values:
1181 -999 can occur only in QC mode and is used as flag to skip
1182 edge detection on a given order. This was explitly asked by QC.
1183 Normal user mode should never have this behaviour.
1184 */
1185
1186 list->list[i].starty = -999;
1187 list->list[i].endy = -999;
1188 xsh_msg("PROBLEMS");
1189 //list->size=list->size-1;
1190 method = "fixed";
1192 "%d out of %d not matching user defined min S/N (%g), or minimum order size", bad_points, pre->ny-2*chunk_hsize, min_snr);
1193
1194 break;
1195
1196 } else {
1197 assure(
1198 size > 3,
1199 CPL_ERROR_ILLEGAL_INPUT,
1200 "can't fit polynomial solution of degree %d to only %d data points "
1201 "parameter detectorder-edges-search-window-half-size=%d "
1202 "may have a too small value "
1203 "or parameter detectorder-min-sn value may be too big "
1204 "or parameter detectorder-chunk-half-size=%d "
1205 "may have been set to a too small or too large large value "
1206 "or parameter detectorder-edges-flux-thresh=%g "
1207 "may have been set to a too small or too large large value", list->list[i].pol_degree, size, window_hsize, chunk_hsize, flux_frac);
1208
1209 list->list[i].starty = positions[0] - chunk_hsize;
1210 list->list[i].endy = positions[size - 1] + chunk_hsize;
1211 }
1212
1213 mean_size_up = mean_size_up / size;
1214 mean_size_low = mean_size_low / size;
1215 xsh_msg_dbg_medium("mean size up %d low %d", mean_size_up, mean_size_low);
1216 if (is_ifu) {
1217 mean_size_slic_low = mean_size_slic_low / size;
1218 mean_size_slic_up = mean_size_slic_up / size;
1219 }
1221 "mean size Slitlets up %d low %d", mean_size_slic_up, mean_size_slic_low);
1222 /* arrange polynomial if start_y and end_y covers only a part of ny */
1224 "starty %d endy %d", list->list[i].starty, list->list[i].endy);
1225
1226 for (y = 1; y < list->list[i].starty; y++) {
1227 int x_center;
1228
1229 check(
1230 x_center = xsh_order_list_eval_int( list, list->list[i].cenpoly, y));
1231 positions[size] = y;
1232 lowervalues[size] = x_center - mean_size_low;
1233 uppervalues[size] = x_center + mean_size_up;
1234 if (is_ifu) {
1235 sliclow[size] = x_center - mean_size_slic_low;
1236 slicup[size] = x_center + mean_size_slic_up;
1237 }
1238 size++;
1239 }
1240 for (y = list->list[i].endy + 1; y <= pre->ny; y++) {
1241 int x_center;
1242
1243 check(
1244 x_center = xsh_order_list_eval_int( list, list->list[i].cenpoly, y));
1245 positions[size] = y;
1246 lowervalues[size] = x_center - mean_size_low;
1247 uppervalues[size] = x_center + mean_size_up;
1248
1249 if (is_ifu) {
1250 sliclow[size] = x_center - mean_size_slic_low;
1251 slicup[size] = x_center + mean_size_slic_up;
1252 }
1253 size++;
1254 }
1255
1256 /*Detected points debugging */
1258 FILE* debug_out = NULL;
1259 int newi = 0;
1260 char openmode[2];
1261
1262 if (i == 0) {
1263 sprintf(openmode, "w");
1264 } else {
1265 sprintf(openmode, "a");
1266 }XSH_NAME_LAMP_MODE_ARM( fname, "detect_edges_points", ".log",
1267 instrument);
1268debug_out = fopen(fname, openmode);
1269
1270 for (newi = 0; newi < size; newi++) {
1271 fprintf(debug_out, "%f %f %f\n", lowervalues[newi], uppervalues[newi],
1272 positions[newi]);
1273 }
1274 fclose(debug_out);
1275 if (is_ifu) {
1276 XSH_NAME_LAMP_MODE_ARM( fname, "orders_slic", ".log", instrument);
1277debug_out = fopen(fname, openmode);
1278
1279 for (newi = 0; newi < size; newi++) {
1280 fprintf(debug_out, "%f %f %f\n", sliclow[newi], slicup[newi],
1281 positions[newi]);
1282 }
1283 fclose(debug_out);
1284 }
1285 }
1286 /* positions convert in binning 1x1 */
1287 list->list[i].starty *= list->bin_y;
1288 list->list[i].endy *= list->bin_y;
1289
1290 for (k = 0; k < size; k++) {
1291 lowervalues[k] *= list->bin_x;
1292 uppervalues[k] *= list->bin_x;
1293 positions[k] *= list->bin_y;
1294 if (is_ifu) {
1295 sliclow[k] *= list->bin_x;
1296 slicup[k] *= list->bin_x;
1297 }
1298 }
1299 /* create vector from values */
1300 check(xpos = cpl_vector_wrap(size,positions));
1301 check(upper = cpl_vector_wrap(size,uppervalues));
1302 check(lower = cpl_vector_wrap(size,lowervalues));
1303 if (is_ifu) {
1304 check( vslicup = cpl_vector_wrap( size, slicup ));
1305 check( vsliclow = cpl_vector_wrap( size, sliclow ));
1306 }
1307
1308 /* create polynomial solutions: fit a polynomial to the found order edges
1309 (and eventually IFU lower and upper slices positions) */
1311 check(
1312 list->list[i].edguppoly = xsh_polynomial_fit_1d_create( xpos, upper, list->list[i].pol_degree, NULL));
1313
1315 check(
1316 list->list[i].edglopoly = xsh_polynomial_fit_1d_create( xpos, lower, list->list[i].pol_degree, NULL));
1317
1318 if (is_ifu) {
1320 check(
1321 list->list[i].sliclopoly = xsh_polynomial_fit_1d_create( xpos, vsliclow, list->list[i].pol_degree, NULL));
1323 check(
1324 list->list[i].slicuppoly = xsh_polynomial_fit_1d_create( xpos, vslicup, list->list[i].pol_degree,NULL));
1325 }
1326
1327
1328 /* ENDREGDEBUG */
1329 check( xsh_unwrap_vector(&xpos));
1330 check( xsh_unwrap_vector(&upper));
1331 check( xsh_unwrap_vector(&lower));
1332 if (is_ifu) {
1333 check( xsh_unwrap_vector( &vslicup));
1334 check( xsh_unwrap_vector( &vsliclow));
1335 }
1336
1337 } /* end loop over i (order list counter) */
1338 /* REG comment due to important memory leaks */
1339 if (strcmp(method, "fixed") != 0) {
1340 check(tab_edges_res=xsh_compute_flat_edges(frame,list,instrument,method));
1341 }
1342 /* Finally save results in edge order table */
1344 XSH_REGDEBUG( "tag %s", tag);
1346check ( result = xsh_order_list_save( list, instrument, fname, tag, pre->ny*list->bin_y));
1347
1348 if (strcmp(method, "fixed") != 0) {
1349 check(cpl_table_save(tab_edges_res, NULL, NULL, fname, CPL_IO_EXTEND));
1350 }
1351 //check( xsh_add_temporary_file( fname));
1352 xsh_msg_dbg_high( " Created %s", fname);
1353
1354 cleanup: if (cpl_error_get_code() != CPL_ERROR_NONE) {
1355 xsh_unwrap_vector(&xpos);
1356 xsh_unwrap_vector(&upper);
1357 xsh_unwrap_vector(&lower);
1358 xsh_unwrap_vector(&vslicup);
1359 xsh_unwrap_vector(&vsliclow);
1360 }
1361 xsh_pre_free(&pre);
1362 xsh_free_table(&tab_edges_res);
1363
1364 xsh_order_list_free(&list);
1365 XSH_FREE( positions);
1366 XSH_FREE( uppervalues);
1367 XSH_FREE( lowervalues);
1368 XSH_FREE( res_flux);
1369 XSH_FREE( res_noise);
1370 XSH_FREE( slicup);
1371 XSH_FREE( sliclow);
1372 XSH_FREE( fname);
1373 return result;
1374}
1375/*---------------------------------------------------------------------------*/
1376
1377/*---------------------------------------------------------------------------*/
static void xsh_detect_edges(xsh_order_list *list, int y, cpl_polynomial *cen_poly, xsh_pre *pre, int window_hsize, double *res_flux, double *res_noise, int chunk_hsize, double min_snr, double flux_frac, int min_size_x, const int decode_bp, int *x_min, float *x_cen_sdivn, int *xup, int *xlow, float *min_low, float *min_up)
Detect order edges: at each y position determines low (left) and upper (right) order edges.
static cpl_table * xsh_compute_flat_edges(cpl_frame *frame, xsh_order_list *list, xsh_instrument *instrument, const char *method)
Measure flat edges (and eventually IFU slices) on master bias using Scharr X filter.
static void xsh_detect_slitlet_ratio(double *res_flux, int window_hsize, double min_low, double min_up, int xlow, int xup, double *ratio_low, double *ratio_up)
static void xsh_detect_max_y(xsh_order_list *list, int chunk_hsize, cpl_polynomial *cen_poly, int cen_start, int cen_end, xsh_pre *pre, const int decode_bp, int *maxy)
Detect Y position where flux is max.
cpl_frame * xsh_detect_order_edge(cpl_frame *frame, cpl_frame *cen_order_tab_frame, xsh_detect_order_param *detectorder_par, xsh_instrument *instrument)
Detect order edges and compute polynomial description of ordermin and order max.
static void xsh_eval_y_avg_chunk(xsh_pre *pre, int xc, int yc, int chunk_y_hsize, int x_hsize, const int decode_bp, double *flux, double *noise)
Evaluate by chunk in Y the total and mean flux and the corresponding errors around x,...
#define HALF_SLIC_WINDOW
static xsh_instrument * instrument
cpl_frame * xsh_order_list_save(xsh_order_list *order_list, xsh_instrument *instrument, const char *filename, const char *tag, const int ny)
Save an order list to a frame.
int xsh_order_list_eval_int(xsh_order_list *list, cpl_polynomial *poly, double y)
Evaluate an order list poly but return the central pixel position rounding the polynomial.
xsh_order_list * xsh_order_list_load(cpl_frame *frame, xsh_instrument *instr)
load an order list from a frame
int xsh_order_list_get_starty(xsh_order_list *list, int i)
get position on Y axis of first pixel detected on order
int xsh_order_list_get_endy(xsh_order_list *list, int i)
get position on Y axis of last pixel detected on order
void xsh_order_list_free(xsh_order_list **list)
free memory associated to an order_list
double xsh_order_list_eval(xsh_order_list *list, cpl_polynomial *poly, double y)
Evaluate an order list poly.
xsh_pre * xsh_pre_load(cpl_frame *frame, xsh_instrument *instr)
Load a xsh_pre structure from a frame.
Definition: xsh_data_pre.c:849
void xsh_pre_free(xsh_pre **pre)
Free a xsh_pre structure.
Definition: xsh_data_pre.c:823
#define XSH_REGDEBUG(...)
Definition: xsh_error.h:132
#define XSH_ASSURE_NOT_ILLEGAL(cond)
Definition: xsh_error.h:107
#define assure(CONDITION, ERROR_CODE,...)
Definition: xsh_error.h:54
#define check(COMMAND)
Definition: xsh_error.h:71
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
XSH_MODE xsh_instrument_get_mode(xsh_instrument *i)
Get a mode on instrument structure.
int size
int * y
int * x
#define xsh_msg_dbg_medium(...)
Definition: xsh_msg.h:44
#define xsh_msg_error(...)
Print an error message.
Definition: xsh_msg.h:62
#define xsh_msg(...)
Print a message on info level.
Definition: xsh_msg.h:121
#define xsh_msg_dbg_high(...)
Definition: xsh_msg.h:40
void xsh_unwrap_vector(cpl_vector **v)
Unwrap a vector and set the pointer to NULL.
Definition: xsh_utils.c:2345
void xsh_free_polynomial(cpl_polynomial **p)
Deallocate a polynomial and set the pointer to NULL.
Definition: xsh_utils.c:2194
void xsh_free_image(cpl_image **i)
Deallocate an image and set the pointer to NULL.
Definition: xsh_utils.c:2116
int xsh_debug_level_get(void)
get debug level
Definition: xsh_utils.c:3142
void xsh_free_table(cpl_table **t)
Deallocate a table and set the pointer to NULL.
Definition: xsh_utils.c:2133
void xsh_free_propertylist(cpl_propertylist **p)
Deallocate a property list and set the pointer to NULL.
Definition: xsh_utils.c:2179
cpl_propertylist * header
xsh_order * list
cpl_polynomial * edguppoly
cpl_polynomial * edglopoly
cpl_polynomial * slicuppoly
cpl_polynomial * sliclopoly
cpl_polynomial * cenpoly
cpl_image * qual
Definition: xsh_data_pre.h:71
cpl_image * data
Definition: xsh_data_pre.h:65
cpl_image * errs
Definition: xsh_data_pre.h:68
@ XSH_LAMP_QTH
@ XSH_ARM_UVB
#define XSH_NAME_LAMP_MODE_ARM(name, id, ext, instr)
@ XSH_MODE_IFU
int nx
int threshold
Definition: xsh_detmon_lg.c:90
int llx
Definition: xsh_detmon_lg.c:85
const char * method
Definition: xsh_detmon_lg.c:78
int urx
Definition: xsh_detmon_lg.c:87
int ny
#define XSH_MEASURE_FLAT_QTH_SLIT_EDGES_UVB
Definition: xsh_dfs.h:205
#define XSH_MEASURE_FLAT_IFU_EDGES
Definition: xsh_dfs.h:210
#define XSH_ORDER_TAB_EDGES
Definition: xsh_dfs.h:554
#define XSH_MEASURE_FLAT_D2_SLIT_EDGES_UVB
Definition: xsh_dfs.h:204
#define XSH_MEASURE_FLAT_QTH_IFU_EDGES_UVB
Definition: xsh_dfs.h:212
#define XSH_MEASURE_FLAT_SLIT_EDGES
Definition: xsh_dfs.h:203
#define XSH_GET_TAG_FROM_ARM(TAG, instr)
Definition: xsh_dfs.h:1548
#define XSH_MEASURE_FLAT_D2_IFU_EDGES_UVB
Definition: xsh_dfs.h:211
#define XSH_GET_TAG_FROM_LAMP(TAG, instr)
Definition: xsh_dfs.h:1608
#define max(a, b)
#define BOOLEAN_TO_STRING(boolean)
Definition: xsh_utils.h:117
#define XSH_NEW_PROPERTYLIST(POINTER)
Definition: xsh_utils.h:70
#define XSH_FREE(POINTER)
Definition: xsh_utils.h:92
@ XSH_DEBUG_LEVEL_MEDIUM
Definition: xsh_utils.h:138
#define XSH_CALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:56
cpl_image * xsh_sobel_lx(cpl_image *in)
Compute X Sobel filter transformation.
cpl_image * xsh_scharr_x(cpl_image *in)
Compute X Scharr filter transformation.
cpl_polynomial * xsh_polynomial_fit_1d_create(const cpl_vector *x_pos, const cpl_vector *values, int degree, double *mse)