# Buggy code
def resource_distribution_plot(
    df_resources,
    df_task,
    type="psutil_process_time_user",
    label="CPU Time Distribution",
    option="avg",
    columns=20,
):
    # E.g., psutil_process_time_user or psutil_process_memory_percent

    min_range = min(df_resources[type].astype("float"))
    max_range = max(df_resources[type].astype("float"))
    time_step = (max_range - min_range) / columns

    x_axis = []
    for i in np.arange(min_range, max_range + time_step, time_step):
        x_axis.append(i)

    apps_dict = dict()
    for i in range(len(df_task)):
        row = df_task.iloc[i]
        apps_dict[row["task_id"]] = []

    def y_axis_setup():
        items = []

        for app, tasks in apps_dict.items():
            tmp = []
            if option == "avg":
                task = (
                    df_resources[df_resources["task_id"] == app][type]
                    .astype("float")
                    .mean()
                )
            elif option == "max":
                task = max(
                    df_resources[df_resources["task_id"] == app][type].astype("float")
                )

            for i in range(len(x_axis) - 1):
                a = task >= x_axis[i]
                b = task < x_axis[i + 1]
                tmp.append(a & b)
            items = np.sum([items, tmp], axis=0)
        return items

    if "memory" not in type:
        xaxis = dict(autorange=True, title="CPU user time (seconds)")
    else:
        xaxis = dict(autorange=True, title="Memory usage (bytes)")
    fig = go.Figure(
        data=[go.Bar(x=x_axis[:-1], y=y_axis_setup(), name="tasks")],
        layout=go.Layout(
            xaxis=xaxis, yaxis=dict(title="Tasks"), title=label + "(" + option + ")"
        ),
    )

    return plot(fig, show_link=False, output_type="div", include_plotlyjs=False)


# Traceback (ZeroDivisionError)
[2019-05-03 18:18:01,362] ERROR in app: Exception on /workflow/9294c39d-a64d-4ad5-9ff8-4b8d757c1af1/resource_usage [GET]
Traceback (most recent call last):
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/awoodard/software/miniconda3/envs/parsl/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/awoodard/ci/viz_server/viz_server/views.py", line 145, in workflow_resources
df_resources, df_task, type='psutil_process_time_user', label='CPU Time Distribution', option='avg'),
File "/Users/awoodard/ci/viz_server/viz_server/plots/default/workflow_resource_plots.py", line 15, in resource_distribution_plot
for i in np.arange(min_range, max_range + time_step, time_step):
ZeroDivisionError: float division by zero

# Fixed code
def resource_distribution_plot(
    df_resources,
    df_task,
    type="psutil_process_time_user",
    label="CPU Time Distribution",
    option="avg",
    columns=20,
):
    # E.g., psutil_process_time_user or psutil_process_memory_percent

    min_range = min(df_resources[type].astype("float"))
    max_range = max(df_resources[type].astype("float"))
    time_step = (max_range - min_range) / columns

    if min_range == max_range:
        x_axis = [min_range]
    else:
        x_axis = []
        for i in np.arange(min_range, max_range + time_step, time_step):
            x_axis.append(i)

    apps_dict = dict()
    for i in range(len(df_task)):
        row = df_task.iloc[i]
        apps_dict[row["task_id"]] = []

    def y_axis_setup():
        items = [0] * len(x_axis)

        for app, tasks in apps_dict.items():
            if option == "avg":
                task = (
                    df_resources[df_resources["task_id"] == app][type]
                    .astype("float")
                    .mean()
                )
            elif option == "max":
                task = max(
                    df_resources[df_resources["task_id"] == app][type].astype("float")
                )

            for i in range(len(x_axis) - 1):
                a = task >= x_axis[i]
                b = task < x_axis[i + 1]
                if a and b:
                    items[i] += 1
            if task >= x_axis[-1]:
                items[-1] += 1
        return items

    if "memory" not in type:
        xaxis = dict(autorange=True, title="CPU user time (seconds)")
    else:
        xaxis = dict(autorange=True, title="Memory usage (bytes)")
    fig = go.Figure(
        data=[go.Bar(x=x_axis, y=y_axis_setup(), name="tasks")],
        layout=go.Layout(
            xaxis=xaxis, yaxis=dict(title="Tasks"), title=label + "(" + option + ")"
        ),
    )

    return plot(fig, show_link=False, output_type="div", include_plotlyjs=False)