arvi 0.2.2__tar.gz → 0.2.3__tar.gz

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.

Files changed (66) hide show
  1. {arvi-0.2.2/arvi.egg-info → arvi-0.2.3}/PKG-INFO +1 -1
  2. {arvi-0.2.2 → arvi-0.2.3}/arvi/__init__.py +7 -19
  3. {arvi-0.2.2 → arvi-0.2.3}/arvi/binning.py +2 -1
  4. {arvi-0.2.2 → arvi-0.2.3}/arvi/config.py +12 -4
  5. {arvi-0.2.2 → arvi-0.2.3}/arvi/dace_wrapper.py +8 -1
  6. {arvi-0.2.2 → arvi-0.2.3}/arvi/exofop_wrapper.py +2 -1
  7. {arvi-0.2.2 → arvi-0.2.3}/arvi/extra_data.py +3 -3
  8. {arvi-0.2.2 → arvi-0.2.3}/arvi/instrument_specific.py +46 -36
  9. {arvi-0.2.2 → arvi-0.2.3}/arvi/plots.py +7 -2
  10. arvi-0.2.3/arvi/reports.py +204 -0
  11. arvi-0.2.3/arvi/setup_logger.py +24 -0
  12. {arvi-0.2.2 → arvi-0.2.3}/arvi/simbad_wrapper.py +2 -3
  13. {arvi-0.2.2 → arvi-0.2.3}/arvi/timeseries.py +10 -6
  14. {arvi-0.2.2 → arvi-0.2.3}/arvi/utils.py +3 -1
  15. {arvi-0.2.2 → arvi-0.2.3/arvi.egg-info}/PKG-INFO +1 -1
  16. {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/SOURCES.txt +1 -0
  17. {arvi-0.2.2 → arvi-0.2.3}/docs/API.md +5 -1
  18. {arvi-0.2.2 → arvi-0.2.3}/docs/detailed.ipynb +13 -19
  19. {arvi-0.2.2 → arvi-0.2.3}/mkdocs.yml +22 -2
  20. arvi-0.2.3/tests/test_config.py +22 -0
  21. arvi-0.2.3/tests/test_import_object.py +33 -0
  22. arvi-0.2.2/arvi/reports.py +0 -130
  23. arvi-0.2.2/arvi/setup_logger.py +0 -20
  24. arvi-0.2.2/tests/test_import_object.py +0 -17
  25. {arvi-0.2.2 → arvi-0.2.3}/.github/dependabot.yml +0 -0
  26. {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/docs-gh-pages.yml +0 -0
  27. {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/install.yml +0 -0
  28. {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/python-publish.yml +0 -0
  29. {arvi-0.2.2 → arvi-0.2.3}/.gitignore +0 -0
  30. {arvi-0.2.2 → arvi-0.2.3}/LICENSE +0 -0
  31. {arvi-0.2.2 → arvi-0.2.3}/README.md +0 -0
  32. {arvi-0.2.2 → arvi-0.2.3}/arvi/HZ.py +0 -0
  33. {arvi-0.2.2 → arvi-0.2.3}/arvi/ariadne_wrapper.py +0 -0
  34. {arvi-0.2.2 → arvi-0.2.3}/arvi/berv.py +0 -0
  35. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/HD86226_PFS1.rdb +0 -0
  36. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/HD86226_PFS2.rdb +0 -0
  37. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/metadata.json +0 -0
  38. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/info.svg +0 -0
  39. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/obs_affected_ADC_issues.dat +0 -0
  40. {arvi-0.2.2 → arvi-0.2.3}/arvi/data/obs_affected_blue_cryostat_issues.dat +0 -0
  41. {arvi-0.2.2 → arvi-0.2.3}/arvi/gaia_wrapper.py +0 -0
  42. {arvi-0.2.2 → arvi-0.2.3}/arvi/headers.py +0 -0
  43. {arvi-0.2.2 → arvi-0.2.3}/arvi/kima_wrapper.py +0 -0
  44. {arvi-0.2.2 → arvi-0.2.3}/arvi/lbl_wrapper.py +0 -0
  45. {arvi-0.2.2 → arvi-0.2.3}/arvi/nasaexo_wrapper.py +0 -0
  46. {arvi-0.2.2 → arvi-0.2.3}/arvi/programs.py +0 -0
  47. {arvi-0.2.2 → arvi-0.2.3}/arvi/spectra.py +0 -0
  48. {arvi-0.2.2 → arvi-0.2.3}/arvi/stats.py +0 -0
  49. {arvi-0.2.2 → arvi-0.2.3}/arvi/stellar.py +0 -0
  50. {arvi-0.2.2 → arvi-0.2.3}/arvi/translations.py +0 -0
  51. {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/dependency_links.txt +0 -0
  52. {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/requires.txt +0 -0
  53. {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/top_level.txt +0 -0
  54. {arvi-0.2.2 → arvi-0.2.3}/docs/downloading_data.md +0 -0
  55. {arvi-0.2.2 → arvi-0.2.3}/docs/index.md +0 -0
  56. {arvi-0.2.2 → arvi-0.2.3}/docs/logo/detective.png +0 -0
  57. {arvi-0.2.2 → arvi-0.2.3}/docs/logo/logo.png +0 -0
  58. {arvi-0.2.2 → arvi-0.2.3}/docs/stylesheets/extra.css +0 -0
  59. {arvi-0.2.2 → arvi-0.2.3}/pyproject.toml +0 -0
  60. {arvi-0.2.2 → arvi-0.2.3}/setup.cfg +0 -0
  61. {arvi-0.2.2 → arvi-0.2.3}/setup.py +0 -0
  62. {arvi-0.2.2 → arvi-0.2.3}/tests/HD10700-Bcor_ESPRESSO18.rdb +0 -0
  63. {arvi-0.2.2 → arvi-0.2.3}/tests/test_binning.py +0 -0
  64. {arvi-0.2.2 → arvi-0.2.3}/tests/test_create_RV.py +0 -0
  65. {arvi-0.2.2 → arvi-0.2.3}/tests/test_simbad.py +0 -0
  66. {arvi-0.2.2 → arvi-0.2.3}/tests/test_stats.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arvi
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- __all__ = ['RV']
1
+ __all__ = ['RV', 'config', 'simbad', 'gaia']
2
2
 
3
3
  from importlib.metadata import version, PackageNotFoundError
4
4
  try:
@@ -8,17 +8,15 @@ except PackageNotFoundError:
8
8
  pass
9
9
 
10
10
  from .config import config
11
- from .timeseries import RV
12
-
13
11
  from .simbad_wrapper import simbad
12
+ from .gaia_wrapper import gaia
14
13
 
15
-
16
- ## OLD
17
- # # the __getattr__ function is always called twice, so we need this
18
- # # to only build and return the RV object on the second time
19
- # _ran_once = False
14
+ from .timeseries import RV
20
15
 
21
16
  def __getattr__(name: str):
17
+ if not config.fancy_import:
18
+ raise AttributeError
19
+
22
20
  if name in (
23
21
  '_ipython_canary_method_should_not_exist_',
24
22
  '_ipython_display_',
@@ -31,15 +29,5 @@ def __getattr__(name: str):
31
29
  globals()[name] = RV(name)
32
30
  return globals()[name]
33
31
  except ValueError as e:
34
- raise ImportError(e) from None
35
- # raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
36
-
37
- ## OLD
38
- # # can't do it any other way :(
39
- # global _ran_once
32
+ raise AttributeError(e)
40
33
 
41
- # if _ran_once:
42
- # _ran_once = False
43
- # return RV(name)
44
- # else:
45
- # _ran_once = True
@@ -1,6 +1,6 @@
1
1
  import numpy as np
2
2
 
3
- from .setup_logger import logger
3
+ from .setup_logger import setup_logger
4
4
 
5
5
  ###############################################################################
6
6
  # the following is mostly a copy of the scipy implementation of
@@ -390,6 +390,7 @@ def binRV(time, rv, err=None, stat='wmean', tstat='wmean', estat='addquad',
390
390
 
391
391
 
392
392
  def bin_ccf_mask(time, ccf_mask):
393
+ logger = setup_logger()
393
394
  indices = binRV(time, None, binning_indices=True)
394
395
  indices = np.r_[indices, time.size]
395
396
  bmask = []
@@ -31,6 +31,8 @@ class config:
31
31
  'check_internet': False,
32
32
  # make all DACE requests without using a .dacerc file
33
33
  'request_as_public': False,
34
+ # enable from arvi import star_name
35
+ 'fancy_import': True,
34
36
  # debug
35
37
  'debug': False,
36
38
  }
@@ -43,10 +45,16 @@ class config:
43
45
  # return {'return_self': 'help!'}
44
46
  return {}
45
47
 
46
- if self.__user_config.has_option('config', name):
47
- self.__conf[name] = self.__user_config.get('config', name)
48
+ try:
49
+ if self.__user_config.has_option('config', name):
50
+ value = self.__user_config.get('config', name)
51
+ value = True if value == 'True' else value
52
+ value = False if value == 'False' else value
53
+ self.__conf[name] = value
48
54
 
49
- return self.__conf[name]
55
+ return self.__conf[name]
56
+ except KeyError:
57
+ raise KeyError(f"unknown config option '{name}'")
50
58
 
51
59
  def __setattr__(self, name, value):
52
60
  if name in config.__setters:
@@ -54,7 +62,7 @@ class config:
54
62
  else:
55
63
  if 'config' not in self.__user_config:
56
64
  self.__user_config.add_section('config')
57
- self.__user_config.set('config', name, value)
65
+ self.__user_config.set('config', name, str(value))
58
66
  save_config(self.__user_config)
59
67
  # raise NameError(f"unknown configuration name '{name}'")
60
68
 
@@ -5,11 +5,13 @@ import collections
5
5
  from functools import lru_cache
6
6
  from itertools import islice
7
7
  import numpy as np
8
- from .setup_logger import logger
8
+
9
+ from .setup_logger import setup_logger
9
10
  from .utils import create_directory, all_logging_disabled, stdout_disabled, tqdm
10
11
 
11
12
 
12
13
  def load_spectroscopy(user=None):
14
+ logger = setup_logger()
13
15
  with all_logging_disabled():
14
16
  from dace_query.spectroscopy import SpectroscopyClass, Spectroscopy as default_Spectroscopy
15
17
  from dace_query import DaceClass
@@ -47,6 +49,7 @@ def load_spectroscopy(user=None):
47
49
 
48
50
  @lru_cache()
49
51
  def get_dace_id(star, verbose=True):
52
+ logger = setup_logger()
50
53
  filters = {"obj_id_catname": {"equal": [star]}}
51
54
  try:
52
55
  with all_logging_disabled():
@@ -58,6 +61,7 @@ def get_dace_id(star, verbose=True):
58
61
  raise ValueError from None
59
62
 
60
63
  def get_arrays(result, latest_pipeline=True, ESPRESSO_mode='HR11', NIRPS_mode='HE', verbose=True):
64
+ logger = setup_logger()
61
65
  arrays = []
62
66
  instruments = [str(i) for i in result.keys()]
63
67
 
@@ -259,6 +263,7 @@ def get_observations_from_instrument(star, instrument, user=None, main_id=None,
259
263
  return r
260
264
 
261
265
  def get_observations(star, instrument=None, user=None, main_id=None, verbose=True):
266
+ logger = setup_logger()
262
267
  if instrument is None:
263
268
  Spectroscopy = load_spectroscopy(user)
264
269
 
@@ -444,6 +449,7 @@ def extract_fits(output_directory, filename=None):
444
449
 
445
450
 
446
451
  def do_symlink_filetype(type, raw_files, output_directory, clobber=False, top_level=None, verbose=True):
452
+ logger = setup_logger()
447
453
  terminations = {
448
454
  'CCF': '_CCF_A.fits',
449
455
  'S1D': '_S1D_A.fits',
@@ -489,6 +495,7 @@ def do_symlink_filetype(type, raw_files, output_directory, clobber=False, top_le
489
495
  def do_download_filetype(type, raw_files, output_directory, clobber=False, user=None,
490
496
  verbose=True, chunk_size=20, parallel_limit=30):
491
497
  """ Download CCFs / S1Ds / S2Ds from DACE """
498
+ logger = setup_logger()
492
499
  raw_files = np.atleast_1d(raw_files)
493
500
 
494
501
  create_directory(output_directory)
@@ -4,9 +4,10 @@ import time
4
4
  import importlib.resources as resources
5
5
  import numpy as np
6
6
 
7
- from .setup_logger import logger
7
+ from .setup_logger import setup_logger
8
8
 
9
9
  def get_toi_list(verbose=True):
10
+ logger = setup_logger()
10
11
  toi_list = resources.files('arvi') / 'data' / 'exofop_toi_list.csv'
11
12
  now = time.time()
12
13
  download = not toi_list.exists() or toi_list.stat().st_mtime < now - 48 * 60 * 60
@@ -3,8 +3,7 @@ from glob import glob
3
3
  import json
4
4
 
5
5
  from numpy import full
6
- from .setup_logger import logger
7
- from . import timeseries
6
+ from .setup_logger import setup_logger
8
7
 
9
8
  refs = {
10
9
  'HD86226': 'Teske et al. 2020 (AJ, 160, 2)'
@@ -12,7 +11,8 @@ refs = {
12
11
 
13
12
  def get_extra_data(star, instrument=None, path=None, verbose=True,
14
13
  check_for_kms=True):
15
-
14
+ from . import timeseries
15
+ logger = setup_logger()
16
16
  if path is None:
17
17
  path = os.path.dirname(__file__)
18
18
  path = os.path.join(path, 'data', 'extra')
@@ -1,7 +1,7 @@
1
1
  import os, sys
2
2
  import numpy as np
3
3
 
4
- from .setup_logger import logger
4
+ from .setup_logger import setup_logger
5
5
  from .utils import ESPRESSO_ADC_issues, ESPRESSO_cryostat_issues
6
6
 
7
7
 
@@ -27,6 +27,7 @@ ESPRESSO_technical_intervention = 58665
27
27
 
28
28
  def divide_ESPRESSO(self):
29
29
  """ Split ESPRESSO data into separate sub ESP18 and ESP19 subsets """
30
+ logger = setup_logger()
30
31
  if self._check_instrument('ESPRESSO', strict=False) is None:
31
32
  return
32
33
  if 'ESPRESSO18' in self.instruments and 'ESPRESSO19' in self.instruments:
@@ -64,6 +65,7 @@ def divide_ESPRESSO(self):
64
65
 
65
66
  def divide_HARPS(self):
66
67
  """ Split HARPS data into separate sub HARPS03 and HARPS15 subsets """
68
+ logger = setup_logger()
67
69
  if self._check_instrument('HARPS', strict=False) is None:
68
70
  return
69
71
  if 'HARPS03' in self.instruments and 'HARPS15' in self.instruments:
@@ -100,6 +102,7 @@ def divide_HARPS(self):
100
102
 
101
103
 
102
104
  def check(self, instrument):
105
+ logger = setup_logger()
103
106
  instruments = self._check_instrument(instrument)
104
107
  if instruments is None:
105
108
  if self.verbose:
@@ -118,6 +121,7 @@ def HARPS_commissioning(self, mask=True, plot=True):
118
121
  plot (bool, optional):
119
122
  Whether to plot the masked points.
120
123
  """
124
+ logger = setup_logger()
121
125
  if check(self, 'HARPS') is None:
122
126
  return
123
127
 
@@ -149,6 +153,7 @@ def HARPS_fiber_commissioning(self, mask=True, plot=True):
149
153
  plot (bool, optional):
150
154
  Whether to plot the masked points.
151
155
  """
156
+ logger = setup_logger()
152
157
  if check(self, 'HARPS') is None:
153
158
  return
154
159
 
@@ -182,6 +187,7 @@ def ADC_issues(self, mask=True, plot=True, check_headers=False):
182
187
  check_headers (bool, optional):
183
188
  Whether to (double-)check the headers for missing/zero keywords.
184
189
  """
190
+ logger = setup_logger()
185
191
  instruments = self._check_instrument('ESPRESSO')
186
192
 
187
193
  if instruments is None:
@@ -225,6 +231,7 @@ def blue_cryostat_issues(self, mask=True, plot=True):
225
231
  mask (bool, optional): Whether to mask out the points.
226
232
  plot (bool, optional): Whether to plot the masked points.
227
233
  """
234
+ logger = setup_logger()
228
235
  instruments = self._check_instrument('ESPRESSO')
229
236
 
230
237
  if instruments is None:
@@ -259,6 +266,7 @@ def qc_scired_issues(self, plot=False, **kwargs):
259
266
  Args:
260
267
  plot (bool, optional): Whether to plot the masked points.
261
268
  """
269
+ logger = setup_logger()
262
270
  from .headers import get_headers
263
271
 
264
272
  instruments = self._check_instrument('ESPRESSO')
@@ -299,38 +307,40 @@ def qc_scired_issues(self, plot=False, **kwargs):
299
307
  return affected
300
308
 
301
309
 
302
- def known_issues(self, mask=True, plot=False, **kwargs):
303
- """ Identify and optionally mask known instrumental issues.
304
-
305
- Args:
306
- mask (bool, optional): Whether to mask out the points.
307
- plot (bool, optional): Whether to plot the masked points.
308
- """
309
- try:
310
- adc = ADC_issues(self, mask, plot, **kwargs)
311
- except IndexError:
312
- logger.error('are the data binned? cannot proceed to mask these points...')
313
-
314
- try:
315
- cryostat = blue_cryostat_issues(self, mask, plot)
316
- except IndexError:
317
- logger.error('are the data binned? cannot proceed to mask these points...')
318
-
319
- try:
320
- harps_comm = HARPS_commissioning(self, mask, plot)
321
- except IndexError:
322
- logger.error('are the data binned? cannot proceed to mask these points...')
323
-
324
- try:
325
- harps_fibers = HARPS_fiber_commissioning(self, mask, plot)
326
- except IndexError:
327
- logger.error('are the data binned? cannot proceed to mask these points...')
328
-
329
- # if None in (adc, cryostat, harps_comm, harps_fibers):
330
- # return
331
-
332
- try:
333
- # return adc | cryostat
334
- return np.logical_or.reduce((adc, cryostat, harps_comm, harps_fibers))
335
- except UnboundLocalError:
336
- return
310
+ class ISSUES:
311
+ def known_issues(self, mask=True, plot=False, **kwargs):
312
+ """ Identify and optionally mask known instrumental issues.
313
+
314
+ Args:
315
+ mask (bool, optional): Whether to mask out the points.
316
+ plot (bool, optional): Whether to plot the masked points.
317
+ """
318
+ logger = setup_logger()
319
+ try:
320
+ adc = ADC_issues(self, mask, plot, **kwargs)
321
+ except IndexError:
322
+ logger.error('are the data binned? cannot proceed to mask these points...')
323
+
324
+ try:
325
+ cryostat = blue_cryostat_issues(self, mask, plot)
326
+ except IndexError:
327
+ logger.error('are the data binned? cannot proceed to mask these points...')
328
+
329
+ try:
330
+ harps_comm = HARPS_commissioning(self, mask, plot)
331
+ except IndexError:
332
+ logger.error('are the data binned? cannot proceed to mask these points...')
333
+
334
+ try:
335
+ harps_fibers = HARPS_fiber_commissioning(self, mask, plot)
336
+ except IndexError:
337
+ logger.error('are the data binned? cannot proceed to mask these points...')
338
+
339
+ # if None in (adc, cryostat, harps_comm, harps_fibers):
340
+ # return
341
+
342
+ try:
343
+ # return adc | cryostat
344
+ return np.logical_or.reduce((adc, cryostat, harps_comm, harps_fibers))
345
+ except UnboundLocalError:
346
+ return
@@ -5,7 +5,7 @@ import numpy as np
5
5
 
6
6
  from astropy.timeseries import LombScargle
7
7
 
8
- from .setup_logger import logger
8
+ from .setup_logger import setup_logger
9
9
  from .config import config
10
10
  from .stats import wmean
11
11
 
@@ -172,6 +172,7 @@ def plot(self, ax=None, show_masked=False, instrument=None, time_offset=0,
172
172
  Figure: the figure
173
173
  Axes: the axis
174
174
  """
175
+ logger = setup_logger()
175
176
  if self.N == 0:
176
177
  if self.verbose:
177
178
  logger.error('no data to plot')
@@ -406,6 +407,7 @@ def plot(self, ax=None, show_masked=False, instrument=None, time_offset=0,
406
407
  def plot_quantity(self, quantity, ax=None, show_masked=False, instrument=None,
407
408
  time_offset=0, remove_50000=False, tooltips=False, show_legend=True,
408
409
  N_in_label=False, **kwargs):
410
+ logger = setup_logger()
409
411
  if self.N == 0:
410
412
  if self.verbose:
411
413
  logger.error('no data to plot')
@@ -531,6 +533,7 @@ def gls(self, ax=None, label=None, instrument=None,
531
533
  Whether to adjust (subtract) the weighted means of each instrument.
532
534
  Default is `config.adjust_means_gls`.
533
535
  """
536
+ logger = setup_logger()
534
537
  if self.N == 0:
535
538
  if self.verbose:
536
539
  logger.error('no data to compute gls')
@@ -692,7 +695,7 @@ def gls_quantity(self, quantity, ax=None, instrument=None,
692
695
  Whether to adjust (subtract) the weighted means of each instrument.
693
696
  Default is `config.adjust_means_gls`.
694
697
  """
695
-
698
+ logger = setup_logger()
696
699
  if not hasattr(self, quantity):
697
700
  if self.verbose:
698
701
  logger.error(f"cannot find '{quantity}' attribute")
@@ -812,6 +815,8 @@ def window_function(self, ax1=None, ax2=None, instrument=None, crosshair=False,
812
815
  crosshair (bool):
813
816
  If True, a crosshair will be drawn on the plot.
814
817
  """
818
+ logger = setup_logger()
819
+
815
820
  if self.N == 0:
816
821
  if self.verbose:
817
822
  logger.error('no data to compute window function')
@@ -0,0 +1,204 @@
1
+ from functools import partial
2
+ import numpy as np
3
+ from astropy.timeseries import LombScargle
4
+
5
+ from .setup_logger import setup_logger
6
+
7
+
8
+ sine_line = None
9
+ residual_gls = None
10
+ def sine_picker(event, self, fig, ax, ax1):
11
+ from .timeseries import fit_sine
12
+ global sine_line, residual_gls
13
+ if sine_line is not None:
14
+ sine_line[0].remove()
15
+ if residual_gls is not None:
16
+ residual_gls[0].remove()
17
+ xdata, ydata = event.artist.get_data()
18
+ ind = event.ind
19
+ period = xdata[ind][0]
20
+ p, sine = fit_sine(self.mtime, self.mvrad, self.msvrad, period=period)
21
+ tt = np.linspace(self.mtime.min(), self.mtime.max(), 100)
22
+ tt -= 50000
23
+ sine_line = ax1.plot(tt, sine(tt), 'k')
24
+ #
25
+ f, p = LombScargle(self.mtime, self.mvrad - sine(self.mtime), self.msvrad).autopower()
26
+ residual_gls = ax.semilogx(1/f, p, 'r')
27
+ fig.canvas.draw_idle()
28
+
29
+
30
+ class REPORTS:
31
+ def summary(self, add_ccf_mask=True, add_prog_id=False, **kwargs):
32
+ from .utils import pretty_print_table
33
+ if isinstance(self, list):
34
+ selfs = self
35
+ else:
36
+ selfs = [self]
37
+
38
+ rows = []
39
+ for self in selfs:
40
+ rows.append([self.star] + [''] * len(self.instruments) + [''])
41
+ rows.append([''] + self.instruments + ['full'])
42
+ rows.append(['N'] + list(self.NN.values()) + [self.N])
43
+ rows.append(['RV span'] + [np.ptp(s.mvrad).round(3) for s in self] + [np.ptp(self.mvrad).round(3)])
44
+ rows.append(['RV std'] + [s.mvrad.std().round(3) for s in self] + [self.mvrad.std().round(3)])
45
+ rows.append(['eRV mean'] + [s.msvrad.mean().round(3) for s in self] + [self.msvrad.mean().round(3)])
46
+
47
+ if add_ccf_mask:
48
+ if hasattr(self, 'ccf_mask'):
49
+ row = ['CCF mask']
50
+ for inst in self.instruments:
51
+ row.append(', '.join(np.unique(getattr(self, inst).ccf_mask)))
52
+ row.append('')
53
+ rows.append(row)
54
+
55
+ if add_prog_id:
56
+ row = ['prog ID']
57
+ for inst in self.instruments:
58
+ p = ', '.join(np.unique(getattr(self, inst).prog_id))
59
+ row.append(p)
60
+ rows.append(row)
61
+
62
+ return pretty_print_table(rows, **kwargs)
63
+
64
+
65
+ def summary_one_instrument(self):
66
+ from .utils import pretty_print_table
67
+ if isinstance(self, list):
68
+ selfs = self
69
+ else:
70
+ selfs = [self]
71
+
72
+ rows = []
73
+ rows.append(['', 'N', 'Δt', 'RV std', 'median σRV'])
74
+ for self in selfs:
75
+ rows.append([
76
+ self.star,
77
+ self.N,
78
+ int(np.ptp(self.mtime).round(0)),
79
+ np.std(self.mvrad).round(1),
80
+ np.median(self.msvrad).round(1),
81
+ ])
82
+
83
+ pretty_print_table(rows)
84
+
85
+
86
+ def summary_stellar(self, show_ra_dec=True, show_pm=True, **kwargs):
87
+ from .utils import pretty_print_table, get_ra_sexagesimal, get_dec_sexagesimal
88
+ if isinstance(self, list):
89
+ selfs = self
90
+ else:
91
+ selfs = [self]
92
+
93
+
94
+
95
+ rows = []
96
+ rows.append(['star'] + [self.star for self in selfs])
97
+ if show_ra_dec:
98
+ rows.append(['RA'] + [get_ra_sexagesimal(self.simbad.ra) for self in selfs])
99
+ rows.append(['DEC'] + [get_dec_sexagesimal(self.simbad.dec) for self in selfs])
100
+
101
+ if show_pm:
102
+ rows.append(['pm ra'] + [(self.gaia or self.simbad).pmra for self in selfs])
103
+ rows.append(['pm dec'] + [(self.gaia or self.simbad).pmdec for self in selfs])
104
+
105
+ rows.append(['π (mas)'] + [(self.gaia or self.simbad).plx for self in selfs])
106
+ #
107
+ rows.append(['B (mag)'] + [self.simbad._B for self in selfs])
108
+ rows.append(['V (mag)'] + [self.simbad._V for self in selfs])
109
+ rows.append(['B-V'] + [self.simbad._B - self.simbad._V for self in selfs])
110
+ rows.append(["log R'HK"] + [np.nanmean(self.rhk).round(2) for self in selfs])
111
+ # rows.append([''] + self.instruments + ['full'])
112
+ # rows.append(['N'] + list(self.NN.values()) + [self.N])
113
+ # rows.append(['RV span'] + [np.ptp(s.mvrad).round(3) for s in self] + [np.ptp(self.mvrad).round(3)])
114
+ # rows.append(['RV std'] + [s.mvrad.std().round(3) for s in self] + [self.mvrad.std().round(3)])
115
+ # rows.append(['eRV mean'] + [s.msvrad.mean().round(3) for s in self] + [self.msvrad.mean().round(3)])
116
+
117
+ return pretty_print_table(rows, **kwargs)
118
+
119
+
120
+
121
+
122
+ def report(self, save=None):
123
+ import matplotlib.pyplot as plt
124
+ import matplotlib.gridspec as gridspec
125
+ from matplotlib.backends.backend_pdf import PdfPages
126
+ logger = setup_logger()
127
+
128
+ # size = A4
129
+ size = 8.27, 11.69
130
+ fig = plt.figure(figsize=size, constrained_layout=True)
131
+ gs = gridspec.GridSpec(5, 3, figure=fig, height_ratios=[2, 2, 1, 1, 0.1])
132
+
133
+ # first row, all columns
134
+ ax1 = plt.subplot(gs[0, :])
135
+
136
+ title = f'{self.star}'
137
+ ax1.set_title(title, loc='left', fontsize=14)
138
+ # ax1.set_title(r"\href{http://www.google.com}{link}", color='blue',
139
+ # loc='center')
140
+
141
+ if self._did_adjust_means:
142
+ title = '(instrument means subtracted) '
143
+ else:
144
+ title = ''
145
+ title += f'V={self.simbad.V}, {self.simbad.sp_type}'
146
+ ax1.set_title(title, loc='right', fontsize=12)
147
+
148
+ self.plot(ax=ax1, N_in_label=True, tooltips=False, remove_50000=True)
149
+
150
+
151
+ ax1.legend().remove()
152
+ legend_ax = plt.subplot(gs[1, -1])
153
+ legend_ax.axis('off')
154
+ leg = plt.legend(*ax1.get_legend_handles_labels(),
155
+ prop={'family': 'monospace'})
156
+ legend_ax.add_artist(leg)
157
+
158
+ second_legend = f'rms : {self.rms:.2f} {self.units}'
159
+ second_legend += f'\nerror: {self.error:.2f} {self.units}'
160
+
161
+ second_legend += f'\n\nCCF masks: {np.unique(self.ccf_mask)}'
162
+
163
+ legend_ax.legend([],
164
+ title=second_legend,
165
+ loc='lower right', frameon=False,
166
+ prop={'family': 'monospace'})
167
+
168
+ ax2 = plt.subplot(gs[1, :-1])
169
+ self.gls(ax=ax2, picker=True)
170
+
171
+ ax3 = plt.subplot(gs[2, :-1])
172
+ self.plot_fwhm(ax=ax3, tooltips=False, remove_50000=True)
173
+ ax3.legend().remove()
174
+ ax3p = plt.subplot(gs[2, -1])
175
+ self.gls_fwhm(ax=ax3p, picker=False)
176
+
177
+ ax4 = plt.subplot(gs[3, :-1])
178
+ self.plot_rhk(ax=ax4, tooltips=False, remove_50000=True)
179
+ ax4.legend().remove()
180
+ ax4p = plt.subplot(gs[3, -1])
181
+ self.gls_rhk(ax=ax4p, picker=False)
182
+
183
+
184
+ if save is None:
185
+ fig.canvas.mpl_connect(
186
+ 'pick_event',
187
+ partial(sine_picker, self=self, fig=fig, ax=ax2, ax1=ax1))
188
+
189
+ if save is not None:
190
+ if save is True:
191
+ save = f'report_{"".join(self.star.split())}.pdf'
192
+
193
+ if save.endswith('.png'):
194
+ fig.savefig(save)
195
+ else:
196
+ with PdfPages(save) as pdf:
197
+ #pdf.attach_note('hello', positionRect=[5, 15, 20, 30])
198
+
199
+ if self.verbose:
200
+ logger.info(f'saving to {save}')
201
+ pdf.savefig(fig)
202
+ # os.system(f'evince {save} &')
203
+
204
+ return fig
@@ -0,0 +1,24 @@
1
+ import sys
2
+
3
+ def setup_logger():
4
+ from loguru import logger
5
+ try:
6
+ import marimo as mo
7
+ if mo.running_in_notebook():
8
+ raise NotImplementedError
9
+ except NotImplementedError:
10
+ pass
11
+ except (ImportError, ModuleNotFoundError):
12
+ logger.remove()
13
+ else:
14
+ logger.remove()
15
+
16
+ logger.configure(extra={"indent": ""})
17
+ logger.add(
18
+ sys.stdout,
19
+ colorize=True,
20
+ # format="<green>{time:YYYY-MM-DDTHH:mm:ss}</green> <level>{message}</level>",
21
+ format="{extra[indent]}<level>{message}</level>",
22
+ )
23
+
24
+ return logger
@@ -1,9 +1,8 @@
1
1
  import os
2
- import numpy as np
3
2
  import requests
4
3
  from dataclasses import dataclass
5
4
 
6
- import pysweetcat
5
+ import numpy as np
7
6
 
8
7
  try:
9
8
  from uncertainties import ufloat
@@ -12,7 +11,6 @@ except ImportError:
12
11
 
13
12
  from .stellar import EFFECTIVE_TEMPERATURES, teff_to_sptype
14
13
  from .translations import translate
15
- from .setup_logger import logger
16
14
 
17
15
  DATA_PATH = os.path.dirname(__file__)
18
16
  DATA_PATH = os.path.join(DATA_PATH, 'data')
@@ -146,6 +144,7 @@ class simbad:
146
144
  star (str): The name of the star to query simbad
147
145
  """
148
146
  from astropy.coordinates import SkyCoord
147
+ import pysweetcat
149
148
 
150
149
  self.star = translate(star, ngc=True, ic=True)
151
150
 
@@ -1,14 +1,16 @@
1
1
  import os
2
2
  from dataclasses import dataclass, field
3
3
  from typing import Union
4
- from functools import lru_cache, partial, partialmethod
4
+ from functools import partial, partialmethod
5
5
  from glob import glob
6
6
  import warnings
7
7
  from copy import deepcopy
8
8
  from datetime import datetime, timezone
9
9
  import numpy as np
10
10
 
11
- from .setup_logger import logger
11
+ from .setup_logger import setup_logger
12
+ logger = setup_logger()
13
+
12
14
  from .config import config
13
15
  from .translations import translate
14
16
  from .dace_wrapper import do_download_filetype, do_symlink_filetype, get_observations, get_arrays
@@ -19,6 +21,8 @@ from .extra_data import get_extra_data
19
21
  from .stats import wmean, wrms
20
22
  from .binning import bin_ccf_mask, binRV
21
23
  from .HZ import getHZ_period
24
+ from .instrument_specific import ISSUES
25
+ from .reports import REPORTS
22
26
  from .utils import sanitize_path, strtobool, there_is_internet, timer, chdir
23
27
  from .utils import lazy_import
24
28
 
@@ -31,8 +35,8 @@ class ExtraFields:
31
35
  return list(self.__dict__.keys())
32
36
 
33
37
 
34
- @dataclass
35
- class RV:
38
+ @dataclass(order=False)
39
+ class RV(ISSUES, REPORTS):
36
40
  """
37
41
  A class holding RV observations
38
42
 
@@ -1245,9 +1249,9 @@ class RV:
1245
1249
 
1246
1250
  from .plots import plot, plot_fwhm, plot_bispan, plot_contrast, plot_rhk, plot_berv, plot_quantity
1247
1251
  from .plots import gls, gls_fwhm, gls_bispan, gls_rhk, gls_quantity, window_function
1248
- from .reports import report
1249
1252
 
1250
- from .instrument_specific import known_issues
1253
+ # from .reports import report
1254
+ # from .instrument_specific import known_issues
1251
1255
 
1252
1256
  def change_instrument_name(self, old_name, new_name, strict=False):
1253
1257
  """ Change the name of an instrument
@@ -21,7 +21,7 @@ except ImportError:
21
21
  tqdm = lambda x, *args, **kwargs: x
22
22
  trange = lambda *args, **kwargs: range(*args, **kwargs)
23
23
 
24
- from .setup_logger import logger
24
+ from .setup_logger import setup_logger
25
25
  from .config import config
26
26
 
27
27
 
@@ -70,6 +70,8 @@ def all_logging_disabled():
70
70
  @contextmanager
71
71
  def timer(name=None):
72
72
  """ A simple context manager to time a block of code """
73
+ logger = setup_logger()
74
+
73
75
  if not config.debug:
74
76
  yield
75
77
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arvi
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT
@@ -54,6 +54,7 @@ docs/logo/logo.png
54
54
  docs/stylesheets/extra.css
55
55
  tests/HD10700-Bcor_ESPRESSO18.rdb
56
56
  tests/test_binning.py
57
+ tests/test_config.py
57
58
  tests/test_create_RV.py
58
59
  tests/test_import_object.py
59
60
  tests/test_simbad.py
@@ -4,13 +4,17 @@ toc: false
4
4
 
5
5
  # API documentation
6
6
 
7
+ ## `arvi.timeseries.RV`
8
+
7
9
  ::: arvi.timeseries.RV
8
10
  handler: python
9
11
  options:
10
- show_root_heading: true
12
+ show_bases: false
13
+ show_root_heading: false
11
14
  show_source: false
12
15
  merge_init_into_class: false
13
16
  group_by_category: true
17
+ show_category_heading: true
14
18
 
15
19
 
16
20
  ## Sub-packages
@@ -2,7 +2,7 @@
2
2
  "cells": [
3
3
  {
4
4
  "cell_type": "code",
5
- "execution_count": 79,
5
+ "execution_count": 1,
6
6
  "metadata": {
7
7
  "tags": [
8
8
  "hide_code"
@@ -36,7 +36,7 @@
36
36
  },
37
37
  {
38
38
  "cell_type": "code",
39
- "execution_count": 80,
39
+ "execution_count": 2,
40
40
  "metadata": {},
41
41
  "outputs": [],
42
42
  "source": [
@@ -45,7 +45,7 @@
45
45
  },
46
46
  {
47
47
  "cell_type": "code",
48
- "execution_count": 81,
48
+ "execution_count": 3,
49
49
  "metadata": {},
50
50
  "outputs": [
51
51
  {
@@ -53,13 +53,7 @@
53
53
  "output_type": "stream",
54
54
  "text": [
55
55
  "\u001b[1mquerying Simbad...\u001b[0m\n",
56
- "\u001b[1mquerying Gaia...\u001b[0m\n"
57
- ]
58
- },
59
- {
60
- "name": "stdout",
61
- "output_type": "stream",
62
- "text": [
56
+ "\u001b[1mquerying Gaia...\u001b[0m\n",
63
57
  "\u001b[1mquerying DACE for HD69830...\u001b[0m\n",
64
58
  "\u001b[33m\u001b[1mrequesting DACE data as public\u001b[0m\n",
65
59
  "\u001b[1mRVs available from\u001b[0m\n",
@@ -181,8 +175,8 @@
181
175
  "metadata": {},
182
176
  "source": [
183
177
  "<div class=\"admonition note\">\n",
184
- " <p class=\"admonition-title\">Note</p>\n",
185
- " <p>\n",
178
+ " <div class=\"admonition-title\">Note</div>\n",
179
+ " <p style=\"margin-top: 1em\">\n",
186
180
  " We used the <code>strict=True</code> option above to select only HIRES and HARPS. By default, the match with the instrument names is done recursively as 'HIRES*', so without <code>strict=True</code> we would have removed both HIRES and HIRES_post04 as well as HARPS and HARPS03.\n",
187
181
  " </p>\n",
188
182
  "</div>"
@@ -379,8 +373,8 @@
379
373
  "metadata": {},
380
374
  "source": [
381
375
  "<div class=\"admonition note\">\n",
382
- " <p class=\"admonition-title\">Note</p>\n",
383
- " <p>\n",
376
+ " <div class=\"admonition-title\">Note</div>\n",
377
+ " <p style=\"margin-top: 1em\">\n",
384
378
  " The names <code>vrad</code> and <code>svrad</code> have become somewhat standard in the community to refer to the radial velocities and their uncertainties.\n",
385
379
  " </p>\n",
386
380
  "</div>"
@@ -555,8 +549,8 @@
555
549
  "metadata": {},
556
550
  "source": [
557
551
  "<div class=\"admonition warning\">\n",
558
- " <p class=\"admonition-title\">Warning</p>\n",
559
- " <p>\n",
552
+ " <div class=\"admonition-title\">Warning</div>\n",
553
+ " <p style=\"margin-top: 1em\">\n",
560
554
  " The <code>remove_instrument</code> method we used above does not modify <code>s.mask</code> but instead completely removes the data from that instrument.\n",
561
555
  " </p>\n",
562
556
  "</div>"
@@ -634,8 +628,8 @@
634
628
  "metadata": {},
635
629
  "source": [
636
630
  "<div class=\"admonition note\">\n",
637
- " <p class=\"admonition-title\">Note</p>\n",
638
- " <p>\n",
631
+ " <div class=\"admonition-title\">Note</div>\n",
632
+ " <p style=\"margin-top: 1em\">\n",
639
633
  " Only the HARPS03 data has log R'HK values, which is why the function warns us about NaN values for the other instruments.\n",
640
634
  " </p>\n",
641
635
  "</div>"
@@ -644,7 +638,7 @@
644
638
  ],
645
639
  "metadata": {
646
640
  "kernelspec": {
647
- "display_name": "Python 3",
641
+ "display_name": "Python 3 (ipykernel)",
648
642
  "language": "python",
649
643
  "name": "python3"
650
644
  },
@@ -1,13 +1,33 @@
1
1
  site_name: arvi
2
-
3
2
  site_dir: _site
4
3
 
4
+ repo_url: https://github.com/j-faria/arvi
5
+ # repo_name: j-faria/arvi
6
+
5
7
  theme:
6
8
  name: "material"
7
9
  logo: logo/detective.png
8
10
  favicon: logo/detective.png
11
+ # palette:
12
+ # primary: amber
9
13
  palette:
10
- primary: amber
14
+ # Palette toggle for light mode
15
+ - media: "(prefers-color-scheme: light)"
16
+ scheme: default
17
+ primary: amber
18
+ accent: indigo
19
+ toggle:
20
+ icon: material/weather-night
21
+ name: Switch to dark mode
22
+ # Palette toggle for dark mode
23
+ - media: "(prefers-color-scheme: dark)"
24
+ scheme: slate
25
+ primary: black
26
+ accent: light blue
27
+ toggle:
28
+ icon: material/weather-sunny
29
+ name: Switch to light mode
30
+
11
31
  features:
12
32
  - content.code.copy
13
33
  - navigation.instant
@@ -0,0 +1,22 @@
1
+ # import pytest
2
+
3
+ def test_config_keys():
4
+ from arvi import config
5
+ assert hasattr(config, 'return_self'), 'config.return_self not found'
6
+ assert hasattr(config, 'adjust_means_gls'), 'config.adjust_means_gls not found'
7
+ assert hasattr(config, 'check_internet'), 'config.check_internet not found'
8
+ assert hasattr(config, 'request_as_public'), 'config.request_as_public not found'
9
+ assert hasattr(config, 'fancy_import'), 'config.fancy_import not found'
10
+ assert hasattr(config, 'debug'), 'config.debug not found'
11
+
12
+
13
+ def test_config_set():
14
+ from arvi import config
15
+ config.return_self = True
16
+ assert config.return_self
17
+
18
+ config.new_option = False
19
+ assert not config.new_option
20
+
21
+ config.new_option_str = 'hello'
22
+ assert config.new_option_str == 'hello'
@@ -0,0 +1,33 @@
1
+ import pytest
2
+ import os
3
+
4
+ def test_import():
5
+ import arvi
6
+ from arvi import RV
7
+
8
+
9
+ def test_import_object():
10
+ from arvi import _51Peg
11
+ from arvi import HD10180
12
+
13
+ def test_import_object_public():
14
+ from arvi import config
15
+
16
+ config.request_as_public = True
17
+
18
+ from arvi import _51Peg
19
+ from arvi import HD10180
20
+
21
+ config.request_as_public = False
22
+
23
+
24
+ def test_fancy_import_off():
25
+ from arvi import config
26
+
27
+ from arvi import HD10180
28
+
29
+ config.fancy_import = False
30
+
31
+ with pytest.raises(ImportError):
32
+ from arvi import HD69830
33
+
@@ -1,130 +0,0 @@
1
- from functools import partial
2
- import numpy as np
3
- from astropy.timeseries import LombScargle
4
-
5
- from .setup_logger import logger
6
-
7
-
8
- sine_line = None
9
- residual_gls = None
10
- def sine_picker(event, self, fig, ax, ax1):
11
- from .timeseries import fit_sine
12
- global sine_line, residual_gls
13
- if sine_line is not None:
14
- sine_line[0].remove()
15
- if residual_gls is not None:
16
- residual_gls[0].remove()
17
- xdata, ydata = event.artist.get_data()
18
- ind = event.ind
19
- period = xdata[ind][0]
20
- p, sine = fit_sine(self.mtime, self.mvrad, self.msvrad, period=period)
21
- tt = np.linspace(self.mtime.min(), self.mtime.max(), 100)
22
- tt -= 50000
23
- sine_line = ax1.plot(tt, sine(tt), 'k')
24
- #
25
- f, p = LombScargle(self.mtime, self.mvrad - sine(self.mtime), self.msvrad).autopower()
26
- residual_gls = ax.semilogx(1/f, p, 'r')
27
- fig.canvas.draw_idle()
28
-
29
-
30
- def summary(self, add_ccf_mask=True, add_prog_id=False):
31
- from .utils import pretty_print_table
32
- rows = []
33
- rows.append([self.star] + [''] * len(self.instruments))
34
- rows.append([''] + self.instruments)
35
- rows.append(['N'] + list(self.NN.values()))
36
-
37
- if add_ccf_mask:
38
- row = ['CCF mask']
39
- for inst in self.instruments:
40
- row.append(', '.join(np.unique(getattr(self, inst).ccf_mask)))
41
- rows.append(row)
42
-
43
- if add_prog_id:
44
- row = ['prog ID']
45
- for inst in self.instruments:
46
- p = ', '.join(np.unique(getattr(self, inst).prog_id))
47
- row.append(p)
48
- rows.append(row)
49
-
50
- pretty_print_table(rows)
51
-
52
-
53
- def report(self, save=None):
54
- import matplotlib.pyplot as plt
55
- import matplotlib.gridspec as gridspec
56
- from matplotlib.backends.backend_pdf import PdfPages
57
-
58
- # size = A4
59
- size = 8.27, 11.69
60
- fig = plt.figure(figsize=size, constrained_layout=True)
61
- gs = gridspec.GridSpec(5, 3, figure=fig, height_ratios=[2, 2, 1, 1, 0.1])
62
-
63
- # first row, all columns
64
- ax1 = plt.subplot(gs[0, :])
65
-
66
- title = f'{self.star}'
67
- ax1.set_title(title, loc='left', fontsize=14)
68
- # ax1.set_title(r"\href{http://www.google.com}{link}", color='blue',
69
- # loc='center')
70
-
71
- if self._did_adjust_means:
72
- title = '(instrument means subtracted) '
73
- else:
74
- title = ''
75
- title += f'V={self.simbad.V}, {self.simbad.sp_type}'
76
- ax1.set_title(title, loc='right', fontsize=12)
77
-
78
- self.plot(ax=ax1, N_in_label=True, tooltips=False, remove_50000=True)
79
-
80
-
81
- ax1.legend().remove()
82
- legend_ax = plt.subplot(gs[1, -1])
83
- legend_ax.axis('off')
84
- leg = plt.legend(*ax1.get_legend_handles_labels(),
85
- prop={'family': 'monospace'})
86
- legend_ax.add_artist(leg)
87
- second_legend = f'rms : {self.rms:.2f} {self.units}\n'
88
- second_legend += f'error: {self.error:.2f} {self.units}'
89
- legend_ax.legend([],
90
- title=second_legend,
91
- loc='lower right', frameon=False,
92
- prop={'family': 'monospace'})
93
-
94
- ax2 = plt.subplot(gs[1, :-1])
95
- self.gls(ax=ax2, picker=True)
96
-
97
- ax3 = plt.subplot(gs[2, :-1])
98
- self.plot_fwhm(ax=ax3, tooltips=False, remove_50000=True)
99
- ax3.legend().remove()
100
- ax3p = plt.subplot(gs[2, -1])
101
- self.gls_fwhm(ax=ax3p, picker=False)
102
-
103
- ax4 = plt.subplot(gs[3, :-1])
104
- self.plot_bis(ax=ax4, tooltips=False, remove_50000=True)
105
- ax4.legend().remove()
106
- ax4p = plt.subplot(gs[3, -1])
107
- self.gls_bis(ax=ax4p, picker=False)
108
-
109
-
110
- if save is None:
111
- fig.canvas.mpl_connect(
112
- 'pick_event',
113
- partial(sine_picker, self=self, fig=fig, ax=ax2, ax1=ax1))
114
-
115
- if save is not None:
116
- if save is True:
117
- save = f'report_{"".join(self.star.split())}.pdf'
118
-
119
- if save.endswith('.png'):
120
- fig.savefig(save)
121
- else:
122
- with PdfPages(save) as pdf:
123
- #pdf.attach_note('hello', positionRect=[5, 15, 20, 30])
124
-
125
- if self.verbose:
126
- logger.info(f'saving to {save}')
127
- pdf.savefig(fig)
128
- # os.system(f'evince {save} &')
129
-
130
- return fig
@@ -1,20 +0,0 @@
1
- import sys
2
- from loguru import logger
3
-
4
- try:
5
- import marimo as mo
6
- if mo.running_in_notebook():
7
- raise ImportError
8
- except (ImportError, ModuleNotFoundError):
9
- pass
10
- else:
11
- logger.remove()
12
-
13
-
14
- logger.configure(extra={"indent": ""})
15
- logger.add(
16
- sys.stdout,
17
- colorize=True,
18
- # format="<green>{time:YYYY-MM-DDTHH:mm:ss}</green> <level>{message}</level>",
19
- format="{extra[indent]}<level>{message}</level>",
20
- )
@@ -1,17 +0,0 @@
1
- import pytest
2
- import os
3
-
4
- def test_import():
5
- import arvi
6
- from arvi import RV
7
-
8
-
9
- def test_import_object():
10
- from arvi import _51Peg
11
-
12
- from arvi import HD10180
13
- # if os.path.exists(os.path.expanduser('~/.dacerc')):
14
- # else:
15
- # with pytest.raises(ImportError):
16
- # from arvi import HD10180
17
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes