<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 First Taste of Plotly
Step1:  Try Plotting a Dirichlet Distribution
Step4:  Make an Interactive 3D Plot with Parameter Selection
<ASSISTANT_TASK:>
Python Code:
trace0 = go.Scatter(
    x=[1, 2, 3, 4],
    y=[10, 15, 13, 17]
)
trace1 = go.Scatter(
    x=[1, 2, 3, 4],
    y=[16, 5, 11, 9]
)
data = go.Data([trace0, trace1])
py.iplot(data, filename = 'basic-line')
Explanation: First Taste of Plotly
End of explanation
alpha = np.array([5, 5, 5])
rv = st.dirichlet(alpha)
coord_step = 0.01
coord_range = np.arange(coord_step, 1, coord_step)
xv, yv = np.meshgrid(coord_range, coord_range)
figure(figsize=(12, 10))
sns.heatmap(xv)
figure(figsize=(12, 10))
sns.heatmap(yv)
zv = 1.0 - xv - yv
zv = np.where(zv > 0.0, zv, np.nan)
figure(figsize=(12, 10))
sns.heatmap(zv)
dv = rv.pdf(np.array((xv, yv, zv)))
figure(figsize=(12, 10))
sns.heatmap(dv, vmin=0, vmax=10)
pd.Series(dv.flatten()).describe()
text = [["pdf: %.2f" % d for d in dv[i]] for i in range(dv.shape[0])]
len(text), len(text[0])
data = [
    go.Surface(
        x=xv,
        y=yv,
        z=zv,
        surfacecolor=dv,
        hoverinfo="x+y+z+text",
        text=text,
        name="Dirichlet(%.2f, %.2f, %.2f)" % tuple(alpha)
    )
]
layout = go.Layout(
    title='Dirichlet Demo',
    autosize=False,
    width=800,
    height=600,
    margin=dict(
        l=65,
        r=50,
        b=65,
        t=90
    )
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='dirichlet_demo')
Explanation: Try Plotting a Dirichlet Distribution
End of explanation
def generate_dirichlet_surface(alpha, coord_step=0.01, visible=False, max_pdf=20):
    
    Generate a plotly 3D surface for standard simplex at granularity coord_step, with colors
    mapped to Dirichlet(alpha) pdf values. Filter out pts with pdf values exceeding max_pdf.
    
    
    rv = st.dirichlet(alpha)
    coord_range = np.arange(coord_step, 1, coord_step)
    xv, yv = np.meshgrid(coord_range, coord_range)
    zv = 1.0 - xv - yv
    zv = np.where(zv > 0.0, zv, np.nan)
    dv = rv.pdf(np.array((xv, yv, zv)))
    
    zv = np.where(dv > max_pdf, np.nan, zv)
    dv = np.where(dv > max_pdf, np.nan, dv)
    
    text = [["pdf: %.4f" % d for d in dv[i]] for i in range(dv.shape[0])]
    name = "%.1f %.1f %.1f" % tuple(alpha)
    res = go.Surface(
            x=xv,
            y=yv,
            z=zv,
            surfacecolor=dv,
            cmin=0.0,
            #cmax=25.0,
            #cauto=False,
            colorscale='Viridis',
            hoverinfo="name+x+y+z+text",
            text=text,
            name=name,
            visible=visible
        )
    return res
def generate_dirichlet_interactive_figure(alpha_range=None):
    
    Generate a plotly 3D figure with Dirichlet distributions corresponding to a range
    of alpha parameters, selectable from drop-down menus.
    
    
    if alpha_range is None:
        alpha_log_beg=-1
        alpha_log_end=1
        alpha_log_step=5
        alpha_log_base=2
        alpha_range = np.logspace(alpha_log_beg, alpha_log_end, alpha_log_step, base=alpha_log_base)
    
    n_range = len(alpha_range)
    n = n_range ** 3
    
    alphas = []
    sfcs = []
    
    visible=True
    visibility = np.eye(n).astype(bool)
    
    group_indices = [[], []]
    
    for group_1 in [True, False]:
        for alpha_x in alpha_range:
            for alpha_y in alpha_range:
                for alpha_z in alpha_range:
                    all_over_1 = alpha_x >= 1 and alpha_y >= 1 and alpha_z >= 1
                    non_decreasing = alpha_x <= alpha_y <= alpha_z
                    
                    if (all_over_1 and group_1) or ((not all_over_1) and non_decreasing and (not group_1)):
                        
                        group_indices[int(all_over_1)].append(len(alphas))
                        alpha = np.array([alpha_x, alpha_y, alpha_z])
                        alphas.append(alpha)
                        print("Generating surface for alpha: %s (group %d)" % (alpha, group_1))
                        sfc = generate_dirichlet_surface(alpha, coord_step=0.01, visible=visible)
                        sfcs.append(sfc)
                        visible=False
                
    data = go.Data(sfcs)
    print("Generating layout & figure")
    layout = go.Layout(
        title='Dirichlet Distribution Interactive Plot',
        legend={'xanchor': 'right'},
        autosize=True,
        width=800,
        height=800,
        #scene={'bgcolor': 'rgb(217, 217, 217)'},
        updatemenus=[
            dict(
                x=0,
                y=1.0 + k_group * 0.1,
                yanchor='top',
                font={'size': 10, 'family': 'courier'},
                buttons=[
                    dict(
                        args=['visible', list(visibility[i])],
                        label='alpha=(%.1f %.1f %.1f)' % tuple(alphas[i]),
                        method='restyle'
                    )
                    for i in group_indices[k_group]]
            )
            for k_group in [0, 1]
        ],
    )
    
    fig = go.Figure(data=data, layout=layout)
    return fig
fig = generate_dirichlet_interactive_figure(alpha_range=np.array([2, 1, 0.9]))
py.iplot(fig, filename='dirichlet_interactive')
Explanation: Make an Interactive 3D Plot with Parameter Selection
End of explanation
<END_TASK>