I have a very simple operation to perform on a FITS file (data is numpy array format) but I cannot get astropy to either save it as a new file or overwrite the existing one.
I'm re-writing some old code that used the numpy pyfits module to work with astronomical FITS files - I want to update this to use the astropy.io fits module. Specifically, some data that I work with is 3D and some is 4D. The 4D stuff is just a convention - the 4th axis contains no useful information (an example of the data can be found here : http://www.mpia.de/THINGS/Data_files/NGC_628_NA_CUBE_THINGS.FITS). So I prefer to remove the extra axis and then the rest of my code can carry on without any special requirements.
Here's the old pyfits-based code I used that works perfectly :
import numpy
import pyfits
filename = 'NGC628.fits'
outfile = 'NGC628_reshaped.fits'
# Get the shape of the file
fitsfile=pyfits.open(filename)
image = fitsfile[0].data
header =fitsfile[0].header
z = image.shape[1] # No. channels
y = image.shape[2] # No. x pixels
x = image.shape[3] # No. y pixels
newimage = numpy.reshape(image,[z,y,x])
pyfits.core.writeto(outfile,newimage,header, clobber=True)
Nothing complicated there, it just reshapes an array and saves it to a new file. Marvellous. Now I want to replace this with the astropy fits module. If I do :
import numpy
from astropy.io import fits as pyfits
fitsfile = pyfits.open('NGC628.fits', mode='update')
image = fitsfile[0].data
header = fitsfile[0].header
z = image.shape[1]
y = image.shape[2]
x = image.shape[3]
image = numpy.reshape(image,[z,y,x])
... then so far, so good. The "image" array is reshaped correctly, as image.shape confirms. But I cannot for the life of me figure out how to save this to a new (or the old) FITS file. Using the old syntax :
fitsfile.writeto('NGC628_2.fits',image,header)
... gives an error message, "AttributeError: 'numpy.ndarray' object has no attribute 'lower'. If instead, based on the astropy documentation, I simply omit the image and header and try and save to the original file :
fitsfile.writeto('NGC628.fits')
Then I get an error that the file already exists. If I provide the keyword "overwrite=True", then it complains about "WinError 32 : The process cannot access the file because it is being used by another process : NGCC628.fits". The file is definitely NOT open in any other programs.
If I specify the new filename NGC628_2.fits, then Python crashes (sends me back to the command prompt) with no errors. A very small file is written that contains only the header data and none of the image data. EDIT : exactly the same thing happens if I use the correct command to write a new FITS file using image and header data, e.g. pyfits.writeto('NGC628_2.fits',image,header).
Just to make things even more confusing, if I do a slightly simpler operation, say, setting all the image data to a constant value and then closing the file :
import numpy
from astropy.io import fits as pyfits
fitsfile = pyfits.open('NGC628.fits', mode='update')
image = fitsfile[0].data
header = fitsfile[0].header
image[:,:,:,:] = 5.0
fitsfile.close()
Then this works - the original file is now an array where every value is equal to 5. I gather from the astropy documentation that simply opening the file in update mode and closing it should be enough, and in this case it is. But this same trick does not work when reshaping the image - the FITS file is unaltered.
So what the heck am I doing wrong ? Either updating the original or saving to a new file would be fine (preferably the latter) but I cannot get either operation to work correctly.
EDIT : I have Python version 3.5.3, numpy version 1.17.3, astropy version 3.2.3, and I'm running Windows 10.