NACO Pipeline Reference Manual  4.4.0
naco_util_img_std_cat.c
1 /* $Id: naco_util_img_std_cat.c,v 1.13 2013-03-12 08:03:07 llundin Exp $
2  *
3  * This file is part of the NACO Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: llundin $
23  * $Date: 2013-03-12 08:03:07 $
24  * $Revision: 1.13 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <string.h>
37 
38 #include "naco_recipe.h"
39 
40 #include <irplib_stdstar.h>
41 #include <irplib_wcs.h>
42 
43 /*-----------------------------------------------------------------------------
44  Defines
45  -----------------------------------------------------------------------------*/
46 
47 #define NFILTERS 8
48 
49 #define RECIPE_STRING "naco_util_img_std_cat"
50 
51 /* Largest seen so far is 74 */
52 #ifndef NACO_ASCII_MAXLINELEN
53 #define NACO_ASCII_MAXLINELEN 1024
54 #endif
55 
56 /*-----------------------------------------------------------------------------
57  Private Functions prototypes
58  -----------------------------------------------------------------------------*/
59 
60 NACO_RECIPE_DEFINE(naco_util_img_std_cat,
61  0,
62  "Standard star catalog creation",
63  RECIPE_STRING " -- Standard star catalog creation.\n"
64  "Convert ASCII-file(s) to a FITS standard star catalog.\n"
65  "This recipe generates a FITS standard star catalog for "
66  "imaging from one or more ASCII-files.\n"
67  "Each line in the text file must have "
68  "4+" IRPLIB_STRINGIFY(NFILTERS) " fields "
69  "separated by white-space.\n"
70  "The first field is the star name, e.g. 'HD108903' which "
71  "will be stored in a "
72  "table column labeled '" IRPLIB_STDSTAR_STAR_COL "'.\n"
73  "The next field is the Right Ascension [degrees] which will "
74  "be stored in a table column labeled '" IRPLIB_STDSTAR_RA_COL
75  "'.\n"
76  "The Right Ascension must be non-negative and less than "
77  "360.\n"
78  "The next field is the Declination [degrees] which will be "
79  "stored in a table column labeled '" IRPLIB_STDSTAR_DEC_COL
80  "'.\n"
81  "The Declination must be within the range -90 to 90.\n"
82  "The next field is the spectral type which will be "
83  "stored in a table column labeled '" IRPLIB_STDSTAR_TYPE_COL
84  "'.\n"
85  "The " IRPLIB_STRINGIFY(NFILTERS) " next fields are the "
86  "magnitudes for the " IRPLIB_STRINGIFY(NFILTERS) " supported "
87  "image filters.\n"
88  "Unknown magnitudes must be indicated by the "
89  "value " IRPLIB_STRINGIFY(IRPLIB_STDSTAR_NOMAG) ".\n"
90  "The filename (without path) of the ASCII file will for "
91  "each star be added in a table column labeled 'CAT_NAME'.\n"
92  "The " IRPLIB_STRINGIFY(NFILTERS) " filter names are "
93  "hard-coded in the recipe.\n"
94  "\n"
95  "Lines beginning with a hash (#) are treated as comments.\n"
96  "\n"
97  "The files listed in the Set Of Frames (sof-file) "
98  "must be tagged:\n"
99  "NACO-ASCII-file " NACO_IMG_STD_ASCII "\n");
100 
101 static IRPLIB_UTIL_SET_ROW(naco_util_img_std_set_row);
102 static IRPLIB_UTIL_CHECK(naco_util_img_std_check);
103 
104 static cpl_error_code naco_util_img_std_cat_cmp(const cpl_table *,
105  cpl_boolean *,
106  double, double,
107  const char *,
108  const char *,
109  const char *,
110  int,
111  const double *, double, double);
112 
113 static double magmin = IRPLIB_STDSTAR_NOMAG;
114 static double magmax = -30.0;
115 static const char * filters[] = {"J","H", "K", "Ks", "L", "M", "Lp", "Mp"};
116 
117 /*-----------------------------------------------------------------------------
118  Functions code
119  -----------------------------------------------------------------------------*/
120 
121 /*----------------------------------------------------------------------------*/
128 /*----------------------------------------------------------------------------*/
129 static int naco_util_img_std_cat(cpl_frameset * framelist,
130  const cpl_parameterlist * parlist)
131 {
132  irplib_framelist * allframes = NULL;
133  irplib_framelist * rawframes = NULL;
134  cpl_frameset * useframes = NULL;
135  cpl_table * self = NULL;
136  int ifilt;
137 
138 
139  bug_if(sizeof(filters) != NFILTERS * sizeof(char*));
140 
141  /* Identify the RAW and CALIB frames in the input frameset */
142  skip_if (naco_dfs_set_groups(framelist));
143 
144  /* FIXME: Using framelists is the simplest way to extract the relevant
145  frames :-( */
146  allframes = irplib_framelist_cast(framelist);
147  bug_if(allframes == NULL);
148 
149  rawframes = irplib_framelist_extract(allframes, NACO_IMG_STD_ASCII);
150  skip_if(rawframes == NULL);
151 
152  irplib_framelist_empty(allframes);
153 
154  useframes = irplib_frameset_cast(rawframes);
155  bug_if(allframes == NULL);
156 
157  /* At least one row per file */
158  self = cpl_table_new(irplib_framelist_get_size(rawframes));
159 
160  irplib_framelist_empty(rawframes);
161 
162 
163  /* Create the table columns - with units */
164  bug_if (cpl_table_new_column(self, IRPLIB_STDSTAR_STAR_COL,
165  CPL_TYPE_STRING));
166  bug_if (cpl_table_new_column(self, IRPLIB_STDSTAR_TYPE_COL,
167  CPL_TYPE_STRING));
168  bug_if (cpl_table_new_column(self, "CAT_NAME", CPL_TYPE_STRING));
169  bug_if (cpl_table_new_column(self, IRPLIB_STDSTAR_RA_COL,
170  CPL_TYPE_DOUBLE));
171  bug_if (cpl_table_new_column(self, IRPLIB_STDSTAR_DEC_COL,
172  CPL_TYPE_DOUBLE));
173 
174  bug_if(cpl_table_set_column_unit(self, IRPLIB_STDSTAR_RA_COL,
175  "Degrees"));
176  bug_if(cpl_table_set_column_unit(self, IRPLIB_STDSTAR_DEC_COL,
177  "Degrees"));
178  for (ifilt=0 ; ifilt < NFILTERS ; ifilt++) {
179  bug_if (cpl_table_new_column(self, filters[ifilt], CPL_TYPE_DOUBLE));
180  bug_if(cpl_table_set_column_unit(self, filters[ifilt], "Magnitude"));
181  }
182 
183  skip_if(irplib_dfs_table_convert(self, framelist, useframes,
184  NACO_ASCII_MAXLINELEN, '#', NULL,
185  NACO_IMG_STD_CAT, parlist, RECIPE_STRING,
186  NULL, NULL, NULL, "NACO", naco_pipe_id,
187  naco_util_img_std_set_row,
188  naco_util_img_std_check));
189 
190  end_skip;
191 
192  cpl_table_delete(self);
193  cpl_frameset_delete(useframes);
194  irplib_framelist_delete(allframes);
195  irplib_framelist_delete(rawframes);
196 
197  return cpl_error_get_code();
198 }
199 
200 /*----------------------------------------------------------------------------*/
220 /*----------------------------------------------------------------------------*/
221 static cpl_error_code naco_util_img_std_cat_cmp(const cpl_table * self,
222  cpl_boolean * puse,
223  double ra,
224  double dec,
225  const char * sname,
226  const char * stype,
227  const char * cat_name,
228  int irow,
229  const double * mags,
230  double dist_max,
231  double mag_tol)
232 {
233 
234  const int nfilters = NFILTERS;
235  int j;
236 
237  *puse = CPL_FALSE;
238 
239  bug_if(self == NULL);
240  bug_if(filters == NULL);
241  bug_if(mags == NULL);
242  bug_if(sname == NULL);
243  bug_if(stype == NULL);
244  bug_if(cat_name == NULL);
245 
246  for (j = 0; j < irow; j++) {
247  const double raj
248  = cpl_table_get_double(self, IRPLIB_STDSTAR_RA_COL, j, NULL);
249  const double decj
250  = cpl_table_get_double(self, IRPLIB_STDSTAR_DEC_COL, j, NULL);
251  double dist;
252  double mag_max_found = 0;
253  int i;
254 
255  if (fabs(decj - dec) > dist_max) continue;
256 
257  dist = irplib_wcs_great_circle_dist(ra, dec, raj, decj);
258 
259  if (dist > dist_max) continue;
260 
261  for (i=0 ; i < nfilters ; i++) {
262  const double mag
263  = cpl_table_get_double(self, filters[i], j, NULL);
264  double mag_dif;
265 
266  if (mags[i] > IRPLIB_STDSTAR_LIMIT) continue;
267 
268  if (mag > IRPLIB_STDSTAR_LIMIT) break;
269 
270  mag_dif = fabs(mags[i] - mag);
271 
272  if (mag_dif > mag_tol) break;
273 
274  if (mag_dif > mag_max_found) mag_max_found = mag_dif;
275  }
276 
277 
278  if (i == nfilters) {
279  cpl_msg_debug(cpl_func, "Skipping star: '%s' at table row %d in "
280  "catalogue '%s' and the star %d have identical "
281  "magnitudes (within %g <= %g) and a distance: "
282  "%g <= %g", sname, 1+irow, cat_name, j+1,
283  mag_max_found, mag_tol, dist, dist_max);
284  if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
285  cpl_table_dump(self, j, 1, stdout);
286  break;
287  }
288  if (dist > 0.0) {
289  cpl_msg_info(cpl_func, "The stars at rows %d and %d ('%s' in "
290  "catalogue '%s') have different magnitudes, but a "
291  "distance: %g <= %g",
292  1+j, 1+irow, sname, cat_name, dist, dist_max);
293  } else {
294  cpl_msg_info(cpl_func, "The stars at rows %d and %d ('%s' in "
295  "catalogue '%s') have different magnitudes, but "
296  "identical coordinates",
297  1+j, 1+irow, sname, cat_name);
298  }
299 #if 0
300  cpl_table_dump(self, j, 1, stderr);
301  for (i=0 ; i < nfilters ; i++) {
302  const double mag
303  = cpl_table_get_double(self, filters[i], j, NULL);
304  const double mag_dif = fabs(mags[i] - mag);
305 
306  if (mag_dif > mag_tol)
307  cpl_msg_warning(cpl_func, "%s(%d): |%g - %g| = %g > %g",
308  filters[i], i, mag, mags[i], mag_dif, mag_tol);
309  }
310 #endif
311  }
312 
313  if (j == irow) *puse = CPL_TRUE;
314 
315  end_skip;
316 
317  return CPL_ERROR_NONE;
318 
319 }
320 
321 
322 /*----------------------------------------------------------------------------*/
331 /*----------------------------------------------------------------------------*/
332 static
333 cpl_error_code naco_util_img_std_check(cpl_table * self,
334  const cpl_frameset * useframes,
335  const cpl_parameterlist * parlist)
336 {
337 
338  bug_if(0);
339  bug_if(self == NULL);
340  bug_if(parlist == NULL);
341 
342  cpl_msg_info(cpl_func, "Created table of %d stars with "
343  "magnitudes from %g to %g from %d catalogues",
344  (int)cpl_table_get_nrow(self),
345  magmin, magmax, (int)cpl_frameset_get_size(useframes));
346 
347  end_skip;
348 
349  return cpl_error_get_code();
350 }
351 
352 
353 /*----------------------------------------------------------------------------*/
376 /*----------------------------------------------------------------------------*/
377 static cpl_boolean naco_util_img_std_set_row(cpl_table * self,
378  const char * line,
379  int irow,
380  const cpl_frame * rawframe,
381  const cpl_parameterlist * parlist)
382 {
383 
384  /* gcc can only check sscanf()s format when it is a string literal */
385 #define FORMAT "%s %lg %lg %s %lg %lg %lg %lg %lg %lg %lg %lg"
386 
387  char sname[NACO_ASCII_MAXLINELEN];
388  char stype[NACO_ASCII_MAXLINELEN];
389  double mags[NFILTERS];
390  double ra, dec;
391  int nvals;
392  int ifilt;
393  cpl_boolean use = CPL_FALSE;
394 
395  bug_if(0);
396  bug_if(self == NULL);
397  bug_if(line == NULL);
398  bug_if(irow < 0);
399  bug_if(rawframe == NULL);
400  bug_if(parlist == NULL);
401 
402  nvals = sscanf(line, FORMAT,
403  sname, &ra, &dec, stype, &(mags[0]), &(mags[1]), &(mags[2]),
404  &(mags[3]), &(mags[4]), &(mags[5]), &(mags[6]), &(mags[7]));
405 
406  error_if (nvals != NFILTERS+4, CPL_ERROR_BAD_FILE_FORMAT,
407  "Line with length=%u has %d not 4+" IRPLIB_STRINGIFY(NFILTERS)
408  " items formatted: %s", (unsigned)strlen(line), nvals, FORMAT);
409 
410  error_if (ra < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
411  "Negative RA=%g in line %s", ra, line);
412 
413  error_if (ra >=360.0, CPL_ERROR_BAD_FILE_FORMAT,
414  "RA=%g is not less than 360 in line %s", ra, line);
415 
416  error_if (dec < -90.0, CPL_ERROR_BAD_FILE_FORMAT,
417  "DEC=%g is not at least -90 in line %s", dec, line);
418 
419  error_if (dec > 90.0, CPL_ERROR_BAD_FILE_FORMAT,
420  "DEC=%g is not at most 90 in line %s", dec, line);
421 
422  for (ifilt=0 ; ifilt < NFILTERS; ifilt++) {
423  if (mags[ifilt] < IRPLIB_STDSTAR_LIMIT) break;
424  }
425 
426  if (ifilt == NFILTERS) {
427  cpl_msg_debug(cpl_func, "Not setting row without a valid magnitude: "
428  "(%d)", 1+irow);
429  } else {
430  const char * rawfile = cpl_frame_get_filename(rawframe);
431  /* Skip path, if any */
432  const char * cat_name = strrchr(rawfile, '/');
433 
434  cat_name = cat_name ? 1+cat_name : rawfile;
435 
436  bug_if(cat_name == NULL);
437 
438  skip_if(naco_util_img_std_cat_cmp(self, &use, ra, dec, sname,
439  stype, cat_name, irow,
440  mags, 0.25e-4, 1e-6));
441 
442  if (use) {
443  bug_if (cpl_table_set_string(self, IRPLIB_STDSTAR_STAR_COL, irow,
444  sname));
445 
446  bug_if (cpl_table_set_string(self, "CAT_NAME", irow, cat_name));
447 
448  bug_if (cpl_table_set_string(self, IRPLIB_STDSTAR_TYPE_COL, irow,
449  stype));
450 
451  bug_if (cpl_table_set_double(self, IRPLIB_STDSTAR_RA_COL, irow,
452  ra));
453 
454  bug_if (cpl_table_set_double(self, IRPLIB_STDSTAR_DEC_COL, irow,
455  dec));
456 
457  for (ifilt=0 ; ifilt < NFILTERS; ifilt++) {
458  if (mags[ifilt] > 27.0 && mags[ifilt] < IRPLIB_STDSTAR_LIMIT) {
459  /* 27 is about the limit of the UT */
460  cpl_msg_warning(cpl_func, "Setting faint (mag=%g) object "
461  "(Filter-%s) in table row %d", mags[ifilt],
462  filters[ifilt], 1+irow);
463  }
464  if (mags[ifilt] > magmax && mags[ifilt] < IRPLIB_STDSTAR_LIMIT)
465  magmax = mags[ifilt];
466  if (mags[ifilt] < magmin) magmin = mags[ifilt];
467  bug_if(cpl_table_set_double(self, filters[ifilt], irow,
468  mags[ifilt]));
469  }
470  }
471  }
472 
473  end_skip;
474 
475  return use;
476 
477 }
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
cpl_error_code irplib_dfs_table_convert(cpl_table *self, cpl_frameset *allframes, const cpl_frameset *useframes, int maxlinelen, char commentchar, const char *product_name, const char *procatg, const cpl_parameterlist *parlist, const char *recipe_name, const cpl_propertylist *mainlist, const cpl_propertylist *extlist, const char *remregexp, const char *instrume, const char *pipe_id, cpl_boolean(*table_set_row)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *), cpl_error_code(*table_check)(cpl_table *, const cpl_frameset *, const cpl_parameterlist *))
Create a DFS product with one table from one or more (ASCII) file(s)
Definition: irplib_utils.c:860
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.