(file) Return to sosh.py CVS log (file) (dir) Up to [Development] / JSOC / proj / globalhs / sosh

  1 tplarson 1.1 import numpy as np
  2              import os
  3              import h5py
  4              import matplotlib.pyplot as plt
  5              #from matplotlib import animation
  6              
  7              modeln=np.array([])
  8              modell=np.array([])
  9              modelnu=np.array([])
 10              rmesh=np.array([])
 11              rho=np.array([])
 12              R=0.0
 13              
 14              def loadmodel():
 15              
 16              #  in_dir = '/home/tplarson/solar/mods'
 17                in_dir = 'mods'
 18                fname = 'mods_p3_eigfcn.h5'
 19                hf = h5py.File(os.path.join(in_dir, fname))
 20              
 21              # load r, rho and R from "model"
 22 tplarson 1.1   global rmesh, rho, R
 23                rmesh, rho, R = [hf['model'][k].value for k in ['r', 'rho', 'R']]
 24                rmesh /= R
 25              
 26              # load l and n from "modes"
 27                global modeln, modell, modelnu
 28                modeln, modell, modelnu = [hf['modes'][k].value for k in ['n', 'l', 'nu']]
 29              
 30              
 31              def getradial(l,n):
 32              
 33              #  in_dir = '/home/tplarson/solar/mods'
 34                in_dir = 'mods'
 35                fname = 'mods_p3_eigfcn.h5'
 36                hf = h5py.File(os.path.join(in_dir, fname))
 37              
 38              # open y1 and y2 data sets from "modes" (without reading the data)
 39                y1ds = hf['modes/y1'] 
 40                y2ds = hf['modes/y2']
 41              
 42                idx = ((modeln == n) & (modell == l))
 43 tplarson 1.1   y1, y2 = y1ds[idx,:], y2ds[idx,:]
 44              
 45              # compute xi_r and xi_h
 46                L2 = l * (l + 1)
 47                xir = (y1 * R).flatten()
 48                if (l > 0):
 49                  xih = (y2 * R / L2).flatten()
 50                else:
 51                  xih = 0.0*xir
 52              
 53                return (xir, xih)
 54              
 55              
 56              def writemodel(lmin=0, lmax=300, rsurf=1.0):
 57              
 58                outfile='modes.model.txt'
 59                file=open(outfile,'w')
 60                in_dir = 'mods'
 61                fname = 'mods_p3_eigfcn.h5'
 62                hf = h5py.File(os.path.join(in_dir, fname))
 63              
 64 tplarson 1.1 # load r, rho and R from "model"
 65                rmesh, c, R = [hf['model'][k].value for k in ['r', 'c', 'R']]
 66                indsurf = np.abs(rmesh-rsurf*R).argmin()
 67              
 68              # load l and n from "modes"
 69                modeln, modell, modelnu, modelsig2, modelE = [hf['modes'][k].value for k in ['n', 'l', 'nu', 'sigma2', 'E']]
 70              
 71                outfmt='{:d} {:d} {:f} {:f} {:f} {:f} {:f} {:f} {:f}'
 72                l=0
 73                while (l <= lmax):
 74                  ind = (modell == l)
 75                  nlist = modeln[ind]
 76                  for n in nlist:
 77                    xir, xih = getradial(l,n)
 78              #      rc=float(xir[indsurf])
 79              #      hc=float(xih[indsurf])
 80                    rc=np.interp(rsurf*R,rmesh,xir)
 81                    hc=np.interp(rsurf*R,rmesh,xih)
 82                    ind2 = (modell == l) & (modeln == n)
 83                    nu = float(modelnu[ind2])
 84                    erg = float(modelE[ind2])*1e6
 85 tplarson 1.1       sig2 = float(modelsig2[ind2])
 86                    if (l > 0):
 87                      L=np.sqrt(l*(l+1))
 88              #        indturn=np.abs(rmesh/c - L/(2*np.pi*nu)).argmin()
 89              #        rturn=float(rmesh[indturn]/R)
 90                      rturn=np.interp(L/(2*np.pi*nu),rmesh/c,rmesh)/R
 91                    else:
 92                      rturn=0.0
 93                    amp=nu*np.sqrt(np.square(rc)+l*(l+1)*np.square(hc))
 94                    nu*=1e6
 95                    amp=float(amp)/30e6
 96              #      outstr=f'{l:d} {n:d} {nu:f} {amp:f} {sig2:f} {rc:f} {hc:f} {rturn:f} {erg:f}'
 97                    outstr=outfmt.format(int(l),int(n),nu,amp,sig2,rc,hc,rturn,erg)
 98                    file.write('%s\n' % (outstr))
 99                  l+=1
100                file.close()
101              
102              
103              
104              def image2sphere(xpixels=1000, ypixels=1000, distobs=220.0, \
105                               bangle=-30.0, pangle=0.0):
106 tplarson 1.1 
107                p = pangle*np.pi/180
108                b0 = bangle*np.pi/180
109                #distobs = 220.0  # solar radii
110                #xpixels = 1000
111                #ypixels = 1000 
112                x0 = xpixels/2-0.5
113                y0 = ypixels/2-0.5
114                imscale = 1.97784*1024/xpixels
115                scale = imscale/(180*60*60/np.pi)
116                rsun=np.tan(np.arcsin(1/distobs))/scale
117              
118              # Sun is sitting at the center of the main coordinate system and has radius 1.
119              # Observer is at robs=(xobs,yobs,zobs) moving with a velocity vobs.
120              # Start by setting robs from distobs and b0
121              
122                robs_x = distobs * np.cos(b0)
123                robs_y = 0.0
124                robs_z = distobs * np.sin(b0)
125              
126              # image coordinates
127 tplarson 1.1   xx = np.linspace(0, xpixels-1, xpixels)
128                yy = np.linspace(0, ypixels-1, ypixels)
129                xx, yy = np.meshgrid(xx, yy)
130              
131                x2 = scale*(xx - x0)
132                y2 = scale*(yy - y0)
133              # Rotate by the P-angle. New coordinate system has the y-axis pointing
134              # towards the solar north pole.
135                x1 =  x2*np.cos(p) + y2*np.sin(p)
136                y1 = -x2*np.sin(p) + y2*np.cos(p)
137              
138              # Now transform to put the coordinates into the solar coordinate system.
139              # First find the directions (vecx and vecy) the x2 and y2 coordinate
140              # axis correspond to. vecsun points towards the Sun. Note that the
141              # (x2,y2,Sun) system is left handed. These vectors are unit vectors.
142              
143                vecx_x=0.0
144                vecx_y=1.0
145                vecx_z=0.0
146                vecy_x=-np.sin(b0)
147                vecy_y=0.0
148 tplarson 1.1   vecy_z=np.cos(b0)
149                vecsun_x=-np.cos(b0)
150                vecsun_y=0.0
151                vecsun_z=-np.sin(b0)
152              
153              # Now the proper direction can be found. These are not unit vectors.
154                x = vecx_x*x1 + vecy_x*y1 + vecsun_x
155                y = vecx_y*x1 + vecy_y*y1 + vecsun_y
156                z = vecx_z*x1 + vecy_z*y1 + vecsun_z
157                qq = 1/np.sqrt(x*x + y*y + z*z)
158              # Make them unit vectors.
159                x*=qq
160                y*=qq
161                z*=qq
162              
163              # Now find intersection with the Sun.
164              # Solve quadratic equation |robs+q*[x1,y1,z1]|=1 for q
165              # a, b and c are terms in a*x^2+bx+c=0. a==1 since [x1,y1,z1] is unit vector.
166                c = robs_x*robs_x + robs_y*robs_y + robs_z*robs_z -1
167                b = 2*(x*robs_x+y*robs_y+z*robs_z)
168                d = b*b - 4*c
169 tplarson 1.1   index = (d >= 0)
170                q = np.zeros([xpixels,ypixels])
171                xsun = np.zeros([xpixels,ypixels])
172                ysun = np.zeros([xpixels,ypixels])
173                zsun = np.zeros([xpixels,ypixels])
174                q[index]=(-b[index] - np.sqrt(d[index]))/2
175                xsun[index]=robs_x + x[index]*q[index]
176                ysun[index]=robs_y + y[index]*q[index]
177                zsun[index]=robs_z + z[index]*q[index]
178              
179                phisun = np.arctan2(ysun,xsun)
180                thetasun = np.pi/2 - np.arcsin(zsun)
181              
182                ph=np.ma.array(phisun, mask=np.logical_not(index))
183                th=np.ma.array(thetasun, mask=np.logical_not(index))
184              
185                return (ph, th) 
186              
187              
188              def image2rtheta(xpixels=1000, ypixels=1000, distobs=220.0):
189              
190 tplarson 1.1   imscale = 1.97784*1024/xpixels
191                scale = imscale/(180*60*60/np.pi)
192                rsun=np.tan(np.arcsin(1/distobs))/scale
193                x0 = xpixels/2-0.5
194                y0 = ypixels/2-0.5
195                xx = (np.linspace(0, xpixels-1, xpixels)-x0)/rsun
196                yy = (np.linspace(0, ypixels-1, ypixels)-y0)/rsun
197                xx, yy = np.meshgrid(xx, yy)
198                rr = np.sqrt(xx*xx+yy*yy)
199                index = (rr <= 1.0)
200                lat = np.arctan(yy/np.abs(xx))
201                r = np.ma.array(rr, mask=np.logical_not(index))
202                theta = np.ma.array(np.pi/2 - lat, mask=np.logical_not(index))
203              
204                return (r, theta)
205              
206              
207              def setplm(l, m, x, plm, dplm): 
208              
209              # adapted from setplm.pro by Jesper Schou
210              # Set plm(*,l)=P_l^m (x) for l=m,lmax
211 tplarson 1.1 # optionally sets dplm(*,l)={{dP_l^m} \over dx} (x) for l=m,lmax
212              # P_l^m 's are normalized to have \int_{-1}^1 (P_l^m (x))^2 dx = 1
213              # Works up to l \approx 1800, see ~/invnew/plm.f for details
214              
215                eps = 1.0e-12
216                x1 = np.maximum(np.minimum(x,1-eps),eps-1)
217                x2 = 1.0/(x1*x1-1.0)
218                x3 = x1*x2
219                c = np.sqrt((2*m+1)/2.0)
220                for i in range(1,m+1):
221                  c *= -np.sqrt(1.0-0.5/i)
222                plm[...,0] = c*(np.sqrt(1.0-x1*x1))**m
223                if (l > m):
224                  c = np.sqrt(2.0*m+3.0)
225                  plm[...,1] = c*x1*plm[...,0]
226                i = m+2
227                while (i <= l):
228                  c1 = np.sqrt((4.0*i*i-1.0)/(i*i-m*m))
229                  c2 = np.sqrt(((2.0*i+1.0)*(i+m-1.0)*(i-m-1.0))/((2.0*i-3.0)*(i*i-m*m)))
230                  plm[...,i-m] = c1*x1*plm[...,i-m-1] - c2*plm[...,i-m-2]
231                  i+=1
232 tplarson 1.1 
233                dplm[...,0] = m*x3*plm[...,0]
234                i = m+1
235                while (i <= l):
236                  c = np.sqrt((2.0*i+1.0)*(i*i-m*m)/(2.0*i-1))
237                  dplm[...,i-m] = i*x3*plm[...,i-m] - c*x2*plm[...,i-m-1]
238                  i+=1
239              
240                return (plm[...,l-m],dplm[...,l-m])
241              
242              
243              def apols(lin, amaxin):
244              
245              # adapted from IDL procedure apols.pro written by Jesper Schou
246              
247                l=np.long(lin)
248                amax=np.minimum(amaxin,2*l)
249              
250                pols=np.zeros((2*l+1,amaxin+1))
251              # It is ESSENTIAL that x is set up such that x(-m)=-x(m) to full machine
252              # accuracy or that the re-orthogonalization is done with respect to all
253 tplarson 1.1 # previous polynomials (second option below).
254              # x=(dindgen(2*l+1)-l)/l
255                x=np.linspace(-1,1,2*l+1)
256              
257                pols[:,0]=1/np.sqrt(2*l+1.0)
258                if (amax >= 1):
259                  pols[:,1]=x/np.sqrt((l+1.0)*(2*l+1.0)/(3.0*l))
260              # for n=2l,amax do begin
261              # Set up polynomials using exact recurrence relation.
262                for n in range(2,amax+1):
263                  a0=2.0*l*(2*n-1.0)/(n*(2*l-n+1))
264                  b0=-(n-1.0)/n*(2*l+n)/(2*l-n+1)
265                  a=a0*np.sqrt((2*n+1.0)/(2*n-1.0)*(2*l-n+1.0)/(2*l+n+1.0))
266                  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))
267                  help=a*x*pols[:,n-1]+b*pols[:,n-2]
268              # Turns out that roundoff kills the algorithm, so we have to re-orthogonalize.
269              # Two choices here. First one is twice as fast and more accurate, but
270              # depends on the rounding being done in the standard IEEE way.
271              #  for j=n-2,0,-2 do begin 
272                  for j in range(n-2,-1,-2):    
273              # This choice is robust to the roundoff, but twice as slow and generally
274 tplarson 1.1 # somewhat less accurate
275              # for j=n-1,0,-1 do begin
276                    help=help-pols[:,j]*np.sum(help*pols[:,j])
277              #  end
278              # Reset norm to 1.
279                  pols[:,n]=help/np.sqrt(np.sum(np.square(help)))
280              
281              # Reset polynomials to have P_l(l)=l by setting overall norm.
282              # Note that this results in more accurate overall normalization, but
283              # that P_l(l) may be very far from l. This is the key to the algorithm.
284                c=l**2*(2*l+1.0)
285              # for n=0l,amax do begin
286                for n in range(0,amax+1):
287                  c=c*(2*l+n+1.0)/(2*l-n+1.0)
288                  pols[:,n]=pols[:,n]*np.sqrt(c/(2*n+1))
289              
290                return pols
291              
292              
293              lsave=0
294              msave=0
295 tplarson 1.1 nsave=1
296              
297              def querylmn():
298              
299                global lsave, msave, nsave
300                lstr=catchc("Enter spherical harmonic degree (l): ",lsave)
301                if lstr == 'q':
302                  return (-1,-1,-1)
303                else:
304                  while True:
305                    try:
306                      lval=int(lstr)
307                      if lval < 0:
308                        print("Degree must be greater than or equal to zero. Try again.")
309                        lstr=catchc("Enter spherical harmonic degree (l): ",lsave)
310                        if lstr == 'q':
311                          return (-1,-1,-1)
312                        continue
313                      break
314                    except:
315                      print("Invalid number, try again.")
316 tplarson 1.1         lstr=catchc("Enter spherical harmonic degree (l): ", lsave)
317                      if lstr == 'q':
318                        return (-1,-1,-1)
319              
320                mstr=catchc("Enter azimuthal order (m): ",msave)
321                if mstr == 'q':
322                  return (-1,-1,-1)
323                else:
324                  while True:
325                    try:
326                      mval=int(mstr)
327                      if np.abs(mval) > lval:
328                        print("Azimuthal order must be in the range -l <= m <= l. Try again.")
329                        mstr=catchc("Enter azimuthal order (m): ",msave)
330                        if mstr == 'q':
331                          return (-1,-1,-1)
332                        continue
333                      break
334                    except:
335                      print("Invalid number, try again.")
336                      mstr=catchc("Enter azimuthal order (m): ",msave)
337 tplarson 1.1         if mstr == 'q':
338                        return (-1,-1,-1)
339              
340                nstr=catchc("Enter radial order (n): ",nsave)
341                if nstr == 'q':
342                  return (-1,-1,-1)
343                else:
344                  while True:
345                    try:
346                      nval=int(nstr)
347                      if nval < 0:
348                        print("Radial order must be greater than or equal to zero. Try again.")
349                        nstr=catchc("Enter radial order (n): ",nsave)
350                        if nstr == 'q':
351                          return (-1,-1,-1)
352                        continue
353                      break
354                    except:
355                      print("Invalid number, try again.")
356                      nstr=catchc("Enter radial order (n): ",nsave)
357                      if nstr == 'q':
358 tplarson 1.1           return (-1,-1,-1)
359              
360                lsave=lval
361                msave=mval
362                nsave=nval
363                return (lval,mval,nval)
364              
365              
366              varlist=['Vr', 'Vt', 'Vp', 'Vh', 'Vmag', 'Vsq']
367              colormap="seismic"
368              plotvar="Vr"
369              isave=0
370              
371              def queryplotparms():
372              
373                global colormap, plotvar, isave
374                print("You may enter 'l' to list options.")
375                cmap=input("Enter name of colormap: ")
376                while True:
377                  if (cmap == 'q'):
378                    return cmap
379 tplarson 1.1     if (cmap == ''):
380                    print("Using saved value colormap = %s." % colormap)
381                    cmap=colormap
382                    break
383                  if (cmap == 'l'):
384                    printcmaps()
385                    print("Current colormap is %s." % colormap)
386                    cmap=input("Enter name of colormap: ")
387                    continue
388                  elif (cmap not in plt.colormaps()):
389                    print("That colormap not registered, try again.")
390                    cmap=input("Enter name of colormap: ")
391                    continue
392                  else:
393                    break
394                colormap=cmap
395                  
396                pvar=input("Enter variable to plot: ")
397                while True:
398                  if (pvar == 'q'):
399                    return pvar
400 tplarson 1.1     if (pvar == ''):
401                    print("Using saved value plotvar = %s." % plotvar)
402                    pvar=plotvar
403                    break
404                  if (pvar == 'l'):
405                    print("Available plotting variables are: ", end="")
406                    for i in varlist[:len(varlist)-1]:
407                      print(i, end=", ")
408                    print("and %s" % varlist[len(varlist)-1], end=".\n")
409                    print("Currently plotting %s." % plotvar)
410                    pvar=input("Enter variable to plot: ")
411                    continue
412                  elif (pvar not in varlist):
413                    print("That variable not available, try again.")
414                    pvar=input("Enter variable to plot: ")
415                    continue
416                  else:
417                    break
418                plotvar=pvar
419              
420                ss=input("Save output to file? (y/n) ")
421 tplarson 1.1   if (ss == 'q'):
422                  return ss
423                if (ss != 'y'):
424                  isave=0
425                  print("Save off.")
426                else:
427                  isave=1
428                  print("Save on.")
429              
430              
431              def catchc(prompt, saveval):
432              
433                valstr=input(prompt)
434                if (valstr == 'q'):
435                  return valstr
436                while (valstr == 'c'):
437                  c=queryplotparms()
438                  if (c == 'q'):
439                    return c
440                  valstr=input(prompt)
441                if (valstr == ''):
442 tplarson 1.1     print("Using saved value %i." % saveval)
443                  valstr=str(saveval)
444                return valstr
445              
446              def printcmaps():
447              
448                print("Options include the following nonexhaustive list.  You may append '_r' to any name to reverse the map. \
449              More information is available at https://matplotlib.org/tutorials/colors/colormaps.html")
450              
451                cmaps = [('Perceptually Uniform Sequential', [
452                          'viridis', 'plasma', 'inferno', 'magma', 'cividis']),
453                       ('Sequential', [
454                          'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
455                          'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
456                          'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
457                       ('Sequential (2)', [
458                          'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
459                          'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
460                          'hot', 'afmhot', 'gist_heat', 'copper']),
461                       ('Diverging', [
462                          'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
463 tplarson 1.1             'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
464              #         ('Cyclic', ['twilight', 'twilight_shifted', 'hsv']),
465                       ('Qualitative', [
466                          'Pastel1', 'Pastel2', 'Paired', 'Accent',
467                          'Dark2', 'Set1', 'Set2', 'Set3',
468                          'tab10', 'tab20', 'tab20b', 'tab20c']),
469                       ('Miscellaneous', ['hsv', 
470                          'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
471                          'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
472                          'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])]
473              
474                for c in cmaps:
475                  print("%s:" % c[0])
476                  for m in c[1]:
477                    print(m,end=" ")
478                  print("")
479              
480              
481              def nothing():
482                return None
483              
484 tplarson 1.1 nframes=64
485              dpi=300
486              pngdirfmt = './png/l{:d}_m{:d}_n{:d}_{:s}'
487              animate=nothing
488              
489              def drawfigure(var, fsize=5):
490              
491                fig, ax = plt.subplots(num=1, figsize=(fsize, fsize))
492              #  ax.set(xlim=(-lim, lim), ylim=(-lim, lim))
493              
494                ax.clear()
495                im=ax.imshow(var,cmap=colormap)
496                ax.set_axis_off()
497                fig.canvas.draw()
498              
499                return (fig,im)
500              
501              def savefigure(animateflag=1):
502              
503                l=lsave
504                m=msave
505 tplarson 1.1   n=nsave
506                if (animateflag == 0):
507                  savestr="l%im%in%i.png" % (l,m,n)
508                  plt.savefig(savestr, dpi=dpi)
509                  print("File saved.")
510                else:
511                  pngdir = pngdirfmt.format(l, m, n, plotvar)
512                  if not os.path.exists(pngdir):
513                    os.makedirs(pngdir)
514                  print("Writing files...", end="")
515                  for i in range(nframes):
516                    animate(i)
517                    fpath = os.path.join(pngdir, '{:03d}.png'.format(i))
518                    print(i, end=" ", flush=True)
519                    plt.savefig(fpath, dpi=dpi)
520                  print("done.")
521              
522              

Karen Tian
Powered by
ViewCVS 0.9.4