X-shooter Pipeline Reference Manual 3.8.15
xsh_model_kernel.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
22 * $Author: amodigli $
23 * $Date: 2012-12-18 16:09:08 $
24 * $Revision: 1.201 $
25
26 */
27
28
29
30
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34#include <xsh_cpl_size.h>
35//dummy edit
36/*-----------------------------------------------------------------------------
37 Includes
38 -----------------------------------------------------------------------------*/
39#include <math.h>
40
41#include <xsh_data_the_map.h>
42#include <xsh_drl.h>
43#include <xsh_data_pre.h>
44#include <xsh_dfs.h>
45#include <xsh_pfits.h>
46#include <xsh_error.h>
47#include <xsh_msg.h>
48#include <xsh_data_instrument.h>
50#include <xsh_badpixelmap.h>
51#include <xsh_model_io.h>
52#include <cpl.h>
53#include <xsh_model_ref_ind.h>
54#include <xsh_data_resid_tab.h>
55#include <xsh_data_arclist.h>
56#include <xsh_model_kernel.h>
57#include <xsh_model_metric.h>
59#include <xsh_utils_wrappers.h>
60//#include <gen_physmod.h>
61
62/*----------------------------------------------------------------------------*/
66/*----------------------------------------------------------------------------*/
67
68#define VERBOSE 0
69#define mm2nm 1000000.0
70#define mm2um 1000.0
71
72#if defined VERBOSE && VERBOSE > 0
73#define XSH_TRACE_MSG(array) \
74xsh_msg("array: %g, %g, %g, %g",array[0],array[1],array[2],array[3]);
75#else
76#define XSH_TRACE_MSG(array)
77#endif
78
79
80/* for conversion from degree to radians */
81//static const DOUBLE DEG2RAD=0.017453292519943295;
82
83typedef struct {
84 int order ;
85 int pos_x ;
86 int pos_y ;
87 double flux ;
89
90static const int vectordim=4;
91
92
95static void xsh_nullmatrix(mat A)
96{
97
98 register int i,j;
99 for(i=0; i<vectordim; i++) {
100 for(j=0; j<vectordim; j++) {
101 A[i][j]=0.0;
102 }
103 }
104
105 //memset(A,0,vectordim*vectordim);
106
107}
108/* Not used
109static void xsh_copymatrix(mat A, mat B)
110{
111
112 int i,j;
113 for(i=0; i<vectordim; i++) {
114 for(j=0; j<vectordim; j++) {
115 A[i][j]=B[i][j];
116 }
117 }
118
119 //memcpy(A,B,vectordim*vectordim);
120}
121*/
122static void xsh_nullvector(vec a)
123{
124
125 int i;
126 for(i=0; i<vectordim; i++) a[i]=0.0;
127
128 //memset(vec,0,vectordim);
129}
130
131static void xsh_copyvector(vec a, vec b)
132{
133 int i;
134 for(i=0; i<vectordim; i++) a[i]=b[i];
135 //memcpy(a,b,vectordim);
136}
137
138static const char*
140{
141
142 const char* tag=NULL;
143
144 if(rec_id==0) {
145 /* if input recipe was xsh_startup */
146 if (p_xs_3->arm == XSH_ARM_UVB) {
148 }
149 else if (p_xs_3->arm == XSH_ARM_VIS) {
151 }
152 else if (p_xs_3->arm == XSH_ARM_NIR) {
154 }
155 } else if(rec_id==1) {
156 /* if input recipe was xsh_predict */
157 if (p_xs_3->arm == XSH_ARM_UVB) {
159 }
160 else if (p_xs_3->arm == XSH_ARM_VIS) {
162 }
163 else if (p_xs_3->arm == XSH_ARM_NIR) {
165 }
166 } else if (rec_id ==2 ) {
167
168 /* if input recipe was xsh_2dmap */
169 if (p_xs_3->arm == XSH_ARM_UVB) {
171 }
172 else if (p_xs_3->arm == XSH_ARM_VIS) {
174 }
175 else if (p_xs_3->arm == XSH_ARM_NIR) {
177 }
178
179 } else if (rec_id ==3 ) {
180
181 /* if input recipe was xsh_wavecal slit */
182 if (p_xs_3->arm == XSH_ARM_UVB) {
184 }
185 else if (p_xs_3->arm == XSH_ARM_VIS) {
187 }
188 else if (p_xs_3->arm == XSH_ARM_NIR) {
190 }
191
192
193 } else if (rec_id ==4 ) {
194
195 /* if input recipe was xsh_wavecal ifu */
196 if (p_xs_3->arm == XSH_ARM_UVB) {
198 }
199 else if (p_xs_3->arm == XSH_ARM_VIS) {
201 }
202 else if (p_xs_3->arm == XSH_ARM_NIR) {
204 }
205
206 } else if (rec_id ==5 ) {
207
208 /* if input recipe was xsh_flexcor */
209 if (p_xs_3->arm == XSH_ARM_UVB) {
211 }
212 else if (p_xs_3->arm == XSH_ARM_VIS) {
214 }
215 else if (p_xs_3->arm == XSH_ARM_NIR) {
217 }
218 }
219 return tag;
220}
221
222
223
224static cpl_error_code
226 DOUBLE* p_wlarray,DOUBLE** ref_ind,
227 const int size, const int annealed,
228 cpl_propertylist* resid_header,
229 cpl_frame* resid_frame,
230 cpl_propertylist** result)
231{
232
233
234 double resx_min=0;
235 double resx_max=0;
236 double resy_min=0;
237 double resy_max=0;
238
239 double resx_med=0;
240 double resy_med=0;
241
242 double resx_avg=0;
243 double resy_avg=0;
244
245 double resx_rms=0;
246 double resy_rms=0;
247
248 int ndat=0;
249 int morder_cnt=0;
250 const char* resid_tbl_name=NULL;
251 cpl_table* resid_tbl=NULL;
252
253 int jj=0;
254 double* pxm=NULL;
255 double* pym=NULL;
256
257 check(resid_tbl_name=cpl_frame_get_filename(resid_frame));
258
259 check(resid_tbl=cpl_table_load(resid_tbl_name,1,0));
260 check(cpl_table_fill_column_window(resid_tbl,
262 check(cpl_table_fill_column_window(resid_tbl,
264
265 check(pxm=cpl_table_get_data_double(resid_tbl,
267 check(pym=cpl_table_get_data_double(resid_tbl,
269
270
271 for (jj=0;jj<size;jj++) {
272 p_xs_3->es_y_tot=p_xs_3->es_y+p_xs_3->slit[msp_coord[jj].slit_pos]*p_xs_3->slit_scale;
273 morder_cnt=msp_coord[jj].order;
274 xsh_3_init(p_xs_3);
275 xsh_3_eval(p_wlarray[jj],morder_cnt,ref_ind,p_xs_3);
276 xsh_3_detpix(p_xs_3);
277 pxm[jj]=p_xs_3->xpospix;
278 pym[jj]=p_xs_3->ypospix;
279/*
280 printf("check %d %lf %lf %d %d %lf %lf %lf %lf %d\n",
281 jj,p_wlarray[jj],p_xs_3->es_y,p_xs_3->chippix[0],
282 msp_coord[jj].arm,p_xs_3->xpospix,p_xs_3->ypospix,
283 msp_coord[jj].x-p_xs_3->xpospix,msp_coord[jj].y-p_xs_3->ypospix,
284 msp_coord[jj].order);
285*/
286 }
287 check( cpl_table_copy_data_double( resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_RESIDXMODEL,
288 cpl_table_get_data_double ( resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_XGAUSS)));
289 check( cpl_table_copy_data_double( resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_RESIDYMODEL,
290 cpl_table_get_data_double ( resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_YGAUSS)));
291
292 check(cpl_table_subtract_columns(resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_RESIDXMODEL,
294 check(cpl_table_subtract_columns(resid_tbl, XSH_RESID_TAB_TABLE_COLNAME_RESIDYMODEL,
296
297 check(cpl_table_save(resid_tbl, resid_header, NULL,resid_tbl_name, CPL_IO_DEFAULT));
298
299
300 check(resx_min=cpl_table_get_column_min(resid_tbl,
302 check(resx_max=cpl_table_get_column_max(resid_tbl,
304 check(resx_avg=cpl_table_get_column_mean(resid_tbl,
306 check(resx_med=cpl_table_get_column_median(resid_tbl,
308 check(resx_rms=cpl_table_get_column_stdev(resid_tbl,
310
311
312 check(resy_min=cpl_table_get_column_min(resid_tbl,
314 check(resy_max=cpl_table_get_column_max(resid_tbl,
316 check(resy_avg=cpl_table_get_column_mean(resid_tbl,
318 check(resy_med=cpl_table_get_column_median(resid_tbl,
320 check(resy_rms=cpl_table_get_column_stdev(resid_tbl,
322 check(ndat=cpl_table_get_nrow(resid_tbl));
323 xsh_free_table(&resid_tbl);
324
325 /* printf ("After Anneal: \n");
326 for (ii=0;ii<adim;ii++) {
327 printf("%d %s %lf \n", aname[ii], (p_all_par+aname[ii])->name, abest[ii]);
328 }*/
329
330 //cpl_propertylist_append_string(*result, "INSTRUME", "XSHOOTER") ;
331
332 cpl_propertylist_append_int(*result,"ESO QC MODEL NDAT",ndat) ;
333
334 if(annealed==0) {
335 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESX_MIN,resx_min) ;
336 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESY_MIN,resy_min) ;
337 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESX_MAX,resx_max) ;
338 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESY_MAX,resy_max) ;
339 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESX_AVG,resx_avg) ;
340 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESY_AVG,resy_avg) ;
341 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESX_MED,resx_med) ;
342 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESY_MED,resy_med) ;
343 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESX_RMS,resx_rms) ;
344 cpl_propertylist_append_double(*result,XSH_QC_MODEL_PREDICT_RESY_RMS,resy_rms) ;
345 } else {
346
347 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESX_MIN,resx_min) ;
348 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESY_MIN,resy_min) ;
349 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESX_MAX,resx_max) ;
350 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESY_MAX,resy_max) ;
351 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESX_AVG,resx_avg) ;
352 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESY_AVG,resy_avg) ;
353 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESX_MED,resx_med) ;
354 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESY_MED,resy_med) ;
355 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESX_RMS,resx_rms) ;
356 cpl_propertylist_append_double(*result,XSH_QC_MODEL_ANNEAL_RESY_RMS,resy_rms) ;
357
358 }
359 cleanup:
360 xsh_free_table(&resid_tbl);
361 return cpl_error_get_code();
362
363
364}
365
366/*----------------------------------------------------------------------------*/
373/*----------------------------------------------------------------------------*/
374
375void xsh_3_init(struct xs_3 * p_xs_3)
376{
377 /*int ii,jj;
378 mat tras_toprism1,tras_toprism2,tras_toprism3;
379 mat tras_toprism4,tras_toprism5,tras_toprism6;
380 mat unity_mat={ {1,0,0,0},
381 {0,1,0,0},
382 {0,0,1,0},
383 {0,0,0,1}};*/
384#ifdef FCCDD_FLAG
385 xsh_rotin(p_xs_3->todetector,-0.062,0.01,0.0);
386#endif
387
388 /******************* Rotation of entrance slit********************/
389 //xsh_showmatrix(p_xs_3->e_slit);
390 xsh_rotin(p_xs_3->e_slit,p_xs_3->mues,p_xs_3->nues,p_xs_3->taues);
391 //xsh_showmatrix(p_xs_3->e_slit);
392 /******************* Rotation into Prism********************/
393 xsh_rotin(p_xs_3->mup_ir_cor,p_xs_3->cmup1,0.0,0.0);
394 xsh_rotin(p_xs_3->mup_ir_cor_out,-p_xs_3->cmup1,0.0,0.0);
395 xsh_rotin(p_xs_3->toprism1,p_xs_3->mup1,p_xs_3->nup1,p_xs_3->taup1);
396 xsh_rotin(p_xs_3->toprism2,p_xs_3->mup2,p_xs_3->nup2,p_xs_3->taup2);
397
398 /******************* Rotation out of Prism********************/
399 /******************* Rotation back to ref********************
400 xsh_transpose(tras_toprism1,p_xs_3->toprism1);
401 xsh_transpose(tras_toprism2,p_xs_3->toprism2);
402 xsh_multiplymatrix(p_xs_3->prism_out,tras_toprism2,tras_toprism1);*/
403 /*Above is not used, instead toprism1 is used when exiting the prism the first time, following the ZEMAX prescription*/
404 /*IR only correction to 1st prism exit*/
405
406 /******************* Rotation into 2nd IR Prism********************/
407 xsh_rotin(p_xs_3->toprism3,p_xs_3->mup3,p_xs_3->nup3,p_xs_3->taup3);
408 xsh_rotin(p_xs_3->toprism4,p_xs_3->mup4,p_xs_3->nup4,p_xs_3->taup4);
409
410 /******************* Rotation out of 2nd IR Prism********************/
411 /******************* Rotation back to ref********************
412 xsh_transpose(tras_toprism3,p_xs_3->toprism3);
413 xsh_transpose(tras_toprism4,p_xs_3->toprism4);
414 xsh_multiplymatrix(p_xs_3->prism_out2,tras_toprism4,tras_toprism3);*/
415 /*Above is not used, instead toprism3 is used when exiting the prism the first time, following the ZEMAX prescription*/
416
417/******************* Rotation into 3rd IR Prism********************/
418 xsh_rotin(p_xs_3->toprism5,p_xs_3->mup5,p_xs_3->nup5,p_xs_3->taup5);
419 xsh_rotin(p_xs_3->toprism6,p_xs_3->mup6,p_xs_3->nup6,p_xs_3->taup6);
420
421 /******************* Rotation out of 3rd IR Prism********************/
422 /******************* Rotation back to ref********************
423 xsh_transpose(tras_toprism5,p_xs_3->toprism5);
424 xsh_transpose(tras_toprism6,p_xs_3->toprism6);
425 xsh_multiplymatrix(p_xs_3->prism_out3,tras_toprism6,tras_toprism5);*/
426 /*Above is not used, instead toprism5 is used when exiting the prism the first time, following the ZEMAX prescription*/
427
428 /******************* Rotation into and out of Grating ********************/
429 xsh_rotin(p_xs_3->tograt,p_xs_3->mug,p_xs_3->nug,p_xs_3->taug);
430 xsh_transpose(p_xs_3->grat_out,p_xs_3->tograt);
431
432 /******************* Rotation back into Prism********************/
433
434 // xsh_transpose(p_xs_3->ret_prism2,p_xs_3->prism_out);
435 /*intuitive version above is replaced with inverse of toprism1 which is actually used when exiting the prism the first time follwing the ZEMAX prescription*/
436 xsh_transpose(p_xs_3->ret_prism2,p_xs_3->toprism1);
437 xsh_transpose(p_xs_3->ret_prism1,p_xs_3->toprism2);
438 xsh_multiplymatrix(p_xs_3->ret_prism_out1,p_xs_3->toprism2,p_xs_3->toprism1);
439 xsh_transpose(p_xs_3->ret_prism4,p_xs_3->toprism3);
440 xsh_transpose(p_xs_3->ret_prism3,p_xs_3->toprism4);
441 xsh_multiplymatrix(p_xs_3->ret_prism_out2,p_xs_3->toprism4,p_xs_3->toprism3);
442 xsh_transpose(p_xs_3->ret_prism6,p_xs_3->toprism5);
443 xsh_transpose(p_xs_3->ret_prism5,p_xs_3->toprism6);
444 xsh_multiplymatrix(p_xs_3->ret_prism_out3,p_xs_3->toprism6,p_xs_3->toprism5);
445
446 /*Chip limits */
447 if (p_xs_3->arm!=2) {
448 p_xs_3->chipxup=p_xs_3->chipx+p_xs_3->pix_Y*(0.5*p_xs_3->chipypix);
449 p_xs_3->chipxdown=p_xs_3->chipx-p_xs_3->pix_Y*(0.5*p_xs_3->chipypix);
450 p_xs_3->chipyup=p_xs_3->chipy+p_xs_3->pix_X*(0.5*p_xs_3->chipxpix);
451 p_xs_3->chipydown=p_xs_3->chipy-p_xs_3->pix_X*(0.5*p_xs_3->chipxpix);
452 }
453 else {
454 p_xs_3->chipxup=p_xs_3->chipx+p_xs_3->pix_X*(0.5*p_xs_3->chipxpix+NIR_FIX);
455 p_xs_3->chipxdown=p_xs_3->chipx-p_xs_3->pix_X*(0.5*p_xs_3->chipxpix);
456 p_xs_3->chipyup=p_xs_3->chipy+p_xs_3->pix_Y*(+0.5*p_xs_3->chipypix);
457 p_xs_3->chipydown=p_xs_3->chipy-p_xs_3->pix_Y*(0.5*p_xs_3->chipypix);
458 }
459}
460
461/*----------------------------------------------------------------------------*/
470/*----------------------------------------------------------------------------*/
471
472void xsh_3_eval(DOUBLE lambda,
473 int morder,
474 DOUBLE** ref_ind,
475 struct xs_3* p_xs_3)
476{
477 DOUBLE lambda_um,lamf,rind_up,rind_down,xx,yy,dndT;
478 vec vres,slitpos2,slitpos,detproj;
479
480 mat mech={ {1,0,0,0},
481 {morder*(p_xs_3->sg),1,0,0},
482 {0,0,1,0},
483 {0,0,0,-1}};
484 mat chrom_corr={ {1,0,0,0},
485 {0,1,0,0},
486 {0,0,1,0},
487 {0,0,0,1}};
488 /* mat mech={ {1,0,0,0},
489 {0,1,0,0},
490 {-morder*(p_xs_3->sg),0,1,0},
491 {0,0,0,-1}}; */
492
493 /* init start vector */
494 vec vres1={lambda,
495 0,
496 0,
497 -p_xs_3->fcol};
498
499
500 XSH_TRACE_MSG(vres1)
501
502 /*----------------------------------------------------------------------*/
503 slitpos[0]=0.0;
504 slitpos[1]=1.0*p_xs_3->es_x;
505 /* config_mjd paramter is used below to check which version of uvb/vis
506 chromatic aberration correction to use, before august 2010 it should
507 be the old version. This doesn't affect NIR*/
508 if (/*p_xs_3->arm!=2 && */p_xs_3->config_mjd>2455409.0) {
509 // printf("new %lf\n",p_xs_3->config_mjd);
510 if (p_xs_3->arm==0) {
511 if (lambda>0.000425) {
512 slitpos[2]=-1.0*p_xs_3->es_y_tot*(1.0+(lambda-0.000425)*p_xs_3->offx);
513 }
514 else{
515 slitpos[2]=-1.0*p_xs_3->es_y_tot*(1.0+(lambda-0.000425)*p_xs_3->offy);
516 }
517 }
518 else if (p_xs_3->arm==1) {
519 if (lambda>0.000650) {
520 slitpos[2]=1.0*(p_xs_3->es_y_tot)*(1.0+(lambda-0.000900)*p_xs_3->offx);
521 }
522 else{
523 slitpos[2]=1.0*(p_xs_3->es_y_tot)*(1.0+(lambda-0.000018)*p_xs_3->offy);
524 }
525 }
526 else if (p_xs_3->arm==2) {
527 if (lambda>0.001400) {
528 slitpos[2]=1.0*(p_xs_3->es_y_tot-p_xs_3->es_y)*(1.0+(lambda-0.001600)*p_xs_3->offx)+p_xs_3->es_y;
529 }
530 else{
531 slitpos[2]=1.0*(p_xs_3->es_y_tot)*(1.0+(lambda-0.000990)*p_xs_3->offy);
532 }
533 }
534 }
535 else {
536 if (p_xs_3->arm==0) {
537 slitpos[2]=-1.0*p_xs_3->es_y_tot;//*(1.0+(lambda-0.000413)*p_xs_3->offx);
538 }
539 else {
540 slitpos[2]=1.0*p_xs_3->es_y_tot;//*(1.0+(lambda-0.000413)*p_xs_3->offx);
541 }
542 }
543 slitpos[3]=0.0;
544 xsh_matrixforvector(slitpos2,p_xs_3->e_slit,slitpos);
545 xsh_subtractvectors(vres1,slitpos2);
546 xsh_copyvector(vres,vres1);
547 xsh_normall(vres);
548 if (p_xs_3->arm!=2 && p_xs_3->config_mjd<2455409.0) {
549 // printf("old %lf \n",p_xs_3->config_mjd);
550 xsh_rotin(chrom_corr,vres[2]*(lambda-p_xs_3->offy)*p_xs_3->offx,0.0,0.0);
551 xsh_matrixforvector(vres,chrom_corr,vres);
552 }
553
554 XSH_TRACE_MSG(vres)
555
556 /***********************Rotation into Prism *******************/
557 //printf("qwerty 00 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
558 if (p_xs_3->arm==2) xsh_matrixforvector(vres,p_xs_3->mup_ir_cor,vres);
559 //printf("qwerty 01 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
560 xsh_matrixforvector(vres,p_xs_3->toprism1,vres);
561 //printf("qwerty 02 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
562
563 lambda_um=lambda* mm2um;
564 lamf=lambda_um*lambda_um;
565
566 if (p_xs_3->arm==1) {
567 /*NOTE: THE EQN BELOW IS FOR THE MANUFACTURER'S DATA,THE 4th, 5th AND 6th COEFFS ARE THE SQUARES OF THE NORMAL COEFFS (SUCH AS USED IN THE ZnSe DATA, hence the different eqn for NIS prisms 2 and 3 below)*/
568
569 p_xs_3->rind=sqrt(ref_ind[0][0]*lamf/(lamf-ref_ind[0][3])+ref_ind[0][1]*lamf/(lamf-ref_ind[0][4])+ref_ind[0][2]*lamf/(lamf-ref_ind[0][5])+1.0);
570
571 /*fit from Ghosh 97, APPLIED OPTICS y Vol. 36, No. 7 y 1 March 1997*/
572 double lam_ig2=0.04963984;
573 double H=71.0867E-06;
574 double G=-50.2451E-06;
575 double R;
576
577 R=lamf/(lamf-lam_ig2);
578 dndT=(G*R+H*R*R)/(2.0*p_xs_3->rind);
579
580 /*approximate fit to dn/dT(lambda) from figure in Schott TIE-29 doc, p7, fig 3-2*/
581 //dndT=(0.5/lambda_um)*0.000010+0.0000005;
582 /*XSH ODR p93 fig4.10 would imply dn/dT=(0.55/lambda_um)*0.000009*/
583 p_xs_3->rind+=dndT*(p_xs_3->temper-293.15);
584 // printf("ref_ind, lambda %lf %lf \n",p_xs_3->rind=rind_down,lambda);
585 }
586 else {
587 //printf("%lf %lf %lf\n",lambda_um, xsh_model_sellmeier_ext(p_xs_3->arm,p_xs_3->temper,lamf),p_xs_3->rind);
588 p_xs_3->rind=xsh_model_sellmeier_ext(p_xs_3->arm,p_xs_3->temper,lamf);
589 }
590
591 /* Adjust refractive index to account for air (as opposed to vaccum) in the
592 UVB and NIR spectrographs - CURRENTLY NOT USED */
593/* if (p_xs_3->arm!=2) { */
594/* p_xs_3->rind=p_xs_3->rind/xsh_model_ref_ind_air(p_xs_3->temper,lamf); */
595/* } */
596
597 /* Refract */
598 xsh_refract(vres,p_xs_3->rind,vres);
599 //printf("qwerty 0 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
600
601 /* Rotate to exit surface */
602 xsh_matrixforvector(vres,p_xs_3->toprism2,vres);
603 //printf("qwerty 1 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
604
605 /* refract */
606 xsh_refract(vres,1.0/(p_xs_3->rind),vres);
607 //printf("qwerty 2 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
608
609 /* Rotate back into referential */
610 /*NOTE: We follow the ZEMAX prescription and use toprism1 here instead of prism_out */
611 xsh_matrixforvector(vres,p_xs_3->toprism1,vres);
612 //printf("qwerty 3 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
613
614
615
616 XSH_TRACE_MSG(vres)
617 if (p_xs_3->arm==2) {
618 XSH_TRACE_MSG(vres)
619
620 /***********************Rotation into 2nd Prism *******************/
621 xsh_matrixforvector(vres,p_xs_3->toprism3,vres);
622 //printf("qwerty 3.1 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
623
624 //ref_ind for ir 2nd prism (ref_ind applies to 2 and 3)
625 /* Calculate ref ind at temperature above using Sellmeier equation */
626 rind_up=sqrt(ref_ind[1][0]*lamf/(lamf-ref_ind[1][3]*ref_ind[1][3])+ref_ind[1][1]*lamf/(lamf-ref_ind[1][4]*ref_ind[1][4])+ref_ind[1][2]*lamf/(lamf-ref_ind[1][5]*ref_ind[1][5])+1.0);
627
628 /* Calculate ref ind at temperature below using Sellmeier equation */
629 rind_down=sqrt(ref_ind[0][0]*lamf/(lamf-ref_ind[0][3]*ref_ind[0][3])+ref_ind[0][1]*lamf/(lamf-ref_ind[0][4]*ref_ind[0][4])+ref_ind[0][2]*lamf/(lamf-ref_ind[0][5]*ref_ind[0][5])+1.0);
630
631 /* Linear interpolation to get ref ind at actual temperature */
632 p_xs_3->rind2=rind_down+((p_xs_3->t_ir_p2-ref_ind[0][6])/(ref_ind[1][6]-ref_ind[0][6]))*(rind_up-rind_down);
633
634 /* Refract */
635 xsh_refract(vres,p_xs_3->rind2,vres);
636 //printf("qwerty 0b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
637
638 /* Rotate to exit surface */
639 xsh_matrixforvector(vres,p_xs_3->toprism4,vres);
640 //printf("qwerty 1b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
641
642 /* refract */
643 xsh_refract(vres,1.0/(p_xs_3->rind2),vres);
644 //printf("qwerty 2b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
645
646 /* Rotate back into referential */
647 /*NOTE: We follow the ZEMAX prescription and use toprism1 here instead of prism_out */
648 xsh_matrixforvector(vres,p_xs_3->toprism3,vres);
649 //printf("qwerty 3b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
650
651 XSH_TRACE_MSG(vres)
652
653 /***********************Rotation into 3rd Prism *******************/
654 xsh_matrixforvector(vres,p_xs_3->toprism5,vres);
655 XSH_TRACE_MSG(vres)
656
657 //rind3 for ir 3rd prism (ref_ind applies to 2 and 3)
658 /* Calculate ref ind at temperature above using Sellmeier equation */
659 rind_up=sqrt(ref_ind[1][0]*lamf/(lamf-ref_ind[1][3]*ref_ind[1][3])+ref_ind[1][1]*lamf/(lamf-ref_ind[1][4]*ref_ind[1][4])+ref_ind[1][2]*lamf/(lamf-ref_ind[1][5]*ref_ind[1][5])+1.0);
660
661 /* Calculate ref ind at temperature below using Sellmeier equation */
662 rind_down=sqrt(ref_ind[0][0]*lamf/(lamf-ref_ind[0][3]*ref_ind[0][3])+ref_ind[0][1]*lamf/(lamf-ref_ind[0][4]*ref_ind[0][4])+ref_ind[0][2]*lamf/(lamf-ref_ind[0][5]*ref_ind[0][5])+1.0);
663
664 /* Linear interpolation to get ref ind at actual temperature */
665 p_xs_3->rind3=rind_down+((p_xs_3->t_ir_p3-ref_ind[0][6])/(ref_ind[1][6]-ref_ind[0][6]))*(rind_up-rind_down);
666
667 /* Refract */
668 xsh_refract(vres,p_xs_3->rind3,vres);
669 XSH_TRACE_MSG(vres)
670
671 //printf("qwerty 0c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
672
673 /* Rotate to exit surface */
674 xsh_matrixforvector(vres,p_xs_3->toprism6,vres);
675 XSH_TRACE_MSG(vres)
676
677 //printf("qwerty 1c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
678
679 /* refract */
680 xsh_refract(vres,1.0/(p_xs_3->rind3),vres);
681 XSH_TRACE_MSG(vres)
682
683
684 //printf("qwerty 2c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
685
686 /* Rotate back into referential */
687 /*NOTE: We follow the ZEMAX prescription and use toprism1 here instead of prism_out */
688 xsh_matrixforvector(vres,p_xs_3->toprism5,vres);
689 XSH_TRACE_MSG(vres)
690
691
692 //printf("qwerty 3c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
693 }
694
695/* p_xs_3->grat_alpha=xsh_physmod_grating(vres, */
696/* morder, */
697/* p_xs_3->sg, */
698/* p_xs_3->tograt, */
699/* p_xs_3->grat_out, */
700/* vres); */
701
702 /* Rotate into grating */
703 xsh_matrixforvector(vres,p_xs_3->tograt,vres);
704 XSH_TRACE_MSG(vres)
705
706
707 p_xs_3->grat_alpha=atan(vres[1]/vres[3]);
708 //printf("qwerty 4 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
709
710 /* Difraction */
711 xsh_matrixforvector(vres,mech,vres);
712 XSH_TRACE_MSG(vres)
713
714
715 //printf("qwerty 5 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
716
717 xsh_normz(vres);
718 XSH_TRACE_MSG(vres)
719
720
721 p_xs_3->grat_beta=atan(vres[1]/vres[3]);
722 //printf("qwerty 6 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
723
724 /*Rotate out of grating*/
725 xsh_matrixforvector(vres,p_xs_3->grat_out,vres);
726 XSH_TRACE_MSG(vres)
727
728
729 //printf("qwerty 7 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
730
731 if (p_xs_3->arm==2) {
732 /* Rotate back into Prism 3*/
733 xsh_matrixforvector(vres,p_xs_3->ret_prism6,vres);
734 XSH_TRACE_MSG(vres)
735
736
737 //printf("qwerty 8c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
738
739 /* refract */
740 xsh_refract(vres,p_xs_3->rind3,vres);
741 XSH_TRACE_MSG(vres)
742
743
744 //printf("qwerty 9c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
745
746 /* Rotate to exit surface */
747 xsh_matrixforvector(vres,p_xs_3->ret_prism5,vres);
748 XSH_TRACE_MSG(vres)
749
750
751 //printf("qwerty 10c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
752
753 /* Refract */
754 xsh_refract(vres,1.0/(p_xs_3->rind3),vres);
755 XSH_TRACE_MSG(vres)
756
757 //printf("qwerty 11c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
758
759 /* Rotate back into referential */
760 xsh_matrixforvector(vres,p_xs_3->ret_prism6,vres);
761 XSH_TRACE_MSG(vres)
762
763 //printf("qwerty 12c %lf %lf %lf \n", vres[1], vres[2], vres[3]);
764
765
766 /* Rotate back into Prism 2*/
767 xsh_matrixforvector(vres,p_xs_3->ret_prism4,vres);
768 XSH_TRACE_MSG(vres)
769
770 //printf("qwerty 8b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
771
772 /* refract */
773 xsh_refract(vres,p_xs_3->rind2,vres);
774 XSH_TRACE_MSG(vres)
775
776 //printf("qwerty 9b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
777
778 /* Rotate to exit surface */
779 xsh_matrixforvector(vres,p_xs_3->ret_prism3,vres);
780 XSH_TRACE_MSG(vres)
781
782 //printf("qwerty 10b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
783
784 /* Refract */
785 xsh_refract(vres,1.0/(p_xs_3->rind2),vres);
786 XSH_TRACE_MSG(vres)
787
788 //printf("qwerty 11b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
789
790 /* Rotate back into referential */
791 xsh_matrixforvector(vres,p_xs_3->ret_prism4,vres);
792 XSH_TRACE_MSG(vres)
793
794 //printf("qwerty 12b %lf %lf %lf \n", vres[1], vres[2], vres[3]);
795 }
796
797 /* Rotate back into Prism 1*/
798 xsh_matrixforvector(vres,p_xs_3->ret_prism2,vres);
799 XSH_TRACE_MSG(vres)
800
801 //printf("qwerty 8 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
802
803 /* refract */
804 xsh_refract(vres,p_xs_3->rind,vres);
805 XSH_TRACE_MSG(vres)
806
807 //printf("qwerty 9 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
808
809 /* Rotate to exit surface */
810 xsh_matrixforvector(vres,p_xs_3->ret_prism1,vres);
811 XSH_TRACE_MSG(vres)
812
813 //printf("qwerty 10 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
814
815 /* Refract */
816 xsh_refract(vres,1.0/(p_xs_3->rind),vres);
817 XSH_TRACE_MSG(vres)
818
819 //printf("qwerty 11 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
820
821 /* Rotate back into referential */
822 xsh_matrixforvector(vres,p_xs_3->ret_prism2,vres);
823 XSH_TRACE_MSG(vres)
824
825 //printf("qwerty 12 %lf %lf %lf \n", vres[1], vres[2], vres[3]);
826 if (p_xs_3->arm==2) xsh_matrixforvector(vres,p_xs_3->mup_ir_cor_out,vres);
827 XSH_TRACE_MSG(vres)
828
829
830#ifdef FCCDD_FLAG
831 xsh_matrixforvector(vres,p_xs_3->todetector,vres);
832 XSH_TRACE_MSG(vres)
833
834#endif
835
836 /* Projection onto the detector (to begin with just a
837 mm pixel grid, later we'll deal with individual chips) */
838 xx=(p_xs_3->flipx)*(p_xs_3->fdet)/((vres[3]/vres[1])*cos(p_xs_3->nud)-sin(p_xs_3->nud));
839 yy=(p_xs_3->flipy)*(p_xs_3->fdet)/((vres[3]/vres[2])*cos(p_xs_3->mud)-sin(p_xs_3->mud));
840
841
842
843
844#ifdef CCCDD_FLAG
845 /*Alternative projection onto a curved detector of radius fdet*/
846 xx=(p_xs_3->flipx)*(p_xs_3->fdet)*vres[1];
847 yy=(p_xs_3->flipy)*(p_xs_3->fdet)*vres[2];
848#endif
849
850#ifdef XCCCDD_FLAG
851 /*Alternative projection onto a curved detector of radius fdet*/
852 xx=(p_xs_3->flipx)*(p_xs_3->fdet)*2.0*vres[1];
853 yy=(p_xs_3->flipy)*(p_xs_3->fdet)*2.0*vres[2];
854#endif
855
856
857 detproj[0]=0.0;
858 detproj[1]=xx*cos(-p_xs_3->taud)+yy*sin(-p_xs_3->taud);
859 detproj[2]=-xx*sin(-p_xs_3->taud)+yy*cos(-p_xs_3->taud);
860 detproj[3]=0.0;
861 xsh_copyvector(vres,detproj);
862 XSH_TRACE_MSG(vres)
863
864
865 p_xs_3->morder=(float)(morder);
866
867 p_xs_3->xdet=vres[1];
868 p_xs_3->ydet=vres[2];
869}
870
871
872/*----------------------------------------------------------------------------*/
878/*----------------------------------------------------------------------------*/
879
880void xsh_3_detpix(struct xs_3 *p_xs_3)
881{
882
883 double xdet2, ydet2;
884
885 double xdet_c, xdet_c2, xdet_c3, ydet_c, ydet_c2, ydet_c3;
886 double d2_y1=0.0;
887 double d2_y2=0.0;
888 double d2_y3=0.0;
889 double pc_x, pc_y, dstn_x, dstn_y;
890 double xdet_c4, ydet_c4;
891 //double h_det;
892 int array_size_fix=0;
893
894 //double mm_c3,mm_c,mm_c2;
895
896 /* Find if on chip */
897 p_xs_3->xpospix=0.0;
898 p_xs_3->ypospix=0.0;
899 p_xs_3->chippix[0]=-1;
900 p_xs_3->chippix[1]=0;
901 p_xs_3->chippix[2]=0;
902
903#ifndef FCCDD_FLAG
904 //mm_c=p_xs_3->morder-(float)(p_xs_3->morder_min+((p_xs_3->morder_max-p_xs_3->morder_min)/2));
905 //mm_c2=mm_c*mm_c;
906 //mm_c3=mm_c*mm_c2;
907 ydet2=p_xs_3->ydet*p_xs_3->ydet;
908 double ydet3=ydet2*p_xs_3->ydet;
909 xdet2=p_xs_3->xdet*p_xs_3->xdet;
910 double xdet3=xdet2*p_xs_3->xdet;
911 xdet_c=p_xs_3->xdet-p_xs_3->chipx;
912 //xdet_c=p_xs_3->xdet-p_xs_3->d2_x1;
913 xdet_c2=xdet_c*xdet_c;
914 xdet_c3=xdet_c2*xdet_c;
915 xdet_c4=xdet_c3*xdet_c;
916 ydet_c=p_xs_3->ydet-p_xs_3->chipy;
917 //ydet_c=p_xs_3->ydet-p_xs_3->d2_x2;
918 ydet_c2=ydet_c*ydet_c;
919 ydet_c3=ydet_c2*ydet_c;
920 ydet_c4=ydet_c3*ydet_c;
921
922 /**********PIN CUSHION DISTORTION************/
923 pc_x=p_xs_3->chipx+
924 (p_xs_3->pc_x_xx*xdet_c2)+
925 (p_xs_3->pc_x_x1*xdet_c)+
926 (p_xs_3->pc_x_yy*ydet_c2)+
927 (p_xs_3->pc_x_y1*ydet_c)+
928 (p_xs_3->pc_x_xy*xdet_c*ydet_c)+
929 (p_xs_3->pc_x_x3*xdet_c3)+
930 (p_xs_3->pc_x_x2y*xdet_c2*ydet_c)+
931 (p_xs_3->pc_x_y2x*xdet_c*ydet_c2)+
932 (p_xs_3->pc_x_y3*ydet_c3)+
933 (p_xs_3->pc4_x_xy3*xdet_c*ydet_c3)+
934 (p_xs_3->pc4_x_x3y*xdet_c3*ydet_c)+
935 (p_xs_3->pc4_x_x2y2*xdet_c2*ydet_c2)+
936 (p_xs_3->pc4_x_x4*xdet_c4)+
937 (p_xs_3->pc4_x_y4*ydet_c4);
938 pc_y=p_xs_3->chipy+
939 (p_xs_3->pc_y_xx*xdet_c2)+
940 (p_xs_3->pc_y_x1*xdet_c)+
941 (p_xs_3->pc_y_yy*ydet_c2)+
942 (p_xs_3->pc_y_y1*ydet_c)+
943 (p_xs_3->pc_y_xy*xdet_c*ydet_c)+
944 (p_xs_3->pc_y_x3*xdet_c3)+
945 (p_xs_3->pc_y_x2y*xdet_c2*ydet_c)+
946 (p_xs_3->pc_y_y2x*xdet_c*ydet_c2)+
947 (p_xs_3->pc_y_y3*ydet_c3)+
948 (p_xs_3->pc4_y_xy3*xdet_c*ydet_c3)+
949 (p_xs_3->pc4_y_x3y*xdet_c3*ydet_c)+
950 (p_xs_3->pc4_y_x2y2*xdet_c2*ydet_c2)+
951 (p_xs_3->pc4_y_x4*xdet_c4)+
952 (p_xs_3->pc4_y_y4*ydet_c4);
953 /*note: pc4 coeffs will be zero for UVB/VIS and old format NIR configs*/
954
955/* else { */
956/* pc_x=(p_xs_3->pc_x_xx*xdet2)+ */
957/* (p_xs_3->pc_x_x1*p_xs_3->xdet)+ */
958/* (p_xs_3->pc_x_yy*ydet2)+ */
959/* (p_xs_3->pc_x_y1*p_xs_3->ydet)+ */
960/* (p_xs_3->pc_x_xy*p_xs_3->xdet*p_xs_3->ydet)+ */
961/* (p_xs_3->pc_x_x3*xdet3)+ */
962/* (p_xs_3->pc_x_x2y*xdet2*p_xs_3->ydet)+ */
963/* (p_xs_3->pc_x_y2x*p_xs_3->xdet*ydet2)+ */
964/* (p_xs_3->pc_x_y3*ydet3); */
965/* pc_y=(p_xs_3->pc_y_xx*xdet2)+ */
966/* (p_xs_3->pc_y_x1*p_xs_3->xdet)+ */
967/* (p_xs_3->pc_y_yy*ydet2)+ */
968/* (p_xs_3->pc_y_y1*p_xs_3->ydet)+ */
969/* (p_xs_3->pc_y_xy*p_xs_3->xdet*p_xs_3->ydet)+ */
970/* (p_xs_3->pc_y_x3*xdet3)+ */
971/* (p_xs_3->pc_y_x2y*xdet2*p_xs_3->ydet)+ */
972/* (p_xs_3->pc_y_y2x*p_xs_3->xdet*ydet2)+ */
973/* (p_xs_3->pc_y_y3*ydet3); */
974/* } */
975 p_xs_3->xdet=pc_x;
976 p_xs_3->ydet=pc_y;
977
978 /*distortion extra*/
979 if (p_xs_3->arm<2) {
980 dstn_y=(p_xs_3->d2_x3*ydet_c3)+(p_xs_3->d2_x2*ydet_c2)+(p_xs_3->d2_x1*ydet_c);
981 //dstn_y=(p_xs_3->d2_x3*mm_c3)+(p_xs_3->d2_x2*mm_c2)+(p_xs_3->d2_x1*mm_c);
982 p_xs_3->ydet=p_xs_3->ydet+dstn_y;
983/* if (p_xs_3->arm==0) { */
984/* d2_y3=(p_xs_3->d2_y3x3*ydet_c3)+(p_xs_3->d2_y3x2*ydet_c2)+(p_xs_3->d2_y3x1*ydet_c)+p_xs_3->d2_y3x0; */
985/* d2_y2=(p_xs_3->d2_y2x3*ydet_c3)+(p_xs_3->d2_y2x2*ydet_c2)+(p_xs_3->d2_y2x1*ydet_c)+p_xs_3->d2_y2x0; */
986/* d2_y1=(p_xs_3->d2_y1x3*ydet_c3)+(p_xs_3->d2_y1x2*ydet_c2)+(p_xs_3->d2_y1x1*ydet_c)+p_xs_3->d2_y1x0; */
987/* dstn_y=(d2_y3*ydet_c3)+(d2_y2*ydet_c2)+(d2_y1*ydet_c); */
988/* p_xs_3->ydet=p_xs_3->ydet+dstn_y; */
989/* } */
990 }
991 else if (p_xs_3->arm==2) {
992 /*Check what sort of coeffs (old or new) are present in the input config,
993 this can be inferred from the d2_ values. Since the old configs were
994 usually used with fixed (i.e. not annealed) non-zero d2_ coeffs, it is
995 sufficient to check one of these.*/
996 if (p_xs_3->d2_x3!=0.0) {
997 dstn_x=(p_xs_3->d2_x3*xdet_c3)+(p_xs_3->d2_x2*xdet_c2)+(p_xs_3->d2_x1*xdet_c);
998 //dstn_x=(p_xs_3->d2_x3*mm_c3)+(p_xs_3->d2_x2*mm_c2)+(p_xs_3->d2_x1*mm_c);
999 p_xs_3->xdet=p_xs_3->xdet+dstn_x;
1000 d2_y3=(p_xs_3->d2_y3x3*xdet_c3)+(p_xs_3->d2_y3x2*xdet_c2)+(p_xs_3->d2_y3x1*xdet_c)+p_xs_3->d2_y3x0;
1001 d2_y2=(p_xs_3->d2_y2x3*xdet_c3)+(p_xs_3->d2_y2x2*xdet_c2)+(p_xs_3->d2_y2x1*xdet_c)+p_xs_3->d2_y2x0;
1002 d2_y1=(p_xs_3->d2_y1x3*xdet_c3)+(p_xs_3->d2_y1x2*xdet_c2)+(p_xs_3->d2_y1x1*xdet_c)+p_xs_3->d2_y1x0;
1003
1004/* d2_y3=(p_xs_3->d2_y3x1*p_xs_3->morder)+p_xs_3->d2_y3x0; */
1005/* d2_y2=(p_xs_3->d2_y2x1*p_xs_3->morder)+p_xs_3->d2_y2x0; */
1006/* d2_y1=(p_xs_3->d2_y1x3*p_xs_3->morder)+p_xs_3->d2_y1x0; */
1007 dstn_y=(d2_y3*ydet_c3)+(d2_y2*ydet_c2)+(d2_y1*ydet_c);
1008 p_xs_3->ydet=p_xs_3->ydet+dstn_y;
1009 }
1010 /* If d2_x3 is zero we can assume that the new coeffs are present*/
1011 else {
1012 dstn_y=(p_xs_3->ca_x1*(xdet_c-p_xs_3->ca_x0)+p_xs_3->ca_y1*(ydet_c-p_xs_3->ca_y0))*p_xs_3->es_y_tot;
1013 p_xs_3->ydet=p_xs_3->ydet+dstn_y;
1014 }
1015 }
1016#endif
1017#ifdef CCCDD_FLAG
1018 /*mapping onto deformed spherical (radius fdet) pixel grid*/
1019 h_det=sqrt(p_xs_3->xdet*p_xs_3->xdet+p_xs_3->xdet*p_xs_3->xdet);
1020 //h_det=sqrt(p_xs_3->xdet*p_xs_3->xdet+p_xs_3->ydet*p_xs_3->ydet);
1021 p_xs_3->xdet=(p_xs_3->fdet*p_xs_3->xdet/h_det)*sin(h_det/p_xs_3->fdet);
1022 p_xs_3->ydet=(p_xs_3->fdet*p_xs_3->ydet/h_det)*sin(h_det/p_xs_3->fdet);
1023#endif
1024 // printf("%lf %lf %lf %lf %lf %lf \n",p_xs_3->chipxup,p_xs_3->chipxdown,p_xs_3->chipyup,p_xs_3->chipydown, p_xs_3->xdet,p_xs_3->ydet);
1025/* if (p_xs_3->xdet<p_xs_3->chipxdown) */
1026/* { */
1027/* p_xs_3->chippix[0]=5; */
1028/* } */
1029/* else if (p_xs_3->xdet>p_xs_3->chipxup) */
1030/* { */
1031/* p_xs_3->chippix[0]=6; */
1032/* } */
1033/* else if (p_xs_3->ydet>p_xs_3->chipyup) */
1034/* { */
1035/* p_xs_3->chippix[0]=7; */
1036/* } */
1037/* else if (p_xs_3->ydet<p_xs_3->chipydown) */
1038/* { */
1039/* p_xs_3->chippix[0]=8; */
1040/* } */
1041
1042/* /\*still need to allow for the possibility that xdet or ydet are NaN*\/ */
1043/* else if (p_xs_3->xdet>p_xs_3->chipxdown && p_xs_3->xdet<p_xs_3->chipxup && p_xs_3->ydet<p_xs_3->chipyup && p_xs_3->ydet>p_xs_3->chipydown) { */
1044 p_xs_3->chippix[0]=1;
1045 /* xpospix=0.5,ypospix=0.5 would be the middle of the bottom left pixel */
1046
1047 if(p_xs_3->arm!=2) {
1048 p_xs_3->xpospix=0.5*(p_xs_3->chipxpix+p_xs_3->xsize_corr)-(p_xs_3->ydet-p_xs_3->chipy)/p_xs_3->pix_X;
1049 p_xs_3->ypospix=0.5*(p_xs_3->chipypix+p_xs_3->ysize_corr)-(p_xs_3->xdet-p_xs_3->chipx)/p_xs_3->pix_Y;
1050 }
1051 else {
1052 p_xs_3->xpospix=0.5*(p_xs_3->chipxpix+p_xs_3->xsize_corr)+(p_xs_3->xdet-p_xs_3->chipx)/p_xs_3->pix_X;
1053 p_xs_3->ypospix=0.5*(p_xs_3->chipypix+p_xs_3->ysize_corr)+(p_xs_3->ydet-p_xs_3->chipy)/p_xs_3->pix_Y;
1054 array_size_fix=NIR_FIX; /*correction for wrong xsh_data_instrument default*/
1055 }
1056 //printf("qwerty %lf %lf \n", p_xs_3->xpospix,p_xs_3->ypospix);
1057
1058 if (p_xs_3->pix_X>0.029) { /*binx=2 */
1059 p_xs_3->xpospix=p_xs_3->xpospix+0.25;
1060 }
1061 if (p_xs_3->pix_Y>0.029) { /*binx=2 */
1062 p_xs_3->ypospix=p_xs_3->ypospix+0.25;
1063 }
1064 /*The limits in chipxup...chipydown are not correct away from the axis of the chip. A pixel could fall within these limits but not actually fall on the chip. So: */
1065 if (p_xs_3->xpospix>p_xs_3->chipxpix-1+array_size_fix) {
1066 p_xs_3->xpospix=-1.0;
1067 p_xs_3->ypospix=-1.0;
1068 p_xs_3->chippix[0]=6;//Above (with orders horizontal)
1069 }
1070 if (p_xs_3->xpospix<0) {
1071 p_xs_3->xpospix=-1.0;
1072 p_xs_3->ypospix=-1.0;
1073 p_xs_3->chippix[0]=5;//Below
1074 }
1075 if (p_xs_3->ypospix<0) {
1076 p_xs_3->xpospix=-1.0;
1077 p_xs_3->ypospix=-1.0;
1078 p_xs_3->chippix[0]=8;//Left (i.e. below disp co-ord)
1079 }
1080 if (p_xs_3->ypospix>p_xs_3->chipypix-1) {
1081 p_xs_3->xpospix=-1.0;
1082 p_xs_3->ypospix=-1.0;
1083 p_xs_3->chippix[0]=7;//Right
1084 }
1085
1086 p_xs_3->chippix[1]=(int)(p_xs_3->xpospix-0.5)+1;
1087 p_xs_3->chippix[2]=(int)(p_xs_3->ypospix-0.5)+1;
1088
1089/* /\*use pix size to determine binning*\/ */
1090/* if (p_xs_3->pix_X>0.029) { /\*binx=2*\/ */
1091/* /\*N-0.75<xpospix<N+0.25 => chippix[1]=N*\/ */
1092/* p_xs_3->chippix[1]=(int)(p_xs_3->xpospix-0.25)+1; */
1093/* } */
1094/* else { */
1095/* /\*N-0.5<xpospix<N+0.5 => chippix[1]=N*\/ */
1096/* p_xs_3->chippix[1]=(int)(p_xs_3->xpospix-0.5)+1; */
1097/* } */
1098/* if (p_xs_3->pix_Y>0.029) { /\*biny=2*\/ */
1099/* /\*N-0.75<ypospix<N+0.25 => chippix[2]=N*\/ */
1100/* p_xs_3->chippix[2]=(int)(p_xs_3->ypospix-0.25)+1; */
1101/* } */
1102/* else { */
1103/* /\*N-0.5<ypospix<N+0.5 => chippix[2]=N*\/ */
1104/* p_xs_3->chippix[2]=(int)(p_xs_3->ypospix-0.5)+1; */
1105/* } */
1106
1107/* } */
1108/* else { */
1109/* p_xs_3->chippix[0]=-2; */
1110/* } */
1111 return;
1112}
1113
1114/*----------------------------------------------------------------------------*/
1123/*----------------------------------------------------------------------------*/
1124
1125/* Note that this function is not used !!*/
1126void
1127xsh_ref_ind_read_old(const char* ref_ind_file,
1128 DOUBLE** ref_ind,
1129 DOUBLE temper)
1130{
1131 int ii,jj,flag;
1132 FILE *p_ref_ind_file; /*pointer to input file */
1133 //printf("temper %lf \n",temper);
1134 /*open refractive index data file */
1135 p_ref_ind_file=fopen(ref_ind_file,"r");
1136 if(p_ref_ind_file==NULL) {
1137 printf("couldn't find ref_ind file\n");
1138 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
1139 return;
1140 }
1141 ii=2; /*start filling from row [2][*] */
1142 flag=0;
1143 while (fscanf(p_ref_ind_file,"%64lf %64lf %64lf %64lf %64lf %64lf %64lf\n",
1144 &ref_ind[ii][6],&ref_ind[ii][0],&ref_ind[ii][1],&ref_ind[ii][2],
1145 &ref_ind[ii][3],&ref_ind[ii][4],&ref_ind[ii][5]) !=EOF)
1146 /* ref_ind[*][6] holds the temperature of the fit */
1147 {
1148 if (temper>=ref_ind[ii][6])
1149 {
1150 /*fill row [0][*] with the current values, the last time that this will be
1151 overwritten is the last time that temper is below the temperature value read in */
1152 flag=1;
1153 for (jj=0; jj<7; jj++)
1154 {
1155 ref_ind[0][jj]=ref_ind[ii][jj];
1156 }
1157 }
1158 else if (temper<ref_ind[ii][6] && flag==1)
1159 {
1160 /*fill row [1][*] with the current values, this will only be written once */
1161 flag=2;
1162 for (jj=0; jj<7; jj++)
1163 {
1164 ref_ind[1][jj]=ref_ind[ii][jj];
1165 }
1166 }
1167 ii++;
1168 }
1169 /*if the conditions are never met so that flag=2 then the temperature is out of range */
1170 if (flag!=2) printf("******* Temperature out of range! ******* %lf \n", temper);
1171 fclose(p_ref_ind_file);
1172 return;
1173}
1174
1175/*----------------------------------------------------------------------------*/
1182/*----------------------------------------------------------------------------*/
1183
1184void xsh_ref_ind_read(int arm, DOUBLE** ref_ind_T,DOUBLE temper)
1185{
1186 int ii,jj,flag;
1187
1188 //printf("temper %lf \n",temper);
1189
1190 ii=2; /*start filling from row [2][*] */
1191 flag=0;
1192 for (ii=2; ii<8; ii+=1) {
1193 for (jj=0;jj<7;jj+=1){
1194 if (arm==0) {
1195 ref_ind_T[ii][jj]=silica_zemax[ii-2][jj];
1196 }
1197 else if (arm==1) {
1198 ref_ind_T[ii][jj]=schott_sf6_manu[ii-2][jj];
1199 }
1200 else {
1201 ref_ind_T[ii][jj]=znse[ii-2][jj];
1202 }
1203 }
1204 /* ref_ind[*][6] holds the temperature of the fit */
1205 if (temper>=ref_ind_T[ii][6])
1206 {
1207 /*fill row [0][*] with the current values, the last time that this will be
1208 overwritten is the last time that temper is below the temperature value read in */
1209 flag=1;
1210 for (jj=0; jj<7; jj++) {
1211 ref_ind_T[0][jj]=ref_ind_T[ii][jj];
1212 }
1213 }
1214 else if (temper<ref_ind_T[ii][6] && flag==1)
1215 {
1216 /*fill row [1][*] with the current values, this will only be written once */
1217 flag=2;
1218 for (jj=0; jj<7; jj++) {
1219 ref_ind_T[1][jj]=ref_ind_T[ii][jj];
1220 }
1221 }
1222 }
1223 /*if the conditions are never met so that flag=2 then the temperature is out of range */
1224 if (flag!=2) {
1225 printf("******* Temperature out of range! ******* %lf \n", temper);
1226 for (jj=0; jj<7; jj++) {
1227 ref_ind_T[1][jj]=ref_ind_T[7][jj];
1228 }
1229 }
1230 return;
1231}
1232
1233#define ERROR 1
1234#define OK 0
1241{
1242 int* array;
1243 /* get memory for the 1D array */
1244 if ((array=(int *)cpl_malloc(asize*sizeof(int))) == NULL)
1245 {
1246 printf("ERROR allocation memory for array1D int\n");
1247 return NULL;
1248 }
1249 return array;
1250}
1257{
1258 DOUBLE* array;
1259 /* get memory for the 1D array */
1260 if ((array=(DOUBLE *)cpl_malloc(asize*sizeof(DOUBLE))) == NULL)
1261 {
1262 printf("ERROR allocation memory for array1D double\n");
1263 return NULL;
1264 }
1265 return array;
1266}
1267
1274double** xsh_alloc2Darray(int asize, int bsize)
1275{
1276 int ii;
1277 double** ccdtemp;
1278 /* get memory for all the 2D arrays */
1279 if ((ccdtemp=(double **)cpl_malloc(asize*sizeof(double *))) == NULL)
1280 {
1281 printf("ERROR allocating memory for ccdtemp at the initial pointer\n");
1282 return NULL;
1283 }
1284
1285 for (ii = 0; ii < asize; ii++)
1286 {
1287 if ( (ccdtemp[ii]=(double *)cpl_malloc(bsize*sizeof(double))) == NULL)
1288 {
1289 printf("ERROR allocating doublle memory for ccdtemp at row=%d\n",ii);
1290 return NULL;
1291 }
1292 }
1293 return ccdtemp;
1294}
1295
1302float** xsh_alloc2Darray_f(int asize, int bsize)
1303{
1304 int ii;
1305 float **ccdtemp;
1306 /* get memory for all the 2D arrays */
1307 if ((ccdtemp=(float **)cpl_malloc(asize*sizeof(float *))) == NULL)
1308 {
1309 printf("ERROR allocating memory for ccdtemp at the initial pointer\n");
1310 return NULL;
1311 }
1312
1313 for (ii = 0; ii < asize; ii++)
1314 {
1315 if ( (ccdtemp[ii]=(float *)cpl_malloc(bsize*sizeof(float))) == NULL)
1316 {
1317 printf("ERROR allocating float memory for ccdtemp at row=%d\n",ii);
1318 return NULL;
1319 }
1320 }
1321 return ccdtemp;
1322}
1323
1331int** xsh_alloc2Darray_i(int asize, int bsize)
1332{
1333 int ii;
1334 int **ccdtemp;
1335 /* get memory for all the 2D arrays */
1336 if ((ccdtemp=(int **)cpl_malloc(asize*sizeof(int *))) == NULL)
1337 {
1338 printf("ERROR allocating memory for ccdtemp at the initial pointer\n");
1339 return NULL;
1340 }
1341
1342 for (ii = 0; ii < asize; ii++)
1343 {
1344 if ( (ccdtemp[ii]=(int *)cpl_malloc(bsize*sizeof(int))) == NULL)
1345 {
1346 printf("ERROR allocating int memory for ccdtemp at row=%d\n",ii);
1347 return NULL;
1348 }
1349 }
1350 return ccdtemp;
1351}
1352
1360int xsh_free2Darray(double ** ccdtemp, int asize)
1361{
1362 int i;
1363 const int my_asize=asize;
1364 for (i=my_asize-1; i >=0; i--)
1365 {
1366 if (ccdtemp[i] !=NULL) cpl_free(ccdtemp[i]);
1367 else
1368 {
1369 printf("Error freeing memory at row= %d\n", i);
1370 return 1;
1371 }
1372 }
1373 if( ccdtemp !=NULL) cpl_free(ccdtemp);
1374 else
1375 {
1376 printf("Error freeing memory at the initial pointer");
1377 return 1;
1378 }
1379 return 0;
1380}
1381
1389int xsh_free2Darray_i(int ** ccdtemp, int asize)
1390{
1391 int i;
1392 for (i=asize-1; i >=0; i--)
1393 {
1394 if (ccdtemp[i] !=NULL) cpl_free(ccdtemp[i]);
1395 else
1396 {
1397 printf("Error freeing memory at row= %d\n", i);
1398 return 1;
1399 }
1400 }
1401 if( ccdtemp !=NULL) cpl_free(ccdtemp);
1402 else
1403 {
1404 printf("Error freeing memory at the initial pointer");
1405 return 1;
1406 }
1407 return 0;
1408}
1409
1417int xsh_free2Darray_f(float ** ccdtemp, int asize)
1418{
1419 int i;
1420 for (i=asize-1; i >=0; i--)
1421 {
1422 if (ccdtemp[i] !=NULL) cpl_free(ccdtemp[i]);
1423 else
1424 {
1425 printf("Error freeing memory at row= %d\n", i);
1426 return 1;
1427 }
1428 }
1429 if( ccdtemp !=NULL) cpl_free(ccdtemp);
1430 else
1431 {
1432 printf("Error freeing memory at the initial pointer");
1433 return 1;
1434 }
1435 return 0;
1436}
1444double * xsh_copy2D_to_1D(double ** ccdtemp,int asize, int bsize)
1445{
1446 int ii;
1447 int jj;
1448 int kk;
1449 double *oneDccdtemp=NULL;
1450 if ( (oneDccdtemp=(double *)cpl_malloc(asize*bsize*sizeof(double))) == NULL)
1451 {
1452 printf("ERROR allocating memory for oneDccdtemp\n");
1453 return NULL;
1454 }
1455 kk=0;
1456 for (ii = 0; ii < asize; ii++)
1457 {
1458 for (jj = 0; jj < bsize; jj++)
1459 {
1460 oneDccdtemp[kk]=ccdtemp[ii][jj];
1461 kk +=1;
1462 }
1463 }
1464 return oneDccdtemp;
1465}
1466
1474double ** xsh_copy1D_to_2D(double * oneDccdtemp, int asize, int bsize)
1475{
1476 int ii;
1477 int jj;
1478 int kk;
1479 double **ccdtemp=NULL;
1480 ccdtemp=xsh_alloc2Darray(asize,bsize);
1481 kk=0;
1482 for (ii = 0; ii < asize; ii++)
1483 {
1484 for (jj = 0; jj < bsize; jj++)
1485 {
1486 ccdtemp[ii][jj]=oneDccdtemp[kk];
1487 kk +=1;
1488 }
1489 }
1490 return ccdtemp;
1491}
1492
1500double *** xsh_alloc3Darray2(int asize, int bsize, int csize)
1501{
1502 int ii;
1503 double ***ccdtemp;
1504
1505 /* get memory for the 3D array */
1506 if ((ccdtemp=(double ***)cpl_malloc(asize*sizeof(double **))) == NULL)
1507 {
1508 printf("ERROR allocating memory for ccdtemp at the initial pointer\n");
1509 return NULL ;
1510 }
1511 for (ii = 0; ii < asize; ii++) ccdtemp[ii]=xsh_alloc2Darray(bsize,csize);
1512 return ccdtemp;
1513}
1514
1515
1523double *** xsh_alloc3Darray(int asize, int bsize, int csize)
1524{
1525 int ii,jj;
1526 double ***ccdtemp;
1527
1528 /* get memory for all the 3D arrays */
1529 if ((ccdtemp=(double ***)cpl_malloc(asize*sizeof(double **))) == NULL)
1530 {
1531 printf("ERROR allocating memory for ccdtemp at the initial pointer\n");
1532 return NULL ;
1533 }
1534
1535 for (ii = 0; ii < asize; ii++)
1536 {
1537 if ( (ccdtemp[ii]=(double **)cpl_malloc(bsize*sizeof(double*))) == NULL)
1538 {
1539 printf("ERROR allocating memory for ccdtemp at row=%d\n",ii);
1540 return NULL;
1541 }
1542 else
1543 {
1544 for (jj = 0; jj < bsize; jj++)
1545 {
1546 if ( (ccdtemp[ii][jj]=(double *)cpl_malloc(csize*sizeof(double))) == NULL)
1547 {
1548 printf("ERROR allocating memory for ccdtemp at row=%d\n",ii);
1549 return NULL;
1550 }
1551 }
1552 }
1553 }
1554 return ccdtemp;
1555}
1556
1565int xsh_free3Darray(double ***ccdtemp, int asize, int bsize)
1566{
1567 int i;
1568 for (i=asize-1; i >=0; i--)
1569 {
1570 if (ccdtemp[i] !=NULL) xsh_free2Darray(ccdtemp[i],bsize);
1571 else
1572 {
1573 printf("Error freeing memory at slide= %d\n", i);
1574 return ERROR;
1575 }
1576 }
1577 if( ccdtemp !=NULL) cpl_free(ccdtemp);
1578 else
1579 {
1580 printf("Error freeing memory at the 3D initial pointer");
1581 return ERROR;
1582 }
1583 return OK;
1584}
1585
1593{
1594 int i;
1595 for(i=0; i<vectordim; i++) a[i]+=b[i];
1596}
1597
1605{
1606 int i;
1607 for(i=0; i<vectordim-1; i++) a[i]+=b[i+1];
1608}
1609
1618{
1619 int i;
1620 for(i=0; i<vectordim; i++) a[i]-=b[i];
1621}
1622
1630{
1631 int i;
1632 DOUBLE scalar;
1633 scalar=0.0;
1634 for(i=0; i<vectordim; i++) scalar += a[i]*b[i];
1635 return scalar;
1636}
1643{
1644 register int i;
1645 for(i=0; i<vectordim; i++) a[i] *=k;
1646}
1647
1653{
1654 int i;
1655 for(i=0; i<vectordim; i++) printf("%lf ", a[i]*1000.0);
1656 printf(" \n");
1657}
1658
1659
1668{
1669 double x2_sqr = a[2]*a[2];
1670 if (x2_sqr > 1.0) {
1671 a[1]=0.0;
1672 a[2]=1.0;
1673 a[3]=0.0;
1674 return;
1675 }
1676 double x1_sqr = a[1]*a[1];
1677 if (x1_sqr > 1.0) {
1678 a[1]=1.0;
1679 a[2]=0.0;
1680 a[3]=0.0;
1681 return;
1682 }
1683 double sum_sqrs = x1_sqr + x2_sqr;
1684 if (sum_sqrs > 1.0) {
1685 double norm = 1./sqrt (sum_sqrs);
1686 a[1] *=norm;
1687 a[2] *=norm;
1688 a[3]=0.0;
1689 }
1690 else{
1691 if (a[3]>=0) a[3]=sqrt(1.0- sum_sqrs);
1692 else a[3]=-sqrt(1.0-sum_sqrs);
1693 }
1694
1695 return;
1696}
1697
1698
1699
1700
1701
1708{
1709 DOUBLE mag;
1710 mag=1./sqrt(a[1]*a[1]+a[2]*a[2]+a[3]*a[3]);
1711 a[1]=a[1]*mag;
1712 a[2]=a[2]*mag;
1713 a[3]=a[3]*mag;
1714}
1715
1723{
1724 register int i,j,k;
1725 xsh_nullmatrix(A);
1726 for(i=0; i<vectordim; i++) {
1727 for(j=0; j<vectordim; j++) {
1728 for(k=0; k<vectordim; k++){
1729 A[i][j] +=B[i][k]*C[k][j];
1730 }
1731 }
1732 }
1733}
1742{
1743 mat temp;
1744 xsh_nullmatrix(temp);
1745 xsh_multiplymatrix(temp,C,D); /* multiply C*D and store the result in temp */
1746 xsh_multiplymatrix(A,B,temp); /* multiply B*temp=B*C*D and store the result in A */
1747}
1748
1754{
1755 int i;
1756 for(i=0; i<vectordim; i++) {
1757 printf("%lf %lf %lf %lf\n", A[i][0],A[i][1],A[i][2],A[i][3]);
1758 }
1759 printf(" \n");
1760}
1761
1767{
1768 int i,j;
1769 for(i=0; i<vectordim; i++) {
1770 for(j=0; j<vectordim; j++) {
1771 A[i][j]=i+j;
1772 }
1773 }
1774}
1775
1783/*
1784void xsh_matrixforvector(vec a,mat B,vec c)
1785{
1786 register int i,j;
1787 vec temp;
1788 xsh_nullvector(temp);
1789 for(i=0; i<vectordim; i++) {
1790 for(j=0; j<vectordim; j++) {
1791 temp[i] +=B[i][j]*c[j];
1792 }
1793 }
1794 xsh_copyvector(a,temp);
1795}
1796*/
1797
1799{
1800 register int i,j;
1801 vec temp;
1802 xsh_nullvector(temp);
1803 for(j=0; j<vectordim; j++) {
1804 double c_j = c[j];
1805 for(i=0; i<vectordim; i++) {
1806 temp[i] +=B[i][j]*c_j;
1807 }
1808 }
1809 xsh_copyvector(a,temp);
1810}
1811
1818{
1819 register int i,j;
1820 for(i=0; i<vectordim; i++) {
1821 for(j=0; j<vectordim; j++) {
1822 A[i][j]=B[j][i];
1823 }
1824 }
1825}
1826
1833void
1834xsh_rotationmatrix(mat A, const char axis, const DOUBLE angle)
1835{
1836 xsh_nullmatrix(A); /*all element to zero */
1837 double sin_a=sin(angle);
1838 double cos_a=cos(angle);
1839
1840 /*change only the element involved in the x rotation */
1841 switch(axis){
1842
1843 case 'x':{
1844 /* 1 0 0 0 , 0 1 0 0, 0 0 c s , 0 0 -s c (left handed) */
1845 A[0][0]=A[1][1]=1;
1846 A[2][2]=A[3][3]=cos_a;
1847 A[2][3]=sin_a;
1848 A[3][2]= -A[2][3];
1849 break;
1850 }
1851
1852 /*change only the element involved in the y rotation */
1853 case 'y':{
1854 /* 1 0 0 0 , 0 c 0 -s, 0 0 1 0 , 0 s 0 c (left handed) */
1855 A[0][0]=A[2][2]=1;
1856 A[1][1]=A[3][3]=cos_a;
1857 A[1][3]=-sin_a;
1858 A[3][1]=-A[1][3];
1859 break;
1860 }
1861
1862 /*change only the element involved in the z rotation */
1863 case 'z':{
1864 A[0][0]=A[3][3]=1;
1865 A[1][1]=A[2][2]=cos_a;
1866 A[1][2]=sin_a;
1867 A[2][1]=-A[1][2];
1868 break;
1869 }
1870 printf("Error on creating rotation matrix\n");
1871 }
1872
1873}
1874
1882void
1883xsh_rotin(mat A,const DOUBLE x_angle, const DOUBLE y_angle,const DOUBLE z_angle)
1884{
1885 mat temp;
1886 mat X,Y,Z;
1887 xsh_rotationmatrix(X,'x',x_angle);
1888 xsh_rotationmatrix(Y,'y',y_angle);
1889 xsh_rotationmatrix(Z,'z',z_angle);
1890
1891 xsh_multiplymatrix(temp,Y,X); /* multiply Y*X and store the result in temp */
1892 xsh_multiplymatrix(A,Z,temp); /* multiply Z*temp=Z*Y*X and store the result in A */
1893}
1894
1895/*----------------------------------------------------------------------------*/
1907/*----------------------------------------------------------------------------*/
1909 int m,
1910 double sg,
1911 mat in_rot,
1912 mat exit_rot,
1913 vec out) {
1914 vec in2, out2;
1915 double alpha;
1916 //double beta;
1917 mat mech={ {1,0,0,0},
1918 {m*(sg),1,0,0},
1919 {0,0,1,0},
1920 {0,0,0,-1} };
1921
1922 xsh_matrixforvector(in2,in_rot,in);
1923 alpha=atan(in2[1]/in2[3]);
1924 xsh_matrixforvector(out2,mech,in2);
1925 xsh_normz(out2);
1926 //double beta=atan(out2[1]/out2[3]);
1927 // NEED TO PASS BACK beta!!!!
1928 xsh_matrixforvector(out,exit_rot,out2);
1929 return alpha;
1930}
1931
1932
1933/*----------------------------------------------------------------------------*/
1942/*----------------------------------------------------------------------------*/
1943
1944
1945void xsh_refract(vec b, DOUBLE rind, vec a)
1946{
1947 DOUBLE phi, pheta, y_signflag, z_signflag, sin_refrangle;
1948 y_signflag=1.0;
1949 z_signflag=1.0;
1950 phi=atan(sqrt(a[1]*a[1]+a[2]*a[2])/a[3]);
1951 pheta=atan(a[1]/a[2]);
1952 if (a[2]<0.0) y_signflag=-1.0;
1953 if (a[3]<0.0) z_signflag=-1.0;
1954
1955 sin_refrangle = sin(phi)/rind;
1956 b[0]=a[0]; //preserve wavelength
1957 b[1]=z_signflag*y_signflag*sin(pheta)*sin_refrangle;
1958 b[2]=z_signflag*y_signflag*cos(pheta)*sin_refrangle;
1959 b[3]=z_signflag*cos(asin(sin_refrangle));
1960 return;
1961}
1962
1963/*
1964void xsh_refract(vec b, DOUBLE rind, vec a)
1965{
1966 DOUBLE phi, pheta, sin_refrangle;
1967
1968 phi=atan(sqrt(a[1]*a[1]+a[2]*a[2])/a[3]);
1969 pheta=atan(a[1]/a[2]);
1970 sin_refrangle = sin(phi)/rind;
1971
1972 b[0]=a[0]; //preserve wavelength
1973 if (a[2]<0.0) {
1974 if (a[3]<0.0) {
1975 b[1] = sin(pheta)*sin_refrangle;
1976 b[2] = cos(pheta)*sin_refrangle;
1977 b[3] = -1.0*cos(asin(sin_refrangle));
1978 } else {
1979 b[1] = -1.0*sin(pheta)*sin_refrangle;
1980 b[2] = -1.0*cos(pheta)*sin_refrangle;
1981 b[3] = cos(asin(sin_refrangle));
1982 }
1983 } else {
1984 if (a[3]<0.0) {
1985 b[1] = -1.0*sin(pheta)*sin_refrangle;
1986 b[2] = -1.0*cos(pheta)*sin_refrangle;
1987 b[3] = -1.0*cos(asin(sin_refrangle));
1988 } else {
1989 b[1] = sin(pheta)*sin_refrangle;
1990 b[2] = cos(pheta)*sin_refrangle;
1991 b[3] = cos(asin(sin_refrangle));
1992 }
1993 }
1994
1995 return;
1996}
1997
1998*/
1999
2000
2001#define ERROR 1
2002#define OK 0
2003
2004
2005
2006
2007
2008static cpl_error_code
2009xsh_model_compute_slitmap_kw(const double slit_min,
2010 const double slit_max,
2011 xsh_xs_3* p_xs_3,
2012 xsh_instrument* instr,
2013 cpl_propertylist** plist)
2014{
2015
2016 int morder=0;
2017 double med_slit_cen=0;
2018 double med_slit_up=0;
2019 double med_slit_lo=0;
2020 double med_slit_slicup=0;
2021 double med_slit_sliclo=0;
2022
2023
2024 /* compute and write specific slitmap KW */
2025 med_slit_cen = (slit_min+slit_max)/2.0;
2026
2027 med_slit_up = med_slit_cen+p_xs_3->es_s/2.0/p_xs_3->slit_scale;
2028 med_slit_lo = med_slit_cen-p_xs_3->es_s/2.0/p_xs_3->slit_scale;
2029 med_slit_slicup = IFU_HI+med_slit_cen;
2030 med_slit_sliclo = IFU_LOW+med_slit_cen;
2031
2032 check( xsh_pfits_set_slitmap_median_cen( *plist, med_slit_cen));
2033 check( xsh_pfits_set_slitmap_median_edgup( *plist, med_slit_up));
2034 check( xsh_pfits_set_slitmap_median_edglo( *plist, med_slit_lo));
2035
2036 for( morder = p_xs_3->morder_min; morder <= p_xs_3->morder_max; morder++){
2037 check( xsh_pfits_set_slitmap_order_cen( *plist, morder, med_slit_cen));
2038 check( xsh_pfits_set_slitmap_order_edgup( *plist, morder, med_slit_up));
2039 check( xsh_pfits_set_slitmap_order_edglo( *plist, morder, med_slit_lo));
2040 }
2041 if ( xsh_instrument_get_mode( instr) == XSH_MODE_IFU){
2042 check( xsh_pfits_set_slitmap_median_slicup( *plist, med_slit_slicup));
2043 check( xsh_pfits_set_slitmap_median_sliclo( *plist, med_slit_sliclo));
2044 for( morder = p_xs_3->morder_min; morder <= p_xs_3->morder_max; morder++){
2045 check( xsh_pfits_set_slitmap_order_slicup( *plist, morder, med_slit_slicup));
2046 check( xsh_pfits_set_slitmap_order_sliclo( *plist, morder, med_slit_sliclo));
2047 }
2048 }
2049
2050 cleanup:
2051
2052 return cpl_error_get_code();
2053}
2054
2055
2056
2057/*----------------------------------------------------------------------------*/
2070/*----------------------------------------------------------------------------*/
2071cpl_error_code xsh_model_maps_create(xsh_xs_3* p_xs_3, xsh_instrument* instr,
2072 const char * wtag, const char * stag, cpl_frame** wmap_frame,
2073 cpl_frame** smap_frame, const int save_tmp)
2074
2075{
2076 int morder_cnt = 0; /* grating spectral order */
2077 DOUBLE lambda; /*wavelength in mm */
2078 DOUBLE lambda_nm; /* wavelength in nm */
2079 DOUBLE blaze_wav, lam_min, lam_max, lam_inc;
2082 long naxes[2];
2083 int ii, jj, binx, biny;
2084 int slitlet, slitlet_min, slitlet_max;
2085 double es_x_config;
2086 double slit_min, slit_max, slit_inc, slit_x, slit_y;
2087 double* ccd_wav; /*detector wavelengths array */
2088 double* ccd_slit; /*detector wavelengths array */
2089 int* ccd_mask; /*detector mask array */
2090 int* ccd_imap; /*detector ifu map array */
2091 cpl_image* ccd_wave_ima = NULL;
2092 cpl_image* ccd_slit_ima = NULL;
2093 cpl_image* ccd_mask_ima = NULL;
2094 cpl_image* ccd_imap_ima = NULL;
2095
2096 cpl_polynomial * fit_wave_2d = NULL;
2097 cpl_polynomial * fit_slit_2d = NULL;
2098 cpl_matrix * mat_xy_sampling_points = NULL;
2099 cpl_vector * vec_w_sampling_points = NULL;
2100 cpl_vector * vec_s_sampling_points = NULL;
2101
2102 cpl_vector* val = NULL;
2103 double* pval = NULL;
2104
2105 DOUBLE** ref_ind = NULL;
2106 double* oneD_AB = NULL; /* 1D array to take contents of ccd */
2107 cpl_propertylist* plist = NULL;
2108 char filename[256];
2109 int array_size_fix = 0; /*in NIR case, this variable corrects for wrong
2110 xsh_data_instrument default*/
2111 int sx = 0;
2112 int sy = 0;
2113 int i = 0;
2114 int j = 0;
2115 double s_val = 0;
2116 double w_val = 0;
2117 int i_val = 0;
2118 cpl_table* tab_xy = NULL;
2119 int size_x = 0;
2120 int size_y = 0;
2121
2122 XSH_ASSURE_NOT_NULL( p_xs_3);
2123 XSH_ASSURE_NOT_NULL( instr);
2124 XSH_ASSURE_NOT_NULL( wtag);
2125 XSH_ASSURE_NOT_NULL( stag);
2126
2127 /* get instrument setting */
2128 check(arm=xsh_instrument_get_arm(instr));
2131 /* x-disp bin */
2133 /* disp bin */
2134
2135 xsh_msg("Generate physical model based wave and slit maps");
2136
2137 /*For IFU mode needs to iterate over 3 slitlets. We define here relevant varable used later to step
2138 * through the slitlets, define their min/max value, and the incremental step to be applied to
2139 * generate the map*/
2140 if (mode == XSH_MODE_IFU) {
2141 slitlet_min = -1;
2142 slitlet_max = 1;
2143 slit_min = IFU_LOW + 0.000001;
2144 slit_max = IFU_HI - 0.000001;
2145 slit_inc = 0.05 * (slit_max - slit_min) * binx;
2146 } else {
2147 slitlet_min = 0;
2148 slitlet_max = 0;
2149 slit_min = (-0.5*p_xs_3->es_s) / p_xs_3->slit_scale;
2150 slit_max = (0.5*p_xs_3->es_s) / p_xs_3->slit_scale;
2151 slit_inc = 0.02 * (slit_max - slit_min) * binx;
2152 }
2153
2154 /*znse_ref is the array holding Sellmeier coefs for ZnSe refractive index
2155 at each temp. Currently hard coded to take 6 temperatures in [2][*] to
2156 [7][*], can be extended. First two rows ([0][*] to [1][*]) take the entries
2157 for the temperature bracketing the operation.
2158 Column [*][0] takes the temperature, the other columns, [*][1] to [*][6]
2159 take the Sellmeier coeffs */
2160 ref_ind = xsh_alloc2Darray(8, 7);
2161
2162 p_xs_3->arm = arm;
2163
2164 /* here we need to define a constant to take care of the NIR arm special case, and
2165 * we load the refractive index coeffs for a given arm and temperature */
2166 if (arm == XSH_ARM_UVB) {
2167 xsh_ref_ind_read(0, ref_ind, p_xs_3->temper);
2168 array_size_fix = 0;
2169 } else if (arm == XSH_ARM_VIS) {
2170 xsh_ref_ind_read(1, ref_ind, p_xs_3->temper);
2171 array_size_fix = 0;
2172 } else {
2173 xsh_ref_ind_read(2, ref_ind, p_xs_3->t_ir_p2);
2174 array_size_fix = NIR_FIX;
2175 }
2176
2177 /*initalize the model. Inside the echelle_init the cfg file is
2178 read and the variables assigned to the xsh structure
2179 initialisation. Sets up those matrices that are not dependent upon
2180 wavelength */
2181
2182 xsh_3_init(p_xs_3);
2183 es_x_config = p_xs_3->es_x;
2184
2185 size_x = p_xs_3->ASIZE + array_size_fix;
2186 size_y = p_xs_3->BSIZE;
2187
2188 /* initialize array to hold wavelength results */
2189 ccd_wave_ima = cpl_image_new(size_x, size_y, CPL_TYPE_DOUBLE);
2190 ccd_slit_ima = cpl_image_new(size_x, size_y, CPL_TYPE_DOUBLE);
2191 ccd_mask_ima = cpl_image_new(size_x, size_y, CPL_TYPE_INT);
2192 ccd_imap_ima = cpl_image_new(size_x, size_y, CPL_TYPE_INT);
2193
2194 ccd_wav = cpl_image_get_data_double(ccd_wave_ima); /* wave map */
2195 ccd_slit = cpl_image_get_data_double(ccd_slit_ima); /* slit map */
2196 ccd_imap = cpl_image_get_data_int(ccd_imap_ima); /* ifu map */
2197 ccd_mask = cpl_image_get_data_int(ccd_mask_ima); /* mask (useful to speed-up code later)*/
2198
2199 int fit_size = 0;
2200 const cpl_size max_deg_2d_w = 5;
2201 const cpl_size max_deg_2d_s = 5;
2202
2203 double x_ord_min = 9999;
2204 double x_ord_max = -1;
2205 double y_ord_min = 9999;
2206 double y_ord_max = -1;
2207 cpl_error_code error2d;
2208 double x_val = 0;
2209 double y_val = 0;
2210 int x_det = 0;
2211 int y_det = 0;
2212 int x_min = 0;
2213 int y_min = 0;
2214 int fit_index = 0;
2215 int x_max = 0;
2216 int y_max = 0;
2217 int ord = 0;
2218
2219
2220 double two_sin_times_minus_nug=2 * (sin(-p_xs_3->nug));
2221 /* vectors we use inside the loop to get fit values from polynomials */
2222 val = cpl_vector_new(2);
2223 pval = cpl_vector_get_data(val);
2224
2225 /* we loop over orders, wavelength, to create the wave map */
2226 for (morder_cnt = p_xs_3->morder_min; morder_cnt <= p_xs_3->morder_max;
2227 morder_cnt += 1) {
2228 /*
2229 xsh_msg("order=%d",morder_cnt);
2230 */
2231 blaze_wav = two_sin_times_minus_nug / (morder_cnt * p_xs_3->sg);
2232 lam_max = blaze_wav
2233 * ((double) (morder_cnt) / ((double) (morder_cnt) - 0.5));
2234 lam_min = blaze_wav
2235 * ((double) (morder_cnt) / (0.5 + (double) (morder_cnt)));
2236 lam_inc = (lam_max - lam_min) / (0.5 * size_y);
2237
2238 xsh_free_table(&tab_xy);
2239 xsh_free_matrix(&mat_xy_sampling_points);
2240 xsh_free_vector(&vec_w_sampling_points);
2241 xsh_free_vector(&vec_s_sampling_points);
2242
2243 for (slitlet = slitlet_min; slitlet < slitlet_max + 1; slitlet++) {
2244
2245 /* reset values */
2246 /* variable counting how many points we are going to fit */
2247 fit_index = 0;
2248 x_ord_min = 9999;
2249 x_ord_max = -1;
2250 y_ord_min = 9999;
2251 y_ord_max = -1;
2252 /* compute slit centres (IFU case) */
2253 if (slitlet == -1) {
2254 slit_x = 0.5 * (IFU_LEFT_MIN + IFU_LEFT_MAX);
2255 i_val = 1;
2256 } else if (slitlet == 1) {
2257 slit_x = 0.5 * (IFU_RIGHT_MIN + IFU_RIGHT_MAX);
2258 i_val = 3;
2259 } else {
2260 slit_x = 0.5 * (IFU_CEN_MIN + IFU_CEN_MAX);
2261 i_val = 2;
2262 }
2263
2264 for (slit_y = slit_min; slit_y <= slit_max; slit_y += slit_inc) {
2265 /* check we do not go out of IFU slice */
2266 if (mode == XSH_MODE_IFU) {
2267 if (xsh_model_map_ifu(slit_x, slit_y, p_xs_3) != 0) {
2268 cpl_msg_error(__func__, "Outside slitlet array");
2269 return CPL_ERROR_UNSPECIFIED;
2270 }
2271 } else {
2272 /* computes actual slit positions in mm for the model */
2273 p_xs_3->es_y_tot = slit_y * p_xs_3->slit_scale + p_xs_3->es_y;
2274 }
2275
2276 /* loop over dispersion (wavelength) direction (here we make an interpolation) */
2277 for (lambda = lam_min - p_xs_3->blaze_pad;
2278 lambda <= lam_max + p_xs_3->blaze_pad; lambda += lam_inc) {
2279 /* lambda is in mm */
2280 lambda_nm = lambda * mm2nm;
2281 /* computes x,y position at a given lambda,order for a given model configuration */
2282 xsh_3_eval(lambda, morder_cnt, ref_ind, p_xs_3);
2283 /* Takes the physical x,y position at the detector array and converts this to a pixel position */
2284 xsh_3_detpix(p_xs_3);
2285 x_val = p_xs_3->xpospix;
2286 y_val = p_xs_3->ypospix;
2287
2288 /* check we are on the detector */
2289 if (p_xs_3->chippix[0] == 1) {
2290 /* check that we are on the detector after distortion correction */
2291 if (p_xs_3->chippix[1] >= 1 && p_xs_3->chippix[1] < size_x + 1
2292 && p_xs_3->chippix[2] >= 1 && p_xs_3->chippix[2] < size_y + 1) {
2293 /* we fill the grid points */
2294
2295 fit_index += 1;
2296
2297 } /* end check that we are on the detector
2298 after distortion correction */
2299
2300 } /* end check we are on the detector */
2301
2302 } /* end loop over lambda */
2303
2304 } /* end loop over slit */
2305
2306 fit_size = fit_index;
2307
2308 xsh_free_matrix(&mat_xy_sampling_points);
2309 xsh_free_vector(&vec_w_sampling_points);
2310 xsh_free_vector(&vec_s_sampling_points);
2311 xsh_free_table(&tab_xy);
2312
2313 mat_xy_sampling_points = cpl_matrix_new(2, fit_size);
2314 vec_w_sampling_points = cpl_vector_new(fit_size);
2315 vec_s_sampling_points = cpl_vector_new(fit_size);
2316
2317 /* define a table to store sampling grid points:x,y positions, corresponding values of lambda,s,order
2318 * Note that this table is used only for debugging purposes !!
2319 * */
2320 tab_xy = cpl_table_new(fit_size);
2321 cpl_table_new_column(tab_xy, "X", CPL_TYPE_DOUBLE);
2322 cpl_table_new_column(tab_xy, "Y", CPL_TYPE_DOUBLE);
2323 cpl_table_new_column(tab_xy, "W", CPL_TYPE_DOUBLE);
2324 cpl_table_new_column(tab_xy, "S", CPL_TYPE_DOUBLE);
2325 cpl_table_new_column(tab_xy, "ord", CPL_TYPE_INT);
2326
2327 cpl_table_fill_column_window_int(tab_xy, "ord", 0, fit_size, 0);
2328 cpl_table_fill_column_window_double(tab_xy, "X", 0, fit_size, 0);
2329 cpl_table_fill_column_window_double(tab_xy, "Y", 0, fit_size, 0);
2330 cpl_table_fill_column_window_double(tab_xy, "W", 0, fit_size, 0);
2331 cpl_table_fill_column_window_double(tab_xy, "S", 0, fit_size, 0);
2332
2333 ord += 1;
2334
2335 double* pxy = NULL;
2336 double* pw = NULL;
2337 double* ps = NULL;
2338 int* pto = NULL;
2339 double* ptx = NULL;
2340 double* pty = NULL;
2341 double* pts = NULL;
2342 double* ptw = NULL;
2343
2344 pxy = cpl_matrix_get_data(mat_xy_sampling_points);
2345 pw = cpl_vector_get_data(vec_w_sampling_points);
2346 ps = cpl_vector_get_data(vec_s_sampling_points);
2347
2348 ptx = cpl_table_get_data_double(tab_xy, "X");
2349 pty = cpl_table_get_data_double(tab_xy, "Y");
2350 pts = cpl_table_get_data_double(tab_xy, "S");
2351 ptw = cpl_table_get_data_double(tab_xy, "W");
2352 pto = cpl_table_get_data_int(tab_xy, "ord");
2353 int fit_index = 0;
2354
2355 /* reset values */
2356 x_ord_min = 9999;
2357 x_ord_max = -1;
2358 y_ord_min = 9999;
2359 y_ord_max = -1;
2360
2361 /* compute slit centres (IFU case) */
2362 for (slit_y = slit_min; slit_y <= slit_max; slit_y += slit_inc) {
2363 /* check we do not go out of IFU slice */
2364 if (mode == XSH_MODE_IFU) {
2365 if (xsh_model_map_ifu(slit_x, slit_y, p_xs_3) != 0) {
2366 cpl_msg_error(__func__, "Outside slitlet array");
2367 return CPL_ERROR_UNSPECIFIED;
2368 }
2369 } else {
2370 /* computes actual slit positions in mm for the model */
2371 p_xs_3->es_y_tot = slit_y * p_xs_3->slit_scale + p_xs_3->es_y;
2372 }
2373
2374 /* loop over dispersion (wavelength) direction (here we make an interpolation) */
2375 for (lambda = lam_min - p_xs_3->blaze_pad;
2376 lambda <= lam_max + p_xs_3->blaze_pad; lambda += lam_inc) {
2377 /* lambda is in mm */
2378 lambda_nm = lambda * mm2nm;
2379 /* computes x,y position at a given lambda,order for a given model configuration */
2380 xsh_3_eval(lambda, morder_cnt, ref_ind, p_xs_3);
2381 /* Takes the physical x,y position at the detector array and converts this to a pixel position */
2382 xsh_3_detpix(p_xs_3);
2383
2384 x_val = p_xs_3->xpospix;
2385 y_val = p_xs_3->ypospix;
2386
2387 /* check we are on the detector */
2388 if (p_xs_3->chippix[0] == 1) {
2389 /* check that we are on the detector after distortion correction */
2390 if (p_xs_3->chippix[1] >= 1 && p_xs_3->chippix[1] < size_x + 1 &&
2391 p_xs_3->chippix[2] >= 1 && p_xs_3->chippix[2] < size_y + 1) {
2392
2393 /* we fill the grid points: lambda, slit, x, y in corresponding table columns,
2394 * and vector/matrix positions
2395 * */
2396 pw[fit_index] = lambda_nm;
2397 ps[fit_index] = slit_y;
2398 check(cpl_matrix_set(mat_xy_sampling_points,0,fit_index,x_val));
2399 check(cpl_matrix_set(mat_xy_sampling_points,1,fit_index,y_val));
2400 pto[fit_index] = morder_cnt;
2401 ptx[fit_index] = x_val;
2402 pty[fit_index] = y_val;
2403 pts[fit_index] = slit_y;
2404 ptw[fit_index] = lambda_nm;
2405
2406 /* determine min/max of x and y values at the given order:
2407 * these values are used to fill a mask with 1/0 values where the
2408 * order is illuminated or not. Later we compute lambda
2409 */
2410 x_ord_min = (x_ord_min < x_val) ? x_ord_min : x_val;
2411 x_ord_max = (x_ord_max > x_val) ? x_ord_max : x_val;
2412
2413 y_ord_min = (y_ord_min < y_val) ? y_ord_min : y_val;
2414 y_ord_max = (y_ord_max > y_val) ? y_ord_max : y_val;
2415
2416 fit_index += 1;
2417
2418 } /* end check that we are on the detector
2419 after distortion correction */
2420
2421 } /* end check we are on the detector */
2422
2423 } /* end loop over lambda */
2424
2425 } /* end loop over slit */
2426
2427 xsh_free_polynomial(&fit_wave_2d);
2428 xsh_free_polynomial(&fit_slit_2d);
2429 fit_wave_2d = cpl_polynomial_new(2);
2430 fit_slit_2d = cpl_polynomial_new(2);
2431 sprintf(filename, "tab_xy_%2.2d.fits", morder_cnt);
2432 //check(cpl_table_save(tab_xy,NULL,NULL,filename,CPL_IO_DEFAULT));
2433
2435 "SIZES vec=%" CPL_SIZE_FORMAT " ncol=%" CPL_SIZE_FORMAT " nrow=%" CPL_SIZE_FORMAT " pol size=%" CPL_SIZE_FORMAT "", cpl_vector_get_size(vec_w_sampling_points), cpl_matrix_get_ncol(mat_xy_sampling_points), cpl_matrix_get_nrow(mat_xy_sampling_points), cpl_polynomial_get_dimension(fit_wave_2d));
2436 /* Here we have to use a polynomial solution to pass from x,y to lambda,s
2437 *
2438 * The physical model works in one direction: we input a photon of a given
2439 * lambda and then we compute where it lands on the detector. This means we
2440 * make the direct transformation:
2441 *
2442 * x=phys(w,s,m,cfg)
2443 * y=phys(w,s,m,cfg)
2444 *
2445 * To compute a wave and a slit map instead we need the inverse transformation. In this case it is simpler
2446 * and sufficiently accurate to fit a 2D polynomial to a grid of sufficiently dense
2447 * x(w,s,m,cfg) and y(w,s,m,cfg) points sampling points and then use the solution to invert the
2448 * transformation and determine at each x,y detector points the corresponding lambda,s
2449 */
2450 /* Performs a polynomial fit to the grid of x,y points each with value lambda: ==>
2451 * determines a wave solution */
2452 check(
2453 error2d=cpl_polynomial_fit(fit_wave_2d,mat_xy_sampling_points, NULL,vec_w_sampling_points, NULL, CPL_FALSE,NULL, &max_deg_2d_w));
2454 /* Performs a polynomial fit to the grid of x,y points each with value lambda: ==>
2455 * determines a slit solution */
2456 check(
2457 error2d=cpl_polynomial_fit(fit_slit_2d,mat_xy_sampling_points, NULL,vec_s_sampling_points, NULL, CPL_FALSE,NULL, &max_deg_2d_s));
2458
2459 sx = (int) (x_ord_max - x_ord_min + 0.5);
2460 sy = size_y; //(int)(y_ord_max-y_ord_min+0.5);
2461
2462 x_min = (int) (x_ord_min + 0.5);
2463 y_min = (int) (y_ord_min + 0.5);
2464 x_max = (int) (x_ord_max + 0.5);
2465 y_max = (int) (y_ord_max + 0.5);
2466
2467 /* initializes the mask to 0, then fill up by 1 only the region covered by the current order */
2468 memset(ccd_mask,0,sizeof(int)*size_x*size_y);
2469 int jj_times_size_x=0;
2470 for (jj = y_min; jj <= y_max; jj++) {
2471 jj_times_size_x=jj * size_x;
2472 for (ii = x_min; ii <= x_max; ii++) {
2473 ccd_mask[jj_times_size_x + ii] = 1;
2474 }
2475 }
2476
2477 /* then finally fill up the given order by the lambda,s values
2478 * computed via the 2D polynomial solutions */
2479 x_det = x_min;
2480 y_det = 0;
2481 int y_det_times_size_x=0;
2482 for (j = 0; j < sy; j++) {
2483
2484 /* TO BE CHECKED IF OFF BY 1 PIX */
2485 /* (if start from 0, j + 1) y position for poly evaluation */
2486 pval[1] = y_det + 1;
2487 x_det = x_min;
2488
2489 y_det_times_size_x=y_det*size_x;
2490 for (i = 0; i < sx; i++) {
2491 /* (if start from 0, i + 1) y position for poly evaluation */
2492 pval[0] = x_det + 1;
2493
2494
2495 int pix_pos=y_det_times_size_x + x_det;
2496 if (ccd_mask[pix_pos] == 1) {
2497 s_val = cpl_polynomial_eval(fit_slit_2d, val);
2498 if (s_val > slit_min) {
2499 if (s_val < slit_max) {
2500
2501 w_val = cpl_polynomial_eval(fit_wave_2d, val);
2502
2503 ccd_wav[pix_pos] = w_val;
2504 ccd_slit[pix_pos] = s_val;
2505 ccd_imap[pix_pos] = i_val;
2506
2507 }
2508 }
2509 } /* end of check over mask */
2510 x_det += 1;
2511 } /* end loop over s */
2512 y_det += 1;
2513 } /* here we have completed to fill up the given order with lambda,s values */
2514
2515
2516 } /* end loop over IFU slices */
2517
2518 } /* end loop over order */
2519
2520 if ((xsh_free2Darray(ref_ind, 8)) != 0) {
2521 cpl_msg_error(__func__, "Cannot free 2D array ref_ind");
2522 return CPL_ERROR_UNSPECIFIED;
2523 }
2524
2525 naxes[0] = size_x;
2526 naxes[1] = size_y;
2527
2528 /* wave map saving */
2529 check(plist=cpl_propertylist_new());
2530 sprintf(filename, "%s.fits", wtag);
2531 check(xsh_pfits_set_pcatg(plist, wtag ) );
2532 double crpix1=1.;
2533 double crval1=1.;
2534 double cdelt1=binx;
2535 double crpix2=1.;
2536 double crval2=1.;
2537 double cdelt2=biny;
2538 check(xsh_pfits_set_wcs(plist, crpix1,crval1,cdelt1,crpix2,crval2,cdelt2 ) );
2539 check(
2540 cpl_image_save(ccd_wave_ima,filename,CPL_BPP_IEEE_FLOAT,plist,CPL_IO_DEFAULT));
2541 xsh_free_propertylist(&plist);
2542
2543 if (save_tmp) {
2544 xsh_add_temporary_file(filename);
2545 }
2546 *wmap_frame = xsh_frame_product(filename, wtag, CPL_FRAME_TYPE_IMAGE,
2547 CPL_FRAME_GROUP_PRODUCT, CPL_FRAME_LEVEL_FINAL);
2548
2549 xsh_msg(
2550 " wave map frame %s %s", cpl_frame_get_filename(*wmap_frame), cpl_frame_get_tag(*wmap_frame));
2551
2552 naxes[0] = size_x;
2553 naxes[1] = size_y;
2554
2555 /*memory allocation for 1D representation of CCD array for cfitsio*/
2556 check(plist=cpl_propertylist_new());
2557 sprintf(filename, "%s.fits", stag);
2558 check(xsh_pfits_set_pcatg(plist, stag ) );
2559
2560 xsh_model_compute_slitmap_kw(slit_min, slit_max, p_xs_3, instr, &plist);
2561 check(xsh_pfits_set_wcs(plist, crpix1,crval1,cdelt1,crpix2,crval2,cdelt2 ) );
2562 check(
2563 cpl_image_save(ccd_slit_ima,filename,CPL_BPP_IEEE_FLOAT,plist,CPL_IO_DEFAULT));
2564
2565 if (mode == XSH_MODE_IFU) {
2566 check(
2567 cpl_image_save(ccd_imap_ima,filename,CPL_BPP_32_SIGNED,NULL,CPL_IO_EXTEND));
2568 }
2569 xsh_free_propertylist(&plist);
2570
2571 if (save_tmp) {
2572 xsh_add_temporary_file(filename);
2573 }
2574 *smap_frame = xsh_frame_product(filename, stag, CPL_FRAME_TYPE_IMAGE,
2575 CPL_FRAME_GROUP_PRODUCT, CPL_FRAME_LEVEL_FINAL);
2576 xsh_msg(
2577 " slit map frame %s %s", cpl_frame_get_filename(*smap_frame), cpl_frame_get_tag(*smap_frame));
2578
2579 cpl_free(oneD_AB);
2580
2581 //If this is freed here then when ima is returned it is
2582 // corrupted. On the other hand after return there is no way to free oneD_AB
2583 //To me this seems to be a problem with returning cpl_images. I am leaving
2584 //it as it is for the moment (i.e. with a memory leak)
2585 cleanup: xsh_free_matrix(&mat_xy_sampling_points);
2586 xsh_free_vector(&vec_w_sampling_points);
2587 xsh_free_vector(&vec_s_sampling_points);
2588 xsh_free_vector(&val);
2589 xsh_free_polynomial(&fit_wave_2d);
2590 xsh_free_polynomial(&fit_slit_2d);
2591 xsh_free_table(&tab_xy);
2592 xsh_free_image(&ccd_wave_ima);
2593 xsh_free_image(&ccd_slit_ima);
2594 xsh_free_image(&ccd_mask_ima);
2595 xsh_free_image(&ccd_imap_ima);
2596 xsh_free_propertylist(&plist);
2597
2598 return cpl_error_get_code();
2599}
2600
2601/*----------------------------------------------------------------------------*/
2613/*----------------------------------------------------------------------------*/
2614int
2616 double yifu,
2617 xsh_xs_3* p_xs_3)
2618{
2619 double xifu_mm, yifu_mm,es_x_tot;
2620 xifu_mm=xifu*IFU_SCALE;
2621 yifu_mm=yifu*IFU_SCALE;
2622 /*check which slitlet (if any) ray passes through*/
2623 if (xifu>IFU_LEFT_MIN && xifu<IFU_LEFT_MAX && yifu>IFU_LOW && yifu<IFU_HI) {
2624 p_xs_3->es_y_tot=(IFU_MAP_LEFT_C0Y+
2625 IFU_MAP_LEFT_C1Y*yifu_mm+
2626 IFU_MAP_LEFT_C2Y*yifu_mm*yifu_mm);
2627 es_x_tot=(IFU_MAP_LEFT_C0X+
2628 IFU_MAP_LEFT_C1X*xifu_mm+
2629 IFU_MAP_LEFT_C2X*xifu_mm*xifu_mm);
2630 }
2631 else if (xifu>IFU_CEN_MIN && xifu<IFU_CEN_MAX && yifu>IFU_LOW && yifu<IFU_HI) {
2632 p_xs_3->es_y_tot=(IFU_MAP_CEN_C0Y+
2633 IFU_MAP_CEN_C1Y*yifu_mm+
2634 IFU_MAP_CEN_C2Y*yifu_mm*yifu_mm);
2635 es_x_tot=(IFU_MAP_CEN_C0X+
2636 IFU_MAP_CEN_C1X*xifu_mm+
2637 IFU_MAP_CEN_C2X*xifu_mm*xifu_mm);
2638 }
2639 else if (xifu>IFU_RIGHT_MIN && xifu<IFU_RIGHT_MAX && yifu>IFU_LOW && yifu<IFU_HI) {
2640 p_xs_3->es_y_tot=(IFU_MAP_RIGHT_C0Y+
2641 IFU_MAP_RIGHT_C1Y*yifu_mm+
2642 IFU_MAP_RIGHT_C2Y*yifu_mm*yifu_mm);
2643 es_x_tot=(IFU_MAP_RIGHT_C0X+
2644 IFU_MAP_RIGHT_C1X*xifu_mm
2645 +IFU_MAP_RIGHT_C2X*xifu_mm*xifu_mm);
2646 }
2647 else {
2648 p_xs_3->es_x=-999;
2649 p_xs_3->es_y=-999;
2650 return 1;
2651 }
2652 /*Correct back to scale of spectrograph entrance slit*/
2653 p_xs_3->es_y_tot= p_xs_3->es_y+p_xs_3->es_y_tot*p_xs_3->slit_scale/IFU_SCALE;
2654 p_xs_3->es_x = p_xs_3->es_x+es_x_tot*p_xs_3->slit_scale/IFU_SCALE;
2655
2656 return 0;
2657}
2658
2659/*----------------------------------------------------------------------------*/
2672/*----------------------------------------------------------------------------*/
2673cpl_vector**
2674xsh_model_locus(struct xs_3* p_xs_3,
2675 xsh_instrument* instr,
2676 double ent_slit_pos)
2677{
2678 int n_order, morder_cnt; /* grating spectral order*/
2679 DOUBLE lambda; /*wavelength in mm */
2680 DOUBLE lambda_nm; /* wavelength in nm */
2681 DOUBLE blaze_wav, lam_min, lam_max;
2682 DOUBLE pixwavlast, pixylast, pixxlast;
2683 int chipdist_current;
2684 double* trace_lam=NULL; /*trace array */
2685 double* trace_xdisp=NULL; /*trace array */
2686 int* trace_mm=NULL; /*trace array */
2687 cpl_vector** loci=NULL ;
2688 FILE* trace_out;
2689 int ii;
2690 DOUBLE** ref_ind=NULL;
2692
2693 XSH_ASSURE_NOT_NULL( p_xs_3);
2694 XSH_ASSURE_NOT_NULL( instr);
2695
2696/*znse_ref is the array holding Sellmeier coefs for ZnSe refractive index at
2697 each temp. Currently hard coded to take 6 temperatures in [2][*] to [7][*],
2698 can be extended. First two rows ([0][*] to [1][*]) take the entries for the
2699 temperature bracketing the operation.
2700 Column [*][0] takes the temperature, the other columns, [*][1] to [*][6]
2701 take the Sellmeier coeffs */
2702 ref_ind=xsh_alloc2Darray(8,7);
2703
2704 check( arm = xsh_instrument_get_arm( instr));
2705 p_xs_3->arm=arm;
2706 if (arm==XSH_ARM_UVB) {
2707 xsh_ref_ind_read(0,ref_ind,290.0);
2708 }
2709 else if (arm==XSH_ARM_VIS) {
2710 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
2711 }
2712 else {
2713 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
2714 }
2715 n_order=16; /*maximum value for all 3 orders used to make sure
2716 that the trace array created is always big enough,
2717 this is the value that should be used when freeing
2718 the memory in the code that calls this function */
2719
2720 /*initalize the model. Inside the echelle_init the cfg file is
2721 read and the variables assigned to the xsh structure
2722 initialisation. Sets up those matrices that are not dependent upon
2723 wavelength */
2724 xsh_3_init(p_xs_3);
2725
2726 trace_out=fopen("trace.dat","w");
2727 if ((trace_lam=xsh_alloc1Darray(p_xs_3->SIZE))==NULL){
2728 cpl_msg_error(__func__, "Cannot allocate 2D array");
2729 fclose(trace_out);
2730 return NULL;
2731 }
2732 if ((trace_xdisp=xsh_alloc1Darray(p_xs_3->SIZE))==NULL){
2733 cpl_msg_error(__func__, "Cannot allocate 2D array");
2734 fclose(trace_out);
2735 return NULL;
2736 }
2737 if ((trace_mm=xsh_alloc1Darray_INT(p_xs_3->SIZE))==NULL){
2738 cpl_msg_error(__func__, "Cannot allocate 2D array");
2739 fclose(trace_out);
2740 return NULL;
2741 }
2742
2743 // p_xs_3->es_x=0.0;
2744 p_xs_3->es_y_tot=p_xs_3->es_y+p_xs_3->slit_scale*ent_slit_pos;
2745
2746 /* Create output vectors */
2747 if ((loci=cpl_malloc(n_order*sizeof(cpl_vector *)))==NULL) {
2748 cpl_msg_error(__func__, "Cannot allocate loci array");
2749 fclose(trace_out);
2750 return NULL;
2751 }
2752 for (ii=0; ii<n_order; ii++) {
2753 loci[ii] = cpl_vector_new(p_xs_3->SIZE) ;
2754 cpl_vector_fill(loci[ii], 0.0) ;
2755 }
2756 for (morder_cnt=p_xs_3->morder_min; morder_cnt<=p_xs_3->morder_max; morder_cnt+=1) {
2757 for (ii=0;ii<p_xs_3->SIZE;ii+=1) {
2758 trace_mm[ii]=0;
2759 trace_lam[ii]=0.0;
2760 trace_xdisp[ii]=0.0;
2761 }
2762 blaze_wav=2*(sin(-p_xs_3->nug))/(morder_cnt*p_xs_3->sg);
2763 lam_max=blaze_wav*((double)(morder_cnt)/((double)(morder_cnt)-0.5));
2764 lam_min=blaze_wav*((double)(morder_cnt)/(0.5+(double)(morder_cnt)));
2765 if (arm==XSH_ARM_NIR) {
2766 chipdist_current=3000;
2767 }
2768 else {
2769 chipdist_current=0;
2770 }
2771 pixxlast=0.0;
2772 pixylast=0.0;
2773 pixwavlast=mm2nm*(lam_min-p_xs_3->blaze_pad);
2774 for (lambda=lam_min-p_xs_3->blaze_pad; lambda<=lam_max+p_xs_3->blaze_pad;
2775 lambda+=(lam_max-lam_min)/10000.0) {
2776 lambda_nm=mm2nm*lambda;
2777 xsh_3_eval(lambda,morder_cnt,ref_ind,p_xs_3);
2778 xsh_3_detpix(p_xs_3);
2779 if (p_xs_3->chippix[0]==1) {
2780 if (p_xs_3->chippix[1]>=1 &&
2781 p_xs_3->chippix[1]<p_xs_3->ASIZE+1 &&
2782 p_xs_3->chippix[2]>=1 &&
2783 p_xs_3->chippix[2]<p_xs_3->BSIZE+1) {
2784/* if (arm==XSH_ARM_NIR){ */
2785/* //printf("%lf %d \n",p_xs_3->xpospix,chipdist_current); */
2786/* if (p_xs_3->xpospix<(double)(chipdist_current)-0.5) { */
2787/* trace_lam[p_xs_3->chippix[1]-1]=pixwavlast+(lambda_nm-pixwavlast)* */
2788/* ((double)(chipdist_current)-0.5-pixxlast)/(p_xs_3->xpospix-pixxlast); */
2789/* trace_xdisp[p_xs_3->chippix[1]-1]=pixylast+(p_xs_3->ypospix-pixylast)* */
2790/* ((double)(chipdist_current)-0.5-pixxlast)/(p_xs_3->xpospix-pixxlast); */
2791/* trace_mm[p_xs_3->chippix[1]-1]=morder_cnt; */
2792/* chipdist_current=p_xs_3->chippix[1]+1; */
2793/* } */
2794/* } */
2795/* else { */
2796 //printf("%lf %d \n",p_xs_3->ypospix,chipdist_current);
2797 if ((arm==XSH_ARM_NIR && p_xs_3->ypospix<(double)(chipdist_current)-0.5) || (arm!=XSH_ARM_NIR && p_xs_3->ypospix>(double)(chipdist_current)-0.5)) {
2798 trace_lam[p_xs_3->chippix[2]-1]=pixwavlast+(lambda_nm-pixwavlast)*
2799 ((double)(chipdist_current)-0.5-pixylast)/(p_xs_3->ypospix-pixylast);
2800 trace_xdisp[p_xs_3->chippix[2]-1]=pixxlast+(p_xs_3->xpospix-pixxlast)*
2801 ((double)(chipdist_current)-0.5-pixylast)/(p_xs_3->ypospix-pixylast);
2802 trace_mm[p_xs_3->chippix[2]-1]=morder_cnt;
2803 chipdist_current=p_xs_3->chippix[2]+1;
2804 }
2805 //}
2806 pixxlast=p_xs_3->xpospix;
2807 pixylast=p_xs_3->ypospix;
2808 }
2809 }
2810 pixwavlast=lambda_nm;
2811 }
2812 for (ii=0;ii<p_xs_3->SIZE;ii+=1) {
2813 fprintf(trace_out,"%d %lf %lf %d\n", trace_mm[ii], trace_lam[ii], trace_xdisp[ii], ii);
2814 // loci[morder_cnt]=trace_xdisp;
2815 cpl_vector_set(loci[morder_cnt-p_xs_3->morder_min], ii, trace_xdisp[ii]) ;
2816 }
2817 }
2818
2819 cpl_free(trace_lam);
2820 cpl_free(trace_xdisp);
2821 cpl_free(trace_mm);
2822 fclose(trace_out);
2823
2824 if ((xsh_free2Darray(ref_ind,8))!=0) {
2825 cpl_msg_error(__func__, "Cannot free 2D array ref_ind");
2826 return NULL;
2827 }
2828 cleanup:
2829 return loci;
2830}
2831
2832/*----------------------------------------------------------------------------*/
2847/*----------------------------------------------------------------------------*/
2848void
2850 xsh_instrument* instr,
2851 double lambda_nm,
2852 int morder,
2853 double ent_slit_pos,
2854 double* x,
2855 double* y)
2856{
2857 DOUBLE lambda=0; /*wavelength in mm */
2858
2859 DOUBLE** ref_ind = NULL;
2861
2862 //xsh_model_io_output_cfg_txt(p_xs_3);
2863 XSH_ASSURE_NOT_NULL( p_xs_3);
2864 XSH_ASSURE_NOT_NULL( instr);
2867
2868 check( arm = xsh_instrument_get_arm( instr));
2869
2870 p_xs_3->arm=arm;
2871 lambda=lambda_nm/mm2nm;
2872/*ref_ind is the array holding Sellmeier coefs for prism refractive
2873 index at each temp. Currently hard coded to take 6 temperatures in
2874 [2][*] to [7][*], can be extended. First two rows ([0][*] to [1][*])
2875 take the entries for the temperature bracketing the operation.
2876 Column [*][0] takes the temperature, the other columns, [*][1] to
2877 [*][6] take the Sellmeier coeffs */
2878 ref_ind=xsh_alloc2Darray(8,7);
2879
2880 if ( arm== XSH_ARM_UVB) {
2881 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
2882 }
2883 else if ( arm == XSH_ARM_VIS) {
2884 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
2885 }
2886 else {
2887 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
2888 }
2889 /*initalize the model. Inside the echelle_init the cfg file is
2890 read and the variables assigned to the xsh structure
2891 initialisation. Sets up those matrices that are not dependent upon
2892 wavelength */
2893
2894 xsh_3_init(p_xs_3);
2895
2896 //p_xs_3->es_x=0.0;
2897 p_xs_3->es_y_tot=p_xs_3->es_y+ent_slit_pos*p_xs_3->slit_scale;
2898
2899 /*call eval and detpix, then create the output vector*/
2900 //xsh_model_io_output_cfg_txt(p_xs_3);
2901 xsh_3_eval(lambda,morder,ref_ind,p_xs_3);
2902 xsh_3_detpix(p_xs_3);
2903
2904 *x = p_xs_3->xpospix;
2905 *y = p_xs_3->ypospix;
2906
2907
2908 cleanup:
2909 if (ref_ind != NULL){
2910 xsh_free2Darray(ref_ind,8);
2911 }
2912 return;
2913}
2914
2921void
2923 int bin_X,
2924 int bin_Y)
2925{
2926 XSH_INSTRCONFIG* instr_config=NULL;
2927 xsh_instrument* instr = NULL;
2928 if (bin_X!=1 || bin_Y!=1) {
2929 instr = xsh_instrument_new();
2930 //printf("%lf %lf %lf %d %d %lf %lf \n ",p_xs_3->pix_X,p_xs_3->pix_Y,p_xs_3->pix,p_xs_3->ASIZE,p_xs_3->BSIZE,p_xs_3->chipxpix,p_xs_3->chipypix);
2931 if (p_xs_3->arm==0) {
2933 cpl_msg_info(__func__,"Setting %d x %d binning for UVB arm",bin_X,bin_Y);
2934 p_xs_3->xsize_corr=UVB_xsize_corr;
2935 p_xs_3->ysize_corr=UVB_ysize_corr;
2936 }
2937 else if (p_xs_3->arm==1) {
2939 cpl_msg_info(__func__,"Setting %d x %d binning for VIS arm",bin_X,bin_Y);
2940 p_xs_3->xsize_corr=VIS_xsize_corr;
2941 p_xs_3->ysize_corr=VIS_ysize_corr;
2942 }
2943 else {
2945 cpl_msg_warning(__func__,"NIR arm does not support binned data");
2946 p_xs_3->xsize_corr=NIR_xsize_corr;
2947 p_xs_3->ysize_corr=NIR_ysize_corr;
2948 bin_X=1;
2949 bin_Y=1;
2950 }
2951 instr_config=xsh_instrument_get_config(instr);
2952 p_xs_3->pix_X=p_xs_3->pix*(float)(bin_X);
2953 p_xs_3->pix_Y=p_xs_3->pix*(float)(bin_Y);
2954 p_xs_3->ASIZE=instr_config->nx;
2955 p_xs_3->ASIZE/=bin_X;
2956 p_xs_3->BSIZE=instr_config->ny;
2957 p_xs_3->BSIZE/=bin_Y;
2958 p_xs_3->SIZE=instr_config->ny;
2959 p_xs_3->SIZE/=bin_Y;
2960 p_xs_3->chipxpix=(float)(instr_config->nx);
2961 p_xs_3->chipxpix/=(float)(bin_X);
2962 p_xs_3->chipypix=(float)(instr_config->ny);
2963 p_xs_3->chipypix/=(float)(bin_Y);
2964 p_xs_3->xsize_corr/=(float)(bin_X);
2965 p_xs_3->ysize_corr/=(float)(bin_Y);
2966
2967 //printf("%lf %lf %lf %d %d %lf %lf \n ",p_xs_3->pix_X,p_xs_3->pix_Y,p_xs_3->pix,p_xs_3->ASIZE,p_xs_3->BSIZE,p_xs_3->chipxpix,p_xs_3->chipypix);
2968 xsh_instrument_free(&instr);
2969 }
2970 return;
2971}
2972
2979cpl_frame*
2981 const char* tab_filename)
2982{
2983 int morder_cnt=0;
2984 int tab_size=0;
2985 int blaze_flag=0;
2986 int cen_flag=0;
2987 int edge_flag;
2988 DOUBLE blaze_min=0.2;
2989 DOUBLE buff=0.0;
2990
2991 DOUBLE lambda=0; /*wavelength in mm */
2992 DOUBLE lambda_nm=0; /* wavelength in nm */
2993 DOUBLE blaze_wav=0;
2994
2995 int fsr_flag=0;
2996 DOUBLE baseline=0.0;
2997 DOUBLE binlfsr=0.0;
2998 DOUBLE binufsr=0.0;
2999 DOUBLE binblaze=0.0;
3000 DOUBLE lam_low=0.0;
3001 DOUBLE lam_hi=0.0;
3002 DOUBLE x_low=0.0;
3003 DOUBLE x_hi=0.0;
3004
3005 DOUBLE blaze_eff=0.0;
3006
3007 DOUBLE lfsr=0;
3008 DOUBLE ufsr=0;
3009 DOUBLE fsr=0;
3010 DOUBLE blaze=0;
3011 DOUBLE p_dif=0;
3012 DOUBLE wlmin=0;
3013 DOUBLE wlmax=0;
3014 DOUBLE wlmin_full=0;
3015 DOUBLE wlmax_full=0;
3016 DOUBLE sinc_arg=0;
3017 DOUBLE wlmean=0;
3018 DOUBLE wlcen=0;
3019 DOUBLE band=0;
3020
3021 int xmin=0;
3022 int blz_frac_xmin=0;
3023 int blz_frac_ymin=0;
3024 int xmax=0;
3025 int blz_frac_xmax=0;
3026 int blz_frac_ymax=0;
3027 int yc=0;
3028 int disp_coord=0;
3029 int extra_ord=0;
3030
3031 cpl_table* sf_tab = NULL;
3032 cpl_table* sf_tab2 = NULL;
3033 cpl_frame* sf_frame=NULL;
3034 cpl_frame* sf_frame2=NULL;
3035 cpl_propertylist *sf_plist = NULL;
3036 cpl_propertylist *x_plist = NULL;
3037
3038 xsh_instrument* inst=NULL;
3039 DOUBLE** ref_ind = NULL;
3040 const char* tag=NULL;
3041 const char* tag2=NULL;
3042 char tab_filename2[256];
3043
3044 ref_ind=xsh_alloc2Darray(8,7);
3045
3046 XSH_ASSURE_NOT_NULL( p_xs_3);
3047 XSH_ASSURE_NOT_NULL( tab_filename);
3048
3049 if (strcmp(tab_filename,"spec_form.fits")==0) {
3050 extra_ord=3;
3051 }
3052 else {
3053 extra_ord=0;
3054 }
3055 sprintf(tab_filename2,"long_%s",tab_filename);
3056
3057 check(inst=xsh_instrument_new());
3058 if (p_xs_3->arm==0) {
3060 tag="SPEC_FORM_UVB";
3061 tag2="SPECTRAL_FORMAT_TAB_UVB";
3062 buff=0.007;
3063 baseline=0.00000025; /*baseline (mm) for local binsize computation*/
3064 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
3065 disp_coord=2; /*The dispersion co-ordinate in p_xs_3->chippix)*/
3066 }
3067 else if (p_xs_3->arm==1) {
3069 tag="SPEC_FORM_VIS";
3070 tag2="SPECTRAL_FORMAT_TAB_VIS";
3071 buff=0.007;
3072 baseline=0.0000005; /*baseline (mm) for local binsize computation*/
3073 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
3074 disp_coord=2; /*The dispersion co-ordinate in p_xs_3->chippix)*/
3075 }
3076 else if (p_xs_3->arm==2) {
3078 tag="SPEC_FORM_NIR";
3079 tag2="SPECTRAL_FORMAT_TAB_NIR";
3080 buff=0.007;
3081 baseline=0.000001; /*baseline (mm) for local binsize computation*/
3082 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
3083 disp_coord=2; /*The dispersion co-ordinate in p_xs_3->chippix)*/
3084 /*Convention is now that disp_coord=2 for all arms, so this is redundant*/
3085 }
3086
3087 check(sf_frame=xsh_frame_product(tab_filename,
3088 tag,
3089 CPL_FRAME_TYPE_TABLE,
3090 CPL_FRAME_GROUP_PRODUCT,
3091 CPL_FRAME_LEVEL_FINAL));
3092
3093/* check(sf_frame2=xsh_frame_product(tab_filename, */
3094/* tag2, */
3095/* CPL_FRAME_TYPE_TABLE, */
3096/* CPL_FRAME_GROUP_PRODUCT, */
3097/* CPL_FRAME_LEVEL_FINAL)); */
3098
3099
3100 tab_size= p_xs_3->morder_max-p_xs_3->morder_min+1;
3101 check(sf_tab = cpl_table_new(tab_size));
3102 check(cpl_table_new_column(sf_tab, "ORDER", CPL_TYPE_INT) );
3103 check(cpl_table_new_column(sf_tab, "LAMP", CPL_TYPE_STRING) );
3104 check(cpl_table_new_column(sf_tab, "WLMIN", CPL_TYPE_FLOAT) );
3105 check(cpl_table_new_column(sf_tab, "WLMAX", CPL_TYPE_FLOAT) );
3106 check(cpl_table_new_column(sf_tab, "DISP_MIN", CPL_TYPE_FLOAT) );
3107 check(cpl_table_new_column(sf_tab, "DISP_MAX", CPL_TYPE_FLOAT) );
3108 check(cpl_table_new_column(sf_tab, "LFSR", CPL_TYPE_FLOAT) );
3109 check(cpl_table_new_column(sf_tab, "UFSR", CPL_TYPE_FLOAT) );
3110 check(cpl_table_new_column(sf_tab, "WLMINFUL", CPL_TYPE_FLOAT) );
3111 check(cpl_table_new_column(sf_tab, "WLMAXFUL", CPL_TYPE_FLOAT) );
3112
3113 tab_size= p_xs_3->morder_max-p_xs_3->morder_min+1+(2*extra_ord);
3114 check(sf_tab2 = cpl_table_new(tab_size));
3115 check(cpl_table_new_column(sf_tab2, "ORDER", CPL_TYPE_INT) );
3116 check(cpl_table_new_column(sf_tab2, "LAMP", CPL_TYPE_STRING) );
3117 check(cpl_table_new_column(sf_tab2, "WLMIN", CPL_TYPE_FLOAT) );
3118 check(cpl_table_new_column(sf_tab2, "WLEN0", CPL_TYPE_FLOAT) );
3119 check(cpl_table_new_column(sf_tab2, "WLMAX", CPL_TYPE_FLOAT) );
3120 check(cpl_table_new_column(sf_tab2, "XDISP_CEN", CPL_TYPE_INT) );
3121 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_WLMIN", CPL_TYPE_DOUBLE) );
3122 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_WLMEAN", CPL_TYPE_DOUBLE) );
3123 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_WLMAX", CPL_TYPE_DOUBLE) );
3124 check(cpl_table_new_column(sf_tab2, "WLCEN", CPL_TYPE_DOUBLE) );
3125 check(cpl_table_new_column(sf_tab2, "BAND", CPL_TYPE_FLOAT) );
3126 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_DISP_MIN", CPL_TYPE_INT) );
3127 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_DISP_MAX", CPL_TYPE_INT) );
3128 check(cpl_table_new_column(sf_tab2, "DISP_MIN", CPL_TYPE_FLOAT) );
3129 check(cpl_table_new_column(sf_tab2, "DISP_MAX", CPL_TYPE_FLOAT) );
3130 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_XDISP_MIN", CPL_TYPE_INT) );
3131 check(cpl_table_new_column(sf_tab2, "BLZ_FRAC_XDISP_MAX", CPL_TYPE_INT) );
3132 check(cpl_table_new_column(sf_tab2, "LFSR", CPL_TYPE_FLOAT) );
3133 check(cpl_table_new_column(sf_tab2, "BLAZE", CPL_TYPE_FLOAT) );
3134 check(cpl_table_new_column(sf_tab2, "UFSR", CPL_TYPE_FLOAT) );
3135 check(cpl_table_new_column(sf_tab2, "FSR", CPL_TYPE_FLOAT) );
3136 check(cpl_table_new_column(sf_tab2, "BIN_LFSR", CPL_TYPE_DOUBLE) );
3137 check(cpl_table_new_column(sf_tab2, "BIN_BLAZE", CPL_TYPE_DOUBLE) );
3138 check(cpl_table_new_column(sf_tab2, "BIN_UFSR", CPL_TYPE_DOUBLE) );
3139 check(cpl_table_new_column(sf_tab2, "WLMINFUL", CPL_TYPE_FLOAT) );
3140 check(cpl_table_new_column(sf_tab2, "WLMAXFUL", CPL_TYPE_FLOAT) );
3141
3142 for (morder_cnt=p_xs_3->morder_min-extra_ord;morder_cnt<=p_xs_3->morder_max+extra_ord;morder_cnt+=1) {
3143 blaze_wav=2000000.0*(sin(-p_xs_3->nug))/(morder_cnt*p_xs_3->sg);
3144 ufsr=blaze_wav*((double)(morder_cnt)/((double)(morder_cnt)-0.5));
3145 lfsr=blaze_wav*((double)(morder_cnt)/(0.5+(double)(morder_cnt)));
3146 fsr=ufsr-lfsr;
3147 edge_flag=0;
3148 blaze_flag=0;
3149 wlmax=0.0;
3150 wlmin=0.0;
3151 wlmax_full=0.0;
3152 wlmin_full=0.0;
3153 cen_flag=0;
3154 fsr_flag=0;
3155 binlfsr=0.0;
3156 binblaze=0.0;
3157 binufsr=0.0;
3158 /*loop over FSR */
3159 for (lambda_nm=lfsr-(1.5*fsr);lambda_nm<ufsr+(1.5*fsr);lambda_nm+=fsr/(3.0*p_xs_3->SIZE)) {
3160 xsh_3_init(p_xs_3);
3161
3162 //p_xs_3->es_x=0.0;
3163 p_xs_3->es_y_tot=p_xs_3->es_y;
3164
3165 lambda=lambda_nm/mm2nm;
3166 xsh_3_eval(lambda,morder_cnt,ref_ind,p_xs_3);
3167 xsh_3_detpix(p_xs_3);
3168
3169 if (p_xs_3->chippix[0]==1) {
3170 if (p_xs_3->chippix[1]>=1 &&
3171 p_xs_3->chippix[1]<p_xs_3->ASIZE+1 &&
3172 p_xs_3->chippix[2]>=1 &&
3173 p_xs_3->chippix[2]<p_xs_3->BSIZE+1) {
3174 if (edge_flag==0) {
3175 edge_flag=1;
3176 wlmin_full=lambda_nm;
3177 }
3178 p_dif=(sin(p_xs_3->grat_alpha-(-p_xs_3->nug))+sin(p_xs_3->grat_beta-(-p_xs_3->nug)));
3179 if (p_xs_3->grat_alpha>p_xs_3->grat_beta) {
3180 sinc_arg=(M_PI/(lambda*p_xs_3->sg))*(cos(p_xs_3->grat_alpha)/cos(p_xs_3->grat_alpha-(-p_xs_3->nug)))*p_dif;
3181 blaze=((sin(sinc_arg))/sinc_arg)*((sin(sinc_arg))/sinc_arg);
3182 }
3183 else {
3184 sinc_arg=(M_PI/(lambda*p_xs_3->sg))*(cos(p_xs_3->grat_beta)/cos(p_xs_3->grat_alpha-(-p_xs_3->nug)))*p_dif;
3185 blaze=(cos(p_xs_3->grat_beta)/cos(p_xs_3->grat_alpha))*(cos(p_xs_3->grat_beta)/cos(p_xs_3->grat_alpha))*((sin(sinc_arg))/sinc_arg)*((sin(sinc_arg))/sinc_arg);
3186 }
3187 // printf("lambda_nm %lf blaxe %lf \n", lambda_nm, blaze);
3188 //printf(" %d %d \n", p_xs_3->chippix[disp_coord],p_xs_3->SIZE/2);
3189 /*logic here may need to be changed with the new flipped UVB config */
3190 if ((cen_flag==0 && p_xs_3->chippix[disp_coord]>=p_xs_3->SIZE/2
3191 && p_xs_3->arm<2) ||
3192 (cen_flag==0 && p_xs_3->chippix[disp_coord]<=p_xs_3->SIZE/2
3193 && p_xs_3->arm==2)) {
3194 yc=p_xs_3->chippix[3-disp_coord];
3195 wlcen=lambda_nm;
3196 cen_flag=1;
3197 }
3198 if (blaze_flag==0 && blaze>blaze_min) {
3199 wlmin=lambda_nm;
3200 blz_frac_xmin=p_xs_3->chippix[disp_coord];
3201 blz_frac_ymin=p_xs_3->chippix[3-disp_coord];
3202 blaze_flag=1;
3203 }
3204 if (blaze_flag==1 && blaze>blaze_min) {
3205 wlmax=lambda_nm;
3206 blz_frac_xmax=p_xs_3->chippix[disp_coord];
3207 blz_frac_ymax=p_xs_3->chippix[3-disp_coord];
3208 }
3209 if (blaze_flag==1 && blaze<blaze_min) {
3210 blaze_flag=2;
3211 }
3212 if (fsr_flag==0 && lambda_nm>lfsr*(1.0-buff)) {
3213 fsr_flag=1;
3214 xmin=p_xs_3->chippix[disp_coord];
3215 lam_low=lambda-baseline;
3216 xsh_3_eval(lam_low,morder_cnt,ref_ind,p_xs_3);
3217 xsh_3_detpix(p_xs_3);
3218 x_low=p_xs_3->ypospix;
3219 lam_hi=lambda+baseline;
3220 xsh_3_eval(lam_hi,morder_cnt,ref_ind,p_xs_3);
3221 xsh_3_detpix(p_xs_3);
3222 x_hi=p_xs_3->ypospix;
3223 if (x_low>0.0 && x_hi>0.0) {
3224 if (p_xs_3->arm==2) {
3225 binlfsr=((lam_hi-lam_low)/(x_low-x_hi))*mm2nm;
3226 }
3227 else {
3228 binlfsr=((lam_hi-lam_low)/(x_hi-x_low))*mm2nm;
3229 }
3230 }
3231 else {
3232 binlfsr=-1.0;
3233 }
3234 }
3235 if (fsr_flag==1 && lambda_nm>blaze_wav) {
3236 fsr_flag=2;
3237 blaze_eff=blaze;
3238 lam_low=lambda-baseline;
3239 xsh_3_eval(lam_low,morder_cnt,ref_ind,p_xs_3);
3240 xsh_3_detpix(p_xs_3);
3241 x_low=p_xs_3->ypospix;
3242 lam_hi=lambda+baseline;
3243 xsh_3_eval(lam_hi,morder_cnt,ref_ind,p_xs_3);
3244 xsh_3_detpix(p_xs_3);
3245 x_hi=p_xs_3->ypospix;
3246 if (x_low>0.0 && x_hi>0.0) {
3247 if (p_xs_3->arm==2) {
3248 binblaze=((lam_hi-lam_low)/(x_low-x_hi))*mm2nm;
3249 }
3250 else {
3251 binblaze=((lam_hi-lam_low)/(x_hi-x_low))*mm2nm;
3252 }
3253 }
3254 else {
3255 binblaze=-1.0;
3256 }
3257 }
3258 if (fsr_flag==2) {
3259 xmax=p_xs_3->chippix[disp_coord];
3260 if (lambda_nm>ufsr*(1.0+buff)) {
3261 fsr_flag=3;
3262 lam_low=lambda-baseline;
3263 xsh_3_eval(lam_low,morder_cnt,ref_ind,p_xs_3);
3264 xsh_3_detpix(p_xs_3);
3265 x_low=p_xs_3->ypospix;
3266 lam_hi=lambda+baseline;
3267 xsh_3_eval(lam_hi,morder_cnt,ref_ind,p_xs_3);
3268 xsh_3_detpix(p_xs_3);
3269 x_hi=p_xs_3->ypospix;
3270 if (x_low>0.0 && x_hi>0.0) {
3271 if (p_xs_3->arm==2) {
3272 binufsr=((lam_hi-lam_low)/(x_low-x_hi))*mm2nm;
3273 }
3274 else {
3275 binufsr=((lam_hi-lam_low)/(x_hi-x_low))*mm2nm;
3276 }
3277 }
3278 else {
3279 binufsr=-1.0;
3280 }
3281 //printf("%d %lf %lf %lf %lf %lf \n,",morder_cnt, lambda_nm, lam_low*mm2nm, lam_hi*mm2nm, x_low, x_hi);
3282 }
3283 }
3284 //printf("%d lambda_nm %lf blaxe %lf %d %lf %lf %d %d \n", morder_cnt, lambda_nm, blaze,blaze_flag,wlmax,wlmin,p_xs_3->chippix[1],p_xs_3->chippix[2]);
3285 }
3286 }
3287 else {
3288 if (edge_flag==1) {
3289 edge_flag=2;
3290 wlmax_full=lambda_nm;
3291 }
3292 }
3293 }
3294 if (blaze_flag>0) {
3295 wlmean=(wlmin+wlmax)/2.0;
3296 band=wlmax-wlmin;
3297 }
3298 else {
3299 band=-1.0;
3300 wlmin=-1.0;
3301 blz_frac_xmin=-1;
3302 blz_frac_ymin=-1;
3303 wlmean=-1.0;
3304 wlmax=-1.0;
3305 blz_frac_xmax=-1;
3306 blz_frac_ymax=-1;
3307 }
3308 if (cen_flag!=1) {
3309 wlcen=-1.0;
3310 yc=-1;
3311 }
3312 if (fsr_flag<3) {
3313 binufsr=-1.0;
3314 if (fsr_flag<2) {
3315 xmax=-1.0;
3316 binblaze=-1.0;
3317 if (fsr_flag<1) {
3318 binlfsr=-1.0;
3319 xmin=-1.0;
3320 }
3321 }
3322 }
3323 //printf("order: %d ; lfsr: %lf ; blaze: %lf; ufsr: %lf ; binlfsr: %lf ; binblaze: %lf ; binufsr: %lf \n", morder_cnt, lfsr, blaze_wav, ufsr, binlfsr, binblaze, binufsr);
3324
3325 if (morder_cnt>=p_xs_3->morder_min && morder_cnt<=p_xs_3->morder_max) {
3326 check(cpl_table_set_int(sf_tab, "ORDER", morder_cnt-p_xs_3->morder_min,morder_cnt));
3327 /*Below the wlmin based on fraction of blaze is replaced with simple 2% wavelength
3328 buffer on lfsr and ufsr */
3329 check(cpl_table_set_float(sf_tab, "WLMIN", morder_cnt-p_xs_3->morder_min,(float)((1.0-buff)*lfsr)));
3330 check(cpl_table_set_float(sf_tab, "WLMAX", morder_cnt-p_xs_3->morder_min,(float)((1.0+buff)*ufsr)));
3331 check(cpl_table_set_float(sf_tab, "DISP_MIN", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmin)));
3332 check(cpl_table_set_float(sf_tab, "DISP_MAX", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmax)));
3333 check(cpl_table_set_float(sf_tab, "DISP_MIN", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmin)));
3334 check(cpl_table_set_float(sf_tab, "DISP_MAX", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmax)));
3335 check(cpl_table_set_float(sf_tab, "WLMINFUL", morder_cnt-p_xs_3->morder_min,(float)(wlmin_full)));
3336 check(cpl_table_set_float(sf_tab, "WLMAXFUL", morder_cnt-p_xs_3->morder_min,(float)(wlmax_full)));
3337 check(cpl_table_set_float(sf_tab, "LFSR", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(lfsr)));
3338 check(cpl_table_set_float(sf_tab, "UFSR", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(ufsr)));
3339 if (p_xs_3->arm==0 && morder_cnt>20) {
3340 check(cpl_table_set_string(sf_tab, "LAMP", morder_cnt-p_xs_3->morder_min,"D2"));
3341 }
3342 else {
3343 check(cpl_table_set_string(sf_tab, "LAMP", morder_cnt-p_xs_3->morder_min,"QTH"));
3344 }
3345 }
3346 check(cpl_table_set_int(sf_tab2, "ORDER", morder_cnt-p_xs_3->morder_min+extra_ord,morder_cnt));
3347 if (p_xs_3->arm==0 && morder_cnt>20) {
3348 check(cpl_table_set_string(sf_tab2, "LAMP", morder_cnt-p_xs_3->morder_min,"D2"));
3349 }
3350 else {
3351 check(cpl_table_set_string(sf_tab2, "LAMP", morder_cnt-p_xs_3->morder_min,"QTH"));
3352 }
3353 check(cpl_table_set_int(sf_tab2, "XDISP_CEN", morder_cnt-p_xs_3->morder_min+extra_ord,yc));
3354 /*Here the wlmin,max based on fraction of blaze is put into BLZ_FRAC_WLMIN,MAX*/
3355 check(cpl_table_set_double(sf_tab2, "BLZ_FRAC_WLMIN", morder_cnt-p_xs_3->morder_min+extra_ord,wlmin));
3356 check(cpl_table_set_double(sf_tab2, "BLZ_FRAC_WLMAX", morder_cnt-p_xs_3->morder_min+extra_ord,wlmax));
3357 check(cpl_table_set_double(sf_tab2, "BLZ_FRAC_WLMEAN", morder_cnt-p_xs_3->morder_min+extra_ord,wlmean));
3358 /*Below the WLMIN is simple 2% wavelength buffer on lfsr and ufsr */
3359 check(cpl_table_set_float(sf_tab2, "WLMIN", morder_cnt-p_xs_3->morder_min+extra_ord,(1.0-buff)*lfsr) );
3360 check(cpl_table_set_float(sf_tab2, "WLMAX", morder_cnt-p_xs_3->morder_min+extra_ord,(1.0+buff)*ufsr));
3361 check(cpl_table_set_float(sf_tab2, "BAND", morder_cnt-p_xs_3->morder_min+extra_ord,band));
3362 check(cpl_table_set_float(sf_tab2, "WLEN0", morder_cnt-p_xs_3->morder_min+extra_ord,((1.0-buff)*lfsr+(1.0+buff)*ufsr)/2.0));
3363 check(cpl_table_set_float(sf_tab2, "WLMINFUL", morder_cnt-p_xs_3->morder_min,(float)(wlmin_full)));
3364 check(cpl_table_set_float(sf_tab2, "WLMAXFUL", morder_cnt-p_xs_3->morder_min,(float)(wlmax_full)));
3365 check(cpl_table_set_double(sf_tab2, "WLCEN", morder_cnt-p_xs_3->morder_min+extra_ord,wlcen));
3366 check(cpl_table_set_int(sf_tab2, "BLZ_FRAC_DISP_MIN", morder_cnt-p_xs_3->morder_min+extra_ord, blz_frac_xmin) );
3367 check(cpl_table_set_int(sf_tab2, "BLZ_FRAC_DISP_MAX", morder_cnt-p_xs_3->morder_min+extra_ord, blz_frac_xmax) );
3368 check(cpl_table_set_float(sf_tab2, "DISP_MIN", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmin)) );
3369 check(cpl_table_set_float(sf_tab2, "DISP_MAX", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(xmax)) );
3370 check(cpl_table_set_int(sf_tab2, "BLZ_FRAC_XDISP_MIN", morder_cnt-p_xs_3->morder_min+extra_ord, blz_frac_ymin) );
3371 check(cpl_table_set_int(sf_tab2, "BLZ_FRAC_XDISP_MAX", morder_cnt-p_xs_3->morder_min+extra_ord, blz_frac_ymax) );
3372 check(cpl_table_set_float(sf_tab2, "LFSR", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(lfsr)));
3373 check(cpl_table_set_float(sf_tab2, "BLAZE", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(blaze_wav)));
3374 check(cpl_table_set_float(sf_tab2, "UFSR", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(ufsr)));
3375 check(cpl_table_set_float(sf_tab2, "FSR", morder_cnt-p_xs_3->morder_min+extra_ord, (float)(ufsr-lfsr)));
3376 check(cpl_table_set_double(sf_tab2, "BIN_LFSR", morder_cnt-p_xs_3->morder_min+extra_ord, binlfsr) );
3377 check(cpl_table_set_double(sf_tab2, "BIN_BLAZE", morder_cnt-p_xs_3->morder_min+extra_ord, binblaze) );
3378 check(cpl_table_set_double(sf_tab2, "BIN_UFSR", morder_cnt-p_xs_3->morder_min+extra_ord, binufsr ));
3379 }
3380
3381 sf_plist = cpl_propertylist_new();
3382 //cpl_propertylist_append_string(sf_plist, "INSTRUME", "XSHOOTER") ;
3383 check( xsh_pfits_set_pcatg(sf_plist, tag));
3384 cpl_msg_info(__func__, "Save the tables") ;
3385
3386 x_plist=cpl_propertylist_new();
3387 cpl_propertylist_append_int(x_plist, XSH_SPECTRALFORMAT_DIST_ORDER,9);
3388
3389/* check(cpl_table_save(sf_tab, sf_plist,x_plist, tab_filename, CPL_IO_DEFAULT)); */
3390/* xsh_msg(" sf table %s %s %s", tab_filename, cpl_frame_get_filename(sf_frame2), */
3391/* cpl_frame_get_tag(sf_frame)); */
3392
3393 check(cpl_table_save(sf_tab2, sf_plist, x_plist, tab_filename, CPL_IO_DEFAULT));
3394 xsh_msg(" sf table %s %s %s", tab_filename, cpl_frame_get_filename(sf_frame),
3395 cpl_frame_get_tag(sf_frame));
3396
3397 cleanup:
3398 xsh_free_propertylist(&sf_plist);
3399 xsh_free_propertylist(&x_plist);
3400
3401 xsh_free_table(&sf_tab);
3402 xsh_free_table(&sf_tab2);
3403 if (ref_ind != NULL){
3404 xsh_free2Darray(ref_ind,8);
3405 }
3406
3407 if ( cpl_error_get_code() != CPL_ERROR_NONE){
3408 xsh_free_frame( &sf_frame);
3409 xsh_free_frame( &sf_frame2);
3410 return NULL;
3411 } else {
3412 return sf_frame;
3413 }
3414
3415}
3416
3417/*----------------------------------------------------------------------------*/
3437/*----------------------------------------------------------------------------*/
3438cpl_frame*
3440 xsh_instrument* instr,
3441 const char* line_list,
3442 int num_ph,
3443 double sep_ph,
3444 const char* THE_filename)
3445{
3446 int morder_cnt; /* grating spectral order counter */
3447 int spos_int;
3448 DOUBLE lambda; /*wavelength in mm */
3449 DOUBLE lambda_nm; /* wavelength in nm */
3450 DOUBLE blaze_wav, lam_min, lam_max, inten;
3451 cpl_table *lines_tab = NULL;
3452 int lines_number, line_no ;
3453 DOUBLE spos;
3454 DOUBLE** ref_ind = NULL;
3455 cpl_table* THE_tab = NULL;
3456 int fitsrow;
3457 int tab_size;
3459 cpl_frame* THE_frame=NULL;
3460 cpl_propertylist *THE_plist = NULL;
3461 const char* tag=NULL;
3462
3463 fitsrow=0;
3464 tab_size = 150000;
3465
3466 XSH_ASSURE_NOT_NULL( p_xs_3);
3467 XSH_ASSURE_NOT_NULL( instr);
3468 XSH_ASSURE_NOT_NULL( THE_filename);
3469
3470 check( arm = xsh_instrument_get_arm( instr));
3471 p_xs_3->arm=arm;
3472
3473/*ref_ind is the array holding Sellmeier coefs for prism refractive
3474 index at each temp. Currently hard coded to take 6 temperatures in
3475 [2][*] to [7][*], can be extended. First two rows ([0][*] to [1][*])
3476 take the entries for the temperature bracketing the operation.
3477 Column [*][0] takes the temperature, the other columns, [*][1] to
3478 [*][6] take the Sellmeier coeffs */
3479 ref_ind=xsh_alloc2Darray(8,7);
3480
3481 if (arm==XSH_ARM_UVB) {
3482 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
3483 }
3484 else if (arm==XSH_ARM_VIS) {
3485 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
3486 }
3487 else {
3488 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
3489 }
3490
3491 /*initalize the model. Inside the echelle_init the cfg file is
3492 read and the variables assigned to the xsh structure
3493 initialisation. Sets up those matrices that are not dependent upon
3494 wavelength */
3495 xsh_3_init(p_xs_3);
3496
3497 // p_xs_3->es_x=0.0;
3498
3499 THE_tab = cpl_table_new(tab_size);
3500 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_WAVELENGTH, CPL_TYPE_FLOAT) ;
3501 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_ORDER, CPL_TYPE_INT) ;
3502 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_SLITINDEX, CPL_TYPE_INT) ;
3503 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_SLITPOSITION, CPL_TYPE_FLOAT) ;
3504 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_DETECTORX, CPL_TYPE_DOUBLE) ;
3505 cpl_table_new_column(THE_tab, XSH_THE_MAP_TABLE_COLNAME_DETECTORY, CPL_TYPE_DOUBLE) ;
3506
3507 /* Read the input FITS lines list */
3508 if ((lines_tab = cpl_table_load(line_list, 1, 0))==NULL) {
3509 cpl_msg_error(__func__, "Cannot find line list %s", line_list);
3510 return NULL;
3511 }
3512 lines_number = cpl_table_get_nrow(lines_tab) ;
3513 if (cpl_table_get_column_type(lines_tab, XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH) == CPL_TYPE_DOUBLE) {
3514 check(cpl_table_duplicate_column(lines_tab,"DWAVELENGTH",lines_tab,XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH));
3515 check(cpl_table_erase_column(lines_tab,XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH));
3516 check(cpl_table_cast_column(lines_tab,"DWAVELENGTH",
3517 XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH,CPL_TYPE_FLOAT));
3518 }
3519 if (cpl_table_get_column_type(lines_tab, XSH_ARCLIST_TABLE_COLNAME_FLUX) == CPL_TYPE_DOUBLE) {
3520 check(cpl_table_duplicate_column(lines_tab,"DFLUX",lines_tab,XSH_ARCLIST_TABLE_COLNAME_FLUX));
3521 check(cpl_table_erase_column(lines_tab,XSH_ARCLIST_TABLE_COLNAME_FLUX));
3522 check(cpl_table_cast_column(lines_tab,"DFLUX",
3523 XSH_ARCLIST_TABLE_COLNAME_FLUX,CPL_TYPE_FLOAT));
3524 }
3525 /* Loop on the lines and call the stis model routine */
3526 for (line_no=0 ; line_no<lines_number ; line_no++) {
3527 /*
3528 check(lambda_nm=cpl_table_get_double(lines_tab,
3529 XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH, line_no, NULL));
3530 check(inten = cpl_table_get(lines_tab,
3531 XSH_ARCLIST_TABLE_COLNAME_FLUX, line_no, NULL));
3532 */
3533
3534 check(lambda_nm=cpl_table_get_float(lines_tab,
3535 XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH, line_no, NULL));
3536 check(inten = cpl_table_get(lines_tab,
3537 XSH_ARCLIST_TABLE_COLNAME_FLUX, line_no, NULL));
3538
3539 /*Calculate the order of the given wavelength */
3540 // morder=(int)(0.5+(sin(p_xs_3->mug+inout/2.0)+sin(p_xs_3->mug-inout/2.0))/((p_xs_3->sg)*lambda));
3541 /* while there is a line in the file read it and call the stis model routine*/
3542 /*without order in input*/
3543 for (morder_cnt=p_xs_3->morder_min;morder_cnt<=p_xs_3->morder_max; morder_cnt+=1) {
3544 // for (morder_cnt=morder-morder_it; morder_cnt<morder+morder_it; morder_cnt+=1) {
3545 blaze_wav=2*(sin(-p_xs_3->nug))/(morder_cnt*p_xs_3->sg);
3546 lam_max=blaze_wav*((double)(morder_cnt)/((double)(morder_cnt)-0.5));
3547 lam_min=blaze_wav*((double)(morder_cnt)/(0.5+(double)(morder_cnt)));
3548 lambda=lambda_nm*1e-6; //lambda in mm
3549 if (lambda>lam_min-p_xs_3->blaze_pad && lambda<lam_max+p_xs_3->blaze_pad) {
3550 for (spos_int=0;spos_int<num_ph; spos_int+=1) {
3551 if (sep_ph>0.0) {
3552 spos=sep_ph*(spos_int-((num_ph-1)/2));
3553 }
3554 else {
3555 if (num_ph>1) {
3556 spos=p_xs_3->slit[spos_int];
3557 }
3558 else if (num_ph==1) {
3559 spos=p_xs_3->slit[4];
3560 }
3561 }
3562 p_xs_3->es_y_tot=p_xs_3->es_y+spos*p_xs_3->slit_scale;
3563 //printf("%lf %d %lf %lf %lf %lf \n",p_xs_3->slit[4], spos_int, p_xs_3->es_y_tot,spos,p_xs_3->slit_scale, p_xs_3->es_y);
3564 xsh_3_eval(lambda,morder_cnt,ref_ind,p_xs_3);
3565 xsh_3_detpix(p_xs_3);
3566 //printf("%lf %d %lf %lf %lf %lf %d\n",lambda_nm, morder_cnt, p_xs_3->es_y_tot, spos, p_xs_3->xdet, p_xs_3->ydet,p_xs_3->chippix[0]);
3567 if (p_xs_3->chippix[0]==1) {
3568 //printf("%lf %lf %lf\n",p_xs_3->es_y_tot, p_xs_3->slit_scale, p_xs_3->es_y_tot/p_xs_3->slit_scale);
3569 cpl_table_set_float(THE_tab, XSH_THE_MAP_TABLE_COLNAME_WAVELENGTH, fitsrow, lambda_nm) ;
3570 cpl_table_set_int(THE_tab, XSH_THE_MAP_TABLE_COLNAME_ORDER, fitsrow, morder_cnt) ;
3571 cpl_table_set_float(THE_tab, XSH_THE_MAP_TABLE_COLNAME_SLITPOSITION, fitsrow, spos);
3572 cpl_table_set_int(THE_tab, XSH_THE_MAP_TABLE_COLNAME_SLITINDEX, fitsrow, spos_int);
3573 cpl_table_set_double(THE_tab, XSH_THE_MAP_TABLE_COLNAME_DETECTORX, fitsrow, p_xs_3->xpospix);
3574 cpl_table_set_double(THE_tab, XSH_THE_MAP_TABLE_COLNAME_DETECTORY, fitsrow, p_xs_3->ypospix);
3575 fitsrow+=1;
3576 }
3577 }
3578 }
3579 }
3580 }
3581 // AMO added to have proper binning in THE map used for SKY lines
3582 //cpl_table_multiply_scalar(THE_tab,XSH_THE_MAP_TABLE_COLNAME_DETECTORX,instr->binx);
3583 //cpl_table_multiply_scalar(THE_tab,XSH_THE_MAP_TABLE_COLNAME_DETECTORY,instr->biny);
3584
3585 THE_plist = cpl_propertylist_new();
3586 //cpl_propertylist_append_string(THE_plist, "INSTRUME", "XSHOOTER") ;
3587 check( cpl_table_set_size(THE_tab,fitsrow));
3588
3589 check( cpl_table_save(THE_tab, THE_plist, NULL, THE_filename,
3590 CPL_IO_DEFAULT));
3591
3592 if (arm == XSH_ARM_UVB) {
3593 tag="THE_UVB";
3594 }
3595 else if (arm == XSH_ARM_VIS) {
3596 tag="THE_VIS";
3597 }
3598 else if (arm == XSH_ARM_NIR) {
3599 tag="THE_NIR";
3600 }
3601
3602 check(THE_frame=xsh_frame_product(THE_filename,
3603 tag,
3604 CPL_FRAME_TYPE_TABLE,
3605 CPL_FRAME_GROUP_PRODUCT,
3606 CPL_FRAME_LEVEL_FINAL));
3607
3608 xsh_msg(" THE table %s %s",THE_filename,tag);
3609
3610
3611 cleanup:
3612 xsh_free_propertylist(&THE_plist);
3613 xsh_free_table(&THE_tab);
3614 xsh_free_table(&lines_tab);
3615 if ( cpl_error_get_code() != CPL_ERROR_NONE){
3616 xsh_free_frame( &THE_frame);
3617 }
3618 if (ref_ind != NULL){
3619 xsh_free2Darray(ref_ind,8);
3620 }
3621
3622
3623 return THE_frame;
3624
3625}
3626
3627/*----------------------------------------------------------------------------*/
3674/*----------------------------------------------------------------------------*/
3675
3676
3677cpl_frame*
3678xsh_model_pipe_anneal(cpl_frame* cfg_frame,
3679 cpl_frame* resid_frame,
3680 int maxit,
3681 double ann_fac,
3682 int scenario,
3683 int rec_id)
3684{
3685 cpl_table* conf_tab = NULL;
3686 const int model_coeff_num=300;
3687 ann_all_par all_par[model_coeff_num];
3688 ann_all_par* p_all_par = NULL;
3689 double abest[model_coeff_num];
3690 double amin[model_coeff_num];
3691 double amax[model_coeff_num];
3692 int aname[model_coeff_num];
3693 int wav_den[40];
3694 int adim=0;
3695
3696 int ii, jj, kk;
3697 int size;
3698 DOUBLE** ref_ind = NULL;
3699 DOUBLE* p_wlarray = NULL;
3700 cpl_frame* MODEL_CONF_OPT_frame=NULL;
3701 cpl_propertylist* MODEL_CONFIG_plist=NULL ;
3702 xsh_resid_tab* resid_tab = NULL;
3703 double *vlambda=NULL, *thpre_x=NULL, *thpre_y=NULL,
3704 *xgauss=NULL, *ygauss=NULL, *vorder=NULL;
3705 int *slitindex=NULL;
3706 coord* msp_coord = NULL;
3707 char out_cfg_filename[256];
3708 xsh_xs_3 xs_3;
3709 xsh_xs_3* p_xs_3=NULL;
3710 DOUBLE wav_den_bin_sz;
3711
3712 cpl_table* resid_tbl = NULL;
3713 cpl_propertylist *resid_header = NULL;
3714 const char* tag=NULL;
3715
3716 p_xs_3=&xs_3;
3717
3718 XSH_ASSURE_NOT_NULL( resid_frame);
3719 XSH_ASSURE_NOT_NULL(cfg_frame);
3720 p_all_par=&all_par[0];
3721
3722 /*
3723 init string variables on full object size to prevent
3724 Conditional jump or move depends on uninitialised value(s)
3725 valgrind error ( indeed xsh_model_readfits() initializes only
3726 a number of elements equal to the input model cfg table size
3727 (~90 params), not model_coeff_num=300
3728 */
3729 for (ii=0;ii<model_coeff_num;ii++) {
3730 sprintf((p_all_par+ii)->name, "%s", "\n");
3731 }
3732
3733 //xsh_msg("passed_frames - resid: %s %s cfg: %s %s", cpl_frame_get_tag(resid_frame),cpl_frame_get_filename(resid_frame),cpl_frame_get_tag(cfg_frame),cpl_frame_get_filename(cfg_frame));
3734
3735 /*Read parameter values in input config and their ranges and flags*/
3736
3737 adim=xsh_model_readfits(abest,
3738 amin,
3739 amax,
3740 aname,
3741 cpl_frame_get_filename(cfg_frame),
3742 cpl_frame_get_tag(cfg_frame),
3743 p_xs_3,
3744 p_all_par);
3745
3746 // ann_fac=0.1;
3747
3748 /* iff use the scenario option to determine if the switches in the input FITS
3749 config file should be used or if an automatic set should be used*/
3750
3751 if (scenario!=0) {
3752 for (ii=0;ii<model_coeff_num;ii++) {
3753 aname[ii]=-1;
3754 abest[ii]=0.0;
3755 amin[ii]=0.0;
3756 amax[ii]=0.0;
3757 }
3758 /*modify parameters for optimisation*/
3759 /*discover their indices and make the link with aname*/
3760 jj=0;
3761 if (scenario<=2) {
3762 /* For the start up scenario (1) open the parameters that may realistically
3763 have physically changed due to intervention etc (eg. we don't change the
3764 relative orientation of prism entrance and exit surfaces because we
3765 don't expect the prism to change shape, but we do allow the
3766 orientation of the prism(s) to change) and that effect the single
3767 pinhole. The tolerances are >> than
3768 any realistic physical movement. There are 14 parameters open in
3769 total for UVB/VIS, 18 for NIR*/
3770 for (ii=0;ii<100;ii++) {
3771 /*fdet is the focal length of the camera*/
3772 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
3773 abest[jj]=p_xs_3->fdet;
3774 amin[jj]=p_xs_3->fdet-(1.0*ann_fac);
3775 amax[jj]=p_xs_3->fdet+(1.0*ann_fac);
3776 aname[jj]=ii;
3777 jj+=1;
3778 }
3779 else {
3780 /*temper is the temperature of the first prism*/
3781 /* if (strncmp((p_all_par+ii)->name,"temper",6)==0) { */
3782 /* aname[jj]=ii; */
3783 /* abest[jj]=p_xs_3->temper; */
3784 /* amin[jj]=p_xs_3->temper-(5.0*ann_fac); */
3785 /* amax[jj]=p_xs_3->temper+(5.0*ann_fac); */
3786 /* jj+=1; */
3787 /* } */
3788
3789 /* jj=xsh_model_open_param((p_all_par+ii)->name, */
3790 /* "temper", */
3791 /* &aname[jj], */
3792 /* ii, */
3793 /* &abest[jj], */
3794 /* p_xs_3->temper, */
3795 /* &amin[jj], */
3796 /* &amax[jj], */
3797 /* ann_fac, */
3798 /* 5.0, */
3799 /* jj); */
3800
3801 /*[mu/nu]p1 are the tip and tilt of the entrance surface (and hence
3802 the whole prism) of the first prism*/
3803 if (strncmp((p_all_par+ii)->name,"mup1",4)==0) {
3804 aname[jj]=ii;
3805 abest[jj]=p_xs_3->mup1/DEG2RAD;
3806 amin[jj]=p_xs_3->mup1/DEG2RAD-(0.1*ann_fac);
3807 amax[jj]=p_xs_3->mup1/DEG2RAD+(0.1*ann_fac);
3808 jj+=1;
3809 }
3810 if (strncmp((p_all_par+ii)->name,"nup1",4)==0) {
3811 aname[jj]=ii;
3812 abest[jj]=p_xs_3->nup1/DEG2RAD;
3813 amin[jj]=p_xs_3->nup1/DEG2RAD-(0.1*ann_fac);
3814 amax[jj]=p_xs_3->nup1/DEG2RAD+(0.1*ann_fac);
3815 jj+=1;
3816 }
3817 if (p_xs_3->arm==2) {
3818 /*[mu/nu]p3 are the tip and tilt of the entrance surface (and hence
3819 the whole prism) of the second prism*/
3820 if (strncmp((p_all_par+ii)->name,"mup3",4)==0) {
3821 aname[jj]=ii;
3822 abest[jj]=p_xs_3->mup3/DEG2RAD;
3823 amin[jj]=p_xs_3->mup3/DEG2RAD-(0.1*ann_fac);
3824 amax[jj]=p_xs_3->mup3/DEG2RAD+(0.1*ann_fac);
3825 jj+=1;
3826 }
3827 if (strncmp((p_all_par+ii)->name,"nup3",4)==0) {
3828 aname[jj]=ii;
3829 abest[jj]=p_xs_3->nup3/DEG2RAD;
3830 amin[jj]=p_xs_3->nup3/DEG2RAD-(0.1*ann_fac);
3831 amax[jj]=p_xs_3->nup3/DEG2RAD+(0.1*ann_fac);
3832 jj+=1;
3833 }
3834 /*[mu/nu]p5 are the tip and tilt of the entrance surface (and hence
3835 the whole prism) of the third prism*/
3836 if (strncmp((p_all_par+ii)->name,"mup5",4)==0) {
3837 aname[jj]=ii;
3838 abest[jj]=p_xs_3->mup5/DEG2RAD;
3839 amin[jj]=p_xs_3->mup5/DEG2RAD-(0.1*ann_fac);
3840 amax[jj]=p_xs_3->mup5/DEG2RAD+(0.1*ann_fac);
3841 jj+=1;
3842 }
3843 if (strncmp((p_all_par+ii)->name,"nup5",4)==0) {
3844 aname[jj]=ii;
3845 abest[jj]=p_xs_3->nup5/DEG2RAD;
3846 amin[jj]=p_xs_3->nup5/DEG2RAD-(0.1*ann_fac);
3847 amax[jj]=p_xs_3->nup5/DEG2RAD+(0.1*ann_fac);
3848 jj+=1;
3849 }
3850 }
3851 /*[mu/nu/tau]g describe the orientation of the grating*/
3852 if (strncmp((p_all_par+ii)->name,"mug",3)==0) {
3853 aname[jj]=ii;
3854 abest[jj]=p_xs_3->mug/DEG2RAD;
3855 amin[jj]=p_xs_3->mug/DEG2RAD-(0.1*ann_fac);
3856 amax[jj]=p_xs_3->mug/DEG2RAD+(0.1*ann_fac);
3857 jj+=1;
3858 }
3859 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
3860 aname[jj]=ii;
3861 abest[jj]=p_xs_3->nug/DEG2RAD;
3862 amin[jj]=p_xs_3->nug/DEG2RAD-(1.0*ann_fac);
3863 amax[jj]=p_xs_3->nug/DEG2RAD+(1.0*ann_fac);
3864 jj+=1;
3865 }
3866 if (strncmp((p_all_par+ii)->name,"taug",4)==0) {
3867 aname[jj]=ii;
3868 abest[jj]=p_xs_3->taug/DEG2RAD;
3869 amin[jj]=p_xs_3->taug/DEG2RAD-(0.1*ann_fac);
3870 amax[jj]=p_xs_3->taug/DEG2RAD+(0.1*ann_fac);
3871 jj+=1;
3872 }
3873 /*[mu/nu/tau]d describe the orientation of the detector*/
3874 if (strncmp((p_all_par+ii)->name,"mud",3)==0) {
3875 aname[jj]=ii;
3876 abest[jj]=p_xs_3->mud/DEG2RAD;
3877 amin[jj]=p_xs_3->mud/DEG2RAD-(1.0*ann_fac);
3878 amax[jj]=p_xs_3->mud/DEG2RAD+(1.0*ann_fac);
3879 jj+=1;
3880 }
3881 if (strncmp((p_all_par+ii)->name,"nud",3)==0) {
3882 aname[jj]=ii;
3883 abest[jj]=p_xs_3->nud/DEG2RAD;
3884 amin[jj]=p_xs_3->nud/DEG2RAD-(1.0*ann_fac);
3885 amax[jj]=p_xs_3->nud/DEG2RAD+(1.0*ann_fac);
3886 jj+=1;
3887 }
3888 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
3889 aname[jj]=ii;
3890 abest[jj]=p_xs_3->taud/DEG2RAD;
3891 amin[jj]=p_xs_3->taud/DEG2RAD-(1.0*ann_fac);
3892 amax[jj]=p_xs_3->taud/DEG2RAD+(1.0*ann_fac);
3893 jj+=1;
3894 }
3895 /*es_y is the location of the central pinhole on the entrance
3896 slit*/
3897 if (strncmp((p_all_par+ii)->name,"es_y",4)==0) {
3898 abest[jj]=p_xs_3->es_y;
3899 amin[jj]=p_xs_3->es_y-(1.0*ann_fac);
3900 amax[jj]=p_xs_3->es_y+(1.0*ann_fac);
3901 aname[jj]=ii;
3902 jj+=1;
3903 }
3904 /* chip[x/y] is the offset of the detector in the focal plane*/
3905 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
3906 abest[jj]=p_xs_3->chipx;
3907 amin[jj]=p_xs_3->chipx-(5.0*ann_fac);
3908 amax[jj]=p_xs_3->chipx+(5.0*ann_fac);
3909 aname[jj]=ii;
3910 jj+=1;
3911 }
3912 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
3913 abest[jj]=p_xs_3->chipy;
3914 amin[jj]=p_xs_3->chipy-(5.0*ann_fac);
3915 amax[jj]=p_xs_3->chipy+(5.0*ann_fac);
3916 aname[jj]=ii;
3917 jj+=1;
3918 }
3919 /* sg is the grating constant*/
3920 if (strncmp((p_all_par+ii)->name,"sg",2)==0) {
3921 abest[jj]=p_xs_3->sg;
3922 amin[jj]=p_xs_3->sg-(1.0*ann_fac);
3923 amax[jj]=p_xs_3->sg+(1.0*ann_fac);
3924 aname[jj]=ii;
3925 jj+=1;
3926 }
3927 }
3928 if (scenario==2) {
3929 /* For the 9ph start scenario (2) add the parameters that will
3930 effect any of the pinholes and may realistically have physically
3931 changed due to intervention etc. (NOTE, it is assumed that "normal"
3932 interventions will not involve replacing the pinhole mask with a
3933 new one, therefore the slit positions are NOT included here. The
3934 tolerances are >> than any realistic physical movement. This takes
3935 the total open parameters to 17 for UVB/VIS, 21 for NIR*/
3936 /*taues is the rotation angle of the entrance slit*/
3937 if (strncmp((p_all_par+ii)->name,"taues",5)==0) {
3938 aname[jj]=ii;
3939 abest[jj]=p_xs_3->taues/DEG2RAD;
3940 amin[jj]=p_xs_3->taues/DEG2RAD-(5.0*ann_fac);
3941 amax[jj]=p_xs_3->taues/DEG2RAD+(5.0*ann_fac);
3942 jj+=1;
3943 }
3944 /*fcol is the focal length of the collimator.*/
3945 if (strncmp((p_all_par+ii)->name,"fcol",4)==0) {
3946 abest[jj]=p_xs_3->fcol;
3947 amin[jj]=p_xs_3->fcol-(5.0*ann_fac);
3948 amax[jj]=p_xs_3->fcol+(5.0*ann_fac);
3949 aname[jj]=ii;
3950 jj+=1;
3951 }
3952 /*slit_scale is the scale of the entrance slit in mm/" */
3953 if (strncmp((p_all_par+ii)->name,"slit_scale",10)==0) {
3954 abest[jj]=p_xs_3->slit_scale;
3955 amin[jj]=p_xs_3->slit_scale-(0.05*ann_fac);
3956 amax[jj]=p_xs_3->slit_scale+(0.05*ann_fac);
3957 aname[jj]=ii;
3958 jj+=1;
3959 }
3960 /*es_x is the location of the central pinhole across the entrance
3961 slit in mm*/
3962 if (strncmp((p_all_par+ii)->name,"es_x",4)==0) {
3963 abest[jj]=p_xs_3->es_x;
3964 amin[jj]=p_xs_3->es_x-(0.1*ann_fac);
3965 amax[jj]=p_xs_3->es_x+(0.1*ann_fac);
3966 aname[jj]=ii;
3967 jj+=1;
3968 }
3969 }
3970 }
3971 adim=jj;
3972 }
3973 if (scenario>2) {
3974 /* For the regular scenario (3) very small changes are allowed for
3975 all active parameters, except the distortion coefficients*/
3976 for (ii=0;ii<100;ii++) {
3977 if (scenario<6) {
3978/* if (strncmp((p_all_par+ii)->name,"temper",6)==0) { */
3979/* aname[jj]=ii; */
3980/* abest[jj]=p_xs_3->temper; */
3981/* amin[jj]=p_xs_3->temper-(5.0*ann_fac); */
3982/* amax[jj]=p_xs_3->temper+(5.0*ann_fac); */
3983/* jj+=1; */
3984/* } */
3985 /*es_y is the location of the central pinhole along the entrance
3986 slit in mm*/
3987 if (strncmp((p_all_par+ii)->name,"es_y",4)==0) {
3988 abest[jj]=p_xs_3->es_y;
3989 amin[jj]=p_xs_3->es_y-(0.01*ann_fac);
3990 amax[jj]=p_xs_3->es_y+(0.01*ann_fac);
3991 aname[jj]=ii;
3992 jj+=1;
3993 }
3994 /*es_x is the location of the central pinhole across the entrance
3995 slit in mm*/
3996 if (strncmp((p_all_par+ii)->name,"es_x",4)==0) {
3997 abest[jj]=p_xs_3->es_x;
3998 amin[jj]=p_xs_3->es_x-(0.01*ann_fac);
3999 amax[jj]=p_xs_3->es_x+(0.01*ann_fac);
4000 aname[jj]=ii;
4001 jj+=1;
4002 }
4003 /*[mu/nu/tau]p1 are the orientation of the entrance surface (and hence
4004 the whole prism) of the first prism */
4005 if (strncmp((p_all_par+ii)->name,"mup1",4)==0) {
4006 aname[jj]=ii;
4007 abest[jj]=p_xs_3->mup1/DEG2RAD;
4008 amin[jj]=p_xs_3->mup1/DEG2RAD-(0.005*ann_fac);
4009 amax[jj]=p_xs_3->mup1/DEG2RAD+(0.005*ann_fac);
4010 jj+=1;
4011 }
4012 if (strncmp((p_all_par+ii)->name,"nup1",4)==0) {
4013 aname[jj]=ii;
4014 abest[jj]=p_xs_3->nup1/DEG2RAD;
4015 amin[jj]=p_xs_3->nup1/DEG2RAD-(0.005*ann_fac);
4016 amax[jj]=p_xs_3->nup1/DEG2RAD+(0.005*ann_fac);
4017 jj+=1;
4018 }
4019/* if (strncmp((p_all_par+ii)->name,"taup1",5)==0) { */
4020/* aname[jj]=ii; */
4021/* abest[jj]=p_xs_3->taup1/DEG2RAD; */
4022/* amin[jj]=p_xs_3->taup1/DEG2RAD-(0.005*ann_fac); */
4023/* amax[jj]=p_xs_3->taup1/DEG2RAD+(0.005*ann_fac); */
4024/* jj+=1; */
4025/* } */
4026 /*[mu/nu/tau]p2 are the orientation of the exit surface
4027 of the first prism*/
4028 if (strncmp((p_all_par+ii)->name,"mup2",4)==0) {
4029 aname[jj]=ii;
4030 abest[jj]=p_xs_3->mup2/DEG2RAD;
4031 amin[jj]=p_xs_3->mup2/DEG2RAD-(0.005*ann_fac);
4032 amax[jj]=p_xs_3->mup2/DEG2RAD+(0.005*ann_fac);
4033 jj+=1;
4034 }
4035 if (strncmp((p_all_par+ii)->name,"nup2",4)==0) {
4036 aname[jj]=ii;
4037 abest[jj]=p_xs_3->nup2/DEG2RAD;
4038 amin[jj]=p_xs_3->nup2/DEG2RAD-(0.005*ann_fac);
4039 amax[jj]=p_xs_3->nup2/DEG2RAD+(0.005*ann_fac);
4040 jj+=1;
4041 }
4042/* if (strncmp((p_all_par+ii)->name,"taup2",5)==0) { */
4043/* aname[jj]=ii; */
4044/* abest[jj]=p_xs_3->taup2/DEG2RAD; */
4045/* amin[jj]=p_xs_3->taup2/DEG2RAD-(0.005*ann_fac); */
4046/* amax[jj]=p_xs_3->taup2/DEG2RAD+(0.005*ann_fac); */
4047/* jj+=1; */
4048/* } */
4049 if (p_xs_3->arm==2) {
4050 /*[mu/nu/tau]p3 are the orientation of the entrance surface (and hence
4051 the whole prism) of the second prism*/
4052 if (strncmp((p_all_par+ii)->name,"mup3",4)==0) {
4053 aname[jj]=ii;
4054 abest[jj]=p_xs_3->mup3/DEG2RAD;
4055 amin[jj]=p_xs_3->mup3/DEG2RAD-(0.005*ann_fac);
4056 amax[jj]=p_xs_3->mup3/DEG2RAD+(0.005*ann_fac);
4057 jj+=1;
4058 }
4059 if (strncmp((p_all_par+ii)->name,"nup3",4)==0) {
4060 aname[jj]=ii;
4061 abest[jj]=p_xs_3->nup3/DEG2RAD;
4062 amin[jj]=p_xs_3->nup3/DEG2RAD-(0.005*ann_fac);
4063 amax[jj]=p_xs_3->nup3/DEG2RAD+(0.005*ann_fac);
4064 jj+=1;
4065 }
4066/* if (strncmp((p_all_par+ii)->name,"taup3",5)==0) { */
4067/* aname[jj]=ii; */
4068/* abest[jj]=p_xs_3->taup3/DEG2RAD; */
4069/* amin[jj]=p_xs_3->taup3/DEG2RAD-(0.005*ann_fac); */
4070/* amax[jj]=p_xs_3->taup3/DEG2RAD+(0.005*ann_fac); */
4071/* jj+=1; */
4072/* } */
4073/* /\*[mu/nu/tau]p4 are the orientation of the exit surface */
4074/* of the second prism*\/ */
4075 if (strncmp((p_all_par+ii)->name,"mup4",4)==0) {
4076 aname[jj]=ii;
4077 abest[jj]=p_xs_3->mup4/DEG2RAD;
4078 amin[jj]=p_xs_3->mup4/DEG2RAD-(0.005*ann_fac);
4079 amax[jj]=p_xs_3->mup4/DEG2RAD+(0.005*ann_fac);
4080 jj+=1;
4081 }
4082 if (strncmp((p_all_par+ii)->name,"nup4",4)==0) {
4083 aname[jj]=ii;
4084 abest[jj]=p_xs_3->nup4/DEG2RAD;
4085 amin[jj]=p_xs_3->nup4/DEG2RAD-(0.005*ann_fac);
4086 amax[jj]=p_xs_3->nup4/DEG2RAD+(0.005*ann_fac);
4087 jj+=1;
4088 }
4089/* if (strncmp((p_all_par+ii)->name,"taup4",5)==0) { */
4090/* aname[jj]=ii; */
4091/* abest[jj]=p_xs_3->taup4/DEG2RAD; */
4092/* amin[jj]=p_xs_3->taup4/DEG2RAD-(0.005*ann_fac); */
4093/* amax[jj]=p_xs_3->taup4/DEG2RAD+(0.005*ann_fac); */
4094/* jj+=1; */
4095/* } */
4096 /*[mu/nu/tau]p5 are the orientation of the entrance surface (and hence
4097 the whole prism) of the third prism*/
4098 if (strncmp((p_all_par+ii)->name,"mup5",4)==0) {
4099 aname[jj]=ii;
4100 abest[jj]=p_xs_3->mup5/DEG2RAD;
4101 amin[jj]=p_xs_3->mup5/DEG2RAD-(0.005*ann_fac);
4102 amax[jj]=p_xs_3->mup5/DEG2RAD+(0.005*ann_fac);
4103 jj+=1;
4104 }
4105 if (strncmp((p_all_par+ii)->name,"nup5",4)==0) {
4106 aname[jj]=ii;
4107 abest[jj]=p_xs_3->nup5/DEG2RAD;
4108 amin[jj]=p_xs_3->nup5/DEG2RAD-(0.005*ann_fac);
4109 amax[jj]=p_xs_3->nup5/DEG2RAD+(0.005*ann_fac);
4110 jj+=1;
4111 }
4112/* if (strncmp((p_all_par+ii)->name,"taup5",5)==0) { */
4113/* aname[jj]=ii; */
4114/* abest[jj]=p_xs_3->taup5/DEG2RAD; */
4115/* amin[jj]=p_xs_3->taup5/DEG2RAD-(0.005*ann_fac); */
4116/* amax[jj]=p_xs_3->taup5/DEG2RAD+(0.005*ann_fac); */
4117/* jj+=1; */
4118/* } */
4119/* /\*[mu/nu]p6 are the tip and tilt of the exit surface */
4120/* of the third prism*\/ */
4121 if (strncmp((p_all_par+ii)->name,"mup6",4)==0) {
4122 aname[jj]=ii;
4123 abest[jj]=p_xs_3->mup6/DEG2RAD;
4124 amin[jj]=p_xs_3->mup6/DEG2RAD-(0.005*ann_fac);
4125 amax[jj]=p_xs_3->mup6/DEG2RAD+(0.005*ann_fac);
4126 jj+=1;
4127 }
4128 if (strncmp((p_all_par+ii)->name,"nup6",4)==0) {
4129 aname[jj]=ii;
4130 abest[jj]=p_xs_3->nup6/DEG2RAD;
4131 amin[jj]=p_xs_3->nup6/DEG2RAD-(0.005*ann_fac);
4132 amax[jj]=p_xs_3->nup6/DEG2RAD+(0.005*ann_fac);
4133 jj+=1;
4134 }
4135/* if (strncmp((p_all_par+ii)->name,"taup6",5)==0) { */
4136/* aname[jj]=ii; */
4137/* abest[jj]=p_xs_3->taup6/DEG2RAD; */
4138/* amin[jj]=p_xs_3->taup6/DEG2RAD-(0.005*ann_fac); */
4139/* amax[jj]=p_xs_3->taup6/DEG2RAD+(0.005*ann_fac); */
4140/* jj+=1; */
4141/* } */
4142 }
4143 /*[mu/nu/tau]g describe the orientation of the grating*/
4144 if (strncmp((p_all_par+ii)->name,"mug",3)==0) {
4145 aname[jj]=ii;
4146 abest[jj]=p_xs_3->mug/DEG2RAD;
4147 amin[jj]=p_xs_3->mug/DEG2RAD-(0.05*ann_fac);
4148 amax[jj]=p_xs_3->mug/DEG2RAD+(0.05*ann_fac);
4149 jj+=1;
4150 }
4151 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
4152 aname[jj]=ii;
4153 abest[jj]=p_xs_3->nug/DEG2RAD;
4154 amin[jj]=p_xs_3->nug/DEG2RAD-(0.5*ann_fac);
4155 amax[jj]=p_xs_3->nug/DEG2RAD+(0.5*ann_fac);
4156 jj+=1;
4157 }
4158 if (strncmp((p_all_par+ii)->name,"taug",4)==0) {
4159 aname[jj]=ii;
4160 abest[jj]=p_xs_3->taug/DEG2RAD;
4161 amin[jj]=p_xs_3->taug/DEG2RAD-(0.05*ann_fac);
4162 amax[jj]=p_xs_3->taug/DEG2RAD+(0.05*ann_fac);
4163 jj+=1;
4164 }
4165 /*[mu/nu/tau]d describe the orientation of the detector*/
4166 if (strncmp((p_all_par+ii)->name,"mud",3)==0) {
4167 aname[jj]=ii;
4168 abest[jj]=p_xs_3->mud/DEG2RAD;
4169 amin[jj]=p_xs_3->mud/DEG2RAD-(0.005*ann_fac);
4170 amax[jj]=p_xs_3->mud/DEG2RAD+(0.005*ann_fac);
4171 jj+=1;
4172 }
4173 if (strncmp((p_all_par+ii)->name,"nud",3)==0) {
4174 aname[jj]=ii;
4175 abest[jj]=p_xs_3->nud/DEG2RAD;
4176 amin[jj]=p_xs_3->nud/DEG2RAD-(0.005*ann_fac);
4177 amax[jj]=p_xs_3->nud/DEG2RAD+(0.005*ann_fac);
4178 jj+=1;
4179 }
4180 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
4181 aname[jj]=ii;
4182 abest[jj]=p_xs_3->taud/DEG2RAD;
4183 amin[jj]=p_xs_3->taud/DEG2RAD-(0.05*ann_fac);
4184 amax[jj]=p_xs_3->taud/DEG2RAD+(0.05*ann_fac);
4185 jj+=1;
4186 }
4187 /*fdet is the focal length of the camera*/
4188 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
4189 abest[jj]=p_xs_3->fdet;
4190 amin[jj]=p_xs_3->fdet-(0.1*ann_fac);
4191 amax[jj]=p_xs_3->fdet+(0.1*ann_fac);
4192 aname[jj]=ii;
4193 jj+=1;
4194 }
4195 /* chip[x/y] is the offset of the detector in the focal plane*/
4196 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4197 abest[jj]=p_xs_3->chipx;
4198 amin[jj]=p_xs_3->chipx-(0.05*ann_fac);
4199 amax[jj]=p_xs_3->chipx+(0.05*ann_fac);
4200 aname[jj]=ii;
4201 jj+=1;
4202 }
4203 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4204 abest[jj]=p_xs_3->chipy;
4205 amin[jj]=p_xs_3->chipy-(0.05*ann_fac);
4206 amax[jj]=p_xs_3->chipy+(0.05*ann_fac);
4207 aname[jj]=ii;
4208 jj+=1;
4209 }
4210 /* sg is the grating constant*/
4211 if (strncmp((p_all_par+ii)->name,"sg",2)==0) {
4212 abest[jj]=p_xs_3->sg;
4213 amin[jj]=p_xs_3->sg-(0.5*ann_fac);
4214 amax[jj]=p_xs_3->sg+(0.5*ann_fac);
4215 aname[jj]=ii;
4216 jj+=1;
4217 }
4218 /*Open also the 1st order terms of the distortion correction, it turns out that
4219 this is the only way to remove unwanted trends in the residuals*/
4220 if (strncmp((p_all_par+ii)->name,"pc_x_y1",7)==0) {
4221 abest[jj]=p_xs_3->pc_x_y1;
4222 amin[jj]=p_xs_3->pc_x_y1-(0.01*ann_fac);
4223 amax[jj]=p_xs_3->pc_x_y1+(0.01*ann_fac);
4224 aname[jj]=ii;
4225 jj+=1;
4226 }
4227 if (strncmp((p_all_par+ii)->name,"pc_y_x1",7)==0) {
4228 abest[jj]=p_xs_3->pc_y_x1;
4229 amin[jj]=p_xs_3->pc_y_x1-(0.01*ann_fac);
4230 amax[jj]=p_xs_3->pc_y_x1+(0.01*ann_fac);
4231 aname[jj]=ii;
4232 jj+=1;
4233 }
4234 if (strncmp((p_all_par+ii)->name,"pc_x_x1",7)==0) {
4235 abest[jj]=p_xs_3->pc_x_x1;
4236 amin[jj]=p_xs_3->pc_x_x1-(0.01*ann_fac);
4237 amax[jj]=p_xs_3->pc_x_x1+(0.01*ann_fac);
4238 aname[jj]=ii;
4239 jj+=1;
4240 }
4241 if (strncmp((p_all_par+ii)->name,"pc_y_y1",7)==0) {
4242 abest[jj]=p_xs_3->pc_y_y1;
4243 amin[jj]=p_xs_3->pc_y_y1-(0.01*ann_fac);
4244 amax[jj]=p_xs_3->pc_y_y1+(0.01*ann_fac);
4245 aname[jj]=ii;
4246 jj+=1;
4247 }
4248 if (scenario>3) {
4249 /*for scenario 4 & 5 include the parameters that affect the
4250 non-central slit positions*/
4251 /*slit_scale is the scale of the entrance slit in mm/" */
4252 if (strncmp((p_all_par+ii)->name,"slit_scale",10)==0) {
4253 abest[jj]=p_xs_3->slit_scale;
4254 amin[jj]=p_xs_3->slit_scale-(0.01*ann_fac);
4255 amax[jj]=p_xs_3->slit_scale+(0.01*ann_fac);
4256 aname[jj]=ii;
4257 jj+=1;
4258 }
4259 /*taues is the rotation angle of the entrance slit*/
4260 if (strncmp((p_all_par+ii)->name,"taues",5)==0) {
4261 aname[jj]=ii;
4262 abest[jj]=p_xs_3->taues/DEG2RAD;
4263 amin[jj]=p_xs_3->taues/DEG2RAD-(0.1*ann_fac);
4264 amax[jj]=p_xs_3->taues/DEG2RAD+(0.1*ann_fac);
4265 jj+=1;
4266 }
4267 /*offx,y describe the chromatic/slit posn correction*/
4268/* if (strncmp((p_all_par+ii)->name,"offx",4)==0) { */
4269/* abest[jj]=0.0;//p_xs_3->offx; */
4270/* amin[jj]=-500.0;//p_xs_3->offx-(20.0*ann_fac); */
4271/* amax[jj]=500.0;//p_xs_3->offx+(20.0*ann_fac); */
4272/* aname[jj]=ii; */
4273/* jj+=1; */
4274/* } */
4275/* if (strncmp((p_all_par+ii)->name,"offy",4)==0) { */
4276/* abest[jj]=0.0012;//p_xs_3->offy; */
4277/* amin[jj]=0.001;//p_xs_3->offy-(0.00001*ann_fac); */
4278/* amax[jj]=0.0025;//p_xs_3->offy+(0.00001*ann_fac); */
4279/* aname[jj]=ii; */
4280/* jj+=1; */
4281/* } */
4282 /*fcol is the focal length of the collimator.*/
4283 if (strncmp((p_all_par+ii)->name,"fcol",4)==0) {
4284 abest[jj]=p_xs_3->fcol;
4285 amin[jj]=p_xs_3->fcol-(0.1*ann_fac);
4286 amax[jj]=p_xs_3->fcol+(0.1*ann_fac);
4287 aname[jj]=ii;
4288 jj+=1;
4289 }
4290/* p_xs_3->slit[0]=-5.6; */
4291/* p_xs_3->slit[1]=-4.2; */
4292/* p_xs_3->slit[2]=-2.8; */
4293/* p_xs_3->slit[3]=-1.4; */
4294/* p_xs_3->slit[4]=0.0; */
4295/* p_xs_3->slit[5]=1.4; */
4296/* p_xs_3->slit[6]=2.8; */
4297/* p_xs_3->slit[7]=4.2; */
4298/* p_xs_3->slit[8]=5.6; */
4299 /*slit[0-8] are the postions of the 9 pinholes along the slit
4300 in arcsec*/
4301/* if (strncmp((p_all_par+ii)->name,"slit[0]",7)==0) { */
4302/* abest[jj]=p_xs_3->slit[0]; */
4303/* amin[jj]=p_xs_3->slit[0]-(0.01*ann_fac); */
4304/* amax[jj]=p_xs_3->slit[0]+(0.01*ann_fac); */
4305/* aname[jj]=ii; */
4306/* jj+=1; */
4307/* } */
4308/* if (strncmp((p_all_par+ii)->name,"slit[1]",7)==0) { */
4309/* abest[jj]=p_xs_3->slit[1]; */
4310/* amin[jj]=p_xs_3->slit[1]-(0.01*ann_fac); */
4311/* amax[jj]=p_xs_3->slit[1]+(0.01*ann_fac); */
4312/* aname[jj]=ii; */
4313/* jj+=1; */
4314/* } */
4315/* if (strncmp((p_all_par+ii)->name,"slit[2]",7)==0) { */
4316/* abest[jj]=p_xs_3->slit[2]; */
4317/* amin[jj]=p_xs_3->slit[2]-(0.01*ann_fac); */
4318/* amax[jj]=p_xs_3->slit[2]+(0.01*ann_fac); */
4319/* aname[jj]=ii; */
4320/* jj+=1; */
4321/* } */
4322/* if (strncmp((p_all_par+ii)->name,"slit[3]",7)==0) { */
4323/* abest[jj]=p_xs_3->slit[3]; */
4324/* amin[jj]=p_xs_3->slit[3]-(0.01*ann_fac); */
4325/* amax[jj]=p_xs_3->slit[3]+(0.01*ann_fac); */
4326/* aname[jj]=ii; */
4327/* jj+=1; */
4328/* } */
4329/* /\* if (strncmp((p_all_par+ii)->name,"slit[4]",7)==0) { *\/ */
4330/* /\* abest[jj]=p_xs_3->slit[4]; *\/ */
4331/* /\* amin[jj]=p_xs_3->slit[4]-(0.001*ann_fac); *\/ */
4332/* /\* amax[jj]=p_xs_3->slit[4]+(0.001*ann_fac); *\/ */
4333/* /\* aname[jj]=ii; *\/ */
4334/* /\* jj+=1; *\/ */
4335/* /\* } *\/ */
4336/* if (strncmp((p_all_par+ii)->name,"slit[5]",7)==0) { */
4337/* abest[jj]=p_xs_3->slit[5]; */
4338/* amin[jj]=p_xs_3->slit[5]-(0.01*ann_fac); */
4339/* amax[jj]=p_xs_3->slit[5]+(0.01*ann_fac); */
4340/* aname[jj]=ii; */
4341/* jj+=1; */
4342/* } */
4343/* if (strncmp((p_all_par+ii)->name,"slit[6]",7)==0) { */
4344/* abest[jj]=p_xs_3->slit[6]; */
4345/* amin[jj]=p_xs_3->slit[6]-(0.01*ann_fac); */
4346/* amax[jj]=p_xs_3->slit[6]+(0.01*ann_fac); */
4347/* aname[jj]=ii; */
4348/* jj+=1; */
4349/* } */
4350/* if (strncmp((p_all_par+ii)->name,"slit[7]",7)==0) { */
4351/* abest[jj]=p_xs_3->slit[7]; */
4352/* amin[jj]=p_xs_3->slit[7]-(0.01*ann_fac); */
4353/* amax[jj]=p_xs_3->slit[7]+(0.01*ann_fac); */
4354/* aname[jj]=ii; */
4355/* jj+=1; */
4356/* } */
4357/* if (strncmp((p_all_par+ii)->name,"slit[8]",7)==0) { */
4358/* abest[jj]=p_xs_3->slit[8]; */
4359/* amin[jj]=p_xs_3->slit[8]-(0.01*ann_fac); */
4360/* amax[jj]=p_xs_3->slit[8]+(0.01*ann_fac); */
4361/* aname[jj]=ii; */
4362/* jj+=1; */
4363/* } */
4364 }
4365 }
4366 if (scenario>=5 && scenario<8) {
4367 if (scenario==6) {
4368 /*5 is the scenario where we just want to optimise distortion coefficients.
4369 Since we are in the scenario >2 loop, but we omitted all the non dist coef
4370 settings explicitly for the scenario==6 case earlier, we need to set chipx/y
4371 here (they will have already been set for scenario==5)*/
4372 /* chip[x/y] is the offset of the detector in the focal plane*/
4373 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4374 abest[jj]=p_xs_3->chipx;
4375 amin[jj]=p_xs_3->chipx-(0.1*ann_fac);
4376 amax[jj]=p_xs_3->chipx+(0.1*ann_fac);
4377 aname[jj]=ii;
4378 jj+=1;
4379 }
4380 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4381 abest[jj]=p_xs_3->chipy;
4382 amin[jj]=p_xs_3->chipy-(0.1*ann_fac);
4383 amax[jj]=p_xs_3->chipy+(0.1*ann_fac);
4384 aname[jj]=ii;
4385 jj+=1;
4386 }
4387 }
4388/* p_xs_3->pc_x_x1=1.0; */
4389/* p_xs_3->pc_y_y1=1.0; */
4390/* p_xs_3->pc_x_y1=0.0; */
4391/* p_xs_3->pc_y_x1=0.0; */
4392/* p_xs_3->pc_x_xx=0.0; */
4393/* p_xs_3->pc_x_yy=0.0; */
4394/* p_xs_3->pc_x_xy=0.0; */
4395/* p_xs_3->pc_x_x3=0.0; */
4396/* p_xs_3->pc_x_y3=0.0; */
4397/* p_xs_3->pc_x_x2y=0.0; */
4398/* p_xs_3->pc_x_y2x=0.0; */
4399/* p_xs_3->pc_y_xx=0.0; */
4400/* p_xs_3->pc_y_yy=0.0; */
4401/* p_xs_3->pc_y_xy=0.0; */
4402/* p_xs_3->pc_y_x3=0.0; */
4403/* p_xs_3->pc_y_y3=0.0; */
4404/* p_xs_3->pc_y_x2y=0.0; */
4405/* p_xs_3->pc_y_y2x=0.0; */
4406/* p_xs_3->d2_x1=0.0; */
4407/* p_xs_3->d2_x2=0.0; */
4408/* p_xs_3->d2_x3=0.0; */
4409/* p_xs_3->d2_y1x0=0.0; */
4410/* p_xs_3->d2_y1x1=0.0; */
4411/* p_xs_3->d2_y2x0=0.0; */
4412/* p_xs_3->d2_y2x1=0.0; */
4413/* p_xs_3->d2_y3x0=0.0; */
4414/* p_xs_3->d2_y3x1=0.0; */
4415
4416 /* For the refine dist_coefs scenarios (5 or 6), we allow very small changes
4417 to the distortion coeffs as well*/
4418 if (strncmp((p_all_par+ii)->name,"pc_x_x1",7)==0) {
4419 abest[jj]=p_xs_3->pc_x_x1;
4420 amin[jj]=p_xs_3->pc_x_x1-(0.001*ann_fac);
4421 amax[jj]=p_xs_3->pc_x_x1+(0.001*ann_fac);
4422 aname[jj]=ii;
4423 jj+=1;
4424 }
4425 if (strncmp((p_all_par+ii)->name,"pc_x_xx",7)==0) {
4426 abest[jj]=p_xs_3->pc_x_xx;
4427 amin[jj]=p_xs_3->pc_x_xx-(0.0001*ann_fac);
4428 amax[jj]=p_xs_3->pc_x_xx+(0.0001*ann_fac);
4429 aname[jj]=ii;
4430 jj+=1;
4431 }
4432 if (strncmp((p_all_par+ii)->name,"pc_x_y1",7)==0) {
4433 abest[jj]=p_xs_3->pc_x_y1;
4434 amin[jj]=p_xs_3->pc_x_y1-(0.001*ann_fac);
4435 amax[jj]=p_xs_3->pc_x_y1+(0.001*ann_fac);
4436 aname[jj]=ii;
4437 jj+=1;
4438 }
4439 if (strncmp((p_all_par+ii)->name,"pc_x_yy",7)==0) {
4440 abest[jj]=p_xs_3->pc_x_yy;
4441 amin[jj]=p_xs_3->pc_x_yy-(0.0001*ann_fac);
4442 amax[jj]=p_xs_3->pc_x_yy+(0.0001*ann_fac);
4443 aname[jj]=ii;
4444 jj+=1;
4445 }
4446 if (strncmp((p_all_par+ii)->name,"pc_x_xy",7)==0) {
4447 abest[jj]=p_xs_3->pc_x_xy;
4448 amin[jj]=p_xs_3->pc_x_xy-(0.0001*ann_fac);
4449 amax[jj]=p_xs_3->pc_x_xy+(0.0001*ann_fac);
4450 aname[jj]=ii;
4451 jj+=1;
4452 }
4453 if (strncmp((p_all_par+ii)->name,"pc_x_x2y",8)==0) {
4454 abest[jj]=p_xs_3->pc_x_x2y;
4455 amin[jj]=p_xs_3->pc_x_x2y-(0.00001*ann_fac);
4456 amax[jj]=p_xs_3->pc_x_x2y+(0.00001*ann_fac);
4457 aname[jj]=ii;
4458 jj+=1;
4459 }
4460 if (strncmp((p_all_par+ii)->name,"pc_x_y2x",8)==0) {
4461 abest[jj]=p_xs_3->pc_x_y2x;
4462 amin[jj]=p_xs_3->pc_x_y2x-(0.00001*ann_fac);
4463 amax[jj]=p_xs_3->pc_x_y2x+(0.00001*ann_fac);
4464 aname[jj]=ii;
4465 jj+=1;
4466 }
4467 if (strncmp((p_all_par+ii)->name,"pc_x_x3",7)==0) {
4468 abest[jj]=p_xs_3->pc_x_x3;
4469 amin[jj]=p_xs_3->pc_x_x3-(0.00001*ann_fac);
4470 amax[jj]=p_xs_3->pc_x_x3+(0.00001*ann_fac);
4471 aname[jj]=ii;
4472 jj+=1;
4473 }
4474 if (strncmp((p_all_par+ii)->name,"pc_x_y3",7)==0) {
4475 abest[jj]=p_xs_3->pc_x_y3;
4476 amin[jj]=p_xs_3->pc_x_y3-(0.00001*ann_fac);
4477 amax[jj]=p_xs_3->pc_x_y3+(0.00001*ann_fac);
4478 aname[jj]=ii;
4479 jj+=1;
4480 }
4481 if (strncmp((p_all_par+ii)->name,"pc_y_x1",7)==0) {
4482 abest[jj]=p_xs_3->pc_y_x1;
4483 amin[jj]=p_xs_3->pc_y_x1-(0.001*ann_fac);
4484 amax[jj]=p_xs_3->pc_y_x1+(0.001*ann_fac);
4485 aname[jj]=ii;
4486 jj+=1;
4487 }
4488 if (strncmp((p_all_par+ii)->name,"pc_y_xx",7)==0) {
4489 abest[jj]=p_xs_3->pc_y_xx;
4490 amin[jj]=p_xs_3->pc_y_xx-(0.0001*ann_fac);
4491 amax[jj]=p_xs_3->pc_y_xx+(0.0001*ann_fac);
4492 aname[jj]=ii;
4493 jj+=1;
4494 }
4495 if (strncmp((p_all_par+ii)->name,"pc_y_y1",7)==0) {
4496 abest[jj]=p_xs_3->pc_y_y1;
4497 amin[jj]=p_xs_3->pc_y_y1-(0.001*ann_fac);
4498 amax[jj]=p_xs_3->pc_y_y1+(0.001*ann_fac);
4499 aname[jj]=ii;
4500 jj+=1;
4501 }
4502 if (strncmp((p_all_par+ii)->name,"pc_y_yy",7)==0) {
4503 abest[jj]=p_xs_3->pc_y_yy;
4504 amin[jj]=p_xs_3->pc_y_yy-(0.0001*ann_fac);
4505 amax[jj]=p_xs_3->pc_y_yy+(0.0001*ann_fac);
4506 aname[jj]=ii;
4507 jj+=1;
4508 }
4509 if (strncmp((p_all_par+ii)->name,"pc_y_xy",7)==0) {
4510 abest[jj]=p_xs_3->pc_y_xy;
4511 amin[jj]=p_xs_3->pc_y_xy-(0.0001*ann_fac);
4512 amax[jj]=p_xs_3->pc_y_xy+(0.0001*ann_fac);
4513 aname[jj]=ii;
4514 jj+=1;
4515 }
4516 if (strncmp((p_all_par+ii)->name,"pc_y_x2y",8)==0) {
4517 abest[jj]=p_xs_3->pc_y_x2y;
4518 amin[jj]=p_xs_3->pc_y_x2y-(0.00001*ann_fac);
4519 amax[jj]=p_xs_3->pc_y_x2y+(0.00001*ann_fac);
4520 aname[jj]=ii;
4521 jj+=1;
4522 }
4523 if (strncmp((p_all_par+ii)->name,"pc_y_y2x",8)==0) {
4524 abest[jj]=p_xs_3->pc_y_y2x;
4525 amin[jj]=p_xs_3->pc_y_y2x-(0.00001*ann_fac);
4526 amax[jj]=p_xs_3->pc_y_y2x+(0.00001*ann_fac);
4527 aname[jj]=ii;
4528 jj+=1;
4529 }
4530 if (strncmp((p_all_par+ii)->name,"pc_y_x3",7)==0) {
4531 abest[jj]=p_xs_3->pc_y_x3;
4532 amin[jj]=p_xs_3->pc_y_x3-(0.00001*ann_fac);
4533 amax[jj]=p_xs_3->pc_y_x3+(0.00001*ann_fac);
4534 aname[jj]=ii;
4535 jj+=1;
4536 }
4537 if (strncmp((p_all_par+ii)->name,"pc_y_y3",7)==0) {
4538 abest[jj]=p_xs_3->pc_y_y3;
4539 amin[jj]=p_xs_3->pc_y_y3-(0.00001*ann_fac);
4540 amax[jj]=p_xs_3->pc_y_y3+(0.00001*ann_fac);
4541 aname[jj]=ii;
4542 jj+=1;
4543 }
4544 if (p_xs_3->arm<2) {
4545 if (strncmp((p_all_par+ii)->name,"d2_x1",5)==0) {
4546 abest[jj]=p_xs_3->d2_x1;
4547 amin[jj]=p_xs_3->d2_x1-(0.01*ann_fac);
4548 amax[jj]=p_xs_3->d2_x1+(0.01*ann_fac);
4549 aname[jj]=ii;
4550 jj+=1;
4551 }
4552 if (strncmp((p_all_par+ii)->name,"d2_x2",5)==0) {
4553 abest[jj]=p_xs_3->d2_x2;
4554 amin[jj]=p_xs_3->d2_x2-(0.001*ann_fac);
4555 amax[jj]=p_xs_3->d2_x2+(0.001*ann_fac);
4556 aname[jj]=ii;
4557 jj+=1;
4558 }
4559 if (strncmp((p_all_par+ii)->name,"d2_x3",5)==0) {
4560 abest[jj]=p_xs_3->d2_x3;
4561 amin[jj]=p_xs_3->d2_x3-(0.0001*ann_fac);
4562 amax[jj]=p_xs_3->d2_x3+(0.0001*ann_fac);
4563 aname[jj]=ii;
4564 jj+=1;
4565 }
4566 }
4567 else if (p_xs_3->arm==2) {
4568 if (strncmp((p_all_par+ii)->name,"pc4_x_xy3",9)==0) {
4569 abest[jj]=p_xs_3->pc4_x_xy3;
4570 amin[jj]=p_xs_3->pc4_x_xy3-(0.000001*ann_fac);
4571 amax[jj]=p_xs_3->pc4_x_xy3+(0.000001*ann_fac);
4572 aname[jj]=ii;
4573 jj+=1;
4574 }
4575 if (strncmp((p_all_par+ii)->name,"pc4_x_x3y",9)==0) {
4576 abest[jj]=p_xs_3->pc4_x_x3y;
4577 amin[jj]=p_xs_3->pc4_x_x3y-(0.000001*ann_fac);
4578 amax[jj]=p_xs_3->pc4_x_x3y+(0.000001*ann_fac);
4579 aname[jj]=ii;
4580 jj+=1;
4581 }
4582 if (strncmp((p_all_par+ii)->name,"pc4_x_x2y2",10)==0) {
4583 abest[jj]=p_xs_3->pc4_x_x2y2;
4584 amin[jj]=p_xs_3->pc4_x_x2y2-(0.000001*ann_fac);
4585 amax[jj]=p_xs_3->pc4_x_x2y2+(0.000001*ann_fac);
4586 aname[jj]=ii;
4587 jj+=1;
4588 }
4589 if (strncmp((p_all_par+ii)->name,"pc4_x_x4",8)==0) {
4590 abest[jj]=p_xs_3->pc4_x_x4;
4591 amin[jj]=p_xs_3->pc4_x_x4-(0.000001*ann_fac);
4592 amax[jj]=p_xs_3->pc4_x_x4+(0.000001*ann_fac);
4593 aname[jj]=ii;
4594 jj+=1;
4595 }
4596 if (strncmp((p_all_par+ii)->name,"pc4_x_y4",8)==0) {
4597 abest[jj]=p_xs_3->pc4_x_y4;
4598 amin[jj]=p_xs_3->pc4_x_y4-(0.000001*ann_fac);
4599 amax[jj]=p_xs_3->pc4_x_y4+(0.000001*ann_fac);
4600 aname[jj]=ii;
4601 jj+=1;
4602 }
4603 if (strncmp((p_all_par+ii)->name,"pc4_y_xy3",9)==0) {
4604 abest[jj]=p_xs_3->pc4_y_xy3;
4605 amin[jj]=p_xs_3->pc4_y_xy3-(0.000001*ann_fac);
4606 amax[jj]=p_xs_3->pc4_y_xy3+(0.000001*ann_fac);
4607 aname[jj]=ii;
4608 jj+=1;
4609 }
4610 if (strncmp((p_all_par+ii)->name,"pc4_y_xy3",9)==0) {
4611 abest[jj]=p_xs_3->pc4_y_xy3;
4612 amin[jj]=p_xs_3->pc4_y_xy3-(0.000001*ann_fac);
4613 amax[jj]=p_xs_3->pc4_y_xy3+(0.000001*ann_fac);
4614 aname[jj]=ii;
4615 jj+=1;
4616 }
4617 if (strncmp((p_all_par+ii)->name,"pc4_y_x2y2",10)==0) {
4618 abest[jj]=p_xs_3->pc4_y_x2y2;
4619 amin[jj]=p_xs_3->pc4_y_x2y2-(0.000001*ann_fac);
4620 amax[jj]=p_xs_3->pc4_y_x2y2+(0.000001*ann_fac);
4621 aname[jj]=ii;
4622 jj+=1;
4623 }
4624 if (strncmp((p_all_par+ii)->name,"pc4_y_x4",8)==0) {
4625 abest[jj]=p_xs_3->pc4_y_x4;
4626 amin[jj]=p_xs_3->pc4_y_x4-(0.000001*ann_fac);
4627 amax[jj]=p_xs_3->pc4_y_x4+(0.000001*ann_fac);
4628 aname[jj]=ii;
4629 jj+=1;
4630 }
4631 if (strncmp((p_all_par+ii)->name,"pc4_y_y4",8)==0) {
4632 abest[jj]=p_xs_3->pc4_y_y4;
4633 amin[jj]=p_xs_3->pc4_y_y4-(0.000001*ann_fac);
4634 amax[jj]=p_xs_3->pc4_y_y4+(0.000001*ann_fac);
4635 aname[jj]=ii;
4636 jj+=1;
4637 }
4638 if (strncmp((p_all_par+ii)->name,"ca_x0",5)==0) {
4639 abest[jj]=p_xs_3->ca_x0;
4640 amin[jj]=p_xs_3->ca_x0-(0.000001*ann_fac);
4641 amax[jj]=p_xs_3->ca_x0+(0.000001*ann_fac);
4642 aname[jj]=ii;
4643 jj+=1;
4644 }
4645 if (strncmp((p_all_par+ii)->name,"ca_x1",5)==0) {
4646 abest[jj]=p_xs_3->ca_x1;
4647 amin[jj]=p_xs_3->ca_x1-(0.000001*ann_fac);
4648 amax[jj]=p_xs_3->ca_x1+(0.000001*ann_fac);
4649 aname[jj]=ii;
4650 jj+=1;
4651 }
4652 if (strncmp((p_all_par+ii)->name,"ca_y0",5)==0) {
4653 abest[jj]=p_xs_3->ca_y0;
4654 amin[jj]=p_xs_3->ca_y0-(0.000001*ann_fac);
4655 amax[jj]=p_xs_3->ca_y0+(0.000001*ann_fac);
4656 aname[jj]=ii;
4657 jj+=1;
4658 }
4659 if (strncmp((p_all_par+ii)->name,"ca_y1",5)==0) {
4660 abest[jj]=p_xs_3->ca_y1;
4661 amin[jj]=p_xs_3->ca_y1-(0.000001*ann_fac);
4662 amax[jj]=p_xs_3->ca_y1+(0.000001*ann_fac);
4663 aname[jj]=ii;
4664 jj+=1;
4665 }
4666 }
4667 }
4668 if (scenario<0) {
4669 /*es_x is the location of the central pinhole across the entrance
4670 slit in mm*/
4671 if (strncmp((p_all_par+ii)->name,"es_x",4)==0) {
4672 abest[jj]=p_xs_3->es_x;
4673 amin[jj]=p_xs_3->es_x-(1.0*ann_fac);
4674 amax[jj]=p_xs_3->es_x+(1.0*ann_fac);
4675 aname[jj]=ii;
4676 jj+=1;
4677 }
4678 }
4679 if (scenario==8) {
4680 if (p_xs_3->arm==0) {
4681 /*[mu/nu/tau]d describe the orientation of the detector*/
4682 if (strncmp((p_all_par+ii)->name,"mud",3)==0) {
4683 aname[jj]=ii;
4684 abest[jj]=p_xs_3->mud/DEG2RAD;
4685 amin[jj]=p_xs_3->mud/DEG2RAD-(0.2*ann_fac);
4686 amax[jj]=p_xs_3->mud/DEG2RAD+(0.2*ann_fac);
4687 jj+=1;
4688 }
4689 if (strncmp((p_all_par+ii)->name,"nud",3)==0) {
4690 aname[jj]=ii;
4691 abest[jj]=p_xs_3->nud/DEG2RAD;
4692 amin[jj]=p_xs_3->nud/DEG2RAD-(0.2*ann_fac);
4693 amax[jj]=p_xs_3->nud/DEG2RAD+(0.2*ann_fac);
4694 jj+=1;
4695 }
4696 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
4697 aname[jj]=ii;
4698 abest[jj]=p_xs_3->taud/DEG2RAD;
4699 amin[jj]=p_xs_3->taud/DEG2RAD-(0.05*ann_fac);
4700 amax[jj]=p_xs_3->taud/DEG2RAD+(0.05*ann_fac);
4701 jj+=1;
4702 }
4703 /*fdet is the focal length of the camera*/
4704 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
4705 abest[jj]=p_xs_3->fdet;
4706 amin[jj]=p_xs_3->fdet-(0.05*ann_fac);
4707 amax[jj]=p_xs_3->fdet+(0.05*ann_fac);
4708 aname[jj]=ii;
4709 jj+=1;
4710 }
4711 /* chip[x/y] is the offset of the detector in the focal plane*/
4712 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4713 abest[jj]=p_xs_3->chipx;
4714 amin[jj]=p_xs_3->chipx-(0.05*ann_fac);
4715 amax[jj]=p_xs_3->chipx+(0.05*ann_fac);
4716 aname[jj]=ii;
4717 jj+=1;
4718 }
4719 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4720 abest[jj]=p_xs_3->chipy;
4721 amin[jj]=p_xs_3->chipy-(0.05*ann_fac);
4722 amax[jj]=p_xs_3->chipy+(0.05*ann_fac);
4723 aname[jj]=ii;
4724 jj+=1;
4725 }
4726 /* sg is the grating constant*/
4727 if (strncmp((p_all_par+ii)->name,"sg",2)==0) {
4728 abest[jj]=p_xs_3->sg;
4729 amin[jj]=p_xs_3->sg-(0.02*ann_fac);
4730 amax[jj]=p_xs_3->sg+(0.02*ann_fac);
4731 aname[jj]=ii;
4732 jj+=1;
4733 }
4734 }
4735 else if (p_xs_3->arm==1) {
4736 if (strncmp((p_all_par+ii)->name,"mup1",4)==0) {
4737 aname[jj]=ii;
4738 abest[jj]=p_xs_3->mup1/DEG2RAD;
4739 amin[jj]=p_xs_3->mup1/DEG2RAD-(0.025*ann_fac);
4740 amax[jj]=p_xs_3->mup1/DEG2RAD+(0.025*ann_fac);
4741 jj+=1;
4742 }
4743 /*[mu/nu/tau]g describe the orientation of the grating*/
4744 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
4745 aname[jj]=ii;
4746 abest[jj]=p_xs_3->nug/DEG2RAD;
4747 amin[jj]=p_xs_3->nug/DEG2RAD-(0.02*ann_fac);
4748 amax[jj]=p_xs_3->nug/DEG2RAD+(0.02*ann_fac);
4749 jj+=1;
4750 }
4751 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
4752 aname[jj]=ii;
4753 abest[jj]=p_xs_3->taud/DEG2RAD;
4754 amin[jj]=p_xs_3->taud/DEG2RAD-(0.01*ann_fac);
4755 amax[jj]=p_xs_3->taud/DEG2RAD+(0.01*ann_fac);
4756 jj+=1;
4757 }
4758 /*fdet is the focal length of the camera*/
4759 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
4760 abest[jj]=p_xs_3->fdet;
4761 amin[jj]=p_xs_3->fdet-(0.1*ann_fac);
4762 amax[jj]=p_xs_3->fdet+(0.1*ann_fac);
4763 aname[jj]=ii;
4764 jj+=1;
4765 }
4766 /* chip[x/y] is the offset of the detector in the focal plane*/
4767 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4768 abest[jj]=p_xs_3->chipx;
4769 amin[jj]=p_xs_3->chipx-(0.05*ann_fac);
4770 amax[jj]=p_xs_3->chipx+(0.05*ann_fac);
4771 aname[jj]=ii;
4772 jj+=1;
4773 }
4774 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4775 abest[jj]=p_xs_3->chipy;
4776 amin[jj]=p_xs_3->chipy-(0.05*ann_fac);
4777 amax[jj]=p_xs_3->chipy+(0.05*ann_fac);
4778 aname[jj]=ii;
4779 jj+=1;
4780 }
4781 /* sg is the grating constant*/
4782 if (strncmp((p_all_par+ii)->name,"sg",2)==0) {
4783 abest[jj]=p_xs_3->sg;
4784 amin[jj]=p_xs_3->sg-(0.01*ann_fac);
4785 amax[jj]=p_xs_3->sg+(0.01*ann_fac);
4786 aname[jj]=ii;
4787 jj+=1;
4788 }
4789 }
4790 else if (p_xs_3->arm==2) {
4791 /*[mu/nu/tau]d describe the orientation of the detector*/
4792 if (strncmp((p_all_par+ii)->name,"mup1",4)==0) {
4793 aname[jj]=ii;
4794 abest[jj]=p_xs_3->mup1/DEG2RAD;
4795 amin[jj]=p_xs_3->mup1/DEG2RAD-(0.01*ann_fac);
4796 amax[jj]=p_xs_3->mup1/DEG2RAD+(0.01*ann_fac);
4797 jj+=1;
4798 }
4799 /*[mu/nu/tau]g describe the orientation of the grating*/
4800 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
4801 aname[jj]=ii;
4802 abest[jj]=p_xs_3->nug/DEG2RAD;
4803 amin[jj]=p_xs_3->nug/DEG2RAD-(0.01*ann_fac);
4804 amax[jj]=p_xs_3->nug/DEG2RAD+(0.01*ann_fac);
4805 jj+=1;
4806 }
4807 if (strncmp((p_all_par+ii)->name,"mud",3)==0) {
4808 aname[jj]=ii;
4809 abest[jj]=p_xs_3->mud/DEG2RAD;
4810 amin[jj]=p_xs_3->mud/DEG2RAD-(0.1*ann_fac);
4811 amax[jj]=p_xs_3->mud/DEG2RAD+(0.3*ann_fac);
4812 jj+=1;
4813 }
4814 if (strncmp((p_all_par+ii)->name,"nud",3)==0) {
4815 aname[jj]=ii;
4816 abest[jj]=p_xs_3->nud/DEG2RAD;
4817 amin[jj]=p_xs_3->nud/DEG2RAD-(0.1*ann_fac);
4818 amax[jj]=p_xs_3->nud/DEG2RAD+(0.3*ann_fac);
4819 jj+=1;
4820 }
4821 /*fdet is the focal length of the camera*/
4822 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
4823 abest[jj]=p_xs_3->fdet;
4824 amin[jj]=p_xs_3->fdet-(0.2*ann_fac);
4825 amax[jj]=p_xs_3->fdet+(0.2*ann_fac);
4826 aname[jj]=ii;
4827 jj+=1;
4828 }
4829 /* chip[x/y] is the offset of the detector in the focal plane*/
4830 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4831 abest[jj]=p_xs_3->chipx;
4832 amin[jj]=p_xs_3->chipx-(0.075*ann_fac);
4833 amax[jj]=p_xs_3->chipx+(0.075*ann_fac);
4834 aname[jj]=ii;
4835 jj+=1;
4836 }
4837 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4838 abest[jj]=p_xs_3->chipy;
4839 amin[jj]=p_xs_3->chipy-(0.075*ann_fac);
4840 amax[jj]=p_xs_3->chipy+(0.075*ann_fac);
4841 aname[jj]=ii;
4842 jj+=1;
4843 }
4844 /*taues is the rotation angle of the entrance slit*/
4845 if (strncmp((p_all_par+ii)->name,"taues",5)==0) {
4846 aname[jj]=ii;
4847 abest[jj]=p_xs_3->taues/DEG2RAD;
4848 amin[jj]=p_xs_3->taues/DEG2RAD-(0.05*ann_fac);
4849 amax[jj]=p_xs_3->taues/DEG2RAD+(0.15*ann_fac);
4850 jj+=1;
4851 }
4852 /*fcol is the focal length of the collimator.*/
4853 if (strncmp((p_all_par+ii)->name,"fcol",4)==0) {
4854 abest[jj]=p_xs_3->fcol;
4855 amin[jj]=p_xs_3->fcol-(1.0*ann_fac);
4856 amax[jj]=p_xs_3->fcol+(1.5*ann_fac);
4857 aname[jj]=ii;
4858 jj+=1;
4859 }
4860 }
4861 }
4862 if (scenario==9) {
4863 /*scenario for NIR AFC*/
4864 if (p_xs_3->arm!=2) {
4865 cpl_msg_error(__func__,"This scenario is only valid for NIR AFC exposures");
4866 return NULL;
4867 }
4868 if (strncmp((p_all_par+ii)->name,"mug",3)==0) {
4869 aname[jj]=ii;
4870 abest[jj]=p_xs_3->mug/DEG2RAD;
4871 amin[jj]=p_xs_3->mug/DEG2RAD-(0.02*ann_fac);
4872 amax[jj]=p_xs_3->mug/DEG2RAD+(0.02*ann_fac);
4873 jj+=1;
4874 }
4875 /*[mu/nu/tau]g describe the orientation of the grating*/
4876 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
4877 aname[jj]=ii;
4878 abest[jj]=p_xs_3->nug/DEG2RAD;
4879 amin[jj]=p_xs_3->nug/DEG2RAD-(0.02*ann_fac);
4880 amax[jj]=p_xs_3->nug/DEG2RAD+(0.02*ann_fac);
4881 jj+=1;
4882 }
4883 /*fdet is the focal length of the camera*/
4884 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
4885 abest[jj]=p_xs_3->fdet;
4886 amin[jj]=p_xs_3->fdet-(0.4*ann_fac);
4887 amax[jj]=p_xs_3->fdet+(0.4*ann_fac);
4888 aname[jj]=ii;
4889 jj+=1;
4890 }
4891 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
4892 aname[jj]=ii;
4893 abest[jj]=p_xs_3->taud/DEG2RAD;
4894 amin[jj]=p_xs_3->taud/DEG2RAD-(0.025*ann_fac);
4895 amax[jj]=p_xs_3->taud/DEG2RAD+(0.025*ann_fac);
4896 jj+=1;
4897 }
4898 /* chip[x/y] is the offset of the detector in the focal plane*/
4899 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
4900 abest[jj]=p_xs_3->chipx;
4901 amin[jj]=p_xs_3->chipx-(0.1*ann_fac);
4902 amax[jj]=p_xs_3->chipx+(0.1*ann_fac);
4903 aname[jj]=ii;
4904 jj+=1;
4905 }
4906 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
4907 abest[jj]=p_xs_3->chipy;
4908 amin[jj]=p_xs_3->chipy-(0.1*ann_fac);
4909 amax[jj]=p_xs_3->chipy+(0.1*ann_fac);
4910 aname[jj]=ii;
4911 jj+=1;
4912 }
4913 }
4914 }
4915 adim=jj;
4916 }
4917 } /*End of setting the automatic open params and ranges*/
4918 else {
4919 if (adim==0) {
4920 cpl_msg_error(__func__,"The use of the phys mod config file optimisation flags and ranges was specified, however the input phys mod config has no optimisation flags set");
4921 return NULL;
4922 }
4923 }
4924 check( resid_tab = xsh_resid_tab_load(resid_frame));
4925 resid_header = resid_tab->header;
4926 check( size = xsh_resid_tab_get_size( resid_tab ) ) ;
4927 xsh_msg ( " Resid Table Size: %d", size ) ;
4928 XSH_CALLOC( msp_coord, coord, size);
4929
4930 /*Get the wavelengths, orders and slit positions matched with the
4931 measured x,y positions from the resid tab*/
4932 check( vlambda = xsh_resid_tab_get_lambda_data( resid_tab));
4933 check( vorder = xsh_resid_tab_get_order_data( resid_tab ));
4934 check( slitindex = xsh_resid_tab_get_slit_index( resid_tab));
4935 check( thpre_x = xsh_resid_tab_get_thpre_x_data( resid_tab ));
4936 check( thpre_y = xsh_resid_tab_get_thpre_y_data( resid_tab ));
4937 check( xgauss = xsh_resid_tab_get_xgauss_data( resid_tab ));
4938 check( ygauss = xsh_resid_tab_get_ygauss_data( resid_tab ));
4939
4940 /*Compute density of calibration features in wavelength bins or
4941 per order*/
4942 if (p_xs_3->arm==0) {
4943 wav_den_bin_sz=25.0;
4944 }
4945 else if (p_xs_3->arm==1) {
4946 wav_den_bin_sz=50.0;
4947 }
4948 else {
4949 wav_den_bin_sz=125.0;
4950 }
4951 for (kk=0;kk<40;kk+=1) {
4952 wav_den[kk]=0;
4953 }
4954 for (kk=0;kk<size;kk+=1){
4955 if (vlambda[kk]>0.0) {
4956 wav_den[(int)(vorder[kk])]+=1;
4957 }
4958 //wav_den[(int)((vlambda[kk])/wav_den_bin_sz)]+=1;
4959 }
4960
4961 kk=0;
4962 for (jj=0;jj<size;jj+=1){
4963 //xsh_msg("To be matched X=%f Y=%f",*(thpre_x+jj),*(thpre_y+jj));
4964 msp_coord[kk].wave=*(vlambda+jj);
4965 msp_coord[kk].x= *(xgauss+jj) ;
4966 //msp_coord[kk].flux=100.0; /* No flux weighting in optimisation*/
4967 /*weight inversely to the density of lines*/
4968 //msp_coord[kk].flux=10000.0/
4969 //(float)(wav_den[(int)((vlambda[jj])/wav_den_bin_sz)]);
4970 /* weight inversely to the order density of lines*/
4971 msp_coord[kk].flux=10000.0/(float)(wav_den[(int)(vorder[jj])]);
4972 msp_coord[kk].order=(int)(*(vorder+jj));
4973 msp_coord[kk].y= *(ygauss+jj);
4974 msp_coord[kk].slit_pos=slitindex[jj];
4975 msp_coord[kk].counter=jj;
4976 msp_coord[kk].arm=p_xs_3->arm;
4977 //printf("slit %d, wvlen %lf, x %lf , y %lf \n",msp_coord[kk].slit_pos,msp_coord[kk].wave,msp_coord[kk].x,msp_coord[kk].y);
4978 kk+=1;
4979 }
4980
4981 /*Set up the refractive index information required for the arm*/
4982 ref_ind=xsh_alloc2Darray(8,7);
4983 if (p_xs_3->arm==0) {
4984 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
4985 }
4986 else if (p_xs_3->arm==1) {
4987 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
4988 }
4989 else if (p_xs_3->arm==2) {
4990 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
4991 }
4992 else {
4993 printf("Arm not set. \n");
4994 return NULL;
4995 }
4996
4997 xsh_3_init(p_xs_3);
4998
4999 /* now allocate memory for the data wavelength structure and fill*/
5000 p_wlarray=xsh_alloc1Darray(size);
5001 for(ii=0;ii<size;ii++) {
5002 p_wlarray[ii]=msp_coord[ii].wave*1e-6;
5003 }
5004
5005#ifdef DEBUG
5006 printf ("Before anneal: \n");
5007 for (ii=0;ii<adim;ii++) {
5008 printf("%d %s %lf \n", aname[ii], (p_all_par+aname[ii])->name, abest[ii]);
5009 }
5010
5011 //xsh_showmatrix(p_xs_3->e_slit);
5012 /*Call the model kernel with the initial values*/
5013 for (jj=0;jj<size;jj++) {
5014 int morder_cnt=msp_coord[jj].order;
5015 p_xs_3->es_y_tot=p_xs_3->es_y+p_xs_3->slit[msp_coord[jj].slit_pos]*p_xs_3->slit_scale;
5016 xsh_3_init(p_xs_3);
5017 //xsh_model_io_output_cfg_txt(p_xs_3);
5018 xsh_3_eval(p_wlarray[jj],morder_cnt,ref_ind,p_xs_3);
5019 xsh_3_detpix(p_xs_3);
5020 printf("check %d %lf %lf %d %d %lf %lf %lf %lf %d %lf %lf \n",
5021 jj,p_wlarray[jj],p_xs_3->es_y_tot,p_xs_3->chippix[0],
5022 msp_coord[jj].arm,p_xs_3->xpospix,p_xs_3->ypospix,
5023 msp_coord[jj].x-p_xs_3->xpospix,msp_coord[jj].y-p_xs_3->ypospix,
5024 msp_coord[jj].order, p_xs_3->xdet, p_xs_3->ydet);
5025 }
5026#endif
5027 /*Call the main anneal algorithm in xsh_model_metric.c*/
5028 MODEL_CONFIG_plist=cpl_propertylist_new();
5029 check(xsh_model_compute_residuals(p_xs_3,msp_coord,p_wlarray,ref_ind,size,0,
5030 resid_header,resid_frame,
5031 &MODEL_CONFIG_plist));
5032
5033 if ((conf_tab = xsh_model_anneal_comp(p_all_par,
5034 adim,
5035 abest,
5036 amin,
5037 amax,
5038 aname,
5039 p_xs_3,
5040 size,
5041 msp_coord,
5042 p_wlarray,
5043 ref_ind,
5044 maxit)) == NULL) {
5045 xsh_free2Darray(ref_ind,8);
5046 cpl_free(p_wlarray);
5047 return NULL ;
5048 }
5049 //AModigliani: added dumping of final model results
5050 check(xsh_model_compute_residuals(p_xs_3,msp_coord,p_wlarray,ref_ind,size,1,
5051 resid_header,resid_frame,
5052 &MODEL_CONFIG_plist));
5053 //cpl_propertylist_dump(MODEL_CONFIG_plist,stdout);
5054 check(tag=xsh_get_tag_opt_mod_cfg(p_xs_3,rec_id));
5055
5056 //sprintf(out_cfg_filename,"new_%s",cpl_frame_get_filename(cfg_frame));
5057 sprintf(out_cfg_filename,"%s.fits",tag);
5058
5059 xsh_msg_dbg_medium("Save the table") ;
5060 xsh_msg_dbg_medium("out file=%s",out_cfg_filename);
5061
5062 check(xsh_pfits_set_pcatg(MODEL_CONFIG_plist, tag ) ) ;
5063
5064 check(cpl_table_save(conf_tab, MODEL_CONFIG_plist, NULL, out_cfg_filename, CPL_IO_DEFAULT));
5065
5066
5067 check(MODEL_CONF_OPT_frame=xsh_frame_product(out_cfg_filename,
5068 tag,
5069 CPL_FRAME_TYPE_TABLE,
5070 CPL_FRAME_GROUP_PRODUCT,
5071 CPL_FRAME_LEVEL_FINAL));
5072 xsh_msg_dbg_medium("optimised model parameter table %s %s", cpl_frame_get_filename(MODEL_CONF_OPT_frame),cpl_frame_get_tag(MODEL_CONF_OPT_frame));
5073
5074 cleanup:
5075
5076 xsh_free_table(&resid_tbl);
5077 xsh_free_table(&conf_tab);
5078 xsh_resid_tab_free(&resid_tab);
5079 if ( cpl_error_get_code() != CPL_ERROR_NONE){
5080 xsh_free_frame( &MODEL_CONF_OPT_frame);
5081 }
5082 XSH_FREE( msp_coord);
5083 XSH_FREE( p_wlarray);
5084 xsh_free_propertylist( &MODEL_CONFIG_plist);
5085
5086 if (ref_ind!=NULL){
5087 xsh_free2Darray(ref_ind,8);
5088 }
5089 return MODEL_CONF_OPT_frame;
5090}
5091
5092/*----------------------------------------------------------------------------*/
5109/*----------------------------------------------------------------------------*/
5110int xsh_model_open_param(char * listname,
5111 char * findname,
5112 int * ref,
5113 int setref,
5114 double * best,
5115 double setbest,
5116 double * min,
5117 double * max,
5118 double gfac,
5119 double fac,
5120 int counter)
5121{
5122 if (strncmp(listname,findname,strlen(findname))==0) {
5123 *ref=setref;
5124 *best=setbest;
5125 *min=setbest-(fac*gfac);
5126 *max=setbest=(fac*gfac);
5127 counter++;
5128 }
5129 return counter;
5130 }
5131/*----------------------------------------------------------------------------*/
5141/*----------------------------------------------------------------------------*/
5142
5143double xsh_model_sellmeier_ext(int arm, double temper, double lam_sqr)
5144{
5145 typedef DOUBLE sellmeier_mat[3][5];
5146 int ii, jj;
5147 double ref_ind,top,bottom;
5148 double T[5];
5149 sellmeier_mat S_UVB={{1.10127, -4.94251E-05, 5.27414E-07, -1.59700E-09, 1.75949E-12},
5150 {1.78752E-05, 4.76391E-05, -4.49019E-07, 1.44546E-09, -1.57223E-12},
5151 {0.793552, -1.27815E-03, 1.84595E-05, -9.20275E-08, 1.48829E-10}};
5152 sellmeier_mat L_UVB={{-0.08906, 9.08730E-06, -6.53638E-08, 7.77072E-11, 6.84605E-14},
5153 {0.297562, -859578E-04, 6.59069E-06, -1.09482E-08, 7.85145E-13},
5154 {9.34454, -7.09788E-03, 1.01968E-04, -5.07660E-07, 8.21348E-10}};
5155
5156 sellmeier_mat S_NIR={{0.104940144,5.40E-06,3.23E-08,1.83E-13,-3.60E-14},
5157 {0.996335571,-3.29E-06,1.48E-08,-3.01E-11,4.99E-14},
5158 {0.832484961,6.38E-04,-2.40E-06,6.10E-10,4.77E-12}};
5159 sellmeier_mat L_NIR={{-3.07E-03,-2.56E-05,6.21E-07,-2.54E-09,2.88E-12},
5160 {9.40E-02,-1.59E-06,1.28E-08,1.82E-12,-3.01E-14},
5161 {9.598633568,3.15E-03,-1.22E-05,5.48E-09,1.96E-11}};
5162 T[0]=1.0;
5163 T[1]=temper;
5164 T[2]=temper*temper;
5165 T[3]=T[2]*temper;
5166 T[4]=T[3]*temper;
5167 ref_ind=1.0;
5168 if (arm==0) {
5169 for (ii=0;ii<3;ii++) {
5170 top=bottom=0.0;
5171 for (jj=0;jj<5;jj++) {
5172 top+=S_UVB[ii][jj]*T[jj];
5173 bottom+=L_UVB[ii][jj]*T[jj];
5174 }
5175 ref_ind+=(top*lam_sqr)/(lam_sqr-(bottom*bottom));
5176 }
5177 }
5178 else if (arm==2) {
5179 for (ii=0;ii<3;ii++) {
5180 top=bottom=0.0;
5181 for (jj=0;jj<5;jj++) {
5182 top+=S_NIR[ii][jj]*T[jj];
5183 bottom+=L_NIR[ii][jj]*T[jj];
5184 }
5185 ref_ind+=(top*lam_sqr)/(lam_sqr-(bottom*bottom));
5186 }
5187 }
5188 return sqrt(ref_ind);
5189}
5190
5191/*----------------------------------------------------------------------------*/
5200/*----------------------------------------------------------------------------*/
5201double
5202xsh_model_ref_ind_air(double temper, double lam_sqr)
5203{
5204 double n288=0, n_air=0;
5205 n288=1.0+(6432.8+((2949810.0*lam_sqr)/(146.0*lam_sqr-1.0))+((25540.0*lam_sqr)/(41.0*lam_sqr-1.0)))*1.0E-08;
5206 n_air=1.0+(n288-1.0)/(1.0+0.0034785*(temper-288.0));
5207 return n_air;
5208}
5209
5210/*----------------------------------------------------------------------------*/
5219/*----------------------------------------------------------------------------*/
5220cpl_vector *
5222 const cpl_vector * in,
5223 int fwhm,
5224 double sigma,
5225 int display)
5226{
5227 cpl_vector * filtered =NULL;
5228 cpl_vector * spec_clean =NULL;
5229 double * pspec_clean =NULL;
5230 int filt_size =0;
5231 cpl_vector * conv_kernel =NULL;
5232 cpl_vector * big_detected =NULL;
5233 double * pbig_detected =NULL;
5234 cpl_vector * detected =NULL;
5235 double * pdetected =NULL;
5236 double max=0, med=0, stdev=0, cur_val=0 ;
5237 int nb_det=0, nb_samples=0 ;
5238 int i=0;
5239 int j=0;
5240
5241 /* Test entries */
5242 if (in == NULL) return NULL ;
5243
5244
5245 /* Initialise */
5246 check(nb_samples = cpl_vector_get_size(in)) ;
5247 filt_size = 50 ;
5248
5249 /* Subrtract the low frequency part */
5250 //cpl_msg_info(__func__, "Low Frequency signal removal") ;
5251 if ((filtered=cpl_vector_filter_median_create(in, filt_size))==NULL){
5252 cpl_msg_error(__func__, "Cannot filter the spectrum") ;
5253 return NULL ;
5254 }
5255 spec_clean = cpl_vector_duplicate(in) ;
5256 cpl_vector_subtract(spec_clean, filtered) ;
5257 cpl_vector_delete(filtered) ;
5258
5259 /* Display if requested */
5260 if (display) {
5261 cpl_plot_vector(
5262 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity (ADU)';",
5263 "t 'Filtered extracted spectrum' w lines", "", spec_clean);
5264 }
5265
5266 /* Convolve */
5267 //cpl_msg_info(__func__, "Spectrum convolution") ;
5268 /* Create convolution kernel */
5269 if ((conv_kernel = cpl_wlcalib_xc_convolve_create_kernel(fwhm,
5270 fwhm)) == NULL) {
5271 cpl_msg_error(cpl_func, "Cannot create convolution kernel") ;
5272 cpl_vector_delete(spec_clean) ;
5273 return NULL ;
5274 }
5275
5276 /* Smooth the instrument resolution */
5277 if (cpl_wlcalib_xc_convolve(spec_clean, conv_kernel)) {
5278 cpl_msg_error(cpl_func, "Cannot smoothe the signal");
5279 cpl_vector_delete(spec_clean) ;
5280 cpl_vector_delete(conv_kernel) ;
5281 return NULL ;
5282 }
5283 cpl_vector_delete(conv_kernel) ;
5284
5285 /* Display if requested */
5286 if (display) {
5287 cpl_plot_vector(
5288 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity (ADU)';",
5289 "t 'Convolved extracted spectrum' w lines", "", spec_clean);
5290 }
5291
5292 /* Apply the detection */
5293 big_detected = cpl_vector_duplicate(spec_clean) ;
5294 pbig_detected = cpl_vector_get_data(big_detected) ;
5295 pspec_clean = cpl_vector_get_data(spec_clean) ;
5296
5297 /* To avoid detection on the side */
5298 pspec_clean[0] = pspec_clean[nb_samples-1] = 0.0 ;
5299
5300 /* Compute stats */
5301 max = cpl_vector_get_max(spec_clean) ;
5302 stdev = cpl_vector_get_stdev(spec_clean) ;
5303 med = cpl_vector_get_median_const(spec_clean) ;
5304
5305 /* Loop on the detected lines */
5306 nb_det = 0 ;
5307 while (max > med + stdev * sigma) {
5308 /* Compute the position */
5309 i=0 ;
5310 while (pspec_clean[i] < max) i++ ;
5311 if (i<=0 || i>=nb_samples-1) break ;
5312
5313 /* Store the detected line */
5314 pbig_detected[nb_det] = (pspec_clean[i]*i +
5315 pspec_clean[i-1]*(i-1) + pspec_clean[i+1]*(i+1)) /
5316 (pspec_clean[i]+pspec_clean[i-1]+pspec_clean[i+1]);
5317 /* Position = index + 1 */
5318
5319 pbig_detected[nb_det] ++ ;
5320 //cpl_msg_info(__func__, "Line nb %d at position %g",
5321 //nb_det+1, pbig_detected[nb_det]) ;
5322 nb_det ++ ;
5323
5324 /* Cancel out the line on the left */
5325 j = i-1 ;
5326 cur_val = pspec_clean[i] ;
5327 while (j>=0 && pspec_clean[j] < cur_val) {
5328 cur_val = pspec_clean[j] ;
5329 pspec_clean[j] = 0.0 ;
5330 j-- ;
5331 }
5332 /* Cancel out the line on the right */
5333 j = i+1 ;
5334 cur_val = pspec_clean[i] ;
5335 while (j<=nb_samples-1 && pspec_clean[j] < cur_val) {
5336 cur_val = pspec_clean[j] ;
5337 pspec_clean[j] = 0.0 ;
5338 j++ ;
5339 }
5340 /* Cancel out the line on center */
5341 pspec_clean[i] = 0.0 ;
5342
5343 /* Recompute the stats */
5344 max = cpl_vector_get_max(spec_clean) ;
5345 stdev = cpl_vector_get_stdev(spec_clean) ;
5346 med = cpl_vector_get_median_const(spec_clean) ;
5347 }
5348 cpl_vector_delete(spec_clean) ;
5349
5350 /* Create the output vector */
5351 if (nb_det == 0) {
5352 detected = NULL ;
5353 } else {
5354 detected = cpl_vector_new(nb_det) ;
5355 pdetected = cpl_vector_get_data(detected) ;
5356 pbig_detected = cpl_vector_get_data(big_detected) ;
5357 for (i=0 ; i<nb_det ; i++) pdetected[i] = pbig_detected[i] ;
5358 }
5359 cpl_vector_delete(big_detected) ;
5360
5361 cleanup:
5362 if(cpl_error_get_code() != CPL_ERROR_NONE) {
5364 }
5365 /* Return */
5366 return detected ;
5367}
5368
5369/*---------------------------------------------------------------------------*/
5376/*---------------------------------------------------------------------------*/
5377int
5378xsh_model_first_anneal(cpl_parameterlist* parlist, cpl_frameset* frameset)
5379{
5380 cpl_frame* xs_config =NULL;
5381 cpl_frame* meas_coord =NULL;
5382 cpl_parameter* param=NULL;
5383 xsh_instrument* instrument = NULL;
5384 const char* arm=NULL;
5385 int nraw=0;
5386 int nrows=0;
5387
5388 cpl_table * conf_tab = NULL;
5389 int ii=0, jj=0;
5390
5391 int sizearraywavelengths=0, adim=0;
5392
5393 struct xs_3 xs_model, *p_xs_3;
5394 ann_all_par all_par[300], *p_all_par;
5395 double abest[300];
5396 double amin[300];
5397 double amax[300];
5398 int aname[300];
5399 int coord_switch=0;
5400
5401
5402 coord *msp_coord = NULL;
5403 DOUBLE ** ref_ind = NULL;
5404 DOUBLE *p_wlarray = NULL;
5405 cpl_table * meas_coord_temp=NULL;
5406 double ann_fac=1.0000000000001;
5407
5408 int MAXIT=10;
5409
5410 FILE* file_list=NULL;
5411 int cnt=0;
5412 double* pw=NULL;
5413 double* px=NULL;
5414 double* py=NULL;
5415 int* po=NULL;
5416 const char * name_i=NULL ;
5417 float wave=0;
5418 float x=0;
5419 float y=0;
5420 int ord=0;
5421
5422 if( (nraw=cpl_frameset_get_size(frameset)) ==0) goto cleanup;
5423
5424 param = cpl_parameterlist_find(parlist,"xsh.xsh_model_compute.arm");
5425 arm = cpl_parameter_get_string(param);
5426 xsh_msg("User selected arm '%s'. Recipe expects '%s' input data",arm,arm);
5427
5428 param = cpl_parameterlist_find(parlist,"xsh.xsh_model_compute.niter");
5429 MAXIT = cpl_parameter_get_int(param);
5430
5431 coord_switch = cpl_parameter_get_int(cpl_parameterlist_find(parlist,"xsh.xsh_model_compute.coord_frame"));
5432
5433 if (arm==NULL) {
5434 xsh_msg_error("arm parameter value not set. exit!");
5435 goto cleanup;
5436 }
5437
5439 if(strcmp(arm,"uvb") == 0) xsh_instrument_set_arm(instrument,XSH_ARM_UVB);
5440 if(strcmp(arm,"vis") == 0) xsh_instrument_set_arm(instrument,XSH_ARM_VIS);
5441 if(strcmp(arm,"nir") == 0) xsh_instrument_set_arm(instrument,XSH_ARM_NIR);
5442
5443
5444
5445
5446 /* Retrieve calibration data */
5447 if((xs_config = xsh_find_frame_with_tag(frameset,XSH_MOD_CFG,
5448 instrument)) == NULL) {
5449 xsh_msg_error("Frame %s not found",
5452 (void*)NULL ) ) ;
5453 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
5454 goto cleanup;
5455 }
5456
5457 if((meas_coord = xsh_find_frame_with_tag(frameset,XSH_MEASCOORD,
5458 instrument))==NULL) {
5459 xsh_msg_warning("Frame %s not found",
5462 (void*)NULL ));
5463
5464
5465 check(param = cpl_parameterlist_find(parlist,
5466 "xsh.xsh_model_compute.name_i"));
5467 check(name_i = cpl_parameter_get_string(param));
5468 xsh_msg("name_i=%s",name_i);
5469 if ( NULL == (file_list = fopen (name_i, "r" ) ) )
5470 {
5471 xsh_msg_error("cannot open %s\n", name_i) ;
5472 goto cleanup ;
5473 }
5474
5475 cnt = 0 ;
5476 while ( fscanf( file_list, "%64g %64g %64g %64d",&wave, &x, &y, &ord ) != EOF )
5477 {
5478 cnt ++ ;
5479 }
5480 fclose(file_list);
5481
5482 nrows= cnt;
5483 check(meas_coord_temp=cpl_table_new(nrows));
5484 check(cpl_table_new_column(meas_coord_temp,"Wavelength",CPL_TYPE_DOUBLE));
5485 check(cpl_table_new_column(meas_coord_temp,"x",CPL_TYPE_DOUBLE));
5486 check(cpl_table_new_column(meas_coord_temp,"y",CPL_TYPE_DOUBLE));
5487 check(cpl_table_new_column(meas_coord_temp,"ORDER",CPL_TYPE_INT));
5488
5489 check(cpl_table_fill_column_window(meas_coord_temp,"Wavelength",0,nrows,-1));
5490 check(cpl_table_fill_column_window(meas_coord_temp,"x",0,nrows,-1));
5491 check(cpl_table_fill_column_window(meas_coord_temp,"y",0,nrows,-1));
5492 check(cpl_table_fill_column_window(meas_coord_temp,"ORDER",0,nrows,-1));
5493
5494 check(pw=cpl_table_get_data_double(meas_coord_temp,"Wavelength"));
5495 check(px=cpl_table_get_data_double(meas_coord_temp,"x"));
5496 check(py=cpl_table_get_data_double(meas_coord_temp,"y"));
5497 check(po=cpl_table_get_data_int(meas_coord_temp,"ORDER"));
5498
5499 if ( NULL == (file_list = fopen (name_i, "r" ) ) )
5500 {
5501 xsh_msg_error("cannot open %s\n", name_i) ;
5502 goto cleanup ;
5503 }
5504
5505 cnt=0;
5506 while ( fscanf( file_list, "%64g %64g %64g %64d",&wave, &x, &y, &ord ) != EOF )
5507 {
5508 pw[cnt]=wave;
5509 px[cnt]=x;
5510 py[cnt]=y;
5511 po[cnt]=ord;
5512
5513 cnt ++ ;
5514 }
5515
5516 fclose(file_list);
5517 check(cpl_table_save(meas_coord_temp, NULL, NULL,"lin_xy_hand.fits",
5518 CPL_IO_DEFAULT));
5519
5520
5521 check(meas_coord=xsh_frame_product("lin_xy_hand.fits",
5522 "LIN_XY_HAND",
5523 CPL_FRAME_TYPE_TABLE,
5524 CPL_FRAME_GROUP_CALIB,
5525 CPL_FRAME_LEVEL_TEMPORARY));
5526
5527
5528 }
5529
5530
5531 /* Apply the computation here */
5532 p_xs_3=&xs_model;
5533 p_all_par=&all_par[0];
5534
5535 cknull_msg(meas_coord_temp=cpl_table_load(cpl_frame_get_filename(meas_coord),1,0),"Cannot load table %s",cpl_frame_get_filename(meas_coord));
5536 check(sizearraywavelengths=cpl_table_get_nrow(meas_coord_temp));
5537 XSH_CALLOC(msp_coord, coord, sizearraywavelengths+5);
5538
5539 adim=xsh_model_readfits(abest,
5540 amin,
5541 amax,
5542 aname,
5543 cpl_frame_get_filename(xs_config),
5544 cpl_frame_get_tag(xs_config),
5545 p_xs_3,
5546 p_all_par);
5547
5548 if (adim==0) {
5549
5550 for (ii=0;ii<300;ii++) {
5551 aname[ii]=-1;
5552 abest[ii]=0.0;
5553 amin[ii]=0.0;
5554 amax[ii]=0.0;
5555 }
5556 /*modify parameters for optimisation*/
5557 /*discover their indices and make the link with aname*/
5558 jj=0;
5559 for (ii=0;ii<100;ii++) {
5560 /* ann_fac allows the tolerances on all open parameters to be scaled*/
5561 /*[mu/nu]p1 are the tip and tilt of the entrance surface (and hence
5562 the whole prism) of the first prism*/
5563 if (strncmp((p_all_par+ii)->name,"temper",6)==0) {
5564 aname[jj]=ii;
5565 abest[jj]=p_xs_3->temper;
5566 amin[jj]=p_xs_3->temper-(5.0*ann_fac);
5567 amax[jj]=p_xs_3->temper+(5.0*ann_fac);
5568 jj+=1;
5569 }
5570 if (strncmp((p_all_par+ii)->name,"fcol",4)==0) {
5571 aname[jj]=ii;
5572 abest[jj]=p_xs_3->fcol;
5573 amin[jj]=p_xs_3->fcol-(5.0*ann_fac);
5574 amax[jj]=p_xs_3->fcol+(5.0*ann_fac);
5575 jj+=1;
5576 }
5577 if (strncmp((p_all_par+ii)->name,"mup1",4)==0) {
5578 aname[jj]=ii;
5579 abest[jj]=p_xs_3->mup1/DEG2RAD;
5580 amin[jj]=p_xs_3->mup1/DEG2RAD-(5.0*ann_fac);
5581 amax[jj]=p_xs_3->mup1/DEG2RAD+(5.0*ann_fac);
5582 jj+=1;
5583 }
5584 if (strncmp((p_all_par+ii)->name,"nup1",4)==0) {
5585 aname[jj]=ii;
5586 abest[jj]=p_xs_3->nup1/DEG2RAD;
5587 amin[jj]=p_xs_3->nup1/DEG2RAD-(5.0*ann_fac);
5588 amax[jj]=p_xs_3->nup1/DEG2RAD+(5.0*ann_fac);
5589 jj+=1;
5590 }
5591
5592 if (p_xs_3->arm==2) {
5593 /*[mu/nu]p3 are the tip and tilt of the entrance surface (and hence
5594 the whole prism) of the second prism*/
5595 if (strncmp((p_all_par+ii)->name,"cmup1",5)==0) {
5596 aname[jj]=ii;
5597 abest[jj]=p_xs_3->cmup1/DEG2RAD;
5598 amin[jj]=p_xs_3->cmup1/DEG2RAD-(5.0*ann_fac);
5599 amax[jj]=p_xs_3->cmup1/DEG2RAD+(5.0*ann_fac);
5600 jj+=1;
5601 }
5602 if (strncmp((p_all_par+ii)->name,"mup3",4)==0) {
5603 aname[jj]=ii;
5604 abest[jj]=p_xs_3->mup3/DEG2RAD;
5605 amin[jj]=p_xs_3->mup3/DEG2RAD-(5.0*ann_fac);
5606 amax[jj]=p_xs_3->mup3/DEG2RAD+(5.0*ann_fac);
5607 jj+=1;
5608 }
5609 if (strncmp((p_all_par+ii)->name,"nup3",4)==0) {
5610 aname[jj]=ii;
5611 abest[jj]=p_xs_3->nup3/DEG2RAD;
5612 amin[jj]=p_xs_3->nup3/DEG2RAD-(5.0*ann_fac);
5613 amax[jj]=p_xs_3->nup3/DEG2RAD+(5.0*ann_fac);
5614 jj+=1;
5615 }
5616 /*[mu/nu]p5 are the tip and tilt of the entrance surface (and hence
5617 the whole prism) of the third prism*/
5618 if (strncmp((p_all_par+ii)->name,"mup5",4)==0) {
5619 aname[jj]=ii;
5620 abest[jj]=p_xs_3->mup5/DEG2RAD;
5621 amin[jj]=p_xs_3->mup5/DEG2RAD-(5.0*ann_fac);
5622 amax[jj]=p_xs_3->mup5/DEG2RAD+(5.0*ann_fac);
5623 jj+=1;
5624 }
5625 if (strncmp((p_all_par+ii)->name,"nup5",4)==0) {
5626 aname[jj]=ii;
5627 abest[jj]=p_xs_3->nup5/DEG2RAD;
5628 amin[jj]=p_xs_3->nup5/DEG2RAD-(5.0*ann_fac);
5629 amax[jj]=p_xs_3->nup5/DEG2RAD+(5.0*ann_fac);
5630 jj+=1;
5631 }
5632 }
5633
5634 /*[mu/nu]g describe the orientation of the grating*/
5635 if (strncmp((p_all_par+ii)->name,"mug",3)==0) {
5636 aname[jj]=ii;
5637 abest[jj]=p_xs_3->mug/DEG2RAD;
5638 amin[jj]=p_xs_3->mug/DEG2RAD-(5.0*ann_fac);
5639 amax[jj]=p_xs_3->mug/DEG2RAD+(5.0*ann_fac);
5640 jj+=1;
5641 }
5642 if (strncmp((p_all_par+ii)->name,"nug",3)==0) {
5643 aname[jj]=ii;
5644 abest[jj]=p_xs_3->nug/DEG2RAD;
5645 amin[jj]=p_xs_3->nug/DEG2RAD-(5.0*ann_fac);
5646 amax[jj]=p_xs_3->nug/DEG2RAD+(5.0*ann_fac);
5647 jj+=1;
5648 }
5649 /*taud is the rotation of the detector*/
5650 if (strncmp((p_all_par+ii)->name,"taud",4)==0) {
5651 aname[jj]=ii;
5652 abest[jj]=p_xs_3->taud/DEG2RAD;
5653 amin[jj]=p_xs_3->taud/DEG2RAD-(5.0*ann_fac);
5654 amax[jj]=p_xs_3->taud/DEG2RAD+(5.0*ann_fac);
5655 jj+=1;
5656 }
5657 /*fdet is the focal length of the camera*/
5658 if (strncmp((p_all_par+ii)->name,"fdet",4)==0) {
5659 abest[jj]=p_xs_3->fdet;
5660 amin[jj]=p_xs_3->fdet-(10.0*ann_fac);
5661 amax[jj]=p_xs_3->fdet+(10.0*ann_fac);
5662 aname[jj]=ii;
5663 jj+=1;
5664 }
5665
5666 /* chip[x/y] is the offset of the detector in the focal plane*/
5667 if (strncmp((p_all_par+ii)->name,"chipx",5)==0) {
5668 abest[jj]=p_xs_3->chipx;
5669 amin[jj]=p_xs_3->chipx-(15.0*ann_fac);
5670 amax[jj]=p_xs_3->chipx+(15.0*ann_fac);
5671 aname[jj]=ii;
5672 jj+=1;
5673 }
5674 if (strncmp((p_all_par+ii)->name,"chipy",5)==0) {
5675 abest[jj]=p_xs_3->chipy;
5676 amin[jj]=p_xs_3->chipy-(15.0*ann_fac);
5677 amax[jj]=p_xs_3->chipy+(15.0*ann_fac);
5678 aname[jj]=ii;
5679 jj+=1;
5680 }
5681 /* sg is the grating constant*/
5682 if (strncmp((p_all_par+ii)->name,"sg",2)==0) {
5683 abest[jj]=p_xs_3->sg;
5684 amin[jj]=p_xs_3->sg-(1.0*ann_fac);
5685 amax[jj]=p_xs_3->sg+(1.0*ann_fac);
5686 aname[jj]=ii;
5687 jj+=1;
5688 }
5689 }
5690 adim=jj;
5691 }
5692
5693 ref_ind=xsh_alloc2Darray(8,7);
5694
5695 if (p_xs_3->arm==0) {
5696 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
5697 }
5698 else if (p_xs_3->arm==1) {
5699 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
5700 }
5701 else if (p_xs_3->arm==2) {
5702 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
5703 }
5704 else {
5705 printf("Arm not set. \n");
5706 return 1;
5707 }
5708
5709 /*We now need to update several matrices (that were set in the
5710 xsh_3_init routine outside of the current loop) for this prism angle */
5711 xsh_3_init(p_xs_3);
5712
5713 /* now allocate memory for the data structure*/
5714 p_wlarray=xsh_alloc1Darray(sizearraywavelengths);
5715 for (ii=0; ii<sizearraywavelengths; ii++) {
5716 msp_coord[ii].counter=ii;
5717 if (coord_switch==1) {
5718 msp_coord[ii].x=cpl_table_get_double(meas_coord_temp,"x",ii,NULL);
5719 msp_coord[ii].y=cpl_table_get_double(meas_coord_temp,"y",ii,NULL);
5720 }
5721 else {
5722 /*if raw co-ordinates were used then the transformation from RAW to PRE,
5723 appropriate to the arm, needs to be applied*/
5724 if (p_xs_3->arm==0) {
5725 msp_coord[ii].x=2097-cpl_table_get_double(meas_coord_temp,"x",ii,NULL);
5726 msp_coord[ii].y=3001-cpl_table_get_double(meas_coord_temp,"y",ii,NULL);
5727 }
5728 if (p_xs_3->arm==1) {
5729 msp_coord[ii].x=-10.0+cpl_table_get_double(meas_coord_temp,"x",ii,NULL);
5730 msp_coord[ii].y=0.0+cpl_table_get_double(meas_coord_temp,"y",ii,NULL);
5731 }
5732 if (p_xs_3->arm==2) {
5733 msp_coord[ii].x=-20.0+cpl_table_get_double(meas_coord_temp,"y",ii,NULL);
5734 msp_coord[ii].y=2045.0-cpl_table_get_double(meas_coord_temp,"x",ii,NULL);
5735 printf("%lf %lf \n",msp_coord[ii].x,msp_coord[ii].y);
5736 }
5737 }
5738 msp_coord[ii].arm=p_xs_3->arm;
5739 msp_coord[ii].flux=100.0;
5740 msp_coord[ii].slit_pos=4;
5741 msp_coord[ii].wave=cpl_table_get_double(meas_coord_temp,"Wavelength",ii,NULL);
5742 msp_coord[ii].order=cpl_table_get_int(meas_coord_temp,"ORDER",ii,NULL);
5743 p_wlarray[ii]=msp_coord[ii].wave*1e-6;
5744 }
5745 xsh_free_table(&meas_coord_temp);
5746
5747#ifdef DEBUG
5748 printf ("Before anneal: \n");
5749 for (ii=0;ii<adim;ii++) {
5750 printf("%d %s %lf \n", aname[ii], (p_all_par+aname[ii])->name, abest[ii]);
5751 }
5752
5753 xsh_showmatrix(p_xs_3->e_slit);
5754 /*Call the model kernel with the initial values*/
5755
5756 for (jj=0;jj<sizearraywavelengths;jj++) {
5757 int morder=msp_coord[jj].order;
5758 p_xs_3->es_y_tot=p_xs_3->es_y+p_xs_3->slit[msp_coord[jj].slit_pos]*p_xs_3->slit_scale;
5759 xsh_3_init(p_xs_3);
5760 xsh_3_eval(p_wlarray[jj],morder,ref_ind,p_xs_3);
5761 xsh_3_detpix(p_xs_3);
5762 printf("check %d %lf %lf %d %d %lf %lf %lf %lf %d\n",
5763 jj,p_wlarray[jj],p_xs_3->es_y_tot,p_xs_3->chippix[0],
5764 msp_coord[jj].arm,p_xs_3->xpospix,p_xs_3->ypospix,
5765 msp_coord[jj].x-p_xs_3->xpospix,msp_coord[jj].y-p_xs_3->ypospix,
5766 msp_coord[jj].order);
5767 }
5768#endif
5769
5770 /*Call the main anneal algorithm in crires_model_metric.c*/
5771 conf_tab = xsh_model_anneal_comp( p_all_par,
5772 adim,
5773 abest,
5774 amin,
5775 amax,
5776 aname,
5777 p_xs_3,
5778 sizearraywavelengths,
5779 msp_coord,
5780 p_wlarray,
5781 ref_ind,
5782 MAXIT);
5783
5784 /* Save the result */
5785 cpl_msg_info(__func__, "Save the products") ;
5786 cpl_msg_indent_more() ;
5787 if (xsh_model_first_anneal_save((const cpl_table*)conf_tab, instrument,
5788 parlist,frameset) == -1) {
5789 cpl_msg_error(__func__, "Cannot save products") ;
5790 cpl_msg_indent_less() ;
5791 xsh_free_table(&conf_tab) ;
5792 return -1 ;
5793 }
5794 xsh_free_table(&conf_tab) ;
5795 cpl_msg_indent_less() ;
5796 goto cleanup;
5797
5798 cleanup:
5800 if(ref_ind!=NULL) xsh_free2Darray(ref_ind,8);
5801 cpl_free(p_wlarray);
5802 xsh_free_table(&conf_tab) ;
5803
5804 /* Return */
5805 if (cpl_error_get_code())
5806 return -1 ;
5807 else
5808 return 0 ;
5809}
5810
5811/*---------------------------------------------------------------------------*/
5820/*---------------------------------------------------------------------------*/
5821int
5823 const cpl_table* out_table,
5824 xsh_instrument* instr,
5825 cpl_parameterlist* parlist,
5826 cpl_frameset* set)
5827{
5828 char name_o[512] ;
5829 cpl_propertylist* plist=NULL ;
5830 cpl_frame* product_frame=NULL ;
5831 cpl_frameset* raws=NULL;
5832 cpl_frame* ref_frame=NULL;
5833
5834 const char* pro_catg=xsh_get_tag_from_arm(XSH_MOD_CFG_FAN,instr);
5835 /* Get the reference frame */
5836 raws=cpl_frameset_new();
5838 check(ref_frame=cpl_frameset_get_frame(raws,0));
5839 check(plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0));
5840 xsh_free_frameset(&raws);
5841
5842 /* Set the file name */
5843 sprintf(name_o,"%s%s",
5844 xsh_get_tag_from_arm(XSH_MOD_CFG_FAN,instr),".fits") ;
5845
5846 cpl_msg_info(__func__, "Writing %s" , name_o) ;
5847
5848 /* Get FITS header from reference file */
5849 cpl_propertylist_append_int(plist,"Num_pinh",9);
5850
5851
5852 /* Create product frame */
5853 check(product_frame=xsh_frame_product(name_o,pro_catg,CPL_FRAME_TYPE_TABLE,
5854 CPL_FRAME_GROUP_PRODUCT,
5855 CPL_FRAME_LEVEL_FINAL));
5856
5857 if (cpl_table_save(out_table, plist, NULL, name_o,
5858 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
5859 cpl_msg_error(__func__, "Cannot save the product");
5860 xsh_free_frame(&product_frame) ;
5861 xsh_free_propertylist(&plist) ;
5862 return -1 ;
5863 }
5864
5865 check(xsh_add_product_table(product_frame,set,parlist,"xsh_startup",
5866 instr,NULL));
5867
5868 cleanup:
5869 xsh_free_propertylist(&plist) ;
5870
5871 /* Return */
5872 if (cpl_error_get_code())
5873 return -1 ;
5874 else
5875 return 0 ;
5876
5877}
5878/*---------------------------------------------------------------------------*/
5896/*---------------------------------------------------------------------------*/
5897int
5899 DOUBLE disp_pix_shift,
5900 struct xs_3* p_xs_3)
5901{
5902 if (p_xs_3->arm!=2) {
5903 p_xs_3->chipy+=p_xs_3->pix_Y*slit_pix_shift;
5904 p_xs_3->chipx+=p_xs_3->pix_X*disp_pix_shift;
5905 }
5906 else {
5907 p_xs_3->chipx-=p_xs_3->pix_X*slit_pix_shift;
5908 p_xs_3->chipy-=p_xs_3->pix_Y*disp_pix_shift;
5909 }
5910 return 0;
5911}
5912
5913
5914static int
5915comp_center2( const void * one, const void * two )
5916{
5917 CENTER_ORDER * first = (CENTER_ORDER *)one ;
5918 CENTER_ORDER * secnd = (CENTER_ORDER *)two ;
5919
5920 if ( first->order < secnd->order ) return -1 ;
5921 else if ( first->order > secnd->order ) return 1 ;
5922 else return 0 ;
5923}
5924
5925static void
5926save_centers(CENTER_ORDER * pcent, int fpos, int npos, const char * arm )
5927{
5928 static FILE * fgnu = NULL, * freg = NULL ;
5929 static const char * gnuname =NULL ;
5930 int first_call =0;
5931 FILE *fout ;
5932 char fname[32] ;
5933 int i=0, order=0 ;
5934 CENTER_ORDER * ppcent=NULL ;
5935
5936 if ( fgnu == NULL ) {
5937 gnuname = xsh_stringcat_any( "all_orders_", arm, ".gnu", (void*)NULL ) ;
5938 fgnu = fopen( gnuname, "w" ) ;
5939 fprintf( fgnu, "set term x11\nplot " ) ;
5940 first_call = 1 ;
5941 }
5942 else first_call = 0 ;
5943 ppcent = pcent + fpos ;
5944 order = ppcent->order ;
5945 sprintf( fname, "order_%s_%02d.dat", arm, order ) ;
5946 fout = fopen( fname, "w" ) ;
5947
5948 if ( !first_call ) fprintf( fgnu, "," ) ;
5949 fprintf( fgnu, "'%s' u 1:2 w points pt 5 t''", fname ) ;
5950
5951 for( i = fpos ; i<npos; i++, ppcent++ )
5952 fprintf( fout, "%d %d %.3lf\n",
5953 ppcent->pos_x, ppcent->pos_y, ppcent->flux ) ;
5954
5955 fclose( fout ) ;
5956 if ( order == 0 ) {
5957 fprintf( fgnu, "\n" ) ;
5958 fclose( fgnu ) ;
5959 }
5960
5961 /* Now create a .reg file */
5962 if ( freg == NULL ) {
5963 freg = fopen( "order_create.reg", "w" ) ;
5964 }
5965 fprintf( freg, "# Region file format: DS9 version 4.0\n" ) ;
5966 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" ) ;
5967 fprintf( freg, "image\n# RED center_x center_y (pixels)\n" ) ;
5968 for( ppcent = pcent+fpos, i = fpos ; i <npos ; i++, ppcent++ ) {
5969 fprintf( freg, "point(%d.,%d.) #point=cross color=red font=\"helvetica 4 normal\"\n", ppcent->pos_x, ppcent->pos_y ) ;
5970 }
5971 if ( order == 0 ) {
5972 fclose( freg ) ;
5973 }
5974}
5975
5986void
5988 int size,
5989 double* order,
5990 double* posx,
5991 double* posy,
5992 int deg_poly,
5993 int edge)
5994{
5995 int ordersize=0;
5996 int i=0;
5997 int nborder=0;
5998 int nb_keep_order=0;
5999 cpl_vector *vx = NULL;
6000 cpl_vector *vy = NULL;
6001
6002 XSH_ASSURE_NOT_NULL( list);
6004 XSH_ASSURE_NOT_NULL( posx);
6005 XSH_ASSURE_NOT_NULL( posy);
6006 XSH_ASSURE_NOT_ILLEGAL( deg_poly >= 0);
6007
6008 xsh_msg("List size=%d",size);
6009 xsh_msg("Fit a polynomial of degree %d by order",deg_poly);
6010 xsh_msg("Search from order %d to %d", list->absorder_min,
6011 list->absorder_max);
6012 for(i=1; i <= size; i++) {
6013 if ( i < size && fabs(order[i-1] - order[i] ) < 0.0001) {
6014 ordersize++;
6015 }
6016 else {
6017 int absorder = order[i-1];
6018
6019 if( (absorder >= list->absorder_min) &&
6020 (absorder <= list->absorder_max) ){
6021
6022 ordersize++;
6023 check( vx = cpl_vector_wrap( ordersize, &(posx[i-ordersize])));
6024 check( vy = cpl_vector_wrap( ordersize, &(posy[i-ordersize])));
6025 xsh_msg_dbg_low("%d) absorder %lg nbpoints %d",
6026 nborder+1, order[i-1],ordersize);
6027 XSH_ASSURE_NOT_ILLEGAL_MSG(ordersize > deg_poly,
6028 "You must have more points to fit correctly this order");
6029 if (edge==-1) {
6030 check( list->list[nb_keep_order].edguppoly =
6031 xsh_polynomial_fit_1d_create(vy, vx, deg_poly,NULL));
6032 } else if (edge==0) {
6033 check( list->list[nb_keep_order].cenpoly =
6034 xsh_polynomial_fit_1d_create(vy, vx, deg_poly,NULL));
6035 } else if (edge==1) {
6036 check( list->list[nb_keep_order].edglopoly =
6037 xsh_polynomial_fit_1d_create(vy, vx, deg_poly,NULL));
6038 }
6039 list->list[nb_keep_order].order = nborder;
6040 list->list[nb_keep_order].absorder = (int)(order[i-1]);
6041
6042 check( xsh_unwrap_vector(&vx));
6043 check( xsh_unwrap_vector(&vy));
6044 nb_keep_order++;
6045 }
6046 else{
6047 xsh_msg("WARNING skipping absorder %d because is not in range",
6048 absorder);
6049 }
6050 nborder++;
6051 ordersize = 0;
6052 }
6053 }
6054 XSH_ASSURE_NOT_ILLEGAL( list->size == nb_keep_order);
6055 cleanup:
6056 xsh_unwrap_vector(&vx);
6057 xsh_unwrap_vector(&vy);
6058 return;
6059}
6060
6061static void
6063 int npos,
6064 CENTER_ORDER * pcent,
6065 int degree,
6066 int edge)
6067{
6068 double * vorder = NULL, * po =NULL;
6069 double * pos_x = NULL, * px =NULL;
6070 double * pos_y = NULL, * py =NULL;
6071 int i =0;
6072
6073 XSH_CALLOC( vorder, double, npos ) ;
6074 XSH_CALLOC( pos_x, double, npos ) ;
6075 XSH_CALLOC( pos_y, double, npos ) ;
6076
6077 po = vorder ;
6078 px = pos_x ;
6079 py = pos_y ;
6080 for( i = 0 ; i<npos ; i++, po++, px++, py++, pcent++ ) {
6081 *po = pcent->order ;
6082 *px = pcent->pos_x ;
6083 *py = pcent->pos_y ;
6084 }
6085
6086 xsh_order_edge_list_fit(list, npos, vorder, pos_x, pos_y, degree, edge) ;
6087
6088 cleanup:
6089 XSH_FREE( vorder ) ;
6090 XSH_FREE( pos_x ) ;
6091 XSH_FREE( pos_y ) ;
6092 return ;
6093}
6094
6095
6096/*----------------------------------------------------------------------------*/
6108/*----------------------------------------------------------------------------*/
6109cpl_frame*
6111 const char* tab_filename)
6112{
6113 int morder_cnt=0; /* grating spectral order */
6114 DOUBLE lambda=0; /*wavelength in mm */
6115 DOUBLE lambda_nm=0; /* wavelength in nm */
6116 DOUBLE blaze_wav=0, lam_min=0, lam_max=0, lam_inc=0;
6117
6118 int ii=0;
6119
6120 int iord=0,fpos=0,edge=0;
6121 double es_x_config=0;
6122 DOUBLE** ref_ind;
6123 cpl_propertylist* plist=NULL;
6124 CENTER_ORDER * centers = NULL ;
6125 xsh_order_list * res_list = NULL ;
6126 int low_y=0,up_y=0;
6127
6128
6129 cpl_frame* order_edges_frame=NULL;
6130
6131 xsh_instrument* instr=NULL;
6132 const char* tag=NULL;
6133
6134 char filename[256];
6135
6136 XSH_ASSURE_NOT_NULL(p_xs_3);
6137 XSH_ASSURE_NOT_NULL(tab_filename);
6138
6139/*znse_ref is the array holding Sellmeier coefs for ZnSe refractive index
6140 at each temp. Currently hard coded to take 6 temperatures in [2][*] to
6141 [7][*], can be extended. First two rows ([0][*] to [1][*]) take the entries
6142 for the temperature bracketing the operation.
6143 Column [*][0] takes the temperature, the other columns, [*][1] to [*][6]
6144 take the Sellmeier coeffs */
6145
6146 ref_ind=xsh_alloc2Darray(8,7);
6147 instr = xsh_instrument_new() ;
6148
6149 if (p_xs_3->arm==0) {
6150 tag="XSH_ORDER_TAB_EDGES_SLIT_UVB";
6151 xsh_ref_ind_read(0,ref_ind,p_xs_3->temper);
6153 }
6154 else if (p_xs_3->arm==1) {
6155 tag="XSH_ORDER_TAB_EDGES_VIS";
6156 xsh_ref_ind_read(1,ref_ind,p_xs_3->temper);
6158 }
6159 else {
6160 tag="XSH_ORDER_TAB_EDGES_NIR";
6161 xsh_ref_ind_read(2,ref_ind,p_xs_3->t_ir_p2);
6163 }
6164
6165 check(res_list=xsh_order_list_create(instr));
6166
6167 /*initalize the model. Inside the echelle_init the cfg file is
6168 read and the variables assigned to the xsh structure
6169 initialisation. Sets up those matrices that are not dependent upon
6170 wavelength */
6171 xsh_3_init(p_xs_3);
6172 es_x_config=p_xs_3->es_x;
6173
6174 for (edge=-1;edge<2;edge++) {
6175 XSH_CALLOC(centers,CENTER_ORDER,((p_xs_3->morder_max-p_xs_3->morder_min+1)*2)*100);
6176 ii=0;
6177 iord=0;
6178 fpos=0;
6179 p_xs_3->es_y_tot=p_xs_3->es_y+fabs(edge)*p_xs_3->es_s/2.0;
6180 for (morder_cnt=p_xs_3->morder_min; morder_cnt<=p_xs_3->morder_max; morder_cnt+=1) {
6181 blaze_wav=2*(sin(-p_xs_3->nug))/(morder_cnt*p_xs_3->sg);
6182 lam_max=blaze_wav*((double)(morder_cnt)/((double)(morder_cnt)-0.5));//+p_xs_3->blaze_pad;
6183 lam_min=blaze_wav*((double)(morder_cnt)/(0.5+(double)(morder_cnt)));//-p_xs_3->blaze_pad;
6184 lam_inc=(lam_max-lam_min)/(99.99);
6185 //printf("blaze wav=%lf %lf %lf\n",blaze_wav,lam_min,lam_max);
6186 for (lambda=lam_min; lambda<=lam_max; lambda+=lam_inc) {
6187 lambda_nm=lambda*mm2nm;
6188 xsh_3_eval(lambda,morder_cnt,ref_ind,p_xs_3);
6189 xsh_3_detpix(p_xs_3);
6190 if (lambda==lam_min) low_y=p_xs_3->chippix[2];
6191 if (p_xs_3->chippix[0]==1) {
6192 if (p_xs_3->chippix[1]>=1 &&
6193 p_xs_3->chippix[1]<p_xs_3->ASIZE+1 &&
6194 p_xs_3->chippix[2]>=1 &&
6195 p_xs_3->chippix[2]<p_xs_3->BSIZE+1) {
6196 printf("%d %d %d %d %lf %lf %lf \n",edge, morder_cnt, ii, fpos, lambda_nm,p_xs_3->xpospix,p_xs_3->ypospix);
6197 centers[ii].order = morder_cnt;
6198 centers[ii].pos_x = p_xs_3->chippix[1] ;
6199 centers[ii].pos_y = p_xs_3->chippix[2] ;
6200 centers[ii].flux = 0.0 ;
6201 }
6202 }
6203 ii++;
6204 }
6205 up_y=p_xs_3->chippix[2];
6206 save_centers(centers, fpos, ii,xsh_instrument_arm_tostring(instr));
6207 printf("%d %d %d, %d %d \n", ii, fpos, morder_cnt, low_y, up_y);
6208 fpos=ii;
6209 res_list->list[iord].starty = low_y ;
6210 res_list->list[iord].endy = up_y ;
6211 res_list->list[iord].absorder = morder_cnt;
6212 iord++;
6213 }
6214 qsort(centers, ii, sizeof(CENTER_ORDER), comp_center2);
6215
6216 fit_order_edge_list(res_list, ii, centers, 5, edge);
6217 XSH_FREE(centers) ;
6218 }
6219
6220 if ((xsh_free2Darray(ref_ind,8))!=0) {
6221 cpl_msg_error(__func__, "Cannot free 2D array ref_ind");
6222 return NULL;
6223 }
6224
6225 check(plist=cpl_propertylist_new());
6226 //cpl_propertylist_append_string(plist, "INSTRUME", "XSHOOTER") ;
6227 sprintf(filename,"%s.fits",tag);
6228 check(xsh_pfits_set_pcatg(plist, tag ) ) ;
6229 cpl_msg_info(__func__, "Save the tables") ;
6230
6231 check(order_edges_frame=xsh_order_list_save(res_list,instr,tab_filename,tag,p_xs_3->BSIZE)) ;
6232
6233 cleanup:
6234 xsh_free_propertylist(&plist);
6235 XSH_FREE( centers ) ;
6236 return order_edges_frame;
6237}
6238
6239
static int degree
static char mode[32]
static double sigma
static xsh_instrument * instrument
int binx
int biny
xsh_order_list * xsh_order_list_create(xsh_instrument *instr)
create an empty order list
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.
double * xsh_resid_tab_get_lambda_data(xsh_resid_tab *resid)
Get the size of the residual tab.
double * xsh_resid_tab_get_ygauss_data(xsh_resid_tab *resid)
Get the ygauss array of the residual tab.
void xsh_resid_tab_free(xsh_resid_tab **resid)
Free memory associated to a resid_tab.
xsh_resid_tab * xsh_resid_tab_load(cpl_frame *resid_tab_frame)
Load a residual tab from a frame.
double * xsh_resid_tab_get_thpre_y_data(xsh_resid_tab *resid)
Get the thpre_y array of the residual tab.
double * xsh_resid_tab_get_thpre_x_data(xsh_resid_tab *resid)
Get the slit_index array of the residual tab.
double * xsh_resid_tab_get_order_data(xsh_resid_tab *resid)
Get the Orders array of the residual tab.
double * xsh_resid_tab_get_xgauss_data(xsh_resid_tab *resid)
Get the xgauss array of the residual tab.
#define XSH_ASSURE_NOT_ILLEGAL(cond)
Definition: xsh_error.h:107
#define check(COMMAND)
Definition: xsh_error.h:71
#define XSH_ASSURE_NOT_ILLEGAL_MSG(cond, msg)
Definition: xsh_error.h:111
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
#define cknull_msg(NULLEXP,...)
Definition: xsh_error.h:73
const char * xsh_instrument_arm_tostring(xsh_instrument *i)
Get the string associated with an arm.
int xsh_instrument_get_binx(xsh_instrument *instrument)
void xsh_instrument_set_arm(xsh_instrument *i, XSH_ARM arm)
Set an arm on instrument structure.
XSH_MODE xsh_instrument_get_mode(xsh_instrument *i)
Get a mode on instrument structure.
XSH_INSTRCONFIG * xsh_instrument_get_config(xsh_instrument *i)
Get the instrument default set of keywords.
int xsh_instrument_get_biny(xsh_instrument *instrument)
XSH_ARM xsh_instrument_get_arm(xsh_instrument *i)
Get an arm on instrument structure.
void xsh_instrument_free(xsh_instrument **instrument)
free an instrument structure
xsh_instrument * xsh_instrument_new(void)
create new instrument structure
int xsh_model_readfits(double *abest, double *amin, double *amax, int *aname, const char *xs_config_file, const char *xs_config_tag, struct xs_3 *p_xs_3, ann_all_par *p_all_par)
Definition: xsh_model_io.c:570
void xsh_transpose(mat A, mat B)
matrix transposal
void xsh_refract(vec b, DOUBLE rind, vec a)
Calculate the new vector after a given incident vector passes a boundary between two materials.
double * xsh_copy2D_to_1D(double **ccdtemp, int asize, int bsize)
copy 2D to 1D array
int ** xsh_alloc2Darray_i(int asize, int bsize)
allocates memory for a 2D array of integers
int xsh_model_open_param(char *listname, char *findname, int *ref, int setref, double *best, double setbest, double *min, double *max, double gfac, double fac, int counter)
Open a parameter in the model config structure for annealing and set the limits.
int xsh_model_offset(DOUBLE slit_pix_shift, DOUBLE disp_pix_shift, struct xs_3 *p_xs_3)
convert a pixel shift measured on the detector to a shift in detector centroid
double xsh_model_sellmeier_ext(int arm, double temper, double lam_sqr)
Get the refractive index for a given temperature and wavelength from the (hard coded) extended Sellme...
float ** xsh_alloc2Darray_f(int asize, int bsize)
allocates memory for a 2D array of floats
void xsh_ref_ind_read(int arm, DOUBLE **ref_ind_T, DOUBLE temper)
Load the refractive index coeffs for a given arm and temperature.
void xsh_matrixforvector(vec a, mat B, vec c)
Realize a*B*c.
static int comp_center2(const void *one, const void *two)
void xsh_ref_ind_read_old(const char *ref_ind_file, DOUBLE **ref_ind, DOUBLE temper)
Load the refractive index array for a given arm and temperature. This old routine is only retained to...
static void save_centers(CENTER_ORDER *pcent, int fpos, int npos, const char *arm)
cpl_vector * xsh_model_refining_detect(const cpl_vector *in, int fwhm, double sigma, int display)
Detect the brightest features in a spectrum.
double xsh_physmod_grating(vec in, int m, double sg, mat in_rot, mat exit_rot, vec out)
Calculate the new vector after a given incident vector is reflected in a prism (i....
void xsh_addvectors3D(vec a, vec b)
add 2 vectors a+=b
void xsh_subtractvectors(vec a, vec b)
subtract 2 vectors a-=b
void xsh_model_get_xy(xsh_xs_3 *p_xs_3, xsh_instrument *instr, double lambda_nm, int morder, double ent_slit_pos, double *x, double *y)
Compute the detector location (floating point pixels) of a given wavelength/entrance slit position.
int xsh_model_map_ifu(double xifu, double yifu, xsh_xs_3 *p_xs_3)
Map the IFU position to spectrograph slit position using transformation provided by Ana for IFU2.
int xsh_free2Darray_f(float **ccdtemp, int asize)
free memory for a 2D array of floats
void xsh_3_detpix(struct xs_3 *p_xs_3)
Takes the physical x,y position at the detector array and converts this to a pixel position.
cpl_frame * xsh_model_order_edges_tab_create(xsh_xs_3 *p_xs_3, const char *tab_filename)
Create an order edges table using the phys mod.
void xsh_model_binxy(xsh_xs_3 *p_xs_3, int bin_X, int bin_Y)
corrects model for detector's binning
double *** xsh_alloc3Darray(int asize, int bsize, int csize)
allocate 3D array
int xsh_model_first_anneal_save(const cpl_table *out_table, xsh_instrument *instr, cpl_parameterlist *parlist, cpl_frameset *set)
Save the product of the recipe.
static cpl_error_code xsh_model_compute_residuals(xsh_xs_3 *p_xs_3, coord *msp_coord, DOUBLE *p_wlarray, DOUBLE **ref_ind, const int size, const int annealed, cpl_propertylist *resid_header, cpl_frame *resid_frame, cpl_propertylist **result)
void xsh_3_eval(DOUBLE lambda, int morder, DOUBLE **ref_ind, struct xs_3 *p_xs_3)
Compute the physical x,y position at the detector array for a given wavelength, order and parameter c...
void xsh_normz(vec a)
normalize vector
double *** xsh_alloc3Darray2(int asize, int bsize, int csize)
allocate 3D array
DOUBLE xsh_scalarproduct(vec a, vec b)
implements scalar product
#define ERROR
void xsh_initializematrix(mat A)
initialize matrix A
int xsh_free3Darray(double ***ccdtemp, int asize, int bsize)
free 3D array
double ** xsh_copy1D_to_2D(double *oneDccdtemp, int asize, int bsize)
copy 1D to 2D array
cpl_frame * xsh_model_spectralformat_create(xsh_xs_3 *p_xs_3, const char *tab_filename)
creates the model spectral format table
static void xsh_copyvector(vec a, vec b)
double xsh_model_ref_ind_air(double temper, double lam_sqr)
Return the refractive index of air at a given wavelength and temperature.
static const char * xsh_get_tag_opt_mod_cfg(xsh_xs_3 *p_xs_3, int rec_id)
#define OK
void xsh_multiplymatrix(mat A, mat B, mat C)
multiply three matrixes A=B*C
void xsh_showmatrix(mat A)
Show matrix.
int xsh_model_first_anneal(cpl_parameterlist *parlist, cpl_frameset *frameset)
Interpret the command line options and execute the data processing.
DOUBLE * xsh_alloc1Darray(int asize)
allocates memory for an array of doubles
int xsh_free2Darray(double **ccdtemp, int asize)
free memory for a 2D array of doubles
int * xsh_alloc1Darray_INT(int asize)
allocates memory for an array of integers
void xsh_3_init(struct xs_3 *p_xs_3)
Pre-compute a number of non-wavelength dependent secondary parameters required by the model.
void xsh_showvector(vec a)
show vector content
static cpl_error_code xsh_model_compute_slitmap_kw(const double slit_min, const double slit_max, xsh_xs_3 *p_xs_3, xsh_instrument *instr, cpl_propertylist **plist)
cpl_error_code xsh_model_maps_create(xsh_xs_3 *p_xs_3, xsh_instrument *instr, const char *wtag, const char *stag, cpl_frame **wmap_frame, cpl_frame **smap_frame, const int save_tmp)
Compute the wavelength and slit maps.
static void xsh_nullmatrix(mat A)
void xsh_multiplythreematrix(mat A, mat B, mat C, mat D)
multiply three matrixes A=B*C*D
void xsh_order_edge_list_fit(xsh_order_list *list, int size, double *order, double *posx, double *posy, int deg_poly, int edge)
Fit edge of an order.
cpl_frame * xsh_model_THE_create(xsh_xs_3 *p_xs_3, xsh_instrument *instr, const char *line_list, int num_ph, double sep_ph, const char *THE_filename)
Compute the THE table (centroid for each feature in lamp spectrum)
double ** xsh_alloc2Darray(int asize, int bsize)
allocates memory for a 2D array of doubles
cpl_vector ** xsh_model_locus(struct xs_3 *p_xs_3, xsh_instrument *instr, double ent_slit_pos)
Compute the locus of the spectrum.
void xsh_addvectors(vec a, vec b)
add 2 vectors a+=b
static void xsh_nullvector(vec a)
void xsh_rotationmatrix(mat A, const char axis, const DOUBLE angle)
matrix rotation
static void fit_order_edge_list(xsh_order_list *list, int npos, CENTER_ORDER *pcent, int degree, int edge)
void xsh_multiply(vec a, DOUBLE k)
applies scalar product to vector
void xsh_normall(vec a)
normalize vector
void xsh_rotin(mat A, const DOUBLE x_angle, const DOUBLE y_angle, const DOUBLE z_angle)
matrix rotation
int xsh_free2Darray_i(int **ccdtemp, int asize)
free memory for a 2D array of integers
cpl_frame * xsh_model_pipe_anneal(cpl_frame *cfg_frame, cpl_frame *resid_frame, int maxit, double ann_fac, int scenario, int rec_id)
Run the annealing (optimisation) algoritm to improve the fit of the model parameter set to a given wa...
int size
int * y
cpl_table * xsh_model_anneal_comp(ann_all_par *p_all_par, int nparam, double *abest, double *amin, double *amax, int *aname, struct xs_3 *p_xs_3, int DS_size, coord *msp_coord, DOUBLE *p_wlarray, DOUBLE **ref_ind, int maxit)
Use the simulated annealing algorithm to adjust the model parameters so that the metric (mean Euclide...
DOUBLE ** ref
int * x
#define xsh_msg_warning(...)
Print an warning message.
Definition: xsh_msg.h:88
#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_low(...)
Definition: xsh_msg.h:48
void xsh_pfits_set_pcatg(cpl_propertylist *plist, const char *value)
Write the PCATG value.
Definition: xsh_pfits.c:1008
void xsh_pfits_set_slitmap_median_cen(cpl_propertylist *plist, double value)
Definition: xsh_pfits.c:3881
void xsh_pfits_set_slitmap_median_slicup(cpl_propertylist *plist, double value)
Definition: xsh_pfits.c:3864
void xsh_pfits_set_slitmap_order_cen(cpl_propertylist *plist, int absorder, double value)
Definition: xsh_pfits.c:3794
cpl_error_code xsh_pfits_set_wcs(cpl_propertylist *header, const double crpix1, const double crval1, const double cdelt1, const double crpix2, const double crval2, const double cdelt2)
Definition: xsh_pfits.c:4364
void xsh_pfits_set_slitmap_median_edglo(cpl_propertylist *plist, double value)
Definition: xsh_pfits.c:3830
void xsh_pfits_set_slitmap_order_edgup(cpl_propertylist *plist, int absorder, double value)
Definition: xsh_pfits.c:3724
void xsh_pfits_set_slitmap_median_edgup(cpl_propertylist *plist, double value)
Definition: xsh_pfits.c:3813
void xsh_pfits_set_slitmap_order_slicup(cpl_propertylist *plist, int absorder, double value)
Definition: xsh_pfits.c:3759
void xsh_pfits_set_slitmap_median_sliclo(cpl_propertylist *plist, double value)
Definition: xsh_pfits.c:3847
void xsh_pfits_set_slitmap_order_edglo(cpl_propertylist *plist, int absorder, double value)
Definition: xsh_pfits.c:3742
void xsh_pfits_set_slitmap_order_sliclo(cpl_propertylist *plist, int absorder, double value)
Definition: xsh_pfits.c:3776
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_vector(cpl_vector **v)
Deallocate a vector and set the pointer to NULL.
Definition: xsh_utils.c:2284
void xsh_free_image(cpl_image **i)
Deallocate an image and set the pointer to NULL.
Definition: xsh_utils.c:2116
void xsh_free_frame(cpl_frame **f)
Deallocate a frame and set the pointer to NULL.
Definition: xsh_utils.c:2269
void xsh_free_frameset(cpl_frameset **f)
Deallocate a frame set and set the pointer to NULL.
Definition: xsh_utils.c:2254
char * xsh_stringcat_any(const char *s,...)
Concatenate an arbitrary number of strings.
Definition: xsh_utils.c:1925
void xsh_free_matrix(cpl_matrix **m)
Deallocate a matrix and set the pointer to NULL.
Definition: xsh_utils.c:2209
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
void xsh_add_temporary_file(const char *name)
Add temporary file to temprary files list.
Definition: xsh_utils.c:1432
unsigned int first
Definition: irplib_error.c:88
int slit_pos
double x
double y
double flux
double wave
DOUBLE mup2
DOUBLE taup1
double ca_x0
DOUBLE fcol
DOUBLE es_x
double d2_y1x0
double d2_y2x0
double d2_y1x3
double pc4_y_x3y
double config_mjd
DOUBLE nup4
DOUBLE pix
DOUBLE mup1
double chipyup
double pc4_y_y4
DOUBLE mup5
DOUBLE mud
DOUBLE rind3
DOUBLE xpospix
mat ret_prism3
double pc_x_y3
double d2_y1x2
DOUBLE pix_Y
double pc4_y_xy3
double chipx
DOUBLE nup3
DOUBLE blaze_pad
DOUBLE taug
double chipydown
double pc_x_x3
double pc_x_x2y
double pc4_y_x4
DOUBLE rind
double pc4_y_x2y2
double d2_y3x0
double pc_y_y1
double d2_y2x2
mat ret_prism2
double d2_x1
double d2_y3x2
DOUBLE nud
int morder_max
double pc4_x_xy3
DOUBLE t_ir_p3
DOUBLE pix_X
double pc_x_xy
double ydet
mat toprism2
double pc_x_y1
double ca_x1
DOUBLE taud
double chipypix
DOUBLE fdet
mat ret_prism_out2
DOUBLE nup1
DOUBLE grat_beta
DOUBLE taup5
double d2_y2x3
double xsize_corr
double chipxdown
DOUBLE taup4
double d2_y1x1
DOUBLE nup2
double pc_y_x1
DOUBLE t_ir_p2
double d2_y2x1
mat ret_prism1
DOUBLE cmup1
mat ret_prism6
double pc4_x_x3y
mat grat_out
mat toprism3
double xdet
DOUBLE slit[10]
DOUBLE flipy
mat ret_prism_out3
double pc_x_y2x
double chipy
DOUBLE grat_alpha
DOUBLE slit_scale
double pc_y_y3
DOUBLE mues
mat ret_prism5
DOUBLE rind2
DOUBLE taup6
DOUBLE flipx
DOUBLE ypospix
mat mup_ir_cor_out
DOUBLE offx
DOUBLE nues
double ca_y1
double pc_x_x1
DOUBLE mup3
DOUBLE es_y
double ca_y0
double pc_x_xx
DOUBLE mup4
DOUBLE temper
double pc4_x_x2y2
mat ret_prism_out1
mat toprism4
mat toprism6
double d2_x2
int morder_min
mat toprism5
double pc4_x_y4
double ysize_corr
DOUBLE nup6
DOUBLE offy
DOUBLE es_y_tot
double d2_x3
mat toprism1
double pc4_x_x4
mat mup_ir_cor
double d2_y3x1
DOUBLE nug
double pc_y_x3
detloc chippix
double d2_y3x3
double pc_y_y2x
double pc_y_x2y
DOUBLE sg
DOUBLE nup5
mat ret_prism4
double chipxup
DOUBLE taup3
DOUBLE mup6
double pc_y_xx
double pc_x_yy
double pc_y_xy
mat todetector
DOUBLE es_s
int morder
DOUBLE taup2
double pc_y_yy
double chipxpix
DOUBLE mug
DOUBLE taues
xsh_order * list
cpl_polynomial * edguppoly
cpl_polynomial * edglopoly
cpl_polynomial * cenpoly
cpl_propertylist * header
#define MAXIT
#define XSH_ARCLIST_TABLE_COLNAME_WAVELENGTH
#define XSH_ARCLIST_TABLE_COLNAME_FLUX
#define IFU_MAP_CEN_C2X
#define IFU_MAP_RIGHT_C2Y
#define IFU_LEFT_MIN
#define IFU_MAP_RIGHT_C2X
#define IFU_MAP_LEFT_C1X
#define IFU_LEFT_MAX
#define IFU_MAP_CEN_C2Y
#define IFU_MAP_RIGHT_C1Y
#define IFU_MAP_RIGHT_C0Y
#define IFU_CEN_MIN
#define IFU_MAP_LEFT_C2Y
#define IFU_MAP_RIGHT_C1X
@ XSH_ARM_UNDEFINED
@ XSH_ARM_UVB
@ XSH_ARM_NIR
@ XSH_ARM_VIS
#define IFU_MAP_RIGHT_C0X
#define IFU_MAP_LEFT_C2X
#define IFU_MAP_LEFT_C1Y
#define IFU_MAP_CEN_C1Y
#define IFU_SCALE
#define IFU_MAP_LEFT_C0Y
#define IFU_MAP_LEFT_C0X
#define IFU_RIGHT_MIN
@ XSH_MODE_IFU
@ XSH_MODE_UNDEFINED
#define IFU_LOW
#define IFU_MAP_CEN_C0X
#define IFU_HI
#define IFU_MAP_CEN_C0Y
#define IFU_RIGHT_MAX
#define IFU_CEN_MAX
#define IFU_MAP_CEN_C1X
#define XSH_RESID_TAB_TABLE_COLNAME_YTHANNEAL
int xsh_resid_tab_get_size(xsh_resid_tab *resid)
#define XSH_RESID_TAB_TABLE_COLNAME_RESIDYMODEL
#define XSH_RESID_TAB_TABLE_COLNAME_XGAUSS
#define XSH_RESID_TAB_TABLE_COLNAME_YGAUSS
#define XSH_RESID_TAB_TABLE_COLNAME_RESIDXMODEL
int * xsh_resid_tab_get_slit_index(xsh_resid_tab *resid)
#define XSH_RESID_TAB_TABLE_COLNAME_XTHANNEAL
#define XSH_THE_MAP_TABLE_COLNAME_SLITINDEX
#define XSH_THE_MAP_TABLE_COLNAME_WAVELENGTH
#define XSH_THE_MAP_TABLE_COLNAME_DETECTORX
#define XSH_THE_MAP_TABLE_COLNAME_SLITPOSITION
#define XSH_THE_MAP_TABLE_COLNAME_ORDER
#define XSH_THE_MAP_TABLE_COLNAME_DETECTORY
int m
Definition: xsh_detmon_lg.c:91
int order
Definition: xsh_detmon_lg.c:80
int xsh_print_rec_status(const int val)
Check if an error has happened and returns error kind and location.
Definition: xsh_dfs.c:877
void xsh_add_product_table(cpl_frame *frame, cpl_frameset *frameset, const cpl_parameterlist *parameters, const char *recipe_id, xsh_instrument *instrument, const char *final_prefix)
Save Table product (input frame has several extensions, 1 table per extension)
Definition: xsh_dfs.c:3146
cpl_error_code xsh_dfs_extract_raw_frames(cpl_frameset *input, cpl_frameset *raws)
split input sof in groups: raw and calib
Definition: xsh_dfs.c:1117
char * xsh_get_tag_from_arm(const char *tag, xsh_instrument *instr)
Find arm specific tag from base and instrument setting.
Definition: xsh_dfs.c:3374
cpl_frame * xsh_frame_product(const char *fname, const char *tag, cpl_frame_type type, cpl_frame_group group, cpl_frame_level level)
Creates a frame with given characteristics.
Definition: xsh_dfs.c:930
cpl_frame * xsh_find_frame_with_tag(cpl_frameset *frames, const char *tag, xsh_instrument *instr)
Find frame with a given tag.
Definition: xsh_dfs.c:3347
#define XSH_MOD_CFG_OPT_REC_VIS
Definition: xsh_dfs.h:1224
#define XSH_MOD_CFG_OPT_AFC_NIR
Definition: xsh_dfs.h:1259
#define XSH_MOD_CFG
Definition: xsh_dfs.h:1261
#define XSH_MOD_CFG_OPT_REC_UVB
Definition: xsh_dfs.h:1223
#define XSH_MOD_CFG_OPT_WAV_SLIT_VIS
Definition: xsh_dfs.h:1241
#define XSH_MOD_CFG_OPT_FMT_NIR
Definition: xsh_dfs.h:1230
#define XSH_MOD_CFG_OPT_2D_VIS
Definition: xsh_dfs.h:1235
#define XSH_MOD_CFG_OPT_WAV_IFU_VIS
Definition: xsh_dfs.h:1247
#define XSH_MEASCOORD
Definition: xsh_dfs.h:1271
#define XSH_MOD_CFG_OPT_FMT_UVB
Definition: xsh_dfs.h:1228
#define XSH_MOD_CFG_OPT_2D_UVB
Definition: xsh_dfs.h:1234
#define XSH_MOD_CFG_OPT_WAV_IFU_UVB
Definition: xsh_dfs.h:1246
#define XSH_MOD_CFG_OPT_WAV_IFU_NIR
Definition: xsh_dfs.h:1248
#define XSH_MOD_CFG_OPT_FMT_VIS
Definition: xsh_dfs.h:1229
#define XSH_MOD_CFG_OPT_WAV_SLIT_UVB
Definition: xsh_dfs.h:1240
#define XSH_MOD_CFG_FAN
Definition: xsh_dfs.h:1276
#define XSH_MOD_CFG_OPT_WAV_SLIT_NIR
Definition: xsh_dfs.h:1242
#define XSH_MOD_CFG_OPT_AFC_UVB
Definition: xsh_dfs.h:1257
#define XSH_MOD_CFG_OPT_2D_NIR
Definition: xsh_dfs.h:1236
#define XSH_MOD_CFG_OPT_AFC_VIS
Definition: xsh_dfs.h:1258
#define XSH_MOD_CFG_OPT_REC_NIR
Definition: xsh_dfs.h:1225
#define C(i)
#define max(a, b)
#define NIR_xsize_corr
#define UVB_xsize_corr
#define VIS_ysize_corr
#define VIS_xsize_corr
#define NIR_ysize_corr
#define UVB_ysize_corr
#define DEG2RAD
Definition: xsh_model_io.h:43
#define mm2nm
static const int vectordim
#define XSH_TRACE_MSG(array)
#define mm2um
DOUBLE mat[4][4]
#define NIR_FIX
DOUBLE vec[4]
double DOUBLE
static double schott_sf6_manu[6][7]
static double znse[6][7]
static double silica_zemax[6][7]
#define XSH_SPECTRALFORMAT_DIST_ORDER
Definition: xsh_pfits.h:210
#define XSH_QC_MODEL_ANNEAL_RESX_MAX
#define XSH_QC_MODEL_ANNEAL_RESY_RMS
#define XSH_QC_MODEL_PREDICT_RESY_MAX
#define XSH_QC_MODEL_ANNEAL_RESX_MED
#define XSH_QC_MODEL_PREDICT_RESX_MAX
#define XSH_QC_MODEL_PREDICT_RESX_MIN
#define XSH_QC_MODEL_ANNEAL_RESX_AVG
#define XSH_QC_MODEL_ANNEAL_RESY_MAX
#define XSH_QC_MODEL_ANNEAL_RESY_MED
#define XSH_QC_MODEL_PREDICT_RESY_MIN
#define XSH_QC_MODEL_PREDICT_RESX_MED
#define XSH_QC_MODEL_PREDICT_RESY_RMS
#define XSH_QC_MODEL_PREDICT_RESX_AVG
#define XSH_QC_MODEL_PREDICT_RESY_AVG
#define XSH_QC_MODEL_PREDICT_RESY_MED
#define XSH_QC_MODEL_ANNEAL_RESY_AVG
#define XSH_QC_MODEL_ANNEAL_RESY_MIN
#define XSH_QC_MODEL_ANNEAL_RESX_RMS
#define XSH_QC_MODEL_ANNEAL_RESX_MIN
#define XSH_QC_MODEL_PREDICT_RESX_RMS
#define XSH_FREE(POINTER)
Definition: xsh_utils.h:92
#define XSH_CALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:56
#define M_PI
Definition: xsh_utils.h:43
cpl_polynomial * xsh_polynomial_fit_1d_create(const cpl_vector *x_pos, const cpl_vector *values, int degree, double *mse)