32 #include "muse_phys.h" 34 #include "muse_pfits.h" 56 return -10474.0 + 116.43*temp - 0.43284*temp*temp + 0.00053840*pow(temp,3);
71 double *d1,
double *d2)
78 *d1 = p1/temp * (1. + p1*(57.90e-8 - 9.3250e-4/temp + 0.25844/temp/temp));
79 *d2 = p2/temp * (1. + p2*(1. + 3.7e-4*p2)
80 * (-2.37321e-3 + 2.23366/temp - 710.792/temp/temp
81 + 7.75141e4/pow(temp,3)));
97 double lisq = 1./(l*l);
98 return 1. + ((2371.34 + 683939.7/(130. - lisq) + 4547.3/(38.9 - lisq)) * d1
99 + (6487.31 + 58.058 * lisq - 0.71150 * lisq*lisq
100 + 0.08851 * lisq*lisq*lisq) * d2) * 1.0e-8;
118 const double A = 8342.54, B = 2406147,
119 C = 15998, D = 96095.43,
120 E = 0.601, F = 0.00972, G = 0.003661;
124 n_5 = 1 + 1e-8 * (A + B / (130 - S) + C / (38.9 - S)),
125 X = (1 + 1e-8 * (E - F * t) * p) / (1 + G * t),
126 n_tp = 1 + p * (n_5 - 1) * X / D,
127 n = n_tp - 10e-10 * (292.75 / (t + 273.15)) * (3.7345 - 0.0401 * S) * pv;
151 const double w0 = 295.235, w1 = 2.6422, w2 = -0.03238, w3 = 0.004028,
152 k0 = 238.0185, k1 = 5792105, k2 = 57.362, k3 = 167917,
153 a0 = 1.58123e-6, a1 = -2.9331e-8, a2 = 1.1043e-10,
154 b0 = 5.707e-6, b1 = -2.051e-8,
155 c0 = 1.9898e-4, c1 = -2.376e-6,
156 d = 1.83e-11, e = -0.765e-8,
157 p_R1 = 101325, T_R1 = 288.15,
160 R = 8.314472, M_v = 0.018015;
161 double t = T - 273.15,
165 r_as = 1e-8 * ((k1 / (k0 - S)) + (k3 / (k2 - S))),
166 r_vs = 1.022e-8 * (w0 + w1 * S + w2 * S*S + w3 * S*S*S),
168 M_a = 0.0289635 + 1.2011e-8 * (xCO2 - 400),
169 r_axs = r_as * (1 + 5.34e-7 * (xCO2 - 450)),
171 Z_m = 1 - (p / T) * (a0 + a1 * t + a2 * t*t + (b0 + b1 * t) * xv
172 + (c0 + c1 * t) * xv*xv)
173 + (p/T)*(p/T) * (d + e * xv*xv),
174 rho_axs = p_R1 * M_a / (Z_a * R * T_R1),
175 rho_v = xv * p * M_v / (Z_m * R * T),
176 rho_a = (1 - xv) * p * M_a / (Z_m * R * T),
177 n = 1 + (rho_a / rho_axs) * r_axs + (rho_v / rho_vs) * r_vs;
195 double lisq = 1./(l*l);
197 double nl = 64.328 + 29498.1 / (146 - lisq) + 255.4 / (41 - lisq);
199 nl *= P / 720.883 * (1 + (1.049 - 0.0157 * T) * 1e-6 * P) / (1 + 0.003661 * T);
201 nl -= (0.0624 - 0.000680 * lisq) / (1 + 0.003661 * T) * f;
263 cpl_ensure_code(aPixtable && aPixtable->
header && aPixtable->
table,
264 CPL_ERROR_NULL_INPUT);
266 == CPL_ERROR_NONE, CPL_ERROR_DATA_NOT_FOUND);
267 cpl_ensure_code(aFlags != 0, CPL_ERROR_UNSUPPORTED_MODE);
272 const char *spectype = cpl_propertylist_get_string(aPixtable->
header,
274 if (spectype && !strncmp(spectype,
"WAVE", 4)) {
275 cpl_msg_warning(__func__,
"Pixel table has spectral type \"%s\", not in " 276 "air wavelengths!", spectype);
277 return cpl_error_set(__func__, CPL_ERROR_TYPE_MISMATCH);
279 if (spectype && strncmp(spectype,
"AWAV", 4)) {
280 cpl_msg_warning(__func__,
"Pixel table has unknown spectral type \"%s\", " 281 "not in air wavelengths, not doing conversion to vacuum!",
283 return cpl_error_set(__func__, CPL_ERROR_TYPE_MISMATCH);
292 cpl_boolean realair = (aFlags & 0x3) >> 1;
295 cpl_errorstate prestate = cpl_errorstate_get();
297 if (!cpl_errorstate_is_equal(prestate)) {
298 cpl_msg_warning(__func__,
"Pixel table header does not contain temperature" 299 ", no conversion to vacuum: %s", cpl_error_get_message());
300 return CPL_ERROR_DATA_NOT_FOUND;
304 prestate = cpl_errorstate_get();
306 if (!cpl_errorstate_is_equal(prestate)) {
307 cpl_msg_warning(__func__,
"Pixel table header does not contain relative " 308 "humidity, no conversion to vacuum: %s",
309 cpl_error_get_message());
310 return CPL_ERROR_DATA_NOT_FOUND;
314 prestate = cpl_errorstate_get();
317 if (!cpl_errorstate_is_equal(prestate)) {
318 cpl_msg_warning(__func__,
"Pixel table header does not contain pressure " 319 "values, no conversion to vacuum: %s",
320 cpl_error_get_message());
321 return CPL_ERROR_DATA_NOT_FOUND;
326 unsigned int method = aFlags & 0xC;
338 cpl_msg_info(__func__,
"Air to vacuum conversion for T=%.2f K, RH=%.2f %%, " 339 "pres=%.1f mbar (%s, Owens)", temp, rhum*100., pres,
340 realair ?
"measured parameters" :
"standard air");
347 const double T = temp,
348 K1 = 1.16705214528E+03,
349 K2 = -7.24213167032E+05,
350 K3 = -1.70738469401E+01,
351 K4 = 1.20208247025E+04,
352 K5 = -3.23255503223E+06,
353 K6 = 1.49151086135E+01,
354 K7 = -4.82326573616E+03,
355 K8 = 4.05113405421E+05,
356 K9 = -2.38555575678E-01,
357 K10 = 6.50175348448E+02,
358 Omega = T + K9 / (T - K10),
359 A = Omega*Omega + K1 * Omega + K2,
360 B = K3 * Omega*Omega + K4 * Omega + K5,
361 C = K6 * Omega*Omega + K7 * Omega + K8,
362 X = -B + sqrt(B*B - 4 * A * C);
363 double psv_w = 1e6 * pow(2 * C / X, 4);
366 const double A1 = -13.928169,
369 Y = A1 * (1 - pow(Theta, -1.5)) + A2 * (1 - pow(Theta, -1.25));
370 double psv_i = 611.657 * exp(Y);
380 const double alpha = 1.00062,
383 double f = alpha + beta * p + gamma * t*t;
386 xv = rhum * f * psv_w / p;
388 xv = rhum * f * psv_i / p;
390 cpl_msg_info(__func__,
"Air to vacuum conversion for T=%.2f degC, RH=%.2f " 391 "%%, p=%.1f Pa (%s, %s)", t, rhum*100., p,
392 realair ?
"measured parameters" :
"standard air",
398 fp = rhum * ps * MUSE_PHYS_hPa_TO_mmHg;
400 pres *= MUSE_PHYS_hPa_TO_mmHg;
401 cpl_msg_info(__func__,
"Air to vacuum conversion for T=%.2f degC, fp=%.3f " 402 "mmHg, P=%.1f mmHg (%s, Filippenko)", temp, fp, pres,
403 realair ?
"measured parameters" :
"standard air");
408 #pragma omp parallel for default(none) \ 409 shared(d1, d2, fp, lbda, method, nmax, p, pres, pv, t, temp, xv) 410 for (i = 0; i < nmax; i++) {
412 lambda = lbda[i] * 1e-4;
435 MUSE_HDR_PT_SPEC_TYPE_COMMENT);
437 return CPL_ERROR_NONE;
double muse_phys_nrindex_edlen(double l, double t, double p, double pv)
Compute the refractive index for the given wavelength following Edlén.
double muse_pfits_get_rhum(const cpl_propertylist *aHeaders)
find out the relavtive humidity (in %)
double muse_phys_nrindex_filippenko(double l, double T, double f, double P)
Compute the refractive index for the given wavelength following Filippenko.
cpl_size muse_pixtable_get_nrow(const muse_pixtable *aPixtable)
get the number of rows within the pixel table
void muse_phys_nrindex_owens_coeffs(double temp, double rhum, double pres, double *d1, double *d2)
Compute the two coefficients for the Owens method.
double muse_pfits_get_pres_start(const cpl_propertylist *aHeaders)
find out the ambient pressure at start of exposure (in mbar)
double muse_phys_nrindex_ciddor(double l, double T, double p, double xv, double xCO2)
Compute the refractive index for the given wavelength following Ciddor.
cpl_table * table
The pixel table.
double muse_phys_nrindex_owens(double l, double d1, double d2)
Compute the refractive index for the given wavelength following Owens.
#define MUSE_HDR_PT_SPEC_TYPE
cpl_error_code muse_cpltable_check(const cpl_table *aTable, const muse_cpltable_def *aDef)
Check whether the table contains the fields of the definition.
Structure definition of MUSE pixel table.
double muse_pfits_get_pres_end(const cpl_propertylist *aHeaders)
find out the ambient pressure at end of exposure (in mbar)
cpl_error_code muse_phys_air_to_vacuum(muse_pixtable *aPixtable, unsigned int aFlags)
Convert a pixel table from air to vacuum wavelengths.
const muse_cpltable_def muse_pixtable_def[]
MUSE pixel table definition.
#define MUSE_PIXTABLE_LAMBDA
double muse_pfits_get_temp(const cpl_propertylist *aHeaders)
find out the ambient temperature (in degrees Celsius)
double muse_phys_nrindex_owens_saturation_pressure(double temp)
Compute the saturation pressure using the Owens calibration.
cpl_error_code muse_pixtable_compute_limits(muse_pixtable *aPixtable)
(Re-)Compute the limits of the coordinate columns of a pixel table.
cpl_propertylist * header
The FITS header.