Project: s41467-025-56348-1 | Function: differential_expression (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Implements differential expression analysis for tRNA abundance comparison between conditions. Performs correlation analysis, statistical calculations, and abundance profiling as described in the Methods section for comparing tRNA levels across samples.

**KEY TERMS:** {
  "log2FoldChange": "fold change analysis",
  "padj": "adjusted p-value",
  "pearsonr": "Pearson correlation coefficient",
  "ave_log10": "log10 transformation",
  "significance": "statistical significance"
}

**CONTEXT CODE:**                     dfs = dfg[dfg['sample'].str.contains(f.split(".")[0])].reset_index(drop=True)
                    #print(len(dfs),"rows")
                    if len(dfs) == 4:
                        sumg = sum(dfs['count'])
                        absent_ = dfs[dfs['end']=='Absent'].reset_index(drop=True).loc[0,'count']/sumg*100
                        absent.append(absent_)
                        c_ = absent_ + dfs[dfs['end']=='C'].reset_index(drop=True).loc[0,'count']/sumg*100
                        c.append(c_)
                        cc_ = c_ + dfs[dfs['end']=='CC'].reset_index(drop=True).loc[0,'count']/sumg*100
                        cc.append(cc_)
                        #cca_ = 100#dfs[dfs['end']=='CA'].reset_index(drop=True).loc[0,'count']/sumg*100
                        #ccad.append(cca_)
                    else:
                        print("error!")
                        print(dfs)
            # For isoacceptor
            genei.append(a)
            cci.append(sum(cc)/len(cc))
            ci.append(sum(c)/len(c))
            absenti.append(sum(absent)/len(absent))
            allin = [sum(cc)/len(cc),sum(c)/len(c),sum(absent)/len(absent)]
            ccai.append(100-sum(allin))

        y = [absenti,ci,cci,ccai]
        ax = fig.add_subplot(1,len(sample),sub)
        bottom = [0 for g in range(len(genei))]
        print("len(bottom) :",len(bottom))
        for y_, l, c in zip(y,['Absent','C','CC','CCA'],['#012E54','#0F4C81','#92B0CA','#E9F4FF']):
            ax.barh(range(1,len(genei)+1),y_,left=bottom,label=l,color=c,align="center")
            bottom = [x + y for (x, y) in zip(bottom, y_)]
            print(l,"ave.",round(sum(y_)/len(y_),2),"%")
            if sub == 1:
                ax.set_yticklabels(genei,ha='right')
                # ax.get_yaxis().set_tick_params(pad=45)
            else:
                ax.set_yticklabels([])
        ax.set_xlim([0,100])
        ax.set_yticks(range(1,len(genei)+1))
        ax.set_ylim(0,len(bottom)+1)
        #ax.set_ylabel('All human tRNA isodecoders',fontsize=10)
        ax.set_xlabel('Percentage(%)',fontsize=10)
        ax.set_xticks([0,20,40,60,80,100])
        ax.tick_params(axis='x',labelsize=10)
        ax.tick_params(axis='y',labelsize=10)
        ax.set_title(s,fontsize=10)
    plt.legend(loc="upper right",bbox_to_anchor=(2,1))
    plt.tight_layout()
    plt.savefig("{}figures/CCAanalysis_isoacceptors.png".format(directory))

# [2] countをscatter plotする
def differential_expression(directory,sampledic,tRNA,log10,organism,significance):
    # MASKED: Implements differential expression analysis for tRNA abundance comparison between conditions. Performs correlation analysis, statistical calculations, and abundance profiling as described in the Methods section for comparing tRNA levels across samples.
    raise NotImplementedError("This function is masked for testing purposes.")
def differential_expression_mouse(directory,sampledic,log10,organism,significance):
    # tRNA: "tRNA-Xxx-XXX-X", or "tRNA-Xxx-XXX", or "mito_tRNA-Xxx-XXX"

    for file in ['cyto_Isodecoder','cyto_Anticodon','mito_Isodecoder']:

        print("file:",file)
        if file == 'cyto_Anticodon':path = "{}DESeq2/cyto/anticodon/".format(directory)
        elif file == 'cyto_Isodecoder':path = "{}DESeq2/cyto/isodecoder/".format(directory)
        elif file == 'mito_Isodecoder':path = "{}DESeq2/organelle/isodecoder/".format(directory)

        f1 = sampledic.loc[0,"sample"]
        f2 = sampledic.loc[1,"sample"]
        ff = [f1,f2]
        ff_ = ff
        col1 = [sampledic.loc[0,"file_unpaired_uniq"]]
        col2 = [sampledic.loc[1,"file_unpaired_uniq"]]
        df = pd.read_csv(f"{path}singleRep-normCounts.csv",usecols=["Gene"]+col1+col2).rename(columns={col1[0]:f1,col2[0]:f2})
        df = df[df['Gene'].str.contains(organism)].reset_index(drop=True)
        df['{}_log10'.format(f1)] = np.log10(df[f1])
        df['{}_log10'.format(f2)] = np.log10(df[f2])
        df.replace([np.inf,-np.inf],0,inplace=True)
        print(df.head())
        print("len(file):",len(df))

        # plot
        fig = plt.figure(figsize=(2.9,3.1))
        ax = fig.add_subplot(111)

        if log10 == 'log10':
            xcol = '{}_log10'.format(f1)
            ycol = '{}_log10'.format(f2)
        else:
            xcol = f1
            ycol = f2

        x = df[xcol]
        y = df[ycol]
        ax.scatter(x,y,c='darkgray',alpha=0.3,edgecolor="darkgray",s=10)
        ax.plot([0,6],[0,6],linewidth=0.5,c='gray')
        r, p_value = pearsonr(df[f1],df[f2])
        ax.text(4,0.5,"R = {}".format(round(r,2)))
        ax.set_ylim(0,6)#maxval)
        ax.set_xlim(0,6)#maxval)
        ax.tick_params(axis='x',labelsize=10)
        ax.tick_params(axis='y',labelsize=10)
        ax.set_xlabel(xcol,fontsize=10)
        ax.set_ylabel(ycol,fontsize=10)
        plt.tight_layout()
        plt.savefig('{}figures/differential_expression_{}.png'.format(directory,file))

# [4] Isodecoder毎に、modificationの判定をする
# 各isodecoderごとに、各位置のRTstopとmismatchのproportionをまとめた表
def RTstop_mismatch(directory,folder,sampledic,organism):#10%のthreshold判定をなくしてみた
    # MASKED: Core algorithm for analyzing RT stops and misincorporations at tRNA modification sites. Processes data for each position to calculate readthrough proportions based on coverage ratios, implementing the key computational method for detecting tRNA modifications described in the paper.
    raise NotImplementedError("This function is masked for testing purposes.")
# [5] % Full length reads
def full_length(directory,sample):
    out = pd.DataFrame()
    o = -1
    for s in sample:
        print("sample:",s)
        df = pd.read_csv("{}RTstop_mismatch_summarized_{}.csv".format(directory,s))
        df["cov"] = df["cov"].astype("float")
        # print(df.head())
        # print(df[df["canon_pos"]=="0"])
        for i in set(df["isodecoder"]):
            # print("isodecoder:",i)
            dfi = df[df["isodecoder"]==i]
            # print(dfi.head())
            for r in set(dfi["replicate_num"]):
                o += 1
                dfr = dfi[dfi["replicate_num"]==r].reset_index(drop=True)
                # print("replicate:",r)
                cov = dfr.loc[0,"cov"]
                if np.isnan(cov):
                    print("NaN in",i)
                    break
                if cov != min(dfr["cov"]):
                    print("min(coverage) does not equal coverage at position 1 in",i)
                    print("min cov",cov)
                    print(dfr.head())
                    # print(dfr.tail())
                # print(cov)
                # print(max(dfr["cov"]))
                # print(cov/max(dfr["cov"])*100)
                out.loc[o,"condition"] = s
                out.loc[o,"cyto_mito"] = dfr.loc[0,"cyto_mito"]
                out.loc[o,"full_length(%)"] = cov/max(dfr["cov"])*100
    print("done")
    # print(out.head())
    # print(out.tail())
    out.to_csv("{}full_length_reads.csv".format(directory),index=False)

    # plot
    sns.set()
    sns.set_style("ticks")
    # color = ["#d0dfed","#7fabdb","#2376c8","#d9c0d3","#d97aa6","#d3095f"]


Complete the function implementation replacing "raise NotImplementedError".