def get_image(expnum, ccd=None, version='p', ext=FITS_EXT,
              subdir=None, prefix=None, cutout=None, return_file=True, flip_image=True):
    """Get a FITS file for this expnum/ccd  from VOSpace.


    @param cutout: (str)
    @param return_file: return an filename (True) or HDUList (False)
    @param expnum: CFHT exposure number (int)
    @param ccd:     @param ccd:
    @param version: [p, s, o]  (char)
    @param ext:
    @param subdir:
    @param prefix:
    @param flip_image: Should the image be x/y flipped after being retrieved?
    @return: astropy.io.fits.PrimaryHDU
    """

    filename = os.path.basename(get_uri(expnum, ccd, version, ext=ext, subdir=subdir, prefix=prefix))
    if os.access(filename, os.F_OK) and return_file and cutout is None:
        return filename

    cutout_string = cutout
    try:
        if os.access(filename, os.F_OK) and cutout:
            cutout = datasec_to_list(cutout)
            hdulist = fits.open(filename)
            if len(hdulist) > 1:
                raise ValueError("Local cutout access not designed to work on MEFs yet.")
            header = hdulist[0].header
            cutout[0] = cutout[0] < 0 and header['NAXIS1'] - cutout[0] + 1 or cutout[0]
            cutout[1] = cutout[1] < 0 and header['NAXIS1'] - cutout[1] + 1 or cutout[1]
            cutout[2] = cutout[2] < 0 and header['NAXIS2'] - cutout[2] + 1 or cutout[2]
            cutout[3] = cutout[3] < 0 and header['NAXIS2'] - cutout[3] + 1 or cutout[3]
            logger.debug("DATA array shape: {}".format(hdulist[0].data.shape))
            logger.debug("CUTOUT array: {} {} {} {}".format(cutout[0],
                                                            cutout[1],
                                                            cutout[2],
                                                            cutout[3]))
            flip = cutout[0] < cutout[1] and 1 or -1
            flop = cutout[2] < cutout[3] and 1 or -1
            header['CRPIX1'] = (header.get("CRPIX1", 1) - cutout[0]) * flip + 1
            header['CRPIX2'] = (header.get("CRPIX2", 1) - cutout[2]) * flop + 1
            header['CD1_1'] = header.get("CD1_1", 1) * flip
            header['CD2_1'] = header.get("CD2_1", 1) * flip
            header['CD2_2'] = header.get("CD2_2", 1) * flop
            header['CD1_2'] = header.get("CD1_2", 1) * flop

            data = hdulist[0].data[cutout[2]-1:cutout[3], cutout[0]-1:cutout[1]]
            hdulist[0].data = data
            header['DATASEC'] = reset_datasec(cutout_string,
                                              header['DATASEC'],
                                              header['NAXIS1'],
                                              header['NAXIS2'])
            if return_file:
                cutout_filename = os.path.splitext(filename)[0]+"_{}_{}_{}_{}.fits".format(cutout[0],
                                                                                           cutout[1],
                                                                                           cutout[2],
                                                                                           cutout[3])
                hdulist.writeto(cutout_filename)
                return cutout_filename
            else:
                return hdulist
    except Exception as e:
        logger.debug(str(e))
        logger.debug("Failed trying to access local copy: {} with cutout [{}:{}, {}:{}], using VOSpace".format(
            filename, cutout[2]-1, cutout[3], cutout[0]-1, cutout[1]))

    cutout = cutout_string

    if not subdir:
        subdir = str(expnum)

    logger.debug("Building list of possible uri locations")
    # # here is the list of places we will look, in order
    if version != 'p':
        locations = [(get_uri(expnum, ccd, version, ext=ext, subdir=subdir, prefix=prefix),
                      cutout)]
    else:
        locations = []
    logger.debug(str(locations))
    if ccd is not None:
        try:
            for this_ext in [ext]:
                ext_no = int(ccd) + 1
                # extension 1 -> 18 +  37,36 should be flipped.
                flip_these_extensions = range(1, 19)
                flip_these_extensions.append(37)
                flip_these_extensions.append(38)
                flip = (cutout is None and "fits" in ext and (
                    (ext_no in flip_these_extensions and flip_image) and "[-*,-*]" or "[*,*]")) or cutout
                locations.append((get_uri(expnum, version=version, ext=this_ext, subdir=subdir),
                                  "[{}]{}".format(ext_no, flip)))
        except Exception as e:
            logger.error(str(e))
            pass
    else:
        uri = get_uri(expnum, ccd, version, ext=ext, subdir=subdir, prefix=prefix)
        locations.append((uri, cutout))
        # uri = get_uri(expnum, ccd, version, ext=ext + ".fz", subdir=subdir, prefix=prefix)
        # locations.append((uri, cutout))

    err = errno.EFAULT
    while len(locations) > 0:
        (uri, cutout) = locations.pop(0)
        try:
            hdu_list = get_hdu(uri, cutout)
            if return_file:
                hdu_list.writeto(filename)
                del hdu_list
                return filename
            else:
                return hdu_list
        except Exception as e:
            err = getattr(e, 'errno', errno.EAGAIN)
            logger.debug("{}".format(type(e)))
            logger.debug("Failed to open {} cutout:{}".format(uri, cutout))
            logger.debug("vos sent back error: {} code: {}".format(str(e), getattr(e, 'errno', 0)))

    if err == errno.EAGAIN:
        time.sleep(5)
        return get_image(expnum, ccd=ccd, version=version, ext=ext,
                         subdir=subdir, prefix=prefix, cutout=cutout, return_file=return_file, flip_image=flip_image)
    raise IOError(err, "Failed to get image at uri: {} using {} {} {} {}.".format(uri, expnum, version, ccd, cutout))