UVES Pipeline Reference Manual  5.5.4
uves_physmod_utils.c
1 /* *
2  * This file is part of the ESO UVES Pipeline *
3  * Copyright (C) 2004,2005 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  * $Id: uves_physmod_utils.c,v 1.19 2010-09-24 09:32:07 amodigli Exp $
21  * $Name: not supported by cvs2svn $
22  * $Revision: 1.19 $
23  *
24  * ===========================================================================
25  */
26 /*----------------------------------------------------------------------------*/
30 /*----------------------------------------------------------------------------*/
31 
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35 
36 /*+++ uves_physmod_utils.c +++++++++++++++++++++++++++++++++++++++++++++++++++
37 
38  .COPYRIGHT (C) 1998 European Southern Observatory
39 
40  .IDENT
41 
42  .KEYWORDS uves physical model, spectroscopy, echelle,
43 
44  .USAGE .
45 
46  .INPUT .
47 
48  .OUTPUT .
49 
50  .RETURN Q1: 0: successful return
51  -1: a successful return failed
52 
53  .PURPOSE Library of UVES Physical Model Functions.
54 
55  .ALGORITHM UVES Physical Model.
56 
57  .ENVIRON MIDAS, UVES context
58 
59  .LANGUAGE C
60 
61  .AUTHOR Pascal Ballester, Olivier BOITQUIN, ESO-DMD
62 
63  .VERSION 1.0 1999/07/01 Creation
64  1999/09/30-SW Binning implemented.
65  1999/10/27-OB Bugs with n index fixed.
66 
67  .COMMENT
68 ----------------------------------------------------------------------------*/
69 
70 
71 /*-----------------------------------------------------------------------------
72  Includes
73  -----------------------------------------------------------------------------*/
74 #include <uves_physmod_utils.h>
75 
76 #include <uves_utils.h>
77 #include <uves_utils_wrappers.h>
78 #include <uves_error.h>
79 #include <uves_msg.h>
80 
81 #include <cpl.h>
82 
83 #include <stdio.h>
84 #include <math.h>
85 
86 /*-----------------------------------------------------------------------------
87  Functions prototypes
88  -----------------------------------------------------------------------------*/
89 static void
90 beta2lamb(double uves_beta_ech, double uves_beta_cd, double* plambda, int m);
91 
92 static double
93 cameraFocal(double lm);
94 
95 static void
96 uves_physmod_find_alpha_beta(double lm,
97  int m,
98  double k,
99  double theta,
100  double *alpha,
101  double *beta);
102 
103 static double
104 uves_physmod_find_lambda(double k, double alpha, double beta);
105 
106 static double
107 uves_physmod_find_order_lambda(double k, double alpha, double beta);
108 /* not used:
109 static void
110 uves_physmod_lambda_model(double* plambda,
111  int m,
112  double fc,
113  double x,
114  double y);
115 */
116 static void
117 uves_physmod_lambda_order_beta(double* plambda,
118  int* pm,
119  double x,
120  double y,
121  double* puves_beta_ech,
122  double* puves_beta_cd);
123 
124 static void
125 uves_physmod_lambda_order_focus_model(double* plambda,
126  double* pdm,
127  double fc,
128  double x,
129  double y);
130 
131 static double uves_physmod_wave_bin(double l, int m);
132 
133 static void uves_physmod_xy2beta(double* puves_beta_ech,
134  double* puves_beta_cd,
135  double fc,
136  double x,
137  double y);
138 
139 static void uves_physmod_set_binning(float binx, float biny);
140 
141 static double dsqrarg;
142 
143 /*-----------------------------------------------------------------------------
144  Defines
145  -----------------------------------------------------------------------------*/
146 
147 #define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)
148 
149 #define PROID "physmod.c"
150 
151 
152 
153 
154 enum uves_arm_ident {UVES_ARM_UNDEF,UVES_ARM_BLUE,UVES_ARM_RED};
155 enum uves_arm_ident uves_arm_ident = UVES_ARM_UNDEF;
156 
157 
158 /* for messout function: no "static" (clear) -
159  no "extern" (otherwise redeclaration in all files neccessary) */
160 
161 /* globals declared as extern in physmod.h */
162 
163 float uves_bin[2] = {1, 1}; /* binning of exposure in x and y */
164 static double uves_physmod_pix_size[2] = {15e-6, 15e-6}; /* meters */
165 static double delta[2] = {75.04, 76.0};
166 
167 static double cdgroov[4] = {1000.0e-6, 660.0e-6, 600.0e-6, 312.5e-6}; /* grooves/nm */
168 static double uves_ech_groov[2] = {31.6e-6, 41.59e-6}; /* grooves/nm */
169 /*double uves_ech_blaze[2] = {75.04, 75.9}; degrees */
170 /*double uves_ech_blaze[2] = {74.74, 76.1};*/
171 static double uves_ech_blaze[2] = {74.57, 75.9}; /* degrees */
172 /*double cdbeam[2] = {45.336, 45.0}; degrees */
173 /*double cdbeam[2] = {45.336, 45.9};*/
174 /*double cdbeam[2] = {45.336, 45.0}; degrees */
175 static double cdbeam[2] = {45.336, 46.0}; /* degrees */
176 /*double uves_ccd_rot[2] = {0.7, -0.45}; degrees */
177 /*double uves_ccd_rot[2] = {-1.0, -1.50}; */
178 /*double uves_ccd_rot[2] = {0.2, -0.45}; degrees */
179 double uves_ccd_rot[2] = {0.3, -0.55}; /* degrees old */
180 /* blue detector upgrade 2004-10-13 */
181 /* double uves_ccd_rot[2] = {0.3, -0.10}; degrees new */
182 static int imsize[2] = {4096, 3000}; /* pixels */
183 static int uves_physmod_row_size[2] = {2048, 2048}; /* pixels */
184 
185 /* Configurations
186  1:Blue CD1, 2:Blue CD2,
187  3:Red CD 3 EEV, 4:Red CD 4 EEV,
188  5:Red CD3 MIT, 6: Red CD4 MIT
189 */
190 
191 /* old */
192 double uves_physmod_offsetx[6]={1391.0,1385.0,1852.0,1835.0,1852.0,1834.0};
193 double uves_physmod_offsety[6]={1030.0,1025.0,2098.0,2104.0,-52.0,-49.0};
194 
195 /* blue detector upgrade 2004-10-13 */
196 /* double uves_physmod_offsetx[6]={1355.0,1350.0,1852.0,1835.0,1852.0,1834.0}; new */
197 /* double uves_physmod_offsety[6]={1030.0,1023.0,2098.0,2104.0,-52.0,-49.0}; new */
198 
199 static double flipx = 1.;
200 static double flipy = -1.;
201 double uves_airt = 25; /* Celsius */
202 double uves_airp = 760; /* mmHg */
203 double uves_airw = 3; /* mmHg */
204 
205 int uves_cfg_indx = 0;
206 int uves_x_disp_id = 0;
207 static int uves_ech_id = 0;
208 double uves_alpha0_cd, uves_beta0_cd;
209 char uves_arm_id = 'x';
210 
211 static double uves_deg2rad = M_PI/180.;
212 
213 /* For history, please keep track HERE of the previous offset used:
214 Garching 1:
215 double uves_physmod_offsetx[6]={1470.0,1450.0,2130.0,2140.0,2130.0,2140.0};
216 double uves_physmod_offsetx[6]={1515.0,1514.0,2010.0,2000.0,2010.0,2000.0};
217 
218 Comissioning 1:
219 double uves_physmod_offsetx[6]={1474.0,1471.0,1960.0,1948.0,1961.0,1949.0};
220 
221 Comissioning 2, Dec 2000:
222 double uves_physmod_offsetx[6]={1390.0,1386.0,1849.0,1840.0,1854.0,1840.0};
223 
224 Paranal 2, Feb 2000:
225 double uves_physmod_offsetx[6]={1390.0,1384.0,1851.0,1840.0,1851.0,1839.0};
226 
227 Garching 1:
228 double uves_physmod_offsety[6]={1030.0,1030.0,2020.0,2020.0,-125.0,-115.0};
229 double uves_physmod_offsety[6]={1029.0,1025.0,2072.0,2080.0,-74.0,-65.0};
230 
231 Comissioning 1:
232 double uves_physmod_offsety[6]={1027.0,1024.0,2069.0,2077.0,-74.0,-65.0};
233 
234 Comissioning 2, Dec 2000:
235 double uves_physmod_offsety[6]={1027.0,1025.0,2084.0,2094.0,-65.0,-54.0};
236 
237 Paranal 2, Feb 2000:
238 double uves_physmod_offsety[6]={1030.0,1025.0,2088.0,2094.0,-57.0,-54.0};
239 
240 The gap between the EEV and MIT chips is estimated to 95 pixels */
241 /*
242 Mean pixel-scales for the 6 configurations:
243  pixscale : 0.252396, 0.246, 0.182, 0.175266, 0.182, 0.175266 */
244 
245 /*---------------------------------------------------------------------*/
246 
247 
259 void
260 uves_physmod_set_incidence(double echred,
261  double echblue,
262  double xred,
263  double xblue)
264 {
265  uves_ech_blaze[0] += echred;
266  uves_ech_blaze[1] += echblue;
267  cdbeam[0] += xred;
268  cdbeam[1] += xblue;
269  uves_msg_debug("uves_ech_blaze=%f,%f ccdbeam=%f,%f",
270  uves_ech_blaze[0],uves_ech_blaze[1],cdbeam[0],cdbeam[1]);
271 }
272 
279 void
280 uves_set_ccd_rot(double* ccdrot,
281  double uves_ccd_rot_off_red,
282  double uves_ccd_rot_off_blue)
283 {
284  uves_ccd_rot[0] =ccdrot[0];
285  uves_ccd_rot[1] =ccdrot[1];
286 
287  uves_ccd_rot[0] += uves_ccd_rot_off_red;
288  uves_ccd_rot[1] += uves_ccd_rot_off_blue;
289 
290  uves_msg_debug("uves_ccd_rot[0,1]=%f,%f uves_ccd_rot_off: red,blue=%f,%f",
291  uves_ccd_rot[0],uves_ccd_rot[1],uves_ccd_rot_off_red,uves_ccd_rot_off_blue);
292 
293 }
294 
304 void
305 uves_physmod_set_offset(double offset_x,
306  double offset_y,
307  double uves_physmod_x_off,
308  double yoff)
309 {
310  uves_physmod_offsetx[uves_cfg_indx-1]=offset_x;
311  uves_physmod_offsety[uves_cfg_indx-1]=offset_y;
312 /*
313  uves_msg("offset_x=%f offset_y=%f",offset_x,offset_y);
314  uves_msg("uves_physmod_offsetx=%f
315  uves_physmod_offsety=%f
316  uves_physmod_x_off=%f
317  yoff=%f",
318  uves_physmod_offsetx[uves_cfg_indx-1],
319  uves_physmod_offsety[uves_cfg_indx-1],
320  uves_physmod_x_off,
321  yoff);
322 */
323  uves_physmod_offsetx[uves_cfg_indx-1] += uves_physmod_x_off;
324  uves_physmod_offsety[uves_cfg_indx-1] += yoff;
325  /*
326  uves_msg("uves_physmod_offsetx=%f
327  uves_physmod_offsety=%f
328  uves_physmod_x_off=%f
329  yoff=%f",
330  uves_physmod_offsetx[uves_cfg_indx-1],
331  uves_physmod_offsety[uves_cfg_indx-1],
332  uves_physmod_x_off,
333  yoff);
334  */
335 }
336 
337 
344 void uves_physmod_set_binning(float binx, float biny)
345 {
346  uves_bin[0] = binx;
347  uves_bin[1] = biny;
348 }
349 
350 
361 void uves_air_config(double p, double t, double w)
362 {
363  uves_airt = t;
364  uves_airp = p;
365  uves_airw = w;
366  uves_msg_debug("uves_airt=%f uves_airp=%f uves_airw=%f",
367  uves_airt,uves_airp,uves_airw);
368 }
369 
374 double uves_air_index(double lambda)
375 {
376  /* wavelength is expected in nanometers. */
377  double t1, t2, t3, airdx;
378 
379  t1 = 1.0e-6/lambda/lambda; /* 1e-6 for nm to um conversion, squared */
380 
381  t2 = (64.328+29498.1/(146.0-t1)+255.4/(41.0-t1))*uves_airp*
382  (1.0+1.0e-6*(1.049-0.0157*uves_airt)*uves_airp)/
383  (720.883*(1.0+0.003661*uves_airt));
384 
385  t3 = t2 - uves_airw*(0.0624 - 0.000680*t1)/(1+0.003661*uves_airt);
386 
387  airdx = 1.0+ t3*1.0e-6;
388  /* airdx = 1.0; */
389  /*
390  uves_msg_debug("uves_airt=%f uves_airp=%f uves_airw=%f",
391  uves_airt,uves_airp,uves_airw);
392  uves_msg_debug("lambda=%f t1=%g t2=%g t3=%g airdx=%g",
393  lambda,t1,t2,t3,airdx);
394  */
395  return(airdx);
396 }
397 
398 
408 void
409 uves_physmod_find_alpha_beta(double lm,
410  int m,
411  double k,
412  double theta,
413  double *alpha,
414  double *beta)
415 {
416 
417  /* Solves sin(alpha) + sin(beta) = m*k*lm, given beta - alpha = theta */
418  uves_msg_debug("lm, m, k, theta : %f %d %f %f",lm,m,k,theta);
419 
420  lm /= uves_air_index(lm);
421 
422  *alpha = 0.5* ( 2*asin( m*k*lm/2/cos(theta*uves_deg2rad/2) ) +
423  theta*uves_deg2rad );
424  *beta = 0.5* ( 2*asin( m*k*lm/2/cos(theta*uves_deg2rad/2) ) -
425  theta*uves_deg2rad );
426  *alpha /= uves_deg2rad;
427  *beta /= uves_deg2rad;
428 }
429 
445 int
446 uves_config(char uves_arm,
447  char uves_ccd_id,
448  int disp,
449  double waveCent,
450  float binx,
451  float biny)
452 {
453 
454  int cfg = 0;
455  uves_ech_id = 2;
456  uves_x_disp_id = disp;
457  uves_arm_id = uves_arm;
458 
459 /* uves_msg("Configuring:
460  Arm %c
461  CCD %c
462  Xdisp %d
463  Wave %f",
464  uves_arm,
465  uves_ccd_id,
466  disp,
467  waveCent);
468 */
469  uves_msg("Cfg: Arm %c CCD %c Xdisp %d Wave %f",
470  uves_arm,uves_ccd_id,disp,waveCent);
471 
472  if (uves_arm == 'b' && disp == 1) cfg = 1;
473  if (uves_arm == 'b' && disp == 2) cfg = 2;
474 
475  if (uves_arm == 'r' && disp == 3) {
476  uves_ech_id = 1;
477  if (uves_ccd_id == 'e') cfg = 3;
478  if (uves_ccd_id == 'm') cfg = 5;
479  }
480  if (uves_arm == 'r' && disp == 4) {
481  uves_ech_id = 1;
482  if (uves_ccd_id == 'e') cfg = 4;
483  if (uves_ccd_id == 'm') cfg = 6;
484  }
485 
486  if (cfg == 0) {
487  cpl_msg_error(__func__,"Wrong configuration!");
488  return -1;
489  }
490 
491  uves_cfg_indx = cfg;
492 
493  (void) uves_physmod_set_binning(binx, biny);
494  (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
495  cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
496 
497 
498  uves_msg("alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
499  uves_alpha0_cd, uves_beta0_cd,cfg, uves_ccd_id);
500 
501  return(cfg);
502 
503 }
513 int
514 uves_config_cpl_new(int uves_arm,
515  int upper,
516  int disp,
517  double waveCent,
518  float binx,
519  float biny)
520 {
521  int cfg = 0;
522  uves_ech_id = 2;
523  uves_x_disp_id = disp;
524 
525 /* uves_msg("Configuring:
526  Arm %c
527  CCD %c
528  Xdisp %d
529  Wave %f",
530  uves_arm,
531  uves_ccd_id,
532  disp,
533  waveCent);
534 */
535  uves_msg("New Cfg: Arm [b/r] %d CCD eev/mit %d Xdisp %d Wave %f",
536  uves_arm,upper,disp,waveCent);
537 
538  if (uves_arm == ARM_BLUE && disp == 1) cfg = 1;
539  if (uves_arm == ARM_BLUE && disp == 2) cfg = 2;
540 
541  if (uves_arm == ARM_RED && disp == 3) {
542  uves_ech_id = 1;
543  if (upper == 0) cfg = 3;
544  if (upper == 1) cfg = 5;
545  }
546  if (uves_arm == ARM_RED && disp == 4) {
547  uves_ech_id = 1;
548  if (upper == 0) cfg = 4;
549  if (upper == 1) cfg = 6;
550  }
551 
552  if (cfg == 0) {
553  cpl_msg_error(__func__,"Wrong configuration!");
554  return -1;
555  }
556 
557  uves_cfg_indx = cfg;
558 
559  (void) uves_physmod_set_binning(binx, biny);
560  (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
561  cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
562 
563 
564  uves_msg("alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
565  uves_alpha0_cd, uves_beta0_cd,cfg, upper == 0 ? 'e' : 'm');
566 
567  return(cfg);
568 
569 }
570 
589 int
590 uves_config_cpl(int blue,
591  int upper,
592  int disp,
593  double waveCent,
594  float binx,
595  float biny)
596 {
597 
598 
599  int cfg = 0;
600  uves_ech_id = 2;
601  uves_x_disp_id = disp;
602 
603 /* uves_msg("Configuring:
604  Arm %c
605  CCD %c
606  Xdisp %d
607  Wave %f",
608  uves_arm,
609  uves_ccd_id,
610  disp,
611  waveCent);
612 */
613  uves_msg("Cfg cpl: Arm [b/r] %d CCD eev/mit %d Xdisp %d Wave %f",
614  blue,upper,disp,waveCent);
615 
616  if (blue == 1 && disp == 1) cfg = 1;
617  if (blue == 1 && disp == 2) cfg = 2;
618 
619  if (blue == 0 && disp == 3) {
620  uves_ech_id = 1;
621  if (upper == 0) cfg = 3;
622  if (upper == 1) cfg = 5;
623  }
624  if (blue == 0 && disp == 4) {
625  uves_ech_id = 1;
626  if (upper == 0) cfg = 4;
627  if (upper == 1) cfg = 6;
628  }
629 
630  if (cfg == 0) {
631  uves_msg_error("Wrong configuration!");
632  return -1;
633  }
634 
635  uves_cfg_indx = cfg;
636 
637  (void) uves_physmod_set_binning(binx, biny);
638  (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
639  cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
640 
641 
642  uves_msg("alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
643  uves_alpha0_cd, uves_beta0_cd,cfg, upper == 0 ? 'e': 'u');
644 
645  return(cfg);
646 
647 }
648 
668 double cameraFocal(double lm)
669 
670 {
671  double nfk=0.;
672  /*uves_msg("lm = %f ", lm);*/
673  /* uves_msg_debug("lm=%g uves_air_index(lm)=%g",lm,uves_air_index(lm)); */
674 
675  lm /= uves_air_index(lm);
676  /* uves_msg_debug("uves_arm=%d",uves_arm_ident); */
677  if (uves_arm_id == 'b' ) {
678  /* uves_msg_debug("uves_arm blue"); */
679  nfk=5.3961886e-7*lm*lm*lm-0.00079597882*lm*lm+0.41122805*lm+287.89644;
680  }
681 
682  if (uves_arm_id == 'r' ) {
683  /* uves_msg_debug("uves_arm red"); */
684  nfk=6.0172051e-13*lm*lm*lm*lm*lm-2.5623231e-9*lm*lm*lm*lm+
685  4.3585543e-6*lm*lm*lm -0.0037286381*lm*lm+
686  1.6289971*lm + 210.06767;
687 
688  }
689  /* uves_msg_debug("lm=%g nfk=%g",lm,nfk); */
690 
691  /*uves_msg("Nfk = %f, lm = %f",nfk/1000.,lm); */
692 return(nfk/1000.);
693 
694 }
695 
696 
702 int uves_physmod_find_order(double lm)
703 {
704  int order;
705  double k, alpha, beta;
706 
707  lm /= uves_air_index(lm);
708 
709  k = uves_ech_groov[uves_ech_id-1];
710  alpha = uves_ech_blaze[uves_ech_id-1];
711  beta = uves_ech_blaze[uves_ech_id-1];
712  order = (int)((sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad))/k/lm + 0.5);
713  /*
714  uves_msg_debug("uves_ech_id=%d lm %g airindex %g k=%g alpha=%g beta=%g
715  order=%d",uves_ech_id,lm,uves_air_index(lm),k,alpha,beta,order);
716  */
717  return order;
718 }
719 
727 double uves_physmod_find_order_lambda(double k, double alpha, double beta)
728 {
729  double ML;
730  ML = ( ( sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad) )/k);
731  ML *= uves_air_index(ML);
732  return(ML);
733 }
734 
735 
742 double uves_physmod_find_lambda(double k, double alpha, double beta)
743 {
744  double L;
745  L = (sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad) )/k ;
746  L *= uves_air_index(L);
747  return(L);
748 }
749 
757 double uves_physmod_find_beta(int m, double k, double l, double alpha)
758 {
759  /* uves_msg ("m, k, l, alpha: %d %f %f %f",m, k, l, alpha); */
760 
761  l /= uves_air_index(l);
762 
763  /* I check that the argument of asin is <=0 otherwhise return
764  a dummy angle (~89 deg) which will produce (x,y) pos out
765  of detector so the line will be discarted
766  */
767  /*
768  uves_msg_debug("l=%g m*k*l=%g alpha=%g",l,m*k*l,alpha);
769  */
770  if ( (m*k*l - sin(alpha*uves_deg2rad)) <=1.0 )
771  {
772  return( (asin(m*k*l - sin(alpha*uves_deg2rad)))/uves_deg2rad );
773  }
774  else
775  {
776  return( (asin(0.999))/uves_deg2rad );
777  }
778 }
779 
788 void
789 uves_physmod_lambda_order2beta(double lambda,
790  int m,
791  double* puves_beta_ech,
792  double* puves_beta_cd,
793  double* pfc)
794 {
795  /* uves_msg ("Disp: %d Ech: %d",uves_x_disp_id,uves_ech_id-1); */
796 
797 /* lambda /= uves_air_index(lambda); bog fixed ! */
798 
799  *pfc = cameraFocal(lambda);
800 
801  /* uves_msg ("New Camera focal (m) : %f",fc); */
802 
803  *puves_beta_ech = uves_physmod_find_beta(m, uves_ech_groov[uves_ech_id-1],
804  lambda, uves_ech_blaze[uves_ech_id-1]);
805 
806  *puves_beta_cd = uves_physmod_find_beta(1, cdgroov[uves_x_disp_id-1],
807  lambda, uves_alpha0_cd);
808  /* uves_msg_debug("fc=%g uves_beta_ech=%g uves_beta_cd=%g"
809  ,*pfc,*puves_beta_ech,*puves_beta_cd); */
810 
811 }
812 
821 void
822 uves_beta2xy(double uves_beta_cd,
823  double uves_beta_ech,
824  double fc,
825  double* px,
826  double* py)
827 {
828  double xd, yd, xr, yr, angle;
829 
830  xd = fc*tan( (uves_beta_ech - uves_ech_blaze[uves_ech_id-1])*
831  uves_deg2rad )/
832  uves_physmod_pix_size[0]/uves_bin[0];
833  yd = fc*tan( (uves_alpha0_cd - uves_beta_cd -
834  cdbeam[uves_ech_id-1])*uves_deg2rad )/
835  uves_physmod_pix_size[1]/uves_bin[1];
836 
837  //CHECK
838  uves_msg_debug("beta(CD), yorg: %f %f", uves_beta_cd, yd);
839 
840  xd = xd*flipx;
841  yd = yd*flipy;
842  uves_msg_debug ("Positions after flip: %f %f",xd,yd);
843 
844  angle = uves_ccd_rot[uves_ech_id-1]*uves_deg2rad;
845  xr = xd*cos(angle) + yd*sin(angle);
846  yr = -xd*sin(angle) + yd*cos(angle);
847 
848  uves_msg_debug ("Rotated positions %f %f",xr,yr);
849 
850  *px = uves_physmod_offsetx[uves_cfg_indx-1] / uves_bin[0] + xr;
851  *py = uves_physmod_offsety[uves_cfg_indx-1] / uves_bin[1] + yr;
852 
853 
854 }
855 
866 void
867 uves_physmod_photo_beta(double lambda,
868  double uves_beta_ech,
869  double uves_beta_cd,
870  double* puves_physmod_rech,
871  double* puves_physmod_rcd,
872  double* pblz)
873 {
874  double gam;
875  /*
876  uves_msg("uves_ech_id = %d, uves_ech_blaze = %f",
877  uves_ech_id,uves_ech_blaze[uves_ech_id-1]);
878  uves_msg("uves_deg2rad=%f uves_beta_ech=%f uves_alpha0_cd=%f",
879  uves_deg2rad,uves_beta_ech,uves_alpha0_cd);
880  */
881  *puves_physmod_rech = cos(uves_ech_blaze[uves_ech_id-1]*uves_deg2rad)/
882  cos(uves_beta_ech*uves_deg2rad);
883 
884  *puves_physmod_rcd = cos(uves_alpha0_cd*uves_deg2rad)/
885  cos(uves_beta_cd*uves_deg2rad);
886  /*
887  uves_msg("puves_physmod_rech=%f *puves_physmod_rcd=%f",
888  *puves_physmod_rech,*puves_physmod_rcd);
889  */
890  /* Computes the blaze function */
891  gam = M_PI / uves_ech_groov[uves_ech_id-1] *
892  cos(delta[uves_ech_id-1]*uves_deg2rad) *
893  (sin((uves_beta_ech-delta[uves_ech_id-1])*uves_deg2rad)-
894  sin((uves_ech_blaze[uves_ech_id-1]-delta[uves_ech_id-1])*
895  uves_deg2rad))
896  / lambda/ uves_air_index(lambda);
897  *pblz = DSQR(sin(gam)/gam);
898  /*
899  uves_msg("gamma = %f, Blaze function = %g ",gam,blz);
900  */
901 }
902 
926 void uves_physmod_pixscl(
927  double wave,
928  int order,
929  double uves_physmod_rech,
930  double uves_physmod_rcd,
931  float binx,
932  float biny,
933  double fc,
934  double slitwidth,
935  double slitlength,
936  double* pbinsize,
937  double* ppixscale,
938  double* ppixscalCD,
939  double* plinewidpx,
940  double* plinelenpx,
941  double* plinewidth,
942  double* presol)
943 {
944  double binsize, pixscale, pixscalCD, linewidpx, linelenpx, linewidth, resol;
945  static double scale;
946 
947  if (!(scale)) scale = (206265.0*15.0*0.015*200*1e-3*binx)/120000;
948 
949  /*
950  uves_msg("scale=%f
951  wave=%f
952  order=%d
953  fc=%f
954  uves_physmod_rech=%f
955  binx=%f
956  biny=%f
957  uves_physmod_rcd=%f",
958  scale,
959  wave,
960  order,
961  fc,
962  uves_physmod_rech,
963  binx,
964  biny,
965  uves_physmod_rcd);
966  */
967 /* Computes the width (in pixel and A) and resolution lines */
968  binsize = uves_physmod_wave_bin(wave, order) * 1e4; /* in mA */
969  pixscale = scale/(fc*uves_physmod_rech); /* in arcsec/pixel */
970  pixscalCD = pixscale *(biny/binx) *uves_physmod_rech/uves_physmod_rcd; /* in arcsec/pixel */
971  linewidpx = slitwidth / pixscale; /* pixel */
972  linelenpx = slitlength /pixscalCD; /* pixel */
973  linewidth = binsize * linewidpx * 1e-3; /* in A (* pixel) */
974  resol = wave * 10.0 / linewidth; /* without unit */
975  /* (10.0: conversion factor from nm to A)*/
976 
977  /*
978  uves_msg("slitwidth=%f slitlength=%f binsize=%f pixscale=%f pixscaleCD=%f",
979  slitwidth, slitlength, binsize, pixscale, pixscalCD);
980 
981  uves_msg("linewidpx=%f linewidth=%f resol=%f",
982  linewidpx, linewidth, resol);
983  */
984  *pbinsize = binsize;
985  *ppixscale = pixscale;
986  *ppixscalCD = pixscalCD;
987  *plinewidpx = linewidpx;
988  *plinelenpx = linelenpx;
989  *plinewidth = linewidth;
990  *presol = resol;
991 
992 }
993 
1001 void
1002 uves_physmod_xy_model(double lambda, int m, double* px, double* py)
1003 {
1004  double fc, uves_beta_ech, uves_beta_cd;
1005  //CHECK
1006  uves_physmod_lambda_order2beta(lambda, m, &uves_beta_ech, &uves_beta_cd, &fc);
1007  uves_msg_debug("lambda=%f m=%d uves_beta_ech=%f,uves_beta_cd=%f,fc=%f",
1008  lambda,m,uves_beta_ech,uves_beta_cd,fc);
1009 
1010  uves_beta2xy(uves_beta_cd, uves_beta_ech, fc, px, py);
1011  uves_msg_debug("px=%f py=%f",*px,*py);
1012 
1013 /* exemple :
1014  uves_physmod_photo_beta(lambda, uves_beta_ech, uves_beta_cd,
1015  puves_physmod_rech, puves_physmod_rcd, pblz);
1016 */
1017 
1018 }
1019 
1028 void
1029 uves_physmod_xy2beta(double* puves_beta_ech,
1030  double* puves_beta_cd,
1031  double fc,
1032  double x,
1033  double y)
1034 {
1035  double xr, yr, xd, yd, angle;
1036 
1037  angle = uves_ccd_rot[uves_ech_id-1]*uves_deg2rad;
1038 
1039  xr = (x - uves_physmod_offsetx[uves_cfg_indx-1]/uves_bin[0]);
1040  yr = (y - uves_physmod_offsety[uves_cfg_indx-1]/uves_bin[1]);
1041 
1042  xd = xr*cos(angle) - yr*sin(angle);
1043  yd = xr*sin(angle) + yr*cos(angle);
1044 
1045  xd /= flipx;
1046  yd /= flipy;
1047 
1048  *puves_beta_ech = atan(xd*uves_physmod_pix_size[0]*uves_bin[0]/fc)/
1049  uves_deg2rad + uves_ech_blaze[uves_ech_id-1];
1050  *puves_beta_cd = uves_alpha0_cd - cdbeam[uves_ech_id-1] -
1051  atan(yd*uves_physmod_pix_size[1]*uves_bin[1]/fc)/
1052  uves_deg2rad;
1053 
1054 }
1055 
1064 static void
1065 beta2lamb(double uves_beta_ech,
1066  double uves_beta_cd,
1067  double* plambda,
1068  int m)
1069 {
1070  uves_beta_cd=uves_beta_cd;
1071  *plambda = uves_physmod_find_lambda(m*uves_ech_groov[uves_ech_id-1],
1072  uves_ech_blaze[uves_ech_id-1], uves_beta_ech);
1073 
1074 }
1075 
1088 void
1089 uves_physmod_lambda_order_focus_model(double* plambda,
1090  double* pdm,
1091  double fc,
1092  double x,
1093  double y)
1094 {
1095 
1096  double uves_beta_ech, uves_beta_cd;
1097 
1098  uves_physmod_xy2beta(&uves_beta_ech, &uves_beta_cd, fc, x, y);
1099 
1100  *plambda = uves_physmod_find_order_lambda(cdgroov[uves_x_disp_id-1],
1101  uves_alpha0_cd, uves_beta_cd);
1102  *pdm = uves_physmod_find_order_lambda(uves_ech_groov[uves_ech_id-1],
1103  uves_ech_blaze[uves_ech_id-1], uves_beta_ech)/(*plambda);
1104 /*
1105  uves_msg(" m= %f, lambda= %f, position (x,y)= (%f , %f)",
1106  *pdm,*plambda, x,y);
1107 */
1108 }
1109 
1110 /*************************************************************************
1111  * Finds the couple lambda,m corresponding to a given position (x,y),
1112  * assuming the focal of the camera for this wavelength is fc.
1113  *************************************************************************
1114  */
1115 /* Not used:
1116 void
1117 uves_physmod_lambda_model(double* plambda,
1118  int m,
1119  double fc,
1120  double x,
1121  double y)
1122 {
1123 
1124  double uves_beta_ech, uves_beta_cd;
1125 
1126  uves_physmod_xy2beta(&uves_beta_ech, &uves_beta_cd, fc, x, y);
1127 
1128 
1129  beta2lamb(uves_beta_ech, uves_beta_cd, plambda, m);
1130 
1131 }
1132 */
1133 
1148 void
1149 uves_physmod_lambda_order_beta(double* plambda,
1150  int* pm,
1151  double x,
1152  double y,
1153  double* puves_beta_ech,
1154  double* puves_beta_cd)
1155 {
1156 
1157 double fcguess=0., wave=0., mdbl=0., xe=0., ye=0., xd=0., yd=0.;
1158 int i=0;
1159 
1160 if (uves_arm_id == 'b') fcguess = 0.360;/*0.35722;*/
1161 if (uves_arm_id == 'r') fcguess = 0.500;
1162 
1163 uves_physmod_lambda_order_focus_model(&wave,&mdbl,fcguess,x,y);
1164 /*
1165 if (x == 1500.) {
1166  uves_msg("m= %f, lambda= %f, position (x,y)= (%f , %f)",mdbl,wave, x,y);
1167  uves_msg("focal guess= %f",fcguess);
1168 }
1169 */
1170 do {
1171 
1172  fcguess = cameraFocal(wave);
1173  /*
1174  if (x == 1500.) {
1175  uves_msg("i= %d, focal = %f, m= %f, lambda= %f", i,fcguess,mdbl,wave);
1176  }
1177  */
1178  if (*pm <= 0) *pm = (int)(mdbl+0.5);
1179 /* uves_physmod_lambda_model(&wave,*pm,fcguess,x,y); */
1180  uves_physmod_xy2beta(puves_beta_ech, puves_beta_cd, fcguess, x, y);
1181  beta2lamb(*puves_beta_ech, *puves_beta_cd, &wave, *pm);
1182 
1183  /*
1184  if (x == 1500.) {
1185  uves_msg("i= %d, focal = %f, m= %d, lambda= %f", i,fcguess,*pm,wave);
1186  }
1187  */
1188 
1189  uves_physmod_xy_model(wave,(int)(mdbl+0.5), &xe, &ye);
1190  /*
1191  if (x == 1500.) {
1192  uves_msg("m= %f, lambda= %f, position (xe,ye)= (%f , %f)",
1193  mdbl,wave, xe,ye);
1194  uves_msg("focal = %f",fcguess);
1195  }
1196  */
1197  i++;
1198 
1199  xd = fabs(x-xe);
1200  yd = fabs(y-ye);
1201 
1202  } while (!((xd < 1.) && (yd < 1.)) && (i <= 4));
1203 
1204 *plambda = wave;
1205 
1206 /*uves_msg("i= %d", i);*/
1207 /* uves_physmod_photo_beta(wave, *puves_beta_ech, *puves_beta_cd,
1208  puves_physmod_rech, puves_physmod_rcd, pblz);
1209 uves_msg("uves_physmod_lambda_order_beta(%f, %d, %f, %f, %f, %f)",
1210  wave, *pm, x, y, *puves_beta_ech, *puves_beta_cd);
1211 */
1212 
1213 }
1214 
1228 void
1229 uves_physmod_lambda_order_model(double* plambda, int* pm, double x, double y)
1230 {
1231 
1232  double uves_beta_ech, uves_beta_cd;
1233 
1234  uves_physmod_lambda_order_beta(plambda, pm, x, y,
1235  &uves_beta_ech, &uves_beta_cd);
1236 
1237 /* exemple :
1238  uves_physmod_photo_beta(*plambda, &uves_beta_ech, &uves_beta_cd,
1239  puves_physmod_rech, puves_physmod_rcd, pblz);
1240 
1241 uves_msg("uves_physmod_lambda_order_beta(%f, %d, %f, %f, %f, %f)",
1242  *plambda, *pm, x, y, uves_beta_ech, uves_beta_cd);
1243 */
1244 }
1245 
1254 void
1255 uves_physmod_find_FSR(int m, double* lambdaC, double* fsrStart, double* fsrEnd)
1256 {
1257 
1258  double tmp_delta;
1259 
1260  *lambdaC = 2*sin(uves_ech_blaze[uves_ech_id-1]*uves_deg2rad)/
1261  m/uves_ech_groov[uves_ech_id-1];
1262 
1263  tmp_delta = *lambdaC/m;
1264 
1265  *fsrStart = *lambdaC - tmp_delta/2.;
1266  *fsrEnd = *lambdaC + tmp_delta/2.;
1267 
1268 }
1269 
1275 double uves_physmod_wave_bin(double l, int m)
1276 {
1277 
1278  double dl, x0,y_0,x1,y_1;
1279 
1280  dl = 20e-4; /* Wavelength increment in nm (nearly one pixel)*/
1281 
1282  uves_physmod_xy_model( l, m,&x0,&y_0);
1283  uves_physmod_xy_model((l+dl),m,&x1,&y_1);
1284 
1285  return( dl/(x1-x0) );
1286 }
1287 
1293 void uves_ccd_size(int* nx, int* ny)
1294 {
1295  /*
1296  uves_msg("imsize[uves_ech_id-1]=%d
1297  uves_physmod_row_size[uves_ech_id-1]=%d
1298  uves_bin[0]=%f uves_bin[1]=%f",
1299  imsize[uves_ech_id-1],
1300  uves_physmod_row_size[uves_ech_id-1],
1301  uves_bin[0],
1302  uves_bin[1]);
1303  */
1304  *nx = imsize[uves_ech_id-1] / uves_bin[0];
1305  *ny = uves_physmod_row_size[uves_ech_id-1] / uves_bin[1];
1306 }
1307 
1318 void uves_physmod_xy_regres(double x,double y,double* px,double* py)
1319 {
1320  double xdiff=0;
1321  double ydiff=0;
1322  int xnpix=0;
1323  int ynpix=0;
1324 
1325  goto simplified;
1326  /* We comment the following to remove a compilation warning
1327  Anyway the code would not be executed due to goto statement
1328  xdiff = xcoef[uves_cfg_indx-1][8]*DSQR(x*y) +
1329  xcoef[uves_cfg_indx-1][7]*x*DSQR(y) +
1330  xcoef[uves_cfg_indx-1][6]*DSQR(y) +
1331  xcoef[uves_cfg_indx-1][5]*DSQR(x)*y +
1332  xcoef[uves_cfg_indx-1][4]*x*y +
1333  xcoef[uves_cfg_indx-1][3]*y +
1334  xcoef[uves_cfg_indx-1][2]*DSQR(x) +
1335  xcoef[uves_cfg_indx-1][1]*x +
1336  xcoef[uves_cfg_indx-1][0];
1337 
1338  ydiff = ycoef[uves_cfg_indx-1][8]*DSQR(x*y) +
1339  ycoef[uves_cfg_indx-1][7]*x*DSQR(y) +
1340  ycoef[uves_cfg_indx-1][6]*DSQR(y) +
1341  ycoef[uves_cfg_indx-1][5]*DSQR(x)*y +
1342  ycoef[uves_cfg_indx-1][4]*x*y +
1343  ycoef[uves_cfg_indx-1][3]*y +
1344  ycoef[uves_cfg_indx-1][2]*DSQR(x) +
1345  ycoef[uves_cfg_indx-1][1]*x +
1346  ycoef[uves_cfg_indx-1][0];
1347  */
1348 
1349  /* New, simplified correction */
1350  simplified: {
1351  uves_ccd_size(&xnpix, &ynpix);
1352  /* uves_msg("xnpix=%d ynpix=%d",xnpix,ynpix); */
1353  xdiff = (-7.)*(x-(double)xnpix/2.)/((double)xnpix/2.);
1354  /* ydiff = (5.)*pow((x-(double)xnpix/2.)/((double)xnpix/2.),2.); */
1355  ydiff = (5.)*DSQR((x-(double)xnpix/2.)/((double)xnpix/2.));
1356  /* uves_msg("xdiff=%f ydiff=%f",xdiff,ydiff); */
1357  *px = x + xdiff;
1358  *py = y + ydiff;
1359  }
1360 }
1361 
#define uves_msg_error(...)
Print an error message.
Definition: uves_msg.h:64
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
Definition: uves_msg.h:119
#define uves_msg_debug(...)
Print a debug message.
Definition: uves_msg.h:97