<jupyter_start><jupyter_text>Manual Curation of Model Aliases<jupyter_code>import biosapi
import json
from biosapi import BIOS
from biosapi.bios_model_alias_mapper import BiosModelAliasMapper
from biosapi.bios_model_reaction import BiosModelReaction
import cobrakbase
#%run ../biosapi/api.py
modelseed_local = cobrakbase.modelseed.from_local('../../../ModelSEEDDatabase')
bios = BIOS()
MODEL_CPD_MAPPING = None
with open('/Users/fliu/workspace/jupyter/python3/annotation-server/data/cpd_mapping_cache4.json', 'r') as f:
    MODEL_CPD_MAPPING = json.loads(f.read())
MODEL_RXN_MAPPING = None
with open('/Users/fliu/workspace/jupyter/python3/annotation-server/data/rxn_mapping_cache4.json', 'r') as f:
    MODEL_RXN_MAPPING = json.loads(f.read())
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__MIT']['M_PYRUVATE__91__CCO__45__MIT__93__']
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__CYTOSOL']['M_WATER'] = ['cpd00001']
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__CYTOSOL']['M_OH'] = ['cpd15275']
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__CYTOSOL']['M_AMMONIUM'] = ['cpd00013']
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__CYTOSOL']['M_AMMONIA'] = []
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__MIT']['M_AMMONIUM__91__CCO__45__MIT__93__'] = ['cpd00013']
MODEL_CPD_MAPPING['iJDZ836']['CCO__45__MIT']['M_AMMONIA__91__CCO__45__MIT__93__'] = []
MODEL_CPD_MAPPING['iAL1006']['C_c']['M_G6P'] = ['cpd19006']
with open('/Users/fliu/workspace/jupyter/python3/annotation-server/data/cpd_mapping_cache4.json', 'w') as f:
    f.write(json.dumps(MODEL_CPD_MAPPING))
MODEL_RXN_MAPPING['iJDZ836']['TRANS__45__RXN2T__45__215__45__L2R__91__CCO__45__MIT__93__']
model_id = 'iJDZ836'
for cmp in MODEL_CPD_MAPPING[model_id]:
    for spi_id in MODEL_CPD_MAPPING[model_id][cmp]:
        if spi_id in cpd_mapping:
            for db_id in cpd_mapping[spi_id]:
                if not db_id in MODEL_CPD_MAPPING[model_id][cmp][spi_id]:
                    MODEL_CPD_MAPPING[model_id][cmp][spi_id].append(db_id)

import pandas as pd
target_model_id = 'iJDZ836'
df_manual_cpd = pd.read_csv('/Users/fliu/workspace/jupyter/data/fungi/cpd_mapping_curated.tsv', sep='\t');
for row_id, d in df_manual_cpd.iterrows():
    model_id = d['model_id']
    if model_id == target_model_id:
        for cpd_id in d.keys():
            if not cpd_id == 'model_id':
                if not pd.isna(d[cpd_id]):
                    seed_cpd = modelseed_local.get_seed_compound(cpd_id)
                    uid = mapper.sid_to_spi_id[d[cpd_id]]
                    resp = bios.set_annotation_model_species(target_model_id, uid, 'ModelSeed', cpd_id, 'fliu', 4)
                    #print(model_id, uid, d[cpd_id], cpd_id, sid_to_spi[d[cpd_id]]['name'], seed_cpd.name)
model_id = 'iJDZ836'
mapper = BiosModelAliasMapper(bios)
mapper.load_model(model_id)
sid_to_spi = {}
for o in mapper.model_species:
    sid_to_spi[o['id']] = o
cpd_mapping = mapper.get_cpd_mapping('ModelSeed', 1)
for k in cpd_mapping:
    if len(cpd_mapping[k]) > 0:
        print(k, cpd_mapping[k])
    break
bigg_to_seed = {}
for seed_id in modelseed_local.compound_aliases:
    if 'BiGG' in modelseed_local.compound_aliases[seed_id]:
        for i in modelseed_local.compound_aliases[seed_id]['BiGG']:
            bigg_to_seed[i] = seed_id
meta_to_seed = {}
for seed_id in modelseed_local.compound_aliases:
    if 'MetaCyc' in modelseed_local.compound_aliases[seed_id]:
        for i in modelseed_local.compound_aliases[seed_id]['MetaCyc']:
            meta_to_seed[i] = seed_id
meta_to_seed['SORBITOL']
ban = set(['OH', 'AMMONIA', 'AMMONIUM'])
for k in cpd_mapping:
    search_str = k.split('__91__CCO__45__EXTRACELLULAR__93__')[0]
    search_str = search_str.split('__91__CCO__45__VAC__45__LUM__93__')[0]
    search_str = search_str.split('__91__CCO__45__GLYOXYSOME__93__')[0]
    search_str = search_str.split('__91__CCO__45__MIT__93__')[0]
    search_str = search_str[2:]
    search_str = search_str.replace('__45__', '-')
    search_str = search_str.replace('__43__', '+')
    if not search_str in ban and search_str in meta_to_seed:
        if not meta_to_seed[search_str] in cpd_mapping[k]:
            print(search_str, cpd_mapping[k], meta_to_seed[search_str])
spi_uid = str(sid_to_id['M_nh4_c'])
for uid in model_species_annotation[spi_uid]['annotation']:
    annotation = model_species_annotation[spi_uid]['annotation'][uid]
    if annotation['database'] == 'ModelSeed':

        print(annotation, score, max_score)
for spi_uid in model_species_annotation:
    spi_uid
spi_uid
from cobrakbase.modelseed.stoich_integration import multi_hasher, CStoichiometryHashLibrary
from cobrakbase.modelseed.stoich_integration import StoichiometryHashLibrary, single_hasher
hfunc = lambda x : single_hasher(x, ['cpd00067_c0', 'cpd00067_e0'])
hlib = StoichiometryHashLibrary(hfunc)
hlib = StoichiometryHashLibrary(hfunc)
for o in model_reactions:
    model_reaction = BiosModelReaction(o)
    stoichiometry = model_reaction.get_stoichiometry()
    hlib.hash_stoichiometry(model_reaction.id, stoichiometry)
def is_standard_match(mresult):
    for o in mresult:
        if o[0] == 'std' and o[0] == 'std':
            return True
        #print(o)
    return False

def is_reverse_match(mresult):
    for o in mresult:
        if o[0] == 'std' and o[0] == 'rev':
            return True
        if o[0] == 'rev' and o[0] == 'std':
            return True
        #print(o)
    return False

def is_exclude_match(mresult):
    for o in mresult:
        if o[0] == 'no_h_std' or o[0] == 'no_h_std':
            return True
        if o[0] == 'no_h_rev' or o[0] == 'no_h_rev':
            return True
    return False


exclude = set(['ATPM', 'BIOMASS_Ecoli'])
for rxn in model.reactions:
     if rxn.id.startswith('EX_'):
        exclude.add(rxn.id)
mapping_rxn = {}
for model_rxn in model.reactions:
    stoichiometry = dict(map(lambda p : (ooo[p[0].id] + '_' + p[0].compartment + '0', p[1]), model_rxn.metabolites.items()))
    m = hlib.match(stoichiometry)
    if not len(m) == 0:
        for match_id in m:
            if is_standard_match(m[match_id]):
                mapping_rxn[model_rxn.id] = (match_id, 'standard')
            elif is_reverse_match(m[match_id]):
                mapping_rxn[model_rxn.id] = (match_id, 'reverse')
            elif len(model_rxn.compartments) == 1 and is_exclude_match(m[match_id]):
                mapping_rxn[model_rxn.id] = (match_id, 'exclude')
            else:
                print('!!', model_rxn)
                #print(model_rxn.id, match_id)
    else:
        #print('xx', model_rxn)
        pass
compartment_config = cobrakbase.core.utils.get_compartment_config(r.data, modelseed.get_seed_reaction(seed_id))
model_reaction = BiosModelReaction(list(filter(lambda x : x['id'] == 'R_PYRt2m', model_reactions))[0])
s = model_reaction.get_stoichiometry()
cs = {}
for k in s:
    cs[(sid_to_spi[k]['id'], sid_to_spi[k]['compartment'])] = s[k]
cs
#replace with seed_ids
sid_to_spi = {}
for o in model_species:
    sid_to_spi[o['id']] = o
rxn05469
import copy
from itertools import permutations
def get_permutations(n):
    perm = permutations(range(n), n) 
    return list(perm)

class StoichiometryHashLibrary:
    
    def __init__(self):
        self.hash_functions = {}
        self.all_hashes = {}
        self.rxn_to_hash = {}
        
    def hash_stoichiometry(self, rxn_id, stoich):
        self.rxn_to_hash[rxn_id] = {}
        for fn_hash_id in self.hash_functions:
            fn_hash = self.hash_functions[fn_hash_id]
            hash_val = fn_hash(stoich)
            self.rxn_to_hash[rxn_id][fn_hash_id] = hash_val
            if not fn_hash_id in self.all_hashes:
                self.all_hashes[fn_hash_id] = {}
            if not hash_val in self.all_hashes[fn_hash_id]:
                self.all_hashes[fn_hash_id][hash_val] = set()
            self.all_hashes[fn_hash_id][hash_val].add(rxn_id)
            
    def match(self, stoichiometry):
        match = {}
        s_hash = self.func_hash(stoichiometry)
        for hash_type in s_hash:
            hash_val = s_hash[hash_type]
            for hash_type_lib in self.all_hashes:
                if hash_val in self.all_hashes[hash_type_lib]:
                    for rxn_id_match in self.all_hashes[hash_type_lib][hash_val]:
                        if not rxn_id_match in match:
                            match[rxn_id_match] = set()
                        match[rxn_id_match].add((hash_type, hash_type_lib, hash_val))
        return match
    
class CStoichiometryHashLibrary(StoichiometryHashLibrary):
    
    def match(self, cstoichiometry):
        match = {}
        cmps = list(set(map(lambda x : x[1], cstoichiometry)))
        index_tests = get_permutations(len(cmps))
        
        for t in index_tests:
            replace = {}
            for i in range(len(cmps)):
                replace[cmps[i]] = str(t[i])
                
            tstoichiometry = copy.deepcopy(cstoichiometry)
            tstoichiometry = dict(map(lambda x : ((x[0][0], replace[x[0][1]]), x[1]), tstoichiometry.items()))
            
            
            for fn_hash_id in self.hash_functions:
                fn_hash = self.hash_functions[fn_hash_id]
                hash_val = fn_hash(tstoichiometry)
                #print(fn_hash_id, hash_val)
                for lib_fn_hash_id in self.all_hashes:
                    if hash_val in self.all_hashes[lib_fn_hash_id]:
                        for rxn_id_match in self.all_hashes[lib_fn_hash_id][hash_val]:
                            if not rxn_id_match in match:
                                match[rxn_id_match] = set()
                            replace_str = ';'.join(map(lambda x : "{}:{}".format(x[0], x[1]), replace.items()))
                            match[rxn_id_match].add((fn_hash_id, lib_fn_hash_id, hash_val, replace_str))
                            #print(rxn_id_match, fn_hash_id, lib_fn_hash_id, hash_val, t)
                
            
            #s_hash = self.func_hash(tstoichiometry)
            
            
            #for hash_type in s_hash:
            #    hash_val = s_hash[hash_type]
            #    for hash_type_lib in self.all_hashes:
            #        if hash_val in self.all_hashes[hash_type_lib]:
            #            for rxn_id_match in self.all_hashes[hash_type_lib][hash_val]:
            #                if not rxn_id_match in match:
            #                    match[rxn_id_match] = set()
            #                replace_str = ';'.join(map(lambda x : "{}:{}".format(x[0], x[1]), replace.items()))
            #                match[rxn_id_match].add((hash_type, hash_type_lib, hash_val, replace_str))
                
        return match
    
fn_rev_stoich = lambda cs : dict(map(lambda x : (x[0], -1 * x[1]), cs.items()))

hlib = CStoichiometryHashLibrary()
hlib.hash_functions = {
    'std' : lambda x : hash(frozenset(x.items())),
    'rev' : lambda x : hash(frozenset(fn_rev_stoich(x).items())),
}
rxn = modelseed_local.get_seed_reaction('rxn05469')
hlib.hash_stoichiometry(rxn.id, rxn.cstoichiometry)
hlib.match({('cpd00020', 'c'): -1.0,
 ('cpd00067', 'c'): -1.0,
 ('cpd00020', 'm'): 1.0,
 ('cpd00067', 'm'): 1.0})
fn_rev_stoich = lambda cs : dict(map(lambda x : (x[0], -1 * x[1]), cs.items()))

hlib = CStoichiometryHashLibrary()
hlib.hash_functions = {
    'std' : lambda x : hash(frozenset(x.items())),
    'rev' : lambda x : hash(frozenset(fn_rev_stoich(x).items())),
}
for rxn_id in modelseed_local.reactions:
    rxn = modelseed_local.get_seed_reaction(rxn_id)
    if not rxn.is_obsolete:
        hlib.hash_stoichiometry(rxn.id, rxn.cstoichiometry)
ooo = {}
for k in cpd_mapping:
    if len(cpd_mapping[k]) > 0:
        ooo[k] = list(cpd_mapping[k])[0]
from biosapi.bios_model_reaction import BiosModelReaction
exclude = set(['R_ATPM'])
for o in mapper.model_reactions:
    model_reaction = BiosModelReaction(o)
    if model_reaction.id.startswith('R_EX_'):
        exclude.add(model_reaction.id)
o = list(filter(lambda x : x['id'] == 'R_HKYNH', mapper.model_reactions))[0]
model_reaction = BiosModelReaction(o)
stoichiometry = mapper.model_reaction.get_stoichiometry()
cs = {}
for k in stoichiometry:
    cmp = sid_to_spi[k]['compartment']
    spi_id = sid_to_spi[k]['id']
    if spi_id in ooo:
        spi_id = ooo[spi_id]
    cs[(spi_id, cmp)] = stoichiometry[k]
cs
for o in model_species:
    if not o['id'] in ooo:
        ooo[o['id']] = bigg_to_seed[o['id'][:-2][2:]]
ooo['M_thymd_c'] = 'cpd00184'
#R_CHTNDA
predicted_rxn_mapping = {}
for o in mapper.model_reactions:
    model_reaction = BiosModelReaction(o)
    if not model_reaction.id in exclude:
        stoichiometry = model_reaction.get_stoichiometry()
        cs = {}
        for k in stoichiometry:
            cmp = sid_to_spi[k]['compartment']
            spi_id = sid_to_spi[k]['id']
            if spi_id in ooo:
                spi_id = ooo[spi_id]
            cs[(spi_id, cmp)] = stoichiometry[k]
        m = hlib.match(cs)
        if len(m) == 1:
            
            predicted_rxn_mapping[model_reaction.id] = list(m.keys())[0]
        elif len(m) > 1:
            print('*', model_reaction.id, list(m.keys()))
        else:
            print('X', model_reaction.id)
target_model_id = 'iJDZ836'
rxn_mapping = mapper.get_rxn_mapping('ModelSeedReaction')
for rxn_id in rxn_mapping:
    if rxn_id in predicted_rxn_mapping:
        seed_id = predicted_rxn_mapping[rxn_id]
        seed_rxn = modelseed_local.get_seed_reaction(seed_id)
        #print(seed_rxn.data['definition'])
        if len(rxn_mapping[rxn_id]) == 0:
            resp = bios.set_annotation_model_reaction(target_model_id, mapper.sid_to_rxn_id[rxn_id], 'ModelSeedReaction', predicted_rxn_mapping[rxn_id], 'auto', 3)
            pass
        elif len(rxn_mapping[rxn_id]) == 1:
            matche_prev = list(rxn_mapping[rxn_id])[0] == predicted_rxn_mapping[rxn_id]
            if matche_prev:
                #print('PREV:', matche_prev, rxn_id, rxn_mapping[rxn_id], predicted_rxn_mapping[rxn_id])
                pass
            else:
                resp = bios.set_annotation_model_reaction(target_model_id, mapper.sid_to_rxn_id[rxn_id], 'ModelSeedReaction', predicted_rxn_mapping[rxn_id], 'auto', 3)
                print('PREV:', matche_prev, rxn_id, rxn_mapping[rxn_id], predicted_rxn_mapping[rxn_id])
        else:
            print('OPT :', rxn_id, rxn_mapping[rxn_id], predicted_rxn_mapping[rxn_id])


resp = set_annotation_model_reaction(bios, 'iMM904', 3154009, 'ModelSeedReaction', 'rxn00256', 'fliu', 5)
resp.content
resp = set_annotation_model_species(bios, 'iMM904', 3153113, 'BiGGMetabolite', 'oaa', 'fliu', 5)
manual_mapping = {
    'cpd00013' : ['M_nh4_c', 'M_nh4_e', 'M_nh4_m', 'M_nh4_n', 'M_nh4_x'],
}

for k in ['M_nh4_c', 'M_nh4_e', 'M_nh4_m', 'M_nh4_n', 'M_nh4_x']:
    #print(k, sid_to_id[k])
    resp = set_annotation_model_species(bios, 'iMM904', sid_to_id[k], 'BiGGMetabolite', 'nh4', 'fliu', 5)
    resp = set_annotation_model_species(bios, 'iMM904', sid_to_id[k], 'ModelSeed', 'cpd00013', 'fliu', 5)
d.keys()
for k in id_sid:
    if id_sid[k] == 'R_CSm':
        print(k)
Databases.BIGG1_REACTION.value<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12695790099795123, 'fraction_numerical': 0.021082545766968476, 'mean_word_length': 3.1628610729023383, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '177791', 'license': 'MIT', 'n_tokens_mistral': 5991, 'n_tokens_neox': 5670, 'n_words': 943, 'path': 'examples/model_annotation.ipynb', 'repo_name': 'Fxe/biosapi', 'size': '15131'}