Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plotting and animation #872

Merged
merged 31 commits into from
Jun 5, 2019
Merged
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
351544d
first stab at unified plotting and video
smartalecH May 13, 2019
da8ee1c
minor fix to pml boundaries
smartalecH May 13, 2019
2685bc4
incomplete changes
smartalecH May 15, 2019
8223c3f
begin support for arbitrary planes
smartalecH May 16, 2019
68b178a
merging
smartalecH May 16, 2019
a4643f6
consolidate bug fixes
smartalecH May 16, 2019
d346f01
debugging
smartalecH May 17, 2019
e102e62
small bugs
smartalecH May 17, 2019
04e6776
bug fixes
smartalecH May 18, 2019
e816cf5
fixed bugs with slicing, added animation run time object
smartalecH May 20, 2019
053c7f2
use mixins
smartalecH May 20, 2019
0aad0c7
retrofit straight waveguide tutorial with animations
smartalecH May 20, 2019
d703c79
fix naming error
smartalecH May 21, 2019
c5e0ccf
refactor visualization as standalone component
smartalecH May 21, 2019
2116ac1
Cleanup and examples
smartalecH May 21, 2019
cc60528
check for library imports
smartalecH May 21, 2019
f630aa6
attempt to fix import error python2
smartalecH May 21, 2019
8d3ec17
Add tutorials
smartalecH May 21, 2019
5d5af2a
update straight example
smartalecH May 21, 2019
884c58f
more cleanup
smartalecH May 21, 2019
78c80cd
refactor run function and visualization base
smartalecH May 28, 2019
97a5c5c
update docs, tutorials, tests, and customization
smartalecH May 30, 2019
0fb7f51
add test file
smartalecH May 30, 2019
17d11a0
fix matplotlib issues in test
smartalecH May 31, 2019
a2bd4c7
remove mp4 and gif on make clean
smartalecH May 31, 2019
beb9eb5
fix tabs
smartalecH May 31, 2019
5465865
fixed deadlocking
smartalecH May 31, 2019
d17e960
fix test for mpi
smartalecH May 31, 2019
36ef7d2
visualization movie bug with ffmpeg
smartalecH Jun 4, 2019
d72fdda
remove hashing
smartalecH Jun 4, 2019
3936d77
fix jshtml with python2
smartalecH Jun 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions python/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,177 @@ def get_sfield_r(self):
def get_sfield_p(self):
return self.get_array(mp.Sp, cmplx=True)

def get_boundary_metadata(self,boundary):
import itertools
corners = []
widths = []
heights = []
def _get_boundary_vertices(thickness,direction,side):
# Left
if direction == mp.X and side == mp.Low:
corner = np.array([self.geometry_center.x - self.cell_size.x/2,self.geometry_center.y - self.cell_size.y/2])
width = thickness
height = self.cell_size.y
# Right
elif direction == mp.X and side == mp.High:
corner = np.array([self.geometry_center.x + self.cell_size.x/2 - thickness,self.geometry_center.y - self.cell_size.y/2])
width = thickness
height = self.cell_size.y
# Top
elif direction == mp.Y and side == mp.Low:
corner = np.array([self.geometry_center.x - self.cell_size.x/2,self.geometry_center.y + self.cell_size.y/2 - thickness])
width = self.cell_size.x
height = thickness
# Bottom
elif direction == mp.Y and side == mp.High:
corner = np.array([self.geometry_center.x - self.cell_size.x/2,self.geometry_center.y - self.cell_size.y/2])
width = self.cell_size.x
height = thickness
else:
corner = []
return corner, width, height

# All 4 side are the same
if boundary.direction == mp.ALL and boundary.side == mp.ALL:
for permutation in itertools.product([mp.X,mp.Y], [mp.Low, mp.High]):
corner, width, height = _get_boundary_vertices(boundary.thickness,*permutation)
corners.append(corner)
widths.append(width)
heights.append(height)
# 2 sides are the same
elif boundary.side == mp.ALL:
for side in [mp.Low, mp.High]:
corner, width, height = _get_boundary_vertices(boundary.thickness,boundary.direction,side)
corners.append(corner)
widths.append(width)
heights.append(height)
# only one side
else:
corners, widths, heights = _get_boundary_vertices(thickness, direction, side)

return corners, widths, heights

def get_src_metadata(self,source):
size = source.size
center = source.center

# Point source
if size.x == size.y == size.z == 0:
return np.array([[center.x,center.y]])

# Line source
else:
# Vertical line
if size.x == 0:
return np.array([
[center.x,center.y-size.y/2],
[center.x,center.y+size.y/2]
])
# Horizontal line
elif size.y == 0:
return np.array([
[center.x-size.x/2,center.y],
[center.x+size.x/2,center.y]
])
else:
return []

def get_monitor_metadata(self,monitor,z_slice=0):
size = monitor.regions[0].size
center = monitor.regions[0].center

# Vertical line
if size.x == 0:
return np.array([
[center.x,center.y-size.y/2],
[center.x,center.y+size.y/2]
])
# Horizontal line
elif size.y == 0:
return np.array([
[center.x-size.x/2,center.y],
[center.x+size.x/2,center.y]
])
else:
return []

def visualize_domain(self,figsize=None,fields=None,labels=True):
stevengj marked this conversation as resolved.
Show resolved Hide resolved
if not self._is_initialized:
self.init_sim()
try:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
except ImportError:
warnings.warn("matplotlib is required for visualize_domain", ImportWarning)
return

f = plt.figure()

# Get domain measurements
grid = self.get_array_metadata(center=self.geometry_center, size=self.cell_size)
extent = [np.min(grid[0]),np.max(grid[0]),np.min(grid[1]),np.max(grid[1])]

# Plot geometry
eps_data = np.rot90(self.get_array(center=self.geometry_center, size=self.cell_size, component=mp.Dielectric))
plt.imshow(eps_data, interpolation='spline36', cmap='binary', extent=extent)

# Plot boundaries
for boundary in self.boundary_layers:
corners, widths, heights = self.get_boundary_metadata(boundary)
for bdry in range(len(widths)):
plt.gca().add_patch(patches.Rectangle(corners[bdry],widths[bdry],heights[bdry],edgecolor='g',facecolor='none', hatch='/'))

# Plot sources
for src in self.sources:
src_loc = self.get_src_metadata(src)
if src_loc.shape[0] == 1:
plt.scatter(src_loc[:,0],src_loc[:,1],color='r')
else:
plt.plot(src_loc[:,0],src_loc[:,1],color='r')

# Plot monitors
for mon in self.dft_objects:
mon_loc = self.get_monitor_metadata(mon)
plt.plot(mon_loc[:,0],mon_loc[:,1],color='b')

# Plot fields
if fields is not None:
plt.imshow(np.rot90(fields), interpolation='spline36', cmap='RdBu', alpha=0.6, extent=extent)

return f

def animate_fields(self,fields,filename_prefix=None,fps=20):
stevengj marked this conversation as resolved.
Show resolved Hide resolved
try:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib import animation
except ImportError:
warnings.warn("matplotlib is required for visualize_domain", ImportWarning)
return

num_frames = len(fields)

# Normalize fields
fields = np.array(fields) / np.max(fields,axis=(0,1,2))

grid = self.get_array_metadata(center=self.geometry_center, size=self.cell_size)
extent = [np.min(grid[0]),np.max(grid[0]),np.min(grid[1]),np.max(grid[1])]
f = self.visualize_domain()
fieldsPlot = plt.imshow(np.rot90(fields[0]), interpolation='spline36', cmap='RdBu', alpha=0.6, extent=extent)
def animate(i):
fieldsPlot.set_data(np.rot90(fields[i]))
return fieldsPlot #return everything that must be updated

anim = animation.FuncAnimation(f, animate,
frames=num_frames, interval=int(1/fps * 1000))

if filename_prefix is not None:
print("Saving video to disk...")
anim.save('{}.mp4'.format(filename_prefix), fps=fps, extra_args=['-vcodec', 'libx264'])
print("Video saved.")

return anim

def visualize_chunks(self):
if self.structure is None:
self.init_sim()
Expand Down