arvi 0.1.12__py3-none-any.whl → 0.1.14__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.

Potentially problematic release.


This version of arvi might be problematic. Click here for more details.

arvi/timeseries.py CHANGED
@@ -11,18 +11,21 @@ import numpy as np
11
11
  from astropy import units
12
12
 
13
13
  from .setup_logger import logger
14
- from .config import return_self, check_internet
14
+ from . import config
15
15
  from .translations import translate
16
- from .dace_wrapper import do_download_filetype, get_observations, get_arrays
16
+ from .dace_wrapper import do_download_filetype, do_symlink_filetype, get_observations, get_arrays
17
17
  from .simbad_wrapper import simbad
18
18
  from .gaia_wrapper import gaia
19
19
  from .extra_data import get_extra_data
20
20
  from .stats import wmean, wrms
21
21
  from .binning import bin_ccf_mask, binRV
22
22
  from .HZ import getHZ_period
23
- from .utils import strtobool, there_is_internet
23
+ from .utils import strtobool, there_is_internet, timer
24
24
 
25
25
 
26
+ class ExtraFields:
27
+ pass
28
+
26
29
  @dataclass
27
30
  class RV:
28
31
  """
@@ -71,7 +74,7 @@ class RV:
71
74
  self.__star__ = translate(self.star)
72
75
 
73
76
  if not self._child:
74
- if check_internet and not there_is_internet():
77
+ if config.check_internet and not there_is_internet():
75
78
  raise ConnectionError('There is no internet connection?')
76
79
 
77
80
  # complicated way to query Simbad with self.__star__ or, if that
@@ -102,8 +105,10 @@ class RV:
102
105
  if self.verbose:
103
106
  logger.info(f'querying DACE for {self.__star__}...')
104
107
  try:
105
- self.dace_result = get_observations(self.__star__, self.instrument,
106
- verbose=self.verbose)
108
+ with timer():
109
+ mid = self.simbad.main_id if hasattr(self, 'simbad') else None
110
+ self.dace_result = get_observations(self.__star__, self.instrument,
111
+ main_id=mid, verbose=self.verbose)
107
112
  except ValueError as e:
108
113
  # querying DACE failed, should we raise an error?
109
114
  if self._raise_on_error:
@@ -216,6 +221,7 @@ class RV:
216
221
  self._did_secular_acceleration = False
217
222
  self._did_sigma_clip = False
218
223
  self._did_adjust_means = False
224
+ self._did_correct_berv = False
219
225
  self.__post_init__()
220
226
 
221
227
  def snapshot(self):
@@ -257,6 +263,10 @@ class RV:
257
263
  table += ' | '.join(map(str, self.NN.values())) + '\n'
258
264
  return table
259
265
 
266
+ @property
267
+ def point(self):
268
+ return [(t.round(4), v.round(4), sv.round(4)) for t, v, sv in zip(self.time, self.vrad, self.svrad)]
269
+
260
270
  @property
261
271
  def mtime(self) -> np.ndarray:
262
272
  """ Masked array of times """
@@ -376,6 +386,7 @@ class RV:
376
386
  s.mask = kwargs.get('mask', np.full_like(s.time, True, dtype=bool))
377
387
 
378
388
  s.instruments = [inst]
389
+ s._quantities = np.array([])
379
390
 
380
391
  return s
381
392
 
@@ -437,6 +448,13 @@ class RV:
437
448
 
438
449
  s = cls(star, _child=True, **kwargs)
439
450
 
451
+ def find_column(data, names):
452
+ has_col = np.array([name in data.dtype.fields for name in names])
453
+ if any(has_col):
454
+ col = np.where(has_col)[0][0]
455
+ return data[names[col]]
456
+ return False
457
+
440
458
  for i, (f, instrument) in enumerate(zip(files, instruments)):
441
459
  data = np.loadtxt(f, skiprows=2, usecols=range(3), unpack=True)
442
460
  _s = cls(star, _child=True, **kwargs)
@@ -465,10 +483,11 @@ class RV:
465
483
  else:
466
484
  data = np.array([], dtype=np.dtype([]))
467
485
 
468
- if 'fwhm' in data.dtype.fields:
469
- _s.fwhm = data['fwhm']
470
- if 'sfwhm' in data.dtype.fields:
471
- _s.fwhm_err = data['sfwhm']
486
+ # try to find FWHM and uncertainty
487
+ if (v := find_column(data, ['fwhm'])) is not False: # walrus !!
488
+ _s.fwhm = v
489
+ if (sv := find_column(data, ['sfwhm', 'fwhm_err', 'sig_fwhm'])) is not False:
490
+ _s.fwhm_err = sv
472
491
  else:
473
492
  _s.fwhm_err = 2 * _s.svrad
474
493
  else:
@@ -478,12 +497,11 @@ class RV:
478
497
  _quantities.append('fwhm')
479
498
  _quantities.append('fwhm_err')
480
499
 
481
- if 'rhk' in data.dtype.fields:
482
- _s.rhk = data['rhk']
500
+ if (v := find_column(data, ['rhk'])) is not False:
501
+ _s.rhk = v
483
502
  _s.rhk_err = np.full_like(time, np.nan)
484
- for possible_name in ['srhk', 'rhk_err']:
485
- if possible_name in data.dtype.fields:
486
- _s.rhk_err = data[possible_name]
503
+ if (sv := find_column(data, ['srhk', 'rhk_err', 'sig_rhk'])) is not False:
504
+ _s.rhk_err = sv
487
505
  else:
488
506
  _s.rhk = np.zeros_like(time)
489
507
  _s.rhk_err = np.full_like(time, np.nan)
@@ -510,6 +528,12 @@ class RV:
510
528
  setattr(_s, q, np.full(time.size, True))
511
529
  _quantities.append(q)
512
530
 
531
+ _s.extra_fields = ExtraFields()
532
+ for field in data.dtype.names:
533
+ if field not in _quantities:
534
+ setattr(_s.extra_fields, field, data[field])
535
+ # _quantities.append(field)
536
+
513
537
  #! end hack
514
538
 
515
539
  _s.mask = np.ones_like(time, dtype=bool)
@@ -537,36 +561,80 @@ class RV:
537
561
  logger.error('iCCF is not installed. Please install it with `pip install iCCF`')
538
562
  return
539
563
 
564
+ verbose = kwargs.get('verbose', True)
565
+
540
566
  if isinstance(files, str):
541
567
  files = [files]
542
568
 
543
- I = iCCF.from_file(files)
569
+ CCFs = iCCF.from_file(files)
570
+
571
+ if not isinstance(CCFs, list):
572
+ CCFs = [CCFs]
544
573
 
545
- objects = np.unique([i.HDU[0].header['OBJECT'].replace(' ', '') for i in I])
574
+ objects = np.unique([i.HDU[0].header['OBJECT'].replace(' ', '') for i in CCFs])
546
575
  if objects.size != 1:
547
576
  logger.warning(f'found {objects.size} different stars in the CCF files, '
548
577
  'choosing the first one')
549
578
  star = objects[0]
550
579
 
551
580
  s = cls(star, _child=True)
581
+ instruments = list(np.unique([i.instrument for i in CCFs]))
552
582
 
553
- # time, RVs, uncertainties
554
- s.time = np.array([i.bjd for i in I])
555
- s.vrad = np.array([i.RV*1e3 for i in I])
556
- s.svrad = np.array([i.RVerror*1e3 for i in I])
583
+ for instrument in instruments:
584
+ # time, RVs, uncertainties
585
+ time = np.array([i.bjd for i in CCFs])
586
+ vrad = np.array([i.RV*1e3 for i in CCFs])
587
+ svrad = np.array([i.RVerror*1e3 for i in CCFs])
588
+ _s = RV.from_arrays(star, time, vrad, svrad, inst=instrument)
557
589
 
558
- s.fwhm = np.array([i.FWHM*1e3 for i in I])
559
- s.fwhm_err = np.array([i.FWHMerror*1e3 for i in I])
590
+ _quantities = []
560
591
 
561
- # mask
562
- s.mask = np.full_like(s.time, True, dtype=bool)
592
+ _s.fwhm = np.array([i.FWHM*1e3 for i in CCFs])
593
+ _s.fwhm_err = np.array([i.FWHMerror*1e3 for i in CCFs])
594
+
595
+ _quantities.append('fwhm')
596
+ _quantities.append('fwhm_err')
597
+
598
+ _s.contrast = np.array([i.contrast for i in CCFs])
599
+ _s.contrast_err = np.array([i.contrast_error for i in CCFs])
600
+
601
+ _quantities.append('contrast')
602
+ _quantities.append('contrast_err')
563
603
 
564
- s.instruments = list(np.unique([i.instrument for i in I]))
604
+ _s.texp = np.array([i.HDU[0].header['EXPTIME'] for i in CCFs])
605
+ _quantities.append('texp')
606
+
607
+ _s.date_night = np.array([
608
+ i.HDU[0].header['DATE-OBS'].split('T')[0] for i in CCFs
609
+ ])
610
+ _quantities.append('date_night')
611
+
612
+ _s.mask = np.full_like(_s.time, True, dtype=bool)
613
+
614
+ _s.drs_qc = np.array([i.HDU[0].header['HIERARCH ESO QC SCIRED CHECK'] for i in CCFs], dtype=bool)
615
+ # mask out drs_qc = False
616
+ if not _s.drs_qc.all():
617
+ n = (~ _s.drs_qc).sum()
618
+ if verbose:
619
+ logger.warning(f'masking {n} points where DRS QC failed for {instrument}')
620
+ _s.mask &= _s.drs_qc
621
+ print(_s.mask)
622
+
623
+ _s._quantities = np.array(_quantities)
624
+ setattr(s, instrument, _s)
625
+
626
+ s._child = False
627
+ s.instruments = instruments
628
+ s._build_arrays()
629
+
630
+ if instruments == ['ESPRESSO']:
631
+ from .instrument_specific import divide_ESPRESSO
632
+ divide_ESPRESSO(s)
565
633
 
566
634
  return s
567
635
 
568
636
 
569
- def _check_instrument(self, instrument, strict=False):# -> list | None:
637
+ def _check_instrument(self, instrument, strict=False, log=False):# -> list | None:
570
638
  """
571
639
  Check if there are observations from `instrument`.
572
640
 
@@ -599,6 +667,10 @@ class RV:
599
667
  if any([instrument in inst for inst in self.instruments]):
600
668
  return [inst for inst in self.instruments if instrument in inst]
601
669
 
670
+ if log:
671
+ logger.error(f"No data from instrument '{instrument}'")
672
+ logger.info(f'available: {self.instruments}')
673
+ return
602
674
 
603
675
  def _build_arrays(self):
604
676
  """ build all concatenated arrays of `self` from each of the `.inst`s """
@@ -642,8 +714,8 @@ class RV:
642
714
  )
643
715
  setattr(self, q, arr)
644
716
 
645
-
646
- def download_ccf(self, instrument=None, index=None, limit=None, directory=None, **kwargs):
717
+ def download_ccf(self, instrument=None, index=None, limit=None,
718
+ directory=None, symlink=False, **kwargs):
647
719
  """ Download CCFs from DACE
648
720
 
649
721
  Args:
@@ -671,9 +743,15 @@ class RV:
671
743
  # remove empty strings
672
744
  files = list(filter(None, files))
673
745
 
674
- do_download_filetype('CCF', files[:limit], directory, **kwargs)
746
+ if symlink:
747
+ if 'top_level' not in kwargs:
748
+ logger.warning('may need to provide `top_level` in kwargs to find file')
749
+ do_symlink_filetype('CCF', files[:limit], directory, **kwargs)
750
+ else:
751
+ do_download_filetype('CCF', files[:limit], directory, verbose=self.verbose, **kwargs)
675
752
 
676
- def download_s1d(self, instrument=None, index=None, limit=None, directory=None, **kwargs):
753
+ def download_s1d(self, instrument=None, index=None, limit=None,
754
+ directory=None, symlink=False, **kwargs):
677
755
  """ Download S1Ds from DACE
678
756
 
679
757
  Args:
@@ -701,9 +779,15 @@ class RV:
701
779
  # remove empty strings
702
780
  files = list(filter(None, files))
703
781
 
704
- do_download_filetype('S1D', files[:limit], directory, **kwargs)
782
+ if symlink:
783
+ if 'top_level' not in kwargs:
784
+ logger.warning('may need to provide `top_level` in kwargs to find file')
785
+ do_symlink_filetype('S1D', files[:limit], directory, **kwargs)
786
+ else:
787
+ do_download_filetype('S1D', files[:limit], directory, verbose=self.verbose, **kwargs)
705
788
 
706
- def download_s2d(self, instrument=None, index=None, limit=None, directory=None, **kwargs):
789
+ def download_s2d(self, instrument=None, index=None, limit=None,
790
+ directory=None, symlink=False, **kwargs):
707
791
  """ Download S2Ds from DACE
708
792
 
709
793
  Args:
@@ -731,11 +815,16 @@ class RV:
731
815
  # remove empty strings
732
816
  files = list(filter(None, files))
733
817
 
734
- do_download_filetype('S2D', files[:limit], directory, **kwargs)
818
+ if symlink:
819
+ if 'top_level' not in kwargs:
820
+ logger.warning('may need to provide `top_level` in kwargs to find file')
821
+ do_symlink_filetype('S2D', files[:limit], directory, **kwargs)
822
+ else:
823
+ do_download_filetype('S2D', files[:limit], directory, verbose=self.verbose, **kwargs)
735
824
 
736
825
 
737
- from .plots import plot, plot_fwhm, plot_bis, plot_rhk, plot_quantity
738
- from .plots import gls, gls_fwhm, gls_bis, gls_rhk
826
+ from .plots import plot, plot_fwhm, plot_bis, plot_rhk, plot_berv, plot_quantity
827
+ from .plots import gls, gls_fwhm, gls_bis, gls_rhk, window_function
739
828
  from .reports import report
740
829
 
741
830
  from .instrument_specific import known_issues
@@ -799,7 +888,7 @@ class RV:
799
888
  if self.verbose:
800
889
  logger.info(f"Removed observations from '{instrument}'")
801
890
 
802
- if return_self:
891
+ if config.return_self:
803
892
  return self
804
893
 
805
894
  def remove_condition(self, condition):
@@ -827,7 +916,7 @@ class RV:
827
916
  index = np.atleast_1d(index)
828
917
  try:
829
918
  instrument_index = self.obs[index]
830
- instrument = np.array(self.instruments)[instrument_index - 1]
919
+ np.array(self.instruments)[instrument_index - 1]
831
920
  except IndexError:
832
921
  logger.errors(f'index {index} is out of bounds for N={self.N}')
833
922
  return
@@ -840,7 +929,7 @@ class RV:
840
929
  # for i, inst in zip(index, instrument):
841
930
  # index_in_instrument = i - (self.obs < instrument_index).sum()
842
931
  # getattr(self, inst).mask[index_in_instrument] = False
843
- if return_self:
932
+ if config.return_self:
844
933
  return self
845
934
 
846
935
  def remove_non_public(self):
@@ -903,7 +992,7 @@ class RV:
903
992
  instruments = self._check_instrument(instrument)
904
993
  rng = np.random.default_rng(seed=seed)
905
994
  for inst in instruments:
906
- s = getattr(self, inst)
995
+ # s = getattr(self, inst)
907
996
  mask_for_this_inst = self.obs == self.instruments.index(inst) + 1
908
997
  # only choose if there are more than n points
909
998
  if self.mask[mask_for_this_inst].sum() > n:
@@ -1008,13 +1097,18 @@ class RV:
1008
1097
  self.vrad = self.vrad - sa * (self.time - epoch) / 365.25
1009
1098
  else:
1010
1099
  for inst in self.instruments:
1100
+ s = getattr(self, inst)
1101
+
1102
+ # if RVs come from a publication, don't remove the secular
1103
+ # acceleration
1104
+ if np.all(s.pub_reference != ''):
1105
+ continue
1106
+
1011
1107
  if 'HIRES' in inst: # never remove it from HIRES...
1012
1108
  continue
1013
1109
  if 'NIRPS' in inst: # never remove it from NIRPS...
1014
1110
  continue
1015
1111
 
1016
- s = getattr(self, inst)
1017
-
1018
1112
  if hasattr(s, '_did_secular_acceleration') and s._did_secular_acceleration:
1019
1113
  continue
1020
1114
 
@@ -1023,8 +1117,37 @@ class RV:
1023
1117
  self._build_arrays()
1024
1118
 
1025
1119
  self._did_secular_acceleration = True
1026
- if return_self:
1120
+ self._did_secular_acceleration_epoch = epoch
1121
+ self._did_secular_acceleration_simbad = force_simbad
1122
+
1123
+ if config.return_self:
1027
1124
  return self
1125
+
1126
+ def _undo_secular_acceleration(self):
1127
+ if self._did_secular_acceleration:
1128
+ _old_verbose = self.verbose
1129
+ self.verbose = False
1130
+ sa = self.secular_acceleration(just_compute=True,
1131
+ force_simbad=self._did_secular_acceleration_simbad)
1132
+ self.verbose = _old_verbose
1133
+ sa = sa.value
1134
+
1135
+ if self._child:
1136
+ self.vrad = self.vrad + sa * (self.time - self._did_secular_acceleration_epoch) / 365.25
1137
+ else:
1138
+ for inst in self.instruments:
1139
+ if 'HIRES' in inst: # never remove it from HIRES...
1140
+ continue
1141
+ if 'NIRPS' in inst: # never remove it from NIRPS...
1142
+ continue
1143
+
1144
+ s = getattr(self, inst)
1145
+
1146
+ s.vrad = s.vrad + sa * (s.time - self._did_secular_acceleration_epoch) / 365.25
1147
+
1148
+ self._build_arrays()
1149
+
1150
+ self._did_secular_acceleration = False
1028
1151
 
1029
1152
  def sigmaclip(self, sigma=5, instrument=None, strict=True):
1030
1153
  """ Sigma-clip RVs (per instrument!) """
@@ -1053,7 +1176,7 @@ class RV:
1053
1176
  # # if insts.size == 1: # of the same instrument?
1054
1177
  # if self.verbose:
1055
1178
  # logger.warning(f'would remove all observations from {insts[0]}, skipping')
1056
- # if return_self:
1179
+ # if config.return_self:
1057
1180
  # return self
1058
1181
  # continue
1059
1182
 
@@ -1065,7 +1188,7 @@ class RV:
1065
1188
  self._did_adjust_means = False
1066
1189
  self.adjust_means()
1067
1190
 
1068
- if return_self:
1191
+ if config.return_self:
1069
1192
  return self
1070
1193
 
1071
1194
  def clip_maxerror(self, maxerror:float):
@@ -1087,7 +1210,7 @@ class RV:
1087
1210
  logger.warning(f'clip_maxerror ({maxerror} {self.units}) removed {n} point' + s)
1088
1211
 
1089
1212
  self._propagate_mask_changes()
1090
- if return_self:
1213
+ if config.return_self:
1091
1214
  return self
1092
1215
 
1093
1216
  def bin(self):
@@ -1220,6 +1343,11 @@ class RV:
1220
1343
  for inst in self.instruments:
1221
1344
  s = getattr(self, inst)
1222
1345
 
1346
+ if s.mtime.size == 0:
1347
+ if self.verbose:
1348
+ logger.info(f'all observations of {inst} are masked')
1349
+ continue
1350
+
1223
1351
  if s.N == 1:
1224
1352
  if self.verbose:
1225
1353
  msg = (f'only 1 observation for {inst}, '
@@ -1231,28 +1359,37 @@ class RV:
1231
1359
 
1232
1360
  s.rv_mean = wmean(s.mvrad, s.msvrad)
1233
1361
  s.vrad -= s.rv_mean
1362
+
1234
1363
  if self.verbose:
1235
1364
  logger.info(f'subtracted weighted average from {inst:10s}: ({s.rv_mean:.3f} {self.units})')
1365
+
1236
1366
  if just_rv:
1237
1367
  continue
1238
- # log_msg = 'same for '
1368
+
1239
1369
  for i, other in enumerate(others):
1240
1370
  y, ye = getattr(s, other), getattr(s, other + '_err')
1241
1371
  m = wmean(y[s.mask], ye[s.mask])
1242
1372
  setattr(s, f'{other}_mean', m)
1243
1373
  setattr(s, other, getattr(s, other) - m)
1244
- # log_msg += other
1245
- # if i < len(others) - 1:
1246
- # log_msg += ', '
1247
-
1248
- # if self.verbose:
1249
- # logger.info(log_msg)
1250
1374
 
1251
1375
  self._build_arrays()
1252
1376
  self._did_adjust_means = True
1253
- if return_self:
1377
+ if config.return_self:
1254
1378
  return self
1255
1379
 
1380
+ def add_to_vrad(self, values):
1381
+ """ Add an array of values to the RVs of all instruments """
1382
+ if values.size != self.vrad.size:
1383
+ raise ValueError(f"incompatible sizes: len(values) must equal self.N, got {values.size} != {self.vrad.size}")
1384
+
1385
+ for inst in self.instruments:
1386
+ s = getattr(self, inst)
1387
+ mask = self.instrument_array == inst
1388
+ s.vrad += values[mask]
1389
+
1390
+ self._build_arrays()
1391
+
1392
+
1256
1393
  def put_at_systemic_velocity(self):
1257
1394
  """
1258
1395
  For instruments in which mean(RV) < ptp(RV), "move" RVs to the systemic
@@ -1474,6 +1611,8 @@ class RV:
1474
1611
 
1475
1612
 
1476
1613
  #
1614
+ from .stellar import calc_prot_age
1615
+
1477
1616
  @property
1478
1617
  def HZ(self):
1479
1618
  if not hasattr(self, 'star_mass'):
@@ -1492,22 +1631,50 @@ class RV:
1492
1631
  return self._planets
1493
1632
 
1494
1633
 
1495
- def fit_sine(t, y, yerr, period='gls', fix_period=False):
1634
+ def fit_sine(t, y, yerr=None, period='gls', fix_period=False):
1635
+ """ Fit a sine curve of the form y = A * sin(2π * t / P + φ) + c
1636
+
1637
+ Args:
1638
+ t (ndarray):
1639
+ Time array
1640
+ y (ndarray):
1641
+ Array of observed values
1642
+ yerr (ndarray, optional):
1643
+ Array of uncertainties. Defaults to None.
1644
+ period (str or float, optional):
1645
+ Initial guess for period or 'gls' to get it from Lomb-Scargle
1646
+ periodogram. Defaults to 'gls'.
1647
+ fix_period (bool, optional):
1648
+ Whether to fix the period. Defaults to False.
1649
+
1650
+ Returns:
1651
+ p (ndarray):
1652
+ Best-fit parameters [A, P, φ, c] or [A, φ, c]
1653
+ f (callable):
1654
+ Function that returns the best-fit sine curve for input times
1655
+ """
1496
1656
  from scipy.optimize import leastsq
1497
1657
  if period == 'gls':
1498
1658
  from astropy.timeseries import LombScargle
1499
1659
  gls = LombScargle(t, y, yerr)
1500
1660
  freq, power = gls.autopower()
1501
1661
  period = 1 / freq[power.argmax()]
1502
-
1503
- if fix_period and period is None:
1504
- logger.error('period is fixed but no value provided')
1505
- return
1506
-
1507
- def sine(t, p):
1508
- return p[0] * np.sin(2 * np.pi * t / p[1] + p[2]) + p[3]
1509
-
1510
- p0 = [y.ptp(), period, 0.0, 0.0]
1511
- xbest, _ = leastsq(lambda p, t, y, ye: (sine(t, p) - y) / ye,
1512
- p0, args=(t, y, yerr))
1662
+ else:
1663
+ period = float(period)
1664
+
1665
+ if yerr is None:
1666
+ yerr = np.ones_like(y)
1667
+
1668
+ if fix_period:
1669
+ def sine(t, p):
1670
+ return p[0] * np.sin(2 * np.pi * t / period + p[1]) + p[2]
1671
+ f = lambda p, t, y, ye: (sine(t, p) - y) / ye
1672
+ p0 = [y.ptp(), 0.0, 0.0]
1673
+ else:
1674
+ def sine(t, p):
1675
+ return p[0] * np.sin(2 * np.pi * t / p[1] + p[2]) + p[3]
1676
+ f = lambda p, t, y, ye: (sine(t, p) - y) / ye
1677
+ p0 = [y.ptp(), period, 0.0, 0.0]
1678
+
1679
+ xbest, _ = leastsq(f, p0, args=(t, y, yerr))
1513
1680
  return xbest, partial(sine, p=xbest)
arvi/translations.py CHANGED
@@ -1,8 +1,10 @@
1
1
  import re
2
2
 
3
3
  STARS = {
4
+ '_51Peg': '51 Peg',
4
5
  'Barnard': 'GJ699',
5
6
  "Barnard's": 'GJ699',
7
+ 'Ross128': 'Ross 128',
6
8
  }
7
9
 
8
10
 
arvi/utils.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import time
2
3
  from contextlib import contextmanager
3
4
  try:
4
5
  from unittest.mock import patch
@@ -19,6 +20,9 @@ except ImportError:
19
20
  tqdm = lambda x, *args, **kwargs: x
20
21
  trange = lambda *args, **kwargs: range(*args, **kwargs)
21
22
 
23
+ from .setup_logger import logger
24
+ from . import config
25
+
22
26
 
23
27
  def create_directory(directory):
24
28
  """ Create a directory if it does not exist """
@@ -61,6 +65,23 @@ def all_logging_disabled():
61
65
  finally:
62
66
  logging.disable(previous_level)
63
67
 
68
+
69
+ @contextmanager
70
+ def timer():
71
+ """ A simple context manager to time a block of code """
72
+ if not config.debug:
73
+ yield
74
+ return
75
+
76
+ logger.debug(f'starting timer')
77
+ start = time.time()
78
+ try:
79
+ yield
80
+ finally:
81
+ end = time.time()
82
+ logger.debug(f'elapsed time: {end - start:.2f} seconds')
83
+
84
+
64
85
  def strtobool(val):
65
86
  """Convert a string representation of truth to true (1) or false (0).
66
87
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: arvi
3
- Version: 0.1.12
3
+ Version: 0.1.14
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT
@@ -0,0 +1,35 @@
1
+ arvi/HZ.py,sha256=u7rguhlILRBW-LOczlY3dkIB4LM8p8W7Xfg4FnNaYG0,2850
2
+ arvi/__init__.py,sha256=stLL3UtXmR1jpNEoMyVohjvkCatunz1w5ZK0ApmWuYQ,814
3
+ arvi/ariadne_wrapper.py,sha256=jv8Wl35LfHl1UH1EklbvxHcQHqaEDhRGNogSYjFt7Y4,2141
4
+ arvi/berv.py,sha256=5avwcmc2nkYH1KDo-z4eMPsS1ElNvold2DWkziV13gE,17633
5
+ arvi/binning.py,sha256=jJ_resqSvfI-2BT0cnGPFckTIei_k2Mk95oZyE5b5zQ,15250
6
+ arvi/config.py,sha256=wyj6FTxN7QOZj8LaHAe_ZdPKVfrNfobNNOHRNLH-S7Q,339
7
+ arvi/dace_wrapper.py,sha256=HmsyThieljcjorSSZgmGTZPGBqNrm9QoPwjoR_GpVKo,17025
8
+ arvi/extra_data.py,sha256=WEEaYeLh52Zdv0uyHO72Ys5MWS3naTAP4wJV2BJ1mbk,2551
9
+ arvi/gaia_wrapper.py,sha256=YxqqlWkLAKBY7AGHfDpNbkOLYWK0lt0L5GZenn0FfxM,3555
10
+ arvi/headers.py,sha256=uvdJebw1M5YkGjE3vJJwYBOnLikib75uuZE9FXB5JJM,1673
11
+ arvi/instrument_specific.py,sha256=fhkvR5jJzpJH7XbT8Fbzkaz6tGeoFYugkJCIAJgSR7o,4746
12
+ arvi/lbl_wrapper.py,sha256=_ViGVkpakvuBR_xhu9XJRV5EKHpj5Go6jBZGJZMIS2Y,11850
13
+ arvi/nasaexo_wrapper.py,sha256=mWt7eHgSZe4MBKCmUvMPTyUPGuiwGTqKugNBvmjOg9s,7306
14
+ arvi/plots.py,sha256=53_rHVh7SeyBylM91PP6mNr7WTGmIoRnR8JfKJPdu7E,25594
15
+ arvi/programs.py,sha256=C0Fbldjf-QEZYYJp5wBKP3h7zraD0O2mJC7Su967STg,4607
16
+ arvi/reports.py,sha256=yrdajC-zz5_kH1Ucc6cU70DK-5dpG0Xyeru-EITKpNo,3355
17
+ arvi/setup_logger.py,sha256=pBzaRTn0hntozjbaRVx0JIbWGuENkvYUApa6uB-FsRo,279
18
+ arvi/simbad_wrapper.py,sha256=fwO0NbMvxAW3RyC58FPkLjXqLs9OkRyK0sYcb0ZVBQA,5571
19
+ arvi/spectra.py,sha256=pTAWSW4vk96DWRQ-6l5mNJHUhiAyaPR-QDjZdOT6Ak0,7489
20
+ arvi/stats.py,sha256=MQiyLvdiAFxIC29uajTy8kuxD-b2Y6mraL4AfWkRJkM,2576
21
+ arvi/stellar.py,sha256=MdO1_-ZXHnMHbkG-a5LvrnYeULy6MCAnWMKPvR4NZxQ,2954
22
+ arvi/timeseries.py,sha256=sdm9l_LHItZHDAVI6r_wsQwkrfbuMX46q3Wqs0y-KGA,60787
23
+ arvi/translations.py,sha256=SUIrJHt3JZdL_GQh3OJyg2Gm3X5ut86w5zW8hZpxHe0,498
24
+ arvi/utils.py,sha256=nuIOuUdysMesWF9ute4v-kbeo6DylWjWW-SJhCsHn9I,4078
25
+ arvi/data/info.svg,sha256=0IMI6W-eFoTD8acnury79WJJakpBwLa4qKS4JWpsXiI,489
26
+ arvi/data/obs_affected_ADC_issues.dat,sha256=tn93uOL0eCTYhireqp1wG-_c3CbxPA7C-Rf-pejVY8M,10853
27
+ arvi/data/obs_affected_blue_cryostat_issues.dat,sha256=z4AK17xfz8tGTDv1FjRvQFnio4XA6PNNfDXuicewHk4,1771
28
+ arvi/data/extra/HD86226_PFS1.rdb,sha256=vfAozbrKHM_j8dYkCBJsuHyD01KEM1asghe2KInwVao,3475
29
+ arvi/data/extra/HD86226_PFS2.rdb,sha256=F2P7dB6gVyzCglUjNheB0hIHVClC5RmARrGwbrY1cfo,4114
30
+ arvi/data/extra/metadata.json,sha256=C69hIw6CohyES6BI9vDWjxwSz7N4VOYX0PCgjXtYFmU,178
31
+ arvi-0.1.14.dist-info/LICENSE,sha256=6JfQgl7SpM55t0EHMFNMnNh-AdkpGW25MwMiTnhdWQg,1068
32
+ arvi-0.1.14.dist-info/METADATA,sha256=duTaG6amS-M9iVUNvfo2RFwnA_fz1gY1ysUB2N_yCaE,1306
33
+ arvi-0.1.14.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
34
+ arvi-0.1.14.dist-info/top_level.txt,sha256=4EeiKDVLD45ztuflTGfQ3TU8GVjJg5Y95xS5XjI-utU,5
35
+ arvi-0.1.14.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5