Python implementation of the SymPlot from the CellPlot package for R.
    -inf or inf enrichments will come out as min found float or max found float, respectively.

    :param df: pandas dataframe with the following columns - 'Enrichment', 'Significant', 'Annotated', 'Term', and 'log2fc'.
               'Annotated'i stands for number of genes annotated with the respective GO term.
                As reported in DAVID by listHits. 
                For log2fc each cell must contain a comma separated string with the log2fc for the genes enriched in the respective term.
               eg. '-inf,-1,2,3.4,3.66,inf'
    :param output_file: prefix for an output file. If given it witll create output_file.SymPlot.svg and output_file.SymPlot.png
    :param figure_title: Figure title.
    :param pvalCol: name of the column containing the p values to determine if the terms should be marked as NS - not significant, use None for no marking
    :returns: a matplotlib figure

def SymPlot(df,output_file=None,figure_title="SymPlot",pvalCol="elimFisher"):
    """
    Python implementation of the SymPlot from the CellPlot package for R.
    -inf or inf enrichments will come out as min found float or max found float, respectively.

    :param df: pandas dataframe with the following columns - 'Enrichment', 'Significant', 'Annotated', 'Term', and 'log2fc'.
               'Annotated'i stands for number of genes annotated with the respective GO term.
                As reported in DAVID by listHits. 
                For log2fc each cell must contain a comma separated string with the log2fc for the genes enriched in the respective term.
               eg. '-inf,-1,2,3.4,3.66,inf'
    :param output_file: prefix for an output file. If given it witll create output_file.SymPlot.svg and output_file.SymPlot.png
    :param figure_title: Figure title.
    :param pvalCol: name of the column containing the p values to determine if the terms should be marked as NS - not significant, use None for no marking
    :returns: a matplotlib figure
    """
    df['Annotated'] = df['Annotated'].astype(float)
    maxAn=df['Annotated'].max()

    arrangment=np.arange(len(df))+.5

    def getINFs(x):
        if x == str(float("inf")):
            return 1
        elif x == str(float("-inf")):
            return -1
        else:
            return x

    enr=df['Enrichment'].tolist()
    enr=[x for x in enr if str(x) != str(float("inf"))]
    enr=[x for x in enr if str(x) != str(float("-inf"))]

    maxE=max(enr)
    minE=min(enr)

    def fix_enrichment(x,minE=minE,maxE=maxE):
        if str(x) == str(float("inf")):
            return maxE
        elif str(x) == str(float("-inf")):
            return minE
        else:
            return x

    df['Enrichment']=df['Enrichment'].apply(lambda x: fix_enrichment(x))

    limits=df['Enrichment'].tolist()
    maxFC=np.percentile(limits,90)
    minFC=np.percentile(limits,10)

    cmap = matplotlib.cm.get_cmap('Spectral')
    norm = matplotlib.colors.Normalize(vmin=minFC, vmax=maxFC)

    if len(df) >= 5:
        size=len(df)*4/10
    else:
        size=5*4/10


    fig = plt.figure(figsize=(8, size))
    #fig.suptitle(figure_title, fontsize=24, fontweight='bold')
    gs = gridspec.GridSpec(1, 3, width_ratios=[2,0.75,2])
    ax1 = plt.subplot(gs[0])
    ax2 = plt.subplot(gs[1])
    ax3 = plt.subplot(gs[2])
    ax4 = fig.add_axes([0.125, 0.11/100*len(df), 0.775, 0.075*10/len(df)])#/100.0075

    alldown=[]
    allup=[]

    for i,pos in zip(df.index.tolist(),arrangment):
        f=df.ix[i,'Enrichment']#sigN=df.ix[i,'Significant']
        ann=float(df.ix[i,'Annotated'])

        if ann!=maxAn:
            p=float(maxAn-ann)/2
        else:
            p=0
        ax2.barh(pos, ann, left=p, color=cmap(norm(float(f))),edgecolor=cmap(norm(float(f))))#

        fcs=df.ix[i,'log2fc'].split(",")
        fcs=pd.DataFrame(fcs)
        fcs[0]=fcs[0].astype(str)
        fcs[0]=fcs[0].apply(lambda x: getINFs(x))
        #fcs=fcs[fcs[0]!=""].astype(float)
        fcs=fcs.astype(float)
        down=len(fcs[fcs[0]<0])/ann*100
        up=len(fcs[fcs[0]>0])/ann*100
        alldown.append(down)
        allup.append(up)

        ax1.barh(pos, down, color="blue",edgecolor='blue')
        ax3.barh(pos, up, color="red",edgecolor='red')

    ax1.spines['top'].set_visible(True)
    ax1.spines['bottom'].set_visible(False)
    ax1.spines['left'].set_visible(False)
    ax1.spines['right'].set_visible(False)

    ax1.tick_params(axis='x',which='both',bottom='off', top='on',labelbottom='off',labeltop='on')
    ax1.tick_params(axis='y',which='both',left='off',right='off',labelleft='on')

    ax2.spines['top'].set_visible(False)
    ax2.spines['bottom'].set_visible(False)
    ax2.spines['left'].set_visible(False)
    ax2.spines['right'].set_visible(False)

    ax2.tick_params(axis='x',which='both',bottom='off',top='off',labelbottom='off',labeltop='off')
    ax2.tick_params(axis='y',which='both',left='off',right='off',labelleft='off')

    ax3.spines['top'].set_visible(True)
    ax3.spines['bottom'].set_visible(False)
    ax3.spines['left'].set_visible(False)
    ax3.spines['right'].set_visible(False)

    ax3.tick_params(axis='x',which='both',bottom='off',top='on',labelbottom='off',labeltop='on')
    ax3.tick_params(axis='y',which='both',left='off',right='off',labelleft='off')

    fa=10*0.1/len(df)+1
    fb=10*0.08/len(df)+1

    ax1.set_title('Downregulated (%)',y=fa)#
    ax2.set_title('Annotated\n(max=%s)' %str(maxAn),y=fb)#
    ax3.set_title('Upregulated (%)',y=fa)

    ax1.set_xlim(max(max(alldown),max(allup)), 0)
    ax2.set_xlim(0, maxAn)
    ax3.set_xlim(0, max(max(alldown),max(allup)))

    ax1.set_ylim(ymax = max(arrangment)+1.5)
    ax2.set_ylim(ymax = max(arrangment)+1.5)
    ax3.set_ylim(ymax = max(arrangment)+1.5)


    ax1.set_yticks(arrangment)#+0.4)
    def get_label_with_sig (df):
        termLabel=df['Term']
        if pvalCol:
            pvalue=df[pvalCol]
            if pvalue > 0.05:
                return "(NS) "+termLabel
            else:
                return termLabel
        else:
            return termLabel

    df['newLabels']=df.apply(get_label_with_sig, axis=1)

    ax1.set_yticklabels(df['newLabels'].tolist())

    cb1 = matplotlib.colorbar.ColorbarBase(ax4, cmap=cmap,norm=norm, orientation='horizontal')
    cb1.set_label('GO Term Enrichment (0.1-0.9 percentiles)\n\n\n'+figure_title)

    fig.subplots_adjust(wspace=0)

    if output_file:
        plt.savefig(output_file+".SymPlot.png",dpi=300,bbox_inches='tight', pad_inches=0.1,format='png')
        plt.savefig(output_file+".SymPlot.svg",dpi=300,bbox_inches='tight', pad_inches=0.1,format='svg')

    return fig