1

I am using an astropy package called WCS.all_world2pix in order to convert many coordinates in degrees to pixel coordinates on an image. While running this on many pairs of coordinates, I eventually came across an error which stopped my program from running. Here is the code leading up the error, and the error itself:

import glob
import numpy as np
import re
from astropy.io import fits
from astropy.wcs import WCS

initial_data, centroid_coords = [], []
image_files = glob.glob('/home/username/Desktop/myfolder/*.fits')

for image in image_files:
    img_data = np.nan_to_num(fits.getdata(image))

    obj_num = int(re.search('2\d{6}', image).group(0))
    count_num = int(re.search('_(\d+)_', image).group(1))
    obj_index = int(np.where(good_data == obj_num)[0])
    count_index = int(np.where(np.array(all_counters[obj_index]) == count_num)[0])

    ra, dec = pos_match[obj_index][count_index]
    w = WCS(image)
    x, y = w.all_world2pix(ra, dec, 0)
    initial_data.append(img_data)
    centroid_coords.append((float(x), float(y)))

The error:

x, y = w.all_world2pix(ra, dec, 0)  
  File "/usr/local/anaconda3/lib/python3.6/site-packages/astropy/wcs/wcs.py", line 1827, in all_world2pix
    'input', *args, **kwargs
  File "/usr/local/anaconda3/lib/python3.6/site-packages/astropy/wcs/wcs.py", line 1269, in _array_converter
    return _return_list_of_arrays(axes, origin)
  File "/usr/local/anaconda3/lib/python3.6/site-packages/astropy/wcs/wcs.py", line 1225, in _return_list_of_arrays
    output = func(xy, origin)
  File "/usr/local/anaconda3/lib/python3.6/site-packages/astropy/wcs/wcs.py", line 1826, in <lambda>
    quiet=quiet),
  File "/usr/local/anaconda3/lib/python3.6/site-packages/astropy/wcs/wcs.py", line 1812, in _all_world2pix
    slow_conv=ind, divergent=inddiv)
astropy.wcs.wcs.NoConvergence: 'WCS.all_world2pix' failed to converge to the requested accuracy.
After 2 iterations, the solution is diverging at least for one input point.

I would just like to be able to skip over those images that cause this error. But I'm unsure how to handle this as an exception, since it's not a usual Type/Value/SyntaxError, etc...

As it's going through my loop, when/if this error occurs I'd just like it to continue to the next element in the loop without appending anything for the one that caused the error. Something like this is what I have in mind:

for image in image_files:
    img_data = np.nan_to_num(fits.getdata(image))
    obj_num = int(re.search('2\d{6}', image).group(0))
    count_num = int(re.search('_(\d+)_', image).group(1))
    obj_index = int(np.where(good_data == obj_num)[0])
    count_index = int(np.where(np.array(all_counters[obj_index]) == count_num)[0])

    ra, dec = pos_match[obj_index][count_index]
    w = WCS(image)
    try:
        x, y = w.all_world2pix(ra, dec, 0)
        initial_data.append(img_data)
        centroid_coords.append((float(x), float(y)))    
    except: # skip images where coordinates fail to converge
        # Not sure how to identify the error here
        continue

How can I handle this exception? I've never actually dealt with these before, so any help is appreciated. Thanks!

2 Answers 2

1

What you have now looks like it'd work. I'd like to recommend two small edits for you though:

  • include the fewest number of lines in the try block as possible, so you don't mask an unexpected error condition
  • catch the specific error, again so you don't mask an unexpected case (except by itself will catch every error)

for image in image_files:
    < the code you already have, up to the `try` block >

    try:
        x, y = w.all_world2pix(ra, dec, 0)
    except NoConvergence:
        continue

    initial_data.append(img_data)
    centroid_coords.append((float(x), float(y)))    

Note you'll probably also need to add an import for the NoConvergence error at the top of your script:

from astropy.wcs.wcs import NoConvergence
Sign up to request clarification or add additional context in comments.

Comments

0

The traceback tells you the exception type, so you can just use that:

except astropy.wcs.wcs.NoConvergence as ex:
    print(f'file {f} raised {ex!r}, skipping')
    continue

Of course you may have to import some additional subpackages or modules to have access to that exception type.

However, what you really want to do is check the documentation. Most well-designed packages will give you a list of exceptions you should expect to see, and often have a handful of easily-accessible superclasses that you’re meant to catch, while the more detailed exceptions may be private and subject to change, or may be public but rarely needed.

For example, maybe there’s something like astropy.WcsError that a whole bunch of private exception types are subclasses of, including the NoConvergence that you’re seeing. If you see something like that in the docs, that’s what you should handle:

except astropy.WcsError as ex:
    print(f'file {f} raised {ex!r}, skipping')
    continue

5 Comments

What exactly does your print statement do here? This didn't work for me, and I'm unfamiliar with the syntax {ex!r} as well as the f before the string starts
@curious_cosmo For the first question: f'{spam} and {eggs}' is a shorthand way of writing '{spam} and {eggs}'.format(spam=spam, eggs=eggs) added in Python 3.6. See the PEP on f-string literals for details. {ex!r} is normal format string syntax that goes all the way back to 2.6/3.0; the !r means to print the repr instead of the str (which is often more useful for debugging purposes, and especially so when printing exceptions).
@curious_cosmo There are probably tutorials (and maybe SO answers) that explain both things better than the official docs that I linked you to, if you need to know more than what I covered but not as much as those dense reference docs.
@curious_cosmo But meanwhile, the print is just an example of what you could print out if you want some feedback about what files are being skipped and why. You can put anything you want there, or nothing at all; you don't have to just copy and paste every line of code you see.
Thank you -- I didn't just copy and paste it and hoped it would work; I tried it just to see what it would output, but there was an error at the print statement so that's why I asked. I did think up my own print statement to put there instead, and my original issue has been solved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.