from __future__ import absolute_import, division, print_function
import numpy as np
from glue.core.data_factories.helpers import has_extension
from glue.core.data import Component, Data
from glue.config import data_factory
__all__ = ['astropy_tabular_data', 'sextractor_factory', 'cds_factory',
'daophot_factory', 'ipac_factory', 'aastex_factory',
'latex_factory']
# In this file, we define data factories based on the Astropy table reader.
def is_readable_by_astropy(filename, **kwargs):
# This identifier is not efficient, because it involves actually trying
# to read in the table. However, we only use this as the identifier for
# the astropy_tabular_data factory which has a priority of 0 and is
# therefore only used as a last attempt if all else fails.
try:
astropy_table_read(filename, **kwargs)
except:
return False
else:
return True
def astropy_table_read(*args, **kwargs):
from astropy.table import Table
# In Python 3, as of Astropy 0.4, if the format is not specified, the
# automatic format identification will fail (astropy/astropy#3013).
# This is only a problem for ASCII formats however, because it is due
# to the fact that the file object in io.ascii does not rewind to the
# start between guesses (due to a bug), so here we can explicitly try
# the ASCII format if the format keyword was not already present. But
# also more generally, we should first try the ASCII readers.
if 'format' not in kwargs:
try:
return Table.read(*args, format='ascii', **kwargs)
except:
pass
# If the above didn't work, attempt to read with no specified format
return Table.read(*args, **kwargs)
@data_factory(label="Catalog (astropy.table parser)",
identifier=is_readable_by_astropy,
priority=0)
[docs]def astropy_tabular_data(*args, **kwargs):
"""
Build a data set from a table. We restrict ourselves to tables
with 1D columns.
All arguments are passed to
astropy.table.Table.read(...).
"""
result = Data()
table = astropy_table_read(*args, **kwargs)
# Loop through columns and make component list
for column_name in table.columns:
c = table[column_name]
u = c.unit if hasattr(c, 'unit') else c.units
if table.masked:
# fill array for now
try:
c = c.filled(fill_value=np.nan)
except ValueError: # assigning nan to integer dtype
c = c.filled(fill_value=-1)
nc = Component.autotyped(c, units=u)
result.add_component(nc, column_name)
return result
@data_factory(label="VO table",
identifier=has_extension('xml vot xml.gz vot.gz'),
priority=1)
def astropy_tabular_data_votable(*args, **kwargs):
kwargs['format'] = 'votable'
return astropy_tabular_data(*args, **kwargs)
@data_factory(label="FITS table",
identifier=has_extension('fits fits.gz fit fit.gz'),
priority=1)
def astropy_tabular_data_fits(*args, **kwargs):
kwargs['format'] = 'fits'
return astropy_tabular_data(*args, **kwargs)
# Add explicit factories for the formats which astropy.table
# can parse, but does not auto-identify
def formatted_table_factory(format, label):
@data_factory(label=label, identifier=lambda *a, **k: False)
def factory(file, **kwargs):
kwargs['format'] = 'ascii.%s' % format
return astropy_tabular_data(file, **kwargs)
# rename function to its variable reference below
# allows pickling to work
factory.__name__ = '%s_factory' % format
return factory
sextractor_factory = formatted_table_factory('sextractor', 'SExtractor Catalog')
cds_factory = formatted_table_factory('cds', 'CDS Catalog')
daophot_factory = formatted_table_factory('daophot', 'DAOphot Catalog')
ipac_factory = formatted_table_factory('ipac', 'IPAC Catalog')
aastex_factory = formatted_table_factory('aastex', 'AASTeX Table')
latex_factory = formatted_table_factory('latex', 'LaTeX Table')