32#include "cr2res_photom.h"
33#include "cr2res_dfs.h"
34#include "cr2res_pfits.h"
35#include "cr2res_utils.h"
36#include "cr2res_extract.h"
42static double cr2res_photom_throughput_avg(
43 const cpl_vector * vec,
44 const cpl_vector * wl,
45 const char * setting) ;
47static cpl_vector * cr2res_photom_conversion(
48 const cpl_bivector * star,
49 const cpl_bivector * photflux,
52static cpl_vector * cr2res_photom_throughput(
53 const cpl_vector * conversion,
54 const cpl_vector * wl,
57static cpl_vector * cr2res_photom_sensitivity(
58 const cpl_vector * conversion,
59 const cpl_vector * sigma,
62static int cr2res_photom_star_find(
63 const cpl_vector * v_ra,
64 const cpl_vector * v_dec,
70static double cr2res_photom_great_circle_dist(
103 const cpl_table * extr,
104 const char * std_star_file,
105 const char * setting,
113 cpl_table ** throughput,
114 cpl_propertylist ** ext_plist)
116 cpl_table * std_star_tab ;
117 cpl_bivector * std_star_biv ;
118 cpl_table * throughput_loc ;
119 cpl_array * col_names ;
124 cpl_bivector * spec_biv ;
125 cpl_bivector * spec_err_biv ;
126 cpl_vector * conversion_vec ;
127 cpl_vector * throughput_vec ;
128 cpl_vector * sensitivity_vec ;
129 double throughput_avg_val, throughput_center ;
130 int throughput_avg_nb ;
131 cpl_propertylist * plist ;
132 const double * pdata ;
134 int order, trace_nb ;
137 if (extr==NULL || std_star_file==NULL || setting == NULL ||
138 throughput==NULL || ext_plist == NULL)
return -1 ;
141 throughput_avg_val = 0.0 ;
142 throughput_avg_nb = 0 ;
145 if ((std_star_tab = cpl_table_load(std_star_file, 1, 0)) == NULL) {
146 cpl_msg_error(__func__,
"Cannot load the std star table") ;
153 cpl_msg_error(__func__,
"Cannot find the star flux") ;
154 cpl_table_delete(std_star_tab) ;
157 cpl_table_delete(std_star_tab) ;
160 throughput_loc = cpl_table_new(cpl_table_get_nrow(extr)) ;
163 col_names = cpl_table_get_column_names(extr);
164 ncols = cpl_table_get_ncol(extr) ;
165 for (j=0 ; j<ncols ; j++) {
166 const char *col_name;
168 col_name = cpl_array_get_string(col_names, j);
170 if (col_type != NULL && !strcmp(col_type, CR2RES_COL_SPEC_SUFFIX)) {
173 &spec_biv, &spec_err_biv)) {
174 cpl_msg_error(__func__,
"Cannot get the extracted spectrum") ;
178 cpl_msg_info(__func__,
179 "Conversion/Sensitivity/Throughput for order/trace: %d/%d",
183 if ((conversion_vec = cr2res_photom_conversion(spec_biv,
184 std_star_biv, exptime))==NULL) {
185 cpl_msg_warning(__func__,
186 "Cannot compute the conversion factor");
188 cpl_bivector_delete(spec_biv) ;
189 cpl_bivector_delete(spec_err_biv) ;
195 if ((throughput_vec = cr2res_photom_throughput(conversion_vec,
196 cpl_bivector_get_x_const(spec_biv), gain))==NULL) {
197 cpl_msg_warning(__func__,
"Cannot compute the throughput");
199 cpl_bivector_delete(spec_biv) ;
200 cpl_bivector_delete(spec_err_biv) ;
201 cpl_vector_delete(conversion_vec) ;
202 if (col_type != NULL) cpl_free(col_type) ;
207 if ((sensitivity_vec = cr2res_photom_sensitivity(conversion_vec,
208 cpl_bivector_get_y_const(spec_err_biv),
210 cpl_msg_warning(__func__,
"Cannot compute the sensitivity");
212 cpl_bivector_delete(spec_biv) ;
213 cpl_bivector_delete(spec_err_biv) ;
214 cpl_vector_delete(conversion_vec) ;
215 cpl_vector_delete(throughput_vec) ;
216 if (col_type != NULL) cpl_free(col_type) ;
223 cpl_table_new_column(throughput_loc, cwname, CPL_TYPE_DOUBLE);
224 pdata = cpl_bivector_get_x_data_const(spec_biv) ;
225 cpl_table_copy_data_double(throughput_loc, cwname, pdata) ;
229 cpl_table_new_column(throughput_loc, ccname, CPL_TYPE_DOUBLE);
230 pdata = cpl_vector_get_data_const(conversion_vec) ;
231 cpl_table_copy_data_double(throughput_loc, ccname, pdata) ;
235 cpl_table_new_column(throughput_loc, csname, CPL_TYPE_DOUBLE);
236 pdata = cpl_vector_get_data_const(sensitivity_vec) ;
237 cpl_table_copy_data_double(throughput_loc, csname, pdata) ;
241 cpl_table_new_column(throughput_loc, ctname, CPL_TYPE_DOUBLE);
242 pdata = cpl_vector_get_data_const(throughput_vec) ;
243 cpl_table_copy_data_double(throughput_loc, ctname, pdata) ;
246 throughput_center = cr2res_photom_throughput_avg(throughput_vec,
247 cpl_bivector_get_x_const(spec_biv), setting) ;
248 if (fabs(throughput_center+1.0) > 1e-3) {
249 throughput_avg_nb ++ ;
250 throughput_avg_val += throughput_center ;
253 cpl_vector_delete(conversion_vec) ;
254 cpl_vector_delete(sensitivity_vec) ;
255 cpl_vector_delete(throughput_vec) ;
256 cpl_bivector_delete(spec_biv) ;
257 cpl_bivector_delete(spec_err_biv) ;
260 if (display && display_trace==trace_nb && display_order==order) {
262"set grid;set xlabel 'Wavelength (nm)';set ylabel 'Conversion (ADU/sec/Jy)';",
263 "t 'Conversion factor' w lines",
"",
264 throughput_loc, cwname, ccname) ;
266"set grid;set xlabel 'Wavelength (nm)';set ylabel 'Sensitivity (Jy/10sig/hour)';",
267 "t 'Sensitivity' w lines",
"",
268 throughput_loc, cwname, csname) ;
270"set grid;set xlabel 'Wavelength (nm)';set ylabel 'Throughput (e-/photons)';",
271 "t 'Throughput' w lines",
"",
272 throughput_loc, cwname, ctname) ;
279 if (col_type != NULL) cpl_free(col_type) ;
281 cpl_array_delete(col_names) ;
282 cpl_bivector_delete(std_star_biv) ;
284 plist = cpl_propertylist_new() ;
285 if (throughput_avg_nb > 0) {
286 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_THROUGHPUT,
287 throughput_avg_val / throughput_avg_nb) ;
289 *throughput = throughput_loc ;
304 const cpl_table * tab,
310 double maxdist, dist ;
314 cpl_vector * wave_vec ;
315 cpl_vector * flux_vec ;
316 cpl_bivector * flux_biv ;
319 if (tab == NULL)
return NULL ;
322 maxdist = CR2RES_PHOTOM_STARSDIST_ARCSEC / 3600.0 ;
325 ras = cpl_vector_wrap(cpl_table_get_nrow(tab),
326 cpl_table_get_data_double((cpl_table*)tab, CR2RES_COL_RA)) ;
327 decs = cpl_vector_wrap(cpl_table_get_nrow(tab),
328 cpl_table_get_data_double((cpl_table*)tab, CR2RES_COL_DEC)) ;
331 cpl_msg_info(__func__,
"Search a star around RA=%g, DEC=%g in the catalog",
333 if ((ind = cr2res_photom_star_find(ras, decs, ra, dec, maxdist,
335 cpl_msg_error(__func__,
"No star found") ;
336 cpl_vector_unwrap(ras) ;
337 cpl_vector_unwrap(decs) ;
340 dist = 3600 * cr2res_photom_great_circle_dist(cpl_vector_get(ras,
341 ind), cpl_vector_get(decs, ind), ra, dec) ;
342 cpl_msg_info(__func__,
"Star found: %s at RA=%g, DEC=%g at %g arcsec",
343 cpl_table_get_string(tab, CR2RES_COL_STDNAME, ind),
344 cpl_vector_get(ras, ind), cpl_vector_get(decs, ind),
346 cpl_vector_unwrap(ras) ;
347 cpl_vector_unwrap(decs) ;
350 wave=cpl_array_duplicate(cpl_table_get_array(tab,CR2RES_COL_PHOTOFLUX,0));
351 flux=cpl_array_duplicate(cpl_table_get_array(tab,CR2RES_COL_PHOTOFLUX,ind));
352 wave_vec = cpl_vector_wrap(cpl_array_get_size(wave),
353 cpl_array_get_data_double(wave)) ;
354 flux_vec = cpl_vector_wrap(cpl_array_get_size(flux),
355 cpl_array_get_data_double(flux)) ;
356 cpl_array_unwrap(wave) ;
357 cpl_array_unwrap(flux) ;
358 flux_biv=cpl_bivector_wrap_vectors(wave_vec, flux_vec) ;
372static double cr2res_photom_throughput_avg(
373 const cpl_vector * vec,
374 const cpl_vector * wl,
375 const char * setting)
377 const double * pvec ;
379 double sum, wmin, wmax ;
384 if (vec == NULL || wl == NULL)
return -1.0 ;
385 nelem = cpl_vector_get_size(vec) ;
386 if (cpl_vector_get_size(wl) != nelem)
return -1.0 ;
392 if (!strcmp(setting,
"Y1028")) {
395 }
else if (!strcmp(setting,
"J1228")) {
398 }
else if (!strcmp(setting,
"H1567")) {
401 }
else if (!strcmp(setting,
"K2148")) {
404 }
else if (!strcmp(setting,
"L3377")) {
407 }
else if (!strcmp(setting,
"M4266")) {
411 if (wmin < 0.0 || wmax < 0.0)
return -1.0 ;
413 cpl_msg_info(__func__,
"Compute the QC.THROUGHPUT between %g and %g nm",
416 pvec = cpl_vector_get_data_const(vec) ;
417 pwl = cpl_vector_get_data_const(wl) ;
421 for (i=0 ; i<nelem ; i++) {
422 if (pwl[i]>wmin && pwl[i]<wmax) {
427 if (nsum > 0)
return sum/nsum ;
450static cpl_vector * cr2res_photom_conversion(
451 const cpl_bivector * star,
452 const cpl_bivector * photflux,
455 cpl_vector * conversion ;
456 cpl_bivector * model ;
461 if (star == NULL)
return NULL ;
462 if (photflux == NULL)
return NULL ;
463 if (fabs(exptime) < 1e-3)
return NULL ;
466 model = cpl_bivector_duplicate(star) ;
467 if (cpl_bivector_interpolate_linear(model, photflux) != CPL_ERROR_NONE) {
468 cpl_msg_error(__func__,
"Cannot interpolate the signal") ;
469 cpl_bivector_delete(model) ;
474 pmodel = cpl_vector_get_data(cpl_bivector_get_y(model)) ;
475 for (i=0 ; i<cpl_bivector_get_size(model) ; i++) {
476 if (fabs(pmodel[i]) == 0.0) pmodel[i] = 1.0 ;
480 conversion = cpl_vector_duplicate(cpl_bivector_get_y_const(star)) ;
481 cpl_vector_divide_scalar(conversion, exptime) ;
483 if (cpl_vector_divide(conversion,
484 cpl_bivector_get_y(model)) != CPL_ERROR_NONE) {
485 cpl_msg_error(__func__,
"Cannot divide the star by the model") ;
486 cpl_bivector_delete(model) ;
489 cpl_bivector_delete(model) ;
513static cpl_vector * cr2res_photom_throughput(
514 const cpl_vector * conversion,
515 const cpl_vector * wl,
519 cpl_vector * throughput ;
520 cpl_vector * wave_m ;
521 cpl_vector * dwave_m ;
526 if (conversion == NULL)
return NULL ;
527 if (wl == NULL)
return NULL ;
531 S = 16 * 3.141592653589793238462 ;
534 wave_m = cpl_vector_duplicate(wl) ;
535 cpl_vector_multiply_scalar(wave_m, 1e-9) ;
538 dwave_m = cpl_vector_duplicate(wave_m) ;
539 pdwave_m = cpl_vector_get_data(dwave_m) ;
540 for (i=cpl_vector_get_size(dwave_m)-1 ; i>0 ; i--)
541 pdwave_m[i] -= pdwave_m[i-1] ;
542 pdwave_m[0] = pdwave_m[1] ;
545 throughput = cpl_vector_duplicate(conversion) ;
546 cpl_vector_multiply_scalar(throughput, gain) ;
547 cpl_vector_multiply_scalar(throughput, h) ;
548 cpl_vector_multiply(throughput, wave_m) ;
549 cpl_vector_divide_scalar(throughput, 1e-32) ;
550 cpl_vector_divide_scalar(throughput, S) ;
551 cpl_vector_divide(throughput, dwave_m) ;
552 cpl_vector_divide_scalar(throughput, 1e6) ;
554 cpl_vector_delete(dwave_m) ;
555 cpl_vector_delete(wave_m) ;
577static cpl_vector * cr2res_photom_sensitivity(
578 const cpl_vector * conversion,
579 const cpl_vector * sigma,
582 cpl_vector * sensitivity ;
584 const double * pconversion ;
585 double * psensitivity ;
589 if (conversion == NULL)
return NULL ;
590 if (sigma == NULL)
return NULL ;
591 if (exptime < 0)
return NULL ;
594 pconversion = cpl_vector_get_data_const(conversion) ;
595 sensitivity = cpl_vector_duplicate(sigma) ;
596 psensitivity = cpl_vector_get_data(sensitivity) ;
599 for (i=0 ; i<cpl_vector_get_size(conversion) ; i++) {
600 if (fabs(pconversion[i])<1e-5) psensitivity[i] = 0.0 ;
601 else psensitivity[i] /= pconversion[i] ;
603 for (i=0 ; i<11 ; i++) psensitivity[i] = 0 ;
606 factor = sqrt(exptime/3600) * 10 ;
609 if (cpl_vector_multiply_scalar(sensitivity, factor) != CPL_ERROR_NONE) {
610 cpl_msg_error(__func__,
"Cannot multiply by the factor") ;
611 cpl_vector_delete(sensitivity) ;
633static int cr2res_photom_star_find(
634 const cpl_vector * v_ra,
635 const cpl_vector * v_dec,
641 int nra, ndec, minind ;
643 const double * pv_ra ;
644 const double * pv_dec ;
648 if (v_ra == NULL || v_dec == NULL)
return -1 ;
653 nra = cpl_vector_get_size(v_ra) ;
654 ndec = cpl_vector_get_size(v_dec) ;
655 pv_ra = cpl_vector_get_data_const(v_ra) ;
656 pv_dec = cpl_vector_get_data_const(v_dec) ;
659 if (nra != ndec)
return -1 ;
660 if (maxdist < 0)
return -1 ;
663 for (i=0 ; i < nra ; i++) {
666 gdist = cr2res_photom_great_circle_dist(pv_ra[i], pv_dec[i], ra, dec);
667 if (i == 0 || gdist < dmin) {
672 if (pdist != NULL) *pdist = dmin;
675 if (dmin > maxdist)
return -1 ;
690static double cr2res_photom_great_circle_dist(
697 const double dra = sin( atan(1.0)/45.0 * (ra2 - ra1 )/2.0 );
698 const double ddec = sin( atan(1.0)/45.0 * (dec2 - dec1)/2.0 );
700 dec1 *= atan(1.0)/45.0;
701 dec2 *= atan(1.0)/45.0;
703 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
char * cr2res_dfs_CONVERSION_colname(int order_idx, int trace)
Get the CONVERSION column name for a given order/trace.
char * cr2res_dfs_SENSITIVITY_colname(int order_idx, int trace)
Get the SENSITIVITY column name for a given order/trace.
char * cr2res_dfs_WAVELENGTH_colname(int order_idx, int trace)
Get the WAVELENGTH column name for a given order/trace.
char * cr2res_dfs_SPEC_colname_parse(const char *colname, int *order_idx, int *trace)
Parse a column name ORDER_TRACE_TYPE format.
char * cr2res_dfs_THROUGHPUT_colname(int order_idx, int trace)
Get the THROUGHPUT column name for a given order/trace.
cpl_bivector * cr2res_photom_conv_get_star(const cpl_table *tab, double ra, double dec)
Get the wished std star photospheric flux.
int cr2res_photom_engine(const cpl_table *extr, const char *std_star_file, const char *setting, double ra, double dec, double gain, double exptime, int display, int display_order, int display_trace, cpl_table **throughput, cpl_propertylist **ext_plist)
Compute the conversion/throughput/sensitivity high level.