ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/globalhs/sosh/soshdata.py
Revision: 1.4
Committed: Mon Apr 8 16:52:19 2019 UTC (4 years, 5 months ago) by tplarson
Content type: text/x-python
Branch: MAIN
CVS Tags: Ver_9-5, Ver_9-4, Ver_LATEST, Ver_9-41, HEAD
Changes since 1.3: +258 -1 lines
Log Message:
new versions

File Contents

# Content
1 import numpy as np
2 import os
3 import re
4 import drms
5 from astropy.io import fits
6 from urllib.request import urlretrieve
7 import soundfile as sf
8 from scipy import fftpack
9
10 import warnings
11 warnings.simplefilter(action='ignore', category=FutureWarning)
12
13 #datadir = '/home/tplarson/solar/data'
14 datadir = '../data'
15
16 def getmodeparms(instrument=None, day=None, lmin=0, lmax=300, makemsplit=True):
17
18 if not os.path.exists(datadir):
19 os.makedirs(datadir)
20
21 if (instrument == None):
22 inst=input("Enter name of instrument: ")
23 else:
24 inst=instrument
25
26 if (day == None):
27 daystr=input("Enter day number: ")
28 else:
29 daystr=str(day)
30
31 mfile=getmfile(inst.lower(), daystr)
32 if (mfile == None):
33 return None
34
35 if (makemsplit):
36 msfile=mfile+'.msplit'
37
38 if os.path.exists(msfile):
39 print("Msplit file already exists.")
40 else:
41 msfile=mkmsplit(mfile,lmin=lmin,lmax=lmax)
42
43 return mfile,msfile
44 else:
45 return mfile
46
47
48 def getmfile(inst, daystr):
49
50 if (inst == 'hmi'):
51 qblank = 'hmi.V_sht_modes[{:d}d][0][300][138240]'
52 avgurl = 'http://sun.stanford.edu/~tplarson/audio/HMI/hmi.average.modes'
53 elif (inst == 'mdi'):
54 qblank = 'mdi.vw_V_sht_modes[{:d}d][0][300][103680]'
55 avgurl = 'http://sun.stanford.edu/~tplarson/audio/MDI/mdi.average.modes'
56 else:
57 print("Invalid instrument, try again.")
58 return None
59
60 if (daystr == 'average'):
61 mblank = '%s.average.modes'
62 mfile=os.path.join(datadir,mblank % inst)
63 if os.path.exists(mfile):
64 print("Mode fits file already exists.")
65 else:
66 try:
67 urlretrieve(avgurl, mfile)
68 except:
69 print("Failure of urlretrieve() for %s." % avgurl)
70 return None
71 else:
72 mblank = '%s.%sd.modes'
73 mfile=os.path.join(datadir,mblank % (inst, daystr))
74 if os.path.exists(mfile):
75 print("Mode fits file already exists.")
76 else:
77 try:
78 day=int(daystr)
79 except:
80 print("Invalid number, try again.")
81 return None
82 qstr=qblank.format(day)
83 c = drms.Client()
84 m = c.query(qstr, seg='m6')
85 if (len(m) == 0):
86 print("No data found for that day number, try again.")
87 return None
88 url = 'http://jsoc.stanford.edu' + m.m6[0]
89 try:
90 urlretrieve(url, mfile)
91 except:
92 print("Failure of urlretrieve() for %s." % url)
93 return None
94
95 return mfile
96
97
98 def mkmsplit(mfile, lmin=0, lmax=300):
99
100 modeparms=np.loadtxt(mfile)
101 lmod=modeparms[:,0]
102 nmod=modeparms[:,1]
103
104 outfmt='{:d} {:d} {:d} {:f} {:f}'
105 outfile = mfile + '.msplit'
106 file=open(outfile,'w')
107
108 l=lmin
109 while (l <= lmax):
110 pols=apols(l,6)
111 ind = (lmod == l)
112 nlist = nmod[ind]
113 for n in nlist:
114 ind2 = (lmod == l) & (nmod == n)
115 ai=np.append([0.0],modeparms[ind2,12:18]/1000)
116 ei=np.append([0.0],modeparms[ind2,18:24]/1000)
117 fx=np.matmul(pols,ai)
118 freq=modeparms[ind2,2]+fx
119 var=np.matmul((pols*pols),(ei*ei))
120 sig=modeparms[ind2,7]+np.sqrt(var)
121 for m in range(-l,l+1):
122 outstr=outfmt.format(int(l),int(n),int(m),freq[m+l],sig[m+l])
123 file.write('%s\n' % (outstr))
124 l+=1
125 file.close()
126 return outfile
127
128
129 def getwavfiles(instrument=None, day=None, l=None, m=None, delfits=False):
130
131 if not os.path.exists(datadir):
132 os.makedirs(datadir)
133
134 if (instrument == None):
135 inst=input("Enter name of instrument: ")
136 else:
137 inst=instrument
138
139 if (inst.lower() == 'hmi'):
140 hind=1
141 elif (inst.lower() == 'mdi'):
142 hind=0
143 else:
144 print("Invalid instrument, try again.")
145 return None
146
147 if (day == None):
148 daystr=input("Enter day number: ")
149 try:
150 day=int(daystr)
151 except:
152 print("Invalid number, try again.")
153 return None
154 if (l == None):
155 lstr=input("Enter spherical harmonic degree: ")
156 try:
157 l=int(lstr)
158 except:
159 print("Invalid number, try again.")
160 return None
161 if (m == None):
162 mstr=input("Enter azimuthal order: ")
163 try:
164 m=int(mstr)
165 m=np.abs(m)
166 if (m > l):
167 print("Abs(m) must be less than l, try again.")
168 return None
169 except:
170 print("Invalid number, try again.")
171 return None
172
173 wblank = '%s.%id_72d.l=%i_m=%i_data%s.wav'
174 wfile=os.path.join(datadir,wblank % (inst.lower(),day,l,m,'r'))
175 wfile2=os.path.join(datadir,wblank % (inst.lower(),day,l,m,'i'))
176 if os.path.exists(wfile) and (m==0 or os.path.exists(wfile2)):
177 if (m == 0):
178 print("Wav file already exists.")
179 return wfile
180 else:
181 print("Wav files already exists.")
182 return wfile,wfile2
183
184 ffile=getfitsfile(inst.lower(),day,l)
185 if (ffile == None):
186 return None
187
188 wf=convertfitstowav(ffile, hind, m, wfile)
189 if (wf == None):
190 return None
191
192 if delfits:
193 os.remove(ffile)
194 return wf
195
196
197 def getfitsfile(inst, day, l):
198
199 if (inst == 'hmi'):
200 qblank = 'hmi.V_sht_gf_72d[{:d}d][{:d}][{:d}][138240]'
201 elif (inst == 'mdi'):
202 qblank = 'mdi.vw_V_sht_gf_72d[{:d}d][{:d}][{:d}][103680]'
203 else:
204 print("Invalid instrument, try again.")
205 return None
206
207 fblank='%s.%id.%i.fits'
208 ffile=os.path.join(datadir,fblank % (inst,day,l))
209 if os.path.exists(ffile):
210 print("Fits file already exists.")
211 else:
212 qstr=qblank.format(day,l,l)
213 c = drms.Client()
214 f = c.query(qstr,seg='data')
215 if (len(f) == 0):
216 print("No data found for that day number and degree, try again.")
217 return None
218 url = 'http://jsoc.stanford.edu' + f.data[0]
219 try:
220 urlretrieve(url, ffile)
221 except:
222 print("Failure of urlretrieve() for %s." % url)
223 return None
224
225 return ffile
226
227
228 def convertfitstowav(ffile, hind, m, wfile):
229
230 hdul = fits.open(ffile)
231 h=hdul[hind]
232 d=h.data
233 x=d[m,0::2]/np.abs(d[m,:]).max()
234 sf.write(wfile, x, 8000, subtype='FLOAT')
235
236 if (m > 0):
237 wfile2=wfile.replace('datar','datai')
238 x=d[m,1::2]/np.abs(d[m,:]).max()
239 sf.write(wfile2, x, 8000, subtype='FLOAT')
240
241 hdul.close()
242 if (m==0):
243 return wfile
244 else:
245 return wfile,wfile2
246
247
248 def apols(lin, amaxin):
249
250 # adapted from IDL procedure apols.pro written by Jesper Schou
251
252 l=np.long(lin)
253 amax=np.minimum(amaxin,2*l)
254
255 pols=np.zeros((2*l+1,amaxin+1))
256 # It is ESSENTIAL that x is set up such that x(-m)=-x(m) to full machine
257 # accuracy or that the re-orthogonalization is done with respect to all
258 # previous polynomials (second option below).
259 # x=(dindgen(2*l+1)-l)/l
260 x=np.linspace(-1,1,2*l+1)
261
262 pols[:,0]=1/np.sqrt(2*l+1.0)
263 if (amax >= 1):
264 pols[:,1]=x/np.sqrt((l+1.0)*(2*l+1.0)/(3.0*l))
265 # for n=2l,amax do begin
266 # Set up polynomials using exact recurrence relation.
267 for n in range(2,amax+1):
268 a0=2.0*l*(2*n-1.0)/(n*(2*l-n+1))
269 b0=-(n-1.0)/n*(2*l+n)/(2*l-n+1)
270 a=a0*np.sqrt((2*n+1.0)/(2*n-1.0)*(2*l-n+1.0)/(2*l+n+1.0))
271 b=b0*np.sqrt((2*n+1.0)/(2*n-3.0)*(2*l-n+1.0)*(2*l-n+2.0)/(2*l+n+1.0)/(2*l+n))
272 help=a*x*pols[:,n-1]+b*pols[:,n-2]
273 # Turns out that roundoff kills the algorithm, so we have to re-orthogonalize.
274 # Two choices here. First one is twice as fast and more accurate, but
275 # depends on the rounding being done in the standard IEEE way.
276 # for j=n-2,0,-2 do begin
277 for j in range(n-2,-1,-2):
278 # This choice is robust to the roundoff, but twice as slow and generally
279 # somewhat less accurate
280 # for j=n-1,0,-1 do begin
281 help=help-pols[:,j]*np.sum(help*pols[:,j])
282 # end
283 # Reset norm to 1.
284 pols[:,n]=help/np.sqrt(np.sum(np.square(help)))
285
286 # Reset polynomials to have P_l(l)=l by setting overall norm.
287 # Note that this results in more accurate overall normalization, but
288 # that P_l(l) may be very far from l. This is the key to the algorithm.
289 c=l**2*(2*l+1.0)
290 # for n=0l,amax do begin
291 for n in range(0,amax+1):
292 c=c*(2*l+n+1.0)/(2*l-n+1.0)
293 pols[:,n]=pols[:,n]*np.sqrt(c/(2*n+1))
294
295 return pols
296
297
298 def splitwavfile(wavfile=None, splitfactor=2, splitboth=True):
299
300 wblank = '%s.%id_%id.l=%i_m=%i_data%s.wav'
301 outlist=[]
302
303 if (wavfile == None):
304 inst=input("Enter name of instrument: ")
305 inst=inst.lower()
306 if (inst != 'mdi' and inst != 'hmi'):
307 print("Invalid instrument, try again.")
308 return None
309 daystr=input("Enter day number: ")
310 try:
311 firstday=int(daystr)
312 except:
313 print("Invalid number, try again.")
314 return None
315 ndstr=input("Enter number of days: ")
316 try:
317 ndaysin=int(ndstr)
318 except:
319 print("Invalid number, try again.")
320 return None
321 lstr=input("Enter spherical harmonic degree: ")
322 try:
323 l=int(lstr)
324 if (l < 0):
325 print("Degree l must be nonnegative, try again.")
326 return None
327 except:
328 print("Invalid number, try again.")
329 return None
330 mstr=input("Enter azimuthal order: ")
331 try:
332 m=int(mstr)
333 m=np.abs(m)
334 if (m > l):
335 print("Abs(m) must be less than l, try again.")
336 return None
337 except:
338 print("Invalid number, try again.")
339 return None
340 ri='r'
341 wavfile=os.path.join(datadir,wblank % (inst,firstday,ndaysin,l,m,ri))
342 else:
343 regmatch = re.search(r"(\S+)\.(\d+)d_(\d+)d\.l=(\d+)_m=(\d+)_data(\S+).wav", wavfile)
344 if (regmatch == None):
345 print("Invalid file name, try again.")
346 return None
347 else:
348 inst=regmatch.group(1)
349 firstday=int(regmatch.group(2))
350 ndaysin=int(regmatch.group(3))
351 l=int(regmatch.group(4))
352 m=int(regmatch.group(5))
353 ri=regmatch.group(6)
354
355 test= ndaysin % splitfactor
356 if (test != 0):
357 print("Timeseries not divisible by that factor.")
358 return None
359
360 # wfile = os.path.join(datadir,wavfile)
361 try:
362 x, sr = sf.read(wavfile)
363 except:
364 print("Invalid file, try again.")
365 return None
366
367 if (inst == 'mdi'):
368 nperday = 1440
369 elif (inst == 'hmi'):
370 nperday = 1920
371
372 ndaysout = ndaysin / splitfactor
373 ndt=int(ndaysout*nperday)
374 day = firstday
375 index=0
376 while (day < firstday+ndaysin):
377 xout=x[index:index+ndt]
378 wfileout = os.path.join(datadir,wblank % (inst,day,ndaysout,l,m,ri))
379 sf.write(wfileout, xout, sr, subtype='FLOAT')
380 day += ndaysout
381 index += ndt
382 outlist.append(wfileout)
383
384 if (splitboth and m > 0):
385 if (ri == 'i'):
386 ir = 'r'
387 elif (ri == 'r'):
388 ir = 'i'
389 wfile=wblank % (inst,firstday,ndaysin,l,m,ir)
390 wavfile = os.path.join(datadir,wfile)
391 try:
392 x, sr = sf.read(wavfile)
393 except:
394 print("Invalid file, try again.")
395 return None
396 day=firstday
397 index=0
398 while (day < firstday+ndaysin):
399 xout=x[index:index+ndt]
400 wfileout = os.path.join(datadir,wblank % (inst,day,ndaysout,l,m,ir))
401 sf.write(wfileout, xout, sr, subtype='FLOAT')
402 day += ndaysout
403 index += ndt
404 outlist.append(wfileout)
405
406 return outlist
407
408
409 def scanspectrum(wavfile=None,downshift=4,firstbin=None,lastbin=None,nbins=200,ndt=10000,binstep=None,ramp=50):
410
411 if (binstep == None):
412 binstep = int(nbins/2)
413
414 wblank = '%s.%id_%id.l=%i_m=%i_data%s.wav'
415 if (wavfile == None):
416 inst=input("Enter name of instrument: ")
417 inst=inst.lower()
418 if (inst != 'mdi' and inst != 'hmi'):
419 print("Invalid instrument, try again.")
420 return None
421 daystr=input("Enter day number: ")
422 try:
423 firstday=int(daystr)
424 except:
425 print("Invalid number, try again.")
426 return None
427 ndstr=input("Enter number of days: ")
428 try:
429 ndaysin=int(ndstr)
430 except:
431 print("Invalid number, try again.")
432 return None
433 lstr=input("Enter spherical harmonic degree: ")
434 try:
435 l=int(lstr)
436 if (l < 0):
437 print("Degree l must be nonnegative, try again.")
438 return None
439 except:
440 print("Invalid number, try again.")
441 return None
442 mstr=input("Enter azimuthal order: ")
443 try:
444 m=int(mstr)
445 m=np.abs(m)
446 if (m > l):
447 print("Abs(m) must be less than l, try again.")
448 return None
449 except:
450 print("Invalid number, try again.")
451 return None
452 ri='r'
453 wavfile=os.path.join(datadir,wblank % (inst,firstday,ndaysin,l,m,ri))
454 print("Wav file is %s" % wavfile)
455 else:
456 regmatch = re.search(r"(\S+)\.(\d+)d_(\d+)d\.l=(\d+)_m=(\d+)_data(\S+).wav", wavfile)
457 if (regmatch == None):
458 print("Invalid file name, try again.")
459 return None
460 else:
461 inst=regmatch.group(1)
462 firstday=int(regmatch.group(2))
463 ndaysin=int(regmatch.group(3))
464 l=int(regmatch.group(4))
465 m=int(regmatch.group(5))
466 ri=regmatch.group(6)
467
468 try:
469 x, sr = sf.read(wavfile)
470 except:
471 print("Invalid file, try again.")
472 return None
473
474 z=np.zeros((len(x)),dtype=np.complex_)
475 if (ri == 'r'):
476 z.real=x
477 else:
478 z.imag=x
479
480 if (m > 0):
481 if (ri == 'i'):
482 ir = 'r'
483 elif (ri == 'r'):
484 ir = 'i'
485 wfile=wblank % (inst,firstday,ndaysin,l,m,ir)
486 wavfile = os.path.join(datadir,wfile)
487 try:
488 x, sr = sf.read(wavfile)
489 except:
490 print("Invalid file, try again.")
491 return None
492 else:
493 x=0.0*x
494
495 if (ri == 'r'):
496 z.imag=x
497 else:
498 z.real=x
499
500 window=np.ones(ndt)
501 if (ramp != 0):
502 rampsamples=int(sr*ramp/1000)
503 if (rampsamples > ndt/2):
504 print("Ramp longer than ndt/2, try again.")
505 return None
506 window[0:rampsamples]=np.linspace(0.0,1.0,rampsamples,endpoint=False)
507 window[ndt-1:ndt-rampsamples-1:-1]=np.linspace(0.0,1.0,rampsamples,endpoint=False)
508
509 nx=len(x)
510 nx2=int(nx/2)
511 if (firstbin == None):
512 firstbin = int(nx2/6)
513 if (lastbin == None):
514 lastbin = int(0.9*nx2)
515 ftz = fftpack.fft(z)
516 freq = fftpack.fftfreq(nx) #*sr
517 if (m >= 0):
518 mag = np.abs(ftz[0:nx2])
519 phase = np.arctan2(ftz[0:nx2].imag,ftz[0:nx2].real)
520 f = freq[0:nx2]/downshift
521 else:
522 mag = np.abs(ftz[nx:nx2:-1])
523 phase = np.arctan2(-1*ftz[nx:nx2:-1].imag,ftz[nx:nx2:-1].real)
524 f = -1*freq[nx:nx2:-1]/downshift
525
526 nstep=int((lastbin-firstbin)/binstep)
527 tlen=nstep*ndt
528 t=np.linspace(0,ndt-1,ndt)
529 xout=np.zeros((tlen))
530 bindex=firstbin
531 tindex=0
532 t0in=0
533 while (bindex + nbins <= lastbin):
534 for i in range(nbins):
535 xout[tindex:tindex+ndt]+=mag[bindex+i]*np.sin(2*np.pi*f[bindex+i]*(t+tindex)+phase[bindex+i])
536 xout[tindex:tindex+ndt]*=window
537 bindex+=binstep
538 tindex+=ndt
539
540 mx=np.abs(xout).max()
541 xout /= mx
542 sf.write('output.wav', xout, sr, subtype='FLOAT')
543
544 return xout
545
546
547 #def plotspectrum(wavfile):
548 # x, sr = sf.read(wavfile)
549 # ftx = fftpack.fft(x)
550 # freqs = fftpack.fftfreq(len(x)) * sr
551
552