From 4f23f0c43f9a74901acc3131e9694c46e890d74d Mon Sep 17 00:00:00 2001 From: Kenneth Jao Date: Fri, 24 Sep 2021 05:54:44 -0400 Subject: [PATCH] Changed loading function, and only create folder with save. --- src/squish/__init__.py | 3 +- src/squish/common.py | 142 +--------------------------------- src/squish/simulation.py | 161 ++++++++++++++++++++++++++++++++++++++- src/squish/squish.py | 3 - 4 files changed, 164 insertions(+), 145 deletions(-) diff --git a/src/squish/__init__.py b/src/squish/__init__.py index e516c1c..a8c29a3 100644 --- a/src/squish/__init__.py +++ b/src/squish/__init__.py @@ -1,2 +1,3 @@ -from .common import DomainParams, Energy, Simulation +from .common import DomainParams, Energy +from .simulation import Simulation from .diagram import Diagram \ No newline at end of file diff --git a/src/squish/common.py b/src/squish/common.py index 8462776..cef396f 100644 --- a/src/squish/common.py +++ b/src/squish/common.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import List, Union, Optional, Iterator +from typing import List, Union, Optional, Iterator, Generator import pickle, numpy as np from pathlib import Path from _squish import AreaEnergy, RadialALEnergy, RadialTEnergy @@ -101,142 +101,4 @@ class Energy: @property def title_str(self) -> str: - return self.mode.title_str - - -class Simulation: - """Generic container for simulations. - - Attributes: - domain (DomainParams): Domain Parameters for this simulation. - energy (Energy): energy being used for caluclations. - path (Path): Path to location of where to store simulation files. - frames (List[VoronoiContainer]): Stores frames of the simulation. - - """ - - __slots__ = ['domain', 'energy', 'path', 'frames'] - - def __init__(self, domain: DomainParams, energy: Energy, name: Optional[str] = None) -> None: - self.domain, self.energy = domain, energy - self.frames = [] - - if name is None: - self.path = generate_filepath(self, OUTPUT_DIR) - else: - self.path = OUTPUT_DIR / name - - self.path.mkdir() - - - def __iter__(self) -> Iterator: - return iter(self.frames) - - def __getitem__(self, key: int) -> Energy: - return self.frames[key] - - - def __len__(self) -> int: - return len(self.frames) - - - def add_frame(self, points: Optional[numpy.ndarray]) -> None: - if points is None: - points = np.random.random_sample((self.domain.n, 2)) * self.domain.dim - else: - if points.shape[1] != 2 or len(points.shape) > 2: - raise ValueError("Sites should be 2 dimensional!") - - if points.shape[0] != self.domain.n: - raise ValueError("Number of sites provided do not match the array!") - - self.frames.append(self.energy.mode(*self.domain, points % self.domain.dim)) - - - def get_distinct(self) -> List[int]: - """Gets the distinct configurations based on the average radii of the sites. - and returns the number of configurations for each distinct configuration. - """ - - distinct_avg_radii, distinct_count, new_frames = [], [], [] - - for frame in self.frames: - avg_radii = np.sort(frame.stats["avg_radius"]) - is_in = False - for i, dist_radii in enumerate(distinct_avg_radii): - if np.allclose(avg_radii, dist_radii, atol=1e-5): - is_in = True - distinct_count[i] += 1 - break - - if not is_in: - distinct_avg_radii.append(avg_radii) - new_frames.append(frame) - - self.frames = new_frames - return distinct_count - - - def save(self, info: Dict) -> None: - path = self.path / 'data.squish' - - with open(path, 'wb') as out: - pickle.dump(info, out, pickle.HIGHEST_PROTOCOL) - - - def frame_data(self, index: int) -> None: - f = self[index] - info = { - "arr": f.site_arr, - "domain": (f.n, f.h, f.w, f.r), - "energy": f.attr_str, - "stats": f.stats - } - return info - - # all_info = [] - # for frame in self.frames: - # frame_info = dict() - # frame_info["arr"] = frame.site_arr - # frame_info["energy"] = {AreaEnergy: "area", RadialALEnergy: "radial-al", - # RadialTEnergy: "radial-t"}[self.energy] - # frame_info["params"] = (frame.n, frame.w, frame.h, frame.r) - # all_info.append(frame_info) - - # class_name = {Flow: "flow", Search: "search", Shrink: "shrink"}[self.__class__] - - # with open(path, 'wb') as output: - # pickle.dump((all_info, class_name), output, pickle.HIGHEST_PROTOCOL) - # print("Wrote to " + path, flush=True) - - - @staticmethod - def load(path: str) -> Simulation: - with open(path, 'rb') as infile: - while True: - try: - yield pickle.load(infile) - except EOFError: - break - - - @staticmethod - def load_old(filename: str) -> Simulation: - """ - Loads the points at every point into a file. - :param filename: [str] name of the file - """ - frames = [] - with open(filename, 'rb') as data: - all_info, sim_class = pickle.load(data) - if type(sim_class) == str: - sim_class = {"flow": Flow, "search": Search, "shrink": Shrink}[sim_class] - - - sim = sim_class(*all_info[0]["params"], "radial-t", 0,0) - for frame_info in all_info: - frames.append(sim.energy(*frame_info["params"], frame_info["arr"])) - #frames[-1].stats = frame_info["stats"] - - sim.frames = frames - return sim + return self.mode.title_str \ No newline at end of file diff --git a/src/squish/simulation.py b/src/squish/simulation.py index 04acc67..3938ecb 100644 --- a/src/squish/simulation.py +++ b/src/squish/simulation.py @@ -5,7 +5,154 @@ import pickle, numpy as np from scipy.linalg import null_space from timeit import default_timer as timer -from .common import DomainParams, Energy, Simulation +from .common import DomainParams, Energy, generate_filepath, OUTPUT_DIR + + +class Simulation: + """Generic container for simulations. + + Attributes: + domain (DomainParams): Domain Parameters for this simulation. + energy (Energy): energy being used for caluclations. + path (Path): Path to location of where to store simulation files. + frames (List[VoronoiContainer]): Stores frames of the simulation. + + """ + + __slots__ = ['domain', 'energy', 'path', 'frames'] + + def __init__(self, domain: DomainParams, energy: Energy, name: Optional[str] = None) -> None: + self.domain, self.energy = domain, energy + self.frames = [] + + if name is None: + self.path = generate_filepath(self, OUTPUT_DIR) + else: + self.path = OUTPUT_DIR / name + + + def __iter__(self) -> Iterator: + return iter(self.frames) + + def __getitem__(self, key: int) -> Energy: + return self.frames[key] + + + def __len__(self) -> int: + return len(self.frames) + + + def add_frame(self, points: Optional[numpy.ndarray]) -> None: + if points is None: + points = np.random.random_sample((self.domain.n, 2)) * self.domain.dim + else: + if points.shape[1] != 2 or len(points.shape) > 2: + raise ValueError("Sites should be 2 dimensional!") + + if points.shape[0] != self.domain.n: + raise ValueError("Number of sites provided do not match the array!") + + self.frames.append(self.energy.mode(*self.domain, points % self.domain.dim)) + + + def get_distinct(self) -> List[int]: + """Gets the distinct configurations based on the average radii of the sites. + and returns the number of configurations for each distinct configuration. + """ + + distinct_avg_radii, distinct_count, new_frames = [], [], [] + + for frame in self.frames: + avg_radii = np.sort(frame.stats["avg_radius"]) + is_in = False + for i, dist_radii in enumerate(distinct_avg_radii): + if np.allclose(avg_radii, dist_radii, atol=1e-5): + is_in = True + distinct_count[i] += 1 + break + + if not is_in: + distinct_avg_radii.append(avg_radii) + new_frames.append(frame) + + self.frames = new_frames + return distinct_count + + + def save(self, info: Dict) -> None: + self.path.mkdir(exist_ok=True) + path = self.path / 'data.squish' + + with open(path, 'ab') as out: + pickle.dump(info, out, pickle.HIGHEST_PROTOCOL) + + + def frame_data(self, index: int) -> None: + f = self[index] + info = { + "arr": f.site_arr, + "domain": (f.n, f.h, f.w, f.r), + "energy": f.energy, + "stats": f.stats + } + return info + + # all_info = [] + # for frame in self.frames: + # frame_info = dict() + # frame_info["arr"] = frame.site_arr + # frame_info["energy"] = {AreaEnergy: "area", RadialALEnergy: "radial-al", + # RadialTEnergy: "radial-t"}[self.energy] + # frame_info["params"] = (frame.n, frame.w, frame.h, frame.r) + # all_info.append(frame_info) + + # class_name = {Flow: "flow", Search: "search", Shrink: "shrink"}[self.__class__] + + # with open(path, 'wb') as output: + # pickle.dump((all_info, class_name), output, pickle.HIGHEST_PROTOCOL) + # print("Wrote to " + path, flush=True) + + + @staticmethod + def load(path: str) -> Tuple[Simulation, Generator]: + def frames() -> Dict: + with open(path, 'rb') as infile: + while True: + try: + yield pickle.load(infile) + except EOFError: + break + + with open(path, 'rb') as infile: + sim_info = pickle.load(infile) + + domain = DomainParams(*sim_info["domain"]) + energy = Energy(sim_info["energy"]) + sim = STR_TO_SIM[sim_info["mode"]](domain, energy, *list(sim_info.values())[3:]) + + return sim, frames() + + + @staticmethod + def load_old(filename: str) -> Simulation: + """ + Loads the points at every point into a file. + :param filename: [str] name of the file + """ + frames = [] + with open(filename, 'rb') as data: + all_info, sim_class = pickle.load(data) + if type(sim_class) == str: + sim_class = {"flow": Flow, "search": Search, "shrink": Shrink}[sim_class] + + + sim = sim_class(*all_info[0]["params"], "radial-t", 0,0) + for frame_info in all_info: + frames.append(sim.energy(*frame_info["params"], frame_info["arr"])) + #frames[-1].stats = frame_info["stats"] + + sim.frames = frames + return sim class Flow(Simulation): @@ -36,6 +183,8 @@ class Flow(Simulation): def initial_data(self) -> Dict: info = { "mode": self.attr_str, + "domain": (self.domain.n, self.domain.w, self.domain.h, self.domain.r), + "energy": self.energy.attr_str, "step_size": self.step_size, "thres": self.thres, "accel": self.accel @@ -126,6 +275,8 @@ class Search(Simulation): def initial_data(self) -> Dict: info = { "mode": self.attr_str, + "domain": (self.domain.n, self.domain.w, self.domain.h, self.domain.r), + "energy": self.energy.attr_str, "step_size": self.step_size, "thres": self.thres, "accel": self.accel, @@ -205,6 +356,8 @@ class Shrink(Simulation): def initial_data(self) -> Dict: info = { "mode": self.attr_str, + "domain": (self.domain.n, self.domain.w, self.domain.h, self.domain.r), + "energy": self.energy.attr_str, "step_size": self.step_size, "thres": self.thres, "accel": self.accel, @@ -241,3 +394,9 @@ class Shrink(Simulation): width -= self.delta i += 1 + +STR_TO_SIM = { + "flow": Flow, + "search": Search, + "shrink": Shrink +} \ No newline at end of file diff --git a/src/squish/squish.py b/src/squish/squish.py index dd41ef8..ab84eff 100644 --- a/src/squish/squish.py +++ b/src/squish/squish.py @@ -45,9 +45,6 @@ def check_params(container: Dict, needed: List[str], valid: Dict) -> None: def main(): # Loading configuration and settings. - Path('simulations').mkdir(exist_ok=True) - Path('figures').mkdir(exist_ok=True) - parser = argparse.ArgumentParser("PackSim") parser.add_argument('sim_conf', metavar='/path/to/config.json', help="configuration file for a simulation")