Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
    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()
Example #5
0
    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()
Example #6
0
    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))
Example #7
0
 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)
Example #8
0
    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)
Example #9
0
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)
Example #10
0
    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)
Example #11
0
    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
Example #12
0
    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()
Example #13
0
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
Example #14
0
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()