示例#1
0
def show_region(fig, region_list):
    h = demo_header()

    n = len(region_list)
    nx = int(math.ceil(n**.5))
    ny = int(math.ceil(1.*n/nx))


    nrows_ncols = (ny, nx)

    grid = [plt.subplot(ny, nx, i+1) for i in range(n)]

    for ax, reg_name in zip(grid, region_list):
        ax.set_aspect(1)

        r = stregion.open(reg_name).as_imagecoord(h)

        patch_list, text_list = r.get_mpl_patches_texts()
        for p in patch_list:
            ax.add_patch(p)
        for t in text_list:
            ax.add_artist(t)

        if plt.rcParams["text.usetex"]:
            reg_name = reg_name.replace("_", r"\_")
        ax.set_title(reg_name, size=10)
        for t in ax.get_xticklabels() + ax.get_yticklabels():
            t.set_visible(False)

    return grid
示例#2
0
def test_region():

    ref_region_name = "test01_img.reg"

    region_list = [
        "test01_fk5_sexagecimal.reg",
        "test01_gal.reg",
        "test01_ds9_physical.reg",
        "test01_fk5_degree.reg",
        "test01_mixed.reg",
        "test01_ciao.reg",
        "test01_ciao_physical.reg",
    ]

    header = demo_header()

    ref_region = stregion.open(join(rootdir,
                                    ref_region_name)).as_imagecoord(header)

    for reg_name in region_list:
        r = stregion.open(join(rootdir, reg_name)).as_imagecoord(header)
        for reg0, reg in zip(ref_region, r):
            if reg.name == "rotbox":
                reg.name = "box"

            assert reg0.name == reg.name
            if reg0.name in ["ellipse", "box"]:
                assert np.allclose(reg0.coord_list[:-1],
                                   reg.coord_list[:-1],
                                   atol=0.01)
                a0 = reg0.coord_list[-1]
                a1 = fix_lon(reg.coord_list[-1], 0)
                assert np.allclose([a0], [a1], atol=0.02)
            else:
                assert np.allclose(reg0.coord_list, reg.coord_list, atol=0.01)
            assert reg0.exclude == reg.exclude
示例#3
0
def build_img_ext_reg_list(images,
                           chip_reg=None,
                           img_wcs_ext='sci',
                           verbose=True):
    # Check that the 'chip_reg' argument is of correct type/form:
    if chip_reg is None:
        nreg = 0
        multireg = False
        chip_reg = []
    elif isinstance(chip_reg, str):
        nreg = 1
        chip_reg = [chip_reg]
        multireg = False
    elif isinstance(chip_reg, list):
        chip_reg = chip_reg[:]
        nreg = len(chip_reg)
        multireg = True
        # check that all elements of the list are either strings or None:
        if [
                True for reg in chip_reg
                if reg is not None and not isinstance(reg, str)
        ]:
            raise TypeError("Argument 'chip_reg' can be either None, " \
                            "a string, or a list of stings and/or None.")
    else:
        raise TypeError("Argument 'chip_reg' can be either None, " \
                        "a string, or a list of stings and/or None.")

    # from the 'images' argument built a list of file *names*
    # ignoring extensions(!) and check that the files exist:
    imgfnames = []
    if not images:
        raise TypeError("Argument 'images' cannot be an empty list or None.")

    if not isinstance(images, list):
        images = [images]

    for fname in images:
        if not isinstance(fname, str):
            raise RuntimeError("Argument 'images' must be either a string " \
                    "or a non-empty list of strings of valid file names.")
        (fn, ext) = extension_from_filename(fname)
        if not os.path.isfile(fn):
            raise IOError("The image file \'%s\' does not exist." % fn)
        imgfnames.append(fn)

    # Get the HDU list of the first file in the list of images. This will be
    # re-used to check available extensions.
    try:
        hdulist = fits.open(imgfnames[0], memmap=False)
        hdulist.close()
    except IOError as e:
        cmsg = "Unable to open the image file \'%s\'." % imgfnames[0]
        if e.args:
            e.args = (e.args[0] + "\n" + cmsg, ) + e.args[1:]
        else:
            e.args = (cmsg, )
        raise e

    except:
        raise

    # initial processing of extensions (get a list of integers, str, or tuples):
    exts = parse_ext(img_wcs_ext, default_extver=None)
    if not isinstance(exts, list):
        exts = [exts]

    # for each string extension in the extension list 'exts', find out how many
    # extension versions exist and create a new list of extensions in which the
    # string (e.g., 'sci') gets replaced with tuples for each available
    # extension version: [('sci',1),('sci',2), etc.]
    extensions = []
    for ext in exts:
        if isinstance(ext, int) or isinstance(ext, tuple):
            extensions.append(ext)
            continue
        extv = get_extver_list(hdulist, extname=ext)
        for v in extv:
            extensions.append((ext, v))

    if not _check_FITS_extensions(hdulist, extensions):
        raise RuntimeError("Not all extensions computed based on the "         \
        "provided 'img_wcs_ext' could be found in the HDU list of the "        \
        "image(s) specified by the argument 'images'. Make sure that all "     \
        "extensions in the 'img_wcs_ext' list are present in input 'images'.")

    nexts = len(extensions)  # <- number of "valid" extensions

    # Warn users if some regions will be dropped out:
    if nreg > nexts:
        print("")
        _print_warning("The number of region files provided through " \
                       "'chip_reg' is larger than the number of extensions " \
                       "derived based on 'img_wcs_ext' that were found " \
                       "in 'images'.")
        _print_warning("The following \"fixed\" region files will " \
                       "be dropped out:")
        for i in range(nexts, nreg):
            _print_warning("chip_reg[%d]: %s" % (i, str(chip_reg[i])))
        chip_reg = chip_reg[:nexts]

    # Warn users if there are more extensions than "chip" regions:
    if nreg == 0:
        chip_reg = nexts * [None]

    elif nreg < nexts:
        print("")
        _print_warning("The number of region files provided through " \
                       "'chip_reg' is smaller than the number of extensions " \
                       "derived based on 'img_wcs_ext' that were found " \
                       "in 'images'.")
        _print_warning("The following extensions have not been assigned any "  \
                       "\"fixed\" (chip related) regions:")
        extlist = "   "
        for ext in extensions[nreg:-1]:
            chip_reg.append(None)
            extlist += str(ext) + ", "
        extlist += str(extensions[-1])
        chip_reg.append(None)
        _print_warning(extlist)

    # Check that the region files exist and try to open/read them:
    region_lists = []

    for fname in chip_reg:
        if fname is None:
            region_lists.append(None)
            continue
        # check region file existence:
        if not os.path.isfile(fname):
            raise IOError("The input \"chip\" region file \'%s\' does not "    \
                          "exist." % fname)
        # try to read regions:
        try:
            reglist = pyregion.open(fname)
            region_lists.append(reglist)
            #TODO: Check that regions are all in *image* coordinates

        except IOError:
            raise IOError("Unable to open the input region file \'%s\'." %     \
                          fname)

        except:
            raise RuntimeError("Unexpected error parsing input region "        \
                               "file \'%s\'. Suspecting either a corrupt "     \
                               "file or an unrecognizable region file format." \
                               % fname)

    # Print the list of pairs extension->chip region:
    if verbose and nreg > 0:
        print("")
        _print_important("Please verify that the following association "  \
              "between the commanded FITS extensions and provided \"fixed\" " \
              "region files is correct:")
        print("-----------------------------")
        print("EXTENSION:   -->   REGION FILE:")
        for i in range(nexts):
            print("{!s:<18.18s} {}".format(extensions[i], chip_reg[i]))

    # Return a list of image file names (with any extensions removed!) to which
    # regions will be mapped AND a list of pairs of the form
    # [region, extension].
    return imgfnames, list(map(list, list(zip(region_lists, extensions))))
示例#4
0
def build_reg_refwcs_header_list(input_reg, refimg, ref_wcs_ext, verbose):
    # check input region file names and initialize region lists:
    region_lists = []
    single_inp_reg = False

    if isinstance(input_reg,
                  str) and len(input_reg) > 0:  # a single region file
        single_inp_reg = True
        input_regfnames = [input_reg]
        ref_wcs_exts = [0]  # for a single input region we assume that the
        # default location of the WCS is in the primary
        # header (if nothing else specified)

    elif isinstance(input_reg,
                    list) and input_reg:  # a non-empty list of files
        # select non-zero length file names;replace all other elements with None
        input_regfnames = [fname if isinstance(fname,str) and \
                           len(fname)>0 else None for fname in input_reg]

        # Populate ref_wcs_exts with "default" FITS extension numbers according
        # to the input region position in the input_regfnames list
        # (starting with 1). That is, if multiple regions are given, then we
        # assume that (if no extension name is provided) the WCS is located in
        # "extensions" of the input reference FITS file (as opposite to the
        # primary header).
        ref_wcs_exts = list(range(1, len(input_regfnames) + 1))

        # Filter out elements of ref_wcs_exts and input_regfnames that
        # correspond to None elements in input_regfnames:
        ref_wcs_exts = [ext for reg,ext in zip(input_regfnames,ref_wcs_exts) \
                        if reg is not None]
        input_regfnames = [reg for reg in input_regfnames if reg is not None]

    else:
        input_regfnames = []
        ref_wcs_exts = []  # unnecessary, really, because of the next "if"

    # Check that we have at least one "valid" input region file name
    if len(input_regfnames) < 1:
        raise RuntimeError("Parameter 'input_reg' must be either a non-zero " \
            "length string or a non-empty list with at least "               \
            "one non-zero length string file name.")

    # Check that the region files exist and try to open/read them:
    ireg = 0
    for fname in input_regfnames:
        # check region file existence:
        if not os.path.isfile(fname):
            raise IOError("The input region file \'%s\' does not exist." % \
                fname)
        # try to read regions:
        try:
            reglist = pyregion.open(fname)
            region_lists.append(reglist)

        except IOError:
            raise IOError("Unable to open the input region file \'%s\'." % \
                fname)

        except:
            raise RuntimeError("Unexpected error parsing input region " \
                "file \'%s\'. Suspecting either a corrupt file or "     \
                "an unrecognizable region file format." % fname)

        # check if WCS is needed to convert from image to sky CS
        if not _needs_ref_WCS(reglist):
            ref_wcs_exts[ireg] = None

        ireg += 1

    # If WCS is needed for conversion to sky coordinates, find the correct
    # FITS extension based either on extension specified in the input reference
    # image 'refimg', optional input argument 'ref_wcs_ext', and/or position of
    # the region file in the input region list 'input_reg'
    if [True for ireg in ref_wcs_exts if ireg is not None]:
        # A reference WCS is required. Check that 'refimg' is an existing file:
        if refimg is None:
            raise ValueError("Argument 'refimg' cannot be None when some " \
                             "input regions are given in logical coordinates.")

        if not isinstance(refimg, str):
            raise TypeError("Argument 'refimg' must be a string with the " \
                            "name of an existing FITS file and, optionally, " \
                            "followed by an extension specification.")

        (refimg_fname, frefext) = extension_from_filename(refimg)

        if not os.path.isfile(refimg_fname):
            raise IOError("The reference FITS file \'%s\' does not exist." % \
                          refimg_fname)

        if frefext:
            # Try to determine the extension name from the reference file name
            refext = parse_ext(frefext)

            if single_inp_reg:

                if isinstance(refext, tuple) or isinstance(refext, int):
                    ref_wcs_exts = [refext]
                elif isinstance(refext, str):  # it is a string:
                    ref_wcs_exts = [(refext, 1)]
                else:
                    raise RuntimeError("Logical error in the code.")

            else:
                # check that FITS extension specified in the reference image file
                # name is not too restrictive (for multiple regions it cannot
                # contain a specific extver):
                if isinstance(refext, tuple):
                    raise RuntimeError("Extension version ('EXTVER') in the "  \
                    "reference file name should not be present when multiple " \
                    "region files (in logical CS) are provided as input. "     \
                    "Only extension name ('EXTNAME') is allowed (e.g., "       \
                    "[SCI], [DQ], etc.)")

                if isinstance(refext, int):
                    raise RuntimeError("Extension number (e.g., [0], [2], "    \
                    "etc.) in the reference file name should not be present "  \
                    "when multiple region files (in logical CS) are "          \
                    "provided as input. Only extension name ('EXTNAME') is "   \
                    "allowed (e.g., [SCI], [DQ], etc.)")

                ref_wcs_exts = [None if extn is None else (refext, extn) \
                                for extn in ref_wcs_exts]

        elif ref_wcs_ext:
            # Try to determine the extension name from the 'ref_wcs_ext'
            # argument:
            refext = parse_ext(ref_wcs_ext)

            if single_inp_reg:
                if isinstance(refext, tuple) or isinstance(refext, int):
                    ref_wcs_exts = [refext]
                elif isinstance(refext, str):  # it is a string:
                    ref_wcs_exts = [(refext, 1)]
                else:
                    raise RuntimeError("Logical error in the code.")

            else:
                # check that FITS extension specified in the reference image
                # file name is not too restrictive (for multiple regions it
                # cannot contain a specific extver):
                if isinstance(refext, tuple):
                    raise RuntimeError("Extension version ('EXTVER') in the "  \
                    "'ref_wcs_ext' argument should not be present when "       \
                    "multiple region files (in logical CS) are provided "      \
                    "as input. Only extension name ('EXTNAME') is allowed "    \
                    "(e.g., [SCI], [DQ], etc.)")

                if isinstance(refext, int):
                    raise RuntimeError("Extension number (e.g., [0], [2], "    \
                    "etc.) in the 'ref_wcs_ext' argument should not be "       \
                    "present when multiple region files (in logical CS) are "  \
                    "provided as input. Only extension name ('EXTNAME') is "   \
                    "allowed (e.g., [SCI], [DQ], etc.)")

                ref_wcs_exts = [None if extn is None else (refext, extn) \
                                for extn in ref_wcs_exts]
        # check if the extensions found above are present
        # in the reference WCS FITS file:
        if (refimg is not None
                and not _check_FITS_extensions(refimg, ref_wcs_exts)):
            raise RuntimeError("Not all FITS extensions derived based on the " \
                "input region(s) and extension names have been found in the "  \
                "input reference WCS file. Unable to proceed.")

        # load headers containing WCS from the reference input FITS file:
        ref_wcs_headers = [None if extn is None \
                           else fits.getheader(refimg_fname, ext=extn, memmap=False) \
                           for extn in ref_wcs_exts ] #TODO: return WCS instead of header

    else:
        # no WCS is needed (regions are already in sky coordinates):
        ref_wcs_headers = [None for reg in region_lists]

    # Return a list of pairs of the form [region, header] with missing regions
    # (i.e., region = None) filtered out. (We do not need to keep order anymore)
    return [p for p in map(list, list(zip(region_lists, ref_wcs_headers))) \
            if p[0] is not None]
示例#5
0
def map_region_files(input_reg,
                     images,
                     img_wcs_ext='sci',
                     refimg=None,
                     ref_wcs_ext='sci',
                     chip_reg=None,
                     outpath='./regions',
                     filter=None,
                     catfname=None,
                     iteractive=False,
                     append=False,
                     verbose=True):
    # Check that output directory exists:
    if outpath in [None, ""]:
        outpath = os.path.curdir + os.path.sep
    elif not os.path.isdir(outpath):
        raise IOError("The output directory \'%s\' does not exist." % outpath)

    if filter is not None and filter.lower() not in ["fast", "precise"]:
        raise TypeError("The 'filter' argument can be None, 'fast', " \
                        "or 'precise'.")

    #TODO: Implement the "precise" checking of region intersection
    # with the image's bounding box.
    if filter is not None and filter.lower() == "precise":
        _print_warning("\"precise\" filter option is not yet supported. "\
                       "Reverting to filter = \"fast\" instead.")
        filter = "fast"

    # create a 2D list of region - header (with WCS) pairs:
    # [[reg1,ref_wcs_header1],[reg2,ref_wcs_header2],...]
    regheaders = build_reg_refwcs_header_list(input_reg, refimg, ref_wcs_ext,
                                              verbose)

    # create a list of input files *without* extensions (if present) and
    # a 2D list of "chip" region - image extension pairs:
    # [[reg1, ext1], [reg2,ext2],...]
    imgfnames, cregext = build_img_ext_reg_list(images, chip_reg, img_wcs_ext,
                                                verbose)

    # build a "master" list of regions in sky coordinates:
    all_sky_regions = []
    for p in regheaders:
        if p[1] is None:  # Already in sky WCS
            all_sky_regions += p[0]
        else:
            all_sky_regions += shapes_img2sky(
                p[0], p[1])  #TODO: implement shapes_img2sky

    all_sky_regions = pyregion.ShapeList(list(all_sky_regions))

    cattb = []
    # create a region file (with regions in image coordinates) for each
    # image extension from the input_reg and chip_reg regions
    for fname in imgfnames:
        imghdu = None
        imghdu = fits.open(fname, memmap=False)
        catreg = []
        try:
            for extp in cregext:
                ext = extp[1]

                # check that the extension is of supported type:
                if not _is_supported_hdu(imghdu[ext].header):
                    raise RuntimeError("Extension {} is of unsupported " \
                                       "type.".format(ext))

                # Remove references to non-SIP distortions from the header
                #TODO: remove this line of code as well as the remove_header_tdd
                # function once publicly available release of pyregion uses
                # all_world2pix and all_pix2world functions and does this header
                # cleanup itself.


#                remove_header_tdd(imghdu[ext].header)

####### added to pass hstwcs instead of header to pyregion
#                if isinstance(ext, str):
#                    ext = findExtname(imghdu, extname = ext, extver = 1)
#                elif isinstance(ext, tuple):
#                    ext = findExtname(imghdu, extname = ext[0], extver = ext[1])

#                wcs = stwcs.wcsutil.HSTWCS(imghdu, ext=ext)
                wcs = _AuxSTWCS(imghdu, ext=ext)
                extreg = all_sky_regions.as_imagecoord(wcs, rot_wrt_axis=2)
                #######

                #extreg = all_sky_regions.as_imagecoord(imghdu[ext].header, rot_wrt_axis=2)

                if extp[0]:  # add "fixed" regions if any
                    extreg = pyregion.ShapeList(extreg + extp[0])

                # filter out regions outside the image:
                if filter and filter.lower() == 'fast':
                    fast_filter_outer_regions(extreg,
                                              imghdu[ext].header['NAXIS1'],
                                              imghdu[ext].header['NAXIS2'],
                                              origin=1)

                if len(extreg) < 1:  # do not create empty region files
                    catreg.append('None')
                    continue

                # generate output region file name:
                extsuffix = _ext2str_suffix(ext)
                basefname, fext = os.path.splitext(os.path.basename(fname))
                regfname = basefname + extsuffix + os.extsep + "reg"
                fullregfname = os.path.join(outpath, regfname)

                catreg.append(regfname)

                # save regions to a file:
                if append and os.path.isfile(fullregfname):
                    old_extreg = pyregion.open(fullregfname)
                    extreg = pyregion.ShapeList(old_extreg + extreg)

                #TODO: pyregion.write does not work well. For now use _regwite
                # (until the bug fixes get to the pyregion project).
                #TODO: we replaced pyregion.write with our implementation
                # of the write (code from _regwrite) in the locally maintained
                # pyregion until these changes get to be implemented in the
                # publicly available release of pyregion.
                #
                _regwrite(extreg, fullregfname)
                #extreg.write(fullregfname) # <- use this instead of _regwrite
                # once the pyregion bugs are fixed.
            cattb.append([fname, catreg])
        except:
            if imghdu:
                imghdu.close()
            raise

    # create exclusions catalog file:
    if catfname:
        catfh = open(os.path.join(outpath, catfname), 'w')
        for catentry in cattb:
            catfh.write(catentry[0])  # image file name
            for reg in catentry[1]:
                catfh.write(' ' + reg)  # region file name
            catfh.write('\n')
        catfh.close()
示例#6
0
    def _combine_exclude_mask(self, mask):
        # create masks from exclude/include regions and combine it with the
        # input DQ mask:
        #
        regmask = None
        if self.src_find_filters is not None and \
           'region_file' in self.src_find_filters:
            reg_file_name = self.src_find_filters['region_file']
            if not os.path.isfile(reg_file_name):
                raise IOError(
                    "The 'exclude' region file '{:s}' does not exist.".format(
                        reg_file_name))
        else:
            return mask

        # get data image size:
        (img_ny, img_nx) = self.source.shape

        # find out if user provided a region file or a mask FITS file:
        reg_file_ext = os.path.splitext(reg_file_name)[-1]
        if reg_file_ext.lower().strip() in ['.fits', '.fit'] and \
           basicFITScheck(reg_file_name):
            # likely we are dealing with a FITS file.
            # check that the file is a simple with 2 axes:
            hdulist = fits.open(reg_file_name, memmap=False)
            extlist = get_extver_list(hdulist, extname=None)
            for ext in extlist:
                usermask = hdulist[ext].data
                if usermask.shape == (img_ny, img_nx):
                    regmask = usermask.astype(np.bool)
                    break
            hdulist.close()
            if regmask is None:
                raise ValueError("None of the image-like extensions in the "
                                 "user-provided exclusion mask '{}' has a "
                                 "correct shape".format(reg_file_name))

        else:
            # we are dealing with a region file:
            reglist = pyregion.open(reg_file_name)

            ## check that regions are in image-like coordinates:
            ##TODO: remove the code below once 'pyregion' package can correctly
            ##      (DS9-like) convert sky coordinates to image coordinates for all
            ##      supported shapes.
            #if not all([ (x.coord_format == 'image' or \
            #              x.coord_format == 'physical') for x in reglist]):
            #    print("WARNING: Some exclusion regions are in sky coordinates.\n"
            #          "         These regions will be ignored.")
            #    # filter out regions in sky coordinates:
            #    reglist = pyregion.ShapeList(
            #        [x for x in reglist if x.coord_format == 'image' or \
            #         x.coord_format == 'physical']
            #    )

            #TODO: comment out next lines if we do not support region files
            #      in sky coordinates and uncomment previous block:
            # Convert regions from sky coordinates to image coordinates:
            auxwcs = _AuxSTWCS(self.wcs)
            reglist = reglist.as_imagecoord(auxwcs, rot_wrt_axis=2)

            # if all regions are exclude regions, then assume that the entire image
            # should be included and that exclude regions exclude from this
            # rectangular region representing the entire image:
            if all([x.exclude for x in reglist]):
                # we slightly widen the box to make sure that
                # the entire image is covered:
                imreg = pyregion.parse(
                    "image;box({:.1f},{:.1f},{:d},{:d},0)".format(
                        (img_nx + 1) / 2.0, (img_ny + 1) / 2.0, img_nx + 1,
                        img_ny + 1))

                reglist = pyregion.ShapeList(imreg + reglist)

            # create a mask from regions:
            regmask = np.asarray(reglist.get_mask(shape=(img_ny, img_nx)),
                                 dtype=np.bool)

        if mask is not None and regmask is not None:
            mask = np.logical_and(regmask, mask)
        else:
            mask = regmask

        #DEBUG:
        if mask is not None:
            fn = os.path.splitext(self.fname)[0] + '_srcfind_mask.fits'
            fits.writeto(fn, mask.astype(dtype=np.uint8), overwrite=True)

        return mask
示例#7
0
    def _combine_exclude_mask(self, mask):
        # create masks from exclude/include regions and combine it with the
        # input DQ mask:
        #
        regmask = None
        if self.src_find_filters is not None and \
           'region_file' in self.src_find_filters:
            reg_file_name = self.src_find_filters['region_file']
            if not os.path.isfile(reg_file_name):
                raise IOError("The 'exclude' region file '{:s}' does not exist."
                              .format(reg_file_name))
        else:
            return mask

        # get data image size:
        (img_ny, img_nx) = self.source.shape

        # find out if user provided a region file or a mask FITS file:
        reg_file_ext = os.path.splitext(reg_file_name)[-1]
        if reg_file_ext.lower().strip() in ['.fits', '.fit'] and \
           basicFITScheck(reg_file_name):
            # likely we are dealing with a FITS file.
            # check that the file is a simple with 2 axes:
            hdulist = fits.open(reg_file_name, memmap=False)
            extlist = get_extver_list(hdulist,extname=None)
            for ext in extlist:
                usermask = hdulist[ext].data
                if usermask.shape == (img_ny, img_nx):
                    regmask = usermask.astype(np.bool)
                    break
            hdulist.close()
            if regmask is None:
                raise ValueError("None of the image-like extensions in the "
                                 "user-provided exclusion mask '{}' has a "
                                 "correct shape".format(reg_file_name))

        else:
            # we are dealing with a region file:
            reglist = pyregion.open(reg_file_name)

            ## check that regions are in image-like coordinates:
            ##TODO: remove the code below once 'pyregion' package can correctly
            ##      (DS9-like) convert sky coordinates to image coordinates for all
            ##      supported shapes.
            #if not all([ (x.coord_format == 'image' or \
            #              x.coord_format == 'physical') for x in reglist]):
            #    print("WARNING: Some exclusion regions are in sky coordinates.\n"
            #          "         These regions will be ignored.")
            #    # filter out regions in sky coordinates:
            #    reglist = pyregion.ShapeList(
            #        [x for x in reglist if x.coord_format == 'image' or \
            #         x.coord_format == 'physical']
            #    )

            #TODO: comment out next lines if we do not support region files
            #      in sky coordinates and uncomment previous block:
            # Convert regions from sky coordinates to image coordinates:
            auxwcs    = _AuxSTWCS(self.wcs)
            reglist = reglist.as_imagecoord(auxwcs, rot_wrt_axis=2)

            # if all regions are exclude regions, then assume that the entire image
            # should be included and that exclude regions exclude from this
            # rectangular region representing the entire image:
            if all([x.exclude for x in reglist]):
                # we slightly widen the box to make sure that
                # the entire image is covered:
                imreg = pyregion.parse("image;box({:.1f},{:.1f},{:d},{:d},0)"
                                       .format((img_nx+1)/2.0, (img_ny+1)/2.0,
                                               img_nx+1, img_ny+1)
                                       )

                reglist = pyregion.ShapeList(imreg + reglist)

            # create a mask from regions:
            regmask = np.asarray(
                reglist.get_mask(shape=(img_ny, img_nx)),
                dtype=np.bool
            )

        if mask is not None and regmask is not None:
            mask = np.logical_and(regmask, mask)
        else:
            mask = regmask

        #DEBUG:
        if mask is not None:
            fn = os.path.splitext(self.fname)[0] + '_srcfind_mask.fits'
            fits.writeto(fn, mask.astype(dtype=np.uint8), overwrite=True)

        return mask
示例#8
0
                     111,
                     nrows_ncols,
                     ngrids=n,
                     add_all=True,
                     share_all=True,
                     axes_class=(pywcsgrid2.Axes, dict(header=h)))

    ax = grid[0]
    ax.set_xlim(300, 1300)
    ax.set_ylim(300, 1300)
    ax.set_aspect(1)

    #plt.imshow(d, origin="lower", cmap=plt.cm.gray_r)

    from mpl_toolkits.axes_grid.anchored_artists import AnchoredText

    for ax, reg_name in zip(grid, region_list):
        r = stregion.open(reg_name).as_imagecoord(h)

        patch_list, text_list = r.get_mpl_patches_texts()
        for p in patch_list:
            ax.add_patch(p)
        for t in text_list:
            ax.add_artist(t)

        atext = AnchoredText(reg_name.replace("_", r"\_"), loc=2)
        ax.add_artist(atext)

    plt.draw()
    plt.show()
示例#9
0
try:
    from astropy.io import fits as pyfits
except ImportError:
    from astropy.io import fits as pyfits

import matplotlib.pyplot as plt
import stregion

import math

if 1:

    reg_name = "test04_img.reg"

    ax = plt.subplot(111)
    ax.set_xlim(600, 1100)
    ax.set_ylim(600, 1100)
    ax.set_aspect(1)

    r = stregion.open(reg_name)

    patch_list, text_list = r.get_mpl_patches_texts()
    for p in patch_list:
        ax.add_patch(p)
    for t in text_list:
        ax.add_artist(t)

    plt.draw()
    plt.show()
示例#10
0
def build_img_ext_reg_list(images, chip_reg=None, img_wcs_ext='sci',
                           verbose=True):
    # Check that the 'chip_reg' argument is of correct type/form:
    if chip_reg is None:
        nreg     = 0
        multireg = False
        chip_reg = []
    elif isinstance(chip_reg, str):
        nreg = 1
        chip_reg = [chip_reg]
        multireg = False
    elif isinstance(chip_reg, list):
        chip_reg = chip_reg[:]
        nreg     = len(chip_reg)
        multireg = True
        # check that all elements of the list are either strings or None:
        if [True for reg in chip_reg
            if reg is not None and not isinstance(reg, str)]:
            raise TypeError("Argument 'chip_reg' can be either None, " \
                            "a string, or a list of stings and/or None.")
    else:
        raise TypeError("Argument 'chip_reg' can be either None, " \
                        "a string, or a list of stings and/or None.")

    # from the 'images' argument built a list of file *names*
    # ignoring extensions(!) and check that the files exist:
    imgfnames = []
    if not images:
        raise TypeError("Argument 'images' cannot be an empty list or None.")

    if not isinstance(images, list):
        images = [images]

    for fname in images:
        if not isinstance(fname, str):
            raise RuntimeError("Argument 'images' must be either a string " \
                    "or a non-empty list of strings of valid file names.")
        (fn, ext) = extension_from_filename(fname)
        if not os.path.isfile(fn):
            raise IOError("The image file \'%s\' does not exist." % fn)
        imgfnames.append(fn)

    # Get the HDU list of the first file in the list of images. This will be
    # re-used to check available extensions.
    try:
        hdulist = fits.open(imgfnames[0], memmap=False)
        hdulist.close()
    except IOError as e:
        cmsg = "Unable to open the image file \'%s\'." % imgfnames[0]
        if e.args:
            e.args = (e.args[0] + "\n" + cmsg,) + e.args[1:]
        else:
            e.args=(cmsg,)
        raise e

    except:
        raise

    # initial processing of extensions (get a list of integers, str, or tuples):
    exts = parse_ext(img_wcs_ext, default_extver=None)
    if not isinstance(exts, list):
        exts = [exts]

    # for each string extension in the extension list 'exts', find out how many
    # extension versions exist and create a new list of extensions in which the
    # string (e.g., 'sci') gets replaced with tuples for each available
    # extension version: [('sci',1),('sci',2), etc.]
    extensions = []
    for ext in exts:
        if isinstance(ext,int) or isinstance(ext,tuple):
            extensions.append(ext)
            continue
        extv = get_extver_list(hdulist, extname=ext)
        for v in extv:
            extensions.append((ext,v))

    if not _check_FITS_extensions(hdulist, extensions):
        raise RuntimeError("Not all extensions computed based on the "         \
        "provided 'img_wcs_ext' could be found in the HDU list of the "        \
        "image(s) specified by the argument 'images'. Make sure that all "     \
        "extensions in the 'img_wcs_ext' list are present in input 'images'.")

    nexts = len(extensions) # <- number of "valid" extensions

    # Warn users if some regions will be dropped out:
    if nreg > nexts:
        print("")
        _print_warning("The number of region files provided through " \
                       "'chip_reg' is larger than the number of extensions " \
                       "derived based on 'img_wcs_ext' that were found " \
                       "in 'images'.")
        _print_warning("The following \"fixed\" region files will " \
                       "be dropped out:")
        for i in range(nexts,nreg):
            _print_warning("chip_reg[%d]: %s" % (i,str(chip_reg[i])))
        chip_reg = chip_reg[:nexts]

    # Warn users if there are more extensions than "chip" regions:
    if nreg == 0:
        chip_reg = nexts * [None]

    elif nreg < nexts:
        print("")
        _print_warning("The number of region files provided through " \
                       "'chip_reg' is smaller than the number of extensions " \
                       "derived based on 'img_wcs_ext' that were found " \
                       "in 'images'.")
        _print_warning("The following extensions have not been assigned any "  \
                       "\"fixed\" (chip related) regions:")
        extlist = "   "
        for ext in extensions[nreg:-1]:
            chip_reg.append(None)
            extlist += str(ext)+", "
        extlist += str(extensions[-1])
        chip_reg.append(None)
        _print_warning(extlist)

    # Check that the region files exist and try to open/read them:
    region_lists = []

    for fname in chip_reg:
        if fname is None:
            region_lists.append(None)
            continue
        # check region file existence:
        if not os.path.isfile(fname):
            raise IOError("The input \"chip\" region file \'%s\' does not "    \
                          "exist." % fname)
        # try to read regions:
        try:
            reglist = pyregion.open(fname)
            region_lists.append(reglist)
            #TODO: Check that regions are all in *image* coordinates

        except IOError:
            raise IOError("Unable to open the input region file \'%s\'." %     \
                          fname)

        except:
            raise RuntimeError("Unexpected error parsing input region "        \
                               "file \'%s\'. Suspecting either a corrupt "     \
                               "file or an unrecognizable region file format." \
                               % fname)

    # Print the list of pairs extension->chip region:
    if verbose and nreg > 0:
        print("")
        _print_important("Please verify that the following association "  \
              "between the commanded FITS extensions and provided \"fixed\" " \
              "region files is correct:")
        print("-----------------------------")
        print("EXTENSION:   -->   REGION FILE:")
        for i in range(nexts):
            print("{!s:<18.18s} {}".format(extensions[i], chip_reg[i]))

    # Return a list of image file names (with any extensions removed!) to which
    # regions will be mapped AND a list of pairs of the form
    # [region, extension].
    return imgfnames, list(map(list, list(zip(region_lists, extensions))))
示例#11
0
def build_reg_refwcs_header_list(input_reg, refimg, ref_wcs_ext, verbose):
    # check input region file names and initialize region lists:
    region_lists = []
    single_inp_reg = False

    if isinstance(input_reg, str) and len(input_reg) > 0: # a single region file
        single_inp_reg  = True
        input_regfnames = [input_reg]
        ref_wcs_exts    = [0] # for a single input region we assume that the
                              # default location of the WCS is in the primary
                              # header (if nothing else specified)

    elif isinstance(input_reg, list) and input_reg: # a non-empty list of files
        # select non-zero length file names;replace all other elements with None
        input_regfnames = [fname if isinstance(fname,str) and \
                           len(fname)>0 else None for fname in input_reg]

        # Populate ref_wcs_exts with "default" FITS extension numbers according
        # to the input region position in the input_regfnames list
        # (starting with 1). That is, if multiple regions are given, then we
        # assume that (if no extension name is provided) the WCS is located in
        # "extensions" of the input reference FITS file (as opposite to the
        # primary header).
        ref_wcs_exts = list(range(1, len(input_regfnames)+1))

        # Filter out elements of ref_wcs_exts and input_regfnames that
        # correspond to None elements in input_regfnames:
        ref_wcs_exts = [ext for reg,ext in zip(input_regfnames,ref_wcs_exts) \
                        if reg is not None]
        input_regfnames = [reg for reg in input_regfnames if reg is not None]

    else:
        input_regfnames = []
        ref_wcs_exts    = [] # unnecessary, really, because of the next "if"

    # Check that we have at least one "valid" input region file name
    if len(input_regfnames) < 1:
        raise RuntimeError("Parameter 'input_reg' must be either a non-zero " \
            "length string or a non-empty list with at least "               \
            "one non-zero length string file name.")

    # Check that the region files exist and try to open/read them:
    ireg = 0
    for fname in input_regfnames:
        # check region file existence:
        if not os.path.isfile(fname):
            raise IOError("The input region file \'%s\' does not exist." % \
                fname)
        # try to read regions:
        try:
            reglist = pyregion.open(fname)
            region_lists.append(reglist)

        except IOError:
            raise IOError("Unable to open the input region file \'%s\'." % \
                fname)

        except:
            raise RuntimeError("Unexpected error parsing input region " \
                "file \'%s\'. Suspecting either a corrupt file or "     \
                "an unrecognizable region file format." % fname)

        # check if WCS is needed to convert from image to sky CS
        if not _needs_ref_WCS(reglist):
            ref_wcs_exts[ireg] = None

        ireg += 1

    # If WCS is needed for conversion to sky coordinates, find the correct
    # FITS extension based either on extension specified in the input reference
    # image 'refimg', optional input argument 'ref_wcs_ext', and/or position of
    # the region file in the input region list 'input_reg'
    if [True for ireg in ref_wcs_exts if ireg is not None]:
        # A reference WCS is required. Check that 'refimg' is an existing file:
        if refimg is None:
            raise ValueError("Argument 'refimg' cannot be None when some " \
                             "input regions are given in logical coordinates.")

        if not isinstance(refimg, str):
            raise TypeError("Argument 'refimg' must be a string with the " \
                            "name of an existing FITS file and, optionally, " \
                            "followed by an extension specification.")

        (refimg_fname, frefext) = extension_from_filename(refimg)

        if not os.path.isfile(refimg_fname):
            raise IOError("The reference FITS file \'%s\' does not exist." % \
                          refimg_fname)

        if frefext:
            # Try to determine the extension name from the reference file name
            refext = parse_ext(frefext)

            if single_inp_reg:

                if isinstance(refext, tuple) or isinstance(refext, int):
                    ref_wcs_exts = [refext]
                elif isinstance(refext, str): # it is a string:
                    ref_wcs_exts = [(refext, 1)]
                else:
                    raise RuntimeError("Logical error in the code.")

            else:
                # check that FITS extension specified in the reference image file
                # name is not too restrictive (for multiple regions it cannot
                # contain a specific extver):
                if isinstance(refext, tuple):
                    raise RuntimeError("Extension version ('EXTVER') in the "  \
                    "reference file name should not be present when multiple " \
                    "region files (in logical CS) are provided as input. "     \
                    "Only extension name ('EXTNAME') is allowed (e.g., "       \
                    "[SCI], [DQ], etc.)")

                if isinstance(refext, int):
                    raise RuntimeError("Extension number (e.g., [0], [2], "    \
                    "etc.) in the reference file name should not be present "  \
                    "when multiple region files (in logical CS) are "          \
                    "provided as input. Only extension name ('EXTNAME') is "   \
                    "allowed (e.g., [SCI], [DQ], etc.)")

                ref_wcs_exts = [None if extn is None else (refext, extn) \
                                for extn in ref_wcs_exts]

        elif ref_wcs_ext:
            # Try to determine the extension name from the 'ref_wcs_ext'
            # argument:
            refext = parse_ext(ref_wcs_ext)

            if single_inp_reg:
                if isinstance(refext, tuple) or isinstance(refext, int):
                    ref_wcs_exts = [refext]
                elif isinstance(refext, str): # it is a string:
                    ref_wcs_exts = [(refext, 1)]
                else:
                    raise RuntimeError("Logical error in the code.")

            else:
                # check that FITS extension specified in the reference image
                # file name is not too restrictive (for multiple regions it
                # cannot contain a specific extver):
                if isinstance(refext, tuple):
                    raise RuntimeError("Extension version ('EXTVER') in the "  \
                    "'ref_wcs_ext' argument should not be present when "       \
                    "multiple region files (in logical CS) are provided "      \
                    "as input. Only extension name ('EXTNAME') is allowed "    \
                    "(e.g., [SCI], [DQ], etc.)")

                if isinstance(refext, int):
                    raise RuntimeError("Extension number (e.g., [0], [2], "    \
                    "etc.) in the 'ref_wcs_ext' argument should not be "       \
                    "present when multiple region files (in logical CS) are "  \
                    "provided as input. Only extension name ('EXTNAME') is "   \
                    "allowed (e.g., [SCI], [DQ], etc.)")

                ref_wcs_exts = [None if extn is None else (refext, extn) \
                                for extn in ref_wcs_exts]
        # check if the extensions found above are present
        # in the reference WCS FITS file:
        if (refimg is not None and
            not _check_FITS_extensions(refimg, ref_wcs_exts)):
            raise RuntimeError("Not all FITS extensions derived based on the " \
                "input region(s) and extension names have been found in the "  \
                "input reference WCS file. Unable to proceed.")

        # load headers containing WCS from the reference input FITS file:
        ref_wcs_headers = [None if extn is None \
                           else fits.getheader(refimg_fname, ext=extn, memmap=False) \
                           for extn in ref_wcs_exts ] #TODO: return WCS instead of header

    else:
        # no WCS is needed (regions are already in sky coordinates):
        ref_wcs_headers = [None for reg in region_lists]

    # Return a list of pairs of the form [region, header] with missing regions
    # (i.e., region = None) filtered out. (We do not need to keep order anymore)
    return [p for p in map(list, list(zip(region_lists, ref_wcs_headers))) \
            if p[0] is not None]
示例#12
0
def map_region_files(input_reg, images, img_wcs_ext='sci',
                     refimg=None, ref_wcs_ext='sci', chip_reg=None,
                     outpath='./regions', filter=None, catfname=None,
                     iteractive=False, append=False, verbose=True):
    # Check that output directory exists:
    if outpath in [None, ""]:
        outpath = os.path.curdir + os.path.sep
    elif not os.path.isdir(outpath):
        raise IOError("The output directory \'%s\' does not exist." % outpath)

    if filter is not None and filter.lower() not in ["fast","precise"]:
        raise TypeError("The 'filter' argument can be None, 'fast', " \
                        "or 'precise'.")

    #TODO: Implement the "precise" checking of region intersection
    # with the image's bounding box.
    if filter is not None and filter.lower() == "precise":
        _print_warning("\"precise\" filter option is not yet supported. "\
                       "Reverting to filter = \"fast\" instead.")
        filter = "fast"

    # create a 2D list of region - header (with WCS) pairs:
    # [[reg1,ref_wcs_header1],[reg2,ref_wcs_header2],...]
    regheaders = build_reg_refwcs_header_list(input_reg, refimg, ref_wcs_ext,
                                              verbose)

    # create a list of input files *without* extensions (if present) and
    # a 2D list of "chip" region - image extension pairs:
    # [[reg1, ext1], [reg2,ext2],...]
    imgfnames, cregext = build_img_ext_reg_list(images, chip_reg, img_wcs_ext,
                                                verbose)

    # build a "master" list of regions in sky coordinates:
    all_sky_regions = []
    for p in regheaders:
        if p[1] is None: # Already in sky WCS
            all_sky_regions += p[0]
        else:
            all_sky_regions += shapes_img2sky(p[0], p[1]) #TODO: implement shapes_img2sky

    all_sky_regions = pyregion.ShapeList(list(all_sky_regions))

    cattb = []
    # create a region file (with regions in image coordinates) for each
    # image extension from the input_reg and chip_reg regions
    for fname in imgfnames:
        imghdu = None
        imghdu = fits.open(fname, memmap=False)
        catreg = []
        try:
            for extp in cregext:
                ext = extp[1]

                # check that the extension is of supported type:
                if not _is_supported_hdu(imghdu[ext].header):
                    raise RuntimeError("Extension {} is of unsupported " \
                                       "type.".format(ext))

                # Remove references to non-SIP distortions from the header
                #TODO: remove this line of code as well as the remove_header_tdd
                # function once publicly available release of pyregion uses
                # all_world2pix and all_pix2world functions and does this header
                # cleanup itself.
#                remove_header_tdd(imghdu[ext].header)

                ####### added to pass hstwcs instead of header to pyregion
#                if isinstance(ext, str):
#                    ext = findExtname(imghdu, extname = ext, extver = 1)
#                elif isinstance(ext, tuple):
#                    ext = findExtname(imghdu, extname = ext[0], extver = ext[1])

#                wcs = stwcs.wcsutil.HSTWCS(imghdu, ext=ext)
                wcs    = _AuxSTWCS(imghdu, ext=ext)
                extreg = all_sky_regions.as_imagecoord(wcs, rot_wrt_axis=2)
                #######

                #extreg = all_sky_regions.as_imagecoord(imghdu[ext].header, rot_wrt_axis=2)

                if extp[0]: # add "fixed" regions if any
                    extreg = pyregion.ShapeList(extreg+extp[0])

                # filter out regions outside the image:
                if filter and filter.lower() == 'fast':
                    fast_filter_outer_regions( extreg,
                                               imghdu[ext].header['NAXIS1'],
                                               imghdu[ext].header['NAXIS2'],
                                               origin = 1 )

                if len(extreg) < 1: # do not create empty region files
                    catreg.append('None')
                    continue

                # generate output region file name:
                extsuffix = _ext2str_suffix(ext)
                basefname, fext = os.path.splitext(os.path.basename(fname))
                regfname = basefname + extsuffix + os.extsep + "reg"
                fullregfname = os.path.join(outpath, regfname)

                catreg.append(regfname)

                # save regions to a file:
                if append and os.path.isfile(fullregfname):
                    old_extreg = pyregion.open(fullregfname)
                    extreg = pyregion.ShapeList(old_extreg + extreg)

                #TODO: pyregion.write does not work well. For now use _regwite
                # (until the bug fixes get to the pyregion project).
                #TODO: we replaced pyregion.write with our implementation
                # of the write (code from _regwrite) in the locally maintained
                # pyregion until these changes get to be implemented in the
                # publicly available release of pyregion.
                #
                _regwrite(extreg, fullregfname)
                #extreg.write(fullregfname) # <- use this instead of _regwrite
                                            # once the pyregion bugs are fixed.
            cattb.append([fname, catreg])
        except:
            if imghdu:
                imghdu.close()
            raise

    # create exclusions catalog file:
    if catfname:
        catfh = open(os.path.join(outpath, catfname), 'w')
        for catentry in cattb:
            catfh.write(catentry[0]) # image file name
            for reg in catentry[1]:
                catfh.write(' ' + reg) # region file name
            catfh.write('\n')
        catfh.close()
    from astropy.io import fits as pyfits

# read in the image
xray_name = "pspc_skyview.fits"
f_xray = pyfits.open(xray_name)

try:
    import pywcsgrid2
    ax = pywcsgrid2.subplot(111, header=f_xray[0].header)
except ImportError:
    ax = plt.subplot(111)

ax.imshow(f_xray[0].data, cmap=cm.gray, vmin=0., vmax=0.00038, origin="lower")

reg_name = "test.reg"
r = stregion.open(reg_name).as_imagecoord(header=f_xray[0].header)

from stregion.mpl_helper import properties_func_default


# Use custom function for patch attribute
def fixed_color(shape, saved_attrs):

    attr_list, attr_dict = saved_attrs
    attr_dict["color"] = "red"
    kwargs = properties_func_default(shape, (attr_list, attr_dict))

    return kwargs


# select region shape with tag=="Group 1"