Coverage for python/lsst/sims/catUtils/baseCatalogModels/BaseCatalogModels.py : 32%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import warnings
2import os
3from lsst.sims.catalogs.db import CatalogDBObject, ChunkIterator
4from sqlalchemy.sql import select, func, column, text
5import lsst.pex.config as pexConfig
6from lsst.utils import getPackageDir
8__all__ = ["BaseCatalogObj", "BaseCatalogConfig"]
10class BaseCatalogConfig(pexConfig.Config):
11 host = pexConfig.Field(
12 dtype = str,
13 doc = "Name of the host",
14 default = "fatboy-private.phys.washington.edu",
15 )
16 port = pexConfig.Field(
17 dtype = str,
18 doc = "Port number of database",
19 default = "1433",
20 )
21 database = pexConfig.Field(
22 dtype = str,
23 doc = "Name of database. For 'sqlite', the filename is the database name",
24 default = "LSSTCATSIM",
25 )
26 driver = pexConfig.Field(
27 dtype = str,
28 doc = "Name of the database backend. Takes format of dialect+driver ",
29 default = "mssql+pymssql",
30 )
32class BaseCatalogObj(CatalogDBObject):
33 """Base class for Catalogs that query the default
34 UW CATSIM database
35 """
37 config = BaseCatalogConfig()
39 #load $SIMS_CATUTILS_DIR/config/db.py
40 config.load(os.path.join(getPackageDir("sims_catUtils"), "config", "db.py"))
42 host = config.host
43 port = config.port
44 database = config.database
45 driver = config.driver
47 def query_columns(self, colnames=None, chunk_size=None,
48 obs_metadata=None, constraint=None,
49 limit=None):
50 """Execute a query from the primary catsim database
52 Execute a query, taking advantage of the spherical geometry library and
53 htmid indexes on all catalog tables in the UW catsim database
55 **Parameters**
57 * colnames : list or None
58 a list of valid column names, corresponding to entries in the
59 `columns` class attribute. If not specified, all columns are
60 queried.
61 * chunk_size : int (optional)
62 if specified, then return an iterator object to query the database,
63 each time returning the next `chunk_size` elements. If not
64 specified, all matching results will be returned.
65 * obs_metadata : object (optional)
66 an observation metadata object which has a "filter" method, which
67 will add a filter string to the query.
68 * constraint : str (optional)
69 a string which is interpreted as SQL and used as a predicate on the query
70 * limit : int (optional)
71 limits the number of rows returned by the query
73 **Returns**
75 * result : list or iterator
76 If chunk_size is not specified, then result is a list of all
77 items which match the specified query. If chunk_size is specified,
78 then result is an iterator over lists of the given size.
79 """
80 query = self._get_column_query(colnames)
82 if obs_metadata is not None and obs_metadata.bounds is not None:
83 if obs_metadata.bounds.boundType == 'circle':
84 regionStr = 'REGION CIRCLE J2000 %f %f %f'%(obs_metadata.bounds.RAdeg,
85 obs_metadata.bounds.DECdeg,
86 60.*obs_metadata.bounds.radiusdeg)
87 elif obs_metadata.bounds.boundType == 'box':
88 regionStr = 'REGION RECT J2000 %f %f %f %f'%(obs_metadata.bounds.RAminDeg,
89 obs_metadata.bounds.DECminDeg,
90 obs_metadata.bounds.RAmaxDeg,
91 obs_metadata.bounds.DECmaxDeg)
92 else:
93 raise RuntimeError("CatalogObject does not know about boundType %s "
94 % obs_metadata.bounds.boundType)
95 else:
96 regionStr = 'REGION CIRCLE J2000 180. 0. 10800.'
97 warnings.warn("Searching over entire sky "
98 "since no bounds specified. "
99 "This could be a very bad idea "
100 "if the database is large")
102 if obs_metadata is not None and regionStr is not None:
103 #add spatial constraints to query.
105 #Hint sql engine to seek on htmid
106 if not self.tableid.endswith('forceseek'):
107 query = query.with_hint(self.table, ' WITH(FORCESEEK)', 'mssql')
109 #aliased subquery for htmid ranges covering the search region
110 htmid_range_alias = select([column('htmidstart'), column('htmidend')]).\
111 select_from(func.fHtmCoverRegion(regionStr)).alias()
113 #SQL is not case sensitive but python is:
114 if 'htmID' in self.columnMap:
115 htmidName = 'htmID'
116 elif 'htmid' in self.columnMap:
117 htmidName = 'htmid'
118 else:
119 htmidName = 'htmId'
121 #Range join on htmid ranges
122 query = query.join(htmid_range_alias,
123 self.table.c[htmidName].between(htmid_range_alias.c.htmidstart,
124 htmid_range_alias.c.htmidend)
125 )
126 query = query.filter(func.sph.fRegionContainsXYZ(func.sph.fSimplifyString(regionStr),
127 self.table.c.cx, self.table.c.cy, self.table.c.cz) == 1)
130 if constraint is not None:
131 query = query.filter(text(constraint))
133 if limit is not None:
134 query = query.limit(limit)
136 return ChunkIterator(self, query, chunk_size)