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