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
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <float.h>
00039
00040 #include <cpl.h>
00041
00042 #include "irplib_std.h"
00043 #include "irplib_irlist.h"
00044
00045
00049
00052 #ifndef IRPLIB_STD_MAXRADIUS
00053
00054 #define IRPLIB_STD_MAXRADIUS 2.0
00055 #endif
00056
00057
00058
00059
00060
00061
00062 static double irplib_great_circle_dist(double, double, double, double);
00063 static int irplib_std_setactive(const char *) ;
00064 static const irplib_irstd * irplib_std_get_closest_star(double, double) ;
00065
00066
00067
00068
00069
00070
00081
00082 irplib_irstd * irplib_std_get_mag_one_cat(
00083 double ra,
00084 double dec,
00085 irplib_band band,
00086 const char * cat,
00087 double * mag)
00088 {
00089 const irplib_irstd * refstar ;
00090
00091
00092 if (cat == NULL) return NULL ;
00093 if (!strcmp(cat, "all")) return NULL ;
00094
00095
00096 irplib_std_setactive("none");
00097 irplib_std_setactive(cat) ;
00098 refstar = irplib_std_get_closest_star(ra, dec) ;
00099
00100
00101 if (refstar == NULL) return NULL ;
00102
00103 cpl_msg_info(cpl_func, "Looking for magnitude (in band %d of %d) for "
00104 "closest star '%s' at (RA,DEC)=(%g,%g)", band, BAND_UNKNOWN,
00105 refstar->name ? refstar->name : "<NULL>", refstar->ra,
00106 refstar->dec);
00107
00108
00109 switch (band) {
00110 case BAND_J:
00111 if (refstar->mag_J < 98.0) {
00112 *mag = (double)(refstar->mag_J) ;
00113 return (irplib_irstd*)refstar ;
00114 } else return NULL ;
00115 case BAND_H:
00116 if (refstar->mag_H < 98.0) {
00117 *mag = (double)(refstar->mag_H) ;
00118 return (irplib_irstd*)refstar ;
00119 } else return NULL ;
00120 case BAND_K:
00121 if (refstar->mag_K < 98.0) {
00122 *mag = (double)(refstar->mag_K) ;
00123 return (irplib_irstd*)refstar ;
00124 } else return NULL ;
00125 case BAND_KS:
00126 if (refstar->mag_Ks < 98.0) {
00127 *mag = (double)(refstar->mag_Ks) ;
00128 return (irplib_irstd*)refstar ;
00129 } else return NULL ;
00130 case BAND_L:
00131 if (refstar->mag_L < 98.0) {
00132 *mag = (double)(refstar->mag_L) ;
00133 return (irplib_irstd*)refstar ;
00134 } else return NULL ;
00135 case BAND_M:
00136 if (refstar->mag_M < 98.0) {
00137 *mag = (double)(refstar->mag_M) ;
00138 return (irplib_irstd*)refstar ;
00139 } else return NULL ;
00140 case BAND_LP:
00141 if (refstar->mag_Lp < 98.0) {
00142 *mag = (double)(refstar->mag_Lp) ;
00143 return (irplib_irstd*)refstar ;
00144 } else return NULL ;
00145 case BAND_MP:
00146 if (refstar->mag_Mp < 98.0) {
00147 *mag = (double)(refstar->mag_Mp) ;
00148 return (irplib_irstd*)refstar ;
00149 } else return NULL ;
00150 default:
00151 return NULL ;
00152 }
00153 }
00154
00155
00168
00169 cpl_vector * irplib_std_get_conversion(
00170 const cpl_bivector * spec,
00171 double dit,
00172 double surface,
00173 double gain,
00174 double mag)
00175 {
00176 double h = 6.62e-27 ;
00177 double c = 3e18 ;
00178 cpl_vector * wave ;
00179 cpl_vector * extr ;
00180 cpl_vector * out ;
00181 double factor ;
00182
00183
00184 if (spec == NULL) return NULL ;
00185 if (dit <= 0.0) return NULL ;
00186
00187
00188 wave = cpl_bivector_get_x(spec) ;
00189 extr = cpl_bivector_get_y(spec) ;
00190
00191
00192 out = cpl_vector_duplicate(extr) ;
00193
00194
00195 cpl_vector_divide_scalar(out, dit) ;
00196
00197
00198 cpl_vector_divide_scalar(out, surface) ;
00199
00200
00201 cpl_vector_multiply_scalar(out, gain) ;
00202
00203
00204 factor = pow(10, mag/2.5) ;
00205 cpl_vector_multiply_scalar(out, factor) ;
00206
00207
00208 factor = (cpl_vector_get(wave, cpl_vector_get_size(wave)-1) -
00209 cpl_vector_get(wave, 0)) / cpl_vector_get_size(wave) ;
00210 cpl_vector_divide_scalar(out, factor) ;
00211
00212
00213 cpl_vector_multiply_scalar(out, h*c) ;
00214 cpl_vector_divide(out, wave) ;
00215
00216 return out ;
00217 }
00218
00219
00227
00228 cpl_vector * irplib_std_get_mag_zero(
00229 const cpl_bivector * sed,
00230 const cpl_vector * waves,
00231 double cent_wl)
00232 {
00233 double wmin, wmax, wstep ;
00234 int nb_sed ;
00235 double * sed_x ;
00236 double * sed_y ;
00237 cpl_bivector * sed_loc ;
00238 double * sed_loc_x ;
00239 double * sed_loc_y ;
00240 cpl_vector * out ;
00241 cpl_bivector * out_biv ;
00242 double f0_jan, f0_erg, cent_val ;
00243 int i ;
00244
00245
00246 if (sed == NULL) return NULL ;
00247 if (waves == NULL) return NULL ;
00248
00249
00250 nb_sed = cpl_bivector_get_size(sed) ;
00251 sed_x = cpl_bivector_get_x_data(sed) ;
00252 sed_y = cpl_bivector_get_y_data(sed) ;
00253 wstep = sed_x[1] - sed_x[0] ;
00254 wmin = cpl_vector_get(waves, 0) ;
00255 wmax = cpl_vector_get(waves, cpl_vector_get_size(waves)-1) ;
00256
00257
00258 sed_loc = cpl_bivector_new(nb_sed + 4) ;
00259 sed_loc_x = cpl_bivector_get_x_data(sed_loc) ;
00260 sed_loc_y = cpl_bivector_get_y_data(sed_loc) ;
00261 for (i=0 ; i<nb_sed ; i++) {
00262 sed_loc_x[i+2] = sed_x[i] ;
00263 sed_loc_y[i+2] = sed_y[i] ;
00264 }
00265
00266
00267 sed_loc_x[1] = sed_loc_x[2] - wstep ;
00268 if (sed_loc_x[2] < wmin) {
00269 sed_loc_x[0] = sed_loc_x[1] - wstep ;
00270 } else {
00271 sed_loc_x[0] = wmin - wstep ;
00272 }
00273 sed_loc_y[0] = 1e20 ;
00274 sed_loc_y[1] = 1e20 ;
00275
00276
00277 sed_loc_x[nb_sed+2] = sed_loc_x[nb_sed+1] + wstep ;
00278 if (sed_loc_x[nb_sed+1] > wmax) {
00279 sed_loc_x[nb_sed+3] = sed_loc_x[nb_sed+2] + wstep ;
00280 } else {
00281 sed_loc_x[nb_sed+3] = wmax + wstep ;
00282 }
00283 sed_loc_y[nb_sed+2] = 1e20 ;
00284 sed_loc_y[nb_sed+3] = 1e20 ;
00285
00286
00287 out = cpl_vector_duplicate(waves) ;
00288 out_biv = cpl_bivector_wrap_vectors((cpl_vector*)waves, out) ;
00289
00290
00291 if (cpl_bivector_interpolate_linear(out_biv, sed_loc) != CPL_ERROR_NONE) {
00292 cpl_msg_error(cpl_func, "Cannot interpolate the wavelength") ;
00293 cpl_bivector_unwrap_vectors(out_biv) ;
00294 cpl_vector_delete(out) ;
00295 cpl_bivector_delete(sed_loc) ;
00296 return NULL ;
00297 }
00298 cpl_bivector_unwrap_vectors(out_biv) ;
00299 cpl_bivector_delete(sed_loc) ;
00300
00301
00302 f0_jan = 5513.15 / ( pow(cent_wl,3) * (exp(1.2848/cent_wl)-1) ) ;
00303
00304
00305 f0_erg = f0_jan * 1e-26 * 1e7 * 3e18 / (1e4 * cent_wl*cent_wl*1e4*1e4) ;
00306
00307
00308 cent_val = cpl_vector_get(out, cpl_vector_get_size(out)/2) ;
00309 if (cent_val <= 0.0) {
00310 cpl_msg_error(cpl_func, "Negative or 0 central value") ;
00311 cpl_vector_delete(out) ;
00312 return NULL ;
00313 }
00314 cpl_vector_multiply_scalar(out, f0_erg/cent_val) ;
00315
00316
00317 return out ;
00318 }
00319
00320
00330
00331 cpl_bivector * irplib_std_get_sed(
00332 const char * seds_file,
00333 const char * sptype)
00334 {
00335 cpl_table * seds ;
00336 cpl_bivector * out ;
00337 cpl_vector * wave ;
00338 cpl_vector * sed ;
00339 cpl_bivector * tmp ;
00340 int nlines ;
00341
00342
00343 if (seds_file == NULL) return NULL ;
00344 if (sptype == NULL) return NULL ;
00345
00346
00347 if ((seds = cpl_table_load(seds_file, 1, 0)) == NULL) {
00348 cpl_msg_error(cpl_func, "Cannot load the table") ;
00349 return NULL ;
00350 }
00351
00352
00353 if (!cpl_table_has_column(seds, sptype)) {
00354 cpl_msg_error(cpl_func, "SED of the requested star not available") ;
00355 cpl_table_delete(seds) ;
00356 return NULL ;
00357 }
00358
00359
00360 nlines = cpl_table_get_nrow(seds) ;
00361
00362
00363 if ((wave = cpl_vector_wrap(nlines,
00364 cpl_table_get_data_double(seds, "Wavelength"))) == NULL) {
00365 cpl_msg_error(cpl_func, "Cannot get the Wavelength column") ;
00366 cpl_table_delete(seds) ;
00367 return NULL ;
00368 }
00369
00370
00371 if ((sed = cpl_vector_wrap(nlines,
00372 cpl_table_get_data_double(seds, sptype))) == NULL) {
00373 cpl_msg_error(cpl_func, "Cannot get the SED column") ;
00374 cpl_table_delete(seds) ;
00375 cpl_vector_unwrap(wave) ;
00376 return NULL ;
00377 }
00378 tmp = cpl_bivector_wrap_vectors(wave, sed) ;
00379
00380
00381 out = cpl_bivector_duplicate(tmp) ;
00382
00383
00384 cpl_bivector_unwrap_vectors(tmp) ;
00385 cpl_vector_unwrap(wave) ;
00386 cpl_vector_unwrap(sed) ;
00387 cpl_table_delete(seds) ;
00388
00389
00390 return out ;
00391 }
00392
00393
00401
00402 irplib_irstd * irplib_std_get_type(
00403 double ra,
00404 double dec)
00405 {
00406 char ** catalog_names ;
00407 const irplib_irstd * refstar ;
00408 int nfound ;
00409 const irplib_irstd ** refstars ;
00410 int i, j ;
00411
00412
00413 catalog_names = (char**)irplib_irlist_catalogs ;
00414 nfound = 0 ;
00415
00416
00417 for (i=0 ; catalog_names[i] ; i++) {
00418 irplib_std_setactive("none");
00419 irplib_std_setactive(catalog_names[i]) ;
00420 refstar = irplib_std_get_closest_star(ra, dec) ;
00421 if (refstar != NULL) nfound ++ ;
00422 }
00423 refstars = cpl_malloc(nfound*sizeof(irplib_irstd*)) ;
00424 j = 0 ;
00425 for (i=0 ; catalog_names[i] ; i++) {
00426 irplib_std_setactive("none");
00427 irplib_std_setactive(catalog_names[i]) ;
00428 refstar = irplib_std_get_closest_star(ra, dec) ;
00429 if (refstar != NULL) {
00430 refstars[j] = refstar ;
00431 j++ ;
00432 }
00433 }
00434
00435
00436 refstar = NULL ;
00437 for (i=0 ; i<nfound ; i++) {
00438 if (strcmp(refstars[i]->sptype, "--")) {
00439 refstar = refstars[i] ;
00440 break ;
00441 }
00442 }
00443
00444 cpl_free(refstars) ;
00445 return (irplib_irstd*)refstar ;
00446 }
00447
00448
00458
00459 irplib_irstd * irplib_std_get_mag(
00460 double ra,
00461 double dec,
00462 irplib_band band,
00463 double * mag)
00464 {
00465 char ** catalog_names ;
00466 const irplib_irstd * refstar ;
00467 int nfound ;
00468 const irplib_irstd ** refstars ;
00469 int i, j ;
00470
00471
00472 catalog_names = (char**)irplib_irlist_catalogs ;
00473 nfound = 0 ;
00474
00475
00476 for (i=0 ; catalog_names[i] ; i++) {
00477 irplib_std_setactive("none");
00478 irplib_std_setactive(catalog_names[i]) ;
00479 refstar = irplib_std_get_closest_star(ra, dec) ;
00480 if (refstar != NULL) nfound ++ ;
00481 }
00482 refstars = cpl_malloc(nfound*sizeof(irplib_irstd*)) ;
00483 j = 0 ;
00484 for (i=0 ; catalog_names[i] ; i++) {
00485 irplib_std_setactive("none");
00486 irplib_std_setactive(catalog_names[i]) ;
00487 refstar = irplib_std_get_closest_star(ra, dec) ;
00488 if (refstar != NULL) {
00489 refstars[j] = refstar ;
00490 j++ ;
00491 }
00492 }
00493
00494
00495 refstar = NULL ;
00496 switch (band) {
00497 case BAND_J:
00498 for (i=0 ; i<nfound ; i++) {
00499 if (refstars[i]->mag_J < 98.0) {
00500 refstar = refstars[i] ;
00501 *mag = (double)(refstar->mag_J) ;
00502 break ;
00503 }
00504 }
00505 break ;
00506 case BAND_H:
00507 for (i=0 ; i<nfound ; i++) {
00508 if (refstars[i]->mag_H < 98.0) {
00509 refstar = refstars[i] ;
00510 *mag = (double)(refstar->mag_H) ;
00511 break ;
00512 }
00513 }
00514 break ;
00515 case BAND_K:
00516 for (i=0 ; i<nfound ; i++) {
00517 if (refstars[i]->mag_K < 98.0) {
00518 refstar = refstars[i] ;
00519 *mag = (double)(refstar->mag_K) ;
00520 break ;
00521 }
00522 }
00523 break ;
00524 case BAND_KS:
00525 for (i=0 ; i<nfound ; i++) {
00526 if (refstars[i]->mag_Ks < 98.0) {
00527 refstar = refstars[i] ;
00528 *mag = (double)(refstar->mag_Ks) ;
00529 break ;
00530 }
00531 }
00532 break ;
00533 case BAND_L:
00534 for (i=0 ; i<nfound ; i++) {
00535 if (refstars[i]->mag_L < 98.0) {
00536 refstar = refstars[i] ;
00537 *mag = (double)(refstar->mag_L) ;
00538 break ;
00539 }
00540 }
00541 break ;
00542 case BAND_M:
00543 for (i=0 ; i<nfound ; i++) {
00544 if (refstars[i]->mag_M < 98.0) {
00545 refstar = refstars[i] ;
00546 *mag = (double)(refstar->mag_M) ;
00547 break ;
00548 }
00549 }
00550 break ;
00551 case BAND_LP:
00552 for (i=0 ; i<nfound ; i++) {
00553 if (refstars[i]->mag_Lp < 98.0) {
00554 refstar = refstars[i] ;
00555 *mag = (double)(refstar->mag_Lp) ;
00556 break ;
00557 }
00558 }
00559 break ;
00560 case BAND_MP:
00561 for (i=0 ; i<nfound ; i++) {
00562 if (refstars[i]->mag_Mp < 98.0) {
00563 refstar = refstars[i] ;
00564 *mag = (double)(refstar->mag_Mp) ;
00565 break ;
00566 }
00567 }
00568 break ;
00569 default:
00570 break ;
00571 }
00572
00573
00574
00575 cpl_free(refstars) ;
00576 return (irplib_irstd*)refstar ;
00577 }
00578
00579
00585
00586 const char * irplib_std_band_name(irplib_band band)
00587 {
00588 switch (band) {
00589 case BAND_J: return "J" ;
00590 case BAND_JS: return "Js" ;
00591 case BAND_JBLOCK: return "J+Block" ;
00592 case BAND_H: return "H" ;
00593 case BAND_K: return "K" ;
00594 case BAND_KS: return "Ks" ;
00595 case BAND_L: return "L" ;
00596 case BAND_M: return "M" ;
00597 case BAND_LP: return "Lp" ;
00598 case BAND_MP: return "Mp" ;
00599 case BAND_Z: return "Z" ;
00600 case BAND_SZ: return "SZ" ;
00601 case BAND_SH: return "SH" ;
00602 case BAND_SK: return "SK" ;
00603 case BAND_SL: return "SL" ;
00604 default: return "Unknown" ;
00605 }
00606 }
00607
00608
00618
00619 const char * irplib_std_catalog_name(int cat_id)
00620 {
00621 return irplib_irlist_catalogs[cat_id] ;
00622 }
00623
00624
00625
00632
00633 const char * irplib_std_get_name(const irplib_irstd * self)
00634 {
00635
00636 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00637
00638 return self->name;
00639 }
00640
00641
00648
00649 const char * irplib_std_get_type_spectral(const irplib_irstd * self)
00650 {
00651
00652 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00653
00654 return self->sptype;
00655 }
00656
00657
00658
00665
00666 const char * irplib_std_get_catalog(const irplib_irstd * self)
00667 {
00668
00669 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00670
00671 return irplib_irlist_catalogs[self->source];
00672 }
00673
00674
00677
00691
00692 static int irplib_std_setactive(const char * catalog)
00693 {
00694 int i ;
00695 int found ;
00696 int active ;
00697
00698
00699 if (catalog==NULL) {
00700 found=0 ;
00701 i=0 ;
00702 while (irplib_irstd_list[i].name != NULL) {
00703 if (irplib_irstd_list[i].select) found++ ;
00704 i++ ;
00705 }
00706 return found ;
00707 }
00708
00709
00710 if (!strcmp(catalog, "none")) {
00711 i=0 ;
00712 while (irplib_irstd_list[i].name!=NULL) {
00713 irplib_irstd_list[i].select=0 ;
00714 i++;
00715 }
00716 return 0 ;
00717 }
00718
00719
00720 if (!strcmp(catalog, "all")) {
00721 i=0 ;
00722 while (irplib_irstd_list[i].name!=NULL) {
00723 irplib_irstd_list[i].select=1 ;
00724 i++;
00725 }
00726 return i ;
00727 }
00728
00729
00730 i=0 ;
00731 active=0 ;
00732 found=0 ;
00733 while (irplib_irstd_list[i].name!=NULL) {
00734 if (!strcmp(catalog, irplib_irlist_catalogs[irplib_irstd_list[i].source])) {
00735 found=1 ;
00736 irplib_irstd_list[i].select=1 ;
00737 }
00738 if (irplib_irstd_list[i].select) {
00739 active++ ;
00740 }
00741 i++ ;
00742 }
00743 if (found<1) return -1 ;
00744 return active ;
00745 }
00746
00747
00760
00761 static const irplib_irstd * irplib_std_get_closest_star(double ra_d,
00762 double dec_d)
00763 {
00764 const irplib_irstd * self = NULL;
00765 const double max_dist = (IRPLIB_STD_MAXRADIUS)/60.0;
00766 double min_dist = DBL_MAX;
00767 int min_index;
00768 int i;
00769
00770
00771
00772 min_index = -1;
00773 for (i = 0; irplib_irstd_list[i].name != NULL; i++) {
00774 if (irplib_irstd_list[i].select) {
00775 const double ra = irplib_irstd_list[i].ra;
00776 const double dec = irplib_irstd_list[i].dec;
00777 const double dist = irplib_great_circle_dist(ra_d, dec_d, ra, dec);
00778
00779 if (min_index < 0 || dist < min_dist) {
00780 min_dist = dist;
00781 min_index = i;
00782 }
00783 }
00784 }
00785
00786 if (min_index < 0) {
00787 cpl_msg_debug(cpl_func, "No standard stars found in catalogue: %d", i);
00788 } else if (min_dist > max_dist) {
00789
00790
00791
00792 cpl_msg_debug(cpl_func, "The distance between the star at (RA,DEC)="
00793 "(%g,%g) and the closest catalogue star at (RA,DEC)="
00794 "(%g, %g) exceeds %g degrees [degrees]: %g (%d)",
00795 ra_d, dec_d, irplib_irstd_list[min_index].ra,
00796 irplib_irstd_list[min_index].dec, max_dist, min_dist,
00797 min_index);
00798 } else {
00799 self = &(irplib_irstd_list[min_index]);
00800 }
00801
00802 return self;
00803 }
00804
00805
00806
00818
00819 static double irplib_great_circle_dist(double ra1, double dec1,
00820 double ra2, double dec2)
00821 {
00822
00823
00824 const double dra = sin( atan(1.0)/45.0 * (ra2 - ra1 )/2.0 );
00825 const double ddec = sin( atan(1.0)/45.0 * (dec2 - dec1)/2.0 );
00826
00827 dec1 *= atan(1.0)/45.0;
00828 dec2 *= atan(1.0)/45.0;
00829
00830 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
00831 * 45.0/atan(1.0);
00832
00833 }