arvi 0.3.0__tar.gz → 0.3.2__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.
Files changed (65) hide show
  1. {arvi-0.3.0/arvi.egg-info → arvi-0.3.2}/PKG-INFO +1 -1
  2. {arvi-0.3.0 → arvi-0.3.2}/arvi/__init__.py +5 -2
  3. {arvi-0.3.0 → arvi-0.3.2}/arvi/config.py +3 -2
  4. {arvi-0.3.0 → arvi-0.3.2}/arvi/dace_wrapper.py +17 -5
  5. {arvi-0.3.0 → arvi-0.3.2}/arvi/plots.py +26 -0
  6. {arvi-0.3.0 → arvi-0.3.2}/arvi/programs.py +15 -21
  7. {arvi-0.3.0 → arvi-0.3.2}/arvi/setup_logger.py +11 -11
  8. {arvi-0.3.0 → arvi-0.3.2}/arvi/simbad_wrapper.py +20 -2
  9. {arvi-0.3.0 → arvi-0.3.2}/arvi/sophie_wrapper.py +1 -1
  10. {arvi-0.3.0 → arvi-0.3.2}/arvi/stats.py +7 -3
  11. {arvi-0.3.0 → arvi-0.3.2/arvi.egg-info}/PKG-INFO +1 -1
  12. {arvi-0.3.0 → arvi-0.3.2}/.github/dependabot.yml +0 -0
  13. {arvi-0.3.0 → arvi-0.3.2}/.github/workflows/docs-gh-pages.yml +0 -0
  14. {arvi-0.3.0 → arvi-0.3.2}/.github/workflows/install.yml +0 -0
  15. {arvi-0.3.0 → arvi-0.3.2}/.github/workflows/python-publish.yml +0 -0
  16. {arvi-0.3.0 → arvi-0.3.2}/.gitignore +0 -0
  17. {arvi-0.3.0 → arvi-0.3.2}/LICENSE +0 -0
  18. {arvi-0.3.0 → arvi-0.3.2}/README.md +0 -0
  19. {arvi-0.3.0 → arvi-0.3.2}/arvi/HZ.py +0 -0
  20. {arvi-0.3.0 → arvi-0.3.2}/arvi/ariadne_wrapper.py +0 -0
  21. {arvi-0.3.0 → arvi-0.3.2}/arvi/berv.py +0 -0
  22. {arvi-0.3.0 → arvi-0.3.2}/arvi/binning.py +0 -0
  23. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/extra/HD86226_PFS1.rdb +0 -0
  24. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/extra/HD86226_PFS2.rdb +0 -0
  25. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/extra/metadata.json +0 -0
  26. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/info.svg +0 -0
  27. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/obs_affected_ADC_issues.dat +0 -0
  28. {arvi-0.3.0 → arvi-0.3.2}/arvi/data/obs_affected_blue_cryostat_issues.dat +0 -0
  29. {arvi-0.3.0 → arvi-0.3.2}/arvi/exofop_wrapper.py +0 -0
  30. {arvi-0.3.0 → arvi-0.3.2}/arvi/extra_data.py +0 -0
  31. {arvi-0.3.0 → arvi-0.3.2}/arvi/gaia_wrapper.py +0 -0
  32. {arvi-0.3.0 → arvi-0.3.2}/arvi/headers.py +0 -0
  33. {arvi-0.3.0 → arvi-0.3.2}/arvi/instrument_specific.py +0 -0
  34. {arvi-0.3.0 → arvi-0.3.2}/arvi/kepmodel_wrapper.py +0 -0
  35. {arvi-0.3.0 → arvi-0.3.2}/arvi/kima_wrapper.py +0 -0
  36. {arvi-0.3.0 → arvi-0.3.2}/arvi/lbl_wrapper.py +0 -0
  37. {arvi-0.3.0 → arvi-0.3.2}/arvi/nasaexo_wrapper.py +0 -0
  38. {arvi-0.3.0 → arvi-0.3.2}/arvi/reports.py +0 -0
  39. {arvi-0.3.0 → arvi-0.3.2}/arvi/spectra.py +0 -0
  40. {arvi-0.3.0 → arvi-0.3.2}/arvi/stellar.py +0 -0
  41. {arvi-0.3.0 → arvi-0.3.2}/arvi/timeseries.py +0 -0
  42. {arvi-0.3.0 → arvi-0.3.2}/arvi/translations.py +0 -0
  43. {arvi-0.3.0 → arvi-0.3.2}/arvi/utils.py +0 -0
  44. {arvi-0.3.0 → arvi-0.3.2}/arvi.egg-info/SOURCES.txt +0 -0
  45. {arvi-0.3.0 → arvi-0.3.2}/arvi.egg-info/dependency_links.txt +0 -0
  46. {arvi-0.3.0 → arvi-0.3.2}/arvi.egg-info/requires.txt +0 -0
  47. {arvi-0.3.0 → arvi-0.3.2}/arvi.egg-info/top_level.txt +0 -0
  48. {arvi-0.3.0 → arvi-0.3.2}/docs/API.md +0 -0
  49. {arvi-0.3.0 → arvi-0.3.2}/docs/detailed.ipynb +0 -0
  50. {arvi-0.3.0 → arvi-0.3.2}/docs/downloading_data.md +0 -0
  51. {arvi-0.3.0 → arvi-0.3.2}/docs/index.md +0 -0
  52. {arvi-0.3.0 → arvi-0.3.2}/docs/logo/detective.png +0 -0
  53. {arvi-0.3.0 → arvi-0.3.2}/docs/logo/logo.png +0 -0
  54. {arvi-0.3.0 → arvi-0.3.2}/docs/stylesheets/extra.css +0 -0
  55. {arvi-0.3.0 → arvi-0.3.2}/mkdocs.yml +0 -0
  56. {arvi-0.3.0 → arvi-0.3.2}/pyproject.toml +0 -0
  57. {arvi-0.3.0 → arvi-0.3.2}/setup.cfg +0 -0
  58. {arvi-0.3.0 → arvi-0.3.2}/setup.py +0 -0
  59. {arvi-0.3.0 → arvi-0.3.2}/tests/HD10700-Bcor_ESPRESSO18.rdb +0 -0
  60. {arvi-0.3.0 → arvi-0.3.2}/tests/test_binning.py +0 -0
  61. {arvi-0.3.0 → arvi-0.3.2}/tests/test_config.py +0 -0
  62. {arvi-0.3.0 → arvi-0.3.2}/tests/test_create_RV.py +0 -0
  63. {arvi-0.3.0 → arvi-0.3.2}/tests/test_import_object.py +0 -0
  64. {arvi-0.3.0 → arvi-0.3.2}/tests/test_simbad.py +0 -0
  65. {arvi-0.3.0 → arvi-0.3.2}/tests/test_stats.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arvi
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT
@@ -17,12 +17,15 @@ def __getattr__(name: str):
17
17
  if not config.fancy_import:
18
18
  raise AttributeError
19
19
 
20
+ if name.startswith('__'):
21
+ return
20
22
  if name in (
21
23
  '_ipython_canary_method_should_not_exist_',
22
24
  '_ipython_display_',
23
- '__custom_documentations__',
24
25
  '_repr_mimebundle_',
25
- '__wrapped__'
26
+ # '__custom_documentations__',
27
+ # '__wrapped__',
28
+ # '__dataframe__'
26
29
  ):
27
30
  return
28
31
 
@@ -36,6 +36,8 @@ class config:
36
36
  'fancy_import': True,
37
37
  # use the 'dark_background' matplotlib theme
38
38
  'dark_plots': False,
39
+ # specific colors per instrument
40
+ 'colors_per_instrument': False,
39
41
  # debug
40
42
  'debug': False,
41
43
  }
@@ -43,7 +45,7 @@ class config:
43
45
 
44
46
  __user_config = get_config()
45
47
 
46
- def __getattr__(self, name):
48
+ def __getattr__(self, name: str):
47
49
  if name in ('__custom_documentations__', ):
48
50
  # return {'return_self': 'help!'}
49
51
  return {}
@@ -54,7 +56,6 @@ class config:
54
56
  value = True if value == 'True' else value
55
57
  value = False if value == 'False' else value
56
58
  self.__conf[name] = value
57
-
58
59
  return self.__conf[name]
59
60
  except KeyError:
60
61
  raise KeyError(f"unknown config option '{name}'")
@@ -310,6 +310,14 @@ def get_observations_from_instrument(star, instrument, user=None, main_id=None,
310
310
  # print([r[k1][k2].keys() for k1 in r.keys() for k2 in r[k1].keys()])
311
311
  return r
312
312
 
313
+ def _warn_harpsn(instrument):
314
+ if 'HARPSN' in instrument or 'HARPS-N' in instrument:
315
+ logger = setup_logger()
316
+ logger.warning(f'Did you mean "HARPN" instead of "{instrument}"?')
317
+ return True
318
+ return False
319
+
320
+
313
321
  def get_observations(star, instrument=None, user=None, main_id=None, verbose=True):
314
322
  logger = setup_logger()
315
323
  if instrument is None:
@@ -331,6 +339,7 @@ def get_observations(star, instrument=None, user=None, main_id=None, verbose=Tru
331
339
  result = get_observations_from_instrument(star, instrument, user, main_id, verbose)
332
340
  except ValueError:
333
341
  msg = f'no {instrument} observations for {star}'
342
+ _warn_harpsn(instrument)
334
343
  raise ValueError(msg) from None
335
344
 
336
345
  # defaultdict --> dict
@@ -410,6 +419,8 @@ def get_observations(star, instrument=None, user=None, main_id=None, verbose=Tru
410
419
  def custom_key(val, strip_EGGS=False):
411
420
  if strip_EGGS:
412
421
  val = val.replace('-EGGS', '').replace(' EGGS', '')
422
+ if val in ('3.3', '3.4', '3.5', '3.6', '3.7', '3.8'):
423
+ val = '0.' + val
413
424
  key = 0
414
425
  key -= 1 if '3.5' in val else 0
415
426
  key -= 1 if 'EGGS' in val else 0
@@ -434,9 +445,10 @@ def get_observations(star, instrument=None, user=None, main_id=None, verbose=Tru
434
445
  logger.info('RVs available from')
435
446
  with logger.contextualize(indent=' '):
436
447
  _inst = ''
437
- for inst in instruments:
448
+ max_len_inst = max([len(inst) for inst in instruments])
449
+ for inst in sorted(instruments):
438
450
  pipelines = list(new_result[inst].keys())
439
- max_len = max([len(pipe) for pipe in pipelines])
451
+ max_len_pipe = max([len(pipe) for pipe in pipelines])
440
452
  for pipe in pipelines:
441
453
  last_pipe = pipe == pipelines[-1]
442
454
  modes = list(new_result[inst][pipe].keys())
@@ -444,11 +456,11 @@ def get_observations(star, instrument=None, user=None, main_id=None, verbose=Tru
444
456
  N = len(new_result[inst][pipe][mode]['rjd'])
445
457
  # LOG
446
458
  if inst == _inst and last_pipe:
447
- logger.info(f'{" ":>12s} └ {pipe:{max_len}s} - {mode} ({N} observations)')
459
+ logger.info(f'{" ":>{max_len_inst}s} └ {pipe:{max_len_pipe}s} - {mode} ({N} observations)')
448
460
  elif inst == _inst:
449
- logger.info(f'{" ":>12s} ├ {pipe:{max_len}s} - {mode} ({N} observations)')
461
+ logger.info(f'{" ":>{max_len_inst}s} ├ {pipe:{max_len_pipe}s} - {mode} ({N} observations)')
450
462
  else:
451
- logger.info(f'{inst:>12s} ├ {pipe:{max_len}s} - {mode} ({N} observations)')
463
+ logger.info(f'{inst:>{max_len_inst}s} ├ {pipe:{max_len_pipe}s} - {mode} ({N} observations)')
452
464
  _inst = inst
453
465
 
454
466
  return new_result
@@ -587,6 +587,32 @@ def plot_xy(self, x, y, ax=None, instrument=None, show_legend=True, **kwargs):
587
587
  return fig, ax
588
588
 
589
589
 
590
+ def plot_several(obj, axs=None, **kwargs):
591
+ try:
592
+ from grid_strategy.strategies import SquareStrategy
593
+ except ImportError:
594
+ raise ImportError("Please install 'grid-strategy' to use this function")
595
+ if axs is None:
596
+ if isinstance(obj, (list, tuple)):
597
+ n = len(obj)
598
+ GS = SquareStrategy().get_grid(n)
599
+ fig = plt.gcf()
600
+ fig.set_size_inches(8, 6)
601
+ axs = [fig.add_subplot(gs) for gs in GS]
602
+ else:
603
+ raise NotImplementedError('`obj` should be a list or tuple')
604
+ else:
605
+ assert isinstance(axs, (list, tuple))
606
+ assert len(axs) == len(obj), 'Number of axes does not match number of objects'
607
+
608
+ kwargs.setdefault('show_legend', False)
609
+ kwargs.setdefault('show_title', True)
610
+
611
+ for ax, s in zip(axs, obj):
612
+ s.plot(ax=ax, **kwargs)
613
+ ax.set(xlabel='', ylabel='')
614
+
615
+
590
616
  # @plot_fast
591
617
  def gls(self, ax=None, label=None, instrument=None,
592
618
  fap=True, fap_method='baluev', adjust_means=config.adjust_means_gls,
@@ -23,6 +23,7 @@ def get_star(star, instrument=None, verbose=False, **kwargs):
23
23
 
24
24
 
25
25
  class LazyRV:
26
+ """ A lazy wrapper around `RV` """
26
27
  def __init__(self, stars: list, instrument: str = None,
27
28
  _parallel_limit=10, _parallel_workers=8):
28
29
  self.stars = stars
@@ -60,25 +61,6 @@ class LazyRV:
60
61
 
61
62
  return result
62
63
 
63
- # # use a with statement to ensure threads are cleaned up promptly
64
- # with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool:
65
- # star_to_RV = {
66
- # pool.submit(get_star, star, self.instrument): star
67
- # for star in self.stars
68
- # }
69
- # logger.info('Querying DACE...')
70
- # pbar = tqdm(concurrent.futures.as_completed(star_to_RV),
71
- # total=self.N, unit='star')
72
- # for future in pbar:
73
- # star = star_to_RV[future]
74
- # pbar.set_description(star)
75
- # try:
76
- # result.append(future.result())
77
- # except ValueError:
78
- # print(f'{star} generated an exception')
79
- # result.append(None)
80
- # return result
81
-
82
64
  def reload(self, **kwargs):
83
65
  self._saved = self._get(**kwargs)
84
66
  return self._saved
@@ -92,12 +74,24 @@ class LazyRV:
92
74
  return self._saved
93
75
 
94
76
  @lru_cache(maxsize=10)
95
- def __getitem__(self, index):
96
- star = self.stars[index]
77
+ def __getitem__(self, index_or_name):
78
+ if isinstance(index_or_name, str):
79
+ index = self.stars.index(index_or_name)
80
+ else:
81
+ index = index_or_name
82
+
97
83
  if self._saved is not None:
98
84
  return self._saved[index]
85
+
86
+ star = self.stars[index]
99
87
  return get_star(star, self.instrument, verbose=True)
100
88
 
89
+ def plot(self, split=20, **kwargs):
90
+ from .plots import plot_several
91
+ from itertools import batched
92
+ S = list(batched(self.__call__(), split))
93
+ for s in S:
94
+ plot_several(s, **kwargs)
101
95
 
102
96
  # sorted by spectral type
103
97
  WG1_stars = [
@@ -2,17 +2,17 @@ import sys
2
2
 
3
3
  def setup_logger():
4
4
  from loguru import logger
5
- try:
6
- import marimo as mo
7
- if mo.running_in_notebook():
8
- raise NotImplementedError
9
- except (NotImplementedError, AttributeError):
10
- pass
11
- except (ImportError, ModuleNotFoundError):
12
- logger.remove()
13
- else:
14
- logger.remove()
15
-
5
+ # try:
6
+ # import marimo as mo
7
+ # if mo.running_in_notebook():
8
+ # return logger
9
+ # raise NotImplementedError
10
+ # except (NotImplementedError, AttributeError):
11
+ # pass
12
+ # except (ImportError, ModuleNotFoundError):
13
+ # logger.remove()
14
+ # else:
15
+ logger.remove()
16
16
  logger.configure(extra={"indent": ""})
17
17
  logger.add(
18
18
  sys.stdout,
@@ -1,4 +1,5 @@
1
1
  import os
2
+ from urllib.error import URLError
2
3
  import requests
3
4
  from dataclasses import dataclass
4
5
  from functools import partial
@@ -64,6 +65,12 @@ JOIN ident ON oidref = oid
64
65
  WHERE id = '{star}';
65
66
  """
66
67
 
68
+ OTYPE_QUERY = """
69
+ SELECT otype FROM basic
70
+ JOIN ident ON oidref = oid
71
+ WHERE id = '{star}';
72
+ """
73
+
67
74
  HD_GJ_HIP_QUERY = """
68
75
  SELECT id2.id
69
76
  FROM ident AS id1 JOIN ident AS id2 USING(oidref)
@@ -209,6 +216,14 @@ class simbad:
209
216
  except IndexError:
210
217
  self.B = self.V = np.nan
211
218
 
219
+ try:
220
+ table21 = run_query(query=OTYPE_QUERY.format(star=self.star))
221
+ if _debug:
222
+ print('table21:\n', table21)
223
+ cols, values = parse_table1(table21, cols, values)
224
+ except IndexError:
225
+ self.otype = None
226
+
212
227
  try:
213
228
  table3 = run_query(query=IDS_QUERY.format(star=self.star))
214
229
  if _debug:
@@ -266,6 +281,8 @@ class simbad:
266
281
  try:
267
282
  setattr(self, col, float(val))
268
283
  except ValueError:
284
+ if val == '':
285
+ val = None
269
286
  setattr(self, col, val)
270
287
 
271
288
  self.coords = SkyCoord(self.ra, self.dec, unit='deg')
@@ -289,9 +306,10 @@ class simbad:
289
306
  else:
290
307
  self.teff = data['teff']
291
308
  self.sweetcat = data
292
-
309
+ except URLError:
310
+ pass
293
311
  except IndexError:
294
- if self.sp_type == '':
312
+ if self.sp_type in (None, ''):
295
313
  if len(self.measurements.teff) > 0:
296
314
  try:
297
315
  self.teff = int(np.mean(self.measurements.teff))
@@ -13,7 +13,7 @@ URL_HEADER = "http://atlas.obs-hp.fr/sophie/sophie.cgi?n=sophiecc&c=i&z=fd&a=t&o
13
13
  def extract_keyword(keyword, text, raise_error=True):
14
14
  for line in text.splitlines():
15
15
  if keyword in line:
16
- value = re.findall(fr'{keyword}\s+([\'\w\d.]+)', line)[0]
16
+ value = re.findall(fr'{keyword}\s+([-\'\w\d.]+)', line)[0]
17
17
  value = value.replace("'", "")
18
18
  try:
19
19
  return float(value)
@@ -1,6 +1,6 @@
1
1
  from functools import partial
2
2
  import numpy as np
3
- from scipy.stats import norm
3
+
4
4
 
5
5
  def wmean(a, e):
6
6
  """Weighted mean of array `a`, with uncertainties given by `e`.
@@ -69,7 +69,7 @@ weighted_median = partial(weighted_quantiles_interpolate, quantiles=0.5)
69
69
 
70
70
 
71
71
 
72
- def sigmaclip_median(a, low=4.0, high=4.0, k=1/norm.ppf(3/4)):
72
+ def sigmaclip_median(a, low=4.0, high=4.0, k=None):
73
73
  """
74
74
  Same as scipy.stats.sigmaclip but using the median and median absolute
75
75
  deviation instead of the mean and standard deviation.
@@ -91,8 +91,12 @@ def sigmaclip_median(a, low=4.0, high=4.0, k=1/norm.ppf(3/4)):
91
91
  - `lower`: Lower clipping limit
92
92
  - `upper`: Upper clipping limit
93
93
  """
94
- from scipy.stats import median_abs_deviation
94
+ from scipy.stats import median_abs_deviation, norm
95
95
  from scipy.stats._stats_py import SigmaclipResult
96
+
97
+ if k is None:
98
+ k = 1 / norm.ppf(3 / 4)
99
+
96
100
  c = np.asarray(a).ravel()
97
101
  delta = 1
98
102
  while delta:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arvi
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT
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
File without changes
File without changes
File without changes
File without changes