00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029
00030 #include <cpl.h>
00031 #include <string.h>
00032 #include <math.h>
00033 #include <sinfo_msg.h>
00034 #include <sinfo_utils_wrappers.h>
00035 #include "sinfo_atmo_disp.h"
00036 #include "sinfo_resampling.h"
00037 #include "sinfo_image_ops.h"
00038
00039 struct _disp_data
00040 {
00041 double p1;
00042 double d1;
00043 double d2;
00044 double N0;
00045 double predelta;
00046 double parallactic_shiftX;
00047 double parallactic_shiftY;
00048 };
00049 typedef struct _disp_data disp_data;
00050 static double sinfo_disp_calc_N(const disp_data* pdata, double lambda);
00051 static void
00052 sinfo_disp_prepare_data(disp_data* pdata,
00053 double lambda0,
00054 double Tc,
00055 double rh,
00056 double airm,
00057 double p,
00058 double parallactic,
00059 double pixelscale );
00060
00061 static void
00062 sinfo_disp_calc(disp_data* pdata, double lambda, double *shiftx, double *shiftY);
00063 static void
00064 sinfo_atmo_rotate_point(double* x_value, double * y_value, double rot_angle);
00065
00066
00067 static double
00068 sinfo_disp_calc_N(const disp_data* pdata, double lambda)
00069 {
00070 double s = 1.0 /lambda;
00071 double s2 = s * s;
00072 double s3 = s2 * s;
00073 double s4 = s3 * s;
00074 double s5 = s4 * s;
00075 double s6 = s5 * s;
00076
00077 double a = 83939.7/(130 - s2);
00078 double b = 4547.3/(38.99 - s2);
00079 double c = 6487.31 + 58.058*s2 - 0.71150*s4 + 0.08851*s6;
00080 double N = 1e-8 * ( ((2371.34 + a + b) * pdata->d1) + ( c * pdata->d2));
00081 return N;
00082
00083 }
00084 static void
00085 sinfo_disp_prepare_data(disp_data* pdata,
00086 double lambda0,
00087 double Tc,
00088 double rh,
00089 double airm,
00090 double p,
00091 double parallactic,
00092 double pixelscale )
00093 {
00094 double ps,p2,p1,T,T2,T3;
00095 double zenith;
00096
00097
00098 T = Tc + 273.15;T2 = T * T; T3 = T2 * T;
00099 ps = -10474 + (116.43 * T) - (0.43284 *T2) + (0.00053840 * T3);
00100 p2 = (rh/100)*ps;
00101 p1 = p - p2;
00102 pdata->d1 = (p1/T)*(1+p1*( (57.90e-8) - ((9.3250e-4)/T) + (0.25844/T2)));
00103 pdata->d2 = (p2/T)*(1+p2*(1+3.7e-4*p2)*( (-2.37321e-3) + (2.23366/T) - (710.792/T2) + ((7.75141e-4)/T3) )) ;
00104 pdata->N0 = sinfo_disp_calc_N(pdata, lambda0);
00105 zenith = acos(1/airm);
00106 pdata->predelta = ((tan(zenith)) / (PI_NUMB/180)) * 3600;
00107 pdata->parallactic_shiftX = sin ( (parallactic)* (PI_NUMB/180) ) / pixelscale;
00108 pdata->parallactic_shiftY = cos ( (parallactic)* (PI_NUMB/180) ) / pixelscale;
00109 sinfo_msg_warning("atm disp N0[%f] d1[%f] d2[%f] pshiftX[%f] pshiftY[%f]",
00110 pdata->N0,pdata->d1, pdata->d2, pdata->parallactic_shiftX ,
00111 pdata->parallactic_shiftY);
00112 }
00113 static void
00114 sinfo_disp_calc(disp_data* pdata, double lambda, double *shiftx, double *shifty)
00115 {
00116 double n = sinfo_disp_calc_N(pdata, lambda);
00117 double delta = pdata->predelta * (n - pdata->N0);
00118 *shiftx = -delta * pdata->parallactic_shiftX;
00119 *shifty = delta * pdata->parallactic_shiftY ;
00120 }
00121
00122 cpl_error_code
00123 sinfo_atm_dispersion_cube(cpl_imagelist* pCube,
00124 int centpix,
00125 double centlambda,
00126 double Tc,
00127 double Rh,
00128 double airm,
00129 double p,
00130 double parallactic,
00131 double pixelscale,
00132 double pixelsz
00133 )
00134 {
00135 cpl_error_code err = CPL_ERROR_NONE;
00136 int cubesize = cpl_imagelist_get_size(pCube);
00137 double * kernel = sinfo_generate_interpolation_kernel("default");
00138 disp_data ddata;
00139 int i = 0;
00140
00141 sinfo_disp_prepare_data(&ddata, centlambda, Tc, Rh, airm, p, parallactic, pixelscale);
00142
00143 for (i = 0; i < cubesize; i++)
00144 {
00145 double shiftx = 0;
00146 double shifty = 0;
00147
00148 cpl_image* pnewImage = 0;
00149
00150 cpl_image* plane = cpl_imagelist_get(pCube, i);
00151
00152
00153 double lambda = centlambda - (centpix - i) * pixelsz;
00154 sinfo_disp_calc(&ddata, lambda, &shiftx, &shifty);
00155
00156
00157
00158
00159 sinfo_msg_warning(" shift image #%d, dx[%f] dy[%f]", i, shiftx, shifty);
00160 pnewImage = sinfo_new_shift_image(
00161 plane,
00162 shiftx,
00163 shifty,
00164 kernel);
00165 err = cpl_imagelist_set(pCube, pnewImage, i);
00166 if (err != CPL_ERROR_NONE)
00167 break;
00168 }
00169 cpl_free(kernel);
00170 return err;
00171
00172 }
00173
00174
00175
00176
00177
00178 cpl_polynomial*
00179 sinfo_atmo_load_polynom(const char* filename)
00180 {
00181 const char* COL_NAME_TEMPLATE = "col_%d";
00182 const char* COL_NAME_VALUE = "value";
00183 cpl_polynomial* poly = NULL;
00184 cpl_table* ptable = NULL;
00185
00186 ptable = cpl_table_load(filename, 1, 0);
00187 if (ptable)
00188 {
00189 int dim = 0;
00190 int nrows = 0;
00191 int i = 0;
00192 int* expo = NULL;
00193
00194 dim = cpl_table_get_ncol(ptable) - 1;
00195 poly = cpl_polynomial_new(dim );
00196 nrows = cpl_table_get_nrow(ptable);
00197 expo = cpl_malloc(dim * sizeof(expo[0]));
00198 memset(&expo[0], 0, dim * sizeof(expo[0]));
00199 for (i = 0; i < nrows; i++)
00200 {
00201 int j = 0;
00202 int inull = 0;
00203 double value = 0;
00204 for (j = 0; j < dim; j++)
00205 {
00206 char col_name[255];
00207 sprintf(col_name, COL_NAME_TEMPLATE, j);
00208 expo[j] = cpl_table_get_int(ptable, col_name, i, &inull);
00209 }
00210 value = cpl_table_get(ptable, COL_NAME_VALUE, i, &inull);
00211 cpl_polynomial_set_coeff(poly, expo, value);
00212 if (cpl_error_get_code() != CPL_ERROR_NONE)
00213 {
00214 if (poly)
00215 {
00216 sinfo_free_polynomial(&poly);
00217 }
00218 break;
00219 }
00220 }
00221 cpl_free(expo);
00222 }
00223 sinfo_free_table(&ptable);
00224 return poly;
00225 }
00226
00227 static void
00228 sinfo_atmo_rotate_point(double* x_value, double * y_value, double rot_angle)
00229 {
00230 double newx = *x_value * cos(rot_angle) - *y_value * sin(rot_angle);
00231 double newy = *x_value * sin(rot_angle) + *y_value * cos(rot_angle);
00232 *x_value = newx;
00233 *y_value = newy;
00234 }
00235
00236 cpl_imagelist*
00237 sinfo_atmo_apply_cube_polynomial_shift(
00238 cpl_polynomial* poly,
00239 cpl_imagelist* pCube,
00240 double lambda0,
00241 double airmass,
00242 double parallactic,
00243 double pixelsz,
00244 int centpix)
00245 {
00246 cpl_imagelist* retcube = NULL;
00247 cpl_error_code err = CPL_ERROR_NONE;
00248 cpl_vector* vparams = NULL;
00249 double * kernel = sinfo_generate_interpolation_kernel("default");
00250 int cubesize = 0;
00251 int i = 0;
00252
00253
00254 double l0_shift_x = 0;
00255 double l0_shift_y = 0;
00256
00257 vparams = cpl_vector_new(2);
00258 cpl_vector_set(vparams, 0, airmass);
00259 cpl_vector_set(vparams, 1, lambda0);
00260 err = cpl_error_get_code();
00261 if (err == CPL_ERROR_NONE)
00262 {
00263 l0_shift_y = cpl_polynomial_eval(poly, vparams);
00264 l0_shift_x = 0;
00265
00266 sinfo_atmo_rotate_point(&l0_shift_x, &l0_shift_y, parallactic);
00267 cubesize = cpl_imagelist_get_size(pCube);
00268 err = cpl_error_get_code();
00269 }
00270 if (err == CPL_ERROR_NONE)
00271 {
00272 retcube = cpl_imagelist_new();
00273 for (i = 0; i < cubesize; i++)
00274 {
00275
00276 double lambda = lambda0 - (centpix - i) * pixelsz;
00277 double shift_y = 0;
00278 double shift_x = 0;
00279
00280 cpl_vector_set(vparams, 1, lambda);
00281
00282 shift_y = cpl_polynomial_eval(poly, vparams);
00283 err = cpl_error_get_code();
00284 if (err == CPL_ERROR_NONE)
00285 {
00286 double res_shift_x = -(shift_x - l0_shift_x);
00287 double res_shift_y = -(shift_y - l0_shift_y);
00288 cpl_image* plane = NULL;
00289 cpl_image* pimresult = NULL;
00290
00291 sinfo_atmo_rotate_point(&res_shift_x, &res_shift_y, parallactic);
00292 plane = cpl_imagelist_get(pCube, i);
00293 pimresult = sinfo_new_shift_image(
00294 plane,
00295 res_shift_x,
00296 res_shift_y,
00297 kernel);
00298 if (err == CPL_ERROR_NONE)
00299 {
00300 err = cpl_imagelist_set(retcube, pimresult, i);
00301 }
00302 else
00303 {
00304 sinfo_msg_error("Error sinfo_new_shift_image, %s",
00305 cpl_error_get_where());
00306 }
00307 if (err != CPL_ERROR_NONE)
00308 break;
00309 }
00310 else
00311 {
00312 sinfo_msg_error("Error polynomial_eval, %s",
00313 cpl_error_get_where());
00314 }
00315 if (err != CPL_ERROR_NONE)
00316 break;
00317 }
00318 }
00319 if (err != CPL_ERROR_NONE)
00320 {
00321 sinfo_free_imagelist(&retcube);
00322 sinfo_msg_error("Error during shift planes in the cube, %s",
00323 cpl_error_get_where());
00324 }
00325 sinfoni_free_vector(&vparams);
00326 cpl_free(kernel);
00327 return retcube;
00328 }