exovetter 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
exovetter/vetters.py CHANGED
@@ -4,6 +4,7 @@ import pprint
4
4
  from abc import ABC, abstractmethod
5
5
 
6
6
  import astropy.units as u
7
+ import numpy as np
7
8
 
8
9
  from exovetter.centroid import centroid as cent
9
10
  from exovetter import transit_coverage
@@ -17,10 +18,15 @@ from exovetter import utils
17
18
  from exovetter import const
18
19
  from exovetter import model
19
20
  from exovetter import viz_transits
21
+ from exovetter import leo
20
22
 
23
+ __all__ = ['BaseVetter', 'ModShift', 'Lpp', 'OddEven',
24
+ 'TransitPhaseCoverage', 'Sweet', 'Centroid',
25
+ 'VizTransits', 'LeoVetter']
21
26
 
22
27
  class BaseVetter(ABC):
23
28
  """Base class for vetters.
29
+
24
30
  Each vetting test should be a subclass of this class.
25
31
 
26
32
  Parameters
@@ -37,7 +43,7 @@ class BaseVetter(ABC):
37
43
  self.metrics = None
38
44
 
39
45
  def name(self):
40
- name = str(type(self)).split('.')[-1][:-2]
46
+ name = str(type(self)).split(".")[-1][:-2]
41
47
  return name
42
48
 
43
49
  def __str__(self):
@@ -87,15 +93,48 @@ class BaseVetter(ABC):
87
93
  class ModShift(BaseVetter):
88
94
  """Modshift vetter."""
89
95
 
90
- def __init__(self, lc_name="flux", **kwargs):
96
+ def __init__(self, lc_name="flux"):
91
97
  """
92
98
  Parameters
93
99
  ----------
94
100
  lc_name : str
95
101
  Name of the flux array in the ``lightkurve`` object.
102
+
103
+ Attributes
104
+ ----------
105
+ time : array
106
+ Time values of the TCE, populated by :meth:`run`.
107
+
108
+ lc_name : str
109
+ Input ``lc_name``.
110
+
111
+ flux : array
112
+ Flux values of the TCE, populated by :meth:`run`.
113
+
114
+ period_days : float
115
+ period of the TCE in days, populated by :meth:`run`.
116
+
117
+ epoch_days : float
118
+ epoch of the TCE in days, populated by :meth:`run`.
119
+
120
+ duration_hrs : float
121
+ transit duration of the TCE in hours, populated by :meth:`run`.
122
+
123
+ box : astropy.units.Quantity object
124
+ Flux from boxcar model of the TCE, populated by :meth:`run`.
125
+
126
+ metrics : dict
127
+ modshift result dictionary populated by :meth:`run`.
96
128
  """
97
- self.metrics = None
129
+
98
130
  self.lc_name = lc_name
131
+ self.time = None
132
+ self.flux = None
133
+ self.period_days = None
134
+ self.epoch_days = None
135
+ self.duration_hrs = None
136
+ self.box = None
137
+ self.metrics = None
99
138
 
100
139
  def run(self, tce, lightcurve, plot=False):
101
140
  """
@@ -107,12 +146,16 @@ class ModShift(BaseVetter):
107
146
  tce object is a dictionary that contains information about the tce
108
147
  to vet, like period, epoch, duration, depth
109
148
 
110
- lc : lightkurve object
149
+ lightcurve : lightkurve object
111
150
  lightkurve object with the time and flux to use for vetting.
112
151
 
152
+ plot: bool
153
+ option to show plot when initialy populating the metrics.
154
+ Same as using the plot() method.
155
+
113
156
  Returns
114
157
  ------------
115
- modshift : dict
158
+ metrics : dict
116
159
  modshift result dictionary containing the following:
117
160
  pri : primary signal
118
161
  sec : secondary signal
@@ -133,9 +176,8 @@ class ModShift(BaseVetter):
133
176
  self.epoch_days = tce.get_epoch(time_offset_q).to_value(u.day)
134
177
  self.duration_hrs = tce["duration"].to_value(u.hour)
135
178
 
136
- self.box = model.create_box_model_for_tce(
137
- tce, self.time * u.day, time_offset_q)
138
- metrics, conv = modshift.compute_modshift_metrics(
179
+ self.box = model.create_box_model_for_tce(tce, self.time * u.day, time_offset_q)
180
+ self.metrics, conv = modshift.compute_modshift_metrics(
139
181
  self.time,
140
182
  self.flux,
141
183
  self.box,
@@ -145,9 +187,7 @@ class ModShift(BaseVetter):
145
187
  show_plot=plot,
146
188
  )
147
189
 
148
- self.modshift = metrics
149
-
150
- return self.modshift
190
+ return self.metrics
151
191
 
152
192
  def plot(self):
153
193
  met, c = modshift.compute_modshift_metrics(
@@ -162,8 +202,7 @@ class ModShift(BaseVetter):
162
202
 
163
203
 
164
204
  class Lpp(BaseVetter):
165
- """Class to handle LPP Vetter functionality.
166
- """
205
+ """LPP vetter."""
167
206
 
168
207
  def __init__(self, map_filename=None, lc_name="flux"):
169
208
  """
@@ -176,7 +215,6 @@ class Lpp(BaseVetter):
176
215
  lc_name : str
177
216
  Name of the flux array in the ``lightkurve`` object.
178
217
 
179
-
180
218
  Attributes
181
219
  ----------
182
220
  map_info : `~exovetter.lpp.Loadmap`
@@ -201,16 +239,44 @@ class Lpp(BaseVetter):
201
239
  plot_data : dict
202
240
  The folded, binned transit prior to the LPP transformation,
203
241
  populated by :meth:`run`.
242
+
243
+ metrics : dict
244
+ lpp result dictionary populated by :meth:`run`.
204
245
  """
205
- self.map_info = lpp.Loadmap(filename=map_filename)
206
246
  self.lc_name = lc_name
247
+ self.map_info = lpp.Loadmap(filename=map_filename)
207
248
  self.tce = None
208
249
  self.lc = None
209
250
  self.norm_lpp = None
210
251
  self.raw_lpp = None
211
252
  self.plot_data = None
253
+ self.metrics = None
212
254
 
213
- def run(self, tce, lightcurve, plot=False):
255
+ def run(self, tce, lightcurve, plot=False):
256
+ """
257
+ Runs lpp.compute_lpp_Transitmetric to populate the vetter object.
258
+
259
+ Parameters
260
+ -----------
261
+ tce : tce object
262
+ tce object is a dictionary that contains information about the tce
263
+ to vet, like period, epoch, duration, depth
264
+
265
+ lightcurve : lightkurve object
266
+ lightkurve object with the time and flux to use for vetting.
267
+
268
+ plot: bool
269
+ option to show plot when initialy populating the metrics.
270
+ Same as using the plot() method.
271
+
272
+ Returns
273
+ ------------
274
+ metrics : dict
275
+ lpp result dictionary containing the following:
276
+ raw_lpp : Raw LPP value
277
+ norm_lpp : LPP value normalized by period and SNR
278
+ plot_data : The folded, binned transit prior to the LPP transformation
279
+ """
214
280
  self.tce = tce
215
281
  self.lc = lightcurve
216
282
 
@@ -220,16 +286,21 @@ class Lpp(BaseVetter):
220
286
  self.lpp_data, self.map_info
221
287
  ) # noqa: E501
222
288
 
223
- return {
289
+ if plot:
290
+ target = self.tce.get("target_name", "Target")
291
+ lpp.plot_lpp_diagnostic(self.plot_data, target, self.norm_lpp)
292
+
293
+ self.metrics = {
224
294
  "raw_lpp": self.raw_lpp,
225
295
  "norm_lpp": self.norm_lpp,
226
296
  "plot_data": self.plot_data,
227
297
  }
228
298
 
299
+ return self.metrics
300
+
229
301
  def plot(self): # pragma: no cover
230
302
  if self.plot_data is None:
231
- raise ValueError(
232
- "LPP plot data is empty. Execute self.run(...) first.")
303
+ raise ValueError("LPP plot data is empty. Execute self.run(...) first.")
233
304
 
234
305
  # target is populated in TCE, assume it already exists.
235
306
  target = self.tce.get("target_name", "Target")
@@ -237,30 +308,31 @@ class Lpp(BaseVetter):
237
308
 
238
309
 
239
310
  class OddEven(BaseVetter):
240
- """Class to calculate whether the depth of the odd transits is
241
- different than the depth of the even transits
242
- """
311
+ """OddEven vetter"""
243
312
 
244
- def __init__(self, lc_name="flux", dur_frac=0.3, plot=False):
313
+ def __init__(self, lc_name="flux", dur_frac=0.3):
245
314
  """
246
315
  Parameters
247
316
  ----------
248
317
  lc_name : str
249
- Input ``lc_name``.
318
+ Name of the flux array in the ``lightkurve`` object.
250
319
 
251
320
  dur_frac:
252
321
  Fraction of in-transit duration to use for depth calculation.
253
322
 
254
323
  Attributes
255
324
  ------------
256
- oe_sigma
257
- significance of difference of odd/even depth measurements
258
-
259
325
  odd_depth : tuple
260
- depth and error on depth of the odd transits
326
+ depth and error on depth of the odd transits, populated by :meth:`run`.
261
327
 
262
328
  even_depth : tuple
263
- depth and error on depth of the even transits
329
+ depth and error on depth of the even transits, populated by :meth:`run`.
330
+
331
+ oe_sigma : astropy.utils.masked.core.MaskedNDArray
332
+ significance of difference of odd/even depth measurements, populated by :meth:`run`.
333
+
334
+ metrics : dict
335
+ modshift result dictionary populated by :meth:`run`.
264
336
  """
265
337
 
266
338
  self.lc_name = lc_name
@@ -268,20 +340,34 @@ class OddEven(BaseVetter):
268
340
  self.odd_depth = None
269
341
  self.even_depth = None
270
342
  self.oe_sigma = None
343
+ self.metrics = None
271
344
 
272
- def run(self, tce, lightcurve):
345
+ def run(self, tce, lightcurve, plot=False):
273
346
  """
347
+ Runs odd_even.calc_odd_even to populate the vetter object.
348
+
274
349
  Parameters
275
350
  ----------
276
- tce : `~exovetter.tce.Tce`
277
- TCE.
351
+ tce : tce object
352
+ tce object is a dictionary that contains information about the tce
353
+ to vet, like period, epoch, duration, depth
278
354
 
279
- lightcurve : obj
280
- ``lightkurve`` object that contains the detrended lightcurve's
281
- time and flux arrays.
355
+ lightcurve : lightkurve object
356
+ lightkurve object with the time and flux to use for vetting.
282
357
 
358
+ plot: bool
359
+ option to show plot when initialy populating the metrics.
360
+ Same as using the plot() method.
283
361
 
362
+ Returns
363
+ ------------
364
+ metrics : dict
365
+ odd_even result dictionary containing the following:
366
+ oe_sigma : significance of difference of odd/even depth measurements
367
+ odd_depth : depth and error on depth of the odd transits
368
+ even_depth : depth and error on depth of the even transits
284
369
  """
370
+
285
371
  self.time, self.flux, time_offset_str = lightkurve_utils.unpack_lk_version( # noqa
286
372
  lightcurve, self.lc_name
287
373
  )
@@ -302,9 +388,24 @@ class OddEven(BaseVetter):
302
388
  dur_frac=self.dur_frac,
303
389
  )
304
390
 
305
- return {'oe_sigma': self.oe_sigma,
306
- 'odd_depth': self.odd_depth,
307
- 'even_depth': self.even_depth}
391
+ self.metrics = {
392
+ "oe_sigma": self.oe_sigma,
393
+ "odd_depth": self.odd_depth,
394
+ "even_depth": self.even_depth,
395
+ }
396
+
397
+ if plot:
398
+ odd_even.diagnostic_plot(
399
+ self.time,
400
+ self.flux,
401
+ self.period,
402
+ self.epoch,
403
+ self.duration * self.dur_frac,
404
+ self.odd_depth,
405
+ self.even_depth,
406
+ )
407
+
408
+ return self.metrics
308
409
 
309
410
  def plot(self): # pragma: no cover
310
411
  odd_even.diagnostic_plot(
@@ -319,48 +420,62 @@ class OddEven(BaseVetter):
319
420
 
320
421
 
321
422
  class TransitPhaseCoverage(BaseVetter):
322
- """Transit Phase Coverage Vetter
323
- """
423
+ """Transit Phase Coverage Vetter"""
324
424
 
325
425
  def __init__(self, lc_name="flux", nbins=10, ndur=2):
326
426
  """
327
427
  Parameters
328
428
  ----------
329
- tce : tce object
330
- tce object is a dictionary that contains information about the tce
331
- to vet, like period, epoch, duration, depth
332
-
333
- lc : lightkurve object
334
- lightkurve object with the time and flux of the data to use for vetting.
429
+ lc_name : str
430
+ Name of the flux array in the ``lightkurve`` object.
335
431
 
336
432
  nbins : integer
337
- number bins to divide-up the in transit points. default is 10, giving
338
- an accuracy of 0.1.
433
+ number bins to divide-up the in transit points. default is 10, giving
434
+ an accuracy of 0.1.
339
435
 
340
436
  ndur : float
341
- the code considers a phase that cover ndur * transit_duration as
342
- "in transit"
437
+ the code considers a phase that cover ndur * transit_duration as
438
+ "in transit". Default is 2
439
+
440
+ Attributes
441
+ ------------
442
+ hist : array
443
+ histogram of the times of length nbins, populated by :meth:`run`.
444
+
445
+ bins : array
446
+ corners of the bins for the histogram, length of nbins+1,
447
+ populated by :meth:`run`.
343
448
 
449
+ metrics : dict
450
+ TransitPhaseCoverage result dictionary populated by :meth:`run`.
344
451
  """
345
452
  self.lc_name = lc_name
346
453
  self.nbins = nbins
347
454
  self.ndur = ndur
455
+ self.hist = None
456
+ self.bins = None
457
+ self.metrics = None
348
458
 
349
- def run(self, tce, lc, plot=False):
350
- """Run the vetter on the specified Threshold Crossing Event (TCE)
351
- and lightcurve to obtain metric.
459
+ def run(self, tce, lightcurve, plot=False):
460
+ """Runs transit_coverage.calc_coverage to populate the vetter object.
352
461
 
353
462
  Parameters
354
463
  ----------
355
- tce : `~exovetter.tce.Tce`
356
- TCE.
464
+ tce : tce object
465
+ tce object is a dictionary that contains information about the tce
466
+ to vet, like period, epoch, duration, depth.
357
467
 
358
- lc : obj
359
- ``lightkurve`` object that contains the detrended lightcurve's
360
- time and flux arrays to use for vetting.
468
+ lightcurve : lightkurve object
469
+ lightkurve object with the time and flux of the data to use for vetting.
470
+
471
+ Returns
472
+ ------------
473
+ metrics : dict
474
+ transit_coverage result dictionary containing the following:
475
+ transit_phase_coverage : Fraction of coverage
361
476
  """
362
477
  time, flux, time_offset_str = lightkurve_utils.unpack_lk_version(
363
- lc, self.lc_name
478
+ lightcurve, self.lc_name
364
479
  ) # noqa: E50
365
480
 
366
481
  p_day = tce["period"].to_value(u.day)
@@ -372,23 +487,27 @@ class TransitPhaseCoverage(BaseVetter):
372
487
  tp_cover, self.hist, self.bins = transit_coverage.calc_coverage(
373
488
  time, p_day, epoch, dur_hour, ndur=self.ndur, nbins=self.nbins)
374
489
 
490
+ self.metrics = {"transit_phase_coverage": tp_cover}
491
+
375
492
  if plot:
376
493
  transit_coverage.plot_coverage(self.hist, self.bins)
377
494
 
378
- return {'transit_phase_coverage': tp_cover}
495
+ return self.metrics
379
496
 
380
497
  def plot(self): # pragma: no cover
381
498
  transit_coverage.plot_coverage(self.hist, self.bins)
382
499
 
383
500
 
384
501
  class Sweet(BaseVetter):
385
- """Class to handle SWEET Vetter functionality.
386
- """
502
+ """SWEET Vetter"""
387
503
 
388
504
  def __init__(self, lc_name="flux", threshold_sigma=3):
389
505
  """
390
506
  Parameters
391
507
  ----------
508
+ lc_name : str
509
+ Name of the flux array in the ``lightkurve`` object.
510
+
392
511
  threshold_sigma : float
393
512
  Threshold for comparing signal to transit period.
394
513
 
@@ -396,27 +515,46 @@ class Sweet(BaseVetter):
396
515
  ----------
397
516
  tce : tce object
398
517
  tce object is a dictionary that contains information about the tce
399
- to vet, like period, epoch, duration, depth
518
+ to vet, like period, epoch, duration, depth.
400
519
 
401
520
  lc : lightkurve object
402
- lightkurve object with the time and flux of the data to use for vetting.
403
-
404
- result : dict
405
- ``'amp'`` contains the best fit amplitude, its uncertainty, and
406
- amplitude-to-uncertainty ratio for half-period, period, and
407
- twice the period. ``'msg'`` contains warnings, if applicable.
408
- Populated by :meth:`run`.
521
+ lightkurve object with the time and flux of the data to use for vetting.
409
522
 
410
- lsf : `~exovetter.utils.WqedLSF`
411
- Least squares fit object, populated by :meth:`run`.
523
+ metrics : dict
524
+ SWEET result dictionary populated by :meth:`run`.
412
525
  """
526
+
527
+ self.lc_name = lc_name
528
+ self.sweet_threshold_sigma = threshold_sigma
413
529
  self.tce = None
414
530
  self.lc = None
415
- self.result = None
416
- self.sweet_threshold_sigma = threshold_sigma
417
- self.lc_name = lc_name
531
+ self.metrics = None
418
532
 
419
533
  def run(self, tce, lightcurve, plot=False):
534
+ """Runs sweet.sweet and sweet.construct_message to populate the vetter object.
535
+
536
+ Parameters
537
+ ----------
538
+ tce : tce object
539
+ tce object is a dictionary that contains information about the tce
540
+ to vet, like period, epoch, duration, depth.
541
+
542
+ lightcurve : lightkurve object
543
+ lightkurve object with the time and flux of the data to use for vetting.
544
+
545
+ plot: bool
546
+ option to show plot when initialy populating the metrics.
547
+ Same as using the plot() method.
548
+
549
+ Returns
550
+ ------------
551
+ metrics : dict
552
+ ``'msg'`` contains warnings, if applicable.
553
+ ``'amp'`` contains the best fit amplitude, its uncertainty, and
554
+ amplitude-to-uncertainty ratio for half-period, period, and
555
+ twice the period.
556
+
557
+ """
420
558
  self.tce = tce
421
559
  self.lc = lightcurve
422
560
 
@@ -432,47 +570,70 @@ class Sweet(BaseVetter):
432
570
  result_dict = sweet.sweet(
433
571
  time, flux, period_days, epoch, duration_days, plot=plot
434
572
  )
435
- result_dict = sweet.construct_message(
436
- result_dict, self.sweet_threshold_sigma)
437
- return result_dict
573
+ self.metrics = sweet.construct_message(result_dict, self.sweet_threshold_sigma)
574
+
575
+ return self.metrics
438
576
 
439
577
  def plot(self): # pragma: no cover
440
578
  self.run(self.tce, self.lc, plot=True)
441
579
 
442
580
 
443
581
  class Centroid(BaseVetter):
444
- """Class to handle centroid vetting
582
+ """Class to handle centroid vetting"""
445
583
 
446
- Parameters
447
- ----------
448
- lc_name : str
449
- Name of the flux array in the ``lightkurve`` object.
584
+ def __init__(self, lc_name="flux"):
585
+ """
586
+ Parameters
587
+ ----------
588
+ lc_name : str
589
+ Name of the flux array in the ``lightkurve`` object.
450
590
 
451
- threshold_sigma : float
452
- Threshold for comparing signal to transit period.
591
+ Attributes
592
+ ----------
593
+ tce : tce object
594
+ tce object is a dictionary that contains information about the tce
595
+ to vet, like period, epoch, duration, depth.
453
596
 
454
- Attributes
455
- ----------
456
- tce : `~exovetter.tce.Tce`
457
- TCE object, a dictionary that contains information about the TCE
458
- to vet, like period, epoch, duration, depth.
597
+ tpf : obj
598
+ ``lightkurve`` target pixel file object with pixels in column lc_name
459
599
 
460
- lk_tpf: obj
461
- ``lightkurve`` target pixel file object with pixels in column lc_name
600
+ metrics : dict
601
+ Centroid result dictionary populated by :meth:`run`."""
462
602
 
463
- sweet : dict
464
- ``'amp'`` contains the best fit amplitude, its uncertainty, and
465
- amplitude-to-uncertainty ratio for half-period, period, and
466
- twice the period. ``'msg'`` contains warnings, if applicable.
467
- They are populated by running the :meth:`run` method.
603
+ self.lc_name = lc_name
604
+ self.tce = None
605
+ self.tpf = None
606
+ self.metrics = None
468
607
 
469
- """
608
+ def run(self, tce, lk_tpf, plot=False, remove_transits=None):
609
+ """Runs ent.compute_diff_image_centroids and cent.measure_centroid_shift
610
+ to populate the vetter object.
470
611
 
471
- def __init__(self, lc_name="flux"):
472
- self.tce = None
473
- self.lc_name = lc_name
612
+ Parameters
613
+ ----------
614
+ tce : tce object
615
+ tce object is a dictionary that contains information about the tce
616
+ to vet, like period, epoch, duration, depth.
617
+
618
+ lk_tpf: obj
619
+ ``lightkurve`` target pixel file object with pixels in column lc_name
474
620
 
475
- def run(self, tce, lk_tpf, plot=False):
621
+ plot : bool
622
+ option to show plot when initialy populating the metrics.
623
+ Same as using the plot() method.
624
+
625
+ remove_transits : list
626
+ List of 0 indexed transit integers to not calculate on.
627
+
628
+ Returns
629
+ ------------
630
+ metrics : dict
631
+ centroid result dictionary containing the following:
632
+ offset : (float) Size of offset in pixels (or whatever unit centroids is in)
633
+ significance : (float) The statistical significance of the transit.
634
+ Values close to 1 mean the transit is likely on the target star.
635
+ Values less than ~1e-3 suggest the target is not the source of the transit.
636
+ """
476
637
 
477
638
  self.tce = tce
478
639
  self.tpf = lk_tpf
@@ -486,18 +647,22 @@ class Centroid(BaseVetter):
486
647
  epoch = tce.get_epoch(time_offset_q).to_value(u.day)
487
648
  duration_days = tce["duration"].to_value(u.day)
488
649
 
489
- centroids, figs = cent.compute_diff_image_centroids(
490
- time, cube, period_days, epoch, duration_days, plot=plot
491
- )
492
- offset, signif, fig = cent.measure_centroid_shift(centroids, plot)
650
+ if remove_transits is None: # reformat to be a blank list
651
+ remove_transits = []
652
+
653
+ centroids, figs, kept_transits = cent.compute_diff_image_centroids(
654
+ time, cube, period_days, epoch, duration_days,
655
+ remove_transits, plot=plot)
656
+
657
+ offset, signif, fig = cent.measure_centroid_shift(centroids, kept_transits, plot)
493
658
  figs.append(fig)
494
659
 
495
660
  # TODO: If plot=True, figs is a list of figure handles.
496
661
  # Do I save those figures, put them in a single pdf,
497
662
  # close them all?
498
663
 
499
- out = dict(offset=offset, significance=signif)
500
- return out
664
+ self.metrics = dict(offset=offset, significance=signif)
665
+ return self.metrics
501
666
 
502
667
  def plot(self): # pragma: no cover
503
668
  self.run(self.tce, self.tpf, plot=True)
@@ -509,15 +674,80 @@ class VizTransits(BaseVetter):
509
674
  with a folded transit.
510
675
  """
511
676
 
512
- def __init__(self, lc_name="flux", max_transits=10, transit_only=False,
513
- smooth=10,):
514
- self.tce = None
677
+ def __init__(self, lc_name="flux", max_transits=10, transit_only=False,
678
+ smooth=10, transit_plot=False, folded_plot=False):
679
+ """
680
+ Parameters
681
+ ----------
682
+ lc_name : str
683
+ Name of the flux array in the ``lightkurve`` object.
684
+
685
+ max_transits : bool
686
+ Total number of transits to plot.
687
+
688
+ transit_only : bool
689
+ Zoom in on the transit
690
+
691
+ smooth : type
692
+ description
693
+
694
+ transit_plot : bool
695
+ Whether or not to show the transit plot
696
+
697
+ folded_plot : book
698
+ Wheter or not to show the folded plot
699
+
700
+ Attributes
701
+ ----------
702
+ tce : tce object
703
+ tce object is a dictionary that contains information about the tce
704
+ to vet, like period, epoch, duration, depth.
705
+
706
+ metrics : dict
707
+ VizTransits result dictionary populated by :meth:`run`.
708
+ """
709
+
515
710
  self.lc_name = lc_name
516
711
  self.max_transits = max_transits
517
712
  self.transit_only = transit_only
713
+ self.transit_plot = transit_plot
714
+ self.folded_plot = folded_plot
518
715
  self.smooth = smooth
716
+ self.tce = None
717
+ self.metrics = None
718
+ self.lc = None
519
719
 
520
720
  def run(self, tce, lightcurve, plot=False):
721
+ """Runs viz_transits.plot_all_transits to populate the vetter object.
722
+
723
+ Parameters
724
+ ----------
725
+ tce : tce object
726
+ tce object is a dictionary that contains information about the tce
727
+ to vet, like period, epoch, duration, depth.
728
+
729
+ lightcurve : lightkurve object
730
+ lightkurve object with the time and flux of the data to use for vetting.
731
+
732
+ plot: bool
733
+ option to show folded and unfolded plot. If true both will show.
734
+
735
+ Returns
736
+ ------------
737
+ metrics : dict
738
+ centroid result dictionary containing the following:
739
+ num_transits : Number of transits with data in transit (3*duration).
740
+ """
741
+
742
+ if plot == True:
743
+ run_transit_plot = True
744
+ run_folded_plot = True
745
+ else:
746
+ run_transit_plot = self.transit_plot
747
+ run_folded_plot = self.folded_plot
748
+
749
+ self.tce = tce
750
+ self.lc = lightcurve
521
751
 
522
752
  time, flux, time_offset_str = lightkurve_utils.unpack_lk_version(
523
753
  lightcurve, self.lc_name) # noqa: E50
@@ -526,25 +756,200 @@ class VizTransits(BaseVetter):
526
756
  time_offset_q = getattr(exo_const, time_offset_str)
527
757
  epoch = tce.get_epoch(time_offset_q).to_value(u.day)
528
758
  duration_days = tce["duration"].to_value(u.day)
529
- depth = tce['depth']
759
+ depth = tce["depth"]
530
760
 
531
761
  n_has_data = viz_transits.plot_all_transits(time, flux, period_days,
532
762
  epoch,
533
763
  duration_days,
534
764
  depth, max_transits=self.max_transits,
535
765
  transit_only=self.transit_only,
536
- plot=plot, units="d")
766
+ plot=run_transit_plot, units="d")
537
767
 
538
768
  viz_transits.plot_fold_transit(time, flux, period_days,
539
769
  epoch, depth, duration_days,
540
770
  smooth=self.smooth,
541
771
  transit_only=self.transit_only,
542
- plot=plot, units="d")
772
+ plot=run_folded_plot, units="d")
543
773
 
544
- return {'num_transits': n_has_data}
774
+ self.metrics = {"num_transits": n_has_data}
545
775
 
546
- def plot(self, tce, lightcurve):
776
+ return self.metrics
777
+
778
+ def plot(self): # pragma: no cover
779
+ # This will always show both. If you want one or the other do run with whichever one initialized
780
+ self.run(self.tce, self.lc, plot=True)
781
+
782
+ # def plot(self, tce, lightcurve): # old plot method
783
+
784
+ # _ = self.run(tce, lightcurve, max_transits=self.max_transits,
785
+ # transit_only=self.transit_only, smooth=self.smooth,
786
+ # plot=True)
787
+
788
+ class LeoVetter(BaseVetter):
789
+ """Leo based vetter (see https://github.com/mkunimoto/LEO-vetter)"""
790
+
791
+ def __init__(self, lc_name="flux", flux_err=None, frac=0.7, max_chases_phase=0.1):
792
+ """
793
+ Parameters
794
+ ----------
795
+ lc_name : str
796
+ Name of the flux array in the ``lightkurve`` object.
797
+
798
+ flux_err : string
799
+ If none provided, defaults to flux_err column of lightkurve. LeoVetter requires realistic flux errors to give meaningful results.
800
+
801
+ frac : float
802
+ fraction of SES for a transit which triggers the chases false alarm statistic (default 0.7)
803
+
804
+ max_chases_phase : float
805
+ maximum to allow the chases search to run on (default 0.1)
806
+
807
+ Attributes
808
+ ----------
809
+ tce : tce object
810
+ tce object is a dictionary that contains information about the tce
811
+ to vet, like period, epoch, duration, depth.
812
+
813
+ lc : lightkurve object
814
+ lightkurve object with the time and flux of the data to use for vetting.
815
+
816
+ metrics : dict
817
+ LeoVetter result dictionary populated by :meth:`run`.
818
+ """
819
+
820
+ self.tce = None
821
+ self.lc_name = lc_name
822
+ self.flux_err= flux_err
823
+ self.frac= frac
824
+ self.max_chases_phase = max_chases_phase
825
+ self.metrics = None
826
+
827
+ def run(self, tce, lightcurve, plot=False):
828
+ """
829
+ Runs leo vetters to populate the vetter object.
547
830
 
548
- _ = self.run(tce, lightcurve, max_transits=self.max_transits,
549
- transit_only=self.transit_only, smooth=self.smooth,
550
- plot=True)
831
+ Parameters
832
+ ----------
833
+ tce : tce object
834
+ Dictionary that contains information about the tce
835
+ to vet, like period, epoch, duration, depth
836
+
837
+ lightcurve : lightkurve object
838
+ lightkurve object with the time and flux to use for vetting.
839
+
840
+ plot: bool
841
+ Option to show plot when initialy populating the metrics.
842
+ Same as using the plot() method.
843
+
844
+ Attributes
845
+ ----------
846
+ MES_series : dep_series/err_series
847
+ N_transit : Number of transits
848
+ SES : Single Event Statistic
849
+ SES_series : Single Event Statistic series for every timestamp
850
+ chases : range for chases metric is between 1.5 transit durations and user specified max_chases_phase
851
+ err_series : Error of MES
852
+ rubble : rubble statistic
853
+ sig_w : White noise following Hartman & Bakos (2016)
854
+ sig_r : Red noise following Hartman & Bakos (2016)
855
+ err : Signal-to-pink-noise following Pont et al. (2006)
856
+ MES : Multiple Event Statistic calculated from mean depth of in transit points
857
+ SHP : MES shape metric
858
+ CHI :
859
+ med_chases : median of chases
860
+ mean_chases : mean of chases
861
+ max_SES : maximum of SES
862
+ DMM :
863
+
864
+ Returns
865
+ ------------
866
+ metrics : dict
867
+ Result dictionary containing sig_w, sig_r, err,
868
+ MES, SHP, CHI, med_chases, mean_chases, max_SES, DMM
869
+ """
870
+
871
+ self.time, self.flux, time_offset_str = lightkurve_utils.unpack_lk_version( # noqa
872
+ lightcurve, self.lc_name
873
+ )
874
+
875
+ self.period = tce["period"].to_value(u.day)
876
+ self.duration = tce["duration"].to_value(u.day)
877
+ time_offset_q = getattr(exo_const, time_offset_str)
878
+ self.epoch = tce.get_epoch(time_offset_q).to_value(u.day)
879
+
880
+ # epo needs to be the time of first transit in TESS BJD
881
+ # (above converted to BTJD but here check it is actually at the beggining of the time series)
882
+ if self.epoch >= self.time[0]:
883
+ N = np.floor((self.epoch-self.time[0])/self.period)
884
+ self.epo = self.epoch - N*self.period
885
+ else:
886
+ N = np.ceil((self.time[0]-self.epoch)/self.period)
887
+ self.epo = self.epoch + N*self.period
888
+
889
+ # create flux_err array defaulted to flux_err col of lc
890
+ if self.flux_err is None:
891
+ print("No flux error given, defaulting to 'flux_err' column of light curve")
892
+ self.flux_err = lightcurve['flux_err']
893
+ else:
894
+ self.flux_err = lightcurve[self.flux_err]
895
+
896
+ # get initial values needed to run transit_event vetter
897
+ leo_vetter = leo.Leo(self.time, self.period, self.epo, self.duration, self.flux, self.flux_err, self.frac, self.max_chases_phase)
898
+
899
+ # calculate SES
900
+ leo_vetter.get_SES_MES()
901
+
902
+ # calculated rubble, chases, etc
903
+ leo_vetter.get_chases()
904
+
905
+ # All available attributes (removed some which aren't very useful)
906
+ self.MES_series = leo_vetter.MES_series
907
+ self.N_transit = leo_vetter.N_transit
908
+ self.SES = leo_vetter.SES
909
+ self.SES_series = leo_vetter.SES_series
910
+ self.chases = leo_vetter.chases
911
+ #self.dep = leo_vetter.dep
912
+ #self.dep_series = leo_vetter.dep_series
913
+ #self.epochs = leo_vetter.epochs
914
+ self.err_series = leo_vetter.err_series
915
+ #self.fit_tran = leo_vetter.fit_tran
916
+ #self.in_tran = leo_vetter.in_tran
917
+ #self.n_in = leo_vetter.n_in
918
+ #self.near_tran = leo_vetter.near_tran
919
+ #self.phase = leo_vetter.phase
920
+ #self.qtran = leo_vetter.qtran
921
+ self.rubble = leo_vetter.rubble
922
+ #self.tran_epochs = leo_vetter.tran_epochs
923
+ #self.zpt = leo_vetter.zpt
924
+ self.sig_w = leo_vetter.sig_w
925
+ self.sig_r = leo_vetter.sig_r
926
+ self.err = leo_vetter.err
927
+ self.MES = leo_vetter.MES
928
+ self.SHP = leo_vetter.SHP
929
+ self.CHI = leo_vetter.CHI
930
+ self.med_chases = leo_vetter.med_chases
931
+ self.mean_cases = leo_vetter.mean_chases
932
+ self.max_SES = leo_vetter.max_SES
933
+ self.DMM = leo_vetter.DMM
934
+
935
+ # Important metrics to directly return
936
+ self.metrics = {
937
+ "sig_w": self.sig_w,
938
+ "sig_r": self.sig_r,
939
+ "err": self.err,
940
+ "MES": self.MES,
941
+ "SHP": self.SHP,
942
+ "CHI": self.CHI,
943
+ "med_chases": self.med_chases,
944
+ "mean_chases": self.mean_cases,
945
+ "max_SES": self.max_SES,
946
+ "DMM": self.DMM,
947
+ }
948
+
949
+ if plot:
950
+ leo_vetter.plot()
951
+
952
+ return self.metrics
953
+
954
+ def plot(self): # pragma: no cover
955
+ self.run(self.tce, self.lc, plot=True)