def cone_search(self, ra, dec, radius): """ Searches for sources in a cone of given radius and center :param ra: decimal degrees, R.A. of the center of the cone :param dec: decimal degrees, Dec. of the center of the cone :param radius: radius in degrees :return: a table with the list of sources """ skycoord = SkyCoord(ra=ra * u.degree, dec=dec * u.degree, frame='icrs') # First check that we have an active internet connection if not internet_connection_is_active(): # pragma: no cover raise ConeSearchFailed("It looks like you don't have an active internet connection. Cannot continue.") with warnings.catch_warnings(): #Ignore all warnings, which are many from the conesearch module warnings.simplefilter('ignore') try: votable = conesearch.conesearch(skycoord, radius, catalog_db=self.catalog, verb=3, verbose=True, cache=False) except VOSError as exc: # Pragma: no cover # Download failed raise ConeSearchFailed("Cone search failed. Reason: %s" % exc.message) else: # Download successful table = votable.to_table() self._last_query_results = table.to_pandas().set_index('name').sort_values("Search_Offset") out = self.apply_format(table) #This is needed to avoid strange errors del votable del table # Save coordinates of center of cone search self._ra = ra self._dec = dec # Make a DataFrame with the name of the source as index return out
def main( ra, dec, radius, output=False ): """ important params: 'RAJ2000','DEJ2000','B1mag','R1mag','B2mag','R2mag','Imag' """ if output != False: if os.path.exists(output) == True: t = ascii.read(output) return t conf.conesearch_dbname = 'conesearch_warn' catalog = 'The USNO-B1.0 Catalog (Monet+ 2003) 1' c = SkyCoord(ra=ra,dec=dec,unit="degree") t = conesearch.conesearch(c, radius*u.degree, catalog_db=catalog).to_table() if len(t) == 0: print "No USNO-B1.0 Catalog (%s,%s,%s)" % (ra,dec,radius) return None name_ls = ["B1mag","B2mag","R1mag","R2mag","Imag"] for name in name_ls: select = np.ma.getmask(t[name]) t[name][select] = np.nan t.rename_column('RAJ2000','RA') t.rename_column('DEJ2000','DEC') filt_ls = ["B","R","I"] for filt in filt_ls: if filt in ["B","R"]: name1 = "%s1mag"%filt n1 = len(t[name1][~np.isnan(t[name1])]) name2 = "%s2mag"%filt n2 = len(t[name2][~np.isnan(t[name2])]) if filt == "R":filt="Rc" if n1 <= n2: t.rename_column(name2,'%sMAG'%filt) elif n2 < n1: t.rename_column(name1,'%sMAG'%filt) if filt == "I": t.rename_column("%smag"%filt,'%scMAG'%filt) if output != False: ascii.write(t,output) #print t return t
def main(ra, dec, radius, output=False): """ important params: 'ra','dec','j_m','j_cmsig','j_msigcom','j_snr',h...,k....,'glon','glat' """ if output != False: if os.path.exists(output) == True: t = ascii.read(output) return t conf.conesearch_dbname = 'conesearch_good' catalog = 'Two Micron All Sky Survey (2MASS) 1' c = SkyCoord(ra=ra, dec=dec, unit="degree") t = conesearch.conesearch(c, radius * u.degree, catalog_db=catalog).to_table() if len(t) == 0: print "No 2MASS Catalog (%s,%s,%s)" % (ra, dec, radius) return None t.rename_column('ra', 'RA') t.rename_column('dec', 'DEC') filt_ls = ["J", "H", "K"] for filt in filt_ls: if filt in ["J", "H"]: t.rename_column('%s_m' % filt.lower(), '%sMAG' % filt) t.rename_column('%s_cmsig' % filt.lower(), '%sMAGERR' % filt) elif filt == "K": t.rename_column('%s_m' % filt.lower(), '%ssMAG' % filt) t.rename_column('%s_cmsig' % filt.lower(), '%ssMAGERR' % filt) if output != False: ascii.write(t, output) #print t return t
from astroquery.vo_conesearch.conesearch import conesearch from astropy import units as u from astropy.coordinates import SkyCoord center = SkyCoord(189.1 * u.deg, 3 * u.deg, frame='galactic') search = conesearch( center=center, radius=1, verb=1, catalog_db= "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=IPHAS2&-out.all&") search.to_table().write('../data/snrpic/iphas-data.fits', format='fits', overwrite=True)
def search(self, **params): """ For compatibility with generic star catalog search. """ self.logger.debug("search params=%s" % (str(params))) ra, dec = params['ra'], params['dec'] if not (':' in ra): # Assume RA and DEC are in degrees ra_deg = float(ra) dec_deg = float(dec) else: # Assume RA and DEC are in standard string notation ra_deg = wcs.hmsStrToDeg(ra) dec_deg = wcs.dmsStrToDeg(dec) # Convert to degrees for search radius radius_deg = float(params['r']) / 60.0 # radius_deg = float(params['r']) # Note requires astropy 0.3.x+ c = coordinates.SkyCoord(ra_deg * units.degree, dec_deg * units.degree, frame='icrs') self.logger.info("Querying catalog: %s" % (self.full_name)) time_start = time.time() with warnings.catch_warnings(): # Ignore VO warnings warnings.simplefilter('ignore') results = conesearch.conesearch(c, radius_deg * units.degree, catalog_db=self.full_name, verbose=False) time_elapsed = time.time() - time_start numsources = results.array.size self.logger.info("Found %d sources in %.2f sec" % (numsources, time_elapsed)) # Scan the returned fields to find ones we need to extract # particulars from (ra, dec, id, magnitude) mags = [] ext = {} fields = results.array.dtype.names for name in fields: ucd = results.get_field_by_id(name).ucd ucd = str(ucd).lower() if ucd == 'id_main': ext['id'] = name elif ucd == 'pos_eq_ra_main': ext['ra'] = name elif ucd == 'pos_eq_dec_main': ext['dec'] = name if ('phot_' in ucd) or ('phot.' in ucd): mags.append(name) self.logger.debug("possible magnitude fields: %s" % str(mags)) if len(mags) > 0: magfield = mags[0] else: magfield = None # prepare the result list starlist = [] arr = results.array for i in range(numsources): source = dict(zip(fields, arr[i])) starlist.append(self.toStar(source, ext, magfield)) # metadata about the list columns = [ ('Name', 'name'), ('RA', 'ra'), ('DEC', 'dec'), ('Mag', 'mag'), ('Preference', 'preference'), ('Priority', 'priority'), ('Description', 'description'), ] # Append extra columns returned by search to table header # TODO: what if not all sources have same record structure? # is this possible with VO? cols = list(fields) cols.remove(ext['ra']) cols.remove(ext['dec']) cols.remove(ext['id']) columns.extend(zip(cols, cols)) # which column is the likely one to color source circles colorCode = 'Mag' info = Bunch.Bunch(columns=columns, color=colorCode) return starlist, info
def cone_search(self, ra, dec, radius): """ Searches for sources in a cone of given radius and center :param ra: decimal degrees, R.A. of the center of the cone :param dec: decimal degrees, Dec. of the center of the cone :param radius: radius in degrees :return: a table with the list of sources """ skycoord = SkyCoord(ra=ra * u.degree, dec=dec * u.degree, frame="icrs") # First check that we have an active internet connection if not internet_connection_is_active(): # pragma: no cover raise ConeSearchFailed( "It looks like you don't have an active internet connection. Cannot continue." ) with warnings.catch_warnings(): # Ignore all warnings, which are many from the conesearch module warnings.simplefilter("ignore") try: votable = conesearch.conesearch( skycoord, radius, catalog_db=self.catalog, verb=3, verbose=True, cache=False, ) except VOSError as exc: # Pragma: no cover # Download failed raise ConeSearchFailed("Cone search failed. Reason: %s" % exc.message) else: # Download successful table = votable # Workaround to comply with newer versions of astroquery if isinstance(votable, astropy.io.votable.tree.Table): table = votable.to_table() if table is None: log.error("Your search returned nothing") return None table.convert_bytestring_to_unicode() pandas_df = (table.to_pandas().set_index("name").sort_values( "Search_Offset")) str_df = pandas_df.select_dtypes([object]) if astropy_old: str_df = str_df.stack().str.decode("utf-8").unstack() for col in str_df: pandas_df[col] = str_df[col] if astropy_old: new_index = [x.decode("utf-8") for x in pandas_df.index] pandas_df.index = new_index self._last_query_results = pandas_df out = self.apply_format(table) # This is needed to avoid strange errors del votable del table # Save coordinates of center of cone search self._ra = ra self._dec = dec # Make a DataFrame with the name of the source as index return out
try: lun = open(file_stars_pkl, 'rb') cat = pickle.load(lun) lun.close() print("Loaded: " + file_stars_pkl) except FileNotFoundError: name_cat = u'Guide Star Catalog v2 1' # name_cat = u'The HST Guide Star Catalog, Version 1.1 (Lasker+ 1992) 1' # works, but 1' errors; investigating # stars = conesearch.conesearch(w.wcs.crval, 0.3, cache=False, catalog_db = name_cat) with data.conf.set_temp('remote_timeout', 200): # This is the very strange syntax to set a timeout delay. # The default is 3 seconds, and that times out often. stars = conesearch.conesearch(w.wcs.crval, radius, cache=False, catalog_db = name_cat) # Extract proper fields ra_cat = np.array(stars.array['ra'])*hbt.d2r # Convert to radians dec_cat = np.array(stars.array['dec'])*hbt.d2r # Convert to radians mag_cat = np.array(stars.array['Mag']) # Sort the stars. I don't know why stars.sort('mag') doesn't work, but it fails. order = np.argsort(mag_cat) ra_cat = ra_cat[order] dec_cat = dec_cat[order] mag_cat = mag_cat[order]
def get_fits_table_from_server(catalog, server, ra, dec, sr, verbose=False): """ This function fetches sources from the specified catalog from the specified server within the search radius and returns a Table containing them. Parameters ---------- catalog : {'sdss9', '2mass', 'ukidss9', 'gmos'} Name of catalog to search. server : str Name of server to query [sdss9_mko | sdss9_cpo | sdss9_vizier | 2mass_mko | 2mass_cpo | 2mass_vizier | ukidss9_mko | ukidss9_cpo] ra : float Right ascension of search center, decimal degrees. dec : float Declination of search center, decimal degrees. sr : float Search radius, decimal degrees. verbose : bool Verbose output. Returns ------- `astropy.table.Table` Sources within the search cone. """ # OK, do the query url = SERVER_URLS[server] cols = CAT_COLS[catalog] server_cols = SERVER_COLMAP[server] if verbose: print("RA, Dec, radius :", ra, dec, sr) print("catalog :", catalog) print("server :", server) print("url :", url) print("cols :", cols) print("server_cols :", server_cols) print("\n\n") # turn on verbose for debug to stdout. # Need verb=3 to get the right cols from vizier # astroquery 0.4 removed the pedantic keyword in favor of the config # item, and switched to returning an astropy table by default (hence # return_astropy_table=False below). # Another change is that conesearch returns None and issue of # NoResultsWarning if no results are found, instead of raising a # VOSError: https://github.com/astropy/astroquery/pull/1528 try: try: table = conesearch((ra, dec), sr, verb=3, catalog_db=url, return_astropy_table=False, verbose=False) except TypeError: # astroquery < 0.4 table = conesearch((ra, dec), sr, verb=3, catalog_db=url, pedantic=False, verbose=False) except VOSError: log.stdinfo("VO conesearch produced no results") return # Did we get any results? if table is None or table.is_empty() or len(table.array) == 0: log.stdinfo(f"No results returned from {server}") return array = table.array if server == 'sdss9_vizier': # Vizier uses the photoObj table from SDSS9, whereas the internal # server uses the calibObj, AKA "datasweep", which contains a subset # of photoObj, "designed for those who want to work with essentially # every well measured object, but only need the most commonly used # parameters". # # To get results similar to calibObj, we filter below on mode=1 to get # only the primary sources (the 'main' photometric observation of an # object). calibObj also uses a cut on magnitudes (see # http://www.sdss3.org/dr9/imaging/catalogs.php) but this is difficult # to reproduce here since the cuts apply to extinction-corrected # magnitudes, and we don't have the extinction values in the Vizier # table. array = array[array['mode'] == 1] # It turns out to be not viable to use UCDs to select the columns, # even for the id, ra, and dec. Even with vizier. <sigh> # The first column is our running integer column ret_table = Table([list(range(1, len(array) + 1))], names=('Id', ), dtype=('i4', )) ret_table.add_column( Column(array[server_cols[0]], name='Cat_Id', dtype='a')) ret_table.add_column( Column(array[server_cols[1]], name='RAJ2000', dtype='f8', unit='deg')) ret_table.add_column( Column(array[server_cols[2]], name='DEJ2000', dtype='f8', unit='deg')) # Now the photometry columns for col in range(3, len(cols)): ret_table.add_column( Column(array[server_cols[col]], name=cols[col], dtype='f4', unit='mag', format='8.4f')) header = add_header_to_table(ret_table) header['CATALOG'] = (catalog.upper(), 'Origin of source catalog') # Add comments to the header to describe it header.add_comment(f'Source catalog derived from the {catalog} catalog') header.add_comment(f'Source catalog fetched from server at {url}') header.add_comment(f'Delivered Table name from server: {table.name}') for col in range(len(cols)): header.add_comment('UCD for field {} is {}'.format( cols[col], table.get_field_by_id(server_cols[col]).ucd)) return ret_table
def nh_jring_create_objectlist(file_in, do_stars=True, bodies = [], num_stars_max = 100): ''' Creates a text file which lists all the stars in a file, with lines like 'star', <xpos>, <ypos>, mag [optional] <xpos> and <ypos> are the x and y coordinate centers, in pixels. The output is sorted by magnitude, if it is available. <bodies> is a list, like ['Adrastea', 'Amalthea'], etc. It is OK to have xpos and ypos be outside the screen. We might want to know that sometimes, for satellites. ''' # file_in = 'lor_0034962025_0x630_sci_1_opnav.fit' dir_images = '/Users/throop/data/NH_Jring/data/jupiter/level2/lor/all/' dir_out = '/Users/throop/data/NH_Jring/out/' file_in_base = file_in.split('/')[-1] # Strip the pathname file_out_base = file_in_base.replace('.fit', '_objects.txt') file_out = dir_out + file_out_base # If we were passed a file = dir_images + file_in_base header = hbt.get_image_header(dir_images + file_in_base) dx_pix = header['NAXIS1'] dy_pix = header['NAXIS2'] radius_search = 0.2 * u.deg with warnings.catch_warnings(): warnings.simplefilter("ignore") w = WCS(file) name_cat = u'Guide Star Catalog v2 1'# Works on gobi only (no tomato laptop) name_cat = 'The HST Guide Star Catalog, Version GSC-ACT (Lasker+ 1996-99) 1' url_cat = 'http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&' # Works always with data.conf.set_temp('remote_timeout', 30): # This is the very strange syntax to set a timeout delay. # The default is 3 seconds, and that times out often. with warnings.catch_warnings(): warnings.simplefilter("ignore") pos = (w.wcs.crval[0], w.wcs.crval[1]) # Get errors about invalid coords. Convert from np arr → tuple, ugh. stars = conesearch.conesearch(pos, radius_search, cache=True, catalog_db = url_cat) # NB: the returned value is a Table, but I have to access via .array[] -- not sure why. ra_stars = np.array(stars.array['ra'])*hbt.d2r # Convert to radians dec_stars = np.array(stars.array['dec'])*hbt.d2r # Convert to radians mag_stars = np.array(stars.array['Mag']) print("Stars downloaded: {}; mag = {} .. {}".format(np.size(mag_stars), np.nanmin(mag_stars), np.nanmax(mag_stars))) print("RA = {} .. {}".format(np.nanmin(ra_stars)*hbt.r2d, np.nanmax(ra_stars)*hbt.r2d)) # Now sort by magnitude, and keep the 100 brightest order = np.argsort(mag_stars) order = np.array(order)[0:num_stars_max] ra_stars = ra_stars[order] dec_stars = dec_stars[order] mag_stars = mag_stars[order] radec_stars = np.transpose(np.array((ra_stars,dec_stars))) x_stars, y_stars = w.wcs_world2pix(radec_stars[:,0]*hbt.r2d, radec_stars[:,1]*hbt.r2d, 0) is_good = np.logical_and( np.logical_and(x_stars >=0, x_stars <= dx_pix), np.logical_and(y_stars >=0, y_stars <= dy_pix) ) # Now make a table t_stars = Table() t_stars['name'] = np.zeros(np.shape(mag_stars[is_good]), dtype='U30') t_stars['name'][:] = u'star' t_stars['x_pix'] = x_stars[is_good] t_stars['y_pix'] = y_stars[is_good] t_stars['mag'] = mag_stars[is_good] #============================================================================== # Now find the satellite locations #============================================================================== if np.size(bodies) > 0: # Look up satellite positions et = header['SPCSCET'] utc = sp.et2utc(et, 'C', 0) x_bodies, y_bodies = hbt.get_pos_bodies(et, bodies, units='pixels', wcs=w) t_sats = Table() t_sats['x_pix'] = x_bodies t_sats['y_pix'] = y_bodies t_sats['name'] = np.array(bodies).astype('U30') #============================================================================== # Merge the stars and sats into one table #============================================================================== t_merged = vstack([t_stars, t_sats]) else: t_merged = t_stars #============================================================================== # And write the table to disk #============================================================================== t_merged.write(file_out, format = 'csv', overwrite = True) print("Wrote: {} ({} objects)".format(file_out, np.shape(t_merged)[0])) # return t_merged
def cone_search(self, ra, dec, radius): """ Searches for sources in a cone of given radius and center :param ra: decimal degrees, R.A. of the center of the cone :param dec: decimal degrees, Dec. of the center of the cone :param radius: radius in degrees :return: a table with the list of sources """ skycoord = SkyCoord(ra=ra * u.degree, dec=dec * u.degree, frame='icrs') # First check that we have an active internet connection if not internet_connection_is_active(): # pragma: no cover raise ConeSearchFailed( "It looks like you don't have an active internet connection. Cannot continue." ) with warnings.catch_warnings(): #Ignore all warnings, which are many from the conesearch module warnings.simplefilter('ignore') try: votable = conesearch.conesearch(skycoord, radius, catalog_db=self.catalog, verb=3, verbose=True, cache=False) except VOSError as exc: # Pragma: no cover # Download failed raise ConeSearchFailed("Cone search failed. Reason: %s" % exc.message) else: # Download successful table = votable.to_table() self._last_query_results = table.to_pandas().set_index( 'name').sort_values("Search_Offset") out = self.apply_format(table) #This is needed to avoid strange errors del votable del table # Save coordinates of center of cone search self._ra = ra self._dec = dec # Make a DataFrame with the name of the source as index return out
def search(self, **params): """ For compatibility with generic star catalog search. """ self.logger.debug("search params=%s" % (str(params))) ra, dec = params['ra'], params['dec'] if not (':' in ra): # Assume RA and DEC are in degrees ra_deg = float(ra) dec_deg = float(dec) else: # Assume RA and DEC are in standard string notation ra_deg = wcs.hmsStrToDeg(ra) dec_deg = wcs.dmsStrToDeg(dec) # Convert to degrees for search radius radius_deg = float(params['r']) / 60.0 # radius_deg = float(params['r']) # Note requires astropy 0.3.x+ c = coordinates.SkyCoord(ra_deg * units.degree, dec_deg * units.degree, frame='icrs') self.logger.info("Querying catalog: %s" % (self.full_name)) time_start = time.time() with warnings.catch_warnings(): # Ignore VO warnings warnings.simplefilter('ignore') results = conesearch.conesearch( c, radius_deg * units.degree, catalog_db=self.full_name, verbose=False) time_elapsed = time.time() - time_start numsources = results.array.size self.logger.info("Found %d sources in %.2f sec" % ( numsources, time_elapsed)) # Scan the returned fields to find ones we need to extract # particulars from (ra, dec, id, magnitude) mags = [] ext = {} fields = results.array.dtype.names for name in fields: ucd = results.get_field_by_id(name).ucd ucd = str(ucd).lower() if ucd == 'id_main': ext['id'] = name elif ucd == 'pos_eq_ra_main': ext['ra'] = name elif ucd == 'pos_eq_dec_main': ext['dec'] = name if ('phot_' in ucd) or ('phot.' in ucd): mags.append(name) self.logger.debug("possible magnitude fields: %s" % str(mags)) if len(mags) > 0: magfield = mags[0] else: magfield = None # prepare the result list starlist = [] arr = results.array for i in range(numsources): source = dict(zip(fields, arr[i])) starlist.append(self.toStar(source, ext, magfield)) # metadata about the list columns = [('Name', 'name'), ('RA', 'ra'), ('DEC', 'dec'), ('Mag', 'mag'), ('Preference', 'preference'), ('Priority', 'priority'), ('Description', 'description'), ] # Append extra columns returned by search to table header # TODO: what if not all sources have same record structure? # is this possible with VO? cols = list(fields) cols.remove(ext['ra']) cols.remove(ext['dec']) cols.remove(ext['id']) columns.extend(zip(cols, cols)) # which column is the likely one to color source circles colorCode = 'Mag' info = Bunch.Bunch(columns=columns, color=colorCode) return starlist, info
# Set up matplotlib import matplotlib.pyplot as plt import streamlit as st st.title('Conesearch Examples') sbar_text = 'This page uses the `astroquery.vo_conesearch` package ' sbar_text += 'and borrows heavily from an astropy-tutorials demo.' st.sidebar.markdown(sbar_text) # options = {'angular diameter': angular_diameter, # 'lookback time: Matplotlib':lookback_mpl, # 'lookback time: Altair': lookback_altair, # 'lookback time: Bokeh': lookback_bokeh, # 'lookback time: Plotly': lookback_plotly, # } # to_plot = st.sidebar.radio("Type of plot", list(options.keys()), 0) st.markdown('## Catalogs available') st.write(conesearch.list_catalogs()) target = st.sidebar.text_input('Astronomical object:', value='m31') st.markdown('## Target object') st.markdown(target) c = coord.SkyCoord.from_name(target, frame='icrs') st.write(c) result = conesearch.conesearch(c, 0.1 * u.degree) st.markdown(f'First non-empty table returned by {result.url}') st.markdown(f'Number of rows is {result.nrows}')
plt.imshow(stretch(image)) # Load matching stars DO_GSC1 = False # Stopped working 2-Oct-2016 DO_GSC2 = True DO_USNOA2 = False #============================================================================== # Get stars from star catalogs #============================================================================== if (DO_GSC1): name_cat = u'The HST Guide Star Catalog, Version 1.1 (Lasker+ 1992) 1' # works, but 1' errors; investigating stars = conesearch.conesearch(w.wcs.crval, radius_search, cache=False, catalog_db = name_cat) ra_stars = np.array(stars.array['RAJ2000'])*d2r # Convert to radians dec_stars = np.array(stars.array['DEJ2000'])*d2r # Convert to radians # table_stars = Table(stars.array.data) if (DO_GSC2): name_cat = u'Guide Star Catalog v2 1' file_pickle = dir_out + file_short.replace('.fit', '') + '.stars_gsc.pkl' # # If there is already a saved pickle file, then load from disk # # if os.path.isfile(file_pickle): # # print("Loading file: " + file_pickle) # lun = open(file_pickle, 'rb') # (ra_stars, dec_stars) = pickle.load(lun)
def navigate_image_stellar(im, wcs_in, name_catalog='', do_plot=True, method='fft', title=''): """ Navigate frame based on stellar images. Result returns is pixel shift (dy, dx). WCS paramaters are returned, *and* modified in place. """ import imreg_dft as ird from astropy.wcs import WCS # from astropy.vo.client import conesearch # Virtual Observatory, ie star catalogs # DEPRECATED! from astroquery.vo_conesearch import conesearch # New home of conesearch # Inputs are the image array, and the WCS structure. # This routine does not do any file IO. The image array and header must be already loaded. # The image is assumed to be stretched properly s.t. stars can be found using DAOphot. NUM_STARS_PHOT = 100 # How many stars to use from DAOPhot. For noisy images, DAO will find a lot of # fake stars, so we need to crank this up higher than the # of cat stars. NUM_STARS_CAT = 50 # How many stars to use from star catalog DO_GSC1 = False DO_GSC12 = True DO_USNOA2 = False #============================================================================== # Calculate the image radius, in radians, based on the size and the pixel scale #============================================================================== dx_pix = hbt.sizex(im) dy_pix = hbt.sizey(im) radec_corner = wcs_in.wcs_pix2world(0, dy_pix/2, 0) radec_center = wcs_in.wcs_pix2world(dx_pix/2, dy_pix/2, 0) (ra_corner, dec_corner) = radec_corner (ra_center, dec_center) = radec_center radius_image = math.sqrt((dec_corner-dec_center)**2 + ((ra_corner-ra_center) / np.cos(dec_corner*hbt.d2r))**2) * hbt.d2r radius_search_deg = radius_image * hbt.r2d # Read the WCS coordinates center_deg = wcs_in.wcs.crval # degrees. # crval is a two-element array of [RA, Dec], in degrees # Stretch the image. This is just for display -- no processing. stretch_percent = 90 stretch = astropy.visualization.PercentileInterval(stretch_percent) # PI(90) scales array to 5th .. 95th %ile. # Display it if (do_plot): plt.imshow(stretch(im)) #============================================================================== # Get stars from star catalogs #============================================================================== if (DO_GSC1): name_cat = u'The HST Guide Star Catalog, Version 1.1 (Lasker+ 1992) 1' # works, but 1' errors; investigating stars = conesearch.conesearch(center_deg, radius_search_deg, cache=True, catalog_db = name_cat) ra_stars = np.array(stars.array['RAJ2000'])*hbt.d2r # Convert to radians dec_stars = np.array(stars.array['DEJ2000'])*hbt.d2r # Convert to radians # table_stars = Table(stars.array.data) if (DO_GSC12): # name_cat = u'The HST Guide Star Catalog, Version 1.2 (Lasker+ 1996) 1' name_cat = u'Guide Star Catalog v2 1' # Works from gobi, not tomato url_cat = 'http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&' # Works always with data.conf.set_temp('remote_timeout', 30): # This is the very strange syntax to set a timeout delay. # The default is 3 seconds, and that times out often. with warnings.catch_warnings(): warnings.simplefilter("ignore") # stars = conesearch.conesearch(wcs_in.wcs.crval, radius_search_deg, cache=True, catalog_db = url_cat) # The various functions of conesearch/ConeSearch/etc are quite confusing, and are in flux. # This line below seems to work. It does not allow an explicit catalog suggstion, but it does the job. c = astropy.coordinates.SkyCoord(wcs_in.wcs.crval[0], wcs_in.wcs.crval[1], unit='deg') stars = ConeSearch.query_region(c, f'{radius_search_deg} deg') ra_stars = np.array(stars.array['ra'])*hbt.d2r # Convert to radians dec_stars = np.array(stars.array['dec'])*hbt.d2r # Convert to radians mag = np.array(stars.array['Mag']) print("Stars downloaded: N = {}; mag = {:.2f} .. {:.2f}".format(np.size(mag), np.nanmin(mag), np.nanmax(mag))) print("RA = {:.2f} .. {:.2f}".format(np.nanmin(ra_stars)*hbt.r2d, np.nanmax(ra_stars)*hbt.r2d)) # Now sort by magnitude, and keep the 100 brightest # This is because this GSC catalog is huge -- typically 2000 stars in LORRI FOV. # We need to reduce its size to fit in our fixed astropy table string length. order = np.argsort(mag) order = np.array(order)[0:NUM_STARS_CAT] ra_stars = ra_stars[order] # Returned as radians dec_stars = dec_stars[order] if (DO_USNOA2): name_cat = u'The USNO-A2.0 Catalogue (Monet+ 1998) 1' # Works but gives stars down to v=17; I want to v=13 stars = conesearch.conesearch(wcs_in.wcs.crval, 0.3, cache=False, catalog_db = name_cat) table_stars = Table(stars.array.data) mask = table_stars['Bmag'] < 13 table_stars_m = table_stars[mask] ra_stars = table_stars_m['RAJ2000']*hbt.d2r # Convert to radians dec_stars = table_stars_m['DEJ2000']*hbt.d2r # Convert to radians ra_stars_cat = ra_stars dec_stars_cat = dec_stars radec_stars_cat = np.transpose(np.array((ra_stars_cat, dec_stars_cat))) (x_stars_cat, y_stars_cat) = wcs_in.wcs_world2pix( radec_stars_cat[:,0]*hbt.r2d, radec_stars_cat[:,1]*hbt.r2d, 0) points_stars_cat = np.transpose((y_stars_cat, x_stars_cat)) # Yes, order is supposed to be (y,x) #============================================================================== # Use DAOphot to search the image for stars. #============================================================================== points_stars_phot = hbt.find_stars(im, num=NUM_STARS_PHOT) # Returns N x 2 aray. 0 = Row = y; 1 = Column = x. y_stars_phot =(points_stars_phot[:,0]) # xy is correct -- see above x_stars_phot =(points_stars_phot[:,1]) # #============================================================================== # Make a plot showing the DAO stars on the image #============================================================================== color_phot = 'red' # Color for stars found photometrically color_cat = 'lightgreen' # Color for stars in catalog DO_PLOT_DAO = False # Plot an intermediate result? if (DO_PLOT_DAO): plt.imshow(stretch(im)) plt.plot(x_stars_phot, y_stars_phot, linestyle='none', marker='o', markersize=9, mec=color_cat, mew=1, color='none', label = 'DAO photometric stars') # plot() uses x, y plt.plot(x_stars_cat, y_stars_cat, linestyle='none', marker='o', markersize=5, color='lightgreen', label = 'Cat stars') # plot() uses x, y plt.title(title) plt.ylim((hbt.sizey(im)),0) plt.xlim((0,hbt.sizex(im))) plt.legend(loc = 'upper left') plt.show() # Up til here, x and y are correct #============================================================================== # Look up the shift between the photometry and the star catalog. # Do this by making a pair of fake images, and then looking up image registration on them. #============================================================================== # I call this pointing process 'opnav'. # It is returned in order (y,x) because that is what imreg_dft uses, even though it is a bit weird. diam_kernel = 11 # How many pixels across are our synthetic stellar images? Should be odd number. Not critical. do_binary = True # For the stellar images, do a binary 1/0 (recommended), or a pixel distance? shape = np.shape(im) # Set shape of output array image_cat = hbt.image_from_list_points(points_stars_cat, shape, diam_kernel, do_binary=do_binary) image_phot = hbt.image_from_list_points(points_stars_phot, shape, diam_kernel, do_binary=do_binary) if (method == 'fft'): # Very fast method # Set up a constraint for the fit. It should be different for 1x1 and 4x4. # For 1x1, it works well to be 100 pixels. if (hbt.sizex(im) == 1024): # For LORRI 1x1 constraint_tx = (0,100) # Mean and stdev. i.e., returned value will be within stdev of mean. constraint_ty = (0,100) if (hbt.sizex(im) == 256): # For LORRI 4x4 constraint_tx = (0,25) # Mean and stdev. i.e., returned value will be within stdev of mean. constraint_ty = (0,25) constraint_angle = 0 # With one value, it is a fixed constraint. constraints = {'tx' : constraint_tx, 'ty' : constraint_ty, 'angle' : constraint_angle} ird.translation(image_cat, image_phot, constraints=constraints) (dy, dx) = ird.translation(image_cat, image_phot, constraints=constraints)['tvec'] dy_opnav = -dy dx_opnav = -dx if (method == 'bruteforce'): # Very slow method ((dx, dy), mat) = hbt.get_translation_images_bruteforce(image_cat, image_phot) dx_opnav = -dx dy_opnav = -dy #============================================================================== # Make a plot, showing DAO positions + catalog positions #============================================================================== do_plot = True if (do_plot): # hbt.figsize((10,10)) plt.imshow(stretch(im)) # Plot the stars -- catalog, and DAO plt.plot(x_stars_cat + dx_opnav, y_stars_cat + dy_opnav, marker='o', ls='None', color=color_cat, alpha = 0.5, ms=12, mew=1, label = 'Cat Stars, adjusted') plt.plot(x_stars_cat, y_stars_cat, marker='o', ls='None', color=color_cat, alpha = 1, ms=4, mew=1, label = 'Cat Stars, raw') plt.plot(x_stars_phot, y_stars_phot, marker='o', ls='None', color='none', markersize=10, mew=1, mec=color_phot, alpha = 1, label = 'DAOfind Stars') plt.title('After navigation, with dx = {:.1f}, dy = {:.1f}, {}'.format(dx_opnav, dy_opnav, title)) plt.legend() # Draw legend. Might be irrel since remove() might keep it; not sure. plt.imshow(stretch(im)) plt.show() #============================================================================== # Return results and exit #============================================================================== # Results are returned in terms of pixel offset and a revised WCS structure. # I don't seem to be able to copy a WCS structure, so I modify the one in place! # Get the pixel location of the center position crpix = wcs_in.wcs.crpix # Center position, in pixels, old # Get the new RA, Dec center of the array. It is just the old location, plus the offset ORIGIN_FORMAT = 1 # 0 for Numpy-style indexing, 1 for Fortran-style and FITS-style. # So what do I used for FITS files in python? Experimentally, 1 is right and 0 is not. (ra_new, dec_new) = wcs_in.wcs_pix2world(crpix[0] - dx_opnav, crpix[1] - dy_opnav, ORIGIN_FORMAT) # Set it wcs_in.wcs.crval = (ra_new, dec_new) return(wcs_in, (dy_opnav, dx_opnav))
def get_fits_table_from_server(catalog, server, ra, dec, sr): """ This function fetches sources from the specified catalog from the specified server within the search radius and returns a Table containing them. Parameters ---------- catalog: str [sdss9 | 2mass | ukidss9 | gmos] name of catalog to search server: str name of server to query [sdss9_mko | sdss9_cpo | sdss9_vizier | 2mass_mko | 2mass_cpo | 2mass_vizier | ukidss9_mko | ukidss9_cpo] ra: float right ascension of search center, decimal degrees dec: float declination of search center, decimal degrees sr: float search radius, decimal degrees Returns ------- Table sources within the search cone """ # This defines the URL for each server # There must be an entry in this dictionary for each server # listed in cat_servers above server_urls = { 'sdss9_mko': "http://mkocatalog2/cgi-bin/conesearch.py?CATALOG=sdss9&", 'sdss9_cpo': "http://cpocatalog2/cgi-bin/conesearch.py?CATALOG=sdss9&", 'sdss9_vizier': "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=sdss9&", '2mass_mko': "http://mkocatalog2/cgi-bin/conesearch.py?CATALOG=twomass_psc&", '2mass_cpo': "http://cpocatalog2/cgi-bin/conesearch.py?CATALOG=twomass_psc&", '2mass_vizier': "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=B/2mass&", 'ukidss9_mko': "http://mkocatalog2/cgi-bin/conesearch.py?CATALOG=ukidss&", 'ukidss9_cpo': "http://cpocatalog2/cgi-bin/conesearch.py?CATALOG=ukidss&", 'gmos_mko': "http://mkocatalog2/cgi-bin/conesearch.py?CATALOG=gmos&", 'gmos_cpo': "http://cpocatalog2/cgi-bin/conesearch.py?CATALOG=gmos&", } # This defines the column names *we* will use for that catalog. # There must be one entry in this list for each catalog listed # in cat_servers above cat_cols = { 'sdss9': ['catid', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'], '2mass': ['catid', 'raj2000', 'dej2000', 'jmag', 'jmag_err', 'hmag', 'hmag_err', 'kmag', 'kmag_err'], 'ukidss9': ['catid', 'raj2000', 'dej2000', 'ymag', 'ymag_err', 'zmag', 'zmag_err', 'jmag', 'jmag_err', 'hmag', 'hmag_err', 'kmag', 'kmag_err'], 'gmos': ['name', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'] } # This defines the column name mapping for each catalog server to our # column names. This copes with both variable server conventions, and # also allows us to point to different columns in the upstream catalog # - eg different model fits magnitides - if we wish # ***** These need to be in the same order as the list in our_cols ***** server_colmap = { 'sdss9_mko': ['objid', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'], 'sdss9_cpo': ['objid', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'], 'sdss9_vizier': ['objID', 'RAJ2000', 'DEJ2000', 'umag', 'e_umag', 'gmag', 'e_gmag', 'rmag', 'e_rmag', 'imag', 'e_imag', 'zmag', 'e_zmag'], '2mass_mko': ['designation', 'ra', 'decl', 'j_m', 'j_cmsig', 'h_m', 'h_cmsig', 'k_m', 'k_cmsig'], '2mass_cpo': ['designation', 'ra', 'decl', 'j_m', 'j_cmsig', 'h_m', 'h_cmsig', 'k_m', 'k_cmsig'], '2mass_vizier': ['_2MASS', 'RAJ2000', 'DEJ2000', 'Jmag', 'Jcmsig', 'Hmag', 'Hcmsig', 'Kmag', 'Kcmsig'], 'ukidss9_mko': ['id', 'raj2000', 'dej2000', 'y_mag', 'y_mag_err', 'z_mag', 'z_mag_err', 'j_mag', 'j_mag_err', 'h_mag', 'h_mag_err', 'k_mag', 'k_mag_err'], 'ukidss9_cpo': ['id', 'raj2000', 'dej2000', 'y_mag', 'y_mag_err', 'z_mag', 'z_mag_err', 'j_mag', 'j_mag_err', 'h_mag', 'h_mag_err', 'k_mag', 'k_mag_err'], 'gmos_mko': ['name', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'], 'gmos_cpo': ['name', 'raj2000', 'dej2000', 'umag', 'umag_err', 'gmag', 'gmag_err', 'rmag', 'rmag_err', 'imag', 'imag_err', 'zmag', 'zmag_err'] } # OK, do the query url = server_urls[server] cols = cat_cols[catalog] server_cols = server_colmap[server] # print "RA, Dec, radius:", ra, dec, sr # print "catalog: %s" % catalog # print "server: %s" % server # print "url: %s" % url # print "cols : %s" % cols # print "server_cols: %s" % server_cols # print "\n\n" # turn on verbose for debug to stdout. # Need verb=3 to get the right cols from vizier try: from astroquery.vo_conesearch.conesearch import conesearch from astroquery.vo_conesearch.exceptions import VOSError except ImportError: # conesearch was deprecated in astropy 2.0 and removed in 3.0, and # moved to astroquery 0.3.5 from astropy.vo.client.conesearch import conesearch from astropy.vo.client.vos_catalog import VOSError # The following phrase is implemented to handle differing function # signatures and return behaviours of vo conesearch function. Under # astropy, conesearch throws a VOSError exception on no results. Which # seems a bit extreme. See the import phrase at top. try: try: # astroquery 0.4 removed the pedantic keyword in favor of the # config item, and switched to returning an astropy table by # default (hence return_astropy_table=False below). # Another change is that conesearch returns None and issue of # NoResultsWarning if no results are found, instead of raising # a VOSError. # https://github.com/astropy/astroquery/pull/1528 table = conesearch((ra, dec), sr, verb=3, catalog_db=url, return_astropy_table=False, verbose=False) except TypeError: table = conesearch((ra, dec), sr, verb=3, catalog_db=url, pedantic=False, verbose=False) except VOSError: log.stdinfo("VO conesearch produced no results") return # Did we get any results? if(table is None or table.is_empty() or len(table.array) == 0): log.stdinfo("No results returned") return # It turns out to be not viable to use UCDs to select the columns, # even for the id, ra, and dec. Even with vizier. <sigh> # The first column is our running integer column ret_table = Table([list(range(1, len(table.array[server_cols[0]])+1))], names=('Id',), dtype=('i4',)) ret_table.add_column(Column(table.array[server_cols[0]], name='Cat_Id', dtype='a')) ret_table.add_column(Column(table.array[server_cols[1]], name='RAJ2000', dtype='f8', unit='deg')) ret_table.add_column(Column(table.array[server_cols[2]], name='DEJ2000', dtype='f8', unit='deg')) # Now the photometry columns for col in range(3, len(cols)): ret_table.add_column(Column(table.array[server_cols[col]], name=cols[col], dtype='f4', unit='mag', format='8.4f')) header = add_header_to_table(ret_table) header['CATALOG'] = (catalog.upper(), 'Origin of source catalog') # Add comments to the header to describe it header.add_comment('Source catalog derived from the {} catalog'. format(catalog)) header.add_comment('Source catalog fetched from server at {}'.format(url)) header.add_comment('Delivered Table name from server: {}'. format(table.name)) for col in range(len(cols)): header.add_comment('UCD for field {} is {}'.format( cols[col], table.get_field_by_id(server_cols[col]).ucd)) return ret_table
def navigate_image_stellar(im, wcs_in, name_catalog='', do_plot=True, method='fft', title=''): """ Navigate frame based on stellar images. Result returns is pixel shift (dy, dx). WCS paramaters are returned, *and* modified in place. """ import imreg_dft as ird from astropy.wcs import WCS # from astropy.vo.client import conesearch # Virtual Observatory, ie star catalogs # DEPRECATED! from astroquery.vo_conesearch import conesearch # New home of conesearch # Inputs are the image array, and the WCS structure. # This routine does not do any file IO. The image array and header must be already loaded. # The image is assumed to be stretched properly s.t. stars can be found using DAOphot. NUM_STARS_PHOT = 100 # How many stars to use from DAOPhot. For noisy images, DAO will find a lot of # fake stars, so we need to crank this up higher than the # of cat stars. NUM_STARS_CAT = 50 # How many stars to use from star catalog DO_GSC1 = False DO_GSC12 = True DO_USNOA2 = False #============================================================================== # Calculate the image radius, in radians, based on the size and the pixel scale #============================================================================== dx_pix = hbt.sizex(im) dy_pix = hbt.sizey(im) radec_corner = wcs_in.wcs_pix2world(0, dy_pix / 2, 0) radec_center = wcs_in.wcs_pix2world(dx_pix / 2, dy_pix / 2, 0) (ra_corner, dec_corner) = radec_corner (ra_center, dec_center) = radec_center radius_image = math.sqrt((dec_corner - dec_center)**2 + ( (ra_corner - ra_center) / np.cos(dec_corner * hbt.d2r))**2) * hbt.d2r radius_search_deg = radius_image * hbt.r2d # Read the WCS coordinates center_deg = wcs_in.wcs.crval # degrees. # crval is a two-element array of [RA, Dec], in degrees # Stretch the image. This is just for display -- no processing. stretch_percent = 90 stretch = astropy.visualization.PercentileInterval( stretch_percent) # PI(90) scales array to 5th .. 95th %ile. # Display it if (do_plot): plt.imshow(stretch(im)) #============================================================================== # Get stars from star catalogs #============================================================================== if (DO_GSC1): name_cat = u'The HST Guide Star Catalog, Version 1.1 (Lasker+ 1992) 1' # works, but 1' errors; investigating stars = conesearch.conesearch(center_deg, radius_search_deg, cache=True, catalog_db=name_cat) ra_stars = np.array( stars.array['RAJ2000']) * hbt.d2r # Convert to radians dec_stars = np.array( stars.array['DEJ2000']) * hbt.d2r # Convert to radians # table_stars = Table(stars.array.data) if (DO_GSC12): # name_cat = u'The HST Guide Star Catalog, Version 1.2 (Lasker+ 1996) 1' name_cat = u'Guide Star Catalog v2 1' # Works from gobi, not tomato url_cat = 'http://gsss.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&' # Works always with data.conf.set_temp( 'remote_timeout', 30): # This is the very strange syntax to set a timeout delay. # The default is 3 seconds, and that times out often. with warnings.catch_warnings(): warnings.simplefilter("ignore") # stars = conesearch.conesearch(wcs_in.wcs.crval, radius_search_deg, cache=True, catalog_db = url_cat) # The various functions of conesearch/ConeSearch/etc are quite confusing, and are in flux. # This line below seems to work. It does not allow an explicit catalog suggstion, but it does the job. c = astropy.coordinates.SkyCoord(wcs_in.wcs.crval[0], wcs_in.wcs.crval[1], unit='deg') stars = ConeSearch.query_region(c, f'{radius_search_deg} deg') ra_stars = np.array(stars.array['ra']) * hbt.d2r # Convert to radians dec_stars = np.array( stars.array['dec']) * hbt.d2r # Convert to radians mag = np.array(stars.array['Mag']) print("Stars downloaded: N = {}; mag = {:.2f} .. {:.2f}".format( np.size(mag), np.nanmin(mag), np.nanmax(mag))) print("RA = {:.2f} .. {:.2f}".format( np.nanmin(ra_stars) * hbt.r2d, np.nanmax(ra_stars) * hbt.r2d)) # Now sort by magnitude, and keep the 100 brightest # This is because this GSC catalog is huge -- typically 2000 stars in LORRI FOV. # We need to reduce its size to fit in our fixed astropy table string length. order = np.argsort(mag) order = np.array(order)[0:NUM_STARS_CAT] ra_stars = ra_stars[order] # Returned as radians dec_stars = dec_stars[order] if (DO_USNOA2): name_cat = u'The USNO-A2.0 Catalogue (Monet+ 1998) 1' # Works but gives stars down to v=17; I want to v=13 stars = conesearch.conesearch(wcs_in.wcs.crval, 0.3, cache=False, catalog_db=name_cat) table_stars = Table(stars.array.data) mask = table_stars['Bmag'] < 13 table_stars_m = table_stars[mask] ra_stars = table_stars_m['RAJ2000'] * hbt.d2r # Convert to radians dec_stars = table_stars_m['DEJ2000'] * hbt.d2r # Convert to radians ra_stars_cat = ra_stars dec_stars_cat = dec_stars radec_stars_cat = np.transpose(np.array((ra_stars_cat, dec_stars_cat))) (x_stars_cat, y_stars_cat) = wcs_in.wcs_world2pix(radec_stars_cat[:, 0] * hbt.r2d, radec_stars_cat[:, 1] * hbt.r2d, 0) points_stars_cat = np.transpose( (y_stars_cat, x_stars_cat)) # Yes, order is supposed to be (y,x) #============================================================================== # Use DAOphot to search the image for stars. #============================================================================== points_stars_phot = hbt.find_stars( im, num=NUM_STARS_PHOT) # Returns N x 2 aray. 0 = Row = y; 1 = Column = x. y_stars_phot = (points_stars_phot[:, 0]) # xy is correct -- see above x_stars_phot = (points_stars_phot[:, 1]) # #============================================================================== # Make a plot showing the DAO stars on the image #============================================================================== color_phot = 'red' # Color for stars found photometrically color_cat = 'lightgreen' # Color for stars in catalog DO_PLOT_DAO = False # Plot an intermediate result? if (DO_PLOT_DAO): plt.imshow(stretch(im)) plt.plot(x_stars_phot, y_stars_phot, linestyle='none', marker='o', markersize=9, mec=color_cat, mew=1, color='none', label='DAO photometric stars') # plot() uses x, y plt.plot(x_stars_cat, y_stars_cat, linestyle='none', marker='o', markersize=5, color='lightgreen', label='Cat stars') # plot() uses x, y plt.title(title) plt.ylim((hbt.sizey(im)), 0) plt.xlim((0, hbt.sizex(im))) plt.legend(loc='upper left') plt.show() # Up til here, x and y are correct #============================================================================== # Look up the shift between the photometry and the star catalog. # Do this by making a pair of fake images, and then looking up image registration on them. #============================================================================== # I call this pointing process 'opnav'. # It is returned in order (y,x) because that is what imreg_dft uses, even though it is a bit weird. diam_kernel = 11 # How many pixels across are our synthetic stellar images? Should be odd number. Not critical. do_binary = True # For the stellar images, do a binary 1/0 (recommended), or a pixel distance? shape = np.shape(im) # Set shape of output array image_cat = hbt.image_from_list_points(points_stars_cat, shape, diam_kernel, do_binary=do_binary) image_phot = hbt.image_from_list_points(points_stars_phot, shape, diam_kernel, do_binary=do_binary) if (method == 'fft'): # Very fast method # Set up a constraint for the fit. It should be different for 1x1 and 4x4. # For 1x1, it works well to be 100 pixels. if (hbt.sizex(im) == 1024): # For LORRI 1x1 constraint_tx = ( 0, 100 ) # Mean and stdev. i.e., returned value will be within stdev of mean. constraint_ty = (0, 100) if (hbt.sizex(im) == 256): # For LORRI 4x4 constraint_tx = ( 0, 25 ) # Mean and stdev. i.e., returned value will be within stdev of mean. constraint_ty = (0, 25) constraint_angle = 0 # With one value, it is a fixed constraint. constraints = { 'tx': constraint_tx, 'ty': constraint_ty, 'angle': constraint_angle } ird.translation(image_cat, image_phot, constraints=constraints) (dy, dx) = ird.translation(image_cat, image_phot, constraints=constraints)['tvec'] dy_opnav = -dy dx_opnav = -dx if (method == 'bruteforce'): # Very slow method ((dx, dy), mat) = hbt.get_translation_images_bruteforce(image_cat, image_phot) dx_opnav = -dx dy_opnav = -dy #============================================================================== # Make a plot, showing DAO positions + catalog positions #============================================================================== do_plot = True if (do_plot): # hbt.figsize((10,10)) plt.imshow(stretch(im)) # Plot the stars -- catalog, and DAO plt.plot(x_stars_cat + dx_opnav, y_stars_cat + dy_opnav, marker='o', ls='None', color=color_cat, alpha=0.5, ms=12, mew=1, label='Cat Stars, adjusted') plt.plot(x_stars_cat, y_stars_cat, marker='o', ls='None', color=color_cat, alpha=1, ms=4, mew=1, label='Cat Stars, raw') plt.plot(x_stars_phot, y_stars_phot, marker='o', ls='None', color='none', markersize=10, mew=1, mec=color_phot, alpha=1, label='DAOfind Stars') plt.title('After navigation, with dx = {:.1f}, dy = {:.1f}, {}'.format( dx_opnav, dy_opnav, title)) plt.legend( ) # Draw legend. Might be irrel since remove() might keep it; not sure. plt.imshow(stretch(im)) plt.show() #============================================================================== # Return results and exit #============================================================================== # Results are returned in terms of pixel offset and a revised WCS structure. # I don't seem to be able to copy a WCS structure, so I modify the one in place! # Get the pixel location of the center position crpix = wcs_in.wcs.crpix # Center position, in pixels, old # Get the new RA, Dec center of the array. It is just the old location, plus the offset ORIGIN_FORMAT = 1 # 0 for Numpy-style indexing, 1 for Fortran-style and FITS-style. # So what do I used for FITS files in python? Experimentally, 1 is right and 0 is not. (ra_new, dec_new) = wcs_in.wcs_pix2world(crpix[0] - dx_opnav, crpix[1] - dy_opnav, ORIGIN_FORMAT) # Set it wcs_in.wcs.crval = (ra_new, dec_new) return (wcs_in, (dy_opnav, dx_opnav))
index_asymptote = 0 if (encounter_phase == 'Outbound') else 1 # We make one call to SPICE to look up the asymptote position # Most SPICE calls are later, but we need to do this one now, ahead of order. (st,lt) = sp.spkezr('MU69', et[index_asymptote], 'J2000', 'LT', 'New Horizons') (junk, ra_asymptote, dec_asymptote) = sp.recrad(st[0:3]) crval = np.array([ra_asymptote, dec_asymptote]) * hbt.r2d radius_search = 0.15 # degrees # We only use these catalog for very fine searches, so narrow is OK. DO_PLOT_GSC = False # Goes to about v=12 if DO_PLOT_GSC: name_cat = u'The HST Guide Star Catalog, Version 1.1 (Lasker+ 1992) 1' # works, but 1' errors; investigating stars = conesearch.conesearch(crval, radius_search, cache=False, catalog_db = name_cat) ra_stars = np.array(stars.array['RAJ2000'])*hbt.d2r # Convert to radians dec_stars = np.array(stars.array['DEJ2000'])*hbt.d2r # Convert to radians mag_stars = np.array(stars.array['Pmag']) if DO_PLOT_USNO: name_cat = u'The USNO-A2.0 Catalogue (Monet+ 1998) 1' stars = conesearch.conesearch(crval, radius_search, cache=False, catalog_db = name_cat) ra_stars = np.array(stars.array['RAJ2000'])*hbt.d2r # Convert to radians id_stars = np.array(stars.array['USNO-A2.0']) # ID id_stars = id_stars.astype('U') # Convert from byte string to Unicode, ugh. dec_stars = np.array(stars.array['DEJ2000'])*hbt.d2r # Convert to radians mag_b_stars = np.array(stars.array['Bmag']) mag_r_stars = np.array(stars.array['Rmag']) usno = Table([id_stars, ra_stars, dec_stars, mag_b_stars, mag_r_stars],