1 /*
2  # This file is part of the Astrometry.net suite.
3  # Licensed under a 3-clause BSD style license - see LICENSE
4  */
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <unistd.h>
11 #include <zlib.h>
12 
13 #include "2mass.h"
14 #include "2mass-fits.h"
15 #include "healpix.h"
16 #include "starutil.h"
17 #include "boilerplate.h"
18 #include "fitsioutils.h"
19 
20 #define OPTIONS "ho:N:"
21 
print_help(char * progname)22 void print_help(char* progname) {
23     BOILERPLATE_HELP_HEADER(stdout);
24     printf("usage:\n"
25            "  %s -o <output-filename-template>\n"
26            "  [-N <healpix-nside>]  (default = 8.)\n"
27            "  <input-file> [<input-file> ...]\n"
28            "\n"
29            "Input files are gzipped 2MASS PSC catalog files, named like psc_aaa.gz."
30            "\n", progname);
31 }
32 
33 
main(int argc,char ** args)34 int main(int argc, char** args) {
35     int c;
36     char* outfn = NULL;
37     int startoptind;
38     int Nside = 8;
39     int HP;
40     int i;
41 
42     twomass_fits** cats;
43 
44     while ((c = getopt(argc, args, OPTIONS)) != -1) {
45         switch (c) {
46         case '?':
47         case 'h':
48             print_help(args[0]);
49             exit(0);
50         case 'N':
51             Nside = atoi(optarg);
52             break;
53         case 'o':
54             outfn = optarg;
55             break;
56         }
57     }
58 
59     if (!outfn || (optind == argc)) {
60         print_help(args[0]);
61         exit(-1);
62     }
63 
64     if (Nside < 1) {
65         fprintf(stderr, "Nside must be >= 1.\n");
66         print_help(args[0]);
67         exit(-1);
68     }
69 
70     HP = 12 * Nside * Nside;
71     cats = calloc((size_t)HP, sizeof(twomass_fits*));
72 
73     printf("Nside = %i, using %i healpixes.\n", Nside, HP);
74 
75     printf("Reading 2MASS files... ");
76     fflush(stdout);
77 
78     startoptind = optind;
79     for (; optind<argc; optind++) {
80         char* infn;
81         gzFile fiz = NULL;
82         char line[1024];
83         int nentries;
84 
85         infn = args[optind];
86         printf("\nReading file %i of %i: %s\n", 1 + optind - startoptind,
87                argc - startoptind, infn);
88         infn = args[optind];
89         fiz = gzopen(infn, "rb");
90         if (!fiz) {
91             fprintf(stderr, "Failed to open file %s: %s\n", infn, strerror(errno));
92             exit(-1);
93         }
94         nentries = 0;
95         for (;;) {
96             twomass_entry e;
97             int hp;
98 
99             if (gzeof(fiz))
100                 break;
101 
102             if (gzgets(fiz, line, 1024) == Z_NULL) {
103                 if (gzeof(fiz))
104                     break;
105                 fprintf(stderr, "Failed to read a line from file %s: %s\n", infn, strerror(errno));
106                 exit(-1);
107             }
108 
109             if (twomass_parse_entry(&e, line)) {
110                 fprintf(stderr, "Failed to parse 2MASS entry from file %s.\n", infn);
111                 exit(-1);
112             }
113 
114             hp = radectohealpix(deg2rad(e.ra), deg2rad(e.dec), Nside);
115             if (!cats[hp]) {
116                 char fn[256];
117                 qfits_header* hdr;
118 
119                 sprintf(fn, outfn, hp);
120                 cats[hp] = twomass_fits_open_for_writing(fn);
121                 if (!cats[hp]) {
122                     fprintf(stderr, "Failed to open 2MASS catalog for writing to file %s (hp %i).\n", fn, hp);
123                     exit(-1);
124                 }
125                 // header remarks...
126                 hdr = twomass_fits_get_primary_header(cats[hp]);
127                 BOILERPLATE_ADD_FITS_HEADERS(hdr);
128                 fits_header_add_int(hdr, "HEALPIX", hp, "The healpix number of this catalog.");
129                 fits_header_add_int(hdr, "NSIDE", Nside, "The healpix resolution.");
130 
131                 fits_add_long_comment(hdr, "The fields are as described in the 2MASS documentation:");
132                 fits_add_long_comment(hdr, "  ftp://ftp.ipac.caltech.edu/pub/2mass/allsky/format_psc.html");
133                 fits_add_long_comment(hdr, "with a few exceptions:");
134                 fits_add_long_comment(hdr, "* all angular fields are measured in degrees");
135                 fits_add_long_comment(hdr, "* the photometric quality flag values are:");
136                 fits_add_long_comment(hdr, "    %i: 'X' in 2MASS, No brightness info available.", TWOMASS_QUALITY_NO_BRIGHTNESS);
137                 fits_add_long_comment(hdr, "    %i: 'U' in 2MASS, The brightness val is an upper bound.", TWOMASS_QUALITY_UPPER_LIMIT_MAG);
138                 fits_add_long_comment(hdr, "    %i: 'F' in 2MASS, No magnitude sigma is available", TWOMASS_QUALITY_NO_SIGMA);
139                 fits_add_long_comment(hdr, "    %i: 'E' in 2MASS, Profile-fit photometry was bad", TWOMASS_QUALITY_BAD_FIT);
140                 fits_add_long_comment(hdr, "    %i: 'A' in 2MASS, Best quality", TWOMASS_QUALITY_A);
141                 fits_add_long_comment(hdr, "    %i: 'B' in 2MASS, ...", TWOMASS_QUALITY_B);
142                 fits_add_long_comment(hdr, "    %i: 'C' in 2MASS, ...", TWOMASS_QUALITY_C);
143                 fits_add_long_comment(hdr, "    %i: 'D' in 2MASS, Worst quality", TWOMASS_QUALITY_D);
144                 fits_add_long_comment(hdr, "* the confusion/contamination flag values are:");
145                 fits_add_long_comment(hdr, "    %i: '0' in 2MASS, No problems.", TWOMASS_CC_NONE);
146                 fits_add_long_comment(hdr, "    %i: 'p' in 2MASS, Persistence.", TWOMASS_CC_PERSISTENCE);
147                 fits_add_long_comment(hdr, "    %i: 'c' in 2MASS, Confusion.", TWOMASS_CC_CONFUSION);
148                 fits_add_long_comment(hdr, "    %i: 'd' in 2MASS, Diffraction.", TWOMASS_CC_DIFFRACTION);
149                 fits_add_long_comment(hdr, "    %i: 's' in 2MASS, Stripe.", TWOMASS_CC_STRIPE);
150                 fits_add_long_comment(hdr, "    %i: 'b' in 2MASS, Band merge.", TWOMASS_CC_BANDMERGE);
151                 fits_add_long_comment(hdr, "* the association flag values are:");
152                 fits_add_long_comment(hdr, "    %i: none.", TWOMASS_ASSOCIATION_NONE);
153                 fits_add_long_comment(hdr, "    %i: Tycho.", TWOMASS_ASSOCIATION_TYCHO);
154                 fits_add_long_comment(hdr, "    %i: USNO A-2.", TWOMASS_ASSOCIATION_USNOA2);
155                 fits_add_long_comment(hdr, "* the NULL value for floats is %f", TWOMASS_NULL);
156                 fits_add_long_comment(hdr, "* the NULL value for the 'ext_key' aka 'xsc_key' field is");
157                 fits_add_long_comment(hdr, "   %i (0x%x).", TWOMASS_KEY_NULL, TWOMASS_KEY_NULL);
158 
159                 if (twomass_fits_write_headers(cats[hp])) {
160                     fprintf(stderr, "Failed to write 2MASS catalog headers: %s\n", fn);
161                     exit(-1);
162                 }
163             }
164             if (twomass_fits_write_entry(cats[hp], &e)) {
165                 fprintf(stderr, "Failed to write 2MASS catalog entry.\n");
166                 exit(-1);
167             }
168 
169             nentries++;
170             if (!(nentries % 100000)) {
171                 printf(".");
172                 fflush(stdout);
173             }
174         }
175         gzclose(fiz);
176         printf("\n");
177 
178         printf("Read %i entries.\n", nentries);
179     }
180 
181     printf("Finishing up...\n");
182     for (i=0; i<HP; i++) {
183         if (!cats[i])
184             continue;
185         if (twomass_fits_fix_headers(cats[i]) ||
186             twomass_fits_close(cats[i])) {
187             fprintf(stderr, "Failed to close 2MASS catalog.\n");
188             exit(-1);
189         }
190     }
191     free(cats);
192     printf("Done!\n");
193 
194     return 0;
195 }
196 
197