def test_compatible_targets(self): modulation_target = ReactionModulationTarget("a", 1, 0) ki_target = ReactionKnockinTarget("a", None) ensemble_1 = EnsembleTarget("a", [modulation_target, ki_target]) ensemble_2 = EnsembleTarget("a", [ki_target, modulation_target]) assert ensemble_1.targets == ensemble_2.targets modulation_target = ReactionModulationTarget("b", 1, 0) swap_target = ReactionCofactorSwapTarget("b", [("nad_c", "nadh_c"), ("nadp_c", "nadph_c")]) ensemble_1 = EnsembleTarget("b", [modulation_target, swap_target]) ensemble_2 = EnsembleTarget("b", [swap_target, modulation_target]) assert ensemble_1.targets == ensemble_2.targets ki_target = ReactionKnockinTarget("c", None) modulation_target = ReactionModulationTarget("c", 1, 0) swap_target = ReactionCofactorSwapTarget("c", [("nad_c", "nadh_c"), ("nadp_c", "nadph_c")]) ensemble = EnsembleTarget("c", [modulation_target, swap_target, ki_target]) assert ensemble.targets[0] == ki_target assert ensemble.targets[1] == swap_target assert ensemble.targets[2] == modulation_target
def test_add_strain_design(self): t1 = ReactionKnockoutTarget('PGI') t2 = ReactionKnockoutTarget('GAPD') t3 = ReactionKnockinTarget("CAD", self.cad_reaction) strain_design1 = StrainDesign([t1, t2, t3]) t4 = ReactionModulationTarget("PGI", 5, 1) strain_design2 = StrainDesign([t4]) self.assertRaises(IncompatibleTargets, strain_design1.__add__, strain_design2) self.assertRaises(IncompatibleTargets, strain_design2.__add__, strain_design1) self.assertRaises(IncompatibleTargets, strain_design1.__iadd__, strain_design2) self.assertRaises(IncompatibleTargets, strain_design2.__iadd__, strain_design1) t5 = ReactionModulationTarget("RPI", 2, 0) strain_design3 = StrainDesign([t5]) strain_design4 = strain_design3 + strain_design1 self.assertIn(t1, strain_design4) self.assertIn(t2, strain_design4) self.assertIn(t3, strain_design4) self.assertNotIn(t4, strain_design4) self.assertIn(t5, strain_design4) strain_design3 += strain_design1 self.assertIn(t1, strain_design3) self.assertIn(t2, strain_design3) self.assertIn(t3, strain_design3) self.assertNotIn(t4, strain_design3) self.assertIn(t5, strain_design3)
def test_reaction_down_regulation_target(self, model): reaction_id = "PGI" ref_val = 4.86 value = 3.4 # (B - A) / A fold_change = -0.30041 down_reg_target = ReactionModulationTarget(reaction_id, value, ref_val) assert round(abs(down_reg_target.fold_change - fold_change), 5) == 0 with model: down_reg_target.apply(model) assert model.reactions.PGI.upper_bound == 3.4 assert model.reactions.PGI.lower_bound == -1000 assert abs(model.slim_optimize() - 0.8706) < 0.0001 assert model.reactions.PGI.upper_bound == 1000 assert model.reactions.PGI.lower_bound == -1000 reaction_id = "RPI" ref_val = -2.28150 value = -1.5 fold_change = -0.342537 down_reg_target = ReactionModulationTarget(reaction_id, value, ref_val) assert round(abs(down_reg_target.fold_change - fold_change), 5) == 0 with model: down_reg_target.apply(model) assert model.reactions.RPI.lower_bound == -1.5 assert model.reactions.RPI.upper_bound == 1000 assert abs(model.slim_optimize() - 0.8691) < 0.0001 assert model.reactions.RPI.lower_bound == -1000 assert model.reactions.RPI.upper_bound == 1000
def test_incompatible_targets(self): ko_target = ReactionKnockoutTarget("a") ki_target = ReactionKnockinTarget("a", None) with pytest.raises(IncompatibleTargets): EnsembleTarget("a", [ko_target, ki_target]) with pytest.raises(IncompatibleTargets): EnsembleTarget("a", [ki_target, ko_target]) ko_target = ReactionKnockoutTarget("b") swap_target = ReactionCofactorSwapTarget("b", [("nad_c", "nadh_c"), ("nadp_c", "nadph_c")]) with pytest.raises(IncompatibleTargets): EnsembleTarget("b", [ko_target, swap_target]) with pytest.raises(IncompatibleTargets): EnsembleTarget("b", [swap_target, ko_target]) modulation_target = ReactionModulationTarget("c", 0, 0) ki_target = ReactionKnockinTarget("c", None) with pytest.raises(IncompatibleTargets): EnsembleTarget("c", [modulation_target, ki_target]) with pytest.raises(IncompatibleTargets): EnsembleTarget("c", [ki_target, modulation_target])
def _generate_designs(solutions, reference_fva): designs = [] for _, solution in solutions.iteritems(): targets = [] relevant_targets = solution[solution.normalized_gaps != 0] for rid, relevant_target in relevant_targets.iterrows(): if relevant_target.normalized_gaps > 0: targets.append( ReactionModulationTarget( rid, reference_fva['upper_bound'][rid], relevant_target.lower_bound)) else: targets.append( ReactionModulationTarget( rid, reference_fva['lower_bound'][rid], relevant_target.upper_bound)) designs.append(StrainDesign(targets)) return designs
def _generate_designs(reference, enforced_levels, reaction_results): for i, level in enumerate(enforced_levels): targets = [] for reaction, value in six.iteritems(reaction_results): if abs(reference[reaction.id]) > 0: if value[i] == 0: targets.append(ReactionKnockoutTarget(reaction.id)) elif value[i] > reference[reaction.id]: targets.append(ReactionModulationTarget(reaction.id, value[i], reference[reaction.id])) yield StrainDesign(targets)
def test_add_strain_design(self, cad_reaction): t1 = ReactionKnockoutTarget('PGI') t2 = ReactionKnockoutTarget('GAPD') t3 = ReactionKnockinTarget("CAD", cad_reaction) strain_design1 = StrainDesign([t1, t2, t3]) t4 = ReactionModulationTarget("PGI", 5, 1) strain_design2 = StrainDesign([t4]) with pytest.raises(IncompatibleTargets): strain_design1.__add__(strain_design2) with pytest.raises(IncompatibleTargets): strain_design2.__add__(strain_design1) with pytest.raises(IncompatibleTargets): strain_design1.__iadd__(strain_design2) with pytest.raises(IncompatibleTargets): strain_design2.__iadd__(strain_design1) t5 = ReactionModulationTarget("RPI", 2, 0) strain_design3 = StrainDesign([t5]) strain_design4 = strain_design3 + strain_design1 assert t1 in strain_design4 assert t2 in strain_design4 assert t3 in strain_design4 assert t4 not in strain_design4 assert t5 in strain_design4 strain_design3 += strain_design1 assert t1 in strain_design3 assert t2 in strain_design3 assert t3 in strain_design3 assert t4 not in strain_design3 assert t5 in strain_design3
def test_invalid_reaction_modulation_target(self, model): reaction_id = "PGI_XY" ref_val = 4.86 value = 4 down_reg_target = ReactionModulationTarget(reaction_id, value, ref_val) with pytest.raises(KeyError): down_reg_target.apply(model) reaction_id = "RPI_Z" ref_val = -2.28150 value = -2.0 down_reg_target = ReactionModulationTarget(reaction_id, value, ref_val) with pytest.raises(KeyError): down_reg_target.apply(model)
def _generate_designs(cls, solutions, reference_fva, reference_fluxes): """ Generates strain designs for Differential FVA. The conversion method has three scenarios: #### 1. Knockout Creates a ReactionKnockoutTarget. #### 2. Flux reversal If the new flux is negative then it should be at least the upper bound of the interval. Otherwise it should be at least the lower bound of the interval. #### 3. The flux increases or decreases This table illustrates the possible combinations. * Gap is the sign of the normalized gap between the intervals. * Ref is the sign of the closest bound (see _closest_bound). * Bound is the value to use +-------------------+ | Gap | Ref | Bound | +-----+-----+-------+ | - | - | LB | | - | + | UB | | + | - | UB | | + | + | LB | +-----+-----+-------+ Parameters ---------- solutions: pandas.Panel The DifferentialFVA panel with all the solutions. Each DataFrame is a design. reference_fva: pandas.DataFrame The FVA limits for the reference strain. reference_fluxes: The optimal flux distribution for the reference strain. Returns ------- list A list of cameo.core.strain_design.StrainDesign for each DataFrame in solutions. """ designs = [] for _, solution in solutions.groupby(('biomass', 'production')): targets = [] relevant_targets = solution.loc[ (numpy.abs(solution['normalized_gaps']) > non_zero_flux_threshold) & (numpy.logical_not(solution['excluded'])) & (numpy.logical_not(solution['free_flux']))] for rid, relevant_row in relevant_targets.iterrows(): if relevant_row.KO: targets.append(ReactionKnockoutTarget(rid)) elif relevant_row.flux_reversal: if reference_fva['upper_bound'][rid] > 0: targets.append( ReactionInversionTarget( rid, value=float_ceil(relevant_row.upper_bound, ndecimals), reference_value=reference_fluxes[rid])) else: targets.append( ReactionInversionTarget( rid, value=float_floor(relevant_row.lower_bound, ndecimals), reference_value=reference_fluxes[rid])) else: gap_sign = relevant_row.normalized_gaps > 0 ref_interval = reference_fva[[ 'lower_bound', 'upper_bound' ]].loc[rid].values row_interval = (relevant_row.lower_bound, relevant_row.upper_bound) closest_bound, ref_sign = cls._closest_bound( ref_interval, row_interval) if gap_sign ^ ref_sign: value = float_ceil(relevant_row.upper_bound, ndecimals) else: value = float_floor(relevant_row.lower_bound, ndecimals) targets.append( ReactionModulationTarget( rid, value=value, reference_value=reference_fva[closest_bound][rid])) designs.append(StrainDesign(targets)) return designs
def _generate_designs(cls, solutions, reference_fva): """ Generates strain designs for Differential FVA. The conversion method has three scenarios: #### 1. Knockout Creates a ReactionKnockoutTarget. #### 2. Flux reversal If the new flux is negative then it should be at least the upper bound of the interval. Otherwise it should be at least the lower bound of the interval. #### 3. The flux increases or decreases This table illustrates the possible combinations. * Gap is the sign of the normalized gap between the intervals. * Ref is the sign of the closest bound (see _closest_bound). * Bound is the value to use +-------------------+ | Gap | Ref | Bound | +-----+-----+-------+ | - | - | LB | | - | + | UB | | + | - | UB | | + | + | LB | +-----+-----+-------+ Parameters ---------- solutions: pandas.Panel The DifferentialFVA panel with all the solutions. Each DataFrame is a design. reference_fva: pandas.DataFrame The FVA limits for the reference strain. Returns ------- list A list of cameo.core.strain_design.StrainDesign for each DataFrame in solutions. """ designs = [] for _, solution in solutions.groupby(['biomass', 'production'], as_index=False, sort=False): targets = [] relevant_targets = solution[ (solution['normalized_gaps'].abs() > non_zero_flux_threshold) & (~solution['excluded']) & (~solution['free_flux'])] # Generate all knock-out targets. for rid in relevant_targets.loc[relevant_targets["KO"], "reaction"]: targets.append(ReactionKnockoutTarget(rid)) # Generate all flux inversion targets. for row in relevant_targets[ relevant_targets["flux_reversal"]].itertuples(): rid = row.Index ref_lower = reference_fva.at[rid, 'lower_bound'] ref_upper = reference_fva.at[rid, 'upper_bound'] if ref_upper > 0: # Production point is negative so closest inversion is # from reference lower bound to production upper bound. targets.append( ReactionInversionTarget(rid, value=row.upper_bound, reference_value=ref_lower)) else: # Production point is positive so closest inversion is # from reference upper bound to production lower bound. targets.append( ReactionInversionTarget(rid, value=row.lower_bound, reference_value=ref_upper)) # Generate all suddenly essential targets where we know the # reference interval lies around zero. for row in relevant_targets[ relevant_targets["suddenly_essential"]].itertuples(): rid = row.Index if row.lower_bound > 0: targets.append( ReactionModulationTarget( rid, value=row.lower_bound, reference_value=reference_fva.at[rid, "upper_bound"])) else: targets.append( ReactionModulationTarget( rid, value=row.upper_bound, reference_value=reference_fva.at[rid, "lower_bound"])) # Generate all other flux modulation targets. for row in relevant_targets[ (~relevant_targets["KO"]) & (~relevant_targets["flux_reversal"]) & (~relevant_targets["suddenly_essential"])].itertuples(): rid = row.Index ref_lower = reference_fva.at[rid, 'lower_bound'] ref_upper = reference_fva.at[rid, 'upper_bound'] if row.normalized_gaps > 0: # For now we ignore reactions that have a positive # normalized gap, indicating that their flux is important # for production, but where the reference flux is higher # than the production flux. if abs(ref_upper) > abs(row.lower_bound): continue targets.append( ReactionModulationTarget( rid, value=row.lower_bound, reference_value=ref_upper, fold_change=row.normalized_gaps)) else: # For now we ignore reactions that have a negative # normalized gap, indicating that their flux needs to # decrease in production, but where the production # interval is larger than the reference interval. if abs(row.upper_bound) > abs(ref_lower): continue targets.append( ReactionModulationTarget( rid, value=row.upper_bound, reference_value=ref_lower, fold_change=row.normalized_gaps)) designs.append(StrainDesign(targets)) return designs