示例#1
0
def apokasc_load(combine=True):
    """
    NAME:
        apokasc_load
    PURPOSE:
        load apokasc result (Precise surface gravity measurement)
    INPUT:
        combine (boolean): True to combine gold snd basic standard
    OUTPUT:
    HISTORY:
        2017-Dec-23 - Written - Henry Leung (University of Toronto)
    """
    catalog_list = Vizier.find_catalogs('apokasc')
    Vizier.ROW_LIMIT = 99999
    catalogs_gold = Vizier.get_catalogs(catalog_list.keys())[1]
    catalogs_basic = Vizier.get_catalogs(catalog_list.keys())[2]
    gold_ra = catalogs_gold['_RA']
    gold_dec = catalogs_gold['_DE']
    gold_logg = catalogs_gold['log_g_']
    basic_ra = catalogs_basic['_RA']
    basic_dec = catalogs_basic['_DE']
    basic_logg = catalogs_basic['log.g2']

    if combine is True:
        ra = np.append(np.array(gold_ra), np.array(basic_ra))
        dec = np.append(np.array(gold_dec), np.array(basic_dec))
        logg = np.append(np.array(gold_logg), np.array(basic_logg))
        return ra, dec, logg
    else:
        return gold_ra, gold_dec, gold_logg, basic_ra, basic_dec, basic_logg
示例#2
0
def load_apokasc(combine=True):
    """
    Load APOKASC asteroseismic surface gravity measurement

    :param combine: True to combine gold and basic standard, otherwise only get gold standard log(g)
    :type combine: boolean
    :return: numpy array of ra, dec, array
    :rtype: ndarrays
    :History:
        | 2017-Dec-23 - Written - Henry Leung (University of Toronto)
    """
    catalog_list = Vizier.find_catalogs('apokasc')
    Vizier.ROW_LIMIT = 99999
    catalogs_gold = Vizier.get_catalogs(catalog_list.keys())[1]
    catalogs_basic = Vizier.get_catalogs(catalog_list.keys())[2]
    gold_ra = catalogs_gold['_RA']
    gold_dec = catalogs_gold['_DE']
    gold_logg = catalogs_gold['log_g_']
    basic_ra = catalogs_basic['_RA']
    basic_dec = catalogs_basic['_DE']
    basic_logg = catalogs_basic['log.g2']

    if combine is True:
        ra = np.append(np.array(gold_ra), np.array(basic_ra))
        dec = np.append(np.array(gold_dec), np.array(basic_dec))
        logg = np.append(np.array(gold_logg), np.array(basic_logg))
        return ra, dec, logg
    else:
        return gold_ra, gold_dec, gold_logg, basic_ra, basic_dec, basic_logg
示例#3
0
def get_vizier_table_as_dataframe(vizier_search_str, srccolumns, dstcolumns,
                                  table_num=0, verbose=1,
                                  whichcataloglist='default'):
    """
    Download a table from Vizier (specified by `vizier_search_str`). Get
    columns specified by the |-separated string, `columns`. Write the
    resulting table to a CSV file, `outcsvpath`.  Sometimes, the table number
    on Vizier (`table_num`) must be specified.  In the context of CDIPS catalog
    construction, this is mostly for making "source|cluster|age" output.

    Args:
        vizier_search_str (str): specifies Vizier search.
        srccolumns (str): columns in the Vizier catalog to get e.g.,
            "RA|DE|age"
        dstcolumns (str): columns to rename them to, e.g., "ra|dec|log10age".
        whichcataloglist (str): "default", else a string to specify the
            catalog, e.g., ""J/A+A/640/A1""
    """

    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs(vizier_search_str)
    if whichcataloglist == 'default':
        catalogs = Vizier.get_catalogs(catalog_list.keys())
    else:
        catalogs = Vizier.get_catalogs(whichcataloglist)

    tab = catalogs[table_num]
    if verbose:
        print(f'initial number of members: {len(tab)}')

    df = tab.to_pandas()

    # rename columns to homogeneous format. e.g.,
    # df = df.rename(columns={"Gaia": "source_id", "Group": "cluster"})
    df = df.rename(
        columns={
            k:v for k,v in zip(srccolumns.split("|"), dstcolumns.split("|"))
        }
    )

    if 'source_id' in dstcolumns.split("|"):
        # strip "Gaia DR2 6083332579305755520" style format if present
        try:
            if np.any(df.source_id.str.contains('Gaia DR2 ')):
                df['source_id'] = df.source_id.str.replace('Gaia DR2 ', '')
        except AttributeError:
            pass

        # if NaNs are present, omit them. (e.g., from EsplinLuhman19)
        if np.any(pd.isnull(df.source_id)):
            N = len(df[pd.isnull(df.source_id)])
            print(f'WRN! Found {N} null source_id values of {len(df)}. Omitting.')
            df = df[~pd.isnull(df.source_id)]

        df['source_id'] = df['source_id'].astype('int64')

    sdf = df[dstcolumns.split("|")]

    return sdf
    def query_ids_1(inp_ids,
                    catalog="II/246",
                    radius=1.0 * u.arcsecond,
                    verbose=True):
        # ""
        # NOTEBOOK: "01_read_opf_cats" [/sample_initial/]
        # "Level-1 code to perform multiple VizieR searches"
        # ""
        # 1) Construct Dummy Row ===========
        Vizier.ROW_LIMIT = 1
        cat_0 = Vizier.get_catalogs(catalog)
        dummy_tb = cat_0[0]
        dummy_tb['_r'] = 0
        dummy_tb['dummy'] = 'Y'
        Vizier.ROW_LIMIT = -1

        # 2) Construct Seed Table ==========
        viz_tb = dummy_tb.copy()

        # 3) Add rows to Seed Table ========
        for inp in inp_ids:
            result = sample_initial.query_ids_0(inp,
                                                catalog=catalog,
                                                radius=radius,
                                                verbose=verbose)
            viz_tb = vstack([viz_tb, Table(result)])

        viz_tb = viz_tb[viz_tb['dummy'] != 'Y']
        viz_tb['_r'] = viz_tb['_r'].to(u.arcsecond)
        viz_tb['_r'].format = '3.2f'
        viz_tb.sort('inp_id')

        return viz_tb
示例#5
0
def get_catalog(params, map_struct):

    cat, = Vizier.get_catalogs('J/ApJS/199/26/table3')

    completeness = 0.5
    alpha = -1.0
    MK_star = -23.55
    MK_max = MK_star + 2.5 * np.log10(gammaincinv(alpha + 2, completeness))

    z = (u.Quantity(cat['cz']) / c.c).to(u.dimensionless_unscaled)
    MK = cat['Ktmag'] - cosmo.distmod(z)
    keep = (z > 0) & (MK < MK_max)

    cat = cat[keep]
    z = z[keep]

    r = cosmo.luminosity_distance(z).to('Mpc').value
    theta = 0.5 * np.pi - cat['DEJ2000'].to('rad').value
    phi = cat['RAJ2000'].to('rad').value
    ipix = hp.ang2pix(map_struct["nside"], theta, phi)

    if "distnorm" in map_struct:
        dp_dV = map_struct["prob"][ipix] * map_struct["distnorm"][ipix] * norm(
            map_struct["distmu"][ipix],
            map_struct["distsigma"][ipix]).pdf(r) / map_struct["pixarea"]
        top50 = cat[np.flipud(np.argsort(dp_dV))][:50]
    else:
        top50 = cat[np.flipud(np.argsort(map_struct["prob"][ipix]))][:50]

    catalogfile = os.path.join(params["outputDir"], 'catalog.dat')
    top50['RAJ2000', 'DEJ2000', 'Ktmag'].write(catalogfile, format='ascii')

    return top50
示例#6
0
def get_tess_limb_darkening_guesses(teff, logg):
    '''
    Given Teff and log(g), query the Claret+2017 limb darkening coefficient
    grid. Return the nearest match.

    TODO: interpolate instead of doing the nearest match. Nearest match is
    good to maybe only ~200 K and ~0.3 in log(g).
    '''

    if not vizier_dependency:
        raise ImportError('This function requires astroquery.'
                          'Try: `conda install -c astropy astroquery`')

    # Assume solar metallicity.
    metallicity = 0

    # Get the Claret quadratic priors for TESS bandpass.  The table below is
    # good from Teff = 1500 - 12000K, logg = 2.5 to 6. We choose values
    # computed with the "r method", see
    # http://vizier.u-strasbg.fr/viz-bin/VizieR-n?-source=METAnot&catid=36000030&notid=1&-out=text
    if not 2300 < teff < 12000:
        if teff < 15000:
            LOGWARNING(
                'using 12000K atmosphere LD coeffs even tho teff={}'.format(
                    teff))
        else:
            LOGERROR('got teff error')
    if not 2.5 < logg < 6:
        if teff < 15000:
            # Rough guess: assume star is B6V, Pecaut & Mamajek (2013) table.
            _Mstar = 4 * units.Msun
            _Rstar = 2.9 * units.Rsun
            logg = np.log10((const.G * _Mstar / _Rstar**2).cgs.value)
        else:
            LOGERROR('got logg error')

    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs('J/A+A/600/A30')
    catalogs = Vizier.get_catalogs(catalog_list.keys())
    t = catalogs[1]
    sel = (t['Type'] == 'r')
    df = t[sel].to_pandas()

    # Each Teff has 8 tabulated logg values. First, find the best teff match.
    foo = df.iloc[(df['Teff'] - teff).abs().argsort()[:8]]
    # Then, among those best 8, get the best logg match.
    bar = foo.iloc[(foo['logg'] - logg).abs().argsort()].iloc[0]

    # TODO: should probably determine these coefficients by INTERPOLATING.
    # (especially in cases when you're FIXING them, rather than letting them
    # float).
    LOGWARNING('skipping interpolation for Claret coefficients.')
    LOGWARNING('data logg={:.3f}, teff={:.1f}'.format(logg, teff))
    LOGWARNING('Claret logg={:.3f}, teff={:.1f}'.format(
        bar['logg'], bar['Teff']))

    u_linear = bar['aLSM']
    u_quad = bar['bLSM']

    return float(u_linear), float(u_quad)
示例#7
0
def main():

    path = os.path.dirname(os.path.abspath(__file__))

    sne_table = ascii.read(os.path.join(path, 'Pantheon.FITRES'))
    sne_table = sne_table[sne_table['RA'] != 0]

    vizier = Vizier(row_limit=2000)
    mcxc_table = vizier.get_catalogs('J/A+A/534/A109/mcxc')[0]

    namespace = parser().parse_args(sys.argv[1:])
    sep = namespace.sep
    z = namespace.z

    table = crossmatch(catalog1=sne_table,
                       catalog2=mcxc_table,
                       colRA1='RA',
                       colDec1='DECL',
                       colZ1='zCMB',
                       colRA2='RAJ2000',
                       colDec2='DEJ2000',
                       colZ2='z',
                       max_sep=sep,
                       use_z=z)
    final_table = table['CID', 'MCXC', 'RAJ2000', 'RA', 'DEJ2000', 'DECL',
                        'DELTA_Z']
    final_table['CID'].name, final_table['MCXC'].name = 'SN name', 'Cluster'

    ascii.write(final_table,
                os.path.join(path, 'CrossTable.csv'),
                format='csv',
                overwrite=True)
示例#8
0
def OS_from_viz(viz_ID,
                file_name,
                extraCols=['default'],
                GUI_name='default',
                GUI_path='default',
                use_redshift='OFF'):
    from astroquery.vizier import Vizier
    v = Vizier()
    v.ROW_LIMIT = -1
    Cats = v.get_catalogs(viz_ID)
    grbCat = Cats[0]
    grbAstroCat = Table(grbCat)
    global colNames
    colNames = ["RAJ2000", "DEJ2000"]
    if extraCols == ['default']:
        otherCols(grbAstroCat)
    else:
        for i in range(len(extraCols)):
            colNames.append(extraCols[i])
    hasDistance(grbAstroCat, use_redshift)
    deleteCols(grbAstroCat)
    #	global viz_key
    viz_key = 1996
    global vizID
    vizID = viz_ID
    #guiforasset = GUI_name
    files2ops.createFiles(grbAstroCat, file_name, GUI_name, GUI_path,
                          "Vizier:" + viz_ID)
def download_furlan_radius_correction_table():
    # Furlan et al 2017

    catalog_list = Vizier.find_catalogs('J/AJ/153/71')

    print({k: v.description for k, v in catalog_list.items()})

    Vizier.ROW_LIMIT = -1

    f17_tablelist = Vizier.get_catalogs(catalog_list.keys())

    companiontab = f17_tablelist[-1]

    df = companiontab.to_pandas()

    for colname in ['KOI', 'Nc', 'Nobs']:
        df[colname] = df[colname].astype(int)

    # Assume planet orbits primary; this is lower bound on contamination.
    # Therefore it's weaker than assuming the planet orbits the next-brightest
    # companion. However, it's what Petigura+ 2018 did. (Probably b/c the converse
    # would throw out too many).
    df = df[df['Orbit'] == b'primary']

    outname = '../data/Furlan_2017_table9.csv'
    df.to_csv(outname, index=False)
    print('saved to {:s}'.format(outname))
示例#10
0
    def _load(self, filename):
        raw = Vizier.get_catalogs('VII/26D')[0]
        if FILTER_DWARFS:
            raw = raw[raw['UGC'] != 10822]  # Draco (UGC 10822)
            raw = raw[raw['UGC'] != 9749]  # Ursa Minor (UGC 9749)
            raw = raw[raw['UGC'] != 5470]  # Leo I (UGC 5470)
            raw = raw[raw['UGC'] != 6253]  # Leo II (UGC 6253)

        self.data.resize(len(raw))
        self.data['name'] = np.char.mod('UGC %s', raw['UGC'])

        ra = np.array([map(float, hms.split()) for hms in raw['RA1950']])
        dec = np.array([map(float, dms.split()) for dms in raw['DE1950']])
        ra = np.vstack([ra.T, np.zeros(len(raw))]).T
        dec = np.vstack([dec.T, np.zeros(len(raw))]).T
        ra1950 = ugali.utils.projector.hms2dec(ra)
        dec1950 = ugali.utils.projector.dms2dec(dec)
        ra2000, dec2000 = ugali.utils.idl.jprecess(ra1950, dec1950)
        self.data['ra'] = ra2000
        self.data['dec'] = dec2000

        self.data[
            'radius'] = raw['MajAxis'] / 60.0  # Major axis on POSS blue print
        # Could also use minor axis 'MinAxis' (no position angle given)

        glon, glat = cel2gal(self.data['ra'], self.data['dec'])
        self.data['glon'], self.data['glat'] = glon, glat
 def __init__(self, *attributes):
     self.attributes = attributes
     Vizier.ROW_LIMIT = -1
     dias_catalog = Vizier.get_catalogs('/B/ocl/clusters')
     if attributes == ():
         self.table = dias_catalog['B/ocl/clusters']
     else:
         self.table = dias_catalog['B/ocl/clusters'][attributes]
示例#12
0
def build_constellation_boundary_database():
    print()
    print("Creating constellation boundary database")
    db = SkyMapDatabase()
    db.drop_table("skymap_constellation_boundaries")
    db.create_table(
        "skymap_constellation_boundaries",
        ["ra1", "dec1", "ra2", "dec2"],
        [float, float, float, float],
    )

    # Retrieve data from Vizier
    print()
    print("Retrieving data from Vizier")
    Vizier.ROW_LIMIT = -1
    catalog = Vizier.get_catalogs("VI/49")
    constbnd = catalog["VI/49/constbnd"]

    print()
    print("Building edges from {} points".format(len(constbnd)))
    prev_hash = None
    edges = []
    for row in constbnd:
        if not row["adj"]:
            prev_hash = None

        current_hash = point_hash(row["RAB1875"], row["DEB1875"])
        if prev_hash is not None:
            e = QuickEdge(prev_hash, current_hash)

            if e not in edges:
                edges.append(e)

        prev_hash = current_hash

    print()
    print("Connecting {} edges".format(len(edges)))
    for i, e1 in enumerate(edges):
        for e2 in edges[i + 1 :]:
            e1.connect(e2)

    print()
    print("Building extended edges")
    new_edges = []
    for i, e in enumerate(edges):
        new_edge = e.extended_edge
        if new_edge not in new_edges:
            new_edges.append(new_edge)

    print()
    print(f"Loading {len(new_edges)} edges to database")
    for i, e in enumerate(new_edges):
        db.insert_row(
            "skymap_constellation_boundaries",
            ["ra1", "dec1", "ra2", "dec2"],
            e.coordinates,
        )
示例#13
0
def make_Rizzuto15_GaiaDR2_crossmatch():
    '''
    Aaron Rizzuto et al (2015) picked out ~400 candidate USco members, then
    surveyed them for Li absorption. Led to 237 spectroscopically confirmed
    members.

    see
    http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/MNRAS/448/2737
    '''

    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs('J/MNRAS/448/2737')
    catalogs = Vizier.get_catalogs(catalog_list.keys())

    cands = catalogs[0]
    usco_pms = catalogs[1] # pre-MS stars in USco
    usco_disk = catalogs[2] # members of USco w/ circumstellar disk

    c = SkyCoord([ra.replace(' ',':')
                    for ra in list(map(str,usco_pms['RAJ2000']))],
                 [de.replace(' ',':')
                    for de in list(map(str,usco_pms['DEJ2000']))],
                 unit=(u.hourangle, u.deg))
    usco_pms['RA'] = c.ra.value
    usco_pms['DEC'] = c.dec.value
    usco_pms.remove_column('RAJ2000')
    usco_pms.remove_column('DEJ2000')
    foo = usco_pms.to_pandas()
    outname = '../data/cluster_data/moving_groups/Rizzuto_15_table_2_USco_PMS.csv'

    foo.to_csv(outname,index=False)
    print('saved {:s}'.format(outname))

    c = SkyCoord([ra.replace(' ',':')
                    for ra in list(map(str,usco_disk['RAJ2000']))],
                 [de.replace(' ',':')
                    for de in list(map(str,usco_disk['DEJ2000']))],
                 unit=(u.hourangle, u.deg))
    usco_disk['RA'] = c.ra.value
    usco_disk['DEC'] = c.dec.value
    usco_disk.remove_column('RAJ2000')
    usco_disk.remove_column('DEJ2000')
    foo = usco_disk.to_pandas()
    outname = os.path.join(datadir, 'Rizzuto_15_table_3_USco_hosts_disk.csv')
    foo.to_csv(outname,index=False)
    print('saved {:s}'.format(outname))

    print(
    ''' I then uploaded these lists to MAST, and used their spatial
        cross-matching with a 3 arcsecond cap, following
            https://archive.stsci.edu/tess/tutorials/upload_list.html

        This crossmatch is the output that I then saved to
            '../results/Rizzuto_15_table_2_USco_PMS_GaiaDR2_crossmatched_2arcsec_MAST.csv'
            '../results/Rizzuto_15_table_3_USco_disks_GaiaDR2_crossmatched_2arcsec_MAST.csv'
    '''
    )
示例#14
0
def green_catalog_download():
    # This allows easy access to Vizier tables:
    # https://astroquery.readthedocs.org/en/latest/vizier/vizier.html
    from astroquery.vizier import Vizier
    Vizier.ROW_LIMIT = -1
    # This is the 2014-05 version of Green's catalog
    # http://vizier.u-strasbg.fr/viz-bin/VizieR?-source=VII/272
    results = Vizier.get_catalogs(['VII/272'])
    table = results[0]
    return table
示例#15
0
    def __init__(self,
                 *attributes,
                 ra_0=0,
                 dec_0=0,
                 r_0=0.5,
                 entire=False,
                 galactic=False):
        """
        Bruno Femenia Castella:
            
            in order to speed up calcularions it does not make sense to scan 
            the whole catalog but only those clusters found within 1.5*r_0 [degs]
            around coordinates [ra_0, dec_0]
        """
        self.attributes = attributes
        Vizier.ROW_LIMIT = -1

        if entire:
            dias_catalog = Vizier.get_catalogs('B/ocl/clusters')
        else:
            center_coord = SkyCoord(ra=ra_0,
                                    dec=dec_0,
                                    unit=(u.deg, u.deg),
                                    frame='icrs')
            dias_catalog = Vizier.query_region(center_coord,
                                               radius=1.5 * r_0 * u.deg,
                                               catalog='B/ocl/clusters')

        if attributes == ():
            self.table = dias_catalog['B/ocl/clusters']
        else:
            self.table = dias_catalog['B/ocl/clusters'][attributes]

        if galactic:
            nel = len(self.table)
            Col_l = Column(name='l',
                           unit=u.deg,
                           dtype=np.float32,
                           description='Galactic longitude',
                           length=nel)
            Col_b = Column(name='b',
                           unit=u.deg,
                           dtype=np.float32,
                           description='Galactic latitude',
                           length=nel)
            for i, row in enumerate(self.table):
                ra = Angle(row['RAJ2000'], unit=u.hourangle)
                dec = Angle(row['DEJ2000'], unit=u.deg)
                cl_radec = SkyCoord(ra, dec, frame='icrs')
                # ra_hms, dec_deg = parse_radec(row['RAJ2000'], row['DEJ2000'])
                # cl_radec=SkyCoord(ra_hms, dec_deg,frame='icrs')
                Col_l[i] = cl_radec.galactic.l.deg
                Col_b[i] = cl_radec.galactic.b.deg

            self.table.add_columns([Col_l, Col_b])
示例#16
0
def make_Casagrande_11_GaiaDR2_crossmatch():
    '''
    Casagrande et al (2011) re-analyzed the Geneva-Copenhagen survey, and got a
    kinematically unbiased sample of solar neighborhood stars with kinematics,
    metallicites, and ages.

    If Casagrande's reported max likelihood ages (from Padova isochrones) are
    below 1 Gyr, then that's interesting enough to look into.

    NOTE that this age cut introduces serious biases into the stellar mass
    distribution -- see Casagrande+2011, Figure 14.

    http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/A+A/530/A138
    '''
    vizier_search_str = 'J/A+A/530/A138'
    table_num = 0
    ra_str = 'RAJ2000'
    dec_str = 'DEJ2000'
    outname = os.path.join(datadir,
                           'Casagrande_2011_table_1_GCS_ages_lt_1Gyr.csv')

    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs(vizier_search_str)
    catalogs = Vizier.get_catalogs(catalog_list.keys())

    tab = catalogs[0]

    # ageMLP: max-likelihood padova isochrone ages
    # ageMLB: max-likelihood BASTI isochrone ages. not queried.
    sel = (tab['ageMLP'] > 0)
    sel &= (tab['ageMLP'] < 1)

    coords = SkyCoord(ra=tab[ra_str], dec=tab[dec_str], frame='icrs',
                      unit=(u.hourangle, u.deg))
    # MAST uploads need these two column names
    tab['RA'] = coords.ra.value
    tab['DEC'] = coords.dec.value
    tab.remove_column('RAJ2000')
    tab.remove_column('DEJ2000')

    foo = tab[sel].to_pandas()
    foo.to_csv(outname,index=False)
    print('saved {:s}'.format(outname))

    print(
    ''' I then uploaded these lists to MAST, and used their spatial
        cross-matching with a 3 arcsecond cap, following
            https://archive.stsci.edu/tess/tutorials/upload_list.html

        This crossmatch is the output that I then saved to
            {:s}
    '''.format(outname.replace('data','results').replace('.csv','_GaiaDR2_3arcsec_crossmatch_MAST.csv'))
    )
示例#17
0
def getRandomVizier(numResults):
    from astroquery.vizier import Vizier
    from astropy import units as u
    v = Vizier(columns=["all"],
               catalog='I/345/gaia2',
               column_filters={
                   "RandomI": "830339102..840339102",
                   "e_Plx": "<0.1"
               })
    v.ROW_LIMIT = numResults
    result = v.get_catalogs('I/345/gaia2')
    result[0].pprint()
    return result[0].keys(), result[0]
示例#18
0
def get_k13_index():
    #
    # the ~3784 row table
    #
    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs('J/A+A/558/A53')
    catalogs = Vizier.get_catalogs(catalog_list.keys())
    k13_index = catalogs[1].to_pandas()
    for c in k13_index.columns:
        if c != 'N':
            k13_index[c] = k13_index[c].str.decode('utf-8')

    return k13_index
示例#19
0
def get_duncan_catalog():
    """
    Parameters
    ----------

    Returns
    -------
    """
    global sindex_catalog

    if sindex_catalog is None:
        catalogs = Vizier.get_catalogs(duncan1991)
        sindex_catalog = catalogs[0]  # This is the table with the data

    return sindex_catalog
示例#20
0
def get_k2_epic_catalog():
    """
    Parameters
    ----------

    Returns
    -------
    """
    global k2_epic_table

    if k2_epic_table is None:
        catalogs = Vizier.get_catalogs(huber2016)
        k2_epic_table = catalogs[0]  # This is the table with the data
        k2_epic_table.add_index('EPIC')
    return k2_epic_table
示例#21
0
def get_k2_epic_catalog():
    """
    Parameters
    ----------

    Returns
    -------
    """
    global k2_epic_table

    if k2_epic_table is None:
        catalogs = Vizier.get_catalogs(huber2016)
        k2_epic_table = catalogs[0]  # This is the table with the data
        k2_epic_table.add_index('EPIC')
    return k2_epic_table
示例#22
0
def flux_star_type(mag, band, star_type, wvl, wvlBand):
    """
    Calculates the flux over a custom wave band, for a given star of a given magnitude in one of the standard bands (I, H, J, etc.)

    Parameters:
        mag (float): magnitude in the band defined by "band"
        band (str): band in which the magnitude is expressed, can be B, J, H, K, L, M, N, R, I
        star_type (str): must be the full star type, i.e. "A0V"
        wvl (float): central wavelength in microns
        wvlBand (float): length of wavelength band in microns

    Returns:
        float: flux of photons (ph/m2/s)
    """
    # get star spectrum, will correspond to a V=0
    Vizier.ROW_LIMIT = -1
    catalog = Vizier.get_catalogs('J/PASP/110/863/synphot')[0]
    pickles_index = numpy.where(catalog["SpType"] == star_type)[0][0] + 1

    ftp = FTP('ftp.stsci.edu')
    ftp.login()

    ss = BytesIO()
    message = ftp.retrbinary('RETR cdbs/grid/pickles/dat_uvk/pickles_uk_' + str(pickles_index) +
                             '.ascii', ss.write)
    ftp.quit()

    # spectrum is in erg/s/cm2/A, first column are wavelengths in A, second column is the spectrum
    erg_spec = numpy.asarray([numpy.asarray(row.split('  '), dtype='float')
                              for row in str(ss.getvalue()).split("\\n")[39:-1]], dtype='float')
    wavelengths = erg_spec[:, 0] * 1e-4

    # translate spectrum in photon/s/m2/micron
    phot_spec = erg_spec[:, 1] * wavelengths / (c.h.value * c.c.value) * 1e-5

    # translate magnitude of band in V
    magV = get_magV(star_type, mag, band)

    # normalise spectrum to correspond to that magnitude
    fac = 10 ** (-magV / 2.5)
    norm_spec = phot_spec * fac

    # integrate over band
    ind = numpy.where((wavelengths >= wvl - wvlBand/2) & (wavelengths <= wvl + wvlBand/2))
    selection = norm_spec[ind]
    flux = (numpy.sum(selection) - (selection[0] + selection[-1]) / 2) * \
           numpy.mean(numpy.diff(wavelengths[ind]))
    return flux
示例#23
0
    def _load(self, filename):
        raw = Vizier.get_catalogs('J/MNRAS/389/678')[0]

        self.data.resize(len(raw))
        self.data['name'] = np.char.strip(raw['Names'])

        ra = np.array([map(float, hms.split()) for hms in raw['RAJ2000']])
        dec = np.array([map(float, dms.split()) for dms in raw['DEJ2000']])
        self.data['ra'] = ugali.utils.projector.hms2dec(ra)
        self.data['dec'] = ugali.utils.projector.dms2dec(dec)

        self.data['radius'] = raw['amaj'] / 60.0  # Major axis
        # Could also use minor axis 'amin' and position angle 'PA'

        glon, glat = cel2gal(self.data['ra'], self.data['dec'])
        self.data['glon'], self.data['glat'] = glon, glat
示例#24
0
    def _load(self, filename):
        raw = Vizier.get_catalogs('J/AJ/144/4')[0]

        self.data.resize(len(raw))
        self.data['name'] = raw['Name']

        ra = np.array([map(float, hms.split()) for hms in raw['RAJ2000']])
        dec = np.array([map(float, dms.split()) for dms in raw['DEJ2000']])
        self.data['ra'] = ugali.utils.projector.hms2dec(ra)
        self.data['dec'] = ugali.utils.projector.dms2dec(dec)

        self.data[
            'radius'] = raw['R1'] / 60.0  # Half-light radius along major axis
        # Could also include elliticity 'Ell' and position angle 'PA'

        glon, glat = cel2gal(self.data['ra'], self.data['dec'])
        self.data['glon'], self.data['glat'] = glon, glat
示例#25
0
def get_k13_param_table():
    #
    # the ~3000 row table with determined parameters
    #
    cols = [
        'map', 'cmd', 'stars', 'Name', 'MWSC', 'Type', 'RAJ2000', 'DEJ2000',
        'r0', 'r1', 'r2', 'pmRA', 'pmDE', 'RV', 'e_RV', 'o_RV', 'd', 'E_B-V_',
        'logt', 'N1sr2', 'rc', 'rt', 'k', 'SType', '__Fe_H_', 'Simbad'
    ]

    v = Vizier(columns=cols)

    v.ROW_LIMIT = -1
    catalog_list = v.find_catalogs('J/A+A/558/A53')
    catalogs = v.get_catalogs(catalog_list.keys())
    k13 = catalogs[0].to_pandas()

    k13['Name'] = k13['Name'].str.decode('utf-8')
    return k13
def read_McLaughlin_vanderMarel2005_data(verbose=True):
    """ We present a database of structural and dynamical properties for 153
    spatially resolved star clusters in the Milky Way, the Large and Small
    Magellanic Clouds, and the Fornax dwarf spheroidal. This database
    complements and extends others in the literature, such as those of Harris
    and Mackey & Gilmore. Our cluster sample comprises 50 young massive clusters
    in the LMC and SMC, and 103 old globular clusters between the four galaxies """
    # This means that by excluding LMC, SMC data we automatically exclude
    # YMCs, thus, we should be left /w only GCs...
    # Am confused though, as to why catalog contains 216 items (not 153?)
    # Also, there's 0: clusters (10 cols/216 rows), 1: table5 (9 cols/4689 rows),
    # 2: models (17 cols/459 rows), 3: table13 (12 cols/67 rows)

    cat_name = "J/ApJS/161/304"
    if verbose:
        print("Retrieving Vizier catalog: '{0}'".format(cat_name))

    Vizier.ROW_LIMIT = -1  # default 50. Now unlimited :)
    return Vizier.get_catalogs(cat_name)[0]
示例#27
0
def get_soubiran_19_rv_table():

    cols = [
        'ID', 'ID2', 'RA_ICRS', 'DE_ICRS', 'dmode', 'Nmemb', 'Nsele', 'RV',
        'e_RV', 's_RV', 'X', 'e_X', 'Y', 'e_Y', 'Z', 'e_Z', 'U', 'e_U', 'V',
        'e_V', 'W', 'e_W', 'Vr', 'e_Vr', 'Vphi', 'e_Vphi', 'Vz', 'e_Vz',
        'Simbad'
    ]

    v = Vizier(columns=cols)

    v.ROW_LIMIT = -1
    catalog_list = v.find_catalogs('J/A+A/619/A155')
    catalogs = v.get_catalogs(catalog_list.keys())
    df = catalogs[0].to_pandas()

    df['ID'] = df['ID'].str.decode('utf-8')

    return df
示例#28
0
    def _load(self, filename):
        raw = Vizier.get_catalogs('J/A+A/558/A53')
        if FILTER_DWARFS:
            raw = [raw[0][raw[0]['MWSC'] != '2020'], raw[1],
                   raw[2]]  # Coma Berenices (Melotte_111)

        self.data.resize(len(raw[0]))

        ids = np.array(map(int, raw[0]['MWSC'])) - 1
        self.data['name'] = raw[1]['Name'][ids]

        self.data['ra'] = raw[0]['RAJ2000']
        self.data['dec'] = raw[0]['DEJ2000']

        self.data['radius'] = raw[0]['r1']  # Radius of central part
        # Could also use core radius 'r0' or radius 'r2'

        glon, glat = cel2gal(self.data['ra'], self.data['dec'])
        self.data['glon'], self.data['glat'] = glon, glat
def CantatGaudin2019_velaOB2_to_csv():
    # https://ui.adsabs.harvard.edu/abs/2019A%26A...626A..17C/abstract

    Vizier.ROW_LIMIT = -1
    catalog_list = Vizier.find_catalogs('J/A+A/626/A17')
    catalogs = Vizier.get_catalogs(catalog_list.keys())

    tab = catalogs[0]
    df = tab.to_pandas()

    outdf = df[['Source','Pop']]

    outdf = outdf.rename(columns={"Source": "source_id", "Pop": "cluster"})

    # Quoting Tristan, discussing Fig3 from the paper:
    #  """
    #  the clumps that are labeled are known "open clusters". The diffuse
    #  stellar distribution in the middle and around was called the Vela OB2
    #  association, supposed to be in front of the clusters or maybe in
    #  between, and everyone thought they were unrelated objects, different
    #  age, different history. In the figure, the colour code indicates stars
    #  that have the same age and velocity.
    #  My conclusion is that there is no object that can be called "Vela OB2"
    #  association. There are clusters, and a diffuse distribution of stars around
    #  each cluster. And the sum of all those fluffy distributions is "the
    #  association". Aggregates of young stars are so sub-structured that it
    #  doesn't even make sense to label all the clumps, and it can even be
    #  difficult to guess which clump observers referred to when they looked at
    #  those regions in the 19th century. There are ongoing debates over whether
    #  NGC 1746 exists, for instance. Which are the stars that were originally
    #  classified as NGC 1746, and does it even matter?
    #  """

    outdf['cluster'] = np.core.defchararray.add(
        np.repeat('cg19velaOB2_pop', len(outdf)),
        nparr(outdf['cluster']).astype(str)
    )

    outpath = os.path.join(clusterdatadir, 'moving_groups',
                           'CantatGaudin2019_velaOB2_MATCH.csv')
    outdf.to_csv(outpath, index=False)
    print('made {}'.format(outpath))
示例#30
0
    def _load(self, filename):
        catalog = Vizier.get_catalogs('VII/151')
        raw = astropy.table.vstack([catalog[0], catalog[2]],
                                   metadata_conflicts='silent')

        self.data.resize(len(raw))
        self.data['name'] = np.char.join(' ', np.char.split(raw['Name1']))

        ra = np.array([map(float, hms.split()) for hms in raw['RA1950']])
        dec = np.array([map(float, dms.split()) for dms in raw['DE1950']])
        dec = np.vstack([dec.T, np.zeros(len(raw))]).T
        ra1950 = ugali.utils.projector.hms2dec(ra)
        dec1950 = ugali.utils.projector.dms2dec(dec)
        ra2000, dec2000 = ugali.utils.idl.jprecess(ra1950, dec1950)
        self.data['ra'] = ra2000
        self.data['dec'] = dec2000

        self.data['radius'] = (10**np.array(raw['lgtt'])) / 60.0  # log(radius)
        # Could also use log(core radius) 'lgtc'

        glon, glat = cel2gal(self.data['ra'], self.data['dec'])
        self.data['glon'], self.data['glat'] = glon, glat
示例#31
0
def get_glade():
    if not os.path.isdir('catalogs/'):
        os.makedirs('catalogs/')

    catalogFile = os.path.join('catalogs/', "glade.hdf5")

    if not os.path.isfile(catalogFile):
        # Unset row limits when querying Vizier
        Vizier.ROW_LIMIT = -1
        cat, = Vizier.get_catalogs('VII/281/glade2')
        ra, dec = cat["RAJ2000"], cat["DEJ2000"]
        distmpc, z, flag1 = cat["Dist"], cat["z"], cat["Flag1"]
        magb, BMAG = cat["Bmag"], cat["BMAG"]
        Jmag, Hmag, Kmag = cat["Jmag"], cat["Hmag"], cat['Kmag']
        flag2, flag3 = cat["Flag2"], cat["Flag3"]
        # Keep track of galaxy identifier
        GWGC, PGC, HyperLEDA = cat["GWGC"], cat["PGC"], cat["HyperLEDA"]
        _2MASS, SDSS = cat["_2MASS"], cat["SDSS-DR12"]

        with h5py.File(catalogFile, 'w') as f:
            f.create_dataset('ra', data=ra)
            f.create_dataset('dec', data=dec)
            f.create_dataset('distmpc', data=distmpc)
            f.create_dataset('Flag1', data=flag1)
            f.create_dataset('magb', data=magb)
            f.create_dataset('BMAG', data=BMAG)
            f.create_dataset('Jmag', data=Jmag)
            f.create_dataset('Hmag', data=Hmag)
            f.create_dataset('Kmag', data=Kmag)
            f.create_dataset('Flag2', data=flag2)
            f.create_dataset('Flag3', data=flag3)

            f.create_dataset('z', data=z)
            # Add galaxy identifier
            f.create_dataset('GWGC', data=GWGC)
            f.create_dataset('PGC', data=PGC)
            f.create_dataset('HyperLEDA', data=HyperLEDA)
            f.create_dataset('2MASS', data=_2MASS)
            f.create_dataset('SDSS', data=SDSS)
示例#32
0
    def download_catalog(self):
        """
        Downloads the flare catalog using Vizier.
        The flare catalog is named 'Guenther_2020_flare_catalog.txt'.
        The star catalog is named 'Guenther_2020_star_catalog.txt'.

        Attributes
        ----------
        flare_table : astropy.table.Table
             Flare catalog that was downloaded.
        """

        Vizier.ROW_LIMIT = -1

        catalog_list = Vizier.find_catalogs('TESS flares sectors')
        catalogs = Vizier.get_catalogs(catalog_list.keys())

        self.flare_table = catalogs[1]
        self.flare_table.rename_column('_tab2_5', 'tpeak')
        self.flare_table.write(os.path.join(self.fn_dir,
                                            self.flare_catalog_name),
                               format='csv')
        return
示例#33
0
def main():
    """Main function"""
    import argparse
    parser = argparse.ArgumentParser(description="Create a starlist of UKIRT Faint Stanadards")
    parser.add_argument("-o", "--output", type=argparse.FileType("w"), default="-", help="Output file")
    parser.add_argument("--fs", action='store_false', dest='full', help="Collect FS stars only")
    opt = parser.parse_args()
    date = datetime.datetime.now().isoformat()
    
    try:
        from astroquery.vizier import Vizier
    except ImportError as e:
        parser.error("Requires 'astroquery' to be installed.\n{0!r}".format(e))
    table = Vizier.get_catalogs([VIZIER_UKIRT_FS_CATALOG])[0]
    
    tl = TargetList([row_to_target(row) for row in table if (str(row['SimbadName'].decode('ascii')).startswith("FS") or opt.full)])
    tl.sort(key = lambda t : t.position.ra)
    
    # Write a header for the starlist so that we know the source.
    opt.output.write("# UKIRT Faint Standard Stars\n")
    opt.output.write("# Data from VIZIER catalog '{0:s}'\n".format(VIZIER_UKIRT_FS_CATALOG))
    opt.output.write("# ADS Reference: '{0:s}'\n".format(VIZIER_ADS_REFERENCE))
    opt.output.write("# Data collected on {0:s}\n".format(date))
    tl.to_starlist(opt.output)
    Save both a png and a pdf version of the image
    """
    pl.savefig(p3(savename.replace("pdf","png")), **kwargs)
    pl.savefig(p3(savename.replace("png","pdf")), **kwargs)

zoomargs = {'x': 49.31, 'y':-0.35, 'width': 0.55, 'height':0.34}
# copied from projection_figures
zoomargs = {'x': 49.23, 'y': -0.28, 'width':1, 'height':0.5}
zoomargs = dict(x=49.27, y=-0.32, width=0.9, height=0.4)

for fignum in (1,2,3):
    if pl.fignum_exists(fignum):
        pl.close(fignum)

Vizier.ROW_LIMIT = 999999
ysos = Vizier.get_catalogs('J/ApJ/706/83/ysos')['J/ApJ/706/83/ysos']
masers = Vizier.query_region('W51', radius='2 deg',
                             catalog='J/A+A/291/261/table1')['J/A+A/291/261/table1']
masers2 = Vizier.query_region('W51', radius='2 deg',
                              catalog='J/MNRAS/418/1689/table2')['J/MNRAS/418/1689/table2']
radec = [coordinates.SkyCoord(r,d,unit=('deg','deg'),frame='icrs')
         for r,d in zip(masers2['RAJ2000'],masers2['DEJ2000'])]
glon,glat = np.array(zip(*[(rd.galactic.l.degree,
                            rd.galactic.b.degree)
                           for rd in radec]))

# Added 5/23/2014
mask = fits.getdata(p1('mask_h2co_signal.fits'))

for suffix,extrastr in ((".fits",""), ):#("_prefiltered.fits", "filtered")):
    parcubefile = fits.open(p1('W51_taucube_fit_parcube_try11'+suffix))
示例#35
0
文件: s4g.py 项目: SKIRT/PTS
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)
示例#36
0
#v = Vizier(columns = ['Vmag','B-V','U-B','V-Rc','Rc-Ic','e_Vmag','e_B-V','e_U-B','e_V-Rc','e_Rc-Ic']


keys = []

Vizier.ROW_LIMIT = -1

if not os.path.exists(directory):
	os.mkdir(directory)

for page in catalogs:
	keys.append(page)

#v = Vizier(columns=['Name','Nova','JD', 'Band', 'mag', 'e_mag', 'Source'])

dataTables = Vizier.get_catalogs(keys)
keys = dataTables.keys()

keyRepeatDict = {}

filename_dict = {}
for key in keys:
	if key not in keyRepeatDict:
		keyRepeatDict[key] = 0
	else:
		keyRepeatDict[key] += 1

	names = ()
	for catalogKey in catalogs:
		if re.search(catalogKey.replace("+", "\+").replace(".", "\."), key):
			names = catalogs[catalogKey]
示例#37
0
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)
示例#38
0
        delete_old_event_files()

# Import data provided directly to OSC
#if do_task('internal'):
#    for datafile in sorted(glob.glob("../tde-internal/*.json"), key=lambda s: s.lower()):
#        if not load_event_from_file(location = datafile, clean = True, delete = False):
#            raise IOError('Failed to find specified file.')
#    journal_events()

# Import primary data sources from Vizier
if do_task('vizier'):
    Vizier.ROW_LIMIT = -1
    # VizieR imports go here

    # 2010ApJ...725..331Y
    result = Vizier.get_catalogs("J/ApJ/725/331/table7")
    table = result[list(result.keys())[0]]
    table.convert_bytestring_to_unicode(python3_only=True)
    for row in table:
        name = row['Name']
        name = add_event(name)
        source = get_source(name, bibcode = '2010ApJ...725..331Y')
        add_quanta(name, 'ra', str(row['_RA']), source, unit = 'radeg')
        add_quanta(name, 'dec', str(row['_DE']), source, unit = 'decdeg')
        add_quanta(name, 'ora', str(row['oRA']), source)
        add_quanta(name, 'odec', str(row['oDE']), source)
    journal_events()

if do_task('writeevents'): 
    files = []
    for rep in repfolders:
示例#39
0
mass-luminosity and mass-temperature diagrams populating the main sequence only
with data from Ekström+ 2012 (Vizier catalog J/A+A/537/A146/iso).

Colors come from vendian.org.
"""
import numpy as np
import imf
import pylab as pl
from astroquery.vizier import Vizier
from labellines import labelLine, labelLines

pl.rcParams['font.size'] = 20

Vizier.ROW_LIMIT=1e7

tbl = Vizier.get_catalogs('J/A+A/537/A146/iso')[0]

agemass = {}
agelum = {}
for age in np.unique(tbl['logAge']):
    agemass[age] = tbl[tbl['logAge']==age]['Mass'].max()
    agelum[age] = tbl[tbl['logAge']==age]['logL'].max()


# mass-temperature diagram
pl.figure(2, figsize=(8,8)).clf()

# select a specific population age to plot - this is the youngest, with all
# stars alive and main-sequence
ok = tbl['logAge'] == 6.5
#                 '<f4',
#                 '<i2',
#                 '<f4',
#                 '<f4',
#                 '<f4',
#                 '<f4',
#                 '<f4']

# Try the *UPDATED* catalog (2009AJ....137.4186L)
# but update the "outputNames" to match

###########
# It should be possible to significantly increase the sample by using the more
# recent data at +50 deg. declination found in "2013AJ....146..131L"
###########
landoltStars = (Vizier.get_catalogs('J/AJ/137/4186'))[0]

outputNames  = ['_RAJ2000',
                '_DEJ2000',
                'Name',
                'Vmag',
                'e_Vmag',
                'B-V',
                'e_B-V',
                'U-B',
                'e_U-B',
                'V-R',
                'e_V-R',
                'R-I',
                'e_R-I',
                'V-I',
示例#41
0
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)
示例#42
0
def do_snls_spectra(catalog):
    """
    """

    task_str = catalog.get_current_task_str()
    result = Vizier.get_catalogs('J/A+A/507/85/table1')
    table = result[list(result.keys())[0]]
    table.convert_bytestring_to_unicode(python3_only=True)
    datedict = {}
    for row in table:
        datedict['SNLS-' + row['SN']] = str(astrotime(row['Date']).mjd)

    oldname = ''
    file_names = glob(os.path.join(catalog.get_current_task_repo(), 'SNLS/*'))
    for fi, fname in enumerate(pbar_strings(file_names, task_str)):
        filename = os.path.basename(fname)
        fileparts = filename.split('_')
        name = 'SNLS-' + fileparts[1]
        name = catalog.get_preferred_name(name)
        if oldname and name != oldname:
            catalog.journal_entries()
        oldname = name
        name = catalog.add_entry(name)
        source = catalog.entries[name].add_source(
            bibcode='2009A&A...507...85B')
        catalog.entries[name].add_quantity(SUPERNOVA.ALIAS, name, source)

        catalog.entries[name].add_quantity(
            SUPERNOVA.DISCOVER_DATE, '20' + fileparts[1][:2], source)

        f = open(fname, 'r')
        data = csv.reader(f, delimiter=' ', skipinitialspace=True)
        specdata = []
        for r, row in enumerate(data):
            if row[0] == '@TELESCOPE':
                telescope = row[1].strip()
            elif row[0] == '@REDSHIFT':
                catalog.entries[name].add_quantity(
                    SUPERNOVA.REDSHIFT, row[1].strip(), source)
            if r < 14:
                continue
            specdata.append(list(filter(None, [x.strip(' \t') for x in row])))
        specdata = [list(i) for i in zip(*specdata)]
        wavelengths = specdata[1]

        fluxes = [pretty_num(float(x) * 1.e-16, sig=get_sig_digits(x))
                  for x in specdata[2]]
        # FIX: this isnt being used
        # errors = [pretty_num(float(x)*1.e-16, sig=get_sig_digits(x)) for x in
        # specdata[3]]

        catalog.entries[name].add_spectrum(
            u_wavelengths='Angstrom', u_fluxes='erg/s/cm^2/Angstrom',
            wavelengths=wavelengths,
            fluxes=fluxes, u_time='MJD' if name in datedict else '',
            time=datedict[name] if name in datedict else '',
            telescope=telescope, source=source,
            filename=filename)
        if catalog.args.travis and fi >= catalog.TRAVIS_QUERY_LIMIT:
            break
    catalog.journal_entries()
    return
示例#43
0
from astroquery.vizier import Vizier
catalog_list = Vizier.find_catalogs('J/ApJS/204/5')
Vizier.ROW_LIMIT = -1

cata = Vizier.get_catalogs(catalog_list.keys())[0]
print len(cata)