示例#1
0
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    fig, axes = plt.subplots(figsize=(11, 8))

    axes.hist(separations, 30, histtype='step')
    axes.set_xlabel(r'Separation / arcseconds')
    axes.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]

        x = hdu['X_coordinate'][:]
        y = hdu['Y_coordinate'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    fig, axes = plt.subplots(2, 2, sharex=True, figsize=(11, 8))
    [(x_axis, y_axis), (x_zoomed, y_zoomed)] = axes

    nsigma = 5
    nbins = 2048 / 128
    print('Using {} bins'.format(nbins))
    x_axis.plot(x, separations, 'k.', color='0.4')
    x_axis.set_ylabel(r'X')

    ledges, x_binned = compute_binned(x, separations, nbins)
    _, x_binned_error = compute_binned_errors(x, separations, ledges)
    bin_centres = compute_bin_centres(ledges)

    for ax in [x_axis, x_zoomed]:
        ax.errorbar(bin_centres[:-1], x_binned[:-1], x_binned_error[:-1],
                color='r', ls='None')
        ax.plot(ledges, x_binned, color='r', drawstyle='steps-post')

    y_axis.plot(y, separations, 'k.', color='0.4')
    y_axis.set_ylabel(r'y')

    ledges, y_binned = compute_binned(y, separations, nbins)
    _, y_binned_error = compute_binned_errors(y, separations, ledges)

    for ax in [y_axis, y_zoomed]:
        ax.errorbar(bin_centres[:-1], y_binned[:-1], x_binned_error[:-1],
                color='r', ls='None')
        ax.plot(ledges, y_binned, color='r', drawstyle='steps-post')

    link_y_limits(x_zoomed, y_zoomed)

    for ax in axes.flatten():
        ax.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
def ra_dec_distance(ra1, dec1, ra2, dec2, use_icrs=False, arcsec=False):
    # conversion between degree and radians
    pi  = 3.1415926536
    d2r = pi/180.00

    if use_icrs:
        coord1 = ICRS(ra=ra1, dec=dec1, unit=(u.degree,u.degree))
        coord2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree,u.degree))
    else:
        coord1 = FK5(ra=ra1, dec=dec1, unit=(u.degree,u.degree))
        coord2 = FK5(ra=ra2, dec=dec2, unit=(u.degree,u.degree))
    # The separation is in unit of arcsecond or degree
    if arcsec:
        sep = coord1.separation(coord2).arcsecond
    else:
        sep = (coord1.separation(coord2).radian / d2r )

    return sep
示例#4
0
文件: region.py 项目: Cadair/gammapy
class SkyCircle(object):
    """A circle on the sky.
    
    Parameters
    ----------
    center : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
        Circle center coordinate
    radius : `~astropy.coordinates.angles.Angle`
        Circle radius
    """
    
    def __init__(self, center, radius):
        from astropy.coordinates import ICRS, Angle
        self.center = ICRS(center)
        self.radius = Angle(radius)

    def contains(self, coordinate):
        """Checks if the coordinate lies inside the circle.

        Parameters
        ----------
        coordinate : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
            Coordinate to check for containment.

        Returns
        -------
        contains : bool
            Does this region contain the coordinate?
        """
        return self.center.separation(coordinate) <= self.radius

    def intersects(self, other):
        """Checks if two sky circles overlap.

        Parameters
        ----------
        other : `~SkyCircle`
            Other region.
        """
        return self.center.separation(other.center) <= self.radius + other.radius
示例#5
0
 def test_moon_radec(self):
     """Verify moon (ra,dec) for first week of 2020"""
     ephem = get_ephem()
     for i, jd in enumerate(self.table['jd']):
         t = Time(jd, format='jd')
         night = ephem.get_night(t)
         f_moon = get_object_interpolator(night, 'moon', altaz=False)
         dec, ra = f_moon(t.mjd)
         truth = ICRS(ra=self.table['ra'][i] * u.deg,
                      dec=self.table['dec'][i] * u.deg)
         calc = ICRS(ra=ra * u.deg, dec=dec * u.deg)
         sep = truth.separation(calc)
         self.assertTrue(abs(sep.to(u.deg).value) < 0.3)
示例#6
0
def test_array_separation():
    c1 = ICRS([0, 0]*u.deg, [0, 0]*u.deg)
    c2 = ICRS([1, 2]*u.deg, [0, 0]*u.deg)

    npt.assert_array_almost_equal(c1.separation(c2).degree, [1, 2])

    c3 = ICRS([0, 3.]*u.deg, [0., 0]*u.deg, distance=[1, 1.] * u.kpc)
    c4 = ICRS([1, 1.]*u.deg, [0., 0]*u.deg, distance=[1, 1.] * u.kpc)

    # the 3-1 separation should be twice the 0-1 separation, but not *exactly* the same
    sep = c3.separation_3d(c4)
    sepdiff = sep[1] - (2 * sep[0])

    assert abs(sepdiff.value) < 1e-5
    assert sepdiff != 0
示例#7
0
def test_array_separation():
    c1 = ICRS([0, 0] * u.deg, [0, 0] * u.deg)
    c2 = ICRS([1, 2] * u.deg, [0, 0] * u.deg)

    npt.assert_array_almost_equal(c1.separation(c2).degree, [1, 2])

    c3 = ICRS([0, 3.] * u.deg, [0., 0] * u.deg, distance=[1, 1.] * u.kpc)
    c4 = ICRS([1, 1.] * u.deg, [0., 0] * u.deg, distance=[1, 1.] * u.kpc)

    # the 3-1 separation should be twice the 0-1 separation, but not *exactly* the same
    sep = c3.separation_3d(c4)
    sepdiff = sep[1] - (2 * sep[0])

    assert abs(sepdiff.value) < 1e-5
    assert sepdiff != 0
示例#8
0
def test_table_can_be_read_and_coords_good():
    objs = Table.read(TABLE_NAME, format='ascii', delimiter=',')
    columns = ['object', 'ra', 'dec']
    for col in columns:
        assert col in objs.colnames
    for row in objs:
        try:
            simbad_pos = ICRS.from_name(row['object'])
        except name_resolve.NameResolveError:
            continue
        table_pos = ICRS(row['ra'], row['dec'], unit=(u.hour, u.degree))
        # CHANGE ASSERT TO IF/THEN, print name then assert 0
        sep = table_pos.separation(simbad_pos).arcsec
        warn = ''
        if sep > MAX_SEP:
            warn = ('Bad RA/Dec for object {}, '
                    'separation is {} arcsec'.format(row['object'], sep))
            print (warn)
        assert len(warn) == 0
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]

        jmag = hdu['jmag'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    nbins = 30
    height, xedges, yedges = np.histogram2d(jmag, separations, nbins)

    fig, axis = plt.subplots(figsize=(11, 8))

    mappable = axis.pcolormesh(xedges[:-1], yedges[:-1], np.log10(height.T + 1), 
            cmap=plt.cm.binary)
    axis.plot(jmag, separations, 'k.', alpha=0.2)

    stat, ledges, _ = stats.binned_statistic(jmag, separations, statistic='median',
            bins=nbins)
    axis.plot(ledges[:-1], stat, drawstyle='steps-post', color='r')

    axis.set_xlabel(r'2MASS J Magnitude')
    axis.set_ylabel(r'Separation / arcseconds')
    axis.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
示例#10
0
class ObjCat(Table):
    """

   The __init__ method has been changed to return something like a record
   array, which has the same number of rows as the old 2D float array, but
   which stores each row as a single tuple.  It is thus a 1D array, sort of
   like a structure array in C.  The columns can be accessed by field name,
   which for now is just 'f0', 'f1', etc., unless the input catalog is in
   SExtractor's FITS LDAC format, in which case the field names actually
   correspond to the SExtractor variable names.

   The code used to expect the old 2D float array format.  It should have
   all been updated, but there may still be some issues.

   """
    def __init__(self,
                 incat,
                 catformat='ldac',
                 verbose=True,
                 namecol=None,
                 racol=None,
                 deccol=None,
                 rafield=None,
                 decfield=None,
                 usecols=False):
        """
      This method gets called when the user types something like
         cat = ObjCat(infile)

      Inputs:
         incat     - input table data.  This can be in one of two forms:
                       1. a file containing the catalog (most common)
                       2. a Table instance containing the catalog data
         catformat - format of the input file, if incat is a filename.  
                     The options are:
                      ascii    - 
                      asciitab -
                      ldac     - 
                      csv      -
                      sdssfits - 
                      secat    -
                     NOTE: this parameter is not used if incat is a Table
                      rather than the name of an input file
      """
        """ Set a flag showing whether the file has been modified """
        self.modified = False
        """ Set other default values """
        self.radec = None
        self.rafield = None
        self.decfield = None
        self.centpos = None
        self.galmask = None
        self.starmask = None
        """
      Start by loading the catalog information
      """
        incattype = (str(type(incat))).split('.')[-1]
        if incattype[0:3] == 'Tab' or incattype[0:4] == 'FITS':
            self.data = incat.copy()
            if rafield:
                self.rafield = rafield
            if decfield:
                self.decfield = decfield
            self.nrows = len(incat)
            self.ncols = len(incat.columns)
            self.catformat = 'Table'

        elif isinstance(incat, str):
            self.load_from_file(incat,
                                catformat=catformat,
                                verbose=verbose,
                                namecol=namecol,
                                racol=racol,
                                deccol=deccol,
                                rafield=rafield,
                                decfield=decfield,
                                usecols=usecols)
        else:
            print('')
            print('ERROR: input catalog must either be a filename or a Table')
            print(' Input catalog type is' + str(type(incat)))
            print('')
            return None

    #-----------------------------------------------------------------------

    def load_from_file(self,
                       incat,
                       catformat='ldac',
                       verbose=True,
                       namecol=None,
                       racol=None,
                       deccol=None,
                       rafield=None,
                       decfield=None,
                       usecols=False):

        if verbose:
            print('')
            print("Loading data from catalog file %s" % incat)
            print("-----------------------------------------------")
            print("Expected catalog format: %s" % catformat)
            print('')
        """
      Define a flag for successful reading of input catalog
      """
        read_success = True
        """ Read in catalog in a manner appropriate to the catformat """
        if catformat == 'secat':
            try:
                self.data = ascii.read(incat)
                ncols = len(self.data.colnames)
                nrows = len(self.data)
                """ Set the field names """
                self.rafield = 'ALPHA_J2000'
                self.decfield = 'DELTA_J2000'
            except:
                print("  ERROR. Problem in loading file %s" % incat)
                print(
                    "  Check to make sure filename matches an existing file.")
                print('')
                print(
                    "  This also may have failed if the input file is in the")
                print("   SExtractor FITS LDAC format.  Checking that...")
                print('')
                read_success = False

        elif catformat == 'asciitab':
            f = open(incat)
            foo = f.readline()
            f.close()
            if foo[0] == '#':
                try:
                    self.data = ascii.read(incat,
                                           guess=False,
                                           format='commented_header')
                except:
                    print('')
                    print('ERROR: Could not read data from %s' % incat)
                    print(' Tried using "commented_header" format but failed')
                    print(' Please check input file.')
                    print('')
                    raise IOError
            else:
                try:
                    self.data = ascii.read(incat)
                except:
                    print('')
                    print('ERROR: Could not properly read data from %s' %
                          incat)
                    print('Tried using the automatic formatting but failed')
                    print(' Please check input file.')
                    print('')
                    raise IOError
            ncols = len(self.data.colnames)
            nrows = len(self.data)
            """ Set the field names """
            if rafield:
                self.rafield = rafield
            if decfield:
                self.decfield = decfield

        elif catformat == 'ascii':
            """ ASCII format """
            try:
                """ Set up the data format in the catalog """
                foo = np.loadtxt(incat, dtype='S30')
                ncols = foo.shape[1]
                del foo
                coltypes = np.ones(ncols, dtype='S3')
                coltypes[:] = 'f8'
                if namecol is not None:
                    print("Object name column: %d" % namecol)
                    coltypes[namecol] = 'S30'
                colstr = ''
                for i in range(ncols):
                    colstr = '%s,%s' % (colstr, coltypes[i])
                colstr = colstr[1:]
                dt = np.dtype(colstr)
                """ Actually read in the data """
                self.informat = 'ascii'
                self.data = np.loadtxt(incat, dtype=dt)
                nrows = self.data.shape[0]
                """ Set the field names """
                if racol is not None:
                    self.rafield = 'f%d' % racol
                else:
                    self.rafield = None
                if deccol is not None:
                    self.decfield = 'f%d' % deccol
                else:
                    self.decfield = None
                if namecol is not None:
                    self.namefield = 'f%d' % namecol
                else:
                    self.namefield = None

            except:
                print("  ERROR. Problem in loading file %s" % incat)
                print(
                    "  Check to make sure filename matches an existing file.")
                print("  ")
                print("  This may have failed if there is a string column in")
                print("   the input catalog (e.g., for an object name).  ")
                print(
                    "  If this is the case, use the namecol to indicate which "
                )
                print(
                    "   column contains the string values (column numbers are "
                )
                print("   zero-indexed)")
                print('')
                print(
                    "  This also may have failed if the input file is in the")
                print("   SExtractor FITS LDAC format.  Checking that...")
                print('')
                read_success = False

        elif catformat.lower() == 'ldac' or read_success == False:
            try:
                self.data = Table.read(incat, format='fits', hdu=2)
            except:
                print("  ERROR. Problem in loading file %s" % incat)
                print(
                    "  Check to make sure filename matches an existing file.")
                print('')
                return
            self.informat = 'ldac'
            nrows = len(self.data)
            ncols = len(self.data.columns)
            """ Set the field names """
            self.rafield = 'ALPHA_J2000'
            self.decfield = 'DELTA_J2000'

        elif catformat.lower() == 'csv' or read_success == False:
            try:
                self.data = Table.read(incat)
            except:
                print("  ERROR. Problem in loading file %s" % incat)
                print(
                    "  Check to make sure filename matches an existing file.")
                print('')
                return
            self.informat = 'csv'
            nrows = len(self.data)
            ncols = len(self.data.columns)
            """ Set the field names """
            self.rafield = 'raStack'
            self.decfield = 'decStack'

        elif catformat.lower() == 'sdssfits' or read_success == False:
            try:
                self.data = Table.read(incat, format='fits', hdu=1)
            except:
                print("  ERROR. Problem in loading file %s" % incat)
                print(
                    "  Check to make sure filename matches an existing file.")
                print('')
                return
            self.informat = 'sdss'
            nrows = len(self.data)
            ncols = len(self.data.columns)
            """ Set the field names """
            self.rafield = 'ra'
            self.decfield = 'dec'
            """
         Split the stars from the galaxies, according to the SDSS 
         classification.
         In the SDSS scheme, type=3 is a galaxy and type=6 is a star
         """
            if 'type' in self.data.colnames:
                objclass = self.data['type']
            elif 'type_r' in self.data.colnames:
                objclass = self.data['type_r']
            else:
                objclass = None

            if objclass is not None:
                self.galmask = objclass == 3
                self.starmask = objclass == 6
            else:
                self.galmask = np.ones(dtype=bool)
                self.starmask = None
            print('Read SDSS catalog from %s' % incat)
            print('Number of galaxies: %5d' % self.galmask.sum())
            if self.starmask is not None:
                print('Number of stars:    %5d' % self.starmask.sum())

        else:
            print('')
            print('Unrecognized format.  Must be one of:')
            print('  ascii, secat, ldac, sdssfits')
            sys.exit()

        if verbose:
            print("Number of rows:    %d" % nrows)
            print("Number of columns: %d" % ncols)
            if self.rafield is not None:
                print('RA field name:  %s' % self.rafield)
            if self.decfield is not None:
                print('Dec field name: %s' % self.decfield)

        self.infile = incat
        self.catformat = catformat
        self.nrows = nrows
        self.ncols = ncols

    #-----------------------------------------------------------------------

    def close_ldac(self):
        """
      Closes the catalog.  If the catalog is in fits format and it has
      been modified (as shown by the modified parameter in this ObjCat class)
      then use flush rather than close.
      """
        """ Close the file if it is in the expected format """
        if self.informat == 'ldac':
            if self.modified:
                self.hdu.flush()
                print('Updating input fits LDAC file: %s' % self.infile)
            else:
                self.hdu.close()
        else:
            print('')
            print('WARNING. Calling close_ldac but file is not in ldac format')
            print('')

    #----------------------------------------------------------------------

    def make_magmask(self, magname, mfaint=None, mbright=None):
        """
      Makes a mask that is True for magnitudes brighter than mfaint and
       fainter than mbright.
      Note that one of these two could have the value None, in which case
       it would be ignored.  For example, if mbright is None, then the mask
       will be True for all galaxies brighter than mfaint

      Inputs:
       magname - the name in the catalog for the column that represents the
                  object magnitudes.  This could be something like, e.g., 'r' 
                  or 'MAG_AUTO'
      """

        mag = self.data[magname].astype(float)
        if mfaint is None and mbright is None:
            self.magmask = np.ones(self.nrows, dtype=bool)
        elif mfaint is None:
            self.magmask = mag >= mbright
        elif mbright is None:
            self.magmask = mag <= mfaint
        else:
            self.magmask = (mag >= mbright) & (mag <= mfaint)

    #-----------------------------------------------------------------------

    def get_radec(self):
        """
      Extracts the RA and Dec information from the data container.  This
      is not necessary, and some of the data containers may not even have
      WCS info, but extracting the coordinates if it does simplifies some
      later tasks.
      """
        """ Extract the information into the new containers """
        self.ra = None
        self.dec = None
        if self.rafield is not None:
            try:
                self.ra = self.data[self.rafield].copy()
            except:
                try:
                    self.ra = self.data['x_world'].copy()
                except:
                    self.ra = None
        if self.decfield is not None:
            try:
                self.dec = self.data[self.decfield].copy()
            except:
                try:
                    self.dec = self.data['y_world'].copy()
                except:
                    self.dec = None
        """ Make sure that values are in the correct range """
        self.ra = self.ra.astype(float)
        self.dec = self.dec.astype(float)
        print(self.ra)
        print(type(self.ra))
        ramask = (self.ra >= 0.) & (self.ra < 360.)
        decmask = (self.dec >= -90.) & (self.dec <= 90.)
        mask = (ramask) & (decmask)
        self.ra = self.ra[mask]
        self.dec = self.dec[mask]
        self.data = self.data[mask]
        """ 
      Put data into a SkyCoords container for easy coordinate-based calculations
      """
        if (self.ra is not None) and (self.dec is not None):
            """ 
         Determine whether the RA coordinate is in hours or in degrees
         For now this test is made simple: if the format of the RA data is
          a string, then the data is expected to be in hms format, otherwise
          expect decimal degrees.
         """
            if type(self.ra[0]) is str or type(self.ra[0]) is np.string_:
                raunit = u.hourangle
            else:
                raunit = u.deg
            self.radec = SkyCoord(self.ra, self.dec, unit=(raunit, u.deg))
        """ 
      If radec has not been set, report this information
      (consider raising an exception in future versions of the code)
      """
        if self.radec is None:
            print('')
            print(
                'WARNING: get_radec was called but RA and Dec information was')
            print(
                '         not found.  Please check the format of your catalog.'
            )
            print('')

    #----------------------------------------------------------------------

    def read_centpos(self, posfile, verbose=False):
        """
      Reads a position in from a file and converts it to an astropy SkyCoord
      format.

      NOTE: right now this is hard-wired to just read in a file in the 
      standard Keck starlist format:

          label rahr ramin rasec decdeg decamin decasec equinox

      which matches the *.pos in CDF's Lenses/Data/* directories

      Inputs:
       posfile - file containing the RA and dec
      """
        """ Read the data from the file """
        posinfo = ascii.read(posfile,
                             names=[
                                 'object', 'rahr', 'ramin', 'rasec', 'decdeg',
                                 'decamin', 'decasec', 'equinox'
                             ])
        """ Convert to SkyCoord format """
        i = posinfo[0]
        ra = '%d:%d:%f' % (i['rahr'], i['ramin'], i['rasec'])
        dec = '%d:%d:%f' % (i['decdeg'], i['decamin'], i['decasec'])
        radec = SkyCoord(ra, dec, unit=(u.hourangle, u.deg))
        """ Print out information if requested """
        if verbose:
            print('')
            print('Object: %s' % i['object'])
            print('Coordinates: %s %s' % \
                     (radec.ra.to_string(unit=u.hourangle, decimal=False,
                                         sep=':', precision=3, pad=True),
                      radec.dec.to_string(decimal=False, sep=':', precision=3,
                                          alwayssign=True, pad=True)))
        """ Save the output within the class """
        self.centpos = radec

    #----------------------------------------------------------------------

    def sort_by_pos(self, centpos):
        """
      Sorts the catalog in terms of distance from some central position, which
      is passed as a SkyCoord variable (from astropy.coordinates)
      """
        """ First check to see that we actual have WCS information  """
        if self.radec is None:
            print('')
            print('ERROR: sort_by_pos.  No WCS information in catalog')
            print('')
            return
        """ Otherwise, use the SkyCoords functionality to easily sort """
        sep = self.radec.separation(centpos)
        try:
            offsets = centpos.spherical_offsets_to(self.radec)
        except:
            offsets = None
        ind = np.argsort(sep.arcsec)
        if self.catformat == 'ascii':
            self.data = self.data[ind, :]
        else:
            print(self.catformat)
            self.data = self.data[ind]
        """ Also sort things that are outside the data table """
        self.radec = self.radec[ind]
        self.ra = self.ra[ind]
        self.dec = self.dec[ind]
        self.sep = sep[ind]
        if offsets is None:
            self.dx = None
            self.dy = None
        else:
            self.dx = (offsets[0].arcsecond)[ind]
            self.dy = (offsets[1].arcsecond)[ind]
        self.sortind = ind

    #-----------------------------------------------------------------------

    def make_reg_file(self,
                      outfile,
                      rcirc,
                      color='green',
                      fluxcol=None,
                      fluxerrcol=None,
                      labcol=None,
                      labdx=0.0012,
                      labdy=0.0012,
                      plot_high_snr=False,
                      mask=None,
                      snrgood=10.):
        """
      Uses the RA and Dec info in the catalog to make a region file that
      can be used with ds9.
      """
        """ 
      Start by putting the RA and Dec info into a somewhat more convenient
      format
      """

        self.get_radec()
        if self.radec is None:
            print('')
            print(
                "ERROR: Could not read RA and Dec information from input file")
            return
        """ 
      If the flux information is given, then report on high SNR detections
      """

        ngood = 0
        snrmask = None
        if fluxcol is not None and fluxerrcol is not None:
            if self.informat == 'ldac':
                if type(fluxcol) is int:
                    flux = self.data.field(fluxcol)
                    fluxerr = self.data.field(fluxerrcol)
                else:
                    flux = self.data[fluxcol]
                    fluxerr = self.data[fluxerrcol]
            else:
                flux = self.data['f%d' % fluxcol]
                fluxerr = self.data['f%d' % fluxerrcol]
            snr = flux / fluxerr
            snrmask = snr > snrgood
        """ Mask the input data if requested """
        print('Total objects in catalog:        %d' % len(self.radec))
        if mask is not None:
            radec = self.radec[mask]
            selmask = mask
            print('Objects selected by mask:        %d' % len(radec))
        else:
            radec = self.radec
            selmask = np.ones(len(radec), dtype=bool)
        ntot = len(radec)
        radeg = radec.ra.degree
        decdeg = radec.dec.degree
        """ Select the high SNR objects, if requested """
        if snrmask is not None:
            selsnrmask = (selmask) & (snrmask)
            radecgood = self.radec[selsnrmask]
            ngood = len(radecgood)
            print('Of those, objects with SNR>%.1f: %d' % (snrgood, ngood))
            gradeg = radecgood.ra.degree
            gdecdeg = radecgood.dec.degree
        """ Write the output region file """
        f = open(outfile, 'w')
        f.write('global color=%s\n' % color)
        for i in range(ntot):
            f.write('fk5;circle(%10.6f,%+10.6f,%.1f")\n' %
                    (radeg[i], decdeg[i], rcirc))
        if plot_high_snr and ngood > 0:
            f.write('global color=red\n')
            for i in range(ngood):
                f.write('fk5;circle(%10.6f,%+10.6f,0.0011)\n' \
                           %(gradeg[i],gdecdeg[i]))
        """ Add labels if requested """
        if labcol is not None:
            lab = self.data[labcol][selmask]
            cosdec = np.cos(pi * self.dec[selmask] / 180.)
            xx = self.ra[selmask] + labdx * cosdec
            yy = self.dec[selmask] + labdy
            f.write('global color=%s\n' % color)
            for i in range(ntot):
                f.write('fk5;text(%10.6f,%+10.6f) # text={%s}\n'% \
                           (xx[i],yy[i],str(lab[i])))
        """ Wrap up """
        print("Wrote region file %s" % outfile)
        f.close()

    #-----------------------------------------------------------------------

    def _print_autoslit_infile(self,
                               filename,
                               galmask,
                               starmask,
                               maskcent,
                               magcol,
                               smagcol,
                               objroot=None,
                               add_lens=False,
                               ndigits=4):
        """

      This method is called by lrismask_prep.  It prints out a file that
      is used as input for the autoslit3 code.

      """
        """ Set up the object name column """
        ind = np.arange(len(self.data)) + 1
        objname = np.zeros(len(self.data), dtype='U16')
        if objroot is not None:
            for i, obj in enumerate(ind):
                objname[i] = '%s_%04d' % (objroot, obj)
        else:
            for i, obj in enumerate(ind):
                objname[i] = '%04d' % obj
        """ Set up the output table """
        outnames = [
            'name', 'priority', 'mag', 'rahr', 'ramin', 'rasec', 'decdeg',
            'decamin', 'decasec', 'epoch', 'equinox', 'pm_ra', 'pm_dec'
        ]
        tmpgal = self.data[galmask]
        radec = self.radec[galmask]
        pri = np.ones(len(tmpgal)) * 100
        tmpgal[magcol][tmpgal[magcol] < 0.] = 99.
        epoch = np.ones(len(tmpgal)) * 2000.
        pm = np.zeros(len(tmpgal))
        galtab = Table([
            objname[galmask], pri, tmpgal[magcol], radec.ra.hms.h,
            radec.ra.hms.m, radec.ra.hms.s, radec.dec.dms.d,
            np.fabs(radec.dec.dms.m),
            np.fabs(radec.dec.dms.s), epoch, epoch, pm, pm
        ],
                       names=outnames)
        """ Set up the guidestar table """
        tmpstar = self.data[starmask]
        radec = self.radec[starmask]
        pri = np.ones(len(tmpstar)) * -1
        epoch = np.ones(len(tmpstar)) * 2000.
        pm = np.zeros(len(tmpstar))
        starname = np.zeros(len(tmpstar), dtype='U16')
        starind = ind[starmask]
        for i, si in enumerate(starind):
            starname[i] = 'S%04d' % si
        startab = Table([
            starname, pri, tmpstar[smagcol], radec.ra.hms.h, radec.ra.hms.m,
            radec.ra.hms.s, radec.dec.dms.d,
            np.fabs(radec.dec.dms.m),
            np.fabs(radec.dec.dms.s), epoch, epoch, pm, pm
        ],
                        names=outnames)
        """
      Make a mini-table containing the mask center and, optionally, the lens.
      These one or two lines will be at the top of the output file
      """
        if add_lens:
            hdrrows = 2
        else:
            hdrrows = 1
        hdrtab = Table(np.zeros((hdrrows, (len(outnames) - 1))),
                       names=outnames[1:])
        hdrtab.add_column(galtab['name'][:hdrrows], index=0)
        ra = maskcent.ra
        dec = maskcent.dec
        hdrtab[0] = [
            'CENTER', 9999, 0., ra.hms.h, ra.hms.m, ra.hms.s, dec.dms.d,
            fabs(dec.dms.m),
            fabs(dec.dms.s), 2000., 2000., 0., 0.
        ]
        if add_lens:
            cra = self.centpos.ra.hms
            cdec = self.centpos.dec.dms
            hdrtab[1] = [
                'Lens', 900, 20., cra.h, cra.m, cra.s, cdec.d,
                fabs(cdec.m),
                fabs(cdec.s), 2000., 2000., 0., 0.
            ]
        """ Combine the two tables """
        outtab = vstack([hdrtab, galtab, startab])
        """ Set up the formatting """
        outtab['priority'].format = '%4d'
        outtab['mag'].format = '%5.2f'
        outtab['rahr'].format = '%02d'
        outtab['ramin'].format = '%02d'
        outtab['rasec'].format = '%06.3f'
        outtab['decdeg'].format = '%+03d'
        outtab['decamin'].format = '%02d'
        outtab['decasec'].format = '%05.2f'
        outtab['epoch'].format = '%6.1f'
        outtab['equinox'].format = '%6.1f'
        outtab['pm_ra'].format = '%3.1f'
        outtab['pm_dec'].format = '%3.1f'
        print('')
        print(outtab)
        """ Save the table to the output file """
        print('')
        print('Writing selected objects to %s' % filename)
        outtab.write(filename, format='ascii.no_header', overwrite=True)

    #-----------------------------------------------------------------------

    def lrismask_prep(self,
                      maskcent,
                      PA,
                      mask_w=3.,
                      mask_h=7.,
                      galmagcol='r',
                      galmagrange=None,
                      galmask='default',
                      starmask='default',
                      smagcol='g',
                      smaglim=[17., 19.],
                      galreg='maskobj.reg',
                      objcolor='green',
                      rcirc=1.,
                      starreg='maskstar.reg',
                      add_lens=True,
                      outfile=None,
                      objroot=None):
        """

      Code to select objects for a LRIS slitmask

      """
        """
      Make sure that the catalog has been sorted, since this code needs to
      use the self.dx and self.dy arrays
      """
        if self.dx is None:
            print('')
            print(
                'Position offsets are missing.  You must run sort_by_pos first'
            )
            print('')
            return
        """ Get the offset of the mask center from the origin of (dx,dy) """
        maskcoord = SkyCoord(maskcent[0], maskcent[1], unit=(u.deg, u.deg))
        maskxy = self.centpos.spherical_offsets_to(maskcoord)
        print('Requested mask center has (dx,dy) = (%+7.2f, %+7.2f)' %
              (maskxy[0].arcsec, maskxy[1].arcsec))
        """ 
      Translate and rotate the object (dx,dy) to a masked-centered frame in
      which the mask is rectilinear.  That is, first make the mask center
      the origin and then rotate by the NEGATIVE of the mask PA.
      """
        rot_ang = -1. * PA * pi / 180.
        xtmp = (self.dx - maskxy[0].arcsec)
        ytmp = (self.dy - maskxy[1].arcsec)
        xx = xtmp * np.cos(rot_ang) + ytmp * np.sin(rot_ang)
        yy = -xtmp * np.sin(rot_ang) + ytmp * np.cos(rot_ang)
        """ Select only the objects that lie within the mask """
        star_extra = 75.
        xbound = 0.5 * mask_w * 60.
        ybound = 0.5 * mask_h * 60.
        objmask = (xx >= -xbound) & (xx <= xbound) & (yy >= -ybound) \
           & (yy <= ybound)
        starsonmask = (xx >= -xbound-star_extra) & (xx <= xbound+star_extra) & \
           (yy >= -ybound) & (yy <= ybound)
        """ Choose the galaxies and stars that fall within the mask """
        if galmask == 'default':
            if self.galmask is not None:
                totgalmask = np.logical_and(self.galmask, objmask)
            else:
                totgalmask = objmask
        elif galmask is not None:
            totgalmask = np.logical_and(galmask, objmask)
        else:
            totgalmask = objmask

        if starmask == 'default':
            if self.starmask is not None:
                totstarmask = np.logical_and(self.starmask, starsonmask)
            else:
                totstarmask = starsonmask
        elif starmask is not None:
            totstarmask = np.logical_and(starmask, starsonmask)
        else:
            totstarmask = starsonmask
        stardata = self.data[smagcol].astype(float)
        guidestarmask = totstarmask & (stardata >= smaglim[0]) & \
           (stardata <= smaglim[1])
        """ Make ds9 region files for diagnostic checks """
        print('')
        print('Making ds9 region file for possible targets for slitmask')
        self.make_reg_file(galreg, rcirc, color=objcolor, mask=totgalmask)
        print('')
        print('Making ds9 region file for possible guide stars for slitmask')
        self.make_reg_file(starreg,
                           rcirc * 1.5,
                           color='red',
                           mask=guidestarmask)
        """ Write out the autoslit3 input file """
        if outfile is not None:
            self._print_autoslit_infile(outfile,
                                        totgalmask,
                                        guidestarmask,
                                        maskcoord,
                                        galmagcol,
                                        smagcol,
                                        objroot=objroot,
                                        add_lens=add_lens)

    #-----------------------------------------------------------------------

    #def plot_radec(self, symb='bo'):
    #-----------------------------------------------------------------------

    def plot_fwhm(self,
                  fwhmcol='FWHM_IMAGE',
                  magcol='MAG_AUTO',
                  xlim=(0, 15),
                  ylim=(28, 16)):
        """
      Plots FWHM vs. magnitude.  This can be used to find the stellar locus
      and, thus, determine the seeing.

      Inputs:
         fwhmcol - column name for the FWHM data.  Default = 'fwhm_image'
         magcol  - column name for the magnitude data.  Default = 'mag_auto'
         xlim    - initial limits for FWHM axis on plot.  Default = (0,15)
         ylim    - initial limits for mag axis on plot.  Default = (28,16)
      """

        try:
            fwhm = self.data[fwhmcol]
        except KeyError:
            print('')
            print('Catalog does not contain a %d column' % fwhmcol)
            print('')
            return
        try:
            mag = self.data[magcol]
        except KeyError:
            print('')
            print('Catalog does not contain a %d column' % magcol)
            print('')
            return
        plt.plot(fwhm, mag, 'bo')
        plt.xlim(xlim)
        plt.ylim(ylim)
        plt.xlabel('FWHM (pixels)')
        plt.ylabel('Magnitude')
        plt.show()

    #-----------------------------------------------------------------------

    def plot_nhist(self,
                   magcol='MAG_AUTO',
                   usestarmask=False,
                   magmin=15,
                   magmax=28,
                   color='b',
                   alpha=1.):
        """
      Plots a histogram of galaxy magnitudes (similar to a log N-log S plot)
      that can be used to determine the magnitude to which the catalog is 
      complete.  A minimum FWHM can be set in order to select objects that
      are likely to be galaxies, but this is not required.

      Inputs:
         magcol      - column containing the magnitudes. Default = 'mag_auto'
         usestarmask - when this parameter is set to True, then use the
                       starmask mask to select the galaxies.
                       NOTE: this means that the set_starmask method has to
                       have been run for each of the input catalogs, or
                       else all objects will be plotted
                       Default=False
         magmin      - minimum magnitude to use for the plot. Default=15
         magmax      - maximum magnitude to use for the plot. Default=28
      """
        """ Get the magnitudes to be plotted """
        if usestarmask:
            if self.starmask is None:
                print('')
                print('WARNING: you have set usestarmask=True but there are')
                print(' no stars selected by the starmask')
                print('Please make sure that set_starmask has been run BEFORE'
                      'runing plot_nhist')
                print(' if you want to use this mask')
                print('')
                return
            else:
                mag = (self.data[self.starmask == False][magcol]).copy()
        else:
            mag = self.data[magcol].copy()

        mag = mag[np.isfinite(mag)]
        """ Plot the histogram """
        nbins = int(2 * (magmax - magmin))
        plt.hist(mag,
                 range=(magmin, magmax),
                 bins=nbins,
                 color=color,
                 alpha=alpha)

        del (mag)

    #-----------------------------------------------------------------------

    def match_radec(self, ra2, dec2, rmatch, dra2=0., ddec2=0., doplot=True):
        """

      *** UNDER CONSTRUCTION!  DO NOT USE YET. ***

      Given a list of ra,dec coordinates (ra2, dec2), possibly from a second
      catalog, and a match tolerance, find the matches to the catalog
      contained in self.data

      Inputs:
        ra2      - RA (decimal degrees) for catalog 
        dec2     - Dec (decimal degrees) for second catalog
        rmatch   - max distance for a valid match (arcsec)
        dra2     - optional offset in ARCSEC to apply to ra2, if there is a known
                   offset between the catalogs (default=0.0)
        ddec2    - optional offset in ARCSEC to apply to dec2, if there is a
                   known offset between the catalogs (default=0.0)
      """

        print('')
        print("Matching catalogs: basic info")
        print("--------------------------------------------")
        print(" Catalog 1: %d coordinates" % self.ra.size)
        print(" Catalog 2: %d coordinates" % ra2.size)
        """ Initialize containers for output information """
        ramatch = np.zeros(self.ra.size)
        decmatch = np.zeros(self.ra.size)
        self.nmatch = np.zeros(self.ra.size, dtype=int)
        self.matchdx = np.zeros(self.ra.size)
        self.matchdy = np.zeros(self.ra.size)
        self.indmatch = np.ones(self.ra.size, dtype=int) * -1
        """ Correct for known shifts """
        ra2 = ra2.copy() + dra2 / (3600. * np.cos(dec2))
        dec2 = dec2.copy() + ddec2 / 3600.
        """ Loop over catalog """
        print('')
        print("Searching for matches...")
        print("------------------------------")
        for i in range(self.ra.size):
            dx, dy = coords.sky_to_darcsec(self.ra[i], self.dec[i], ra2, dec2)
            dpos = np.sqrt(dx**2 + dy**2)
            isort = np.argsort(dpos)
            if dpos[isort[0]] <= rmatch:
                ramatch[i] = self.ra[i]
                decmatch[i] = self.dec[i]
                self.matchdx[i] = dx[isort[0]]
                self.matchdy[i] = dy[isort[0]]
                self.nmatch[i] = dpos[dpos <= rmatch].size
                self.indmatch[i] = isort[0]
            del dx, dy, dpos
        print(" Number of matches between the catalogs:  %d" %
              (self.nmatch > 0).sum())
        mra = ramatch[self.nmatch > 0]
        mdec = decmatch[self.nmatch > 0]
        mdx = self.matchdx[self.nmatch > 0]
        mdy = self.matchdy[self.nmatch > 0]
        mdx0 = np.median(mdx)
        mdy0 = np.median(mdy)
        print(" Median offset for matches (RA):  %+6.2f arcsec" % mdx0)
        print(" Median offset for matches (Dec): %+6.2f arcsec" % mdy0)
        """ Plot up some offsets, if desired """
        if doplot:
            plt.figure(1)
            plt.scatter(mdx, mdy)
            plt.axis('scaled')
            plt.xlabel(r'$\Delta \alpha$ (arcsec)')
            plt.ylabel(r'$\Delta \delta$ (arcsec)')
            plt.title('Offsets between matched sources (rmatch = %5.2f)' %
                      rmatch)
            plt.axvline(0.0, color='r')
            plt.axhline(0.0, color='r')
            plt.plot(np.array([mdx0]), np.array([mdy0]), 'r*', ms=20)
            plt.xlim(-1.1 * rmatch, 1.1 * rmatch)
            plt.ylim(-1.1 * rmatch, 1.1 * rmatch)

            plt.figure(2)
            #
            ax1 = plt.subplot(221)
            plt.scatter(mra, mdy)
            plt.setp(ax1.get_xticklabels(), visible=False)
            plt.ylabel(r'$\Delta \delta$ (arcsec)')
            plt.axhline(0.0, color='r')
            #
            ax2 = plt.subplot(223, sharex=ax1)
            plt.scatter(mra, mdx)
            plt.xlabel(r'$\alpha$')
            plt.ylabel(r'$\Delta \alpha$ (arcsec)')
            plt.axhline(0.0, color='r')
            #
            ax3 = plt.subplot(222, sharey=ax1)
            plt.scatter(mdec, mdy)
            plt.axhline(0.0, color='r')
            plt.setp(ax3.get_xticklabels(), visible=False)
            plt.setp(ax3.get_yticklabels(), visible=False)
            #
            ax4 = plt.subplot(224)
            plt.scatter(mdec, mdx)
            plt.xlabel(r'$\delta$')
            plt.axhline(0.0, color='r')
            plt.setp(ax4.get_yticklabels(), visible=False)

            plt.show()
        """ Clean up """
        del ramatch, decmatch
        del mdx, mdy, mra, mdec

    #-----------------------------------------------------------------------

    def print_ccmap(self, outfile, verbose=True):
        """
      Prints out a file that can be used as the input for the pyraf ccmap
      task.  This file has 4 columns:  x  y  RA  Dec

      Inputs:
         outfile   -  output file to be used as input for ccmap
         verbose   -  print task info
      """
        if verbose:
            print('')
            print("Printing to file for use in ccmap:  %s" % outfile)
            print('')
        f = open(outfile, 'w')
        f.write('# (x,y) catalog: %s\n' % self.infile)
        f.write('# Astrometric catalog: %s\n' % self.matchcat)
        f.write('# Columns are x y RA Dec\n')
        for i in range(self.nmatch):
            f.write('%8.2f %8.2f  %11.7f %+11.7f\n' % \
                       (self.matchx[i],self.matchy[i],self.matchra[i],
                        self.matchdec[i]))
        f.close()

    #-----------------------------------------------------------------------

    def find_closest_xy(self, xast, yast, xcol, ycol):
        """
      Finds the closest match, in (x,y) space to each member of the astrometric
      catalog (represented by xast,yast).
      """

        self.matchind = np.zeros(xast.size, dtype=int)

        xfield = 'f%d' % xcol
        yfield = 'f%d' % ycol

        for i in range(xast.size):
            dx = xast[i] - self.data[xfield]
            dy = yast[i] - self.data[yfield]
            dpos = dx**2 + dy**2
            sindex = np.argsort(dpos)
            self.matchind[i] = sindex[0]

        self.matchdx = xast - self.data[xfield][self.matchind]
        self.matchdy = yast - self.data[yfield][self.matchind]

    #-----------------------------------------------------------------------

    def match_xy(self, xa, ya, max_offset=None, xcol=8, ycol=9, verbose=True):
        """
      Find the closest match to each astrometric catalog object and calculate the
      offsets.
      Do two loops, to deal with possible confusion of sources on first pass
      through
      """
        dxmed = 0
        dymed = 0
        for i in range(2):
            if verbose:
                print('')
                print('Pass %d' % (i + 1))
                print('------------------------')
            xa0 = xa - dxmed
            ya0 = ya - dymed
            self.find_closest_xy(xa0, ya0, xcol, ycol)
            dxmed = np.median(self.matchdx)
            dymed = np.median(self.matchdy)
            if max_offset is not None:
                dpos = np.sqrt(self.matchdx**2 + self.matchdy**2)
                goodmask = dpos < max_offset
                if verbose:
                    print("Applying a maximum offset cut of %7.1f pixels" %
                          max_offset)
                    print("Median shifts before clipping: %7.2f %7.2f" %
                          (dxmed, dymed))
            else:
                goodmask = np.ones(xa.size, dtype=bool)
            dxm = self.matchdx[goodmask]
            dym = self.matchdy[goodmask]
            dxmed = np.median(dxm)
            dymed = np.median(dym)
            if verbose:
                print("Median shifts after pass:   %7.2f %7.2f" %
                      (dxmed, dymed))
        """
      Transfer information into object and clean up
      """
        if verbose:
            print('')
            print('Found %d astrometric objects within FOV of image' % xa.size)
            print('Matched %d objects to astrometric catalog.' % dxm.size)
        self.nmatch = dxm.size
        self.goodmask = goodmask.copy()
        self.matchind = self.matchind[goodmask]
        del xa0, ya0, goodmask

    #-----------------------------------------------------------------------

    def match_fits_to_ast(self,
                          fitsfile,
                          astcat,
                          outfile=None,
                          max_offset=None,
                          racol=1,
                          deccol=2,
                          xcol=8,
                          ycol=9,
                          doplot=True,
                          edgedist=50.,
                          imhdu=0,
                          verbose=True):
        """
      Given the fits file from which this object (self) was defined 
      and an astrometric catalog, find the closest matches of the 
      astrometric objects to those contained in this object, using the WCS 
      information in the fits header.
      """

        if (verbose):
            print("Running match_fits_to_ast with:")
            print("   fitsfile = %s" % fitsfile)
            print("   astcat   = %s" % astcat)
        self.infits = fitsfile
        self.matchcat = astcat
        """
      Start by opening the fits file and reading the appropriate columns from
      the catalogs
      """
        hdulist = imf.open_fits(fitsfile)
        hdr = hdulist[imhdu].header
        if verbose:
            print('')
            hdulist.info()
        """
      Select the astrometric catalog objects that fall within the fits file FOV
      (at least with its current WCS)
      """
        # raa,deca,xa,ya,astmask = select_good_ast(astcat,hdr,racol,deccol,edgedist)
        if verbose:
            print('Found %d astrometric objects within FOV of image' %
                  raa.size)
        """
      Find the closest match to each astrometric catalog object
      """
        self.match_xy(xa, ya, max_offset, xcol, ycol, verbose)
        """ Transfer info about matches into the object """
        xfield = 'f%d' % xcol
        yfield = 'f%d' % ycol
        self.astmask = astmask.copy()
        self.matchx = self.data[xfield][self.matchind].copy()
        self.matchy = self.data[yfield][self.matchind].copy()
        self.matchra = raa[self.goodmask].copy()
        self.matchdec = deca[self.goodmask].copy()
        self.matchdx = self.matchdx[self.goodmask]
        self.matchdy = self.matchdy[self.goodmask]
        """ Plot the offsets if desired """
        if doplot:
            dxmed = np.median(self.matchdx)
            dymed = np.median(self.matchdx)
            plt.figure()
            plt.scatter(self.matchdx, self.matchdy)
            plt.xlabel('x offset (pix)')
            plt.ylabel('y offset (pix)')
            plt.axhline(color='k')
            plt.axvline(color='k')
            plt.axvline(dxmed, color='r')
            plt.axhline(dymed, color='r')
            print('')
            print("Black lines represent x=0 and y=0 axes")
            print("Red lines show median offsets of dx_med=%7.2f and "
                  "dy_med=%7.2f" % (dxmed, dymed))
            #plt.show()
        """ Write the output file, in a format appropriate for input to ccmap """
        if outfile is not None:
            self.print_ccmap(outfile, verbose)
        """ Clean up """
        hdulist.close()
        del hdr, raa, deca, xa, ya, astmask

    # -----------------------------------------------------------------------

    def set_starmask(self, mask):
        """
      Takes the input mask and assigns it to an internal mask associated
      with this instance of the ObjCat class.
      The internal mask is called starmask and has values of True for objects
      that have been identified as stars by the provided external mask.

      The external mask will be based on some characteristics in the catalog.
      Examples could be objects with a SExtractor CLASS_STAR value greater
       than 0.7, or a FWHM_IMAGE less than a certain value, or ...
      """

        self.starmask = mask

    # -----------------------------------------------------------------------

    def set_galmask(self, mask):
        self.galmask = mask
示例#11
0
def proc_sa104(file_path=None,outdir=None, bias_fil=None):

    from astropy.coordinates import ICRS 
    from astropy.io import ascii
    from astropy import units as u
    from astropy.io.fits import getdata
    import xastropy.PH136.experiments.hrdiagram as hrd

    # Defaults
    if file_path == None: 
        file_path = 'Raw/'
    if outdir == None: 
        outdir = 'Std/'

    # Bias frame
    if bias_fil == None:
        bias_fil = 'Bias.fits'
    bias_img,bias_head = getdata(bias_fil,0,header=True)
    

    # Read Log
    data = ascii.read('simple.log',delimiter='|')
    nfil = len(data)
    all_coord = ICRS(ra=data['RA'], dec=data['DEC'], unit=(u.hour,u.degree))

    # M67 coords
    sa104_rac = '12:43:44.3'
    sa104_decc = '-00:29:40.0'
    sa104_c = ICRS(sa104_rac, sa104_decc, unit=(u.hour,u.degree))

    # Find all SA 104
    sep = (sa104_c.separation(all_coord)).degree
    isa104, = np.where( sep < 1. ) # 1 degree
    sa104 = data[isa104]

    # Filters
    all_filt=np.array(sa104['Filter'])
    filters,ifilt = np.unique(all_filt,return_index=True)

    # Loop on Filterse
    all_fil = []
    for ff in filters:

        # Load Sky frame
        skyfil = 'Sky_'+ff+'.fits'
        sky_img,head = getdata(skyfil,0,header=True)

        # Images
        idx = np.where(sa104['Filter'] == ff) 

        # Loop on images
        for kk in np.concatenate(idx,axis=0):
            # Read
            img,head = getdata(sa104[kk]['File'],0,header=True)

            # Bias subtract
            img = img - bias_img

            # Trim
            timg = hrd.trimflip_img(img)

            # Flat field
            timg = timg / sky_img

            # Normalize by exposure
            timg = timg / sa104[kk]['Exp']

            # Filename
            outfil = outdir+'SA104_t'+str(int(sa104[kk]['Exp']))+'_'+ff+'.fits'

            # Check for duplicate
            flg_skip = 0
            mt = [i for i in range(len(all_fil)) if all_fil[i] == outfil] 
            if len(mt) > 0:
                print 'Duplicate image', outfil
                print 'Skipping...'
                continue
            all_fil.append(outfil)
            

            # Write
            print 'Writing ', outfil
            fits.writeto(outfil, timg, head, clobber=True)
            
    return
示例#12
0
def proc_m67(file_path=None,outdir=None, bias_fil=None):

    from astropy.coordinates import ICRS 
    from astropy.io import ascii
    from astropy import units as u
    from astropy.io.fits import getdata
    import xastropy.PH136.experiments.hrdiagram as hrd

    # Defaults
    if file_path == None: 
        file_path = 'Raw/'
    if outdir == None: 
        outdir = 'Science/'

    # Bias frame
    if bias_fil == None:
        bias_fil = 'Bias.fits'
    bias_img,bias_head = getdata(bias_fil,0,header=True)
    

    # Read Log
    data = ascii.read('simple.log',delimiter='|')
    nfil = len(data)
    all_coord = ICRS(ra=data['RA'], dec=data['DEC'], unit=(u.hour,u.degree))

    # M67 coords
    m67_rac = '08:54:24'
    m67_decc = '+11:49:00'
    m67_c = ICRS(m67_rac, m67_decc, unit=(u.hour,u.degree))

    # Find all M67
    sep = (m67_c.separation(all_coord)).degree
    im67, = np.where( sep < 1. ) # 1 degree
    m67 = data[im67]

    # 5 positions
    m67_ra = ['08:52:02.2', '08:52:15.3', '08:51:49.9', '08:51:50.0', '08:52:16.2']
    m67_dec = ['+11:52:41.0', '+11:55:51.0', '+11:55:53.0', '+11:49:38.0', '+11:49:40.0']
    m67_pointings = ICRS(ra=m67_ra, dec=m67_dec, unit=(u.hour, u.degree))

    # Filters
    all_filt=np.array(m67['Filter'])
    filters,ifilt = np.unique(all_filt,return_index=True)

    # Loop on Filterse
    all_fil = []
    for ff in filters:

        # Load Sky frame
        skyfil = 'Sky_'+ff+'.fits'
        sky_img,head = getdata(skyfil,0,header=True)

        # Images
        idx = np.where(m67['Filter'] == ff) 

        # Loop on images
        for kk in np.concatenate(idx,axis=0):
            # Read
            img,head = getdata(m67[kk]['File'],0,header=True)

            # Bias subtract
            img = img - bias_img

            # Trim
            timg = hrd.trimflip_img(img)

            # Flat field
            timg = timg / sky_img

            # Normalize by exposure
            timg = timg / m67[kk]['Exp']

            # Filename
            coord = ICRS(head['RA'], head['DEC'], unit=(u.hour,u.degree))
            sep = (coord.separation(m67_pointings)).degree
            ipos = np.argmin(sep)
            outfil = outdir+'M67_C'+str(ipos)+'_t'+str(int(m67[kk]['Exp']))+'_'+ff+'.fits'

            # Check for duplicate
            flg_skip = 0
            mt = [i for i in range(len(all_fil)) if all_fil[i] == outfil] 
            if len(mt) > 0:
                print 'Duplicate image', outfil
                print 'Skipping...'
                continue
            all_fil.append(outfil)
            

            # Write
            print 'Writing ', outfil
            fits.writeto(outfil, timg, clobber=True)
            
    return
示例#13
0
def PulsarVis(sourcename, times):

    if sourcename in {'PSRJ0030+0451', 'PSRJ0437-4715'}:
        SunAvoidance = 55.0 * u.deg
    else:
        SunAvoidance = 45.0 * u.deg
    print("Sun Avoidance: {0:.3f}".format(SunAvoidance))
    MoonAvoidance = 15.0 * u.deg
    # Each pulsar's feasible observation range based on ISS hardware data
    if sourcename in 'PSRB1821-24':  #Analysis ticket 890
        HardwareUpperAvoidance = 120 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 88 * u.deg  #0*u.deg
    elif sourcename in 'PSRB1937+21':
        HardwareUpperAvoidance = 142.0 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 91.0 * u.deg  #0*u.deg
    elif sourcename in 'PSRJ0218+4232':
        HardwareUpperAvoidance = 156.0 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 88.0 * u.deg  #0*u.deg
    elif sourcename in 'PSRJ0030+0451':
        HardwareUpperAvoidance = 148.0 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 95.0 * u.deg  #0*u.deg
    elif sourcename in 'PSRJ0437-4715':
        HardwareUpperAvoidance = 95.0 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 35.0 * u.deg  #0*u.deg
    else:
        HardwareUpperAvoidance = 360.0 * u.deg  #360*u.deg
        HardwareLowerAvoidance = 0.0 * u.deg  #0*u.deg

    print("ISS Upper:", HardwareUpperAvoidance, "Lower:",
          HardwareLowerAvoidance, "\n".format(HardwareLowerAvoidance,
                                              HardwareUpperAvoidance))

    tle160lines = [
        '1 25544U 98067A   17160.91338884 +.00001442 +00000-0 +29152-4 0  9993',
        '2 25544 051.6425 074.5823 0004493 253.3640 193.9362 15.54003243060621'
    ]

    tle167lines = [
        '1 25544U 98067A   17167.53403196 +.00002711 +00000-0 +48329-4 0  9994',
        '2 25544 051.6431 041.5846 0004445 283.0899 147.8207 15.54043876061656'
    ]

    platform = 'ISS (ZARYA)'

    # Set up two TLEs so we can compute the precession rate from the
    # change of RA of ascending node with time
    tle1 = tlefile.read(platform, line1=tle160lines[0], line2=tle160lines[1])
    tle2 = tlefile.read(platform, line1=tle167lines[0], line2=tle167lines[1])

    #    print(platform)
    ISSInclination = tle2.inclination * u.deg
    #    print("Inclination = {0:.3f}".format(ISSInclination))

    StarboardPoleDec0 = -1 * (90.0 * u.deg - ISSInclination)
    PortPoleDec0 = -1 * StarboardPoleDec0

    #print("Starboard Orbit Pole Declination {0:.2f}".format(StarboardPoleDec0))
    #    print("Port Orbit Pole Declination {0:.2f}".format(PortPoleDec0))

    # Compute ISS precession rate in degrees per day
    ISSPrecessionRate = (tle2.right_ascension - tle1.right_ascension) / (
        tle2.epoch_day - tle1.epoch_day) * u.deg / u.d
    #    print("ISS Precession Rate {0:.3f} ({1:.3f} period)".format(ISSPrecessionRate,
    #                                                               np.abs(360.0*u.deg/ISSPrecessionRate)))

    ttle2 = Time("{0:4d}-01-01T00:00:00".format(int(tle2.epoch_year) + 2000),
                 format='isot',
                 scale='utc') + tle2.epoch_day * u.d
    #    print("ttle2 = ",ttle2.isot)
    StarboardPoleRA0 = np.fmod(tle2.right_ascension + 90.0, 360.0) * u.deg
    PortPoleRA0 = np.fmod(StarboardPoleRA0 + 180.0 * u.deg, 360.0 * u.deg)

    #   print("Starboard Pole RA @ ttle2 = {0:.3f}".format(StarboardPoleRA0))
    #   print("Port Pole RA @ ttle2 = {0:.3f}".format(PortPoleRA0))

    def StarboardPoleDec(t):
        return np.ones_like(t) * StarboardPoleDec0

    def PortPoleDec(t):
        return np.ones_like(t) * StarboardPoleDec0

    def StarboardPoleRA(t):
        return np.fmod(
            StarboardPoleRA0 + (t - ttle2).to(u.d) * ISSPrecessionRate,
            360.0 * u.deg)

    def PortPoleRA(t):
        return np.fmod(StarboardPoleRA(t) + 180.0 * u.deg, 360.0 * u.deg)

    def StarboardPoleCoord(t):
        return SkyCoord(StarboardPoleRA(t).value,
                        StarboardPoleDec(t).value,
                        unit=u.deg,
                        frame="icrs")

    def PortPoleCoord(t):
        return SkyCoord(PortPoleRA(t).value,
                        PortPoleDec(t).value,
                        unit=u.deg,
                        frame="icrs")

    now = Time.now()
    doy_now = np.float(now.yday.split(':')[1])
    #   print("Current DOY = {0}".format(np.int(doy_now)))
    #print("StarboardPoleRA (now) = {0:.3f}".format(StarboardPoleRA(now)))
    #print("PortPoleRA (now) = {0:.3f}".format(PortPoleRA(now)))

    if sourcename[0:2] != 'PSR':
        SourcePos = get_icrs_coordinates(sourcename)
    else:
        splitstr = sourcename.split(',')
        SourcePos = ICRS(ra=Angle(double(splitstr[0])),
                         dec=Angle(double(splitstr[1])))
    #print("\nSource: {0} at {1}, {2}".format(sourcename,SourcePos.ra, SourcePos.dec))
    #print("Separation from Starboard Pole = {0:.3f}".format(SourcePos.separation(StarboardPoleCoord(now))))
    #print("Separation from Port Pole = {0:.3f}".format(SourcePos.separation(PortPoleCoord(now))))

    #Calculate terms and references to do check
    #doy2XXX = np.arange(365.0)
    #times = doy2XXX*u.d + startepoch

    issseps = SourcePos.separation(StarboardPoleCoord(times)).to(u.deg)

    # The Sun and Moon positions are returned in the GCRS frame
    # Convert them to ICRS so .separation doesn't go insane when
    # comparing different frames with different obstimes.
    SunPos = get_sun(times)
    SunPos = SkyCoord(SunPos.ra, SunPos.dec, frame='icrs')
    MoonPos = get_moon(times)
    MoonPos = SkyCoord(MoonPos.ra, MoonPos.dec, frame='icrs')
    # Hold indicies when Sun and Moon cause constraint violation
    sunseps = SourcePos.separation(SunPos).to(u.deg)
    idxsun = sunseps < SunAvoidance
    moonseps = SourcePos.separation(MoonPos).to(u.deg)
    idxmoon = moonseps < MoonAvoidance
    # Hold indicies when sep is outside of 91 to 142 deg due to hardware violation (KWood analysis 10/27/2017)
    idxang = ~((issseps > HardwareLowerAvoidance) &
               (issseps < HardwareUpperAvoidance))
    # Apply all vis constraints
    indxall = idxsun | idxmoon | idxang  #true when constraint is violated
    # Generate and populate signal output
    vis = np.ones(len(doy2XXX))
    vis[indxall] = float('NaN')

    #Return result
    return vis
示例#14
0
class Secat:

   """

   The __init__ method has been changed to return something like a record
   array, which has the same number of rows as the old 2D float array, but
   which stores each row as a single tuple.  It is thus a 1D array, sort of
   like a structure array in C.  The columns can be accessed by field name,
   which for now is just 'f0', 'f1', etc., unless the input catalog is in
   SExtractor's FITS LDAC format, in which case the field names actually
   correspond to the SExtractor variable names.

   The code used to expect the old 2D float array format.  It should have
   all been updated, but there may still be some issues.

   """

   def __init__(self, incat, catformat='ldac', verbose=True, namecol=None,
                racol=None, deccol=None, rafield=None, decfield=None,
                usecols=False):
      """
      This method gets called when the user types something like
         secat = Secat(infile)

      Inputs:
         incat     - input table data.  This can be in one of two forms:
                       1. a file containing the catalog (most common)
                       2. a Table instance containing the catalog data
         catformat - format of the input file, if incat is a filename.  
                     The options are:
                      ascii    - 
                      asciitab -
                      ldac     - 
                      sdssfits - 
                      secat    -
                     NOTE: this parameter is not used if incat is a Table
                      rather than the name of an input file
      """

      """ Set a flag showing whether the file has been modified """
      self.modified = False

      """ Set other default values """
      self.radec = None
      self.rafield = None
      self.decfield = None
      self.centpos = None
      self.galmask = None
      self.starmask = None

      """
      Start by loading the catalog information
      """
      incattype = (str(type(incat))).split('.')[-1]
      if incattype[0:3] == 'Tab' or incattype[0:4] == 'FITS':
         self.data = incat.copy()
         if rafield:
            self.rafield = rafield
         if decfield:
            self.decfield = decfield
         self.nrows = len(incat)
         self.ncols = len(incat.columns)
         self.catformat = 'Table'

      elif isinstance(incat, str):
         self.load_from_file(incat, catformat=catformat, verbose=verbose,
                             namecol=namecol, racol=racol, deccol=deccol,
                             rafield=rafield, decfield=decfield,
                             usecols=usecols)
      else:
         print('')
         print('ERROR: input catalog must either be a filename or a Table')
         print(' Input catalog type is' + str(type(incat)))
         print('')
         return None

   #-----------------------------------------------------------------------

   def load_from_file(self, incat, catformat='ldac', verbose=True, namecol=None,
                      racol=None, deccol=None, rafield=None, decfield=None,
                      usecols=False):

      if verbose:
         print ""
         print "Loading data from catalog file %s" % incat
         print "-----------------------------------------------"
         print "Expected catalog format: %s" % catformat
         print ""

      """
      Define a flag for successful reading of input catalog
      """
      read_success = True

      """ Read in catalog in a manner appropriate to the catformat """
      if catformat == 'secat':
         try:
            self.data = ascii.read(incat)
            ncols = len(self.data.colnames)
            nrows = len(self.data)
            """ Set the field names """
            self.rafield  = 'ALPHA_J2000'
            self.decfield = 'DELTA_J2000'
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print ""
            print "  This also may have failed if the input file is in the"
            print "   SExtractor FITS LDAC format.  Checking that..."
            print ""
            read_success = False

      elif catformat == 'asciitab':
         f = open(incat)
         foo = f.readline()
         f.close()
         if foo[0] == '#':
            try:
               self.data = ascii.read(incat, guess=False,
                                      format='commented_header')
            except:
               print('')
               print('ERROR: Could not read data from %s' % incat)
               print(' Tried using "commented_header" format but failed') 
               print(' Please check input file.')
               print('')
               raise IOError
         else:
            try:
               self.data = ascii.read(incat)
            except:
               print ''
               print 'ERROR: Could not properly read data from %s' % incat
               print 'Tried using the automatic formatting but failed'
               print ' Please check input file.'
               print ''
               raise IOError
         ncols = len(self.data.colnames)
         nrows = len(self.data)
         """ Set the field names """
         if rafield:
            self.rafield = rafield
         if decfield:
            self.decfield = decfield

      elif catformat=='ascii':
         """ ASCII format """
         try:
            """ Set up the data format in the catalog """
            foo = np.loadtxt(incat,dtype='S30')
            ncols = foo.shape[1]
            del foo
            coltypes = np.ones(ncols,dtype='S3')
            coltypes[:] = 'f8'
            if namecol is not None:
               print "Object name column: %d" % namecol
               coltypes[namecol] = 'S30'
            colstr = ''
            for i in range(ncols):
               colstr = '%s,%s' % (colstr,coltypes[i])
            colstr = colstr[1:]
            dt = np.dtype(colstr)

            """ Actually read in the data """
            self.informat = 'ascii'
            self.data = np.loadtxt(incat,dtype=dt)
            nrows = self.data.shape[0]

            """ Set the field names """
            if racol is not None:
               self.rafield = 'f%d' % racol
            else:
               self.rafield = None
            if deccol is not None:
               self.decfield = 'f%d' % deccol
            else:
               self.decfield = None
            if namecol is not None:
               self.namefield = 'f%d' % namecol
            else:
               self.namefield = None

         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            print "  This may have failed if there is a string column in"
            print "   the input catalog (e.g., for an object name).  "
            print "  If this is the case, use the namecol to indicate which "
            print "   column contains the string values (column numbers are "
            print "   zero-indexed)"
            print ""
            print "  This also may have failed if the input file is in the"
            print "   SExtractor FITS LDAC format.  Checking that..."
            print ""
            read_success = False

      elif catformat.lower()=='ldac' or read_success==False:
         try:
            self.data = Table.read(incat, format='fits', hdu=2)
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            return
         self.informat = 'ldac'
         nrows = len(self.data)
         ncols = len(self.data.columns)

         """ Set the field names """
         self.rafield = 'ALPHA_J2000'
         self.decfield = 'DELTA_J2000'

      elif catformat.lower()=='sdssfits' or read_success==False:
         try:
            self.data = Table.read(incat, format='fits', hdu=1)
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            return
         self.informat = 'sdss'
         nrows = len(self.data)
         ncols = len(self.data.columns)

         """ Set the field names """
         self.rafield = 'ra'
         self.decfield = 'dec'

         """
         Split the stars from the galaxies, according to the SDSS 
         classification.
         In the SDSS scheme, type=3 is a galaxy and type=6 is a star
         """
         if 'type' in self.data.colnames:
            oclass = self.data['type']
         elif 'type_r' in self.data.colnames:
            oclass = self.data['type_r']
         else:
            oclass = None
   
         if oclass is not None:
            self.galmask = oclass == 3
            self.starmask = oclass == 6
         else:
            self.galmask = np.ones(dtype=bool)
            self.starmask = None
         print('Read SDSS catalog from %s' % incat)
         print('Number of galaxies: %5d' % self.galmask.sum())
         if self.starmask is not None:
            print('Number of stars:    %5d' % self.starmask.sum())

      else:
         print ''
         print 'Unrecognized format.  Must be one of:'
         print '  ascii, secat, ldac, sdssfits'
         sys.exit()

      if verbose:
         print "Number of rows:    %d" % nrows
         print "Number of columns: %d" % ncols
         if self.rafield is not None:
            print 'RA field name:  %s' % self.rafield
         if self.decfield is not None:
            print 'Dec field name: %s' % self.decfield

      self.infile = incat
      self.catformat = catformat
      self.nrows = nrows
      self.ncols = ncols
      
   #-----------------------------------------------------------------------

   def close_ldac(self):
      """
      Closes the catalog.  If the catalog is in fits format and it has
      been modified (as shown by the modified parameter in this Secat class)
      then use flush rather than close.
      """

      """ Close the file if it is in the expected format """
      if self.informat == 'ldac':
         if self.modified:
            self.hdu.flush()
            print 'Updating input fits LDAC file: %s' % self.infile
         else:
            self.hdu.close()
      else:
         print ''
         print 'WARNING. Calling close_ldac but file is not in ldac format'
         print ''

   #----------------------------------------------------------------------

   def make_magmask(self, magname, mfaint=None, mbright=None):
      """
      Makes a mask that is True for magnitudes brighter than mfaint and
       fainter than mbright.
      Note that one of these two could have the value None, in which case
       it would be ignored.  For example, if mbright is None, then the mask
       will be True for all galaxies brighter than mfaint

      Inputs:
       magname - the name in the catalog for the column that represents the
                  object magnitudes.  This could be something like, e.g., 'r' 
                  or 'MAG_AUTO'
      """

      mag = self.data[magname]
      if mfaint is None and mbright is None:
         self.magmask = np.ones(self.nrows,dtype=bool)
      elif mfaint is None:
         self.magmask = mag >= mbright
      elif mbright is None:
         self.magmask = mag <= mfaint
      else:
         self.magmask = (mag >= mbright) & (mag <= mfaint)

   #-----------------------------------------------------------------------

   def get_radec(self):
      """
      Extracts the RA and Dec information from the data container.  This
      is not necessary, and some of the data containers may not even have
      WCS info, but extracting the coordinates if it does simplifies some
      later tasks.
      """

      """ Extract the information into the new containers """
      self.ra = None
      self.dec = None
      if self.rafield is not None:
         try:
            self.ra  = self.data[self.rafield].copy()
         except:
            try:
               self.ra = self.data['x_world'].copy()
            except:
               self.ra = None
      if self.decfield is not None:
         try:
            self.dec = self.data[self.decfield].copy()
         except:
            try:
               self.dec = self.data['y_world'].copy()
            except:
               self.dec = None

      """ 
      Put data into a SkyCoords container for easy coordinate-based calculations
      """
      if (self.ra is not None) and (self.dec is not None):
         """ 
         Determine whether the RA coordinate is in hours or in degrees
         For now this test is made simple: if the format of the RA data is
          a string, then the data is expected to be in hms format, otherwise
          expect decimal degrees.
         """
         if type(self.ra[0]) is str or type(self.ra[0]) is np.string_:
            raunit = u.hourangle
         else:
            raunit = u.deg
         self.radec = SkyCoord(self.ra,self.dec,unit=(raunit,u.deg))

      """ 
      If radec has not been set, report this information
      (consider raising an exception in future versions of the code)
      """
      if self.radec is None:
         print ''
         print 'WARNING: get_radec was called but RA and Dec information was'
         print '         not found.  Please check the format of your catalog.'
         print ''

   #----------------------------------------------------------------------

   def read_centpos(self, posfile, verbose=False):
      """
      Reads a position in from a file and converts it to an astropy SkyCoord
      format.

      NOTE: right now this is hard-wired to just read in a file in the 
      standard Keck starlist format:

          label rahr ramin rasec decdeg decamin decasec equinox

      which matches the *.pos in CDF's Lenses/Data/* directories

      Inputs:
       posfile - file containing the RA and dec
      """

      """ Read the data from the file """
      posinfo = ascii.read(posfile, 
                           names=['object', 'rahr', 'ramin', 'rasec',
                                  'decdeg', 'decamin', 'decasec', 'equinox'])

      """ Convert to SkyCoord format """
      i = posinfo[0]
      ra  = '%d:%d:%f' % (i['rahr'], i['ramin'], i['rasec'])
      dec = '%d:%d:%f' % (i['decdeg'], i['decamin'], i['decasec'])
      radec = SkyCoord(ra, dec, unit=(u.hourangle, u.deg))

      """ Print out information if requested """
      if verbose:
         print('')
         print('Object: %s' % i['object'])
         print('Coordinates: %s %s' % \
                  (radec.ra.to_string(unit=u.hourangle, decimal=False,
                                      sep=':', precision=3, pad=True),
                   radec.dec.to_string(decimal=False, sep=':', precision=3,
                                       alwayssign=True, pad=True)))

      """ Save the output within the class """
      self.centpos = radec

   #----------------------------------------------------------------------

   def sort_by_pos(self, centpos):
      """
      Sorts the catalog in terms of distance from some central position, which
      is passed as a SkyCoord variable (from astropy.coordinates)
      """

      """ First check to see that we actual have WCS information  """
      if self.radec is None:
         print ''
         print 'ERROR: sort_by_pos.  No WCS information in catalog'
         print ''
         return

      """ Otherwise, use the SkyCoords functionality to easily sort """
      sep   = self.radec.separation(centpos)
      try:
         offsets = self.radec.spherical_offsets_to(centpos)
      except:
         offsets = None
      ind   = np.argsort(sep.arcsec)
      if self.catformat == 'ascii':
         self.data = self.data[ind,:]
      else:
         print self.catformat
         self.data = self.data[ind]

      """ Also sort things that are outside the data table """
      self.radec   = self.radec[ind]
      self.ra      = self.ra[ind]
      self.dec     = self.ra[ind]
      self.sep     = sep[ind]
      if offsets is None:
         self.dx = None
         self.dy = None
      else:
         self.dx = (offsets[0].arcsecond)[ind]
         self.dy = (offsets[1].arcsecond)[ind]
      self.sortind = ind


   #-----------------------------------------------------------------------

   def make_reg_file(self, outfile, rcirc, color='green', fluxcol=None, 
                     fluxerrcol=None, labcol=None, labdx=0.0012, labdy=0.0012,
                     plot_high_snr=False, mask=None, snrgood=10.):
      """
      Uses the RA and Dec info in the catalog to make a region file that
      can be used with ds9.
      """

      """ 
      Start by putting the RA and Dec info into a somewhat more convenient
      format
      """

      self.get_radec()
      if self.radec is None:
         print ""
         print "ERROR: Could not read RA and Dec information from input file"
         return

      """ 
      If the flux information is given, then report on high SNR detections
      """

      ngood = 0
      snrmask = None
      if fluxcol is not None and fluxerrcol is not None:
         if self.informat == 'ldac':
            if type(fluxcol) is int:
               flux = self.data.field(fluxcol)
               fluxerr = self.data.field(fluxerrcol)
            else:
               flux = self.data[fluxcol]
               fluxerr = self.data[fluxerrcol]
         else:
            flux = self.data['f%d' %fluxcol]
            fluxerr = self.data['f%d' % fluxerrcol]
         snr = flux / fluxerr
         snrmask = snr>snrgood

      """ Mask the input data if requested """
      print('Total objects in catalog:        %d' % len(self.radec))
      if mask is not None:
         radec  = self.radec[mask]
         selmask = mask
         print('Objects selected by mask:        %d' % len(radec))
      else:
         radec = self.radec
         selmask = np.ones(len(radec), dtype=bool)
      ntot   = len(radec)
      radeg  = radec.ra.degree
      decdeg = radec.dec.degree

      """ Select the high SNR objects, if requested """
      if snrmask is not None:
         selsnrmask = (selmask) & (snrmask)
         radecgood = self.radec[selsnrmask]
         ngood = len(radecgood)
         print 'Of those, objects with SNR>%.1f: %d' % (snrgood,ngood)
         gradeg  = radecgood.ra.degree
         gdecdeg = radecgood.dec.degree
         
      """ Write the output region file """
      f = open(outfile,'w')
      f.write('global color=%s\n' % color)
      for i in range(ntot):
         f.write('fk5;circle(%10.6f,%+10.6f,%.1f")\n' % 
                 (radeg[i],decdeg[i],rcirc))
      if plot_high_snr and ngood>0:
         f.write('global color=red\n')
         for i in range(ngood):
            f.write('fk5;circle(%10.6f,%+10.6f,0.0011)\n' \
                       %(gradeg[i],gdecdeg[i]))

      """ Add labels if requested """
      if labcol is not None:
         lab = self.data[labcol][selmask]
         cosdec = np.cos(pi * self.dec[selmask] / 180.)
         xx = self.ra[selmask] + labdx * cosdec
         yy = self.dec[selmask] + labdy
         f.write('global color=%s\n' % color)
         for i in range(ntot):
            f.write('fk5;text(%10.6f,%+10.6f) # text={%s}\n'% \
                       (xx[i],yy[i],str(lab[i])))

      """ Wrap up """
      print "Wrote region file %s" % outfile
      f.close()


   #-----------------------------------------------------------------------

   #def plot_radec(self, symb='bo'):
   #-----------------------------------------------------------------------

   def plot_fwhm(self, fwhmcol='FWHM_IMAGE', magcol='MAG_AUTO', 
                 xlim=(0,15), ylim=(28,16)):
      """
      Plots FWHM vs. magnitude.  This can be used to find the stellar locus
      and, thus, determine the seeing.

      Inputs:
         fwhmcol - column name for the FWHM data.  Default = 'fwhm_image'
         magcol  - column name for the magnitude data.  Default = 'mag_auto'
         xlim    - initial limits for FWHM axis on plot.  Default = (0,15)
         ylim    - initial limits for mag axis on plot.  Default = (28,16)
      """

      try:
         fwhm = self.data[fwhmcol]
      except KeyError:
         print ''
         print 'Catalog does not contain a %d column' % fwhmcol
         print ''
         return
      try:
         mag = self.data[magcol]
      except KeyError:
         print ''
         print 'Catalog does not contain a %d column' % magcol
         print ''
         return
      plt.plot(fwhm,mag,'bo')
      plt.xlim(xlim)
      plt.ylim(ylim)
      plt.xlabel('FWHM (pixels)')
      plt.ylabel('Magnitude')
      plt.show()

   #-----------------------------------------------------------------------

   def plot_nhist(self, magcol='MAG_AUTO', usestarmask=False,
                  magmin=15, magmax=28, color='b', alpha=1.):
      """
      Plots a histogram of galaxy magnitudes (similar to a log N-log S plot)
      that can be used to determine the magnitude to which the catalog is 
      complete.  A minimum FWHM can be set in order to select objects that
      are likely to be galaxies, but this is not required.

      Inputs:
         magcol      - column containing the magnitudes. Default = 'mag_auto'
         usestarmask - when this parameter is set to True, then use the
                       starmask mask to select the galaxies.
                       NOTE: this means that the set_starmask method has to
                       have been run for each of the input catalogs, or
                       else all objects will be plotted
                       Default=False
         magmin      - minimum magnitude to use for the plot. Default=15
         magmax      - maximum magnitude to use for the plot. Default=28
      """

      """ Get the magnitudes to be plotted """
      if usestarmask:
         if self.starmask is None:
            print('')
            print('WARNING: you have set usestarmask=True but there are')
            print(' no stars selected by the starmask')
            print('Please make sure that set_starmask has been run BEFORE'
                  'runing plot_nhist')
            print(' if you want to use this mask')
            print('')
            return
         else:
            mag = (self.data[self.starmask==False][magcol]).copy()
      else:
         mag = self.data[magcol].copy()

      mag = mag[np.isfinite(mag)]

      """ Plot the histogram """
      nbins = int(2 * (magmax - magmin))
      plt.hist(mag,range=(magmin, magmax), bins=nbins, color=color, 
               alpha=alpha)

      del(mag)

   #-----------------------------------------------------------------------

   def match_radec(self, ra2, dec2, rmatch, dra2=0., ddec2=0., doplot=True):
      """

      *** UNDER CONSTRUCTION!  DO NOT USE YET. ***

      Given a list of ra,dec coordinates (ra2, dec2), possibly from a second
      catalog, and a match tolerance, find the matches to the catalog
      contained in self.data

      Inputs:
        ra2      - RA (decimal degrees) for catalog 
        dec2     - Dec (decimal degrees) for second catalog
        rmatch   - max distance for a valid match (arcsec)
        dra2     - optional offset in ARCSEC to apply to ra2, if there is a known
                   offset between the catalogs (default=0.0)
        ddec2    - optional offset in ARCSEC to apply to dec2, if there is a
                   known offset between the catalogs (default=0.0)
      """

      print ""
      print "Matching catalogs: basic info"
      print "--------------------------------------------"
      print " Catalog 1: %d coordinates" % self.ra.size
      print " Catalog 2: %d coordinates" % ra2.size

      """ Initialize containers for output information """
      ramatch  = np.zeros(self.ra.size)
      decmatch = np.zeros(self.ra.size)
      self.nmatch   = np.zeros(self.ra.size,dtype=int)
      self.matchdx  = np.zeros(self.ra.size)
      self.matchdy  = np.zeros(self.ra.size)
      self.indmatch = np.ones(self.ra.size,dtype=int) * -1

      """ Correct for known shifts """
      ra2 = ra2.copy() + dra2/(3600.*np.cos(dec2))
      dec2 = dec2.copy() + ddec2/3600.

      """ Loop over catalog """
      print ""
      print "Searching for matches..."
      print "------------------------------"
      for i in range(self.ra.size):
         dx,dy = coords.sky_to_darcsec(self.ra[i],self.dec[i],ra2,dec2)
         dpos = np.sqrt(dx**2 + dy**2)
         isort = np.argsort(dpos)
         if dpos[isort[0]]<=rmatch:
            ramatch[i]  = self.ra[i]
            decmatch[i] = self.dec[i]
            self.matchdx[i]  = dx[isort[0]]
            self.matchdy[i]  = dy[isort[0]]
            self.nmatch[i]   = dpos[dpos<=rmatch].size
            self.indmatch[i] = isort[0]
         del dx,dy,dpos
      print " Number of matches between the catalogs:  %d" % \
          (self.nmatch>0).sum()
      mra  = ramatch[self.nmatch>0]
      mdec = decmatch[self.nmatch>0]
      mdx  = self.matchdx[self.nmatch>0]
      mdy  = self.matchdy[self.nmatch>0]
      mdx0 = np.median(mdx)
      mdy0 = np.median(mdy)
      print " Median offset for matches (RA):  %+6.2f arcsec" % mdx0
      print " Median offset for matches (Dec): %+6.2f arcsec" % mdy0

      """ Plot up some offsets, if desired """
      if doplot:
         plt.figure(1)
         plt.scatter(mdx,mdy)
         plt.axis('scaled')
         plt.xlabel(r'$\Delta \alpha$ (arcsec)')
         plt.ylabel(r'$\Delta \delta$ (arcsec)')
         plt.title('Offsets between matched sources (rmatch = %5.2f)' % rmatch)
         plt.axvline(0.0,color='r')
         plt.axhline(0.0,color='r')
         plt.plot(np.array([mdx0]),np.array([mdy0]),'r*',ms=20)
         plt.xlim(-1.1*rmatch,1.1*rmatch)
         plt.ylim(-1.1*rmatch,1.1*rmatch)

         plt.figure(2)
         #
         ax1 = plt.subplot(221)
         plt.scatter(mra,mdy)
         plt.setp(ax1.get_xticklabels(), visible=False)
         plt.ylabel(r'$\Delta \delta$ (arcsec)')
         plt.axhline(0.0,color='r')
         #
         ax2 = plt.subplot(223, sharex=ax1)
         plt.scatter(mra,mdx)
         plt.xlabel(r'$\alpha$')
         plt.ylabel(r'$\Delta \alpha$ (arcsec)')
         plt.axhline(0.0,color='r')
         #
         ax3 = plt.subplot(222, sharey=ax1)
         plt.scatter(mdec,mdy)
         plt.axhline(0.0,color='r')
         plt.setp(ax3.get_xticklabels(), visible=False)
         plt.setp(ax3.get_yticklabels(), visible=False)
         #
         ax4 = plt.subplot(224)
         plt.scatter(mdec,mdx)
         plt.xlabel(r'$\delta$')
         plt.axhline(0.0,color='r')
         plt.setp(ax4.get_yticklabels(), visible=False)

         plt.show()

      """ Clean up """
      del ramatch,decmatch
      del mdx,mdy,mra,mdec

   #-----------------------------------------------------------------------

   def print_ccmap(self, outfile, verbose=True):
      """
      Prints out a file that can be used as the input for the pyraf ccmap
      task.  This file has 4 columns:  x  y  RA  Dec

      Inputs:
         outfile   -  output file to be used as input for ccmap
         verbose   -  print task info
      """
      if verbose:
         print ""
         print "Printing to file for use in ccmap:  %s" % outfile
         print ""
      f = open(outfile,'w')
      f.write('# (x,y) catalog: %s\n' % self.infile)
      f.write('# Astrometric catalog: %s\n' % self.matchcat)
      f.write('# Columns are x y RA Dec\n')
      for i in range(self.nmatch):
         f.write('%8.2f %8.2f  %11.7f %+11.7f\n' % \
                    (self.matchx[i],self.matchy[i],self.matchra[i],
                     self.matchdec[i]))
      f.close()

   #-----------------------------------------------------------------------

   def find_closest_xy(self, xast, yast, xcol, ycol):

      """
      Finds the closest match, in (x,y) space to each member of the astrometric
      catalog (represented by xast,yast).
      """

      self.matchind = np.zeros(xast.size, dtype=int)

      xfield = 'f%d' % xcol
      yfield = 'f%d' % ycol

      for i in range(xast.size):
         dx = xast[i] - self.data[xfield]
         dy = yast[i] - self.data[yfield]
         dpos = dx**2 + dy**2
         sindex = np.argsort(dpos)
         self.matchind[i] = sindex[0]

      self.matchdx = xast - self.data[xfield][self.matchind]
      self.matchdy = yast - self.data[yfield][self.matchind]

   #-----------------------------------------------------------------------

   def match_xy(self, xa, ya, max_offset=None, xcol=8, ycol=9, verbose=True):

      """
      Find the closest match to each astrometric catalog object and calculate the
      offsets.
      Do two loops, to deal with possible confusion of sources on first pass
      through
      """
      dxmed = 0
      dymed = 0
      for i in range(2):
         if verbose:
            print ''
            print 'Pass %d' % (i+1)
            print '------------------------'
         xa0 = xa - dxmed
         ya0 = ya - dymed
         self.find_closest_xy(xa0,ya0,xcol,ycol)
         dxmed = np.median(self.matchdx)
         dymed = np.median(self.matchdy)
         if max_offset is not None:
            dpos = np.sqrt(self.matchdx**2 + self.matchdy**2)
            goodmask = dpos<max_offset
            if verbose:
               print "Applying a maximum offset cut of %7.1f pixels" % max_offset
               print "Median shifts before clipping: %7.2f %7.2f" % (dxmed,dymed)
         else:
            goodmask = np.ones(xa.size,dtype=bool)
         dxm  = self.matchdx[goodmask]
         dym  = self.matchdy[goodmask]
         dxmed = np.median(dxm)
         dymed = np.median(dym)
         if verbose:
            print "Median shifts after pass:   %7.2f %7.2f" % (dxmed,dymed)

      """
      Transfer information into object and clean up
      """
      if verbose:
         print ''
         print 'Found %d astrometric objects within FOV of image' % xa.size
         print 'Matched %d objects to astrometric catalog.' % dxm.size
      self.nmatch = dxm.size
      self.goodmask = goodmask.copy()
      self.matchind = self.matchind[goodmask]
      del xa0,ya0,goodmask

   #-----------------------------------------------------------------------

   def match_fits_to_ast(self, fitsfile, astcat, outfile=None, max_offset=None, 
                         racol=1, deccol=2, xcol=8, ycol=9, 
                         doplot=True, edgedist=50., imhdu=0, verbose=True):

      """
      Given the fits file from which this object (self) was defined 
      and an astrometric catalog, find the closest matches of the 
      astrometric objects to those contained in this object, using the WCS 
      information in the fits header.
      """

      if(verbose):
         print "Running match_fits_to_ast with:"
         print "   fitsfile = %s" % fitsfile
         print "   astcat   = %s" % astcat
      self.infits = fitsfile
      self.matchcat = astcat

      """
      Start by opening the fits file and reading the appropriate columns from
      the catalogs
      """
      hdulist = imf.open_fits(fitsfile)
      hdr = hdulist[imhdu].header
      if verbose:
         print ""
         hdulist.info()

      """
      Select the astrometric catalog objects that fall within the fits file FOV
      (at least with its current WCS)
      """
      raa,deca,xa,ya,astmask = select_good_ast(astcat,hdr,racol,deccol,edgedist)
      if verbose:
         print 'Found %d astrometric objects within FOV of image' % raa.size
         
      """
      Find the closest match to each astrometric catalog object
      """
      self.match_xy(xa,ya,max_offset,xcol,ycol,verbose)

      """ Transfer info about matches into the object """
      xfield = 'f%d' % xcol
      yfield = 'f%d' % ycol
      self.astmask  = astmask.copy()
      self.matchx   = self.data[xfield][self.matchind].copy()
      self.matchy   = self.data[yfield][self.matchind].copy()
      self.matchra  = raa[self.goodmask].copy()
      self.matchdec = deca[self.goodmask].copy()
      self.matchdx  = self.matchdx[self.goodmask]
      self.matchdy  = self.matchdy[self.goodmask]

      """ Plot the offsets if desired """
      if doplot:
         dxmed = np.median(self.matchdx)
         dymed = np.median(self.matchdx)
         plt.figure()
         plt.scatter(self.matchdx,self.matchdy)
         plt.xlabel('x offset (pix)')
         plt.ylabel('y offset (pix)')
         plt.axhline(color='k')
         plt.axvline(color='k')
         plt.axvline(dxmed,color='r')
         plt.axhline(dymed,color='r')
         print ""
         print "Black lines represent x=0 and y=0 axes"
         print "Red lines show median offsets of dx_med=%7.2f and dy_med=%7.2f" \
             % (dxmed,dymed)
         #plt.show()

      """ Write the output file, in a format appropriate for input to ccmap """
      if outfile is not None:
         self.print_ccmap(outfile,verbose)

      """ Clean up """
      hdulist.close()
      del hdr,raa,deca,xa,ya,astmask

   # -----------------------------------------------------------------------

   def set_starmask(self, mask):
      """
      Takes the input mask and assigns it to an internal mask associated
      with this instance of the Secat class.
      The internal mask is called starmask and has values of True for objects
      that have been identified as stars by the provided external mask.

      The external mask will be based on some characteristics in the catalog.
      Examples could be objects with a SExtractor CLASS_STAR value greater
       than 0.7, or a FWHM_IMAGE less than a certain value, or ...
      """

      self.starmask = mask
示例#15
0
r = (rX + rY)

# and for the pointing center
# first go from altitude to zenith angle
theta0 = numpy.radians((90 - obs.elevation))
phi0 = numpy.radians(obs.azimuth)
# this is the response for XX and YY
try:
    respX, respY = primary_beam.MWA_Tile_analytic(theta0,
                                                  phi0,
                                                  freq=obs.center_channel *
                                                  1.28e6,
                                                  delays=obs.delays)
except:
    logger.error('Error creating primary beams\n')
    sys.exit(1)
rX = numpy.real(numpy.conj(respX) * respX)
rY = numpy.real(numpy.conj(respY) * respY)
# make a pseudo-I beam
r0 = (rX + rY)

coord_pointing = ICRS(ra=obs.RA, dec=obs.Dec, unit=(u.degree, u.degree))
separation = coord.separation(coord_pointing).degree

logger.info('Observation at gpstime=%d, %d MHz, delays=%s' %
            (obs.observation_number, obs.center_channel * 1.28, obs.delays))
logger.info('Calculating for RA,Dec=%s' %
            (coord.to_string(precision=1, sep=':')))
print 'Separation: %.2f deg' % separation
print 'Power: %.2f' % (r / r0)
示例#16
0

now = Time.now()
doy_now = np.float(now.yday.split(':')[1])
print("Current DOY = {0}".format(np.int(doy_now)))
print("StarboardPoleRA (now) = {0:.3f}".format(StarboardPoleRA(now)))
print("PortPoleRA (now) = {0:.3f}".format(PortPoleRA(now)))

if args.ra is None or args.dec is None:
    SourcePos = get_icrs_coordinates(args.sourcename)
else:
    SourcePos = ICRS(ra=Angle(args.ra), dec=Angle(args.dec))
print("\nSource: {0} at {1}, {2}".format(args.sourcename, SourcePos.ra,
                                         SourcePos.dec))
print("Separation from Starboard Pole = {0:.3f}".format(
    SourcePos.separation(StarboardPoleCoord(now))))
print("Separation from Port Pole = {0:.3f}".format(
    SourcePos.separation(PortPoleCoord(now))))

# Plot separation from orbit pole for all of 2017 and beyond
doy2017 = np.arange(600.0)
times = doy2017 * u.d + Time("2017-01-01T00:00:00", format='isot', scale='utc')

fig, ax = plt.subplots()
seps = SourcePos.separation(StarboardPoleCoord(times))
ax.plot(doy2017, seps.to(u.deg))

# The Sun and Moon positions are returned in the GCRS frame
# Convert them to ICRS so .separation doesn't go insane when
# comparing different frames with different obstimes.
SunPos = get_sun(times)