arvi 0.2.1__py3-none-any.whl → 0.2.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.

Potentially problematic release.


This version of arvi might be problematic. Click here for more details.

arvi/reports.py CHANGED
@@ -2,7 +2,7 @@ from functools import partial
2
2
  import numpy as np
3
3
  from astropy.timeseries import LombScargle
4
4
 
5
- from .setup_logger import logger
5
+ from .setup_logger import setup_logger
6
6
 
7
7
 
8
8
  sine_line = None
@@ -27,104 +27,178 @@ def sine_picker(event, self, fig, ax, ax1):
27
27
  fig.canvas.draw_idle()
28
28
 
29
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)
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
121
35
  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
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
arvi/setup_logger.py CHANGED
@@ -1,11 +1,24 @@
1
1
  import sys
2
- from loguru import logger
3
2
 
4
- logger.remove()
5
- logger.configure(extra={"indent": ""})
6
- logger.add(
7
- sys.stdout,
8
- colorize=True,
9
- # format="<green>{time:YYYY-MM-DDTHH:mm:ss}</green> <level>{message}</level>",
10
- format="{extra[indent]}<level>{message}</level>",
11
- )
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
arvi/simbad_wrapper.py CHANGED
@@ -1,9 +1,8 @@
1
1
  import os
2
- import numpy as np
3
2
  import requests
4
3
  from dataclasses import dataclass
5
4
 
6
- import pysweetcat
5
+ import numpy as np
7
6
 
8
7
  try:
9
8
  from uncertainties import ufloat
@@ -12,7 +11,6 @@ except ImportError:
12
11
 
13
12
  from .stellar import EFFECTIVE_TEMPERATURES, teff_to_sptype
14
13
  from .translations import translate
15
- from .setup_logger import logger
16
14
 
17
15
  DATA_PATH = os.path.dirname(__file__)
18
16
  DATA_PATH = os.path.join(DATA_PATH, 'data')
@@ -146,6 +144,7 @@ class simbad:
146
144
  star (str): The name of the star to query simbad
147
145
  """
148
146
  from astropy.coordinates import SkyCoord
147
+ import pysweetcat
149
148
 
150
149
  self.star = translate(star, ngc=True, ic=True)
151
150
 
@@ -170,41 +169,52 @@ class simbad:
170
169
  if _debug:
171
170
  print('table1:', table1)
172
171
  cols, values = parse_table1(table1)
172
+ except IndexError:
173
+ raise ValueError(f'simbad query for {star} failed') from None
173
174
 
175
+ try:
174
176
  table2 = run_query(query=BV_QUERY.format(star=self.star))
175
177
  if _debug:
176
178
  print('table2:', table2)
177
179
  cols, values = parse_table1(table2, cols, values)
180
+ except IndexError:
181
+ self.B = self.V = np.nan
178
182
 
183
+ try:
179
184
  table3 = run_query(query=IDS_QUERY.format(star=self.star))
180
185
  if _debug:
181
186
  print('table3:', table3)
182
187
  line = table3.splitlines()[2]
183
188
  self.ids = line.replace('"', '').replace(' ', ' ').replace(' ', ' ').replace(' ', ' ').split('|')
189
+ except IndexError:
190
+ self.ids = []
191
+
192
+ table4 = run_query(query=FILTERS_QUERY.format(star=self.star))
193
+ if _debug:
194
+ print('table4:\n', table4)
195
+ for row in table4.splitlines()[2:]:
196
+ filter_name, mag, mag_err, bibcode = row.replace('"', '').split('|')
197
+ filter_name = filter_name.strip()
198
+ try:
199
+ setattr(self, '_' + filter_name, ufloat(float(mag), float(mag_err)))
200
+ except ValueError:
201
+ setattr(self, '_' + filter_name, float(mag))
184
202
 
185
- table4 = run_query(query=FILTERS_QUERY.format(star=self.star))
186
- for row in table4.splitlines()[2:]:
187
- filter_name, mag, mag_err, bibcode = row.replace('"', '').split('|')
188
- filter_name = filter_name.strip()
189
- try:
190
- setattr(self, '_' + filter_name, ufloat(float(mag), float(mag_err)))
191
- except ValueError:
192
- setattr(self, '_' + filter_name, float(mag))
193
-
194
- # measurements table
195
- table5 = run_query(query=MEAS_QUERY.format(star=self.star))
196
- _teff, _logg, _feh, _bibcode = [], [], [], []
197
- for row in table5.splitlines()[2:]:
198
- teff, log_g, log_g_prec, fe_h, fe_h_prec, bibcode = row.replace('"', '').split('|')
199
- _bibcode.append(bibcode)
200
- _teff.append(parse_value(teff))
201
- _logg.append(parse_value(log_g, prec=log_g_prec))
202
- _feh.append(parse_value(fe_h, prec=fe_h_prec))
203
-
204
- self.measurements = Measurements(_teff, _logg, _feh, _bibcode)
203
+ # measurements table
204
+ table5 = run_query(query=MEAS_QUERY.format(star=self.star))
205
+ if _debug:
206
+ print('table5:\n', table5)
207
+
208
+ _teff, _logg, _feh, _bibcode = [], [], [], []
209
+ for row in table5.splitlines()[2:]:
210
+ teff, log_g, log_g_prec, fe_h, fe_h_prec, bibcode = row.replace('"', '').split('|')
211
+ _bibcode.append(bibcode)
212
+ _teff.append(parse_value(teff))
213
+ _logg.append(parse_value(log_g, prec=log_g_prec))
214
+ _feh.append(parse_value(fe_h, prec=fe_h_prec))
215
+
216
+ self.measurements = Measurements(_teff, _logg, _feh, _bibcode)
205
217
 
206
- except IndexError:
207
- raise ValueError(f'simbad query for {star} failed') from None
208
218
 
209
219
  try:
210
220
  self.gaia_id = int([i for i in self.ids if 'Gaia DR3' in i][0]
@@ -245,8 +255,9 @@ class simbad:
245
255
 
246
256
  except IndexError:
247
257
  if self.sp_type == '':
248
- self.teff = int(np.mean(self.measurements.teff))
249
- self.sp_type = teff_to_sptype(self.teff)
258
+ if len(self.measurements.teff) > 0:
259
+ self.teff = int(np.mean(self.measurements.teff))
260
+ self.sp_type = teff_to_sptype(self.teff)
250
261
  elif self.sp_type[:2] in EFFECTIVE_TEMPERATURES:
251
262
  self.teff = EFFECTIVE_TEMPERATURES[self.sp_type[:2]]
252
263
 
arvi/timeseries.py CHANGED
@@ -1,23 +1,28 @@
1
1
  import os
2
2
  from dataclasses import dataclass, field
3
3
  from typing import Union
4
- from functools import lru_cache, partial, partialmethod
4
+ from functools import partial, partialmethod
5
5
  from glob import glob
6
6
  import warnings
7
7
  from copy import deepcopy
8
8
  from datetime import datetime, timezone
9
9
  import numpy as np
10
10
 
11
- from .setup_logger import logger
11
+ from .setup_logger import setup_logger
12
+ logger = setup_logger()
13
+
12
14
  from .config import config
13
15
  from .translations import translate
14
16
  from .dace_wrapper import do_download_filetype, do_symlink_filetype, get_observations, get_arrays
15
17
  from .simbad_wrapper import simbad
16
18
  from .gaia_wrapper import gaia
19
+ from .exofop_wrapper import exofop
17
20
  from .extra_data import get_extra_data
18
21
  from .stats import wmean, wrms
19
22
  from .binning import bin_ccf_mask, binRV
20
23
  from .HZ import getHZ_period
24
+ from .instrument_specific import ISSUES
25
+ from .reports import REPORTS
21
26
  from .utils import sanitize_path, strtobool, there_is_internet, timer, chdir
22
27
  from .utils import lazy_import
23
28
 
@@ -30,8 +35,8 @@ class ExtraFields:
30
35
  return list(self.__dict__.keys())
31
36
 
32
37
 
33
- @dataclass
34
- class RV:
38
+ @dataclass(order=False)
39
+ class RV(ISSUES, REPORTS):
35
40
  """
36
41
  A class holding RV observations
37
42
 
@@ -68,23 +73,29 @@ class RV:
68
73
  _did_adjust_means: bool = field(init=False, repr=False, default=False)
69
74
  _did_simbad_query: bool = field(init=False, repr=False, default=False)
70
75
  _did_gaia_query: bool = field(init=False, repr=False, default=False)
76
+ _did_toi_query: bool = field(init=False, repr=False, default=False)
71
77
  _raise_on_error: bool = field(init=True, repr=False, default=True)
78
+ __masked_numbers: bool = field(init=False, repr=False, default=False)
72
79
  #
73
80
  _simbad = None
74
81
  _gaia = None
82
+ _toi = None
75
83
 
76
84
  def __repr__(self):
77
85
  ni = len(self.instruments)
78
86
  if self.N == 0:
79
87
  return f"RV(star='{self.star}', N=0)"
80
88
 
81
- i = f'{ni} instrument' + ('s' if ni > 1 else '')
89
+ if self._child:
90
+ i = ''
91
+ else:
92
+ i = f', {ni} instrument' + ('s' if ni > 1 else '')
82
93
 
83
94
  if self.time.size == self.mtime.size:
84
- return f"RV(star='{self.star}', N={self.N}, {i})"
95
+ return f"RV(star='{self.star}', N={self.N}{i})"
85
96
  else:
86
97
  nmasked = self.N - self.mtime.size
87
- return f"RV(star='{self.star}', N={self.N}, masked={nmasked}, {i})"
98
+ return f"RV(star='{self.star}', N={self.N}, masked={nmasked}{i})"
88
99
 
89
100
  @property
90
101
  def simbad(self):
@@ -144,6 +155,26 @@ class RV:
144
155
  self._did_gaia_query = True
145
156
  return self._gaia
146
157
 
158
+ @property
159
+ def toi(self):
160
+ if self._toi is not None:
161
+ return self._toi
162
+
163
+ if 'TOI' not in self.__star__ or 'TIC' not in self.__star__ or self._child or self._did_toi_query:
164
+ return None
165
+
166
+ if self.verbose:
167
+ logger.info('querying ExoFOP...')
168
+
169
+ try:
170
+ self._toi = exofop(self.__star__)
171
+ except ValueError:
172
+ if self.verbose:
173
+ logger.error(f'ExoFOP query for {self.__star__} failed')
174
+
175
+ self._did_toi_query = True
176
+ return self._toi
177
+
147
178
  def __post_init_special_sun(self):
148
179
  import pickle
149
180
  from .extra_data import get_sun_data
@@ -168,7 +199,7 @@ class RV:
168
199
  import concurrent.futures
169
200
  with timer('simbad and gaia queries'):
170
201
  with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
171
- executor.map(self.__getattribute__, ('simbad', 'gaia'))
202
+ executor.map(self.__getattribute__, ('simbad', 'gaia', 'toi'))
172
203
 
173
204
  # with timer('simbad query'):
174
205
  # self.simbad
@@ -241,7 +272,6 @@ class RV:
241
272
  # all other quantities
242
273
  self._build_arrays()
243
274
 
244
-
245
275
  if self.load_extra_data:
246
276
  if isinstance(self.load_extra_data, str):
247
277
  path = self.load_extra_data
@@ -314,6 +344,16 @@ class RV:
314
344
  for inst in self.instruments:
315
345
  yield getattr(self, inst)
316
346
 
347
+ @property
348
+ def _masked_numbers(self):
349
+ return self.__masked_numbers
350
+
351
+ @_masked_numbers.setter
352
+ def _masked_numbers(self, value):
353
+ self.__masked_numbers = value
354
+ if not self._child:
355
+ for s in self:
356
+ s._masked_numbers = value
317
357
 
318
358
  def reload(self):
319
359
  self._did_secular_acceleration = False
@@ -335,19 +375,35 @@ class RV:
335
375
  @property
336
376
  def N(self) -> int:
337
377
  """Total number of observations"""
378
+ if self._masked_numbers:
379
+ return self.mtime.size
338
380
  return self.time.size
339
381
 
340
382
  @property
341
383
  def NN(self):
342
384
  """ Total number of observations per instrument """
385
+ if self._child:
386
+ return {self.instruments[0]: self.N}
343
387
  return {inst: getattr(self, inst).N for inst in self.instruments}
344
388
 
345
389
  @property
346
390
  def N_nights(self) -> int:
347
391
  """ Number of individual nights """
348
- if self.mtime.size == 0:
349
- return 0
350
- return binRV(self.mtime, None, None, binning_bins=True).size - 1
392
+ def get_nights(t):
393
+ return binRV(t, None, None, binning_bins=True).size - 1
394
+
395
+ if self._masked_numbers:
396
+ if self._child:
397
+ return get_nights(self.mtime)
398
+ else:
399
+ return sum([get_nights(s.mtime) for s in self])
400
+ else:
401
+ if self._child:
402
+ return get_nights(self.time)
403
+ else:
404
+ return sum([get_nights(s.time) for s in self])
405
+ # return binRV(_t, None, None, binning_bins=True).size - 1
406
+ # return sum(list(self.NN.values()))
351
407
 
352
408
  @property
353
409
  def NN_nights(self):
@@ -516,8 +572,8 @@ class RV:
516
572
  return s
517
573
 
518
574
  @classmethod
519
- def from_rdb(cls, files, star=None, instrument=None, units='ms',
520
- header_skip=2, **kwargs):
575
+ def from_rdb(cls, files, star=None, instrument=None, instrument_suffix=None,
576
+ units='ms', header_skip=2, **kwargs):
521
577
  """ Create an RV object from an rdb file or a list of rdb files
522
578
 
523
579
  Args:
@@ -568,6 +624,9 @@ class RV:
568
624
  if instruments.size == 1 and len(files) > 1:
569
625
  instruments = np.repeat(instruments, len(files))
570
626
 
627
+ if instrument_suffix is not None:
628
+ instruments = [i + instrument_suffix for i in instruments]
629
+
571
630
  factor = 1e3 if units == 'kms' else 1.0
572
631
 
573
632
  s = cls(star, _child=True, **kwargs)
@@ -744,6 +803,8 @@ class RV:
744
803
 
745
804
  s._child = False
746
805
  s.instruments = list(map(str, instruments))
806
+ s.filenames = list(map(str, files))
807
+
747
808
  s._build_arrays()
748
809
 
749
810
  if kwargs.get('do_adjust_means', False):
@@ -1188,9 +1249,9 @@ class RV:
1188
1249
 
1189
1250
  from .plots import plot, plot_fwhm, plot_bispan, plot_contrast, plot_rhk, plot_berv, plot_quantity
1190
1251
  from .plots import gls, gls_fwhm, gls_bispan, gls_rhk, gls_quantity, window_function
1191
- from .reports import report
1192
1252
 
1193
- from .instrument_specific import known_issues
1253
+ # from .reports import report
1254
+ # from .instrument_specific import known_issues
1194
1255
 
1195
1256
  def change_instrument_name(self, old_name, new_name, strict=False):
1196
1257
  """ Change the name of an instrument
arvi/utils.py CHANGED
@@ -21,7 +21,7 @@ except ImportError:
21
21
  tqdm = lambda x, *args, **kwargs: x
22
22
  trange = lambda *args, **kwargs: range(*args, **kwargs)
23
23
 
24
- from .setup_logger import logger
24
+ from .setup_logger import setup_logger
25
25
  from .config import config
26
26
 
27
27
 
@@ -70,6 +70,8 @@ def all_logging_disabled():
70
70
  @contextmanager
71
71
  def timer(name=None):
72
72
  """ A simple context manager to time a block of code """
73
+ logger = setup_logger()
74
+
73
75
  if not config.debug:
74
76
  yield
75
77
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arvi
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: The Automated RV Inspector
5
5
  Author-email: João Faria <joao.faria@unige.ch>
6
6
  License: MIT