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*Generate the standard multi-survey lightcurve plots for the marshall transients* 

5 

6:Author: 

7 David Young 

8""" 

9from __future__ import print_function 

10from builtins import str 

11from builtins import zip 

12from builtins import range 

13from builtins import object 

14import sys 

15import os 

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

17from fundamentals import tools 

18from fundamentals import fmultiprocess 

19from fundamentals.mysql import readquery, writequery 

20from fundamentals.mysql import database 

21from astrocalc.times import conversions, now 

22import numpy as np 

23# SUPPRESS MATPLOTLIB WARNINGS 

24import warnings 

25warnings.filterwarnings("ignore") 

26import matplotlib as mpl 

27from matplotlib import dates 

28import matplotlib.pyplot as plt 

29import matplotlib.ticker as ticker 

30import matplotlib.ticker as mtick 

31from matplotlib.backends.backend_pdf import PdfPages 

32import math 

33 

34from numpy.polynomial.chebyshev import chebfit, chebval 

35 

36 

37class marshall_lightcurves(object): 

38 """ 

39 *The worker class for the marshall_lightcurves module* 

40 

41 **Key Arguments** 

42 

43 - ``log`` -- logger 

44 - ``settings`` -- the settings dictionary 

45 - ``dbConn`` -- the database connection for the mrshall 

46 - ``transientBucketIds`` -- the transientBucketId(s) requiring lightcurves to be regenerated. (int or list) 

47 

48 

49 **Usage** 

50 

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

52 

53 To initiate a marshall_lightcurves object, use the following: 

54 

55 ```python 

56 from marshallEngine.lightcurves import marshall_lightcurves 

57 lc = marshall_lightcurves( 

58 log=log, 

59 dbConn=dbConn, 

60 settings=settings, 

61 transientBucketIds=[28421489, 28121353, 4637952, 27409808] 

62 ) 

63 lc.plot() 

64 ``` 

65 

66 """ 

67 

68 def __init__( 

69 self, 

70 log, 

71 dbConn, 

72 settings=False, 

73 transientBucketIds=[] 

74 ): 

75 self.log = log 

76 log.debug("instansiating a new 'marshall_lightcurves' object") 

77 self.settings = settings 

78 self.dbConn = dbConn 

79 self.transientBucketIds = transientBucketIds 

80 # xt-self-arg-tmpx 

81 

82 # CONVERT TRANSIENTBUCKETIDS TO LIST 

83 if not isinstance(self.transientBucketIds, list): 

84 self.transientBucketIds = [self.transientBucketIds] 

85 

86 return None 

87 

88 def _select_data_for_transient( 

89 self, 

90 transientBucketId): 

91 """*get the transient lightcurve data from the marshall database* 

92 

93 **Key Arguments** 

94 

95 - ``transientBucketId`` -- the transientBucketId of source to get data for 

96 

97 """ 

98 self.log.debug('starting the ``_select_data_for_transient`` method') 

99 

100 # SELECT THE DATA REQUIRED FOR THIS LIGHTCURVE PLOT 

101 sqlQuery = """ 

102 SELECT 

103 transientBucketId, 

104 survey, 

105 magnitude, 

106 magnitudeError, 

107 observationDate, 

108 observationMJD, 

109 IFNULL(filter, '?') as filter, 

110 name, 

111 limitingMag, 

112 concat(ROUND(observationMJD, 2), SUBSTRING(filter, 1, 1)) as uniqueConstraint, 

113 concat(ROUND(observationMJD, 0), SUBSTRING(filter, 1, 1)) as limitConstraint 

114 FROM 

115 transientBucket 

116 WHERE 

117 replacedByRowId = 0 

118 AND transientBucketId = %(transientBucketId)s 

119 AND magnitude IS NOT NULL 

120 -- AND filter is not null 

121 ORDER BY uniqueConstraint ASC, magnitudeError desc, magnitude asc 

122 """ % locals() 

123 transientData = readquery( 

124 sqlQuery=sqlQuery, 

125 dbConn=self.dbConn, 

126 log=self.log 

127 ) 

128 

129 theseMags = [] 

130 theseMags[:] = [a 

131 for a in transientData if a["limitingMag"] == 0] 

132 

133 # CLIP OUTLIERS 

134 if len(theseMags) > 4: 

135 allmags = [] 

136 allmags[:] = [a["magnitude"] for a in theseMags] 

137 mean = np.mean(allmags) 

138 std = np.std(allmags) 

139 

140 if std > 0.1: 

141 allmags[:] = [a for a in transientData if (abs( 

142 a["magnitude"] - mean) < 2 * std) or a["limitingMag"] == 1] 

143 transientData = allmags 

144 

145 # NO DATA? 

146 if len(transientData) == 0: 

147 return False, False, False 

148 

149 # SPLIT DATA BY FILTER - MAGNITUDES AND LIMITS 

150 filterList = [] 

151 filterList[:] = set([r["filter"][0] for r in transientData]) 

152 

153 dataset = {} 

154 flatdata = {"mag": [], "mjd": []} 

155 flatLimits = {"mag": [], "mjd": []} 

156 for f in filterList: 

157 mag = [] 

158 magErr = [] 

159 magMjd = [] 

160 limit = [] 

161 limitMjd = [] 

162 magNoErr = [] 

163 magNoErrMjd = [] 

164 magNoErrFudge = [] 

165 catch = [] 

166 limitCatcher = {} 

167 for r in transientData: 

168 if r["filter"][0] == f and r["uniqueConstraint"] not in catch: 

169 if r["limitingMag"] == 0 and r["magnitudeError"]: 

170 mag.append(r["magnitude"]) 

171 magErr.append(r["magnitudeError"]) 

172 magMjd.append(r["observationMJD"]) 

173 flatdata["mag"].append(r["magnitude"]) 

174 flatdata["mjd"].append(r["observationMJD"]) 

175 catch.append(r["uniqueConstraint"]) 

176 elif r["limitingMag"] == 0 and not r["magnitudeError"]: 

177 magNoErr.append(r["magnitude"]) 

178 magNoErrFudge.append(0.3) 

179 magNoErrMjd.append(r["observationMJD"]) 

180 flatdata["mag"].append(r["magnitude"]) 

181 flatdata["mjd"].append(r["observationMJD"]) 

182 catch.append(r["uniqueConstraint"]) 

183 elif r["limitConstraint"] not in limitCatcher: 

184 limitCatcher[r["limitConstraint"]] = [ 

185 r["magnitude"], r["observationMJD"]] 

186 elif limitCatcher[r["limitConstraint"]][0] < r["magnitude"]: 

187 limitCatcher[r["limitConstraint"]] = [ 

188 r["magnitude"], r["observationMJD"]] 

189 

190 for k, v in list(limitCatcher.items()): 

191 limit.append(v[0]) 

192 limitMjd.append(v[1]) 

193 flatLimits["mag"].append(v[0]) 

194 flatLimits["mjd"].append(v[1]) 

195 

196 dataset[f] = { 

197 "limit": limit, 

198 "limitMjd": limitMjd, 

199 "mag": mag, 

200 "magErr": magErr, 

201 "magMjd": magMjd, 

202 "magNoErr": magNoErr, 

203 "magNoErrFudge": magNoErrFudge, 

204 "magNoErrMjd": magNoErrMjd 

205 } 

206 

207 if len(flatdata["mag"]) == 0: 

208 return False, False, False 

209 

210 self.log.debug('completed the ``_select_data_for_transient`` method') 

211 return dataset, flatdata, flatLimits 

212 

213 def _create_lightcurve_plot_file( 

214 self, 

215 dataset, 

216 flatdata, 

217 flatLimits, 

218 objectNames, 

219 saveLocation, 

220 saveFileName): 

221 """*Generate the lightcurve and save to file* 

222 

223 **Key Arguments** 

224 

225 - ``log`` -- logger 

226 - ``dataset`` -- the observational dataset split into filters (and then mags, limits etc) 

227 - ``flatdata`` -- a flattened dataset to determine current magnitude 

228 - ``flatLimits`` -- a flattened dataset of non-detection limits 

229 - ``objectNames`` -- a single name or a list of names 

230 - ``saveLocation`` -- the folder to save the plot file to 

231 - ``saveFileName`` -- the filename to give the plot file (without extension) 

232 

233 

234 **Return** 

235 

236 - ``filepath`` -- path to the lightcurve file 

237 - ``currentMag`` -- a prediction of the current magnitude if there is enough recent data 

238 - ``gradient`` -- a prediction of the gradient of recent data (on rise or decline?) 

239 

240 """ 

241 self.log.debug('starting the ``_create_lightcurve_plot_file`` method') 

242 

243 # CONVERTER TO CONVERT MJD TO DATE 

244 converter = conversions( 

245 log=self.log 

246 ) 

247 

248 # INITIATE THE PLOT FIGURE - SQUARE 

249 fig = plt.figure( 

250 num=None, 

251 figsize=(10, 10), 

252 dpi=100, 

253 facecolor=None, 

254 edgecolor=None, 

255 frameon=True) 

256 ax = fig.add_subplot(1, 1, 1) 

257 

258 # TICK LABEL SIZE 

259 mpl.rc('ytick', labelsize=25) 

260 mpl.rc('xtick', labelsize=25) 

261 mpl.rcParams.update({'font.size': 25}) 

262 

263 # INITIAL RESTRICTIONS 

264 currentMag = -9999 

265 gradient = -9999 

266 

267 # WHAT IS TODAY MJD (FIR CURRENT MAG ESTIMATE) 

268 todayMjd = now( 

269 log=self.log 

270 ).get_mjd() 

271 

272 # MAKE ARRAYS OF TIME AND MAG FOR PLOTS 

273 bigTimeArray, bigMagArray = np.array( 

274 flatdata["mjd"]), np.array(flatdata["mag"]) 

275 # SORT TWO LIST BASED ON FIRST 

276 bigTimeArray, bigMagArray = zip( 

277 *[(x, y) for x, y in sorted(zip(bigTimeArray, bigMagArray))]) 

278 

279 # BIN DATA FOR POLYNOMIALS 

280 binData = True 

281 if binData is True: 

282 distinctMjds = {} 

283 for mjd, mag in zip(bigTimeArray, bigMagArray): 

284 # DICT KEY IS THE UNIQUE INTEGER MJD 

285 key = str(int(math.floor(mjd / 1.0))) 

286 # FIRST DATA POINT OF THE NIGHTS? CREATE NEW DATA SET 

287 if key not in distinctMjds: 

288 distinctMjds[key] = { 

289 "mjds": [mjd], 

290 "mags": [mag] 

291 } 

292 # OR NOT THE FIRST? APPEND TO ALREADY CREATED LIST 

293 else: 

294 distinctMjds[key]["mjds"].append(mjd) 

295 distinctMjds[key]["mags"].append(mag) 

296 

297 # ALL DATA NOW IN MJD SUBSETS. SO FOR EACH SUBSET (I.E. INDIVIDUAL 

298 # NIGHTS) ... 

299 summedMagnitudes = { 

300 'mjds': [], 

301 'mags': [] 

302 } 

303 for k, v in list(distinctMjds.items()): 

304 # GIVE ME THE MEAN MJD 

305 meanMjd = sum(v["mjds"]) / len(v["mjds"]) 

306 summedMagnitudes["mjds"].append(meanMjd) 

307 # GIVE ME THE MEAN MAG 

308 meanMag = sum(v["mags"]) / len(v["mags"]) 

309 summedMagnitudes["mags"].append(meanMag) 

310 

311 bigTimeArray = summedMagnitudes["mjds"] 

312 bigMagArray = summedMagnitudes["mags"] 

313 

314 bigTimeArray = np.array(bigTimeArray) 

315 bigMagArray = np.array(bigMagArray) 

316 

317 # DETERMINE SENSIBLE AXIS LIMITS FROM FLATTENED DATA 

318 # LIMITS HERE ARE LOWER AND UPPER MJDS FOR X-AXIS 

319 xLowerLimit = bigTimeArray.min() 

320 xUpperLimit = bigTimeArray.max() 

321 latestTime = xUpperLimit 

322 xBorder = math.fabs((xUpperLimit - xLowerLimit)) * 0.1 

323 if xBorder < 5: 

324 xBorder = 5. 

325 xLowerLimit -= xBorder 

326 xUpperLimit += xBorder 

327 fixedXUpperLimit = xUpperLimit 

328 timeRange = xUpperLimit - xLowerLimit 

329 

330 # POLYNOMIAL CONSTAINTS USING COMBINED DATASETS 

331 # POLYNOMIAL/LINEAR SETTINGS 

332 # SETTINGS FILE 

333 polyOrder = 5 

334 # EITHER USE DATA IN THESE LAST NUMBER OF DAYS OR ... 

335 lastNumDays = 10. 

336 # ... IF NOT ENOUGH DATA USE THE LAST NUMBER OF DATA POINTS 

337 predictCurrentMag = True 

338 lastNumDataPoints = 3 

339 numAnchors = 3 

340 anchorSeparation = 70 

341 latestMag = bigMagArray[0] 

342 anchorPointMag = latestMag + 0.5 

343 polyTimeArray, polyMagArray = [], [] 

344 

345 # QUIT IF NOT ENOUGH DATA FOR POLYNOMIAL 

346 if len(bigTimeArray) <= lastNumDataPoints or timeRange < 3.: 

347 predictCurrentMag = False 

348 

349 if max(bigTimeArray) < todayMjd - 120: 

350 predictCurrentMag = False 

351 

352 if predictCurrentMag: 

353 # USE ONLY THE LAST N DAYS OF DATA FOR LINEAR FIT 

354 mask = np.where(bigTimeArray - 

355 bigTimeArray.max() < -lastNumDays, False, True) 

356 

357 # DETERMINE GRADIENT OF SLOPE FROM LAST `LASTNUMDAYS` DAYS 

358 linearTimeArray = bigTimeArray[mask] 

359 linearMagArray = bigMagArray[mask] 

360 # FIT AND PLOT THE POLYNOMIAL ASSOCSIATED WITH ALL DATA SETS 

361 thisLinear = chebfit(linearTimeArray, linearMagArray, 1) 

362 gradient = thisLinear[1] 

363 

364 firstAnchorPointTime = anchorSeparation + latestTime 

365 

366 # CREATE THE ARRAY OF DATA USED TO GERNERATE THE POLYNOMIAL 

367 polyTimeArray = bigTimeArray 

368 polyMagArray = bigMagArray 

369 

370 # ANCHOR THE POLYNOMIAL IN THE FUTURE SO THAT ALL PREDICTED LIGHTCURVES 

371 # EVENTUALLY FADE TO NOTHING 

372 extraTimes = np.arange(0, numAnchors) * \ 

373 anchorSeparation + firstAnchorPointTime 

374 extraMags = np.ones(numAnchors) * anchorPointMag 

375 polyTimeArray = np.append(polyTimeArray, extraTimes) 

376 polyMagArray = np.append(polyMagArray, extraMags) 

377 

378 # POLYNOMIAL LIMTIS 

379 xPolyLowerLimit = min(polyTimeArray) - 2.0 

380 xPolyUpperLimit = max(polyTimeArray) + 2.0 

381 

382 # SET AXIS LIMITS 

383 xUpperLimit = 5 

384 yLowerLimit = min(bigMagArray) - 0.3 

385 yUpperLimit = max(bigMagArray) + 0.5 

386 yBorder = math.fabs((yUpperLimit - yLowerLimit)) * 0.1 

387 yLowerLimit -= yBorder 

388 yUpperLimit += yBorder 

389 

390 # EXTEND LOWER X-LIMIT FOR NON-DETECTIONS 

391 xLowerTmp = xLowerLimit 

392 for t, m in zip(flatLimits["mjd"], flatLimits["mag"]): 

393 if m > yLowerLimit and t < xLowerTmp + 2 and t > xLowerLimit - 40: 

394 xLowerTmp = t - 2 

395 xLowerLimit = xLowerTmp 

396 

397 if predictCurrentMag: 

398 thisPoly = chebfit(polyTimeArray, polyMagArray, polyOrder) 

399 # FLATTEN INTO A FUNCTION TO MAKE PLOTTING EASIER 

400 xData = np.arange(xPolyLowerLimit, todayMjd + 50, 1) 

401 flatLinear = chebval(xData, thisLinear) 

402 flatPoly = chebval(xData, thisPoly) 

403 plt.plot(xData, flatPoly, label="poly") 

404 plt.plot(xData, flatLinear, label="linear") 

405 

406 # PREDICT A CURRENT MAGNITUDE FROM THE PLOT 

407 

408 currentMag = chebval(todayMjd, thisPoly) 

409 self.log.debug( 

410 'currentMag: %(currentMag)0.2f, m=%(gradient)s' % locals()) 

411 

412 ls = "*g" % locals() 

413 currentMagArray = np.array([currentMag]) 

414 nowArray = np.array([todayMjd]) 

415 line = ax.plot(nowArray, currentMagArray, 

416 ls, label="current estimate") 

417 

418 lineExtras = ax.plot(extraTimes, extraMags, "+") 

419 

420 # SET THE AXES / VIEWPORT FOR THE PLOT 

421 # if currentMag < yLowerLimit: 

422 # yLowerLimit = currentMag - 0.4 

423 

424 if currentMag > 23: 

425 currentMag = -9999. 

426 

427 plt.clf() 

428 plt.cla() 

429 ax = fig.add_subplot(1, 1, 1) 

430 # print(currentMag) 

431 # print(bigTimeArray) 

432 # print(bigMagArray) 

433 

434 # PLOT DATA VIA FILTER. MAGS AND LIMITS 

435 filterColor = { 

436 "r": "#29a329", 

437 "g": "#268bd2", 

438 "G": "#859900", 

439 "o": "#cb4b16", 

440 "c": "#2aa198", 

441 "U": "#6c71c4", 

442 "B": "blue", 

443 "V": "#008000", 

444 "R": "#e67300", 

445 "I": "#dc322f", 

446 "w": "#cc2900", 

447 "y": "#ff6666", 

448 "z": "#990000", 

449 } 

450 i = 0 

451 handles = [] 

452 handlesAdded = [] 

453 for k, v in list(dataset.items()): 

454 mag = v["mag"] 

455 magErr = v["magErr"] 

456 magMjd = v["magMjd"] 

457 limit = v["limit"] 

458 limitMjd = v["limitMjd"] 

459 magNoErr = v["magNoErr"] 

460 magNoErrMjd = v["magNoErrMjd"] 

461 magNoErrFudge = v["magNoErrFudge"] 

462 

463 if k in filterColor: 

464 color = filterColor[k] 

465 else: 

466 color = "black" 

467 

468 if len(limit): 

469 for l, m in zip(limit, limitMjd): 

470 plt.text(m, l, u"\u21A7", fontname='STIXGeneral', 

471 size=30, va='top', ha='center', clip_on=True, color=color, zorder=1) 

472 if len(magNoErr): 

473 theseMags = ax.errorbar(magNoErrMjd, magNoErr, yerr=magNoErrFudge, color=color, fmt='o', mfc=color, 

474 mec=color, zorder=2, ms=12., alpha=0.8, linewidth=1.2, label=k, capsize=0) 

475 theseMags[-1][0].set_linestyle('--') 

476 

477 if len(mag): 

478 theseMags = ax.errorbar(magMjd, mag, yerr=magErr, color=color, fmt='o', mfc=color, 

479 mec=color, zorder=3, ms=12., alpha=0.8, linewidth=1.2, label=k, capsize=10) 

480 

481 if not len(mag): 

482 theseMags = ax.errorbar([-500], [20], yerr=[0.2], color=color, fmt='o', mfc=color, 

483 mec=color, zorder=3, ms=12., alpha=0.8, linewidth=1.2, label=k, capsize=10) 

484 

485 if k not in handlesAdded: 

486 handles.append(theseMags) 

487 handlesAdded.append(k) 

488 

489 # ADD LEGEND 

490 plt.legend(handles=handles, prop={ 

491 'size': 13.5}, bbox_to_anchor=(1., 1.25), loc=0, borderaxespad=0., ncol=18, scatterpoints=1) 

492 

493 # RHS AXIS TICKS 

494 plt.setp(ax.xaxis.get_majorticklabels(), 

495 rotation=45, horizontalalignment='right') 

496 ax.xaxis.set_major_formatter(mtick.FormatStrFormatter('%5.0f')) 

497 

498 # CHANGE PLOT TO FIXED TIME 

499 # SETUP THE AXES 

500 xUpperLimit = fixedXUpperLimit 

501 ax.set_xlabel('MJD', labelpad=20, fontsize=30) 

502 ax.set_ylabel('Magnitude', labelpad=20, fontsize=30) 

503 ax.set_title('') 

504 ax.set_xlim([xLowerLimit, xUpperLimit]) 

505 ax.set_ylim([yUpperLimit, yLowerLimit]) 

506 ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%d')) 

507 

508 # GENERATE UT DATE AXIS FOR TOP OF PLOT 

509 lower, upper = ax.get_xlim() 

510 utLower = converter.mjd_to_ut_datetime(mjd=lower, datetimeObject=True) 

511 utUpper = converter.mjd_to_ut_datetime(mjd=upper, datetimeObject=True) 

512 ax3 = ax.twiny() 

513 ax3.set_xlim([utLower, utUpper]) 

514 ax3.grid(True) 

515 ax.xaxis.grid(False) 

516 plt.setp(ax3.xaxis.get_majorticklabels(), 

517 rotation=45, horizontalalignment='left', fontsize=14) 

518 ax3.xaxis.set_major_formatter(dates.DateFormatter('%b %d, %y')) 

519 

520 # Y TICK FORMAT 

521 y_formatter = mpl.ticker.FormatStrFormatter("%2.1f") 

522 ax.yaxis.set_major_formatter(y_formatter) 

523 

524 # PRINT CURRENT MAG AS SANITY CHECK 

525 # fig.text(0.1, 1.02, currentMag, ha="left", fontsize=40) 

526 

527 # RECURSIVELY CREATE MISSING DIRECTORIES 

528 if not os.path.exists(saveLocation): 

529 try: 

530 os.makedirs(saveLocation) 

531 except: 

532 pass 

533 # SAVE THE PLOT 

534 filepath = """%(saveLocation)s%(saveFileName)s.png""" % locals() 

535 plt.savefig(filepath, format='PNG', bbox_inches='tight', transparent=False, 

536 pad_inches=0.4) 

537 # plt.show() 

538 plt.clf() # clear figure 

539 plt.close() 

540 

541 # TEST THAT PLOT FILE HAS ACTUALLY BEEN GENERATED 

542 try: 

543 with open(filepath): 

544 pass 

545 fileExists = True 

546 except IOError: 

547 raise IOError( 

548 "the path --pathToFile-- %s does not exist on this machine" % 

549 (filepath,)) 

550 filepath = False 

551 

552 self.log.debug('completed the ``_create_lightcurve_plot_file`` method') 

553 

554 return filepath, currentMag, gradient 

555 

556 def plot( 

557 self): 

558 """*generate a batch of lightcurves using multiprocessing given their transientBucketIds* 

559 

560 **Return** 

561 

562 - ``filepath`` -- path to the last generated plot file 

563 

564 

565 **Usage** 

566 

567 ```python 

568 from marshallEngine.lightcurves import marshall_lightcurves 

569 lc = marshall_lightcurves( 

570 log=log, 

571 dbConn=dbConn, 

572 settings=settings, 

573 transientBucketIds=[28421489, 28121353, 4637952, 27409808] 

574 ) 

575 lc.plot() 

576 ``` 

577 

578 """ 

579 self.log.debug('starting the ``plot`` method') 

580 

581 # DEFINE AN INPUT ARRAY 

582 total = len(self.transientBucketIds) 

583 

584 thisDict = {"database settings": self.settings["database settings"]} 

585 

586 if total: 

587 print("updating lightcurves for %(total)s transients" % locals()) 

588 print() 

589 

590 # USE IF ISSUES IN _plot_one FUNCTION 

591 # for transientBucketId in self.transientBucketIds: 

592 # _plot_one( 

593 # transientBucketId=transientBucketId, 

594 # log=self.log, 

595 # settings=self.settings 

596 # ) 

597 

598 results = fmultiprocess(log=self.log, function=_plot_one, 

599 inputArray=self.transientBucketIds, poolSize=False, timeout=3600, settings=self.settings) 

600 

601 sqlQuery = "" 

602 updatedTransientBucketIds = [] 

603 for t, r in zip(self.transientBucketIds, results): 

604 if not r[0]: 

605 # LIGHTCURVE NOT GENERATED 

606 continue 

607 updatedTransientBucketIds.append(t) 

608 filepath = r[0] 

609 currentMagnitude = r[1] 

610 gradient = r[2] 

611 sqlQuery += """update transientBucketSummaries set currentMagnitudeEstimate = %(currentMagnitude)s, currentMagnitudeEstimateUpdated = NOW(), recentSlopeOfLightcurve = %(gradient)s where transientBucketId = %(t)s; 

612 """ % locals() 

613 ids = [] 

614 ids[:] = [str(i) for i in updatedTransientBucketIds] 

615 updatedTransientBucketIds = (",").join(ids) 

616 sqlQuery += "update pesstoObjects set master_pessto_lightcurve = 1 where transientBucketId in (%(updatedTransientBucketIds)s);" % locals( 

617 ) 

618 

619 if len(updatedTransientBucketIds): 

620 writequery( 

621 log=self.log, 

622 sqlQuery=sqlQuery, 

623 dbConn=self.dbConn, 

624 ) 

625 else: 

626 filepath = False 

627 

628 self.log.debug('completed the ``plot`` method') 

629 

630 return filepath 

631 

632 

633def _plot_one( 

634 transientBucketId, 

635 log, 

636 settings): 

637 """*plot a single transeint lightcurve* 

638 

639 **Key Arguments** 

640 

641 - ``transientBucketId`` -- the id of the single transient to plot. 

642 - ``settings`` -- dictionary of settings 

643 - ``dbConn`` -- marshall database connection 

644 

645 

646 **Return** 

647 

648 - ``filepath`` -- path to the plot file 

649 - ``currentMag`` -- an estimate of the current magnitude (from slope of recent LC). -9999 if inaccurate. 

650 - ``gradient`` -- gradient of slope of the recent LC. -9999 if inaccurate. 

651 

652 """ 

653 log.debug('starting the ``_plot_one`` method') 

654 

655 # MULTIPROCESSING NEEDS ONE CONNECTION PERPROCESS 

656 sys.stdout.write("\x1b[1A\x1b[2K") 

657 print("updating LC for transient %(transientBucketId)s" % locals()) 

658 dbConn = database( 

659 log=log, 

660 dbSettings=settings["database settings"] 

661 ).connect() 

662 

663 # LC OBJECT 

664 lc = marshall_lightcurves( 

665 log=log, 

666 dbConn=dbConn, 

667 settings=settings, 

668 transientBucketIds=transientBucketId 

669 ) 

670 

671 cacheFolder = settings[ 

672 "cache-directory"] + "/transients/" 

673 saveLocation = """%(cacheFolder)s/%(transientBucketId)s/""" % locals() 

674 

675 # SELECT DATA AND PLOT THE SOURCE 

676 dataset, flatdata, flatLimits = lc._select_data_for_transient( 

677 transientBucketId) 

678 if dataset: 

679 filepath, currentMag, gradient = lc._create_lightcurve_plot_file( 

680 dataset=dataset, 

681 flatdata=flatdata, 

682 flatLimits=flatLimits, 

683 objectNames="test object", 

684 saveLocation=saveLocation, 

685 saveFileName="master_lightcurve" 

686 ) 

687 else: 

688 return False, False, False 

689 

690 log.debug('completed the ``_plot_one`` method') 

691 return filepath, currentMag, gradient 

692 

693 # use the tab-trigger below for new method 

694 # xt-class-method