Esempio n. 1
0
 def makeSACat(self, imgfile, extref=False):
     """
     Makes a catalog of objects to be used for input to superalign from a external reference catalog.
     Catalog should be of form: ID RA(deg) Dec(deg) Mag
     Output appends _sa
     """
     if extref:
         wcs = self.refwcs
     else:
         wcs = HSTWCS(imgfile)
     cat = imgfile.replace('.fits', '.cat')
     outcat = imgfile.replace('.fits', '_sa.cat')
     data = ascii.read(cat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
     arcs = (wcs.all_world2pix(zip(data['ra'], data['dec']), 1) - [wcs.naxis1/2, wcs.naxis2/2])*wcs.pscale
     ascii.write([data['id'], arcs[:,0], arcs[:,1], data['mag']], outcat, format='no_header')
     return
Esempio n. 2
0
 def makeSACat(self, imgfile, extref=False):
     """
     Makes a catalog of objects to be used for input to superalign from a external reference catalog.
     Catalog should be of form: ID RA(deg) Dec(deg) Mag
     Output appends _sa
     """
     if extref:
         wcs = self.refwcs
     else:
         wcs = HSTWCS(imgfile)
     cat = imgfile.replace('.fits', '.cat')
     outcat = imgfile.replace('.fits', '_sa.cat')
     data = ascii.read(cat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
     arcs = (wcs.all_world2pix(list(zip(data['ra'], data['dec'])), 1) -
             [wcs.naxis1 / 2, wcs.naxis2 / 2]) * wcs.pscale
     ascii.write([data['id'], arcs[:, 0], arcs[:, 1], data['mag']],
                 outcat,
                 format='no_header',
                 overwrite=True)
     return
Esempio n. 3
0
def refineShiftMCMC(drzfile):
    """
     Refine shifts using MCMC
    """
    dsn = drzfile[:9]
    wcs = HSTWCS(fits.open(drzfile))
    wcsn = fits.getval(drzfile, 'wcsname')
    try:
        refcat = np.loadtxt('%s_drz_sci_sa_ref_match.cat' % dsn,
                            usecols=(1, 2))
        imgcat = np.loadtxt('%s_drz_sci_sa_match.cat' % dsn, usecols=(1, 2))

        refcatw = wcs.all_world2pix(refcat, 1)
        imgcatw = wcs.all_world2pix(imgcat, 1)

        ox, oy = wcs.wcs.crpix.tolist()

        offset, err = mcmcShifts.findOffsetMCMC(imgcatw,
                                                refcatw,
                                                maxShift=(10, 10, 0.3),
                                                rotOrigin=(ox, oy),
                                                precision=0.01,
                                                visualize=False)
        print(drzfile, offset, err)

        dxp, dyp, dtp = offset
        updatehdr.updatewcs_with_shift(drzfile,
                                       drzfile,
                                       wcsname='DRZWCS',
                                       xsh=dxp,
                                       ysh=dyp,
                                       rot=dtp,
                                       scale=1.0,
                                       force=True)
        return offset
    except UserWarning:
        pass
Esempio n. 4
0
class MakeCat(object):
    def __init__(self, refimg):
        super(MakeCat, self).__init__()
        self.refimg = str(refimg)
        self.refwcs = HSTWCS(self.refimg)

    def getInstDet(self, imgfile):
        """Get the instrument/detector of an HST image (e.g. acswfc)"""
        hdr = fits.getheader(imgfile)
        return '%s%s' % (hdr['instrume'].lower(), hdr['detector'].lower())

    def findSources(self,
                    inputfile,
                    outputfile,
                    instdet,
                    weightfile=None,
                    extref=False,
                    **sconfig):
        """Finds objects in image"""
        # Set up SExtractor
        sex = sextractor.SExtractor()
        # Load the default configuration
        if instdet == 'acswfc' or instdet == 'wfc3uvis':
            for k, v in _sex_config_ACSWFC.items():
                sex.config[k] = v
        if instdet == 'wfc3ir':
            for k, v in _sex_config_WFC3IR.items():
                sex.config[k] = v
        if sconfig:
            # Load any runtime configuration
            for k, v in sconfig.items():
                sex.config[k] = v
        if weightfile:
            sex.config['WEIGHT_IMAGE'] = weightfile
            sex.config['WEIGHT_TYPE'] = 'MAP_WEIGHT'
            sex.config['WEIGHT_GAIN'] = 'N'
        sex.config['CATALOG_NAME'] = outputfile
        # Load default parameters'
        sex.config['PARAMETERS_LIST'] = []
        for p in _sex_parms:
            sex.config['PARAMETERS_LIST'].append(p)
        # Run SExtractor
        sex.run(inputfile)
        cfg = _sa_config[instdet]
        low_limit = cfg['low_limit']
        hi_limit = cfg['hi_limit']
        objectlist = []
        for l in [i.split() for i in open(outputfile).readlines()]:
            if l[0] != '#':
                x = float(l[1])
                y = float(l[2])
                ra = float(l[3])
                if l[4].startswith('+'):
                    dec = float(l[4][1:])
                else:
                    dec = float(l[4])
                aa = float(l[5])
                ba = float(l[6])
                r = ba / aa
                m = float(l[7])
                f = float(l[8])
                fwhm = float(l[9])

                if min(2.3 * ba, fwhm) >= low_limit and max(
                        2.3 * aa,
                        fwhm) < hi_limit and r > cfg['min_axis_ratio']:
                    objectlist.append(Object(x, y, ra, dec, r, m, f))

        return objectlist

    def removeCloseSources(self, objectlist):
        """Removes objects from catalog with multiple close detections"""
        for objecti in objectlist:
            for objectj in objectlist:
                dist = ((objecti.x - objectj.x)**2 +
                        (objecti.y - objectj.y)**2)**0.5
                if dist < 10 and dist > 0:
                    if objecti.mag < objectj.mag:
                        objectj.nextToBig = 1
                    else:
                        objecti.nextToBig = 1
        objectlist_keep = []
        for objecti in objectlist:
            if not objecti.nextToBig:
                objectlist_keep.append(objecti)
            else:
                print('Excluding object at %i %i' % (objecti.x, objecti.y))
        return objectlist_keep

    def makeCat(self, imgfile, instdet, weightfile=None, extref=False):
        """Makes a catalog of objects to be used for input to superalign and creates a DS9 region file of objects"""

        imgfile_cat = '%s_all.cat' % imgfile.replace('.fits', '')
        imgfile_reg = '%s_all.reg' % imgfile.replace('.fits', '')

        o_radec = []
        ext = 0
        objectlist = self.findSources('%s[%s]' % (imgfile, ext),
                                      imgfile_cat,
                                      instdet,
                                      weightfile,
                                      extref=extref)
        cleanobjectlist = self.removeCloseSources(objectlist)
        print('Found %s sources' % len(cleanobjectlist))
        wcs = HSTWCS(str(imgfile))
        for obj in cleanobjectlist:
            sky = wcs.all_pix2world(np.array([[obj.x, obj.y]]), 1)
            o_radec.append([obj.ra[0], obj.dec[0]])
            obj.ra = sky[0][0]
            obj.dec = sky[0][1]

        # Write out a ds9 region file of object selected for alignment
        regout = open(imgfile_reg, 'w')
        regout.write(
            'global color=green font="helvetica 8 normal" edit=1 move=1 delete=1 include=1 fixed=0\nfk5\n'
        )
        for i, rd in enumerate(o_radec):
            oid = i + 1
            regout.write('circle(%s,%s,%s") # color=%s text={%s}\n' %
                         (rd[0], rd[1], 0.5, 'red', oid))
        regout.close()

        # Now we need to write out the catalog in the reference image coords in arcseconds with respect to center of the image
        catout = open(imgfile_cat, 'w')
        for i, obj in enumerate(cleanobjectlist):
            oid = i + 1
            catout.write('%i %.9f %.9f %.4f %.4f %.4f\n' %
                         (oid, obj.ra, obj.dec, obj.x, obj.y, obj.mag))
        catout.close()
        return

    def makeSACat(self, imgfile, extref=False):
        """
        Makes a catalog of objects to be used for input to superalign from a external reference catalog.
        Catalog should be of form: ID RA(deg) Dec(deg) Mag
        Output appends _sa
        """
        if extref:
            wcs = self.refwcs
        else:
            wcs = HSTWCS(imgfile)
        cat = imgfile.replace('.fits', '.cat')
        outcat = imgfile.replace('.fits', '_sa.cat')
        data = ascii.read(cat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
        arcs = (wcs.all_world2pix(list(zip(data['ra'], data['dec'])), 1) -
                [wcs.naxis1 / 2, wcs.naxis2 / 2]) * wcs.pscale
        ascii.write([data['id'], arcs[:, 0], arcs[:, 1], data['mag']],
                    outcat,
                    format='no_header',
                    overwrite=True)
        return

    def makeSACatExtRef(self, refcat, outcat):
        """
        Makes a catalog of objects to be used for input to superalign from a external reference catalog.
        Catalog should be of form: ID RA(deg) Dec(deg) Mag
        """
        data = ascii.read(refcat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
        arcs = (
            self.refwcs.all_world2pix(list(zip(data['ra'], data['dec'])), 1) -
            [self.refwcs.naxis1 / 2, self.refwcs.naxis2 / 2
             ]) * self.refwcs.pscale
        ascii.write([data['id'], arcs[:, 0], arcs[:, 1], data['mag']],
                    outcat,
                    format='no_header',
                    overwrite=True)
        return
Esempio n. 5
0
def characterize_gaia_distribution(hap_obj, log_level=logutil.logging.NOTSET):
    """Statistically describe distribution of GAIA sources in footprint.

    Computes and writes the file to a json file:

    - Number of GAIA sources
    - X centroid location
    - Y centroid location
    - X offset of centroid from image center
    - Y offset of centroid from image center
    - X standard deviation
    - Y standard deviation
    - minimum closest neighbor distance
    - maximum closest neighbor distance
    - mean closest neighbor distance
    - standard deviation of closest neighbor distances

    Parameters
    ----------
    hap_obj : drizzlepac.hlautils.Product.FilterProduct
        hap product object to process

    log_level : int, optional
        The desired level of verboseness in the log statements displayed on the screen and written to the .log file.
        Default value is 'NOTSET'.

    Returns
    -------
    Nothing
    """
    log.setLevel(log_level)

    # get table of GAIA sources in footprint
    gaia_table = generate_gaia_catalog(
        hap_obj, columns_to_remove=['mag', 'objID', 'GaiaID'])

    # if log_level is either 'DEBUG' or 'NOTSET', write out GAIA sources to DS9 region file
    if log_level <= logutil.logging.DEBUG:
        reg_file = "{}_gaia_sources.reg".format(hap_obj.drizzle_filename[:-9])
        gaia_table.write(reg_file, format='ascii.csv')
        log.debug(
            "Wrote GAIA source RA and Dec positions to DS9 region file '{}'".
            format(reg_file))

    # convert RA, Dec to image X, Y
    outwcs = HSTWCS(hap_obj.drizzle_filename + "[1]")
    x, y = outwcs.all_world2pix(gaia_table['RA'], gaia_table['DEC'], 1)

    # compute stats for the distribution
    centroid = [np.mean(x), np.mean(y)]
    centroid_offset = []
    for idx in range(0, 2):
        centroid_offset.append(outwcs.wcs.crpix[idx] - centroid[idx])
    std_dev = [np.std(x), np.std(y)]

    # Find straight-line distance to the closest neighbor for each GAIA source
    xys = np.array([x, y])
    xys = xys.reshape(len(x), 2)
    tree = KDTree(xys)
    neighborhood = tree.query(xys, 2)
    min_seps = np.empty([0])
    for sep_pair in neighborhood[0]:
        min_seps = np.append(min_seps, sep_pair[1])

    # add statistics to out_dict
    out_dict = collections.OrderedDict()
    out_dict["units"] = "pixels"
    out_dict["Number of GAIA sources"] = len(gaia_table)
    axis_list = ["X", "Y"]
    title_list = [
        "centroid", "offset of centroid from image center",
        "standard deviation"
    ]
    for item_value, item_title in zip([centroid, centroid_offset, std_dev],
                                      title_list):
        for axis_item in enumerate(axis_list):
            log.info("{} {} ({}): {}".format(axis_item[1], item_title,
                                             out_dict["units"],
                                             item_value[axis_item[0]]))
            out_dict["{} {}".format(axis_item[1],
                                    item_title)] = item_value[axis_item[0]]
    min_sep_stats = [
        min_seps.min(),
        min_seps.max(),
        min_seps.mean(),
        min_seps.std()
    ]
    min_sep_title_list = [
        "minimum closest neighbor distance",
        "maximum closest neighbor distance", "mean closest neighbor distance",
        "standard deviation of closest neighbor distances"
    ]
    for item_value, item_title in zip(min_sep_stats, min_sep_title_list):
        log.info("{} ({}): {}".format(item_title, out_dict["units"],
                                      item_value))
        out_dict[item_title] = item_value

    # write catalog to HapDiagnostic-formatted .json file.
    diag_obj = du.HapDiagnostic(log_level=log_level)
    diag_obj.instantiate_from_hap_obj(
        hap_obj,
        data_source="{}.characterize_gaia_distribution".format(__taskname__),
        description=
        "A statistical characterization of the distribution of GAIA sources in image footprint"
    )
    diag_obj.add_data_item(out_dict,
                           "distribution characterization statistics")
    diag_obj.write_json_file(hap_obj.drizzle_filename[:-9] +
                             "_svm_gaia_distribution_characterization.json",
                             clobber=True)
Esempio n. 6
0
    def make_grismcat(self,
                      drizzle_image="",
                      catalog=None,
                      hard_angle=False,
                      hard_angle_value=90.):
        """Make the grism catalog.

        The method creates a new input object list. The positional
        information on objects in a drizzled image are projected
        back into the coordinate system of one input image.
        A selection is done on the basis of the projected coordinates,
        and the selected objects are stored to a new IOL file with an
        updated object angle that is in the projected coordinate system.

        Parameters
        ----------
        drizzle_image : str
            The name of the drizzled mosaic image that the catalog
            was constructed from.

        catalog : astropy.table.Table
            A the master catalog which will be used to
            create the dither image catalog with updated angles

        hard_angle : bool
            This will always set the extraction angle to 90degrees.

        hard_angle_value : float
            If a specified angle for extraction is preferred then
            this is the value to use and will replace THETA_IMAGE
            in the output catalog. It's currently specified in
            degrees, and is converted appropriately for whatever
            units are used in the catalog itself.

        Returns
        -------
        Nothing

        Notes
        -----
        This method previous took the names of two text files that contained the
        displayed position and angles calculated from the catalog entry. That
        functionality has been moved to memory since awtran is no longer in use.
        The catalog is read directly.
        """

        if not drizzle_image:
            raise aXeError("IOLPREP: No drizzle image specified.")

        if catalog is None:
            raise aXeError("IOLPREP: No input catalog provided.")
        if not isinstance(catalog, Table):
            raise aXeError(
                "IOLPREP: Expected input catalog to be an astropy table")

        _log.info("\n >>>> Working on Input Object List: {0:s} >>>>\n".format(
            self.iol_name))

        # now translate ra dec to new image pixel points
        # this must go through the wcs of the mosaic image
        # and then through the wcs for the individual image
        _log.info(
            "Converting coordinates using wcs from grism image {0}\n".format(
                self.filename))
        trad = catalog['THETA_IMAGE']
        xcat = catalog['X_IMAGE']
        ycat = catalog['Y_IMAGE']

        # translate to degrees if necessary
        if catalog['THETA_IMAGE'].unit.name == 'deg':
            translate = True
        elif catalog['THETA_IMAGE'].unit.name == 'rad':
            translate = False
            hard_angle_value = math.radians(hard_angle_value)
        else:
            raise aXeError("Unknown unit on THETA_IMAGE in input catalog")

        # 10.0 is a made up scaling length to use to
        # get the angle precision
        shifted_x = []
        shifted_y = []
        for t, x, y in zip(trad, xcat, ycat):
            if translate:
                angle = math.radians(t)

            shifted_x.append(x + 10.0 * math.cos(angle))
            shifted_y.append(y + 10.0 * math.sin(angle))

        # translate the catalog (x, y) to (ra, dec)
        mosaic_image_wcs = HSTWCS(drizzle_image, ext=1)
        mosaic_image_ra, mosaic_image_dec = mosaic_image_wcs.wcs_pix2world(
            shifted_x, shifted_y, 1)
        # compute  the location in the dithered image using the shifted coords
        dither_image_wcs = HSTWCS(self.filename)
        dither_image_x, dither_image_y = dither_image_wcs.all_world2pix(
            mosaic_image_ra, mosaic_image_dec, 1)
        trans_ra, trans_dec = mosaic_image_wcs.wcs_pix2world(xcat, ycat, 1)
        trans_x, trans_y = dither_image_wcs.all_world2pix(
            trans_ra, trans_dec, 1)

        output_catalog = deepcopy(catalog)
        for row in range(len(catalog) - 1, -1, -1):
            x = trans_x[row]
            y = trans_y[row]
            # check whether the object position is
            # in the range to be stored
            if ((self.dim_info[0] <= x <= self.dim_info[1])
                    and (self.dim_info[2] <= y <= self.dim_info[3])):

                # compute the new object angle
                dx = xcat[row] - x
                dy = ycat[row] - y
                angle = math.atan2(dy, dx)  # compute local angle change

                # return to degrees for catalog if necessary
                if translate:
                    angle = math.degrees(angle)

                # _log.info("dx {} dy {}  angle {} x,y: ({},{})\n".format(dx, dy, angle, x, y))
                # fill in the new position and angle
                output_catalog['X_IMAGE'][row] = trans_x[row]
                output_catalog['Y_IMAGE'][row] = trans_y[row]
                if hard_angle:
                    output_catalog['THETA_IMAGE'][row] = hard_angle_value
                else:
                    output_catalog['THETA_IMAGE'][row] = angle
            else:
                _log.info(
                    f"{x}\t{y}\t{self.dim_info}\t{output_catalog['NUMBER'][row]}"
                )
                output_catalog.remove_row(row)

        # save the new IOL, this is done especially for the C
        # code which is expecting Source Extractor style catalog
        # files. Decided to keep the output here consistent with
        # the C code so that it can continue to be used separately.
        # numbers start at 1 not zero. The output formatting allows
        # the astropy.sextractor formatter to read the catalog file.
        # There isn't currently an astropy writer for that format.
        if os.access(self.iol_name, os.F_OK):
            os.remove(self.iol_name)
        of = open(self.iol_name, 'w')
        for num, name in zip(range(len(output_catalog.colnames) + 1),
                             output_catalog.colnames):
            of.write("# {0:d} {1:s}\t\t{2:s}\t\t[{3:s}]\n".format(
                num + 1, name, output_catalog[name].description,
                str(output_catalog[name].unit)))
        output_catalog.write(of, format='ascii.no_header', overwrite=False)
        of.close()

        _log.info(
            f"\n >>>> Catalog: {self.iol_name} written with {len(catalog)} entries.>>>> \n"
        )
Esempio n. 7
0
class MakeCat(object):
    def __init__(self, refimg):
        super(MakeCat, self).__init__()
        self.refimg = str(refimg)
        self.refwcs = HSTWCS(self.refimg)
        
    def getInstDet(self, imgfile):
        """Get the instrument/detector of an HST image (e.g. acswfc)"""
        hdr = fits.getheader(imgfile)
        return '%s%s' % (hdr['instrume'].lower(), hdr['detector'].lower())

    def findSources(self, inputfile, outputfile, instdet, weightfile=None, extref=False, **sconfig):
        """Finds objects in image"""
        # Set up SExtractor
        sex = sextractor.SExtractor()
        # Load the default configuration
        if instdet == 'acswfc' or instdet == 'wfc3uvis':
            for k,v in _sex_config_ACSWFC.iteritems():
                sex.config[k] = v
        if instdet == 'wfc3ir':
            for k,v in _sex_config_WFC3IR.iteritems():
                sex.config[k] = v
        if sconfig:
            # Load any runtime configuration
            for k,v in sconfig.iteritems():
                sex.config[k] = v
        if weightfile:
            sex.config['WEIGHT_IMAGE'] = weightfile
            sex.config['WEIGHT_TYPE'] = 'MAP_WEIGHT'
            sex.config['WEIGHT_GAIN'] = 'N'
        sex.config['CATALOG_NAME'] = outputfile
        # Load default parameters'
        sex.config['PARAMETERS_LIST'] = []
        for p in _sex_parms:
            sex.config['PARAMETERS_LIST'].append(p)
        # Run SExtractor
        sex.run(inputfile)
        cfg = _sa_config[instdet]
        low_limit = cfg['low_limit']
        hi_limit = cfg['hi_limit']
        objectlist = []
        for l in [i.split() for i in open(outputfile).readlines()]:
            if l[0] != '#':
                x = float(l[1])
                y = float(l[2])
                ra = float(l[3])
                if l[4].startswith('+'):
                    dec = float(l[4][1:])
                else:
                    dec = float(l[4])
                aa = float(l[5])
                ba = float(l[6])
                r = ba / aa
                m = float(l[7])
                f = float(l[8])
                fwhm = float(l[9])

                if min(2.3 * ba, fwhm) >= low_limit and max(2.3 * aa, fwhm) < hi_limit and r > cfg['min_axis_ratio']:
                    objectlist.append(Object(x, y, ra, dec, r, m, f))
                    
        return objectlist

    def removeCloseSources(self, objectlist):
        """Removes objects from catalog with multiple close detections"""
        for objecti in objectlist:
            for objectj in objectlist:
                dist = ((objecti.x - objectj.x) ** 2 + (objecti.y - objectj.y) ** 2) ** 0.5
                if dist < 10 and dist > 0:
                    if objecti.mag < objectj.mag:
                        objectj.nextToBig = 1
                    else:
                        objecti.nextToBig = 1
        objectlist_keep = []
        for objecti in objectlist:
            if not objecti.nextToBig:
                objectlist_keep.append(objecti)
            else:
                print 'Excluding object at %i %i' % (objecti.x, objecti.y)
        return objectlist_keep
    
    
    def makeCat(self, imgfile, instdet, weightfile=None, extref=False):
        """Makes a catalog of objects to be used for input to superalign and creates a DS9 region file of objects"""
        
        imgfile_cat = '%s.cat' % imgfile.replace('.fits', '')
        imgfile_reg = '%s.reg' % imgfile.replace('.fits', '')
    
        o_radec = []
        ext = 0
        objectlist = self.findSources('%s[%s]' % (imgfile, ext), imgfile_cat, instdet, weightfile, extref=extref)
        cleanobjectlist = self.removeCloseSources(objectlist)
        print 'Found %s sources' % len(cleanobjectlist)
        wcs = HSTWCS(str(imgfile))
        for obj in cleanobjectlist:
            sky = wcs.all_pix2world(np.array([[obj.x, obj.y]]), 1)
            o_radec.append([obj.ra[0], obj.dec[0]])
            obj.ra = sky[0][0]
            obj.dec = sky[0][1]
        
        # Write out a ds9 region file of object selected for alignment
        regout = open(imgfile_reg, 'w')
        regout.write('global color=green font="helvetica 8 normal" edit=1 move=1 delete=1 include=1 fixed=0\nfk5\n')
        for i,rd in enumerate(o_radec):
            oid = i+1
            regout.write('circle(%s,%s,%s") # color=%s text={%s}\n' % (rd[0], rd[1], 0.5, 'red', oid))
        regout.close()
    
        # Now we need to write out the catalog in the reference image coords in arcseconds with respect to center of the image
        catout = open(imgfile_cat, 'w')
        for i,obj in enumerate(cleanobjectlist):
            oid = i+1
            catout.write('%i %.9f %.9f %.4f %.4f %.4f\n' % (oid, obj.ra, obj.dec, obj.x, obj.y, obj.mag))
        catout.close()
        return
    
    def makeSACat(self, imgfile, extref=False):
        """
        Makes a catalog of objects to be used for input to superalign from a external reference catalog.
        Catalog should be of form: ID RA(deg) Dec(deg) Mag
        Output appends _sa
        """
        if extref:
            wcs = self.refwcs
        else:
            wcs = HSTWCS(imgfile)
        cat = imgfile.replace('.fits', '.cat')
        outcat = imgfile.replace('.fits', '_sa.cat')
        data = ascii.read(cat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
        arcs = (wcs.all_world2pix(zip(data['ra'], data['dec']), 1) - [wcs.naxis1/2, wcs.naxis2/2])*wcs.pscale
        ascii.write([data['id'], arcs[:,0], arcs[:,1], data['mag']], outcat, format='no_header')
        return
    
    def makeSACatExtRef(self, refcat, outcat):
        """
        Makes a catalog of objects to be used for input to superalign from a external reference catalog.
        Catalog should be of form: ID RA(deg) Dec(deg) Mag
        """
        data = ascii.read(refcat, names=['id', 'ra', 'dec', 'x', 'y', 'mag'])
        arcs = (self.refwcs.all_world2pix(zip(data['ra'], data['dec']), 1) - [self.refwcs.naxis1/2, self.refwcs.naxis2/2])*self.refwcs.pscale
        ascii.write([data['id'], arcs[:,0], arcs[:,1], data['mag']], outcat, format='no_header')
        return
    def make_grismcat(self,
                      data_name,
                      data_angle,
                      grism_cat,
                      mdrizzle_image,
                      odd_signs=None):
        """
        Input:
            data_name      - filename of the position data
            data_angle     - filename of the displaced positions
            grism_cat      - refernece to the axecat object
            mdrizzle_image - name of the multidrizzled image

        Return:
            -

        Description:
            The method creates a new input object list. The positional
            information on objects in a multidrizzled image are projected
            back into the coordinate system of one nput image.
            A selection is done on the basis of the projected coordinates,
            and the selected objects are stored to a new IOL file
        """

        import os
        import os.path
        import math

        from . import awtran

        print('')
        print(' >>>> Working on Input Object List: ', self.iol_name, '>>>>')
        print('')

        #------------------------------------------------------------------------
        # newer faster version from aXe-1.7 on:
        #
        if (self.useMdriz):
            print("Using multidrizzle coeffs for coordinate transformation\n")
            dir_pts = awtran.b(mdrizzle_image + "[SCI]",
                               self.header_name,
                               List=data_name)
            ang_pts = awtran.b(mdrizzle_image + "[SCI]",
                               self.header_name,
                               List=data_angle)

        else:
            #use HSTWCS instead for the astrodrizzle image
            #read in the data_name file
            # awtran gives back this format: all_out.append("%10.3f %10.3f %10.3f %10.3f" % (xin,yin,xout,yout))

            hstimage = HSTWCS(mdrizzle_image, ext=1)

            datanamefile = open(data_name, 'r')
            datapoints = datanamefile.readlines()
            data = [list(map(float, line.split())) for line in datapoints]

            skypoints = hstimage.all_pix2world(
                data,
                1)  #trans points are now in ra and dec from mdrizzle_image
            #now translate to new image pixel points

            newhstimage = HSTWCS(self.header_name)

            trans_pts = newhstimage.all_world2pix(skypoints[:, 0],
                                                  skypoints[:, 1], 1)

            #pix2sky returns (2,len) array of points, reshape for what awtran returned
            dir_pts = list()

            for i in range(0, len(trans_pts[0])):
                dir_pts.append("%10.8g %10.8g %10.8g %10.8g" %
                               (trans_pts[0][i], trans_pts[1][i],
                                skypoints[i, 0], skypoints[i, 1]))

            #now the same for the ang file points
            angfile = open(data_angle, 'r')
            angpoints = angfile.readlines()
            data = [list(map(float, line.split())) for line in datapoints]

            ang_pts = list()
            for i in range(0, len(trans_pts[0])):
                ang_pts.append(
                    "%10.8g %10.8g %10.8g %10.8g" %
                    (data[i][0], data[i][1], trans_pts[0][i], trans_pts[1][i]))

        # delete the first element,
        # which contains a description only
        # but only for the multidrizzle version
        #-------------------------------------------------------------------------
        if self.useMdriz:
            del (dir_pts[0])
            del (ang_pts[0])

        # start the reverse index;
        # iterate over all objects
        r_index = len(dir_pts) - 1

        for index in range(grism_cat.nrows):
            # extract the projected object positions
            x_ori = float(dir_pts[r_index].split()[0])
            y_ori = float(dir_pts[r_index].split()[1])

            # check whether the object position is
            # range to be stored
            if x_ori >= self.dim_info[0] and x_ori <= self.dim_info[1] and \
               y_ori >= self.dim_info[2] and y_ori <= self.dim_info[3]:

                # extract the displaced projected position
                x_ang = float(ang_pts[r_index].split()[0])
                y_ang = float(ang_pts[r_index].split()[1])

                # compute the new object angle
                dx = x_ang - x_ori
                dy = y_ang - y_ori
                angle = math.atan2(dy, dx) / math.pi * 180.0

                # Note: this correction is only necessary
                #       as long as there are two different
                #       flavors in pydrizzle and iraf.drizzle
                if (self.useMdriz):
                    if odd_signs != None:
                        if odd_signs[0]:
                            x_ori -= 0.5
                        if odd_signs[1]:
                            y_ori -= 0.5

                # fill in the new position and angle
                grism_cat['X_IMAGE'][r_index] = x_ori
                grism_cat['Y_IMAGE'][r_index] = y_ori
                grism_cat['THETA_IMAGE'][r_index] = angle

            # delete outside entries
            else:
                grism_cat.delete(r_index)

            # decrease the reverse index
            r_index -= 1

        # save the new IOL
        grism_cat.writeto(self.iol_name)

        print('')
        print(' >>>> Catalog: ', self.iol_name, 'written with ',
              grism_cat.nrows, 'entries.>>>>')
        print('')