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