예제 #1
0
 def test_touch(self):
     Cache.clean()
     self.assertDictEqual(Cache.get_objects(), {})
     Cache.touch(self.__d, 'd')
     self.assertDictEqual(Cache.get('d'), self.__d)
     Cache.touch(None, 'd')
     self.assertDictEqual(Cache.get('d'), self.__d)
     Cache.touch({}, 'd')
     self.assertDictEqual(Cache.get('d'), self.__d)
예제 #2
0
def __build_all_pathways(
    pathways: Dict,
    transfos: Dict,
    sink_molecules: List,
    rr_reactions: Dict,
    compounds_cache: Dict,
    max_subpaths_filter: int,
    lower_flux_bound: float,
    upper_flux_bound: float,
    logger: Logger = getLogger(__name__)
) -> Dict:
    """Builds pathways based on all combinations over
    reaction rules and template reactions (see
    `build_pathway_combinatorics` documentation).

    Parameters
    ----------
    pathways: Dict
        Metabolic pathways as list of chemical
        reactions where each reaction is defined by:
            - transformation ID,
            - reaction rule ID, and
            - template reaction ID
    transfos: Dict
        Full chemical transformations
    sink_molecules: List
        Sink chemical species IDs
    rr_reactions: Dict
        Reaction rules cache
    compounds_cache: Dict
        Compounds cache
    max_subpaths_filter: int
        Number of pathways (best) kept per master pathway
    lower_flux_bound: float
        Lower flux bound for all new reactions created
    upper_flux_bound: float
        Upper flux bound for all new reactions created
    logger: Logger, optional

    Returns
    -------
    Set of ranked rpPathway objects
    """

    res_pathways = {}

    nb_pathways = 0
    nb_unique_pathways = 0

    ## PATHWAYS
    for path_idx, transfos_lst in pathways.items():

        # Combine over multiple template reactions
        sub_pathways = list(itertools_product(*transfos_lst))

        ## SUB-PATHWAYS
        # # Keep only topX best sub_pathways
        # # within a same master pathway
        res_pathways[path_idx] = []
        for sub_path_idx in range(len(sub_pathways)):

            pathway = rpPathway(
                id=str(path_idx).zfill(3)+'_'+str(sub_path_idx+1).zfill(4),
                logger=logger
            )
            logger.debug(pathway.get_id())

            ## ITERATE OVER REACTIONS
            nb_reactions = len(sub_pathways[sub_path_idx])
            for rxn_idx in range(nb_reactions):

                rxn = sub_pathways[sub_path_idx][rxn_idx]
                transfo_id = rxn['rp2_transfo_id']
                transfo = transfos[transfo_id]
                rule_ids = rxn['rule_ids']
                tmpl_rxn_id = rxn['tmpl_rxn_ids']

                ## COMPOUNDS
                # Template reaction compounds
                added_cmpds = transfo['complement'][rule_ids][tmpl_rxn_id]['added_cmpds']
                # Add missing compounds to the cache
                for side in added_cmpds.keys():
                    for spe_id in added_cmpds[side].keys():
                        logger.debug(f'Add missing compound {spe_id}')
                        if spe_id not in Cache.get_objects():
                            try:
                                rpCompound(
                                    id=spe_id,
                                    smiles=compounds_cache[spe_id]['smiles'],
                                    inchi=compounds_cache[spe_id]['inchi'],
                                    inchikey=compounds_cache[spe_id]['inchikey'],
                                    formula=compounds_cache[spe_id]['formula'],
                                    name=compounds_cache[spe_id]['name']
                                )
                            except KeyError:
                                rpCompound(
                                    id=spe_id
                                )

                ## REACTION
                # Compounds from original transformation
                core_species = {
                    'right': deepcopy(transfo['right']),
                    'left': deepcopy(transfo['left'])
                }
                compounds = __add_compounds(core_species, added_cmpds)
                # revert reaction index (forward)
                rxn_idx_forward = nb_reactions - rxn_idx
                rxn = rpReaction(
                    id='rxn_'+str(rxn_idx_forward),
                    ec_numbers=transfo['ec'],
                    reactants=dict(compounds['left']),
                    products=dict(compounds['right']),
                    lower_flux_bound=lower_flux_bound,
                    upper_flux_bound=upper_flux_bound
                )
                # write infos
                for info_id, info in sub_pathways[sub_path_idx][rxn_idx].items():
                    getattr(rxn, 'set_'+info_id)(info)
                rxn.set_rule_score(rr_reactions[rule_ids][tmpl_rxn_id]['rule_score'])
                rxn.set_idx_in_path(rxn_idx_forward)

                # Add at the beginning of the pathway
                # to have the pathway in forward direction
                # Search for the target in the current reaction
                target_id = [spe_id for spe_id in rxn.get_products_ids() if 'TARGET' in spe_id]
                if target_id != []:
                    target_id = target_id[0]
                else:
                    target_id = None
                logger.debug(f'rxn: {rxn._to_dict()}')
                pathway.add_reaction(
                    rxn=rxn,
                    target_id=target_id
                )

                ## TRUNK SPECIES
                pathway.add_species_group(
                    'trunk',
                    [
                        spe_id
                        for value
                        in core_species.values()
                        for spe_id in value.keys()
                    ]
                )

                ## COMPLETED SPECIES
                pathway.add_species_group(
                    'completed',
                    [
                        spe_id
                        for value
                        in added_cmpds.values()
                        for spe_id in value.keys()
                    ]
                )

            ## SINK
            pathway.set_sink_species(
                list(
                    set(pathway.get_species_ids()) & set(sink_molecules)
                )
            )

            nb_pathways += 1

            ## RANK AMONG ALL SUB-PATHWAYS OF THE CURRENT MASTER PATHWAY
            res_pathways[path_idx] = __keep_unique_pathways(
                res_pathways[path_idx],
                pathway,
                logger
            )

        nb_unique_pathways += len(res_pathways[path_idx])

    # Flatten lists of pathways
    pathways = sum(
        [
            pathways
            for pathways in res_pathways.values()
        ], [])

    # Globally sort pathways
    pathways = sorted(pathways)[-max_subpaths_filter:]

    logger.info(f'Pathways statistics')
    logger.info(f'-------------------')
    logger.info(f'   pathways: {nb_pathways}')
    logger.info(f'   unique pathways: {nb_unique_pathways}')
    logger.info(f'   selected pathways: {len(pathways)} (topX filter = {max_subpaths_filter})')

    # Return topX pathway objects
    return [
        pathway.object
        for pathway in pathways
    ]

    # Transform the list of Item into a list of Pathway
    results = {}
    nb_sel_pathways = 0
    for res_pathway_idx, res_pathway in res_pathways.items():
        results[res_pathway_idx] = [pathway.object for pathway in res_pathway]
        nb_sel_pathways += len(results[res_pathway_idx])

    logger.info(f'Pathways selected: {nb_sel_pathways}/{nb_pathways}')

    return results
예제 #3
0
 def test_get_objects(self):
     Cache.clean()
     Cache.add(self.__d, 'd')
     self.assertDictEqual(Cache.get_objects(), {'d': self.__d})