1 /*
2 # This file is part of the Astrometry.net suite.
3 # Licensed under a 3-clause BSD style license - see LICENSE
4 */
5
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include <string.h>
11
12 #include "startree.h"
13 #include "fitstable.h"
14 #include "boilerplate.h"
15 #include "errors.h"
16 #include "log.h"
17 #include "fitsioutils.h"
18
19 const char* OPTIONS = "hvL:d:t:bsSci:o:R:D:PTkn:";
20
printHelp(char * progname)21 void printHelp(char* progname) {
22 BOILERPLATE_HELP_HEADER(stdout);
23 printf("\nUsage: %s\n"
24 " -i <input-fits-catalog-name>\n"
25 " -o <output-star-kdtree-name>\n"
26 " [-R <ra-column-name>]: name of RA in FITS table (default RA)\n"
27 " [-D <dec-column-name>]: name of DEC in FITS table (default DEC)\n"
28 " [-b]: build bounding boxes (default: splitting planes)\n"
29 " [-L Nleaf]: number of points in a kdtree leaf node (default 25)\n"
30 " [-t <tree type>]: {double,float,u32,u16}, default u32.\n"
31 " [-d <data type>]: {double,float,u32,u16}, default u32.\n"
32 " [-S]: include separate splitdim array\n"
33 " [-c]: run kdtree_check on the resulting tree\n"
34 " [-P]: unpermute tree + tag-along data\n"
35 " [-T]: write tag-along table as first extension HDU\n"
36 " [-k]: keep RA,Dec columns in tag-along table\n"
37 " [-n <name>]: kd-tree name (default \"stars\")\n"
38 " [-v]: +verbose\n"
39 "\n", progname);
40 }
41
42
main(int argc,char * argv[])43 int main(int argc, char *argv[]) {
44 int argidx, argchar;
45 startree_t* starkd;
46 fitstable_t* cat;
47 fitstable_t* tag;
48 int Nleaf = 0;
49 char* skdtfn = NULL;
50 char* catfn = NULL;
51 char* progname = argv[0];
52 char* racol = NULL;
53 char* deccol = NULL;
54 int loglvl = LOG_MSG;
55 char* treename = NULL;
56
57 int datatype = 0;
58 int treetype = 0;
59 int buildopts = 0;
60 anbool checktree = FALSE;
61 anbool unpermute = FALSE;
62 anbool remove_radec = TRUE;
63 u32* perm = NULL;
64 anbool tagalong_first = FALSE;
65
66 if (argc <= 2) {
67 printHelp(progname);
68 return 0;
69 }
70
71 while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
72 switch (argchar) {
73 case 'T':
74 tagalong_first = TRUE;
75 break;
76 case 'n':
77 treename = optarg;
78 break;
79 case 'k':
80 remove_radec = FALSE;
81 break;
82 case 'P':
83 unpermute = TRUE;
84 break;
85 case 'R':
86 racol = optarg;
87 break;
88 case 'D':
89 deccol = optarg;
90 break;
91 case 'c':
92 checktree = TRUE;
93 break;
94 case 'L':
95 Nleaf = (int)strtoul(optarg, NULL, 0);
96 break;
97 case 'i':
98 catfn = optarg;
99 break;
100 case 'o':
101 skdtfn = optarg;
102 break;
103 case 't':
104 treetype = kdtree_kdtype_parse_tree_string(optarg);
105 break;
106 case 'd':
107 datatype = kdtree_kdtype_parse_data_string(optarg);
108 break;
109 case 'b':
110 buildopts |= KD_BUILD_BBOX;
111 break;
112 case 's':
113 buildopts |= KD_BUILD_SPLIT;
114 break;
115 case 'S':
116 buildopts |= KD_BUILD_SPLITDIM;
117 break;
118 case 'v':
119 loglvl++;
120 break;
121 case '?':
122 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
123 case 'h':
124 printHelp(progname);
125 return 0;
126 default:
127 return -1;
128 }
129
130 if (optind < argc) {
131 for (argidx = optind; argidx < argc; argidx++)
132 fprintf (stderr, "Non-option argument %s\n", argv[argidx]);
133 printHelp(progname);
134 exit(-1);
135 }
136
137 if (!(catfn && skdtfn)) {
138 printHelp(progname);
139 exit(-1);
140 }
141
142 log_init(loglvl);
143 fits_use_error_system();
144
145 logmsg("Building star kdtree: reading %s, writing to %s\n", catfn, skdtfn);
146
147 logverb("Reading star catalogue...");
148 cat = fitstable_open(catfn);
149 if (!cat) {
150 ERROR("Couldn't read catalog");
151 exit(-1);
152 }
153 logmsg("Got %i stars\n", fitstable_nrows(cat));
154
155 starkd = startree_build(cat, racol, deccol, datatype, treetype,
156 buildopts, Nleaf, argv, argc);
157 if (!starkd) {
158 ERROR("Failed to create star kdtree");
159 exit(-1);
160 }
161 if (checktree) {
162 logverb("Checking tree...\n");
163 if (kdtree_check(starkd->tree)) {
164 ERROR("kdtree_check failed!");
165 exit(-1);
166 }
167 }
168
169 if (treename) {
170 free(starkd->tree->name);
171 starkd->tree->name = strdup(treename);
172 }
173
174 if (unpermute) {
175 perm = starkd->tree->perm;
176 starkd->tree->perm = NULL;
177 }
178
179 if (tagalong_first) {
180 logmsg("Writing tag-along data...\n");
181 tag = fitstable_open_for_writing(skdtfn);
182 if (fitstable_write_primary_header(tag)) {
183 ERROR("Failed to write primary header");
184 exit(-1);
185 }
186 if (startree_write_tagalong_table(cat, tag, racol, deccol,
187 (int*)perm, remove_radec)) {
188 ERROR("Failed to write tag-along table");
189 exit(-1);
190 }
191 if (fitstable_close(tag)) {
192 ERROR("Failed to close tag-along data");
193 exit(-1);
194 }
195 // Append kd-tree
196 logverb("Appending kd-tree structure...\n");
197 FILE* fid = fopen(skdtfn, "r+b");
198 if (!fid) {
199 SYSERROR("Failed to open startree output file to append kd-tree: %s", skdtfn);
200 exit(-1);
201 }
202 if (fseeko(fid, 0, SEEK_END)) {
203 SYSERROR("Failed to seek to the end of the startree file to append kd-tree: %s", skdtfn);
204 exit(-1);
205 }
206 off_t off = ftello(fid);
207 printf("Offset to write starkd: %lu\n", (unsigned long)off);
208
209 if (startree_append_to(starkd, fid)) {
210 ERROR("Failed to append star kdtree");
211 exit(-1);
212 }
213 startree_close(starkd);
214 if (fclose(fid)) {
215 SYSERROR("Failed to close star kdtree file after appending tree\n");
216 exit(-1);
217 }
218 } else {
219 if (startree_write_to_file(starkd, skdtfn)) {
220 ERROR("Failed to write star kdtree");
221 exit(-1);
222 }
223 startree_close(starkd);
224
225 // Append tag-along table.
226 logmsg("Writing tag-along data...\n");
227 tag = fitstable_open_for_appending(skdtfn);
228
229 if (startree_write_tagalong_table(cat, tag, racol, deccol,
230 (int*)perm, remove_radec)) {
231 ERROR("Failed to write tag-along table");
232 exit(-1);
233 }
234
235 if (fitstable_close(tag)) {
236 ERROR("Failed to close tag-along data");
237 exit(-1);
238 }
239 }
240 fitstable_close(cat);
241 return 0;
242 }
243
244
245