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 <assert.h>
00037 #include <cpl.h>
00038
00039
00040 #include <qfits.h>
00041
00042
00043 #include "visir_utils.h"
00044 #include "visir_pfits.h"
00045 #include "visir_dfs.h"
00046 #include "visir_inputs.h"
00047
00048
00049
00050
00051
00052 #define RECIPENAME "visir_util_spc_std_cat"
00053
00054
00055
00056
00057
00058 static int visir_util_spc_std_cat_create(cpl_plugin *);
00059 static int visir_util_spc_std_cat_exec(cpl_plugin *);
00060 static int visir_util_spc_std_cat_destroy(cpl_plugin *);
00061 static int visir_util_spc_std_cat(const cpl_parameterlist *, cpl_frameset *);
00062 static int visir_util_spc_std_cat_save(void **, int, int,
00063 const cpl_parameterlist *,
00064 cpl_frameset *);
00065
00066
00067
00068
00069
00070 static const char * recipename = RECIPENAME;
00071
00072 static char visir_util_spc_std_cat_description[] =
00073 "This recipe generates a FITS standard star catalog for spectroscopy from \n"
00074 "a set of ASCII-files named <Star_Name>.txt, e.g. HD133165.txt.\n"
00075 "All input ASCII-files must comprise the same number of lines.\n"
00076 "The first line of the ASCII-file must have 6 fields separated by white-space.\n"
00077 "The first three fields are the RA (hh mm ss) which will be stored in degrees\n"
00078 "in a table column labeled 'RA' - all three are non-negative and hh and mm \n"
00079 "are integer.\n"
00080 "The 3 last fields are the DEC (dd mm ss) which will be stored in degrees in \n"
00081 "a table column labeled 'DEC' - all three are non-negative, dd and mm are \n"
00082 "integer, while dd has either a '+' or a '-' prepended (including -00).\n"
00083 "The remaining lines must all consist of two fields separated by white-space.\n"
00084 "The first field is the wavelength (in microns) and the second the (positive)\n"
00085 "model flux in W/m2/m. The wavelengths must be identical in all the input "
00086 "files.\n";
00087
00088 const int starnamelen = 32;
00089
00090
00091
00092
00093
00094
00103
00104 int cpl_plugin_get_info(cpl_pluginlist * list)
00105 {
00106 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
00107 cpl_plugin * plugin = &recipe->interface;
00108
00109
00110 if (cpl_plugin_init(plugin,
00111 CPL_PLUGIN_API,
00112 VISIR_BINARY_VERSION,
00113 CPL_PLUGIN_TYPE_RECIPE,
00114 recipename,
00115 "Convert a text file into a FITS standard star catalog",
00116 visir_util_spc_std_cat_description,
00117 "Lars Lundin",
00118 PACKAGE_BUGREPORT,
00119 visir_get_license(),
00120 visir_util_spc_std_cat_create,
00121 visir_util_spc_std_cat_exec,
00122 visir_util_spc_std_cat_destroy)) return 1;
00123
00124 if (cpl_pluginlist_append(list, plugin)) return 1;
00125
00126 return 0;
00127 }
00128
00129
00138
00139 static int visir_util_spc_std_cat_create(cpl_plugin * plugin)
00140 {
00141 cpl_recipe * recipe = (cpl_recipe *)plugin;
00142
00143
00144 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) return 1;
00145
00146
00147 recipe->parameters = cpl_parameterlist_new();
00148
00149 return 0;
00150 }
00151
00152
00158
00159 static int visir_util_spc_std_cat_exec(cpl_plugin * plugin)
00160 {
00161 cpl_recipe * recipe = (cpl_recipe *)plugin;
00162
00163
00164 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) return 1;
00165
00166 return visir_util_spc_std_cat(recipe->parameters, recipe->frames);
00167 }
00168
00169
00175
00176 static int visir_util_spc_std_cat_destroy(cpl_plugin * plugin)
00177 {
00178 cpl_recipe * recipe = (cpl_recipe *)plugin;
00179
00180
00181 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) return 1;
00182 cpl_parameterlist_delete(recipe->parameters);
00183 return 0;
00184 }
00185
00186
00197
00198 static int visir_util_spc_std_cat(
00199 const cpl_parameterlist * parlist,
00200 cpl_frameset * framelist)
00201 {
00202 int nfiles;
00203 const cpl_frame * frame;
00204 char * starnames = NULL;
00205 double * ras = NULL;
00206 double * decs = NULL;
00207 double * wls = NULL;
00208 double * vals = NULL;
00209 cpl_bivector * spectrum = NULL;
00210 void ** data = NULL;
00211 FILE * in = NULL;
00212 char line[1024];
00213 const double max_radius = VISIR_STAR_MAX_RADIUS;
00214 double mindist;
00215 int iloc1, iloc2;
00216 int nvals;
00217 int i;
00218
00219
00220 if (cpl_error_get_code()) return cpl_error_get_code();
00221
00222
00223 nfiles = cpl_frameset_get_size(framelist);
00224
00225 skip_if (nfiles < 1);
00226
00227
00228 starnames = cpl_malloc(nfiles * starnamelen);
00229 ras = cpl_malloc(nfiles * sizeof(double));
00230 decs = cpl_malloc(nfiles * sizeof(double));
00231
00232 nvals = 2300;
00233
00234
00235 for (i=0, frame = cpl_frameset_get_first(framelist); frame != NULL ;
00236 i++, frame = cpl_frameset_get_next(framelist)) {
00237 int ra1, ra2, dec1, dec2;
00238 double ra3, dec3;
00239 int nlen;
00240 char isign;
00241
00242 const char * filename = cpl_frame_get_filename(frame);
00243
00244 skip_if (filename == NULL);
00245
00246
00247 if ((in = fopen(filename, "r")) == NULL) {
00248 cpl_msg_error(__func__, "Could not open file number %d (%s)", i+1,
00249 filename);
00250 skip_if (1);
00251 }
00252
00253
00254
00255 fgets(line, 1024, in);
00256
00257 if (sscanf(line, "%d %d %lg %c%d %d %lg ", &ra1, &ra2, &ra3, &isign,
00258 &dec1, &dec2, &dec3) != 7) {
00259 cpl_msg_error(__func__, "Invalid first line in file number %d (%s)",
00260 i+1, filename);
00261 skip_if (1);
00262 }
00263
00264
00265 spectrum = cpl_bivector_new(nvals);
00266 skip_if (visir_bivector_load(spectrum, in));
00267
00268 fclose(in);
00269 in = NULL;
00270
00271 if (i == 0) {
00272 nvals = cpl_bivector_get_size(spectrum);
00273
00274 wls = cpl_malloc(nfiles * nvals * sizeof(double));
00275 vals = cpl_malloc(nfiles * nvals * sizeof(double));
00276 } else if (nvals != cpl_bivector_get_size(spectrum)) {
00277
00278 cpl_msg_error(__func__, "Length of spectrum in file number %d (%s) is "
00279 "different from the previous (with length %d)", i+1,
00280 filename, nvals);
00281 skip_if (1);
00282 }
00283
00284 skip_if (visir_star_convert(line, ra1, ra2, ra3, isign, dec1, dec2,
00285 dec3, cpl_bivector_get_y_data(spectrum),
00286 nvals, &(ras[i]), &(decs[i])));
00287
00288
00289 nlen = snprintf(starnames+i*starnamelen, starnamelen,
00290 qfits_get_base_name(qfits_get_root_name((char*)filename)));
00291 skip_if (nlen < 1);
00292 if (nlen >= starnamelen) {
00293 cpl_msg_error(__func__, "File number %d (%s) has too long (%d) "
00294 "basename for the FITS table (max=%d)", i+1, filename,
00295 nlen, starnamelen);
00296 skip_if(1);
00297 }
00298
00299 memcpy(wls +i*nvals, cpl_bivector_get_x_data(spectrum),
00300 sizeof(double)*nvals);
00301 memcpy(vals+i*nvals, cpl_bivector_get_y_data(spectrum),
00302 sizeof(double)*nvals);
00303
00304 cpl_bivector_delete(spectrum);
00305 spectrum = NULL;
00306
00307 }
00308
00309 skip_if (i != nfiles);
00310
00311
00312 data = cpl_malloc(5*sizeof(void*));
00313 data[0] = starnames;
00314 data[1] = ras;
00315 data[2] = decs;
00316 data[3] = wls;
00317 data[4] = vals;
00318
00319 mindist = visir_star_dist_min(ras, decs, nfiles, &iloc1, &iloc2);
00320
00321 if (mindist < max_radius)
00322 cpl_msg_warning(__func__, "The pair of closest stars is %s (%d) and %s "
00323 "(%d) with the distance: %g",
00324 cpl_frame_get_filename(cpl_frameset_get_frame(framelist,
00325 iloc1)), iloc1,
00326 cpl_frame_get_filename(cpl_frameset_get_frame(framelist,
00327 iloc2)), iloc2,
00328 mindist);
00329
00330
00331 else
00332 cpl_msg_info(__func__, "The pair of closest stars is %s (%d) and %s "
00333 "(%d) with the distance: %g",
00334 cpl_frame_get_filename(cpl_frameset_get_frame(framelist,
00335 iloc1)), iloc1,
00336 cpl_frame_get_filename(cpl_frameset_get_frame(framelist,
00337 iloc2)), iloc2,
00338 mindist);
00339
00340
00341 cpl_msg_info(__func__, "Saving the table with %d rows each with a spectrum "
00342 "length of %d", nfiles, nvals);
00343 if (visir_util_spc_std_cat_save(data, nvals, nfiles, parlist, framelist)) {
00344 cpl_msg_error(__func__, "Could not save products");
00345 skip_if (1);
00346 }
00347
00348 end_skip;
00349
00350 cpl_free(data);
00351 cpl_free(starnames);
00352 cpl_free(ras);
00353 cpl_free(decs);
00354 cpl_free(wls);
00355 cpl_free(vals);
00356
00357 cpl_bivector_delete(spectrum);
00358 if (in) fclose(in);
00359
00360 return cpl_error_get_code();
00361 }
00362
00363
00376
00377 static int visir_util_spc_std_cat_save(
00378 void ** data,
00379 int nvals,
00380 int nfiles,
00381 const cpl_parameterlist * parlist,
00382 cpl_frameset * set)
00383 {
00384 const char * file = RECIPENAME ".fits";
00385 cpl_frame * product_frame;
00386 qfits_header * qheader;
00387 qfits_table * table;
00388 qfits_col * col;
00389
00390
00391 visir_assure_code(data, CPL_ERROR_NULL_INPUT);
00392 visir_assure_code(parlist, CPL_ERROR_NULL_INPUT);
00393 visir_assure_code(set, CPL_ERROR_NULL_INPUT);
00394
00395 visir_assure_code(cpl_parameterlist_get_size(parlist) == 0,
00396 CPL_ERROR_UNSUPPORTED_MODE);
00397
00398
00399 cpl_msg_info(__func__, "Writing %s" , file);
00400
00401
00402 qheader = qfits_table_prim_header_default();
00403 qfits_header_add(qheader, "INSTRUME", "VISIR", NULL, NULL);
00404 qfits_header_add(qheader, "PIPEFILE", (char*)file, NULL, NULL);
00405 qfits_header_add(qheader, "HIERARCH ESO PRO TYPE", "REDUCED", NULL, NULL);
00406 qfits_header_add(qheader, "HIERARCH ESO PRO CATG",
00407 VISIR_SPEC_STD_CAT_PROCATG, NULL, NULL);
00408 qfits_header_add(qheader, "HIERARCH ESO PRO STATUS", "Ok", NULL, NULL);
00409 qfits_header_add(qheader, "HIERARCH ESO PRO REC1 ID",
00410 (char*)recipename, NULL, NULL);
00411 qfits_header_add(qheader, "HIERARCH ESO PRO REC1 DRS ID", "CPL", NULL,NULL);
00412 qfits_header_add(qheader, "HIERARCH ESO PRO DATE",
00413 qfits_get_date_iso8601(), NULL, NULL);
00414
00415
00416 table = qfits_table_new((char*)file, QFITS_BINTABLE, -1, 5, nfiles);
00417 col = table->col;
00418 qfits_col_fill(col, starnamelen, 0, sizeof(char), TFITS_BIN_TYPE_A, "STARS",
00419 " ", " ", " ", 0, 0.0, 0, 1.0, 0);
00420 col++;
00421 qfits_col_fill(col, 1, 0, sizeof(double), TFITS_BIN_TYPE_D, "RA", " ",
00422 " ", " ", 0, 0.0, 0, 1.0, starnamelen);
00423 col++;
00424 qfits_col_fill(col, 1, 0, sizeof(double), TFITS_BIN_TYPE_D, "DEC", " ",
00425 " ", " ", 0, 0.0, 0, 1.0, starnamelen+sizeof(double));
00426 col++;
00427 qfits_col_fill(col, nvals, 0, sizeof(double), TFITS_BIN_TYPE_D,
00428 "WAVELENGTHS", " ", " ", " ", 0, 0.0, 0, 1.0,
00429 starnamelen+2*sizeof(double));
00430 col++;
00431 qfits_col_fill(col, nvals, 0, sizeof(double), TFITS_BIN_TYPE_D,
00432 "MODEL_FLUX", " ", " ", " ", 0, 0.0, 0, 1.0,
00433 starnamelen+2*sizeof(double)+nvals*sizeof(double));
00434
00435
00436 if (qfits_save_table_hdrdump((void**)data, table, qheader) == -1) {
00437 cpl_msg_error(__func__, "Could save the FITS file %s", file);
00438 qfits_header_destroy(qheader);
00439 qfits_table_close(table);
00440 visir_assure_code(0, CPL_ERROR_FILE_IO);
00441 }
00442 qfits_header_destroy(qheader);
00443 qfits_table_close(table);
00444
00445
00446 product_frame = cpl_frame_new();
00447 cpl_frame_set_filename(product_frame, file);
00448 cpl_frame_set_tag(product_frame, VISIR_SPEC_STD_CAT_PROCATG);
00449 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_TABLE);
00450 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
00451 cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
00452
00453
00454 cpl_frameset_insert(set, product_frame);
00455
00456 return cpl_error_get_code();
00457 }