1 /*============================================================================
2 WCSLIB 7.7 - an implementation of the FITS WCS standard.
3 Copyright (C) 1995-2021, Mark Calabretta
4
5 This file is part of WCSLIB.
6
7 WCSLIB is free software: you can redistribute it and/or modify it under the
8 terms of the GNU Lesser General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or (at your option)
10 any later version.
11
12 WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with WCSLIB. If not, see http://www.gnu.org/licenses.
19
20 Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
21 http://www.atnf.csiro.au/people/Mark.Calabretta
22 $Id: tfitshdr.c,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
23 *=============================================================================
24 *
25 * tfitshdr tests fitshdr(), the FITS parser for image headers, by reading a
26 * test header and printing the resulting fitskey structs.
27 *
28 * Input comes from file 'fitshdr.fits' using either fits_hdr2str() from
29 * CFITSIO if the DO_CFITSIO preprocessor is defined, or read directly using
30 * fgets() otherwise.
31 *
32 * wcshdr() is called first to extract all WCS-related keyrecords from the
33 * input header before passing it on to fitshdr().
34 *
35 *---------------------------------------------------------------------------*/
36
37 #include <wcsconfig_tests.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #if defined HAVE_CFITSIO && defined DO_CFITSIO
44 #include <fitsio.h>
45 #endif
46
47 #include <fitshdr.h>
48 #include <wcshdr.h>
49 #include <wcsutil.h>
50
main()51 int main()
52
53 {
54 char infile[] = "fitshdr.fits";
55 char text[80];
56 int i, j, k, nkeyrec, nkeyids, nreject, status;
57 struct fitskey *keys, *kptr;
58 struct fitskeyid keyids[8];
59 #if defined HAVE_CFITSIO && defined DO_CFITSIO
60 char *header;
61 fitsfile *fptr;
62 #else
63 char keyrec[81], header[288001];
64 int end;
65 FILE *fptr;
66 #endif
67
68 struct wcsprm *wcs;
69 int ctrl, nwcs, relax;
70
71
72 // Set line buffering in case stdout is redirected to a file, otherwise
73 // stdout and stderr messages will be jumbled (stderr is unbuffered).
74 setvbuf(stdout, NULL, _IOLBF, 0);
75
76 printf("Testing FITS image header parser (tfitshdr.c)\n"
77 "---------------------------------------------\n\n");
78
79 // Read in the FITS header.
80 #if defined HAVE_CFITSIO && defined DO_CFITSIO
81 status = 0;
82
83 if (fits_open_file(&fptr, infile, READONLY, &status)) {
84 fits_report_error(stderr, status);
85 return 1;
86 }
87
88 if (fits_hdr2str(fptr, 0, NULL, 0, &header, &nkeyrec, &status)) {
89 fits_report_error(stderr, status);
90 return 1;
91 }
92
93 fits_close_file(fptr, &status);
94 #else
95 if ((fptr = fopen(infile, "r")) == 0) {
96 printf("ERROR opening %s\n", infile);
97 return 1;
98 }
99
100 k = 0;
101 end = 0;
102 nkeyrec = 0;
103 for (j = 0; j < 100; j++) {
104 for (i = 0; i < 36; i++) {
105 if (fgets(keyrec, 81, fptr) == 0) {
106 break;
107 }
108
109 memcpy(header+k, keyrec, 80);
110 k += 80;
111 nkeyrec++;
112
113 if (strncmp(keyrec, "END ", 10) == 0) {
114 // An END keyrecord was read, but read the rest of the block.
115 end = 1;
116 }
117 }
118
119 if (end) break;
120 }
121 fclose(fptr);
122 #endif
123
124 printf("Found %d header keyrecords.\n", nkeyrec);
125
126
127 // Cull recognized, syntactically valid WCS keyrecords from the header.
128 relax = WCSHDR_all;
129 ctrl = -1;
130 if ((status = wcspih(header, nkeyrec, relax, ctrl, &nreject, &nwcs,
131 &wcs))) {
132 fprintf(stderr, "wcspih ERROR %d: %s.\n", status, wcs_errmsg[status]);
133 return 1;
134 }
135 wcsvfree(&nwcs, &wcs);
136
137 // Number remaining.
138 nkeyrec = strlen(header) / 80;
139
140
141 // Specific keywords to be located or culled.
142 strcpy(keyids[0].name, "SIMPLE ");
143 strcpy(keyids[1].name, "BITPIX ");
144 strcpy(keyids[2].name, "NAXIS ");
145 strcpy(keyids[3].name, "COMMENT ");
146 strcpy(keyids[4].name, "HISTORY ");
147 strcpy(keyids[5].name, " ");
148 strcpy(keyids[6].name, "END ");
149 nkeyids = 7;
150
151 if (nkeyids) {
152 printf("\nThe following keyrecords will not be listed:\n");
153 for (i = 0; i < nkeyids; i++) {
154 printf(" \"%8s\"\n", keyids[i].name);
155 }
156 }
157
158
159 // Parse the header.
160 if ((status = fitshdr(header, nkeyrec, nkeyids, keyids, &nreject, &keys))) {
161 printf("fitskey ERROR %d: %s.\n", status, fitshdr_errmsg[status]);
162 }
163 #if defined HAVE_CFITSIO && defined DO_CFITSIO
164 fits_free_memory(header, &status);
165 #endif
166
167 // Report the results.
168 printf("\n%d header keyrecords parsed by fitshdr(), %d rejected:\n\n",
169 nkeyrec, nreject);
170 kptr = keys;
171 for (i = 0; i < nkeyrec; i++, kptr++) {
172 // Skip syntactically valid keyrecords that were indexed.
173 if (kptr->keyno < 0 && !kptr->status) continue;
174
175 // Basic keyrecord info.
176 printf("%4d%5d %-8s%3d", kptr->keyno, kptr->status, kptr->keyword,
177 kptr->type);
178
179 // Format the keyvalue for output.
180 switch (abs(kptr->type)%10) {
181 case 1:
182 // Logical.
183 sprintf(text, "%c", kptr->keyvalue.i?'T':'F');
184 break;
185 case 2:
186 // 32-bit signed integer.
187 sprintf(text, "%d", kptr->keyvalue.i);
188 break;
189 case 3:
190 // 64-bit signed integer.
191 #ifdef WCSLIB_INT64
192 sprintf(text, "%+lld", kptr->keyvalue.k);
193 #else
194 if (kptr->keyvalue.k[2]) {
195 sprintf(text, "%+d%09d%09d", kptr->keyvalue.k[2],
196 abs(kptr->keyvalue.k[1]),
197 abs(kptr->keyvalue.k[0]));
198 } else {
199 sprintf(text, "%+d%09d", kptr->keyvalue.k[1],
200 abs(kptr->keyvalue.k[0]));
201 }
202 #endif
203 break;
204 case 4:
205 // Very long integer.
206 k = 0;
207 for (j = 7; j > 0; j--) {
208 if (kptr->keyvalue.l[j]) {
209 k = j;
210 break;
211 }
212 }
213
214 sprintf(text, "%+d", kptr->keyvalue.l[k]);
215 for (j = k-1; j >= 0; j--) {
216 sprintf(text+strlen(text), "%09d", abs(kptr->keyvalue.l[j]));
217 }
218
219 break;
220 case 5:
221 // Float.
222 sprintf(text, "%+13.6e", kptr->keyvalue.f);
223 break;
224 case 6:
225 // Int complex.
226 sprintf(text, "%.0f %.0f", kptr->keyvalue.c[0],
227 kptr->keyvalue.c[1]);
228 break;
229 case 7:
230 // Float complex.
231 sprintf(text, "%+13.6e %+13.6e", kptr->keyvalue.c[0],
232 kptr->keyvalue.c[1]);
233 break;
234 case 8:
235 // String.
236 sprintf(text, "\"%s\"", kptr->keyvalue.s);
237 break;
238 default:
239 // No value.
240 *text = '\0';
241 break;
242 }
243
244 if (kptr->type > 0) {
245 // Keyvalue successfully extracted.
246 printf(" %s", text);
247 } else if (kptr->type < 0) {
248 // Syntax error of some type while extracting the keyvalue.
249 printf(" (%s)", text);
250 }
251
252 // Units?
253 if (kptr->ulen) {
254 printf(" %.*s", kptr->ulen-2, kptr->comment+1);
255 }
256
257 // Comment text or reject keyrecord.
258 printf("\n%s\n", kptr->comment);
259 }
260
261
262 // Print indexes.
263 printf("\n\nIndexes of selected keywords:\n");
264 for (i = 0; i < nkeyids; i++) {
265 printf("%-8s%5d%5d%5d", keyids[i].name, keyids[i].count, keyids[i].idx[0],
266 keyids[i].idx[1]);
267
268 // Print logical (SIMPLE) and integer (BITPIX, NAXIS) values.
269 if (keyids[i].count) {
270 kptr = keys + keyids[i].idx[0];
271 printf("%4d", kptr->type);
272
273 if (kptr->type == 1) {
274 printf("%5c", kptr->keyvalue.i?'T':'F');
275 } else if (kptr->type == 2) {
276 printf("%5d", kptr->keyvalue.i);
277 }
278 }
279 printf("\n");
280 }
281
282 wcsdealloc(keys);
283
284 return 0;
285 }
286