def __init__(self, setting: RIDTConfig, data_store: DataStore, dir_agent: DirectoryAgent, quantity: str): """The :class:`DataStoreCSVWriter` constructor. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. dir_agent : :class:`~.DirectoryAgent` The path to the output directory for the run. data_store : :class:`~.DataStore` The data store to be analysed. quantity: :obj:`str` The string id for the quantity stored in the data store. """ self.dir_agent = dir_agent self.setting = setting self.units = Units(setting) self.domain = Domain(setting) self.quantity = quantity self.write(data_store)
def setUp(self) -> None: this_dir = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(this_dir, "../../default/config.json") with open(path) as f: loaded_json = json.load(f) self.config = RIDTConfig(loaded_json) self.domain = Domain(self.config)
def __init__(self, setting: RIDTConfig): """The :class:`~.UncertaintyMask` constructor. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run. """ self.setting = setting self.radius = setting.models.eddy_diffusion.analysis.exclude_radius_meters self.sources = self.get_source_locations() self.domain = Domain(setting)
def __init__(self, setting: RIDTConfig, space: ComputationalSpace, analysis: Dict[RIDTConfig, DataStoreAnalyser], outdir: str, quantity: str): """The :class`~.BatchResultsWriter` class initialiser. Parameters ---------- setting : :class:`~.RIDTConfig` The settings for the run in question. space : :class:`~.ComputationalSpace` The :class:`~.ComputationalSpace` instance corresponding to the :attr:`settings` attribute. analysis : :obj:`dict` [:class:`~.RIDTConfig`, :class:`~.DataStoreAnalyser`] A dictionary of :class:`~.DataStoreAnalyser` instances for each :class:`~.RIDTConfig` object in :attr:`space`. outdir : :obj:`str` The path to the output directory for the run. quantity : :obj:`str` The string id for the quantity stored in the data store. """ self.setting = setting self.domain = Domain(setting) self.units = Units(setting) self.quantity = quantity self.thresholds = self.threshold_converter() self.space = space self.analysis = analysis self.outdir = outdir self.summary() self.write()
def __init__(self, setting: RIDTConfig, analysis: DataStoreAnalyser, dir_agent: DirectoryAgent, quantity: str): """The :class`~.ResultsWriter` class initialiser. Parameters ---------- setting : :class:`~.RIDTConfig` The settings for the run in question. analysis : :class:`~.DataStoreAnalyser` :class:`~.DataStoreAnalyser` instance to be written. dir_agent: :class:`~.DirectoryAgent` The directory agent for run. quantity : :obj:`str` The string id for the quantity stored in the data store. """ self.setting = setting self.units = Units(setting) self.quantity = quantity self.thresholds = self.threshold_converter() self.analysis = analysis self.dir_agent = dir_agent self.domain = Domain(setting) if quantity == "concentration": self.summary() self.maximum() self.exceedance_analysis() self.extrema()
def run(self, setting: RIDTConfig) -> None: """Evaluates the model for a set of parameters, for all geometries. Loops over all monitor locations that have been selected for evaluation and evaluates them over their respective domains. Writes output to :attr:`data_store`. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. Returns ------- None """ self.data_store.add_run(setting) domain = Domain(setting) solver = EddyDiffusion(setting) locations = setting.models.eddy_diffusion.monitor_locations for geometry in self.geometries: print(f"Evaluating {geometry} monitor locations...") for name, item in getattr(locations, geometry).items(): print(f"Evaluating {name}...") space = getattr(domain, geometry)(item) output = solver(*getattr(domain, geometry)(item), domain.time) self.data_store[setting].add(geometry, name, squeeze(output))
def __init__(self, setting: RIDTConfig, geometry: str, id: str, quantity: str): self.setting = setting self.geometry = geometry self.id = id self.quantity = quantity self.units = Units(setting) self.domain = Domain(setting)
def setUp(self) -> None: this_dir = os.path.dirname(os.path.abspath(__file__)) with ConfigFileParser(join(this_dir, "st23/config.json")) as cfp: self.c = cfp self.bds = BatchDataStore() self.domain = Domain(self.c) self.output_dir = join(this_dir, "st23/data") Path(self.output_dir).mkdir(parents=True, exist_ok=True) self.edr = EddyDiffusionRun(self.c, self.output_dir)
class TestDomain(unittest.TestCase): def setUp(self) -> None: this_dir = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(this_dir, "../../default/config.json") with open(path) as f: loaded_json = json.load(f) self.config = RIDTConfig(loaded_json) self.domain = Domain(self.config) def test_point(self): """Tests to make sure that the types of the points are arrays.""" points = self.config.models.eddy_diffusion.monitor_locations.points for point in points.values(): for array in self.domain.points(point): self.assertEqual(type(array), np.ndarray) def test_line(self): """Tests to make sure that the types of the lines are arrays.""" lines = self.config.models.eddy_diffusion.monitor_locations.lines for line in lines.values(): for array in self.domain.lines(line): self.assertEqual(type(array), np.ndarray) def test_plane(self): """Tests to make sure that the types of the planes are arrays.""" planes = self.config.models.eddy_diffusion.monitor_locations.planes for plane in planes.values(): for array in self.domain.planes(plane): self.assertEqual(type(array), np.ndarray)
def run(self, setting: RIDTConfig) -> None: """Evaluates the model for a set of parameters. Writes output to :attr:`data_store`. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. Returns ------- None """ self.data_store.add_run(setting) domain = Domain(setting) solver = WellMixed(setting) output = solver(domain.time) self.data_store[setting].add("points", "well_mixed", output)
def __init__(self, settings: RIDTConfig, output_dir: str, quantity: str): """The :class:`~.ContourPlot` constructor. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. outdir : :obj:`str` The path to the output directory for the run. quantity : :obj:`str` The string id for the quantity stored in the data store. """ self.settings = settings self.output_dir = output_dir self.units = Units(settings) self.domain = Domain(self.settings) self.quantity = quantity self.config = self.settings.models.eddy_diffusion.planes_plots
def __init__(self, setting: RIDTConfig, data_store: DataStore, quantity: str): """The :class`~.DataStoreAnalyser` class initialiser. Calls the :meth:`~.DataStoreAnalyser.evaluate` method. If flag is set in config file, will exclude values within 2m of all sources. Parameters ---------- setting : :class:`~.RIDTConfig` The settings for the run in question. data_store : :class:`~.DataStore` The data store to be analysed. quantity : :obj:`str` The string id for the quantity stored in the data store. """ self.setting = setting self.units = Units(setting) self.domain = Domain(self.setting) self.quantity = quantity self.thresholds = self.threshold_converter() self.data_store = data_store if self.setting.models.eddy_diffusion.analysis.exclude_uncertain_values: self.exclude_uncertain_values() self.maximum = list() self.exceedance = list() self.percent_exceedance = list() self.max_percent_exceedance = list() self.evaluate()
class UncertaintyMask: """Provides the ability to mask uncertain values in quantity grids. Attributes ---------- settings : :class:`~.RIDTConfig` The settings for the run. sources : :obj:`List`[:class:`~numpy.ndarray`] The list of source term positions found in the settings instance. domain : :class:`~.Domain` The instance of :class:`~.Domain` corresponding to :attr:`settings`. radius : :obj:`float` The radius of the sphere around each source, inside which values will be masked. """ def __init__(self, setting: RIDTConfig): """The :class:`~.UncertaintyMask` constructor. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run. """ self.setting = setting self.radius = setting.models.eddy_diffusion.analysis.exclude_radius_meters self.sources = self.get_source_locations() self.domain = Domain(setting) def get_source_locations(self): """Get the source settings objects from the run settings instance. Returns ------- :obj:`List`[:class:`~numpy.ndarray`] The list of source term positions found in the settings instance. """ rv = list() modes = ["instantaneous", "infinite_duration", "fixed_duration"] for mode in modes: sources = getattr(self.setting.modes, mode).sources rv += [array((s.x, s.y, s.z)) for s in sources.values()] return rv def mask(self, geometry: str, id: str, data: ndarray): """Masks all elements in the grid that are within 2m of a source. Parameters ---------- geometry : :obj:`str` The type of grid to be masked. id : :obj:`str` The id of the grid to be masked. data : :class:`~ndarray.ndarray` The grid to be masked. Returns ------- :class:`~numpy.ndarray` The masked array. """ print(f"Excluding uncertain values in {id}...") return getattr(self, f"mask_{geometry}")(id, data) def mask_points(self, id: str, data: ndarray): """Mask values in point array close to a source. Parameters ---------- id : :obj:`str` The id of the point. data : :class:`~.numpy.ndarray` The array to be masked. Returns ------- :class:`~.numpy.ndarray` The masked copy. """ point = self.setting.models.eddy_diffusion.monitor_locations.points[id] location = self.domain.point_cartesian(point) rv = deepcopy(data) for s in self.sources: if norm(s - location) <= self.radius: rv.fill(nan) return rv def mask_lines(self, id: str, data: ndarray): """Mask values in line array close to a source. Parameters ---------- id : :obj:`str` The id of the line. data : :class:`~.numpy.ndarray` The array to be masked. Returns ------- :class:`~.numpy.ndarray` The masked copy. """ line = self.setting.models.eddy_diffusion.monitor_locations.lines[id] locations = self.domain.line_cartesian(line) rv = deepcopy(data) for idx, location in locations: for s in self.sources: if norm(s - array(location)) <= self.radius: for idt, time in enumerate(self.domain.time): rv[idt][idx] = nan return rv def mask_planes(self, id: str, data: ndarray): """Mask values in plane array close to a source. Parameters ---------- id : :obj:`str` The id of the plane. data : :class:`~.numpy.ndarray` The array to be masked. Returns ------- :class:`~.numpy.ndarray` The masked copy. """ plane = self.setting.models.eddy_diffusion.monitor_locations.planes[id] locations = self.domain.plane_cartesian(plane) rv = deepcopy(data) for idx, location in locations: for s in self.sources: if norm(s - array(location)) <= self.radius: for idt, time in enumerate(self.domain.time): rv[idt][idx] = nan return rv def mask_domain(self, id: str, data: ndarray): """Mask values in domain array close to a source. Note ---- The `id` parameter is a placeholder for future functionality, where multiple domains can be defined. Parameters ---------- id : :obj:`str` The id of the domain. data : :class:`~.numpy.ndarray` The array to be masked. Returns ------- :class:`~.numpy.ndarray` The masked copy. """ locations = self.domain.domain_cartesian() rv = deepcopy(data) for idx, location in locations: for s in self.sources: if norm(s - array(location)) <= self.radius: for idt, time in enumerate(self.domain.time): rv[idt][idx] = nan return rv
class DataStoreCSVWriter: """Class that writes a :class:`~.DataStore` instance to CSV files. Attributes ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. dir_agent : :class:`~.DirectoryAgent` The path to the output directory for the run. domain : :class:`~.Domain` The instance of :class:`~.Domain` corresponding to :attr:`setting`. units : :class:`~.Units` The instance of :class:`~.Units` corresponding to :attr:`setting`. data_store : :class:`~.DataStore` The data store to be analysed. quantity: :obj:`str` The string id for the quantity stored in the data store. """ def __init__(self, setting: RIDTConfig, data_store: DataStore, dir_agent: DirectoryAgent, quantity: str): """The :class:`DataStoreCSVWriter` constructor. Parameters ---------- settings : :class:`~.RIDTConfig` The settings for the run in question. dir_agent : :class:`~.DirectoryAgent` The path to the output directory for the run. data_store : :class:`~.DataStore` The data store to be analysed. quantity: :obj:`str` The string id for the quantity stored in the data store. """ self.dir_agent = dir_agent self.setting = setting self.units = Units(setting) self.domain = Domain(setting) self.quantity = quantity self.write(data_store) @property def geometries(self): """:obj:`list` [:obj:`str`] : the list of geometries selected for evaluation in :attr:`settings`. """ locations = self.setting.models.eddy_diffusion.monitor_locations return [g for g, e in locations.evaluate.items() if e] def write(self, data_store: DataStore) -> None: """Loops over entries in the data store and writes the data to csv file. Parameters ---------- data_store : :class:`~.DataStore` The data store to be analysed. Returns ------- None """ for geometry in self.geometries: self.dir_agent.create_data_dir(geometry, self.quantity) for id in getattr(data_store, geometry): self.write_csv(geometry, id, data_store.get(geometry, id)) def write_csv(self, geometry: str, id: str, data: ndarray) -> None: """Takes string identifiers and the grid and writes them to a csv file. Parameters ---------- geometry : :obj:`str` The type of grid to be written. id : :obj:`str` The id of the grid to be written. data : :class:`~numpy.ndarray` The grid to be written. Raises ------ :class:`~.RIDTOSError` If unable to create the file on disk. Returns ------- None """ path = join(self.dir_agent.ddir, id + ".csv") factor = getattr(self.units, f"{self.quantity}_factor") try: f = open(path, 'w', newline="") except OSError as e: raise RIDTOSError(e) writer = csv.writer(f, delimiter=",") writer.writerow([ f"time ({self.units.time})", f"x ({self.units.space})", f"y ({self.units.space})", f"z ({self.units.space})", f"value ({getattr(self.units, f'{self.quantity}')})" ]) indices = list(product(*[range(i) for i in data.shape])) print(f"Writing {id} {self.quantity} data to a csv file...") for index in tqdm(indices, total=len(indices), **bar_args): values = self.domain.values(id, index) writer.writerow(list(values) + [data[index] / factor]) f.close()