arvi 0.2.2__tar.gz → 0.2.4__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.
- {arvi-0.2.2/arvi.egg-info → arvi-0.2.4}/PKG-INFO +2 -2
- {arvi-0.2.2 → arvi-0.2.4}/README.md +1 -1
- {arvi-0.2.2 → arvi-0.2.4}/arvi/__init__.py +7 -19
- {arvi-0.2.2 → arvi-0.2.4}/arvi/binning.py +2 -1
- {arvi-0.2.2 → arvi-0.2.4}/arvi/config.py +15 -4
- {arvi-0.2.2 → arvi-0.2.4}/arvi/dace_wrapper.py +16 -6
- {arvi-0.2.2 → arvi-0.2.4}/arvi/exofop_wrapper.py +2 -1
- {arvi-0.2.2 → arvi-0.2.4}/arvi/extra_data.py +3 -3
- {arvi-0.2.2 → arvi-0.2.4}/arvi/instrument_specific.py +46 -36
- {arvi-0.2.2 → arvi-0.2.4}/arvi/plots.py +95 -7
- arvi-0.2.4/arvi/reports.py +204 -0
- arvi-0.2.4/arvi/setup_logger.py +24 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/simbad_wrapper.py +2 -3
- {arvi-0.2.2 → arvi-0.2.4}/arvi/timeseries.py +10 -6
- {arvi-0.2.2 → arvi-0.2.4}/arvi/utils.py +3 -1
- {arvi-0.2.2 → arvi-0.2.4/arvi.egg-info}/PKG-INFO +2 -2
- {arvi-0.2.2 → arvi-0.2.4}/arvi.egg-info/SOURCES.txt +1 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/API.md +5 -1
- {arvi-0.2.2 → arvi-0.2.4}/docs/detailed.ipynb +13 -19
- {arvi-0.2.2 → arvi-0.2.4}/mkdocs.yml +22 -2
- arvi-0.2.4/tests/test_config.py +22 -0
- arvi-0.2.4/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.4}/.github/dependabot.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/.github/workflows/docs-gh-pages.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/.github/workflows/install.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/.github/workflows/python-publish.yml +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/.gitignore +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/LICENSE +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/HZ.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/ariadne_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/berv.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/extra/HD86226_PFS1.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/extra/HD86226_PFS2.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/extra/metadata.json +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/info.svg +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/obs_affected_ADC_issues.dat +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/data/obs_affected_blue_cryostat_issues.dat +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/gaia_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/headers.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/kima_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/lbl_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/nasaexo_wrapper.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/programs.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/spectra.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/stats.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/stellar.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi/translations.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi.egg-info/dependency_links.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi.egg-info/requires.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/arvi.egg-info/top_level.txt +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/downloading_data.md +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/index.md +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/logo/detective.png +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/logo/logo.png +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/docs/stylesheets/extra.css +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/pyproject.toml +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/setup.cfg +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/setup.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/tests/HD10700-Bcor_ESPRESSO18.rdb +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/tests/test_binning.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/tests/test_create_RV.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/tests/test_simbad.py +0 -0
- {arvi-0.2.2 → arvi-0.2.4}/tests/test_stats.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arvi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: The Automated RV Inspector
|
|
5
5
|
Author-email: João Faria <joao.faria@unige.ch>
|
|
6
6
|
License: MIT
|
|
@@ -23,7 +23,7 @@ Requires-Dist: kepmodel
|
|
|
23
23
|
Dynamic: license-file
|
|
24
24
|
|
|
25
25
|
<p align="center">
|
|
26
|
-
<img width = "140" src="https://
|
|
26
|
+
<img width = "140" src="https://raw.githubusercontent.com/j-faria/arvi/refs/heads/main/docs/logo/logo.png"/>
|
|
27
27
|
</p>
|
|
28
28
|
|
|
29
29
|
This package sits alongside [DACE](https://dace.unige.ch/) to help with the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img width = "140" src="https://
|
|
2
|
+
<img width = "140" src="https://raw.githubusercontent.com/j-faria/arvi/refs/heads/main/docs/logo/logo.png"/>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
This package sits alongside [DACE](https://dace.unige.ch/) to help with the
|
|
@@ -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 = []
|
|
@@ -8,6 +8,7 @@ def get_config_path():
|
|
|
8
8
|
|
|
9
9
|
def get_config():
|
|
10
10
|
config = configparser.ConfigParser()
|
|
11
|
+
config.add_section('config')
|
|
11
12
|
if (path := get_config_path()).exists():
|
|
12
13
|
config.read(path)
|
|
13
14
|
return config
|
|
@@ -31,6 +32,10 @@ class config:
|
|
|
31
32
|
'check_internet': False,
|
|
32
33
|
# make all DACE requests without using a .dacerc file
|
|
33
34
|
'request_as_public': False,
|
|
35
|
+
# enable from arvi import star_name
|
|
36
|
+
'fancy_import': True,
|
|
37
|
+
# use the 'dark_background' matplotlib theme
|
|
38
|
+
'dark_plots': False,
|
|
34
39
|
# debug
|
|
35
40
|
'debug': False,
|
|
36
41
|
}
|
|
@@ -43,10 +48,16 @@ class config:
|
|
|
43
48
|
# return {'return_self': 'help!'}
|
|
44
49
|
return {}
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
try:
|
|
52
|
+
if self.__user_config.has_option('config', name):
|
|
53
|
+
value = self.__user_config.get('config', name)
|
|
54
|
+
value = True if value == 'True' else value
|
|
55
|
+
value = False if value == 'False' else value
|
|
56
|
+
self.__conf[name] = value
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
return self.__conf[name]
|
|
59
|
+
except KeyError:
|
|
60
|
+
raise KeyError(f"unknown config option '{name}'")
|
|
50
61
|
|
|
51
62
|
def __setattr__(self, name, value):
|
|
52
63
|
if name in config.__setters:
|
|
@@ -54,7 +65,7 @@ class config:
|
|
|
54
65
|
else:
|
|
55
66
|
if 'config' not in self.__user_config:
|
|
56
67
|
self.__user_config.add_section('config')
|
|
57
|
-
self.__user_config.set('config', name, value)
|
|
68
|
+
self.__user_config.set('config', name, str(value))
|
|
58
69
|
save_config(self.__user_config)
|
|
59
70
|
# raise NameError(f"unknown configuration name '{name}'")
|
|
60
71
|
|
|
@@ -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
|
|
@@ -45,8 +47,10 @@ def load_spectroscopy(user=None):
|
|
|
45
47
|
logger.warning('requesting DACE data as public (no .dacerc file found)')
|
|
46
48
|
return default_Spectroscopy
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
@lru_cache(maxsize=1024)
|
|
52
|
+
def get_dace_id(star, verbose=True, raise_error=False):
|
|
53
|
+
logger = setup_logger()
|
|
50
54
|
filters = {"obj_id_catname": {"equal": [star]}}
|
|
51
55
|
try:
|
|
52
56
|
with all_logging_disabled():
|
|
@@ -55,9 +59,13 @@ def get_dace_id(star, verbose=True):
|
|
|
55
59
|
except KeyError:
|
|
56
60
|
if verbose:
|
|
57
61
|
logger.error(f"Could not find DACE ID for {star}")
|
|
62
|
+
if not raise_error:
|
|
63
|
+
return None
|
|
58
64
|
raise ValueError from None
|
|
59
65
|
|
|
66
|
+
|
|
60
67
|
def get_arrays(result, latest_pipeline=True, ESPRESSO_mode='HR11', NIRPS_mode='HE', verbose=True):
|
|
68
|
+
logger = setup_logger()
|
|
61
69
|
arrays = []
|
|
62
70
|
instruments = [str(i) for i in result.keys()]
|
|
63
71
|
|
|
@@ -66,7 +74,6 @@ def get_arrays(result, latest_pipeline=True, ESPRESSO_mode='HR11', NIRPS_mode='H
|
|
|
66
74
|
|
|
67
75
|
# select ESPRESSO mode, which is defined at the level of the pipeline
|
|
68
76
|
if 'ESPRESSO' in inst:
|
|
69
|
-
|
|
70
77
|
find_mode = [ESPRESSO_mode in pipe for pipe in pipelines]
|
|
71
78
|
# the mode was not found
|
|
72
79
|
if not any(find_mode):
|
|
@@ -160,12 +167,12 @@ def get_observations_from_instrument(star, instrument, user=None, main_id=None,
|
|
|
160
167
|
|
|
161
168
|
found_dace_id = False
|
|
162
169
|
try:
|
|
163
|
-
dace_id = get_dace_id(star, verbose=verbose)
|
|
170
|
+
dace_id = get_dace_id(star, verbose=verbose, raise_error=True)
|
|
164
171
|
found_dace_id = True
|
|
165
172
|
except ValueError as e:
|
|
166
173
|
if main_id is not None:
|
|
167
174
|
try:
|
|
168
|
-
dace_id = get_dace_id(main_id, verbose=verbose)
|
|
175
|
+
dace_id = get_dace_id(main_id, verbose=verbose, raise_error=True)
|
|
169
176
|
found_dace_id = True
|
|
170
177
|
except ValueError:
|
|
171
178
|
pass
|
|
@@ -259,6 +266,7 @@ def get_observations_from_instrument(star, instrument, user=None, main_id=None,
|
|
|
259
266
|
return r
|
|
260
267
|
|
|
261
268
|
def get_observations(star, instrument=None, user=None, main_id=None, verbose=True):
|
|
269
|
+
logger = setup_logger()
|
|
262
270
|
if instrument is None:
|
|
263
271
|
Spectroscopy = load_spectroscopy(user)
|
|
264
272
|
|
|
@@ -444,6 +452,7 @@ def extract_fits(output_directory, filename=None):
|
|
|
444
452
|
|
|
445
453
|
|
|
446
454
|
def do_symlink_filetype(type, raw_files, output_directory, clobber=False, top_level=None, verbose=True):
|
|
455
|
+
logger = setup_logger()
|
|
447
456
|
terminations = {
|
|
448
457
|
'CCF': '_CCF_A.fits',
|
|
449
458
|
'S1D': '_S1D_A.fits',
|
|
@@ -489,6 +498,7 @@ def do_symlink_filetype(type, raw_files, output_directory, clobber=False, top_le
|
|
|
489
498
|
def do_download_filetype(type, raw_files, output_directory, clobber=False, user=None,
|
|
490
499
|
verbose=True, chunk_size=20, parallel_limit=30):
|
|
491
500
|
""" Download CCFs / S1Ds / S2Ds from DACE """
|
|
501
|
+
logger = setup_logger()
|
|
492
502
|
raw_files = np.atleast_1d(raw_files)
|
|
493
503
|
|
|
494
504
|
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
|
|
|
@@ -13,10 +13,12 @@ from .utils import lazy_import
|
|
|
13
13
|
plt = lazy_import('matplotlib.pyplot')
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def
|
|
16
|
+
def plot_settings(func):
|
|
17
17
|
@wraps(func)
|
|
18
18
|
def wrapper(*args, **kwargs):
|
|
19
|
-
with plt.style.context('fast'):
|
|
19
|
+
# with plt.style.context('fast'):
|
|
20
|
+
theme = 'dark_background' if config.dark_plots else 'fast'
|
|
21
|
+
with plt.style.context(theme):
|
|
20
22
|
return func(*args, **kwargs)
|
|
21
23
|
return wrapper
|
|
22
24
|
|
|
@@ -135,7 +137,7 @@ def clickable_legend(fig, ax, leg):
|
|
|
135
137
|
pass
|
|
136
138
|
return on_pick_legend
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
@plot_settings
|
|
139
141
|
def plot(self, ax=None, show_masked=False, instrument=None, time_offset=0,
|
|
140
142
|
remove_50000=False, tooltips=True, show_title=False, show_legend=True, label=None,
|
|
141
143
|
jitter=None, N_in_label=False, versus_n=False, show_histogram=False, bw=False, **kwargs):
|
|
@@ -172,6 +174,7 @@ def plot(self, ax=None, show_masked=False, instrument=None, time_offset=0,
|
|
|
172
174
|
Figure: the figure
|
|
173
175
|
Axes: the axis
|
|
174
176
|
"""
|
|
177
|
+
logger = setup_logger()
|
|
175
178
|
if self.N == 0:
|
|
176
179
|
if self.verbose:
|
|
177
180
|
logger.error('no data to plot')
|
|
@@ -402,10 +405,11 @@ def plot(self, ax=None, show_masked=False, instrument=None, time_offset=0,
|
|
|
402
405
|
return fig, ax
|
|
403
406
|
|
|
404
407
|
|
|
405
|
-
@plot_fast
|
|
408
|
+
# @plot_fast
|
|
406
409
|
def plot_quantity(self, quantity, ax=None, show_masked=False, instrument=None,
|
|
407
410
|
time_offset=0, remove_50000=False, tooltips=False, show_legend=True,
|
|
408
411
|
N_in_label=False, **kwargs):
|
|
412
|
+
logger = setup_logger()
|
|
409
413
|
if self.N == 0:
|
|
410
414
|
if self.verbose:
|
|
411
415
|
logger.error('no data to plot')
|
|
@@ -504,7 +508,88 @@ plot_rhk = partialmethod(plot_quantity, quantity='rhk')
|
|
|
504
508
|
plot_berv = partialmethod(plot_quantity, quantity='berv')
|
|
505
509
|
|
|
506
510
|
|
|
507
|
-
|
|
511
|
+
def plot_xy(self, x, y, ax=None, instrument=None, show_legend=True, **kwargs):
|
|
512
|
+
logger = setup_logger()
|
|
513
|
+
if self.N == 0:
|
|
514
|
+
if self.verbose:
|
|
515
|
+
logger.error('no data to plot')
|
|
516
|
+
return
|
|
517
|
+
|
|
518
|
+
if ax is None:
|
|
519
|
+
fig, ax = plt.subplots(1, 1, constrained_layout=True)
|
|
520
|
+
else:
|
|
521
|
+
fig = ax.figure
|
|
522
|
+
|
|
523
|
+
kwargs.setdefault('marker', 'o')
|
|
524
|
+
kwargs.setdefault('ls', '')
|
|
525
|
+
kwargs.setdefault('capsize', 0)
|
|
526
|
+
kwargs.setdefault('ms', 4)
|
|
527
|
+
|
|
528
|
+
instruments = self._check_instrument(instrument)
|
|
529
|
+
|
|
530
|
+
for inst in instruments:
|
|
531
|
+
s = self if self._child else getattr(self, inst)
|
|
532
|
+
label = inst
|
|
533
|
+
|
|
534
|
+
missing = False
|
|
535
|
+
try:
|
|
536
|
+
xdata = getattr(s, x).copy()
|
|
537
|
+
except AttributeError:
|
|
538
|
+
missing = True
|
|
539
|
+
try:
|
|
540
|
+
e_xdata = getattr(s, x + '_err').copy()
|
|
541
|
+
except AttributeError:
|
|
542
|
+
e_xdata = np.zeros_like(xdata)
|
|
543
|
+
|
|
544
|
+
try:
|
|
545
|
+
ydata = getattr(s, y).copy()
|
|
546
|
+
except AttributeError:
|
|
547
|
+
missing = True
|
|
548
|
+
try:
|
|
549
|
+
e_ydata = getattr(s, y + '_err').copy()
|
|
550
|
+
except AttributeError:
|
|
551
|
+
e_ydata = np.zeros_like(ydata)
|
|
552
|
+
|
|
553
|
+
if missing:
|
|
554
|
+
lines, *_ = ax.errorbar([], [], [],
|
|
555
|
+
label=label, picker=True, **kwargs)
|
|
556
|
+
continue
|
|
557
|
+
|
|
558
|
+
ax.errorbar(xdata[s.mask], ydata[s.mask], e_xdata[s.mask], e_ydata[s.mask],
|
|
559
|
+
label=label, **kwargs)
|
|
560
|
+
|
|
561
|
+
# if show_masked:
|
|
562
|
+
# ax.errorbar(self.time[~self.mask] - time_offset,
|
|
563
|
+
# getattr(self, quantity)[~self.mask],
|
|
564
|
+
# getattr(self, quantity + '_err')[~self.mask],
|
|
565
|
+
# label='masked', fmt='x', ms=10, color='k', zorder=-2)
|
|
566
|
+
|
|
567
|
+
if show_legend:
|
|
568
|
+
leg = ax.legend()
|
|
569
|
+
on_pick_legend = clickable_legend(fig, ax, leg)
|
|
570
|
+
plt.connect('pick_event', on_pick_legend)
|
|
571
|
+
|
|
572
|
+
ax.minorticks_on()
|
|
573
|
+
|
|
574
|
+
delta = 'Δ' if self._did_adjust_means else ''
|
|
575
|
+
|
|
576
|
+
# ylabel = {
|
|
577
|
+
# quantity.lower(): quantity,
|
|
578
|
+
# 'fwhm': f'{delta}FWHM [{self.units}]',
|
|
579
|
+
# 'bispan': f'{delta}BIS [{self.units}]',
|
|
580
|
+
# 'rhk': r"$\log$ R'$_{HK}$",
|
|
581
|
+
# 'berv': 'BERV [km/s]',
|
|
582
|
+
# }
|
|
583
|
+
|
|
584
|
+
# ax.set_ylabel(ylabel[quantity.lower()])
|
|
585
|
+
|
|
586
|
+
if config.return_self:
|
|
587
|
+
return self
|
|
588
|
+
else:
|
|
589
|
+
return fig, ax
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
# @plot_fast
|
|
508
593
|
def gls(self, ax=None, label=None, instrument=None,
|
|
509
594
|
fap=True, fap_method='baluev', adjust_means=config.adjust_means_gls,
|
|
510
595
|
picker=True, **kwargs):
|
|
@@ -531,6 +616,7 @@ def gls(self, ax=None, label=None, instrument=None,
|
|
|
531
616
|
Whether to adjust (subtract) the weighted means of each instrument.
|
|
532
617
|
Default is `config.adjust_means_gls`.
|
|
533
618
|
"""
|
|
619
|
+
logger = setup_logger()
|
|
534
620
|
if self.N == 0:
|
|
535
621
|
if self.verbose:
|
|
536
622
|
logger.error('no data to compute gls')
|
|
@@ -692,7 +778,7 @@ def gls_quantity(self, quantity, ax=None, instrument=None,
|
|
|
692
778
|
Whether to adjust (subtract) the weighted means of each instrument.
|
|
693
779
|
Default is `config.adjust_means_gls`.
|
|
694
780
|
"""
|
|
695
|
-
|
|
781
|
+
logger = setup_logger()
|
|
696
782
|
if not hasattr(self, quantity):
|
|
697
783
|
if self.verbose:
|
|
698
784
|
logger.error(f"cannot find '{quantity}' attribute")
|
|
@@ -812,6 +898,8 @@ def window_function(self, ax1=None, ax2=None, instrument=None, crosshair=False,
|
|
|
812
898
|
crosshair (bool):
|
|
813
899
|
If True, a crosshair will be drawn on the plot.
|
|
814
900
|
"""
|
|
901
|
+
logger = setup_logger()
|
|
902
|
+
|
|
815
903
|
if self.N == 0:
|
|
816
904
|
if self.verbose:
|
|
817
905
|
logger.error('no data to compute window function')
|