fitsio
fitsio copied to clipboard
filtering by integer bitwise mask when reading bintable not working for large ints
I'm trying to filter on a bitmask while reading a binary table, e.g. following https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node102.html .
It appears that (c)fitsio is treating my integer mask as a float, requiring it to be cast back as an int, which then loses information for the lowest bits when high bits are set because of the int -> float -> int round trip.
Example:
import numpy as np
import fitsio
# create a mask where all bits up to bit n are set
mask = np.array([2**n-1 for n in range(1,64)])
x = np.arange(len(mask))
data = np.core.records.fromarrays([mask,x], names=('mask', 'x'))
filename = 'blat.fits'
fitsio.write(filename, data, clobber=True)
with fitsio.FITS(filename) as fx:
# Trying to use 'mask' directly results in
# OSError: FITSIO status = 431: syntax error in expression
# Bitwise operations with incompatible types; only (bit OP bit) and (int OP int)
# w = fx[1].where('(mask & 1) == 1')
# Cast to (int) avoids error, but misses largest entries
w1 = fx[1].where('((int)mask & 1) == 1')
w2 = np.where((mask & 1) == 1)[0] # w1 should be the same as this but isn't
w3 = np.where((mask.astype(float).astype(int) & 1) == 1)[0] # w1 matches this instead
print(f'{w1=}')
print(f'{w2=}')
print(f'{w3=}')
Results:
w1=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52])
w2=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62])
w3=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52])
Note that w1 (derived with fitsio.FITS.where) is missing the largest masks, but it matches w3 which is derived by casting mask to float and back to int before doing the bitwise masking operation.
I'm using fitsio 1.2.1.