AstroToolkit 1.0.0__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.
- AstroToolkit/Figures/HRD.py +82 -0
- AstroToolkit/Figures/SED.py +364 -0
- AstroToolkit/Figures/__init__.py +0 -0
- AstroToolkit/Miscellaneous/ProperMotionCorrection.py +50 -0
- AstroToolkit/Miscellaneous/ReadFits.py +35 -0
- AstroToolkit/Miscellaneous/TestFile.py +138 -0
- AstroToolkit/Miscellaneous/__init__.py +0 -0
- AstroToolkit/Overlays/Overlay_GALEX.py +148 -0
- AstroToolkit/Overlays/Overlay_Gaia.py +63 -0
- AstroToolkit/Overlays/Overlay_ROSAT.py +20 -0
- AstroToolkit/Overlays/Overlay_Selection.py +42 -0
- AstroToolkit/Overlays/Overlay_ZTF.py +46 -0
- AstroToolkit/Overlays/__init__.py +0 -0
- AstroToolkit/Surveys/DSS.py +153 -0
- AstroToolkit/Surveys/GALEX.py +45 -0
- AstroToolkit/Surveys/Gaia.py +168 -0
- AstroToolkit/Surveys/PanSTARRS.py +221 -0
- AstroToolkit/Surveys/ROSAT.py +51 -0
- AstroToolkit/Surveys/SDSS.py +78 -0
- AstroToolkit/Surveys/SkyMapper.py +215 -0
- AstroToolkit/Surveys/TWOMASS.py +45 -0
- AstroToolkit/Surveys/WISE.py +45 -0
- AstroToolkit/Surveys/ZTF.py +206 -0
- AstroToolkit/Surveys/__init__.py +0 -0
- AstroToolkit/Timeseries/__init__.py +0 -0
- AstroToolkit/Timeseries/pyaov.py +781 -0
- AstroToolkit/Timeseries/ztfanalysis.py +847 -0
- AstroToolkit/Tools.py +1222 -0
- AstroToolkit/__init__.py +0 -0
- AstroToolkit-1.0.0.dist-info/LICENSE +0 -0
- AstroToolkit-1.0.0.dist-info/METADATA +934 -0
- AstroToolkit-1.0.0.dist-info/RECORD +34 -0
- AstroToolkit-1.0.0.dist-info/WHEEL +5 -0
- AstroToolkit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Python wrapper for period search routines
|
|
5
|
+
# (C) Alex Schwarzenberg-Czerny, 2011 alex@camk.edu.pl
|
|
6
|
+
# Based on the wrapper scheme contributed by Ewald Zietsman <ewald.zietsman@gmail.com>
|
|
7
|
+
|
|
8
|
+
import matplotlib.pyplot as pl
|
|
9
|
+
import numpy as np
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from ..Timeseries import aov as _aov
|
|
13
|
+
|
|
14
|
+
'''
|
|
15
|
+
Time Series Analysis Package (TSA)
|
|
16
|
+
by Alex Schwarzenberg-Czerny (C)2011-2021
|
|
17
|
+
Based/Expanded on ESO MIDAS/TSA context by the same author
|
|
18
|
+
|
|
19
|
+
Routines For Periodograms/Frequency spectra:
|
|
20
|
+
amhw, aovw, atrw, pspw, f_mw, lomw, fgrid
|
|
21
|
+
Routines for analysis in Time domain:
|
|
22
|
+
covar, fouw, prew
|
|
23
|
+
Auxillary routines:
|
|
24
|
+
norm_obs, peak, pldat, plper, simul, totals,
|
|
25
|
+
|
|
26
|
+
For help type e.g.: help(pyaov.amhw)
|
|
27
|
+
|
|
28
|
+
NOTE: in all subroutines from times is subtracted EPOCH=(t_min+t_max)/2.
|
|
29
|
+
|
|
30
|
+
General Reference:
|
|
31
|
+
Schwarzenberg-Czerny, A., 1998, Baltic Astronomy, v.7, p.43-69
|
|
32
|
+
'''
|
|
33
|
+
|
|
34
|
+
CTMIN = 5 # global, min. bin population
|
|
35
|
+
|
|
36
|
+
# a wrapper for the amhw function
|
|
37
|
+
def amhw(tin, vin, er, fup, fstep, fr0=0., nh2=3):
|
|
38
|
+
'''
|
|
39
|
+
th,fr,frmax=pyaov.amhw(time, valin, error, fup, fstep, fr0=0., nh2=3)
|
|
40
|
+
|
|
41
|
+
Purpose: Returns multiharmonic AOV periodogram, obtained by fitting data
|
|
42
|
+
with a series of trigonometric polynomials. For default nh2=3 this
|
|
43
|
+
is Lomb-Scargle periodogram corrected for constant shift.
|
|
44
|
+
Input:
|
|
45
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
46
|
+
fup: frequency to stop calculation at, float
|
|
47
|
+
fstep: size of frequency steps, float
|
|
48
|
+
Optional input:
|
|
49
|
+
nh2[=3]: no. of model parms. (number of harmonics=nh2/2)
|
|
50
|
+
fr0[=0.]: start frequency
|
|
51
|
+
|
|
52
|
+
Output:
|
|
53
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
54
|
+
where m = (fup-fr0)/fstep+1
|
|
55
|
+
frmax: frequency of maximum
|
|
56
|
+
|
|
57
|
+
Method:
|
|
58
|
+
General method involving projection onto orthogonal trigonometric
|
|
59
|
+
polynomials is due to Schwarzenberg-Czerny, 1996. For nh2=2 or 3 it reduces
|
|
60
|
+
Ferraz-Mello (1991), i.e. to Lomb-Scargle periodogram improved by constant
|
|
61
|
+
shift of values. Advantage of the shift is vividly illustrated by Foster (1995).
|
|
62
|
+
Please quote:
|
|
63
|
+
A. Schwarzenberg-Czerny, 1996, Astrophys. J.,460, L107.
|
|
64
|
+
Other references:
|
|
65
|
+
G. Foster, 1995, AJ v.109, p.1889 (his Fig.1).
|
|
66
|
+
S. Ferraz-Mello, 1981, AJ v.86, p.619.
|
|
67
|
+
N. R. Lomb, 1976, Ap&SS v.39, p.447.
|
|
68
|
+
A. Schwarzenberg-Czerny, 1998, Baltic Astronomy, 7, 43.
|
|
69
|
+
'''
|
|
70
|
+
|
|
71
|
+
'''
|
|
72
|
+
print('time: ',tin)
|
|
73
|
+
print('mags: ',vin)
|
|
74
|
+
print('errors: ',er)
|
|
75
|
+
print('final frequency: ',fup)
|
|
76
|
+
print('step size: ',fstep)
|
|
77
|
+
'''
|
|
78
|
+
|
|
79
|
+
nfr = pre("amhw", tin, vin, er, fup, fstep, fr0)
|
|
80
|
+
try:
|
|
81
|
+
th, npar, stat, vr = _aov.aov.aovdrv("AMHW",tin, vin, er, nh2, 0, \
|
|
82
|
+
fr0, fstep, nfr, "AOV")
|
|
83
|
+
return post("amhw", th, nfr, fstep, fr0)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(e)
|
|
86
|
+
print("amhw: Something unexpected went wrong")
|
|
87
|
+
return 0
|
|
88
|
+
|
|
89
|
+
# a wrapper for the aovw function
|
|
90
|
+
def aovw(tin, vin, er, fup, fstep, fr0=0., nh2=3, ncov=2):
|
|
91
|
+
'''
|
|
92
|
+
th,fr,frmax=pyaov.aovw(time, valin, error, fup, fstep, fr0=0., \
|
|
93
|
+
nh2=3, ncov=2)
|
|
94
|
+
|
|
95
|
+
Purpose: Returns AOV periodogram, obtained by phase-folding and binning
|
|
96
|
+
of data.
|
|
97
|
+
Input:
|
|
98
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
99
|
+
fup: frequency to stop calculation at, float
|
|
100
|
+
fstep: size of frequency steps, float
|
|
101
|
+
Optional input:
|
|
102
|
+
nh2[=3]: number of phase bins
|
|
103
|
+
fr0[=0.]: start frequency
|
|
104
|
+
ncov[=2]: number of coverages
|
|
105
|
+
|
|
106
|
+
Output:
|
|
107
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
108
|
+
where m = (fup-fr0)/fstep+1
|
|
109
|
+
frmax: frequency of maximum
|
|
110
|
+
|
|
111
|
+
Please quote:
|
|
112
|
+
A. Schwarzenberg-Czerny, 1989, MNRAS 241, 153.
|
|
113
|
+
A. Schwarzenberg-Czerny & J.-Ph. Beaulieu, 2006, MNRAS 365, 165
|
|
114
|
+
'''
|
|
115
|
+
|
|
116
|
+
nfr = pre("aovw", tin, vin, er, fup, fstep, fr0)
|
|
117
|
+
try:
|
|
118
|
+
th, npar, stat, vr = _aov.aov.aovdrv("AOVW", tin, vin, er, nh2, ncov, \
|
|
119
|
+
fr0, fstep, nfr, "AOV")
|
|
120
|
+
return post("aovw", th, nfr, fstep, fr0)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
print(e)
|
|
123
|
+
print("aovw: Something unexpected went wrong")
|
|
124
|
+
return 0
|
|
125
|
+
|
|
126
|
+
# a wrapper for the aovtrw function
|
|
127
|
+
def atrw(tin, vin, er, fup, fstep, fr0=0., nh2=30, ncov=2):
|
|
128
|
+
'''
|
|
129
|
+
th,fr,frmax=pyaov.atrw(time, valin, error, fup, fstep, \
|
|
130
|
+
fr0=0., nh2=30, ncov=2)
|
|
131
|
+
|
|
132
|
+
Purpose: Returns AOV periodogram for search of transits/eclipses.
|
|
133
|
+
For this purpose data are fitted with a box-like (inverted top-hat) function.
|
|
134
|
+
|
|
135
|
+
Input:
|
|
136
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
137
|
+
fup: frequency to stop calculation at, float
|
|
138
|
+
fstep: size of frequency steps, float
|
|
139
|
+
Optional input:
|
|
140
|
+
nh2[=30]: number of phase bins
|
|
141
|
+
fr0[=0.]: start frequency
|
|
142
|
+
ncov[=2]: number of bin coverages overlapping in phase
|
|
143
|
+
|
|
144
|
+
Output:
|
|
145
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
146
|
+
where m = (fup-fr0)/fstep+1
|
|
147
|
+
frmax: frequency of maximum
|
|
148
|
+
|
|
149
|
+
Please quote:
|
|
150
|
+
A. Schwarzenberg-Czerny, 1989, MNRAS 241, 153.
|
|
151
|
+
A. Schwarzenberg-Czerny & J.-Ph. Beaulieu, 2006, MNRAS 365, 165
|
|
152
|
+
'''
|
|
153
|
+
|
|
154
|
+
nfr = pre("atrw", tin, vin, er, fup, fstep, fr0)
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
th, npar, stat, vr = _aov.aov.aovdrv("ATRW", tin, vin, er, nh2, ncov, \
|
|
158
|
+
fr0, fstep, nfr, "AOV")
|
|
159
|
+
return post("atrw", th, nfr, fstep, fr0)
|
|
160
|
+
except Exception as e:
|
|
161
|
+
print(e)
|
|
162
|
+
print("atrw: Something unexpected went wrong")
|
|
163
|
+
return 0
|
|
164
|
+
|
|
165
|
+
# a wrapper for the covar function
|
|
166
|
+
def covar(t1,v1,e1,t2,v2,e2,nct=11,eps=0.0,iscale=0,ifunct=0):
|
|
167
|
+
'''
|
|
168
|
+
lav,lmi,lmx,cc,cmi,cmx=covar(t1,v1,e1,t2,v2,e2, \
|
|
169
|
+
nct=11,eps=0.0,iscale=0,ifunct=0)
|
|
170
|
+
|
|
171
|
+
Purpose: Calculates cross-correlation function (CCF) for unevenly sampled data
|
|
172
|
+
Input:
|
|
173
|
+
t1,v1,e1: time, value & error of data set 1, numpy arrays of size (n1*1)
|
|
174
|
+
t2,v2,e2: same for data 2, float size (n2*1)
|
|
175
|
+
Optional Input:
|
|
176
|
+
nct: minimum number of pairs per bin
|
|
177
|
+
eps: minimum separation of consecutive lags on bin flexible boundary
|
|
178
|
+
|
|
179
|
+
Output:
|
|
180
|
+
lav,lmi,lmx(nlag)- average & range of lags for a lag bin
|
|
181
|
+
, numpy arrays of size (nlag*1), and ...
|
|
182
|
+
cc,cmi,cmx(nlag)- ... average & range of correlations
|
|
183
|
+
|
|
184
|
+
Reference: Alexander, T., 1997, in Astronomical Time Series, Eds. D. Maoz et al.,
|
|
185
|
+
Dordrecht: Kluwer, ASSL, v218, p163
|
|
186
|
+
'''
|
|
187
|
+
# unimplemented Optional Input:
|
|
188
|
+
# iscale=0: output scale: iscale/=1 -linear; iscale=1 -logarythmic
|
|
189
|
+
# ifunct=0: output function: ifunct/=1 -correlation; ifunct=1 -structure
|
|
190
|
+
|
|
191
|
+
# check the arrays here, make sure they are all the same size
|
|
192
|
+
try:
|
|
193
|
+
assert t1.size == d1.size == v1.size
|
|
194
|
+
except AssertionError:
|
|
195
|
+
print('covar: Input arrays1 must be same size')
|
|
196
|
+
return 0
|
|
197
|
+
try:
|
|
198
|
+
assert t2.size == d2.size == v2.size
|
|
199
|
+
except AssertionError:
|
|
200
|
+
print('covar: Input arrays2 must be same size')
|
|
201
|
+
return 0
|
|
202
|
+
try:
|
|
203
|
+
assert nct >0
|
|
204
|
+
except AssertionError:
|
|
205
|
+
print('covar: Non positive minimum count per bin')
|
|
206
|
+
return 0
|
|
207
|
+
|
|
208
|
+
# maybe something else can go wrong?
|
|
209
|
+
try:
|
|
210
|
+
llav,lmi,lmx,cc,cmi,cmx,ilag = _aov.aov.covar(t1,d1,v1,t2,d2,v2, \
|
|
211
|
+
t1.size*t2.size/nct,eps=eps,iscale=iscale,ifunct=ifunct)
|
|
212
|
+
|
|
213
|
+
return llav[:ilag],lmi[:ilag],lmx[:ilag],cc[:ilag],cmi[:ilag],cmx[:ilag]
|
|
214
|
+
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(e)
|
|
217
|
+
print("covar: Something unexpected went wrong")
|
|
218
|
+
return 0
|
|
219
|
+
|
|
220
|
+
def fgrid(time):
|
|
221
|
+
'''
|
|
222
|
+
fup,fstep,fr0=pyaov.fgrid(time)
|
|
223
|
+
|
|
224
|
+
Purpose: Evaluate time column and derive a suitable frequency grid
|
|
225
|
+
Input:
|
|
226
|
+
time: numpy array of size (n*1)
|
|
227
|
+
|
|
228
|
+
Output:
|
|
229
|
+
fup,fstep,fr0: Frequency maximum, step & minimum, float
|
|
230
|
+
'''
|
|
231
|
+
|
|
232
|
+
# check the arrays here, make sure they are all the same size
|
|
233
|
+
try:
|
|
234
|
+
assert time.size >=5
|
|
235
|
+
except AssertionError:
|
|
236
|
+
print('fgrid: Too few time moments')
|
|
237
|
+
return 0
|
|
238
|
+
|
|
239
|
+
# maybe something else can go wrong?
|
|
240
|
+
try:
|
|
241
|
+
fup,fstep,fr0 = _aov.aov.fgrid(time)
|
|
242
|
+
|
|
243
|
+
return fup,fstep,fr0
|
|
244
|
+
|
|
245
|
+
except Exception as e:
|
|
246
|
+
print(e)
|
|
247
|
+
print("fgrid: Something unexpected went wrong")
|
|
248
|
+
return 0
|
|
249
|
+
|
|
250
|
+
# a wrapper for the fouw function
|
|
251
|
+
def fouw(time, valin, error, frin, nh2=3):
|
|
252
|
+
'''
|
|
253
|
+
frout,dfrout,valout,cof,dcof=pyaov.fouw(time, valin, error, \
|
|
254
|
+
frin, bacgnd=0., nh2=3)
|
|
255
|
+
|
|
256
|
+
Purpose: fit data with Fourier series, adjusting frequency if needed.
|
|
257
|
+
Returns frequency, pre-whitened residuals,Fourier coefficients and errors
|
|
258
|
+
Input:
|
|
259
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
260
|
+
frin: initial frequency, float
|
|
261
|
+
Optional input:
|
|
262
|
+
nh2[=3]: no. of model parms. (number of harmonics=nh2/2)
|
|
263
|
+
|
|
264
|
+
Output:
|
|
265
|
+
frout: final frequency, float
|
|
266
|
+
dfrout: frequency error(if bacgnd correctly set from mhaov|aov|aovtr)
|
|
267
|
+
valout: residuals from fit/data prewhitened with freq
|
|
268
|
+
numpy array of size (n*1)
|
|
269
|
+
cof, dcof: Fourier coefficients & errors,
|
|
270
|
+
numpy arrays of size (m*1) where m = nh2/2*2+2
|
|
271
|
+
cof(m)-float epoch t0, for double use directly time values
|
|
272
|
+
dcof(m)-error of frequency
|
|
273
|
+
Fourier series:
|
|
274
|
+
fin(ph)=cof(1)+sum_{n=1}^{nh2/2}(cof(2n-1)Cos(ph*n)+cof(2n)*Sin(ph*n))
|
|
275
|
+
where ph=2pi*frout*(t-t0) and t0=(max(t)+min(t))/2
|
|
276
|
+
|
|
277
|
+
Please quote:
|
|
278
|
+
A.Schwarzenberg-Czerny, 1995, Astr. & Astroph. Suppl, 110,405
|
|
279
|
+
'''
|
|
280
|
+
|
|
281
|
+
# check the arrays here, make sure they are all the same size
|
|
282
|
+
try:
|
|
283
|
+
assert time.size == valin.size == error.size
|
|
284
|
+
except AssertionError:
|
|
285
|
+
print('fouw: Input arrays must be same size')
|
|
286
|
+
return 0
|
|
287
|
+
|
|
288
|
+
# maybe something else can go wrong?
|
|
289
|
+
try:
|
|
290
|
+
frout,dfrout,valout,cof,dcof = _aov.aov.fouw(time, valin, \
|
|
291
|
+
error, frin, nh2)
|
|
292
|
+
return frout,dfrout,valout,cof,dcof
|
|
293
|
+
|
|
294
|
+
except Exception as e:
|
|
295
|
+
print(e)
|
|
296
|
+
print("fouw: Something unexpected went wrong")
|
|
297
|
+
return 0
|
|
298
|
+
|
|
299
|
+
def f_mw(tin, vin, er, fup, fstep, fr0=0.):
|
|
300
|
+
'''
|
|
301
|
+
th,fr,frmax=pyaov.f_mw(time, valin, error, fup, fstep, fr0=0.)
|
|
302
|
+
|
|
303
|
+
Purpose: Returns generalized L-S periodogram
|
|
304
|
+
of data, using the original Ferraz-Mello (1981) algorithm.
|
|
305
|
+
Input:
|
|
306
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
307
|
+
fup: frequency to stop calculation at, float
|
|
308
|
+
fstep: size of frequency steps, float
|
|
309
|
+
Optional input:
|
|
310
|
+
fr0[=0.]: start frequency
|
|
311
|
+
|
|
312
|
+
Output:
|
|
313
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
314
|
+
where m = (fup-fr0)/fstep+1
|
|
315
|
+
frmax: frequency of maximum
|
|
316
|
+
|
|
317
|
+
Reference:
|
|
318
|
+
S. Ferraz-Mello, 1981, Astronomical Journal 86, 619.
|
|
319
|
+
A. Schwarzenberg-Czerny, 1998, Baltic Astronomy, 7, 43.
|
|
320
|
+
'''
|
|
321
|
+
|
|
322
|
+
nfr = pre("f_mw", tin, vin, er, fup, fstep, fr0)
|
|
323
|
+
try:
|
|
324
|
+
th, npar, stat, vr = _aov.aov.aovdrv("F_MW", tin, vin, er, 0, 0, \
|
|
325
|
+
fr0, fstep, nfr, "RAW")
|
|
326
|
+
return post("f_mw", th, nfr, fstep, fr0)
|
|
327
|
+
except Exception as e:
|
|
328
|
+
print(e)
|
|
329
|
+
print("f_mw: Something unexpected went wrong")
|
|
330
|
+
return 0
|
|
331
|
+
|
|
332
|
+
def lomw(tin, vin, er, fup, fstep, fr0=0.):
|
|
333
|
+
'''
|
|
334
|
+
th,fr,frmax=pyaov.lomw(time, valin, error, fup, fstep, fr0=0., \
|
|
335
|
+
nh2=3, ncov=2)
|
|
336
|
+
|
|
337
|
+
Purpose: Returns AOV periodogram, obtained by phase-folding and binning
|
|
338
|
+
of data.
|
|
339
|
+
Input:
|
|
340
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
341
|
+
fup: frequency to stop calculation at, float
|
|
342
|
+
fstep: size of frequency steps, float
|
|
343
|
+
Optional input:
|
|
344
|
+
fr0[=0.]: start frequency
|
|
345
|
+
|
|
346
|
+
Output:
|
|
347
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
348
|
+
where m = (fup-fr0)/fstep+1
|
|
349
|
+
frmax: frequency of maximum
|
|
350
|
+
|
|
351
|
+
Reference:
|
|
352
|
+
N.R. Lomb, 1976, Astrophysics and Space Science, 39, 447.
|
|
353
|
+
A. Schwarzenberg-Czerny, 1998, Baltic Astronomy, 7, 43.
|
|
354
|
+
'''
|
|
355
|
+
|
|
356
|
+
nfr = pre("lomw", tin, vin, er, fup, fstep, fr0)
|
|
357
|
+
try:
|
|
358
|
+
th, npar, stat, vr = _aov.aov.aovdrv("LOMW", tin, vin, er, 0, 0, \
|
|
359
|
+
fr0, fstep, nfr, "RAW")
|
|
360
|
+
return post("lomw", th, nfr, fstep, fr0)
|
|
361
|
+
except Exception as e:
|
|
362
|
+
print(e)
|
|
363
|
+
print("lomw: Something unexpected went wrong")
|
|
364
|
+
return 0
|
|
365
|
+
|
|
366
|
+
def normalize(x,error,mean=0.,var=1.):
|
|
367
|
+
'''
|
|
368
|
+
y = pyaov.normalize(x,error,mean=0.,var=1.)
|
|
369
|
+
|
|
370
|
+
Purpose: converts series to one of specified mean and variance var.
|
|
371
|
+
Input:
|
|
372
|
+
x: input time series, numpy array (n*1)
|
|
373
|
+
error: used to calculate weights w = 1/error**2,
|
|
374
|
+
observations with null error are ignored
|
|
375
|
+
Optional Input:
|
|
376
|
+
mean,var: final mean and variance of the normalized series.
|
|
377
|
+
For var==0 only mean is shifted.
|
|
378
|
+
|
|
379
|
+
Output:
|
|
380
|
+
x: normalized time series, numpy array (n*1)
|
|
381
|
+
|
|
382
|
+
'''
|
|
383
|
+
|
|
384
|
+
# check the arrays here, make sure they are all the same size
|
|
385
|
+
try:
|
|
386
|
+
assert x.size > 1, 'Normalize:Input arrays length must be >1'
|
|
387
|
+
assert x.size == error.size,'Normalize:Input arrays length must be equal'
|
|
388
|
+
assert var >= 0.,'Normalize:negative target variance'
|
|
389
|
+
except AssertionError:
|
|
390
|
+
return 0
|
|
391
|
+
|
|
392
|
+
# maybe something else can go wrong?
|
|
393
|
+
try:
|
|
394
|
+
w = error
|
|
395
|
+
ndx = w <= 0.
|
|
396
|
+
w[ndx] = 1.
|
|
397
|
+
w = 1./np.square(w)
|
|
398
|
+
w[ndx] = 0.
|
|
399
|
+
n = len(w)-len(ndx)
|
|
400
|
+
|
|
401
|
+
sw = np.sum(w)
|
|
402
|
+
av = np.sum(x*w)/sw
|
|
403
|
+
y = x-av
|
|
404
|
+
vr = np.sum(np.square(y)*w)
|
|
405
|
+
va = vr/sw*n/(n-1)
|
|
406
|
+
if (var>0. and va>0.):
|
|
407
|
+
y=y*np.sqrt(var/va)
|
|
408
|
+
y=y+mean
|
|
409
|
+
return y, n, sw, av, vr
|
|
410
|
+
|
|
411
|
+
except Exception as e:
|
|
412
|
+
print (e)
|
|
413
|
+
print ("Normalize: Something unexpected went wrong!!")
|
|
414
|
+
return 0
|
|
415
|
+
|
|
416
|
+
def peak(f):
|
|
417
|
+
'''
|
|
418
|
+
xm,fm,dx = pyaov.peak(f)
|
|
419
|
+
from ort
|
|
420
|
+
Scan EVENSAMPLED series for a peak
|
|
421
|
+
Result location & width is in units of f indices (starting from 0)
|
|
422
|
+
INPUT:
|
|
423
|
+
f:- values at even spaced arguments, numpy array (n*1)
|
|
424
|
+
OUTPUT:
|
|
425
|
+
xm-peak location (first element: 0 in Py, 1 in F90)
|
|
426
|
+
fm-peak value
|
|
427
|
+
dx-peak halfwidth at zero level
|
|
428
|
+
SPECIAL CONDITIONS:
|
|
429
|
+
dx<0 no valid peak with positive value
|
|
430
|
+
METHOD:
|
|
431
|
+
Fits parabola to top 3 points
|
|
432
|
+
(C) Alex Schwarzenberg-Czerny, 1999-2005 alex@camk.edu.pl
|
|
433
|
+
'''
|
|
434
|
+
try:
|
|
435
|
+
assert f.size >0
|
|
436
|
+
except AssertionError:
|
|
437
|
+
print('peak: Too few components')
|
|
438
|
+
return 0
|
|
439
|
+
|
|
440
|
+
# maybe something else can go wrong?
|
|
441
|
+
try:
|
|
442
|
+
xm, fm, dx = _aov.aov.peak(f)
|
|
443
|
+
# NOTE: aov.aovsub.peak follows Fortran indexing convention
|
|
444
|
+
# For Python 1 must be subtracted from xm output
|
|
445
|
+
return xm-1., fm, dx
|
|
446
|
+
|
|
447
|
+
except Exception as e:
|
|
448
|
+
print(e)
|
|
449
|
+
print("peak: Something unexpected went wrong")
|
|
450
|
+
return 0
|
|
451
|
+
|
|
452
|
+
# make a plot of data
|
|
453
|
+
def pldat(time, value):
|
|
454
|
+
'''
|
|
455
|
+
pyaov.pldat(time, value)
|
|
456
|
+
|
|
457
|
+
Purpose:
|
|
458
|
+
Plots periodogram and data folded with its peak frequency
|
|
459
|
+
|
|
460
|
+
Input:
|
|
461
|
+
time, value: numpy arrays of size (n*1)
|
|
462
|
+
|
|
463
|
+
Output:
|
|
464
|
+
Plot window. Close it to proceed further.
|
|
465
|
+
'''
|
|
466
|
+
|
|
467
|
+
pl.figure(figsize=(9,9))
|
|
468
|
+
|
|
469
|
+
pl.subplot(211)
|
|
470
|
+
pl.plot(time, value, 'k.')
|
|
471
|
+
# pl.title('Data')
|
|
472
|
+
pl.xlabel('Time')
|
|
473
|
+
pl.ylabel('Data Value')
|
|
474
|
+
|
|
475
|
+
pl.show()
|
|
476
|
+
|
|
477
|
+
# make a periodogram plot
|
|
478
|
+
def plper(nam,frmax, time, value, freqs, th):
|
|
479
|
+
'''
|
|
480
|
+
pyaov.plper(frmax, time, value, freqs, th)
|
|
481
|
+
|
|
482
|
+
Purpose:
|
|
483
|
+
Plots periodogram and data folded with its peak frequency
|
|
484
|
+
|
|
485
|
+
Input:
|
|
486
|
+
frmax: the frequency used for phase folding
|
|
487
|
+
set frmax=0 to avoid phase folded plot
|
|
488
|
+
time, value: numpy arrays of size (n*1)
|
|
489
|
+
freqs, th: frequencies & periodogram (m*1)
|
|
490
|
+
|
|
491
|
+
Output:
|
|
492
|
+
Plot window. Close it to proceed further.
|
|
493
|
+
'''
|
|
494
|
+
|
|
495
|
+
pl.figure(figsize=(9,9))
|
|
496
|
+
|
|
497
|
+
if frmax>0. : # plot phase folded data
|
|
498
|
+
pl.subplot(211)
|
|
499
|
+
ph=np.mod(time*frmax,1.)
|
|
500
|
+
pl.plot(ph, value, 'k.')
|
|
501
|
+
pl.xlabel('Phase')
|
|
502
|
+
pl.ylabel('Data Value')
|
|
503
|
+
pl.subplots_adjust( hspace=0.3)
|
|
504
|
+
|
|
505
|
+
pl.subplot(212) # plot periodogram
|
|
506
|
+
pl.plot(freqs, th, 'k')
|
|
507
|
+
pl.title(nam)
|
|
508
|
+
pl.ylabel('Statistics')
|
|
509
|
+
pl.xlabel('Frequency')
|
|
510
|
+
|
|
511
|
+
pl.show()
|
|
512
|
+
|
|
513
|
+
def post(nam, th, nfr, fstep, fr0):
|
|
514
|
+
'''
|
|
515
|
+
Auxillary routine for post-processing of periodograms
|
|
516
|
+
th, freqs, frmax = post(nam, th, nfr, fstep, fr0)
|
|
517
|
+
'''
|
|
518
|
+
xm, fm, dx = peak(th)
|
|
519
|
+
frmax = fr0 + xm * fstep
|
|
520
|
+
print(nam+': Peak of %f at frequency %f' % (fm,frmax))
|
|
521
|
+
# make an array that contains the frequencies too
|
|
522
|
+
freqs = np.arange(nfr)*fstep+fr0
|
|
523
|
+
return th, freqs, frmax
|
|
524
|
+
|
|
525
|
+
def pre(nam, tin, vin, er, fup, fstep, fr0):
|
|
526
|
+
# test input for periodograms
|
|
527
|
+
'''
|
|
528
|
+
Auxillary routine for testing input oto periodogram routines.
|
|
529
|
+
nfr = pre(nam, tin, vin, er, fup, fstep, fr0)
|
|
530
|
+
'''
|
|
531
|
+
nobs = tin.size
|
|
532
|
+
assert nobs == vin.size == er.size, \
|
|
533
|
+
nam+': Input arrays must be the same dimensions'
|
|
534
|
+
nfr = int((fup - fr0)/fstep+1.5)
|
|
535
|
+
assert nfr>0, nam+': wrong frequency range'
|
|
536
|
+
if (tin.max()-tin.min())*fstep>0.2:
|
|
537
|
+
print(nam+': warning: undersampling in frequency')
|
|
538
|
+
return nfr
|
|
539
|
+
|
|
540
|
+
# a wrapper for the prew function
|
|
541
|
+
def prew(time, valin, error, frin, nh2=3):
|
|
542
|
+
'''
|
|
543
|
+
frout,dfrout,valout=pyaov.prew(time, valin, error, frin, nh2=3)
|
|
544
|
+
|
|
545
|
+
Purpose:
|
|
546
|
+
Improve trig orthogonal polynomial fit by tweaking of frequency.
|
|
547
|
+
Returns frequency and pre-whitened residuals.
|
|
548
|
+
Note: valin-valout returns a fitted interpolation trig polynomial.
|
|
549
|
+
|
|
550
|
+
Input:
|
|
551
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
552
|
+
frin: initial frequency, float
|
|
553
|
+
Optional input:
|
|
554
|
+
nh2[=3]: no. of model parms. (number of harmonics=nh2/2)
|
|
555
|
+
|
|
556
|
+
Output:
|
|
557
|
+
frout: final frequency, float
|
|
558
|
+
dfrout: its error
|
|
559
|
+
valout: residuals from fit/data prewhitened with freq
|
|
560
|
+
numpy array of size (n*1)
|
|
561
|
+
|
|
562
|
+
Please quote:
|
|
563
|
+
A.Schwarzenberg-Czerny, 1996, Astrophys. J.,460, L107.
|
|
564
|
+
'''
|
|
565
|
+
|
|
566
|
+
# check the arrays here, make sure they are all the same size
|
|
567
|
+
try:
|
|
568
|
+
assert time.size == valin.size == error.size
|
|
569
|
+
except AssertionError:
|
|
570
|
+
print('prew: Input arrays must be the same dimensions')
|
|
571
|
+
return 0
|
|
572
|
+
|
|
573
|
+
# maybe something else can go wrong?
|
|
574
|
+
try:
|
|
575
|
+
frout,dfrout,valout = _aov.aov.prew(time, valin, error, \
|
|
576
|
+
frin, nh2)
|
|
577
|
+
|
|
578
|
+
return frout,dfrout,valout
|
|
579
|
+
|
|
580
|
+
except Exception as e:
|
|
581
|
+
print(e)
|
|
582
|
+
print("prew: Something unexpected went wrong")
|
|
583
|
+
return 0
|
|
584
|
+
|
|
585
|
+
# a wrapper for the powspw function
|
|
586
|
+
def pspw(tin, vin, er, fup, fstep, fr0=0.):
|
|
587
|
+
'''
|
|
588
|
+
th,fr,frmax=pyaov.pspw(time, valin, error, fup, fstep, fr0=0.)
|
|
589
|
+
|
|
590
|
+
Purpose: Returns Power Spectrum. Principal use for calculation of window function.
|
|
591
|
+
For periodogram we recommend amhv routine with nh2=2 instead.
|
|
592
|
+
Input:
|
|
593
|
+
time, valin, error : numpy arrays of size (n*1)
|
|
594
|
+
fup: frequency to stop calculation at, float
|
|
595
|
+
fstep: size of frequency steps, float
|
|
596
|
+
Optional input:
|
|
597
|
+
fr0[=0.]: start frequency
|
|
598
|
+
|
|
599
|
+
Output:
|
|
600
|
+
th,fr: periodogram values & frequencies: numpy arrays of size (m*1)
|
|
601
|
+
where m = (fup-fr0)/fstep+1
|
|
602
|
+
frmax: frequency of maximum
|
|
603
|
+
Method:
|
|
604
|
+
For unit weights exactly corresponds to Deeming DPS. Weights are
|
|
605
|
+
assumed to be proportional to number of fictional repeated measurements
|
|
606
|
+
and so accountend within Deeming scheme.
|
|
607
|
+
Reference:
|
|
608
|
+
T. J. Deeming, 1975, Ap&SS, v36, pp.137-158
|
|
609
|
+
A. Schwarzenberg-Czerny, 1998, Baltic Astronomy, 7, 43.
|
|
610
|
+
|
|
611
|
+
'''
|
|
612
|
+
nfr = pre("pspw", tin, vin, er, fup, fstep, fr0)
|
|
613
|
+
try:
|
|
614
|
+
th, npar, stat, vr = _aov.aov.aovdrv("PSPW",tin, vin, er, 0, 0, \
|
|
615
|
+
fr0, fstep, nfr, "RAW")
|
|
616
|
+
return post("pspw", th, nfr, fstep, fr0)
|
|
617
|
+
except Exception as e:
|
|
618
|
+
print(e)
|
|
619
|
+
print("pspw: Something unexpected went wrong")
|
|
620
|
+
return 0
|
|
621
|
+
|
|
622
|
+
def refine(xd, yd, ed, fr): #
|
|
623
|
+
'''
|
|
624
|
+
fr,dfr,valout,nh2 = refine(xd, yd, ed, fr)
|
|
625
|
+
Refine frequency by orthogonal polynomials fit initial data from box text
|
|
626
|
+
'''
|
|
627
|
+
try:
|
|
628
|
+
n=xd.size
|
|
629
|
+
assert n >0 and n == yd.size and n == ed.size, \
|
|
630
|
+
"refine: wrong array sizes"
|
|
631
|
+
assert fr > 0., "refine: frequency must be positive"
|
|
632
|
+
except AssertionError:
|
|
633
|
+
return 0
|
|
634
|
+
|
|
635
|
+
try:
|
|
636
|
+
nh2new = 1
|
|
637
|
+
ndx = ed > 0.
|
|
638
|
+
n = len(ndx)
|
|
639
|
+
snew = np.sum(np.square(yd[ndx]/ed[ndx]))
|
|
640
|
+
next = True
|
|
641
|
+
valout = np.array(yd)
|
|
642
|
+
frout = (fr)
|
|
643
|
+
|
|
644
|
+
while next: # fit a longer orthogonal polynomial series
|
|
645
|
+
nh2old=(nh2new)
|
|
646
|
+
sold=(snew)
|
|
647
|
+
nh2new += 2
|
|
648
|
+
|
|
649
|
+
fr, dfr, val=prew(xd, yd, ed, frout, nh2=nh2new)
|
|
650
|
+
|
|
651
|
+
snew = np.sum(np.square(val[ndx]/ed[ndx]))
|
|
652
|
+
fnew = (sold-snew)*(n-nh2new)/(2*snew)
|
|
653
|
+
# stop if (S_{j-1} - S_j)/S_j < F(1,N-j-1) = Fisher(N-j-1)
|
|
654
|
+
# where S=sum((O-C)^2*w)
|
|
655
|
+
if ( (fnew > Fisher(n-nh2new)) or (nh2new < 4) ): # still improving fit
|
|
656
|
+
next = True
|
|
657
|
+
dfrout = (dfr)
|
|
658
|
+
frout = (fr)
|
|
659
|
+
valout=np.array(val)
|
|
660
|
+
else:
|
|
661
|
+
next = False
|
|
662
|
+
return frout,dfrout,valout,nh2new-2
|
|
663
|
+
except Exception as e:
|
|
664
|
+
print(e)
|
|
665
|
+
print("pspw: Something unexpected went wrong")
|
|
666
|
+
return 0
|
|
667
|
+
|
|
668
|
+
def Fisher(x):
|
|
669
|
+
# returns Fisher-Snedecor test value, F(1,x) for q=0.95
|
|
670
|
+
# holds for integer x, 2<= x<=10000
|
|
671
|
+
a, b, c, d =3.04218309, 1.17632271, 1.32270521, 0.17300204
|
|
672
|
+
y = np.log(x)
|
|
673
|
+
return np.exp(a * np.exp(-b * y) + c + d/y)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
def simul(fr,span,no,s2n=3.,seed=1949):
|
|
678
|
+
'''
|
|
679
|
+
t, v, er = simul(no,s2n=3.)
|
|
680
|
+
Input:
|
|
681
|
+
no - number of observations
|
|
682
|
+
s2n - signal-to-noise {amplitude units]
|
|
683
|
+
Output:
|
|
684
|
+
t[no],v[no],er[no] simulated times, values end errors of a light curve
|
|
685
|
+
'''
|
|
686
|
+
rng = np.random.default_rng(seed)
|
|
687
|
+
t=np.zeros(no)
|
|
688
|
+
v=np.zeros(no)
|
|
689
|
+
e=np.zeros(no)
|
|
690
|
+
e[:] = np.exp(-rng.random(no))
|
|
691
|
+
v[:] = np.random.normal(size=no)/s2n
|
|
692
|
+
|
|
693
|
+
for k in np.arange(no):
|
|
694
|
+
t[k] = span*np.sin(k*1.)**4
|
|
695
|
+
t[-1] =span
|
|
696
|
+
for k in np.arange(no):
|
|
697
|
+
dph = fr*t[k]
|
|
698
|
+
omt = np.pi*2*(dph-np.floor(dph))
|
|
699
|
+
v[k]+= 11.90+0.434*np.cos(omt+4.72)+ \
|
|
700
|
+
0.237*np.cos(2.*omt+0.741)
|
|
701
|
+
return t,v,e
|
|
702
|
+
|
|
703
|
+
# a wrapper for the totals function
|
|
704
|
+
|
|
705
|
+
def test_per(nam):
|
|
706
|
+
# import aov as _aov
|
|
707
|
+
# get simulated data
|
|
708
|
+
|
|
709
|
+
a = np.loadtxt(nam,comments="!")
|
|
710
|
+
t, v, e = a[:,0],a[:,1],a[:,2]
|
|
711
|
+
print("Close plots to see the next demo")
|
|
712
|
+
# calculate the periodogram
|
|
713
|
+
th,fr,frmax=amhw(t,v,e,2.8,0.0001,fr0=2.7,nh2=5)
|
|
714
|
+
# make a plot
|
|
715
|
+
plper("amhw",frmax, t, v, fr, th)
|
|
716
|
+
|
|
717
|
+
# calculate the periodogram
|
|
718
|
+
th,fr,frmax=pspw(t,v,e,2.8,0.0001,fr0=2.7)
|
|
719
|
+
# make a plot
|
|
720
|
+
plper("pspw",frmax, t, v, fr, th)
|
|
721
|
+
|
|
722
|
+
# calculate the periodogram
|
|
723
|
+
th,fr,frmax=atrw(t,v,e,2.8,0.0001,nh2=5,fr0=2.7)
|
|
724
|
+
print("This example of atrw is poor as data contain no sharp eclipses")
|
|
725
|
+
# make a plot
|
|
726
|
+
plper("atrw",frmax, t, v, fr, th)
|
|
727
|
+
|
|
728
|
+
# calculate the periodogram
|
|
729
|
+
th,fr,frmax=aovw(t,v,e,2.8,0.0001,nh2=5,fr0=2.7)
|
|
730
|
+
# make a plot
|
|
731
|
+
plper("aovw",frmax, t, v, fr, th)
|
|
732
|
+
|
|
733
|
+
# calculate the periodogram
|
|
734
|
+
th,fr,frmax=f_mw(t,v,e,2.8,0.0001,fr0=2.7)
|
|
735
|
+
# make a plot
|
|
736
|
+
plper("f_mw",frmax, t, v, fr, th)
|
|
737
|
+
|
|
738
|
+
# calculate the periodogram
|
|
739
|
+
th,fr,frmax=lomw(t,v,e,2.8,0.0001,fr0=2.7)
|
|
740
|
+
# make a plot
|
|
741
|
+
plper("lomw",frmax, t, v, fr, th)
|
|
742
|
+
|
|
743
|
+
def totals(x,er):
|
|
744
|
+
'''
|
|
745
|
+
pyaov.totals(x,er)
|
|
746
|
+
|
|
747
|
+
Purpose: Evaluate statistical parameters of vector x
|
|
748
|
+
Input:
|
|
749
|
+
x: vector of data, numpy array of size (n*1)
|
|
750
|
+
|
|
751
|
+
Output:
|
|
752
|
+
Prints some statistical info
|
|
753
|
+
'''
|
|
754
|
+
# check the arrays here, make sure they are all the same size
|
|
755
|
+
try:
|
|
756
|
+
n=x.size
|
|
757
|
+
assert x.size >0
|
|
758
|
+
assert er.size == n
|
|
759
|
+
|
|
760
|
+
except AssertionError:
|
|
761
|
+
print('totals: Too few components')
|
|
762
|
+
return 0
|
|
763
|
+
|
|
764
|
+
# maybe something else can go wrong?
|
|
765
|
+
try:
|
|
766
|
+
_aov.aov.totals(x,er)
|
|
767
|
+
|
|
768
|
+
return 1
|
|
769
|
+
|
|
770
|
+
except Exception as e:
|
|
771
|
+
print(e)
|
|
772
|
+
print("totals: Something unexpected went wrong")
|
|
773
|
+
return 0
|
|
774
|
+
|
|
775
|
+
#==============================================
|
|
776
|
+
# if you run this script from the command line this will
|
|
777
|
+
# run. It will not run if you import this file.
|
|
778
|
+
|
|
779
|
+
if __name__ == "__main__":
|
|
780
|
+
test_per("test.dat")
|
|
781
|
+
|