Example #1
0
    def test_verify(self):

        """Verifies that the config.json file is created
        in the correct directory, then removes the created
        files."""

        da = DataStore()
        dsa = DataStoreAnalyser(self.c, da, "concentration")

        bds = BatchDataStore()
        bds.add_run(self.c)

        bdsw = BatchResultsWriter(
            self.c, self.space, {self.c: dsa}, self.out_dir, "concentration"
        )

        try:
            bdsw.write()
        except BatchDataStoreIDError as e:
            pass
        self.assertIn(
            "batch_run_summary.txt", os.listdir(f"{self.out_dir}")
        )

        with open(os.path.join(self.this_dir, "st14/run/batch_run_summary.txt")) as f:
            txt = f.read()

        self.assertIn(
            "Computational space dimensions: 1 x",
            txt
        )
Example #2
0
class TestBatchDataStore(unittest.TestCase):

    "Unit tests for the :class:`~.BatchDataStore` class." ""

    def setUp(self) -> None:
        """setUp method which instantiates the :class:`~.RIDTConfig` class,
        and the :class:`~.BatchDataStore` class."""

        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.bds = BatchDataStore()

    def test_add_run(self):
        """Adds a run to the batch data store then checks
        to make sure the new items match the type of
        the ones added."""

        self.bds.add_run(self.config)
        self.assertEqual(type(self.bds.store), dict)
        for key, val in self.bds.store.items():
            self.assertEqual(type(key), RIDTConfig)
            self.assertEqual(type(val), DataStore)
Example #3
0
    def setUp(self) -> None:
        """setUp method which instantiates the :class:`~.RIDTConfig` class,
        and the :class:`~.BatchDataStore` class."""

        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.bds = BatchDataStore()
Example #4
0
    def evaluate(self, data_store: Union[DataStore, BatchDataStore])\
            -> Union[DataStore, BatchDataStore]:
        """Iterates over all geometries and computes exposures.

        Parameters
        ----------
        data_store : Union[:class:`~.DataStore`, :class:`~.BatchDataStore`]
            The data store or batch data store to be analysed.

        Returns
        -------
        Union[:class:`~.DataStore`, :class:`~.BatchDataStore`]
            The computed exposures.

        Raises
        ------
        :obj:`TypeError`
            If the `data_store` is not a :class:`~.DataStore` or
            :class:`~.BatchDataStore`.

        """
        if isinstance(data_store, DataStore):
            rv = DataStore()
            for geometry in self.geometries:
                for name, data in getattr(data_store, geometry).items():
                    rv.add(geometry, name, self.compute(data))
            return rv
        elif isinstance(data_store, BatchDataStore):
            rv = BatchDataStore()
            for setting, store in data_store.items():
                rv.add_run(setting)
                rv[setting] = self.evaluate(data_store[setting])
            return rv
        else:
            raise TypeError(f"Expecting {DataStore} or {BatchDataStore}.")
Example #5
0
    def test_verify(self):

        """Verifies that the config.json file is created
        in the correct directory, then removes the created
        files."""

        bds = BatchDataStore()
        for space in self.space.space:
            bds.add_run(space)

        try:
            BatchDataStoreWriter(
                self.c, bds, self.space, self.directory, "concentration")
        except BatchDataStoreIDError as e:
            pass
        self.assertIn(
            "batch_config.json", os.listdir(f"{self.directory}")
        )
Example #6
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 #7
0
    def __init__(self, settings: RIDTConfig, outdir: str):
        """The constructor for the :class:`EddyDiffusionRun` class.

        Parameters
        ----------
        settings : :class:`~.RIDTConfig`
            The settings for the run in question.

        outdir : :obj:`str`
            The path to the output directory for the run.

        """
        self.settings = settings
        self.outdir = outdir
        self.data_store = BatchDataStore()
        self.exposure_store = None
        self.space = self.prepare()
        self.evaluate()
        self.compute_exposure()
        self.write()
        self.plot()
        self.analyse()
Example #8
0
class EddyDiffusionRun:
    """The class which orchestrates an Eddy Diffusion model run.

    Attributes
    ----------
    setting : :class:`~.RIDTConfig`
        The settings for the run in question.

    data_store : :class:`~.BatchDataStore`
        The batch run data store for concentration values.

    outdir: :obj:`str`
        The path to the output directory for the run.
    
    space : :class:`~.ComputationalSpace`
        The :class:`~.ComputationalSpace` instance corresponding to the
        :attr:`settings` attribute.
    
    exposure_store : :obj:`Union`[:class:`~.BatchDataStore`, None]
        The batch run data store for exposure values.
    
    """
    def __init__(self, settings: RIDTConfig, outdir: str):
        """The constructor for the :class:`EddyDiffusionRun` class.

        Parameters
        ----------
        settings : :class:`~.RIDTConfig`
            The settings for the run in question.

        outdir : :obj:`str`
            The path to the output directory for the run.

        """
        self.settings = settings
        self.outdir = outdir
        self.data_store = BatchDataStore()
        self.exposure_store = None
        self.space = self.prepare()
        self.evaluate()
        self.compute_exposure()
        self.write()
        self.plot()
        self.analyse()

    @property
    def geometries(self):
        """:obj:`list` [:obj:`str`] : the list of geometries selected for
        evaluation in :attr:`settings`.

        """
        locations = self.settings.models.eddy_diffusion.monitor_locations
        return [g for g, e in locations.evaluate.items() if e]

    def prepare(self) -> ComputationalSpace:
        """Instantiates :class:`~.ComputationalSpace` instance.

        Generates a :class:`~.ComputationalSpace` instance from
        :attr:`settings`. 

        Returns
        -------
        :class:`~.ComputationalSpace`
            The Computational Space created from :attr:`settings`. 
        """
        print("Preparing Eddy Diffusion run...")
        restrict = {"models": "eddy_diffusion"}
        return ComputationalSpace(self.settings, restrict)

    def evaluate(self) -> None:
        """Loops over all elements in :attr:`space` and evaluates the model.

        Returns
        -------
        None

        """
        for setting in self.space.space:
            count = f"{self.space.linear_index(setting) + 1}/{len(self.space)}"
            print(f"Evaluating computational space element {count}")
            self.run(setting)

    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 compute_exposure(self) -> None:
        """Computes the exposure from the concentration data.

        Saves the result to a new data store :attr:`exposure_store`

        Returns
        -------
        None

        """
        if self.settings.compute_exposure:
            print("\nComputing exposure...")
            self.exposure_store = Exposure(self.settings, self.data_store)

    def args(self, data_store: BatchDataStore, quantity: str) -> tuple:
        """A helper function that returns a tuple of some values.

        Parameters
        ----------

        data_store : :class:`~.BatchDataStore`
            A batch data store.

        quantity : :obj:`str`
            The name of the quantity in the data store.

        Returns
        -------
        :obj:`tuple`
            The various quantites as a tuple.

        """
        return self.settings, data_store, self.space, self.outdir, quantity

    def write(self) -> None:
        """Writes all data stores to disk.

        Returns
        -------
        None

        """
        print("\nWriting data to disk... ")
        BatchDataStoreWriter(*self.args(self.data_store, "concentration"))
        if self.settings.compute_exposure:
            BatchDataStoreWriter(*self.args(self.exposure_store, "exposure"))

    def plot(self) -> None:
        """Plots all requested data and writes it to disk.

        Returns
        -------
        None

        """
        print("\nProducing plots... ")
        BatchDataStorePlotter(*self.args(self.data_store, "concentration"))
        if self.settings.compute_exposure:
            BatchDataStorePlotter(*self.args(self.exposure_store, "exposure"))

    def analyse(self) -> None:
        """Performs all relevant analysis and writes it to disk.

        Returns
        -------
        None

        """
        if not self.settings.models.eddy_diffusion.analysis.perform_analysis:
            return
        print("\nPerforming data analysis...")
        BatchDataStoreAnalyser(*self.args(self.data_store, "concentration"))
        if self.settings.compute_exposure:
            BatchDataStoreAnalyser(*self.args(self.exposure_store, "exposure"))
Example #9
0
class WellMixedRun:
    """The class which orchestrates an Well Mixed model run.

    Attributes
    ----------
    setting : :class:`~.RIDTConfig`
        The settings for the run in question.

    data_store : :class:`~.BatchDataStore`
        The batch run data store for concentration values.

    outdir: :obj:`str`
        The path to the output directory for the run.
    
    space : :class:`~.ComputationalSpace`
        The :class:`~.ComputationalSpace` instance corresponding to the
        :attr:`settings` attribute.
    
    exposure_store : :obj:`Union`[:class:`~.BatchDataStore`, None]
        The batch run data store for exposure values.
    
    """
    def __init__(self, settings: RIDTConfig, output_dir: str):
        """The constructor for the :class:`EddyDiffusion` class.

        Parameters
        ----------
        settings : :class:`~.RIDTConfig`
            The settings for the run in question.

        outdir : :obj:`str`
            The path to the output directory for the run.

        """
        self.settings = settings
        self.outdir = output_dir
        self.data_store = BatchDataStore()
        self.exposure_store = None
        self.space = self.prepare()
        self.evaluate()
        self.compute_exposure()
        self.write()
        self.plot()
        print("\n")

    def prepare(self) -> ComputationalSpace:
        """Instantiates :class:`~.ComputationalSpace` instance.

        Generates a :class:`~.ComputationalSpace` instance from
        :attr:`settings`. 

        Returns
        -------
        :class:`~.ComputationalSpace`
            The Computational Space created from :attr:`settings`. 
        """
        print("Preparing Well Mixed run... ")
        restrict = {"models": "well_mixed"}
        return ComputationalSpace(self.settings, restrict)

    def evaluate(self) -> None:
        """Loops over all elements in :attr:`space` and evaluates the model.

        Returns
        -------
        None

        """
        print("Evaluating model over domain... ")
        for setting in self.space.space:
            count = f"{self.space.linear_index(setting) + 1}/{len(self.space)}"
            print(f"Evaluating computational space element {count}")
            self.run(setting)

    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 compute_exposure(self):
        """Computes the exposure from the concentration data.

        Saves the result to a new data store :attr:`exposure_store`

        Returns
        -------
        None

        """
        if self.settings.compute_exposure:
            print("Computing exposure...")
            self.exposure_store = Exposure(self.settings, self.data_store)

    def args(self, data_store: BatchDataStore, quantity: str) -> tuple:
        """A helper function that returns a tuple of some values.

        Parameters
        ----------

        data_store : :class:`~.BatchDataStore`
            A batch data store.

        quantity : :obj:`str`
            The name of the quantity in the data store.

        Returns
        -------
        :obj:`tuple`
            The various quantities as a tuple.

        """
        return self.settings, data_store, self.space, self.outdir, quantity

    def write(self) -> None:
        """Writes all data stores to disk.

        Returns
        -------
        None

        """
        print("\nWriting data to disk... ")
        BatchDataStoreWriter(*self.args(self.data_store, "concentration"))
        if self.settings.compute_exposure:
            BatchDataStoreWriter(*self.args(self.exposure_store, "exposure"))

    def plot(self) -> None:
        """Plots all requested data and writes it to disk.

        Returns
        -------
        None

        """
        print("\nProducing plots... ")
        BatchDataStorePlotter(*self.args(self.data_store, "concentration"))
        if self.settings.compute_exposure:
            BatchDataStorePlotter(*self.args(self.exposure_store, "exposure"))