VIRCAM Pipeline 2.3.15
casu_getstds.c
1/* $Id: casu_getstds.c,v 1.7 2015/11/27 12:06:41 jim Exp $
2 *
3 * This file is part of the CASU Pipeline utilities
4 * Copyright (C) 2015 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jim $
23 * $Date: 2015/11/27 12:06:41 $
24 * $Revision: 1.7 $
25 * $Name: $
26 */
27
28/* Includes */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#ifndef _POSIX_C_SOURCE
35#define _POSIX_C_SOURCE 200112L
36#endif
37
38#ifndef _XOPEN_SOURCE
39#define _XOPEN_SOURCE 500 /* posix 2001, mkstemp */
40#endif
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <sys/stat.h>
45#include <sys/types.h>
46#include <sys/socket.h>
47#include <netdb.h>
48#include <netinet/in.h>
49#include <fcntl.h>
50#include <ctype.h>
51#include <assert.h>
52#include <errno.h>
53#include <string.h>
54#include <libgen.h>
55
56#include <unistd.h>
57#include <string.h>
58#include <cpl.h>
59
60#include <math.h>
61
62#include "casu_mods.h"
63#include "catalogue/casu_utils.h"
64#include "catalogue/casu_wcsutils.h"
65
66#define CACHEDIR ".catcache"
67#define CACHEIND ".catcache/index"
68#define SZBUF 1024
69
70#define CDS "vizier.cds.unistra.fr"
71#define BUFMAX 32768
72#define PORT 80
73
74static cpl_table *casu_2mass_extract(char *path, float ramin, float ramax,
75 float decmin, float decmax);
76static cpl_table *casu_ppmxl_extract(char *path, float ramin1, float ramax1,
77 float decmin, float decmax);
78static cpl_table *casu_apass_extract(char *path, float ramin1, float ramax1,
79 float decmin, float decmax);
80static cpl_table *casu_local_extract(char *path, float ramin1, float ramax1,
81 float decmin, float decmax);
82static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im,
83 float dec1_im, float dec2_im, char *cacheloc);
84static void addto_cache(cpl_table *stds, char *catname, float ramin,
85 float ramax, float decmin, float decmax,
86 char *cacheloc);
87static char *form_request(float ra, float dec, float dra, float ddec,
88 float equinox, const char *catid);
89static char *url_encode(char *instring);
90static int connect_site(const char *site, int *sock);
91static int send_request(int sock, char *req_string, int isbin);
92static int get_response(int soc, cpl_table **outtab);
93
96static void calculate_magerr(cpl_table* stds, const char* magerr, const char* flux, const char* fluxerr)
97{
98 const double k = 1.086;
99 cpl_table_duplicate_column(stds, magerr, stds, fluxerr);
100 cpl_table_divide_columns(stds, magerr, flux);
101 cpl_table_multiply_scalar(stds, magerr, k);
102}
103
104/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167extern int casu_getstds(cpl_propertylist *plist, int cache, char *path,
168 char *catname, int cdssearch, char *cacheloc,
169 cpl_table **stds, int *status) {
170 const char *fctid = "casu_getstds";
171 double xx1,xx2,yy1,yy2,r,d,xx,yy,*rad,*decd,dra,ddec;
172 float ramin,ramax,decmin,decmax,*ra,*dec,*x,*y,ramid,decmid;
173 cpl_wcs *wcs;
174 int n,i,sock;
175 cpl_propertylist *p;
176 char *req_string,catname2[64],*cdscatname,*cdscatid,*path2;
177 int isbin = (cdssearch > 6 ? 1 : 0);
178
179 /* Inherited status */
180
181 *stds = NULL;
182 if (*status != CASU_OK)
183 return(*status);
184 if (plist == NULL)
185 FATAL_ERROR
186
187 /* Get the coverage of the input WCS */
188
189 (void)casu_coverage(plist,0,&xx1,&xx2,&yy1,&yy2,status);
190 ramin = (float)xx1;
191 ramax = (float)xx2;
192 decmin = (float)yy1;
193 decmax = (float)yy2;
194 dra = ramax - ramin;
195 ddec = decmax - decmin;
196 ramid = 0.5*(ramax+ramin);
197 decmid = 0.5*(decmax+decmin);
198
199 cpl_msg_info(fctid, "Searching catalogue %d, RA/Dec range [%f:%f, %f:%f]", cdssearch, ramin, ramax, decmin, decmax);
200
201 /* If using the cache, then check if for a previously used table */
202
203 cdscatid = NULL;
204 if (cdssearch > 0) {
205 if (casu_getstds_cdslist(cdssearch,&cdscatname,&cdscatid,status) !=
206 CASU_OK)
207 return(*status);
208 (void)strcpy(catname2,cdscatname);
209 freespace(cdscatname);
210 } else {
211 (void)strcpy(catname2,catname);
212 }
213 *stds = NULL;
214 if (cache)
215 *stds = check_cache(catname2,ramin,ramax,decmin,decmax,cacheloc);
216
217 /* If there was nothing in the cache (or you didn't use it) then search
218 the standard catalogues */
219
220 if (*stds == NULL) {
221
222 /* Read the standards from local catalogues */
223
224 if (cdssearch == 0) {
225 cpl_msg_info(fctid, "Reading local catalogue");
226
227 path2 = cpl_strdup(path);
228 if (! strcmp(catname2,"casu_2mass")) {
229 *stds = casu_2mass_extract(dirname(path2),ramin,ramax,decmin,
230 decmax);
231 } else if (! strcmp(catname2,"casu_ppmxl")) {
232 *stds = casu_ppmxl_extract(dirname(path2),ramin,ramax,decmin,
233 decmax);
234 } else if (! strcmp(catname2,"casu_apass")) {
235 *stds = casu_apass_extract(dirname(path2),ramin,ramax,decmin,
236 decmax);
237 } else {
238 *stds = casu_local_extract(path2,ramin,ramax,decmin,decmax);
239 }
240 cpl_free(path2);
241 if (*stds == NULL) {
242 cpl_msg_error(fctid,"Unable to extract data in %s",path);
243 FATAL_ERROR
244 }
245
246 /* Read the standards from CDS */
247
248 } else {
249 cpl_msg_info(fctid, "Requesting catalogue data from CDS");
250
251 req_string = form_request(ramid,decmid,dra,ddec,2000.0,
252 cdscatid);
253 freespace(cdscatid);
254
255 /* Now make the connection to the site */
256
257 if (connect_site(CDS,&sock) != CASU_OK) {
258 cpl_msg_warning(fctid,"Couldn't connect to CDS");
259 FATAL_ERROR
260 }
261
262 /* Send the request to the site */
263
264 if (send_request(sock,req_string,isbin) != CASU_OK) {
265 cpl_msg_warning(fctid,"Couldn't send request to site CDS");
266 FATAL_ERROR
267 }
268
269 /* Get the response from the the server and write it to the
270 output table */
271
272 if (get_response(sock,stds) != CASU_OK) {
273 cpl_msg_warning(fctid,"Error receiving info from site CDS");
274 FATAL_ERROR
275 }
276
277 /* Close up the connection */
278
279 close(sock);
280
281 /* Do some modifications to the table */
282
283 if (cpl_table_has_column(*stds, "RAJ2000")) {
284 cpl_table_name_column(*stds, "RAJ2000", "RA");
285 } else {
286 cpl_table_duplicate_column(*stds, "RA", *stds, "_RAJ2000");
287 }
288 if (cpl_table_has_column(*stds, "DEJ2000")) {
289 cpl_table_name_column(*stds, "DEJ2000", "Dec");
290 } else {
291 cpl_table_duplicate_column(*stds, "Dec", *stds, "_DEJ2000");
292 }
293
294 /* Calculate mag errors for the Gaia syntphot catalog */
295 if (cdssearch == 8) {
296 cpl_table_duplicate_column(*stds, "DEC", *stds, "Dec");
297 calculate_magerr(*stds, "ERR_Umag", "FU", "e_FU");
298 calculate_magerr(*stds, "ERR_Bmag", "FB", "e_FB");
299 calculate_magerr(*stds, "ERR_Vmag", "FV", "e_FV");
300 calculate_magerr(*stds, "ERR_Rmag", "FR", "e_FR");
301 calculate_magerr(*stds, "ERR_Imag", "FI", "e_FI");
302 cpl_table_new_column(*stds, "OBJECT", CPL_TYPE_STRING);
303 }
304 }
305
306 /* Add this table to the cache if you want to */
307
308 if (cache)
309 addto_cache(*stds,catname2,ramin,ramax,decmin,decmax,cacheloc);
310 } else {
311 freespace(cdscatid);
312 }
313
314 n = (int)cpl_table_get_nrow(*stds);
315 cpl_msg_info(fctid, "Found %d stars in catalogue", n);
316
317 /* If there are no rows in the table, this may be a cause for concern.
318 So add the columns into the table and then set a warning return
319 status */
320
321 if (n == 0) {
322 cpl_table_new_column(*stds,"xpredict",CPL_TYPE_FLOAT);
323 cpl_table_new_column(*stds,"ypredict",CPL_TYPE_FLOAT);
324 WARN_RETURN
325 }
326
327 if (cdssearch == 8) {
328 for (i = 0; i < n; i++) {
329 long long src = cpl_table_get_long_long(*stds, "Source", i, NULL);
330 char* tmpstr = cpl_sprintf("%lld", src);
331 cpl_table_set_string(*stds, "OBJECT", i, tmpstr);
332 cpl_free(tmpstr);
333 }
334 }
335
336 /* Now fill the coordinates in */
337
338 wcs = cpl_wcs_new_from_propertylist((const cpl_propertylist *)plist);
339 if (cpl_table_get_column_type(*stds,"RA") == CPL_TYPE_FLOAT) {
340 ra = cpl_table_get_data_float(*stds,"RA");
341 dec = cpl_table_get_data_float(*stds,"Dec");
342 x = cpl_malloc(n*sizeof(*x));
343 y = cpl_malloc(n*sizeof(*y));
344 for (i = 0; i < n; i++) {
345 r = (double)ra[i];
346 d = (double)dec[i];
347 casu_radectoxy(wcs,r,d,&xx,&yy);
348 x[i] = (float)xx;
349 y[i] = (float)yy;
350 }
351 } else {
352 rad = cpl_table_get_data_double(*stds,"RA");
353 decd = cpl_table_get_data_double(*stds,"Dec");
354 x = cpl_malloc(n*sizeof(*x));
355 y = cpl_malloc(n*sizeof(*y));
356 for (i = 0; i < n; i++) {
357 r = rad[i];
358 d = decd[i];
359 casu_radectoxy(wcs,r,d,&xx,&yy);
360 x[i] = (float)xx;
361 y[i] = (float)yy;
362 }
363 }
364 cpl_wcs_delete(wcs);
365
366 /* Add the predicted x,y coordinates columns to the table */
367
368 cpl_table_wrap_float(*stds,x,"xpredict");
369 cpl_table_set_column_unit(*stds,"xpredict","pixels");
370 cpl_table_wrap_float(*stds,y,"ypredict");
371 cpl_table_set_column_unit(*stds,"ypredict","pixels");
372
373 /* Finally sort this by ypredict */
374
375 p = cpl_propertylist_new();
376 cpl_propertylist_append_bool(p,"ypredict",0);
377 cpl_table_sort(*stds,p);
378 cpl_propertylist_delete(p);
379
380 /* Get out of here */
381
382 GOOD_STATUS
383}
384
385/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425static const int maxcds = 8;
426static const char *cdscatnames[9] =
427 {"","2mass","usnob","ppmxl","landolt","wise", "apass", "gaiadr3", "gaiasyntphot"};
428static const char *cdscats[9] =
429 {"","II/246","I/284","I/317","II/183A","II/311", "II/336", "I/355", "I/360/syntphot"};
430
431extern int casu_getstds_cdslist(int cdschoice, char **cdscatname,
432 char **cdscatid, int *status) {
433 const char *fctid = "casu_getstds_cdslist";
434
435 if (*status != CASU_OK)
436 return(*status);
437
438 /* Check that the choice is within the bounds of possibility */
439
440 *cdscatname = NULL;
441 *cdscatid = NULL;
442 if (cdschoice < 0 || cdschoice > maxcds) {
443 cpl_msg_error(fctid,"CDS catalogue choice must be >= 0 && <= %d",
444 maxcds);
445 return(CASU_FATAL);
446 }
447 *cdscatname = cpl_strdup(cdscatnames[cdschoice]);
448 *cdscatid = cpl_strdup(cdscats[cdschoice]);
449 GOOD_STATUS
450}
451
452/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
479extern int casu_get_cdschoice(const char* cdscatname)
480{
481
482 for (int i=1; i<=maxcds; i++) {
483 if (!strcmp(cdscatname, cdscatnames[i])) {
484 return i;
485 }
486 }
487 return 0;
488}
489
490
491/*---------------------------------------------------------------------------*/
519/*---------------------------------------------------------------------------*/
520
521static cpl_table *casu_2mass_extract(char *path, float ramin1, float ramax1,
522 float decmin, float decmax) {
523 cpl_table *t,*s,*o;
524 int i,nrows,start,finish,first_index,last_index,irow,init,j;
525 int first_index_ra,last_index_ra,wrap,iwrap;
526 float dectest,ratest,ramin,ramax;
527 char fullname[SZBUF];
528 cpl_array *a;
529 const char *deccol = "Dec";
530 cpl_propertylist *p;
531
532 /* Create an output table */
533
534 o = cpl_table_new(0);
535 init = 1;
536
537 /* Create a cpl array */
538
539 a = cpl_array_wrap_string((char **)&deccol,1);
540
541 /* Is there a wrap around problem? */
542
543 wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
544
545 /* Loop for each query. If there is a wrap around problem then we need 2
546 queries. If not, then we only need 1 */
547
548 for (iwrap = 0; iwrap < wrap; iwrap++) {
549 if (wrap == 2) {
550 if (iwrap == 0) {
551 ramin = ramin1 + 360.0;
552 ramax = 360.0;
553 } else {
554 ramin = 0.000001;
555 ramax = ramax1;
556 }
557 } else {
558 ramin = ramin1;
559 ramax = ramax1;
560 }
561
562 /* Find out where in the index to look */
563
564 first_index_ra = (int)ramin;
565 last_index_ra = min((int)ramax,359);
566
567 /* Look at the min and max RA and decide which files need to be
568 opened. */
569
570 for (i = first_index_ra; i <= last_index_ra; i++) {
571
572 /* Ok, we've found one that needs opening. Read the file with
573 the relevant CPL call */
574
575 (void)snprintf(fullname,SZBUF,"%s/npsc%03d.fits",path,i);
576
577 /* Read the propertylist so that you know how many rows there
578 are in the table */
579
580 p = cpl_propertylist_load(fullname,1);
581 if (p == NULL) {
582 freetable(o);
583 cpl_array_unwrap(a);
584 return(NULL);
585 }
586 nrows = cpl_propertylist_get_int(p,"NAXIS2");
587 cpl_propertylist_delete(p);
588
589 /* Load various rows until you find the Dec range that you
590 have specified. First the minimum Dec */
591
592 start = 0;
593 finish = nrows;
594 first_index = nrows/2;
595 while (finish - start >= 2) {
596 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)first_index,
597 1);
598 dectest = cpl_table_get_double(t,"Dec",0,NULL);
599 cpl_table_delete(t);
600 if (dectest < decmin) {
601 start = first_index;
602 first_index = (first_index + finish)/2;
603 } else {
604 finish = first_index;
605 first_index = (first_index + start)/2;
606 }
607 }
608
609 /* Load various rows until you find the Dec range that you
610 have specified. Now the maximum Dec */
611
612 start = first_index;
613 finish = nrows;
614 last_index = start + (finish - start)/2;
615 while (finish - start >= 2) {
616 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)last_index,
617 1);
618 dectest = cpl_table_get_double(t,"Dec",0,NULL);
619 cpl_table_delete(t);
620 if (dectest < decmax) {
621 start = last_index;
622 last_index = (last_index + finish)/2;
623 } else {
624 finish = last_index;
625 last_index = (last_index + start)/2;
626 }
627 }
628 if (last_index < first_index)
629 last_index = first_index;
630
631 /* Ok now now load all the rows in the relevant dec limits */
632
633 nrows = last_index - first_index + 1;
634 if ((t = cpl_table_load_window(fullname,1,1,NULL,
635 (cpl_size)first_index,
636 (cpl_size)nrows)) == NULL) {
637 freetable(o);
638 cpl_array_unwrap(a);
639 return(NULL);
640 }
641 cpl_table_unselect_all(t);
642
643 /* Right, we now know what range of rows to search. Go through
644 these and pick the ones that are in the correct range of RA.
645 If a row qualifies, then 'select' it. */
646
647 for (j = 0; j < nrows; j++) {
648 ratest = cpl_table_get_double(t,"RA",(cpl_size)j,NULL);
649 if (cpl_error_get_code() != CPL_ERROR_NONE) {
650 cpl_table_delete(t);
651 cpl_array_unwrap(a);
652 freetable(o);
653 return(NULL);
654 }
655 if (ratest >= ramin && ratest <= ramax)
656 cpl_table_select_row(t,(cpl_size)j);
657 }
658
659 /* Extract the rows that have been selected now and append them
660 onto the output table */
661
662 s = cpl_table_extract_selected(t);
663 if (init == 1) {
664 cpl_table_copy_structure(o,t);
665 init = 0;
666 }
667 irow = (int)cpl_table_get_nrow(o) + 1;
668 cpl_table_insert(o,s,(cpl_size)irow);
669
670 /* Tidy up */
671
672 cpl_table_delete(t);
673 cpl_table_delete(s);
674 }
675 }
676
677 /* Ok, now just return the table and get out of here */
678
679 cpl_array_unwrap(a);
680 return(o);
681}
682
683/*---------------------------------------------------------------------------*/
711/*---------------------------------------------------------------------------*/
712
713static cpl_table *casu_ppmxl_extract(char *path, float ramin1, float ramax1,
714 float decmin, float decmax) {
715 cpl_table *t,*s,*o;
716 int i,nrows,start,finish,first_index,last_index,irow,init,j;
717 int first_index_ra,last_index_ra,wrap,iwrap;
718 float dectest,ratest,ramin,ramax;
719 char fullname[SZBUF];
720 cpl_array *a;
721 const char *deccol = "Dec";
722 cpl_propertylist *p;
723
724 /* Create an output table */
725
726 o = cpl_table_new(0);
727 init = 1;
728
729 /* Create a cpl array */
730
731 a = cpl_array_wrap_string((char **)&deccol,1);
732
733 /* Is there a wrap around problem? */
734
735 wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
736
737 /* Loop for each query. If there is a wrap around problem then we need 2
738 queries. If not, then we only need 1 */
739
740 for (iwrap = 0; iwrap < wrap; iwrap++) {
741 if (wrap == 2) {
742 if (iwrap == 0) {
743 ramin = ramin1 + 360.0;
744 ramax = 360.0;
745 } else {
746 ramin = 0.000001;
747 ramax = ramax1;
748 }
749 } else {
750 ramin = ramin1;
751 ramax = ramax1;
752 }
753
754 /* Find out where in the index to look */
755
756 first_index_ra = (int)ramin;
757 last_index_ra = min((int)ramax,359);
758
759 /* Look at the min and max RA and decide which files need to be
760 opened. */
761
762 for (i = first_index_ra; i <= last_index_ra; i++) {
763
764 /* Ok, we've found one that needs opening. Read the file with
765 the relevant CPL call */
766
767 (void)snprintf(fullname,SZBUF,"%s/nppmxl%03d.fits",path,i);
768
769 /* Read the propertylist so that you know how many rows there
770 are in the table */
771
772 p = cpl_propertylist_load(fullname,1);
773 if (p == NULL) {
774 freetable(o);
775 cpl_array_unwrap(a);
776 return(NULL);
777 }
778 nrows = cpl_propertylist_get_int(p,"NAXIS2");
779 cpl_propertylist_delete(p);
780
781 /* Load various rows until you find the Dec range that you
782 have specified. First the minimum Dec */
783
784 start = 0;
785 finish = nrows;
786 first_index = nrows/2;
787 while (finish - start >= 2) {
788 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)first_index,
789 1);
790 dectest = (float)cpl_table_get_double(t,"Dec",0,NULL);
791 cpl_table_delete(t);
792 if (dectest < decmin) {
793 start = first_index;
794 first_index = (first_index + finish)/2;
795 } else {
796 finish = first_index;
797 first_index = (first_index + start)/2;
798 }
799 }
800
801 /* Load various rows until you find the Dec range that you
802 have specified. Now the maximum Dec */
803
804 start = first_index;
805 finish = nrows;
806 last_index = start + (finish - start)/2;
807 while (finish - start >= 2) {
808 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)last_index,
809 1);
810 dectest = (float)cpl_table_get_double(t,"Dec",0,NULL);
811 cpl_table_delete(t);
812 if (dectest < decmax) {
813 start = last_index;
814 last_index = (last_index + finish)/2;
815 } else {
816 finish = last_index;
817 last_index = (last_index + start)/2;
818 }
819 }
820 if (last_index < first_index)
821 last_index = first_index;
822
823 /* Ok now now load all the rows in the relevant dec limits */
824
825 nrows = last_index - first_index + 1;
826 if ((t = cpl_table_load_window(fullname,1,1,NULL,
827 (cpl_size)first_index,
828 (cpl_size)nrows)) == NULL) {
829 freetable(o);
830 cpl_array_unwrap(a);
831 return(NULL);
832 }
833 cpl_table_unselect_all(t);
834
835 /* Right, we now know what range of rows to search. Go through
836 these and pick the ones that are in the correct range of RA.
837 If a row qualifies, then 'select' it. */
838
839 for (j = 0; j < nrows; j++) {
840 ratest = (float)cpl_table_get_double(t,"RA",(cpl_size)j,NULL);
841 if (cpl_error_get_code() != CPL_ERROR_NONE) {
842 cpl_table_delete(t);
843 cpl_array_unwrap(a);
844 freetable(o);
845 return(NULL);
846 }
847 if (ratest >= ramin && ratest <= ramax)
848 cpl_table_select_row(t,(cpl_size)j);
849 }
850
851 /* Extract the rows that have been selected now and append them
852 onto the output table */
853
854 s = cpl_table_extract_selected(t);
855 if (init == 1) {
856 cpl_table_copy_structure(o,t);
857 init = 0;
858 }
859 irow = (int)cpl_table_get_nrow(o) + 1;
860 cpl_table_insert(o,s,(cpl_size)irow);
861
862 /* Tidy up */
863
864 cpl_table_delete(t);
865 cpl_table_delete(s);
866 }
867 }
868
869 /* Ok, now just return the table and get out of here */
870
871 cpl_array_unwrap(a);
872 return(o);
873}
874
875/*---------------------------------------------------------------------------*/
903/*---------------------------------------------------------------------------*/
904
905static cpl_table *casu_apass_extract(char *path, float ramin1, float ramax1,
906 float decmin, float decmax) {
907 cpl_table *t,*s,*o;
908 int i,nrows,start,finish,first_index,last_index,irow,init,j;
909 int first_index_ra,last_index_ra,wrap,iwrap;
910 float dectest,ratest,ramin,ramax;
911 char fullname[SZBUF];
912 cpl_array *a;
913 const char *racol = "RA";
914 cpl_propertylist *p;
915
916 /* Create an output table */
917
918 o = cpl_table_new(0);
919 init = 1;
920
921 /* Create a cpl array */
922
923 a = cpl_array_wrap_string((char **)&racol,1);
924
925 /* Is there a wrap around problem? */
926
927 wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
928
929 /* Loop for each query. If there is a wrap around problem then we need 2
930 queries. If not, then we only need 1 */
931
932 for (iwrap = 0; iwrap < wrap; iwrap++) {
933 if (wrap == 2) {
934 if (iwrap == 0) {
935 ramin = ramin1 + 360.0;
936 ramax = 360.0;
937 } else {
938 ramin = 0.000001;
939 ramax = ramax1;
940 }
941 } else {
942 ramin = ramin1;
943 ramax = ramax1;
944 }
945
946 /* Find out where in the index to look */
947
948 first_index_ra = (int)ramin;
949 last_index_ra = min((int)ramax,359);
950
951 /* Look at the min and max RA and decide which files need to be
952 opened. */
953
954 for (i = first_index_ra; i <= last_index_ra; i++) {
955
956 /* Ok, we've found one that needs opening. Read the file with
957 the relevant CPL call */
958
959 (void)snprintf(fullname,SZBUF,"%s/casuapass_%03d.fits",path,i);
960
961 /* Read the propertylist so that you know how many rows there
962 are in the table */
963
964 p = cpl_propertylist_load(fullname,1);
965 if (p == NULL) {
966 freetable(o);
967 cpl_array_unwrap(a);
968 return(NULL);
969 }
970 nrows = cpl_propertylist_get_int(p,"NAXIS2");
971 cpl_propertylist_delete(p);
972
973 /* Load various rows until you find the RA range that you
974 have specified. First the minimum RA */
975
976 start = 0;
977 finish = nrows;
978 first_index = nrows/2;
979 while (finish - start >= 2) {
980 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)first_index,
981 1);
982 ratest = (float)cpl_table_get_double(t,"RA",0,NULL);
983 cpl_table_delete(t);
984 if (ratest < ramin) {
985 start = first_index;
986 first_index = (first_index + finish)/2;
987 } else {
988 finish = first_index;
989 first_index = (first_index + start)/2;
990 }
991 }
992
993 /* Load various rows until you find the RA range that you
994 have specified. Now the maximum RA */
995
996 start = first_index;
997 finish = nrows;
998 last_index = start + (finish - start)/2;
999 while (finish - start >= 2) {
1000 t = cpl_table_load_window(fullname,1,1,a,(cpl_size)last_index,
1001 1);
1002 ratest = (float)cpl_table_get_double(t,"RA",0,NULL);
1003 cpl_table_delete(t);
1004 if (ratest < ramax) {
1005 start = last_index;
1006 last_index = (last_index + finish)/2;
1007 } else {
1008 finish = last_index;
1009 last_index = (last_index + start)/2;
1010 }
1011 }
1012 if (last_index < first_index)
1013 last_index = first_index;
1014
1015 /* Ok now now load all the rows in the relevant RA limits */
1016
1017 nrows = last_index - first_index + 1;
1018 if ((t = cpl_table_load_window(fullname,1,1,NULL,
1019 (cpl_size)first_index,
1020 (cpl_size)nrows)) == NULL) {
1021 freetable(o);
1022 cpl_array_unwrap(a);
1023 return(NULL);
1024 }
1025 cpl_table_unselect_all(t);
1026
1027 /* Right, we now know what range of rows to search. Go through
1028 these and pick the ones that are in the correct range of RA.
1029 If a row qualifies, then 'select' it. */
1030
1031 for (j = 0; j < nrows; j++) {
1032 dectest = (float)cpl_table_get_double(t,"Dec",(cpl_size)j,NULL);
1033 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1034 cpl_table_delete(t);
1035 cpl_array_unwrap(a);
1036 freetable(o);
1037 return(NULL);
1038 }
1039 if (dectest >= decmin && dectest <= decmax)
1040 cpl_table_select_row(t,(cpl_size)j);
1041 }
1042
1043 /* Extract the rows that have been selected now and append them
1044 onto the output table */
1045
1046 s = cpl_table_extract_selected(t);
1047 if (init == 1) {
1048 cpl_table_copy_structure(o,t);
1049 init = 0;
1050 }
1051 irow = (int)cpl_table_get_nrow(o) + 1;
1052 cpl_table_insert(o,s,(cpl_size)irow);
1053
1054 /* Tidy up */
1055
1056 cpl_table_delete(t);
1057 cpl_table_delete(s);
1058 }
1059 }
1060
1061 /* Ok, now just return the table and get out of here */
1062
1063 cpl_array_unwrap(a);
1064 return(o);
1065}
1066
1067/*---------------------------------------------------------------------------*/
1096/*---------------------------------------------------------------------------*/
1097
1098static cpl_table *casu_local_extract(char *path, float ramin1, float ramax1,
1099 float decmin, float decmax) {
1100 cpl_table *whole,*out,*out2;
1101 int wrap,iwrap,nrows;
1102 float ramin,ramax;
1103 cpl_propertylist *p;
1104
1105 /* First read the input file. It's assumed this isn't so big that it's
1106 going to take very long. */
1107
1108 whole = cpl_table_load((const char *)path,1,0);
1109
1110 /* Is there a wrap around problem? */
1111
1112 wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
1113
1114 /* Loop for each query. If there is a wrap around problem then we need 2
1115 queries. If not, then we only need 1 */
1116
1117 out = NULL;
1118 for (iwrap = 0; iwrap < wrap; iwrap++) {
1119 if (wrap == 2) {
1120 if (iwrap == 0) {
1121 ramin = ramin1 + 360.0;
1122 ramax = 360.0;
1123 } else {
1124 ramin = 0.000001;
1125 ramax = ramax1;
1126 }
1127 } else {
1128 ramin = ramin1;
1129 ramax = ramax1;
1130 }
1131 cpl_table_unselect_all(whole);
1132
1133 /* Select on RA and Dec */
1134
1135 cpl_table_or_selected_double(whole,"RA",CPL_NOT_LESS_THAN,
1136 (double)ramin);
1137 cpl_table_and_selected_double(whole,"RA",CPL_NOT_GREATER_THAN,
1138 (double)ramax);
1139 cpl_table_and_selected_double(whole,"Dec",CPL_NOT_LESS_THAN,
1140 (double)decmin);
1141 cpl_table_and_selected_double(whole,"Dec",CPL_NOT_GREATER_THAN,
1142 (double)decmax);
1143
1144 /* If this is the first time through, then create the output table */
1145
1146 if (out == NULL) {
1147 out = cpl_table_extract_selected(whole);
1148 } else {
1149 out2 = cpl_table_extract_selected(whole);
1150 nrows = cpl_table_get_nrow(out);
1151 cpl_table_insert(out,out2,nrows+1);
1152 cpl_table_delete(out2);
1153 }
1154 }
1155
1156 /* Sort the table by Dec and get out of here*/
1157
1158 p = cpl_propertylist_new();
1159 cpl_propertylist_append_bool(p,"Dec",0);
1160 cpl_table_sort(out,p);
1161 cpl_propertylist_delete(p);
1162 return(out);
1163}
1164
1165/*---------------------------------------------------------------------------*/
1195/*---------------------------------------------------------------------------*/
1196
1197static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im,
1198 float dec1_im, float dec2_im, char *cacheloc) {
1199 int wrap1,wrap2;
1200 FILE *fd;
1201 char fname[BUFSIZ],catname2[SZBUF];
1202 char * cat_cache = NULL;
1203 float best,ra1_cat,ra2_cat,dec1_cat,dec2_cat,d1,d2,fra,fdec,ftot;
1204 cpl_table *out_cat;
1205
1206 /* Open the index file. NB the path and file name are hardcoded */
1207
1208 (void)snprintf(fname,BUFSIZ,"%s/%s",cacheloc,CACHEIND);
1209 fd = fopen(fname,"r");
1210 if (fd == NULL)
1211 return(NULL);
1212
1213 /* Check to see if there is wrap around in the coordinates */
1214
1215 wrap1 = (ra1_im < 0.0 ? 1 : 0);
1216
1217 /* Now see if you have any matching entries */
1218
1219 best = 0.0;
1220 // Todo: the hard coded numbers should be changed to use BUFSIZ and SZBUF
1221 while (fscanf(fd,"%8191s %1023s %g %g %g %g",
1222 fname,catname2,&ra1_cat,&ra2_cat,
1223 &dec1_cat,&dec2_cat) != EOF) {
1224 wrap2 = (ra1_cat < 0.0 ? 1 : 0);
1225 if (wrap1 != wrap2)
1226 continue;
1227 if (strcmp(catname,catname2))
1228 continue;
1229
1230 /* Check to see if there is at least some overlap */
1231
1232 if (!(((ra1_im >= ra1_cat && ra1_im <= ra2_cat) ||
1233 (ra2_im >= ra1_cat && ra2_im <= ra2_cat)) &&
1234 ((dec1_im >= dec1_cat && dec1_im <= dec2_cat) ||
1235 (dec2_im >= dec1_cat && dec2_im <= dec2_cat))))
1236 continue;
1237
1238 /* Work out exactly how much there is in each coordinate */
1239
1240 d1 = max(0.0,ra1_cat-ra1_im);
1241 d2 = max(0.0,ra2_im-ra2_cat);
1242 fra = 1.0 - (d1 + d2)/(ra2_im - ra1_im);
1243 d1 = max(0.0,dec1_cat-dec1_im);
1244 d2 = max(0.0,dec2_im-dec2_cat);
1245 fdec = 1.0 - (d1 + d2)/(dec2_im - dec1_im);
1246 ftot = fra*fdec;
1247
1248 /* Keep track of which is the best one */
1249
1250 if (ftot > best) {
1251 cpl_free(cat_cache); /* As we are in a loop free old allocation */
1252 cat_cache = cpl_sprintf("%s/%s/%s",cacheloc,CACHEDIR,fname);
1253 best = ftot;
1254 }
1255 }
1256 fclose(fd);
1257
1258 /* Return a bad status if there isn't sufficient overlap */
1259
1260 if (best < 0.9)
1261 return(NULL);
1262
1263 /* If there is enough overlap, then try and read the FITS table. If it
1264 reads successfully, then return the table pointer */
1265
1266 out_cat = cpl_table_load(cat_cache,1,1);
1267 cpl_free(cat_cache);
1268
1269 cpl_msg_info(cpl_func, "Using cached catalogue data");
1270
1271 return(out_cat);
1272}
1273
1274/*---------------------------------------------------------------------------*/
1302/*---------------------------------------------------------------------------*/
1303
1304static void addto_cache(cpl_table *stds, char *catname, float ramin,
1305 float ramax, float decmin, float decmax,
1306 char *cacheloc) {
1307 FILE *fd;
1308 char newname[SZBUF];
1309 int i;
1310
1311 /* Check to see if the cache directory exists. If it doesn't, then create
1312 it. */
1313
1314 (void)snprintf(newname,SZBUF,"%s/%s",cacheloc,CACHEDIR);
1315 if (access(newname,0) != 0)
1316 mkdir(newname,0755);
1317
1318 /* Open the index file with 'append' access */
1319
1320 (void)snprintf(newname,SZBUF,"%s/%s",cacheloc,CACHEIND);
1321 fd = fopen(newname,"a");
1322
1323 /* Check the files in the directory to get a number that isn't already
1324 being used */
1325
1326 i = 0;
1327 while (i >= 0) {
1328 i++;
1329 snprintf(newname,SZBUF,"%s/%s/cch_%08d",cacheloc,CACHEDIR,i);
1330 if (access(newname,F_OK) != 0)
1331 break;
1332 }
1333
1334 /* Now write the current entry and make a copy of the file into the
1335 directory */
1336
1337 snprintf(newname,SZBUF,"%s/%s/cch_%08d",cacheloc,CACHEDIR,i);
1338 cpl_table_save(stds,NULL,NULL,newname,CPL_IO_DEFAULT);
1339 snprintf(newname,SZBUF,"cch_%08d",i);
1340 if (cpl_error_get_code() == CPL_ERROR_NONE)
1341 fprintf(fd, "%s %s %g %g %g %g\n",newname,catname,ramin-0.0005,
1342 ramax+0.0005,decmin-0.0005,decmax+0.0005);
1343 fclose(fd);
1344}
1345
1346/*---------------------------------------------------------------------------*/
1369/*---------------------------------------------------------------------------*/
1370
1371static int get_response(int sock, cpl_table **outtab) {
1372 int nnewline,i,nv,irem = 0,fd;
1373 long nrows;
1374 char buf[BUFMAX],outfile[32];
1375 const char *fctid = "get_response";
1376
1377 /* Read from the socket until we find the double newline */
1378
1379 nnewline = 0;
1380 while (1) {
1381 nv = recv(sock,buf,sizeof(buf),0);
1382 if (nv <= 0) {
1383 cpl_msg_warning(fctid,"Unable to find double newline");
1384 return(CASU_FATAL);
1385 }
1386 for (i = 0; i < nv; i++) {
1387 if (buf[i] == '\n') {
1388 nnewline++;
1389 if (nnewline == 2)
1390 break;
1391 } else {
1392 if (nnewline && buf[i] != '\r')
1393 nnewline = 0;
1394 }
1395 }
1396 if (nnewline == 2) {
1397 irem = i + 1;
1398 break;
1399 }
1400 }
1401
1402 /* Shift the buffer */
1403
1404 for (i = irem; i < nv; i++)
1405 buf[i-irem] = buf[i];
1406 nv -= irem;
1407
1408 /* Open the output file */
1409
1410 (void)snprintf(outfile,32,"stdsXXXXXX");
1411 fd = mkstemp(outfile);
1412
1413 /* Now write the data to the output file */
1414
1415 while (1) {
1416 ssize_t written = write(fd,buf,nv);
1417 if(written != nv) {
1418 cpl_msg_info(cpl_func, "Not all bytes could be written - "
1419 "check diskspace");
1420 }
1421 nv = recv(sock,buf,sizeof(buf),0);
1422 if (nv == 0)
1423 break;
1424 else if (nv < 0) {
1425 cpl_msg_warning(fctid,"Read from socket failed");
1426 close(fd);
1427 remove(outfile);
1428 return(CASU_FATAL);
1429 }
1430 }
1431
1432 /* Close the output file. Check and see if a table was created and whether
1433 or not it contains any rows... */
1434
1435 close(fd);
1436 *outtab = cpl_table_load(outfile,1,0);
1437 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1438 cpl_msg_warning(fctid,"No standards were found");
1439 cpl_error_reset();
1440 remove(outfile);
1441 *outtab = NULL;
1442 return(CASU_FATAL);
1443 } else {
1444 nrows = (int)cpl_table_get_nrow(*outtab);
1445 if (nrows <= 0) {
1446 cpl_msg_warning(fctid,"No standards table had no rows");
1447 remove(outfile);
1448 freetable(*outtab);
1449 return(CASU_FATAL);
1450 }
1451 }
1452
1453 /* Get out of here */
1454
1455 remove(outfile);
1456 return(CASU_OK);
1457}
1458
1459/*---------------------------------------------------------------------------*/
1485/*---------------------------------------------------------------------------*/
1486
1487static int send_request(int sock, char *req_string, int isbin) {
1488 char buf[BUFMAX];
1489 const char *fctid = "send_request";
1490
1491 /* Form the full request contents and send it. */
1492
1493 if (isbin) {
1494 sprintf(buf,"GET /viz-bin/asu-binfits?%s HTTP/1.0\r\n\r\n",req_string);
1495 } else {
1496 sprintf(buf,"GET /viz-bin/asu-fits?%s HTTP/1.0\r\n\r\n",req_string);
1497 }
1498 if (send(sock,buf,strlen(buf),0) < 0) {
1499 cpl_msg_warning(fctid,"Attempt to send message failed, error: %d\n",
1500 errno);
1501 return(CASU_FATAL);
1502 }
1503 return(CASU_OK);
1504}
1505
1506/*---------------------------------------------------------------------------*/
1529/*---------------------------------------------------------------------------*/
1530
1531static int connect_site(const char *site, int *sock) {
1532 struct hostent *hp;
1533 struct sockaddr_in ssin;
1534 const char *fctid = "connect_site";
1535
1536 /* Get host pointer */
1537
1538 hp = gethostbyname(site);
1539 if (hp == NULL) {
1540 cpl_msg_warning(fctid,"Unable to get host information for %s\n",site);
1541 return(CASU_FATAL);
1542 }
1543 ssin.sin_family = hp->h_addrtype;
1544 memcpy(&ssin.sin_addr,hp->h_addr_list[0],hp->h_length);
1545 ssin.sin_port = htons(PORT);
1546
1547 /* Create an IP-family socket on which to make the connection */
1548
1549 *sock = socket(hp->h_addrtype,SOCK_STREAM,0);
1550 if (*sock < 0) {
1551 cpl_msg_warning(fctid,"Unable to create socket descriptor for %s\n",
1552 site);
1553 return (CASU_FATAL);
1554 }
1555
1556 /* Connect to that address...*/
1557
1558 if (connect(*sock,(struct sockaddr*)&ssin,sizeof(ssin)) < 0) {
1559 cpl_msg_warning(fctid,"Unable to connect to site: %s\n",site);
1560 return(CASU_FATAL);
1561 }
1562
1563 /* Otherwise send back a good status */
1564
1565 return(CASU_OK);
1566}
1567
1568/*---------------------------------------------------------------------------*/
1596/*---------------------------------------------------------------------------*/
1597
1598static char *form_request(float ra, float dec, float dra, float ddec,
1599 float equinox, const char *catid) {
1600 const char *fctid = "form_request";
1601 static char buf[2*BUFSIZ];
1602 char buf2[BUFSIZ],equi[1];
1603
1604 cpl_msg_debug(fctid, "catid is: %s", catid);
1605
1606 /* Format each of the fields and then add them to the buffer that will
1607 become the query string. URLencode them before appending. First
1608 the coordinates */
1609
1610 (void)snprintf(buf2,BUFSIZ,"-c=%8.3f %8.3f",ra,dec);
1611 (void)strncpy(buf,url_encode(buf2),BUFSIZ);
1612
1613 /* Now the box size */
1614
1615 (void)snprintf(buf2,BUFSIZ,"-c.bd=%g/%g",dra,ddec);
1616 (void)strncat(buf,"&",BUFSIZ);
1617 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1618
1619 /* The catalogue name */
1620
1621 (void)snprintf(buf2,BUFSIZ,"-source=%s",catid);
1622 (void)strncat(buf,"&",BUFSIZ);
1623 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1624
1625 /* The equinox */
1626
1627 equi[0] = (equinox == 1950.0 ? 'B' : 'J');
1628 (void)snprintf(buf2,BUFSIZ,"-c.eq=%c%g",equi[0],equinox);
1629 (void)strncat(buf,"&",BUFSIZ);
1630 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1631
1632 /* Finally make sure that we don't truncate the result and that we
1633 sort by RA */
1634
1635 (void)snprintf(buf2,BUFSIZ,"-out.max=unlimited");
1636 (void)strncat(buf,"&",BUFSIZ);
1637 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1638 (void)snprintf(buf2,BUFSIZ,"-sort=_RA*-c.eq");
1639 (void)strncat(buf,"&",BUFSIZ);
1640 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1641 (void)snprintf(buf2,BUFSIZ,"-out.add=_RA*-c.eq");
1642 (void)strncat(buf,"&",BUFSIZ);
1643 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1644 (void)snprintf(buf2,BUFSIZ,"-out.add=_DEC*-c.eq");
1645 (void)strncat(buf,"&",BUFSIZ);
1646 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1647
1648 /* Special case for the gaiasyntphot table */
1649 if (strcmp(catid, cdscats[7]) == 0) {
1650 cpl_msg_debug(fctid, "Adding extra fields");
1651 (void)snprintf(buf2,BUFSIZ,"-out.add=VarFlag");
1652 (void)strncat(buf,"&",BUFSIZ);
1653 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1654 (void)snprintf(buf2,BUFSIZ,"-out.add=NSS");
1655 (void)strncat(buf,"&",BUFSIZ);
1656 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1657 (void)snprintf(buf2,BUFSIZ,"-out.add=Gmag");
1658 (void)strncat(buf,"&",BUFSIZ);
1659 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1660 (void)snprintf(buf2,BUFSIZ,"-out.add=RUWE");
1661 (void)strncat(buf,"&",BUFSIZ);
1662 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1663 } else if (strcmp(catid, cdscats[8]) == 0) {
1664 cpl_msg_debug(fctid, "Adding -out.all");
1665 (void)snprintf(buf2,BUFSIZ,"-out.all");
1666 (void)strncat(buf,"&",BUFSIZ);
1667 (void)strncat(buf,url_encode(buf2),BUFSIZ);
1668 }
1669
1670 cpl_msg_debug(fctid, "Query is: %s", buf);
1671
1672 /* Right, get out of here */
1673
1674 return(buf);
1675}
1676
1677/*---------------------------------------------------------------------------*/
1695/*---------------------------------------------------------------------------*/
1696
1697static char *url_encode(char *instring) {
1698 static char buf[BUFSIZ];
1699 int i,j,k,len;
1700
1701 /* First copy over everything before the equal sign */
1702
1703 k = 0;
1704 do {
1705 buf[k] = instring[k];
1706 } while (instring[k++] != '=');
1707 len = strlen(instring);
1708
1709 /* Copy over the string, substituting the things that we don't want in
1710 a URL */
1711
1712 j = k;
1713 for (i = k; i < len; i++) {
1714 assert(j < (int)sizeof(buf));
1715 if (instring[i] == ' ')
1716 buf[j++] = '+';
1717 else if (isalnum((unsigned char)instring[i]))
1718 buf[j++] = instring[i];
1719 else {
1720 sprintf(buf+j,"%%%2x",(unsigned char)instring[i]);
1721 j += 3;
1722 }
1723 }
1724 buf[j] = '\0';
1725 return(buf);
1726}
1727
1731/*
1732
1733$Log: casu_getstds.c,v $
1734Revision 1.7 2015/11/27 12:06:41 jim
1735Detabbed a few things
1736
1737Revision 1.6 2015/11/25 13:50:03 jim
1738cacheloc parameter added
1739
1740Revision 1.5 2015/11/25 10:24:49 jim
1741Changed so that catpath always contains the full path of a file and the
1742file name is stripped off in the event that you're using local
17432mass, apass or ppmxl catalogues
1744
1745Revision 1.4 2015/10/04 18:43:14 jim
1746fixed small bug when no standards are returned
1747
1748Revision 1.3 2015/08/07 13:06:54 jim
1749Fixed copyright to ESO
1750
1751Revision 1.2 2015/08/06 05:34:02 jim
1752Fixes to get rid of compiler moans
1753
1754Revision 1.1.1.1 2015/06/12 10:44:32 jim
1755Initial import
1756
1757Revision 1.15 2015/05/20 11:58:00 jim
1758Changed URL for CDS
1759
1760Revision 1.14 2015/05/14 11:46:33 jim
1761All RA and Dec columns are officially double
1762
1763Revision 1.13 2015/05/13 11:42:27 jim
1764superficial changes
1765
1766Revision 1.12 2015/03/12 09:16:51 jim
1767Modified to remove some compiler moans
1768
1769Revision 1.11 2015/03/09 19:51:58 jim
1770Fixed undefined value
1771
1772Revision 1.10 2015/03/03 10:48:11 jim
1773Fixed some memory leaks
1774
1775Revision 1.9 2015/01/29 11:48:15 jim
1776modified comments
1777
1778Revision 1.8 2015/01/09 12:13:15 jim
1779*** empty log message ***
1780
1781Revision 1.7 2014/12/11 12:23:33 jim
1782new version
1783
1784Revision 1.6 2014/04/23 05:39:41 jim
1785Now reads local standard tables
1786
1787Revision 1.5 2014/04/09 11:26:36 jim
1788Order of catalogues for CDS was wrong
1789
1790Revision 1.4 2014/04/09 11:08:21 jim
1791Get rid of a couple of compiler moans
1792
1793Revision 1.3 2014/04/09 09:09:51 jim
1794Detabbed
1795
1796Revision 1.2 2013/11/21 09:38:13 jim
1797detabbed
1798
1799Revision 1.1.1.1 2013-08-27 12:07:48 jim
1800Imported
1801
1802
1803*/
int casu_get_cdschoice(const char *cdscatname)
Definition: casu_getstds.c:479
int casu_getstds(cpl_propertylist *plist, int cache, char *path, char *catname, int cdssearch, char *cacheloc, cpl_table **stds, int *status)
Get a table of standard stars that appear on an image from a catalogue.
Definition: casu_getstds.c:167
void casu_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x, double *y)
int casu_coverage(cpl_propertylist *plist, int fudge, double *ra1, double *ra2, double *dec1, double *dec2, int *status)