Skip to content

Instantly share code, notes, and snippets.

@TomNicholas
Created December 24, 2019 14:23
Show Gist options
  • Save TomNicholas/c8a0d4d7269df44bf36fdb7ca8b45c02 to your computer and use it in GitHub Desktop.
Save TomNicholas/c8a0d4d7269df44bf36fdb7ca8b45c02 to your computer and use it in GitHub Desktop.
Fabio's implementation of 3D plotting with mayavi
from netCDF4 import Dataset
import numpy as np
import scipy.interpolate
import scipy.io
import matplotlib.pyplot as plt
import math
def extract_region(var, regions, ir, yguards=True):
"""
Extract the data from an N-dimensional (with N=2 or N=4) variable corresponding to a given region
Inputs :
- the N-dimensional variable
- the list of all possible regions
- the index of the region of interest
- if it has to return y guard cells
Output :
- an N-dimensional array
"""
ixi = regions[ir].ix[0]
iyi = regions[ir].iy[0]
nx = regions[ir].ix.shape[0]
ny = regions[ir].iy.shape[0]
if(var.ndim == 2):
# 2D (x-y) array
if(yguards):
vartmp = np.full((nx,ny+2),np.nan)
vartmp[:,1:-1] = var[ixi:ixi+nx,iyi:iyi+ny]
if(regions[ir].yl == None):
# If no yl data: extrapolate
vartmp[:,0] = 2.*vartmp[:,1] - vartmp[:,2]
else:
vartmp[:,0] = var[ixi:ixi+nx,regions[regions[ir].yl].iy[-1]]
if(regions[ir].yu == None):
# If no yu data: extrapolate
vartmp[:,-1] = 2.*vartmp[:,-2] - vartmp[:,-3]
else:
vartmp[:,-1] = var[ixi:ixi+nx,regions[regions[ir].yu].iy[0]]
return vartmp
else:
return var[ixi:ixi+nx,iyi:iyi+ny]
elif(var.ndim == 4):
# 4D (t-x-y-z) array
if(yguards):
nt = var.shape[0]
nz = var.shape[3]
vartmp = np.full((nt,nx,ny+2,nz),np.nan)
vartmp[:,:,1:-1,:] = var[:,ixi:ixi+nx,iyi:iyi+ny,:]
if(regions[ir].yl == None):
# If no yl data: extrapolate
vartmp[:,:,0,:] = 2.*vartmp[:,:,1,:] - vartmp[:,:,2,:]
else:
ixi = regions[ir].ix[0]
vartmp[:,:,0,:] = var[:,ixi:ixi+nx,regions[regions[ir].yl].iy[-1],:]
if(regions[ir].yu == None):
# If no yl data: extrapolate
vartmp[:,:,-1,:] = 2.*vartmp[:,:,-2,:] - vartmp[:,:,-3,:]
else:
ixi = regions[ir].ix[0]
vartmp[:,:,-1,:] = var[:,ixi:ixi+nx,regions[regions[ir].yu].iy[0],:]
return vartmp
else:
return var[:,ixi:ixi+nx,iyi:iyi+ny,:]
def interpy(var, regions, ir, N):
"""
Return var interpolated along y on a grid N times more refined in region region
Inputs :
- the N-dimensional variable to be interpolated (for 4D variables these must be field aligned!)
- the list of all regions
- the index of the region of interest
- the refining factor N
Output :
- the interpolated N-dimensional variable
"""
nx = regions[ir].ix.shape[0]
ny = regions[ir].iy.shape[0]
nyi = ny*N
y = (np.arange(ny+2)-0.5)/ny
yi = (np.arange(nyi)+0.5)/nyi
vartmp = extract_region(var, regions, ir)
if(var.ndim == 2):
f = scipy.interpolate.interp1d(y, vartmp, axis=1)
elif(var.ndim == 4):
f = scipy.interpolate.interp1d(y, vartmp, axis=2)
return f(yi)
def shiftZ(var, zperiod, toaligned, zShift):
"""
Shift in z to aligned/orthogonal coordinates
"""
if(toaligned):
sign = 1
else:
sign = -1
nz = var.shape[3]
var_fft = np.fft.fft(var,axis=3)
kz = np.arange(0,nz*zperiod,zperiod)
var_aligned_fft = var_fft*np.exp(sign*1j*np.transpose(np.tile(zShift,(nz,1,1)),(1,2,0))*kz)
if(nz % 2 == 0):
nfft = int(nz/2)
var_aligned_fft[:,:,:,nfft] = var_aligned_fft[:,:,:,nfft].real
var_aligned_fft[:,:,:,nfft+1:] = np.conj(var_aligned_fft[:,:,:,nfft-1:0:-1])
else:
nfft = int((nz-1)/2)
var_aligned_fft[:,:,:,nfft+1:] = np.conj(var_aligned_fft[:,:,:,nfft:0:-1])
return np.fft.ifft(var_aligned_fft).real
class region:
"""
x-y subregion of the poloidal plane
ix and iy are the indexes defining the region (must be a sub domain of 0:nx-1 and 0:ny-1, respectively)
xl and xr point to the regions on the left/right of the subregion
yl and yu point to the regions below/above the subregion
"""
def __init__(self, ix=[], iy=[], xl=None, xr=None, yl=None, yu=None):
self.ix = ix
self.iy = iy
self.xl = xl
self.xr = xr
self.yl = yl
self.yu = yu
class field3D(object):
"""
3D field containing:
- the 4D (t,x,y,z) variable
- the Rxy and Zxy grid
- the zShift
- the different regions in the poloidal plane
- zperiod
"""
def __init__(self,filename=None, varname=None, yguards=True, isaligned=False, gridname=None, zperiod=None):
if filename is not None and varname is not None and gridname is not None:
self.filename = filename
self.varname = varname
self.isaligned = isaligned
# Load the variable
if(filename[-2:] == "nc"):
dataset = Dataset(filename)
self.var = np.array(dataset.variables[varname])
self.t = np.array(dataset.variables["t_array"])
elif(filename[-3:] == "mat"):
#data = scipy.io.loadmat(filename, variable_names={'t',varname})
data = scipy.io.loadmat(filename, variable_names=varname)
self.var = data[varname]
#self.t = data['t']
if(zperiod == None):
raise NameError("Please specify zperiod")
# Load the grid
self.griddata = Dataset(gridname)
self.gridname = gridname
self.Rxy = np.array(self.griddata.variables['Rxy'])
self.Zxy = np.array(self.griddata.variables['Zxy'])
self.zShift = np.array(self.griddata.variables['zShift'])
self.ShiftAngle = np.array(self.griddata.variables['ShiftAngle'])
self.zperiod = zperiod
# Interpolated variable
self.Rxy_i = None
self.Zxy_i = None
self.zShift_i = None
self.var_i = None
self.isaligned_i = None
self.regions_i = None
self.t_i = None
ixseps1 = self.griddata.variables['ixseps1'][0]
ixseps2 = self.griddata.variables['ixseps2'][0]
jyseps1_1 = self.griddata.variables['jyseps1_1'][0]
jyseps2_1 = self.griddata.variables['jyseps2_1'][0]
jyseps1_2 = self.griddata.variables['jyseps1_2'][0]
jyseps2_2 = self.griddata.variables['jyseps2_2'][0]
ny_inner = self.griddata.variables['ny_inner'][0]
nx = self.griddata.variables['nx'][0]
ny = self.griddata.variables['ny'][0]
if(self.var.shape[2] == ny and self.Rxy.shape[1] == ny):
print("The variable and the grid have the same number of y points.")
elif(self.var.shape[2] == ny+4 and self.Rxy.shape[1] == ny):
print("The variable has y guard cells, the grid not, removing guard cells from variables.")
self.var = self.var[:,:,2:-2,:]
elif(self.var.shape[2] == ny+4 and self.Rxy.shape[1] == ny+8):
print("The variable and the grid have y guard cells and the configuration has 4 targets, removing guard cells.")
self.var = self.var[:,:,2:-2,:]
self.Rxy = self.Rxy[:,np.r_[2:ny_inner+2,ny_inner+6:ny+6]]
self.Zxy = self.Zxy[:,np.r_[2:ny_inner+2,ny_inner+6:ny+6]]
self.zShift = self.zShift[:,np.r_[2:ny_inner+2,ny_inner+6:ny+6]]
elif(self.var.shape[2] == ny+4 and self.Rxy.shape[1] == ny+4):
print("The variable and the grid have y guard cells and the configuration has 2 targets, removing guard cells.")
self.var = self.var[:,:,2:-2,:]
self.Rxy = self.Rxy[:,2:-2]
self.Zxy = self.Zxy[:,2:-2]
self.zShift = self.zShift[:,2:-2]
else:
raise NameError("Not implemented for this number of y guard cells.")
if(nx != self.var.shape[1] or ny != self.var.shape[2]):
raise NameError("Variable size not consistent with grid size.")
regions = []
# Create the regions depending on the topology considered.
# Possibilities :
# - Core only
# - Target to target.
# - s-alpha
# - SN
# - X-point
# - Connected DN
# - Disconnected DN
if(jyseps2_1 == jyseps1_2):
if(ixseps1 != ixseps2):
raise NameError("Unknown topology.")
elif(ixseps1 > nx-1):
if(jyseps1_1 < 0 and jyseps2_2 >= ny-1):
print("Core only topology")
regions.append(region(ix=np.arange(nx), iy=np.arange(ny), yl=0, yu=0))
else:
raise NameError("Unknown topology.")
elif(ixseps1 <= 0):
print("Target to target topology")
regions.append(region(ix=np.arange(nx), iy=np.arange(ny)))
elif(jyseps1_1 < 0 and jyseps2_2 >= ny-1):
print("s-alpha topology")
# Core region (0)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny), xr=1, yl=0, yu=0))
# SOL region (1)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(ny), xl=0))
elif(jyseps1_1 >= 0 and jyseps2_2 < ny-1):
print("Single null topology")
# PFR inner (0)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_1+1), xr=4, yu=3))
# Core inner (1)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xr=5, yl=2, yu=2))
# Core outer (2)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xr=6, yl=1, yu=1))
# PFR outer (3)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xr=7, yl=0))
# SOL (4-7, clockwise)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps1_1+1), xl=0, yu=5))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xl=1, yl=4, yu=6))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xl=2, yl=5, yu=7))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy= np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xl=3, yl=6))
else:
raise NameError("Unknown topology.")
else:
if(ixseps1 == ixseps2):
if(jyseps1_1 == jyseps2_1 and jyseps1_2 == jyseps2_2):
print("X-point topology")
# Lower PFR, inner (0)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_1+1), xr=4, yu=3))
# Upper PFR, inner (1)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xr=5, yl=2))
# Upper PFR, outer (2)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xr=6, yu=1))
# Lower PFR, outer (3)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny-jyseps1_2-1)+jyseps1_2+1, xr=7, yl=0))
# Inner SOL (4-5)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps1_1+1), xl=0, yu=5))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xl=1, yl=4))
# Outer SOL (6-7)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xl=2, yu=7))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(ny-jyseps1_2-1)+jyseps1_2+1, xl=3, yl=6))
else:
print("Connected double null topology")
# Lower PFR, inner (0)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_1+1), xr=6, yu=5))
# Core inner (1)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xr=7, yl=4, yu=4))
# Upper PFR, inner (2)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xr=8, yl=3))
# Upper PFR, outer (3)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xr=9, yu=2))
# Core outer (4)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xr=10, yl=1, yu=1))
# Lower PFR, outer (5)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xr=11, yl=0))
# Inner SOL (6-8)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps1_1+1), xl=0, yu=7))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xl=1, yl=6, yu=8))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xl=2, yl=7))
# Outer SOL (9-11)
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xl=3, yu=10))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xl=4, yl=9, yu=11))
regions.append(region(ix=np.arange(nx-ixseps1)+ixseps1, iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xl=5, yl=10))
elif(ixseps1 > 0 and ixseps2 <= nx-1 and ixseps1 < ixseps2):
print("Disconnected double null topology")
# Lower PFR, inner (0)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps1_1+1), xr=6, yu=5))
# Core inner (1)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xr=7, yl=4, yu=4))
# Upper PFR, inner (2)
regions.append(region(ix=np.arange(ixseps2), iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xr=12, yl=3))
# Upper PFR, outer (3)
regions.append(region(ix=np.arange(ixseps2), iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xr=13, yu=2))
# Core outer (4)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xr=8, yl=1, yu=1))
# Lower PFR, outer (5)
regions.append(region(ix=np.arange(ixseps1), iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xr=9, yl=0))
# SOL between separatrices, inner (6-7)
regions.append(region(ix=np.arange(ixseps2-ixseps1)+ixseps1, iy=np.arange(jyseps1_1+1), xl=0, xr=10, yu=7))
regions.append(region(ix=np.arange(ixseps2-ixseps1)+ixseps1, iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xl=1, xr=11, yl=6, yu=8))
# SOL between separatrices, outer (8-9)
regions.append(region(ix=np.arange(ixseps2-ixseps1)+ixseps1, iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xl=4, xr=14, yl=7, yu=9))
regions.append(region(ix=np.arange(ixseps2-ixseps1)+ixseps1, iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xl=5, xr=15, yl=8))
# Inner SOL (10-12)
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(jyseps1_1+1), xl=6, yu=11))
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(jyseps2_1-jyseps1_1)+jyseps1_1+1, xl=7, yl=10, yu=12))
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(ny_inner-jyseps2_1-1)+jyseps2_1+1, xl=2, yl=11))
# Outer SOL (13-15)
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(jyseps1_2-ny_inner+1)+ny_inner, xl=3, yu=14))
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(jyseps2_2-jyseps1_2)+jyseps1_2+1, xl=8, yl=13, yu=15))
regions.append(region(ix=np.arange(nx-ixseps2)+ixseps2, iy=np.arange(ny-jyseps2_2-1)+jyseps2_2+1, xl=9, yl=14))
else:
raise NameError("Unknown topology.")
self.regions = regions
else:
raise NameError("Need a filename, a varname, and a gridfile to create a Field3D.")
def interp_var(self,N,it=None,aligned=False,log_interp=False):
"""
3D interpolation in y of field.
Inputs :
- The refinement factor N
- the timestep (None for all times)
- the interpolated variable is field aligned?
- Performing the interpolation in logarithmic?
"""
if(it == None):
nt = self.var.shape[0]
#self.t_i = self.t
else:
nt = 1
#self.t_i = self.t[it]
nx = self.var.shape[1]
ny = N*self.var.shape[2]
nz = self.var.shape[3]
zperiod = self.zperiod
self.Rxy_i = np.full((nx,ny),np.nan)
self.Zxy_i = np.full((nx,ny),np.nan)
self.zShift_i = np.full((nx,ny),np.nan)
self.var_i = np.full((nt,nx,ny,nz),np.nan)
self.isaligned_i = aligned
#Extract the relevant data
if(it == None):
var_tmp = self.var
else:
var_tmp = np.tile(self.var[it,:,:,:],(1,1,1,1))
if(log_interp):
var_tmp = np.log(var_tmp+1e-12)
if(not self.isaligned):
#Go to aligned coordinates
print("Shifting in z to field aligned...")
var_aligned = shiftZ(var_tmp, zperiod, True, self.zShift)
else:
var_aligned = var_tmp
# Interpolate in y
print("Interpolate in y...")
regions = []
for ir in range(len(self.regions)):
r = self.regions[ir]
nx = r.ix.shape[0]
nyi = r.iy.shape[0]*N
regions.append(region(ix=r.ix, iy=np.arange(nyi)+N*r.iy[0], xl=r.xl, xr=r.xr, yl=r.yl, yu=r.yu))
ixi = r.ix[0]
iyi = regions[-1].iy[0]
# Interpolate Rxy, Zxy, and zShift
self.Rxy_i[ixi:ixi+nx,iyi:iyi+nyi] = interpy(self.Rxy, self.regions, ir, N)
self.Zxy_i[ixi:ixi+nx,iyi:iyi+nyi] = interpy(self.Zxy, self.regions, ir, N)
if(r.yl == r.yu and r.yl != None):
# Core region, need to correct zShift
zShift_tmp = extract_region(self.zShift, self.regions, ir)
# Correct the guard cells
if(r.yl == ir):
# Only one core region, r
zShift_tmp[:,0] = zShift_tmp[:,-2] - self.ShiftAngle[ixi:ixi+nx]
zShift_tmp[:,-1] = zShift_tmp[:,1] + self.ShiftAngle[ixi:ixi+nx]
elif(r.yl > ir):
# Two core regions, I'm the lower one
zShift_tmp[:,0] = self.zShift[ixi:ixi+nx,self.regions[r.yl].iy[-1]] - self.ShiftAngle[ixi:ixi+nx]
else:
# Two core regions, I'm the upper one
zShift_tmp[:,-1] = self.zShift[ixi:ixi+nx,self.regions[r.yu].iy[0]] + self.ShiftAngle[ixi:ixi+nx]
# Interpolate in y
y = (np.arange(r.iy.shape[0]+2)-0.5)/r.iy.shape[0]
yi = (np.arange(nyi)+0.5)/nyi
f = scipy.interpolate.interp1d(y, zShift_tmp, axis=1)
self.zShift_i[ixi:ixi+nx,iyi:iyi+nyi] = f(yi)
else:
self.zShift_i[ixi:ixi+nx,iyi:iyi+nyi] = interpy(self.zShift, self.regions, ir, N)
# Interpolate in y var_aligned
self.var_i[:,ixi:ixi+nx,iyi:iyi+nyi,:] = interpy(var_aligned, self.regions, ir, N)
self.regions_i = regions
if(not aligned):
print("Shifting in z to orthogonal...")
self.var_i = shiftZ(self.var_i, zperiod, False, self.zShift_i)
if(log_interp):
self.var_i = np.exp(self.var_i)
def plot(self,method,interpolated=False,it=None,ix=None,iy=None,iz=None,remove_toroidal=0):
"""
Plot methods:
- method = 'xy',...
- plot for interpolated quantity?
- it->which snapshot
- ix = at which radial location?
- iy = at which poloidal location?
- iz = at which toroidal location?
- remove_toroidal = 0 -> no modifications
remove_toroidal = 1 -> A - A_DC (z-fluctuations)
remove_toroidal = 2 -> (A-A_DC)/A_DC (relative z.fluctuations)
"""
if(interpolated):
if(not isinstance(self.Rxy_i,np.ndarray)):
raise NameError("Execute field3D.interp_var before trying to plot the interpolated variable.")
var = self.var_i
Rxy = self.Rxy_i
Zxy = self.Zxy_i
regions = self.regions_i
isaligned = self.isaligned_i
else:
var = self.var
Rxy = self.Rxy
Zxy = self.Zxy
regions = self.regions
isaligned = self.isaligned
if(var.shape[0] > 1 and it == None):
raise NameError("Plot error: variable has several timesteps, but it not defined")
elif(var.shape[0] > 1):
var = var[it,:,:,:]
else:
var = var[0,:,:,:]
nz = var.shape[2]
if(remove_toroidal == 1):
var = var - np.transpose(np.tile(np.mean(var,axis=2),(nz,1,1)),(1,2,0))
elif(remove_toroidal == 2):
var_DC = np.transpose(np.tile(np.mean(var,axis=2),(nz,1,1)),(1,2,0)) + 1e-12
var = (var - var_DC)/var_DC
if(method == 'xy'):
if(isaligned):
# For the moment 'xy' only for plotting a poloidal plane
raise NameError("Plot xy error: variable is not orthogonal")
fig = plt.figure()
ax_list = fig.axes
if(iz == None):
raise NameError("Plot method xy, iz not defined.")
else:
var = var[:,:,iz]
m = var[2:-2,:].min()
M = var[2:-2,:].max()
for ir in range(len(regions)):
r = regions[ir]
nx = r.ix.shape[0]
ny = r.iy.shape[0]
ixi = r.ix[0]
iyi = r.iy[0]
# Remove x guard cells
if(r.xl == None):
ixi = 2
nx = nx - 2
if(r.xr == None):
nx = nx-2
var_tmp = var[ixi:ixi+nx,iyi:iyi+ny]
Rxy_tmp = Rxy[ixi:ixi+nx,iyi:iyi+ny]
Zxy_tmp = Zxy[ixi:ixi+nx,iyi:iyi+ny]
# Add guard cells to remove gaps in plotting between different regions
if(r.xr != None):
var_tmp = np.vstack([var_tmp, var[regions[r.xr].ix[0],iyi:iyi+ny]])
Rxy_tmp = np.vstack([Rxy_tmp, Rxy[regions[r.xr].ix[0],iyi:iyi+ny] ])
Zxy_tmp = np.vstack([Zxy_tmp, Zxy[regions[r.xr].ix[0],iyi:iyi+ny] ])
nx = nx+1
if(r.yu != None):
var_tmp = np.vstack([var_tmp.T, var[ixi:ixi+nx,regions[r.yu].iy[0]] ]).T
Rxy_tmp = np.vstack([Rxy_tmp.T, Rxy[ixi:ixi+nx,regions[r.yu].iy[0]] ]).T
Zxy_tmp = np.vstack([Zxy_tmp.T, Zxy[ixi:ixi+nx,regions[r.yu].iy[0]] ]).T
plt.pcolormesh(Rxy_tmp,Zxy_tmp,var_tmp, vmin=m, vmax=M, shading='gouraud',cmap='jet')
plt.colorbar()
plt.gca().set_aspect('equal', adjustable='box')
elif(method == 'xyz'):
if(isaligned):
raise NameError("Plot xyz error: variable is not orthogonal")
try:
from mayavi import mlab
havemayavi = True
except:
from mpl_toolkits import mplot3d
from matplotlib import cm
ax = plt.axes(projection='3d')
ax.view_init(elev=0., azim=-150)
havemayavi = false
print("Don't have mayavi installed, using mplot3d (bad performances...).")
dz = 2*math.pi/(self.zperiod*nz)
z = np.arange(nz)*dz
nx = var.shape[0]
ny = var.shape[1]
# Create the coordinates
print("Computing coordinates for 3D plot...")
X = np.transpose(np.tile(Rxy,(nz,1,1)),(1,2,0))*np.tile(np.cos(z),(nx,ny,1))
Y = np.transpose(np.tile(Rxy,(nz,1,1)),(1,2,0))*np.tile(np.sin(z),(nx,ny,1))
Z = np.transpose(np.tile(Zxy,(nz,1,1)),(1,2,0))
m = var[2:-2,:,:].min()
M = var[2:-2,:,:].max()
print("Plotting...")
for ir in range(len(regions)):
r = regions[ir]
nx = r.ix.shape[0]
ny = r.iy.shape[0]
ixi = r.ix[0]
iyi = r.iy[0]
# Remove x guard cells
if(r.xl == None):
ixi = 2
nx = nx - 2
if(r.xr == None):
nx = nx-2
var_tmp = var[ixi:ixi+nx,iyi:iyi+ny,:]
X_tmp = X[ixi:ixi+nx,iyi:iyi+ny,:]
Y_tmp = Y[ixi:ixi+nx,iyi:iyi+ny,:]
Z_tmp = Z[ixi:ixi+nx,iyi:iyi+ny,:]
# Add guard cells to remove gaps in plotting between different regions
if(r.xr != None):
var_tmp = np.vstack([var_tmp, np.tile(var[regions[r.xr].ix[0],iyi:iyi+ny,:],(1,1,1))])
X_tmp = np.vstack([X_tmp, np.tile(X[regions[r.xr].ix[0],iyi:iyi+ny,:],(1,1,1))])
Y_tmp = np.vstack([Y_tmp, np.tile(Y[regions[r.xr].ix[0],iyi:iyi+ny,:],(1,1,1))])
Z_tmp = np.vstack([Z_tmp, np.tile(Z[regions[r.xr].ix[0],iyi:iyi+ny,:],(1,1,1))])
nx = nx+1
if(r.yu != None):
var_tmp = np.vstack([np.transpose(var_tmp,(1,0,2)),np.tile(var[ixi:ixi+nx,regions[r.yu].iy[0],:],(1,1,1))])
X_tmp = np.vstack([np.transpose(X_tmp,(1,0,2)),np.tile(X[ixi:ixi+nx,regions[r.yu].iy[0],:],(1,1,1))])
Y_tmp = np.vstack([np.transpose(Y_tmp,(1,0,2)),np.tile(Y[ixi:ixi+nx,regions[r.yu].iy[0],:],(1,1,1))])
Z_tmp = np.vstack([np.transpose(Z_tmp,(1,0,2)),np.tile(Z[ixi:ixi+nx,regions[r.yu].iy[0],:],(1,1,1))])
var_tmp = np.transpose(var_tmp,(1,0,2))
X_tmp = np.transpose(X_tmp,(1,0,2))
Y_tmp = np.transpose(Y_tmp,(1,0,2))
Z_tmp = np.transpose(Z_tmp,(1,0,2))
if(not havemayavi):
# Rescale the variable between 0 and 1 for color plotting
var_tmp = (var_tmp-m)/(M-m)
shade = False
rstride = 1
cstride = 1
antialiased = False
# Plot the inner and outer surfaces
if(r.xl == None):
surf = ax.plot_surface(X_tmp[0,:,:], Y_tmp[0,:,:], Z_tmp[0,:,:], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[0,:,:]), \
linewidth=0, antialiased=antialiased, shade=shade)
if(r.xr == None):
surf = ax.plot_surface(X_tmp[-1,:,:], Y_tmp[-1,:,:], Z_tmp[-1,:,:], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[-1,:,:]), \
linewidth=0, antialiased=antialiased, shade=shade)
# Plot the target surfaces
if(r.yl == None):
surf = ax.plot_surface(X_tmp[:,0,:], Y_tmp[:,0,:], Z_tmp[:,0,:], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[:,0,:]), \
linewidth=0, antialiased=antialiased, shade=shade)
if(r.yu == None):
surf = ax.plot_surface(X_tmp[:,-1,:], Y_tmp[:,-1,:], Z_tmp[:,-1,:], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[:,-1,:]), \
linewidth=0, antialiased=antialiased, shade=shade)
# Plot the first and last poloidal planes
iz = 0
surf = ax.plot_surface(X_tmp[:,:,iz], Y_tmp[:,:,iz], Z_tmp[:,:,iz], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[:,:,iz]), \
linewidth=0, antialiased=antialiased, shade=shade)
iz = nz-1
surf = ax.plot_surface(X_tmp[:,:,iz], Y_tmp[:,:,iz], Z_tmp[:,:,iz], \
rstride=rstride, cstride=cstride, facecolors=cm.jet(var_tmp[:,:,iz]), \
linewidth=0, antialiased=antialiased, shade=shade)
else:
# Plot the inner and outer surfaces
if(r.xl == None):
mlab.mesh(X_tmp[0,:,:], Y_tmp[0,:,:], Z_tmp[0,:,:], scalars=var_tmp[0,:,:], vmin=m, vmax=M)
if(r.xr == None):
mlab.mesh(X_tmp[-1,:,:], Y_tmp[-1,:,:], Z_tmp[-1,:,:], scalars=var_tmp[-1,:,:], vmin=m, vmax=M)
# Plot the target surfaces
if(r.yl == None):
mlab.mesh(X_tmp[:,0,:], Y_tmp[:,0,:], Z_tmp[:,0,:], scalars=var_tmp[:,0,:], vmin=m, vmax=M)
if(r.yu == None):
mlab.mesh(X_tmp[:,-1,:], Y_tmp[:,-1,:], Z_tmp[:,-1,:], scalars=var_tmp[:,-1,:], vmin=m, vmax=M)
# Plot the first and last poloidal planes
iz = 0
mlab.mesh(X_tmp[:,:,iz], Y_tmp[:,:,iz], Z_tmp[:,:,iz], scalars=var_tmp[:,:,iz], vmin=m, vmax=M)
iz = nz-1
mlab.mesh(X_tmp[:,:,iz], Y_tmp[:,:,iz], Z_tmp[:,:,iz], scalars=var_tmp[:,:,iz], vmin=m, vmax=M)
plt.show()
@TomNicholas
Copy link
Author

TomNicholas commented Dec 24, 2019

Produces plots like this:

3D_figure

Would be great to use to plot 3D s-alpha results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment