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

1#!/usr/bin/env python 

2# encoding: utf-8 

3""" 

4*request, update and read status of observation blocks with the SOXS Scheduler* 

5 

6:Author: 

7 Marco Landoni & David Young 

8 

9:Date Created: 

10 November 17, 2021 

11""" 

12from builtins import object 

13import sys 

14import os 

15os.environ['TERM'] = 'vt100' 

16from fundamentals import tools 

17from fundamentals.mysql import readquery, writequery 

18import requests 

19import json 

20 

21 

22class soxs_scheduler(object): 

23 """ 

24 *request, update and read status of observation blocks with the SOXS Scheduler * 

25 

26 **Key Arguments:** 

27 - ``log`` -- logger 

28 - ``dbConn`` -- marshall DB connection 

29 - ``settings`` -- the settings dictionary 

30 

31 **Usage:** 

32 

33 To setup your logger, settings and database connections, please use the ``fundamentals`` package (`see tutorial here <http://fundamentals.readthedocs.io/en/latest/#tutorial>`_).  

34 

35 To initiate a soxs_scheduler object, use the following: 

36 

37 ```eval_rst 

38 .. todo:: 

39 

40 - add usage info 

41 - create a sublime snippet for usage 

42 - create cl-util for this class 

43 - add a tutorial about ``soxs_scheduler`` to documentation 

44 - create a blog post about what ``soxs_scheduler`` does 

45 ``` 

46 

47 To initialise the scheduler object: 

48 

49 ```python 

50 from marshallEngine.services import soxs_scheduler 

51 schr = soxs_scheduler( 

52 log=log, 

53 dbConn=dbConn, 

54 settings=settings 

55 ) 

56 ``` 

57 

58 """ 

59 

60 def __init__( 

61 self, 

62 log, 

63 dbConn, 

64 settings=False, 

65 

66 ): 

67 self.log = log 

68 log.debug("instansiating a new 'soxs_scheduler' object") 

69 self.settings = settings 

70 self.dbConn = dbConn 

71 self.baseurl = self.settings["scheduler_baseurl"] 

72 

73 # Initial Actions 

74 self.update_scheduler_ob_table() 

75 

76 return None 

77 

78 def _create_single_auto_ob( 

79 self, 

80 transientBucketId, 

81 target_name, 

82 raDeg, 

83 decDeg, 

84 magnitude_list, 

85 existenceCheck=True): 

86 """*request to generate a single auto ob from the soxs scheduler* 

87 

88 **Key Arguments:** 

89 - ``transientBucketId`` -- the transients ID from the marshall. 

90 - ``target_name`` -- the master name of the target. 

91 - ``raDeg`` -- the target RA. 

92 - ``decDeg`` -- the target declination. 

93 - ``magnitude_list`` -- the list of lists of magnitudes. [['g':19.06],['r':19.39]] 

94 - ``existenceCheck`` -- check local database to see if OB already exists for this transient. Default *True*. 

95 

96 **Return:** 

97 - None 

98 

99 **Usage:** 

100 

101 ```python 

102 usage code  

103 ``` 

104 

105 --- 

106 

107 ```eval_rst 

108 .. todo:: 

109 

110 - add usage info 

111 - create a sublime snippet for usage 

112 - write a command-line tool for this method 

113 - update package tutorial with command-line tool info if needed 

114 ``` 

115 """ 

116 self.log.debug('starting the ``_create_single_auto_ob`` method') 

117 

118 if existenceCheck: 

119 # CHECK FOR EXISTENCE OF OB IN LOCAL DATABASE 

120 sqlQuery = f""" 

121 select ob_id from scheduler_obs where transientBucketId = {transientBucketId} 

122 """ 

123 rows = readquery( 

124 log=self.log, 

125 sqlQuery=sqlQuery, 

126 dbConn=self.dbConn 

127 ) 

128 if len(rows): 

129 obid = rows[0]['ob_id'] 

130 self.log.warning( 

131 'You are trying to create an OB for transient {transientBucketId}, but it is already assigned OBID = {obid}') 

132 return obid 

133 

134 try: 

135 schd_status_code = 0 

136 http_status_code = 500 

137 response = requests.post( 

138 url="https://soxs-scheduler-pwoxq.ondigitalocean.app/createAutoOB", 

139 headers={ 

140 "Content-Type": "application/json; charset=utf-8", 

141 }, 

142 data=json.dumps({ 

143 "magnitude_list": magnitude_list, 

144 "declination": float(decDeg), 

145 "target_name": target_name, 

146 "transientBucketID": transientBucketId, 

147 "right_ascension": float(raDeg) 

148 }) 

149 ) 

150 

151 response = response.json() 

152 schd_status_code = response["status"] 

153 content = response["data"] 

154 http_status_code = content["status_code"] 

155 

156 except requests.exceptions.RequestException: 

157 self.log.error( 

158 'HTTP Request failed to scheduler `createAutoOB` resource failed') 

159 if http_status_code != 201 or schd_status_code != 1: 

160 error = content["payload"] 

161 print(f"createAutoOB failed with error: '{error}'") 

162 return -1 

163 

164 obid = content["payload"][0]['OB_ID'] 

165 

166 # UPDATE THE SCHEDULER TABLE 

167 sqlQuery = f""" 

168 update scheduler_obs set ob_id = {obid} where transientBucketId = {transientBucketId}; 

169 """ 

170 rows = writequery( 

171 log=self.log, 

172 sqlQuery=sqlQuery, 

173 dbConn=self.dbConn 

174 ) 

175 

176 self.log.debug('completed the ``_create_single_auto_ob`` method') 

177 return obid 

178 

179 def request_all_required_auto_obs( 

180 self): 

181 """*request OBs for all new transients* 

182 

183 **Key Arguments:** 

184 # - 

185 

186 **Return:** 

187 - None 

188 

189 **Usage:** 

190 

191 ```python 

192 usage code  

193 ``` 

194 

195 --- 

196 

197 ```eval_rst 

198 .. todo:: 

199 

200 - add usage info 

201 - create a sublime snippet for usage 

202 - write a command-line tool for this method 

203 - update package tutorial with command-line tool info if needed 

204 ``` 

205 """ 

206 self.log.debug('starting the ``request_all_required_auto_obs`` method') 

207 

208 # GENERATE THE LIST OF TRANSIENTS NEEDING AN OB 

209 sqlQuery = f""" 

210 SELECT  

211 t.transientBucketId, s.targetName, t.raDeg, t.decDeg, s.latestMag, s.latestMagFilter 

212 FROM 

213 scheduler_obs s, 

214 transientbucketsummaries t 

215 WHERE 

216 t.transientBucketId = s.transientBucketId AND s.OB_ID is null 

217 """ 

218 

219 rows = readquery( 

220 log=self.log, 

221 sqlQuery=sqlQuery, 

222 dbConn=self.dbConn) 

223 passList = [] 

224 failedIds = [] 

225 

226 for r in rows: 

227 # GET FIRST CHARACTER OF FILTER 

228 ffilter = r['latestMagFilter'] 

229 if not ffilter: 

230 ffilter = "" 

231 else: 

232 ffilter = ffilter[0] 

233 try: 

234 transientBucketId = r['transientBucketId'] 

235 obid = self._create_single_auto_ob( 

236 transientBucketId=transientBucketId, 

237 target_name=r['targetName'], 

238 raDeg=r['raDeg'], 

239 decDeg=r['decDeg'], 

240 magnitude_list=[ 

241 [ffilter, float(r['latestMag'])]] 

242 ) 

243 if -1 == obid: 

244 failedIds.append(transientBucketId) 

245 else: 

246 passList.append(transientBucketId) 

247 except Exception as e: 

248 print(e) 

249 failedIds.append(transientBucketId) 

250 pass 

251 

252 print(f"{len(passList)} OBs added to the scheduler, {len(failedIds)} failed to be added.") 

253 

254 self.log.debug( 

255 'completed the ``request_all_required_auto_obs`` method') 

256 return (passList, failedIds) 

257 

258 def update_scheduler_ob_table( 

259 self): 

260 """*sync the scheduler ob tables with the core marshall tables to bring it up-to-date* 

261 

262 **Usage:** 

263 

264 ```python 

265 schr.update_scheduler_ob_table() 

266 ``` 

267 """ 

268 self.log.debug('starting the ``update_scheduler_ob_table`` method') 

269 

270 sqlQuery = f""" 

271 call update_scheduler_obs(); 

272 """ 

273 writequery( 

274 log=self.log, 

275 sqlQuery=sqlQuery, 

276 dbConn=self.dbConn 

277 ) 

278 

279 self.log.debug('completed the ``update_scheduler_ob_table`` method') 

280 return 

281 

282 # use the tab-trigger below for new method 

283 # xt-class-method