Example #1
0
def dpam2dpam_strands(dpam,pams):
    """
    Duplicates dpam dataframe to be compatible for searching PAMs on - strand

    :param dpam: dataframe with pam information
    :param pams: pams to be used for actual designing of guides.
    """
    
    dpam=del_Unnamed(dpam)
    dpam['rPAM']=dpam.apply(lambda x : s2re(x['PAM'],multint2reg) ,axis=1)
    dpam=set_index(dpam,'PAM')
    dpam['strand']='+'
    dpamr=pd.DataFrame(columns=dpam.columns)
    dpam.loc[:,'reverse complement']=np.nan
    dpam.loc[:,'original']=np.nan
    for pam in dpam.index:
        pamr=reverse_complement_multintseq(pam,nt2complement)
        dpam.loc[pam,'reverse complement']=pamr
        dpam.loc[pam,'original']=pam
        dpamr.loc[pamr,'original']=pam
        dpam.loc[pam,'original position']=dpam.loc[pam,'position']
        dpamr.loc[pamr,'original position']=dpam.loc[pam,'position']
        dpamr.loc[pamr,['position','guide length','Description']]=dpam.loc[pam,['position','guide length','Description']]
        dpamr.loc[pamr,['rPAM']]=reverse_complement_multintseqreg(pam,multint2regcomplement,nt2complement)    
    dpamr['position']= dpamr.apply(lambda x: 'up' if x['position']=='down' else 'down',axis=1)
    dpamr['strand']='-'
    dpam_strands=dpam.append(dpamr,sort=True)
    dpam_strands.index.name='PAM'
    dpam_strands.loc[:,'is a reverse complement']=pd.isnull(dpam_strands.loc[:,'reverse complement'])
    pams_strands=pams+dpam_strands.loc[pams,'reverse complement'].dropna().tolist()
    dpam_strands=dpam_strands.loc[pams_strands,:]
    return dpam_strands
Example #2
0
def get_possible_mutagenesis(
    dcodontable,
    dcodonusage,
    BEs,
    pos_muts,
    host,
):
    """
    Assesses possible mutagenesis strategies, given the set of Base editors and positions of mutations.

    :param dcodontable: Codon table
    :param dcodonusage: Codon usage table
    :param BEs: Base editors (dict), see global_vars.py
    :param pos_muts: positions of mutations
    :param host: host organism
    :returns: possible mutagenesis strategies as a pandas dataframe
    """
    def write_dmutagenesis(cdni, posi, codon, codonmut, ntwt, ntmut, aa, aamut,
                           method):
        """
        Write dmutagenesis table for each iteraction in get_possible_mutagenesis.
        """
        dmutagenesis.loc[cdni, 'codon'] = codon
        dmutagenesis.loc[cdni, 'position of mutation in codon'] = int(posi)
        dmutagenesis.loc[cdni, 'codon mutation'] = codonmut
        dmutagenesis.loc[cdni, 'nucleotide'] = ntwt
        dmutagenesis.loc[cdni, 'nucleotide mutation'] = ntmut
        dmutagenesis.loc[cdni, 'amino acid'] = aa
        dmutagenesis.loc[cdni, 'amino acid mutation'] = aamut
        dmutagenesis.loc[cdni, 'mutation on strand'] = method.split(' on ')[1]
        dmutagenesis.loc[cdni,
                         'strand: mutation'] = method.split(' on ')[1].replace(
                             ' strand', '')
        dmutagenesis.loc[cdni, 'method'] = method.split(' on ')[0]
        dmutagenesis.loc[cdni,
                         'codon mutation usage Fraction'] = dcodonusage.loc[
                             codonmut, 'Fraction']
        dmutagenesis.loc[cdni,
                         'codon mutation usage Frequency'] = dcodonusage.loc[
                             codonmut, 'Frequency']
        return dmutagenesis

    def get_sm(dmutagenesis, BEs, positions, codon, muti, cdni):
        """
        Fetches single nucleotide mutagenesis strategies.
        """
        for method in BEs:
            for posi in positions:
                if BEs[method][0] == codon[posi]:
                    for ntmut in BEs[method][1]:
                        if posi == 0:
                            codonmut = '{}{}{}'.format(ntmut, codon[1],
                                                       codon[2])
                        elif posi == 1:
                            codonmut = '{}{}{}'.format(codon[0], ntmut,
                                                       codon[2])
                        elif posi == 2:
                            codonmut = '{}{}{}'.format(codon[0], codon[1],
                                                       ntmut)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = BEs[method][0]
                        if '-' in method.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis = write_dmutagenesis(
                            **{
                                'cdni': cdni,
                                'posi': posi + 1,
                                'codon': codon,
                                'codonmut': codonmut,
                                'ntwt': ntwt,
                                'ntmut': ntmut,
                                'aa': aa,
                                'aamut': aamut,
                                'method': method
                            })
        return dmutagenesis, muti

    def get_dm(dmutagenesis, BEs, positions_dm, codon, muti, cdni):
        """
        Fetches double nucleotide mutagenesis strategies.
        """
        for method in BEs:
            for posi1, posi2 in positions_dm:
                if (BEs[method][0] == codon[posi1]) and (BEs[method][0]
                                                         == codon[posi2]):
                    for ntmut1, ntmut2 in itertools.product(''.join(
                            BEs[method][1]),
                                                            repeat=2):
                        if (posi1 == 0) and (posi2 == 1):
                            codonmut = '{}{}{}'.format(ntmut1, ntmut2,
                                                       codon[2])
                        elif (posi1 == 1) and (posi2 == 2):
                            codonmut = '{}{}{}'.format(codon[0], ntmut1,
                                                       ntmut2)
                        elif (posi1 == 0) and (posi2 == 2):
                            codonmut = '{}{}{}'.format(ntmut1, codon[1],
                                                       ntmut2)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = '{}{}'.format(BEs[method][0], BEs[method][0])
                        ntmut = '{}{}'.format(ntmut1, ntmut2)
                        if '-' in method.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis = write_dmutagenesis(
                            **{
                                'cdni': cdni,
                                'posi': '{}{}'.format(posi1, posi2),
                                'codon': codon,
                                'codonmut': codonmut,
                                'ntwt': ntwt,
                                'ntmut': ntmut,
                                'aa': aa,
                                'aamut': aamut,
                                'method': method
                            })
        return dmutagenesis, muti

    def get_tm(dmutagenesis, BEs, positions_tm, codon, muti, cdni):
        """
        Fetches triple nucleotide mutagenesis strategies.
        """
        for method in BEs:
            for posi1, posi2, posi3 in positions_tm:
                if (BEs[method][0] == codon[posi1]) and (
                        BEs[method][0] == codon[posi2]) and (BEs[method][0]
                                                             == codon[posi3]):
                    for ntmut1, ntmut2, ntmut3 in itertools.product(''.join(
                            BEs[method][1]),
                                                                    repeat=3):
                        codonmut = '{}{}{}'.format(ntmut1, ntmut2, ntmut3)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = '{}{}{}'.format(BEs[method][0], BEs[method][0],
                                               BEs[method][0])
                        ntmut = '{}{}{}'.format(ntmut1, ntmut2, ntmut3)
                        if '-' in method.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis = write_dmutagenesis(
                            **{
                                'cdni': cdni,
                                'posi': '123',
                                'codon': codon,
                                'codonmut': codonmut,
                                'ntwt': ntwt,
                                'ntmut': ntmut,
                                'aa': aa,
                                'aamut': aamut,
                                'method': method
                            })
        return dmutagenesis, muti

    def get_dm_combo(dmutagenesis, BEs, positions_dm, codon, muti, cdni,
                     method):
        """
        Fetches double nucleotide mutagenesis strategies utilising 2 different base editors simultaneously.
        """
        methods = [
            m for m in itertools.product(BEs.keys(), repeat=2) if ((
                m[0].split('on')[1] == m[1].split('on')[1])) and (m[0] != m[1])
        ]
        for method1, method2 in methods:
            for posi1, posi2 in positions_dm:
                if (BEs[method1][0] == codon[posi1]) and (BEs[method2][0]
                                                          == codon[posi2]):
                    ntmuts = [(n1, n2) for n1 in ''.join(BEs[method1][1])
                              for n2 in ''.join(BEs[method2][1])]
                    for ntmut1, ntmut2 in ntmuts:
                        if (posi1 == 0) and (posi2 == 1):
                            codonmut = '{}{}{}'.format(ntmut1, ntmut2,
                                                       codon[2])
                        elif (posi1 == 1) and (posi2 == 2):
                            codonmut = '{}{}{}'.format(codon[0], ntmut1,
                                                       ntmut2)
                        elif (posi1 == 0) and (posi2 == 2):
                            codonmut = '{}{}{}'.format(ntmut1, codon[1],
                                                       ntmut2)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = '{}{}'.format(BEs[method1][0], BEs[method2][0])
                        ntmut = '{}{}'.format(ntmut1, ntmut2)
                        if '-' in method1.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis = write_dmutagenesis(
                            **{
                                'cdni': cdni,
                                'posi': '{}{}'.format(posi1, posi2),
                                'codon': codon,
                                'codonmut': codonmut,
                                'ntwt': ntwt,
                                'ntmut': ntmut,
                                'aa': aa,
                                'aamut': aamut,
                                'method': method + ' on ' +
                                method1.split('on')[1]
                            })
        return dmutagenesis, muti

    def get_tm_combo(dmutagenesis, BEs, positions_tm, codon, muti, cdni,
                     method):
        """
        Fetches triple nucleotide mutagenesis strategies utilising 2 different base editors simultaneously.
        """
        methods = [
            m for m in itertools.product(BEs.keys(), repeat=3)
            if ((m[0].split('on')[1] == m[1].split('on')[1] == m[2].split('on')
                 [1])) and not (m[0] == m[1] == m[2])
        ]
        for method1, method2, method3 in methods:
            for posi1, posi2, posi3 in positions_tm:
                if (BEs[method1][0] == codon[posi1]) and (
                        BEs[method2][0] == codon[posi2]) and (BEs[method3][0]
                                                              == codon[posi3]):
                    ntmuts = [(n1, n2, n3) for n1 in ''.join(BEs[method1][1])
                              for n2 in ''.join(BEs[method2][1])
                              for n3 in ''.join(BEs[method3][1])]
                    for ntmut1, ntmut2, ntmut3 in ntmuts:
                        codonmut = '{}{}{}'.format(ntmut1, ntmut2, ntmut3)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = '{}{}{}'.format(BEs[method1][0],
                                               BEs[method2][0],
                                               BEs[method3][0])
                        ntmut = '{}{}{}'.format(ntmut1, ntmut2, ntmut3)
                        if '-' in method1.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis = write_dmutagenesis(
                            **{
                                'cdni': cdni,
                                'posi': '123',
                                'codon': codon,
                                'codonmut': codonmut,
                                'ntwt': ntwt,
                                'ntmut': ntmut,
                                'aa': aa,
                                'aamut': aamut,
                                'method': method + ' on ' +
                                method1.split('on')[1]
                            })
        return dmutagenesis, muti

    #double nucleotide mutations
    positions = {0: '@1st position', 1: '@2nd position', 2: '@3rd position'}
    #double nucleotide mutations
    positions_dm = [(i, j) for i in positions.keys() for j in positions.keys()
                    if i < j]
    #double nucleotide mutations
    positions_tm = [[0, 1, 2]]

    dmutagenesis = dcodontable.copy()
    # test=True
    test = False
    for cdni in dmutagenesis.index:
        codon = dmutagenesis.loc[cdni, 'codon']
        aa = dmutagenesis.loc[cdni, 'amino acid']
        muti = 0
        if test:
            print(codon)
        #single nucleuotide mutations
        dmutagenesis, muti = get_sm(dmutagenesis, BEs, positions, codon, muti,
                                    cdni)
        #double nucleotide mutations
        dmutagenesis, muti = get_dm(dmutagenesis, BEs, positions_dm, codon,
                                    muti, cdni)
        #triple nucleotide mutations
        dmutagenesis, muti = get_tm(dmutagenesis, BEs, positions_tm, codon,
                                    muti, cdni)
        # #double nucleotide mutations combinations
        # dmutagenesis,muti=get_dm_combo(dmutagenesis,BEs,positions_dm,codon,muti,cdni,method='undefined')
        # #triple nucleotide mutations combinations
        # dmutagenesis,muti=get_tm_combo(dmutagenesis,BEs,positions_tm,codon,muti,cdni,method='undefined')

    dmutagenesis['nucleotide mutation: count'] = [
        len(s) for s in dmutagenesis['nucleotide mutation']
    ]
    dmutagenesis = dmutagenesis.sort_values('codon')
    # Adding information of Allowed activity window
    dmutagenesis = dmutagenesis.set_index('method').join(pos_muts)
    dmutagenesis = dmutagenesis.reset_index()

    from beditor.lib.io_seqs import reverse_complement_multintseq
    from beditor.lib.global_vars import nt2complement
    dmutagenesis['nucleotide: wild-type'] = dmutagenesis.apply(
        lambda x: x['nucleotide']
        if x['strand: mutation'] == '+' else reverse_complement_multintseq(
            x['nucleotide'], nt2complement),
        axis=1)
    dmutagenesis['nucleotide: mutation'] = dmutagenesis.apply(
        lambda x: x['nucleotide mutation']
        if x['strand: mutation'] == '+' else reverse_complement_multintseq(
            x['nucleotide mutation'], nt2complement),
        axis=1)

    return dmutagenesis
Example #3
0
def make_guides(cfg,dseq,dmutagenesis,dpam,
               test=False,
               dbug=False):
    """
    Wrapper around submodules that design guides by
    1. searching all PAM sequences on 'both' the strands,
    2. filtering guides by all possible strategies (given in dmutagenesis) e.g. activity window,
    Finally generates a table.

    :param cfg: configuration dict
    :param dseq: dsequences dataframe
    :param dmutagenesis: dmutagenesis dataframe
    :param dpam: dpam dataframe
    :param test: debug mode on
    :param dbug: more verbose
    """
    from beditor.lib.io_strs import s2re
    flankaas=7#FIXME if flank length changes

    dseq=dseq.reset_index()
    dseq.index=range(len(dseq))
    dpam=set_index(dpam,'PAM')                
#     for gi in trange(len(dseq),desc='designing guides'):
    gierrfltmutpos=[]
    gierrdenan=[]
    gierrfltguidel=[]
    gierrpamnotfound=[]
    gierrcannotmutate=[]
    dseq_cols=['transcript: id','aminoacid: position','aminoacid: wild-type','codon: wild-type','id',]
    for gi in dseq.index:
        if cfg['mutations']=='mutations':
            dseqi=pd.DataFrame(dseq.loc[gi,dseq_cols+['amino acid mutation']]).T
            dmutagenesis_gi=pd.merge(dseqi,
                dmutagenesis,
                how='inner',
                left_on=['aminoacid: wild-type','codon: wild-type','amino acid mutation'],
                right_on=['amino acid','codon','amino acid mutation'])                    
        else:
            dseqi=pd.DataFrame(dseq.loc[gi,dseq_cols]).T
            dmutagenesis_gi=pd.merge(dseqi,
                dmutagenesis,
                how='inner',
                left_on=['aminoacid: wild-type','codon: wild-type'],
                right_on=['amino acid','codon'])        
        if len(dmutagenesis_gi)!=0:
            logging.info(f"working on {dseq.loc[gi,'id']}")
#             codon=dseq.loc[gi,'codon: wild-type']
            pos_codon=(flankaas)*3
            dpamsearches=get_pam_searches(dpam=dpam,
                 seq=dseq.loc[gi,'transcript: sequence'],
                 pos_codon=pos_codon,
                 test=test)
            # print(dpamsearches.columns) #RMME
            if dpamsearches is None:
                continue
            if len(dpamsearches)!=0:
                # filter by guide length
                dpamsearchesflt=dpamsearches.loc[dpamsearches['guide length']==dpamsearches['guide sequence length'],:]
                if len(dpamsearchesflt)!=0:
                    dpamsearches_strategy=pd.merge(dpamsearchesflt.reset_index(),dmutagenesis_gi.reset_index(),
                             how='inner',
                             on=['strand'],suffixes=['',': dmutagenesis_gi'])
                    if len(dpamsearches_strategy)!=0:                                 
                        if not 'dguides' in locals():
                            dguides=dpamsearches_strategy.copy()
                        else:
                            dguides=dguides.append(dpamsearches_strategy)
                        del dpamsearches_strategy
                    else:
                        gierrdenan.append(gi)
                        if dbug:
                            print('empty after removing nan seqs')
                else:
                    gierrfltguidel.append(gi)
                    if dbug:
                        print(f"empty after filtering by guide length. {dpamsearches['guide sequence length'].tolist()}")
            else:
                gierrpamnotfound.append(gi)
                if dbug:
                    print(f"no pam among {dpam.index.tolist()} were found {dseq.loc[gi,'transcript: sequence']}")
        else:
            gierrcannotmutate.append(gi)
            if dbug:
                print(f"can not mutate {dseqi['codon: wild-type'].tolist()}. its not in {dmutagenesis['codon'].tolist()}")

    gierrfltmutpos=[]
    gierrdenan=[]
    gierrfltguidel=[]
    gierrpamnotfound=[]
    gierrcannotmutate=[]

    err2idxs={'gierrfltmutpos':gierrfltmutpos,
              'gierrdenan':gierrdenan,
              'gierrfltguidel':gierrfltguidel,
              'gierrpamnotfound':gierrpamnotfound,
              'gierrcannotmutate':gierrcannotmutate,
             }

    if 'dguides' in locals():        
        # 0-based indexing 'position of guide ini/end', 'position of PAM ini/end'
        # 1-based indexing 'position of mutation in codon'
    
        logging.info('#reverse complement guides on negative strand sequences')
        dguides.loc[:,'PAM']=dguides.apply(lambda x : reverse_complement_multintseq(x['PAM'],nt2complement) if x['is a reverse complement'] else x['PAM'],axis=1)
        for colseq in ['guide+PAM sequence','guide sequence','PAM sequence']:
            dguides.loc[:,colseq]=dguides.apply(lambda x : str(str2seq(x[colseq]).reverse_complement()) if x['is a reverse complement'] else x[colseq],axis=1)

        logging.info('get dposition')
        dpositions=dguides.apply(lambda x: guide2dpositions(x),axis=1).apply(pd.Series)
#         posmut,posmutfrompam,distmutfrompam,posguideini,posguideend,activity_sequence
        dpositions.columns=['position of mutation','position of mutation from PAM','distance of mutation from PAM',
                           'position of guide ini','position of guide end','activity sequence']
#         dguides.to_csv('test_dguides.csv',sep='\t')
#         dpositions.to_csv('test_dposition.csv',sep='\t')
        for col in dpositions:
            dguides[col]=dpositions[col]
        
        logging.info('filter by # of editable nts in activity seq')
        logging.info(dguides.shape)
        dguides_noflt=dguides.copy()
        dguides=dguides.loc[(dguides.apply(lambda x : np.sum([x['activity sequence'].count(nt) for nt in  x['nucleotide']])==len(x['nucleotide']),axis=1)),:]
        logging.info(dguides.shape)
        if len(dguides)!=0:
            # if dbug:
            #     dguides.to_csv('test.tsv',sep='\t')
            logging.info('#filter by location of mutation within guide')
            dguides=dguides.loc[dguides.apply(lambda x : True if (x['distance of mutation from PAM: minimum']<=abs(x['distance of mutation from PAM'])<=x['distance of mutation from PAM: maximum']) else False,axis=1),:]
            if len(dguides)!=0:

                dguides.loc[:,'strategy']=dguides.apply(lambda x: f"{x['method']};{x['strand']};@{int(x['distance of mutation from PAM'])};{x['PAM']};{x['codon']}:{x['codon mutation']};{x['amino acid']}:{x['amino acid mutation']};",axis=1)
                dguides.loc[:,'guide: id']=dguides.apply(lambda x: f"{x['id']}|{int(x['aminoacid: position']) if not pd.isnull(x['aminoacid: position']) else 'nucleotide'}|({x['strategy']})",axis=1)
                dguides.loc[:,'guide+PAM length']=dguides.apply(lambda x: len(x['guide+PAM sequence']),axis=1)
                dguides=dguides.drop_duplicates(subset=['guide: id'])
                return dguides,dguides_noflt,err2idxs
            else:
                return None,dguides_noflt,None        
        else:
            return None,dguides_noflt,None        
    else:
        return None,None,None        
Example #4
0
def get_possible_mutagenesis(
    cfg,
    dcodontable,
    dcodonusage,
    BEs,
    pos_muts,
    host,
):
    """
    Assesses possible mutagenesis strategies, given the set of Base editors and positions of mutations.

    :param dcodontable: Codon table
    :param dcodonusage: Codon usage table
    :param BEs: Base editors (dict), see global_vars.py
    :param pos_muts: positions of mutations
    :param host: host organism
    :returns: possible mutagenesis strategies as a pandas dataframe
    """
    def write_dmutagenesis(cdni, posi, codon, codonmut, ntwt, ntmut, aa, aamut,
                           method):
        """
        Write dmutagenesis table for each iteraction in get_possible_mutagenesis.
        """
        dmutagenesis.loc[cdni, 'codon'] = codon
        dmutagenesis.loc[cdni, 'position of mutation in codon'] = int(posi)
        dmutagenesis.loc[cdni, 'codon mutation'] = codonmut
        dmutagenesis.loc[cdni, 'nucleotide'] = ntwt
        dmutagenesis.loc[cdni, 'nucleotide mutation'] = ntmut
        dmutagenesis.loc[cdni, 'amino acid'] = aa
        dmutagenesis.loc[cdni, 'amino acid mutation'] = aamut
        dmutagenesis.loc[cdni, 'mutation on strand'] = method.split(' on ')[1]
        dmutagenesis.loc[cdni,
                         'strand: mutation'] = method.split(' on ')[1].replace(
                             ' strand', '')
        dmutagenesis.loc[cdni, 'method'] = method.split(' on ')[0]
        dmutagenesis.loc[cdni,
                         'codon mutation usage Fraction'] = dcodonusage.loc[
                             codonmut, 'Fraction']
        dmutagenesis.loc[cdni,
                         'codon mutation usage Frequency'] = dcodonusage.loc[
                             codonmut, 'Frequency']
        return dmutagenesis

    def get_sm(dmutagenesis, BEs, positions, codon, muti, cdni):
        """
        Fetches single nucleotide mutagenesis strategies.
        """
        for method in BEs:
            for posi in positions:
                if BEs[method][0] == codon[posi]:
                    for ntmut in BEs[method][1]:
                        if posi == 0:
                            codonmut = '{}{}{}'.format(ntmut, codon[1],
                                                       codon[2])
                        elif posi == 1:
                            codonmut = '{}{}{}'.format(codon[0], ntmut,
                                                       codon[2])
                        elif posi == 2:
                            codonmut = '{}{}{}'.format(codon[0], codon[1],
                                                       ntmut)
                        aamut = str(
                            Seq.Seq(codonmut,
                                    Alphabet.generic_dna).translate(table=1))
                        # if (aamut!='*') and (aamut!=aa): #  nonsence and synonymous
                        if muti == 0:
                            cdni = cdni
                        else:
                            cdni = len(dmutagenesis) + 1
                        muti += 1
                        ntwt = BEs[method][0]
                        if '-' in method.split(' on ')[1]:
                            ntwt = str(
                                Seq.Seq(
                                    ntwt,
                                    Alphabet.generic_dna).reverse_complement())
                            ntmut = str(
                                Seq.Seq(
                                    ntmut,
                                    Alphabet.generic_dna).reverse_complement())
                        dmutagenesis_row = {
                            'cdni': cdni,
                            'posi': posi + 1,
                            'codon': codon,
                            'codonmut': codonmut,
                            'ntwt': ntwt,
                            'ntmut': ntmut,
                            'aa': aa,
                            'aamut': aamut,
                            'method': method
                        }
                        #                         print(dmutagenesis_row)
                        dmutagenesis = write_dmutagenesis(**dmutagenesis_row)
#                 else:
#                     logging.warning(f"BEs[{method}][0]!=codon[{posi}]")
        return dmutagenesis, muti

    #double nucleotide mutations
    positions = {0: '@1st position', 1: '@2nd position', 2: '@3rd position'}
    #double nucleotide mutations
    positions_dm = [(i, j) for i in positions.keys() for j in positions.keys()
                    if i < j]
    #double nucleotide mutations
    positions_tm = [[0, 1, 2]]

    dmutagenesis = dcodontable.copy()
    # test=True
    test = False
    for cdni in dmutagenesis.index:
        codon = dmutagenesis.loc[cdni, 'codon']
        aa = dmutagenesis.loc[cdni, 'amino acid']
        muti = 0
        if test:
            print(codon)
        #single nucleuotide mutations
        dmutagenesis, muti = get_sm(dmutagenesis, BEs, positions, codon, muti,
                                    cdni)
    if len(dmutagenesis) == 0:
        from beditor.lib.global_vars import saveemptytable
        logging.warning('no guides designed; saving an empty table.')
        dmutagenesis = saveemptytable(cfg)
    else:
        #         to_table(dmutagenesis,'test.tsv') #FIXME
        #         print(dmutagenesis.shape)
        dmutagenesis = dmutagenesis.dropna()  #FIXME
        #         print(dmutagenesis.shape)
        dmutagenesis['nucleotide mutation: count'] = [
            len(s) for s in dmutagenesis['nucleotide mutation']
        ]
        dmutagenesis = dmutagenesis.sort_values('codon')
        # Adding information of Allowed activity window
        dmutagenesis = dmutagenesis.set_index('method').join(pos_muts)
        dmutagenesis = dmutagenesis.reset_index()

        from beditor.lib.io_seqs import reverse_complement_multintseq
        from beditor.lib.global_vars import nt2complement
        dmutagenesis['nucleotide: wild-type'] = dmutagenesis.apply(
            lambda x: x['nucleotide']
            if x['strand: mutation'] == '+' else reverse_complement_multintseq(
                x['nucleotide'], nt2complement),
            axis=1)
        dmutagenesis['nucleotide: mutation'] = dmutagenesis.apply(
            lambda x: x['nucleotide mutation']
            if x['strand: mutation'] == '+' else reverse_complement_multintseq(
                x['nucleotide mutation'], nt2complement),
            axis=1)

    return dmutagenesis