예제 #1
0
    def test_singleton(self):
        r1 = RandomStateManager.instance()
        r2 = RandomStateManager.instance()
        self.assertEqual(r1, r2)

        r1.seed(123)
        r2.seed(456)
        np.testing.assert_equal(r1.get_state(), r2.get_state())
        self.assertEqual(r1, r2)
예제 #2
0
    def __init__(self, model, wc_sim_config, options=None):
        """
        Args:
            model (:obj:`Model`): the model being simulated
            wc_sim_config (:obj:`WCSimulationConfig`): a whole-cell simulation configuration
            options (:obj:`dict`, optional): options for submodels, keyed by submodel class name
        """
        # initialize simulation infrastructure
        self.simulation = SimulationEngine()
        self.random_state = RandomStateManager.instance()

        # create simulation attributes
        self.model = model
        self.wc_sim_config = wc_sim_config
        self.options = options

        self._skipped_submodels = self.prepare_skipped_submodels()

        # a model without submodels cannot be simulated
        submodel_ids = set(
            [submodel.id for submodel in self.model.get_submodels()])
        if not submodel_ids - self.skipped_submodels():
            raise MultialgorithmError(
                f"model {self.model.id} cannot be simulated because it contains"
                f" no submodels")
예제 #3
0
파일: nrm.py 프로젝트: hongzhonglu/wc_sim
    def __init__(self, id, dynamic_model, reactions, species, dynamic_compartments,
                 local_species_population, options=None):
        """ Initialize an NRM submodel object

        Args:
            id (:obj:`str`): unique id of this dynamic NRM submodel
            dynamic_model (:obj:`DynamicModel`): the aggregate state of a simulation
            reactions (:obj:`list` of :obj:`Reaction`): the reactions modeled by this NRM submodel
            species (:obj:`list` of :obj:`Species`): the species that participate in the reactions modeled
                by this NRM submodel, with their initial concentrations
            dynamic_compartments (:obj:`dict`): :obj:`DynamicCompartment`\ s, keyed by id, that contain
                species which participate in reactions that this NRM submodel models, including
                adjacent compartments used by its transfer reactions
            local_species_population (:obj:`LocalSpeciesPopulation`): the store that maintains this
                NRM submodel's species population
            options (:obj:`dict`, optional): NRM submodel options

        Raises:
            :obj:`MultialgorithmError`: if the initial NRM wait exponential moving average is not positive
        """
        super().__init__(id, dynamic_model, reactions, species, dynamic_compartments,
                         local_species_population)
        self.random_state = RandomStateManager.instance()
        self.execution_time_priority_queue = PQDict()
        self.options = options
        # to enable testing of uninitialized instances auto_initialize controls initialization here
        # auto_initialize defaults to True
        auto_initialize = True
        if options is not None and 'auto_initialize' in options:
            auto_initialize = options['auto_initialize']
        if auto_initialize:
            self.initialize()
예제 #4
0
    def setUp(self):

        # make a Compartment & use it to make a DynamicCompartment
        comp_id = 'comp_id'
        self.mean_init_volume = 1E-17
        self.compartment = Compartment(id=comp_id,
                                       name='name',
                                       init_volume=InitVolume(
                                           mean=self.mean_init_volume,
                                           std=self.mean_init_volume / 40.))
        self.compartment.init_density = Parameter(
            id='density_{}'.format(comp_id),
            value=1100.,
            units=unit_registry.parse_units('g l^-1'))

        self.random_state = RandomStateManager.instance()
        self.dynamic_compartment = DynamicCompartment(None, self.random_state,
                                                      self.compartment)

        self.abstract_compartment = Compartment(
            id=comp_id,
            name='name',
            init_volume=InitVolume(mean=self.mean_init_volume, std=0),
            physical_type=onto['WC:abstract_compartment'])
        self.abstract_dynamic_compartment = DynamicCompartment(
            None, self.random_state, self.abstract_compartment)
예제 #5
0
    def setUp(self):
        comp_id = 'comp_id'

        # make a LocalSpeciesPopulation
        self.num_species = 100
        species_nums = list(range(0, self.num_species))
        self.species_ids = list(
            map(lambda x: "species_{}[{}]".format(x, comp_id), species_nums))
        self.all_pops = 1E6
        self.init_populations = dict(
            zip(self.species_ids, [self.all_pops] * len(species_nums)))
        self.all_m_weights = 50
        self.molecular_weights = dict(
            zip(self.species_ids, [self.all_m_weights] * len(species_nums)))
        self.local_species_pop = LocalSpeciesPopulation(
            'test',
            self.init_populations,
            self.molecular_weights,
            random_state=RandomStateManager.instance())

        # make Compartments & use them to make a DynamicCompartments
        self.mean_init_volume = 1E-17
        self.compartment = Compartment(id=comp_id,
                                       name='name',
                                       init_volume=InitVolume(
                                           mean=self.mean_init_volume,
                                           std=self.mean_init_volume / 40.))
        self.compartment.init_density = Parameter(
            id='density_{}'.format(comp_id),
            value=1100.,
            units=unit_registry.parse_units('g l^-1'))
        self.random_state = RandomStateManager.instance()
        self.dynamic_compartment = DynamicCompartment(None, self.random_state,
                                                      self.compartment,
                                                      self.species_ids)

        self.abstract_compartment = Compartment(
            id=comp_id,
            name='name',
            init_volume=InitVolume(mean=self.mean_init_volume, std=0),
            physical_type=onto['WC:abstract_compartment'])
        self.abstract_dynamic_compartment = DynamicCompartment(
            None, self.random_state, self.abstract_compartment)
예제 #6
0
    def __init__(self,
                 id,
                 dynamic_model,
                 reactions,
                 species,
                 dynamic_compartments,
                 local_species_population,
                 default_center_of_mass=None,
                 options=None):
        """ Initialize an SSA submodel object.

        Args:
            id (:obj:`str`): unique id of this dynamic SSA submodel
            dynamic_model (:obj:`DynamicModel`): the aggregate state of a simulation
            reactions (:obj:`list` of :obj:`Reaction`): the reactions modeled by this SSA submodel
            species (:obj:`list` of :obj:`Species`): the species that participate in the reactions modeled
                by this SSA submodel, with their initial concentrations
            dynamic_compartments (:obj:`dict`): :obj:`DynamicCompartment`\ s, keyed by id, that contain
                species which participate in reactions that this SSA submodel models, including
                adjacent compartments used by its transfer reactions
            local_species_population (:obj:`LocalSpeciesPopulation`): the store that maintains this
                SSA submodel's species population
            default_center_of_mass (:obj:`float`, optional): the center-of-mass for the
                :obj:`ExponentialMovingAverage`
            options (:obj:`dict`, optional): SSA submodel options

        Raises:
            :obj:`MultialgorithmError`: if the initial SSA wait exponential moving average is not positive
        """
        super().__init__(id, dynamic_model, reactions, species,
                         dynamic_compartments, local_species_population)
        self.options = options
        self.num_SsaWaits = 0
        # `initial_ssa_wait_ema` must be positive, as otherwise an infinite sequence of SsaWait
        # messages will be executed at the start of a simulation if no reactions are enabled
        initial_ssa_wait_ema = config_multialgorithm['initial_ssa_wait_ema']
        if initial_ssa_wait_ema <= 0:  # pragma: no cover
            raise MultialgorithmError(
                f"'initial_ssa_wait_ema' must be positive to avoid infinite sequence of "
                "SsaWait messages, but it is {initial_ssa_wait_ema}")
        if default_center_of_mass is None:
            default_center_of_mass = config_multialgorithm[
                'default_center_of_mass']
        self.ema_of_inter_event_time = ExponentialMovingAverage(
            initial_ssa_wait_ema, center_of_mass=default_center_of_mass)
        self.random_state = RandomStateManager.instance()

        self.log_with_time("init: id: {}".format(id))
        self.log_with_time("init: species: {}".format(
            str([s.id for s in species])))
예제 #7
0
    def test_initialize_mass_and_density(self):
        self.dynamic_compartment.initialize_mass_and_density(
            self.local_species_pop)
        estimated_accounted_mass = self.num_species * self.all_pops * self.all_m_weights / Avogadro
        self.assertAlmostEqual(self.dynamic_compartment.init_accounted_mass,
                               estimated_accounted_mass,
                               places=IEEE_64_BIT_FLOATING_POINT_PLACES)
        self.assertTrue(0 < self.dynamic_compartment.init_mass)
        self.assertAlmostEqual(self.dynamic_compartment.accounted_fraction,
                               self.dynamic_compartment.init_accounted_mass / \
                                self.dynamic_compartment.init_mass,
                               places=IEEE_64_BIT_FLOATING_POINT_PLACES)

        # test abstract compartment
        self.abstract_dynamic_compartment.initialize_mass_and_density(
            self.local_species_pop)
        self.assertAlmostEqual(
            self.abstract_dynamic_compartment.init_accounted_mass,
            estimated_accounted_mass,
            places=IEEE_64_BIT_FLOATING_POINT_PLACES)
        self.assertEqual(self.abstract_dynamic_compartment.init_accounted_mass,
                         self.abstract_dynamic_compartment.init_mass)
        self.assertFalse(
            hasattr(self.abstract_dynamic_compartment,
                    'init_accounted_density'))

        empty_local_species_pop = LocalSpeciesPopulation(
            'test', {}, {}, random_state=RandomStateManager.instance())
        dynamic_compartment = DynamicCompartment(None, self.random_state,
                                                 self.compartment)
        with self.assertRaisesRegex(MultialgorithmError,
                                    "initial accounted ratio is 0"):
            dynamic_compartment.initialize_mass_and_density(
                empty_local_species_pop)

        dynamic_compartment = self.specify_init_accounted_fraction(
            (DynamicCompartment.MAX_ALLOWED_INIT_ACCOUNTED_FRACTION + 1) / 2)
        with warnings.catch_warnings(record=True) as w:
            dynamic_compartment.initialize_mass_and_density(
                self.local_species_pop)
            self.assertIn("initial accounted ratio (", str(w[-1].message))
            self.assertIn(") greater than 1.0", str(w[-1].message))

        dynamic_compartment = self.specify_init_accounted_fraction(2)
        with self.assertRaises(MultialgorithmError):
            dynamic_compartment.initialize_mass_and_density(
                self.local_species_pop)
 def __init__(self, init_val):
     self.value = init_val
     self.random_state = RandomStateManager.instance()
예제 #9
0
 def expected_molar_conc(self, dynamic_submodel, species_id):
     species = list(filter(lambda s: s.id == species_id, dynamic_submodel.species))[0]
     init_volume = species.compartment.init_volume.mean
     copy_num = ModelUtilities.sample_copy_num_from_concentration(species, init_volume, RandomStateManager.instance())
     volume = dynamic_submodel.dynamic_compartments[species.compartment.id].volume()
     return copy_num / (volume * Avogadro)
예제 #10
0
    def run(self,
            time_max,
            results_dir=None,
            progress_bar=True,
            checkpoint_period=None,
            seed=None,
            ode_time_step=None,
            dfba_time_step=None,
            profile=False,
            submodels_to_skip=None,
            verbose=True,
            options=None):
        """ Run one simulation

        Args:
            time_max (:obj:`float`): the maximum time of a simulation; a stop condition may end it
                earlier (sec)
            results_dir (:obj:`str`, optional): path to a directory in which results are stored
            progress_bar (:obj:`bool`, optional): whether to show the progress of a simulation in
                in a real-time bar on a terminal
            checkpoint_period (:obj:`float`, optional): the period between simulation state checkpoints (sec)
            ode_time_step (:obj:`float`, optional): time step length of ODE submodel (sec)
            dfba_time_step (:obj:`float`, optional): time step length of dFBA submodel (sec)
            profile (:obj:`bool`, optional): whether to output a profile of the simulation's performance
                created by a Python profiler
            seed (:obj:`object`, optional): a seed for the simulation's `numpy.random.RandomState`;
                if provided, `seed` will reseed the simulator's PRNG
            submodels_to_skip (:obj:`list` of :obj:`str`, optional): submodels that should not be run,
                identified by their ids
            verbose (:obj:`bool`, optional): whether to print success output
            options (:obj:`dict`, optional): options for submodels, passed to `MultialgorithmSimulation`

        Returns:
            :obj:`tuple` of (`int`, `str`): number of simulation events, pathname of directory
                containing the results, or :obj:`tuple` of (`int`, `None`): number of simulation events,
                `None` if `results_dir is None`, or :obj:`tuple` of (`pstats.Stats`, `None`): profile
                stats, `None` if `profile is True`

        Raises:
            :obj:`MultialgorithmError`: if the simulation raises an exception
        """
        self._prepare()

        # create simulation configurations
        # create and validate DE sim configuration
        self.de_sim_config = SimulationConfig(time_max,
                                              output_dir=results_dir,
                                              progress=progress_bar,
                                              profile=profile)
        self.de_sim_config.validate()

        # create and validate WC configuration
        self.wc_sim_config = WCSimulationConfig(
            de_simulation_config=self.de_sim_config,
            random_seed=seed,
            ode_time_step=ode_time_step,
            dfba_time_step=dfba_time_step,
            checkpoint_period=checkpoint_period,
            submodels_to_skip=submodels_to_skip,
            verbose=verbose)
        self.wc_sim_config.validate()

        # create author metadata for DE sim
        try:
            username = getpass.getuser()
        except KeyError:  # pragma: no cover
            username = '******'
        self.author_metadata = AuthorMetadata(
            name='Unknown name',
            email='Unknown email',
            username=username,
            organization='Unknown organization')

        # create WC sim metadata
        wc_simulation_metadata = WCSimulationMetadata(self.wc_sim_config)
        if self.model_path is not None:
            wc_simulation_metadata.set_wc_model_repo(self.model_path)

        if seed is not None:
            RandomStateManager.initialize(seed=seed)

        # create a multi-algorithmic simulator
        multialgorithm_simulation = MultialgorithmSimulation(
            self.model, self.wc_sim_config, options)
        self.simulation_engine, self.dynamic_model = multialgorithm_simulation.build_simulation(
        )
        self.simulation_engine.initialize()

        # set stop_condition after the dynamic model is created
        self.de_sim_config.stop_condition = self.dynamic_model.get_stop_condition(
        )

        # run simulation
        try:
            # provide DE config and author metadata to DE sim
            simulate_rv = self.simulation_engine.simulate(
                sim_config=self.de_sim_config,
                author_metadata=self.author_metadata)

            # add WC sim metadata to the output after the simulation, which requires an empty output dir
            # TODO: have simulation_engine.simulate() allow certain files in self.de_sim_config.output_dir, and move
            # this code above
            if self.de_sim_config.output_dir is not None:
                WCSimulationMetadata.write_dataclass(
                    wc_simulation_metadata, self.de_sim_config.output_dir)

            if profile:
                stats = simulate_rv
                return stats, None
            else:
                num_events = simulate_rv

        except SimulatorError as e:  # pragma: no cover
            raise MultialgorithmError(
                f'Simulation terminated with simulator error:\n{e}')
        except BaseException as e:  # pragma: no cover
            raise MultialgorithmError(
                f'Simulation terminated with error:\n{e}')

        if verbose:
            print(f'Simulated {num_events} events')
        if results_dir:
            # summarize results in an HDF5 file in results_dir
            RunResults(results_dir)
            if verbose:
                print(f"Saved checkpoints and run results in '{results_dir}'")
            return (num_events, results_dir)
        else:
            return (num_events, None)