Small fixes for diagrams and simulations

This commit is contained in:
Kenneth Jao 2021-09-24 05:02:07 -04:00
parent 7e5e711533
commit 3841e6fe6b
5 changed files with 45 additions and 33 deletions

3
.gitignore vendored
View File

@ -8,5 +8,4 @@ src/packsim.c
*.so *.so
*.json *.json
figures/ squish_output/
simulations/

View File

@ -142,7 +142,7 @@ class Simulation:
def add_frame(self, points: Optional[numpy.ndarray]) -> None: def add_frame(self, points: Optional[numpy.ndarray]) -> None:
if points is None: if points is None:
points = np.random.random_sample((self.domain.n, 2)) points = np.random.random_sample((self.domain.n, 2)) * self.domain.dim
else: else:
if points.shape[1] != 2 or len(points.shape) > 2: if points.shape[1] != 2 or len(points.shape) > 2:
raise ValueError("Sites should be 2 dimensional!") raise ValueError("Sites should be 2 dimensional!")

View File

@ -8,7 +8,7 @@ from multiprocessing import Pool, cpu_count
from .common import DomainParams from .common import DomainParams
SYMM = np.array([[1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1], [0,-1], [1,-1]]) SYMM = np.array([[0,0], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1], [0,-1], [1,-1]])
class SimData: class SimData:
"""Stores diagram information for a simulation. """Stores diagram information for a simulation.
@ -54,7 +54,7 @@ class SimData:
Tuple[numpy.ndarray, numpy.ndarray]: the histogram and its bins. Tuple[numpy.ndarray, numpy.ndarray]: the histogram and its bins.
""" """
if cumulative: if cumul:
values = np.concatenate([f[stat] for f in self.stats[:(i+1)]]) values = np.concatenate([f[stat] for f in self.stats[:(i+1)]])
else: else:
values = self.stats[i][stat] values = self.stats[i][stat]
@ -70,7 +70,7 @@ class SimData:
hist, bin_edges = np.histogram(values, bins=bins, range=bounds) hist, bin_edges = np.histogram(values, bins=bins, range=bounds)
bin_list = np.array([(bin_edges[i] + bin_edges[i+1])/2 for i in range(len(bin_edges)-1)]) bin_list = np.array([(bin_edges[i] + bin_edges[i+1])/2 for i in range(len(bin_edges)-1)])
if avg and cumulative: if avg and cumul:
return hist / (i+1), bin_list return hist / (i+1), bin_list
return hist, bin_list return hist, bin_list
@ -122,7 +122,7 @@ class Diagram:
def voronoi_plot(self, i: int, ax: AxesSubplot) -> None: def voronoi_plot(self, i: int, ax: AxesSubplot) -> None:
domain = self.sim.domains[i] domain = self.sim.domains[i]
n,w,h = domain.n, domain.w, domain.h n, w, h = domain.n, domain.w, domain.h
scale = 1.5 scale = 1.5
area = n <= 60 area = n <= 60
@ -138,14 +138,27 @@ class Diagram:
props = dict(boxstyle='round', facecolor='wheat', alpha=0.8) props = dict(boxstyle='round', facecolor='wheat', alpha=0.8)
if area: defects = {5: {"x": [], "y": []}, 7: {"x": [], "y": []}}
global SYMM
for j in range(n): for j in range(n):
for s in np.concatenate(([[0,0]], SYMM)): for s in SYMM:
txt = ax.text(*(self.sim.voronois[i].points[j] + s*self.sim.domains[i].dim), vec = (self.sim.voronois[i].points[j] + s*self.sim.domains[i].dim)
str(round(self.sim.stats[i]["site_areas"][j], 3)))
if area:
txt = ax.text(*vec, str(round(self.sim.stats[i]["site_areas"][j], 3)))
txt.set_clip_on(True) txt.set_clip_on(True)
if self.sim.stats[i]["site_edge_count"][j] == 5:
defects[5]["x"].append(vec[0])
defects[5]["y"].append(vec[1])
elif self.sim.stats[i]["site_edge_count"][j] == 7:
defects[7]["x"].append(vec[0])
defects[7]["y"].append(vec[1])
ax.scatter(defects[5]["x"], defects[5]["y"], marker="p", color="red")
ax.scatter(defects[7]["x"], defects[7]["y"], marker="*", color="red")
ax.text(0.05, 0.95, f'Energy: {self.sim.energies[i]}', transform=ax.transAxes, fontsize=14, ax.text(0.05, 0.95, f'Energy: {self.sim.energies[i]}', transform=ax.transAxes, fontsize=14,
verticalalignment='top', bbox=props) verticalalignment='top', bbox=props)
@ -208,7 +221,7 @@ class Diagram:
def site_energies_plot(self, i: int, ax: AxesSubplot) -> None: def site_energies_plot(self, i: int, ax: AxesSubplot) -> None:
y, x = self.sim.hist("site_energies", i, self.cumulative, avg=True) y, x = self.sim.hist("site_energies", i, cumul=self.cumulative, avg=True)
ax.bar(x, y, width=0.8*(x[1]-x[0])) ax.bar(x, y, width=0.8*(x[1]-x[0]))
ax.title.set_text('Site Energies') ax.title.set_text('Site Energies')
@ -220,7 +233,7 @@ class Diagram:
def avg_radius_plot(self, i: int, ax: AxesSubplot) -> None: def avg_radius_plot(self, i: int, ax: AxesSubplot) -> None:
y, x = self.sim.hist("avg_radius", i, self.cumulative, avg=True) y, x = self.sim.hist("avg_radius", i, cumul=self.cumulative, avg=True)
ax.bar(x, y, width=0.8*(x[1]-x[0])) ax.bar(x, y, width=0.8*(x[1]-x[0]))
ax.title.set_text('Site Average Radii') ax.title.set_text('Site Average Radii')
@ -232,7 +245,7 @@ class Diagram:
def isoparam_avg_plot(self, i: int, ax: AxesSubplot) -> None: def isoparam_avg_plot(self, i: int, ax: AxesSubplot) -> None:
y, x = self.sim.hist("isoparam_avg", i, self.cumulative, avg=True) y, x = self.sim.hist("isoparam_avg", i, cumul=self.cumulative, avg=True)
ax.bar(x,y, width=0.8*(x[1]-x[0])) ax.bar(x,y, width=0.8*(x[1]-x[0]))
ax.title.set_text('Site Isoperimetric Averages') ax.title.set_text('Site Isoperimetric Averages')
@ -261,9 +274,13 @@ class Diagram:
def eigs_plot(self, i: int, ax: AxesSubplot) -> None: def eigs_plot(self, i: int, ax: AxesSubplot) -> None:
eigs = self.sim.stats[i]["eigs"] try:
ax.plot(list(range(len(eigs))), eigs, marker='o', linestyle='dashed', color='C0') eigs = self.sim.stats[i]["eigs"]
ax.plot([0,len(eigs)], [0, 0], color="red") ax.plot(list(range(len(eigs))), eigs, marker='o', linestyle='dashed', color='C0')
ax.plot([0,len(eigs)], [0, 0], color="red")
except KeyError:
ax.text(0.5, 0.5, "Not Computed")
ax.title.set_text('Hessian Eigenvalues') ax.title.set_text('Hessian Eigenvalues')
ax.set_xlabel("") ax.set_xlabel("")
ax.set_ylabel("Value") ax.set_ylabel("Value")
@ -272,7 +289,6 @@ class Diagram:
def render_frames(self, frames: List[int], fol: str = 'frames') -> None: def render_frames(self, frames: List[int], fol: str = 'frames') -> None:
(self.sim.path / fol).mkdir(exist_ok=True) (self.sim.path / fol).mkdir(exist_ok=True)
combo_list = [] combo_list = []
print(cpu_count())
for i in range(cpu_count()): for i in range(cpu_count()):
combo_list.append((self, frames[:int((i+1)*len(frames)/cpu_count())], combo_list.append((self, frames[:int((i+1)*len(frames)/cpu_count())],
fol, len(frames))) fol, len(frames)))
@ -281,14 +297,8 @@ class Diagram:
for _ in pool.imap_unordered(render_frame_range, combo_list): for _ in pool.imap_unordered(render_frame_range, combo_list):
pass pass
# for i, frame in enumerate(frames):
# self.generate_frame(frame, "save", fol)
# hashes = int(21*i/len(frames))
# print(f'Generating frames... |{"#"*hashes}{" "*(20-hashes)}|' + \
# f' {i+1}/{len(frames)} frames rendered.', flush=True, end='\r')
print(flush=True) print(flush=True)
print(f'Wrote to \"{self.sim.path / fol}\".', flush=True)
def render_video(self, time: int, mode: str) -> None: def render_video(self, time: int, mode: str) -> None:
if mode not in ["use_all", "sample"]: if mode not in ["use_all", "sample"]:

View File

@ -198,7 +198,7 @@ class Shrink(Simulation):
name: Optional[str] = None) -> None: name: Optional[str] = None) -> None:
super().__init__(domain, energy, name=name) super().__init__(domain, energy, name=name)
self.step_size, self.thres, self.accel = step_size, thres, accel self.step_size, self.thres, self.accel = step_size, thres, accel
self.delta, self.stop_width = self.domain.w*delta, self.domain.w*stop_width self.delta, self.stop_width = self.domain.w*delta/100, self.domain.w*stop_width
@property @property
@ -208,8 +208,8 @@ class Shrink(Simulation):
"step_size": self.step_size, "step_size": self.step_size,
"thres": self.thres, "thres": self.thres,
"accel": self.accel, "accel": self.accel,
"kernel_step": self.kernel_step, "delta": self.delta,
"count": self.count "stop_width": self.stop_width
} }
return info return info
@ -225,9 +225,11 @@ class Shrink(Simulation):
new_sites = None new_sites = None
width = self.domain.w width = self.domain.w
i = 0
while width >= self.stop_width: while width >= self.stop_width:
# Get to equilibrium. # Get to equilibrium.
sim = Flow(self.domain, self.energy, self.thres, self.step_size, self.accel) new_domain = DomainParams(self.domain.n, width, self.domain.h, self.domain.r)
sim = Flow(new_domain, self.energy, self.thres, self.step_size, self.accel)
sim.add_frame(new_sites) sim.add_frame(new_sites)
sim.run(False, log, log_steps) sim.run(False, log, log_steps)
new_sites = sim[-1].site_arr new_sites = sim[-1].site_arr
@ -235,6 +237,7 @@ class Shrink(Simulation):
self.frames.append(sim[-1]) self.frames.append(sim[-1])
if save: self.save(self.frame_data(i)) if save: self.save(self.frame_data(i))
if log: print(f'Width: {self.w:.4f}\n') if log: print(f'Width: {width:.4f}\n')
width -= self.delta width -= self.delta
i += 1

View File

@ -148,7 +148,7 @@ def config_sim(args):
if save_diagram: if save_diagram:
diagram = Diagram(sim, dia_params["figures"]) diagram = Diagram(sim, dia_params["figures"])
if dia_params["filetype"] == "img": if dia_params["filetype"] == "img":
diagram.render_frames() diagram.render_frames(range(len(sim)))
elif dia_params["filetype"] == "mp4": elif dia_params["filetype"] == "mp4":
if mode == "flow": if mode == "flow":
diagram.render_video(dia_params["time"], "sample") diagram.render_video(dia_params["time"], "sample")