24#if !defined(_POSIX_C_SOURCE) || (_POSIX_C_SOURCE - 0) < 200112L
25#define _POSIX_C_SOURCE 200112L
75static hdrl_parameter_typeobj hdrl_dar_parameter_type = {
77 (hdrl_alloc *)&cpl_malloc,
78 (hdrl_free *)&cpl_free,
80 sizeof(hdrl_dar_parameter),
93cpl_error_code hdrl_dar_parameter_verify(
const hdrl_parameter *param)
95 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
96 return CPL_ERROR_NULL_INPUT,
"NULL Input Parameters");
98 cpl_error_ensure(hdrl_parameter_check_type(param, &hdrl_dar_parameter_type), CPL_ERROR_ILLEGAL_INPUT,
99 return CPL_ERROR_ILLEGAL_INPUT,
"Expected DAR parameter");
101 const hdrl_dar_parameter *p_loc = (
const hdrl_dar_parameter *)param;
102 hdrl_value airmass = p_loc->airmass;
103 hdrl_value parang = p_loc->parang;
104 hdrl_value posang = p_loc->posang;
105 hdrl_value temp = p_loc->temp;
106 hdrl_value rhum = p_loc->rhum;
107 hdrl_value pres = p_loc->pres;
109 cpl_error_ensure(airmass.data >= 0. && airmass.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
110 return CPL_ERROR_ILLEGAL_INPUT,
"Airmass parameter not valid");
112 cpl_error_ensure(parang.data >= -180. && parang.data <= 180. && parang.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
113 return CPL_ERROR_ILLEGAL_INPUT,
"Paralactic angle not valid");
115 cpl_error_ensure(posang.data >= -360. && posang.data <= 360. && posang.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
116 return CPL_ERROR_ILLEGAL_INPUT,
"Position angle not valid");
118 cpl_error_ensure(temp.data >= -273.15 && temp.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
119 return CPL_ERROR_ILLEGAL_INPUT,
"Temperature not valid");
121 cpl_error_ensure(rhum.data >= 0. && rhum.data <=100 && rhum.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
122 return CPL_ERROR_ILLEGAL_INPUT,
"Humidity percent value not valid");
124 cpl_error_ensure( pres.data >= 0. && pres.error >= 0., CPL_ERROR_ILLEGAL_INPUT,
125 return CPL_ERROR_ILLEGAL_INPUT,
"Pressure not valid");
127 cpl_wcs* wcs = p_loc->wcs;
129 cpl_error_ensure(wcs != NULL, CPL_ERROR_NULL_INPUT,
130 return CPL_ERROR_NULL_INPUT,
"NULL WCS Input");
132 return CPL_ERROR_NONE;
160 hdrl_value posang, hdrl_value temp, hdrl_value rhum, hdrl_value pres, cpl_wcs *wcs)
162 hdrl_dar_parameter *p = (hdrl_dar_parameter *)hdrl_parameter_new(&hdrl_dar_parameter_type);
164 p->airmass = airmass;
174 if (hdrl_dar_parameter_verify((hdrl_parameter *)p) != CPL_ERROR_NONE) {
179 return (hdrl_parameter *)p;
219 const hdrl_value lambdaRef,
const cpl_vector *lambdaIn,
220 cpl_vector *xShift, cpl_vector *yShift, cpl_vector *xShiftErr, cpl_vector *yShiftErr)
223 cpl_error_ensure(params && lambdaIn && xShift && yShift != NULL, CPL_ERROR_NULL_INPUT,
224 return CPL_ERROR_NULL_INPUT,
"NULL Input Parameters");
227 if (hdrl_dar_parameter_verify(params) != CPL_ERROR_NONE) {
228 return CPL_ERROR_UNSPECIFIED;
231 cpl_error_ensure(lambdaRef.data >= 0, CPL_ERROR_ILLEGAL_INPUT,
232 return CPL_ERROR_ILLEGAL_INPUT,
"Reference wavelength must be >=0");
235 const hdrl_dar_parameter *p_loc = (
const hdrl_dar_parameter *)params;
236 hdrl_value airmass = p_loc->airmass;
237 hdrl_value parang = p_loc->parang;
238 hdrl_value posang = p_loc->posang;
239 hdrl_value temp = p_loc->temp;
240 hdrl_value rhum = p_loc->rhum;
241 hdrl_value pres = p_loc->pres;
242 cpl_wcs *wcs = p_loc->wcs;
245 cpl_ensure_code(airmass.data >= 1., cpl_error_get_code());
248 hdrl_value z = {acos(1. / airmass.data),
249 airmass.error * fabs( (-1. / pow(airmass.data, 2)) / sqrt(1. - pow(1. / airmass.data, 2)) )};
257 double temp_kel_data = temp.data + 273.15;
258 double temp_kel_err = (temp.error / fabs(temp.data)) * fabs(temp_kel_data);
259 hdrl_value temp_kel = {temp_kel_data, temp_kel_err};
266 double HDRL_PHYS_hPa_TO_mmHg = 0.75006158;
273 hdrl_value fp = {rhum.data *sp.data *HDRL_PHYS_hPa_TO_mmHg,
274 fabs(HDRL_PHYS_hPa_TO_mmHg * sp.data ) * rhum.error
275 + fabs(HDRL_PHYS_hPa_TO_mmHg * rhum.data) * sp.error};
278 pres.data *= HDRL_PHYS_hPa_TO_mmHg;
279 pres.error *= HDRL_PHYS_hPa_TO_mmHg;
282 hdrl_value lambdaRef_um = {lambdaRef.data * 1e-4,lambdaRef.error * 1e-4};
287 hdrl_value x_shift = {-sin( (parang.data + posang.data) * CPL_MATH_RAD_DEG),
288 parang.error * fabs(-CPL_MATH_RAD_DEG * cos(parang.data + posang.data))
289 + posang.error * fabs(-CPL_MATH_RAD_DEG * cos(parang.data + posang.data))};
291 hdrl_value y_shift = { cos( (parang.data + posang.data) * CPL_MATH_RAD_DEG),
292 parang.error * fabs(-CPL_MATH_RAD_DEG * sin(parang.data + posang.data))
293 + posang.error * fabs(-CPL_MATH_RAD_DEG * sin(parang.data + posang.data))};
296 double xscale, yscale;
297 hdrl_dar_wcs_get_scales(wcs, &xscale, &yscale);
299 x_shift.data /= xscale;
300 x_shift.error /= xscale;
302 y_shift.data /= yscale;
303 y_shift.error /= yscale;
307 hdrl_value dr0 = {tan(z.data) * CPL_MATH_DEG_RAD,
308 z.error * fabs( (1. + pow(tan(z.data), 2)) * CPL_MATH_DEG_RAD)};
316 cpl_size nmax = cpl_vector_get_size(lambdaIn);
318 HDRL_OMP(omp parallel
for \
320 shared( nmax, lambdaIn, \
321 xShift, yShift, xShiftErr, yShiftErr, \
322 lambdaRef_um, pres, temp, fp, dr0, nr0, \
324 for (i = 0; i < nmax; i++) {
326 double lambda = cpl_vector_get(lambdaIn, i);
327 if (isfinite(lambda) != 0) {
329 hdrl_value lambda_um = {lambda * 1e-4, lambdaRef_um.error};
332 hdrl_value dr = {dr0.data * (nr0.data - nr.data),
333 dr0.error * fabs(nr0.data - nr.data)
334 + nr0.error * fabs( dr0.data)
335 + nr.error * fabs(-dr0.data)};
337 hdrl_value shiftPlaneX = {x_shift.data * dr.data,
338 x_shift.error * fabs(dr.data)
339 + dr.error * fabs(x_shift.data)};
340 cpl_vector_set(xShift, i, shiftPlaneX.data );
341 cpl_vector_set(xShiftErr, i, shiftPlaneX.error);
343 hdrl_value shiftPlaneY = {y_shift.data * dr.data,
344 y_shift.error * fabs(dr.data)
345 + dr.error * fabs(y_shift.data)};
346 cpl_vector_set(yShift, i, shiftPlaneY.data );
347 cpl_vector_set(yShiftErr, i, shiftPlaneY.error);
351 cpl_vector_set(xShift, i, NAN);
352 cpl_vector_set(xShiftErr, i, NAN);
354 cpl_vector_set(yShift, i, NAN);
355 cpl_vector_set(yShiftErr, i, NAN);
359 return CPL_ERROR_NONE;
383 double errorT = hvT.error;
385 return (hdrl_value){-10474.0 + 116.43 * T - 0.43284 * T * T + 0.00053840 * pow(T, 3),
386 errorT * fabs(0.0016152 * T * T - 0.86568 * T + 116.43)};
427 hdrl_value hvL, hdrl_value hvP, hdrl_value hvT, hdrl_value hvF)
434 double errorL = hvL.error,
440 double lisq = 1. / (l * l);
441 double errorLisq = errorL * fabs(-2. / pow(l, 3) );
444 double nl1 = 64.328 + 29498.1 / (146. - lisq) + 255.4 / (41. - lisq);
445 double errorNl1 = errorLisq * fabs( 29498.1 / pow(146. - lisq, 2) + 255.4 / pow(41. - lisq, 2) );
448 double factor = 1.e-6;
449 double nl2A = nl1 * ( P / 720.883 * (1. + (1.049 -0.0157 * T) * 1e-6 * P) / (1. + 0.003661 * T) );
450 double errorNl2A1 = errorNl1 * fabs( factor *(P / 720.883 * (1. + (1.049 - 0.0157 * T) * 1e-6 * P) / (1. + 0.003661 * T) ) );
451 double errorNl2A2 = errorP * fabs( factor *(nl1 / (720.883 * (1. + 0.003661 * T)) *( (1. + (1.049 - 0.0157 * T) * 1e-6 * P) + P * (1.049 - 0.0157 * T) * 1e-6) ) );
452 double errorNl2A3 = errorT * fabs( factor *(nl1 * P / 720.883 * ( ( -0.0157 * 1e-6 * P * (1. + 0.003661 * T) - 0.003661 * (1. + (1.049 - 0.0157 * T) * 1e-6 * P) )/pow(1. + 0.003661 * T, 2) ) ) );
453 double errorNl2A = errorNl2A1 + errorNl2A2 + errorNl2A3;
456 double nl2B = (0.0624 - 0.000680 * lisq) / (1. + 0.003661 * T) * f;
457 double errorNl2B1 = errorLisq * fabs( -0.000680 * f / (1. + 0.003661 * T) );
458 double errorNl2B2 = errorT * fabs( -0.003661 * (0.0624 - 0.000680 * lisq) * f / pow(1. + 0.003661 * T, 2) );
459 double errorNl2B3 = errorF * fabs( (0.0624 - 0.000680 * lisq) / (1. + 0.003661 * T) );
460 double errorNl2B = errorNl2B1 + errorNl2B2 + errorNl2B3;
463 double nl2 = nl2A - nl2B;
464 double errorNl2 = errorNl2A + errorNl2B;
467 double nl3 = nl2 * 1e-6 + 1.;
468 double errorNl3 = fabs(errorNl2 * 1e-6);
470 return (hdrl_value){nl3,errorNl3};
495cpl_error_code hdrl_dar_wcs_get_scales(
500 cpl_ensure_code(aXScale && aYScale, CPL_ERROR_NULL_INPUT);
502 cpl_errorstate prestate = cpl_errorstate_get();
504 const cpl_matrix *cd = cpl_wcs_get_cd(wcs);
507 double cd11 = cpl_matrix_get(cd, 0, 0),
508 cd12 = cpl_matrix_get(cd, 0, 1),
509 cd21 = cpl_matrix_get(cd, 1, 0),
510 cd22 = cpl_matrix_get(cd, 1, 1);
512 double det = cd11 * cd22 - cd12 * cd21;
513 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
521 if (cd12 == 0. && cd21 == 0.) {
524 return CPL_ERROR_NONE;
528 *aXScale = sqrt(cd11 * cd11 + cd12 * cd12);
529 *aYScale = sqrt(cd22 * cd22 + cd21 * cd21);
531 return CPL_ERROR_NONE;
cpl_error_code hdrl_dar_compute(const hdrl_parameter *params, const hdrl_value lambdaRef, const cpl_vector *lambdaIn, cpl_vector *xShift, cpl_vector *yShift, cpl_vector *xShiftErr, cpl_vector *yShiftErr)
Correct the pixel coordinates of all pixels of a given pixel table for differential atmospheric refra...
hdrl_value hdrl_dar_filippenko_refractive_index(hdrl_value hvL, hdrl_value hvP, hdrl_value hvT, hdrl_value hvF)
Compute the refractive index for the given wavelength following Filippenko formulae....
hdrl_parameter * hdrl_dar_parameter_create(hdrl_value airmass, hdrl_value parang, hdrl_value posang, hdrl_value temp, hdrl_value rhum, hdrl_value pres, cpl_wcs *wcs)
Creates DAR parameters object with the values in the header.
hdrl_value hdrl_dar_owens_saturation_pressure(hdrl_value hvT)
Compute the saturation pressure using the Owens calibration.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter