def getteff(c,cone=10): G = nan while G != G and cone < 180: print "cone search radius",cone #if True: try: width = u.Quantity(cone, u.arcsec) height = u.Quantity(cone, u.arcsec) result = Gaia.cone_search_async(c,width) result = result.get_results() #print result.columns useindx = 0 print "len result",len(result) if len(result) > 1: Gmag = [] for i in range(len(result)): Gmag.append(result[i]["phot_g_mean_mag"]) Gmag = array(Gmag) print Gmag useindx = argmin(Gmag) G = result[useindx]["phot_g_mean_mag"] teff = result[useindx]["teff_val"] rstar = result[useindx]["radius_val"] except IndexError: G = nan teff = nan rstar = nan cone += 20 return teff,rstar,G
def get_GAIA_data(coord, radius): """Query Gaia database. Parameters ---------- coord : SkyCoord Position to search. radius : float Radius of search cone. Returns ------- objects table with the objects including the following info: ra (deg), ra_error (milliarcsec), dec (deg), dec_error (milliarcsec), mag """ j = Gaia.cone_search_async(coord, radius) r = j.get_results() #r.pprint() #r.show_in_browser() catalog_data = r.to_pandas() catalog_data["mag"] = catalog_data["phot_g_mean_mag"] catalog_data = catalog_data[["ra", "ra_error", "dec", "dec_error", "mag"]] print("Found {} sources in GAIA within a radius of {}".format( catalog_data.shape[0], radius)) #columns: ra, ra_error, dec, dec_error, mag return catalog_data
def select_sources_from_gaia(): # Use some set of criteria to choose sources for measurement. coord = astropy.coordinates.SkyCoord(hdr['CRVAL1'],hdr['CRVAL2'],unit='deg') result = Gaia.cone_search_async(coord,radius=10*u.arcminute) catalog = result.get_data() pass
def _select_stars_for_psf(self, sscat, imfile): ''' method to obtain stars from SExtractor catalog by comparing to GAIA sscat : input ldac-format catalog from which to select stars imfile : image file on which sscat is based; needed for header's CRVAL kw ''' # Read in header, get catalog of GAIA sources that overlap the field, ish. hdr = fits.getheader(imfile) coord = astropy.coordinates.SkyCoord(hdr['CRVAL1'], hdr['CRVAL2'], unit='deg') result = Gaia.cone_search_async(coord, radius=14 * u.arcminute) catalog = result.get_data() catalog_wg = catalog[catalog['parallax'] >= catalog['parallax_error']] # get RA/Dec of input catalog, cross-match against GAIA ss = fits.open(sscat) sexmatcher = eu.htm.Matcher(16, ra=ss[2].data['ALPHAWIN_J2000'], dec=ss[2].data['DELTAWIN_J2000']) gaia_matches, sexmatches, dist = sexmatcher.match(catalog_wg['ra'], catalog_wg['dec'], radius=6E-4, maxmatch=1) # Save result to file, return filename outname = sscat.replace('.ldac', '.star') ss[2].data = ss[2].data[sexmatches] ss.writeto(outname, overwrite=True) return outname
def make_psf_models(self): """ Start by making reference star file for later psfcat matching This arrangement is special to DECam data of a single cluster, where all images will have roughly the same center """ hdr = fits.getheader(self.image_files[0]) coord = astropy.coordinates.SkyCoord(hdr['CRVAL1'], hdr['CRVAL2'], unit='deg') result = Gaia.cone_search_async(coord, radius=1.2 * u.degree) catalog = result.get_data() catalog_wg = catalog[catalog['parallax'] >= catalog['parallax_error']] """ now do actual PSF modelling """ self.psfEx_models = [] for i, imagefile in enumerate(self.image_files): weightfile = self.weight_files[i] psfex_model_file = self._make_psf_model(imagefile, weightfile=weightfile, star_reference=catalog_wg) # move checkimages to psfex_output cmd = ' '.join(['mv chi* resi* samp* snap* proto*', self.psf_path]) os.system(cmd) try: self.psfEx_models.append(psfex.PSFEx(psfex_model_file)) except: pdb.set_trace()
def cone_search( *, name=None, radius=None, ra=None, dec=None, columns=[ "ra", "ra_error", "dec", "dec_error", "parallax", "parallax_error", "pmra", "pmra_error", "pmdec", "pmdec_error", ], dump_to_file=False, row_limit=50, **kwargs, ): if not isinstance(radius, (float, int)): raise ValueError("radious must be specified with int or float") else: radius = u.Quantity(radius, u.degree) if not ((name is not None) ^ (ra is not None and dec is not None)): raise ValueError("'name' or 'ra' and 'dec' are required (not both)") if name is not None: if not isinstance(name, str): raise ValueError("name must be string") else: coord = simbad_search(name) if (ra, dec) != (None, None): if not isinstance(ra, (float, int)) or not isinstance(dec, (float, int)): raise ValueError("ra and dec must be numeric") else: coord = SkyCoord(ra, dec, unit=(u.degree, u.degree), frame="icrs") if not isinstance(row_limit, int): raise ValueError("row_limit must be int") """ elif row_limit == -1: warnings.warn("Row limit set to unlimited.") """ Gaia.ROW_LIMIT = row_limit job = Gaia.cone_search_async( coordinate=coord, radius=radius, columns=columns, dump_to_file=dump_to_file, **kwargs, ) if not dump_to_file: table = job.get_results() return table
def checkNeighbor(variableRa, variableDec, sourceId): coord = SkyCoord(ra=variableRa, dec=variableDec, unit=(u.degree, u.degree), frame='icrs') radius = u.Quantity(0.00138889, u.deg) j = Gaia.cone_search_async(coord, radius) r = j.get_results() if len(r['ra']) > 1: for neighbor in range(len(r['ra'])): #make sure neighbor is different from target star if r['source_id'][neighbor] != sourceId: return 1 return 0
def find_in_gaia(ra, dec): # First do a large search using 30 arcsec coord = SkyCoord(ra=ra, dec=dec, unit=(u.degree, u.degree), frame='icrs') radius = u.Quantity(30.0, u.arcsec) q = Gaia.cone_search_async(coord, radius) gaia = q.get_results() gaia = gaia[np.nan_to_num(gaia['parallax']) > 0] warning = (len(gaia) == 0) # Then propagate the Gaia coordinates to 2000, and find the best match to the # input coordinates if not warning: ra2015 = np.array(gaia['ra']) * u.deg dec2015 = np.array(gaia['dec']) * u.deg parallax = np.array(gaia['parallax']) * u.mas pmra = np.array(gaia['pmra']) * u.mas / u.yr pmdec = np.array(gaia['pmdec']) * u.mas / u.yr c2015 = SkyCoord(ra=ra2015, dec=dec2015, distance=Distance(parallax=parallax, allow_negative=True), pm_ra_cosdec=pmra, pm_dec=pmdec, obstime=Time(2015.5, format='decimalyear')) c2000 = c2015.apply_space_motion(dt=-15.5 * u.year) idx, sep, _ = coord.match_to_catalog_sky(c2000) # The best match object best = gaia[idx] gaia_id = best['source_id'] MG = 5 + 5 * np.log10( best['parallax'] / 1000) + best['phot_g_mean_mag'] bprp = best['bp_rp'] gaia_id = np.int(gaia_id) G = np.float(best['phot_g_mean_mag']) MG = np.float(MG) bprp = np.float(bprp) return gaia_id, G, MG, bprp
def query_gaia(self, n_stars=1000): from astroquery.gaia import Gaia header = fits.getheader(self.stack_fits) shape = fits.getdata(self.stack_fits).shape cone_radius = np.sqrt(2) * np.max(shape) * self.telescope.pixel_scale / 120 wcs = WCS(header) coord = self.skycoord radius = u.Quantity(cone_radius, u.arcminute) gaia_query = Gaia.cone_search_async(coord, radius, verbose=False, ) self.gaia_data = gaia_query.get_results() skycoords = SkyCoord( ra=self.gaia_data['ra'], dec=self.gaia_data['dec'], pm_ra_cosdec=self.gaia_data['pmra'], pm_dec=self.gaia_data['pmdec'], radial_velocity=self.gaia_data['radial_velocity']) self.gaia_data["x"], self.gaia_data["y"] = np.array(wcsutils.skycoord_to_pixel(skycoords, self.wcs))
def checkNeighbor(variableRa, variableDec, sourceId): coord = SkyCoord(ra=variableRa, dec=variableDec, unit=(u.degree, u.degree), frame='icrs') radius = u.Quantity(0.00138889, u.deg) j = Gaia.cone_search_async(coord, radius) r = j.get_results() if len(r['ra']) > 1: for neighbor in range(len(r['ra'])): #make sure neighbor is different from target star if r['source_id'][neighbor] != sourceId: # flag star brighter than 8 magnitude within 50" if r['phot_g_mean_mag'][neighbor] < 8: return 1 # flag star brighter than 12 magnitude within 30" elif r['dist'][neighbor] < 0.00833333 and r['phot_g_mean_mag'][neighbor] < 12: return 1 # flag star brighter than 20 magnitude within 10" elif r['dist'][neighbor] < 0.00277778 and r['phot_g_mean_mag'][neighbor] < 20: return 1 # flag star within 5" elif r['dist'][neighbor] < 0.00138889: return 1 return 0
def get_gaia_data(coord, approx_mag=None, radius=None, mag_tol=1.0, **kwargs): """Cross match to Gaia and construct a dataset for isochrone fitting Args: coord (SkyCoord): The coordinates of the source approx_mag (float, optional): The magnitude of the source in an optical band. If provided, only sources with a Gaia G mag within ``mag_tol`` mag will be returned. mag_tol (float, optional): The magnitude tolerance. radius (Quantity, optional): The angular search radius. Raises: ValueError: If no match is found or if any of the parameters are not finite in the catalog. Returns: The data dictionary """ # coord = SkyCoord(ra=toi.RA, dec=toi.Dec, unit=(u.hourangle, u.deg)) if radius is None: radius = 20 * u.arcsec j = Gaia.cone_search_async(coord, radius) r = j.get_results() # Only select targets within 1 mag of the target if approx_mag is not None: r = r[np.abs(r["phot_g_mean_mag"] - approx_mag) < mag_tol] if not len(r): raise ValueError("no matches found") # Select the closest target r = r[0] return _parse_gaia_data(r, **kwargs)
def _get_gaia_id(ra, dec, radius): c = SkyCoord(ra, dec, unit=(u.deg, u.deg), frame='icrs') j = Gaia.cone_search_async(c, radius) res = j.get_results() return res['source_id'][0]
def get_gaia_data(coord, approx_mag=None, radius=None, **kwargs): """Cross match to Gaia and construct a dataset for isochrone fitting Args: coord (SkyCoord): The coordinates of the source approx_mag (float, optional): The magnitude of the source in an optical band. If provided, only sources with a Gaia G mag within 1 mag will be returned. radius (Quantity, optional): The angular search radius. Raises: ValueError: If no match is found or if any of the parameters are not finite in the catalog. Returns: The data dictionary """ # coord = SkyCoord(ra=toi.RA, dec=toi.Dec, unit=(u.hourangle, u.deg)) if radius is None: radius = 20 * u.arcsec j = Gaia.cone_search_async(coord, radius) r = j.get_results() # Only select targets within 1 mag of the target if approx_mag is not None: r = r[np.abs(r["phot_g_mean_mag"] - approx_mag) < 1] if not len(r): raise ValueError("no matches found") # Select the closest target r = r[0] # Parallax offset reference: https://arxiv.org/abs/1805.03526 plx = r["parallax"] + 0.082 plx_err = np.sqrt(r["parallax_error"] ** 2 + 0.033 ** 2) if not (np.isfinite(plx) and np.isfinite(plx_err)): raise ValueError("non finite parallax") # Convert flux error to magnitude error by linear propagation, this # should be ok for bright sources factor = 2.5 / np.log(10) params = {} for band in ["G", "BP", "RP"]: mag = float(r["phot_{0}_mean_mag".format(band.lower())]) err = float(r["phot_{0}_mean_flux_error".format(band.lower())]) err /= float(r["phot_{0}_mean_flux".format(band.lower())]) err *= factor if not (np.isfinite(mag) and np.isfinite(err)): raise ValueError("non finite params") params[band] = (mag, err) params["parallax"] = (float(plx), float(plx_err)) # Make sure that the dtypes are all correct for k, v in params.items(): params[k] = np.array(v, dtype=np.float64) if params["parallax"][0] > 0: params["max_distance"] = np.clip(2000 / plx, 100, np.inf) params = dict(params, **kwargs) return params
def query(coordi, photo_filters, CCD_structure, exposure_time, catalog): ''' This funtion uses all the functions above to query Simbad and extract the information about the stars in a specific area of the sky Parameters ---------- coordi : string It contains the center of the area of interest photo_filter : list (string elements) It is a list where a element is a string that identifies a filter, e.g. "U","R","I" CCD_structure : array (float elements) This object contains the information about the measure of the CCD [0] : the length of the CCD on the x axis in mm [1] : the length of the CCD on the y axis in mm [2] : the length of a single pixel in mm exposure_time : int It is the exposure time used to obtain the image, it is in seconds Outputs ------- data : list It is a list of array that contains [0] : array, the position of the stars along the x axis [1] : array, the position of the stars along the y axis [2] : array, the number of electrons generates by the stars on the CCD center : list It contains the center of the sky portion in "RA" and "DEC" ''' log.info(hist()) radius = radius_sky_portion(CCD_structure) coordi = coord.SkyCoord(coordi, frame = 'icrs', unit=(u.hourangle, u.deg)) center = [0,0] center[0] = coordi.ra.degree center[1] = coordi.dec.degree data = Data_structure() AirMass = 1 #simple Antola if catalog == 'Simbad': Controll_V = False for n, i in enumerate(photo_filters): if i == "g": photo_filters[n] = "V" photo_filters_temp = photo_filters if "V" in photo_filters_temp: photo_filters_temp.append("g") Controll_V = True f =['flux({0})'.format(x) for x in photo_filters_temp] [Simbad.add_votable_fields(g) for g in f] result_table = Simbad.query_region(coordi, radius) Stars_number = len(result_table) len_filter_list = len(photo_filters_temp) if Controll_V: log.warning('If filter V is not available, g filter will be used instead') log.info(hist(f"Creating {Stars_number} stars:")) for i in range(Stars_number): log.info(f"Star n° {i+1}/{Stars_number}") row = result_table[i] tot = 0 magnitudo = [] for j in range(11, 11+len_filter_list): #controll if row[j] is np.ma.masked: row[j] = 0 magnitudo.append(row[j]) tot = magnitudo_to_electrons(magnitudo, photo_filters_temp, AirMass, exposure_time, Controll_V) if tot != 0: #if total flux is 0 the object is not passed c = coord.SkyCoord(row[1], row[2], frame = 'icrs', unit=(u.hourangle, u.deg))##change here x, y = Coordinator(c, center, CCD_structure, catalog) data[0].append(x) data[1].append(y) data[2].append(tot) elif catalog == 'Gaia': Gaia.ROW_LIMIT = -1 tables = Gaia.cone_search_async(coordi, radius) tables = tables.get_results() photonis = tables['phot_g_mean_flux'][:] mag = tables['phot_g_mean_mag'][:] pos_ra = tables['ra'][:] pos_dec = tables['dec'][:] number_of_stars = len(photonis) for i in range(number_of_stars): c = coord.SkyCoord(pos_ra[i], pos_dec[i], frame = 'icrs', unit=(u.degree, u.degree)) x, y = Coordinator(c, center, CCD_structure, catalog) mag_atm_att = AirMass*0.2 #extinction_coefficient_mean mag[i] = mag[i] + mag_atm_att mag[i] = 10**(6.74-0.4*mag[i]) #here becomes photons quantum_efficiency = 0.3 transmissivity = 0.5 multiplier = quantum_efficiency * transmissivity * exposure_time *0.5 data[0].append(x) data[1].append(y) data[2].append(mag[i] * multiplier) return data, center
# # match the catalog - ignore all sources with multiple counterparts # tree = scipy.spatial.KDTree(catalog[:, 2:4]) # get ra/dec from reference center_pos = wcs.getCentreWCSCoords() print center_pos coord = astropy.coordinates.SkyCoord(ra=center_pos[0], dec=center_pos[1], unit=(u.degree, u.degree), frame='fk5') radius = Quantity(4.0, u.arcmin) j = Gaia.cone_search_async(coord, radius) r = j.get_results() # r.pprint() #try: #print r[r.keys()[0]]['ra'] print r['ra'] print r['dec'] #except: # pass for iteration in range(3): # convert the x/y from HST into ra/dec using the latest and greatest WCS astro_wcs = astropy.wcs.WCS(header=ext.header)
def make_gaia(coords, image=os.path.join('.', 'synthetic_gaia.fits'), epoch="J2020.5"): """ Creates a synthetic image from GAIA DR2 photometry along the specified coordinates. Returns the synthetic image in fits format. Parameters: coords: Coordinates of centre of image. image: File name of image. Default is synthetic_gaia.fits epoch: Epoch to translate image. Default is J2020.5 """ ##### ##### Define GMOS parameters ##### GMOS FoV is 330 arcsec ##### GMOS slit length is 330 arcsec ##### GMOS fwhm chosen in 0.3 arcsec ##### Image created is 390 arcsec, to accomadte additional overlays ##### GMOS read noise is 3.96 (e-/ADU) ##### GMOS gain is 1.829 (e- rms) ##### gmosfov = 390 * u.arcsec fwhm = 0.3 * u.arcsec shape = (1300, 1300) zeroarr = np.zeros(shape) width = 390 * u.arcsec height = 390 * u.arcsec ##### Read coordinates and epoch coords = coords epoch = Time(epoch, format='jyear_str') ##### Query GAIA DR2 using astroquery TAP+ ##### Synchronous query, limit of 2000 rows print('Searching GAIA TAP+ for stars over the GMOS FoV...') gaiasearch = Gaia.cone_search_async(coordinate=coords, radius=gmosfov, verbose=False) searchresults = gaiasearch.get_results() nstars = len(searchresults) print(nstars, 'stars recovered from GAIA TAP+ query over the GMOS FoV') if nstars == 2000: warnings.warn( 'Asynchronous TAP+ service query limit reached, image is incomplete.' ) fitshdr = mkfitshdr(coords, zeroarr, image, epoch) hdr = fitshdr[0] hdu = fitshdr[1] hdul = fitshdr[2] w = fitshdr[3] c = SkyCoord(ra=searchresults['ra'], dec=searchresults['dec'], pm_ra_cosdec=searchresults['pmra'], pm_dec=searchresults['pmdec'], obstime=Time(searchresults['ref_epoch'], format='decimalyear')) cnew = c ###### in the current implementation, transformation of the image to the epoch is not applied ###### cnew = c.apply_space_motion(new_obstime=Time(epoch)) star_coords = w.wcs_world2pix([cnew.ra.deg], [cnew.dec.deg], 0) xvalue = star_coords[0].ravel() yvalue = star_coords[1].ravel() flux = (searchresults['phot_g_mean_flux'] * u.mag).value ##### Error values cerr = SkyCoord(ra=searchresults['ra_error'], dec=searchresults['dec_error']) xerrvalue = cerr.ra.value yerrvalue = cerr.dec.value xerrmask = np.nan_to_num(xerrvalue, nan=0.0, posinf=0.0, neginf=0.0) yerrmask = np.nan_to_num(yerrvalue, nan=0.0, posinf=0.0, neginf=0.0) xerrmask[xerrmask < 1.0] = 1.0 yerrmask[yerrmask < 1.0] = 1.0 ##### Error values less than 1.0 lead to incorrect values in photutils. Error values of 1.0 lead to no significiant differences in images compared to no error. ##### Create Table of results t = Table([flux, xvalue, yvalue, xerrmask, yerrmask], names=('flux', 'x_mean', 'y_mean', 'x_stddev', 'y_stddev'), dtype=('i8', 'i8', 'i8', 'i8', 'i8')) print('Table of stars is being generated as an image') zeroarr = make_gaussian_sources_image(shape, t) ##### Read noise read_noise = np.random.normal(scale=(3.92 / 1.829), size=shape) noise_image = make_noise_image(shape, distribution='poisson', mean=0.5) ##### synth_image = zeroarr + noise_image ##### ###### read_noise is disabled hdu = fits.PrimaryHDU(synth_image, header=hdr) hdul = fits.HDUList([hdu]) hdul.writeto(image, overwrite=True) print('Synthetic GAIA DR2 image is saved as', image) return image
def WDGaiaRadius(ra,dec,teff,teff_err=None,searchradius=5.0,modelmass=0.6, modelpath='AllModels/',A_G=0): """Estimate WD Radius from Gaia astrometry. Queries for Gaia data and distances from Bailer-Jones et al. (2018, ApJ, 156, 2). Scales Bergeron et al. DA (no DBs currently) cooling models (http://www.astro.umontreal.ca/~bergeron/CoolingModels/) until the radius reproduces the Gaia magnitude at the parallactic distance. Corrects for extinction if coefficient A_G is provided in magnitudes, following the prescription of Gentile-Fusillo et al. (2019, MNRAS, 482, 4570). Uses https://github.com/keatonb/BergeronToPandas to read in Bergeron models. If error on Teff given, includes contribution roughly in quadrature. Returns measurement and lower, upper bounds defined by Bailer-Jones et al. confidence interval. ra, dec should be in decimal degrees teff,teff_err in Kelvin from spectroscopy searchradius is in arcseconds modelmass in solar units must match a file from the Bergeron models that is new enough to include synthetic Gaia magnitudes. """ #First query Gaia sources coord = SkyCoord(ra=ra, dec=dec, unit=(u.degree, u.degree), frame='icrs') searchradius = u.Quantity(searchradius, u.arcsec) j = Gaia.cone_search_async(coord, searchradius) r = j.get_results() print("Gaia sources within {}: {}".format(searchradius,len(r))) if len(r) > 0: r.sort("dist") #Accept nearest sourceid = r["source_id"][0] Gmag = r["phot_g_mean_mag"][0] print("Nearest has Gaia G mag of {}.".format(Gmag)) b = r["b"][0] #Galactic latitude in degrees #Extinction correction following Gentile-Fusillo et al. 2019 parallax = r["parallax"][0]*1e-3 #arcsec extcorr = -A_G*(1. - np.exp(-np.sin(np.abs(b*np.pi/180)) / (200*parallax))) Gmag += extcorr print("Extinction correction of {} then applied to get G = {} mag.".format(extcorr,Gmag)) #Then get Bailer-Jones distance v = Vizier(columns=['*'], column_filters={"Source":str(sourceid)}).get_catalogs('I/347') dist = np.array([v[0]["rest"][0],v[0]["b_rest"][0],v[0]["B_rest"][0]]) print("Distance constraints from Bailer-Jones et al: {}".format(dist)) #Referencing Bergeron cooling models modelfile = os.path.join(modelpath, "Table_Mass_{:.1f}".format(modelmass)) print("Referencing Bergeron model file at "+modelfile) models = list(BergeronToPandas(modelfile).values())[0] #Constants G = 6.67259e-8 #cm3 g-1 s-2 Msun = 1.99e33 #g Rsun = 6.96e10 #cm modelteff = models['Teff'].values modellogg = models['logg'].values modelradius = np.sqrt(G*modelmass*Msun/(10.**modellogg))/Rsun #solar radii modelGmag = models['G'].values #Define interpolation functions teff2radius = interp1d(modelteff,modelradius) teff2Gmag = interp1d(modelteff,modelGmag) distancemodulus = 5.*np.log10(dist)-5. #Start with values assuming along loaded model track trackradius = teff2radius(teff) trackGmag = teff2Gmag(teff) estGmag = trackGmag + distancemodulus #Scale to measured magnitude remaining = estGmag - Gmag fluxratio = 2.512**remaining radiusratio = np.sqrt(fluxratio) gaiaradius = trackradius * radiusratio #Include effect of Teff_err if given if teff_err is not None: testteff = np.array([teff,teff+teff_err,teff-teff_err]) trackradius = teff2radius(testteff) trackGmag = teff2Gmag(testteff) estGmag = trackGmag + distancemodulus[0] remaining = estGmag - Gmag fluxratio = 2.512**remaining radiusratio = np.sqrt(fluxratio) gr2 = trackradius * radiusratio #combine roughly in quadrature gaiaradius = gaiaradius[0] + np.sqrt((gaiaradius - gaiaradius[0])**2. + (gr2 - gr2[0])**2.)*np.array([1,-1,1]) return gaiaradius else: #No Gaia results? print("Returning 'None's") return None,None,None
def make_gaia_image(skycoord, fov, sampling, fwhm, obsdate=dup.parse("2018 07 01 00:00:00 UTC"), fn=os.path.join('.', 'pseudo_gaia.fits')): ''' Given a coordinate, use the Gaia catalogue to create a mock image of the sky. Args: skycoord: the astropy SkyCoord of the center of the image fov: size of the image to create, in astropy.units sampling: pixel size of the image to create, in astropy.units fwhm: fwhm of the fake stars in the image, in astropy.units obsdate: date of the observation (to propagate the motion of the stars) as datetime.datetime object fn: relative path + FITS filename Returns: The FITS filename ''' # Ok, assemble an array of the suitable size nx = int(np.floor((fov / sampling).value)) im = np.zeros((nx, nx)) # Query GAIA print(' Querying GAIA to create a pseudo-image of the sky ...') # Make it a sync search, because I don't think I need more than 2000 targets ... # TODO: figure out why cone_search fails ... and fix it ! Swap to async for now... j = Gaia.cone_search_async(skycoord, fov, verbose=False) r = j.get_results() nstars = len(r) # TODO: well, what if I do need more than 2000 targets ? # Issue a warning for now ... if nstars == 2000: warnings.warn( ' Reached query limit of 2k stars. Gaia image will not be complete.' ) # Create a very basic header for the FITS file hdr = fits.Header() hdr.set('CRPIX1', nx / 2, 'X reference pixel') hdr.set('CRPIX2', nx / 2, 'Y reference pixel') hdr.set('CRVAL1', skycoord.ra.deg, 'Reference longitude') hdr.set('CRVAL2', skycoord.dec.deg, 'Reference latitude') hdr.set('CTYPE1', 'RA---TAN', 'Coordinates -- projection') hdr.set('CTYPE2', 'DEC--TAN', 'Coordinates -- projection') hdr.set('CDELT1', -sampling.to(u.deg).value, 'X scale') # mind the sign ! hdr.set('CDELT2', sampling.to(u.deg).value, 'Y scale') hdr.set('RADESYS', 'ICRS', 'Coordinate system') hdr.set('EQUINOX', 2000.0, 'Epoch of the equinox') hdr['COMMENT'] = 'Artificial sky image reconstructed from the Gaia catalogue.' hdr['COMMENT'] = 'Number of stars: %i' % (nstars) hdr['COMMENT'] = 'FWHM: %i mas' % (int(fwhm.to(u.mas).value)) hdr['COMMENT'] = 'Bandpass: 285.5-908 THz ' hdr['COMMENT'] = 'Epoch: %s' % (obsdate.strftime('%Y-%h-%d %H:%M:%S UTC')) hdr['COMMENT'] = 'Created %s with fcmaker v%s' % ( datetime.utcnow().strftime('%Y-%h-%d %H:%M:%S UTC'), fcm_v.__version__) hdr['COMMENT'] = 'See http://fpavogt.github.io/fcmaker for details.' # Save the empty FITS file for now hdu = fits.PrimaryHDU(im, header=hdr) hdul = fits.HDUList([hdu]) hdul.writeto(fn, overwrite=True) # Re-extract the WCS info w = WCS(fn) # Prepare some variables x, y = np.meshgrid(np.arange(0, nx, 1), np.arange(0, nx, 1)) sigma = (fwhm / sampling).value / (2 * np.sqrt(2 * np.log(2))) # For each star, add a Gaussian of the suitable size for s in range(nstars): # First, create a SkyCoord entry star = SkyCoord( ra=r['ra'][s], dec=r['dec'][s], obstime=Time(r['ref_epoch'][s], format='decimalyear'), frame='icrs', unit=(u.deg, u.deg), pm_ra_cosdec=r['pmra'][s] * u.mas / u.yr, pm_dec=r['pmdec'][s] * u.mas / u.yr, # I must specify a generic distance to the target, # if I want to later on propagate the proper motions distance=fcm_m.default_pm_d, ) # Then, propagate the star at the time of the observation star_now = star.apply_space_motion(new_obstime=Time(obsdate)) # Get the image coordinate of the star star_coords = w.wcs_world2pix([star_now.ra.deg], [star_now.dec.deg], 0) # The distance of all pixels to the star d = np.sqrt((x - star_coords[0])**2 + (y - star_coords[1])**2) # Add the star to the array ... scale it as a function of its flux im += r['phot_g_mean_flux'][s] * np.exp(-( (d)**2 / (2.0 * (fwhm / sampling).value**2))) # Save the final FITS file hdu = fits.PrimaryHDU(im, header=hdr) hdul = fits.HDUList([hdu]) hdul.writeto(fn, overwrite=True) return fn
context.prog_name = prog_name ##--------------------------------------------------------------------------## ##--------------------------------------------------------------------------## ##--------------------------------------------------------------------------## ## Search cone setup: tgtcoo = coord.SkyCoord(ra=context.RA_deg, dec=context.DE_deg, unit=(uu.deg, uu.deg), frame='icrs') cone_radius = uu.Quantity(context.radius, uu.deg) ## Perform query: sys.stderr.write("Running query ... \n") tik = time.time() qobj = Gaia.cone_search_async(tgtcoo, cone_radius) hits = qobj.get_results() tok = time.time() sys.stderr.write("Query time: %.3f seconds.\n" % (tok - tik)) ## Save results: if context.output_file: sys.stderr.write("Saving to %s ... " % context.output_file) hits.write(context.output_file, format='ascii.csv') sys.stderr.write("done.\n") ###################################################################### # CHANGELOG (fetch_gaia_nearby.py): #--------------------------------------------------------------------- # # 2019-09-05:
def solve_wcs(input_file, telescope, sex_config_dir='./Config', static_mask=None, proc=None, log=None): #start time t_start = time.time() if log: log.info('Running solve_wcs version: ' + str(__version__)) #import telescope parameter file global tel try: tel = importlib.import_module('tel_params.' + telescope) except ImportError: print('No such telescope file, please check that you have entered the'+\ ' correct name or this telescope is available.''') sys.exit(-1) #get data and header info hdr = fits.open(input_file) data = hdr[tel.wcs_extension()].data data_y, data_x = np.shape(data) header = hdr[tel.wcs_extension()].header ra = header['CRVAL1'] dec = header['CRVAL2'] #run sextractor if log: log.info('Running SExtractor.') cat_name = input_file.replace('.fits', '.cat') table = run_sextractor(input_file, cat_name, tel, sex_config_dir=sex_config_dir, log=log) #mask and sort table if log: log.info('Masking sources and applying brightness cuts.') table = table[(table['FLAGS'] == 0) & (table['EXT_NUMBER'] == tel.wcs_extension() + 1) & (table['MAGERR_BEST'] != 99)] if static_mask: with fits.open(static_mask) as mask_hdu: stat_mask = mask_hdu[0].data table = table[(stat_mask[table['YWIN_IMAGE'].astype(int) - 1, table['XWIN_IMAGE'].astype(int) - 1] != 0)] table.sort('MAG_BEST') table = table[table['MAG_BEST'] < (np.median(table['MAG_BEST']) - np.std(table['MAG_BEST']))] if log: log.info('Total of %d usable stars' % len(table)) #make quads using brightest stars if log: log.info('Making quads with the brightest 50 stars.') ind = list(itertools.combinations(np.arange(4), 2)) stars, d, ds, ratios = make_quads(table['XWIN_IMAGE'], table['YWIN_IMAGE'], use=50) #query gaia if log: log.info( 'Searching GAIA DR3 for stars within 10 arcmins of WCS in header.') Gaia.ROW_LIMIT = -1 job = Gaia.cone_search_async(SkyCoord(ra * u.deg, dec * u.deg, frame='icrs'), 10 * u.arcmin, table_name='gaiaedr3.gaia_source') gaiaorig = job.get_results() gaiaorig.sort('phot_g_mean_mag') if log: log.info(str(len(gaiaorig)) + ' GAIA stars found.') # Mask catalog so all data are inside nominal image if log: log.info('Applying image mask to GAIA sources.') mask = mask_catalog_for_wcs(gaiaorig, wcs.WCS(header), 1, data_x, data_y) gaia = gaiaorig[mask] if log: log.info( str(len(gaia)) + ' GAIA stars found within the image footprint.') #make quads using stars brigher than 20 mag if log: log.info( 'Making quads with the brightest stars brighter than 20 mag and fainter than 14 mag.' ) gaia = gaia[gaia['phot_g_mean_mag'] < 20] gaia = gaia[gaia['phot_g_mean_mag'] > 14] gaiastars, gaiad, gaiads, gaiaratios = make_quads(gaia['ra'], gaia['dec'], use=50, sky_coords=True) #match quads if log: log.info('Matching quads between the detected and cataloged stars.') try: starsx, starsy, gaiastarsra, gaiastarsdec = match_quads( stars, gaiastars, d, gaiad, ds, gaiads, ratios, gaiaratios, sky_coords=True) if log: log.info('Found ' + str(len(starsx)) + ' unique star matches.') #calculate inital transformation if log: log.info( 'Calculating the initial transformation between the matched stars.' ) gaiax, gaiay = wcs.utils.skycoord_to_pixel( SkyCoord(gaiastarsra, gaiastarsdec, unit='deg'), wcs.WCS(header), 1) tform = tf.estimate_transform('euclidean', np.c_[starsx, starsy], np.c_[gaiax, gaiay]) #apply initial transformation to header if log: log.info( 'Applying the initial transformation to the existing WCS in the header.' ) header_new = apply_wcs_transformation(header, tform) except: if log: log.error('Unique star matching failed.') crpix1, crpix2, cd11, cd12, cd21, cd22 = wcs_keyword = tel.WCS_keywords( ) header['CD1_1'] = header[cd11] header['CD1_2'] = header[cd12] header['CD2_1'] = header[cd21] header['CD2_2'] = header[cd22] header['CTYPE1'] = 'RA---TAN' header['CTYPE2'] = 'DEC--TAN' old_keywords = tel.WCS_keywords_old() for old in old_keywords: try: del header[old] except: pass header_new = header #matching all stars to catalog if log: log.info('Matching all stars to the catalog.') stars_ra, stars_dec = (wcs.WCS(header_new)).all_pix2world( table['XWIN_IMAGE'], table['YWIN_IMAGE'], 1) stars_radec = SkyCoord(stars_ra * u.deg, stars_dec * u.deg) gaia_radec = SkyCoord(gaia['ra'], gaia['dec'], unit='deg') idx, d2, d3 = gaia_radec.match_to_catalog_sky(stars_radec) match = d2 < 5.0 * u.arcsec idx = idx[match] starx_match = [table['XWIN_IMAGE'][x] for x in idx] stary_match = [table['YWIN_IMAGE'][x] for x in idx] gaia_radec = SkyCoord(gaia[match]['ra'], gaia[match]['dec'], unit='deg') gaiax_match, gaiay_match = wcs.utils.skycoord_to_pixel( gaia_radec, wcs.WCS(header_new), 1) if log: log.info('Found ' + str(len(starx_match)) + ' star matches within 5".') #calculate and apply full transformation if log: log.info( 'Calculating the full transformation between the matched stars.') tform = tf.estimate_transform('euclidean', np.c_[starx_match, stary_match], np.c_[gaiax_match, gaiay_match]) if log: log.info( 'Applying the full transformation to the existing WCS in the header.' ) header_new['CRPIX1'] = header_new['CRPIX1'] - tform.translation[0] header_new['CRPIX2'] = header_new['CRPIX2'] - tform.translation[1] cd = np.array([ header_new['CD1_1'], header_new['CD1_2'], header_new['CD2_1'], header_new['CD2_2'] ]).reshape(2, 2) cd_matrix = tf.EuclideanTransform(rotation=tform.rotation) cd_transformed = tf.warp(cd, cd_matrix) header_new['CD1_1'] = cd_transformed[0][0] header_new['CD1_2'] = cd_transformed[0][1] header_new['CD2_1'] = cd_transformed[1][0] header_new['CD2_2'] = cd_transformed[1][1] header_new['WCS_REF'] = ('GAIA-DR2', 'Reference catalog for astrometric solution.') header_new['WCS_NUM'] = (len(starx_match), 'Number of stars used for astrometric solution.') #calculate polynomial distortion if log: log.info( 'Calculating and applying the higher order polynomial distortion.') header_dist = apply_wcs_distortion(header_new, starx_match, stary_match, gaia[match]['ra'], gaia[match]['dec']) #calculate error. This error now uses dvrms() instead of np.median. if log: log.info('Calculating the rms on the astrometry.') stars_ra, stars_dec = (wcs.WCS(header_dist)).all_pix2world( starx_match, stary_match, 1) stars_radec = SkyCoord(stars_ra * u.deg, stars_dec * u.deg) error = calculate_error(stars_radec, gaia_radec, header_dist) #write out new fits fits.writeto(input_file.replace('.fits', '_wcs.fits'), data, header_dist, overwrite=True) #end and run time t_end = time.time() if log: log.info('Solve_wcs ran in ' + str(t_end - t_start) + ' sec') else: print('Solve_wcs ran in ' + str(t_end - t_start) + ' sec') return 'Median rms on astrometry is %.3f arcsec.' % error
def draw_fc(fc_params, bk_image=None, bk_lam=None, do_pdf=False, do_png=False): ''' The finding chart master plotting function. Args: fc_params: a dictionnary containing the OB parameters bk_image: the background image as string, either a SkyView entry, or local filename bk_lam: the wavelength of the chart as a string do_pdf (bool): save a pdf file, in addition to jpg do_png (bool): save a png file, in addition to jpg Returns: The finding chart filename as a string ''' # Load all the fields dictionaries fields = fcm_id.get_fields_dict(fc_params) # Get the radius and center of the charts (left_radius, right_radius) = fcm_id.get_chart_radius(fc_params) (left_center, right_center) = fcm_id.get_chart_center(fc_params) # Get the background image in place (fn_bk_image_L, survey_L, bk_lam_L) = get_bk_image(bk_image, bk_lam, left_center, left_radius, fc_params) # If this is not the DSS2 Red, then download this as well for the right-hand-side plot if not (survey_L == 'DSS2 Red'): (fn_bk_image_R, survey_R, bk_lam_R) = get_bk_image('DSS2 Red', None, right_center, right_radius, fc_params) else: (fn_bk_image_R, survey_R, bk_lam_R) = copy.deepcopy( (fn_bk_image_L, survey_L, bk_lam_L)) # Start the plotting plt.close(1) fig1 = plt.figure( 1, figsize=(14.17, 7)) #14.17 inches, at 50% = 1 full page plot in A&A. ax1 = aplpy.FITSFigure(fn_bk_image_L, figure=fig1, north=fcm_m.set_North, subplot=[0.12, 0.12, 0.35, 0.76]) ax1.show_grayscale(invert=True, stretch='linear', pmin=fcm_id.get_pmin(survey_L), pmax=99.9) ax2 = aplpy.FITSFigure(fn_bk_image_R, figure=fig1, north=fcm_m.set_North, subplot=[0.59, 0.12, 0.38, 0.8]) ax2.show_grayscale(invert=True, stretch='linear', pmin=fcm_id.get_pmin(survey_R)) ax1.recenter(left_center.ra, left_center.dec, radius=left_radius / 3600.) ax2.recenter(right_center.ra, right_center.dec, radius=right_radius / 3600.) # I will be adding stuff to the left-hand-side plot ... start collecting them ax1_legend_items = [] # Do I have the epoch of observation for the background image ? ''' try: bk_obsdate = fits.getval(fn_bk_image, 'DATE-OBS') # If not specified, assume UTC time zone for bk image if bk_obsdate.tzinfo is None: # #warnings.warn(' "--obsdate" timezone not specified. Assuming UTC.') bk_obsdate = bk_obsdate.replace(tzinfo=pytz.utc) nowm_time = Time(bk_obsdate) pm_track_time = (fcm_obsdate - bk_obsdate).total_seconds()*u.s except: # If not, just shows the default length set in fcmaker_metadata nowm_time = Time(fcm_m.obsdate) - fcm_m.pm_track_time pm_track_time = fcm_m.pm_track_time ''' # Just keep things simple. Same lookback time for all charts. nowm_time = Time(fcm_m.obsdate) - fcm_m.pm_track_time #pm_track_time = fcm_m.pm_track_time # If yes, then let's show where are the fastest stars moved from/to. #if do_GAIA_pm and (fcm_m.min_abs_GAIA_pm >=0): if (fcm_m.min_abs_GAIA_pm >= 0): # Query GAIA print( ' Querying GAIA DR2 to look for high proper motion stars in the area ...' ) # Make it a sync search, because I don't think I need more than 2000 targets ... # 2020-04: for some reason the sync search fails ... run an async one for now. j = Gaia.cone_search_async(left_center, right_radius * u.arcsec, verbose=False) r = j.get_results() selected = np.sqrt(r['pmra']**2 + r['pmdec']**2 ) * u.mas / u.yr > fcm_m.min_abs_GAIA_pm # Show the fastest stars past_tracks = [] future_tracks = [] # Need to propagate their coords to the fc epoch and the obstime for s in range(len(r['ra'][selected])): star = SkyCoord( ra=r['ra'][selected][s], dec=r['dec'][selected][s], obstime=Time(r['ref_epoch'][selected][s], format='decimalyear'), frame='icrs', unit=(u.deg, u.deg), pm_ra_cosdec=r['pmra'][selected][s] * u.mas / u.yr, pm_dec=r['pmdec'][selected][s] * u.mas / u.yr, # I must specify a generic distance to the target, # if I want to later on propagate the proper motions distance=fcm_m.default_pm_d, ) now = star.apply_space_motion(new_obstime=Time(fcm_m.obsdate)) nowm = star.apply_space_motion(new_obstime=nowm_time) past_tracks += [ np.array([[nowm.ra.deg, now.ra.deg], [nowm.dec.deg, now.dec.deg]]) ] for ax in [ax1, ax2]: ax.show_markers([now.ra.deg], [now.dec.deg], marker='.', color='crimson', facecolor='crimson', edgecolor='crimson') #if len(r['ra'][selected])>0: # # Prepare a dedicated legend entry # ax1_legend_items += [mlines.Line2D([], [],color='crimson', # markerfacecolor='crimson', # markeredgecolor='crimson', # linestyle='-', # linewidth=0.75, # marker='.', # #markersize=10, # label='PM* (track$=-$%.1f yr)' % (pm_track_time.to(u.yr).value)) ] for ax in [ax1, ax2]: ax.show_lines(past_tracks, color='crimson', linewidth=0.75, linestyle='-') # Query UCAC2 via Vizier over the finding chart area, to look for suitable Guide Stars print(' Querying UCAC2 via Vizier to look for possible Guide Stars ...') Vizier.ROW_LIMIT = 10000 gs_table = Vizier.query_region( right_center, radius=right_radius * u.arcsec, inner_radius=fcm_id.get_inner_GS_search(fc_params) * u.arcsec, catalog="UCAC2") gs_table = gs_table[gs_table.keys()[0]] # Turn the table into a list of SkyCoord, that I can clean as I go. # Only select guide stars in the nominal GS mag range gs_list = [ SkyCoord( ra=line['RAJ2000'], dec=line['DEJ2000'], obstime=Time('J2000'), equinox='J2000', frame='icrs', unit=(u.deg, u.deg), pm_ra_cosdec=line['pmRA'] / 1000. * u.mas / u.yr, pm_dec=line['pmDE'] / 1000. * u.mas / u.yr, # Assume a fixed distance, so that I can then propagate proper motions distance=100. * u.pc).apply_space_motion(new_obstime=Time(fcm_m.obsdate)) for line in gs_table if fcm_m.gs_mag[0] <= line['UCmag'] <= fcm_m.gs_mag[1] ] # Here, I will show all the ephemeris points I have prepared, ahead of the # observations (If I have any) if len(fc_params['ephem_points_past']) > 0: ax1.show_markers( [item.ra.deg for item in fc_params['ephem_points_past']], [item.dec.deg for item in fc_params['ephem_points_past']], marker='*', color='crimson', s=100, facecolor='none', edgecolor='crimson') # Prepare a dedicated legend entry ax1_legend_items += [ mlines.Line2D( [], [], color='crimson', markerfacecolor='none', markeredgecolor='crimson', linestyle='', #linewidth=0.75, marker='*', #markersize=10, label='Target ($\Delta T=-%.0f$ min)' % (fc_params['ephem_past_delta'].total_seconds() / 60.)) ] if len(fc_params['ephem_points_future']) > 0: ax1.show_markers( [item.ra.deg for item in fc_params['ephem_points_future']], [item.dec.deg for item in fc_params['ephem_points_future']], marker='*', color='crimson', s=100, facecolor='crimson', edgecolor='crimson') # Prepare a dedicated legend entry ax1_legend_items += [ mlines.Line2D( [], [], color='crimson', markerfacecolor='crimson', markeredgecolor='crimson', linestyle='', #linewidth=0.75, marker='*', #markersize=10, label='Target ($\Delta T=+%.0f$ min)' % (fc_params['ephem_future_delta'].total_seconds() / 60.)) ] # Show the observation footprint for f in fields: # Call the function that will plot all the important stuff for this field. fcm_id.plot_field(ax1, ax2, fc_params, fields[f]) # Keep all the possible guide stars in the area. gs_list = [ star for star in gs_list if (fields[f][2].separation(star) > (fcm_id.get_inner_GS_search(fc_params) / 3600. * u.deg)) and ( fields[f][2].separation(star) < (fcm_id.get_GS_outer_radius(fc_params) / 3600. * u.deg)) ] # Show all the suitable Guide Star in the area if len(gs_list) > 0: ax2.show_markers([np.array(star.ra) for star in gs_list], [np.array(star.dec) for star in gs_list], marker='o', edgecolor='crimson', s=50, linewidth=1.0) else: warnings.warn('Watch out ... no suitable Guide Star found in UCAC2 !') # Add orientation arrows to the large view plot add_orient(ax2, right_center, radius=(right_radius * 0.82) * u.arcsec, arrow_width=(right_radius * 0.82) / 4.5 * u.arcsec, usetex=fcm_m.fcm_usetex) add_orient(ax1, left_center, radius=(left_radius * 0.82) * u.arcsec, arrow_width=(left_radius * 0.82) / 4.5 * u.arcsec, usetex=fcm_m.fcm_usetex) # Add a scale bar (scl, scll) = fcm_id.get_scalebar(fc_params['inst'], ins_mode=fc_params['ins_mode']) ax1.add_scalebar(scl) # Length in degrees ax1.scalebar.show(scl, label=scll, corner='bottom left', color='k', frame=1) ax1.scalebar.set_font_size(12) scl2 = np.floor(right_radius / 60 / 6) / 60. scll2 = r'%.0f$^{\prime}$' % (scl2 * 60) ax2.add_scalebar(scl2) ax2.scalebar.show(scl2, label=scll2, corner='bottom left', color='k', frame=1) ax2.scalebar.set_font_size(12) for ax in [ax1, ax2]: ax.scalebar.set_linewidth(2) # Fine tune things a bit further, just because I can ... for ax in [ax1, ax2]: ax.tick_labels.set_xformat('hh:mm:ss') ax.axis_labels.set_xpad(10) ax.ticks.set_linewidth(1.5) ax.ticks.set_length(10) ax.ticks.set_color('k') ax.axis_labels.set_xtext('R.A. [J2000]') ax1.axis_labels.set_ytext('Dec. [J2000]') #ax1.axis_labels.set_ypad(-10) ax2.axis_labels.set_ytext(' ') # Add the required OB information to comply with ESO requirements ... # ... and make the life of the night astronomer a lot easier ! ax1.add_label(0.0, 1.11, 'Run ID: ' + fc_params['prog_id'] + ' | ' + fc_params['pi'], relative=True, horizontalalignment='left', size=14) # Fix some bugs for anyone not using LaTeX ... sigh ... if fcm_m.fcm_usetex: lab = fc_params['ob_name'].replace('_', '\_') else: lab = fc_params['ob_name'] ax1.add_label(0.0, 1.06, 'OB: %i | %s' % (fc_params['ob_id'], lab), relative=True, horizontalalignment='left', size=14) #ax1.add_label(0.0,1.08, r'$\lambda_{fc}$: %s (%s)' % (bk_lam_L, survey_L), relative=True, # horizontalalignment='left') # Display the Wavelength of the plots ax1.add_label(0.02, 0.965, r'%s (%s)' % (bk_lam_L, survey_L), relative=True, fontsize=12, horizontalalignment='left', verticalalignment='center', bbox=dict(edgecolor='w', facecolor='w', alpha=0.85)) ax2.add_label(0.02, 0.965, r'%s (%s)' % (bk_lam_R, survey_R), relative=True, fontsize=12, horizontalalignment='left', verticalalignment='center', bbox=dict(edgecolor='w', facecolor='w', alpha=0.85)) # Add a legend (if warranted) for the left plot if len(ax1_legend_items) > 0: ax1.ax.legend( handles=ax1_legend_items, bbox_to_anchor=(-0.03, 0.82, 0.4, .1), #loc='lower right', ncol=1, #mode="expand", borderaxespad=0., fontsize=10, borderpad=0.3, handletextpad=0., handlelength=2.0) # Start keeping track of any tags I need to show tag_string = r' ' # Show the obsdate ax1.add_label(1.0, 1.02, r'Date: ' + datetime.strftime(fcm_m.obsdate, '%Y-%m-%d %H:%M %Z'), relative=True, color='k', horizontalalignment='right', fontsize=10) # Show the OB tags if 'moving_target' in fc_params['tags']: tag_string += '$\leadsto$ ' if 'parallactic_angle' in fc_params['tags']: tag_string += '$\measuredangle$ ' if len(tag_string) > 1: # only show the tag if it has a non-zero length ax1.add_label( -0.18, 1.08, tag_string, relative=True, color='k', horizontalalignment='center', verticalalignment='center', fontsize=30, bbox=dict(edgecolor='k', facecolor='lightsalmon', alpha=1, linewidth=1, boxstyle="sawtooth,pad=0.2,tooth_size=0.075"), ) # Finally include the version of fcmaker in there ax1.add_label(1.01, 0.00, r'Created with fcmaker v%s' % (fcm_v.__version__), relative=True, horizontalalignment='left', verticalalignment='bottom', fontsize=10, rotation=90) # Save it all, both jpg for upload to p2, and pdf for nice quality. fn_out = os.path.join( fcm_m.plot_loc, fc_params['ob_name'].replace(' ', '_') + '_' + survey_L.replace(' ', '-')) fig1.savefig(fn_out + '.jpg') if do_pdf: fig1.savefig(fn_out + '.pdf') if do_png: fig1.savefig(fn_out + '.png') plt.close() return fn_out + '.jpg'
def querycat_gaia(ralist=None, declist=None, cone_search=False, width=10.0, height=10.0, radius=5.0, dr2=False, test=False, debug=False): """ """ import time from astropy.table import Table, vstack import astropy.units as u from astropy.coordinates import SkyCoord from astroquery.gaia import Gaia if dr2: help(Gaia) gaiadr2_table = Gaia.load_table('gaiadr2.gaia_source') for column in (gaiadr1_table.get_columns()): print(column.get_name()) if debug: help(Gaia) width = u.Quantity(width/3600.0, u.degree) height = u.Quantity(height/3600.0, u.degree) radius = u.Quantity(radius/3600.0, u.degree) if test is True: ralist = [180.0] declist = [0.0] width = u.Quantity(30.0, u.arcsec) height = u.Quantity(30.0, u.arcsec) radius = u.Quantity(15.0, u.arcsec) result_nrows = 0 for isource, (ra, dec) in enumerate(zip(ralist, declist)): coord = SkyCoord(ra=ra, dec=dec, unit=(u.degree, u.degree), frame='icrs') t0 = time.time() if not cone_search: result = Gaia.query_object_async(coordinate=coord, width=width, height=height) # help(result) if debug: result.pprint() result.info('stats') if cone_search: job = Gaia.cone_search_async(coord, radius) # help(job) result = job.get_results() print('Number of rows:', len(result)) print('Elapsed time(secs):',time.time() - t0) if debug: help(result) result.pprint() result.info('stats') result_nrows = result_nrows + len(result) if isource == 0: result_all = result if isource > 0: result_all = vstack([result_all, result]) #def fix_vot_object(): table = result_all print('icol, format, dtype') # help(table) # help(table.columns) for (icol, column) in enumerate(table.columns): print(icol, table.columns[icol].name, table.columns[icol].format, table.columns[icol].dtype) # convert the columns for dtype = object which is not # supported by FITs to bool if table.columns[icol].dtype == 'object': colname = table.columns[icol].name NewColumn = Table.Column(table[colname].data, dtype='bool') table.replace_column(colname, NewColumn) print() result_all = table print('Number of Gaia sources returned:', result_nrows, len(result_all)) return result_all
from cleaner import cleaner omask = cleaner(lkf.time, lkf.flux) ntime = lkf.time.value[~omask] nflux = lkf.flux.value[~omask] nflux_err = lkf.flux_err.value[~omask] lkf = TessLightCurve(time=ntime, flux=nflux, flux_err=nflux_err) #Gaia sources and dilution factor if args.gaia: from astroquery.gaia import Gaia Gaia.ROW_LIMIT = -1 gaiawh = u.Quantity(21*args.size*np.sqrt(2)/2, u.arcsec) gaiar = Gaia.cone_search_async(coord, gaiawh).get_results() #gaiar = Gaia.query_object_async(coord, width=gaiawh, height=gaiawh) gma = gaiar['phot_rp_mean_mag'] < args.maxgaiamag*u.mag gra, gdec = gaiar['ra'][gma], gaiar['dec'][gma] grpmag = gaiar['phot_rp_mean_mag'][gma] gsep = gaiar['dist'][gma]*3600 gaiar = gaiar[gma] #Come back to origin (0,0) for a while goffsetx = column if args.folder is not None else 0 goffsety = row if args.folder is not None else 0 go = 0 if args.folder is None else 1 gx, gy = w.all_world2pix(gra, gdec, go) + (np.ones(2)*.5)[:,None]
def do_gaia_match(df): # first, crossmatch against SIMBAD to get the coordinates starnames = nparr(df['star']) for ix, s in enumerate(starnames): # manual string subbing for simbad query if 'Qatar' in s: starnames[ix] = s.replace('-', ' ') if s == 'WASP-70A': starnames[ix] = s.rstrip('A') ras, decs = [], [] print('running SIMBAD query...') for ix, starname in enumerate(starnames): print(ix, starname) result = Simbad.query_object(starname) if len(result) != 1: raise AssertionError ras.append(result['RA'].tolist()[0]) decs.append(result['DEC'].tolist()[0]) ras = np.array(ras) decs = np.array(decs) coords = SkyCoord(ras, decs, frame='icrs', unit=(u.hourangle, u.deg)) # then, crossmatch against Gaia to get the absolute G mags radius = units.Quantity(2, units.arcsec) sep, gaia_id, parallax, gmag, dr2_teff, dr2_radius, dr2_lum, distance = ( [], [], [], [], [], [], [], []) print('running Gaia query...') for ix, sysname, coord in zip(range(len(coords)), nparr(df['star']), coords): print('{:d}/{:d} --- {:s}'.format(ix, len(coords), sysname)) j = Gaia.cone_search_async(coord, radius) r = j.get_results() if len(r) == 0: print('\tno match, skipping') for l in [ sep, gaia_id, parallax, gmag, dr2_teff, dr2_radius, dr2_lum, distance ]: l.append(np.nan) continue if len(r) > 1: print('\tmatched {:d} within 2arcsec, skipping'.format(len(r))) for l in [ sep, gaia_id, parallax, gmag, dr2_teff, dr2_radius, dr2_lum, distance ]: l.append(np.nan) continue sep.append(float((r['dist'] * units.deg).to(units.arcsec).value)) gaia_id.append(int(r['source_id'])) plx = float(r['parallax'] * 1e-3) parallax.append(plx) distance.append(1 / plx) gmag.append(float(r['phot_g_mean_mag'])) dr2_teff.append(float(r['teff_val'])) dr2_radius.append(float(r['radius_val'])) dr2_lum.append(float(r['lum_val'])) sep, gaia_id, parallax, gmag, dr2_teff, dr2_radius, dr2_lum, distance = ( nparr(sep), nparr(gaia_id), nparr(parallax), nparr(gmag), nparr(dr2_teff), nparr(dr2_radius), nparr(dr2_lum), nparr(distance)) df['sep'] = sep df['gaia_id'] = gaia_id df['parallax'] = parallax df['gmag'] = gmag df['dr2_teff'] = dr2_teff df['dr2_radius'] = dr2_radius df['dr2_lum'] = dr2_lum df['distance'] = distance savname = '../data/bonomo_HJs_plus_DR2.csv' df.to_csv(savname, index=False) print('made {}'.format(savname))