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.
- {arvi-0.2.2/arvi.egg-info → arvi-0.2.3}/PKG-INFO +1 -1
- {arvi-0.2.2 → arvi-0.2.3}/arvi/__init__.py +7 -19
- {arvi-0.2.2 → arvi-0.2.3}/arvi/binning.py +2 -1
- {arvi-0.2.2 → arvi-0.2.3}/arvi/config.py +12 -4
- {arvi-0.2.2 → arvi-0.2.3}/arvi/dace_wrapper.py +8 -1
- {arvi-0.2.2 → arvi-0.2.3}/arvi/exofop_wrapper.py +2 -1
- {arvi-0.2.2 → arvi-0.2.3}/arvi/extra_data.py +3 -3
- {arvi-0.2.2 → arvi-0.2.3}/arvi/instrument_specific.py +46 -36
- {arvi-0.2.2 → arvi-0.2.3}/arvi/plots.py +7 -2
- arvi-0.2.3/arvi/reports.py +204 -0
- arvi-0.2.3/arvi/setup_logger.py +24 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/simbad_wrapper.py +2 -3
- {arvi-0.2.2 → arvi-0.2.3}/arvi/timeseries.py +10 -6
- {arvi-0.2.2 → arvi-0.2.3}/arvi/utils.py +3 -1
- {arvi-0.2.2 → arvi-0.2.3/arvi.egg-info}/PKG-INFO +1 -1
- {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/SOURCES.txt +1 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/API.md +5 -1
- {arvi-0.2.2 → arvi-0.2.3}/docs/detailed.ipynb +13 -19
- {arvi-0.2.2 → arvi-0.2.3}/mkdocs.yml +22 -2
- arvi-0.2.3/tests/test_config.py +22 -0
- arvi-0.2.3/tests/test_import_object.py +33 -0
- arvi-0.2.2/arvi/reports.py +0 -130
- arvi-0.2.2/arvi/setup_logger.py +0 -20
- arvi-0.2.2/tests/test_import_object.py +0 -17
- {arvi-0.2.2 → arvi-0.2.3}/.github/dependabot.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/docs-gh-pages.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/install.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/.github/workflows/python-publish.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/.gitignore +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/LICENSE +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/README.md +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/HZ.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/ariadne_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/berv.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/HD86226_PFS1.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/HD86226_PFS2.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/extra/metadata.json +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/info.svg +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/obs_affected_ADC_issues.dat +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/data/obs_affected_blue_cryostat_issues.dat +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/gaia_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/headers.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/kima_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/lbl_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/nasaexo_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/programs.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/spectra.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/stats.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/stellar.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi/translations.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/dependency_links.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/requires.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/arvi.egg-info/top_level.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/downloading_data.md +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/index.md +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/logo/detective.png +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/logo/logo.png +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/docs/stylesheets/extra.css +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/pyproject.toml +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/setup.cfg +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/setup.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/tests/HD10700-Bcor_ESPRESSO18.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/tests/test_binning.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/tests/test_create_RV.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/tests/test_simbad.py +0 -0
- {arvi-0.2.2 → arvi-0.2.3}/tests/test_stats.py +0 -0
|
@@ -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
|
|
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
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 .
|
|
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
|
|
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
|
|
@@ -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
|
-
|
|
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":
|
|
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":
|
|
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":
|
|
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
|
-
" <
|
|
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
|
-
" <
|
|
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
|
-
" <
|
|
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
|
-
" <
|
|
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
|
-
|
|
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
|
+
|
arvi-0.2.2/arvi/reports.py
DELETED
|
@@ -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
|
arvi-0.2.2/arvi/setup_logger.py
DELETED
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|