Hide keyboard shortcuts

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 

7 

8__all__ = ["BaseCatalogObj", "BaseCatalogConfig"] 

9 

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 ) 

31 

32class BaseCatalogObj(CatalogDBObject): 

33 """Base class for Catalogs that query the default 

34 UW CATSIM database 

35 """ 

36 

37 config = BaseCatalogConfig() 

38 

39 #load $SIMS_CATUTILS_DIR/config/db.py 

40 config.load(os.path.join(getPackageDir("sims_catUtils"), "config", "db.py")) 

41 

42 host = config.host 

43 port = config.port 

44 database = config.database 

45 driver = config.driver 

46 

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 

51 

52 Execute a query, taking advantage of the spherical geometry library and 

53 htmid indexes on all catalog tables in the UW catsim database 

54 

55 **Parameters** 

56 

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 

72 

73 **Returns** 

74 

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) 

81 

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") 

101 

102 if obs_metadata is not None and regionStr is not None: 

103 #add spatial constraints to query. 

104 

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') 

108 

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() 

112 

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' 

120 

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) 

128 

129 

130 if constraint is not None: 

131 query = query.filter(text(constraint)) 

132 

133 if limit is not None: 

134 query = query.limit(limit) 

135 

136 return ChunkIterator(self, query, chunk_size) 

137