arvi 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arvi/__init__.py +3 -20
- arvi/dace_wrapper.py +47 -3
- arvi/simbad_wrapper.py +16 -7
- arvi/timeseries.py +49 -11
- arvi/utils.py +32 -0
- {arvi-0.0.2.dist-info → arvi-0.0.3.dist-info}/METADATA +1 -1
- arvi-0.0.3.dist-info/RECORD +15 -0
- arvi-0.0.2.dist-info/RECORD +0 -14
- {arvi-0.0.2.dist-info → arvi-0.0.3.dist-info}/LICENSE +0 -0
- {arvi-0.0.2.dist-info → arvi-0.0.3.dist-info}/WHEEL +0 -0
- {arvi-0.0.2.dist-info → arvi-0.0.3.dist-info}/top_level.txt +0 -0
arvi/__init__.py
CHANGED
|
@@ -1,30 +1,13 @@
|
|
|
1
|
-
__version__ = '0.0.
|
|
1
|
+
__version__ = '0.0.3'
|
|
2
2
|
__all__ = []
|
|
3
3
|
|
|
4
4
|
from .timeseries import RV
|
|
5
5
|
|
|
6
6
|
_ran_once = False
|
|
7
|
+
|
|
7
8
|
def __getattr__(name: str):
|
|
8
|
-
global _ran_once
|
|
9
|
+
global _ran_once # can't do it any other way :(
|
|
9
10
|
if _ran_once:
|
|
10
11
|
return RV(name)
|
|
11
12
|
else:
|
|
12
13
|
_ran_once = True
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# from importlib import import_module
|
|
16
|
-
|
|
17
|
-
# HACK_IMPORTS = True
|
|
18
|
-
|
|
19
|
-
# if HACK_IMPORTS:
|
|
20
|
-
# timeseries = import_module('.timeseries', 'arvi')
|
|
21
|
-
# class FakeModule(object):
|
|
22
|
-
# def __getattribute__(self, name):
|
|
23
|
-
# print(name)
|
|
24
|
-
# r = RV(name)
|
|
25
|
-
# return r
|
|
26
|
-
# # first, load (some) subpackages
|
|
27
|
-
# # then, replace the 'arvi' module to allow for dynamic imports
|
|
28
|
-
# # of the type "from arvi import HD1"
|
|
29
|
-
# import sys
|
|
30
|
-
# sys.modules['arvi'] = FakeModule()
|
arvi/dace_wrapper.py
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tarfile
|
|
1
3
|
import numpy as np
|
|
2
|
-
from dace_query
|
|
4
|
+
from dace_query import DaceClass
|
|
5
|
+
from dace_query.spectroscopy import SpectroscopyClass, Spectroscopy as default_Spectroscopy
|
|
3
6
|
from .setup_logger import logger
|
|
4
7
|
|
|
8
|
+
def load_spectroscopy():
|
|
9
|
+
if 'DACERC' in os.environ:
|
|
10
|
+
dace = DaceClass(dace_rc_config_path=os.environ['DACERC'])
|
|
11
|
+
return SpectroscopyClass(dace_instance=dace)
|
|
12
|
+
# elif os.path.exists(os.path.expanduser('~/.dacerc')):
|
|
13
|
+
return default_Spectroscopy
|
|
14
|
+
|
|
5
15
|
|
|
6
16
|
def get_arrays(result, latest_pipeline=True):
|
|
7
17
|
arrays = []
|
|
@@ -25,11 +35,22 @@ def get_arrays(result, latest_pipeline=True):
|
|
|
25
35
|
|
|
26
36
|
|
|
27
37
|
def get_observations(star, save_rdb=False, verbose=True):
|
|
38
|
+
Spectroscopy = load_spectroscopy()
|
|
28
39
|
result = Spectroscopy.get_timeseries(target=star,
|
|
29
40
|
sorted_by_instrument=True,
|
|
30
41
|
output_format='numpy')
|
|
31
42
|
instruments = list(result.keys())
|
|
32
43
|
|
|
44
|
+
# sort pipelines, being extra careful with HARPS pipeline names
|
|
45
|
+
# (i.e. ensure that 3.0.0 > 3.5)
|
|
46
|
+
class sorter:
|
|
47
|
+
def __call__(self, x):
|
|
48
|
+
return '0.3.5' if x == '3.5' else x
|
|
49
|
+
|
|
50
|
+
for inst in instruments:
|
|
51
|
+
result[inst] = dict(sorted(result[inst].items(),
|
|
52
|
+
key=sorter(), reverse=True))
|
|
53
|
+
|
|
33
54
|
if verbose:
|
|
34
55
|
logger.info('RVs available from')
|
|
35
56
|
with logger.contextualize(indent=' '):
|
|
@@ -44,5 +65,28 @@ def get_observations(star, save_rdb=False, verbose=True):
|
|
|
44
65
|
return result
|
|
45
66
|
|
|
46
67
|
|
|
47
|
-
def
|
|
48
|
-
|
|
68
|
+
def do_download_ccf(raw_files, output_directory, verbose=True):
|
|
69
|
+
raw_files = np.atleast_1d(raw_files)
|
|
70
|
+
if not os.path.isdir(output_directory):
|
|
71
|
+
os.makedirs(output_directory)
|
|
72
|
+
if verbose:
|
|
73
|
+
logger.info(f"Downloading {len(raw_files)} CCFs into '{output_directory}'...")
|
|
74
|
+
|
|
75
|
+
Spectroscopy = load_spectroscopy()
|
|
76
|
+
|
|
77
|
+
from .utils import all_logging_disabled, stdout_disabled
|
|
78
|
+
with stdout_disabled(), all_logging_disabled():
|
|
79
|
+
Spectroscopy.download_files(raw_files[:2],
|
|
80
|
+
file_type='ccf',
|
|
81
|
+
output_directory=output_directory)
|
|
82
|
+
|
|
83
|
+
if verbose:
|
|
84
|
+
logger.info('Extracting .fits files')
|
|
85
|
+
|
|
86
|
+
file = os.path.join(output_directory, 'spectroscopy_download.tar.gz')
|
|
87
|
+
tar = tarfile.open(file, "r")
|
|
88
|
+
for member in tar.getmembers():
|
|
89
|
+
if member.isreg(): # skip if the TarInfo is not a file
|
|
90
|
+
member.name = os.path.basename(member.name) # remove the path
|
|
91
|
+
tar.extract(member, output_directory)
|
|
92
|
+
os.remove(file)
|
arvi/simbad_wrapper.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
2
|
import requests
|
|
3
3
|
|
|
4
|
+
from astropy.coordinates import SkyCoord
|
|
5
|
+
|
|
4
6
|
QUERY = """
|
|
5
7
|
SELECT basic.OID,
|
|
6
8
|
RA,
|
|
@@ -58,6 +60,7 @@ class simbad:
|
|
|
58
60
|
Attributes:
|
|
59
61
|
ra (float): right ascension
|
|
60
62
|
dec (float): declination
|
|
63
|
+
coords (SkyCoord): coordinates as a SkyCoord object
|
|
61
64
|
main_id (str): main identifier
|
|
62
65
|
plx_value (float): parallax
|
|
63
66
|
rvz_radvel (float): radial velocity
|
|
@@ -72,15 +75,18 @@ class simbad:
|
|
|
72
75
|
star (str): The name of the star to query simbad
|
|
73
76
|
"""
|
|
74
77
|
self.star = star
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
try:
|
|
79
|
+
table1 = run_query(query=QUERY.format(star=star))
|
|
80
|
+
cols, values = parse_table(table1)
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
table2 = run_query(query=BV_QUERY.format(star=star))
|
|
83
|
+
cols, values = parse_table(table2, cols, values)
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
table3 = run_query(query=IDS_QUERY.format(star=star))
|
|
86
|
+
line = table3.splitlines()[2]
|
|
87
|
+
self.ids = line.replace('"', '').replace(' ', ' ').split('|')
|
|
88
|
+
except IndexError:
|
|
89
|
+
raise ValueError(f'simbad query for {star} failed')
|
|
84
90
|
|
|
85
91
|
for col, val in zip(cols, values):
|
|
86
92
|
try:
|
|
@@ -88,6 +94,9 @@ class simbad:
|
|
|
88
94
|
except ValueError:
|
|
89
95
|
setattr(self, col, val)
|
|
90
96
|
|
|
97
|
+
self.coords = SkyCoord(self.ra, self.dec, unit='deg')
|
|
98
|
+
|
|
99
|
+
|
|
91
100
|
def __repr__(self):
|
|
92
101
|
V = self.V
|
|
93
102
|
sp_type = self.sp_type
|
arvi/timeseries.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Union
|
|
2
3
|
from functools import partial
|
|
3
4
|
from datetime import datetime, timezone
|
|
4
5
|
import numpy as np
|
|
5
6
|
|
|
6
7
|
from .setup_logger import logger
|
|
7
8
|
from .translations import translate
|
|
8
|
-
from .dace_wrapper import get_observations, get_arrays
|
|
9
|
+
from .dace_wrapper import get_observations, get_arrays, do_download_ccf
|
|
9
10
|
from .simbad_wrapper import simbad
|
|
10
11
|
from .stats import wmean, wrms
|
|
11
12
|
|
|
@@ -29,6 +30,7 @@ class RV:
|
|
|
29
30
|
N: int = field(init=False, repr=True)
|
|
30
31
|
verbose: bool = field(init=True, repr=False, default=True)
|
|
31
32
|
do_sigma_clip: bool = field(init=True, repr=False, default=True)
|
|
33
|
+
do_maxerror: Union[bool, float] = field(init=True, repr=False, default=100)
|
|
32
34
|
do_adjust_means: bool = field(init=True, repr=False, default=True)
|
|
33
35
|
#
|
|
34
36
|
_child: bool = field(init=True, repr=False, default=False)
|
|
@@ -37,7 +39,10 @@ class RV:
|
|
|
37
39
|
|
|
38
40
|
def __post_init__(self):
|
|
39
41
|
self.__star__ = translate(self.star)
|
|
40
|
-
|
|
42
|
+
try:
|
|
43
|
+
self.simbad = simbad(self.__star__)
|
|
44
|
+
except ValueError as e:
|
|
45
|
+
logger.error(e.msg)
|
|
41
46
|
|
|
42
47
|
if not self._child:
|
|
43
48
|
if self.verbose:
|
|
@@ -71,11 +76,16 @@ class RV:
|
|
|
71
76
|
# all other quantities
|
|
72
77
|
self._build_arrays()
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
# do clip_maxerror, sigmaclip, adjust_means
|
|
80
|
+
if not self._child:
|
|
81
|
+
if self.do_maxerror:
|
|
82
|
+
self.clip_maxerror(self.do_maxerror)
|
|
83
|
+
|
|
84
|
+
if self.do_sigma_clip:
|
|
85
|
+
self.sigmaclip()
|
|
76
86
|
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
if self.do_adjust_means:
|
|
88
|
+
self.adjust_means()
|
|
79
89
|
|
|
80
90
|
|
|
81
91
|
def reload(self):
|
|
@@ -171,6 +181,21 @@ class RV:
|
|
|
171
181
|
)
|
|
172
182
|
setattr(self, q, arr)
|
|
173
183
|
|
|
184
|
+
|
|
185
|
+
def download_ccf(self, instrument=None):
|
|
186
|
+
directory = f'{self.star}_downloads'
|
|
187
|
+
if instrument is None:
|
|
188
|
+
files = [file for file in self.raw_file if file.endswith('.fits')]
|
|
189
|
+
else:
|
|
190
|
+
if instrument not in self.instruments:
|
|
191
|
+
logger.error(f"No data from instrument '{instrument}'")
|
|
192
|
+
logger.info(f'available: {self.instruments}')
|
|
193
|
+
return
|
|
194
|
+
files = getattr(self, instrument).raw_file
|
|
195
|
+
|
|
196
|
+
do_download_ccf(files, directory)
|
|
197
|
+
|
|
198
|
+
|
|
174
199
|
from .plots import plot, plot_fwhm, plot_bis
|
|
175
200
|
from .plots import gls, gls_fwhm, gls_bis
|
|
176
201
|
from .reports import report
|
|
@@ -237,12 +262,19 @@ class RV:
|
|
|
237
262
|
self.mask[~ind] = False
|
|
238
263
|
self._propagate_mask_changes()
|
|
239
264
|
|
|
240
|
-
def
|
|
265
|
+
def clip_maxerror(self, maxerror:float, plot=False):
|
|
241
266
|
""" Mask out points with RV error larger than `maxerror` """
|
|
242
267
|
if self._child:
|
|
243
268
|
return
|
|
244
269
|
self.maxerror = maxerror
|
|
245
|
-
self.
|
|
270
|
+
above = self.svrad > maxerror
|
|
271
|
+
n = above.sum()
|
|
272
|
+
self.mask[above] = False
|
|
273
|
+
|
|
274
|
+
if self.verbose and above.sum() > 0:
|
|
275
|
+
s = 's' if (n == 0 or n > 1) else ''
|
|
276
|
+
logger.warning(f'clip_maxerror removed {n} point' + s)
|
|
277
|
+
|
|
246
278
|
self._propagate_mask_changes()
|
|
247
279
|
|
|
248
280
|
def adjust_means(self, just_rv=False):
|
|
@@ -258,13 +290,19 @@ class RV:
|
|
|
258
290
|
logger.info(f'subtracted weighted average from {inst:10s}: ({s.rv_mean:.3f} {self.units})')
|
|
259
291
|
if just_rv:
|
|
260
292
|
continue
|
|
261
|
-
|
|
293
|
+
log_msg = 'same for '
|
|
294
|
+
for i, other in enumerate(others):
|
|
262
295
|
y, ye = getattr(s, other), getattr(s, other + '_err')
|
|
263
296
|
m = wmean(y, ye)
|
|
264
297
|
setattr(s, f'{other}_mean', m)
|
|
265
298
|
setattr(s, other, getattr(s, other) - m)
|
|
266
|
-
|
|
267
|
-
|
|
299
|
+
log_msg += other
|
|
300
|
+
if i < len(others) - 1:
|
|
301
|
+
log_msg += ', '
|
|
302
|
+
|
|
303
|
+
if self.verbose:
|
|
304
|
+
logger.info(log_msg)
|
|
305
|
+
|
|
268
306
|
self._build_arrays()
|
|
269
307
|
self._did_adjust_means = True
|
|
270
308
|
|
arvi/utils.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from mock import patch
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@contextmanager
|
|
8
|
+
def stdout_disabled():
|
|
9
|
+
devnull = open(os.devnull, 'w')
|
|
10
|
+
with patch('sys.stdout', devnull):
|
|
11
|
+
yield
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@contextmanager
|
|
15
|
+
def all_logging_disabled():
|
|
16
|
+
"""
|
|
17
|
+
A context manager that will prevent any logging messages triggered during
|
|
18
|
+
the body from being processed.
|
|
19
|
+
"""
|
|
20
|
+
# two kind-of hacks here:
|
|
21
|
+
# * can't get the highest logging level in effect => delegate to the user
|
|
22
|
+
# * can't get the current module-level override => use an undocumented
|
|
23
|
+
# (but non-private!) interface
|
|
24
|
+
|
|
25
|
+
previous_level = logging.root.manager.disable
|
|
26
|
+
|
|
27
|
+
logging.disable(logging.CRITICAL)
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
yield
|
|
31
|
+
finally:
|
|
32
|
+
logging.disable(previous_level)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
arvi/__init__.py,sha256=d4UTdSj3oRwFvO1a_m5uz_fqEVFR9U-afio38MNuESU,241
|
|
2
|
+
arvi/dace_wrapper.py,sha256=0zId_2uti-_UOkCZHJnRvajO5EMNgwNfc5AgV-LjSPQ,3340
|
|
3
|
+
arvi/plots.py,sha256=uOruz1xhlx7nNjIEtLTX6gs_iya2Yds71eIYoYt2LVw,6925
|
|
4
|
+
arvi/reports.py,sha256=FtalLbmBHOSHQ3RldImUZTHPc3cc3Z3W5r3d-31FIo8,3261
|
|
5
|
+
arvi/setup_logger.py,sha256=nvnd2PtXYnpYMGleTeqAKFe-TnC6SjNlTZ-EmiewLyY,278
|
|
6
|
+
arvi/simbad_wrapper.py,sha256=7XnuM7Kq5kK4EchHjh-uyRoTWm6kCx0sx7Ak0eDaALo,3023
|
|
7
|
+
arvi/stats.py,sha256=OIlXisf_kuUhfDRhvCirmJ2e-YSIJnoBjdFOXaYd0bQ,868
|
|
8
|
+
arvi/timeseries.py,sha256=tWKAn5tCQpI1YaCE_breyQ_dXAsj0X06jox4nH9ES5E,11159
|
|
9
|
+
arvi/translations.py,sha256=eyUJei8wlsyBecTz8E_ntpP35-Mre2Tzm_mUMMGaZWY,150
|
|
10
|
+
arvi/utils.py,sha256=OPb6rXafv7b8vRRTEg9zQAQnhi3lRLICF62R8Fhy43A,788
|
|
11
|
+
arvi-0.0.3.dist-info/LICENSE,sha256=6JfQgl7SpM55t0EHMFNMnNh-AdkpGW25MwMiTnhdWQg,1068
|
|
12
|
+
arvi-0.0.3.dist-info/METADATA,sha256=01PYughU6O-f6cwMA_6elKUMallpnN5uaxN6k8xgeys,827
|
|
13
|
+
arvi-0.0.3.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
14
|
+
arvi-0.0.3.dist-info/top_level.txt,sha256=4EeiKDVLD45ztuflTGfQ3TU8GVjJg5Y95xS5XjI-utU,5
|
|
15
|
+
arvi-0.0.3.dist-info/RECORD,,
|
arvi-0.0.2.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
arvi/__init__.py,sha256=rEegmfeT2Xy3gBLpx7_MZOHUcbo_Mg_4aPlD_QsGzaI,708
|
|
2
|
-
arvi/dace_wrapper.py,sha256=N3-cdj8YrryZFA4Tztrb3cJ-2MKgWjLV0rJ6bue8bQQ,1567
|
|
3
|
-
arvi/plots.py,sha256=uOruz1xhlx7nNjIEtLTX6gs_iya2Yds71eIYoYt2LVw,6925
|
|
4
|
-
arvi/reports.py,sha256=FtalLbmBHOSHQ3RldImUZTHPc3cc3Z3W5r3d-31FIo8,3261
|
|
5
|
-
arvi/setup_logger.py,sha256=nvnd2PtXYnpYMGleTeqAKFe-TnC6SjNlTZ-EmiewLyY,278
|
|
6
|
-
arvi/simbad_wrapper.py,sha256=oCcyoWPtkP2RntUNZ3Y0pPFk1hK2nawRlYHCpTRETaE,2725
|
|
7
|
-
arvi/stats.py,sha256=OIlXisf_kuUhfDRhvCirmJ2e-YSIJnoBjdFOXaYd0bQ,868
|
|
8
|
-
arvi/timeseries.py,sha256=KHTUHEgp7m_ZQYGufntn-pHwFqzVhAlqFWuFolsWUEM,9893
|
|
9
|
-
arvi/translations.py,sha256=eyUJei8wlsyBecTz8E_ntpP35-Mre2Tzm_mUMMGaZWY,150
|
|
10
|
-
arvi-0.0.2.dist-info/LICENSE,sha256=6JfQgl7SpM55t0EHMFNMnNh-AdkpGW25MwMiTnhdWQg,1068
|
|
11
|
-
arvi-0.0.2.dist-info/METADATA,sha256=U7NMIBTxucQP3aY7siFcaR04dXGfxthu3HEI40bi7xI,827
|
|
12
|
-
arvi-0.0.2.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
13
|
-
arvi-0.0.2.dist-info/top_level.txt,sha256=4EeiKDVLD45ztuflTGfQ3TU8GVjJg5Y95xS5XjI-utU,5
|
|
14
|
-
arvi-0.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|