<commit_before>#  corda.py
#  
#  Copyright 2016 <NAME> <mail[at]cdiener.com>
#  
#  MIT license. See LICENSE for more information.

from cobra.solvers import solver_dict, get_solver_name
from cobra.manipulation.modify import convert_to_irreversible
from cobra import Model, Metabolite, Reaction
import numpy as np
from collections import Counter
from .util import safe_revert_reversible
import sys
from os import devnull

TOL = 1e-5  # Tolerance to judge whether a flux is non-zero

class CORDA(object):
    
    def __init__(self, model, confidence, met_prod=None, flux_target=1, n=10, 
        penalty_factor=100, support=5, solver=None, **solver_kwargs):
        """Initialize parameters and model"""
        self.model = model.copy()
        self.objective = model.objective.copy()
        convert_to_irreversible(self.model)
        
        # Map confidences from forward to backward reactions
        self.conf = {}
        for r in self.model.reactions:
            r.objective_coefficient = 0
            r.upper_bound = 1000
            if r.id in confidence: self.conf[r.id] = confidence[r.id]
            elif "reflection" in r.notes:
                rev = self.model.reactions.get_by_id(r.notes["reflection"])
                self.conf[r.id] = confidence[rev.id]
            else:
                raise ValueError("{} missing from confidence!".format(r.id))
        self.__conf_old = self.conf.copy()
        
        self.built = False
        self.tflux = flux_target
        self.impossible = []
        self.n = n
        self.noise = 0.5
        self.support = support
        self.pf = penalty_factor
        self.solver = solver_dict[get_solver_name() if solver is None else solver]
        self.sargs = solver_kwargs
        
        self.m_pen = Metabolite("penalty")
        self.r_pen = Reaction("EX_penalty")
        self.r_pen.notes["mock"] = self.m_pen
        self.r_pen.add_metabolites({self.m_pen: -1})
        self.r_pen.objective_coefficient = 1.0
        self.r_pen.upper_bound = 1e6
        
        
        if met_prod:
            for mid in met_prod:
                r = Reaction("EX_CORDA_" + mid)
                r.notes["mock"] = mid
                r.add_metabolites({self.model.metabolites.get_by_id(mid): -1})
                self.model.add_reaction(r)
                self.conf[r.id] = 3
                
    def __perturb(self, lp, m):
        noise = np.random.uniform(high=self.noise, size=len(m.reactions))
        pen_id = m.metabolites.index("penalty")
        
        for i, r in enumerate(m.reactions):
            if self.m_pen in r.metabolites and r.id != "EX_penalty":
                coef = r.metabolites[self.m_pen]
                self.solver.change_coefficient(lp, pen_id, 
                    i, coef + noise[i])
        <commit_msg>Expanded forms for metabolite tests<commit_after>#  corda.py
#  
#  Copyright 2016 <NAME> <<EMAIL>[at]c<EMAIL>>
#  
#  MIT license. See LICENSE for more information.

from cobra.solvers import solver_dict, get_solver_name
from cobra.manipulation.modify import convert_to_irreversible
from cobra import Model, Metabolite, Reaction
import numpy as np
from collections import Counter
from .util import safe_revert_reversible
import sys
from os import devnull

TOL = 1e-5  # Tolerance to judge whether a flux is non-zero

class CORDA(object):
    
    def __init__(self, model, confidence, met_prod=None, flux_target=1, n=10, 
        penalty_factor=100, support=5, solver=None, **solver_kwargs):
        """Initialize parameters and model"""
        self.model = model.copy()
        self.objective = model.objective.copy()
        convert_to_irreversible(self.model)
        
        # Map confidences from forward to backward reactions
        self.conf = {}
        for r in self.model.reactions:
            r.objective_coefficient = 0
            r.upper_bound = 1000
            if r.id in confidence: self.conf[r.id] = confidence[r.id]
            elif "reflection" in r.notes:
                rev = self.model.reactions.get_by_id(r.notes["reflection"])
                self.conf[r.id] = confidence[rev.id]
            else:
                raise ValueError("{} missing from confidence!".format(r.id))
        self.__conf_old = self.conf.copy()
        
        self.built = False
        self.tflux = flux_target
        self.impossible = []
        self.n = n
        self.noise = 0.5
        self.support = support
        self.pf = penalty_factor
        self.solver = solver_dict[get_solver_name() if solver is None else solver]
        self.sargs = solver_kwargs
        
        self.m_pen = Metabolite("penalty")
        self.r_pen = Reaction("EX_penalty")
        self.r_pen.notes["mock"] = self.m_pen
        self.r_pen.add_metabolites({self.m_pen: -1})
        self.r_pen.objective_coefficient = 1.0
        self.r_pen.upper_bound = 1e6
        
        
        if met_prod:
            for mid in met_prod:
                r = Reaction("EX_CORDA_" + mid)
                r.notes["mock"] = mid
                if type(mid) == str:
                    r.add_metabolites({mid: -1})
                elif type(mid) == dict:
                    r.add_metabolites(mid)
                else:
                    raise ValueError("metabolite test not string or dictionary")
                self.model.add_reaction(r)
                self.conf[r.id] = 3
                
    def __perturb(self, lp, m):
        noise = np.random.uniform(high=self.noise, size=len(m.reactions))
        pen_id = m.metabolites.index("penalty")
        
        for i, r in enumerate(m.reactions):
            if self.m_pen in r.metabolites and r.id != "EX_penalty":
                coef = r.metabolites[self.m_pen]
                self.solver.change_coefficient(lp, pen_id, 
                    i, coef + noise[i])
        
{'fraction_non_alphanumeric': 0.10022386774582401, 'fraction_numerical': 0.009299121749612537, 'mean_word_length': 1.992272024729521, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4495577', 'n_tokens_mistral': 1896, 'n_tokens_neox': 1778, 'n_words': 409}