Skip to content

Commit

Permalink
Merge branch 'devel' into optknock
Browse files Browse the repository at this point in the history
  • Loading branch information
KristianJensen committed Oct 9, 2015
2 parents 7022d26 + a7b7530 commit 2f04949
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 68 deletions.
27 changes: 27 additions & 0 deletions cameo/strain_design/heuristic/multiprocess/__init__.py
Expand Up @@ -12,4 +12,31 @@
# See the License for the specific language governing permissions and
# limitations under the License.


"""
Multiprocess heuristic optimization.
It implements an islands model. Multiple processes run in parallel and each single process is an heuristic optimization.
All of those processes are connected to a Queue and every iteration an individual from a process migrates through the
Queue to another process enriching the results of the receiving by introducing variability.
For information on how to run Gene Knockout or Reaction Knockout optimizations refer to
~cameo.strain_design.heuristic.optimization
The result is the same as in the single objective. The knockouts solutions resulting from all processes are merged.
Examples
--------
>>> from cameo import models
>>> from cameo.strain_design.heuristic.multiprocess import MultiprocessGeneKnockoutOptimization
>>> from cameo.strain_design.heuristic.objective_functions import biomass_product_coupled_yield
>>> import inspyred
>>> model = models.bigg.iJO1366
>>> objective_function = biomass_product_coupled_yield('Ec_biomass_iJO1366_core_53p95M', 'EX_succ_e', 'EX_glc__D_e')
>>> opt = MultiprocessGeneKnockoutOptimization(model=model, objective_function=objective_function,
>>> heuristic_method=inspyred.ec.GA, max_migrants=1)
>>> result = opt.run()
"""
from .optimization import MultiprocessGeneKnockoutOptimization, MultiprocessReactionKnockoutOptimization
2 changes: 2 additions & 0 deletions cameo/strain_design/heuristic/multiprocess/migrators.py
Expand Up @@ -14,6 +14,8 @@

from __future__ import absolute_import, print_function

__all__ = ['MultiprocessingMigrator']

import six.moves.queue
from cameo.parallel import RedisQueue
from uuid import uuid4
Expand Down
2 changes: 2 additions & 0 deletions cameo/strain_design/heuristic/multiprocess/observers.py
Expand Up @@ -14,6 +14,8 @@

from __future__ import absolute_import, print_function

__all__ = ['CliMultiprocessProgressObserver', 'IPythonNotebookMultiprocessProgressObserver']

import six
from six.moves.queue import Empty
from uuid import uuid4
Expand Down
20 changes: 15 additions & 5 deletions cameo/strain_design/heuristic/multiprocess/optimization.py
Expand Up @@ -39,6 +39,16 @@ class MultiprocessRunner(object):
Runner for multiprocessing model. It generates the non-pickable
objects on the beginning of the process.
Attributes
----------
island_class: class
The class to be used when building the island process
init_kwargs: dict
The island_class constructor arguments.
migrator: Queue (supporting multiprocess)
The queue used to migrate individuals between islands
run_kwargs: dict
The arguments necessary to run the island
"""

def __init__(self, island_class, init_kwargs, migrator, run_kwargs):
Expand All @@ -59,7 +69,7 @@ class MultiprocessHeuristicOptimization(StrainDesignMethod):
Heuristic Optimization abstract implementation.
Arguments
=========
---------
model: SolverBasedModel
A model to simulate.
Expand Down Expand Up @@ -108,7 +118,7 @@ class MultiprocessKnockoutOptimization(MultiprocessHeuristicOptimization):
Heuristic Knockout Optimization Abstract implementation.
Arguments
=========
---------
model: SolverBasedModel
A model to simulate.
Expand Down Expand Up @@ -166,15 +176,15 @@ def run(self, view=config.default_view, number_of_islands=None, **kwargs):
for observer in self.observers:
observer.finish()

return reduce(KnockoutOptimizationResult.merge, results)
return reduce(KnockoutOptimizationResult.__iadd__, results)


class MultiprocessReactionKnockoutOptimization(MultiprocessKnockoutOptimization):
"""
Heuristic Knockout Optimization Reaction implementation.
Arguments
=========
---------
model: SolverBasedModel
A model to simulate.
Expand Down Expand Up @@ -217,7 +227,7 @@ class MultiprocessGeneKnockoutOptimization(MultiprocessKnockoutOptimization):
Heuristic Knockout Optimization Gene implementation.
Arguments
=========
---------
model: SolverBasedModel
A model to simulate.
Expand Down
2 changes: 2 additions & 0 deletions cameo/strain_design/heuristic/multiprocess/plotters.py
Expand Up @@ -14,6 +14,8 @@

from __future__ import absolute_import, print_function

__all__ = ['IPythonNotebookBokehMultiprocessPlotObserver']

import six.moves.queue

from uuid import uuid1
Expand Down
69 changes: 68 additions & 1 deletion cameo/strain_design/heuristic/objective_functions.py
Expand Up @@ -14,11 +14,13 @@
# limitations under the License.

from __future__ import absolute_import, print_function
from functools import partial
from cameo.util import TimeMachine

__all__ = ['biomass_product_coupled_yield', 'product_yield', 'number_of_knockouts']

from cobra import Reaction
from cameo import config
from cameo import config, flux_variability_analysis


class ObjectiveFunction(object):
Expand Down Expand Up @@ -117,6 +119,71 @@ def reactions(self):
return [self.biomass, self.product, self.substrate]


class biomass_product_coupled_min_yield(ObjectiveFunction):
"""
Biomass-Product Coupled Yield: (v[biomass] * min(v[product])) / v[substrate] [1]
Parameters
----------
biomass: str or Reaction
biomass reaction identifier
product: str or Reaction
product reaction identifier
substrate: str or Reaction
substrate reaction identifier
Returns
-------
float
fitness value
"""

def __init__(self, biomass, product, substrate, *args, **kwargs):
super(biomass_product_coupled_min_yield, self).__init__(*args, **kwargs)
if isinstance(biomass, Reaction):
biomass = biomass.id
self.biomass = biomass
if isinstance(product, Reaction):
product = product.id
self.product = product
if isinstance(substrate, Reaction):
substrate = substrate.id
self.substrate = substrate
self.__name__ = self.__class__.__name__

def __call__(self, model, solution, decoded_representation):
try:
biomass_flux = round(solution.fluxes[self.biomass], config.ndecimals)
with TimeMachine() as tm:
biomass_reaction = model.reactions.get_by_id(self.biomass)
tm(do=partial(setattr, biomass_reaction, 'lower_bound', biomass_flux),
undo=partial(setattr, biomass_reaction, 'lower_bound', biomass_reaction.lower_bound))
for reaction_ko in decoded_representation[0]:
reaction_ko.knock_out(tm)

fva_res = flux_variability_analysis(model, reactions=[self.product])

min_product_flux = fva_res["lower_bound"][self.product]
substrate_flux = round(abs(solution.fluxes[self.substrate]), config.ndecimals)
return round((biomass_flux * min_product_flux) / substrate_flux, config.ndecimals)

except ZeroDivisionError:
return 0.0

def _repr_latex_(self):
return "$$bpcy = \\frac{(%s * min(%s))}{%s}$$" % (
self.biomass.replace("_", "\\_"), self.product.replace("_", "\\_"), self.substrate.replace("_", "\\_"))

@property
def name(self):
return "bpcy = (%s * min(%s)) / %s" % (self.biomass, self.product, self.substrate)

@property
def reactions(self):
return [self.biomass, self.product, self.substrate]


class product_yield(ObjectiveFunction):
"""
Product Yield Objective function: v[product]/v[substrate]
Expand Down

0 comments on commit 2f04949

Please sign in to comment.