1# cython: language_level=3 2from collections import OrderedDict 3 4cdef Py_ssize_t BLOCK_SIZE = 2880 # the FITS block size 5cdef Py_ssize_t CARD_LENGTH = 80 6cdef str VALUE_INDICATOR = '= ' # The standard FITS value indicator 7cdef str END_CARD = 'END' + ' ' * 77 8 9 10def parse_header(fileobj): 11 """Fast (and incomplete) parser for FITS headers. 12 13 This parser only reads the standard 8 character keywords, and ignores the 14 CONTINUE, COMMENT, HISTORY and HIERARCH cards. The goal is to find quickly 15 the structural keywords needed to build the HDU objects. 16 17 The implementation is straightforward: first iterate on the 2880-bytes 18 blocks, then iterate on the 80-bytes cards, find the value separator, and 19 store the parsed (keyword, card image) in a dictionary. 20 21 """ 22 23 cards = OrderedDict() 24 cdef list read_blocks = [] 25 cdef int found_end = 0 26 cdef bytes block 27 cdef str header_str, block_str, card_image, keyword 28 cdef Py_ssize_t idx, end_idx, sep_idx 29 30 while found_end == 0: 31 # iterate on blocks 32 block = fileobj.read(BLOCK_SIZE) 33 if not block or len(block) < BLOCK_SIZE: 34 # header looks incorrect, raising exception to fall back to 35 # the full Header parsing 36 raise Exception 37 38 block_str = block.decode('ascii') 39 read_blocks.append(block_str) 40 idx = 0 41 while idx < BLOCK_SIZE: 42 # iterate on cards 43 end_idx = idx + CARD_LENGTH 44 card_image = block_str[idx:end_idx] 45 idx = end_idx 46 47 # We are interested only in standard keyword, so we skip 48 # other cards, e.g. CONTINUE, HIERARCH, COMMENT. 49 if card_image[8:10] == VALUE_INDICATOR: 50 # ok, found standard keyword 51 keyword = card_image[:8].strip() 52 cards[keyword.upper()] = card_image 53 else: 54 sep_idx = card_image.find(VALUE_INDICATOR, 0, 8) 55 if sep_idx > 0: 56 keyword = card_image[:sep_idx] 57 cards[keyword.upper()] = card_image 58 elif card_image == END_CARD: 59 found_end = 1 60 break 61 62 # we keep the full header string as it may be needed later to 63 # create a Header object 64 header_str = ''.join(read_blocks) 65 return header_str, cards 66