VIRCAM Pipeline  1.3.4
vircam/vircam_getstds.c
1 /* $Id: vircam_getstds.c,v 1.26 2013-10-15 16:38:52 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: jim $
23  * $Date: 2013-10-15 16:38:52 $
24  * $Revision: 1.26 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <cpl.h>
39 
40 #include <math.h>
41 
42 #include "vircam_mods.h"
43 #include "vircam_utils.h"
44 #include "vircam_wcsutils.h"
45 
46 #define CACHEDIR ".catcache"
47 #define CACHEIND ".catcache/index"
48 #define SZBUF 1024
49 
50 static cpl_table *vircam_2mass_extract(char *path, float ramin, float ramax,
51  float decmin, float decmax);
52 static cpl_table *vircam_ppmxl_extract(char *path, float ramin1, float ramax1,
53  float decmin, float decmax);
54 static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im,
55  float dec1_im, float dec2_im);
56 static void addto_cache(cpl_table *stds, char *catname, float ramin,
57  float ramax, float decmin, float decmax);
58 
61 /*---------------------------------------------------------------------------*/
110 /*---------------------------------------------------------------------------*/
111 
112 extern int vircam_getstds(cpl_propertylist *plist, int cache, char *path,
113  char *catname, cpl_table **stds, int *status) {
114  const char *fctid = "vircam_getstds";
115  double xx1,xx2,yy1,yy2,r,d,xx,yy,*rad,*decd;
116  float ramin,ramax,decmin,decmax,*ra,*dec,*x,*y;
117  cpl_wcs *wcs;
118  int n,i;
119  cpl_propertylist *p;
120 
121  /* Inherited status */
122 
123  *stds = NULL;
124  if (*status != VIR_OK)
125  return(*status);
126 
127  /* See if the catname is OK */
128 
129  if (strcmp(catname,"2mass") && strcmp(catname,"ppmxl")) {
130  cpl_msg_error(fctid,"Catalogue %s not recognised",catname);
131  FATAL_ERROR
132  }
133 
134  /* Get the coverage of the input WCS */
135 
136  (void)vircam_coverage(plist,0,&xx1,&xx2,&yy1,&yy2,status);
137  ramin = (float)xx1;
138  ramax = (float)xx2;
139  decmin = (float)yy1;
140  decmax = (float)yy2;
141 
142  /* If using the cache, then check if for a previously used table */
143 
144  *stds = NULL;
145  if (cache)
146  *stds = check_cache(catname,ramin,ramax,decmin,decmax);
147 
148  /* If there was nothing in the cache (or you didn't use it) then search
149  the standard catalogues */
150 
151  if (*stds == NULL) {
152 
153  /* Read the standards from the catalogue */
154 
155  if (! strcmp(catname,"2mass")) {
156  *stds = vircam_2mass_extract(path,ramin,ramax,decmin,decmax);
157  } else if (! strcmp(catname,"ppmxl")) {
158  *stds = vircam_ppmxl_extract(path,ramin,ramax,decmin,decmax);
159  }
160  if (*stds == NULL) {
161  cpl_msg_error(fctid,"Unable to extract data in %s\n",path);
162  FATAL_ERROR
163  }
164 
165  /* Add this table to the cache if you want to */
166 
167  if (cache)
168  addto_cache(*stds,catname,ramin,ramax,decmin,decmax);
169  }
170 
171  /* If there are no rows in the table, this may be a cause for concern.
172  So add the columns into the table and then set a warning return
173  status */
174 
175  n = (int)cpl_table_get_nrow(*stds);
176  if (n == 0) {
177  cpl_table_new_column(*stds,"xpredict",CPL_TYPE_FLOAT);
178  cpl_table_new_column(*stds,"ypredict",CPL_TYPE_FLOAT);
179  WARN_RETURN
180  }
181 
182  /* Now fill the coordinates in */
183 
184  wcs = cpl_wcs_new_from_propertylist((const cpl_propertylist *)plist);
185  if (cpl_table_get_column_type(*stds,"RA") == CPL_TYPE_FLOAT) {
186  ra = cpl_table_get_data_float(*stds,"RA");
187  dec = cpl_table_get_data_float(*stds,"Dec");
188  x = cpl_malloc(n*sizeof(*x));
189  y = cpl_malloc(n*sizeof(*y));
190  for (i = 0; i < n; i++) {
191  r = (double)ra[i];
192  d = (double)dec[i];
193  vircam_radectoxy(wcs,r,d,&xx,&yy);
194  x[i] = (float)xx;
195  y[i] = (float)yy;
196  }
197  } else {
198  rad = cpl_table_get_data_double(*stds,"RA");
199  decd = cpl_table_get_data_double(*stds,"Dec");
200  x = cpl_malloc(n*sizeof(*x));
201  y = cpl_malloc(n*sizeof(*y));
202  for (i = 0; i < n; i++) {
203  r = rad[i];
204  d = decd[i];
205  vircam_radectoxy(wcs,r,d,&xx,&yy);
206  x[i] = (float)xx;
207  y[i] = (float)yy;
208  }
209  }
210  cpl_wcs_delete(wcs);
211 
212  /* Add the predicted x,y coordinates columns to the table */
213 
214  cpl_table_wrap_float(*stds,x,"xpredict");
215  cpl_table_set_column_unit(*stds,"xpredict","pixels");
216  cpl_table_wrap_float(*stds,y,"ypredict");
217  cpl_table_set_column_unit(*stds,"ypredict","pixels");
218 
219  /* Finally sort this by ypredict */
220 
221  p = cpl_propertylist_new();
222  cpl_propertylist_append_bool(p,"ypredict",0);
223  cpl_table_sort(*stds,p);
224  cpl_propertylist_delete(p);
225 
226  /* Get out of here */
227 
228  GOOD_STATUS
229 }
230 
231 
232 /*---------------------------------------------------------------------------*/
260 /*---------------------------------------------------------------------------*/
261 
262 static cpl_table *vircam_2mass_extract(char *path, float ramin1, float ramax1,
263  float decmin, float decmax) {
264  cpl_table *t,*s,*o;
265  int i,nrows,start,finish,first_index,last_index,irow,init,j;
266  int first_index_ra,last_index_ra,wrap,iwrap;
267  float dectest,ratest,ramin,ramax;
268  char fullname[SZBUF];
269  cpl_array *a;
270  const char *deccol = "Dec";
271  cpl_propertylist *p;
272 
273  /* Create an output table */
274 
275  o = cpl_table_new(0);
276  init = 1;
277 
278  /* Create a cpl array */
279 
280  a = cpl_array_wrap_string((char **)&deccol,1);
281 
282  /* Is there a wrap around problem? */
283 
284  wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
285 
286  /* Loop for each query. If there is a wrap around problem then we need 2
287  queries. If not, then we only need 1 */
288 
289  for (iwrap = 0; iwrap < wrap; iwrap++) {
290  if (wrap == 2) {
291  if (iwrap == 0) {
292  ramin = ramin1 + 360.0;
293  ramax = 360.0;
294  } else {
295  ramin = 0.000001;
296  ramax = ramax1;
297  }
298  } else {
299  ramin = ramin1;
300  ramax = ramax1;
301  }
302 
303  /* Find out where in the index to look */
304 
305  first_index_ra = (int)ramin;
306  last_index_ra = min((int)ramax,359);
307 
308  /* Look at the min and max RA and decide which files need to be
309  opened. */
310 
311  for (i = first_index_ra; i <= last_index_ra; i++) {
312 
313  /* Ok, we've found one that needs opening. Read the file with
314  the relevant CPL call */
315 
316  (void)snprintf(fullname,SZBUF,"%s/npsc%03d.fits",path,i);
317 
318  /* Read the propertylist so that you know how many rows there
319  are in the table */
320 
321  p = cpl_propertylist_load(fullname,1);
322  if (p == NULL) {
323  freetable(o);
324  cpl_array_unwrap(a);
325  return(NULL);
326  }
327  nrows = cpl_propertylist_get_int(p,"NAXIS2");
328  cpl_propertylist_delete(p);
329 
330  /* Load various rows until you find the Dec range that you
331  have specified. First the minimum Dec */
332 
333  start = 0;
334  finish = nrows;
335  first_index = nrows/2;
336  while (finish - start >= 2) {
337  t = cpl_table_load_window(fullname,1,0,a,(cpl_size)first_index,
338  1);
339  dectest = cpl_table_get_float(t,"Dec",0,NULL);
340  cpl_table_delete(t);
341  if (dectest < decmin) {
342  start = first_index;
343  first_index = (first_index + finish)/2;
344  } else {
345  finish = first_index;
346  first_index = (first_index + start)/2;
347  }
348  }
349 
350  /* Load various rows until you find the Dec range that you
351  have specified. Now the maximum Dec */
352 
353  start = first_index;
354  finish = nrows;
355  last_index = start + (finish - start)/2;
356  while (finish - start >= 2) {
357  t = cpl_table_load_window(fullname,1,0,a,(cpl_size)last_index,
358  1);
359  dectest = cpl_table_get_float(t,"Dec",0,NULL);
360  cpl_table_delete(t);
361  if (dectest < decmax) {
362  start = last_index;
363  last_index = (last_index + finish)/2;
364  } else {
365  finish = last_index;
366  last_index = (last_index + start)/2;
367  }
368  }
369  if (last_index < first_index)
370  last_index = first_index;
371 
372  /* Ok now now load all the rows in the relevant dec limits */
373 
374  nrows = last_index - first_index + 1;
375  if ((t = cpl_table_load_window(fullname,1,0,NULL,
376  (cpl_size)first_index,
377  (cpl_size)nrows)) == NULL) {
378  freetable(o);
379  cpl_array_unwrap(a);
380  return(NULL);
381  }
382  cpl_table_unselect_all(t);
383 
384  /* Right, we now know what range of rows to search. Go through
385  these and pick the ones that are in the correct range of RA.
386  If a row qualifies, then 'select' it. */
387 
388  for (j = 0; j < nrows; j++) {
389  ratest = cpl_table_get_float(t,"RA",(cpl_size)j,NULL);
390  if (cpl_error_get_code() != CPL_ERROR_NONE) {
391  cpl_table_delete(t);
392  cpl_array_unwrap(a);
393  freetable(o);
394  return(NULL);
395  }
396  if (ratest >= ramin && ratest <= ramax)
397  cpl_table_select_row(t,(cpl_size)j);
398  }
399 
400  /* Extract the rows that have been selected now and append them
401  onto the output table */
402 
403  s = cpl_table_extract_selected(t);
404  if (init == 1) {
405  cpl_table_copy_structure(o,t);
406  init = 0;
407  }
408  irow = (int)cpl_table_get_nrow(o) + 1;
409  cpl_table_insert(o,s,(cpl_size)irow);
410 
411  /* Tidy up */
412 
413  cpl_table_delete(t);
414  cpl_table_delete(s);
415  }
416  }
417 
418  /* Ok, now just return the table and get out of here */
419 
420  cpl_array_unwrap(a);
421  return(o);
422 }
423 
424 /*---------------------------------------------------------------------------*/
452 /*---------------------------------------------------------------------------*/
453 
454 static cpl_table *vircam_ppmxl_extract(char *path, float ramin1, float ramax1,
455  float decmin, float decmax) {
456  cpl_table *t,*s,*o;
457  int i,nrows,start,finish,first_index,last_index,irow,init,j;
458  int first_index_ra,last_index_ra,wrap,iwrap;
459  float dectest,ratest,ramin,ramax;
460  char fullname[SZBUF];
461  cpl_array *a;
462  const char *deccol = "Dec";
463  cpl_propertylist *p;
464 
465  /* Create an output table */
466 
467  o = cpl_table_new(0);
468  init = 1;
469 
470  /* Create a cpl array */
471 
472  a = cpl_array_wrap_string((char **)&deccol,1);
473 
474  /* Is there a wrap around problem? */
475 
476  wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
477 
478  /* Loop for each query. If there is a wrap around problem then we need 2
479  queries. If not, then we only need 1 */
480 
481  for (iwrap = 0; iwrap < wrap; iwrap++) {
482  if (wrap == 2) {
483  if (iwrap == 0) {
484  ramin = ramin1 + 360.0;
485  ramax = 360.0;
486  } else {
487  ramin = 0.000001;
488  ramax = ramax1;
489  }
490  } else {
491  ramin = ramin1;
492  ramax = ramax1;
493  }
494 
495  /* Find out where in the index to look */
496 
497  first_index_ra = (int)ramin;
498  last_index_ra = min((int)ramax,359);
499 
500  /* Look at the min and max RA and decide which files need to be
501  opened. */
502 
503  for (i = first_index_ra; i <= last_index_ra; i++) {
504 
505  /* Ok, we've found one that needs opening. Read the file with
506  the relevant CPL call */
507 
508  (void)snprintf(fullname,SZBUF,"%s/nppmxl%03d.fits",path,i);
509 
510  /* Read the propertylist so that you know how many rows there
511  are in the table */
512 
513  p = cpl_propertylist_load(fullname,1);
514  if (p == NULL) {
515  freetable(o);
516  cpl_array_unwrap(a);
517  return(NULL);
518  }
519  nrows = cpl_propertylist_get_int(p,"NAXIS2");
520  cpl_propertylist_delete(p);
521 
522  /* Load various rows until you find the Dec range that you
523  have specified. First the minimum Dec */
524 
525  start = 0;
526  finish = nrows;
527  first_index = nrows/2;
528  while (finish - start >= 2) {
529  t = cpl_table_load_window(fullname,1,0,a,(cpl_size)first_index,
530  1);
531  dectest = cpl_table_get_double(t,"Dec",0,NULL);
532  cpl_table_delete(t);
533  if (dectest < decmin) {
534  start = first_index;
535  first_index = (first_index + finish)/2;
536  } else {
537  finish = first_index;
538  first_index = (first_index + start)/2;
539  }
540  }
541 
542  /* Load various rows until you find the Dec range that you
543  have specified. Now the maximum Dec */
544 
545  start = first_index;
546  finish = nrows;
547  last_index = start + (finish - start)/2;
548  while (finish - start >= 2) {
549  t = cpl_table_load_window(fullname,1,0,a,(cpl_size)last_index,
550  1);
551  dectest = cpl_table_get_double(t,"Dec",0,NULL);
552  cpl_table_delete(t);
553  if (dectest < decmax) {
554  start = last_index;
555  last_index = (last_index + finish)/2;
556  } else {
557  finish = last_index;
558  last_index = (last_index + start)/2;
559  }
560  }
561  if (last_index < first_index)
562  last_index = first_index;
563 
564  /* Ok now now load all the rows in the relevant dec limits */
565 
566  nrows = last_index - first_index + 1;
567  if ((t = cpl_table_load_window(fullname,1,0,NULL,
568  (cpl_size)first_index,
569  (cpl_size)nrows)) == NULL) {
570  freetable(o);
571  cpl_array_unwrap(a);
572  return(NULL);
573  }
574  cpl_table_unselect_all(t);
575 
576  /* Right, we now know what range of rows to search. Go through
577  these and pick the ones that are in the correct range of RA.
578  If a row qualifies, then 'select' it. */
579 
580  for (j = 0; j < nrows; j++) {
581  ratest = cpl_table_get_double(t,"RA",(cpl_size)j,NULL);
582  if (cpl_error_get_code() != CPL_ERROR_NONE) {
583  cpl_table_delete(t);
584  cpl_array_unwrap(a);
585  freetable(o);
586  return(NULL);
587  }
588  if (ratest >= ramin && ratest <= ramax)
589  cpl_table_select_row(t,(cpl_size)j);
590  }
591 
592  /* Extract the rows that have been selected now and append them
593  onto the output table */
594 
595  s = cpl_table_extract_selected(t);
596  if (init == 1) {
597  cpl_table_copy_structure(o,t);
598  init = 0;
599  }
600  irow = (int)cpl_table_get_nrow(o) + 1;
601  cpl_table_insert(o,s,(cpl_size)irow);
602 
603  /* Tidy up */
604 
605  cpl_table_delete(t);
606  cpl_table_delete(s);
607  }
608  }
609 
610  /* Ok, now just return the table and get out of here */
611 
612  cpl_array_unwrap(a);
613  return(o);
614 }
615 
616 /*---------------------------------------------------------------------------*/
644 /*---------------------------------------------------------------------------*/
645 
646 static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im,
647  float dec1_im, float dec2_im) {
648  int wrap1,wrap2;
649  FILE *fd;
650  char fname[BUFSIZ],catname2[SZBUF],cat_cache[SZBUF];
651  float best,ra1_cat,ra2_cat,dec1_cat,dec2_cat,d1,d2,fra,fdec,ftot;
652  cpl_table *out_cat;
653 
654  /* Open the index file. NB the path and file name are hardcoded */
655 
656  fd = fopen(CACHEIND,"r");
657  if (fd == NULL)
658  return(NULL);
659 
660  /* Check to see if there is wrap around in the coordinates */
661 
662  wrap1 = (ra1_im < 0.0 ? 1 : 0);
663 
664  /* Now see if you have any matching entries */
665 
666  best = 0.0;
667  while (fscanf(fd,"%s %s %g %g %g %g",fname,catname2,&ra1_cat,&ra2_cat,
668  &dec1_cat,&dec2_cat) != EOF) {
669  wrap2 = (ra1_cat < 0.0 ? 1 : 0);
670  if (wrap1 != wrap2)
671  continue;
672  if (strcmp(catname,catname2))
673  continue;
674 
675  /* Check to see if there is at least some overlap */
676 
677  if (!(((ra1_im >= ra1_cat && ra1_im <= ra2_cat) ||
678  (ra2_im >= ra1_cat && ra2_im <= ra2_cat)) &&
679  ((dec1_im >= dec1_cat && dec1_im <= dec2_cat) ||
680  (dec2_im >= dec1_cat && dec2_im <= dec2_cat))))
681  continue;
682 
683  /* Work out exactly how much there is in each coordinate */
684 
685  d1 = max(0.0,ra1_cat-ra1_im);
686  d2 = max(0.0,ra2_im-ra2_cat);
687  fra = 1.0 - (d1 + d2)/(ra2_im - ra1_im);
688  d1 = max(0.0,dec1_cat-dec1_im);
689  d2 = max(0.0,dec2_im-dec2_cat);
690  fdec = 1.0 - (d1 + d2)/(dec2_im - dec1_im);
691  ftot = fra*fdec;
692 
693  /* Keep track of which is the best one */
694 
695  if (ftot > best) {
696  snprintf(cat_cache,SZBUF,"%s/%s",CACHEDIR,fname);
697  best = ftot;
698  }
699  }
700  fclose(fd);
701 
702  /* Return a bad status if there isn't sufficient overlap */
703 
704  if (best < 0.9)
705  return(NULL);
706 
707  /* If there is enough overlap, then try and read the FITS table. If it
708  reads successfully, then return the table pointer */
709 
710  out_cat = cpl_table_load(cat_cache,1,0);
711  return(out_cat);
712 }
713 
714 /*---------------------------------------------------------------------------*/
740 /*---------------------------------------------------------------------------*/
741 
742 static void addto_cache(cpl_table *stds, char *catname, float ramin,
743  float ramax, float decmin, float decmax) {
744  FILE *fd;
745  char newname[SZBUF];
746  int i;
747 
748  /* Check to see if the cache directory exists. If it doesn't, then create
749  it. */
750 
751  if (access(CACHEDIR,0) != 0)
752  mkdir(CACHEDIR,0755);
753 
754  /* Open the index file with 'append' access */
755 
756  fd = fopen(CACHEIND,"a");
757 
758  /* Check the files in the directory to get a number that isn't already
759  being used */
760 
761  i = 0;
762  while (i >= 0) {
763  i++;
764  snprintf(newname,SZBUF,"%s/cch_%08d",CACHEDIR,i);
765  if (access(newname,F_OK) != 0)
766  break;
767  }
768 
769  /* Now write the current entry and make a copy of the file into the
770  directory */
771 
772  snprintf(newname,SZBUF,"%s/cch_%08d",CACHEDIR,i);
773  cpl_table_save(stds,NULL,NULL,newname,CPL_IO_DEFAULT);
774  snprintf(newname,SZBUF,"cch_%08d",i);
775  if (cpl_error_get_code() == CPL_ERROR_NONE)
776  fprintf(fd, "%s %s %g %g %g %g\n",newname,catname,ramin-0.0005,
777  ramax+0.0005,decmin-0.0005,decmax+0.0005);
778  fclose(fd);
779 }
780 
784 /*
785 
786 $Log: not supported by cvs2svn $
787 Revision 1.25 2012/01/15 17:40:09 jim
788 Minor modifications to take into accout the changes in cpl API for v6
789 
790 Revision 1.24 2012/01/04 08:57:09 jim
791 Renamed cache directories
792 
793 Revision 1.23 2010/07/13 11:16:50 jim
794 A few changes to deal with compiler whinges
795 
796 Revision 1.22 2010/06/03 12:15:31 jim
797 A few mods to get rid of compiler warnings
798 
799 Revision 1.21 2008/05/06 08:40:10 jim
800 Modified to use cpl_wcs interface
801 
802 Revision 1.20 2007/10/25 17:34:00 jim
803 Modified to remove lint warnings
804 
805 Revision 1.19 2007/10/19 09:25:09 jim
806 Fixed problems with missing includes
807 
808 Revision 1.18 2007/10/19 06:55:06 jim
809 Modifications made to use new method for directing the recipes to the
810 standard catalogues using the sof
811 
812 Revision 1.17 2007/10/15 12:50:53 jim
813 Modified to read new version of 2mass catalogue files
814 
815 Revision 1.16 2007/03/29 12:19:39 jim
816 Little changes to improve documentation
817 
818 Revision 1.15 2007/03/01 12:42:41 jim
819 Modified slightly after code checking
820 
821 Revision 1.14 2007/02/25 06:34:20 jim
822 Plugged memory leak
823 
824 Revision 1.13 2007/01/17 23:54:00 jim
825 Plugged some memory leaks
826 
827 Revision 1.12 2006/12/18 17:14:17 jim
828 Another tidy of some error messages
829 
830 Revision 1.11 2006/12/18 16:41:47 jim
831 Added bit to check for the existence of the index file rather than asking cpl
832 to do that check with loading the table
833 
834 Revision 1.10 2006/12/18 12:51:20 jim
835 Tightened up some of the error reporting
836 
837 Revision 1.9 2006/12/15 12:03:27 jim
838 Fixed bug in 2mass_extract where index was offset by -1
839 
840 Revision 1.8 2006/11/27 12:07:22 jim
841 Argument list now contains catname. Modified caching routines to take this
842 into account.
843 
844 Revision 1.7 2006/08/11 12:45:41 jim
845 Modified to use wcslib
846 
847 Revision 1.6 2006/07/04 09:19:05 jim
848 replaced all sprintf statements with snprintf
849 
850 Revision 1.5 2006/06/08 14:50:09 jim
851 Initialised output table to NULL and fixed a problem in check_cache that
852 resets the cpl error code
853 
854 Revision 1.4 2006/03/23 21:18:47 jim
855 Minor changes mainly to comment headers
856 
857 Revision 1.3 2006/03/22 13:58:31 jim
858 Cosmetic fixes to keep lint happy
859 
860 Revision 1.2 2006/01/23 16:05:33 jim
861 tidied up error handling
862 
863 Revision 1.1 2006/01/23 10:31:56 jim
864 New file
865 
866 
867 */
void vircam_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x, double *y)
int vircam_getstds(cpl_propertylist *plist, int cache, char *path, char *catname, cpl_table **stds, int *status)
Get a table of standard stars that appear on an image from a catalogue.
int vircam_coverage(cpl_propertylist *plist, int fudge, double *ra1, double *ra2, double *dec1, double *dec2, int *status)