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/local/bin/python 

2# encoding: utf-8 

3""" 

4*model for transient data in the marshall database - use this code to grab the transient data* 

5 

6:Author: 

7 David Young 

8""" 

9from future import standard_library 

10standard_library.install_aliases() 

11from builtins import zip 

12from builtins import object 

13import sys 

14import os 

15import collections 

16from sqlalchemy.sql import text 

17import urllib.request 

18import urllib.parse 

19import urllib.error 

20from astrocalc.coords import unit_conversion 

21from dryxPyramid.models.models_base import base_model 

22import re 

23 

24 

25class models_transients_get(base_model): 

26 """ 

27 The worker class for the `models_transients_get` module 

28 

29 **Key Arguments** 

30 

31 - ``log`` -- logger 

32 - ``request`` -- the pyramid request 

33 - ``elementId`` -- the specific element id requests (or False) 

34 

35 """ 

36 

37 def __init__(self, log, request, elementId=False, search=False, tcsCatalogueId=False): 

38 super().__init__(log, request, elementId, search) 

39 

40 self.resourceName = "transients" 

41 self.defaultQs = { # the query string defaults 

42 "mwl": "inbox", 

43 "format": "html_tickets", 

44 "ticketLimit": 10, 

45 "tableLimit": 100, 

46 "pageStart": 0, 

47 "sortBy": "dateAdded", 

48 "sortDesc": False, 

49 "filterBy1": "decDeg", 

50 "filterValue1": 30, 

51 "filterOp1": "<", 

52 "filterBy2": False, 

53 "filterValue2": False, 

54 "filterOp2": "=" 

55 } 

56 self.tcsCatalogueId = tcsCatalogueId 

57 

58 self._set_default_parameters() 

59 self.transientData, self.matchedTransientBucketIds, self.totalTicketCount = self._get_transient_data_from_database() 

60 

61 log.debug( 

62 "instansiating a new 'models_transients_get' object") 

63 return None 

64 

65 def get(self): 

66 """ 

67 *get the transientData object* 

68 

69 **Return** 

70 

71 - ``transientData`` 

72 

73 """ 

74 self.log.debug('starting the ``get`` method') 

75 

76 self.transientAkas = self._get_associated_transient_aka() 

77 self.transientLightcurveData = self._get_associated_lightcurve_data() 

78 self.transientAtelMatches = self._get_associated_atel_data() 

79 self.transients_comments = self._get_associated_comments() 

80 self.transient_history = self._get_associated_transient_history() 

81 self.transient_crossmatches = self._get_associated_transient_crossmatches() 

82 

83 self.log.debug('completed the ``get`` method') 

84 

85 if "format" in self.qs and (self.qs["format"] == "json" or self.qs["format"] == "csv" or self.qs["format"] == "plain_table"): 

86 self._clean_data_for_plain_text_outputs() 

87 return self.transientData 

88 

89 qs = self.qs 

90 self.log.debug("""self.qs: `%(qs)s`""" % locals()) 

91 

92 return self.qs, self.transientData, self.transientAkas, self.transientLightcurveData, self.transientAtelMatches, self.transients_comments, self.totalTicketCount, self.transient_history, self.transient_crossmatches 

93 

94 def _get_transient_data_from_database( 

95 self): 

96 """ 

97 *get the sqlquery based on the request object parameters* 

98 

99 **Return** 

100 

101 - ``objectData`` 

102 - ``matchedTransientBucketIds`` 

103 - ``totalTicketCount`` 

104 

105 """ 

106 self.log.debug('starting the ``get_data_from_database`` method') 

107 

108 tcsCatalogueId = self.tcsCatalogueId 

109 sqlWhereList = [] 

110 regex1 = re.compile(r'[^A-Za-z0-9]') 

111 regex2 = re.compile(r'^(AT|SN)') 

112 # SEARCH 

113 if self.search and "q" in self.request.params: 

114 searchString = self.request.params["q"] 

115 searchString = regex1.sub('', searchString) 

116 searchString = regex2.sub('^(AT|SN)', searchString) 

117 self.log.debug("""searchString: `%(searchString)s`""" % locals()) 

118 

119 sqlQuery = f""" 

120 select DISTINCT transientBucketId from marshall_transient_akas where REGEXP_REPLACE(name,"[^A-Za-z0-9]","") REGEXP '{searchString}'  

121 union 

122 select DISTINCT transientBucketId from pesstoObjects where REGEXP_REPLACE(pi_name,"[^A-Za-z0-9]","") REGEXP '{searchString}'  

123 """ 

124 rows = self.request.db.execute( 

125 text(sqlQuery)).fetchall() 

126 

127 searchList = "" 

128 for row in rows: 

129 transientBucketId = row["transientBucketId"] 

130 searchList = """%(searchList)s %(transientBucketId)s,""" % locals( 

131 ) 

132 

133 thisWhere = """t.transientBucketId in (%(searchList)s -99)""" % locals( 

134 ) 

135 

136 sqlWhereList.append(thisWhere) 

137 thisPageName = searchString 

138 self.log.debug("""searchList: `%(searchList)s`""" % locals()) 

139 

140 # Single Element Id (i.e. transientBucketId) 

141 if self.elementId: 

142 thisTransientBucketId = self.elementId 

143 thisWhere = """t.transientBucketId in (%(thisTransientBucketId)s)""" % locals( 

144 ) 

145 sqlWhereList.append(thisWhere) 

146 

147 # MARSHALL WORKFLOW 

148 if "mwl" in self.qs: 

149 if self.qs["mwl"] == "allObsQueue": 

150 thisWhere = """(marshallWorkflowLocation = "following" or marshallWorkflowLocation = "pending observation") """ 

151 elif self.qs["mwl"] == "all": 

152 thisWhere = """1=1""" 

153 else: 

154 thisWhere = """marshallWorkflowLocation = "%(mwl)s" """ % self.qs 

155 sqlWhereList.append(thisWhere) 

156 

157 # ALERT WORKFLOW 

158 if "awl" in self.qs: 

159 thisWhere = """alertWorkflowLocation = "%(awl)s" """ % self.qs 

160 sqlWhereList.append(thisWhere) 

161 

162 # CLASSIFIED? 

163 if "cf" in self.qs: 

164 thisWhere = """classifiedFlag = "%(cf)s" """ % self.qs 

165 sqlWhereList.append(thisWhere) 

166 

167 # SNOOZED? 

168 if "snoozed" in self.qs: 

169 thisWhere = """snoozed = "%(snoozed)s" """ % self.qs 

170 sqlWhereList.append(thisWhere) 

171 

172 # FILTER? 

173 if "filterBy1" in self.qs and self.qs['filterBy1'] and "filterValue1" in self.qs and self.qs['filterValue1'] and "filterOp1" in self.qs and self.qs['filterOp1']: 

174 if self.qs['filterBy1'] in ("decDeg", "raDeg"): 

175 thisWhere = """t.`%(filterBy1)s` %(filterOp1)s %(filterValue1)s """ % self.qs 

176 else: 

177 try: 

178 self.qs["filterValue1"] = float(self.qs["filterValue1"]) 

179 thisWhere = """`%(filterBy1)s` %(filterOp1)s %(filterValue1)s """ % self.qs 

180 except: 

181 thisWhere = """`%(filterBy1)s` %(filterOp1)s "%(filterValue1)s" """ % self.qs 

182 

183 sqlWhereList.append(thisWhere) 

184 

185 if "filterBy2" in self.qs and self.qs['filterBy2'] and "filterValue2" in self.qs and self.qs['filterValue2'] and "filterOp2" in self.qs and self.qs['filterOp2']: 

186 if self.qs['filterBy2'] in ("decDeg", "raDeg"): 

187 thisWhere = """t.`%(filterBy2)s` %(filterOp2)s %(filterValue2)s """ % self.qs 

188 else: 

189 try: 

190 self.qs["filterValue2"] = float(self.qs["filterValue2"]) 

191 thisWhere = """`%(filterBy2)s` %(filterOp2)s %(filterValue2)s """ % self.qs 

192 except: 

193 thisWhere = """`%(filterBy2)s` %(filterOp2)s "%(filterValue2)s" """ % self.qs 

194 

195 sqlWhereList.append(thisWhere) 

196 

197 if "phaseiiiCheck" in self.qs: 

198 phaseiiiCheck = self.qs["phaseiiiCheck"] 

199 if phaseiiiCheck == "null": 

200 phaseiiiCheck = "is null" 

201 else: 

202 phaseiiiCheck = "= %(phaseiiiCheck)s" % locals() 

203 thisWhere = """t.transientBucketId in (SELECT transientBucketId FROM phase_iii_transient_catalogue_ssdr3 p, sherlock_classifications s where s.transient_object_id=p.TransientBucketId and s.matchVerified %(phaseiiiCheck)s) """ % locals() 

204 sqlWhereList.append(thisWhere) 

205 

206 # tcsCatalogueId? 

207 if tcsCatalogueId: 

208 thisWhere = """cm.catalogue_table_id = %(tcsCatalogueId)s """ % locals( 

209 ) 

210 if "tcsRank" in self.qs: 

211 rank = self.qs["tcsRank"] 

212 thisWhere += """ and cm.rank=%(rank)s""" % locals() 

213 sqlWhereList = [] 

214 sqlWhereList.append(thisWhere) 

215 tcsCm = ", sherlock_crossmatches cm" 

216 tec = "and t.transientBucketId = cm.transient_object_id" 

217 sec = "and s.transientBucketId = cm.transient_object_id" 

218 else: 

219 tcsCm = "" 

220 tec = "" 

221 sec = "" 

222 

223 # COMBINE THE WHERE CLAUSES 

224 queryWhere = "" 

225 for i, v in enumerate(sqlWhereList[:-1]): 

226 queryWhere = """%(queryWhere)s %(v)s and""" % locals() 

227 if len(sqlWhereList): 

228 finalWhere = sqlWhereList[-1] 

229 queryWhere = """where %(queryWhere)s %(finalWhere)s""" % locals() 

230 

231 # Now build the SQL Query 

232 tep = "and t.transientBucketId = p.transientBucketId" 

233 sep = "and s.transientBucketId = p.transientBucketId" 

234 

235 orderBy = "" 

236 if "sortBy" in self.qs and self.qs["sortBy"] is not False: 

237 sortRev = 0 

238 sortDirection = "" 

239 if "dateAdded" in self.qs["sortBy"] or "earliestDetection" in self.qs["sortBy"] or "Comment" in self.qs["sortBy"] or "lastNonDetectionDate" in self.qs["sortBy"]: 

240 sortRev = 1 

241 

242 if (self.qs["sortDesc"] == "True" or self.qs["sortDesc"] == True) and sortRev == 0: 

243 sortDirection = "desc" 

244 elif (self.qs["sortDesc"] != "True" and self.qs["sortDesc"] != True) and sortRev == 1: 

245 sortDirection = "desc" 

246 

247 if self.qs["sortBy"] == "redshift": 

248 sqlQuery = """ 

249 select s.transientBucketId from transientBucketSummaries s, pesstoObjects p %(tcsCm)s %(queryWhere)s %(sep)s %(sec)s order by s.best_redshift %(sortDirection)s 

250 """ % locals() 

251 elif self.qs["sortBy"] == "latestComment": 

252 sqlQuery = """ 

253 select * from (select t.transientBucketId from pesstoObjects p, transientBucketSummaries t %(tcsCm)s %(queryWhere)s %(tec)s %(tep)s) as a LEFT OUTER JOIN (SELECT pesstoObjectsId, MAX(dateCreated) AS latestCommentDate FROM pesstoObjectsComments GROUP BY pesstoObjectsId) as b ON a.transientBucketId = b.pesstoObjectsId ORDER BY latestCommentDate %(sortDirection)s 

254 """ % locals() 

255 

256 elif self.qs["sortBy"] == "pi_name": 

257 # the ticket selection query 

258 sortBy = self.qs["sortBy"] 

259 sqlQuery = """ 

260 select t.transientBucketId from transientBucketSummaries t, pesstoObjects p %(tcsCm)s %(queryWhere)s %(tep)s %(tec)s order by case when p.%(sortBy)s is null then 1 else 0 end, p.%(sortBy)s %(sortDirection)s 

261 """ % locals() 

262 

263 elif self.qs["sortBy"] == "observationPriority": 

264 sortBy = self.qs["sortBy"] 

265 sqlQuery = """ 

266 select t.transientBucketId from transientBucketSummaries t, pesstoObjects p %(tcsCm)s %(queryWhere)s %(tep)s %(tec)s order by p.%(sortBy)s %(sortDirection)s, case when t.dateAdded is null then 1 else 0 end, t.dateAdded desc 

267 """ % locals() 

268 

269 else: 

270 # the ticket selection query 

271 sortBy = self.qs["sortBy"] 

272 sqlQuery = """ 

273 select t.transientBucketId from transientBucketSummaries t, pesstoObjects p %(tcsCm)s %(queryWhere)s %(tep)s %(tec)s order by case when t.%(sortBy)s is null then 1 else 0 end, t.%(sortBy)s %(sortDirection)s 

274 """ % locals() 

275 else: 

276 sqlQuery = """ 

277 select t.transientBucketId from transientBucket t, pesstoObjects p %(tcsCm)s %(queryWhere)s and replacedByRowId =0 %(tep)s %(tec)s 

278 """ % locals() 

279 

280 # Add the limits and pagination to query 

281 pageStart = self.qs["pageStart"] 

282 limit = self.qs["limit"] 

283 sqlQuery = """%(sqlQuery)s limit %(pageStart)s, %(limit)s""" % locals() 

284 

285 # grab the transientBucketIds 

286 

287 rows = self.request.db.execute(sqlQuery).fetchall() 

288 self.log.debug("""{rows}""".format(**dict(globals(), **locals()))) 

289 # GET ORDERED LIST OF THE TRANSIENTBUCKETIDs 

290 matchedTransientBucketIds = "" 

291 for aRow in rows: 

292 tbi = aRow["transientBucketId"] 

293 matchedTransientBucketIds = """%(matchedTransientBucketIds)s %(tbi)s,""" % locals( 

294 ) 

295 matchedTransientBucketIds = "%(matchedTransientBucketIds)s -99" % locals( 

296 ) 

297 

298 # select column names 

299 selectColumns = "" 

300 skipColumns = [ 

301 "lastNonDetectionDate", "classificationWRTMax", "classificationPhase"] 

302 tables = {"transientBucketSummaries": "s", 

303 "transientBucket": "t", 

304 "pesstoObjects": "p", 

305 "sherlock_classifications": "sc"} 

306 

307 thisSchema = self.request.registry.settings["database_schema"] 

308 for k, v in list(tables.items()): 

309 sqlQuery = """SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where table_name = "%(k)s" and TABLE_SCHEMA = "%(thisSchema)s" """ % locals( 

310 ) 

311 rows = self.request.db.execute(sqlQuery).fetchall() 

312 self.log.debug( 

313 """rows: {rows}""".format(**dict(globals(), **locals()))) 

314 

315 for row in rows: 

316 if row["COLUMN_NAME"] not in skipColumns or k == "transientBucketSummaries": 

317 skipColumns.append(row["COLUMN_NAME"]) 

318 columnName = row["COLUMN_NAME"] 

319 selectColumns = """{selectColumns} {v}.{columnName},""".format( 

320 **dict(globals(), **locals())) 

321 

322 selectColumns = selectColumns[:-1] 

323 

324 self.log.debug( 

325 """selectColumns: {selectColumns}""".format(**dict(globals(), **locals()))) 

326 

327 # grab the remaining data assocatied with the transientBucketIds 

328 sqlQuery = """ 

329 select %(selectColumns)s from transientBucket t, transientBucketSummaries s, pesstoObjects p, sherlock_classifications sc where t.replacedByRowId = 0 and t.transientBucketId in (%(matchedTransientBucketIds)s) and t.masterIdFlag = 1 and t.transientBucketId = p.transientBucketId and p.transientBucketId=s.transientBucketId and t.transientBucketId = sc.transient_object_id order by FIELD(t.transientBucketId, %(matchedTransientBucketIds)s) 

330 """ % locals() 

331 tmpObjectData = self.request.db.execute( 

332 text(sqlQuery)).fetchall() 

333 

334 objectData = [] 

335 objectData[:] = [dict(list(zip(list(row.keys()), row))) 

336 for row in tmpObjectData] 

337 # for row in objectData: 

338 # row = dict(zip(row.keys(), row)) 

339 self.log.debug( 

340 """{objectData}""".format(**dict(globals(), **locals()))) 

341 

342 # get the total ticket count 

343 totalTicketCount = self._get_total_ticket_count_for_list( 

344 queryWhere=queryWhere) 

345 

346 self.log.debug('completed the ``get_data_from_database`` method') 

347 return objectData, matchedTransientBucketIds, totalTicketCount 

348 

349 def _set_default_parameters( 

350 self): 

351 """ 

352 *set default parameters in the request object if they have not yet been set* 

353 """ 

354 self.log.debug('starting the ``set_default_parameters`` method') 

355 

356 self.log.debug("""these are the current query string key/values: {self.qs}""".format( 

357 **dict(globals(), **locals()))) 

358 

359 # Assign the default values for the variables if they do not exist 

360 # Set inbox as the default view 

361 checkList = ["q", "mwl", "cf", "awl", "snoozed"] 

362 setDefaults = True 

363 for item in checkList: 

364 if item in self.qs: 

365 setDefaults = False 

366 

367 if setDefaults is True and self.search == False and self.elementId == False: 

368 self.qs[u"mwl"] = u"inbox" 

369 

370 # set ticketView as the default data type 

371 if "format" not in self.qs: 

372 self.qs["format"] = self.defaultQs["format"] 

373 

374 # setup default pagination and limits 

375 if "limit" not in self.qs: 

376 if self.qs["format"] == "html_table": 

377 self.qs["limit"] = self.defaultQs["tableLimit"] 

378 elif self.qs["format"] == "html_tickets": 

379 self.qs["limit"] = self.defaultQs["ticketLimit"] 

380 else: 

381 self.qs["limit"] = 20000 

382 

383 if "pageStart" not in self.qs: 

384 self.qs["pageStart"] = self.defaultQs["pageStart"] 

385 

386 if "sortBy" not in self.qs: 

387 if "mwl" in self.qs and self.qs["mwl"] in ["following", "pending observation", "allObsQueue"]: 

388 self.qs["sortBy"] = "observationPriority" 

389 self.qs["sortDesc"] = False 

390 elif ("mwl" in self.qs and self.qs["mwl"] in ["inbox"]) or "snoozed" in self.qs: 

391 self.qs["sortBy"] = "currentMagnitudeDate" 

392 self.qs["sortDesc"] = True 

393 else: 

394 self.qs["sortBy"] = self.defaultQs["sortBy"] 

395 self.qs["sortDesc"] = self.defaultQs["sortDesc"] 

396 

397 # ADD THE REST OF THE DEFAULTS TO THE QUERY STRING 

398 for k, v in list(self.defaultQs.items()): 

399 if k not in self.qs and 'q' not in self.qs and not self.elementId: 

400 if "awl" in self.qs and k == "mwl": 

401 continue 

402 self.qs[k] = v 

403 

404 self.qs["filterText1"] = "" 

405 if "filterBy1" in self.qs and self.qs["filterBy1"] and (self.qs["filterBy1"].lower() == "false" or "null" in self.qs["filterBy1"].lower()): 

406 self.qs["filterBy1"] = False 

407 if "filterBy1" in self.qs and self.qs["filterBy1"]: 

408 if "filterOp1" not in self.qs: 

409 self.qs["filterOp1"] = self.defaultQs["filterOp1"] 

410 if self.qs["filterOp1"].lower() == "eq": 

411 self.qs["filterOp1"] = "=" 

412 elif self.qs["filterOp1"].lower() == "lt": 

413 self.qs["filterOp1"] = "<" 

414 elif self.qs["filterOp1"].lower() == "gt": 

415 self.qs["filterOp1"] = ">" 

416 elif self.qs["filterOp1"].lower() == "neq": 

417 self.qs["filterOp1"] = "!=" 

418 

419 self.qs[ 

420 "filterText1"] = "with <strong>%(filterBy1)s %(filterOp1)s %(filterValue1)s</strong> " % self.qs 

421 

422 self.qs["filterText2"] = "" 

423 if "filterBy2" in self.qs and self.qs["filterBy2"] and self.qs["filterBy2"].lower() == "false": 

424 self.qs["filterBy2"] = False 

425 if "filterBy2" in self.qs and self.qs["filterBy2"]: 

426 if "filterOp2" not in self.qs: 

427 self.qs["filterOp2"] = self.defaultQs["filterOp2"] 

428 if self.qs["filterOp2"].lower() == "eq": 

429 self.qs["filterOp2"] = "=" 

430 elif self.qs["filterOp2"].lower() == "lt": 

431 self.qs["filterOp2"] = "<" 

432 elif self.qs["filterOp2"].lower() == "gt": 

433 self.qs["filterOp2"] = ">" 

434 elif self.qs["filterOp2"].lower() == "neq": 

435 self.qs["filterOp2"] = "!=" 

436 

437 self.qs[ 

438 "filterText2"] = "with <strong>%(filterBy2)s %(filterOp2)s %(filterValue2)s</strong> " % self.qs 

439 self.qs["filterText2"] = self.qs["filterText2"].replace( 

440 "sherlockClassification", "contextual classification") 

441 

442 self.log.debug("""these are the new query string key/values: {self.qs}""".format( 

443 **dict(globals(), **locals()))) 

444 

445 self.log.debug('completed the ``set_default_parameters`` method') 

446 return None 

447 

448 def _get_associated_transient_aka( 

449 self): 

450 """ 

451 *get associated aka names for the trasnsients* 

452 

453 **Return** 

454 

455 - ``objectAkas`` -- the akas for the objects found 

456 

457 """ 

458 self.log.debug('starting the ``_get_associated_transient_aka`` method') 

459 from marshall_webapp.models.transients_akas import models_transients_akas_get 

460 transients_akas = models_transients_akas_get( 

461 log=self.log, 

462 request=self.request, 

463 elementId=self.matchedTransientBucketIds 

464 ) 

465 akas = transients_akas.get() 

466 

467 self.log.debug( 

468 'completed the ``_get_associated_transient_aka`` method') 

469 return akas 

470 

471 def _get_associated_lightcurve_data( 

472 self): 

473 """ 

474 *get associated lightcurve data for the matched transients* 

475 

476 **Return** 

477 

478 - ``lightCurveData`` -- the found objects' lightcurve data 

479 

480 """ 

481 self.log.debug( 

482 'completed the ````_get_associated_lightcurve_data`` method') 

483 

484 matchedTransientBucketIds = self.matchedTransientBucketIds 

485 

486 sqlQuery = """ 

487 select transientBucketId, magnitude, filter, survey, surveyObjectUrl, observationDate from transientBucket where replacedByRowId = 0 and transientBucketId in (%(matchedTransientBucketIds)s) and observationDate is not null and observationDate != 0000-00-00 and magnitude is not null and magnitude < 50 and limitingMag = 0 order by observationDate desc; 

488 """ % locals() 

489 lightCurveDataTmp = self.request.db.execute(sqlQuery).fetchall() 

490 lightCurveData = [] 

491 lightCurveData[:] = [dict(list(zip(list(row.keys()), row))) 

492 for row in lightCurveDataTmp] 

493 

494 self.log.debug( 

495 'completed the ``_get_associated_lightcurve_data`` method') 

496 return lightCurveData 

497 

498 def _get_associated_atel_data( 

499 self): 

500 """ 

501 *get associated atel data for the matched transients* 

502 

503 **Return** 

504 

505 - ``transientAtelMatches`` -- the matched atels fot the transients 

506 

507 """ 

508 self.log.debug('starting the ``_get_associated_atel_data`` method') 

509 

510 matchedTransientBucketIds = self.matchedTransientBucketIds 

511 

512 sqlQuery = """ 

513 select distinct transientBucketId, name, surveyObjectUrl from transientBucket where replacedByRowId = 0 and transientBucketId in (%(matchedTransientBucketIds)s) and name like "%%atel_%%" 

514 """ % locals() 

515 transientAtelMatchesTmp = self.request.db.execute(sqlQuery).fetchall() 

516 transientAtelMatches = [] 

517 transientAtelMatches[:] = [ 

518 dict(list(zip(list(row.keys()), row))) for row in transientAtelMatchesTmp] 

519 

520 self.log.debug('completed the ``_get_associated_atel_data`` method') 

521 return transientAtelMatches 

522 

523 def _get_associated_comments( 

524 self): 

525 """ 

526 *get associated comments for the transients* 

527 

528 **Return** 

529 

530 - ``objectComments`` -- object comments 

531 

532 """ 

533 self.log.debug('starting the ``_get_associated_comments`` method') 

534 

535 matchedTransientBucketIds = self.matchedTransientBucketIds 

536 

537 sqlQuery = """ 

538 select * from pesstoObjectsComments where pesstoObjectsID in (%(matchedTransientBucketIds)s) order by dateCreated desc 

539 """ % locals() 

540 objectCommentsTmp = self.request.db.execute(sqlQuery).fetchall() 

541 objectComments = [] 

542 objectComments[:] = [dict(list(zip(list(row.keys()), row))) 

543 for row in objectCommentsTmp] 

544 

545 self.log.debug('completed the ``_get_associated_comments`` method') 

546 return objectComments 

547 

548 def _get_total_ticket_count_for_list( 

549 self, 

550 queryWhere): 

551 """ 

552 *get total ticket count for list* 

553 

554 **Key Arguments** 

555 

556 - ``queryWhere`` -- the where segment of the ticket list sqlQuery string 

557 

558 

559 **Return** 

560 

561 - ``totalTickets`` -- total number of object in list 

562 

563 """ 

564 self.log.debug( 

565 'completed the ````_get_total_ticket_count_for_list`` method') 

566 

567 tcsCatalogueId = self.tcsCatalogueId 

568 if self.search: 

569 sqlQuery = """ 

570 select count(*) from pesstoObjects p, transientBucketSummaries t %(queryWhere)s and t.transientBucketId = p.transientBucketId; 

571 """ % locals() 

572 totalTicketsTmp = self.request.db.execute(sqlQuery).fetchall() 

573 totalTickets = [] 

574 totalTickets[:] = [dict(list(zip(list(row.keys()), row))) 

575 for row in totalTicketsTmp] 

576 totalTickets = totalTickets[0]["count(*)"] 

577 elif self.elementId: 

578 totalTickets = 1 

579 elif tcsCatalogueId: 

580 if "tcsRank" in self.qs: 

581 sqlQuery = """ 

582 select top_ranked_transient_associations as count from tcs_stats_catalogues where table_id = %(tcsCatalogueId)s; 

583 """ % locals() 

584 else: 

585 sqlQuery = """ 

586 select all_transient_associations as count from tcs_stats_catalogues where table_id = %(tcsCatalogueId)s; 

587 """ % locals() 

588 ticketCountRowsTmp = self.request.db.execute(sqlQuery).fetchall() 

589 ticketCountRows = [] 

590 ticketCountRows[:] = [dict(list(zip(list(row.keys()), row))) 

591 for row in ticketCountRowsTmp] 

592 totalTickets = 0 

593 for row in ticketCountRows: 

594 totalTickets += row["count"] 

595 elif 'filterBy1' in self.qs or 'filterBy2' in self.qs: 

596 tcsCm = ", sherlock_crossmatches cm" 

597 tec = "and t.transientBucketId = cm.transient_object_id" 

598 sec = "and s.transientBucketId = cm.transient_object_id" 

599 tep = "and t.transientBucketId = p.transientBucketId" 

600 sep = "and s.transientBucketId = p.transientBucketId" 

601 

602 sqlQuery = """ 

603 select count(*) as count from transientBucketSummaries t, pesstoObjects p %(queryWhere)s %(tep)s 

604 """ % locals() 

605 

606 ticketCountRowsTmp = self.request.db.execute(sqlQuery).fetchall() 

607 ticketCountRows = [] 

608 ticketCountRows[:] = [dict(list(zip(list(row.keys()), row))) 

609 for row in ticketCountRowsTmp] 

610 totalTickets = 0 

611 for row in ticketCountRows: 

612 totalTickets += row["count"] 

613 elif 'phase_iii_transient_catalogue_ssdr3' in queryWhere: 

614 sqlQuery = """ 

615 select count(*) as count FROM phase_iii_transient_catalogue_ssdr3 p, sherlock_classifications s where s.transient_object_id=p.TransientBucketId and s.matchVerified is null 

616 """ % locals() 

617 ticketCountRowsTmp = self.request.db.execute(sqlQuery).fetchall() 

618 ticketCountRows = [] 

619 ticketCountRows[:] = [dict(list(zip(list(row.keys()), row))) 

620 for row in ticketCountRowsTmp] 

621 totalTickets = 0 

622 for row in ticketCountRows: 

623 totalTickets += row["count"] 

624 else: 

625 ticketCountWhere = queryWhere.replace("marshallWorkflowLocation", "listName").replace( 

626 "alertWorkflowLocation", "listName").replace('classifiedFlag = "1"', 'listName="classified"').replace('snoozed = "1"', 'listName="snoozed"') 

627 sqlQuery = """ 

628 select count from meta_workflow_lists_counts %(ticketCountWhere)s; 

629 """ % locals() 

630 ticketCountRowsTmp = self.request.db.execute(sqlQuery).fetchall() 

631 ticketCountRows = [] 

632 ticketCountRows[:] = [dict(list(zip(list(row.keys()), row))) 

633 for row in ticketCountRowsTmp] 

634 totalTickets = 0 

635 for row in ticketCountRows: 

636 totalTickets += row["count"] 

637 

638 self.log.debug( 

639 'completed the ``_get_total_ticket_count_for_list`` method') 

640 return totalTickets 

641 

642 def _clean_data_for_plain_text_outputs( 

643 self): 

644 """ 

645 *clean data for plain text outputs* 

646 

647 **Return** 

648 

649 - None 

650 

651 """ 

652 self.log.debug( 

653 'completed the ````_clean_data_for_plain_text_outputs`` method') 

654 

655 # ASTROCALC UNIT CONVERTER OBJECT 

656 converter = unit_conversion( 

657 log=self.log 

658 ) 

659 

660 # assoicate the correct column name to mysql database column name 

661 tmpDict = {} 

662 tableColumnNames = collections.OrderedDict( 

663 sorted(tmpDict.items())) 

664 tableColumnNames["masterName"] = "name" 

665 tableColumnNames["observationPriority"] = "priority" 

666 tableColumnNames["raDeg"] = "ra" 

667 tableColumnNames["decDeg"] = "dec" 

668 tableColumnNames["recentClassification"] = "spectral class" 

669 tableColumnNames["classificationPhase"] = "classification phase" 

670 tableColumnNames["classificationWRTMax"] = "classificationWRTMax" 

671 tableColumnNames["classificationDate"] = "classification date" 

672 tableColumnNames["currentMagnitude"] = "latest mag" 

673 tableColumnNames["absolutePeakMagnitude"] = "abs peak mag" 

674 tableColumnNames["best_redshift"] = "z" 

675 tableColumnNames["distanceMpc"] = "mpc" 

676 tableColumnNames["earliestDetection"] = "discovery date" 

677 tableColumnNames["lastNonDetectionDate"] = "last non-detection date" 

678 tableColumnNames["dateAdded"] = "added to marshall" 

679 tableColumnNames["pi_name"] = "PI" 

680 tableColumnNames["pi_email"] = "pi email" 

681 

682 # a list of names for table and csv views 

683 tableColumns = [ 

684 "masterName", 

685 "observationPriority", 

686 "raDeg", 

687 "decDeg", 

688 "recentClassification", 

689 "classificationPhase", 

690 "classificationWRTMax", 

691 "classificationDate", 

692 "currentMagnitude", 

693 "absolutePeakMagnitude", 

694 "best_redshift", 

695 "distanceMpc", 

696 "earliestDetection", 

697 "lastNonDetectionDate", 

698 "dateAdded", 

699 "pi_name" 

700 ] 

701 

702 # convert priorities to words 

703 for obj in self.transientData: 

704 

705 for item in self.transientAkas: 

706 if item["transientBucketId"] == obj["transientBucketId"]: 

707 obj["masterName"] = item["name"] 

708 break 

709 

710 if "marshallWorkflowLocation" in obj: 

711 if obj["marshallWorkflowLocation"] == "following": 

712 for n, w, c in zip([1, 2, 3, 4], ["CRITICAL", "IMPORTANT", "USEFUL", "NONE"], ["green", "yellow", "red", "blue"]): 

713 if obj["observationPriority"] == n: 

714 obj["observationPriority"] = w 

715 break 

716 elif obj["marshallWorkflowLocation"] == "pending observation": 

717 for n, w, c in zip([1, 2, 3], ["HIGH", "MEDIUM", "LOW"], ["green", "yellow", "red"]): 

718 if obj["observationPriority"] == n: 

719 obj["observationPriority"] = w 

720 break 

721 

722 newTransientData = [] 

723 for oldRow in self.transientData: 

724 tmpRow = {} 

725 newRow = collections.OrderedDict(sorted(tmpRow.items())) 

726 

727 for oldName, newName in list(tableColumnNames.items()): 

728 

729 newRow[newName] = oldRow[oldName] 

730 if "decdeg" in oldName.lower(): 

731 

732 raSex = converter.ra_decimal_to_sexegesimal( 

733 ra=float(oldRow["raDeg"]), 

734 delimiter=":" 

735 ) 

736 newRow["ra (sex)"] = raSex 

737 decSex = converter.dec_decimal_to_sexegesimal( 

738 dec=float(oldRow["decDeg"]), 

739 delimiter=":" 

740 ) 

741 newRow["dec (sex)"] = decSex 

742 newTransientData.append(newRow) 

743 

744 self.transientData = newTransientData 

745 

746 self.log.debug( 

747 'completed the ``_clean_data_for_plain_text_outputs`` method') 

748 return None 

749 

750 def _get_associated_transient_history( 

751 self): 

752 """ 

753 *get associated transient history* 

754 """ 

755 self.log.debug( 

756 'completed the ````_get_associated_transient_history`` method') 

757 

758 matchedTransientBucketIds = self.matchedTransientBucketIds 

759 

760 sqlQuery = """ 

761 select * from transients_history_logs where transientBucketId in (%(matchedTransientBucketIds)s) order by dateCreated desc 

762 """ % locals() 

763 

764 objectHistoryTmp = self.request.db.execute(sqlQuery).fetchall() 

765 objectHistory = [] 

766 objectHistory[:] = [dict(list(zip(list(row.keys()), row))) 

767 for row in objectHistoryTmp] 

768 

769 from operator import itemgetter 

770 objectHistory = list(objectHistory) 

771 objectHistory = sorted( 

772 objectHistory, key=itemgetter('dateCreated'), reverse=False) 

773 

774 self.log.debug( 

775 'completed the ``_get_associated_transient_history`` method') 

776 return objectHistory 

777 

778 def _get_associated_transient_crossmatches( 

779 self): 

780 """ 

781 *get associated transient crossmatches* 

782 """ 

783 self.log.debug( 

784 'completed the ````_get_associated_transient_crossmatches`` method') 

785 

786 from astrocalc.coords import unit_conversion 

787 # ASTROCALC UNIT CONVERTER OBJECT 

788 converter = unit_conversion( 

789 log=self.log 

790 ) 

791 

792 matchedTransientBucketIds = self.matchedTransientBucketIds 

793 

794 sqlQuery = """ 

795 select *, t.raDeg, t.decDeg from sherlock_crossmatches t, transientBucket b where b.replacedByRowId = 0 and b.transientBucketId in (%(matchedTransientBucketIds)s) and b.transientBucketId = t.transient_object_id and b.masterIDFlag = 1 and rank is not null order by rank 

796 """ % locals() 

797 

798 crossmatchesTmp = self.request.db.execute(sqlQuery).fetchall() 

799 crossmatches = [] 

800 crossmatches[:] = [dict(list(zip(list(row.keys()), row))) 

801 for row in crossmatchesTmp] 

802 

803 from operator import itemgetter 

804 crossmatches = list(crossmatches) 

805 crossmatches = sorted( 

806 crossmatches, key=itemgetter('rank'), reverse=False) 

807 

808 for c in crossmatches: 

809 c["object_link"] = None 

810 objectName = urllib.parse.quote(c["catalogue_object_id"]) 

811 if "ned" in c["catalogue_table_name"].lower(): 

812 c[ 

813 "object_link"] = "https://ned.ipac.caltech.edu/cgi-bin/objsearch?objname=%(objectName)s&extend=no&hconst=73&omegam=0.27&omegav=0.73&corr_z=1&out_csys=Equatorial&out_equinox=J2000.0&obj_sort=RA+or+Longitude&of=pre_text&zv_breaker=30000.0&list_limit=5&img_stamp=YES" % locals() 

814 elif "sdss" in c["catalogue_table_name"].lower(): 

815 c[ 

816 "object_link"] = "http://skyserver.sdss.org/dr12/en/tools/explore/Summary.aspx?id=%(objectName)s" % locals() 

817 ra = converter.ra_decimal_to_sexegesimal( 

818 ra=c["raDeg"], 

819 delimiter="" 

820 ) 

821 dec = converter.dec_decimal_to_sexegesimal( 

822 dec=c["decDeg"], 

823 delimiter="" 

824 ) 

825 c["catalogue_object_id"] = "SDSS J" + ra[0:9] + dec[0:9] 

826 objectName = urllib.parse.quote(c["catalogue_object_id"]) 

827 elif "milliquas" in c["catalogue_table_name"].lower(): 

828 c[ 

829 "object_link"] = "https://heasarc.gsfc.nasa.gov/db-perl/W3Browse/w3query.pl?bparam_name=%(objectName)s&navtrail=%%3Ca+class%%3D%%27navpast%%27+href%%3D%%27https%%3A%%2F%%2Fheasarc.gsfc.nasa.gov%%2FW3Browse%%2Fall%%2Fmilliquas.html%%27%%3E+Choose+Tables%%3C%%2Fa%%3E+%%3E+%%3Ca+class%%3D%%27navpast%%27+href%%3D%%27%%2Fcgi-bin%%2FW3Browse%%2Fw3table.pl%%3FREAL_REMOTE_HOST%%3D143.117.37.81%%26tablehead%%3Dname%%253Dmilliquas%%26Action%%3DMore%%2BOptions%%26REAL_REMOTE_HOST%%3D143%%252E117%%252E37%%252E81%%26Equinox%%3D2000%%26Action%%3DMore%%2BOptions%%26sortby%%3Dpriority%%26ResultMax%%3D1000%%26maxpriority%%3D99%%26Coordinates%%3DEquatorial%%26tablehead%%3Dname%%253Dmilliquas%%26Action%%3DParameter%%2BSearch%%27%%3EParameter+Search%%3C%%2Fa%%3E&popupFrom=Query+Results&tablehead=name%%3Dheasarc_milliquas%%26description%%3DMillion+Quasars+Catalog+%%28MILLIQUAS%%29%%2C+Version+4.5+%%2810+May+2015%%29%%26url%%3Dhttp%%3A%%2F%%2Fheasarc.gsfc.nasa.gov%%2FW3Browse%%2Fgalaxy-catalog%%2Fmilliquas.html%%26archive%%3DN%%26radius%%3D1%%26mission%%3DGALAXY+CATALOG%%26priority%%3D5%%26tabletype%%3DObject&dummy=Examples+of+query+constraints%%3A&varon=name&bparam_name%%3A%%3Aunit=+&bparam_name%%3A%%3Aformat=char25&varon=ra&bparam_ra=&bparam_ra%%3A%%3Aunit=degree&bparam_ra%%3A%%3Aformat=float8%%3A.5f&varon=dec&bparam_dec=&bparam_dec%%3A%%3Aunit=degree&bparam_dec%%3A%%3Aformat=float8%%3A.5f&varon=bmag&bparam_bmag=&bparam_bmag%%3A%%3Aunit=mag&bparam_bmag%%3A%%3Aformat=float8%%3A4.1f&varon=rmag&bparam_rmag=&bparam_rmag%%3A%%3Aunit=mag&bparam_rmag%%3A%%3Aformat=float8%%3A4.1f&varon=redshift&bparam_redshift=&bparam_redshift%%3A%%3Aunit=+&bparam_redshift%%3A%%3Aformat=float8%%3A6.3f&varon=radio_name&bparam_radio_name=&bparam_radio_name%%3A%%3Aunit=+&bparam_radio_name%%3A%%3Aformat=char22&varon=xray_name&bparam_xray_name=&bparam_xray_name%%3A%%3Aunit=+&bparam_xray_name%%3A%%3Aformat=char22&bparam_lii=&bparam_lii%%3A%%3Aunit=degree&bparam_lii%%3A%%3Aformat=float8%%3A.5f&bparam_bii=&bparam_bii%%3A%%3Aunit=degree&bparam_bii%%3A%%3Aformat=float8%%3A.5f&bparam_broad_type=&bparam_broad_type%%3A%%3Aunit=+&bparam_broad_type%%3A%%3Aformat=char4&bparam_optical_flag=&bparam_optical_flag%%3A%%3Aunit=+&bparam_optical_flag%%3A%%3Aformat=char3&bparam_red_psf_flag=&bparam_red_psf_flag%%3A%%3Aunit=+&bparam_red_psf_flag%%3A%%3Aformat=char1&bparam_blue_psf_flag=&bparam_blue_psf_flag%%3A%%3Aunit=+&bparam_blue_psf_flag%%3A%%3Aformat=char1&bparam_ref_name=&bparam_ref_name%%3A%%3Aunit=+&bparam_ref_name%%3A%%3Aformat=char6&bparam_ref_redshift=&bparam_ref_redshift%%3A%%3Aunit=+&bparam_ref_redshift%%3A%%3Aformat=char6&bparam_qso_prob=&bparam_qso_prob%%3A%%3Aunit=percent&bparam_qso_prob%%3A%%3Aformat=int2%%3A3d&bparam_alt_name_1=&bparam_alt_name_1%%3A%%3Aunit=+&bparam_alt_name_1%%3A%%3Aformat=char22&bparam_alt_name_2=&bparam_alt_name_2%%3A%%3Aunit=+&bparam_alt_name_2%%3A%%3Aformat=char22&Entry=&Coordinates=J2000&Radius=Default&Radius_unit=arcsec&NR=CheckCaches%%2FGRB%%2FSIMBAD%%2FNED&Time=&ResultMax=10&displaymode=Display&Action=Start+Search&table=heasarc_milliquas" % locals() 

830 elif ("ps1" not in c["catalogue_table_name"].lower()) and ("ritter" not in c["catalogue_table_name"].lower()) and ("down" not in c["catalogue_table_name"].lower()) and ("guide_star" not in c["catalogue_table_name"].lower()) and ("kepler" not in c["catalogue_table_name"].lower()): 

831 c[ 

832 "object_link"] = "http://simbad.u-strasbg.fr/simbad/sim-id?Ident=%(objectName)s&NbIdent=1&Radius=2&Radius.unit=arcmin&submit=submit+id" % locals() 

833 

834 c["best_mag"] = None 

835 c["best_mag_error"] = None 

836 c["best_mag_filter"] = None 

837 filters = ["R", "V", "B", "I", "J", "G", "H", "K", "U", 

838 "_r", "_g", "_i", "_g", "_z", "_y", "_u", "unkMag"] 

839 for f in filters: 

840 if c[f] and not c["best_mag"]: 

841 c["best_mag"] = c[f] 

842 c["best_mag_error"] = c[f + "Err"] 

843 c["best_mag_filter"] = f.replace( 

844 "_", "").replace("Mag", "") 

845 

846 self.log.debug( 

847 'completed the ``_get_associated_transient_crossmatches`` method') 

848 return crossmatches 

849 

850 # xt-class-method