Example #1
0
class TestPathway(unittest.TestCase):
    def setUp(self):
        self.logger = create_logger(name='Test core.Pathway')
        self.pathway_fixture = {
            'flux': [
                -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0,
                -1.0, -1.0, -1.0, 2.0, 1.0, 1.0, 1.0, -1.0, 1.0
            ],
            'iteration':
            1,
            'reaction_id': [
                'R00200', 'R00300', 'R00658', 'R01059', 'R01063', 'R01512',
                'R01518', 'R01519', 'R01538', 'R08570', 'EX_glc', 'EX_nad',
                'EX_adp', 'EX_phosphate', 'EX_pyruvate', 'EX_nadh', 'EX_atp',
                'EX_h2o', 'EX_nadp', 'EX_nadph'
            ]
        }

        self.p1 = Pathway(id=1,
                          name='OptStoic',
                          reaction_ids=self.pathway_fixture['reaction_id'],
                          fluxes=self.pathway_fixture['flux'])

    @unittest.skip("Need to update test!")
    def test_rearrange_pathway(self):
        self.logger.info("Test rearranging reaction order")
        self.p1.rearrange_reaction_order()

    def test_kegg_model_generation(self):
        self.logger.info(
            "Creating 'res' folder in the current directory if not exist...")
        # outputFilepath = 'res'
        # outputFilename = 'OptStoic'
        # try:
        #     os.makedirs(outputFilepath)
        # except OSError:
        #     if not os.path.isdir(outputFilepath):
        #         raise Exception

        self.logger.info("Test create KEGG model file")

        filename = "./test_kegg_model_generation.txt"
        f = open(filename, 'a+')
        kegg_model_text = generate_kegg_model(self.p1, filehandle=f)
        print(kegg_model_text)
        self.assertIn('R01512', kegg_model_text)
        self.assertIn('R01512', kegg_model_text)
        f.close()

        if os.path.exists(filename):
            os.remove(filename)
Example #2
0
def runAnalysis(resultDict, numATP, outputFilePath, imgFormat='png', shift_pathway_id_by=0,\
                sourceSubstrateID='C00031', endSubstrateID='C00022', darkBackgroundMode=False):
    logging.info("Analyzing results... \n")

    pathway_objects = []

    outputFileName='OptStoic_gams_{0}ATP'.format(numATP)

    f = open(os.path.join(outputFilePath, outputFileName + '_KeggModel.txt'), 'w+')

    for ind, res in sorted(resultDict.items()):
        logging.debug("Pathway %s"%ind)
        if "pathway" not in res:
            logging.info("OptStoic terminated with infeasible solution.")
            continue
        elif "num_reaction" not in res:
            logging.info("Pathway is incomplete...")
            continue

        p = Pathway(id=int(ind)+shift_pathway_id_by, name='OptStoic_gams', reaction_ids=list(res['pathway'].keys()),
                    fluxes=list(res['pathway'].values()), sourceSubstrateID=sourceSubstrateID, endSubstrateID=endSubstrateID,
                    total_flux_no_exchange=res['total_flux_no_exchange'],
                    note={'modelstat': res.get("modelstat"), 'solvestat': res.get("solvestat")})
        p.rearrange_reaction_order()
        pathway_objects.append(p)
        generate_kegg_model(p, filehandle=f)

        graph_title = "{0}_{1}ATP_P{2}".format(p.name, p.nATP, p.id)
        if res['modelstat'] != 1:
            graph_title += '; Modelstat={0}'.format(res['modelstat'])
        if imgFormat:
            draw_pathway(p, os.path.join(outputFilePath+'/pathway_{0:03d}'.format(p.id)),
                        imageFormat=imgFormat, graphTitle=graph_title, darkBackgroundMode=darkBackgroundMode)


    #pickle.dump(resultDict, open(outputFilePath+outputFileName+'_pathways_dict.pkl', 'w+'))
    pickle.dump(pathway_objects, open(outputFilePath + outputFileName + '_pathways_obj.pkl', 'w+'))

    logging.info("\nDone!\n")
    logging.info("Check your output folder: %s"%outputFilePath)

    return pathway_objects
Example #3
0
    def setUp(self):
        self.logger = create_logger(name='Test core.Pathway')
        self.pathway_fixture = {
            'flux': [
                -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0,
                -1.0, -1.0, -1.0, 2.0, 1.0, 1.0, 1.0, -1.0, 1.0
            ],
            'iteration':
            1,
            'reaction_id': [
                'R00200', 'R00300', 'R00658', 'R01059', 'R01063', 'R01512',
                'R01518', 'R01519', 'R01538', 'R08570', 'EX_glc', 'EX_nad',
                'EX_adp', 'EX_phosphate', 'EX_pyruvate', 'EX_nadh', 'EX_atp',
                'EX_h2o', 'EX_nadp', 'EX_nadph'
            ]
        }

        self.p1 = Pathway(id=1,
                          name='OptStoic',
                          reaction_ids=self.pathway_fixture['reaction_id'],
                          fluxes=self.pathway_fixture['flux'])
Example #4
0
    def solve_gurobi_cl(self,
                        exclude_existing_solution=False,
                        outputfile="OptStoic_pulp_result_gcl.txt",
                        max_iteration=None,
                        cleanup=True,
                        gurobi_options=GUROBI_OPTIONS):
        """
        Solve OptStoic problem using Gurobi command line (gurobi_cl)
        when pulp.solvers.GUROBI_CMD failed.
        Require the module "gurobi_command_line_solver.py".

        Args:
            exclude_existing_solution (bool, optional): If true and if self.pathway is not None,
                exclude the pathways from being identified.
            outputfile (str, optional): name of outpufile
            max_iteration (None, optional): Externally specified maximum number of pathway
                to be found using OpStoic. If not specified,
                it will set to the internal max iterations.
            cleanup (bool, optional): If True, delete the temporary .lp and .sol file. Set as
                False for debugging.
            gurobi_options (TYPE, optional): Description

        Returns:
            TYPE: Description

        Raises:
            ValueError: Description
        """
        if self.objective not in ['MinFlux', 'MinRxn']:
            raise ValueError("The objective for OptStoic is not correctly "
                             "defined. Please use either 'MinFlux' or "
                             "'MinRxn'.")

        if max_iteration is None:
            max_iteration = self.max_iteration

        t1 = time.time()

        self.logger.info(
            "Finding multiple pathways using"
            " Optstoic %s and Gurobi CL...", self.objective)
        lp_prob, v, vf, vb, yf, yb, a, G = self.create_minflux_problem()

        # Create integer cut for existing pathways
        if exclude_existing_solution and bool(self.pathways):
            self.iteration = max(self.pathways.keys()) + 1
            if self.iteration > max_iteration:
                raise ValueError('Max iteration is less than current '
                                 'iteration. Increase max_iteration '
                                 'before solving!')

            for ind, pathway in self.pathways.items():
                rxnlist = list(set(pathway.reaction_ids_no_exchange))
                condition = pulp.lpSum([(1 - yf[j] - yb[j])
                                        for j in rxnlist]) >= 1
                lp_prob += condition, "IntegerCut_%d" % ind

        # Solve problem
        self.logger.info("Solving problem...")

        # if self.iteration == 1:
        #     result_output = open(os.path.join(
        #         self.result_filepath, outputfile), "w+")
        # else:
        #     result_output = open(os.path.join(
        #         self.result_filepath, outputfile), "a+")

        while True and self.iteration <= max_iteration:
            self.logger.info("Iteration %s", self.iteration)
            lp_prob.writeLP(self.lp_prob_fname + ".lp", mip=1)
            e1 = time.time()
            lp_status, solver_message = solve_with_gurobi_cl_debug(
                self.lp_prob_fname, options=gurobi_options)
            e2 = time.time()
            self.logger.info("This iteration solved in %.3f seconds.",
                             (e2 - e1))

            # The solution is printed if it was deemed "optimal
            if lp_status in ["Optimal", "Time_limit"]:
                objective_function, varValue = parse_gurobi_sol(
                    self.lp_prob_fname)

                res = {}
                res['reaction_id'] = []
                res['flux'] = []
                res['iteration'] = self.iteration
                res['time'] = (e2 - e1)
                res['modelstat'] = lp_status
                res['solvestat'] = solver_message

                # result_output.write("\nIteration no.: %d\n" %self.iteration)
                # result_output.write("\nModelstat: %s\n" %lp_status)

                for j in self.database.reactions:
                    if 'v_' + j in varValue:
                        v = varValue['v_' + j]
                        if v > EPS or v < -EPS:
                            res['reaction_id'].append(j)
                            res['flux'].append(v)
                            #result_output.write("%s %.8f\n" %(j, v))

                # result_output.write("%s = %.8f\n" %(self.objective, objective_function))
                # result_output.write("----------------------------------\n\n")

                integer_cut_reactions = list(
                    set(res['reaction_id']) -
                    set(self.database.user_defined_export_rxns))

                self.pathways[self.iteration] = Pathway(
                    id=self.iteration,
                    name='Pathway_{:03d}'.format(self.iteration),
                    reaction_ids=res['reaction_id'],
                    fluxes=res['flux'],
                    sourceSubstrateID='C00031',
                    endSubstrateID='C00022',
                    note=res)
                # Keep a copy of pathways in case program terminate midway
                self.write_pathways_to_json(json_filename="temp_pathways.json")

                # Integer cut constraint is added so that
                # the same solution cannot be returned again
                condition = pulp.lpSum([(1 - yf[j] - yb[j])
                                        for j in integer_cut_reactions]) >= 1
                lp_prob += condition, "IntegerCut_%d" % self.iteration
                self.iteration += 1

            # If a new optimal solution cannot be found, end the program
            else:
                break

        # result_output.close()
        # Clean up directory
        if cleanup:
            self.logger.debug("Cleaning up directory...")
            os.remove("./" + self.lp_prob_fname + ".lp")
            os.remove("./" + self.lp_prob_fname + ".sol")
            os.remove("./gurobi.log")

        self.lp_prob = lp_prob

        return self.lp_prob, self.pathways
Example #5
0
    def solve(self,
              exclude_existing_solution=False,
              outputfile="OptStoic_pulp_result.txt",
              max_iteration=None):
        """
        Solve OptStoic problem using pulp.solvers interface

        Args:
            exclude_existing_solution (bool, optional): If True, create and add integer cut
                constraints for pathways that are found using the same OptStoic instance,
                but solved in previous function call.
            outputfile (str, optional): name of outpufile
            max_iteration (None, optional): Externally specified maximum number of pathway to be
                found using OpStoic. If not specified, it will set to the internal max iterations.

        Returns:
            TYPE: Description

        Raises:
            ValueError: Description
        """
        if self.objective not in ['MinFlux', 'MinRxn']:
            raise ValueError(
                "The objective for OptStoic is not correctly defined. Please use either 'MinFlux' or 'MinRxn'."
            )

        if max_iteration is None:
            max_iteration = self.max_iteration

        self.logger.info("Finding multiple pathways using Optstoic %s...",
                         self.objective)
        lp_prob, v, vf, vb, yf, yb, a, G = self.create_minflux_problem()

        # Create integer cut for existing pathways
        if exclude_existing_solution and bool(self.pathways):
            self.iteration = max(self.pathways.keys()) + 1
            if self.iteration > max_iteration:
                raise ValueError('Max iteration is less than current '
                                 'iteration. Increase max_iteration '
                                 'before solving!')

            for ind, pathway in self.pathways.items():
                rxnlist = list(set(pathway.reaction_ids_no_exchange))
                condition = pulp.lpSum([(1 - yf[j] - yb[j])
                                        for j in rxnlist]) >= 1
                lp_prob += condition, "IntegerCut_%d" % ind

        self.logger.info("Solving problem...")
        # if self.iteration == 1:
        #     result_output = open(os.path.join(self.result_filepath, outputfile), "w+")
        # else:
        #     result_output = open(os.path.join(self.result_filepath, outputfile), "a+")

        while True and self.iteration <= max_iteration:
            self.logger.info("Iteration %s", self.iteration)
            # lp_prob.writeLP("OptStoic.lp", mip=1)  # optional
            e1 = time.time()
            lp_prob.solve(solver=self.pulp_solver)
            e2 = time.time()
            self.logger.info("This iteration solved in %.3f seconds.",
                             (e2 - e1))

            # The solution is printed if it was deemed "optimal
            if pulp.LpStatus[lp_prob.status] == "Optimal":
                self.logger.info("Writing result to output file...")
                # result_output.write("\nIteration no.: %d\n" %self.iteration)
                # result_output.write("\nModelstat: %s\n" %pulp.LpStatus[lp_prob.status])
                res = {}
                res['reaction_id'] = []
                res['flux'] = []
                res['iteration'] = self.iteration
                res['time'] = (e2 - e1)
                res['modelstat'] = "Optimal"

                for j in self.database.reactions:
                    if v[j].varValue is not None:
                        if v[j].varValue > EPS or v[j].varValue < -EPS:
                            res['reaction_id'].append(j)
                            res['flux'].append(v[j].varValue)
                #             result_output.write("%s %.8f\n" %(v[j].name, v[j].varValue))

                # result_output.write("%s = %.8f\n" % (self.objective, pulp.value(lp_prob.objective)))
                # result_output.write("----------------------------------\n\n")

                integer_cut_reactions = list(
                    set(res['reaction_id']) -
                    set(self.database.user_defined_export_rxns))

                self.pathways[self.iteration] = Pathway(
                    id=self.iteration,
                    name='Pathway_{:03d}'.format(self.iteration),
                    reaction_ids=res['reaction_id'],
                    fluxes=res['flux'],
                    sourceSubstrateID='C00031',
                    endSubstrateID='C00022',
                    note=res)

                self.write_pathways_to_json(json_filename="temp_pathways.json")

                # Integer cut constraint is added so that
                # the same solution cannot be returned again
                condition = pulp.lpSum([(1 - yf[j] - yb[j])
                                        for j in integer_cut_reactions]) >= 1
                lp_prob += condition, "IntegerCut_%d" % self.iteration
                self.iteration += 1

            # If a new optimal solution cannot be found, end the program
            else:
                break

        # result_output.close()

        self.lp_prob = lp_prob

        return self.lp_prob, self.pathways
Example #6
0
            }

    EMP = {
            'R00200': -2.00000000,
            'R00299': 1.00000000,
            'R00658': 2.00000000,
            'R00756': 1.00000000,
            'R00771': 1.00000000,
            'R01015': -1.00000000,
            'R01061': 2.00000000,
            'R01068': 1.00000000,
            'R01512': -2.00000000,
            'R01518': -2.00000000,
            'EX_glc': -1.00000000,
            'EX_nad': -2.00000000,
            'EX_adp': -2.00000000,
            'EX_phosphate':-2.00000000,
            'EX_pyruvate': 2.00000000,
            'EX_nadh': 2.00000000,
            'EX_atp': 2.00000000,
            'EX_h2o': 2.00000000,
            'EX_h+': 2.00000000
    }

    EDpath = Pathway(id='ED', name='ED', reaction_ids=list(ED.keys()), fluxes=list(ED.values()))
    EDpath.rearrange_reaction_order()
    res = []
    for cpath in all_pathways:
        if EDpath.is_same_pathway_with(cpath):
            print(cpath)
        res.append(EDpath.get_pathway_similarity_index(cpath))