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.
@@ -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
+