def get_gaiadr3_dist(gaiadr2, gaia3): #vqdr3 = Vizier(columns=['Source','Plx','e_Plx', 'FG','e_FG','Gmag','e_Gmag', 'BPmag','e_BPmag', 'RPmag','e_RPmag', 'o_Gmag'], row_limit=5000) vqdr3_dist = Vizier(row_limit=5000) radius_search = 10.0 * u.arcsec try: #result_gaia_vizier_dr3=vqdr3.query_object("Gaia DR2 "+str(gaiadr2), catalog=["I/350/gaiaedr3"], radius=radius_search) result_dist = vqdr3_dist.query_object("Gaia DR2 " + str(gaiadr2), catalog=["I/352/gedr3dis"], radius=radius_search) #iline = np.where(result_gaia_vizier_dr3[0]['Source'] == int(gaia3))[0][0] #print(result_gaia_vizier_dr3[0]['Source','Plx','e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag'][iline]) # std_g_flux_norm1_v = result_gaia_vizier_dr3[0]['e_FG'][iline]*np.sqrt(result_gaia_vizier_dr3[0]['o_Gmag'][iline])/result_gaia_vizier_dr3[0]['FG'][iline] iline_d = np.where(result_dist[0]['Source'] == int(gaia3))[0][0] #print(result_dist[0]['Source','rgeo', 'rpgeo'][iline_d]) except: try: #result_gaia_vizier_dr3=vqdr3.query_object("Gaia DR2 "+str(gaiadr2), catalog=["I/350/gaiaedr3"], radius=100*radius_search) result_dist = vqdr3_dist.query_object("Gaia DR2 " + str(gaiadr2), catalog=["I/352/gedr3dis"], radius=20 * radius_search) #iline = np.where(result_gaia_vizier_dr3[0]['Source'] == int(gaia3))[0][0] iline_d = np.where(result_dist[0]['Source'] == int(gaia3))[0][0] except: print("problem") return -1, -1, -1, -1 #print("Ilines:", iline, iline_d) rgeo = result_dist[0][iline_d]["rgeo"] b_rgeo = result_dist[0][iline_d]["b_rgeo"] B_rgeo = result_dist[0][iline_d]["B_rgeo"] ergeo = np.max([rgeo - b_rgeo, B_rgeo - rgeo]) rpgeo = result_dist[0][iline_d]["rgeo"] b_rpgeo = result_dist[0][iline_d]["b_rpgeo"] B_rpgeo = result_dist[0][iline_d]["B_rpgeo"] erpgeo = np.max([rpgeo - b_rpgeo, B_rpgeo - rpgeo]) return rgeo, ergeo, rpgeo, erpgeo
def get_gaia_dr2_paralax(filename = 'gaiadr2/gaiaid_sc.rdb', fileout= 'gaiadr2/tmp.rdb', append= True): if os.path.isfile(fileout): filetmp = open(fileout,"r") strlines = filetmp.readlines() filetmp.close() name_tmp, gaiaid_tmp = np.loadtxt(fileout, unpack=True,usecols=(0,1), skiprows=2, delimiter="\t", dtype=str) else: print("Fresh start") gaiaid_tmp = [] strlines = ['name\tgaia_id\tPlx\te_Plx\tGmag\te_Gmag\tRPmag\te_RPmag\tBPmag\te_BPmag\tFG\te_FG\tG_flux_std_n\n'] strlines.append('----\t-------\t---\t-----\t----\t------\t-----\t-------\t-----\t-------\t--\t----\t------------\n') print("Result GAIA vizier") vq2 = Vizier(columns=['Source','Plx','e_Plx', 'FG','e_FG','Gmag','e_Gmag', 'BPmag','e_BPmag', 'RPmag','e_RPmag', 'o_Gmag'], row_limit=5000) name, gaia_id = np.loadtxt(filename, unpack=True, usecols=(0,1), skiprows=2, delimiter="\t", dtype=str) radius_search = 10.0*u.arcsec #ist = 3127 # for i,gaiadr2 in enumerate(gaia_id[ist:]): #i += ist for i,gaiadr2 in enumerate(gaia_id): print(i, len(gaia_id), name[i], gaiadr2) if gaiadr2 in gaiaid_tmp and name[i] in name_tmp: print("This one already in place") continue if gaiadr2 == "-1": print(name[i], "No gaia id dr2") strlines.append('%s\t%s\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n' % (name[i], gaiadr2)) else: result_gaia_vizier=vq2.query_object("Gaia DR2 "+str(gaiadr2), catalog=["I/345/gaia2"], radius=radius_search*15.) try: iline = np.where(result_gaia_vizier[0]['Source'] == int(gaiadr2))[0][0] print(result_gaia_vizier[0]['Source','Plx','e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag'][iline]) std_g_flux_norm1_v = result_gaia_vizier[0]['e_FG'][iline]*np.sqrt(result_gaia_vizier[0]['o_Gmag'][iline])/result_gaia_vizier[0]['FG'][iline] except IndexError: result_gaia_vizier=vq2.query_object("Gaia DR2 "+str(gaiadr2), catalog=["I/345/gaia2"], radius=radius_search*25.) try: iline = np.where(result_gaia_vizier[0]['Source'] == int(gaiadr2))[0][0] print(result_gaia_vizier[0]['Source','Plx','e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag'][iline]) std_g_flux_norm1_v = result_gaia_vizier[0]['e_FG'][iline]*np.sqrt(result_gaia_vizier[0]['o_Gmag'][iline])/result_gaia_vizier[0]['FG'][iline] except IndexError: result_gaia_vizier = [Table( [[-1], [-1],[-1], [-1] ,[-1], [-1] ,[-1] ,[-1] ,[-1] , [-1] ] , names=('Plx','e_Plx','Gmag','e_Gmag','FG','e_FG','RPmag','e_RPmag','BPmag','e_BPmag')) ] std_g_flux_norm1_v = -1 iline=0 print("Iline2:", iline) strlines.append('%s\t%s\t%7.4f\t%7.4f\t%7.4f\t%7.4f\t%7.4f\t%7.4f\t%7.4f\t%7.4f\t%.3e\t%.3e\t%10.7f\n' % (name[i], gaiadr2, result_gaia_vizier[0]['Plx'][iline], result_gaia_vizier[0]['e_Plx'][iline], result_gaia_vizier[0]['Gmag'][iline], result_gaia_vizier[0]['e_Gmag'][iline], result_gaia_vizier[0]['RPmag'][iline], result_gaia_vizier[0]['e_RPmag'][iline], result_gaia_vizier[0]['BPmag'][iline], result_gaia_vizier[0]['e_BPmag'][iline], result_gaia_vizier[0]['FG'][iline], result_gaia_vizier[0]['e_FG'][iline], std_g_flux_norm1_v)) print(strlines[-1]) fileo = open('gaiadr2/tmp2.rdb', "w") for line in strlines: fileo.write(line) fileo.close()
def get_gaiadr3_data(gaiadr2, gaia3, name_search=None): vq2 = Vizier(columns=[ 'Source', 'Plx', 'e_Plx', 'FG', 'e_FG', 'Gmag', 'e_Gmag', 'BPmag', 'e_BPmag', 'RPmag', 'e_RPmag', 'o_Gmag' ], row_limit=5000) radius_search = 10.0 * u.arcsec if name_search is None: result_gaia_vizier_dr3 = vq2.query_object("Gaia DR2 " + str(gaiadr2), catalog=["I/350/gaiaedr3"], radius=radius_search * 15.) else: result_gaia_vizier_dr3 = vq2.query_object(name_search, catalog=["I/350/gaiaedr3"], radius=radius_search * 15.) try: iline3 = np.where( result_gaia_vizier_dr3[0]['Source'] == int(gaia3))[0][0] print(result_gaia_vizier_dr3[0]['Source', 'Plx', 'e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag'][iline3]) std_g_flux_norm1_v = result_gaia_vizier_dr3[0]['e_FG'][ iline3] * np.sqrt(result_gaia_vizier_dr3[0]['o_Gmag'][iline3] ) / result_gaia_vizier_dr3[0]['FG'][iline3] except IndexError: result_gaia_vizier_dr3 = vq2.query_object("Gaia DR2 " + str(gaiadr2), catalog=["I/350/gaiaedr3"], radius=radius_search * 25.) try: iline3 = np.where( result_gaia_vizier_dr3[0]['Source'] == int(gaia3))[0][0] print(result_gaia_vizier_dr3[0]['Source', 'Plx', 'e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag'][iline3]) std_g_flux_norm1_v = result_gaia_vizier_dr3[0]['e_FG'][ iline3] * np.sqrt(result_gaia_vizier_dr3[0]['o_Gmag'][iline3] ) / result_gaia_vizier_dr3[0]['FG'][iline3] except IndexError: result_gaia_vizier_dr3 = Table( [[-1], [-1], [-1], [-1], [-1], [-1], [-1], [-1], [-1], [-1]], names=('Plx', 'e_Plx', 'Gmag', 'e_Gmag', 'FG', 'e_FG', 'RPmag', 'e_RPmag', 'BPmag', 'e_BPmag')) return result_gaia_vizier_dr3, -1 print("Iline2:", iline3) print(result_gaia_vizier_dr3) return result_gaia_vizier_dr3[0][iline3], std_g_flux_norm1_v
def get_parallax(objectname, radius=5): v_gaia = Vizier(columns=[ "Plx", "e_Plx", '+_r', 'Gmag', 'nueff', 'pscol', 'ELAT', 'Solved' ]) data = v_gaia.query_object(objectname, catalog=['I/350/gaiaedr3'], radius=radius * u.arcsec) if len(data) == 0: return None, None data = data['I/350/gaiaedr3'][0] plx, plx_e = data['Plx'], data['e_Plx'] if not data['pscol']: data['pscol'] = 0 # apply parallax zero point correction of Lindgren. If not possible, use the average offset. # https://arxiv.org/pdf/2012.01742.pdf # https://gitlab.com/icc-ub/public/gaiadr3_zeropoint try: zp = zpt.get_zpt(data['Gmag'], data['nueff'], data['pscol'], data['ELAT'], data['Solved']) except Exception: warnings.warn( "Could not calculate the parallax zero point offset based on Lindgren+2020, using average" ) zp = 0.02 plx -= zp return plx, plx_e
def get_inclination(self): """ This function ... :return: """ # Inform the user log.info( "Querying the catalog of radial profiles for 161 face-on spirals ..." ) # The Vizier querying object vizier = Vizier() vizier.ROW_LIMIT = -1 # Radial profiles for 161 face-on spirals (Munoz-Mateos+, 2007) radial_profiles_result = vizier.query_object(self.galaxy_name, catalog="J/ApJ/658/1006") # Catalog doesnt contain data for a lot of galaxies # If it doesnt, use DustPedia galaxy info as a backup solution if len(radial_profiles_result) == 0 or len( radial_profiles_result[0]) == 0: inclination = Angle(self.info["Inclination"][0], "deg") # We have a table and it is not empty else: table = radial_profiles_result[0] # distance = float(table[0]["Dist"]) inclination = Angle(float(table[0]["i"]), "deg") # Set the inclination self.properties.inclination = inclination
def get_hip(name): """ Given a star's Bayer designation, queries VizieR and attempts to locate a Hipparcos star ID at the location. Returns an integer HIP ID if found, or None otherwise Maintains a .hip_cache_stars file to speed up lookups; you can delete the .hip_cache_stars file to perform fresh lookups. """ # Search the Hipparcos catalog, and only return results that include # a HIP (Hipparcos) column, sorting the results by magnitude. The # top result is almost certainly the star we want. v = Vizier(catalog='I/239/hip_main', columns=["HIP", "+Vmag"]) try: result = v.query_object(name) except EOFError: # if we get no results we might get an EOFError return None try: table = result['I/239/hip_main'] except TypeError: # A TypeError means that the results didn't include anything from # the I/239/hip_main catalog. The "in" operator doesn't seem to # work with Table objects. return None else: return table['HIP'][0]
def request_vizier(hd_identifiers): v = Vizier(columns=['Vmag', 'b-y', 'm1', 'c1', 'Beta'], catalog="II/215/catalog") big_table_hd = Table(names=('Vmag', 'b-y', 'm1', 'c1', 'Beta')) for hd_object in hd_identifiers: print(str(hd_object)) hd_object = str(hd_object).strip() if not hd_object or hd_object == "NaN": #If string is empty then: or hd_object== 'NaN' big_table_hd.add_row([np.nan, np.nan, np.nan, np.nan, np.nan]) else: try: result = v.query_object(hd_object)[0][0] except IndexError: # This handles if HD identifier does not exist in the catalog big_table_hd.add_row([np.nan, np.nan, np.nan, np.nan, np.nan]) else: big_table_hd = vstack([big_table_hd, result], join_type='outer', metadata_conflicts='silent') df_0 = big_table_hd.to_pandas() return df_0
def get_ucac4_id_as_dataframe(object_name): result = Vizier.query_object(object_name, catalog=['I/322A']) if len(result) == 0: logging.warning(f"Returned result from vizier for object {object_name} is empty.") df = result[0].to_pandas() df2 = df.loc[df['UCAC4'] == object_name.split()[1].encode('UTF-8')] return df2
def get_wcs(pattern): for filename in pattern: which_hdu = choose_hdu(filename) header = fits.getheader(filename, which_hdu) data = fits.getdata(filename, ext=0) threshold = detect_threshold(data, nsigma=2.) sigma = 3.0 * gaussian_fwhm_to_sigma # FWHM = 3. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() mean, median, std = sigma_clipped_stats(data, sigma=3) daofind = DAOStarFinder(fwhm=3.0, threshold=5. * std) sources = daofind(data - median) for col in sources.colnames: sources[col].info.format = '%.8g' # for consistent table output x = np.array(sources['xcentroid']) y = np.array(sources['ycentroid']) OB = header['OBJECT'] cobj = SkyCoord.from_name(OB, parse=True) cobjx = cobj.ra.degree cobjy = cobj.dec.degree refx = x[1] refy = y[1] Bin = float(header['CCDSUM'][0]) Res = 0.25 #arcsec/px f_arcsec = Bin * Res #arcsec/px f = f_arcsec / 3600 for n in x: dx = x - refx xscal = cobjx + (f * dx) for n in y: dy = y - refy yscal = cobjy + (f * dy) fig1, ax = plt.subplots() c1 = SkyCoord(ra=xscal * u.degree, dec=yscal * u.degree) # ra and dec of each source ax.plot(xscal, yscal, 'ok', ms=5) result = Vizier.query_object(OB) interesting_table = result['I/305/out'] x1 = np.array(interesting_table['RAJ2000']) y1 = np.array(interesting_table['DEJ2000']) c2 = SkyCoord(ra=x1 * u.degree, dec=y1 * u.degree) fig2, ax = plt.subplots() ax.plot(x1, y1, 'or', mfc='none', ms=10) idx, d2d, d3d = c1.match_to_catalog_sky(c2) fig3, ax = plt.subplots() ax.plot(xscal, yscal, 'ok', ms=5) ax.plot(x1, y1, 'or', mfc='none', ms=10) plt.show() dx, d2d, d3d = c1.match_to_catalog_sky(c2)
def showVizierCatalogs(name): from astroquery.vizier import Vizier Vizier.ROW_LIMIT = 50 from astropy import coordinates from astropy import units as u c = coordinates.SkyCoord(ra, dec, unit=('deg', 'deg'), frame='icrs') results = Vizier.query_object(name) return results
def vizierLocationForTarget(exp, target, doMotionCorrection): """Get the target location from Vizier optionally correction motion. Parameters ---------- target : `str` The name of the target, e.g. 'HD 55852' Returns ------- targetLocation : `lsst.geom.SpherePoint` or `None` Location of the target object, optionally corrected for proper motion and parallax. Raises ------ ValueError If object not found in Hipparcos2 via Vizier. This is quite common, even for bright objects. """ # do not import at the module level - tests crash due to a race # condition with directory creation from astroquery.vizier import Vizier result = Vizier.query_object( target) # result is an empty table list for an unknown target try: star = result['I/311/hip2'] except TypeError: # if 'I/311/hip2' not in result (result doesn't allow easy checking without a try) raise ValueError epoch = "J1991.25" coord = SkyCoord( ra=star[0]['RArad'] * u.Unit(star['RArad'].unit), dec=star[0]['DErad'] * u.Unit(star['DErad'].unit), obstime=epoch, pm_ra_cosdec=star[0]['pmRA'] * u.Unit(star['pmRA'].unit), # NB contains cosdec already pm_dec=star[0]['pmDE'] * u.Unit(star['pmDE'].unit), distance=Distance(parallax=star[0]['Plx'] * u.Unit(star['Plx'].unit))) if doMotionCorrection: expDate = exp.getInfo().getVisitInfo().getDate() obsTime = astropy.time.Time(expDate.get(expDate.EPOCH), format='jyear', scale='tai') newCoord = coord.apply_space_motion(new_obstime=obsTime) else: newCoord = coord raRad, decRad = newCoord.ra.rad, newCoord.dec.rad ra = geom.Angle(raRad) dec = geom.Angle(decRad) targetLocation = geom.SpherePoint(ra, dec) return targetLocation
def test_query_target_error(self): jwst = JwstClass(show_messages=False) simbad = Simbad() ned = Ned() vizier = Vizier() # Testing default parameters with pytest.raises(ValueError) as err: jwst.query_target(target_name="M1", target_resolver="") assert "This target resolver is not allowed" in err.value.args[0] with pytest.raises(ValueError) as err: jwst.query_target("TEST") assert "This target name cannot be determined with this resolver: ALL" in err.value.args[ 0] with pytest.raises(ValueError) as err: jwst.query_target(target_name="M1", target_resolver="ALL") assert err.value.args[0] in [ f"This target name cannot be determined " f"with this resolver: ALL", "Missing " f"required argument: 'width'" ] # Testing no valid coordinates from resolvers simbad_file = data_path( 'test_query_by_target_name_simbad_ned_error.vot') simbad_table = Table.read(simbad_file) simbad.query_object = MagicMock(return_value=simbad_table) ned_file = data_path('test_query_by_target_name_simbad_ned_error.vot') ned_table = Table.read(ned_file) ned.query_object = MagicMock(return_value=ned_table) vizier_file = data_path('test_query_by_target_name_vizier_error.vot') vizier_table = Table.read(vizier_file) vizier.query_object = MagicMock(return_value=vizier_table) # coordinate_error = 'coordinate must be either a string or astropy.coordinates' with pytest.raises(ValueError) as err: jwst.query_target(target_name="test", target_resolver="SIMBAD", radius=units.Quantity(5, units.deg)) assert 'This target name cannot be determined with this resolver: SIMBAD' in err.value.args[ 0] with pytest.raises(ValueError) as err: jwst.query_target(target_name="test", target_resolver="NED", radius=units.Quantity(5, units.deg)) assert 'This target name cannot be determined with this resolver: NED' in err.value.args[ 0] with pytest.raises(ValueError) as err: jwst.query_target(target_name="test", target_resolver="VIZIER", radius=units.Quantity(5, units.deg)) assert 'This target name cannot be determined with this resolver: VIZIER' in err.value.args[ 0]
def getVizierResults(name, radius): from astroquery.vizier import Vizier from astropy import units as u v = Vizier(columns=["all"], catalog='I/345/gaia2') v.ROW_LIMIT = 25000 results = v.query_object(name, catalog='I/345/gaia2', radius=radius * u.arcsec) keys = results[0].keys() objectList = gaiaClass.GAIAObjects(gaiaTable=results[0]) return objectList
def get_s4g_properties(self): """ This function ... :return: """ # Inform the user log.info("Querying the S4G catalog ...") # The Vizier querying object vizier = Vizier(columns=[ 'Name', 'RAJ2000', 'DEJ2000', 'amaj', 'ell', 'Dmean', "e_Dmean", "PA" ]) vizier.ROW_LIMIT = -1 # Get parameters from S4G catalog result = vizier.query_object(self.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Galaxy name for S4G catalog self.properties.name = table["Name"][0] # Galaxy center from decomposition (?) ra_center = table["RAJ2000"][0] dec_center = table["DEJ2000"][0] center = SkyCoordinate(ra=ra_center, dec=dec_center, unit="deg", frame='fk5') self.properties.center = center # Center position #self.properties.center = SkyCoordinate(ra=self.info["RA"][0], dec=self.info["DEC"][0], unit="deg") # center position from DustPedia # Distance self.properties.distance = table["Dmean"][0] * u("Mpc") self.properties.distance_error = table["e_Dmean"][0] * u("Mpc") # Major axis, ellipticity, position angle self.properties.major_arcsec = table["amaj"][0] * u("arcsec") self.properties.major = (self.properties.distance * self.properties.major_arcsec).to( "pc", equivalencies=dimensionless_angles()) # Ellipticity self.properties.ellipticity = table["ell"][0] self.properties.position_angle = Angle(table["PA"][0] + 90.0, u("deg"))
def get_galaxy_s4g_one_component_info(name): """ This function ... :param name: :return: """ # The Vizier querying object vizier = Vizier() vizier.ROW_LIMIT = -1 # Get the "galaxies" table result = vizier.query_object(name, catalog=["J/ApJS/219/4/galaxies"]) # No results? if len(result) == 0: return None, None, None, None, None, None # Get table table = result[0] # PA: [0.2/180] Outer isophote position angle # e_PA: [0/63] Standard deviation in PA # Ell: [0.008/1] Outer isophote ellipticity # e_Ell: [0/0.3] Standard deviation in Ell # PA1: Elliptical isophote position angle in deg # n: Sersic index # Re: effective radius in arcsec # Tmag: total magnitude s4g_name = table["Name"][0] pa = Angle(table["PA"][0] - 90., "deg") pa_error = Angle(table["e_PA"][0], "deg") ellipticity = table["Ell"][0] ellipticity_error = table["e_Ell"][0] n = table["n"][0] re = table["Re"][0] * u("arcsec") mag = table["Tmag"][0] # Return the results return s4g_name, pa, ellipticity, n, re, mag
def strom_phot(star): from astroquery.vizier import Vizier import numpy as np import os EP2015_stromgren = Vizier(catalog="J/A+A/580/A23") result = EP2015_stromgren.query_object(star) #print result if not result: return 0 #print result[0].keys() by = result[0]["b-y"][0] c1 = result[0]["c1"][0] m1 = result[0]["m1"][0] beta = result[0]["beta"][0] if not beta: return 0 if (2.72 < beta < 2.88) & (0.05 < by < 0.22): n = 6 elif (2.87 < beta < 2.93) & (-0.01 < by < 0.06): n = 5 elif (2.60 < beta < 2.72) & (0.22 < by < 0.39): n = 7 elif (0.02 < m1 < 0.76) & (0.39 < by < 1.00): n = 8 else: n = 6 with open("starParam.pro", "wb") as idl_code: idl_code.write("uvbybeta," + str(by) + ',' + str(m1) + ',' + str(c1) + ',' + str(beta) + ',' + str(n) + ',Teff\n') idl_code.write("print,'readline: ',Teff") os.system("nohup nice $IDL_DIR/bin/idl < starParam.pro > idlout.txt") idl_output = open("idlout.txt", "rb") out = idl_output.readlines() temp = np.float(out[-1][9:]) return temp
def getUniqueVizierResult(name, radius): from astroquery.vizier import Vizier from astropy import units as u v = Vizier(columns=["all"], catalog='I/345/gaia2') v.ROW_LIMIT = 25000 results = v.query_object(name, catalog='I/345/gaia2') # results = v.query_object(name, catalog='I/345/gaia2', radius = radius * u.arcsec) keys = results[0].keys() results[0].pprint() print("Number of results: %d" % len(results[0])) raStr, decStr = getSimbadCoordinates(name) targetRA, targetDEC = parseCoords(raStr, decStr) print("Location of %s is %f, %f" % (name, targetRA, targetDEC)) objectList = gaiaClass.GAIAObjects(gaiaTable=results[0]) closestMatch = objectList.calcAngularDistance(targetRA, targetDEC) singleResult = objectList.getObjectByDR2Name(closestMatch) return keys, singleResult
def query_catalog_for_object(identifier, catalog=duncan1991): """ Parameters ---------- identifier : str catalog : str (optional) Returns ------- """ query = Vizier.query_object(identifier, catalog=catalog) if len(query) > 0: return query[0][0] else: return dict(Smean=np.nan, Smin=np.nan, Smax=np.nan)
def create_vizier_metafile(): result = Vizier.query_object("sirius") text_file = open("D:\\Programming\\Astronomy\\VizierMeta.txt", "w") text_file.truncate() for table in result: #print table.colnames text_file.write('(' + table.meta['name'] + ') ' + table.meta['description'] + '\n') for col in table.colnames: text_file.write('\t' + col + '\n') text_file.write('\n') text_file.write('\n') #print table.colnames #print table.meta['description'] text_file.close()
def get_galaxy_s4g_one_component_info(name): """ This function ... :param name: :return: """ # The Vizier querying object vizier = Vizier() vizier.ROW_LIMIT = -1 # Get the "galaxies" table result = vizier.query_object(name, catalog=["J/ApJS/219/4/galaxies"]) table = result[0] # PA: [0.2/180] Outer isophote position angle # e_PA: [0/63] Standard deviation in PA # Ell: [0.008/1] Outer isophote ellipticity # e_Ell: [0/0.3] Standard deviation in Ell # PA1: Elliptical isophote position angle in deg # n: Sersic index # Re: effective radius in arcsec # Tmag: total magnitude s4g_name = table["Name"][0] pa = Angle(table["PA"][0] - 90., "deg") pa_error = Angle(table["e_PA"][0], "deg") ellipticity = table["Ell"][0] ellipticity_error = table["e_Ell"][0] n = table["n"][0] re = table["Re"][0] * u("arcsec") mag = table["Tmag"][0] # Return the results return s4g_name, pa, ellipticity, n, re, mag
def get_s4g_properties(self): """ This function ... :return: """ # Inform the user log.info("Querying the S4G catalog ...") # The Vizier querying object vizier = Vizier(columns=['Name', 'RAJ2000', 'DEJ2000', 'amaj', 'ell', 'Dmean', "e_Dmean", "PA"]) vizier.ROW_LIMIT = -1 # Get parameters from S4G catalog result = vizier.query_object(self.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Galaxy name for S4G catalog self.properties.name = table["Name"][0] # Galaxy center from decomposition (?) ra_center = table["RAJ2000"][0] dec_center = table["DEJ2000"][0] center = SkyCoordinate(ra=ra_center, dec=dec_center, unit="deg", frame='fk5') self.properties.center = center # Center position #self.properties.center = SkyCoordinate(ra=self.info["RA"][0], dec=self.info["DEC"][0], unit="deg") # center position from DustPedia # Distance self.properties.distance = table["Dmean"][0] * u("Mpc") self.properties.distance_error = table["e_Dmean"][0] * u("Mpc") # Major axis, ellipticity, position angle self.properties.major_arcsec = table["amaj"][0] * u("arcsec") self.properties.major = (self.properties.distance * self.properties.major_arcsec).to("pc", equivalencies=dimensionless_angles()) # Ellipticity self.properties.ellipticity = table["ell"][0] self.properties.position_angle = Angle(table["PA"][0] + 90.0, u("deg"))
def query_objects(self, names: TList[str]) -> TList[CatalogSource]: """ Return a list of VizieR catalog objects with the specified names :param names: object names :return: list of catalog objects with the given names """ kwargs = {} if self.vizier_server: kwargs['vizier_server'] = self.vizier_server viz = Vizier( catalog=self.vizier_catalog, columns=self._columns, row_limit=len(names), **kwargs) rows = [] for name in names: resp = viz.query_object( name, catalog=viz.catalog, cache=self.cache) if resp: rows.append(resp[0][0]) return self.table_to_sources(rows)
def query(): result = Vizier.query_object("Betelgeuse", catalog=["V/137D/XHIP", "V/85A/catalog"]) #result = Vizier.query_object("sirius", catalog="J/A+A/501/949/table") text_file = open("D:\\Programming\\Astronomy\\VizierTest.txt", "w") text_file.truncate() for table in result: text_file.write('\n') text_file.write('\n') text_file.write('(' + table.meta['name'] + ') ' + table.meta['description'] + '\n') text_file.write('\n') text_file.write('\n') for row in table: for col in table.colnames: text_file.write(col + '\t' + str(row[col]) + '\n') text_file.write('\n') #print row[col] #print row text_file.close()
def query_KIC(self, ID = None, radius = 10.0*u.arcsec): warnings.filterwarnings("ignore", category = MergeConflictWarning) if ID is None: ID = self.IDs['KIC'] tbl = Table(names = ('KIC',), dtype = (int,)) for i, id in tqdm(enumerate(ID)): if not isinstance(id, ): tbl.add_row(None) tbl[-1]['KIC'] = int(re.sub(r"\D", "", id)) else: job = Vizier.query_object(object_name = id, catalog = 'V/133/kic', radius = radius) if len(job) > 0: id_int = int(id.replace('KIC','')) idx = job[0]['KIC'] == id_int id_int = int(id.replace('KIC','')) idx = job[0]['KIC'] == id_int tbl = avstack([tbl, job[0][idx]]) else: tbl.add_row(None) tbl[-1]['KIC'] = int(re.sub(r"\D", "", id)) warnings.warn(f'Unable to find KIC entry for {id}') self.KIC = tbl return self.KIC
E1DecRange = [] # Loop through each Landolt star and retrieve the USNO-B1 data for that object. for iStar, star in enumerate(landoltStars): # Parse the star's name in SimbadName simbadName = star['SimbadName'].decode('utf-8') # Parse this star's pointing RA, Dec = star['_RAJ2000'], star['_DEJ2000'] # Skip over Landolt stars more than 10 degrees from the equator. if np.abs(Dec) > 20.0: print('Star {0} is far from the equator... skipping'.format(simbadName)) continue # Query the USNO-B1.0 data for this object USNOB = Vizier.query_object(simbadName, radius = 5.0*u.arcsec, catalog='USNO-B1') if len(USNOB) > 0: # Some match was found, so grab that 'catalog' USNOB = USNOB[0] else: print('Star {0} not matched in USNO-B1.0... skipping'.format(simbadName)) continue # If there is more than one object returned, if len(USNOB) > 1: # Then find the object closest to the query point and just use that. matchInd = np.where(USNOB['_r'].data == USNOB['_r'].data.min()) USNOB = USNOB[matchInd] # Test if we know where this data came from
def get_galaxy_info(name, position): """ This function ... :param name: :param position: :return: """ # Obtain more information about this galaxy try: ned_result = Ned.query_object(name) ned_entry = ned_result[0] # Get a more common name for this galaxy (sometimes, the name obtained from NED is one starting with 2MASX .., use the PGC name in this case) if ned_entry["Object Name"].startswith("2MASX "): gal_name = name else: gal_name = ned_entry["Object Name"] # Get the redshift gal_redshift = ned_entry["Redshift"] if isinstance(gal_redshift, np.ma.core.MaskedConstant): gal_redshift = None # Get the type (G=galaxy, HII ...) gal_type = ned_entry["Type"] if isinstance(gal_type, np.ma.core.MaskedConstant): gal_type = None except astroquery.exceptions.RemoteServiceError: # Set attributes gal_name = name gal_redshift = None gal_type = None except astroquery.exceptions.TimeoutError: # Set attributes gal_name = name gal_redshift = None gal_type = None except: # Set attributes gal_name = name gal_redshift = None gal_type = None # Create a new Vizier object and set the row limit to -1 (unlimited) viz = Vizier(keywords=["galaxies", "optical"]) viz.ROW_LIMIT = -1 # Query Vizier and obtain the resulting table result = viz.query_object(name.replace(" ", ""), catalog=["VII/237"]) # Not found ... TODO: fix this ... this object was in the first query output if len(result) == 0: return name, position, None, None, [], None, None, None, None, None, None table = result[0] # Get the correct entry (sometimes, for example for mergers, querying with the name of one galaxy gives two hits! We have to obtain the right one each time!) if len(table) == 0: raise ValueError("The galaxy could not be found under this name") elif len(table) == 1: entry = table[0] else: entry = None # Some rows don't have names, if no match is found based on the name just take the row that has other names defined rows_with_names = [] for row in table: if row["ANames"]: rows_with_names.append(row) # If only one row remains, take that one for the galaxy we are looking for if len(rows_with_names) == 1: entry = rows_with_names[0] # Else, loop over the rows where names are defined and look for a match else: for row in rows_with_names: names = row["ANames"] if name.replace(" ", "") in names or gal_name.replace( " ", "") in names: entry = row break # If no matches are found, look for the table entry for which the coordinate matches the given position (if any) if entry is None and position is not None: for row in table: if ('_RAJ2000' in row.colnames) and ('_DEJ2000' in row.colnames): ra_key, dec_key = '_RAJ2000', '_DEJ2000' elif ('RAJ2000' in row.colnames) and ('DEJ2000' in row.colnames): ra_key, dec_key = 'RAJ2000', 'DEJ2000' if np.isclose( astropy.coordinates.Angle(row[ra_key] + ' hours').deg, position.ra.value) and np.isclose( astropy.coordinates.Angle(row[dec_key] + ' degrees').deg, position.dec.value): entry = row break # Note: another temporary fix if entry is None: return name, position, None, None, [], None, None, None, None, None, None # Get the right ascension and the declination if ('_RAJ2000' in entry.colnames) and ('_DEJ2000' in entry.colnames): ra_key, dec_key = '_RAJ2000', '_DEJ2000' elif ('RAJ2000' in entry.colnames) and ('DEJ2000' in entry.colnames): ra_key, dec_key = 'RAJ2000', 'DEJ2000' position = SkyCoordinate(ra=entry[ra_key], dec=entry[dec_key], unit="deg", frame="fk5") # Get the names given to this galaxy gal_names = entry["ANames"].split() if entry["ANames"] else [] # Get the size of the galaxy ratio = np.power(10.0, entry["logR25"]) if entry["logR25"] else None diameter = np.power(10.0, entry["logD25"]) * 0.1 * Unit( "arcmin") if entry["logD25"] else None #print(" D25_diameter = ", diameter) radial_profiles_result = viz.query_object(name, catalog="J/ApJ/658/1006") if len(radial_profiles_result) > 0: radial_profiles_entry = radial_profiles_result[0][0] gal_distance = radial_profiles_entry["Dist"] * Unit("Mpc") gal_inclination = Angle(radial_profiles_entry["i"], "deg") gal_d25 = radial_profiles_entry["D25"] * Unit("arcmin") else: gal_distance = None gal_inclination = None gal_d25 = None # Get the size of major and minor axes gal_major = diameter gal_minor = diameter / ratio if diameter is not None and ratio is not None else None # Get the position angle of the galaxy gal_pa = Angle(entry["PA"] - 90.0, "deg") if entry["PA"] else None # Create and return a new Galaxy instance return gal_name, position, gal_redshift, gal_type, gal_names, gal_distance, gal_inclination, gal_d25, gal_major, gal_minor, gal_pa
class S4G(Configurable): """ This class ... """ def __init__(self, *args, **kwargs): """ The constructor ... :param kwargs: """ # Call the constructor of the base class super(S4G, self).__init__(*args, **kwargs) # Names self.ngc_name = None self.ngc_name_nospaces = None # The Vizier querying object, specifying the necessary columns for this class self.vizier = Vizier(columns=[ 'Name', 'RAJ2000', 'DEJ2000', 'Dmean', 'e_Dmean', 'amaj', 'ell', '[3.6]', '[4.5]', 'e_[3.6]', 'e_[4.5]', 'PA' ]) self.vizier.ROW_LIMIT = -1 # The DustPedia database #self.database = DustPediaDatabase() # The path for the S4G decomposition models #self.components_2d_s4g_path = None # The galaxy properties object self.properties = None # The dictionary of components self.components = dict() # self.disk_pa = None self.disk = None self.bulge = None # ----------------------------------------------------------------- def run(self, **kwargs): """ This function ... :return: """ # 1. Call the setup function self.setup(**kwargs) # 2. Get galaxy properties self.get_properties() # Tracing spiral density waves in M81: (Kendall et. al, 2008) # - Sersic bulge: # n = 2.62 # Re = 46.2 arcsec # b/a = 0.71 # PA = −31.9° # - Exponential disk: # Rs = 155.4 arcsec # b/a = 0.52 # PA = −28.3° # self.get_p4() # currently (writing on the 31th of march 2016) there is a problem with the effective radius values # (at least for M81) on Vizier as well as in the PDF version of table 7 (S4G models homepage). # 3. Parse the S4G table 8 to get the decomposition parameters self.get_parameters_from_table() # 4. Show if self.config.show: self.show() # 5. Writing if self.config.output is not None: self.write() # ----------------------------------------------------------------- def setup(self, **kwargs): """ This function ... :param kwargs: :return: """ # Call the setup function of the base class super(S4G, self).setup(**kwargs) # Create the galaxy properties object self.properties = GalaxyProperties() self.properties.name = self.config.galaxy_name # Set the path #self.components_2d_s4g_path = fs.create_directory_in(self.components_2d_path, "S4G") # ----------------------------------------------------------------- def get_properties(self): """ This function ... :return: """ # Inform the user log.info("Getting the galaxy properties ...") # Name self.get_ngc_name() #self.get_dustpedia_info() # S4G self.get_s4g_properties() #self.get_inclination() # To first order, cos i = b/a where a & b # are the observed major and minor # axes (assume disk is intrinsically # circular) # But this implies galaxies have zero # thickness at i = 90°! Better to assume # that spirals are oblate ellipsoids with # intrinsic axis ratios a:a:c. If q = c/a, # then after a bit a simple geometry # cos^2(i) = [ (b/a)^2 - q^2 ] / (1-q^2) # The best fit to observed spirals yields # q = 0.13 for Sc galaxies # Ellipticity (1-b/a) b_to_a = 1. - self.properties.ellipticity # Calculate the inclination inclination_deg = 90. - math.degrees(math.acos(b_to_a)) inclination = Angle(inclination_deg, "deg") self.properties.inclination = inclination # ----------------------------------------------------------------- def get_ngc_name(self): """ This function ... :return: """ # Get the NGC name of the galaxy self.properties.ngc_name = catalogs.get_ngc_name( self.config.galaxy_name) # Set ... self.ngc_name = self.properties.ngc_name self.ngc_name_nospaces = self.ngc_name.replace(" ", "") # ----------------------------------------------------------------- def get_dustpedia_info(self): """ This function ... :return: """ # Inform the user log.info("Fetching galaxy info from the DustPedia database ...") # Get the info self.info = self.database.get_galaxy_info(self.ngc_name_nospaces) # ----------------------------------------------------------------- def get_s4g_properties(self): """ This function ... :return: """ # Inform the user log.info("Querying the S4G catalog ...") # Get parameters from S4G catalog result = self.vizier.query_object(self.config.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Galaxy name for S4G catalog self.properties.name = table["Name"][0] # Galaxy center from decomposition (?) ra_center = table["RAJ2000"][0] dec_center = table["DEJ2000"][0] center = SkyCoordinate(ra=ra_center, dec=dec_center, unit="deg", frame='fk5') self.properties.center = center # Center position #self.properties.center = SkyCoordinate(ra=self.info["RA"][0], dec=self.info["DEC"][0], unit="deg") # center position from DustPedia # Distance self.properties.distance = table["Dmean"][0] * u("Mpc") self.properties.distance_error = table["e_Dmean"][0] * u("Mpc") # Major axis, ellipticity, position angle self.properties.major_arcsec = table["amaj"][0] * u("arcsec") self.properties.major = (self.properties.distance * self.properties.major_arcsec).to( "pc", equivalencies=dimensionless_angles()) # Ellipticity self.properties.ellipticity = table["ell"][0] self.properties.position_angle = Angle(table["PA"][0] + 90.0, u("deg")) # Magnitudes asymptotic_ab_magnitude_i1 = table["__3.6_"][0] asymptotic_ab_magnitude_i2 = table["__4.5_"][0] asymptotic_ab_magnitude_i1_error = table["e__3.6_"][0] asymptotic_ab_magnitude_i2_error = table["e__4.5_"][0] #self.properties.i1_mag = asymptotic_ab_magnitude_i1 #self.properties.i1_mag_error = asymptotic_ab_magnitude_i1_error #self.properties.i2_mag = asymptotic_ab_magnitude_i2 #self.properties.i2_mag_error = asymptotic_ab_magnitude_i2_error #self.properties.i1_fluxdensity = unitconversion.ab_to_jansky(self.properties.i1_mag) * Unit("Jy") #i1_fluxdensity_lower = unitconversion.ab_to_jansky( # self.properties.i1_mag + self.properties.i1_mag_error) * Unit("Jy") #i1_fluxdensity_upper = unitconversion.ab_to_jansky( # self.properties.i1_mag - self.properties.i1_mag_error) * Unit("Jy") #i1_error = ErrorBar(i1_fluxdensity_lower, i1_fluxdensity_upper, at=self.properties.i1_fluxdensity) #self.properties.i1_error = i1_error.average #self.properties.i2_fluxdensity = unitconversion.ab_to_jansky(self.properties.i2_mag) * Unit("Jy") #i2_fluxdensity_lower = unitconversion.ab_to_jansky( # self.properties.i2_mag + self.properties.i2_mag_error) * Unit("Jy") #i2_fluxdensity_upper = unitconversion.ab_to_jansky( # self.properties.i2_mag - self.properties.i2_mag_error) * Unit("Jy") #i2_error = ErrorBar(i2_fluxdensity_lower, i2_fluxdensity_upper, at=self.properties.i2_fluxdensity) #self.properties.i2_error = i2_error.average # Other ... # absolute_magnitude_i1 = table["M3.6"][0] # absolute_magnitude_i2 = table["M4.5"][0] # stellar_mass = 10.0**table["logM_"][0] * u.Unit("Msun") # ----------------------------------------------------------------- def get_inclination(self): """ This function ... :return: """ # Inform the user log.info( "Querying the catalog of radial profiles for 161 face-on spirals ..." ) # Radial profiles for 161 face-on spirals (Munoz-Mateos+, 2007) radial_profiles_result = self.vizier.query_object( self.config.galaxy_name, catalog="J/ApJ/658/1006") distance = float(radial_profiles_result[0][0]["Dist"]) inclination = Angle(float(radial_profiles_result[0][0]["i"]), "deg") # Set the inclination self.properties.inclination = inclination # ----------------------------------------------------------------- def get_p4(self): """ This function ... :return: """ #http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/ApJS/219/4 # J/ApJS/219/4: S4G pipeline 4: multi-component decompositions (Salo+, 2015) # - J/ApJS/219/4/galaxies: Parameters of the galaxies; center, outer orientation, sky background; and 1-component Sersic fits (tables 1 and 6) (2352 rows) # - J/ApJS/219/4/table7: *Parameters of final multicomponent decompositions (Note) (4629 rows) # Inform the user log.info("Querying the S4G pipeline 4 catalog ...") # Get the "galaxies" table result = self.vizier.query_object(self.config.galaxy_name, catalog=["J/ApJS/219/4/galaxies"]) table = result[0] # PA: [0.2/180] Outer isophote position angle # e_PA: [0/63] Standard deviation in PA # Ell: [0.008/1] Outer isophote ellipticity # e_Ell: [0/0.3] Standard deviation in Ell pa = Angle(table["PA"][0] - 90., "deg") pa_error = Angle(table["e_PA"][0], "deg") ellipticity = table["Ell"][0] ellipticity_error = table["e_Ell"][0] # Get the "table7" table result = self.vizier.get_catalogs("J/ApJS/219/4/table7") table = result[0] # Name: Galaxy name # Mod: Type of final decomposition model # Nc: [1/4] Number of components in the model (1-4) # Q: [3/5] Quality flag, 5=most reliable # C: Physical interpretation of the component # Fn: The GALFIT function used for the component (sersic, edgedisk, expdisk, ferrer2 or psf) # f1: [0.006/1] "sersic" fraction of the total model flux # mag1: [7/19.4] "sersic" total 3.6um AB magnitude # q1: [0.1/1] "sersic" axis ratio # PA1: [0.08/180] "sersic" position angle [deg] # Re: [0.004/430] "sersic" effective radius (Re) [arcsec] # n: [0.01/20] "sersic" parameter n # f2: [0.02/1] "edgedisk" fraction of the total model flux # mu02: [11.8/24.6] "edgedisk" central surface face-on brightness (µ0) [mag/arcsec2] # PA2: [-90/90] "edgedisk" PA [deg] # hr2: [1/153] "edgedisk" exponential scale length (hr) [arcsec] # hz2: [0.003/39] "edgedisk" z-scale hz [arcsec] # f3: [0.02/1] "expdisk" fraction of the total model flux # mag3: [6.5/18.1] "expdisk" total 3.6um AB magnitude [mag] # q3: [0.1/1] "expdisk" axis ratio # PA3: [-90/90] "expdisk" position angle [deg] # hr3: [0.7/332] "expdisk" exponential scale length (hr) [arcsec] # mu03: [16.4/25.3] "expdisk" central surface face-on brightness (µ0) [mag/arcsec2] # f4: [0.003/0.6] "ferrer2" fraction of the total model flux # mu04: [16/24.8] "ferrer2" central surface sky brightness (µ0) [mag/arcsec2] # q4: [0.01/1] "ferrer2" axis ratio # PA4: [-90/90] "ferrer2" position angle [deg] # Rbar: [3.7/232.5] "ferrer2" outer truncation radius of the bar (Rbar) [arcsec] # f5: [0.001/0.4] "psf" fraction of the total model flux # mag5: [11.5/21.1] "psf" total 3.6um AB magnitude [mag] indices = tables.find_indices(table, self.ngc_name_nospaces, "Name") labels = { "sersic": 1, "edgedisk": 2, "expdisk": 3, "ferrer2": 4, "psf": 5 } #units = {"f": None, "mag": "mag", "q": None, "PA": "deg", } # Loop over the indices for index in indices: model_type = table["Mod"][index] number_of_components = table["Nc"][index] quality = table["Q"][index] interpretation = table["C"][index] functionname = table["Fn"][index] component_parameters = Map() if self.parameters.model_type is not None: assert model_type == self.parameters.model_type if self.parameters.number_of_components is not None: assert number_of_components == self.parameters.number_of_components if self.parameters.quality is not None: assert quality == self.parameters.quality self.parameters.model_type = model_type self.parameters.number_of_components = number_of_components self.parameters.quality = quality for key in table.colnames: if not key.endswith(str(labels[functionname])): continue parameter = key[:-1] value = table[key][index] if parameter == "PA": value = Angle(value + 90., "deg") if quadrant(value) == 2: value = value - Angle(180., "deg") elif quadrant(value) == 3: value = value + Angle(180., "deg") if value.to("deg").value > 180.: value = value - Angle(360., "deg") elif value.to("deg").value < -180.: value = value + Angle(360., "deg") elif parameter == "mag": parameter = "fluxdensity" value = unitconversion.ab_to_jansky(value) * u("Jy") elif parameter == "mu0": value = value * u("mag/arcsec2") elif parameter == "hr": value = value * u("arcsec") value = (self.parameters.distance * value).to( "pc", equivalencies=dimensionless_angles()) elif parameter == "hz": value = value * u("arcsec") value = (self.parameters.distance * value).to( "pc", equivalencies=dimensionless_angles()) component_parameters[parameter] = value if functionname == "sersic": re = table["Re"][index] * u("arcsec") component_parameters["Re"] = ( self.parameters.distance * re).to( "pc", equivalencies=dimensionless_angles()) component_parameters["n"] = table["n"][index] elif functionname == "ferrer2": rbar = table["Rbar"][index] * u("arcsec") component_parameters["Rbar"] = ( self.parameters.distance * rbar).to( "pc", equivalencies=dimensionless_angles()) if interpretation == "B": # bulge self.parameters.bulge = component_parameters elif interpretation == "D": # disk self.parameters.disk = component_parameters else: raise RuntimeError("Unrecognized component: " + interpretation) # Determine the full path to the parameters file #path = fs.join(self.components_path, "parameters.dat") # Write the parameters to the specified location #write_parameters(self.parameters, path) # ----------------------------------------------------------------- def get_parameters_from_table(self): """ This function ... :return: """ # Inform the user log.info( "Getting the structural galaxy parameters from the S4G catalog ..." ) # Inform the user log.info("Parsing S4G table 8 to get the decomposition parameters ...") #The table columns are: # (1) the running number (1-2352), # (2) the galaxy name, # (3) the type of final decomposition model, # (4) the number N of components in the final model , and # (5) the quality flag Q. # 6- 8 for unresolved central component ('psf'; phys, frel, mag), # 9-15 for inner sersic-component ('sersic1'; phys, frel, mag, re, ar, pa, n), # 16-22 for inner disk-component ('expo1'; phys, frel, mag, hr, ar, pa, mu0), # 23-28 for inner ferrers-component ('ferrers1'; phys, frel, mu0, rout, ar, pa), # 29-34 for inner edge-on disk component ('edgedisk1'; phys, frel, mu0, rs, hs, pa ). # 35-41 for outer sersic-component ('sersic2'; phys, frel, mag, re, ar, pa, n), # 42-49 for outer disk-component ('expo2'; phys, frel, mag, hr, ar, pa, mu0), # 50-55 for outer ferrers-component ('ferrers2'; phys, frel, mu0, rout, ar, pa), # 56-61 for outer edge-on disk component ('edgedisk2'; phys, frel, mu0, rs, hs, pa ). sersic_1_index = 8 disk_1_index = 15 edgedisk_1_index = 28 #For each function: #the first entry stands for the physical intepretation of the component: #'N' for a central source (or unresolved bulge), 'B' for a bulge (or elliptical), 'D' for a disk, 'BAR' for a bar, and 'Z' for an edge-on disk. # 'rel = the relative contribution of the component to the total model flux, # mag = the component's total 3.6 micron AB magnitude, # mu0 = the central surface brightness (mag/arcsec^2; de-projected central surface brightness for expdisk and edgedisk, and # sky-plane central surface brightness for ferrer) # ar = axial ratio # pa = position angle (degrees ccw from North) # n = sersic index # hr = exponential scale lenght (arcsec) # rs = radial scale lenght (arcsec) # hs = vertical scale height (arcsec) # rout = bar outer truncation radius (arcsec) # SERSIC: phys, frel, mag, re, ar, pa, n # DISK: phys, frel, mag, hr, ar, pa, mu0 # EDGEDISK: phys frel mu0 rs hs pa with open(local_table_path, 'r') as s4g_table: for line in s4g_table: splitted = line.split() if len(splitted) < 2: continue name = splitted[1] #print(list(name)) # Only look at the line corresponding to the galaxy if name != self.ngc_name_nospaces: continue #if self.ngc_name_nospaces not in name: continue #self.parameters.model_type = splitted[2] #self.parameters.number_of_components = splitted[3] #self.parameters.quality = splitted[4] ## BULGE #self.parameters.bulge.interpretation = splitted[sersic_1_index].split("|")[1] bulge_f = float(splitted[sersic_1_index + 1]) mag = float(splitted[sersic_1_index + 2]) bulge_fluxdensity = unitconversion.ab_to_jansky(mag) * u("Jy") # Effective radius in pc re_arcsec = float(splitted[sersic_1_index + 3]) * u("arcsec") bulge_re = (self.properties.distance * re_arcsec).to( "pc", equivalencies=dimensionless_angles()) bulge_q = float(splitted[sersic_1_index + 4]) bulge_pa = Angle( float(splitted[sersic_1_index + 5]) - 90., "deg") bulge_n = float(splitted[sersic_1_index + 6]) # Create the bulge component bulge = SersicModel2D(rel_contribution=bulge_f, fluxdensity=bulge_fluxdensity, effective_radius=bulge_re, axial_ratio=bulge_q, position_angle=bulge_pa, index=bulge_n) # Add the bulge to the components dictionary self.components["bulge"] = bulge ## DISK if splitted[disk_1_index + 1] != "-": #self.parameters.disk.interpretation = splitted[disk_1_index].split("|")[1] disk_f = float(splitted[disk_1_index + 1]) mag = float(splitted[disk_1_index + 2]) disk_fluxdensity = unitconversion.ab_to_jansky(mag) * u( "Jy") # Scale length in pc hr_arcsec = float(splitted[disk_1_index + 3]) * u("arcsec") disk_hr = (self.properties.distance * hr_arcsec).to( "pc", equivalencies=dimensionless_angles()) disk_q = float(splitted[disk_1_index + 4]) # axial ratio disk_pa = Angle( float(splitted[disk_1_index + 5]) - 90., "deg") disk_mu0 = float( splitted[disk_1_index + 6]) * u("mag/arcsec2") # Create the disk component disk = ExponentialDiskModel2D(rel_contribution=disk_f, fluxdensity=disk_fluxdensity, scalelength=disk_hr, axial_ratio=disk_q, position_angle=disk_pa, mu0=disk_mu0) else: # phys frel mu0 rs hs pa disk_f = float(splitted[edgedisk_1_index + 1]) mag = None fluxdensity = None # frel mu0 rs hs pa #print(disk_f) disk_mu0 = float( splitted[edgedisk_1_index + 2]) * u("mag/arcsec2") # rs hs pa # rs = radial scale lenght (arcsec) # hs = vertical scale height (arcsec) rs = float(splitted[edgedisk_1_index + 3]) hs = float(splitted[edgedisk_1_index + 4]) #print(rs) #print(hs) disk_pa = Angle( float(splitted[edgedisk_1_index + 5]) - 90., "deg") #print(disk_pa) disk_q = hs / rs # Create the disk component disk = ExponentialDiskModel2D(rel_contribution=disk_f, scalelength=rs, axial_ratio=disk_q, position_angle=disk_pa, mu0=disk_mu0) # Add the disk to the components dictionary self.components["disk"] = disk # Set the disk position angle self.disk_pa = self.components["disk"].position_angle # ----------------------------------------------------------------- def create_bulge_model(self): """ :return: """ # Inform the user log.info("Creating the bulge model ...") # Create a Sersic model for the bulge self.bulge = SersicModel3D.from_2d(self.components["bulge"], self.properties.inclination, self.disk_pa) # ----------------------------------------------------------------- def create_disk_model(self): """ :return: """ # Inform the user log.info("Creating the disk model ...") # Create an exponential disk model for the disk self.disk = ExponentialDiskModel3D.from_2d(self.components["disk"], self.properties.inclination, self.disk_pa) # ----------------------------------------------------------------- def show(self): """ This function ... :return: """ print(fmt.green + "Galaxy properties" + fmt.reset + ":") print("") print(self.properties) print("") for name in self.components: print(fmt.green + name + fmt.reset + ":") print("") print(self.components[name]) print("") # ----------------------------------------------------------------- def write(self): """ This function ... :return: """ # Inform the user log.info("Writing ...") # Write the properties self.write_properties() # Write the components self.write_components() # ----------------------------------------------------------------- def write_properties(self): """ This function ... :return: """ # Determine the path and save path = self.output_path_file("properties.dat") self.properties.saveto(path) # ----------------------------------------------------------------- def write_components(self): """ This function ... :return: """ # Loop over the components for name in self.components: # Determine the path path = self.output_path_file(name + ".mod") # Save the model self.components[name].saveto(path)
class SEDFetcher(OldConfigurable): """ This class ... """ def __init__(self, config=None): """ The constructor ... """ # Call the constructor of the base class super(SEDFetcher, self).__init__(config, "modeling") # -- Attributes -- # The name of the galaxy self.galaxy_name = None # The NGC ID of the galaxy self.ngc_id = None # The Vizier querying object self.vizier = Vizier(keywords=["galaxies"]) self.vizier.ROW_LIMIT = -1 # The observed SED self.seds = dict() # The filters self.filters = dict() # ----------------------------------------------------------------- @classmethod def from_arguments(cls, arguments): """ This function ... :param arguments: :return: """ # Create a new SEDFetcher instance if arguments.config is not None: fetcher = cls(arguments.config) elif arguments.settings is not None: fetcher = cls(arguments.settings) else: fetcher = cls() # Set the output path if arguments.output_path is not None: fetcher.config.output_path = arguments.output_path # Run from the command line, so always write out the SEDs fetcher.config.write_seds = True fetcher.config.writing.seds_path = "SEDs" # Return the new instance return fetcher # ----------------------------------------------------------------- def run(self, galaxy_name): """ This function ... :param galaxy_name """ # 1. Call the setup function self.setup(galaxy_name) # 2. If requested, query the GALEX ultraviolet atlas of nearby galaxies catalog (Gil de Paz+, 2007) if "GALEX" in self.config.catalogs: self.get_galex() # 3. If requested, query the 2MASS Extended sources catalog (IPAC/UMass, 2003-2006) if "2MASS" in self.config.catalogs: self.get_2mass() # SDSS ? # Ilse "Voor de galaxieen in de noordelijke hemisfeer heb je SDSS data beschikbaar, en die kan je dan # beter gebruiken (ipv. SINGS) om je fit te constrainen in het optische gebied. Er zal binnenkort een nieuwe # paper van Daniel Dale uitkomen met gehercalibreerde fluxen in de optische banden, die je dan kan gebruiken. # 5. If requested, query the Radial distribution in SINGS galaxies (I.) catalogs (Munoz-Mateos+, 2009) # Opm. Ilse: "voor vele SINGS galaxieen is de calibratie van de optische data heel slecht, dus krijg je een # offset en datapunten die een beetje random blijken te zijn." if "SINGS" in self.config.catalogs: self.get_sings() # If requested, query the LVL global optical photometry (Cook+, 2014) catalog if "LVL" in self.config.catalogs: self.get_lvl() # If requested, query the Spitzer Local Volume Legacy: IR photometry (Dale+, 2009) if "Spitzer" in self.config.catalogs: self.get_spitzer() # If requested, query the Spitzer/IRS ATLAS project source (Hernan-Caballero+, 2011) if "Spitzer/IRS" in self.config.catalogs: self.get_spitzer_irs() # If requested, query the Compendium of ISO far-IR extragalactic data (Brauher+, 2008) if "IRAS" in self.config.catalogs: self.get_iras() # If requested, query the Imperial IRAS-FSC redshift catalogue (IIFSCz) (Wang+, 2009) if "IRAS-FSC" in self.config.catalogs: self.get_iras_fsc() # If requested, query the S4G catalog for IRAC fluxes if "S4G" in self.config.catalogs: self.get_s4g() # If requested, query the Spectroscopy and abundances of SINGS galaxies (Moustakas+, 2010) catalog if "Emission lines" in self.config.catalogs: self.get_emission_lines() # If requested, query the Atlas of UV-to-MIR galaxy SEDs (Brown+, 2014) if "Brown" in self.config.catalogs: self.get_brown() # If requested, query the Planck Catalog of Compact Sources Release 1 (Planck, 2013) if "Planck" in self.config.catalogs: self.get_planck() # SPECIFIC for M81: not enabled, no time to figure out the unit conversion now #if self.ngc_id == "NGC 3031": self.get_m81() # Other interesting catalogs: # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/199/22 # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/212/18/sample&-c=NGC%203031&-c.u=arcmin&-c.r=2&-c.eq=J2000&-c.geom=r&-out.max=50&-out.form=HTML%20Table&-oc.form=sexa # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/220/6 # Writing self.write() # ----------------------------------------------------------------- def setup(self, galaxy_name): """ This function ... :param galaxy_name: :return: """ # Call the setup function of the base class super(SEDFetcher, self).setup() # Set the galaxy name self.galaxy_name = galaxy_name # Get the NGC ID of the galaxy self.ngc_id = catalogs.get_ngc_name(self.galaxy_name) # Create a dictionary of filters keys = ["Ha", "FUV", "NUV", "U", "B", "V", "R", "J", "H", "K", "IRAS 12", "IRAS 25", "IRAS 60", "IRAS 100", "I1", "I2", "I3", "I4", "MIPS 24", "MIPS 70", "MIPS 160", "SDSS u", "SDSS g", "SDSS r", "SDSS i", "SDSS z"] for key in keys: self.filters[key] = Filter.from_string(key) # ----------------------------------------------------------------- def get_galex(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the GALEX ultraviolet atlas of nearby galaxies ...") # GALEX: "J/ApJS/173/185" of "J/ApJS/173/185/galex": B and V (2007ApJS..173..185G) # Interesting columns: # # - "MajAxis": Major-axis diameter of the D25 ellipse [arcmin] # - "MinAxis": Minor-axis diameter of the D25 ellipse [arcmin] # - "PA": Position angle of the D25 ellipse [deg] # - "Dist": Distance to the galaxy [Mpc] # - "Morph": Morphological type # - "T": Morphological type T # - "FUV": FUV (120-177nm) image mean sky background [ct/s] # - "sigFUV": Mean standard deviation of the FUV sky. Note (2): Measured by averaging the standard deviation within several regions around the position of the object. [ct/s] # - "e_FUV": The standard deviation of the mean FUV sky [ct/s] # - "NUV": Mean NUV (177-300nm) sky background [ct/s] # - "sigNUV": Mean standard deviation of the NUV sky [ct/s] # - "e_NUV": The standard deviation of the mean NUV sky [ct/s] # - "D25FUV": Observed D25 ellipse FUV band AB magnitude [mag] # - "e_D25FUV": Uncertainty in D25FUV [mag] # - "D25NUV": Observed D25 ellipse NUV band AB magnitude [mag] # - "e_D25NUV": Uncertainty in D25NUV [mag] # - "AFUV": Foreground FUV extinction [mag] # - "ANUV": Foreground NUV extinction [mag] # - "asyFUV": Observed asymptotic FUV (120-177nm) AB magnitude [mag] # - "e_asyFUV": Uncertainty in asyFUV [mag] # - "asyNUV": Observed asymptotic NUV (177-300nm) AB magnitude [mag] # - "e_asyNUV": Uncertainty in asyNUV [mag] # - "logFUV": Log of the FUV (120-177nm) luminosity [W] # - "logNUV": Log of the NUV (177-300nm) luminosity [W] # - "Umag": Johnson U band integrated magnitude [mag] Note (1): In the Vega scale. Published as part of the RC3 catalog, Cat. VII/155) # - "e_Umag": Uncertainty in Umag [mag] # - "Bmag": Johnson B band integrated magnitude [mag] # - "e_Bmag": Uncertainty in Bmag [mag] # - "Vmag": Johnson V band integrated magnitude [mag] # - "e_Vmag": Uncertainty in Vmag [mag] # - "Jmag": 2MASS J band total magnitude [mag] # - "e_Jmag": Uncertainty in Jmag [mag] # - "Hmag": 2MASS H band total magnitude [mag] # - "e_Hmag": Uncertainty in Hmag [mag] # - "Kmag": 2MASS K band total magnitude [mag] # - "e_Kmag": Uncertainty in Kmag [mag] # - "F12um": IRAS 12 micron flux density [Jy] # - "e_F12um": Uncertainty in F12um [Jy] # - "F25um": IRAS 25 micron flux density [Jy] # - "e_F25um": Uncertainty in F25um [Jy] # - "F60um": IRAS 60 micron flux density [Jy] # - "e_F60um": Uncertainty in F60um [Jy] # - "F100um": IRAS 100 micron flux density [Jy] # - "e_F100um": Uncertainty in F100um [Jy] result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJS/173/185/galex") # Result is a list of tables, we only have one table with one entry # Create an SED sed = ObservedSED() # All AB magnitudes # FUV -- if not result[0]["asyFUV"].mask[0]: fuv_mag = result[0]["asyFUV"][0] fuv_mag_error = result[0][0]["e_asyFUV"] fuv_mag_lower = fuv_mag - fuv_mag_error fuv_mag_upper = fuv_mag + fuv_mag_error # flux fuv = unitconversion.ab_to_jansky(fuv_mag) fuv_lower = unitconversion.ab_to_jansky(fuv_mag_upper) fuv_upper = unitconversion.ab_to_jansky(fuv_mag_lower) fuv_error = ErrorBar(fuv_lower, fuv_upper, at=fuv) sed.add_entry(self.filters["FUV"], fuv, fuv_error) # NUV -- if not result[0]["asyNUV"].mask[0]: nuv_mag = result[0][0]["asyNUV"] nuv_mag_error = result[0][0]["e_asyNUV"] nuv_mag_lower = nuv_mag - nuv_mag_error nuv_mag_upper = nuv_mag + nuv_mag_error # flux nuv = unitconversion.ab_to_jansky(nuv_mag) nuv_lower = unitconversion.ab_to_jansky(nuv_mag_upper) nuv_upper = unitconversion.ab_to_jansky(nuv_mag_lower) nuv_error = ErrorBar(nuv_lower, nuv_upper, at=nuv) sed.add_entry(self.filters["NUV"], nuv, nuv_error) # U band -- if not result[0]["Umag"].mask[0]: # From Vega magnitude system to AB magnitudes u_mag = unitconversion.vega_to_ab(result[0][0]["Umag"], "U") u_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Umag"], "U") u_mag_lower = u_mag - u_mag_error u_mag_upper = u_mag + u_mag_error # U band flux u = unitconversion.ab_to_jansky(u_mag) u_lower = unitconversion.ab_to_jansky(u_mag_upper) u_upper = unitconversion.ab_to_jansky(u_mag_lower) u_error = ErrorBar(u_lower, u_upper, at=u) sed.add_entry(self.filters["U"], u, u_error) # B band -- if not result[0]["Bmag"].mask[0]: b_mag = unitconversion.vega_to_ab(result[0][0]["Bmag"], "B") b_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Bmag"], "B") b_mag_lower = b_mag - abs(b_mag_error) b_mag_upper = b_mag + abs(b_mag_error) #print("bmag", b_mag) #print("bmagerror", b_mag_error) #print("bmaglower", b_mag_lower) #print("bmagupper", b_mag_upper) # B band flux b = unitconversion.ab_to_jansky(b_mag) b_lower = unitconversion.ab_to_jansky(b_mag_upper) b_upper = unitconversion.ab_to_jansky(b_mag_lower) b_error = ErrorBar(b_lower, b_upper, at=b) sed.add_entry(self.filters["B"], b, b_error) # V band -- if not result[0]["Vmag"].mask[0]: v_mag = unitconversion.vega_to_ab(result[0][0]["Vmag"], "V") v_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Vmag"], "V") v_mag_lower = v_mag - v_mag_error v_mag_upper = v_mag + v_mag_error # V band flux v = unitconversion.ab_to_jansky(v_mag) v_lower = unitconversion.ab_to_jansky(v_mag_upper) v_upper = unitconversion.ab_to_jansky(v_mag_lower) v_error = ErrorBar(v_lower, v_upper, at=v) sed.add_entry(self.filters["V"], v, v_error) # In 2MASS magnitude system -> can be converted directly into Jy (see below) # J band -- if not result[0]["Jmag"].mask[0]: j_mag = result[0][0]["Jmag"] j_mag_error = result[0][0]["e_Jmag"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error # J band flux j = unitconversion.photometry_2mass_mag_to_jy(j_mag, "J") j_lower = unitconversion.photometry_2mass_mag_to_jy(j_mag_upper, "J") j_upper = unitconversion.photometry_2mass_mag_to_jy(j_mag_lower, "J") j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H band -- if not result[0]["Hmag"].mask[0]: h_mag = result[0][0]["Hmag"] h_mag_error = result[0][0]["e_Hmag"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error # H band flux h = unitconversion.photometry_2mass_mag_to_jy(h_mag, "H") h_lower = unitconversion.photometry_2mass_mag_to_jy(h_mag_upper, "H") h_upper = unitconversion.photometry_2mass_mag_to_jy(h_mag_lower, "H") h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # K band -- if not result[0]["Kmag"].mask[0]: k_mag = result[0][0]["Kmag"] k_mag_error = result[0][0]["e_Kmag"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # K band flux k = unitconversion.photometry_2mass_mag_to_jy(k_mag, "Ks") k_lower = unitconversion.photometry_2mass_mag_to_jy(k_mag_upper, "Ks") k_upper = unitconversion.photometry_2mass_mag_to_jy(k_mag_lower, "Ks") k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # F12 band flux if not result[0]["F12um"].mask[0]: f12 = result[0][0]["F12um"] f12_error = ErrorBar(result[0][0]["e_F12um"]) sed.add_entry(self.filters["IRAS 12"], f12, f12_error) # F25 band flux if not result[0]["F25um"].mask[0]: f25 = result[0][0]["F25um"] f25_error = ErrorBar(result[0][0]["e_F25um"]) sed.add_entry(self.filters["IRAS 25"], f25, f25_error) # F60 band flux if not result[0]["F60um"].mask[0]: f60 = result[0][0]["F60um"] f60_error = ErrorBar(result[0][0]["e_F60um"]) sed.add_entry(self.filters["IRAS 60"], f60, f60_error) # F100 band flux if not result[0]["F100um"].mask[0]: f100 = result[0][0]["F100um"] f100_error = ErrorBar(result[0][0]["e_F100um"]) sed.add_entry(self.filters["IRAS 100"], f100, f100_error) # Add the SED to the dictionary self.seds["GALEX"] = sed # ----------------------------------------------------------------- def get_2mass(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the 2MASS Extended Catalog ...") # 2MASS Extended Catalog: "VII/233/xsc": J, H, K (2006AJ....131.1163S) # Interesting columns: # # - "J.ext": J magnitude in r.ext (j_m_ext) [mag] # - "e_J.ext": σ(J.ext) (j_msig_ext) [mag] # - "H.ext": H magnitude in r.ext (h_m_ext) [mag] # - "e_H.ext": σ(H.ext) (h_msig_ext) [mag] # - "K.ext": J magnitude in r.ext (k_m_ext) [mag] # - "e_K.ext": σ(K.ext) (k_msig_ext) [mag] result = self.vizier.query_object(self.galaxy_name, catalog="VII/233/xsc") # Create an SED sed = ObservedSED() # In 2MASS magnitude system -> can be converted directly into Jy (see below) j_mag = result[0][0]["J.ext"] j_mag_error = result[0][0]["e_J.ext"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error h_mag = result[0][0]["H.ext"] h_mag_error = result[0][0]["e_H.ext"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error k_mag = result[0][0]["K.ext"] k_mag_error = result[0][0]["e_K.ext"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # J band flux j = unitconversion.photometry_2mass_mag_to_jy(j_mag, "J") j_lower = unitconversion.photometry_2mass_mag_to_jy(j_mag_upper, "J") j_upper = unitconversion.photometry_2mass_mag_to_jy(j_mag_lower, "J") j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H band flux h = unitconversion.photometry_2mass_mag_to_jy(h_mag, "H") h_lower = unitconversion.photometry_2mass_mag_to_jy(h_mag_upper, "H") h_upper = unitconversion.photometry_2mass_mag_to_jy(h_mag_lower, "H") h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # K band flux k = unitconversion.photometry_2mass_mag_to_jy(k_mag, "Ks") k_lower = unitconversion.photometry_2mass_mag_to_jy(k_mag_upper, "Ks") k_upper = unitconversion.photometry_2mass_mag_to_jy(k_mag_lower, "Ks") k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # Add the SED to the dictionary self.seds["2MASS"] = sed # ----------------------------------------------------------------- def get_sings(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the SINGS catalog ...") # Radial distribution in SINGS galaxies. I. # J/ApJ/703/1569/table1 (c)Sample (75 rows) # J/ApJ/703/1569/table2 UV, optical and NIR surface photometry profiles (2206 rows) # J/ApJ/703/1569/table3 UV, optical (SDSS) and NIR photometry profiles (2161 rows) # J/ApJ/703/1569/table4 IRAC and MIPS surface photometry (4319 rows) # J/ApJ/703/1569/table5 UV, optical, and near-IR asymptotic magnitudes for SINGS galaxies lacking SDSS data (43 rows) # J/ApJ/703/1569/table6 UV, optical (SDSS), and near-IR asymptotic magnitudes (32 rows) # J/ApJ/703/1569/table7 IRAC and MIPS asymptotic magnitudes (75 rows) # J/ApJ/703/1569/table8 Non-parametrical morphological estimators (300 rows) result = self.vizier.get_catalogs("J/ApJ/703/1569") # Result is a TableList with 8 tables (0 to 7) # We need: # - Table6 -> index 5 # - Table7 -> index 6 # Table6 # - "Name": Galaxy name (NGC ...) # - "FUV": GALEX FUV 0.153um-band AB magnitude [mag] # - "e_FUV": FUV uncertainty [mag] # - "NUV": GALEX NUV 0.227um-band AB magnitude [mag] # - "e_NUV": NUV uncertainty [mag] # - "umag": SDSS u-band 0.354um AB magnitude [mag] # - "e_umag": umag uncertainty [mag] # - "gmag": SDSS g-band 0.477um AB magnitude [mag] # - "e_gmag": gmag uncertainty [mag] # - "rmag": SDSS r-band 0.623um AB magnitude [mag] # - "e_rmag": rmag uncertainty [mag] # - "imag": SDSS i-band 0.762um AB magnitude [mag] # - "e_imag": imag uncertainty [mag] # - "zmag": SDSS z-band 0.913um AB magnitude [mag] # - "e_zmag": zmag uncertainty [mag] # - "Jmag": 2MASS J-band 1.25um AB magnitude [mag] # - "e_Jmag": Jmag uncertainty [mag] # - "Hmag": 2MASS H-band 1.65um AB magnitude [mag] # - "e_Hmag": Hmag uncertainty [mag] # - "Ksmag": 2MASS Ks-band 2.17um AB magnitude [mag] # - "e_Ksmag": Ksmag uncertainty [mag] # Find the row index that corresponds with the specified galaxy galaxy_index = tables.find_index(result[5], self.ngc_id) # FUV fuv_mag = result[5][galaxy_index]["FUV"] fuv_mag_error = result[5][galaxy_index]["e_FUV"] fuv_mag_lower = fuv_mag - fuv_mag_error fuv_mag_upper = fuv_mag + fuv_mag_error # NUV nuv_mag = result[5][galaxy_index]["NUV"] nuv_mag_error = result[5][galaxy_index]["e_NUV"] nuv_mag_lower = nuv_mag - nuv_mag_error nuv_mag_upper = nuv_mag + nuv_mag_error # u u_mag = result[5][galaxy_index]["umag"] u_mag_error = result[5][galaxy_index]["e_umag"] u_mag_lower = u_mag - u_mag_error u_mag_upper = u_mag + u_mag_error # g g_mag = result[5][galaxy_index]["gmag"] g_mag_error = result[5][galaxy_index]["e_gmag"] g_mag_lower = g_mag - abs(g_mag_error) g_mag_upper = g_mag + abs(g_mag_error) #print("gmag", g_mag) #print("gmagerror", g_mag_error) #print("gmaglower", g_mag_lower) #print("gmagupper", g_mag_upper) # r r_mag = result[5][galaxy_index]["rmag"] r_mag_error = result[5][galaxy_index]["e_rmag"] r_mag_lower = r_mag - r_mag_error r_mag_upper = r_mag + r_mag_error # i i_mag = result[5][galaxy_index]["imag"] i_mag_error = result[5][galaxy_index]["e_imag"] i_mag_lower = i_mag - i_mag_error i_mag_upper = i_mag + i_mag_error # z z_mag = result[5][galaxy_index]["zmag"] z_mag_error = result[5][galaxy_index]["e_zmag"] z_mag_lower = z_mag - z_mag_error z_mag_upper = z_mag + z_mag_error # J j_mag = result[5][galaxy_index]["Jmag"] j_mag_error = result[5][galaxy_index]["e_Jmag"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error # H h_mag = result[5][galaxy_index]["Hmag"] h_mag_error = result[5][galaxy_index]["e_Hmag"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error # Ks k_mag = result[5][galaxy_index]["Ksmag"] k_mag_error = result[5][galaxy_index]["e_Ksmag"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # Create an SED sed = ObservedSED() # FUV fuv = unitconversion.ab_to_jansky(fuv_mag) fuv_lower = unitconversion.ab_to_jansky(fuv_mag_upper) fuv_upper = unitconversion.ab_to_jansky(fuv_mag_lower) fuv_error = ErrorBar(fuv_lower, fuv_upper, at=fuv) sed.add_entry(self.filters["FUV"], fuv, fuv_error) # NUV nuv = unitconversion.ab_to_jansky(nuv_mag) nuv_lower = unitconversion.ab_to_jansky(nuv_mag_upper) nuv_upper = unitconversion.ab_to_jansky(nuv_mag_lower) nuv_error = ErrorBar(nuv_lower, nuv_upper, at=nuv) sed.add_entry(self.filters["NUV"], nuv, nuv_error) # u u = unitconversion.ab_to_jansky(u_mag) u_lower = unitconversion.ab_to_jansky(u_mag_upper) u_upper = unitconversion.ab_to_jansky(u_mag_lower) u_error = ErrorBar(u_lower, u_upper, at=u) sed.add_entry(self.filters["SDSS u"], u, u_error) # g g = unitconversion.ab_to_jansky(g_mag) g_lower = unitconversion.ab_to_jansky(g_mag_upper) g_upper = unitconversion.ab_to_jansky(g_mag_lower) g_error = ErrorBar(g_lower, g_upper, at=g) sed.add_entry(self.filters["SDSS g"], g, g_error) # r r = unitconversion.ab_to_jansky(r_mag) r_lower = unitconversion.ab_to_jansky(r_mag_upper) r_upper = unitconversion.ab_to_jansky(r_mag_lower) r_error = ErrorBar(r_lower, r_upper, at=r) sed.add_entry(self.filters["SDSS r"], r, r_error) # i i = unitconversion.ab_to_jansky(i_mag) i_lower = unitconversion.ab_to_jansky(i_mag_upper) i_upper = unitconversion.ab_to_jansky(i_mag_lower) i_error = ErrorBar(i_lower, i_upper, at=i) sed.add_entry(self.filters["SDSS i"], i, i_error) # z z = unitconversion.ab_to_jansky(z_mag) z_lower = unitconversion.ab_to_jansky(z_mag_upper) z_upper = unitconversion.ab_to_jansky(z_mag_lower) z_error = ErrorBar(z_lower, z_upper, at=z) sed.add_entry(self.filters["SDSS z"], z, z_error) # J j = unitconversion.ab_to_jansky(j_mag) j_lower = unitconversion.ab_to_jansky(j_mag_upper) j_upper = unitconversion.ab_to_jansky(j_mag_lower) j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H h = unitconversion.ab_to_jansky(h_mag) h_lower = unitconversion.ab_to_jansky(h_mag_upper) h_upper = unitconversion.ab_to_jansky(h_mag_lower) h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # Ks k = unitconversion.ab_to_jansky(k_mag) k_lower = unitconversion.ab_to_jansky(k_mag_upper) k_upper = unitconversion.ab_to_jansky(k_mag_lower) k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # Table7: IRAC and MIPS asymptotic magnitudes # - "logF3.6": Spitzer/IRAC 3.6um flux density [logJy] # - "e_logF3.6": logF3.6 uncertainty [logJy] # - "logF4.5": Spitzer/IRAC 4.5um flux density [logJy] # - "e_logF4.5": logF4.5 uncertainty [logJy] # - "logF5.8": Spitzer/IRAC 5.8um flux density [logJy] # - "e_logF5.8": logF5.8 uncertainty [logJy] # - "logF8.0": Spiter/IRAC 8.0um flux density [logJy] # - "e_logF8.0": logF8.0 uncertainty [logJy] # - "logF24": Spiter/MIPS 24um flux density [logJy] # - "e_logF24": logF24 uncertainty [logJy] # - "logF70": Spiter/MIPS 70um flux density [logJy] # - "e_logF70": logF70 uncertainty [logJy] # - "logF160": Spiter/MIPS 160um flux density [logJy] # - "e_logF160": logF160 uncertainty [logJy] # Table7 -> index 6 galaxy_index = tables.find_index(result[6], self.ngc_id) # 3.6 micron i1_log = result[6][galaxy_index]["logF3.6"] i1_log_error = result[6][galaxy_index]["e_logF3.6"] i1_log_lower = i1_log - i1_log_error i1_log_upper = i1_log + i1_log_error # 4.5 micron i2_log = result[6][galaxy_index]["logF4.5"] i2_log_error = result[6][galaxy_index]["e_logF4.5"] i2_log_lower = i2_log - i2_log_error i2_log_upper = i2_log + i2_log_error # 5.8 micron i3_log = result[6][galaxy_index]["logF5.8"] i3_log_error = result[6][galaxy_index]["e_logF5.8"] i3_log_lower = i3_log - i3_log_error i3_log_upper = i3_log + i3_log_error # 8.0 micron i4_log = result[6][galaxy_index]["logF8.0"] i4_log_error = result[6][galaxy_index]["e_logF8.0"] i4_log_lower = i4_log - i4_log_error i4_log_upper = i4_log + i4_log_error #print("i4log", i4_log) #print("i4_log_error", i4_log_error) #print("i4_log_lower", i4_log_lower) #print("i4_log_upper", i4_log_upper) # 24 micron mips24_log = result[6][galaxy_index]["logF24"] mips24_log_error = result[6][galaxy_index]["e_logF24"] mips24_log_lower = mips24_log - mips24_log_error mips24_log_upper = mips24_log + mips24_log_error # 70 micron mips70_log = result[6][galaxy_index]["logF70"] mips70_log_error = result[6][galaxy_index]["e_logF70"] mips70_log_lower = mips70_log - mips70_log_error mips70_log_upper = mips70_log + mips70_log_error # 160 micron mips160_log = result[6][galaxy_index]["logF160"] mips160_log_error = result[6][galaxy_index]["e_logF160"] mips160_log_lower = mips160_log - mips160_log_error mips160_log_upper = mips160_log + mips160_log_error # Calculate data points and errobars in Janskys, add to the SED # 3.6 micron i1 = 10.**i1_log i1_lower = 10.**i1_log_lower i1_upper = 10.**i1_log_upper i1_error = ErrorBar(i1_lower, i1_upper, at=i1) sed.add_entry(self.filters["I1"], i1, i1_error) # 4.5 micron i2 = 10.**i2_log i2_lower = 10.**i2_log_lower i2_upper = 10.**i2_log_upper i2_error = ErrorBar(i2_lower, i2_upper, at=i2) sed.add_entry(self.filters["I2"], i2, i2_error) # 5.8 micron i3 = 10.**i3_log i3_lower = 10.**i3_log_lower i3_upper = 10.**i3_log_upper i3_error = ErrorBar(i3_lower, i3_upper, at=i3) sed.add_entry(self.filters["I3"], i3, i3_error) # 8.0 micron i4 = 10.**i4_log i4_lower = 10.**i4_log_lower i4_upper = 10.**i4_log_upper i4_error = ErrorBar(i4_lower, i4_upper, at=i4) sed.add_entry(self.filters["I4"], i4, i4_error) # 24 micron mips24 = 10.**mips24_log mips24_lower = 10.**mips24_log_lower mips24_upper = 10.**mips24_log_upper mips24_error = ErrorBar(mips24_lower, mips24_upper, at=mips24) sed.add_entry(self.filters["MIPS 24"], mips24, mips24_error) # 70 micron mips70 = 10.**mips70_log mips70_lower = 10.**mips70_log_lower mips70_upper = 10.**mips70_log_upper mips70_error = ErrorBar(mips70_lower, mips70_upper, at=mips70) sed.add_entry(self.filters["MIPS 70"], mips70, mips70_error) # 160 micron mips160 = 10.**mips160_log mips160_lower = 10.**mips160_log_lower mips160_upper = 10.**mips160_log_upper mips160_error = ErrorBar(mips160_lower, mips160_upper, at=mips160) sed.add_entry(self.filters["MIPS 160"], mips160, mips160_error) # Add the SED to the dictionary self.seds["SINGS"] = sed # ----------------------------------------------------------------- def get_lvl(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the LVL catalog ...") # Create an SED sed = ObservedSED() # "J/MNRAS/445/881": LVL global optical photometry (Cook+, 2014) # - "J/MNRAS/445/881/sample": Galaxies of the Spitzer Local Volume Legacy (LVL): properties (table1) and R25 photometry # - "J/MNRAS/445/881/table3": Photometry within the IR apertures of Dale et al. (2009, Cat. J/ApJ/703/517) (258 rows) # - "J/MNRAS/445/881/table4": Photometry within the UV apertures of Lee et al. (2011, Cat. J/ApJS/192/6) (258 rows) result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/445/881/sample") # ALL IN AB MAGNITUDE SYSTEM # Umag # Bmag # Vmag # Rmag # umag # gmag # rmag # imag # zmag # On SimBad, only sdss bands are used, from /sample ... relevant_bands = [("U", "U"), ("B", "B"), ("V", "V"), ("R", "R"), ("u", "SDSS u"), ("g", "SDSS g"), ("r", "SDSS r"), ("i", "SDSS i"), ("z", "SDSS z")] for band_prefix_catalog, filter_name in relevant_bands: column_name = band_prefix_catalog + "mag" error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # AB magnitude magnitude = result[0][0][column_name] magnitude_error = result[0][0][error_column_name] magnitude_lower = magnitude - magnitude_error magnitude_upper = magnitude + magnitude_error # Convert to Jy fluxdensity = unitconversion.ab_to_jansky(magnitude) fluxdensity_lower = unitconversion.ab_to_jansky(magnitude_upper) fluxdensity_upper = unitconversion.ab_to_jansky(magnitude_lower) fluxdensity_error = ErrorBar(fluxdensity_lower, fluxdensity_upper, at=fluxdensity) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["LVL"] = sed # ----------------------------------------------------------------- def get_spitzer(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the Spitzer catalog ...") # "J/ApJ/703/517": The Spitzer Local Volume Legacy: IR photometry (Dale+, 2009) # "J/ApJ/703/517/sample": Galaxy sample (table 1) and infrared flux densities (table 2) (258 rows) # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/703/517/sample") # F1.25: 2MASS J band (1.25 micron) flux density [Jy] # e_F1.25: Uncertainty in F1.25 [Jy] # F1.65: 2MASS H band (1.65 micron) flux density [Jy] # e_F1.65: Uncertainty in F1.65 [Jy] # F2.17: 2MASS Ks band (2.17 micron) flux density [Jy] # e_F2.17: Uncertainty in F2.17 [Jy] # F3.6: Spitzer/IRAC 3.5 micron band flux density [Jy] # e_F3.6: Uncertainty in F3.6 [Jy] # F4.5: Spitzer/IRAC 4.5 micron band flux density [Jy] # e_F4.5: Uncertainty in F4.5 [Jy] # F5.8: Spitzer/IRAC 5.8 micron band flux density [Jy] # e_F5.8: Uncertainty in F5.8 [Jy] # F8.0: Spitzer/IRAC 8.0 micron band flux density [Jy] # e_F8.0: Uncertainty in F8.0 [Jy] # F24: Spitzer/MIPS 24 micron flux density [Jy] # e_F24: Uncertainty in F24 [Jy] # F70: Spitzer/MIPS 70 micron band flux density [Jy] # e_F70: Uncertainty in F70 [Jy] # F160: Spitzer/MIPS 160 micron band flux density [Jy] # e_F160: Uncertainty in F160 [Jy] relevant_bands = [("1.25", "J"), ("1.65", "H"), ("2.17", "K"), ("3.6", "I1"), ("4.5", "I2"), ("5.8", "I3"), ("8.0", "I4"), ("24", "MIPS 24"), ("70", "MIPS 70"), ("160", "MIPS 160")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F" + band_prefix_catalog error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(result[0][0][error_column_name]) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["Spitzer"] = sed # ----------------------------------------------------------------- def get_spitzer_irs(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the Spitzer/IRS catalog ...") # "J/MNRAS/414/500": Spitzer/IRS ATLAS project source (Hernan-Caballero+, 2011) # - "J/MNRAS/414/500/catalog": Spitzer/IRS ATLAS project source catalog, version 1.0 (739 rows) # !! Parentheses () are converted into underscores _ in the resulting Astropy tables!! # F(3.6): IRAC1 (3.6um) flux density [Jy] # e_F(3.6): rms uncertainty on F(3.6) [Jy] # F(8.0): IRAC4 (8.0um) flux density [Jy] # e_F(8.0): rms uncertainty on F(8.0) [Jy] # F(24): 24um flux density [Jy] # e_F(24): rms uncertainty on F(24) [Jy] # F(70): 70um or similar band flux density [Jy] # e_F(70): rms uncertainty on F(70) [Jy] # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/414/500/catalog") relevant_bands = [("3.6", "I1"), ("8.0", "I4"), ("24", "MIPS 24"), ("70", "MIPS 70")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F_" + band_prefix_catalog + "_" error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(result[0][0][error_column_name]) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["Spitzer-IRS"] = sed # ----------------------------------------------------------------- def get_iras(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the IRAS catalog ...") # "J/ApJS/178/280": Compendium of ISO far-IR extragalactic data (Brauher+, 2008) # - "J/ApJS/178/280/table1": *Galaxies and properties # F12: IRAS 12um band flux density [Jy] # F25: IRAS 25um band flux density [Jy] # F60: IRAS 60um band flux density [Jy] # F100: IRAS 100um band flux density [Jy] # No errors ... # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJS/178/280/table1") relevant_bands = [("12", "IRAS 12"), ("25", "IRAS 25"), ("60", "IRAS 60"), ("100", "IRAS 100")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F" + band_prefix_catalog # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS"] = sed # ----------------------------------------------------------------- def get_iras_fsc(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the IRAS-FSC catalog ...") # "J/MNRAS/398/109": Imperial IRAS-FSC redshift catalogue (IIFSCz) (Wang+, 2009) # - "J/MNRAS/398/109/iifsczv4": IIFSCz Catalogue (MRR+LW 18/04/09)[spectrum/SED] (60303 rows) # S12um: IRAS-FSC flux at 12um [Jy] # S25um: IRAS-FSC flux at 25um [Jy] # S60um: IRAS-FSC flux at 60um [Jy] # S100um: IRAS-FSC flux at 100um [Jy] # not used in Simbad: # umag: SDSS u magnitude [mag: which system??] # e_umag: # gmag: # e_gmag: # rmag: # e_rmag: # imag: # e_imag: # zmag: # e_zmag: # Jmag: 2MASS J magnitude [mag: which system??] # e_Jmag: rms uncertainty on Jmag [mag: which system??] # Hmag: 2MASS H magnitude [mag] # e_Hmag: rms uncertainty on Hmag [mag] # Kmag: 2MASS K magnitude [mag] # e_Kmag rms uncertainty on Kmag [mag] # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/398/109/iifsczv4") relevant_bands = [("12", "IRAS 12"), ("25", "IRAS 25"), ("60", "IRAS 60"), ("100", "IRAS 100")] for band_prefix_catalog, filter_name in relevant_bands: # Flux and error already in Jy fluxdensity = result[0][0]["S" + band_prefix_catalog + "um"] fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS-FSC"] = sed # ----------------------------------------------------------------- def get_s4g(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # Get parameters from S4G catalog result = self.vizier.query_object(self.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Magnitudes i1_mag = table["__3.6_"][0] i2_mag = table["__4.5_"][0] i1_mag_error = table["e__3.6_"][0] i2_mag_error = table["e__4.5_"][0] i1_fluxdensity = unitconversion.ab_to_jansky(i1_mag) i1_fluxdensity_lower = unitconversion.ab_to_jansky(i1_mag + i1_mag_error) i1_fluxdensity_upper = unitconversion.ab_to_jansky(i1_mag - i1_mag_error) i1_error = ErrorBar(i1_fluxdensity_lower, i1_fluxdensity_upper, at=i1_fluxdensity) # Add data point to SED sed.add_entry(self.filters["I1"], i1_fluxdensity, i1_error) i2_fluxdensity = unitconversion.ab_to_jansky(i2_mag) i2_fluxdensity_lower = unitconversion.ab_to_jansky(i2_mag + i2_mag_error) i2_fluxdensity_upper = unitconversion.ab_to_jansky(i2_mag - i2_mag_error) i2_error = ErrorBar(i2_fluxdensity_lower, i2_fluxdensity_upper, at=i2_fluxdensity) # Add data point to SED sed.add_entry(self.filters["I2"], i2_fluxdensity, i2_error) # Add the SED to the dictionary self.seds["S4G"] = sed # ----------------------------------------------------------------- def get_brown(self): """ This function ... :return: """ # J/ApJS/212/18/sample # AB magnitudes for the sample with neither foreground nor intrinsic dust extinction corrections, and modeled Milky Way foreground dust extinction # Create an SED sed = ObservedSED() # FUV: [12.5/22.9] GALEX FUV AB band magnitude # e_FUV: # UVW2: # e_UVW2: # UVM2: # e_UVM2: # NUV: # e_NUV: # UVW1: # e_UVW1: # Umag: [11.9/15.7] Swift/UVOT U AB band magnitude # e_Umag: # umag: # e_umag: # gmag: # e_gmag: # Vmag: # e_Vmag: # rmag: # e_rmag: # imag: # e_imag: # zmag: # e_zmag: # Jmag: # e_Jmag: # Hmag: # e_Hmag: # Ksmag: # e_Ksmag: # W1mag: # e_W1mag: # [3.6]: # e_[3.6]: # [4.5]: # e_[4.5]: # W2mag: # e_W2mag: # [5.8]: # e_[5.8]: # [8.0]: # e_[8.0]: # W3mag: # e_W3mag: # W4mag: # e_W4mag: # W4'mag: Corrected WISE W4 AB band magnitude # e_W4'mag: # [24]: # e_[24]: pass # ----------------------------------------------------------------- def get_planck(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # The second release is not yet available ... ?? # ----------------------------------------------------------------- def get_emission_lines(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # J/ApJS/190/233/Opt # Get result result = self.vizier.get_catalogs("J/ApJS/190/233/Opt") table = result[0] galaxy_index = tables.find_index(table, self.ngc_id, "Name") # FHa: The Hα 6563 Angstrom line flux (aW/m2) # e_FHa: Uncertainty in Ha (aW/m2) # FNII: The [NII] 6584Å line flux (aW/m2) # e_FNII: Uncertainty in NII (aW/m2) # H alpha ha_flux = table["FHa"][galaxy_index] * Unit("aW/m2") ha_flux_error = table["e_FHa"][galaxy_index] * Unit("aW/m2") # NII n2_flux = table["FNII"][galaxy_index] * Unit("aW/m2") n2_flux_error = table["e_FNII"][galaxy_index] * Unit("aW/m2") ha_filter = self.filters["Ha"] ha_wavelength = ha_filter.centerwavelength() * Unit("micron") ha_frequency = ha_wavelength.to("Hz", equivalencies=spectral()) # Calculate flux density ha_fluxdensity = (ha_flux / ha_frequency).to("Jy") ha_fluxdensity_error = (ha_flux_error / ha_frequency).to("Jy") ha_errorbar = ErrorBar(ha_fluxdensity_error) # Add entry sed.add_entry(ha_filter, ha_fluxdensity, ha_errorbar) # Add the SED to the dictionary self.seds["Lines"] = sed # ----------------------------------------------------------------- def get_m81(self): """ This function ... :return: """ # UV through far-IR analysis of M81 (Perez-Gonzalez+, 2006) # "J/ApJ/648/987" # Two tables: # - "J/ApJ/648/987/table1": Positions and photometry (GLOBALBKG and LOCALBKG cases) for the regions selected at 160um resolution # - "J/ApJ/648/987/table2": Positions and photometry for the regions selected at 24um resolution # Table 1 #result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/648/987/table1") # Looks like this (only 3 matches) #1 M81 09 55 32.2 +69 03 59.0 680.0 40.78 43.18 42.84 42.63 42.61 41.98 42.67 42.99 #2 Reg02 09 55 32.2 +69 03 59.0 64.0 39.67 42.63 42.28 41.98 41.76 41.25 41.83 41.78 #3 Reg03 09 55 32.2 +69 03 59.0 104.0 39.40 42.38 42.03 41.76 41.58 40.90 41.62 41.78 #galaxy_index = tables.find_index(result, self.galaxy_name) # Table 2 # Interesting rows: # - logLFUV: Log of the FUV luminosity [1e-7 W] or [erg/s] # - logLNUV: Log of the NUV luminosity [1e-7 W] or [erg/s] # - logLHa: Log of the H-alpha luminosity [1e-7 W] or [erg/s] # - logL8: Log of the 8um luminosity [1e-7 W] or [erg/s] # - logL24: Log of the 24um luminosity [1e-7 W] or [erg/s] result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/648/987/table2") galaxy_index = tables.find_index(result[0], self.galaxy_name) # Create an SED sed = ObservedSED() relevant_bands = [("FUV", "FUV"), ("NUV", "NUV"), ("Ha", "Ha"), ("8", "I4"), ("24", "MIPS 24")] for band_prefix_catalog, filter_name in relevant_bands: # Flux and error already in Jy log = result[0][galaxy_index]["logL" + band_prefix_catalog] flux = 10.**log # In erg/s frequency = 0.0 # TODO: calculate this! # Also: calculate the amount of flux per unit area ! : divide also by 4 pi d_galaxy**2 ! fluxdensity = flux / frequency fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS-FSC"] = sed # ----------------------------------------------------------------- def write(self): """ This function ... :return: """ # Inform the user log.info("Writing ...") # If requested, write out the SEDs if self.config.write_seds: self.write_seds() # ----------------------------------------------------------------- def write_seds(self): """ This function ... :return: """ # Inform the user log.info("Writing the SEDs ...") # Determine the full path to the SEDs directory path = self.full_output_path(self.config.writing.seds_path) # Create the SEDs directory if necessary fs.create_directory(path) # Loop over the different SEDs for label in self.seds: # Debugging info log.debug("Writing SED from " + label) # Determine the path to the new SED file sed_path = fs.join(path, label + ".dat") # Save the SED at the specified location self.seds[label].save(sed_path)
from astroquery.vizier import Vizier v = Vizier(columns=['Vmag', 'b-y','m1','c1','Beta'], catalog="II/215/catalog") result = v.query_object('HD 48915')[0][0] print (result)
def find_location_gs(source_name, source_alt_az, minute, hour, day, month, year, plot_grids=True): """Find out where we are on Earth. Args: source_name (str): source_ra_dec (tuple of floats): minute, hour, day, month, year (ints): Returns: lat_long (tuple of floats): your location. """ alt, az = source_alt_az source_obj = Vizier.query_object(source_name, catalog='V/50')[0] source_ra_dec = (source_obj['RAJ2000'][0], source_obj['DEJ2000'][0]) source_ra_hms = tuple(map(float, source_ra_dec[0].split())) source_dec_dms = tuple(map(float, source_ra_dec[1].split())) source_ra = Angle(source_ra_hms, unit='hourangle').degree source_dec = Angle(source_dec_dms, unit=u.deg).degree lats = np.arange(-90., 90, res) longs = np.arange(-180, 180, res) ra_grid = np.zeros((len(lats), len(longs))) dec_grid = np.zeros((len(lats), len(longs))) score_grid = np.zeros((len(lats), len(longs))) # Run the grid lat_counter, long_counter = 0, 0 for i in range(len(lats)): for j in range(len(longs)): # Need to sort out angular units lat, long = lats[i], longs[j] ra, dec = altaz_to_radec((alt, az), pos=(lat, long), minute=minute, hour=hour, day=day, month=month, year=year, tz_offset=5) # pos_grid[i, j] = {'RA': ra, 'DEC': dec} ra_grid[i, j] = ra dec_grid[i, j] = dec # Bad - planar: score = np.sqrt((ra - source_ra)**2 + (dec - source_dec)**2) # Good - spherical: # score = np.arccos(np.sin(dec) * np.sin(source_dec) + np.cos(dec) * np.cos(source_dec) * np.cos(abs(ra - source_ra))) score_grid[i, j] = score verbose = False if verbose is True: print('RA, Source RA:', ra, source_ra) print('DEC, Source DEC:', dec, source_dec) print('Score:', score) print('\n') else: step = long_counter + lat_counter * len(lats) print (str(step) + '/' + str(len(lats) * len(longs))) long_counter += 1 outname = 'latlong-gridsearch-results_' + str(res) score_df = pd.DataFrame(score_grid) score_df.to_csv(outname + '.csv') if plot_grids is True: lat_coord = (90 + local_latlong[0]) * res long_coord = (180 + local_latlong[1]) * res plt.contour(score_grid) plt.plot([lat_coord], [long_coord], 'or') plt.matshow(score_grid, cmap='magma') xtick_locs = np.arange(0, len(longs), len(longs)/6) xtick_labs = [int(longs[i]) for i in xtick_locs] plt.xticks(xtick_locs, xtick_labs) # plt.ylim(max(lats), min(lats)) ytick_locs = np.arange(0, len(lats), len(lats)/10) ytick_labs = [int(lats[i]) for i in ytick_locs] plt.yticks(ytick_locs, ytick_labs) plt.savefig(outname + '.png', dpi=200) plt.show(block=False) return {'RA': ra_grid, 'DEC': dec_grid, 'SCORE': score_grid}
def find_location(source_name, source_alt_az, minute=minute_now, hour=hour_now, day=day_now, month=month_now, year=year_now, plot_grids=True): """Find out where we are on Earth. Args: source_name (str): source_ra_dec (tuple of floats): minute, hour, day, month, year (ints): Returns: lat_long (tuple of floats): your location. """ alt, az = source_alt_az source_obj = Vizier.query_object(source_name, catalog='V/50')[0] source_ra_dec = (source_obj['RAJ2000'][0], source_obj['DEJ2000'][0]) source_ra_hms = tuple(map(float, source_ra_dec[0].split())) source_dec_dms = tuple(map(float, source_ra_dec[1].split())) source_ra = Angle(source_ra_hms, unit='hourangle').degree source_dec = Angle(source_dec_dms, unit=u.deg).degree lat_crit = 0.01 step = 20 lats = np.linspace(-90, 90, step) longs = np.linspace(-180., 180., 2*step) lat_min, lat_max = 0, len(lats) - 1 long_min, long_max = 0, len(longs) - 1 real_lat, real_long = 41.55, -72.65 counter = 0 while abs(lats[1] - lats[0]) > lat_crit: lats = np.linspace(lats[lat_min], lats[lat_max], step) longs = np.linspace(longs[long_min], longs[long_max], 2*step) score_grid = np.zeros((len(lats), len(longs))) # Run the grid for i in range(len(lats)): for j in range(len(longs)): lat, long = lats[i], longs[j] ra, dec = altaz_to_radec((alt, az), pos=(lat, long), minute=minute, hour=hour, day=day, month=month, year=year, tz_offset=5) score = np.sqrt((ra - source_ra)**2 + (dec - source_dec)**2) score_grid[i, j] = score idx = np.where(score_grid == np.nanmin(score_grid)) lat_min = idx[0][0] - 2 if idx[0][0] > 1 else 0 lat_max = idx[0][0] + 2 if idx[0][0] < len(lats) - 2 else len(lats) - 1 long_min = idx[1][0] - 2 if idx[1][0] > 1 else 0 long_max = idx[1][0] + 2 if idx[1][0] < len(longs) - 2 else len(longs) - 1 plt.matshow(score_grid, cmap='magma_r') plt.contour(score_grid, cmap='magma') xtick_locs = np.arange(0, len(longs), len(longs)/6) xtick_labs = [int(longs[i]) for i in xtick_locs] plt.xticks(xtick_locs, xtick_labs) ytick_locs = np.arange(0, len(lats), len(lats)/6) ytick_labs = [int(lats[i]) for i in ytick_locs] plt.yticks(ytick_locs, ytick_labs) i, j = 0, 0 while longs[i] < real_long and i < len(longs) - 1: i += 1 while lats[j] < real_lat and j < len(lats) - 1: j += 1 print i, j if i != 0 and j != 0 and i != len(longs) and i != len(lats): plt.plot([i], [j], 'or') plt.savefig('window-evolution' + str(counter) + '.png') plt.close counter += 1 return (lats[idx[0][0]], longs[idx[1][0]]) outname = 'latlong-gridsearch-results_' + str(res) score_df = pd.DataFrame(score_grid) score_df.to_csv(outname + '.csv') if plot_grids is True: lat_coord = (90 + local_latlong[0]) * res long_coord = (180 + local_latlong[1]) * res plt.contour(score_grid) plt.plot([lat_coord], [long_coord], 'or') plt.matshow(score_grid, cmap='magma') xtick_locs = np.arange(0, len(longs), len(longs)/6) xtick_labs = [int(longs[i]) for i in xtick_locs] plt.xticks(xtick_locs, xtick_labs) # plt.ylim(max(lats), min(lats)) ytick_locs = np.arange(0, len(lats), len(lats)/10) ytick_labs = [int(lats[i]) for i in ytick_locs] plt.yticks(ytick_locs, ytick_labs) plt.savefig(outname + '.png', dpi=200) plt.show(block=False) return {'RA': ra_grid, 'DEC': dec_grid, 'SCORE': score_grid}
from astroquery.simbad import Simbad S = Simbad() S.add_votable_fields('rv_value') dir = sys.argv[1] files = glob.glob(dir + '/*p08.fits') templates = glob.glob('/home/rajikak/tools/RV_standards/*') print("*************") for file in files: a = pyfits.open(file) object_name = a[1].header['OBJNAME'] #get RV data on the standard: #From Vizier table: result = Vizier.query_object(object_name) interesting_table = result['J/ApJS/141/503/table1'] object_RV = float(interesting_table[0]['__RV_']) / 1000. flux_stamp, wave = ps.read_and_find_star_p08(file) spectrum, sig = ps.weighted_extract_spectrum(flux_stamp) rv, rv_sig = ps.calc_rv_template(spectrum, wave, sig, templates, ([0, 5400], [6870, 6890])) rv += a[1].header['RADVEL'] print("object_name: " + object_name) print("object RV: " + str(object_RV) + "km/s") print("Retrieved RV from standards: " + str(rv) + "km/s") print("*************")
def vizier_query(obj, params=True, method='both', coordinate=False): """Give mean/median values of some parameters for an object. This script use VizieR for looking up the object. :obj: The object to query (e.g. HD20010). :parama: Extra parameters to look for (default is Teff, logg, __Fe_H_). :method: Print median, main or both :returns: A dictionary with the parameters """ with warnings.catch_warnings(): warnings.simplefilter('ignore') cat = Vizier.query_object(obj) if coordinate: for c in cat: try: ra = c['RAJ2000'][0] dec = c['DEJ2000'][0] except KeyError: ra = 0 if ra != 0: break print('\n\n%s %s %s' % (obj, ra, dec)) else: print('\n\nObject: %s' % obj) parameters = {'Teff': [], 'logg': [], '__Fe_H_': []} if params: params=['Teff', 'logg', '__Fe_H_'] for param in params: parameters[param] = [] for ci in cat: for column in parameters.keys(): try: parameters[column].append(ci[column].quantity) except (TypeError, KeyError): pass for key in parameters.keys(): pi = parameters[key] parameters[key] = _q2a(pi) if len(parameters[key]): mean = round(np.nanmean(parameters[key]), 2) median = round(np.nanmedian(parameters[key]), 2) else: mean = 'Not available' median = 'Not available' if key.startswith('__'): key = '[Fe/H]' if method == 'mean': print('\n%s:\tMean value: %s' % (key, mean)) elif method == 'median': print('\n%s\tMedian value: %s' % (key, median)) else: print('\n%s:\tMean value: %s' % (key, mean)) print('%s:\tMedian value: %s' % (key, median)) return parameters, cat
class SEDFetcher(OldConfigurable): """ This class ... """ def __init__(self, config=None): """ The constructor ... """ # Call the constructor of the base class super(SEDFetcher, self).__init__(config, "modeling") # -- Attributes -- # The name of the galaxy self.galaxy_name = None # The NGC ID of the galaxy self.ngc_id = None # The Vizier querying object self.vizier = Vizier(keywords=["galaxies"]) self.vizier.ROW_LIMIT = -1 # The observed SED self.seds = dict() # The filters self.filters = dict() # ----------------------------------------------------------------- @classmethod def from_arguments(cls, arguments): """ This function ... :param arguments: :return: """ # Create a new SEDFetcher instance if arguments.config is not None: fetcher = cls(arguments.config) elif arguments.settings is not None: fetcher = cls(arguments.settings) else: fetcher = cls() # Set the output path if arguments.output_path is not None: fetcher.config.output_path = arguments.output_path # Run from the command line, so always write out the SEDs fetcher.config.write_seds = True fetcher.config.writing.seds_path = "SEDs" # Return the new instance return fetcher # ----------------------------------------------------------------- def run(self, galaxy_name): """ This function ... :param galaxy_name """ # 1. Call the setup function self.setup(galaxy_name) # 2. If requested, query the GALEX ultraviolet atlas of nearby galaxies catalog (Gil de Paz+, 2007) if "GALEX" in self.config.catalogs: self.get_galex() # 3. If requested, query the 2MASS Extended sources catalog (IPAC/UMass, 2003-2006) if "2MASS" in self.config.catalogs: self.get_2mass() # SDSS ? # Ilse "Voor de galaxieen in de noordelijke hemisfeer heb je SDSS data beschikbaar, en die kan je dan # beter gebruiken (ipv. SINGS) om je fit te constrainen in het optische gebied. Er zal binnenkort een nieuwe # paper van Daniel Dale uitkomen met gehercalibreerde fluxen in de optische banden, die je dan kan gebruiken. # 5. If requested, query the Radial distribution in SINGS galaxies (I.) catalogs (Munoz-Mateos+, 2009) # Opm. Ilse: "voor vele SINGS galaxieen is de calibratie van de optische data heel slecht, dus krijg je een # offset en datapunten die een beetje random blijken te zijn." if "SINGS" in self.config.catalogs: self.get_sings() # If requested, query the LVL global optical photometry (Cook+, 2014) catalog if "LVL" in self.config.catalogs: self.get_lvl() # If requested, query the Spitzer Local Volume Legacy: IR photometry (Dale+, 2009) if "Spitzer" in self.config.catalogs: self.get_spitzer() # If requested, query the Spitzer/IRS ATLAS project source (Hernan-Caballero+, 2011) if "Spitzer/IRS" in self.config.catalogs: self.get_spitzer_irs() # If requested, query the Compendium of ISO far-IR extragalactic data (Brauher+, 2008) if "IRAS" in self.config.catalogs: self.get_iras() # If requested, query the Imperial IRAS-FSC redshift catalogue (IIFSCz) (Wang+, 2009) if "IRAS-FSC" in self.config.catalogs: self.get_iras_fsc() # If requested, query the S4G catalog for IRAC fluxes if "S4G" in self.config.catalogs: self.get_s4g() # If requested, query the Spectroscopy and abundances of SINGS galaxies (Moustakas+, 2010) catalog if "Emission lines" in self.config.catalogs: self.get_emission_lines() # If requested, query the Atlas of UV-to-MIR galaxy SEDs (Brown+, 2014) if "Brown" in self.config.catalogs: self.get_brown() # If requested, query the Planck Catalog of Compact Sources Release 1 (Planck, 2013) if "Planck" in self.config.catalogs: self.get_planck() # SPECIFIC for M81: not enabled, no time to figure out the unit conversion now #if self.ngc_id == "NGC 3031": self.get_m81() # Other interesting catalogs: # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/199/22 # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/212/18/sample&-c=NGC%203031&-c.u=arcmin&-c.r=2&-c.eq=J2000&-c.geom=r&-out.max=50&-out.form=HTML%20Table&-oc.form=sexa # http://vizier.cfa.harvard.edu/viz-bin/VizieR-3?-source=J/ApJS/220/6 # Writing self.write() # ----------------------------------------------------------------- def setup(self, galaxy_name): """ This function ... :param galaxy_name: :return: """ # Call the setup function of the base class super(SEDFetcher, self).setup() # Set the galaxy name self.galaxy_name = galaxy_name # Get the NGC ID of the galaxy self.ngc_id = catalogs.get_ngc_name(self.galaxy_name) # Create a dictionary of filters keys = [ "Ha", "FUV", "NUV", "U", "B", "V", "R", "J", "H", "K", "IRAS 12", "IRAS 25", "IRAS 60", "IRAS 100", "I1", "I2", "I3", "I4", "MIPS 24", "MIPS 70", "MIPS 160", "SDSS u", "SDSS g", "SDSS r", "SDSS i", "SDSS z" ] for key in keys: self.filters[key] = Filter.from_string(key) # ----------------------------------------------------------------- def get_galex(self): """ This function ... :return: """ # Inform the user log.info( "Getting fluxes from the GALEX ultraviolet atlas of nearby galaxies ..." ) # GALEX: "J/ApJS/173/185" of "J/ApJS/173/185/galex": B and V (2007ApJS..173..185G) # Interesting columns: # # - "MajAxis": Major-axis diameter of the D25 ellipse [arcmin] # - "MinAxis": Minor-axis diameter of the D25 ellipse [arcmin] # - "PA": Position angle of the D25 ellipse [deg] # - "Dist": Distance to the galaxy [Mpc] # - "Morph": Morphological type # - "T": Morphological type T # - "FUV": FUV (120-177nm) image mean sky background [ct/s] # - "sigFUV": Mean standard deviation of the FUV sky. Note (2): Measured by averaging the standard deviation within several regions around the position of the object. [ct/s] # - "e_FUV": The standard deviation of the mean FUV sky [ct/s] # - "NUV": Mean NUV (177-300nm) sky background [ct/s] # - "sigNUV": Mean standard deviation of the NUV sky [ct/s] # - "e_NUV": The standard deviation of the mean NUV sky [ct/s] # - "D25FUV": Observed D25 ellipse FUV band AB magnitude [mag] # - "e_D25FUV": Uncertainty in D25FUV [mag] # - "D25NUV": Observed D25 ellipse NUV band AB magnitude [mag] # - "e_D25NUV": Uncertainty in D25NUV [mag] # - "AFUV": Foreground FUV extinction [mag] # - "ANUV": Foreground NUV extinction [mag] # - "asyFUV": Observed asymptotic FUV (120-177nm) AB magnitude [mag] # - "e_asyFUV": Uncertainty in asyFUV [mag] # - "asyNUV": Observed asymptotic NUV (177-300nm) AB magnitude [mag] # - "e_asyNUV": Uncertainty in asyNUV [mag] # - "logFUV": Log of the FUV (120-177nm) luminosity [W] # - "logNUV": Log of the NUV (177-300nm) luminosity [W] # - "Umag": Johnson U band integrated magnitude [mag] Note (1): In the Vega scale. Published as part of the RC3 catalog, Cat. VII/155) # - "e_Umag": Uncertainty in Umag [mag] # - "Bmag": Johnson B band integrated magnitude [mag] # - "e_Bmag": Uncertainty in Bmag [mag] # - "Vmag": Johnson V band integrated magnitude [mag] # - "e_Vmag": Uncertainty in Vmag [mag] # - "Jmag": 2MASS J band total magnitude [mag] # - "e_Jmag": Uncertainty in Jmag [mag] # - "Hmag": 2MASS H band total magnitude [mag] # - "e_Hmag": Uncertainty in Hmag [mag] # - "Kmag": 2MASS K band total magnitude [mag] # - "e_Kmag": Uncertainty in Kmag [mag] # - "F12um": IRAS 12 micron flux density [Jy] # - "e_F12um": Uncertainty in F12um [Jy] # - "F25um": IRAS 25 micron flux density [Jy] # - "e_F25um": Uncertainty in F25um [Jy] # - "F60um": IRAS 60 micron flux density [Jy] # - "e_F60um": Uncertainty in F60um [Jy] # - "F100um": IRAS 100 micron flux density [Jy] # - "e_F100um": Uncertainty in F100um [Jy] result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJS/173/185/galex") # Result is a list of tables, we only have one table with one entry # Create an SED sed = ObservedSED() # All AB magnitudes # FUV -- if not result[0]["asyFUV"].mask[0]: fuv_mag = result[0]["asyFUV"][0] fuv_mag_error = result[0][0]["e_asyFUV"] fuv_mag_lower = fuv_mag - fuv_mag_error fuv_mag_upper = fuv_mag + fuv_mag_error # flux fuv = unitconversion.ab_to_jansky(fuv_mag) fuv_lower = unitconversion.ab_to_jansky(fuv_mag_upper) fuv_upper = unitconversion.ab_to_jansky(fuv_mag_lower) fuv_error = ErrorBar(fuv_lower, fuv_upper, at=fuv) sed.add_entry(self.filters["FUV"], fuv, fuv_error) # NUV -- if not result[0]["asyNUV"].mask[0]: nuv_mag = result[0][0]["asyNUV"] nuv_mag_error = result[0][0]["e_asyNUV"] nuv_mag_lower = nuv_mag - nuv_mag_error nuv_mag_upper = nuv_mag + nuv_mag_error # flux nuv = unitconversion.ab_to_jansky(nuv_mag) nuv_lower = unitconversion.ab_to_jansky(nuv_mag_upper) nuv_upper = unitconversion.ab_to_jansky(nuv_mag_lower) nuv_error = ErrorBar(nuv_lower, nuv_upper, at=nuv) sed.add_entry(self.filters["NUV"], nuv, nuv_error) # U band -- if not result[0]["Umag"].mask[0]: # From Vega magnitude system to AB magnitudes u_mag = unitconversion.vega_to_ab(result[0][0]["Umag"], "U") u_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Umag"], "U") u_mag_lower = u_mag - u_mag_error u_mag_upper = u_mag + u_mag_error # U band flux u = unitconversion.ab_to_jansky(u_mag) u_lower = unitconversion.ab_to_jansky(u_mag_upper) u_upper = unitconversion.ab_to_jansky(u_mag_lower) u_error = ErrorBar(u_lower, u_upper, at=u) sed.add_entry(self.filters["U"], u, u_error) # B band -- if not result[0]["Bmag"].mask[0]: b_mag = unitconversion.vega_to_ab(result[0][0]["Bmag"], "B") b_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Bmag"], "B") b_mag_lower = b_mag - abs(b_mag_error) b_mag_upper = b_mag + abs(b_mag_error) #print("bmag", b_mag) #print("bmagerror", b_mag_error) #print("bmaglower", b_mag_lower) #print("bmagupper", b_mag_upper) # B band flux b = unitconversion.ab_to_jansky(b_mag) b_lower = unitconversion.ab_to_jansky(b_mag_upper) b_upper = unitconversion.ab_to_jansky(b_mag_lower) b_error = ErrorBar(b_lower, b_upper, at=b) sed.add_entry(self.filters["B"], b, b_error) # V band -- if not result[0]["Vmag"].mask[0]: v_mag = unitconversion.vega_to_ab(result[0][0]["Vmag"], "V") v_mag_error = unitconversion.vega_to_ab(result[0][0]["e_Vmag"], "V") v_mag_lower = v_mag - v_mag_error v_mag_upper = v_mag + v_mag_error # V band flux v = unitconversion.ab_to_jansky(v_mag) v_lower = unitconversion.ab_to_jansky(v_mag_upper) v_upper = unitconversion.ab_to_jansky(v_mag_lower) v_error = ErrorBar(v_lower, v_upper, at=v) sed.add_entry(self.filters["V"], v, v_error) # In 2MASS magnitude system -> can be converted directly into Jy (see below) # J band -- if not result[0]["Jmag"].mask[0]: j_mag = result[0][0]["Jmag"] j_mag_error = result[0][0]["e_Jmag"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error # J band flux j = unitconversion.photometry_2mass_mag_to_jy(j_mag, "J") j_lower = unitconversion.photometry_2mass_mag_to_jy( j_mag_upper, "J") j_upper = unitconversion.photometry_2mass_mag_to_jy( j_mag_lower, "J") j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H band -- if not result[0]["Hmag"].mask[0]: h_mag = result[0][0]["Hmag"] h_mag_error = result[0][0]["e_Hmag"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error # H band flux h = unitconversion.photometry_2mass_mag_to_jy(h_mag, "H") h_lower = unitconversion.photometry_2mass_mag_to_jy( h_mag_upper, "H") h_upper = unitconversion.photometry_2mass_mag_to_jy( h_mag_lower, "H") h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # K band -- if not result[0]["Kmag"].mask[0]: k_mag = result[0][0]["Kmag"] k_mag_error = result[0][0]["e_Kmag"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # K band flux k = unitconversion.photometry_2mass_mag_to_jy(k_mag, "Ks") k_lower = unitconversion.photometry_2mass_mag_to_jy( k_mag_upper, "Ks") k_upper = unitconversion.photometry_2mass_mag_to_jy( k_mag_lower, "Ks") k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # F12 band flux if not result[0]["F12um"].mask[0]: f12 = result[0][0]["F12um"] f12_error = ErrorBar(result[0][0]["e_F12um"]) sed.add_entry(self.filters["IRAS 12"], f12, f12_error) # F25 band flux if not result[0]["F25um"].mask[0]: f25 = result[0][0]["F25um"] f25_error = ErrorBar(result[0][0]["e_F25um"]) sed.add_entry(self.filters["IRAS 25"], f25, f25_error) # F60 band flux if not result[0]["F60um"].mask[0]: f60 = result[0][0]["F60um"] f60_error = ErrorBar(result[0][0]["e_F60um"]) sed.add_entry(self.filters["IRAS 60"], f60, f60_error) # F100 band flux if not result[0]["F100um"].mask[0]: f100 = result[0][0]["F100um"] f100_error = ErrorBar(result[0][0]["e_F100um"]) sed.add_entry(self.filters["IRAS 100"], f100, f100_error) # Add the SED to the dictionary self.seds["GALEX"] = sed # ----------------------------------------------------------------- def get_2mass(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the 2MASS Extended Catalog ...") # 2MASS Extended Catalog: "VII/233/xsc": J, H, K (2006AJ....131.1163S) # Interesting columns: # # - "J.ext": J magnitude in r.ext (j_m_ext) [mag] # - "e_J.ext": σ(J.ext) (j_msig_ext) [mag] # - "H.ext": H magnitude in r.ext (h_m_ext) [mag] # - "e_H.ext": σ(H.ext) (h_msig_ext) [mag] # - "K.ext": J magnitude in r.ext (k_m_ext) [mag] # - "e_K.ext": σ(K.ext) (k_msig_ext) [mag] result = self.vizier.query_object(self.galaxy_name, catalog="VII/233/xsc") # Create an SED sed = ObservedSED() # In 2MASS magnitude system -> can be converted directly into Jy (see below) j_mag = result[0][0]["J.ext"] j_mag_error = result[0][0]["e_J.ext"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error h_mag = result[0][0]["H.ext"] h_mag_error = result[0][0]["e_H.ext"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error k_mag = result[0][0]["K.ext"] k_mag_error = result[0][0]["e_K.ext"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # J band flux j = unitconversion.photometry_2mass_mag_to_jy(j_mag, "J") j_lower = unitconversion.photometry_2mass_mag_to_jy(j_mag_upper, "J") j_upper = unitconversion.photometry_2mass_mag_to_jy(j_mag_lower, "J") j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H band flux h = unitconversion.photometry_2mass_mag_to_jy(h_mag, "H") h_lower = unitconversion.photometry_2mass_mag_to_jy(h_mag_upper, "H") h_upper = unitconversion.photometry_2mass_mag_to_jy(h_mag_lower, "H") h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # K band flux k = unitconversion.photometry_2mass_mag_to_jy(k_mag, "Ks") k_lower = unitconversion.photometry_2mass_mag_to_jy(k_mag_upper, "Ks") k_upper = unitconversion.photometry_2mass_mag_to_jy(k_mag_lower, "Ks") k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # Add the SED to the dictionary self.seds["2MASS"] = sed # ----------------------------------------------------------------- def get_sings(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the SINGS catalog ...") # Radial distribution in SINGS galaxies. I. # J/ApJ/703/1569/table1 (c)Sample (75 rows) # J/ApJ/703/1569/table2 UV, optical and NIR surface photometry profiles (2206 rows) # J/ApJ/703/1569/table3 UV, optical (SDSS) and NIR photometry profiles (2161 rows) # J/ApJ/703/1569/table4 IRAC and MIPS surface photometry (4319 rows) # J/ApJ/703/1569/table5 UV, optical, and near-IR asymptotic magnitudes for SINGS galaxies lacking SDSS data (43 rows) # J/ApJ/703/1569/table6 UV, optical (SDSS), and near-IR asymptotic magnitudes (32 rows) # J/ApJ/703/1569/table7 IRAC and MIPS asymptotic magnitudes (75 rows) # J/ApJ/703/1569/table8 Non-parametrical morphological estimators (300 rows) result = self.vizier.get_catalogs("J/ApJ/703/1569") # Result is a TableList with 8 tables (0 to 7) # We need: # - Table6 -> index 5 # - Table7 -> index 6 # Table6 # - "Name": Galaxy name (NGC ...) # - "FUV": GALEX FUV 0.153um-band AB magnitude [mag] # - "e_FUV": FUV uncertainty [mag] # - "NUV": GALEX NUV 0.227um-band AB magnitude [mag] # - "e_NUV": NUV uncertainty [mag] # - "umag": SDSS u-band 0.354um AB magnitude [mag] # - "e_umag": umag uncertainty [mag] # - "gmag": SDSS g-band 0.477um AB magnitude [mag] # - "e_gmag": gmag uncertainty [mag] # - "rmag": SDSS r-band 0.623um AB magnitude [mag] # - "e_rmag": rmag uncertainty [mag] # - "imag": SDSS i-band 0.762um AB magnitude [mag] # - "e_imag": imag uncertainty [mag] # - "zmag": SDSS z-band 0.913um AB magnitude [mag] # - "e_zmag": zmag uncertainty [mag] # - "Jmag": 2MASS J-band 1.25um AB magnitude [mag] # - "e_Jmag": Jmag uncertainty [mag] # - "Hmag": 2MASS H-band 1.65um AB magnitude [mag] # - "e_Hmag": Hmag uncertainty [mag] # - "Ksmag": 2MASS Ks-band 2.17um AB magnitude [mag] # - "e_Ksmag": Ksmag uncertainty [mag] # Find the row index that corresponds with the specified galaxy galaxy_index = tables.find_index(result[5], self.ngc_id) # FUV fuv_mag = result[5][galaxy_index]["FUV"] fuv_mag_error = result[5][galaxy_index]["e_FUV"] fuv_mag_lower = fuv_mag - fuv_mag_error fuv_mag_upper = fuv_mag + fuv_mag_error # NUV nuv_mag = result[5][galaxy_index]["NUV"] nuv_mag_error = result[5][galaxy_index]["e_NUV"] nuv_mag_lower = nuv_mag - nuv_mag_error nuv_mag_upper = nuv_mag + nuv_mag_error # u u_mag = result[5][galaxy_index]["umag"] u_mag_error = result[5][galaxy_index]["e_umag"] u_mag_lower = u_mag - u_mag_error u_mag_upper = u_mag + u_mag_error # g g_mag = result[5][galaxy_index]["gmag"] g_mag_error = result[5][galaxy_index]["e_gmag"] g_mag_lower = g_mag - abs(g_mag_error) g_mag_upper = g_mag + abs(g_mag_error) #print("gmag", g_mag) #print("gmagerror", g_mag_error) #print("gmaglower", g_mag_lower) #print("gmagupper", g_mag_upper) # r r_mag = result[5][galaxy_index]["rmag"] r_mag_error = result[5][galaxy_index]["e_rmag"] r_mag_lower = r_mag - r_mag_error r_mag_upper = r_mag + r_mag_error # i i_mag = result[5][galaxy_index]["imag"] i_mag_error = result[5][galaxy_index]["e_imag"] i_mag_lower = i_mag - i_mag_error i_mag_upper = i_mag + i_mag_error # z z_mag = result[5][galaxy_index]["zmag"] z_mag_error = result[5][galaxy_index]["e_zmag"] z_mag_lower = z_mag - z_mag_error z_mag_upper = z_mag + z_mag_error # J j_mag = result[5][galaxy_index]["Jmag"] j_mag_error = result[5][galaxy_index]["e_Jmag"] j_mag_lower = j_mag - j_mag_error j_mag_upper = j_mag + j_mag_error # H h_mag = result[5][galaxy_index]["Hmag"] h_mag_error = result[5][galaxy_index]["e_Hmag"] h_mag_lower = h_mag - h_mag_error h_mag_upper = h_mag + h_mag_error # Ks k_mag = result[5][galaxy_index]["Ksmag"] k_mag_error = result[5][galaxy_index]["e_Ksmag"] k_mag_lower = k_mag - k_mag_error k_mag_upper = k_mag + k_mag_error # Create an SED sed = ObservedSED() # FUV fuv = unitconversion.ab_to_jansky(fuv_mag) fuv_lower = unitconversion.ab_to_jansky(fuv_mag_upper) fuv_upper = unitconversion.ab_to_jansky(fuv_mag_lower) fuv_error = ErrorBar(fuv_lower, fuv_upper, at=fuv) sed.add_entry(self.filters["FUV"], fuv, fuv_error) # NUV nuv = unitconversion.ab_to_jansky(nuv_mag) nuv_lower = unitconversion.ab_to_jansky(nuv_mag_upper) nuv_upper = unitconversion.ab_to_jansky(nuv_mag_lower) nuv_error = ErrorBar(nuv_lower, nuv_upper, at=nuv) sed.add_entry(self.filters["NUV"], nuv, nuv_error) # u u = unitconversion.ab_to_jansky(u_mag) u_lower = unitconversion.ab_to_jansky(u_mag_upper) u_upper = unitconversion.ab_to_jansky(u_mag_lower) u_error = ErrorBar(u_lower, u_upper, at=u) sed.add_entry(self.filters["SDSS u"], u, u_error) # g g = unitconversion.ab_to_jansky(g_mag) g_lower = unitconversion.ab_to_jansky(g_mag_upper) g_upper = unitconversion.ab_to_jansky(g_mag_lower) g_error = ErrorBar(g_lower, g_upper, at=g) sed.add_entry(self.filters["SDSS g"], g, g_error) # r r = unitconversion.ab_to_jansky(r_mag) r_lower = unitconversion.ab_to_jansky(r_mag_upper) r_upper = unitconversion.ab_to_jansky(r_mag_lower) r_error = ErrorBar(r_lower, r_upper, at=r) sed.add_entry(self.filters["SDSS r"], r, r_error) # i i = unitconversion.ab_to_jansky(i_mag) i_lower = unitconversion.ab_to_jansky(i_mag_upper) i_upper = unitconversion.ab_to_jansky(i_mag_lower) i_error = ErrorBar(i_lower, i_upper, at=i) sed.add_entry(self.filters["SDSS i"], i, i_error) # z z = unitconversion.ab_to_jansky(z_mag) z_lower = unitconversion.ab_to_jansky(z_mag_upper) z_upper = unitconversion.ab_to_jansky(z_mag_lower) z_error = ErrorBar(z_lower, z_upper, at=z) sed.add_entry(self.filters["SDSS z"], z, z_error) # J j = unitconversion.ab_to_jansky(j_mag) j_lower = unitconversion.ab_to_jansky(j_mag_upper) j_upper = unitconversion.ab_to_jansky(j_mag_lower) j_error = ErrorBar(j_lower, j_upper, at=j) sed.add_entry(self.filters["J"], j, j_error) # H h = unitconversion.ab_to_jansky(h_mag) h_lower = unitconversion.ab_to_jansky(h_mag_upper) h_upper = unitconversion.ab_to_jansky(h_mag_lower) h_error = ErrorBar(h_lower, h_upper, at=h) sed.add_entry(self.filters["H"], h, h_error) # Ks k = unitconversion.ab_to_jansky(k_mag) k_lower = unitconversion.ab_to_jansky(k_mag_upper) k_upper = unitconversion.ab_to_jansky(k_mag_lower) k_error = ErrorBar(k_lower, k_upper, at=k) sed.add_entry(self.filters["K"], k, k_error) # Table7: IRAC and MIPS asymptotic magnitudes # - "logF3.6": Spitzer/IRAC 3.6um flux density [logJy] # - "e_logF3.6": logF3.6 uncertainty [logJy] # - "logF4.5": Spitzer/IRAC 4.5um flux density [logJy] # - "e_logF4.5": logF4.5 uncertainty [logJy] # - "logF5.8": Spitzer/IRAC 5.8um flux density [logJy] # - "e_logF5.8": logF5.8 uncertainty [logJy] # - "logF8.0": Spiter/IRAC 8.0um flux density [logJy] # - "e_logF8.0": logF8.0 uncertainty [logJy] # - "logF24": Spiter/MIPS 24um flux density [logJy] # - "e_logF24": logF24 uncertainty [logJy] # - "logF70": Spiter/MIPS 70um flux density [logJy] # - "e_logF70": logF70 uncertainty [logJy] # - "logF160": Spiter/MIPS 160um flux density [logJy] # - "e_logF160": logF160 uncertainty [logJy] # Table7 -> index 6 galaxy_index = tables.find_index(result[6], self.ngc_id) # 3.6 micron i1_log = result[6][galaxy_index]["logF3.6"] i1_log_error = result[6][galaxy_index]["e_logF3.6"] i1_log_lower = i1_log - i1_log_error i1_log_upper = i1_log + i1_log_error # 4.5 micron i2_log = result[6][galaxy_index]["logF4.5"] i2_log_error = result[6][galaxy_index]["e_logF4.5"] i2_log_lower = i2_log - i2_log_error i2_log_upper = i2_log + i2_log_error # 5.8 micron i3_log = result[6][galaxy_index]["logF5.8"] i3_log_error = result[6][galaxy_index]["e_logF5.8"] i3_log_lower = i3_log - i3_log_error i3_log_upper = i3_log + i3_log_error # 8.0 micron i4_log = result[6][galaxy_index]["logF8.0"] i4_log_error = result[6][galaxy_index]["e_logF8.0"] i4_log_lower = i4_log - i4_log_error i4_log_upper = i4_log + i4_log_error #print("i4log", i4_log) #print("i4_log_error", i4_log_error) #print("i4_log_lower", i4_log_lower) #print("i4_log_upper", i4_log_upper) # 24 micron mips24_log = result[6][galaxy_index]["logF24"] mips24_log_error = result[6][galaxy_index]["e_logF24"] mips24_log_lower = mips24_log - mips24_log_error mips24_log_upper = mips24_log + mips24_log_error # 70 micron mips70_log = result[6][galaxy_index]["logF70"] mips70_log_error = result[6][galaxy_index]["e_logF70"] mips70_log_lower = mips70_log - mips70_log_error mips70_log_upper = mips70_log + mips70_log_error # 160 micron mips160_log = result[6][galaxy_index]["logF160"] mips160_log_error = result[6][galaxy_index]["e_logF160"] mips160_log_lower = mips160_log - mips160_log_error mips160_log_upper = mips160_log + mips160_log_error # Calculate data points and errobars in Janskys, add to the SED # 3.6 micron i1 = 10.**i1_log i1_lower = 10.**i1_log_lower i1_upper = 10.**i1_log_upper i1_error = ErrorBar(i1_lower, i1_upper, at=i1) sed.add_entry(self.filters["I1"], i1, i1_error) # 4.5 micron i2 = 10.**i2_log i2_lower = 10.**i2_log_lower i2_upper = 10.**i2_log_upper i2_error = ErrorBar(i2_lower, i2_upper, at=i2) sed.add_entry(self.filters["I2"], i2, i2_error) # 5.8 micron i3 = 10.**i3_log i3_lower = 10.**i3_log_lower i3_upper = 10.**i3_log_upper i3_error = ErrorBar(i3_lower, i3_upper, at=i3) sed.add_entry(self.filters["I3"], i3, i3_error) # 8.0 micron i4 = 10.**i4_log i4_lower = 10.**i4_log_lower i4_upper = 10.**i4_log_upper i4_error = ErrorBar(i4_lower, i4_upper, at=i4) sed.add_entry(self.filters["I4"], i4, i4_error) # 24 micron mips24 = 10.**mips24_log mips24_lower = 10.**mips24_log_lower mips24_upper = 10.**mips24_log_upper mips24_error = ErrorBar(mips24_lower, mips24_upper, at=mips24) sed.add_entry(self.filters["MIPS 24"], mips24, mips24_error) # 70 micron mips70 = 10.**mips70_log mips70_lower = 10.**mips70_log_lower mips70_upper = 10.**mips70_log_upper mips70_error = ErrorBar(mips70_lower, mips70_upper, at=mips70) sed.add_entry(self.filters["MIPS 70"], mips70, mips70_error) # 160 micron mips160 = 10.**mips160_log mips160_lower = 10.**mips160_log_lower mips160_upper = 10.**mips160_log_upper mips160_error = ErrorBar(mips160_lower, mips160_upper, at=mips160) sed.add_entry(self.filters["MIPS 160"], mips160, mips160_error) # Add the SED to the dictionary self.seds["SINGS"] = sed # ----------------------------------------------------------------- def get_lvl(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the LVL catalog ...") # Create an SED sed = ObservedSED() # "J/MNRAS/445/881": LVL global optical photometry (Cook+, 2014) # - "J/MNRAS/445/881/sample": Galaxies of the Spitzer Local Volume Legacy (LVL): properties (table1) and R25 photometry # - "J/MNRAS/445/881/table3": Photometry within the IR apertures of Dale et al. (2009, Cat. J/ApJ/703/517) (258 rows) # - "J/MNRAS/445/881/table4": Photometry within the UV apertures of Lee et al. (2011, Cat. J/ApJS/192/6) (258 rows) result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/445/881/sample") # ALL IN AB MAGNITUDE SYSTEM # Umag # Bmag # Vmag # Rmag # umag # gmag # rmag # imag # zmag # On SimBad, only sdss bands are used, from /sample ... relevant_bands = [("U", "U"), ("B", "B"), ("V", "V"), ("R", "R"), ("u", "SDSS u"), ("g", "SDSS g"), ("r", "SDSS r"), ("i", "SDSS i"), ("z", "SDSS z")] for band_prefix_catalog, filter_name in relevant_bands: column_name = band_prefix_catalog + "mag" error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # AB magnitude magnitude = result[0][0][column_name] magnitude_error = result[0][0][error_column_name] magnitude_lower = magnitude - magnitude_error magnitude_upper = magnitude + magnitude_error # Convert to Jy fluxdensity = unitconversion.ab_to_jansky(magnitude) fluxdensity_lower = unitconversion.ab_to_jansky(magnitude_upper) fluxdensity_upper = unitconversion.ab_to_jansky(magnitude_lower) fluxdensity_error = ErrorBar(fluxdensity_lower, fluxdensity_upper, at=fluxdensity) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["LVL"] = sed # ----------------------------------------------------------------- def get_spitzer(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the Spitzer catalog ...") # "J/ApJ/703/517": The Spitzer Local Volume Legacy: IR photometry (Dale+, 2009) # "J/ApJ/703/517/sample": Galaxy sample (table 1) and infrared flux densities (table 2) (258 rows) # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/703/517/sample") # F1.25: 2MASS J band (1.25 micron) flux density [Jy] # e_F1.25: Uncertainty in F1.25 [Jy] # F1.65: 2MASS H band (1.65 micron) flux density [Jy] # e_F1.65: Uncertainty in F1.65 [Jy] # F2.17: 2MASS Ks band (2.17 micron) flux density [Jy] # e_F2.17: Uncertainty in F2.17 [Jy] # F3.6: Spitzer/IRAC 3.5 micron band flux density [Jy] # e_F3.6: Uncertainty in F3.6 [Jy] # F4.5: Spitzer/IRAC 4.5 micron band flux density [Jy] # e_F4.5: Uncertainty in F4.5 [Jy] # F5.8: Spitzer/IRAC 5.8 micron band flux density [Jy] # e_F5.8: Uncertainty in F5.8 [Jy] # F8.0: Spitzer/IRAC 8.0 micron band flux density [Jy] # e_F8.0: Uncertainty in F8.0 [Jy] # F24: Spitzer/MIPS 24 micron flux density [Jy] # e_F24: Uncertainty in F24 [Jy] # F70: Spitzer/MIPS 70 micron band flux density [Jy] # e_F70: Uncertainty in F70 [Jy] # F160: Spitzer/MIPS 160 micron band flux density [Jy] # e_F160: Uncertainty in F160 [Jy] relevant_bands = [("1.25", "J"), ("1.65", "H"), ("2.17", "K"), ("3.6", "I1"), ("4.5", "I2"), ("5.8", "I3"), ("8.0", "I4"), ("24", "MIPS 24"), ("70", "MIPS 70"), ("160", "MIPS 160")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F" + band_prefix_catalog error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(result[0][0][error_column_name]) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["Spitzer"] = sed # ----------------------------------------------------------------- def get_spitzer_irs(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the Spitzer/IRS catalog ...") # "J/MNRAS/414/500": Spitzer/IRS ATLAS project source (Hernan-Caballero+, 2011) # - "J/MNRAS/414/500/catalog": Spitzer/IRS ATLAS project source catalog, version 1.0 (739 rows) # !! Parentheses () are converted into underscores _ in the resulting Astropy tables!! # F(3.6): IRAC1 (3.6um) flux density [Jy] # e_F(3.6): rms uncertainty on F(3.6) [Jy] # F(8.0): IRAC4 (8.0um) flux density [Jy] # e_F(8.0): rms uncertainty on F(8.0) [Jy] # F(24): 24um flux density [Jy] # e_F(24): rms uncertainty on F(24) [Jy] # F(70): 70um or similar band flux density [Jy] # e_F(70): rms uncertainty on F(70) [Jy] # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/414/500/catalog") relevant_bands = [("3.6", "I1"), ("8.0", "I4"), ("24", "MIPS 24"), ("70", "MIPS 70")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F_" + band_prefix_catalog + "_" error_column_name = "e_" + column_name # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(result[0][0][error_column_name]) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["Spitzer-IRS"] = sed # ----------------------------------------------------------------- def get_iras(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the IRAS catalog ...") # "J/ApJS/178/280": Compendium of ISO far-IR extragalactic data (Brauher+, 2008) # - "J/ApJS/178/280/table1": *Galaxies and properties # F12: IRAS 12um band flux density [Jy] # F25: IRAS 25um band flux density [Jy] # F60: IRAS 60um band flux density [Jy] # F100: IRAS 100um band flux density [Jy] # No errors ... # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJS/178/280/table1") relevant_bands = [("12", "IRAS 12"), ("25", "IRAS 25"), ("60", "IRAS 60"), ("100", "IRAS 100")] for band_prefix_catalog, filter_name in relevant_bands: column_name = "F" + band_prefix_catalog # Skip masked values if result[0][column_name].mask[0]: continue # Flux and error already in Jy fluxdensity = result[0][0][column_name] fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS"] = sed # ----------------------------------------------------------------- def get_iras_fsc(self): """ This function ... :return: """ # Inform the user log.info("Getting fluxes from the IRAS-FSC catalog ...") # "J/MNRAS/398/109": Imperial IRAS-FSC redshift catalogue (IIFSCz) (Wang+, 2009) # - "J/MNRAS/398/109/iifsczv4": IIFSCz Catalogue (MRR+LW 18/04/09)[spectrum/SED] (60303 rows) # S12um: IRAS-FSC flux at 12um [Jy] # S25um: IRAS-FSC flux at 25um [Jy] # S60um: IRAS-FSC flux at 60um [Jy] # S100um: IRAS-FSC flux at 100um [Jy] # not used in Simbad: # umag: SDSS u magnitude [mag: which system??] # e_umag: # gmag: # e_gmag: # rmag: # e_rmag: # imag: # e_imag: # zmag: # e_zmag: # Jmag: 2MASS J magnitude [mag: which system??] # e_Jmag: rms uncertainty on Jmag [mag: which system??] # Hmag: 2MASS H magnitude [mag] # e_Hmag: rms uncertainty on Hmag [mag] # Kmag: 2MASS K magnitude [mag] # e_Kmag rms uncertainty on Kmag [mag] # Create an SED sed = ObservedSED() result = self.vizier.query_object(self.galaxy_name, catalog="J/MNRAS/398/109/iifsczv4") relevant_bands = [("12", "IRAS 12"), ("25", "IRAS 25"), ("60", "IRAS 60"), ("100", "IRAS 100")] for band_prefix_catalog, filter_name in relevant_bands: # Flux and error already in Jy fluxdensity = result[0][0]["S" + band_prefix_catalog + "um"] fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS-FSC"] = sed # ----------------------------------------------------------------- def get_s4g(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # Get parameters from S4G catalog result = self.vizier.query_object(self.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Magnitudes i1_mag = table["__3.6_"][0] i2_mag = table["__4.5_"][0] i1_mag_error = table["e__3.6_"][0] i2_mag_error = table["e__4.5_"][0] i1_fluxdensity = unitconversion.ab_to_jansky(i1_mag) i1_fluxdensity_lower = unitconversion.ab_to_jansky(i1_mag + i1_mag_error) i1_fluxdensity_upper = unitconversion.ab_to_jansky(i1_mag - i1_mag_error) i1_error = ErrorBar(i1_fluxdensity_lower, i1_fluxdensity_upper, at=i1_fluxdensity) # Add data point to SED sed.add_entry(self.filters["I1"], i1_fluxdensity, i1_error) i2_fluxdensity = unitconversion.ab_to_jansky(i2_mag) i2_fluxdensity_lower = unitconversion.ab_to_jansky(i2_mag + i2_mag_error) i2_fluxdensity_upper = unitconversion.ab_to_jansky(i2_mag - i2_mag_error) i2_error = ErrorBar(i2_fluxdensity_lower, i2_fluxdensity_upper, at=i2_fluxdensity) # Add data point to SED sed.add_entry(self.filters["I2"], i2_fluxdensity, i2_error) # Add the SED to the dictionary self.seds["S4G"] = sed # ----------------------------------------------------------------- def get_brown(self): """ This function ... :return: """ # J/ApJS/212/18/sample # AB magnitudes for the sample with neither foreground nor intrinsic dust extinction corrections, and modeled Milky Way foreground dust extinction # Create an SED sed = ObservedSED() # FUV: [12.5/22.9] GALEX FUV AB band magnitude # e_FUV: # UVW2: # e_UVW2: # UVM2: # e_UVM2: # NUV: # e_NUV: # UVW1: # e_UVW1: # Umag: [11.9/15.7] Swift/UVOT U AB band magnitude # e_Umag: # umag: # e_umag: # gmag: # e_gmag: # Vmag: # e_Vmag: # rmag: # e_rmag: # imag: # e_imag: # zmag: # e_zmag: # Jmag: # e_Jmag: # Hmag: # e_Hmag: # Ksmag: # e_Ksmag: # W1mag: # e_W1mag: # [3.6]: # e_[3.6]: # [4.5]: # e_[4.5]: # W2mag: # e_W2mag: # [5.8]: # e_[5.8]: # [8.0]: # e_[8.0]: # W3mag: # e_W3mag: # W4mag: # e_W4mag: # W4'mag: Corrected WISE W4 AB band magnitude # e_W4'mag: # [24]: # e_[24]: pass # ----------------------------------------------------------------- def get_planck(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # The second release is not yet available ... ?? # ----------------------------------------------------------------- def get_emission_lines(self): """ This function ... :return: """ # Create an SED sed = ObservedSED() # J/ApJS/190/233/Opt # Get result result = self.vizier.get_catalogs("J/ApJS/190/233/Opt") table = result[0] galaxy_index = tables.find_index(table, self.ngc_id, "Name") # FHa: The Hα 6563 Angstrom line flux (aW/m2) # e_FHa: Uncertainty in Ha (aW/m2) # FNII: The [NII] 6584Å line flux (aW/m2) # e_FNII: Uncertainty in NII (aW/m2) # H alpha ha_flux = table["FHa"][galaxy_index] * Unit("aW/m2") ha_flux_error = table["e_FHa"][galaxy_index] * Unit("aW/m2") # NII n2_flux = table["FNII"][galaxy_index] * Unit("aW/m2") n2_flux_error = table["e_FNII"][galaxy_index] * Unit("aW/m2") ha_filter = self.filters["Ha"] ha_wavelength = ha_filter.centerwavelength() * Unit("micron") ha_frequency = ha_wavelength.to("Hz", equivalencies=spectral()) # Calculate flux density ha_fluxdensity = (ha_flux / ha_frequency).to("Jy") ha_fluxdensity_error = (ha_flux_error / ha_frequency).to("Jy") ha_errorbar = ErrorBar(ha_fluxdensity_error) # Add entry sed.add_entry(ha_filter, ha_fluxdensity, ha_errorbar) # Add the SED to the dictionary self.seds["Lines"] = sed # ----------------------------------------------------------------- def get_m81(self): """ This function ... :return: """ # UV through far-IR analysis of M81 (Perez-Gonzalez+, 2006) # "J/ApJ/648/987" # Two tables: # - "J/ApJ/648/987/table1": Positions and photometry (GLOBALBKG and LOCALBKG cases) for the regions selected at 160um resolution # - "J/ApJ/648/987/table2": Positions and photometry for the regions selected at 24um resolution # Table 1 #result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/648/987/table1") # Looks like this (only 3 matches) #1 M81 09 55 32.2 +69 03 59.0 680.0 40.78 43.18 42.84 42.63 42.61 41.98 42.67 42.99 #2 Reg02 09 55 32.2 +69 03 59.0 64.0 39.67 42.63 42.28 41.98 41.76 41.25 41.83 41.78 #3 Reg03 09 55 32.2 +69 03 59.0 104.0 39.40 42.38 42.03 41.76 41.58 40.90 41.62 41.78 #galaxy_index = tables.find_index(result, self.galaxy_name) # Table 2 # Interesting rows: # - logLFUV: Log of the FUV luminosity [1e-7 W] or [erg/s] # - logLNUV: Log of the NUV luminosity [1e-7 W] or [erg/s] # - logLHa: Log of the H-alpha luminosity [1e-7 W] or [erg/s] # - logL8: Log of the 8um luminosity [1e-7 W] or [erg/s] # - logL24: Log of the 24um luminosity [1e-7 W] or [erg/s] result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/648/987/table2") galaxy_index = tables.find_index(result[0], self.galaxy_name) # Create an SED sed = ObservedSED() relevant_bands = [("FUV", "FUV"), ("NUV", "NUV"), ("Ha", "Ha"), ("8", "I4"), ("24", "MIPS 24")] for band_prefix_catalog, filter_name in relevant_bands: # Flux and error already in Jy log = result[0][galaxy_index]["logL" + band_prefix_catalog] flux = 10.**log # In erg/s frequency = 0.0 # TODO: calculate this! # Also: calculate the amount of flux per unit area ! : divide also by 4 pi d_galaxy**2 ! fluxdensity = flux / frequency fluxdensity_error = ErrorBar(0.0) # Add data point to SED sed.add_entry(self.filters[filter_name], fluxdensity, fluxdensity_error) # Add the SED to the dictionary self.seds["IRAS-FSC"] = sed # ----------------------------------------------------------------- def write(self): """ This function ... :return: """ # Inform the user log.info("Writing ...") # If requested, write out the SEDs if self.config.write_seds: self.write_seds() # ----------------------------------------------------------------- def write_seds(self): """ This function ... :return: """ # Inform the user log.info("Writing the SEDs ...") # Determine the full path to the SEDs directory path = self.full_output_path(self.config.writing.seds_path) # Create the SEDs directory if necessary fs.create_directory(path) # Loop over the different SEDs for label in self.seds: # Debugging info log.debug("Writing SED from " + label) # Determine the path to the new SED file sed_path = fs.join(path, label + ".dat") # Save the SED at the specified location self.seds[label].save(sed_path)
def vizier_query(object, params=None, method="both", coordinate=False): """Give mean/median values of some parameters for an object. This script use VizieR for looking up the object. :object: The object to query (e.g. HD20010). :parama: Extra parameters to look for (default is Teff, logg, __Fe_H_). :method: Print median, main or both :returns: A dictionary with the parameters """ methods = ("median", "mean", "both") if method not in methods: raise ValueError("method must be one of:", methods) with warnings.catch_warnings(): warnings.simplefilter("ignore") cat = Vizier.query_object(object) if coordinate: for c in cat: try: ra = c["RAJ2000"][0] dec = c["DEJ2000"][0] except KeyError: ra = 0 pass if ra != 0: break print("%s %s %s" % (object, ra, dec)) else: print("Object: %s" % object) parameters = {"Teff": [], "logg": [], "__Fe_H_": []} if params: params = ["Teff", "logg", "__Fe_H_"] for param in params: parameters[param] = [] for ci in cat: for column in parameters.keys(): try: parameters[column].append(ci[column].quantity) except (TypeError, KeyError): pass for key in parameters.keys(): pi = parameters[key] parameters[key] = _q2a(pi) if len(parameters[key]): mean = round(np.nanmean(parameters[key]), 2) median = round(np.nanmedian(parameters[key]), 2) else: mean = "Not available" median = "Not available" if key.startswith("__"): key = "[Fe/H]" if method == "mean": print("\n%s:\tMean value: %s" % (key, mean)) elif method == "median": print("\n%s\tMedian value: %s" % (key, median)) else: print("\n%s:\tMean value: %s" % (key, mean)) print("%s:\tMedian value: %s" % (key, median)) return parameters, cat
class S4G(Configurable): """ This class ... """ def __init__(self, *args, **kwargs): """ The constructor ... :param kwargs: """ # Call the constructor of the base class super(S4G, self).__init__(*args, **kwargs) # The inclination self.inclination = None # The galaxy properties object self.properties = None # The dictionary of components self.components = dict() # The Vizier service self.vizier = None # ----------------------------------------------------------------- def _run(self, **kwargs): """ This function ... :return: """ # 2. Get galaxy properties self.get_properties() # 3. Get the components self.get_components() # 4. Show if self.config.show: self.show() # 5. Writing if self.config.write: self.write() # ----------------------------------------------------------------- def setup(self, **kwargs): """ This function ... :param kwargs: :return: """ # Call the setup function of the base class super(S4G, self).setup(**kwargs) # Get the inclination self.inclination = kwargs.pop("inclination", None) # Create the galaxy properties object self.properties = GalaxyProperties() self.properties.name = self.config.galaxy_name # Get the NGC name of the galaxy self.properties.ngc_name = self.ngc_name # ----------------------------------------------------------------- @lazyproperty def ngc_name(self): """ This function ... :return: """ return catalogs.get_ngc_name(self.config.galaxy_name) # ----------------------------------------------------------------- @property def ngc_name_nospaces(self): """ This function ... :return: """ return self.ngc_name.replace(" ", "") # ----------------------------------------------------------------- def get_properties(self): """ This function ... :return: """ # Inform the user log.info("Getting the galaxy properties ...") # S4G self.get_s4g_properties() # To first order, cos i = b/a where a & b # are the observed major and minor # axes (assume disk is intrinsically # circular) # But this implies galaxies have zero # thickness at i = 90°! Better to assume # that spirals are oblate ellipsoids with # intrinsic axis ratios a:a:c. If q = c/a, # then after a bit a simple geometry # cos^2(i) = [ (b/a)^2 - q^2 ] / (1-q^2) # The best fit to observed spirals yields # q = 0.13 for Sc galaxies # Ellipticity (1-b/a) # b_to_a = 1. - self.properties.ellipticity # # # Calculate the inclination # inclination_deg = 90. - math.degrees(math.acos(b_to_a)) # inclination = Angle(inclination_deg, "deg") # # # Check the inclination # if self.inclination is not None: # difference = abs(self.inclination - inclination) # rel_difference = difference / self.inclination # if rel_difference > 0.1: # log.warning("The inclination angle calculated based on the decomposition differs by " + str(rel_difference*100) + "% from the specified inclination") # # # Set the incliantion # self.properties.inclination = inclination # ----------------------------------------------------------------- def get_s4g_properties(self): """ This function ... :return: """ # Inform the user log.info("Querying the S4G catalog ...") # The Vizier querying object, specifying the necessary columns for this class self.vizier = Vizier(columns=['Name', 'RAJ2000', 'DEJ2000', 'Dmean', 'e_Dmean', 'amaj', 'ell', '[3.6]', '[4.5]', 'e_[3.6]', 'e_[4.5]', 'PA']) self.vizier.ROW_LIMIT = -1 # Get parameters from S4G catalog result = self.vizier.query_object(self.config.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Galaxy name for S4G catalog self.properties.name = table["Name"][0] # Galaxy center from decomposition (?) ra_center = table["RAJ2000"][0] dec_center = table["DEJ2000"][0] center = SkyCoordinate(ra=ra_center, dec=dec_center, unit="deg", frame='fk5') self.properties.center = center # Center position #self.properties.center = SkyCoordinate(ra=self.info["RA"][0], dec=self.info["DEC"][0], unit="deg") # center position from DustPedia # Distance self.properties.distance = table["Dmean"][0] * u("Mpc") self.properties.distance_error = table["e_Dmean"][0] * u("Mpc") # Major axis, ellipticity, position angle self.properties.major_arcsec = table["amaj"][0] * u("arcsec") self.properties.major = (self.properties.distance * self.properties.major_arcsec).to("pc", equivalencies=dimensionless_angles()) # Ellipticity self.properties.ellipticity = table["ell"][0] self.properties.position_angle = Angle(table["PA"][0] + 90.0, u("deg")) # Magnitudes asymptotic_ab_magnitude_i1 = table["__3.6_"][0] asymptotic_ab_magnitude_i2 = table["__4.5_"][0] asymptotic_ab_magnitude_i1_error = table["e__3.6_"][0] asymptotic_ab_magnitude_i2_error = table["e__4.5_"][0] #self.properties.i1_mag = asymptotic_ab_magnitude_i1 #self.properties.i1_mag_error = asymptotic_ab_magnitude_i1_error #self.properties.i2_mag = asymptotic_ab_magnitude_i2 #self.properties.i2_mag_error = asymptotic_ab_magnitude_i2_error #self.properties.i1_fluxdensity = unitconversion.ab_to_jansky(self.properties.i1_mag) * Unit("Jy") #i1_fluxdensity_lower = unitconversion.ab_to_jansky( # self.properties.i1_mag + self.properties.i1_mag_error) * Unit("Jy") #i1_fluxdensity_upper = unitconversion.ab_to_jansky( # self.properties.i1_mag - self.properties.i1_mag_error) * Unit("Jy") #i1_error = ErrorBar(i1_fluxdensity_lower, i1_fluxdensity_upper, at=self.properties.i1_fluxdensity) #self.properties.i1_error = i1_error.average #self.properties.i2_fluxdensity = unitconversion.ab_to_jansky(self.properties.i2_mag) * Unit("Jy") #i2_fluxdensity_lower = unitconversion.ab_to_jansky( # self.properties.i2_mag + self.properties.i2_mag_error) * Unit("Jy") #i2_fluxdensity_upper = unitconversion.ab_to_jansky( # self.properties.i2_mag - self.properties.i2_mag_error) * Unit("Jy") #i2_error = ErrorBar(i2_fluxdensity_lower, i2_fluxdensity_upper, at=self.properties.i2_fluxdensity) #self.properties.i2_error = i2_error.average # Other ... # absolute_magnitude_i1 = table["M3.6"][0] # absolute_magnitude_i2 = table["M4.5"][0] # stellar_mass = 10.0**table["logM_"][0] * u.Unit("Msun") # ----------------------------------------------------------------- def get_components(self): """ This function ... :return: """ # Inform the user log.info("Getting the components ...") # self.get_p4() # currently (writing on the 31th of march 2016) there is a problem with the effective radius values # (at least for M81) on Vizier as well as in the PDF version of table 7 (S4G models homepage). # Parse the S4G table 8 to get the decomposition parameters self.get_parameters_from_table() # ----------------------------------------------------------------- def get_p4(self): """ This function ... :return: """ #http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/ApJS/219/4 # J/ApJS/219/4: S4G pipeline 4: multi-component decompositions (Salo+, 2015) # - J/ApJS/219/4/galaxies: Parameters of the galaxies; center, outer orientation, sky background; and 1-component Sersic fits (tables 1 and 6) (2352 rows) # - J/ApJS/219/4/table7: *Parameters of final multicomponent decompositions (Note) (4629 rows) # Inform the user log.info("Querying the S4G pipeline 4 catalog ...") # Get the "galaxies" table result = self.vizier.query_object(self.config.galaxy_name, catalog=["J/ApJS/219/4/galaxies"]) table = result[0] # PA: [0.2/180] Outer isophote position angle # e_PA: [0/63] Standard deviation in PA # Ell: [0.008/1] Outer isophote ellipticity # e_Ell: [0/0.3] Standard deviation in Ell pa = Angle(table["PA"][0] - 90., "deg") pa_error = Angle(table["e_PA"][0], "deg") ellipticity = table["Ell"][0] ellipticity_error = table["e_Ell"][0] # Get the "table7" table result = self.vizier.get_catalogs("J/ApJS/219/4/table7") table = result[0] # Name: Galaxy name # Mod: Type of final decomposition model # Nc: [1/4] Number of components in the model (1-4) # Q: [3/5] Quality flag, 5=most reliable # C: Physical interpretation of the component # Fn: The GALFIT function used for the component (sersic, edgedisk, expdisk, ferrer2 or psf) # f1: [0.006/1] "sersic" fraction of the total model flux # mag1: [7/19.4] "sersic" total 3.6um AB magnitude # q1: [0.1/1] "sersic" axis ratio # PA1: [0.08/180] "sersic" position angle [deg] # Re: [0.004/430] "sersic" effective radius (Re) [arcsec] # n: [0.01/20] "sersic" parameter n # f2: [0.02/1] "edgedisk" fraction of the total model flux # mu02: [11.8/24.6] "edgedisk" central surface face-on brightness (µ0) [mag/arcsec2] # PA2: [-90/90] "edgedisk" PA [deg] # hr2: [1/153] "edgedisk" exponential scale length (hr) [arcsec] # hz2: [0.003/39] "edgedisk" z-scale hz [arcsec] # f3: [0.02/1] "expdisk" fraction of the total model flux # mag3: [6.5/18.1] "expdisk" total 3.6um AB magnitude [mag] # q3: [0.1/1] "expdisk" axis ratio # PA3: [-90/90] "expdisk" position angle [deg] # hr3: [0.7/332] "expdisk" exponential scale length (hr) [arcsec] # mu03: [16.4/25.3] "expdisk" central surface face-on brightness (µ0) [mag/arcsec2] # f4: [0.003/0.6] "ferrer2" fraction of the total model flux # mu04: [16/24.8] "ferrer2" central surface sky brightness (µ0) [mag/arcsec2] # q4: [0.01/1] "ferrer2" axis ratio # PA4: [-90/90] "ferrer2" position angle [deg] # Rbar: [3.7/232.5] "ferrer2" outer truncation radius of the bar (Rbar) [arcsec] # f5: [0.001/0.4] "psf" fraction of the total model flux # mag5: [11.5/21.1] "psf" total 3.6um AB magnitude [mag] indices = tables.find_indices(table, self.ngc_name_nospaces, "Name") labels = {"sersic": 1, "edgedisk": 2, "expdisk": 3, "ferrer2": 4, "psf": 5} #units = {"f": None, "mag": "mag", "q": None, "PA": "deg", } # Loop over the indices for index in indices: model_type = table["Mod"][index] number_of_components = table["Nc"][index] quality = table["Q"][index] interpretation = table["C"][index] functionname = table["Fn"][index] component_parameters = Map() if self.parameters.model_type is not None: assert model_type == self.parameters.model_type if self.parameters.number_of_components is not None: assert number_of_components == self.parameters.number_of_components if self.parameters.quality is not None: assert quality == self.parameters.quality self.parameters.model_type = model_type self.parameters.number_of_components = number_of_components self.parameters.quality = quality for key in table.colnames: if not key.endswith(str(labels[functionname])): continue parameter = key[:-1] value = table[key][index] if parameter == "PA": value = Angle(value + 90., "deg") if quadrant(value) == 2: value = value - Angle(180., "deg") elif quadrant(value) == 3: value = value + Angle(180., "deg") if value.to("deg").value > 180.: value = value - Angle(360., "deg") elif value.to("deg").value < -180.: value = value + Angle(360., "deg") elif parameter == "mag": parameter = "fluxdensity" value = unitconversion.ab_to_jansky(value) * u("Jy") elif parameter == "mu0": value = value * u("mag/arcsec2") elif parameter == "hr": value = value * u("arcsec") value = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) elif parameter == "hz": value = value * u("arcsec") value = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) component_parameters[parameter] = value if functionname == "sersic": re = table["Re"][index] * u("arcsec") component_parameters["Re"] = (self.parameters.distance * re).to("pc", equivalencies=dimensionless_angles()) component_parameters["n"] = table["n"][index] elif functionname == "ferrer2": rbar = table["Rbar"][index] * u("arcsec") component_parameters["Rbar"] = (self.parameters.distance * rbar).to("pc", equivalencies=dimensionless_angles()) if interpretation == "B": # bulge self.parameters.bulge = component_parameters elif interpretation == "D": # disk self.parameters.disk = component_parameters else: raise RuntimeError("Unrecognized component: " + interpretation) # Determine the full path to the parameters file #path = fs.join(self.components_path, "parameters.dat") # Write the parameters to the specified location #write_parameters(self.parameters, path) # ----------------------------------------------------------------- def get_parameters_from_table(self): """ This function ... :return: """ # Inform the user log.info("Getting the structural galaxy parameters from the S4G catalog ...") # Inform the user log.info("Parsing S4G table 8 to get the decomposition parameters ...") #The table columns are: # (1) the running number (1-2352), # (2) the galaxy name, # (3) the type of final decomposition model, # (4) the number N of components in the final model , and # (5) the quality flag Q. # 6- 8 for unresolved central component ('psf'; phys, frel, mag), # 9-15 for inner sersic-component ('sersic1'; phys, frel, mag, re, ar, pa, n), # 16-22 for inner disk-component ('expo1'; phys, frel, mag, hr, ar, pa, mu0), # 23-28 for inner ferrers-component ('ferrers1'; phys, frel, mu0, rout, ar, pa), # 29-34 for inner edge-on disk component ('edgedisk1'; phys, frel, mu0, rs, hs, pa ). # 35-41 for outer sersic-component ('sersic2'; phys, frel, mag, re, ar, pa, n), # 42-49 for outer disk-component ('expo2'; phys, frel, mag, hr, ar, pa, mu0), # 50-55 for outer ferrers-component ('ferrers2'; phys, frel, mu0, rout, ar, pa), # 56-61 for outer edge-on disk component ('edgedisk2'; phys, frel, mu0, rs, hs, pa ). sersic_1_index = 8 disk_1_index = 15 edgedisk_1_index = 28 #For each function: #the first entry stands for the physical intepretation of the component: #'N' for a central source (or unresolved bulge), 'B' for a bulge (or elliptical), 'D' for a disk, 'BAR' for a bar, and 'Z' for an edge-on disk. # 'rel = the relative contribution of the component to the total model flux, # mag = the component's total 3.6 micron AB magnitude, # mu0 = the central surface brightness (mag/arcsec^2; de-projected central surface brightness for expdisk and edgedisk, and # sky-plane central surface brightness for ferrer) # ar = axial ratio # pa = position angle (degrees ccw from North) # n = sersic index # hr = exponential scale lenght (arcsec) # rs = radial scale lenght (arcsec) # hs = vertical scale height (arcsec) # rout = bar outer truncation radius (arcsec) # SERSIC: phys, frel, mag, re, ar, pa, n # DISK: phys, frel, mag, hr, ar, pa, mu0 # EDGEDISK: phys frel mu0 rs hs pa with open(local_table_path, 'r') as s4g_table: for line in s4g_table: splitted = line.split() if len(splitted) < 2: continue name = splitted[1] #print(list(name)) # Only look at the line corresponding to the galaxy if name != self.ngc_name_nospaces: continue #if self.ngc_name_nospaces not in name: continue #self.parameters.model_type = splitted[2] #self.parameters.number_of_components = splitted[3] #self.parameters.quality = splitted[4] ## BULGE #self.parameters.bulge.interpretation = splitted[sersic_1_index].split("|")[1] bulge_f = float(splitted[sersic_1_index + 1]) mag = float(splitted[sersic_1_index + 2]) bulge_fluxdensity = unitconversion.ab_to_jansky(mag) * u("Jy") # Effective radius in pc re_arcsec = float(splitted[sersic_1_index + 3]) * u("arcsec") bulge_re = (self.properties.distance * re_arcsec).to("pc", equivalencies=dimensionless_angles()) bulge_q = float(splitted[sersic_1_index + 4]) bulge_pa = Angle(float(splitted[sersic_1_index + 5]) - 90., "deg") bulge_n = float(splitted[sersic_1_index + 6]) # Create the bulge component bulge = SersicModel2D(rel_contribution=bulge_f, fluxdensity=bulge_fluxdensity, effective_radius=bulge_re, axial_ratio=bulge_q, position_angle=bulge_pa, index=bulge_n) # Add the bulge to the components dictionary self.components["bulge"] = bulge ## DISK if splitted[disk_1_index + 1] != "-": #self.parameters.disk.interpretation = splitted[disk_1_index].split("|")[1] disk_f = float(splitted[disk_1_index + 1]) mag = float(splitted[disk_1_index + 2]) disk_fluxdensity = unitconversion.ab_to_jansky(mag) * u("Jy") # Scale length in pc hr_arcsec = float(splitted[disk_1_index + 3]) * u("arcsec") disk_hr = (self.properties.distance * hr_arcsec).to("pc", equivalencies=dimensionless_angles()) disk_q = float(splitted[disk_1_index + 4]) # axial ratio disk_pa = Angle(float(splitted[disk_1_index + 5]) - 90., "deg") disk_mu0 = float(splitted[disk_1_index + 6]) * u("mag/arcsec2") # Create the disk component disk = ExponentialDiskModel2D(rel_contribution=disk_f, fluxdensity=disk_fluxdensity, scalelength=disk_hr, axial_ratio=disk_q, position_angle=disk_pa, mu0=disk_mu0) else: # phys frel mu0 rs hs pa disk_f = float(splitted[edgedisk_1_index + 1]) mag = None fluxdensity = None # frel mu0 rs hs pa #print(disk_f) disk_mu0 = float(splitted[edgedisk_1_index + 2]) * u("mag/arcsec2") # rs hs pa # rs = radial scale lenght (arcsec) # hs = vertical scale height (arcsec) rs = float(splitted[edgedisk_1_index + 3]) hs = float(splitted[edgedisk_1_index + 4]) #print(rs) #print(hs) disk_pa = Angle(float(splitted[edgedisk_1_index + 5]) - 90., "deg") #print(disk_pa) disk_q = hs / rs # Create the disk component disk = ExponentialDiskModel2D(rel_contribution=disk_f, scalelength=rs, axial_ratio=disk_q, position_angle=disk_pa, mu0=disk_mu0) # Add the disk to the components dictionary self.components["disk"] = disk # ----------------------------------------------------------------- @property def disk_pa(self): """ This function ... :return: """ return self.components["disk"].position_angle # ----------------------------------------------------------------- def show(self): """ This function ... :return: """ print(fmt.green + "Galaxy properties" + fmt.reset + ":") print("") print(self.properties) print("") for name in self.components: print(fmt.green + name + fmt.reset + ":") print("") print(self.components[name]) print("") # ----------------------------------------------------------------- def write(self): """ This function ... :return: """ # Inform the user log.info("Writing ...") # Write the properties self.write_properties() # Write the components self.write_components() # ----------------------------------------------------------------- def write_properties(self): """ This function ... :return: """ # Inform the user log.info("Writing the properties ...") # Determine the path and save path = self.output_path_file("properties.dat") self.properties.saveto(path) # ----------------------------------------------------------------- def write_components(self): """ This function ... :return: """ # Inform the user log.info("Writing the components ...") # Loop over the components for name in self.components: # Determine the path path = self.output_path_file(name + ".mod") # Save the model self.components[name].saveto(path)
def get_galaxy_info(name, position): """ This function ... :param name: :param position: :return: """ # Obtain more information about this galaxy try: ned_result = Ned.query_object(name) ned_entry = ned_result[0] # Get a more common name for this galaxy (sometimes, the name obtained from NED is one starting with 2MASX .., use the PGC name in this case) if ned_entry["Object Name"].startswith("2MASX "): gal_name = name else: gal_name = ned_entry["Object Name"] # Get the redshift gal_redshift = ned_entry["Redshift"] if isinstance(gal_redshift, np.ma.core.MaskedConstant): gal_redshift = None # Get the type (G=galaxy, HII ...) gal_type = ned_entry["Type"] if isinstance(gal_type, np.ma.core.MaskedConstant): gal_type = None except astroquery.exceptions.RemoteServiceError: # Set attributes gal_name = name gal_redshift = None gal_type = None except astroquery.exceptions.TimeoutError: # Set attributes gal_name = name gal_redshift = None gal_type = None except: # Set attributes gal_name = name gal_redshift = None gal_type = None # Create a new Vizier object and set the row limit to -1 (unlimited) viz = Vizier(keywords=["galaxies", "optical"]) viz.ROW_LIMIT = -1 # Query Vizier and obtain the resulting table result = viz.query_object(name.replace(" ", ""), catalog=["VII/237"]) # Not found ... TODO: fix this ... this object was in the first query output if len(result) == 0: return name, position, None, None, [], None, None, None, None, None, None table = result[0] # Get the correct entry (sometimes, for example for mergers, querying with the name of one galaxy gives two hits! We have to obtain the right one each time!) if len(table) == 0: raise ValueError("The galaxy could not be found under this name") elif len(table) == 1: entry = table[0] else: entry = None # Some rows don't have names, if no match is found based on the name just take the row that has other names defined rows_with_names = [] for row in table: if row["ANames"]: rows_with_names.append(row) # If only one row remains, take that one for the galaxy we are looking for if len(rows_with_names) == 1: entry = rows_with_names[0] # Else, loop over the rows where names are defined and look for a match else: for row in rows_with_names: names = row["ANames"] if name.replace(" ", "") in names or gal_name.replace(" ", "") in names: entry = row break # If no matches are found, look for the table entry for which the coordinate matches the given position (if any) if entry is None and position is not None: for row in table: if np.isclose(row["_RAJ2000"], position.ra.value) and np.isclose(row["_DEJ2000"], position.dec.value): entry = row break # Note: another temporary fix if entry is None: return name, position, None, None, [], None, None, None, None, None, None # Get the right ascension and the declination position = SkyCoordinate(ra=entry["_RAJ2000"], dec=entry["_DEJ2000"], unit="deg", frame="fk5") # Get the names given to this galaxy gal_names = entry["ANames"].split() if entry["ANames"] else [] # Get the size of the galaxy ratio = np.power(10.0, entry["logR25"]) if entry["logR25"] else None diameter = np.power(10.0, entry["logD25"]) * 0.1 * Unit("arcmin") if entry["logD25"] else None #print(" D25_diameter = ", diameter) radial_profiles_result = viz.query_object(name, catalog="J/ApJ/658/1006") if len(radial_profiles_result) > 0: radial_profiles_entry = radial_profiles_result[0][0] gal_distance = radial_profiles_entry["Dist"] * Unit("Mpc") gal_inclination = Angle(radial_profiles_entry["i"], "deg") gal_d25 = radial_profiles_entry["D25"] * Unit("arcmin") else: gal_distance = None gal_inclination = None gal_d25 = None # Get the size of major and minor axes gal_major = diameter gal_minor = diameter / ratio if diameter is not None and ratio is not None else None # Get the position angle of the galaxy gal_pa = Angle(entry["PA"] - 90.0, "deg") if entry["PA"] else None # Create and return a new Galaxy instance return gal_name, position, gal_redshift, gal_type, gal_names, gal_distance, gal_inclination, gal_d25, gal_major, gal_minor, gal_pa
GAIA_X_match = pd.read_csv(csv_path+csv_gaia_id) GAIA_X_match = GAIA_X_match[GAIA_X_match['Identifier'].isin(data_csv["Name"].tolist())] # only select those identifiers also in the actual dataframe # find data of all stars contained within the cross match and the data csv, not containing any NaNs data_csv = data_csv[data_csv["Name"].isin(GAIA_X_match['Identifier'].tolist())] # all stars to be queried starnames = GAIA_X_match["Identifier"].tolist() GAIA_ids = GAIA_X_match['GaiaID'].values.astype(str) # look up GAIA catalog inputs for the stars plxs = [] e_plxs = [] starnames_GAIA = [] for starname,GAIA_id in zip(starnames,GAIA_ids): star = Vizier.query_object(starname, catalog=["Gaia"]) for table_name in star.keys(): dataframe = star[table_name].to_pandas() if re.search(r'345\/gaia2',table_name): table_of_sourcenames = star[table_name]["Source"] dataframe = star[table_name].to_pandas() matchindex = [i for i,j in enumerate(table_of_sourcenames) if re.search(GAIA_id,str(j))] PLX = dataframe.iloc[matchindex]["Plx"].values e_PLX = dataframe.iloc[matchindex]["e_Plx"].values plxs.append(PLX[0]) e_plxs.append(e_PLX[0]) print(starname) # convert lists to numpy arrays PLXs = np.array(plxs).astype(str) e_PLXs = np.array(e_plxs).astype(str)
result_table['FLUX_BIBCODE_z'][0].decode('utf-8')) else: print("M", args.target, "SDSS z", result_table['FLUX_z'][0], "0.05 # ", result_table['FLUX_BIBCODE_z'][0].decode('utf-8'),"; e_mag set to 0.05") print("#") #2: get Tycho magnitudes from vizier (Tycho2 catalog and supplements) # need to request all columns since by default, no error columns are returned. vquery=Vizier(columns=["**"]) # query catalogs res = vquery.query_object(args.target,catalog=["I/259/tyc2", "I/259/suppl_1", "I/259/suppl_2"]) # some weird but necessary type conversion stuff for table_name in res.keys(): tyc2table = res[table_name] # print results if len(res) > 0: # to make sure star is in the catalog; fails otherwise print("#") print("# Tycho 2") print("#") if tyc2table['BTmag'][0] != None: print("M", args.target, "Tycho Bt", tyc2table['BTmag'][0], tyc2table['e_BTmag'][0]," # ", "2000A&A...355L..27H")
diff = tab['{} mag'.format(oneBand)] - tab['{}mag_2mass'.format( oneBand)] plot_density_scatter(axArr[bandInd, 0], tab['{} mag'.format(oneBand)], diff) axArr[bandInd, 0].set_ylim(-0.2, 0.2) axArr[bandInd, 0].set_ylabel(r"{} (UKIRT) - {} (2MASS)".format( oneBand, oneBand)) axArr[bandInd, 0].set_xlabel("{} (UKIRT)".format(oneBand)) plot_density_scatter(axArr[bandInd, 1], tab['J mag'] - tab['K mag'], diff) axArr[bandInd, 1].set_xlabel("J (UKIRT) - K (UKIRT)") axArr[bandInd, 1].set_ylim(-0.2, 0.2) # minmax_show = [np.nanmin(tab['J mag']),np.nanmax(tab['Jmag_2mass'])] #plt.plot(minmax_show,1.0) plt.show() return tm_res """ Vizier.query_object("NGC 2506",catalog="II/246/out") result = Vizier.query_object("NGC 2506") #catalog_list = Vizier.find_catalogs('NGC 2506') tm_res = Vizier(catalog='II/246/out').query_region("NGC 2506",radius=0.3 *u.deg)[0] catalog="II/246/out" """
class GalaxyDecomposer(DecompositionComponent): """ This class... """ def __init__(self, config=None): """ The constructor ... :param config: :return: """ # Call the constructor of the base class super(GalaxyDecomposer, self).__init__(config) # The NGC name of the galaxy self.ngc_id = None self.ngc_id_nospaces = None # The Vizier querying object self.vizier = Vizier() self.vizier.ROW_LIMIT = -1 # The bulge and disk parameters self.parameters = Map() # The SKIRT execution context self.skirt = SkirtExec() # The bulge and disk model self.bulge = None self.disk = None # The bulge and disk image self.bulge_image = None self.disk_image = None self.model_image = None # The projection systems self.projections = dict() # The instruments self.instruments = dict() # The reference coordinate system self.reference_wcs = None # The PSF (of the reference image) for convolution with the simulated images self.psf = None # ----------------------------------------------------------------- @classmethod def from_arguments(cls, arguments): """ This function ... :param arguments: :return: """ # Create a new GalaxyDecomposer instance decomposer = cls(arguments.config) # Set the input and output path decomposer.config.path = arguments.path # Return the new instance return decomposer # ----------------------------------------------------------------- def run(self): """ This function ... :return: """ # 1. Call the setup function self.setup() # 2. Get the parameters self.get_parameters() # 3. Create the models self.create_models() # 4. Create the projection systems self.create_projections() # 4. Create the instruments self.create_instruments() # 2. Simulate the bulge and disk images self.simulate() # 3. Writing self.write() # ----------------------------------------------------------------- def setup(self): """ This function ... :return: """ # Call the setup function of the base class super(GalaxyDecomposer, self).setup() # TEMP: provide a cfg file for this class self.config.bulge_packages = 1e7 self.config.disk_packages = 1e8 # Get the NGC name of the galaxy self.ngc_id = catalogs.get_ngc_name(self.galaxy_name) self.ngc_id_nospaces = self.ngc_id.replace(" ", "") # Get the coordinate system describing the pixel grid of the prepared images reference_path = fs.join(self.prep_path, self.reference_image, "result.fits") self.reference_wcs = CoordinateSystem.from_file(reference_path) # Load the PSF aniano = AnianoKernels() self.psf = aniano.get_psf("PACS_160") # ----------------------------------------------------------------- def get_parameters(self): """ This function ... :return: """ # Inform the user log.info("Getting the structural galaxy parameters from the S4G catalog ...") # Tracing spiral density waves in M81: (Kendall et. al, 2008) # - Sersic bulge: # n = 2.62 # Re = 46.2 arcsec # b/a = 0.71 # PA = −31.9° # - Exponential disk: # Rs = 155.4 arcsec # b/a = 0.52 # PA = −28.3° # Query the S4G catalog using Vizier for general parameters self.get_general_parameters() # Get the decomposition parameters #self.get_p4() currently (writing on 31 of march 2016) there is a problem with the effective radius values # (at least for M81) on Vizier as well as in the PDF version of table 7 (S4G models homepage). # Parse the S4G table 8 to get the decomposition parameters self.get_parameters_from_table() #self.parameters.bulge.n = 2.62 #self.parameters.bulge.PA = Angle(-31.9 + 90., "deg") #self.parameters.bulge.q = 0.71 #value = 46.2 * Unit("arcsec") #self.parameters.bulge.Re = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) #value = 155.4 * Unit("arcsec") #self.parameters.disk.hr = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) #self.parameters.disk.q = 0.52 #self.parameters.disk.PA = Angle(-28.3 + 90., "deg") # ----------------------------------------------------------------- def get_general_parameters(self): """ This function ... :return: """ # Inform the user log.info("Querying the S4G catalog ...") # Get parameters from S4G catalog result = self.vizier.query_object(self.galaxy_name, catalog=["J/PASP/122/1397/s4g"]) table = result[0] # Galaxy name for S4G catalog self.parameters.galaxy_name = table["Name"][0] # Galaxy center from decomposition (?) ra_center = table["_RAJ2000"][0] dec_center = table["_DEJ2000"][0] center = SkyCoordinate(ra=ra_center, dec=dec_center, unit="deg", frame='fk5') self.parameters.center = center # Distance self.parameters.distance = table["Dmean"][0] * Unit("Mpc") self.parameters.distance_error = table["e_Dmean"][0] * Unit("Mpc") # Major axis, ellipticity, position angle self.parameters.major_arcsec = table["amaj"][0] * Unit("arcsec") self.parameters.major = (self.parameters.distance * self.parameters.major_arcsec).to("pc", equivalencies=dimensionless_angles()) # Ellipticity self.parameters.ellipticity = table["ell"][0] self.parameters.position_angle = Angle(table["PA"][0] + 90.0, Unit("deg")) # Magnitudes asymptotic_ab_magnitude_i1 = table["__3.6_"][0] asymptotic_ab_magnitude_i2 = table["__4.5_"][0] asymptotic_ab_magnitude_i1_error = table["e__3.6_"][0] asymptotic_ab_magnitude_i2_error = table["e__4.5_"][0] self.parameters.i1_mag = asymptotic_ab_magnitude_i1 self.parameters.i1_mag_error = asymptotic_ab_magnitude_i1_error self.parameters.i2_mag = asymptotic_ab_magnitude_i2 self.parameters.i2_mag_error = asymptotic_ab_magnitude_i2_error self.parameters.i1_fluxdensity = unitconversion.ab_to_jansky(self.parameters.i1_mag) * Unit("Jy") i1_fluxdensity_lower = unitconversion.ab_to_jansky(self.parameters.i1_mag + self.parameters.i1_mag_error) * Unit("Jy") i1_fluxdensity_upper = unitconversion.ab_to_jansky(self.parameters.i1_mag - self.parameters.i1_mag_error) * Unit("Jy") i1_error = ErrorBar(i1_fluxdensity_lower, i1_fluxdensity_upper, at=self.parameters.i1_fluxdensity) self.parameters.i1_error = i1_error.average self.parameters.i2_fluxdensity = unitconversion.ab_to_jansky(self.parameters.i2_mag) * Unit("Jy") i2_fluxdensity_lower = unitconversion.ab_to_jansky(self.parameters.i2_mag + self.parameters.i2_mag_error) * Unit("Jy") i2_fluxdensity_upper = unitconversion.ab_to_jansky(self.parameters.i2_mag - self.parameters.i2_mag_error) * Unit("Jy") i2_error = ErrorBar(i2_fluxdensity_lower, i2_fluxdensity_upper, at=self.parameters.i2_fluxdensity) self.parameters.i2_error = i2_error.average # Other ... #absolute_magnitude_i1 = table["M3.6"][0] #absolute_magnitude_i2 = table["M4.5"][0] #stellar_mass = 10.0**table["logM_"][0] * u.Unit("Msun") # Inform the user log.info("Querying the catalog of radial profiles for 161 face-on spirals ...") # Radial profiles for 161 face-on spirals (Munoz-Mateos+, 2007) radial_profiles_result = self.vizier.query_object(self.galaxy_name, catalog="J/ApJ/658/1006") distance = float(radial_profiles_result[0][0]["Dist"]) inclination = Angle(float(radial_profiles_result[0][0]["i"]), "deg") # Set the inclination self.parameters.inclination = inclination # ----------------------------------------------------------------- def get_p4(self): """ This function ... :return: """ #http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/ApJS/219/4 # J/ApJS/219/4: S4G pipeline 4: multi-component decompositions (Salo+, 2015) # - J/ApJS/219/4/galaxies: Parameters of the galaxies; center, outer orientation, sky background; and 1-component Sersic fits (tables 1 and 6) (2352 rows) # - J/ApJS/219/4/table7: *Parameters of final multicomponent decompositions (Note) (4629 rows) # Inform the user log.info("Querying the S4G pipeline 4 catalog ...") # Get the "galaxies" table result = self.vizier.query_object(self.galaxy_name, catalog=["J/ApJS/219/4/galaxies"]) table = result[0] # PA: [0.2/180] Outer isophote position angle # e_PA: [0/63] Standard deviation in PA # Ell: [0.008/1] Outer isophote ellipticity # e_Ell: [0/0.3] Standard deviation in Ell pa = Angle(table["PA"][0] - 90., "deg") pa_error = Angle(table["e_PA"][0], "deg") ellipticity = table["Ell"][0] ellipticity_error = table["e_Ell"][0] # Get the "table7" table result = self.vizier.get_catalogs("J/ApJS/219/4/table7") table = result[0] # Name: Galaxy name # Mod: Type of final decomposition model # Nc: [1/4] Number of components in the model (1-4) # Q: [3/5] Quality flag, 5=most reliable # C: Physical interpretation of the component # Fn: The GALFIT function used for the component (sersic, edgedisk, expdisk, ferrer2 or psf) # f1: [0.006/1] "sersic" fraction of the total model flux # mag1: [7/19.4] "sersic" total 3.6um AB magnitude # q1: [0.1/1] "sersic" axis ratio # PA1: [0.08/180] "sersic" position angle [deg] # Re: [0.004/430] "sersic" effective radius (Re) [arcsec] # n: [0.01/20] "sersic" parameter n # f2: [0.02/1] "edgedisk" fraction of the total model flux # mu02: [11.8/24.6] "edgedisk" central surface face-on brightness (µ0) [mag/arcsec2] # PA2: [-90/90] "edgedisk" PA [deg] # hr2: [1/153] "edgedisk" exponential scale length (hr) [arcsec] # hz2: [0.003/39] "edgedisk" z-scale hz [arcsec] # f3: [0.02/1] "expdisk" fraction of the total model flux # mag3: [6.5/18.1] "expdisk" total 3.6um AB magnitude [mag] # q3: [0.1/1] "expdisk" axis ratio # PA3: [-90/90] "expdisk" position angle [deg] # hr3: [0.7/332] "expdisk" exponential scale length (hr) [arcsec] # mu03: [16.4/25.3] "expdisk" central surface face-on brightness (µ0) [mag/arcsec2] # f4: [0.003/0.6] "ferrer2" fraction of the total model flux # mu04: [16/24.8] "ferrer2" central surface sky brightness (µ0) [mag/arcsec2] # q4: [0.01/1] "ferrer2" axis ratio # PA4: [-90/90] "ferrer2" position angle [deg] # Rbar: [3.7/232.5] "ferrer2" outer truncation radius of the bar (Rbar) [arcsec] # f5: [0.001/0.4] "psf" fraction of the total model flux # mag5: [11.5/21.1] "psf" total 3.6um AB magnitude [mag] indices = tables.find_indices(table, self.ngc_id_nospaces, "Name") labels = {"sersic": 1, "edgedisk": 2, "expdisk": 3, "ferrer2": 4, "psf": 5} #units = {"f": None, "mag": "mag", "q": None, "PA": "deg", } # Loop over the indices for index in indices: model_type = table["Mod"][index] number_of_components = table["Nc"][index] quality = table["Q"][index] interpretation = table["C"][index] functionname = table["Fn"][index] component_parameters = Map() if self.parameters.model_type is not None: assert model_type == self.parameters.model_type if self.parameters.number_of_components is not None: assert number_of_components == self.parameters.number_of_components if self.parameters.quality is not None: assert quality == self.parameters.quality self.parameters.model_type = model_type self.parameters.number_of_components = number_of_components self.parameters.quality = quality for key in table.colnames: if not key.endswith(str(labels[functionname])): continue parameter = key[:-1] value = table[key][index] if parameter == "PA": value = Angle(value + 90., "deg") if quadrant(value) == 2: value = value - Angle(180., "deg") elif quadrant(value) == 3: value = value + Angle(180., "deg") if value.to("deg").value > 180.: value = value - Angle(360., "deg") elif value.to("deg").value < -180.: value = value + Angle(360., "deg") elif parameter == "mag": parameter = "fluxdensity" value = unitconversion.ab_to_jansky(value) * Unit("Jy") elif parameter == "mu0": value = value * Unit("mag/arcsec2") elif parameter == "hr": value = value * Unit("arcsec") value = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) elif parameter == "hz": value = value * Unit("arcsec") value = (self.parameters.distance * value).to("pc", equivalencies=dimensionless_angles()) component_parameters[parameter] = value if functionname == "sersic": re = table["Re"][index] * Unit("arcsec") component_parameters["Re"] = (self.parameters.distance * re).to("pc", equivalencies=dimensionless_angles()) component_parameters["n"] = table["n"][index] elif functionname == "ferrer2": rbar = table["Rbar"][index] * Unit("arcsec") component_parameters["Rbar"] = (self.parameters.distance * rbar).to("pc", equivalencies=dimensionless_angles()) if interpretation == "B": # bulge self.parameters.bulge = component_parameters elif interpretation == "D": # disk self.parameters.disk = component_parameters else: raise RuntimeError("Unrecognized component: " + interpretation) # Determine the full path to the parameters file path = fs.join(self.components_path, "parameters.dat") # Write the parameters to the specified location write_parameters(self.parameters, path) # ----------------------------------------------------------------- def get_parameters_from_table(self): """ This function ... :return: """ # Inform the user log.info("Parsing S4G table 8 to get the decomposition parameters ...") #The table columns are: # (1) the running number (1-2352), # (2) the galaxy name, # (3) the type of final decomposition model, # (4) the number N of components in the final model , and # (5) the quality flag Q. # 6- 8 for unresolved central component ('psf'; phys, frel, mag), # 9-15 for inner sersic-component ('sersic1'; phys, frel, mag, re, ar, pa, n), # 16-22 for inner disk-component ('expo1'; phys, frel, mag, hr, ar, pa, mu0), # 23-28 for inner ferrers-component ('ferrers1'; phys, frel, mu0, rout, ar, pa), # 29-34 for inner edge-on disk component ('edgedisk1'; phys, frel, mu0, rs, hs, pa ). # 35-41 for outer sersic-component ('sersic2'; phys, frel, mag, re, ar, pa, n), # 42-49 for outer disk-component ('expo2'; phys, frel, mag, hr, ar, pa, mu0), # 50-55 for outer ferrers-component ('ferrers2'; phys, frel, mu0, rout, ar, pa), # 56-61 for outer edge-on disk component ('edgedisk2'; phys, frel, mu0, rs, hs, pa ). sersic_1_index = 8 disk_1_index = 15 #For each function: #the first entry stands for the physical intepretation of the component: #'N' for a central source (or unresolved bulge), 'B' for a bulge (or elliptical), 'D' for a disk, 'BAR' for a bar, and 'Z' for an edge-on disk. # 'rel = the relative contribution of the component to the total model flux, # mag = the component's total 3.6 micron AB magnitude, # mu0 = the central surface brightness (mag/arcsec^2; de-projected central surface brightness for expdisk and edgedisk, and # sky-plane central surface brightness for ferrer) # ar = axial ratio # pa = position angle (degrees ccw from North) # n = sersic index # hr = exponential scale lenght (arcsec) # rs = radial scale lenght (arcsec) # hs = vertical scale height (arcsec) # rout = bar outer truncation radius (arcsec) # SERSIC: phys, frel, mag, re, ar, pa, n # DISK: phys, frel, mag, hr, ar, pa, mu0 with open(local_table_path, 'r') as s4g_table: for line in s4g_table: splitted = line.split() if len(splitted) < 2: continue name = splitted[1] # Only look at the line corresponding to the galaxy if name != self.ngc_id_nospaces: continue self.parameters.model_type = splitted[2] self.parameters.number_of_components = splitted[3] self.parameters.quality = splitted[4] # BULGE self.parameters.bulge = Map() #self.parameters.bulge.interpretation = splitted[sersic_1_index].split("|")[1] self.parameters.bulge.f = float(splitted[sersic_1_index + 1]) mag = float(splitted[sersic_1_index + 2]) self.parameters.bulge.fluxdensity = unitconversion.ab_to_jansky(mag) * Unit("Jy") # Effective radius in pc re_arcsec = float(splitted[sersic_1_index + 3]) * Unit("arcsec") self.parameters.bulge.Re = (self.parameters.distance * re_arcsec).to("pc", equivalencies=dimensionless_angles()) self.parameters.bulge.q = float(splitted[sersic_1_index + 4]) self.parameters.bulge.PA = Angle(float(splitted[sersic_1_index + 5]) - 90., "deg") self.parameters.bulge.n = float(splitted[sersic_1_index + 6]) # DISK self.parameters.disk = Map() #self.parameters.disk.interpretation = splitted[disk_1_index].split("|")[1] self.parameters.disk.f = float(splitted[disk_1_index + 1]) mag = float(splitted[disk_1_index + 2]) self.parameters.disk.fluxdensity = unitconversion.ab_to_jansky(mag) * Unit("Jy") # Scale length in pc hr_arcsec = float(splitted[disk_1_index + 3]) * Unit("arcsec") self.parameters.disk.hr = (self.parameters.distance * hr_arcsec).to("pc", equivalencies=dimensionless_angles()) self.parameters.disk.q = float(splitted[disk_1_index + 4]) # axial ratio self.parameters.disk.PA = Angle(float(splitted[disk_1_index + 5]) - 90., "deg") self.parameters.disk.mu0 = float(splitted[disk_1_index + 6]) * Unit("mag/arcsec2") # ----------------------------------------------------------------- def get_spiral_properties(self): """ This function ... :return: """ # http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/A+A/582/A86 # J/A+A/582/A86: Catalogue of features in the S4G (Herrera-Endoqui+, 2015) # - J/A+A/582/A86/table2: Properties of bars, ring- and lens-structures in the S4G (2387 rows) # - J/A+A/582/A86/table3: Properties of spiral arms in the S4G (1854 rows) # Get table2 result = self.vizier.query_object(self.galaxy_name, catalog=["J/A+A/582/A86/table2"]) table = result[0] # Name: Galaxy name # Class: Morphological classification # Type: Type of feature # sma: Semi-major axis [arcsec] # PA: Position angle [deg] # Ell: Ellipticity # smaEll: Semi-major axis from ellipticity [arcsec] # dsma: Deprojected semi-major axis [arcsec] # dPA: Deprojected position angle [deg] # dEll: Deprojected ellipticity # dsmaEll: Deprojexted semi-major axis from Ell [arcsec] # Qual: [1/3] Quality flag # Get table 3 result = self.vizier.query_object(self.galaxy_name, catalog=["J/A+A/582/A86/table3"]) table = result[0] # Name: Galaxy name # Class: Morphological classification # Type: Type of arms # Segment: Segment # Pitchang: Pitch angle [deg] # ri: Inner radius [arcsec] # ro: Outer radius [arcsec] # Qual: [1/2] Quality flag # ----------------------------------------------------------------- def create_models(self): """ :return: """ # Create the bulge model self.create_bulge_model() # Create the disk model self.create_disk_model() # ----------------------------------------------------------------- def create_bulge_model(self): """ :return: """ # Create a Sersic model for the bulge self.bulge = SersicModel.from_galfit(self.parameters.bulge, self.parameters.inclination, self.parameters.disk.PA) # ----------------------------------------------------------------- def create_disk_model(self): """ :return: """ # Create an exponential disk model for the disk self.disk = ExponentialDiskModel.from_galfit(self.parameters.disk, self.parameters.inclination, self.parameters.disk.PA) # ----------------------------------------------------------------- def create_projections(self): """ This function ... :return: """ # Inform the user log.info("Creating the projection systems ...") # Create the 'earth' projection system azimuth = 0.0 self.projections["earth"] = GalaxyProjection.from_wcs(self.reference_wcs, self.parameters.center, self.parameters.distance, self.parameters.inclination, azimuth, self.parameters.disk.PA) # Create the face-on projection system self.projections["faceon"] = FaceOnProjection.from_wcs(self.reference_wcs, self.parameters.center, self.parameters.distance) # Create the edge-on projection system self.projections["edgeon"] = EdgeOnProjection.from_wcs(self.reference_wcs, self.parameters.center, self.parameters.distance) # ----------------------------------------------------------------- def create_instruments(self): """ This function ... :return: """ # Inform the user log.info("Creating the instruments ...") # Loop over the projection systems for name in self.projections: # Create the instrument from the projection system self.instruments[name] = SimpleInstrument.from_projection(self.projections[name]) # ----------------------------------------------------------------- def simulate(self): """ This function ... :return: """ # Simulate the stellar bulge without deprojection self.simulate_bulge_simple() # Simulate the stellar bulge self.simulate_bulge() # Simulate the stellar disk self.simulate_disk() # Simulate the bulge + disk model self.simulate_model() # ----------------------------------------------------------------- def simulate_bulge_simple(self): """ :return: """ # Inform the user log.info("Creating ski file to simulate the bulge image ...") # Load the bulge ski file template bulge_template_path = fs.join(template_path, "bulge.ski") ski = SkiFile(bulge_template_path) # Set the number of photon packages ski.setpackages(self.config.bulge_packages) # Change the ski file parameters # component_id, index, radius, y_flattening=1, z_flattening=1 ski.set_stellar_component_sersic_geometry(0, self.parameters.bulge.n, self.parameters.bulge.Re, y_flattening=self.parameters.bulge.q) # Remove all existing instruments ski.remove_all_instruments() # Create the instrument distance = self.parameters.distance inclination = 0.0 azimuth = Angle(90., "deg") #position_angle = self.parameters.bulge.PA + Angle(90., "deg") # + 90° because we can only do y_flattening and not x_flattening position_angle = self.parameters.bulge.PA pixels_x = self.reference_wcs.xsize pixels_y = self.reference_wcs.ysize pixel_center = self.parameters.center.to_pixel(self.reference_wcs) center = Position(0.5*pixels_x - pixel_center.x - 0.5, 0.5*pixels_y - pixel_center.y - 0.5) center_x = center.x * Unit("pix") center_y = center.y * Unit("pix") center_x = (center_x * self.reference_wcs.pixelscale.x.to("deg/pix") * distance).to("pc", equivalencies=dimensionless_angles()) center_y = (center_y * self.reference_wcs.pixelscale.y.to("deg/pix") * distance).to("pc", equivalencies=dimensionless_angles()) field_x_angular = self.reference_wcs.pixelscale.x.to("deg/pix") * pixels_x * Unit("pix") field_y_angular = self.reference_wcs.pixelscale.y.to("deg/pix") * pixels_y * Unit("pix") field_x_physical = (field_x_angular * distance).to("pc", equivalencies=dimensionless_angles()) field_y_physical = (field_y_angular * distance).to("pc", equivalencies=dimensionless_angles()) fake = SimpleInstrument(distance, inclination, azimuth, position_angle, field_x_physical, field_y_physical, pixels_x, pixels_y, center_x, center_y) # Add the instrument ski.add_instrument("earth", fake) # Create the directory to simulate the bulge simple_bulge_directory = fs.join(self.components_path, "bulge_simple") fs.create_directory(simple_bulge_directory) # Determine the path to the ski file ski_path = fs.join(simple_bulge_directory, "bulge.ski") # Save the ski file to the new path ski.saveto(ski_path) # Determine the path to the simulation output directory out_path = fs.join(simple_bulge_directory, "out") # Create the output directory fs.create_directory(out_path) # Create a SkirtArguments object arguments = SkirtArguments() # Adjust the parameters arguments.ski_pattern = ski_path arguments.output_path = out_path arguments.single = True # we expect a single simulation from the ski pattern # Inform the user log.info("Running the bulge simulation ...") # Run the simulation simulation = self.skirt.run(arguments, silent=False if log.is_debug() else True) # Determine the path to the output FITS file bulge_image_path = fs.join(out_path, "bulge_earth_total.fits") # Check if the output contains the "bulge_earth_total.fits" file if not fs.is_file(bulge_image_path): raise RuntimeError("Something went wrong with the simple bulge simulation: output FITS file missing") # ----------------------------------------------------------------- def simulate_bulge(self): """ This function ... :return: """ # Inform the user log.info("Creating ski file to simulate the bulge image ...") # Load the bulge ski file template bulge_template_path = fs.join(template_path, "bulge.ski") ski = SkiFile(bulge_template_path) # Set the number of photon packages ski.setpackages(self.config.bulge_packages) # Set the bulge geometry ski.set_stellar_component_geometry(0, self.bulge) # Remove all existing instruments ski.remove_all_instruments() # Add the instruments for name in self.instruments: ski.add_instrument(name, self.instruments[name]) # Determine the path to the ski file ski_path = fs.join(self.bulge_path, "bulge.ski") # Save the ski file to the new path ski.saveto(ski_path) # Determine the path to the simulation output directory out_path = fs.join(self.bulge_path, "out") # Create the output directory fs.create_directory(out_path) # Create a SkirtArguments object arguments = SkirtArguments() # Adjust the parameters arguments.ski_pattern = ski_path arguments.output_path = out_path arguments.single = True # we expect a single simulation from the ski pattern # Inform the user log.info("Running the bulge simulation ...") # Run the simulation simulation = self.skirt.run(arguments, silent=False if log.is_debug() else True) # Determine the path to the output FITS file bulge_image_path = fs.join(out_path, "bulge_earth_total.fits") # Check if the output contains the "bulge_earth_total.fits" file if not fs.is_file(bulge_image_path): raise RuntimeError("Something went wrong with the bulge simulation: output FITS file missing") # Open the bulge image self.bulge_image = Frame.from_file(bulge_image_path) # Set the coordinate system of the bulge image self.bulge_image.wcs = self.reference_wcs # Debugging log.debug("Rescaling the bulge image to the bulge flux density at 3.6 micron ...") # Rescale to the 3.6um flux density fluxdensity = self.parameters.bulge.fluxdensity self.bulge_image *= fluxdensity.to("Jy").value / np.sum(self.bulge_image) self.bulge_image.unit = "Jy" # Debugging log.debug("Convolving the bulge image to the PACS 160 resolution ...") # Convolve the frame to the PACS 160 resolution self.bulge_image = self.bulge_image.convolved(self.psf) # ----------------------------------------------------------------- def simulate_disk(self): """ This function ... :return: """ # Inform the user log.info("Creating ski file to simulate the disk image ...") # Load the disk ski file template disk_template_path = fs.join(template_path, "disk.ski") ski = SkiFile(disk_template_path) # Set the number of photon packages ski.setpackages(self.config.disk_packages) # Change the ski file parameters ski.set_stellar_component_geometry(0, self.disk) # Remove all existing instruments ski.remove_all_instruments() # Add the instruments for name in self.instruments: ski.add_instrument(name, self.instruments[name]) # Determine the path to the ski file ski_path = fs.join(self.disk_path, "disk.ski") # Save the ski file to the new path ski.saveto(ski_path) # Determine the path to the simulation output directory out_path = fs.join(self.disk_path, "out") # Create the output directory fs.create_directory(out_path) # Create a SkirtArguments object arguments = SkirtArguments() # Adjust the parameters arguments.ski_pattern = ski_path arguments.output_path = out_path arguments.single = True # we expect a single simulation from the ski pattern # Inform the user log.info("Running the disk simulation ...") # Run the simulation simulation = self.skirt.run(arguments, silent=False if log.is_debug() else True) # Determine the path to the output FITS file disk_image_path = fs.join(out_path, "disk_earth_total.fits") # Check if the output contains the "disk_earth_total.fits" file if not fs.is_file(disk_image_path): raise RuntimeError("Something went wrong with the disk simulation: output FITS file missing") # Open the disk image self.disk_image = Frame.from_file(disk_image_path) # Set the coordinate system of the disk image self.disk_image.wcs = self.reference_wcs # Debugging log.debug("Rescaling the disk image to the disk flux density at 3.6 micron ...") # Rescale to the 3.6um flux density fluxdensity = self.parameters.disk.fluxdensity self.disk_image *= fluxdensity.to("Jy").value / np.sum(self.disk_image) self.disk_image.unit = "Jy" # Debugging log.debug("Convolving the disk image to the PACS 160 resolution ...") # Convolve the frame to the PACS 160 resolution self.disk_image = self.disk_image.convolved(self.psf) # ----------------------------------------------------------------- def simulate_model(self): """ This function ... """ # Inform the user log.info("Creating ski file to simulate the bulge+disk model image ...") # Load the disk ski file template disk_template_path = fs.join(template_path, "model.ski") ski = SkiFile(disk_template_path) # Set the number of photon packages ski.setpackages(self.config.disk_packages) # Change the ski file parameters ski.set_stellar_component_geometry(0, self.disk) ski.set_stellar_component_geometry(1, self.bulge) # Set the luminosities of the two components ski.set_stellar_component_luminosities(0, [self.parameters.disk.f]) ski.set_stellar_component_luminosities(1, [self.parameters.bulge.f]) # Remove all existing instruments ski.remove_all_instruments() # Add the instruments for name in self.instruments: ski.add_instrument(name, self.instruments[name]) # Determine the path to the ski file ski_path = fs.join(self.model_path, "model.ski") # Save the ski file to the new path ski.saveto(ski_path) # Determine the path to the simulation output directory out_path = fs.join(self.model_path, "out") # Create the output directory fs.create_directory(out_path) # Create a SkirtArguments object arguments = SkirtArguments() # Adjust the parameters arguments.ski_pattern = ski_path arguments.output_path = out_path arguments.single = True # we expect a single simulation from the ski pattern # Inform the user log.info("Running the disk+bulge simulation ...") # Run the simulation simulation = self.skirt.run(arguments, silent=False if log.is_debug() else True) # Determine the path to the output FITS file model_image_path = fs.join(out_path, "model_earth_total.fits") # Check if the output contains the "model_earth_total.fits" file if not fs.is_file(model_image_path): raise RuntimeError("Something went wrong with the disk+bulge simulation: output FITS file missing") # Open the model image self.model_image = Frame.from_file(model_image_path) # Set the coordinate system of the model image self.model_image.wcs = self.reference_wcs # Debugging log.debug("Rescaling the model image to the bulge+disk flux density at 3.6 micron ...") # Rescale to the 3.6um flux density fluxdensity = self.parameters.bulge.fluxdensity + self.parameters.disk.fluxdensity # sum of bulge and disk component flux density self.model_image *= fluxdensity.to("Jy").value / np.sum(self.model_image) self.model_image.unit = "Jy" # Debugging log.debug("Convolving the model image to the PACS 160 resolution ...") # Convolve the frame to the PACS 160 resolution self.model_image = self.model_image.convolved(self.psf) # ----------------------------------------------------------------- def write(self): """ This function ... :return: """ # Inform the user log.info("Writing ...") # Write out the final bulge and disk images self.write_images() # Write out the parameters in a data file self.write_parameters() # Write the projection systems self.write_projections() # Write out the disk ellipse self.write_disk_ellipse() # ----------------------------------------------------------------- def write_images(self): """ This function ... :return: """ # Determine the path to the bulge image and save it final_bulge_path = fs.join(self.components_path, "bulge.fits") self.bulge_image.save(final_bulge_path) # Determine the path to the disk image and save it final_disk_path = fs.join(self.components_path, "disk.fits") self.disk_image.save(final_disk_path) # Determine the path to the model image and save it final_model_path = fs.join(self.components_path, "model.fits") self.model_image.save(final_model_path) # ----------------------------------------------------------------- def write_parameters(self): """ This function ... :return: """ # Inform the user log.info("Writing data file with parameters ...") # Determine the full path to the parameters file path = fs.join(self.components_path, "parameters.dat") # Write the parameters to the specified location write_parameters(self.parameters, path) # ----------------------------------------------------------------- def write_projections(self): """ This function ... :return: """ # Inform the user log.info("Writing the projection systems ...") # Loop over the projection systems for name in self.projections: # Determine the path to the projection file path = fs.join(self.components_path, name + ".proj") # Write the projection system self.projections[name].save(path) # ----------------------------------------------------------------- def write_disk_ellipse(self): """ This function ... :return: """ # Inform the user log.info("Writing regions file with disk ellipse ...") minor = (1.0 - self.parameters.ellipticity) * self.parameters.major_arcsec # Ellipse radius radius = Extent(self.parameters.major_arcsec, minor) # Create sky ellipse sky_ellipse = SkyEllipse(self.parameters.center, radius, self.parameters.position_angle) # Create region region = SkyRegion() region.append(sky_ellipse) region_path = fs.join(self.components_path, "disk.reg") region.save(region_path)