180 #include <uves_physmod_utils.h>
182 #include <uves_utils.h>
183 #include <uves_utils_wrappers.h>
184 #include <uves_error.h>
185 #include <uves_msg.h>
196 beta2lamb(
double uves_beta_ech,
double uves_beta_cd,
double* plambda,
int m);
199 cameraFocal(
double lm);
202 uves_physmod_find_alpha_beta(
double lm,
210 uves_physmod_find_lambda(
double k,
double alpha,
double beta);
213 uves_physmod_find_order_lambda(
double k,
double alpha,
double beta);
223 uves_physmod_lambda_order_beta(
double* plambda,
227 double* puves_beta_ech,
228 double* puves_beta_cd);
231 uves_physmod_lambda_order_focus_model(
double* plambda,
237 static double uves_physmod_wave_bin(
double l,
int m);
239 static void uves_physmod_xy2beta(
double* puves_beta_ech,
240 double* puves_beta_cd,
245 static void uves_physmod_set_binning(
float binx,
float biny);
247 static double dsqrarg;
253 #define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)
255 #define PROID "physmod.c"
260 enum uves_arm_ident {UVES_ARM_UNDEF,UVES_ARM_BLUE,UVES_ARM_RED};
261 enum uves_arm_ident uves_arm_ident = UVES_ARM_UNDEF;
269 float uves_bin[2] = {1, 1};
270 static double uves_physmod_pix_size[2] = {15e-6, 15e-6};
271 static double delta[2] = {75.04, 76.0};
273 static double cdgroov[4] = {1000.0e-6, 660.0e-6, 600.0e-6, 312.5e-6};
274 static double uves_ech_groov[2] = {31.6e-6, 41.59e-6};
277 static double uves_ech_blaze[2] = {74.57, 75.9};
281 static double cdbeam[2] = {45.336, 46.0};
285 double uves_ccd_rot[2] = {0.3, -0.55};
288 static int imsize[2] = {4096, 3000};
289 static int uves_physmod_row_size[2] = {2048, 2048};
298 double uves_physmod_offsetx[6]={1391.0,1385.0,1852.0,1835.0,1852.0,1834.0};
299 double uves_physmod_offsety[6]={1030.0,1025.0,2098.0,2104.0,-52.0,-49.0};
305 static double flipx = 1.;
306 static double flipy = -1.;
307 double uves_airt = 25;
308 double uves_airp = 760;
309 double uves_airw = 3;
311 int uves_cfg_indx = 0;
312 int uves_x_disp_id = 0;
313 static int uves_ech_id = 0;
314 double uves_alpha0_cd, uves_beta0_cd;
315 char uves_arm_id =
'x';
317 static double uves_deg2rad = M_PI/180.;
366 uves_physmod_set_incidence(
double echred,
371 uves_ech_blaze[0] += echred;
372 uves_ech_blaze[1] += echblue;
376 uves_ech_blaze[0],uves_ech_blaze[1],cdbeam[0],cdbeam[1]);
386 uves_set_ccd_rot(
double* ccdrot,
387 double uves_ccd_rot_off_red,
388 double uves_ccd_rot_off_blue)
390 uves_ccd_rot[0] =ccdrot[0];
391 uves_ccd_rot[1] =ccdrot[1];
393 uves_ccd_rot[0] += uves_ccd_rot_off_red;
394 uves_ccd_rot[1] += uves_ccd_rot_off_blue;
396 uves_msg_debug(
"uves_ccd_rot[0,1]=%f,%f uves_ccd_rot_off: red,blue=%f,%f",
397 uves_ccd_rot[0],uves_ccd_rot[1],uves_ccd_rot_off_red,uves_ccd_rot_off_blue);
411 uves_physmod_set_offset(
double offset_x,
413 double uves_physmod_x_off,
416 uves_physmod_offsetx[uves_cfg_indx-1]=offset_x;
417 uves_physmod_offsety[uves_cfg_indx-1]=offset_y;
429 uves_physmod_offsetx[uves_cfg_indx-1] += uves_physmod_x_off;
430 uves_physmod_offsety[uves_cfg_indx-1] += yoff;
450 void uves_physmod_set_binning(
float binx,
float biny)
467 void uves_air_config(
double p,
double t,
double w)
473 uves_airt,uves_airp,uves_airw);
480 double uves_air_index(
double lambda)
483 double t1, t2, t3, airdx;
485 t1 = 1.0e-6/lambda/lambda;
487 t2 = (64.328+29498.1/(146.0-t1)+255.4/(41.0-t1))*uves_airp*
488 (1.0+1.0e-6*(1.049-0.0157*uves_airt)*uves_airp)/
489 (720.883*(1.0+0.003661*uves_airt));
491 t3 = t2 - uves_airw*(0.0624 - 0.000680*t1)/(1+0.003661*uves_airt);
493 airdx = 1.0+ t3*1.0e-6;
515 uves_physmod_find_alpha_beta(
double lm,
526 lm /= uves_air_index(lm);
528 *alpha = 0.5* ( 2*asin( m*k*lm/2/cos(theta*uves_deg2rad/2) ) +
529 theta*uves_deg2rad );
530 *beta = 0.5* ( 2*asin( m*k*lm/2/cos(theta*uves_deg2rad/2) ) -
531 theta*uves_deg2rad );
532 *alpha /= uves_deg2rad;
533 *beta /= uves_deg2rad;
552 uves_config(
char uves_arm,
562 uves_x_disp_id = disp;
563 uves_arm_id = uves_arm;
575 uves_msg(
"Cfg: Arm %c CCD %c Xdisp %d Wave %f",
576 uves_arm,uves_ccd_id,disp,waveCent);
578 if (uves_arm ==
'b' && disp == 1) cfg = 1;
579 if (uves_arm ==
'b' && disp == 2) cfg = 2;
581 if (uves_arm ==
'r' && disp == 3) {
583 if (uves_ccd_id ==
'e') cfg = 3;
584 if (uves_ccd_id ==
'm') cfg = 5;
586 if (uves_arm ==
'r' && disp == 4) {
588 if (uves_ccd_id ==
'e') cfg = 4;
589 if (uves_ccd_id ==
'm') cfg = 6;
593 cpl_msg_error(__func__,
"Wrong configuration!");
599 (void) uves_physmod_set_binning(binx, biny);
600 (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
601 cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
604 uves_msg(
"alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
605 uves_alpha0_cd, uves_beta0_cd,cfg, uves_ccd_id);
620 uves_config_cpl_new(
int uves_arm,
629 uves_x_disp_id = disp;
641 uves_msg(
"New Cfg: Arm [b/r] %d CCD eev/mit %d Xdisp %d Wave %f",
642 uves_arm,upper,disp,waveCent);
644 if (uves_arm == ARM_BLUE && disp == 1) cfg = 1;
645 if (uves_arm == ARM_BLUE && disp == 2) cfg = 2;
647 if (uves_arm == ARM_RED && disp == 3) {
649 if (upper == 0) cfg = 3;
650 if (upper == 1) cfg = 5;
652 if (uves_arm == ARM_RED && disp == 4) {
654 if (upper == 0) cfg = 4;
655 if (upper == 1) cfg = 6;
659 cpl_msg_error(__func__,
"Wrong configuration!");
665 (void) uves_physmod_set_binning(binx, biny);
666 (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
667 cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
670 uves_msg(
"alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
671 uves_alpha0_cd, uves_beta0_cd,cfg, upper == 0 ?
'e' :
'm');
696 uves_config_cpl(
int blue,
707 uves_x_disp_id = disp;
719 uves_msg(
"Cfg cpl: Arm [b/r] %d CCD eev/mit %d Xdisp %d Wave %f",
720 blue,upper,disp,waveCent);
722 if (blue == 1 && disp == 1) cfg = 1;
723 if (blue == 1 && disp == 2) cfg = 2;
725 if (blue == 0 && disp == 3) {
727 if (upper == 0) cfg = 3;
728 if (upper == 1) cfg = 5;
730 if (blue == 0 && disp == 4) {
732 if (upper == 0) cfg = 4;
733 if (upper == 1) cfg = 6;
743 (void) uves_physmod_set_binning(binx, biny);
744 (void) uves_physmod_find_alpha_beta(waveCent, 1, cdgroov[uves_x_disp_id-1],
745 cdbeam[uves_ech_id-1], &uves_alpha0_cd, &uves_beta0_cd);
748 uves_msg(
"alpha, beta for Xdisp: %f %f\nin config %d and CCD-ID %c",
749 uves_alpha0_cd, uves_beta0_cd,cfg, upper == 0 ?
'e':
'u');
774 double cameraFocal(
double lm)
781 lm /= uves_air_index(lm);
783 if (uves_arm_id ==
'b' ) {
785 nfk=5.3961886e-7*lm*lm*lm-0.00079597882*lm*lm+0.41122805*lm+287.89644;
788 if (uves_arm_id ==
'r' ) {
790 nfk=6.0172051e-13*lm*lm*lm*lm*lm-2.5623231e-9*lm*lm*lm*lm+
791 4.3585543e-6*lm*lm*lm -0.0037286381*lm*lm+
792 1.6289971*lm + 210.06767;
808 int uves_physmod_find_order(
double lm)
811 double k, alpha, beta;
813 lm /= uves_air_index(lm);
815 k = uves_ech_groov[uves_ech_id-1];
816 alpha = uves_ech_blaze[uves_ech_id-1];
817 beta = uves_ech_blaze[uves_ech_id-1];
818 order = (int)((sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad))/k/lm + 0.5);
833 double uves_physmod_find_order_lambda(
double k,
double alpha,
double beta)
836 ML = ( ( sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad) )/k);
837 ML *= uves_air_index(ML);
848 double uves_physmod_find_lambda(
double k,
double alpha,
double beta)
851 L = (sin(alpha*uves_deg2rad) + sin(beta*uves_deg2rad) )/k ;
852 L *= uves_air_index(L);
863 double uves_physmod_find_beta(
int m,
double k,
double l,
double alpha)
867 l /= uves_air_index(l);
876 if ( (m*k*l - sin(alpha*uves_deg2rad)) <=1.0 )
878 return( (asin(m*k*l - sin(alpha*uves_deg2rad)))/uves_deg2rad );
882 return( (asin(0.999))/uves_deg2rad );
895 uves_physmod_lambda_order2beta(
double lambda,
897 double* puves_beta_ech,
898 double* puves_beta_cd,
905 *pfc = cameraFocal(lambda);
909 *puves_beta_ech = uves_physmod_find_beta(m, uves_ech_groov[uves_ech_id-1],
910 lambda, uves_ech_blaze[uves_ech_id-1]);
912 *puves_beta_cd = uves_physmod_find_beta(1, cdgroov[uves_x_disp_id-1],
913 lambda, uves_alpha0_cd);
928 uves_beta2xy(
double uves_beta_cd,
929 double uves_beta_ech,
934 double xd, yd, xr, yr, angle;
936 xd = fc*tan( (uves_beta_ech - uves_ech_blaze[uves_ech_id-1])*
938 uves_physmod_pix_size[0]/uves_bin[0];
939 yd = fc*tan( (uves_alpha0_cd - uves_beta_cd -
940 cdbeam[uves_ech_id-1])*uves_deg2rad )/
941 uves_physmod_pix_size[1]/uves_bin[1];
950 angle = uves_ccd_rot[uves_ech_id-1]*uves_deg2rad;
951 xr = xd*cos(angle) + yd*sin(angle);
952 yr = -xd*sin(angle) + yd*cos(angle);
956 *px = uves_physmod_offsetx[uves_cfg_indx-1] / uves_bin[0] + xr;
957 *py = uves_physmod_offsety[uves_cfg_indx-1] / uves_bin[1] + yr;
973 uves_physmod_photo_beta(
double lambda,
974 double uves_beta_ech,
976 double* puves_physmod_rech,
977 double* puves_physmod_rcd,
987 *puves_physmod_rech = cos(uves_ech_blaze[uves_ech_id-1]*uves_deg2rad)/
988 cos(uves_beta_ech*uves_deg2rad);
990 *puves_physmod_rcd = cos(uves_alpha0_cd*uves_deg2rad)/
991 cos(uves_beta_cd*uves_deg2rad);
997 gam = M_PI / uves_ech_groov[uves_ech_id-1] *
998 cos(delta[uves_ech_id-1]*uves_deg2rad) *
999 (sin((uves_beta_ech-delta[uves_ech_id-1])*uves_deg2rad)-
1000 sin((uves_ech_blaze[uves_ech_id-1]-delta[uves_ech_id-1])*
1002 / lambda/ uves_air_index(lambda);
1003 *pblz = DSQR(sin(gam)/gam);
1032 void uves_physmod_pixscl(
1035 double uves_physmod_rech,
1036 double uves_physmod_rcd,
1050 double binsize, pixscale, pixscalCD, linewidpx, linelenpx, linewidth, resol;
1051 static double scale;
1053 if (!(scale)) scale = (206265.0*15.0*0.015*200*1e-3*binx)/120000;
1074 binsize = uves_physmod_wave_bin(wave, order) * 1e4;
1075 pixscale = scale/(fc*uves_physmod_rech);
1076 pixscalCD = pixscale *(biny/binx) *uves_physmod_rech/uves_physmod_rcd;
1077 linewidpx = slitwidth / pixscale;
1078 linelenpx = slitlength /pixscalCD;
1079 linewidth = binsize * linewidpx * 1e-3;
1080 resol = wave * 10.0 / linewidth;
1090 *pbinsize = binsize;
1091 *ppixscale = pixscale;
1092 *ppixscalCD = pixscalCD;
1093 *plinewidpx = linewidpx;
1094 *plinelenpx = linelenpx;
1095 *plinewidth = linewidth;
1108 uves_physmod_xy_model(
double lambda,
int m,
double* px,
double* py)
1110 double fc, uves_beta_ech, uves_beta_cd;
1112 uves_physmod_lambda_order2beta(lambda, m, &uves_beta_ech, &uves_beta_cd, &fc);
1113 uves_msg_debug(
"lambda=%f m=%d uves_beta_ech=%f,uves_beta_cd=%f,fc=%f",
1114 lambda,m,uves_beta_ech,uves_beta_cd,fc);
1116 uves_beta2xy(uves_beta_cd, uves_beta_ech, fc, px, py);
1135 uves_physmod_xy2beta(
double* puves_beta_ech,
1136 double* puves_beta_cd,
1141 double xr, yr, xd, yd, angle;
1143 angle = uves_ccd_rot[uves_ech_id-1]*uves_deg2rad;
1145 xr = (x - uves_physmod_offsetx[uves_cfg_indx-1]/uves_bin[0]);
1146 yr = (y - uves_physmod_offsety[uves_cfg_indx-1]/uves_bin[1]);
1148 xd = xr*cos(angle) - yr*sin(angle);
1149 yd = xr*sin(angle) + yr*cos(angle);
1154 *puves_beta_ech = atan(xd*uves_physmod_pix_size[0]*uves_bin[0]/fc)/
1155 uves_deg2rad + uves_ech_blaze[uves_ech_id-1];
1156 *puves_beta_cd = uves_alpha0_cd - cdbeam[uves_ech_id-1] -
1157 atan(yd*uves_physmod_pix_size[1]*uves_bin[1]/fc)/
1171 beta2lamb(
double uves_beta_ech,
1172 double uves_beta_cd,
1176 uves_beta_cd=uves_beta_cd;
1177 *plambda = uves_physmod_find_lambda(m*uves_ech_groov[uves_ech_id-1],
1178 uves_ech_blaze[uves_ech_id-1], uves_beta_ech);
1195 uves_physmod_lambda_order_focus_model(
double* plambda,
1202 double uves_beta_ech, uves_beta_cd;
1204 uves_physmod_xy2beta(&uves_beta_ech, &uves_beta_cd, fc, x, y);
1206 *plambda = uves_physmod_find_order_lambda(cdgroov[uves_x_disp_id-1],
1207 uves_alpha0_cd, uves_beta_cd);
1208 *pdm = uves_physmod_find_order_lambda(uves_ech_groov[uves_ech_id-1],
1209 uves_ech_blaze[uves_ech_id-1], uves_beta_ech)/(*plambda);
1255 uves_physmod_lambda_order_beta(
double* plambda,
1259 double* puves_beta_ech,
1260 double* puves_beta_cd)
1263 double fcguess=0., wave=0., mdbl=0., xe=0., ye=0., xd=0., yd=0.;
1266 if (uves_arm_id ==
'b') fcguess = 0.360;
1267 if (uves_arm_id ==
'r') fcguess = 0.500;
1269 uves_physmod_lambda_order_focus_model(&wave,&mdbl,fcguess,x,y);
1278 fcguess = cameraFocal(wave);
1284 if (*pm <= 0) *pm = (int)(mdbl+0.5);
1286 uves_physmod_xy2beta(puves_beta_ech, puves_beta_cd, fcguess, x, y);
1287 beta2lamb(*puves_beta_ech, *puves_beta_cd, &wave, *pm);
1295 uves_physmod_xy_model(wave,(
int)(mdbl+0.5), &xe, &ye);
1308 }
while (!((xd < 1.) && (yd < 1.)) && (i <= 4));
1335 uves_physmod_lambda_order_model(
double* plambda,
int* pm,
double x,
double y)
1338 double uves_beta_ech, uves_beta_cd;
1340 uves_physmod_lambda_order_beta(plambda, pm, x, y,
1341 &uves_beta_ech, &uves_beta_cd);
1361 uves_physmod_find_FSR(
int m,
double* lambdaC,
double* fsrStart,
double* fsrEnd)
1366 *lambdaC = 2*sin(uves_ech_blaze[uves_ech_id-1]*uves_deg2rad)/
1367 m/uves_ech_groov[uves_ech_id-1];
1369 tmp_delta = *lambdaC/m;
1371 *fsrStart = *lambdaC - tmp_delta/2.;
1372 *fsrEnd = *lambdaC + tmp_delta/2.;
1381 double uves_physmod_wave_bin(
double l,
int m)
1384 double dl, x0,y_0,x1,y_1;
1388 uves_physmod_xy_model( l, m,&x0,&y_0);
1389 uves_physmod_xy_model((l+dl),m,&x1,&y_1);
1391 return( dl/(x1-x0) );
1399 void uves_ccd_size(
int* nx,
int* ny)
1410 *nx = imsize[uves_ech_id-1] / uves_bin[0];
1411 *ny = uves_physmod_row_size[uves_ech_id-1] / uves_bin[1];
1424 void uves_physmod_xy_regres(
double x,
double y,
double* px,
double* py)
1457 uves_ccd_size(&xnpix, &ynpix);
1459 xdiff = (-7.)*(x-(double)xnpix/2.)/((double)xnpix/2.);
1461 ydiff = (5.)*DSQR((x-(
double)xnpix/2.)/((
double)xnpix/2.));