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

1try: 

2 from itertools import zip_longest 

3except ImportError: 

4 from itertools import izip_longest as zip_longest 

5 

6__all__ = ["CUT_TYPEMAP", "FieldSelection"] 

7 

8CUT_TYPEMAP = { 

9 "RA": "fieldRA", 

10 "Dec": "fieldDec", 

11 "GL": "fieldGL", 

12 "GB": "fieldGB", 

13 "EL": "fieldEL", 

14 "EB": "fieldEB" 

15} 

16"""Mapping of short names to field database column names.""" 

17 

18class FieldSelection(object): 

19 """Class for constructing SQL queries on the survey fields database. 

20 

21 This class is for creating SQL queries to perform on the survey fields 

22 database. It does not actually perform the queries. 

23 """ 

24 

25 def base_select(self): 

26 """Return the base field query. 

27 

28 Returns 

29 ------- 

30 str 

31 """ 

32 return "select * from Field" 

33 

34 def combine_queries(self, *queries, **kwargs): 

35 """Combine a set of queries. 

36 

37 Parameters 

38 ---------- 

39 queries : str instances 

40 A set of queries to join via the given operators. 

41 combiners : tuple of str 

42 A set of logical operations (and, or etc.) to join the queries 

43 with. Defaults is an empty tuple. NOTE: A tuple with one logical 

44 operator must look like ('and',). 

45 order_by : str, optional 

46 Set the order by clause. Default is fieldId. 

47 

48 Returns 

49 ------- 

50 str: 

51 The fully combined query. 

52 """ 

53 combiners = kwargs.get("combiners", ()) 

54 if len(combiners) != len(queries) - 1: 

55 raise RuntimeError("Number of combiners must be one less than " 

56 "number of queries!") 

57 

58 order_by = kwargs.get("order_by", "fieldId") 

59 

60 final_query = [] 

61 final_query.append(self.base_select()) 

62 final_query.append("where") 

63 for combine, query in zip_longest(combiners, queries): 

64 final_query.append(query) 

65 if combine is not None: 

66 final_query.append(combine) 

67 final_query.append("order by {}".format(order_by)) 

68 

69 return self.finish_query(" ".join(final_query)) 

70 

71 def finish_query(self, query): 

72 """Put a semicolon at the end of a query. 

73 

74 Parameters 

75 ---------- 

76 query : str 

77 The SQL query to finish. 

78 

79 Returns 

80 ------- 

81 str 

82 The finished SQl query. 

83 """ 

84 return query + ";" 

85 

86 def galactic_region(self, maxB, minB, endL, exclusion=False): 

87 """Create a galactic region. 

88 

89 This function creates a sloping region around the galactic plane to 

90 either include or exclude fields. 

91 

92 Parameters 

93 ---------- 

94 maxB : float 

95 The maximum galactic latitude at the galactic longitude of zero. 

96 minB : float 

97 The minimum galactic latitude at the galactic longitude of endL. 

98 endL : float 

99 The galactic longitude for the end of the envelope region. 

100 exclusion : bool, optional 

101 Flag to construct the query as an exclusion. Default is False. 

102 

103 Returns 

104 ------- 

105 str 

106 The appropriate query. 

107 """ 

108 region_select = ">" if exclusion else "<=" 

109 band = maxB - minB 

110 sql = '(abs(fieldGB) {0} ({1} - ({2} * '\ 

111 'abs(fieldGL)) / {3}))'.format(region_select, maxB, band, endL) 

112 

113 return sql 

114 

115 def get_all_fields(self): 

116 """Return query for all fields. 

117 

118 Returns 

119 ------- 

120 str 

121 The query for all the fields. 

122 """ 

123 return self.finish_query(self.base_select()) 

124 

125 def select_region(self, region_type, start_value, end_value): 

126 """Create a simple bounded region. 

127 

128 This function creates a bounded cut query based on the input values as 

129 bounds for a given region. If start_value < end_value, the cut looks 

130 like [start_value, end_value]. If start_value > end_value, the bounded 

131 cut is or'd between the following cuts: [start_value, 360] and 

132 [0, end_value]. 

133 

134 Parameters 

135 ---------- 

136 region_type : str 

137 The name of the region to cut on. 

138 start_value : float 

139 The starting value (degrees) of the cut region. 

140 end_value : float 

141 The ending value (degrees) of the cut region. 

142 

143 Returns 

144 ------- 

145 str 

146 The appropriate query. 

147 """ 

148 column_name = CUT_TYPEMAP[region_type] 

149 if end_value > start_value: 

150 sql = '{0} between {1} and {2}'.format(column_name, start_value, 

151 end_value) 

152 else: 

153 sql = '({0} between {1} and 360 or '\ 

154 '{0} between 0 and {2})'.format(column_name, start_value, 

155 end_value) 

156 

157 return sql 

158 

159 def select_user_regions(self, id_list): 

160 """Create a query for a list of fields.of 

161 

162 This function creates a query focusing on field Ids. It is recommended 

163 not to use this with more than a dozen Ids. 

164 

165 Parameters 

166 ---------- 

167 id_list : list[int] 

168 A set of field Ids to construct a query for.query 

169 

170 Returns 

171 ------- 

172 str 

173 The appropriate query. 

174 """ 

175 sql = [] 

176 for fid in id_list: 

177 sql.append("fieldId={}".format(fid)) 

178 sql.append("or") 

179 

180 # Don't need last or 

181 del sql[-1] 

182 

183 return " ".join(sql)