41 #include "irplib_utils.h"
43 #include "isaac_physicalmodel.h"
44 #include "isaac_pfits.h"
50 #define ISAAC_LR_DIR 7.0
51 #define ISAAC_MR_DIR 31.5
53 #define ISAAC_LR_GRATING 40.0
54 #define ISAAC_MR_GRATING 210.0
56 #define ISAAC_FOCAL_LENGTH_MM 175.0
58 #define ISAAC_PIXEL_SIZE_S 18.5
59 #define ISAAC_PIXEL_SIZE_M 27.0
61 #define ISAAC_BEAM_DIFF 2.72
62 #define ISAAC_PUPIL_SIZE_MM 100.0
64 #define ISAAC_FLGTH_S1 1.75
65 #define ISAAC_FLGTH_S2 3.25
66 #define ISAAC_FLGTH_L1 1.56
67 #define ISAAC_FLGTH_L2 4.77
68 #define ISAAC_FLGTH_L3 9.88
70 #define ANGLE_IN_DEFAULT 0.00
71 #define ANGLE_OUT_DEFAULT 0.00
102 double * disprel = NULL;
103 cpl_propertylist * plist = cpl_propertylist_load(filename, 0);
104 const char * objective;
105 const char * resolution;
110 cpl_matrix * x_val = NULL;
111 cpl_vector * y_val = NULL;
112 cpl_polynomial * poly_fit = NULL;
113 double * coefs = NULL;
119 skip_if_lt (poly_deg, 0,
"polynomial degree");
123 error_if(cpl_error_get_code(), cpl_error_get_code(),
124 "cannot get central wlen from [%s]", filename);
130 error_if(cpl_error_get_code(), cpl_error_get_code(),
131 "cannot get objective from [%s]", filename);
135 error_if(cpl_error_get_code(), cpl_error_get_code(),
136 "cannot get resolution from [%s]", filename);
139 cpl_msg_info(cpl_func,
"configuration for ISAAC physical model: ");
140 cpl_msg_info(cpl_func,
"resolution: %s", resolution);
141 cpl_msg_info(cpl_func,
"lambda_c [Angstrom]: %g", wl_c);
142 cpl_msg_info(cpl_func,
"objective : %s", objective);
146 error_if(cpl_error_get_code(), cpl_error_get_code(),
147 "cannot get NAXIS1 from [%s]", filename);
149 skip_if_lt(npix, 2,
"NAXIS1");
152 if ( wl_c >= 8900 && wl_c < 9900 ) {
154 }
else if ( wl_c >= 9900 && wl_c < 11000 ) {
156 }
else if ( wl_c >= 11000 && wl_c < 14000 ) {
158 }
else if ( wl_c >= 14000 && wl_c < 18500 ) {
160 }
else if ( wl_c >= 18500 && wl_c < 25000 ) {
166 disprel = (
double*)cpl_malloc((poly_deg+1) *
sizeof(double));
168 if (poly_deg == 3 && resolution[0] ==
'M' && 8900 <= wl_c && wl_c < 25000) {
172 const double a = -1.218717e-7;
173 const double b = 0.003395204;
174 const double c = 1337.455;
175 const double d = -1.617833e-4;
176 const double e = 3.132269;
177 const double f = -2.496095;
179 const double c1 = wl_c;
180 const double c2 = (( a * (order*c1) + b) * (order*c1) + c) / order;
181 const double c3 = ( d * (order*c1) + e ) / order;
182 const double c4 = f / order;
183 double k0 = -(npix+1) / (
double)(npix-1);
184 double k1 = 2 / (double)(npix-1);
186 double * p = disprel;
193 cpl_msg_debug(cpl_func,
194 "Reduced polynomial(%d:%d): %g + %g * z + %g * z^2 "
195 "+ %g * z^3\n", order, npix, p[0], p[1], p[2], p[3]);
198 p[0] += k0 * ( p[1] + k0 * ( p[2] + k0 * p[3]));
200 p[1] += k0 * ( 2*p[2] + k0 * 3*p[3]);
210 const cpl_boolean sampsym = CPL_TRUE;
215 error_if (coefs == NULL, cpl_error_get_code(),
216 "cannot compute the physical model");
218 y_val = cpl_vector_wrap(npix, coefs);
220 x_val = cpl_matrix_new(1, npix);
221 px_val = cpl_matrix_get_data(x_val);
223 for (i = 0; i < npix; i++) {
224 px_val[i] = (double)(i+1);
228 poly_fit = cpl_polynomial_new(1);
229 skip_if(cpl_polynomial_fit(poly_fit, x_val, &sampsym, y_val, NULL,
230 CPL_FALSE, NULL, &poly_deg));
232 for (i = 0; i <= poly_deg; i++) {
233 disprel[i] = cpl_polynomial_get_coeff(poly_fit, &i);
239 if (cpl_error_get_code()) {
244 cpl_matrix_delete(x_val);
245 cpl_polynomial_delete(poly_fit);
246 (void)cpl_vector_unwrap(y_val);
249 cpl_propertylist_delete(plist);
278 const char * objective,
279 const char * resolution,
282 double beam_diff, focal_length, pixel_size, pupil;
284 double isaacLRGrating, isaacMRGrating;
288 double angle_in, angle_out;
294 isaacLRGrating = ISAAC_LR_GRATING;
295 isaacMRGrating = ISAAC_MR_GRATING;
296 focal_length = ISAAC_FOCAL_LENGTH_MM;
297 pixel_size = ISAAC_PIXEL_SIZE_S;
298 beam_diff = ISAAC_BEAM_DIFF;
299 pupil = ISAAC_PUPIL_SIZE_MM;
300 loc_pi = 3.1415926535897932384626433;
303 if (objective[0] ==
'S') {
304 if (objective[1] ==
'1') focal_length = pupil*ISAAC_FLGTH_S1;
305 if (objective[1] ==
'2') focal_length = pupil*ISAAC_FLGTH_S2;
306 pixel_size = ISAAC_PIXEL_SIZE_S;
307 }
else if (objective[0] ==
'L') {
308 if (objective[1] ==
'1') focal_length = pupil*ISAAC_FLGTH_L1;
309 if (objective[1] ==
'2') focal_length = pupil*ISAAC_FLGTH_L2;
310 if (objective[1] ==
'3') focal_length = pupil*ISAAC_FLGTH_L3;
311 pixel_size = ISAAC_PIXEL_SIZE_M;
313 cpl_msg_error(cpl_func,
"unsupported objective");
318 focal_length *= 1e-3;
321 cpl_msg_info(cpl_func,
"configuration for ISAAC physical model: ");
322 if (resolution[0]==
'L') cpl_msg_info(cpl_func,
"low resolution");
323 if (resolution[0]==
'M') cpl_msg_info(cpl_func,
"medium resolution");
324 cpl_msg_info(cpl_func,
"lambda_c : %g", lambda_c);
325 cpl_msg_info(cpl_func,
"objective : %s", objective);
326 cpl_msg_info(cpl_func,
"focal length : %g", focal_length);
329 if (resolution[0] ==
'L') { gr = isaacLRGrating;}
330 else if (resolution[0] ==
'M') { gr = isaacMRGrating;}
332 cpl_msg_error(cpl_func,
"wrong grating! %c", resolution[0]);
339 beam_diff *= loc_pi / 180.0;
344 if ( lambda_c >= 890 && lambda_c < 8000) {
345 if ( lambda_c >= 890 && lambda_c < 990 ) {
347 }
else if ( lambda_c >= 990 && lambda_c < 1100 ) {
349 }
else if ( lambda_c >= 1100 && lambda_c < 1400 ) {
351 }
else if ( lambda_c >= 1400 && lambda_c < 1850 ) {
353 }
else if ( lambda_c >= 1850 && lambda_c < 2500 ) {
355 }
else if ( lambda_c >= 2500 && lambda_c < 5500 ) {
361 order = (int)(0.5 + (sin(ANGLE_IN_DEFAULT) + sin(ANGLE_OUT_DEFAULT)) /
364 cpl_msg_error(cpl_func,
"wrong order! %d", order);
368 cpl_msg_info(cpl_func,
"order : %d", order);
373 det = 2 * sin(beam_diff);
374 a = order * gr * lambda_c * sin(beam_diff);
375 b = sqrt(order * gr * lambda_c * order * gr * lambda_c *
376 (sin(beam_diff) * sin(beam_diff) + 2 * cos(beam_diff) - 2)
377 + 2 * sin(beam_diff) * sin(beam_diff) * (1-cos(beam_diff)));
378 angle_in = asin((a-b)/det);
379 angle_out = angle_in + beam_diff;
381 disp = cpl_malloc(nbpix *
sizeof(
double));
383 for (i=0; i<nbpix; i++) {
385 x = (double)(i-(nbpix/2.)) * pixel_size * 1e-6;
386 disp[i]=(sin(angle_in)+sin(angle_out+atan(x/focal_length)))/(order*gr);
const char * isaac_pfits_get_objective(const cpl_propertylist *plist)
find out the objective
double isaac_pfits_get_wlen(const cpl_propertylist *plist)
find out the central wavelength
int isaac_pfits_get_naxis1(const cpl_propertylist *plist)
find out the NAXIS1 keyword
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
double * isaac_physical_model(double lambda_c, const char *objective, const char *resolution, int nbpix)
ISAAC physical model.
double * isaac_get_disprel_estimate(const char *filename, cpl_size poly_deg)
Estimate the instrument wavelength range.