6 from .astrometry_net
import multiindex_new, multiindex_add_index, INDEX_ONLY_LOAD_METADATA, healpixDistance
7 from .astrometryNetDataConfig
import AstrometryNetDataConfig
9 __all__ = [
"getIndexPath",
"getConfigFromEnvironment",
"AstrometryNetCatalog",
"generateCache"]
12 """!Get the path to the specified astrometry.net index file
14 No effort is made to confirm that the file exists, so it may be used to locate the
15 path to a non-existent file (e.g., to write).
17 @param[in] fn path to index file; if relative, then relative to astrometry_net_data
18 if that product is setup, else relative to the current working directory
19 @return the absolute path to the index file
27 return os.path.abspath(fn)
28 return os.path.join(andir, fn)
32 """Find the config file from the environment
34 The andConfig.py file is in the astrometry_net_data directory.
40 andConfigPath =
"andConfig.py"
41 if not os.path.exists(andConfigPath):
42 raise RuntimeError(
"Unable to find andConfig.py in the current directory. "
43 "Did you forget to setup astrometry_net_data?")
45 andConfigPath = os.path.join(anDir,
"andConfig.py")
46 if not os.path.exists(andConfigPath):
47 raise RuntimeError(
"Unable to find andConfig.py in astrometry_net_data directory %s" % (anDir,))
49 andConfig = AstrometryNetDataConfig()
50 andConfig.load(andConfigPath)
54 """A wrapper for the multiindex_t, which only reads the data when it needs to
56 The MultiIndexCache may be instantiated directly, or via the 'fromFilenameList'
57 class method, which loads it from a list of filenames.
59 def __init__(self, filenameList, healpix, nside):
62 @param filenameList List of filenames; first is the multiindex, then
63 follows the individual index files
64 @param healpix Healpix number
65 @param nside Healpix nside
67 if len(filenameList) < 2:
68 raise RuntimeError(
"Insufficient filenames provided for multiindex (%s): expected >= 2" %
75 self.
log = getDefaultLog()
79 """Construct from a list of filenames
81 The list of filenames should contain the multiindex filename first,
82 then the individual index filenames. The healpix and nside are
83 determined by reading the indices, so this is not very efficient.
85 self = cls(filenameList, 0, 0)
87 healpixes = set(self[i].healpix
for i
in range(len(self)))
88 nsides = set(self[i].hpnside
for i
in range(len(self)))
89 assert len(healpixes) == 1
90 assert len(nsides) == 1
96 """Read the indices"""
97 if self.
_mi is not None:
100 if not os.path.exists(fn):
101 raise RuntimeError(
"Unable to get filename for astrometry star file %s" % (self.
_filenameList[0],))
102 self.
_mi = multiindex_new(fn)
105 raise RuntimeError(
'Failed to read stars from astrometry multiindex filename "%s"' % fn)
108 self.log.logdebug(
'Unable to find index part of multiindex %s' % fn)
111 if not os.path.exists(fn):
112 self.log.warn(
"Unable to get filename for astrometry index %s" % (fn,))
114 self.log.logdebug(
'Reading index from multiindex file "%s"' % fn)
115 if multiindex_add_index(self.
_mi, fn, INDEX_ONLY_LOAD_METADATA):
116 raise RuntimeError(
'Failed to read index from multiindex filename "%s"' % fn)
118 self.log.logdebug(
' index %i, hp %i (nside %i), nstars %i, nquads %i' %
119 (ind.indexid, ind.healpix, ind.hpnside, ind.nstars, ind.nquads))
122 """Reload the indices."""
132 """Unload the indices"""
139 """!Is the index within range of the provided coordinates?
141 @param coord Coordinate to check (lsst.afw.coord.Coord)
142 @param distance Angular distance (lsst.afw.geom.Angle)
159 """An interface to an astrometry.net catalog
161 Behaves like a list of MultiIndexCache (or multiindex_t).
163 These should usually be constructed using the 'fromEnvironment'
164 class method, which wraps the 'fromIndexFiles' and 'fromCache'
165 alternative class methods.
167 _cacheFilename =
"andCache.fits"
172 @param andConfig Configuration (an AstrometryNetDataConfig)
176 if self.config.allowCache
and os.path.exists(cacheName):
182 """Initialise from the index files in an AstrometryNetDataConfig"""
183 indexFiles = zip(andConfig.indexFiles, andConfig.indexFiles) + andConfig.multiIndexFiles
184 self.
_multiInds = [MultiIndexCache.fromFilenameList(fnList)
for fnList
in indexFiles]
187 """Write a cache file
189 The cache file is a FITS file with all the required information to build the
190 AstrometryNetCatalog quickly. The first table extension contains a row for each multiindex,
191 storing the healpix and nside values. The second table extension contains a row
192 for each filename in all the multiindexes. The two may be JOINed through the
196 numFilenames =
sum(len(ind._filenameList)
for ind
in self.
_multiInds)
197 maxLength = max(len(fn)
for ind
in self.
_multiInds for fn
in ind._filenameList) + 1
200 first = pyfits.new_table([pyfits.Column(name=
"id", format=
"K"),
201 pyfits.Column(name=
"healpix", format=
"K"),
202 pyfits.Column(name=
"nside", format=
"K"),
204 first.data.field(
"id")[:] = numpy.arange(len(self.
_multiInds), dtype=int)
205 first.data.field(
"healpix")[:] = numpy.array([ind._healpix
for ind
in self.
_multiInds])
206 first.data.field(
"nside")[:] = numpy.array([ind._nside
for ind
in self.
_multiInds])
209 second = pyfits.new_table([pyfits.Column(name=
"id", format=
"K"),
210 pyfits.Column(name=
"filename", format=
"%dA" % (maxLength)),
211 ], nrows=numFilenames)
212 ident = second.data.field(
"id")
213 filenames = second.data.field(
"filename")
216 for fn
in ind._filenameList:
221 pyfits.HDUList([pyfits.PrimaryHDU(), first, second]).writeto(outName, clobber=
True)
224 """Initialise from a cache file
226 Ingest the cache file written by the 'writeCache' method and
227 use that to quickly instantiate the AstrometryNetCatalog.
229 with pyfits.open(filename)
as hduList:
230 first = hduList[1].data
231 second = hduList[2].data
234 filenames = {i: []
for i
in first.field(
"id")}
235 for id2, fn
in zip(second.field(
"id"), second.field(
"filename")):
236 filenames[id2].append(fn)
238 zip(first.field(
"id"), first.field(
"healpix"), first.field(
"nside"))]
241 cacheFiles = set(second.field(
"filename"))
242 configFiles = set(
sum(self.config.multiIndexFiles, []) + self.config.indexFiles)
243 assert(cacheFiles == configFiles)
256 """Generate a cache file"""
257 if andConfig
is None:
261 for index
in catalog:
265 for index
in catalog:
def getIndexPath
Get the path to the specified astrometry.net index file.
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, Scalar >::type sum(Scalar const &scalar)
std::string getPackageDir(std::string const &packageName)
return the root directory of a setup package
def isWithinRange
Is the index within range of the provided coordinates?
def getConfigFromEnvironment