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

1from builtins import zip 

2from lsst.sims.catalogs.db import DBObject 

3from lsst.sims.utils import ObservationMetaData 

4from .BaseCatalogModels import BaseCatalogConfig 

5from lsst.utils import getPackageDir 

6from collections import OrderedDict 

7import numpy 

8import math 

9import os 

10 

11from lsst.sims.utils import CircleBounds 

12 

13__all__ = ["OpSim3_61DBObject"] 

14 

15 

16class OpSim3_61DBObject(DBObject): 

17 """ 

18 This is a class which allows you to query the databse of OpSim runs (v 3_61) 

19 """ 

20 config = BaseCatalogConfig() 

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

22 host = config.host 

23 port = config.port 

24 database = config.database 

25 driver = config.driver 

26 

27 #This is the table that this DBObject is querying 

28 tableid = 'output_opsim3_61' 

29 

30 #: These are interpreted as SQL strings. 

31 #They are passed to SpatialBounds objects 

32 #and indicate the RA and Dec columns in degrees 

33 raColName = 'fieldradeg' 

34 decColName = 'fielddecdeg' 

35 

36 # columnNames maps column names as stored in the OpSim3_61 database 

37 # to column names as they occur in the OpSim v3.3.5 summary table 

38 columnNames = [('obsHistID','obshistid'), 

39 ('SIM_SEED','expdate'), 

40 ('pointingRA','fieldra'), 

41 ('pointingDec','fielddec'), 

42 ('moonRA','moonra'), 

43 ('moonDec','moondec'), 

44 ('rotSkyPos','rotskypos'), 

45 ('rotTelPos','rottelpos'), 

46 ('rawSeeing','rawseeing'), 

47 ('sunAlt','sunalt'), 

48 ('moonAlt','moonalt'), 

49 ('dist2Moon','dist2moon'), 

50 ('moonPhase','moonphase'), 

51 ('expMJD','expmjd'), 

52 ('airmass', 'airmass'), 

53 ('filter', 'filter'), 

54 ('visitExpTime', 'exptime-4.0', float)] 

55 

56 #columnTypes is a dict indicating the data types 

57 #of the columns referred to in columnNames. 

58 #columns not mentioned are floats 

59 columnTypes ={'SIM_SEED':int, 

60 'filter':(str,1), 

61 'obsHistID':numpy.int64} 

62 

63 def __init__(self, driver=None, host=None, port=None, database=None): 

64 super(OpSim3_61DBObject, self).__init__(driver=driver, host=host, port=port, database=database) 

65 

66 def getBasicQuery(self): 

67 """ 

68 This class creates a string that is an SQL query of all the 

69 columns needed to create an ObservationMetaData suitable for 

70 generating a PhoSim input catalog. No constraints 

71 are placed on the query (it will grab all entries in the database) 

72 """ 

73 query = 'SELECT ' 

74 for name in self.columnNames: 

75 if query != 'SELECT ': 

76 query += ', ' 

77 query += name[1] 

78 query += ' FROM ' + self.tableid 

79 

80 dtype=numpy.dtype([(name[0], self.columnTypes[name[0]]) if name[0] in self.columnTypes else (name[0], float) for name in self.columnNames]) 

81 

82 return query, dtype 

83 

84 def executeConstrainedQuery(self, spatialBound, constraint=None): 

85 """ 

86 This method will perform a query which is contrained on the sky by spatialBound. 

87 You can add a supplementary constraint on another column using the 'contraint' kwarg. 

88 

89 param [in] spatialBound a SpatialBound object specifying the region of the sky from 

90 which you want your pointings drawn 

91 

92 param [in] constraint an optional constraint on another column. Should be a string 

93 of the form 'airmass=1.1' 

94 

95 param [out] a recarray of all of the pointings matching your constraints. This recarray 

96 will contain all of the columns necessary for constructing an ObservationMetaData object 

97 suitable for generating a PhoSim input catalog. 

98 """ 

99 query, dtype = self.getBasicQuery() 

100 query += ' WHERE '+spatialBound.to_SQL(self.raColName, self.decColName) 

101 if constraint is not None: 

102 query += ' and %s' % constraint 

103 

104 

105 results = self.execute_arbitrary(query, dtype=dtype) 

106 return results 

107 

108 def getObservationMetaData(self, searchCenter, searchRadius, constraint=None, 

109 fovRadius=1.75, makeCircBounds=True, makeBoxBounds=False): 

110 """ 

111 This method will perform a query on the OpSim3_61 for pointings within a given region 

112 on the sky. It will then return a list of ObservationMetaData corresponding to the 

113 OpSim pointings returned by that query. 

114 

115 param [in] searchCenter is a tuple (RA, Dec) indicating the center of the region 

116 of the sky wherein to search for OpSim pointings (in degrees). 

117 

118 param [in] searchRadius is the radius of the region of the sky wherein to search 

119 for OpSim pointings (in degrees). 

120 

121 param [in] constraint an optional constraint on another column. Should be a string 

122 of the form 'airmass=1.1' 

123 

124 param [in] fovRadius is the radius (in degrees) of the resulting ObservationMetaDatas' 

125 fields of view. If you have specified a box bounds this will be half the length of each 

126 side of the box. 

127 

128 param [in] makeCircBounds a boolean telling this method to construct an ObservationMetaData 

129 for a circular region of the sky centered on the specified OpSim pointing 

130 

131 param [in] make BoxBounds a boolean telling this method to construct an 

132 ObservationMetaData for a square region of the sky centered on the specified 

133 OpSim pointing 

134 """ 

135 

136 spatialBound = CircleBounds(numpy.radians(searchCenter[0]), numpy.radians(searchCenter[1]), 

137 numpy.radians(searchRadius)) 

138 

139 # get the results of the query as a numpy recarray 

140 result = self.executeConstrainedQuery(spatialBound, constraint=constraint) 

141 

142 obs_list = [] 

143 ra_list = numpy.degrees(result['pointingRA']) 

144 dec_list = numpy.degrees(result['pointingDec']) 

145 rotSkyPos_list = numpy.degrees(result['rotSkyPos']) 

146 for pointing, ra, dec, rotSkyPos in zip(result, ra_list, dec_list, rotSkyPos_list): 

147 

148 mjd = pointing['expMJD'] 

149 

150 #because makeCircBounds defaults to True, check whether the user is 

151 #requesting boxBounds before deciding to instantiate 

152 #circBounds 

153 

154 boundType = None 

155 boundLength = None 

156 if makeBoxBounds: 

157 boundType = 'box' 

158 boundLength = numpy.array([fovRadius/math.cos(numpy.radians(dec)), fovRadius]) 

159 elif makeCircBounds: 

160 boundType = 'circle' 

161 boundLength = fovRadius 

162 else: 

163 raise ValueErr("Need either makeBoxBounds or makeCircBounds") 

164 

165 obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, 

166 rotSkyPos=rotSkyPos, mjd=mjd, 

167 bandpassName=result['filter'][0], 

168 boundType=boundType, boundLength=boundLength) 

169 

170 raw_opsim_dict = dict([(k, pointing[k]) for k in result.dtype.names]) 

171 obs.OpsimMetaData = raw_opsim_dict 

172 obs_list.append(obs) 

173 

174 return obs_list