WCSLIB: fitshdr.h Source File

WCSLIB 7.1

fitshdr.h
Go to the documentation of this file.
1 /*============================================================================
2
3 WCSLIB 7.1 - an implementation of the FITS WCS standard.
4 Copyright (C) 1995-2020, Mark Calabretta
5
6 This file is part of WCSLIB.
7
8 WCSLIB is free software: you can redistribute it and/or modify it under the
9 terms of the GNU Lesser General Public License as published by the Free
10 Software Foundation, either version 3 of the License, or (at your option)
11 any later version.
12
13 WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16 more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with WCSLIB. If not, see http://www.gnu.org/licenses.
20
21 Direct correspondence concerning WCSLIB to mark@calabretta.id.au
22
23 Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
24 http://www.atnf.csiro.au/people/Mark.Calabretta
25 $Id: fitshdr.h,v 7.1 2019/12/31 13:25:19 mcalabre Exp $
26 *=============================================================================
27 *
28 * WCSLIB 7.1 - C routines that implement the FITS World Coordinate System
29 * (WCS) standard. Refer to the README file provided with WCSLIB for an
30 * overview of the library.
31 *
32 *
33 * Summary of the fitshdr routines
34 * -------------------------------
35 * The Flexible Image Transport System (FITS), is a data format widely used in
36 * astronomy for data interchange and archive. It is described in
37 *
38 = "Definition of the Flexible Image Transport System (FITS), version 3.0",
39 = Pence, W.D., Chiappetti, L., Page, C.G., Shaw, R.A., & Stobie, E. 2010,
40 = A&A, 524, A42 - http://dx.doi.org/10.1051/0004-6361/201015362
41 *
42 * See also http://fits.gsfc.nasa.gov
43 *
44 * fitshdr() is a generic FITS header parser provided to handle keyrecords that
45 * are ignored by the WCS header parsers, wcspih() and wcsbth(). Typically the
46 * latter may be set to remove WCS keyrecords from a header leaving fitshdr()
47 * to handle the remainder.
48 *
49 *
50 * fitshdr() - FITS header parser routine
51 * --------------------------------------
52 * fitshdr() parses a character array containing a FITS header, extracting
53 * all keywords and their values into an array of fitskey structs.
54 *
55 * Given:
56 * header const char []
57 * Character array containing the (entire) FITS header,
58 * for example, as might be obtained conveniently via the
59 * CFITSIO routine fits_hdr2str().
60 *
61 * Each header "keyrecord" (formerly "card image")
62 * consists of exactly 80 7-bit ASCII printing characters
63 * in the range 0x20 to 0x7e (which excludes NUL, BS,
64 * TAB, LF, FF and CR) especially noting that the
65 * keyrecords are NOT null-terminated.
66 *
67 * nkeyrec int Number of keyrecords in header[].
68 *
69 * nkeyids int Number of entries in keyids[].
70 *
71 * Given and returned:
72 * keyids struct fitskeyid []
73 * While all keywords are extracted from the header,
74 * keyids[] provides a convienient way of indexing them.
75 * The fitskeyid struct contains three members;
76 * fitskeyid::name must be set by the user while
77 * fitskeyid::count and fitskeyid::idx are returned by
78 * fitshdr(). All matched keywords will have their
79 * fitskey::keyno member negated.
80 *
81 * Returned:
82 * nreject int* Number of header keyrecords rejected for syntax
83 * errors.
84 *
85 * keys struct fitskey**
86 * Pointer to an array of nkeyrec fitskey structs
87 * containing all keywords and keyvalues extracted from
88 * the header.
89 *
90 * Memory for the array is allocated by fitshdr() and
91 * this must be freed by the user. See wcsdealloc().
92 *
93 * Function return value:
94 * int Status return value:
95 * 0: Success.
96 * 1: Null fitskey pointer passed.
97 * 2: Memory allocation failed.
98 * 3: Fatal error returned by Flex parser.
99 *
100 * Notes:
101 * 1: Keyword parsing is done in accordance with the syntax defined by
102 * NOST 100-2.0, noting the following points in particular:
103 *
104 * a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
105 * 1-8, blank-filled with no embedded spaces, composed only of the
106 * ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
107 *
108 * fitshdr() accepts any characters in columns 1-8 but flags keywords
109 * that do not conform to standard syntax.
110 *
111 * b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
112 * occurring in columns 9 and 10. If these are absent then the
113 * keyword has no value and columns 9-80 may contain any ASCII text
114 * (but see note 2 for CONTINUE keyrecords). This is copied to the
115 * comment member of the fitskey struct.
116 *
117 * c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
118 * value if the value/comment field, columns 11-80, consists entirely
119 * of spaces, possibly followed by a comment.
120 *
121 * d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
122 * not significant and the parser always removes them. A string
123 * containing nothing but blanks will be replaced with a single
124 * blank.
125 *
126 * Sect. 5.2.1 also states that a quote character (') in a string
127 * value is to be represented by two successive quote characters and
128 * the parser removes the repeated quote.
129 *
130 * e: The parser recognizes free-format character (NOST 100-2.0,
131 * Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
132 * (Sect. 5.2.4) for all keywords.
133 *
134 * f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
135 * except indirectly in limiting it to 70 digits. The parser will
136 * translate an integer keyvalue to a 32-bit signed integer if it
137 * lies in the range -2147483648 to +2147483647, otherwise it
138 * interprets it as a 64-bit signed integer if possible, or else a
139 * "very long" integer (see fitskey::type).
140 *
141 * g: END not followed by 77 blanks is not considered to be a legitimate
142 * end keyrecord.
143 *
144 * 2: The parser supports a generalization of the OGIP Long String Keyvalue
145 * Convention (v1.0) whereby strings may be continued onto successive
146 * header keyrecords. A keyrecord contains a segment of a continued
147 * string if and only if
148 *
149 * a: it contains the pseudo-keyword CONTINUE,
150 *
151 * b: columns 9 and 10 are both blank,
152 *
153 * c: columns 11 to 80 contain what would be considered a valid string
154 * keyvalue, including optional keycomment, if column 9 had contained
155 * '=',
156 *
157 * d: the previous keyrecord contained either a valid string keyvalue or
158 * a valid CONTINUE keyrecord.
159 *
160 * If any of these conditions is violated, the keyrecord is considered in
161 * isolation.
162 *
163 * Syntax errors in keycomments in a continued string are treated more
164 * permissively than usual; the '/' delimiter may be omitted provided that
165 * parsing of the string keyvalue is not compromised. However, the
166 * FITSHDR_COMMENT status bit will be set for the keyrecord (see
167 * fitskey::status).
168 *
169 * As for normal strings, trailing blanks in a continued string are not
170 * significant.
171 *
172 * In the OGIP convention "the '&' character is used as the last non-blank
173 * character of the string to indicate that the string is (probably)
174 * continued on the following keyword". This additional syntax is not
175 * required by fitshdr(), but if '&' does occur as the last non-blank
176 * character of a continued string keyvalue then it will be removed, along
177 * with any trailing blanks. However, blanks that occur before the '&'
178 * will be preserved.
179 *
180 *
181 * fitskeyid struct - Keyword indexing
182 * -----------------------------------
183 * fitshdr() uses the fitskeyid struct to return indexing information for
184 * specified keywords. The struct contains three members, the first of which,
185 * fitskeyid::name, must be set by the user with the remainder returned by
186 * fitshdr().
187 *
188 * char name[12]:
189 * (Given) Name of the required keyword. This is to be set by the user;
190 * the '.' character may be used for wildcarding. Trailing blanks will be
191 * replaced with nulls.
192 *
193 * int count:
194 * (Returned) The number of matches found for the keyword.
195 *
196 * int idx[2]:
197 * (Returned) Indices into keys[], the array of fitskey structs returned by
198 * fitshdr(). Note that these are 0-relative array indices, not keyrecord
199 * numbers.
200 *
201 * If the keyword is found in the header the first index will be set to the
202 * array index of its first occurrence, otherwise it will be set to -1.
203 *
204 * If multiples of the keyword are found, the second index will be set to
205 * the array index of its last occurrence, otherwise it will be set to -1.
206 *
207 *
208 * fitskey struct - Keyword/value information
209 * ------------------------------------------
210 * fitshdr() returns an array of fitskey structs, each of which contains the
211 * result of parsing one FITS header keyrecord. All members of the fitskey
212 * struct are returned by fitshdr(), none are given by the user.
213 *
214 * int keyno
215 * (Returned) Keyrecord number (1-relative) in the array passed as input to
216 * fitshdr(). This will be negated if the keyword matched any specified in
217 * the keyids[] index.
218 *
219 * int keyid
220 * (Returned) Index into the first entry in keyids[] with which the
221 * keyrecord matches, else -1.
222 *
223 * int status
224 * (Returned) Status flag bit-vector for the header keyrecord employing the
225 * following bit masks defined as preprocessor macros:
226 *
227 * - FITSHDR_KEYWORD: Illegal keyword syntax.
228 * - FITSHDR_KEYVALUE: Illegal keyvalue syntax.
229 * - FITSHDR_COMMENT: Illegal keycomment syntax.
230 * - FITSHDR_KEYREC: Illegal keyrecord, e.g. an END keyrecord with
231 * trailing text.
232 * - FITSHDR_TRAILER: Keyrecord following a valid END keyrecord.
233 *
234 * The header keyrecord is syntactically correct if no bits are set.
235 *
236 * char keyword[12]
237 * (Returned) Keyword name, null-filled for keywords of less than eight
238 * characters (trailing blanks replaced by nulls).
239 *
240 * Use
241 *
242 = sprintf(dst, "%.8s", keyword)
243 *
244 * to copy it to a character array with null-termination, or
245 *
246 = sprintf(dst, "%8.8s", keyword)
247 *
248 * to blank-fill to eight characters followed by null-termination.
249 *
250 * int type
251 * (Returned) Keyvalue data type:
252 * - 0: No keyvalue (both the value and type are undefined).
253 * - 1: Logical, represented as int.
254 * - 2: 32-bit signed integer.
255 * - 3: 64-bit signed integer (see below).
256 * - 4: Very long integer (see below).
257 * - 5: Floating point (stored as double).
258 * - 6: Integer complex (stored as double[2]).
259 * - 7: Floating point complex (stored as double[2]).
260 * - 8: String.
261 * - 8+10*n: Continued string (described below and in fitshdr() note 2).
262 *
263 * A negative type indicates that a syntax error was encountered when
264 * attempting to parse a keyvalue of the particular type.
265 *
266 * Comments on particular data types:
267 * - 64-bit signed integers lie in the range
268 *
269 = (-9223372036854775808 <= int64 < -2147483648) ||
270 = (+2147483647 < int64 <= +9223372036854775807)
271 *
272 * A native 64-bit data type may be defined via preprocessor macro
273 * WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
274 * will be typedef'd to 'int64' here. If WCSLIB_INT64 is not set, then
275 * int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
276 * computed as
277 *
278 = ((keyvalue.k[2]) * 1000000000 +
279 = keyvalue.k[1]) * 1000000000 +
280 = keyvalue.k[0]
281 *
282 * and may reported via
283 *
284 = if (keyvalue.k[2]) {
285 = printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
286 = abs(keyvalue.k[0]));
287 = } else {
288 = printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
289 = }
290 *
291 * where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
292 * +999999999.
293 *
294 * - Very long integers, up to 70 decimal digits in length, are encoded
295 * in keyvalue.l as an array of int[8], each of which stores 9 decimal
296 * digits. fitskey::keyvalue is to be computed as
297 *
298 = (((((((keyvalue.l[7]) * 1000000000 +
299 = keyvalue.l[6]) * 1000000000 +
300 = keyvalue.l[5]) * 1000000000 +
301 = keyvalue.l[4]) * 1000000000 +
302 = keyvalue.l[3]) * 1000000000 +
303 = keyvalue.l[2]) * 1000000000 +
304 = keyvalue.l[1]) * 1000000000 +
305 = keyvalue.l[0]
306 *
307 * - Continued strings are not reconstructed, they remain split over
308 * successive fitskey structs in the keys[] array returned by
309 * fitshdr(). fitskey::keyvalue data type, 8 + 10n, indicates the
310 * segment number, n, in the continuation.
311 *
312 * int padding
313 * (An unused variable inserted for alignment purposes only.)
314 *
315 * union keyvalue
316 * (Returned) A union comprised of
317 *
318 * - fitskey::i,
319 * - fitskey::k,
320 * - fitskey::l,
321 * - fitskey::f,
322 * - fitskey::c,
323 * - fitskey::s,
324 *
325 * used by the fitskey struct to contain the value associated with a
326 * keyword.
327 *
328 * int i
329 * (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
330 * (fitskey::type == 2) data types in the fitskey::keyvalue union.
331 *
332 * int64 k
333 * (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
334 * fitskey::keyvalue union.
335 *
336 * int l[8]
337 * (Returned) Very long integer (fitskey::type == 4) data type in the
338 * fitskey::keyvalue union.
339 *
340 * double f
341 * (Returned) Floating point (fitskey::type == 5) data type in the
342 * fitskey::keyvalue union.
343 *
344 * double c[2]
345 * (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
346 * data types in the fitskey::keyvalue union.
347 *
348 * char s[72]
349 * (Returned) Null-terminated string (fitskey::type == 8) data type in the
350 * fitskey::keyvalue union.
351 *
352 * int ulen
353 * (Returned) Where a keycomment contains a units string in the standard
354 * form, e.g. [m/s], the ulen member indicates its length, inclusive of
355 * square brackets. Otherwise ulen is zero.
356 *
357 * char comment[84]
358 * (Returned) Keycomment, i.e. comment associated with the keyword or, for
359 * keyrecords rejected because of syntax errors, the compete keyrecord
360 * itself with null-termination.
361 *
362 * Comments are null-terminated with trailing spaces removed. Leading
363 * spaces are also removed from keycomments (i.e. those immediately
364 * following the '/' character), but not from COMMENT or HISTORY keyrecords
365 * or keyrecords without a value indicator ("= " in columns 9-80).
366 *
367 *
368 * Global variable: const char *fitshdr_errmsg[] - Status return messages
369 * ----------------------------------------------------------------------
370 * Error messages to match the status value returned from each function.
371 *
372 *===========================================================================*/
373
374 #ifndef WCSLIB_FITSHDR
375 #define WCSLIB_FITSHDR
376
377 #include "wcsconfig.h"
378
379 #ifdef __cplusplus
380 extern "C" {
381 #endif
382
383 #define FITSHDR_KEYWORD 0x01
384 #define FITSHDR_KEYVALUE 0x02
385 #define FITSHDR_COMMENT 0x04
386 #define FITSHDR_KEYREC 0x08
387 #define FITSHDR_CARD 0x08 /* Alias for backwards compatibility. */
388 #define FITSHDR_TRAILER 0x10
389
390
391 extern const char *fitshdr_errmsg[];
392
393 enum fitshdr_errmsg_enum {
394 FITSHDRERR_SUCCESS = 0, /* Success. */
395 FITSHDRERR_NULL_POINTER = 1, /* Null fitskey pointer passed. */
396 FITSHDRERR_MEMORY = 2, /* Memory allocation failed. */
397 FITSHDRERR_FLEX_PARSER = 3 /* Fatal error returned by Flex parser. */
398 };
399
400 #ifdef WCSLIB_INT64
401 typedef WCSLIB_INT64 int64;
402 #else
403 typedef int int64[3];
404 #endif
405
406
407 /* Struct used for indexing the keywords. */
408 struct fitskeyid {
409 char name[12]; /* Keyword name, null-terminated. */
410 int count; /* Number of occurrences of keyword. */
411 int idx[2]; /* Indices into fitskey array. */
412 };
413
414 /* Size of the fitskeyid struct in int units, used by the Fortran wrappers. */
415 #define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
416
417
418 /* Struct used for storing FITS keywords. */
419 struct fitskey {
420 int keyno; /* Header keyrecord sequence number (1-rel).*/
421 int keyid; /* Index into fitskeyid[]. */
422 int status; /* Header keyrecord status bit flags. */
423 char keyword[12]; /* Keyword name, null-filled. */
424 int type; /* Keyvalue type (see above). */
425 int padding; /* (Dummy inserted for alignment purposes.) */
426 union {
427 int i; /* 32-bit integer and logical values. */
428 int64 k; /* 64-bit integer values. */
429 int l[8]; /* Very long signed integer values. */
430 double f; /* Floating point values. */
431 double c[2]; /* Complex values. */
432 char s[72]; /* String values, null-terminated. */
433 } keyvalue; /* Keyvalue. */
434 int ulen; /* Length of units string. */
435 char comment[84]; /* Comment (or keyrecord), null-terminated. */
436 };
437
438 /* Size of the fitskey struct in int units, used by the Fortran wrappers. */
439 #define KEYLEN (sizeof(struct fitskey)/sizeof(int))
440
441
442 int fitshdr(const char header[], int nkeyrec, int nkeyids,
443 struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
444
445
446 #ifdef __cplusplus
447 }
448 #endif
449
450 #endif /* WCSLIB_FITSHDR */
FITSHDRERR_MEMORY
@ FITSHDRERR_MEMORY
Definition: fitshdr.h:396
fitskey::comment
char comment[84]
Definition: fitshdr.h:435
fitskey::type
int type
Definition: fitshdr.h:424
fitskey::keyid
int keyid
Definition: fitshdr.h:421
FITSHDRERR_FLEX_PARSER
@ FITSHDRERR_FLEX_PARSER
Definition: fitshdr.h:397
fitskey::c
double c[2]
Definition: fitshdr.h:431
fitskey::keyno
int keyno
Definition: fitshdr.h:420
fitskey::i
int i
Definition: fitshdr.h:427
fitskey::s
char s[72]
Definition: fitshdr.h:432
fitskeyid::idx
int idx[2]
Definition: fitshdr.h:411
fitskeyid::name
char name[12]
Definition: fitshdr.h:409
fitskey::status
int status
Definition: fitshdr.h:422
fitskey::keyvalue
union fitskey::@1 keyvalue
fitskey::k
int64 k
Definition: fitshdr.h:428
int64
int int64[3]
64-bit signed integer data type.
Definition: fitshdr.h:403
fitskeyid::count
int count
Definition: fitshdr.h:410
fitshdr
int fitshdr(const char header[], int nkeyrec, int nkeyids, struct fitskeyid keyids[], int *nreject, struct fitskey **keys)
FITS header parser routine.
fitskey::f
double f
Definition: fitshdr.h:430
fitshdr_errmsg_enum
fitshdr_errmsg_enum
Definition: fitshdr.h:393
fitskey::keyword
char keyword[12]
Definition: fitshdr.h:423
fitskey::ulen
int ulen
Definition: fitshdr.h:434
FITSHDRERR_NULL_POINTER
@ FITSHDRERR_NULL_POINTER
Definition: fitshdr.h:395
fitskey::padding
int padding
Definition: fitshdr.h:425
fitskey
Keyword/value information.
Definition: fitshdr.h:419
fitskey::l
int l[8]
Definition: fitshdr.h:429
fitskeyid
Keyword indexing.
Definition: fitshdr.h:408
fitshdr_errmsg
const char * fitshdr_errmsg[]
Status return messages.
FITSHDRERR_SUCCESS
@ FITSHDRERR_SUCCESS
Definition: fitshdr.h:394