From 142415c71bac5ebd0397776946bf495af5520262 Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:29:30 +0200 Subject: [PATCH 01/21] Update _gantt.py --- plotly/figure_factory/_gantt.py | 396 ++++++++++++++++++++++---------- 1 file changed, 279 insertions(+), 117 deletions(-) diff --git a/plotly/figure_factory/_gantt.py b/plotly/figure_factory/_gantt.py index e341655b9ce..a19f78f4bfd 100644 --- a/plotly/figure_factory/_gantt.py +++ b/plotly/figure_factory/_gantt.py @@ -2,6 +2,8 @@ from numbers import Number +import copy + from plotly import exceptions, optional_imports import plotly.colors as clrs from plotly.figure_factory import utils @@ -12,6 +14,22 @@ REQUIRED_GANTT_KEYS = ['Task', 'Start', 'Finish'] +def get_corner_points(x0, y0, x1, y1): + """ + Returns the corner points of a scatter rectangle + + :param x0: x-start + :param y0: y-lower + :param x1: x-end + :param y1: y-upper + :return: ([x], [y]), tuple of lists containing the x and y values + """ + + return ( + [x0, x1, x1, x0], + [y0, y0, y1, y1] + ) + def validate_gantt(df): """ Validates the inputted dataframe or list @@ -52,7 +70,8 @@ def validate_gantt(df): def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, - width, tasks=None, task_names=None, data=None, group_tasks=False): + width, tasks=None, task_names=None, data=None, group_tasks=False, + show_hover_fill=True, show_colorbar=True): """ Refer to create_gantt() for docstring """ @@ -71,15 +90,32 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "hoverinfo": hoverinfo } + + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], size=1), + "name": "", + "showlegend": False + } + # create the list of task names for index in range(len(tasks)): tn = tasks[index]['name'] @@ -97,7 +133,6 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -111,22 +146,53 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, if color_index >= len(colors): color_index = 0 tasks[index]['fillcolor'] = colors[color_index] - # Add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(tn) + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) + color_index += 1 + showlegend = show_colorbar + layout = dict( title=title, - showlegend=False, + showlegend=showlegend, height=height, width=width, shapes=[], @@ -170,15 +236,15 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, type='date' ) ) - layout['shapes'] = tasks - fig = graph_objs.Figure(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False): + task_names=None, data=None, group_tasks=False, + show_hover_fill=True): """ Refer to FigureFactory.create_gantt() for docstring """ @@ -198,16 +264,41 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "showlegend": False, + "hoverinfo" : hoverinfo } + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], + size=1), + "name": "", + "showlegend": False + } + + index_vals = [] + for row in range(len(tasks)): + if chart[row][index_col] not in index_vals: + index_vals.append(chart[row][index_col]) + + index_vals.sort() + # compute the color for task based on indexing column if isinstance(chart[0][index_col], Number): # check that colors has at least 2 colors @@ -235,7 +326,6 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -258,34 +348,55 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, intermed_color, clrs.label_rgb ) tasks[index]['fillcolor'] = intermed_color + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) + # relabel colors with 'rgb' colors = clrs.color_parser(colors, clrs.label_rgb) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data for colorscale visibility - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[index, index], - name='', - marker={'color': 'white', - 'colorscale': [[0, colors[0]], [1, colors[1]]], - 'showscale': True, - 'cmax': 100, - 'cmin': 0} - ) + scatter_data_dict["centers"]["marker"].update(dict( + colorscale = [[0, colors[0]], [1, colors[1]]], + showscale = True, + cmax = 100, + cmin = 0) ) if isinstance(chart[0][index_col], str): @@ -329,7 +440,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) + # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index @@ -341,36 +452,54 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, tasks[index]['fillcolor'] = index_vals_dict[ chart[index][index_col] ] + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) + + # relabel colors with 'rgb' + colors = clrs.color_parser(colors, clrs.label_rgb) + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data to generate legend showlegend = True - for k, index_value in enumerate(index_vals): - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[k, k], - showlegend=True, - name=str(index_value), - hoverinfo='none', - marker=dict( - color=colors[k], - size=1 - ) - ) - ) + for k in scatter_data_dict: + if k != "centers": + scatter_data_dict[k]["showlegend"] = showlegend layout = dict( title=title, @@ -418,18 +547,18 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, type='date' ) ) - layout['shapes'] = tasks - fig = dict(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False): + task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Refer to FigureFactory.create_gantt() for docstring """ + if tasks is None: tasks = [] if task_names is None: @@ -446,14 +575,30 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "hoverinfo" : hoverinfo + } + + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], size=1), + "name": "", + "showlegend": False } index_vals = [] @@ -487,7 +632,6 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -498,37 +642,51 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, tasks[index]['y1'] = groupID + bar_width tasks[index]['fillcolor'] = colors[chart[index][index_col]] + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - showlegend=False, - name='', - marker={'color': 'white'} + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data to generate legend showlegend = True - for k, index_value in enumerate(index_vals): - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[k, k], - showlegend=True, - hoverinfo='none', - name=str(index_value), - marker=dict( - color=colors[index_value], - size=1 - ) - ) - ) + + for index_value in index_vals: + scatter_data_dict[colors[index_value]]["name"] = str(index_value) + layout = dict( title=title, @@ -576,16 +734,15 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, type='date' ) ) - layout['shapes'] = tasks - fig = dict(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def create_gantt(df, colors=None, index_col=None, show_colorbar=False, reverse_colors=False, title='Gantt Chart', bar_width=0.2, showgrid_x=False, showgrid_y=False, height=600, width=900, - tasks=None, task_names=None, data=None, group_tasks=False): + tasks=None, task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Returns figure for a gantt chart @@ -608,6 +765,8 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, index_col must be one of the keys in all the items of df. :param (bool) show_colorbar: determines if colorbar will be visible. Only applies if values in the index column are numeric. + :param (bool) show_hover_fill: enables/disables the hovertext for the + filled area of the chart. :param (bool) reverse_colors: reverses the order of selected colors :param (str) title: the title of the chart :param (float) bar_width: the width of the horizontal bars in the plot @@ -761,7 +920,8 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, fig = gantt( chart, colors, title, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, task_names=None, data=None, - group_tasks=group_tasks + group_tasks=group_tasks, show_hover_fill=show_hover_fill, + show_colorbar=show_colorbar ) return fig else: @@ -769,13 +929,15 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, fig = gantt_colorscale( chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks + tasks=None, task_names=None, data=None, group_tasks=group_tasks, + show_hover_fill=show_hover_fill ) return fig else: fig = gantt_dict( chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks + tasks=None, task_names=None, data=None, group_tasks=group_tasks, + show_hover_fill=show_hover_fill ) return fig From 2b501803dcbe23d101849be2d278b3066ca40e1d Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:31:55 +0200 Subject: [PATCH 02/21] Gantt chart to scatter plot Gantt chart now uses scatter plots: - updating all the functions accordingly - unit tests updated - new param: show_hover_fill for hiding the text for the filled area --- plotly/figure_factory/_gantt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plotly/figure_factory/_gantt.py b/plotly/figure_factory/_gantt.py index a19f78f4bfd..55a59eb4e47 100644 --- a/plotly/figure_factory/_gantt.py +++ b/plotly/figure_factory/_gantt.py @@ -745,7 +745,6 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, tasks=None, task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Returns figure for a gantt chart - :param (array|list) df: input data for gantt chart. Must be either a a dataframe or a list. If dataframe, the columns must include 'Task', 'Start' and 'Finish'. Other columns can be included and From 5ec20dde66543e121748f5ae7ce16a2cd622208b Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:33:46 +0200 Subject: [PATCH 03/21] updated test for the scatter plot gantt chart --- .../test_figure_factory.py | 112 ++++++++---------- 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index c9b69ef209f..ff5d19b4a98 100644 --- a/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -1332,71 +1332,55 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = {'data': [{'marker': {'color': 'white'}, + exp_gantt_chart = {'data': [{'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15'], + 'y': [0, 0, 1, 1], + 'mode': 'markers', + 'text': [None, None, None, None], + 'marker': {'color': ['rgb(31, 119, 180)', + 'rgb(31, 119, 180)', + 'rgb(255, 127, 14)', + 'rgb(255, 127, 14)'], + 'size': 1}, 'name': '', - 'type': 'scatter', - 'x': ['2009-01-01', '2009-02-30'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'type': 'scatter', - 'x': ['2009-03-05', '2009-04-15'], - 'y': [1, 1]}], - 'layout': {'height': 600, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(31, 119, 180)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-01-01', - 'x1': '2009-02-30', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 127, 14)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-03-05', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': 0.8, - 'y1': 1.2, - 'yref': 'y'}], - 'showlegend': False, - 'title': {'text': 'Gantt Chart'}, - 'width': 900, - 'xaxis': {'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'showgrid': False, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 3], - 'showgrid': False, - 'ticktext': ['Job A', 'Job B'], - 'tickvals': [0, 1], - 'zeroline': False}}} + 'showlegend': False}, + {'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], + 'y': [-0.2, -0.2, 0.2, 0.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(31, 119, 180)', + 'name': 'Job A'}, + {'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], + 'y': [0.8, 0.8, 1.2, 1.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(255, 127, 14)', + 'name': 'Job B'}], + 'layout': {'title': 'Gantt Chart', + 'showlegend': False, + 'height': 600, + 'width': 900, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': False, + 'ticktext': ['Job A', 'Job B'], + 'tickvals': [0, 1], + 'range': [-1, 3], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': False, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}}} self.assert_fig_equal(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) From 93473aef628e1ace3d19c99e54e7021877e74d96 Mon Sep 17 00:00:00 2001 From: CSK Date: Mon, 15 Jul 2019 12:55:29 +0200 Subject: [PATCH 04/21] tests fixed --- .../test_tools/test_figure_factory.py | 356 ++++++++---------- 1 file changed, 151 insertions(+), 205 deletions(-) diff --git a/plotly/tests/test_optional/test_tools/test_figure_factory.py b/plotly/tests/test_optional/test_tools/test_figure_factory.py index 655be1570f8..168495580d8 100644 --- a/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1512,141 +1512,103 @@ def test_gannt_groups_and_descriptions(self): group_tasks=True ) - exp_gantt_chart = { - 'data': [{'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task A - 1', - 'x': ['2008-10-05', '2009-04-15'], - 'y': [2, 2]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task B - 1', - 'x': ['2008-12-06', '2009-03-15'], - 'y': [1, 1]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task C - 1', - 'x': ['2008-09-07', '2009-03-15'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task C - 2', - 'x': ['2009-05-08', '2009-04-15'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task A - 2', - 'x': ['2009-04-20', '2009-05-30'], - 'y': [2, 2]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(220, 0, 0)', 'size': 1}, - 'name': 'TA', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [0, 0]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(170, 14, 200)', 'size': 1}, - 'name': 'TB', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [1, 1]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(255, 230, 41)', 'size': 1}, - 'name': 'TC', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [2, 2]}], - 'layout': {'height': 600, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(220, 0, 0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-10-05', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': 1.8, - 'y1': 2.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(170, 14, 200)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-12-06', - 'x1': '2009-03-15', - 'xref': 'x', - 'y0': 0.8, - 'y1': 1.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 230, 41)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-09-07', - 'x1': '2009-03-15', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 230, 41)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-05-08', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(220, 0, 0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-04-20', - 'x1': '2009-05-30', - 'xref': 'x', - 'y0': 1.8, - 'y1': 2.2, - 'yref': 'y'}], - 'showlegend': True, - 'title': 'Gantt Chart', - 'width': 900, - 'xaxis': {'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'showgrid': False, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 4], - 'showgrid': False, - 'ticktext': ['Task C', 'Task B', 'Task A'], - 'tickvals': [0, 1, 2], - 'zeroline': False}} - } + exp_gantt_chart = {'data': [{'x': ['2008-10-05', + '2009-04-15', + '2008-12-06', + '2009-03-15', + '2008-09-07', + '2009-03-15', + '2009-05-08', + '2009-04-15', + '2009-04-20', + '2009-05-30'], + 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], + 'mode': 'markers', + 'text': ['Task A - 1', + 'Task A - 1', + 'Task B - 1', + 'Task B - 1', + 'Task C - 1', + 'Task C - 1', + 'Task C - 2', + 'Task C - 2', + 'Task A - 2', + 'Task A - 2'], + 'marker': {'color': ['rgb(220, 0, 0)', + 'rgb(220, 0, 0)', + 'rgb(170, 14, 200)', + 'rgb(170, 14, 200)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(220, 0, 0)', + 'rgb(220, 0, 0)'], + 'size': 1}, + 'name': '', + 'showlegend': False}, + {'x': ['2008-10-05', + '2009-04-15', + '2009-04-15', + '2008-10-05', + '2008-10-05', + '2009-04-20', + '2009-05-30', + '2009-05-30', + '2009-04-20'], + 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(220, 0, 0)', + 'name': 'TA'}, + {'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], + 'y': [0.8, 0.8, 1.2, 1.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(170, 14, 200)', + 'name': 'TB'}, + {'x': ['2008-09-07', + '2009-03-15', + '2009-03-15', + '2008-09-07', + '2008-09-07', + '2009-05-08', + '2009-04-15', + '2009-04-15', + '2009-05-08'], + 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(255, 230, 41)', + 'name': 'TC'}], + 'layout': {'title': 'Gantt Chart', + 'showlegend': True, + 'height': 600, + 'width': 900, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': False, + 'ticktext': ['Task C', 'Task B', 'Task A'], + 'tickvals': [0, 1, 2], + 'range': [-1, 4], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': False, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}} + } self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) @@ -1660,9 +1622,6 @@ def test_gannt_groups_and_descriptions(self): self.assertEqual(test_gantt_chart['data'][3], exp_gantt_chart['data'][3]) - self.assertEqual(test_gantt_chart['data'][4], - exp_gantt_chart['data'][4]) - self.assertEqual(test_gantt_chart['layout'], exp_gantt_chart['layout']) @@ -1685,73 +1644,57 @@ def test_gantt_all_args(self): height=500, width=500 ) - exp_gantt_chart = { - 'data': [{'marker': {'color': 'white'}, - 'name': '', - 'x': ['2010-01-01', '2011-02-02'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'x': ['2011-01-01', '2012-06-05'], - 'y': [1, 1]}], - 'layout': {'height': 500, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(220.0, 220.0, 220.0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2010-01-01', - 'x1': '2011-02-02', - 'xref': 'x', - 'y0': -0.5, - 'y1': 0.5, - 'yref': 'y'}, - {'fillcolor': 'rgb(166.25, 167.5, 208.0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2011-01-01', - 'x1': '2012-06-05', - 'xref': 'x', - 'y0': 0.5, - 'y1': 1.5, - 'yref': 'y'}], - 'showlegend': False, - 'title': 'Title', - 'width': 500, - 'xaxis': {'rangeselector': {'buttons': [ - {'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'} - ]}, - 'showgrid': True, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 3], - 'showgrid': True, - 'ticktext': ['Run', 'Fast'], - 'tickvals': [0, 1], - 'zeroline': False}} - } + exp_gantt_chart = {'data': [{'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05'], + 'y': [0, 0, 1, 1], + 'mode': 'markers', + 'text': [None, None, None, None], + 'marker': {'color': ['rgb(220.0, 220.0, 220.0)', + 'rgb(220.0, 220.0, 220.0)', + 'rgb(166.25, 167.5, 208.0)', + 'rgb(166.25, 167.5, 208.0)'], + 'size': 1}, + 'name': '', + 'showlegend': False}, + {'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], + 'y': [-0.5, -0.5, 0.5, 0.5], + 'mode': 'none', + 'fill': 'toself', + 'showlegend': False, + 'hoverinfo': 'name', + 'fillcolor': 'rgb(220.0, 220.0, 220.0)', + 'name': '0'}, + {'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], + 'y': [0.5, 0.5, 1.5, 1.5], + 'mode': 'none', + 'fill': 'toself', + 'showlegend': False, + 'hoverinfo': 'name', + 'fillcolor': 'rgb(166.25, 167.5, 208.0)', + 'name': '25'}], + 'layout': {'title': 'Title', + 'showlegend': False, + 'height': 500, + 'width': 500, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': True, + 'ticktext': ['Run', 'Fast'], + 'tickvals': [0, 1], + 'range': [-1, 3], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': True, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}}} self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) @@ -1759,6 +1702,9 @@ def test_gantt_all_args(self): self.assertEqual(test_gantt_chart['data'][1], exp_gantt_chart['data'][1]) + self.assertEqual(test_gantt_chart['data'][2], + exp_gantt_chart['data'][2]) + self.assertEqual(test_gantt_chart['layout'], exp_gantt_chart['layout']) From 806ca349f3a11275a44f17d642b94ac511a815ed Mon Sep 17 00:00:00 2001 From: CSK Date: Mon, 15 Jul 2019 13:18:24 +0200 Subject: [PATCH 05/21] update for successful tests, once again --- plotly/figure_factory/_gantt.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plotly/figure_factory/_gantt.py b/plotly/figure_factory/_gantt.py index 55a59eb4e47..5655c4eac9d 100644 --- a/plotly/figure_factory/_gantt.py +++ b/plotly/figure_factory/_gantt.py @@ -237,7 +237,8 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + #fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig @@ -548,7 +549,8 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + # fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig @@ -735,7 +737,8 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + # fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig From 76ad15bd82b292290cadc6e561a613a2201403a7 Mon Sep 17 00:00:00 2001 From: csaba Date: Tue, 16 Jul 2019 21:38:10 +0200 Subject: [PATCH 06/21] updated tests --- plotly/figure_factory/_gantt.py | 9 +- .../test_figure_factory.py | 83 +++++++++---------- 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/plotly/figure_factory/_gantt.py b/plotly/figure_factory/_gantt.py index 5655c4eac9d..acc935550d6 100644 --- a/plotly/figure_factory/_gantt.py +++ b/plotly/figure_factory/_gantt.py @@ -237,8 +237,7 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, ) ) - #fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig @@ -549,8 +548,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - # fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig @@ -737,8 +735,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - # fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig diff --git a/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index ff5d19b4a98..1105f926d7b 100644 --- a/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -1332,61 +1332,58 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = {'data': [{'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15'], - 'y': [0, 0, 1, 1], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': False, + 'yaxis': {'range': [-1, 3], + 'zeroline': False, + 'ticktext': ['Job A', 'Job B'], + 'tickvals': [0, 1], + 'autorange': False, + 'showgrid': False}, + 'title': 'Gantt Chart', + 'height': 600, + 'shapes': [], + 'width': 900, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': False}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': [None, None, None, None], 'marker': {'color': ['rgb(31, 119, 180)', 'rgb(31, 119, 180)', 'rgb(255, 127, 14)', 'rgb(255, 127, 14)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], - 'y': [-0.2, -0.2, 0.2, 0.2], + 'mode': 'markers', + 'y': [0, 0, 1, 1], + 'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15']}, + {'name': 'Job B', + 'fillcolor': 'rgb(255, 127, 14)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(31, 119, 180)', - 'name': 'Job A'}, - {'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], 'y': [0.8, 0.8, 1.2, 1.2], + 'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], + 'fill': 'toself'}, + {'name': 'Job A', + 'fillcolor': 'rgb(31, 119, 180)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(255, 127, 14)', - 'name': 'Job B'}], - 'layout': {'title': 'Gantt Chart', - 'showlegend': False, - 'height': 600, - 'width': 900, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': False, - 'ticktext': ['Job A', 'Job B'], - 'tickvals': [0, 1], - 'range': [-1, 3], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': False, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}}} - - self.assert_fig_equal(test_gantt_chart['data'][0], - exp_gantt_chart['data'][0]) + 'y': [-0.2, -0.2, 0.2, 0.2], + 'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], + 'fill': 'toself'}]} - self.assert_fig_equal(test_gantt_chart['layout'], - exp_gantt_chart['layout']) + self.assert_fig_equal(test_gantt_chart, + exp_gantt_chart) class TestViolin(NumpyTestUtilsMixin, TestCase): From ca88c35fc477431134e9807995023dbc1478cc25 Mon Sep 17 00:00:00 2001 From: csaba Date: Tue, 16 Jul 2019 22:13:29 +0200 Subject: [PATCH 07/21] updated tests --- .../test_tools/test_figure_factory.py | 209 +++++++++--------- 1 file changed, 99 insertions(+), 110 deletions(-) diff --git a/plotly/tests/test_optional/test_tools/test_figure_factory.py b/plotly/tests/test_optional/test_tools/test_figure_factory.py index 168495580d8..cde28f5e944 100644 --- a/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1512,18 +1512,32 @@ def test_gannt_groups_and_descriptions(self): group_tasks=True ) - exp_gantt_chart = {'data': [{'x': ['2008-10-05', - '2009-04-15', - '2008-12-06', - '2009-03-15', - '2008-09-07', - '2009-03-15', - '2009-05-08', - '2009-04-15', - '2009-04-20', - '2009-05-30'], - 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': True, + 'yaxis': {'range': [-1, 4], + 'zeroline': False, + 'ticktext': ['Task C', 'Task B', 'Task A'], + 'tickvals': [0, 1, 2], + 'autorange': False, + 'showgrid': False}, + 'title': 'Gantt Chart', + 'height': 600, + 'shapes': [], + 'width': 900, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': False}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': ['Task A - 1', 'Task A - 1', 'Task B - 1', @@ -1545,9 +1559,31 @@ def test_gannt_groups_and_descriptions(self): 'rgb(220, 0, 0)', 'rgb(220, 0, 0)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2008-10-05', + 'mode': 'markers', + 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], + 'x': ['2008-10-05', + '2009-04-15', + '2008-12-06', + '2009-03-15', + '2008-09-07', + '2009-03-15', + '2009-05-08', + '2009-04-15', + '2009-04-20', + '2009-05-30']}, + {'name': 'TB', + 'fillcolor': 'rgb(170, 14, 200)', + 'mode': 'none', + 'hoverinfo': 'name', + 'y': [0.8, 0.8, 1.2, 1.2], + 'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], + 'fill': 'toself'}, + {'name': 'TA', + 'fillcolor': 'rgb(220, 0, 0)', + 'mode': 'none', + 'hoverinfo': 'name', + 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + 'x': ['2008-10-05', '2009-04-15', '2009-04-15', '2008-10-05', @@ -1556,20 +1592,13 @@ def test_gannt_groups_and_descriptions(self): '2009-05-30', '2009-05-30', '2009-04-20'], - 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], - 'mode': 'none', - 'fill': 'toself', - 'hoverinfo': 'name', - 'fillcolor': 'rgb(220, 0, 0)', - 'name': 'TA'}, - {'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], - 'y': [0.8, 0.8, 1.2, 1.2], + 'fill': 'toself'}, + {'name': 'TC', + 'fillcolor': 'rgb(255, 230, 41)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(170, 14, 200)', - 'name': 'TB'}, - {'x': ['2008-09-07', + 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + 'x': ['2008-09-07', '2009-03-15', '2009-03-15', '2008-09-07', @@ -1578,52 +1607,12 @@ def test_gannt_groups_and_descriptions(self): '2009-04-15', '2009-04-15', '2009-05-08'], - 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], - 'mode': 'none', - 'fill': 'toself', - 'hoverinfo': 'name', - 'fillcolor': 'rgb(255, 230, 41)', - 'name': 'TC'}], - 'layout': {'title': 'Gantt Chart', - 'showlegend': True, - 'height': 600, - 'width': 900, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': False, - 'ticktext': ['Task C', 'Task B', 'Task A'], - 'tickvals': [0, 1, 2], - 'range': [-1, 4], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': False, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}} - } + 'fill': 'toself'}]} - self.assertEqual(test_gantt_chart['data'][0], - exp_gantt_chart['data'][0]) - self.assertEqual(test_gantt_chart['data'][1], - exp_gantt_chart['data'][1]) - self.assertEqual(test_gantt_chart['data'][2], - exp_gantt_chart['data'][2]) - - self.assertEqual(test_gantt_chart['data'][3], - exp_gantt_chart['data'][3]) - - self.assertEqual(test_gantt_chart['layout'], - exp_gantt_chart['layout']) + self.assertDictEqual(test_gantt_chart['data'][0], + exp_gantt_chart['data'][0]) def test_gantt_all_args(self): @@ -1644,57 +1633,57 @@ def test_gantt_all_args(self): height=500, width=500 ) - exp_gantt_chart = {'data': [{'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05'], - 'y': [0, 0, 1, 1], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': False, + 'yaxis': {'range': [-1, 3], + 'zeroline': False, + 'ticktext': ['Run', 'Fast'], + 'tickvals': [0, 1], + 'autorange': False, + 'showgrid': True}, + 'title': 'Title', + 'height': 500, + 'shapes': [], + 'width': 500, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': True}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': [None, None, None, None], 'marker': {'color': ['rgb(220.0, 220.0, 220.0)', 'rgb(220.0, 220.0, 220.0)', 'rgb(166.25, 167.5, 208.0)', 'rgb(166.25, 167.5, 208.0)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], - 'y': [-0.5, -0.5, 0.5, 0.5], + 'mode': 'markers', + 'y': [0, 0, 1, 1], + 'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05']}, + {'showlegend': False, + 'name': '25', + 'fillcolor': 'rgb(166.25, 167.5, 208.0)', 'mode': 'none', - 'fill': 'toself', - 'showlegend': False, 'hoverinfo': 'name', - 'fillcolor': 'rgb(220.0, 220.0, 220.0)', - 'name': '0'}, - {'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], 'y': [0.5, 0.5, 1.5, 1.5], + 'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], + 'fill': 'toself'}, + {'showlegend': False, + 'name': '0', + 'fillcolor': 'rgb(220.0, 220.0, 220.0)', 'mode': 'none', - 'fill': 'toself', - 'showlegend': False, 'hoverinfo': 'name', - 'fillcolor': 'rgb(166.25, 167.5, 208.0)', - 'name': '25'}], - 'layout': {'title': 'Title', - 'showlegend': False, - 'height': 500, - 'width': 500, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': True, - 'ticktext': ['Run', 'Fast'], - 'tickvals': [0, 1], - 'range': [-1, 3], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': True, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}}} + 'y': [-0.5, -0.5, 0.5, 0.5], + 'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], + 'fill': 'toself'}]} self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) From 3a0998b9d4ff567b71386de5415aef5f7352a76e Mon Sep 17 00:00:00 2001 From: michaelbabyn <41019918+michaelbabyn@users.noreply.github.com> Date: Sat, 15 Jun 2019 14:39:14 -0400 Subject: [PATCH 08/21] don't override plotlyServerURL if one is set in iplot/plot (#1615) * only set plotlyServerURL using the plotly_domain in the .config file if one isn't specified in the config dict passed to iplot/plot * make it clear that the default in clean_config.get is None --- packages/python/plotly/plotly/offline/offline.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/offline/offline.py b/packages/python/plotly/plotly/offline/offline.py index b3d765c3a0d..40c59412e31 100644 --- a/packages/python/plotly/plotly/offline/offline.py +++ b/packages/python/plotly/plotly/offline/offline.py @@ -161,7 +161,8 @@ def _get_jconfig(config=None): plotly_platform_url = plotly.tools.get_config_plotly_server_url() - clean_config['plotlyServerURL'] = plotly_platform_url + if not clean_config.get('plotlyServerURL', None): + clean_config['plotlyServerURL'] = plotly_platform_url if (plotly_platform_url != 'https://plot.ly' and clean_config.get('linkText', None) == 'Export to plot.ly'): From 9bacc9b069a393d3acd937392bf51fcf21ae3905 Mon Sep 17 00:00:00 2001 From: Emmanuelle Gouillart Date: Wed, 3 Jul 2019 15:59:54 +0200 Subject: [PATCH 09/21] Scraper function for sphinx-gallery, in plotly.io (#1577) * scraper function for sphinx-gallery, in plotly.io. scraper function + skeleton of sphinx doc with minimal gallery (two examples) * added psutil dep to tox.ini * python 2 compatibility * added orca dep to package.json for tests * removed typo * corrected bug * python 2 compatibility * added electron * try to configure orca * Moved test file so that it's tested by the orca build only. * use custom renderer for sphinx-gallery * removed sphinx files which are now in plotly-sphinx-gallery + changed name of renderer sphinx -> sphinx-gallery, and changed wording of documentation * Modified test with new renderer name * try to fix py2 compatibility * write_html instead of offline.plot * change import order --- packages/python/plotly/plotly/io/__init__.py | 3 +- .../plotly/plotly/io/_base_renderers.py | 20 +++- .../python/plotly/plotly/io/_renderers.py | 4 +- plotly/io/_sg_scraper.py | 104 ++++++++++++++++++ plotly/tests/test_orca/test_sg_scraper.py | 60 ++++++++++ 5 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 plotly/io/_sg_scraper.py create mode 100644 plotly/tests/test_orca/test_sg_scraper.py diff --git a/packages/python/plotly/plotly/io/__init__.py b/packages/python/plotly/plotly/io/__init__.py index c0478c70ac0..7b26dbfb297 100644 --- a/packages/python/plotly/plotly/io/__init__.py +++ b/packages/python/plotly/plotly/io/__init__.py @@ -5,8 +5,9 @@ from ._templates import templates, to_templated +from ._html import to_html, write_html + from ._renderers import renderers, show from . import base_renderers -from ._html import to_html, write_html diff --git a/packages/python/plotly/plotly/io/_base_renderers.py b/packages/python/plotly/plotly/io/_base_renderers.py index bfe7bb01fdb..652bbc817ad 100644 --- a/packages/python/plotly/plotly/io/_base_renderers.py +++ b/packages/python/plotly/plotly/io/_base_renderers.py @@ -6,10 +6,11 @@ import os import six -from plotly.io import to_json, to_image +from plotly.io import to_json, to_image, write_image, write_html from plotly import utils, optional_imports from plotly.io._orca import ensure_server from plotly.offline.offline import _get_jconfig, get_plotlyjs +from plotly.tools import return_figure_from_figure_or_data ipython_display = optional_imports.get_module('IPython.display') IPython = optional_imports.get_module('IPython') @@ -637,3 +638,20 @@ def render(self, fig_dict): validate=False, ) open_html_in_browser(html, self.using, self.new, self.autoraise) + + +class SphinxGalleryRenderer(ExternalRenderer): + + def render(self, fig_dict): + stack = inspect.stack() + # Name of script from which plot function was called is retrieved + try: + filename = stack[3].filename # let's hope this is robust... + except: #python 2 + filename = stack[3][1] + filename_root, _ = os.path.splitext(filename) + filename_html = filename_root + '.html' + filename_png = filename_root + '.png' + figure = return_figure_from_figure_or_data(fig_dict, True) + _ = write_html(fig_dict, file=filename_html) + write_image(figure, filename_png) diff --git a/packages/python/plotly/plotly/io/_renderers.py b/packages/python/plotly/plotly/io/_renderers.py index 5ff06e5ea14..42aeb366501 100644 --- a/packages/python/plotly/plotly/io/_renderers.py +++ b/packages/python/plotly/plotly/io/_renderers.py @@ -11,7 +11,8 @@ from plotly.io._base_renderers import ( MimetypeRenderer, ExternalRenderer, PlotlyRenderer, NotebookRenderer, KaggleRenderer, ColabRenderer, JsonRenderer, PngRenderer, JpegRenderer, - SvgRenderer, PdfRenderer, BrowserRenderer, IFrameRenderer) + SvgRenderer, PdfRenderer, BrowserRenderer, IFrameRenderer, + SphinxGalleryRenderer) from plotly.io._utils import validate_coerce_fig_to_dict ipython = optional_imports.get_module('IPython') @@ -393,6 +394,7 @@ def show(fig, renderer=None, validate=True, **kwargs): renderers['chrome'] = BrowserRenderer(config=config, using='chrome') renderers['chromium'] = BrowserRenderer(config=config, using='chromium') renderers['iframe'] = IFrameRenderer(config=config) +renderers['sphinx_gallery'] = SphinxGalleryRenderer() # Set default renderer # -------------------- diff --git a/plotly/io/_sg_scraper.py b/plotly/io/_sg_scraper.py new file mode 100644 index 00000000000..5e57c85a5f0 --- /dev/null +++ b/plotly/io/_sg_scraper.py @@ -0,0 +1,104 @@ +# This module defines an image scraper for sphinx-gallery +# https://sphinx-gallery.github.io/ +# which can be used by projects using plotly in their documentation. +import inspect, os + +import plotly +from glob import glob +import shutil + +plotly.io.renderers.default = 'sphinx_gallery' + + +def plotly_sg_scraper(block, block_vars, gallery_conf, **kwargs): + """Scrape Plotly figures for galleries of examples using + sphinx-gallery. + + Examples should use ``plotly.io.show()`` to display the figure with + the custom sphinx_gallery renderer. + + Since the sphinx_gallery renderer generates both html and static png + files, we simply crawl these files and give them the appropriate path. + + Parameters + ---------- + block : tuple + A tuple containing the (label, content, line_number) of the block. + block_vars : dict + Dict of block variables. + gallery_conf : dict + Contains the configuration of Sphinx-Gallery + **kwargs : dict + Additional keyword arguments to pass to + :meth:`~matplotlib.figure.Figure.savefig`, e.g. ``format='svg'``. + The ``format`` kwarg in particular is used to set the file extension + of the output file (currently only 'png' and 'svg' are supported). + + Returns + ------- + rst : str + The ReSTructuredText that will be rendered to HTML containing + the images. + + Notes + ----- + Add this function to the image scrapers + """ + examples_dirs = gallery_conf['examples_dirs'] + if isinstance(examples_dirs, (list, tuple)): + examples_dirs = examples_dirs[0] + pngs = sorted(glob(os.path.join(examples_dirs, + '*.png'))) + htmls = sorted(glob(os.path.join(examples_dirs, + '*.html'))) + image_path_iterator = block_vars['image_path_iterator'] + image_names = list() + seen = set() + for html, png in zip(htmls, pngs): + if png not in seen: + seen |= set(png) + this_image_path_png = next(image_path_iterator) + this_image_path_html = (os.path.splitext( + this_image_path_png)[0] + '.html') + image_names.append(this_image_path_html) + shutil.move(png, this_image_path_png) + shutil.move(html, this_image_path_html) + # Use the `figure_rst` helper function to generate rST for image files + return figure_rst(image_names, gallery_conf['src_dir']) + + +def figure_rst(figure_list, sources_dir): + """Generate RST for a list of PNG filenames. + + Depending on whether we have one or more figures, we use a + single rst call to 'image' or a horizontal list. + + Parameters + ---------- + figure_list : list + List of strings of the figures' absolute paths. + sources_dir : str + absolute path of Sphinx documentation sources + + Returns + ------- + images_rst : str + rst code to embed the images in the document + """ + + figure_paths = [os.path.relpath(figure_path, sources_dir) + .replace(os.sep, '/').lstrip('/') + for figure_path in figure_list] + images_rst = "" + figure_name = figure_paths[0] + ext = os.path.splitext(figure_name)[1] + figure_path = os.path.join('images', os.path.basename(figure_name)) + images_rst = SINGLE_HTML % figure_path + return images_rst + + +SINGLE_HTML = """ +.. raw:: html + :file: %s +""" + diff --git a/plotly/tests/test_orca/test_sg_scraper.py b/plotly/tests/test_orca/test_sg_scraper.py new file mode 100644 index 00000000000..e53ab6b59d7 --- /dev/null +++ b/plotly/tests/test_orca/test_sg_scraper.py @@ -0,0 +1,60 @@ +import plotly +import os +import shutil +import pytest + + +# Fixtures +# -------- +@pytest.fixture() +def setup(): + # Reset orca state + plotly.io.orca.config.restore_defaults(reset_server=False) + + +# Run setup before every test function in this file +pytestmark = pytest.mark.usefixtures("setup") + + +def execute_plotly_example(): + """ + Some typical code which would go inside a gallery example. + """ + import plotly.graph_objs as go + + # Create random data with numpy + import numpy as np + + N = 200 + random_x = np.random.randn(N) + random_y_0 = np.random.randn(N) + random_y_1 = np.random.randn(N) - 1 + + # Create traces + trace_0 = go.Scatter( + x=random_x, + y=random_y_0, + mode='markers', + name='Above', + ) + + fig = go.Figure(data=[trace_0]) + plotly.io.show(fig) + + +def test_scraper(): + from plotly.io._sg_scraper import plotly_sg_scraper + # test that monkey-patching worked ok + assert plotly.io.renderers.default == 'sphinx_gallery' + # Use dummy values for arguments of plotly_sg_scraper + block = '' # we don't need actually code + import tempfile + tempdir = tempfile.mkdtemp() + gallery_conf = {'src_dir':tempdir, + 'examples_dirs':'plotly/tests/test_orca'} + names = iter(['0', '1', '2']) + block_vars = {'image_path_iterator':names} + execute_plotly_example() + res = plotly_sg_scraper(block, block_vars, gallery_conf) + shutil.rmtree(tempdir) + assert ".. raw:: html" in res From 8d9abded2a6e35774350aa642df5b0fa78bb8f9f Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:29:30 +0200 Subject: [PATCH 10/21] Update _gantt.py --- .../plotly/plotly/figure_factory/_gantt.py | 396 ++++++++++++------ 1 file changed, 279 insertions(+), 117 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index e341655b9ce..a19f78f4bfd 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -2,6 +2,8 @@ from numbers import Number +import copy + from plotly import exceptions, optional_imports import plotly.colors as clrs from plotly.figure_factory import utils @@ -12,6 +14,22 @@ REQUIRED_GANTT_KEYS = ['Task', 'Start', 'Finish'] +def get_corner_points(x0, y0, x1, y1): + """ + Returns the corner points of a scatter rectangle + + :param x0: x-start + :param y0: y-lower + :param x1: x-end + :param y1: y-upper + :return: ([x], [y]), tuple of lists containing the x and y values + """ + + return ( + [x0, x1, x1, x0], + [y0, y0, y1, y1] + ) + def validate_gantt(df): """ Validates the inputted dataframe or list @@ -52,7 +70,8 @@ def validate_gantt(df): def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, - width, tasks=None, task_names=None, data=None, group_tasks=False): + width, tasks=None, task_names=None, data=None, group_tasks=False, + show_hover_fill=True, show_colorbar=True): """ Refer to create_gantt() for docstring """ @@ -71,15 +90,32 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "hoverinfo": hoverinfo } + + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], size=1), + "name": "", + "showlegend": False + } + # create the list of task names for index in range(len(tasks)): tn = tasks[index]['name'] @@ -97,7 +133,6 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -111,22 +146,53 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, if color_index >= len(colors): color_index = 0 tasks[index]['fillcolor'] = colors[color_index] - # Add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(tn) + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) + color_index += 1 + showlegend = show_colorbar + layout = dict( title=title, - showlegend=False, + showlegend=showlegend, height=height, width=width, shapes=[], @@ -170,15 +236,15 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, type='date' ) ) - layout['shapes'] = tasks - fig = graph_objs.Figure(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False): + task_names=None, data=None, group_tasks=False, + show_hover_fill=True): """ Refer to FigureFactory.create_gantt() for docstring """ @@ -198,16 +264,41 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "showlegend": False, + "hoverinfo" : hoverinfo } + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], + size=1), + "name": "", + "showlegend": False + } + + index_vals = [] + for row in range(len(tasks)): + if chart[row][index_col] not in index_vals: + index_vals.append(chart[row][index_col]) + + index_vals.sort() + # compute the color for task based on indexing column if isinstance(chart[0][index_col], Number): # check that colors has at least 2 colors @@ -235,7 +326,6 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -258,34 +348,55 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, intermed_color, clrs.label_rgb ) tasks[index]['fillcolor'] = intermed_color + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) + # relabel colors with 'rgb' colors = clrs.color_parser(colors, clrs.label_rgb) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data for colorscale visibility - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[index, index], - name='', - marker={'color': 'white', - 'colorscale': [[0, colors[0]], [1, colors[1]]], - 'showscale': True, - 'cmax': 100, - 'cmin': 0} - ) + scatter_data_dict["centers"]["marker"].update(dict( + colorscale = [[0, colors[0]], [1, colors[1]]], + showscale = True, + cmax = 100, + cmin = 0) ) if isinstance(chart[0][index_col], str): @@ -329,7 +440,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) + # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index @@ -341,36 +452,54 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, tasks[index]['fillcolor'] = index_vals_dict[ chart[index][index_col] ] + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - name='', - marker={'color': 'white'} + scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) + + # relabel colors with 'rgb' + colors = clrs.color_parser(colors, clrs.label_rgb) + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) + + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data to generate legend showlegend = True - for k, index_value in enumerate(index_vals): - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[k, k], - showlegend=True, - name=str(index_value), - hoverinfo='none', - marker=dict( - color=colors[k], - size=1 - ) - ) - ) + for k in scatter_data_dict: + if k != "centers": + scatter_data_dict[k]["showlegend"] = showlegend layout = dict( title=title, @@ -418,18 +547,18 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, type='date' ) ) - layout['shapes'] = tasks - fig = dict(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False): + task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Refer to FigureFactory.create_gantt() for docstring """ + if tasks is None: tasks = [] if task_names is None: @@ -446,14 +575,30 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, task['description'] = chart[index]['Description'] tasks.append(task) - shape_template = { - 'type': 'rect', - 'xref': 'x', - 'yref': 'y', - 'opacity': 1, - 'line': { - 'width': 0, - } + # create a scatter trace for every task group + scatter_data_dict = dict() + + if show_hover_fill: + hoverinfo = "name" + else: + hoverinfo = "skip" + + scatter_data_template = { + "x": [], + "y": [], + "mode": "none", + "fill": "toself", + "hoverinfo" : hoverinfo + } + + scatter_data_dict["centers"] = { + "x": [], + "y": [], + "mode": "markers", + "text": [], + "marker": dict(color=[], size=1), + "name": "", + "showlegend": False } index_vals = [] @@ -487,7 +632,6 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, for index in range(len(tasks)): tn = tasks[index]['name'] del tasks[index]['name'] - tasks[index].update(shape_template) # If group_tasks is True, all tasks with the same name belong # to the same row. @@ -498,37 +642,51 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, tasks[index]['y1'] = groupID + bar_width tasks[index]['fillcolor'] = colors[chart[index][index_col]] + color_id = tasks[index]['fillcolor'] + + if color_id not in scatter_data_dict: + scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + + scatter_data_dict[color_id]["fillcolor"] = color_id + + # if there are already values append the gap + if len(scatter_data_dict[color_id]["x"]) > 0: + # a gap on the scatterplot separates the rectangles from each other + scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["y"].append(None) - # add a line for hover text and autorange - entry = dict( - x=[tasks[index]['x0'], tasks[index]['x1']], - y=[groupID, groupID], - showlegend=False, - name='', - marker={'color': 'white'} + xs, ys = get_corner_points( + tasks[index]['x0'], + tasks[index]['y0'], + tasks[index]['x1'], + tasks[index]['y1'] ) + + scatter_data_dict[color_id]["x"] += xs + scatter_data_dict[color_id]["y"] += ys + + # append dummy markers for showing start and end of interval + scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) + scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["y"].append(groupID) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if "description" in tasks[index]: - entry['text'] = tasks[index]['description'] + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) del tasks[index]['description'] - data.append(entry) + else: + scatter_data_dict["centers"]["text"].append(None) + scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - # generate dummy data to generate legend showlegend = True - for k, index_value in enumerate(index_vals): - data.append( - dict( - x=[tasks[index]['x0'], tasks[index]['x0']], - y=[k, k], - showlegend=True, - hoverinfo='none', - name=str(index_value), - marker=dict( - color=colors[index_value], - size=1 - ) - ) - ) + + for index_value in index_vals: + scatter_data_dict[colors[index_value]]["name"] = str(index_value) + layout = dict( title=title, @@ -576,16 +734,15 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, type='date' ) ) - layout['shapes'] = tasks - fig = dict(data=data, layout=layout) + fig = dict(data=list(scatter_data_dict.values()), layout=layout) return fig def create_gantt(df, colors=None, index_col=None, show_colorbar=False, reverse_colors=False, title='Gantt Chart', bar_width=0.2, showgrid_x=False, showgrid_y=False, height=600, width=900, - tasks=None, task_names=None, data=None, group_tasks=False): + tasks=None, task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Returns figure for a gantt chart @@ -608,6 +765,8 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, index_col must be one of the keys in all the items of df. :param (bool) show_colorbar: determines if colorbar will be visible. Only applies if values in the index column are numeric. + :param (bool) show_hover_fill: enables/disables the hovertext for the + filled area of the chart. :param (bool) reverse_colors: reverses the order of selected colors :param (str) title: the title of the chart :param (float) bar_width: the width of the horizontal bars in the plot @@ -761,7 +920,8 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, fig = gantt( chart, colors, title, bar_width, showgrid_x, showgrid_y, height, width, tasks=None, task_names=None, data=None, - group_tasks=group_tasks + group_tasks=group_tasks, show_hover_fill=show_hover_fill, + show_colorbar=show_colorbar ) return fig else: @@ -769,13 +929,15 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, fig = gantt_colorscale( chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks + tasks=None, task_names=None, data=None, group_tasks=group_tasks, + show_hover_fill=show_hover_fill ) return fig else: fig = gantt_dict( chart, colors, title, index_col, show_colorbar, bar_width, showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks + tasks=None, task_names=None, data=None, group_tasks=group_tasks, + show_hover_fill=show_hover_fill ) return fig From f5ef8c31c61e00d2a789d7782b5bc5e5120369e8 Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:31:55 +0200 Subject: [PATCH 11/21] Gantt chart to scatter plot Gantt chart now uses scatter plots: - updating all the functions accordingly - unit tests updated - new param: show_hover_fill for hiding the text for the filled area --- packages/python/plotly/plotly/figure_factory/_gantt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index a19f78f4bfd..55a59eb4e47 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -745,7 +745,6 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, tasks=None, task_names=None, data=None, group_tasks=False, show_hover_fill=True): """ Returns figure for a gantt chart - :param (array|list) df: input data for gantt chart. Must be either a a dataframe or a list. If dataframe, the columns must include 'Task', 'Start' and 'Finish'. Other columns can be included and From aa372e70ce1d0a1b0d0464b889c3cc90682805a8 Mon Sep 17 00:00:00 2001 From: csabaszan Date: Mon, 15 Jul 2019 00:33:46 +0200 Subject: [PATCH 12/21] updated test for the scatter plot gantt chart --- .../test_figure_factory.py | 112 ++++++++---------- 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 4dd5b7a01c8..6a887229ef3 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -1335,71 +1335,55 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = {'data': [{'marker': {'color': 'white'}, + exp_gantt_chart = {'data': [{'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15'], + 'y': [0, 0, 1, 1], + 'mode': 'markers', + 'text': [None, None, None, None], + 'marker': {'color': ['rgb(31, 119, 180)', + 'rgb(31, 119, 180)', + 'rgb(255, 127, 14)', + 'rgb(255, 127, 14)'], + 'size': 1}, 'name': '', - 'type': 'scatter', - 'x': ['2009-01-01', '2009-02-30'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'type': 'scatter', - 'x': ['2009-03-05', '2009-04-15'], - 'y': [1, 1]}], - 'layout': {'height': 600, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(31, 119, 180)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-01-01', - 'x1': '2009-02-30', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 127, 14)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-03-05', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': 0.8, - 'y1': 1.2, - 'yref': 'y'}], - 'showlegend': False, - 'title': {'text': 'Gantt Chart'}, - 'width': 900, - 'xaxis': {'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'showgrid': False, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 3], - 'showgrid': False, - 'ticktext': ['Job A', 'Job B'], - 'tickvals': [0, 1], - 'zeroline': False}}} + 'showlegend': False}, + {'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], + 'y': [-0.2, -0.2, 0.2, 0.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(31, 119, 180)', + 'name': 'Job A'}, + {'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], + 'y': [0.8, 0.8, 1.2, 1.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(255, 127, 14)', + 'name': 'Job B'}], + 'layout': {'title': 'Gantt Chart', + 'showlegend': False, + 'height': 600, + 'width': 900, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': False, + 'ticktext': ['Job A', 'Job B'], + 'tickvals': [0, 1], + 'range': [-1, 3], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': False, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}}} self.assert_fig_equal(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) From f31ec647341cb5b0775f97c0631b5e2a16e2a989 Mon Sep 17 00:00:00 2001 From: CSK Date: Mon, 15 Jul 2019 12:55:29 +0200 Subject: [PATCH 13/21] tests fixed --- .../test_tools/test_figure_factory.py | 356 ++++++++---------- 1 file changed, 151 insertions(+), 205 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py index 4f0c27e4f7b..85f6033ee32 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1514,141 +1514,103 @@ def test_gannt_groups_and_descriptions(self): group_tasks=True ) - exp_gantt_chart = { - 'data': [{'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task A - 1', - 'x': ['2008-10-05', '2009-04-15'], - 'y': [2, 2]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task B - 1', - 'x': ['2008-12-06', '2009-03-15'], - 'y': [1, 1]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task C - 1', - 'x': ['2008-09-07', '2009-03-15'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task C - 2', - 'x': ['2009-05-08', '2009-04-15'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'showlegend': False, - 'text': 'Task A - 2', - 'x': ['2009-04-20', '2009-05-30'], - 'y': [2, 2]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(220, 0, 0)', 'size': 1}, - 'name': 'TA', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [0, 0]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(170, 14, 200)', 'size': 1}, - 'name': 'TB', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [1, 1]}, - {'hoverinfo': 'none', - 'marker': {'color': 'rgb(255, 230, 41)', 'size': 1}, - 'name': 'TC', - 'showlegend': True, - 'x': ['2009-04-20', '2009-04-20'], - 'y': [2, 2]}], - 'layout': {'height': 600, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(220, 0, 0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-10-05', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': 1.8, - 'y1': 2.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(170, 14, 200)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-12-06', - 'x1': '2009-03-15', - 'xref': 'x', - 'y0': 0.8, - 'y1': 1.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 230, 41)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2008-09-07', - 'x1': '2009-03-15', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(255, 230, 41)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-05-08', - 'x1': '2009-04-15', - 'xref': 'x', - 'y0': -0.2, - 'y1': 0.2, - 'yref': 'y'}, - {'fillcolor': 'rgb(220, 0, 0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2009-04-20', - 'x1': '2009-05-30', - 'xref': 'x', - 'y0': 1.8, - 'y1': 2.2, - 'yref': 'y'}], - 'showlegend': True, - 'title': 'Gantt Chart', - 'width': 900, - 'xaxis': {'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'showgrid': False, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 4], - 'showgrid': False, - 'ticktext': ['Task C', 'Task B', 'Task A'], - 'tickvals': [0, 1, 2], - 'zeroline': False}} - } + exp_gantt_chart = {'data': [{'x': ['2008-10-05', + '2009-04-15', + '2008-12-06', + '2009-03-15', + '2008-09-07', + '2009-03-15', + '2009-05-08', + '2009-04-15', + '2009-04-20', + '2009-05-30'], + 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], + 'mode': 'markers', + 'text': ['Task A - 1', + 'Task A - 1', + 'Task B - 1', + 'Task B - 1', + 'Task C - 1', + 'Task C - 1', + 'Task C - 2', + 'Task C - 2', + 'Task A - 2', + 'Task A - 2'], + 'marker': {'color': ['rgb(220, 0, 0)', + 'rgb(220, 0, 0)', + 'rgb(170, 14, 200)', + 'rgb(170, 14, 200)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(255, 230, 41)', + 'rgb(220, 0, 0)', + 'rgb(220, 0, 0)'], + 'size': 1}, + 'name': '', + 'showlegend': False}, + {'x': ['2008-10-05', + '2009-04-15', + '2009-04-15', + '2008-10-05', + '2008-10-05', + '2009-04-20', + '2009-05-30', + '2009-05-30', + '2009-04-20'], + 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(220, 0, 0)', + 'name': 'TA'}, + {'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], + 'y': [0.8, 0.8, 1.2, 1.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(170, 14, 200)', + 'name': 'TB'}, + {'x': ['2008-09-07', + '2009-03-15', + '2009-03-15', + '2008-09-07', + '2008-09-07', + '2009-05-08', + '2009-04-15', + '2009-04-15', + '2009-05-08'], + 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + 'mode': 'none', + 'fill': 'toself', + 'hoverinfo': 'name', + 'fillcolor': 'rgb(255, 230, 41)', + 'name': 'TC'}], + 'layout': {'title': 'Gantt Chart', + 'showlegend': True, + 'height': 600, + 'width': 900, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': False, + 'ticktext': ['Task C', 'Task B', 'Task A'], + 'tickvals': [0, 1, 2], + 'range': [-1, 4], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': False, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}} + } self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) @@ -1662,9 +1624,6 @@ def test_gannt_groups_and_descriptions(self): self.assertEqual(test_gantt_chart['data'][3], exp_gantt_chart['data'][3]) - self.assertEqual(test_gantt_chart['data'][4], - exp_gantt_chart['data'][4]) - self.assertEqual(test_gantt_chart['layout'], exp_gantt_chart['layout']) @@ -1687,73 +1646,57 @@ def test_gantt_all_args(self): height=500, width=500 ) - exp_gantt_chart = { - 'data': [{'marker': {'color': 'white'}, - 'name': '', - 'x': ['2010-01-01', '2011-02-02'], - 'y': [0, 0]}, - {'marker': {'color': 'white'}, - 'name': '', - 'x': ['2011-01-01', '2012-06-05'], - 'y': [1, 1]}], - 'layout': {'height': 500, - 'hovermode': 'closest', - 'shapes': [{'fillcolor': 'rgb(220.0, 220.0, 220.0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2010-01-01', - 'x1': '2011-02-02', - 'xref': 'x', - 'y0': -0.5, - 'y1': 0.5, - 'yref': 'y'}, - {'fillcolor': 'rgb(166.25, 167.5, 208.0)', - 'line': {'width': 0}, - 'opacity': 1, - 'type': 'rect', - 'x0': '2011-01-01', - 'x1': '2012-06-05', - 'xref': 'x', - 'y0': 0.5, - 'y1': 1.5, - 'yref': 'y'}], - 'showlegend': False, - 'title': 'Title', - 'width': 500, - 'xaxis': {'rangeselector': {'buttons': [ - {'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, - 'label': '1m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 6, - 'label': '6m', - 'step': 'month', - 'stepmode': 'backward'}, - {'count': 1, - 'label': 'YTD', - 'step': 'year', - 'stepmode': 'todate'}, - {'count': 1, - 'label': '1y', - 'step': 'year', - 'stepmode': 'backward'}, - {'step': 'all'} - ]}, - 'showgrid': True, - 'type': 'date', - 'zeroline': False}, - 'yaxis': {'autorange': False, - 'range': [-1, 3], - 'showgrid': True, - 'ticktext': ['Run', 'Fast'], - 'tickvals': [0, 1], - 'zeroline': False}} - } + exp_gantt_chart = {'data': [{'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05'], + 'y': [0, 0, 1, 1], + 'mode': 'markers', + 'text': [None, None, None, None], + 'marker': {'color': ['rgb(220.0, 220.0, 220.0)', + 'rgb(220.0, 220.0, 220.0)', + 'rgb(166.25, 167.5, 208.0)', + 'rgb(166.25, 167.5, 208.0)'], + 'size': 1}, + 'name': '', + 'showlegend': False}, + {'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], + 'y': [-0.5, -0.5, 0.5, 0.5], + 'mode': 'none', + 'fill': 'toself', + 'showlegend': False, + 'hoverinfo': 'name', + 'fillcolor': 'rgb(220.0, 220.0, 220.0)', + 'name': '0'}, + {'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], + 'y': [0.5, 0.5, 1.5, 1.5], + 'mode': 'none', + 'fill': 'toself', + 'showlegend': False, + 'hoverinfo': 'name', + 'fillcolor': 'rgb(166.25, 167.5, 208.0)', + 'name': '25'}], + 'layout': {'title': 'Title', + 'showlegend': False, + 'height': 500, + 'width': 500, + 'shapes': [], + 'hovermode': 'closest', + 'yaxis': {'showgrid': True, + 'ticktext': ['Run', 'Fast'], + 'tickvals': [0, 1], + 'range': [-1, 3], + 'autorange': False, + 'zeroline': False}, + 'xaxis': {'showgrid': True, + 'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'label': '1w', + 'step': 'day', + 'stepmode': 'backward'}, + {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, + {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, + {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, + {'step': 'all'}]}, + 'type': 'date'}}} self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) @@ -1761,6 +1704,9 @@ def test_gantt_all_args(self): self.assertEqual(test_gantt_chart['data'][1], exp_gantt_chart['data'][1]) + self.assertEqual(test_gantt_chart['data'][2], + exp_gantt_chart['data'][2]) + self.assertEqual(test_gantt_chart['layout'], exp_gantt_chart['layout']) From 09ec6afc79317b437815082ba232f0dc6fc4ad46 Mon Sep 17 00:00:00 2001 From: CSK Date: Mon, 15 Jul 2019 13:18:24 +0200 Subject: [PATCH 14/21] update for successful tests, once again --- packages/python/plotly/plotly/figure_factory/_gantt.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index 55a59eb4e47..5655c4eac9d 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -237,7 +237,8 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + #fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig @@ -548,7 +549,8 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + # fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig @@ -735,7 +737,8 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - fig = dict(data=list(scatter_data_dict.values()), layout=layout) + # fig = dict(data=list(scatter_data_dict.values()), layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) return fig From a5d806ad98a754b27b6dfea819946ed13caa4875 Mon Sep 17 00:00:00 2001 From: csaba Date: Tue, 16 Jul 2019 21:38:10 +0200 Subject: [PATCH 15/21] updated tests --- .../plotly/plotly/figure_factory/_gantt.py | 9 +- .../test_figure_factory.py | 83 +++++++++---------- 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index 5655c4eac9d..acc935550d6 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -237,8 +237,7 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, ) ) - #fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig @@ -549,8 +548,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - # fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig @@ -737,8 +735,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, ) ) - # fig = dict(data=list(scatter_data_dict.values()), layout=layout) - fig = dict(data=[scatter_data_dict[k] for k in scatter_data_dict], layout=layout) + fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) return fig diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 6a887229ef3..68a4cae01ae 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -1335,61 +1335,58 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = {'data': [{'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15'], - 'y': [0, 0, 1, 1], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': False, + 'yaxis': {'range': [-1, 3], + 'zeroline': False, + 'ticktext': ['Job A', 'Job B'], + 'tickvals': [0, 1], + 'autorange': False, + 'showgrid': False}, + 'title': 'Gantt Chart', + 'height': 600, + 'shapes': [], + 'width': 900, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': False}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': [None, None, None, None], 'marker': {'color': ['rgb(31, 119, 180)', 'rgb(31, 119, 180)', 'rgb(255, 127, 14)', 'rgb(255, 127, 14)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], - 'y': [-0.2, -0.2, 0.2, 0.2], + 'mode': 'markers', + 'y': [0, 0, 1, 1], + 'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15']}, + {'name': 'Job B', + 'fillcolor': 'rgb(255, 127, 14)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(31, 119, 180)', - 'name': 'Job A'}, - {'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], 'y': [0.8, 0.8, 1.2, 1.2], + 'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], + 'fill': 'toself'}, + {'name': 'Job A', + 'fillcolor': 'rgb(31, 119, 180)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(255, 127, 14)', - 'name': 'Job B'}], - 'layout': {'title': 'Gantt Chart', - 'showlegend': False, - 'height': 600, - 'width': 900, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': False, - 'ticktext': ['Job A', 'Job B'], - 'tickvals': [0, 1], - 'range': [-1, 3], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': False, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}}} - - self.assert_fig_equal(test_gantt_chart['data'][0], - exp_gantt_chart['data'][0]) + 'y': [-0.2, -0.2, 0.2, 0.2], + 'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], + 'fill': 'toself'}]} - self.assert_fig_equal(test_gantt_chart['layout'], - exp_gantt_chart['layout']) + self.assert_fig_equal(test_gantt_chart, + exp_gantt_chart) class TestViolin(NumpyTestUtilsMixin, TestCaseNoTemplate): From 441a0e6590ca6bd64fedd93eebcc0b631a6ca30d Mon Sep 17 00:00:00 2001 From: csaba Date: Tue, 16 Jul 2019 22:13:29 +0200 Subject: [PATCH 16/21] updated tests --- .../test_tools/test_figure_factory.py | 209 +++++++++--------- 1 file changed, 99 insertions(+), 110 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py index 85f6033ee32..dd3aff3f54a 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1514,18 +1514,32 @@ def test_gannt_groups_and_descriptions(self): group_tasks=True ) - exp_gantt_chart = {'data': [{'x': ['2008-10-05', - '2009-04-15', - '2008-12-06', - '2009-03-15', - '2008-09-07', - '2009-03-15', - '2009-05-08', - '2009-04-15', - '2009-04-20', - '2009-05-30'], - 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': True, + 'yaxis': {'range': [-1, 4], + 'zeroline': False, + 'ticktext': ['Task C', 'Task B', 'Task A'], + 'tickvals': [0, 1, 2], + 'autorange': False, + 'showgrid': False}, + 'title': 'Gantt Chart', + 'height': 600, + 'shapes': [], + 'width': 900, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': False}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': ['Task A - 1', 'Task A - 1', 'Task B - 1', @@ -1547,9 +1561,31 @@ def test_gannt_groups_and_descriptions(self): 'rgb(220, 0, 0)', 'rgb(220, 0, 0)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2008-10-05', + 'mode': 'markers', + 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], + 'x': ['2008-10-05', + '2009-04-15', + '2008-12-06', + '2009-03-15', + '2008-09-07', + '2009-03-15', + '2009-05-08', + '2009-04-15', + '2009-04-20', + '2009-05-30']}, + {'name': 'TB', + 'fillcolor': 'rgb(170, 14, 200)', + 'mode': 'none', + 'hoverinfo': 'name', + 'y': [0.8, 0.8, 1.2, 1.2], + 'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], + 'fill': 'toself'}, + {'name': 'TA', + 'fillcolor': 'rgb(220, 0, 0)', + 'mode': 'none', + 'hoverinfo': 'name', + 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + 'x': ['2008-10-05', '2009-04-15', '2009-04-15', '2008-10-05', @@ -1558,20 +1594,13 @@ def test_gannt_groups_and_descriptions(self): '2009-05-30', '2009-05-30', '2009-04-20'], - 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], - 'mode': 'none', - 'fill': 'toself', - 'hoverinfo': 'name', - 'fillcolor': 'rgb(220, 0, 0)', - 'name': 'TA'}, - {'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], - 'y': [0.8, 0.8, 1.2, 1.2], + 'fill': 'toself'}, + {'name': 'TC', + 'fillcolor': 'rgb(255, 230, 41)', 'mode': 'none', - 'fill': 'toself', 'hoverinfo': 'name', - 'fillcolor': 'rgb(170, 14, 200)', - 'name': 'TB'}, - {'x': ['2008-09-07', + 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + 'x': ['2008-09-07', '2009-03-15', '2009-03-15', '2008-09-07', @@ -1580,52 +1609,12 @@ def test_gannt_groups_and_descriptions(self): '2009-04-15', '2009-04-15', '2009-05-08'], - 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], - 'mode': 'none', - 'fill': 'toself', - 'hoverinfo': 'name', - 'fillcolor': 'rgb(255, 230, 41)', - 'name': 'TC'}], - 'layout': {'title': 'Gantt Chart', - 'showlegend': True, - 'height': 600, - 'width': 900, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': False, - 'ticktext': ['Task C', 'Task B', 'Task A'], - 'tickvals': [0, 1, 2], - 'range': [-1, 4], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': False, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}} - } + 'fill': 'toself'}]} - self.assertEqual(test_gantt_chart['data'][0], - exp_gantt_chart['data'][0]) - self.assertEqual(test_gantt_chart['data'][1], - exp_gantt_chart['data'][1]) - self.assertEqual(test_gantt_chart['data'][2], - exp_gantt_chart['data'][2]) - - self.assertEqual(test_gantt_chart['data'][3], - exp_gantt_chart['data'][3]) - - self.assertEqual(test_gantt_chart['layout'], - exp_gantt_chart['layout']) + self.assertDictEqual(test_gantt_chart['data'][0], + exp_gantt_chart['data'][0]) def test_gantt_all_args(self): @@ -1646,57 +1635,57 @@ def test_gantt_all_args(self): height=500, width=500 ) - exp_gantt_chart = {'data': [{'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05'], - 'y': [0, 0, 1, 1], - 'mode': 'markers', + exp_gantt_chart = {'layout': {'showlegend': False, + 'yaxis': {'range': [-1, 3], + 'zeroline': False, + 'ticktext': ['Run', 'Fast'], + 'tickvals': [0, 1], + 'autorange': False, + 'showgrid': True}, + 'title': 'Title', + 'height': 500, + 'shapes': [], + 'width': 500, + 'xaxis': {'zeroline': False, + 'rangeselector': {'buttons': [{'count': 7, + 'step': 'day', + 'stepmode': 'backward', + 'label': '1w'}, + {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, + {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, + {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, + {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, + {'step': 'all'}]}, + 'type': 'date', + 'showgrid': True}, + 'hovermode': 'closest'}, + 'data': [{'showlegend': False, + 'name': '', 'text': [None, None, None, None], 'marker': {'color': ['rgb(220.0, 220.0, 220.0)', 'rgb(220.0, 220.0, 220.0)', 'rgb(166.25, 167.5, 208.0)', 'rgb(166.25, 167.5, 208.0)'], 'size': 1}, - 'name': '', - 'showlegend': False}, - {'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], - 'y': [-0.5, -0.5, 0.5, 0.5], + 'mode': 'markers', + 'y': [0, 0, 1, 1], + 'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05']}, + {'showlegend': False, + 'name': '25', + 'fillcolor': 'rgb(166.25, 167.5, 208.0)', 'mode': 'none', - 'fill': 'toself', - 'showlegend': False, 'hoverinfo': 'name', - 'fillcolor': 'rgb(220.0, 220.0, 220.0)', - 'name': '0'}, - {'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], 'y': [0.5, 0.5, 1.5, 1.5], + 'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], + 'fill': 'toself'}, + {'showlegend': False, + 'name': '0', + 'fillcolor': 'rgb(220.0, 220.0, 220.0)', 'mode': 'none', - 'fill': 'toself', - 'showlegend': False, 'hoverinfo': 'name', - 'fillcolor': 'rgb(166.25, 167.5, 208.0)', - 'name': '25'}], - 'layout': {'title': 'Title', - 'showlegend': False, - 'height': 500, - 'width': 500, - 'shapes': [], - 'hovermode': 'closest', - 'yaxis': {'showgrid': True, - 'ticktext': ['Run', 'Fast'], - 'tickvals': [0, 1], - 'range': [-1, 3], - 'autorange': False, - 'zeroline': False}, - 'xaxis': {'showgrid': True, - 'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'label': '1w', - 'step': 'day', - 'stepmode': 'backward'}, - {'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'}, - {'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'}, - {'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, - {'step': 'all'}]}, - 'type': 'date'}}} + 'y': [-0.5, -0.5, 0.5, 0.5], + 'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], + 'fill': 'toself'}]} self.assertEqual(test_gantt_chart['data'][0], exp_gantt_chart['data'][0]) From 92c8fcef6ab5664e5286e5bffe8e0200de4dec09 Mon Sep 17 00:00:00 2001 From: CSK Date: Mon, 22 Jul 2019 10:20:16 +0200 Subject: [PATCH 17/21] code reformatted --- .../plotly/plotly/figure_factory/_gantt.py | 502 ++++++++++-------- .../test_figure_factory.py | 149 ++++-- .../test_tools/test_figure_factory.py | 497 ++++++++++------- 3 files changed, 695 insertions(+), 453 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index acc935550d6..eea768a9dae 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -9,9 +9,9 @@ from plotly.figure_factory import utils from plotly.graph_objs import graph_objs -pd = optional_imports.get_module('pandas') +pd = optional_imports.get_module("pandas") -REQUIRED_GANTT_KEYS = ['Task', 'Start', 'Finish'] +REQUIRED_GANTT_KEYS = ["Task", "Start", "Finish"] def get_corner_points(x0, y0, x1, y1): @@ -25,10 +25,8 @@ def get_corner_points(x0, y0, x1, y1): :return: ([x], [y]), tuple of lists containing the x and y values """ - return ( - [x0, x1, x1, x0], - [y0, y0, y1, y1] - ) + return ([x0, x1, x1, x0], [y0, y0, y1, y1]) + def validate_gantt(df): """ @@ -40,8 +38,7 @@ def validate_gantt(df): if key not in df: raise exceptions.PlotlyError( "The columns in your dataframe must include the " - "following keys: {0}".format( - ', '.join(REQUIRED_GANTT_KEYS)) + "following keys: {0}".format(", ".join(REQUIRED_GANTT_KEYS)) ) num_of_rows = len(df.index) @@ -56,22 +53,36 @@ def validate_gantt(df): # validate if df is a list if not isinstance(df, list): - raise exceptions.PlotlyError("You must input either a dataframe " - "or a list of dictionaries.") + raise exceptions.PlotlyError( + "You must input either a dataframe " "or a list of dictionaries." + ) # validate if df is empty if len(df) <= 0: - raise exceptions.PlotlyError("Your list is empty. It must contain " - "at least one dictionary.") + raise exceptions.PlotlyError( + "Your list is empty. It must contain " "at least one dictionary." + ) if not isinstance(df[0], dict): - raise exceptions.PlotlyError("Your list must only " - "include dictionaries.") + raise exceptions.PlotlyError("Your list must only " "include dictionaries.") return df -def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, - width, tasks=None, task_names=None, data=None, group_tasks=False, - show_hover_fill=True, show_colorbar=True): +def gantt( + chart, + colors, + title, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=False, + show_hover_fill=True, + show_colorbar=True, +): """ Refer to create_gantt() for docstring """ @@ -83,11 +94,13 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, data = [] for index in range(len(chart)): - task = dict(x0=chart[index]['Start'], - x1=chart[index]['Finish'], - name=chart[index]['Task']) - if 'Description' in chart[index]: - task['description'] = chart[index]['Description'] + task = dict( + x0=chart[index]["Start"], + x1=chart[index]["Finish"], + name=chart[index]["Task"], + ) + if "Description" in chart[index]: + task["description"] = chart[index]["Description"] tasks.append(task) # create a scatter trace for every task group @@ -103,7 +116,7 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, "y": [], "mode": "none", "fill": "toself", - "hoverinfo": hoverinfo + "hoverinfo": hoverinfo, } scatter_data_dict["centers"] = { @@ -113,12 +126,12 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, "text": [], "marker": dict(color=[], size=1), "name": "", - "showlegend": False + "showlegend": False, } # create the list of task names for index in range(len(tasks)): - tn = tasks[index]['name'] + tn = tasks[index]["name"] # Is added to task_names if group_tasks is set to False, # or if the option is used (True) it only adds them if the # name is not already in the list @@ -131,22 +144,22 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, color_index = 0 for index in range(len(tasks)): - tn = tasks[index]['name'] - del tasks[index]['name'] + tn = tasks[index]["name"] + del tasks[index]["name"] # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index if group_tasks: groupID = task_names.index(tn) - tasks[index]['y0'] = groupID - bar_width - tasks[index]['y1'] = groupID + bar_width + tasks[index]["y0"] = groupID - bar_width + tasks[index]["y1"] = groupID + bar_width # check if colors need to be looped if color_index >= len(colors): color_index = 0 - tasks[index]['fillcolor'] = colors[color_index] - color_id = tasks[index]['fillcolor'] + tasks[index]["fillcolor"] = colors[color_index] + color_id = tasks[index]["fillcolor"] if color_id not in scatter_data_dict: scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) @@ -157,22 +170,24 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, # if there are already values append the gap if len(scatter_data_dict[color_id]["x"]) > 0: # a gap on the scatterplot separates the rectangles from each other - scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["x"].append( + scatter_data_dict[color_id]["x"][-1] + ) scatter_data_dict[color_id]["y"].append(None) xs, ys = get_corner_points( - tasks[index]['x0'], - tasks[index]['y0'], - tasks[index]['x1'], - tasks[index]['y1'] + tasks[index]["x0"], + tasks[index]["y0"], + tasks[index]["x1"], + tasks[index]["y1"], ) scatter_data_dict[color_id]["x"] += xs scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) - scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) + scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["marker"]["color"].append(color_id) @@ -181,7 +196,7 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, if "description" in tasks[index]: scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - del tasks[index]['description'] + del tasks[index]["description"] else: scatter_data_dict["centers"]["text"].append(None) scatter_data_dict["centers"]["text"].append(None) @@ -196,7 +211,7 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, height=height, width=width, shapes=[], - hovermode='closest', + hovermode="closest", yaxis=dict( showgrid=showgrid_y, ticktext=task_names, @@ -209,42 +224,44 @@ def gantt(chart, colors, title, bar_width, showgrid_x, showgrid_y, height, showgrid=showgrid_x, zeroline=False, rangeselector=dict( - buttons=list([ - dict(count=7, - label='1w', - step='day', - stepmode='backward'), - dict(count=1, - label='1m', - step='month', - stepmode='backward'), - dict(count=6, - label='6m', - step='month', - stepmode='backward'), - dict(count=1, - label='YTD', - step='year', - stepmode='todate'), - dict(count=1, - label='1y', - step='year', - stepmode='backward'), - dict(step='all') - ]) + buttons=list( + [ + dict(count=7, label="1w", step="day", stepmode="backward"), + dict(count=1, label="1m", step="month", stepmode="backward"), + dict(count=6, label="6m", step="month", stepmode="backward"), + dict(count=1, label="YTD", step="year", stepmode="todate"), + dict(count=1, label="1y", step="year", stepmode="backward"), + dict(step="all"), + ] + ) ), - type='date' - ) + type="date", + ), ) - fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) + fig = dict( + data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout + ) return fig -def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, - showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False, - show_hover_fill=True): +def gantt_colorscale( + chart, + colors, + title, + index_col, + show_colorbar, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=False, + show_hover_fill=True, +): """ Refer to FigureFactory.create_gantt() for docstring """ @@ -257,11 +274,13 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, showlegend = False for index in range(len(chart)): - task = dict(x0=chart[index]['Start'], - x1=chart[index]['Finish'], - name=chart[index]['Task']) - if 'Description' in chart[index]: - task['description'] = chart[index]['Description'] + task = dict( + x0=chart[index]["Start"], + x1=chart[index]["Finish"], + name=chart[index]["Task"], + ) + if "Description" in chart[index]: + task["description"] = chart[index]["Description"] tasks.append(task) # create a scatter trace for every task group @@ -278,7 +297,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, "mode": "none", "fill": "toself", "showlegend": False, - "hoverinfo" : hoverinfo + "hoverinfo": hoverinfo, } scatter_data_dict["centers"] = { @@ -286,10 +305,9 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, "y": [], "mode": "markers", "text": [], - "marker": dict(color=[], - size=1), + "marker": dict(color=[], size=1), "name": "", - "showlegend": False + "showlegend": False, } index_vals = [] @@ -312,7 +330,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, # create the list of task names for index in range(len(tasks)): - tn = tasks[index]['name'] + tn = tasks[index]["name"] # Is added to task_names if group_tasks is set to False, # or if the option is used (True) it only adds them if the # name is not already in the list @@ -324,16 +342,16 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, task_names.reverse() for index in range(len(tasks)): - tn = tasks[index]['name'] - del tasks[index]['name'] + tn = tasks[index]["name"] + del tasks[index]["name"] # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index if group_tasks: groupID = task_names.index(tn) - tasks[index]['y0'] = groupID - bar_width - tasks[index]['y1'] = groupID + bar_width + tasks[index]["y0"] = groupID - bar_width + tasks[index]["y1"] = groupID + bar_width # unlabel color colors = clrs.color_parser(colors, clrs.unlabel_rgb) @@ -341,14 +359,10 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, highcolor = colors[1] intermed = (chart[index][index_col]) / 100.0 - intermed_color = clrs.find_intermediate_color( - lowcolor, highcolor, intermed - ) - intermed_color = clrs.color_parser( - intermed_color, clrs.label_rgb - ) - tasks[index]['fillcolor'] = intermed_color - color_id = tasks[index]['fillcolor'] + intermed_color = clrs.find_intermediate_color(lowcolor, highcolor, intermed) + intermed_color = clrs.color_parser(intermed_color, clrs.label_rgb) + tasks[index]["fillcolor"] = intermed_color + color_id = tasks[index]["fillcolor"] if color_id not in scatter_data_dict: scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) @@ -362,22 +376,24 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, # if there are already values append the gap if len(scatter_data_dict[color_id]["x"]) > 0: # a gap on the scatterplot separates the rectangles from each other - scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["x"].append( + scatter_data_dict[color_id]["x"][-1] + ) scatter_data_dict[color_id]["y"].append(None) xs, ys = get_corner_points( - tasks[index]['x0'], - tasks[index]['y0'], - tasks[index]['x1'], - tasks[index]['y1'] + tasks[index]["x0"], + tasks[index]["y0"], + tasks[index]["x1"], + tasks[index]["y1"], ) scatter_data_dict[color_id]["x"] += xs scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) - scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) + scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["marker"]["color"].append(color_id) @@ -386,17 +402,19 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, if "description" in tasks[index]: scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - del tasks[index]['description'] + del tasks[index]["description"] else: scatter_data_dict["centers"]["text"].append(None) scatter_data_dict["centers"]["text"].append(None) if show_colorbar is True: - scatter_data_dict["centers"]["marker"].update(dict( - colorscale = [[0, colors[0]], [1, colors[1]]], - showscale = True, - cmax = 100, - cmin = 0) + scatter_data_dict["centers"]["marker"].update( + dict( + colorscale=[[0, colors[0]], [1, colors[1]]], + showscale=True, + cmax=100, + cmin=0, + ) ) if isinstance(chart[0][index_col], str): @@ -426,7 +444,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, # create the list of task names for index in range(len(tasks)): - tn = tasks[index]['name'] + tn = tasks[index]["name"] # Is added to task_names if group_tasks is set to False, # or if the option is used (True) it only adds them if the # name is not already in the list @@ -438,21 +456,19 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, task_names.reverse() for index in range(len(tasks)): - tn = tasks[index]['name'] - del tasks[index]['name'] + tn = tasks[index]["name"] + del tasks[index]["name"] # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index if group_tasks: groupID = task_names.index(tn) - tasks[index]['y0'] = groupID - bar_width - tasks[index]['y1'] = groupID + bar_width + tasks[index]["y0"] = groupID - bar_width + tasks[index]["y1"] = groupID + bar_width - tasks[index]['fillcolor'] = index_vals_dict[ - chart[index][index_col] - ] - color_id = tasks[index]['fillcolor'] + tasks[index]["fillcolor"] = index_vals_dict[chart[index][index_col]] + color_id = tasks[index]["fillcolor"] if color_id not in scatter_data_dict: scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) @@ -466,22 +482,24 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, # if there are already values append the gap if len(scatter_data_dict[color_id]["x"]) > 0: # a gap on the scatterplot separates the rectangles from each other - scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["x"].append( + scatter_data_dict[color_id]["x"][-1] + ) scatter_data_dict[color_id]["y"].append(None) xs, ys = get_corner_points( - tasks[index]['x0'], - tasks[index]['y0'], - tasks[index]['x1'], - tasks[index]['y1'] + tasks[index]["x0"], + tasks[index]["y0"], + tasks[index]["x1"], + tasks[index]["y1"], ) scatter_data_dict[color_id]["x"] += xs scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) - scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) + scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["marker"]["color"].append(color_id) @@ -490,7 +508,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, if "description" in tasks[index]: scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - del tasks[index]['description'] + del tasks[index]["description"] else: scatter_data_dict["centers"]["text"].append(None) scatter_data_dict["centers"]["text"].append(None) @@ -507,7 +525,7 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, height=height, width=width, shapes=[], - hovermode='closest', + hovermode="closest", yaxis=dict( showgrid=showgrid_y, ticktext=task_names, @@ -520,41 +538,44 @@ def gantt_colorscale(chart, colors, title, index_col, show_colorbar, bar_width, showgrid=showgrid_x, zeroline=False, rangeselector=dict( - buttons=list([ - dict(count=7, - label='1w', - step='day', - stepmode='backward'), - dict(count=1, - label='1m', - step='month', - stepmode='backward'), - dict(count=6, - label='6m', - step='month', - stepmode='backward'), - dict(count=1, - label='YTD', - step='year', - stepmode='todate'), - dict(count=1, - label='1y', - step='year', - stepmode='backward'), - dict(step='all') - ]) + buttons=list( + [ + dict(count=7, label="1w", step="day", stepmode="backward"), + dict(count=1, label="1m", step="month", stepmode="backward"), + dict(count=6, label="6m", step="month", stepmode="backward"), + dict(count=1, label="YTD", step="year", stepmode="todate"), + dict(count=1, label="1y", step="year", stepmode="backward"), + dict(step="all"), + ] + ) ), - type='date' - ) + type="date", + ), ) - fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) + fig = dict( + data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout + ) return fig -def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, - showgrid_x, showgrid_y, height, width, tasks=None, - task_names=None, data=None, group_tasks=False, show_hover_fill=True): +def gantt_dict( + chart, + colors, + title, + index_col, + show_colorbar, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=False, + show_hover_fill=True, +): """ Refer to FigureFactory.create_gantt() for docstring """ @@ -568,11 +589,13 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, showlegend = False for index in range(len(chart)): - task = dict(x0=chart[index]['Start'], - x1=chart[index]['Finish'], - name=chart[index]['Task']) - if 'Description' in chart[index]: - task['description'] = chart[index]['Description'] + task = dict( + x0=chart[index]["Start"], + x1=chart[index]["Finish"], + name=chart[index]["Task"], + ) + if "Description" in chart[index]: + task["description"] = chart[index]["Description"] tasks.append(task) # create a scatter trace for every task group @@ -588,7 +611,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, "y": [], "mode": "none", "fill": "toself", - "hoverinfo" : hoverinfo + "hoverinfo": hoverinfo, } scatter_data_dict["centers"] = { @@ -598,7 +621,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, "text": [], "marker": dict(color=[], size=1), "name": "", - "showlegend": False + "showlegend": False, } index_vals = [] @@ -618,7 +641,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, # create the list of task names for index in range(len(tasks)): - tn = tasks[index]['name'] + tn = tasks[index]["name"] # Is added to task_names if group_tasks is set to False, # or if the option is used (True) it only adds them if the # name is not already in the list @@ -630,19 +653,19 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, task_names.reverse() for index in range(len(tasks)): - tn = tasks[index]['name'] - del tasks[index]['name'] + tn = tasks[index]["name"] + del tasks[index]["name"] # If group_tasks is True, all tasks with the same name belong # to the same row. groupID = index if group_tasks: groupID = task_names.index(tn) - tasks[index]['y0'] = groupID - bar_width - tasks[index]['y1'] = groupID + bar_width + tasks[index]["y0"] = groupID - bar_width + tasks[index]["y1"] = groupID + bar_width - tasks[index]['fillcolor'] = colors[chart[index][index_col]] - color_id = tasks[index]['fillcolor'] + tasks[index]["fillcolor"] = colors[chart[index][index_col]] + color_id = tasks[index]["fillcolor"] if color_id not in scatter_data_dict: scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) @@ -652,22 +675,24 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, # if there are already values append the gap if len(scatter_data_dict[color_id]["x"]) > 0: # a gap on the scatterplot separates the rectangles from each other - scatter_data_dict[color_id]["x"].append(scatter_data_dict[color_id]["x"][-1]) + scatter_data_dict[color_id]["x"].append( + scatter_data_dict[color_id]["x"][-1] + ) scatter_data_dict[color_id]["y"].append(None) xs, ys = get_corner_points( - tasks[index]['x0'], - tasks[index]['y0'], - tasks[index]['x1'], - tasks[index]['y1'] + tasks[index]["x0"], + tasks[index]["y0"], + tasks[index]["x1"], + tasks[index]["y1"], ) scatter_data_dict[color_id]["x"] += xs scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]['x0']) - scatter_data_dict["centers"]["x"].append(tasks[index]['x1']) + scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) + scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["y"].append(groupID) scatter_data_dict["centers"]["marker"]["color"].append(color_id) @@ -676,7 +701,7 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, if "description" in tasks[index]: scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - del tasks[index]['description'] + del tasks[index]["description"] else: scatter_data_dict["centers"]["text"].append(None) scatter_data_dict["centers"]["text"].append(None) @@ -687,14 +712,13 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, for index_value in index_vals: scatter_data_dict[colors[index_value]]["name"] = str(index_value) - layout = dict( title=title, showlegend=showlegend, height=height, width=width, shapes=[], - hovermode='closest', + hovermode="closest", yaxis=dict( showgrid=showgrid_y, ticktext=task_names, @@ -707,42 +731,45 @@ def gantt_dict(chart, colors, title, index_col, show_colorbar, bar_width, showgrid=showgrid_x, zeroline=False, rangeselector=dict( - buttons=list([ - dict(count=7, - label='1w', - step='day', - stepmode='backward'), - dict(count=1, - label='1m', - step='month', - stepmode='backward'), - dict(count=6, - label='6m', - step='month', - stepmode='backward'), - dict(count=1, - label='YTD', - step='year', - stepmode='todate'), - dict(count=1, - label='1y', - step='year', - stepmode='backward'), - dict(step='all') - ]) + buttons=list( + [ + dict(count=7, label="1w", step="day", stepmode="backward"), + dict(count=1, label="1m", step="month", stepmode="backward"), + dict(count=6, label="6m", step="month", stepmode="backward"), + dict(count=1, label="YTD", step="year", stepmode="todate"), + dict(count=1, label="1y", step="year", stepmode="backward"), + dict(step="all"), + ] + ) ), - type='date' - ) + type="date", + ), ) - fig = dict(data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout) + fig = dict( + data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout + ) return fig -def create_gantt(df, colors=None, index_col=None, show_colorbar=False, - reverse_colors=False, title='Gantt Chart', bar_width=0.2, - showgrid_x=False, showgrid_y=False, height=600, width=900, - tasks=None, task_names=None, data=None, group_tasks=False, show_hover_fill=True): +def create_gantt( + df, + colors=None, + index_col=None, + show_colorbar=False, + reverse_colors=False, + title="Gantt Chart", + bar_width=0.2, + showgrid_x=False, + showgrid_y=False, + height=600, + width=900, + tasks=None, + task_names=None, + data=None, + group_tasks=False, + show_hover_fill=True, +): """ Returns figure for a gantt chart :param (array|list) df: input data for gantt chart. Must be either a @@ -892,7 +919,8 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, "In order to use an indexing column and assign colors to " "the values of the index, you must choose an actual " "column name in the dataframe or key if a list of " - "dictionaries is being used.") + "dictionaries is being used." + ) # validate gantt index column index_list = [] @@ -902,9 +930,9 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, # Validate colors if isinstance(colors, dict): - colors = clrs.validate_colors_dict(colors, 'rgb') + colors = clrs.validate_colors_dict(colors, "rgb") else: - colors = clrs.validate_colors(colors, 'rgb') + colors = clrs.validate_colors(colors, "rgb") if reverse_colors is True: colors.reverse() @@ -917,26 +945,58 @@ def create_gantt(df, colors=None, index_col=None, show_colorbar=False, "assigning colors to particular values in a dictioanry." ) fig = gantt( - chart, colors, title, bar_width, showgrid_x, showgrid_y, - height, width, tasks=None, task_names=None, data=None, - group_tasks=group_tasks, show_hover_fill=show_hover_fill, - show_colorbar=show_colorbar + chart, + colors, + title, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=group_tasks, + show_hover_fill=show_hover_fill, + show_colorbar=show_colorbar, ) return fig else: if not isinstance(colors, dict): fig = gantt_colorscale( - chart, colors, title, index_col, show_colorbar, bar_width, - showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks, - show_hover_fill=show_hover_fill + chart, + colors, + title, + index_col, + show_colorbar, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=group_tasks, + show_hover_fill=show_hover_fill, ) return fig else: fig = gantt_dict( - chart, colors, title, index_col, show_colorbar, bar_width, - showgrid_x, showgrid_y, height, width, - tasks=None, task_names=None, data=None, group_tasks=group_tasks, - show_hover_fill=show_hover_fill + chart, + colors, + title, + index_col, + show_colorbar, + bar_width, + showgrid_x, + showgrid_y, + height, + width, + tasks=None, + task_names=None, + data=None, + group_tasks=group_tasks, + show_hover_fill=show_hover_fill, ) return fig diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index d35b842622a..9ddc6edb4e6 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -2042,58 +2042,103 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = {'layout': {'showlegend': False, - 'yaxis': {'range': [-1, 3], - 'zeroline': False, - 'ticktext': ['Job A', 'Job B'], - 'tickvals': [0, 1], - 'autorange': False, - 'showgrid': False}, - 'title': 'Gantt Chart', - 'height': 600, - 'shapes': [], - 'width': 900, - 'xaxis': {'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'step': 'day', - 'stepmode': 'backward', - 'label': '1w'}, - {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, - {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, - {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, - {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, - {'step': 'all'}]}, - 'type': 'date', - 'showgrid': False}, - 'hovermode': 'closest'}, - 'data': [{'showlegend': False, - 'name': '', - 'text': [None, None, None, None], - 'marker': {'color': ['rgb(31, 119, 180)', - 'rgb(31, 119, 180)', - 'rgb(255, 127, 14)', - 'rgb(255, 127, 14)'], - 'size': 1}, - 'mode': 'markers', - 'y': [0, 0, 1, 1], - 'x': ['2009-01-01', '2009-02-30', '2009-03-05', '2009-04-15']}, - {'name': 'Job B', - 'fillcolor': 'rgb(255, 127, 14)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [0.8, 0.8, 1.2, 1.2], - 'x': ['2009-03-05', '2009-04-15', '2009-04-15', '2009-03-05'], - 'fill': 'toself'}, - {'name': 'Job A', - 'fillcolor': 'rgb(31, 119, 180)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [-0.2, -0.2, 0.2, 0.2], - 'x': ['2009-01-01', '2009-02-30', '2009-02-30', '2009-01-01'], - 'fill': 'toself'}]} - - self.assert_fig_equal(test_gantt_chart, - exp_gantt_chart) + exp_gantt_chart = { + "layout": { + "showlegend": False, + "yaxis": { + "range": [-1, 3], + "zeroline": False, + "ticktext": ["Job A", "Job B"], + "tickvals": [0, 1], + "autorange": False, + "showgrid": False, + }, + "title": "Gantt Chart", + "height": 600, + "shapes": [], + "width": 900, + "xaxis": { + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "step": "day", + "stepmode": "backward", + "label": "1w", + }, + { + "count": 1, + "step": "month", + "stepmode": "backward", + "label": "1m", + }, + { + "count": 6, + "step": "month", + "stepmode": "backward", + "label": "6m", + }, + { + "count": 1, + "step": "year", + "stepmode": "todate", + "label": "YTD", + }, + { + "count": 1, + "step": "year", + "stepmode": "backward", + "label": "1y", + }, + {"step": "all"}, + ] + }, + "type": "date", + "showgrid": False, + }, + "hovermode": "closest", + }, + "data": [ + { + "showlegend": False, + "name": "", + "text": [None, None, None, None], + "marker": { + "color": [ + "rgb(31, 119, 180)", + "rgb(31, 119, 180)", + "rgb(255, 127, 14)", + "rgb(255, 127, 14)", + ], + "size": 1, + }, + "mode": "markers", + "y": [0, 0, 1, 1], + "x": ["2009-01-01", "2009-02-30", "2009-03-05", "2009-04-15"], + }, + { + "name": "Job B", + "fillcolor": "rgb(255, 127, 14)", + "mode": "none", + "hoverinfo": "name", + "y": [0.8, 0.8, 1.2, 1.2], + "x": ["2009-03-05", "2009-04-15", "2009-04-15", "2009-03-05"], + "fill": "toself", + }, + { + "name": "Job A", + "fillcolor": "rgb(31, 119, 180)", + "mode": "none", + "hoverinfo": "name", + "y": [-0.2, -0.2, 0.2, 0.2], + "x": ["2009-01-01", "2009-02-30", "2009-02-30", "2009-01-01"], + "fill": "toself", + }, + ], + } + + self.assert_fig_equal(test_gantt_chart, exp_gantt_chart) class TestViolin(NumpyTestUtilsMixin, TestCaseNoTemplate): diff --git a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py index 6fa672d2310..6b50b300be7 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1764,206 +1764,343 @@ def test_gannt_groups_and_descriptions(self): # check if grouped gantt chart matches with expected output df = [ - dict(Task='Task A', Description='Task A - 1', Start='2008-10-05', - Finish='2009-04-15', IndexCol='TA'), - dict(Task="Task B", Description='Task B - 1', Start='2008-12-06', - Finish='2009-03-15', IndexCol='TB'), - dict(Task="Task C", Description='Task C - 1', Start='2008-09-07', - Finish='2009-03-15', IndexCol='TC'), - dict(Task="Task C", Description='Task C - 2', Start='2009-05-08', - Finish='2009-04-15', IndexCol='TC'), - dict(Task="Task A", Description='Task A - 2', Start='2009-04-20', - Finish='2009-05-30', IndexCol='TA') + dict( + Task="Task A", + Description="Task A - 1", + Start="2008-10-05", + Finish="2009-04-15", + IndexCol="TA", + ), + dict( + Task="Task B", + Description="Task B - 1", + Start="2008-12-06", + Finish="2009-03-15", + IndexCol="TB", + ), + dict( + Task="Task C", + Description="Task C - 1", + Start="2008-09-07", + Finish="2009-03-15", + IndexCol="TC", + ), + dict( + Task="Task C", + Description="Task C - 2", + Start="2009-05-08", + Finish="2009-04-15", + IndexCol="TC", + ), + dict( + Task="Task A", + Description="Task A - 2", + Start="2009-04-20", + Finish="2009-05-30", + IndexCol="TA", + ), ] test_gantt_chart = ff.create_gantt( - df, colors=dict(TA='rgb(220, 0, 0)', TB='rgb(170, 14, 200)', - TC=(1, 0.9, 0.16)), show_colorbar=True, index_col='IndexCol', - group_tasks=True + df, + colors=dict(TA="rgb(220, 0, 0)", TB="rgb(170, 14, 200)", TC=(1, 0.9, 0.16)), + show_colorbar=True, + index_col="IndexCol", + group_tasks=True, ) - exp_gantt_chart = {'layout': {'showlegend': True, - 'yaxis': {'range': [-1, 4], - 'zeroline': False, - 'ticktext': ['Task C', 'Task B', 'Task A'], - 'tickvals': [0, 1, 2], - 'autorange': False, - 'showgrid': False}, - 'title': 'Gantt Chart', - 'height': 600, - 'shapes': [], - 'width': 900, - 'xaxis': {'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'step': 'day', - 'stepmode': 'backward', - 'label': '1w'}, - {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, - {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, - {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, - {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, - {'step': 'all'}]}, - 'type': 'date', - 'showgrid': False}, - 'hovermode': 'closest'}, - 'data': [{'showlegend': False, - 'name': '', - 'text': ['Task A - 1', - 'Task A - 1', - 'Task B - 1', - 'Task B - 1', - 'Task C - 1', - 'Task C - 1', - 'Task C - 2', - 'Task C - 2', - 'Task A - 2', - 'Task A - 2'], - 'marker': {'color': ['rgb(220, 0, 0)', - 'rgb(220, 0, 0)', - 'rgb(170, 14, 200)', - 'rgb(170, 14, 200)', - 'rgb(255, 230, 41)', - 'rgb(255, 230, 41)', - 'rgb(255, 230, 41)', - 'rgb(255, 230, 41)', - 'rgb(220, 0, 0)', - 'rgb(220, 0, 0)'], - 'size': 1}, - 'mode': 'markers', - 'y': [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], - 'x': ['2008-10-05', - '2009-04-15', - '2008-12-06', - '2009-03-15', - '2008-09-07', - '2009-03-15', - '2009-05-08', - '2009-04-15', - '2009-04-20', - '2009-05-30']}, - {'name': 'TB', - 'fillcolor': 'rgb(170, 14, 200)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [0.8, 0.8, 1.2, 1.2], - 'x': ['2008-12-06', '2009-03-15', '2009-03-15', '2008-12-06'], - 'fill': 'toself'}, - {'name': 'TA', - 'fillcolor': 'rgb(220, 0, 0)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], - 'x': ['2008-10-05', - '2009-04-15', - '2009-04-15', - '2008-10-05', - '2008-10-05', - '2009-04-20', - '2009-05-30', - '2009-05-30', - '2009-04-20'], - 'fill': 'toself'}, - {'name': 'TC', - 'fillcolor': 'rgb(255, 230, 41)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], - 'x': ['2008-09-07', - '2009-03-15', - '2009-03-15', - '2008-09-07', - '2008-09-07', - '2009-05-08', - '2009-04-15', - '2009-04-15', - '2009-05-08'], - 'fill': 'toself'}]} - - - - self.assertDictEqual(test_gantt_chart['data'][0], - exp_gantt_chart['data'][0]) + exp_gantt_chart = { + "layout": { + "showlegend": True, + "yaxis": { + "range": [-1, 4], + "zeroline": False, + "ticktext": ["Task C", "Task B", "Task A"], + "tickvals": [0, 1, 2], + "autorange": False, + "showgrid": False, + }, + "title": "Gantt Chart", + "height": 600, + "shapes": [], + "width": 900, + "xaxis": { + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "step": "day", + "stepmode": "backward", + "label": "1w", + }, + { + "count": 1, + "step": "month", + "stepmode": "backward", + "label": "1m", + }, + { + "count": 6, + "step": "month", + "stepmode": "backward", + "label": "6m", + }, + { + "count": 1, + "step": "year", + "stepmode": "todate", + "label": "YTD", + }, + { + "count": 1, + "step": "year", + "stepmode": "backward", + "label": "1y", + }, + {"step": "all"}, + ] + }, + "type": "date", + "showgrid": False, + }, + "hovermode": "closest", + }, + "data": [ + { + "showlegend": False, + "name": "", + "text": [ + "Task A - 1", + "Task A - 1", + "Task B - 1", + "Task B - 1", + "Task C - 1", + "Task C - 1", + "Task C - 2", + "Task C - 2", + "Task A - 2", + "Task A - 2", + ], + "marker": { + "color": [ + "rgb(220, 0, 0)", + "rgb(220, 0, 0)", + "rgb(170, 14, 200)", + "rgb(170, 14, 200)", + "rgb(255, 230, 41)", + "rgb(255, 230, 41)", + "rgb(255, 230, 41)", + "rgb(255, 230, 41)", + "rgb(220, 0, 0)", + "rgb(220, 0, 0)", + ], + "size": 1, + }, + "mode": "markers", + "y": [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], + "x": [ + "2008-10-05", + "2009-04-15", + "2008-12-06", + "2009-03-15", + "2008-09-07", + "2009-03-15", + "2009-05-08", + "2009-04-15", + "2009-04-20", + "2009-05-30", + ], + }, + { + "name": "TB", + "fillcolor": "rgb(170, 14, 200)", + "mode": "none", + "hoverinfo": "name", + "y": [0.8, 0.8, 1.2, 1.2], + "x": ["2008-12-06", "2009-03-15", "2009-03-15", "2008-12-06"], + "fill": "toself", + }, + { + "name": "TA", + "fillcolor": "rgb(220, 0, 0)", + "mode": "none", + "hoverinfo": "name", + "y": [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + "x": [ + "2008-10-05", + "2009-04-15", + "2009-04-15", + "2008-10-05", + "2008-10-05", + "2009-04-20", + "2009-05-30", + "2009-05-30", + "2009-04-20", + ], + "fill": "toself", + }, + { + "name": "TC", + "fillcolor": "rgb(255, 230, 41)", + "mode": "none", + "hoverinfo": "name", + "y": [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + "x": [ + "2008-09-07", + "2009-03-15", + "2009-03-15", + "2008-09-07", + "2008-09-07", + "2009-05-08", + "2009-04-15", + "2009-04-15", + "2009-05-08", + ], + "fill": "toself", + }, + ], + } + + self.assertDictEqual(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) def test_gantt_all_args(self): # check if gantt chart matches with expected output - df = [{'Task': 'Run', - 'Start': '2010-01-01', - 'Finish': '2011-02-02', - 'Complete': 0}, - {'Task': 'Fast', - 'Start': '2011-01-01', - 'Finish': '2012-06-05', - 'Complete': 25}] + df = [ + { + "Task": "Run", + "Start": "2010-01-01", + "Finish": "2011-02-02", + "Complete": 0, + }, + { + "Task": "Fast", + "Start": "2011-01-01", + "Finish": "2012-06-05", + "Complete": 25, + }, + ] test_gantt_chart = ff.create_gantt( - df, colors='Blues', index_col='Complete', reverse_colors=True, - title='Title', bar_width=0.5, showgrid_x=True, showgrid_y=True, - height=500, width=500 + df, + colors="Blues", + index_col="Complete", + reverse_colors=True, + title="Title", + bar_width=0.5, + showgrid_x=True, + showgrid_y=True, + height=500, + width=500, ) - exp_gantt_chart = {'layout': {'showlegend': False, - 'yaxis': {'range': [-1, 3], - 'zeroline': False, - 'ticktext': ['Run', 'Fast'], - 'tickvals': [0, 1], - 'autorange': False, - 'showgrid': True}, - 'title': 'Title', - 'height': 500, - 'shapes': [], - 'width': 500, - 'xaxis': {'zeroline': False, - 'rangeselector': {'buttons': [{'count': 7, - 'step': 'day', - 'stepmode': 'backward', - 'label': '1w'}, - {'count': 1, 'step': 'month', 'stepmode': 'backward', 'label': '1m'}, - {'count': 6, 'step': 'month', 'stepmode': 'backward', 'label': '6m'}, - {'count': 1, 'step': 'year', 'stepmode': 'todate', 'label': 'YTD'}, - {'count': 1, 'step': 'year', 'stepmode': 'backward', 'label': '1y'}, - {'step': 'all'}]}, - 'type': 'date', - 'showgrid': True}, - 'hovermode': 'closest'}, - 'data': [{'showlegend': False, - 'name': '', - 'text': [None, None, None, None], - 'marker': {'color': ['rgb(220.0, 220.0, 220.0)', - 'rgb(220.0, 220.0, 220.0)', - 'rgb(166.25, 167.5, 208.0)', - 'rgb(166.25, 167.5, 208.0)'], - 'size': 1}, - 'mode': 'markers', - 'y': [0, 0, 1, 1], - 'x': ['2010-01-01', '2011-02-02', '2011-01-01', '2012-06-05']}, - {'showlegend': False, - 'name': '25', - 'fillcolor': 'rgb(166.25, 167.5, 208.0)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [0.5, 0.5, 1.5, 1.5], - 'x': ['2011-01-01', '2012-06-05', '2012-06-05', '2011-01-01'], - 'fill': 'toself'}, - {'showlegend': False, - 'name': '0', - 'fillcolor': 'rgb(220.0, 220.0, 220.0)', - 'mode': 'none', - 'hoverinfo': 'name', - 'y': [-0.5, -0.5, 0.5, 0.5], - 'x': ['2010-01-01', '2011-02-02', '2011-02-02', '2010-01-01'], - 'fill': 'toself'}]} + exp_gantt_chart = { + "layout": { + "showlegend": False, + "yaxis": { + "range": [-1, 3], + "zeroline": False, + "ticktext": ["Run", "Fast"], + "tickvals": [0, 1], + "autorange": False, + "showgrid": True, + }, + "title": "Title", + "height": 500, + "shapes": [], + "width": 500, + "xaxis": { + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "step": "day", + "stepmode": "backward", + "label": "1w", + }, + { + "count": 1, + "step": "month", + "stepmode": "backward", + "label": "1m", + }, + { + "count": 6, + "step": "month", + "stepmode": "backward", + "label": "6m", + }, + { + "count": 1, + "step": "year", + "stepmode": "todate", + "label": "YTD", + }, + { + "count": 1, + "step": "year", + "stepmode": "backward", + "label": "1y", + }, + {"step": "all"}, + ] + }, + "type": "date", + "showgrid": True, + }, + "hovermode": "closest", + }, + "data": [ + { + "showlegend": False, + "name": "", + "text": [None, None, None, None], + "marker": { + "color": [ + "rgb(220.0, 220.0, 220.0)", + "rgb(220.0, 220.0, 220.0)", + "rgb(166.25, 167.5, 208.0)", + "rgb(166.25, 167.5, 208.0)", + ], + "size": 1, + }, + "mode": "markers", + "y": [0, 0, 1, 1], + "x": ["2010-01-01", "2011-02-02", "2011-01-01", "2012-06-05"], + }, + { + "showlegend": False, + "name": "25", + "fillcolor": "rgb(166.25, 167.5, 208.0)", + "mode": "none", + "hoverinfo": "name", + "y": [0.5, 0.5, 1.5, 1.5], + "x": ["2011-01-01", "2012-06-05", "2012-06-05", "2011-01-01"], + "fill": "toself", + }, + { + "showlegend": False, + "name": "0", + "fillcolor": "rgb(220.0, 220.0, 220.0)", + "mode": "none", + "hoverinfo": "name", + "y": [-0.5, -0.5, 0.5, 0.5], + "x": ["2010-01-01", "2011-02-02", "2011-02-02", "2010-01-01"], + "fill": "toself", + }, + ], + } self.assertEqual(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) self.assertEqual(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) - self.assertEqual(test_gantt_chart['data'][2], - exp_gantt_chart['data'][2]) + self.assertEqual(test_gantt_chart["data"][2], exp_gantt_chart["data"][2]) - self.assertEqual(test_gantt_chart['layout'], - exp_gantt_chart['layout']) + self.assertEqual(test_gantt_chart["layout"], exp_gantt_chart["layout"]) class Test2D_Density(TestCaseNoTemplate, NumpyTestUtilsMixin): From 25a92f91be5e7c3eed7286b8c67a04394f5dbd98 Mon Sep 17 00:00:00 2001 From: csaba Date: Sun, 28 Jul 2019 14:15:31 +0200 Subject: [PATCH 18/21] returning go.Figure instead of dict legendgroups for markers marker opacity is 0 --- .../plotly/plotly/figure_factory/_gantt.py | 182 +++--- .../test_figure_factory.py | 202 +++---- .../test_tools/test_figure_factory.py | 520 +++++++++--------- 3 files changed, 498 insertions(+), 406 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index eea768a9dae..93d518ba159 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -7,14 +7,14 @@ from plotly import exceptions, optional_imports import plotly.colors as clrs from plotly.figure_factory import utils -from plotly.graph_objs import graph_objs +import plotly.graph_objects as go pd = optional_imports.get_module("pandas") REQUIRED_GANTT_KEYS = ["Task", "Start", "Finish"] -def get_corner_points(x0, y0, x1, y1): +def _get_corner_points(x0, y0, x1, y1): """ Returns the corner points of a scatter rectangle @@ -105,6 +105,7 @@ def gantt( # create a scatter trace for every task group scatter_data_dict = dict() + marker_data_dict = dict() if show_hover_fill: hoverinfo = "name" @@ -119,14 +120,14 @@ def gantt( "hoverinfo": hoverinfo, } - scatter_data_dict["centers"] = { + marker_data_template = { "x": [], "y": [], "mode": "markers", "text": [], - "marker": dict(color=[], size=1), + "marker": dict(color="", size=1, opacity=0), "name": "", - "showlegend": False, + "showlegend": False } # create the list of task names @@ -166,6 +167,7 @@ def gantt( scatter_data_dict[color_id]["fillcolor"] = color_id scatter_data_dict[color_id]["name"] = str(tn) + scatter_data_dict[color_id]["legendgroup"] = color_id # if there are already values append the gap if len(scatter_data_dict[color_id]["x"]) > 0: @@ -175,7 +177,7 @@ def gantt( ) scatter_data_dict[color_id]["y"].append(None) - xs, ys = get_corner_points( + xs, ys = _get_corner_points( tasks[index]["x0"], tasks[index]["y0"], tasks[index]["x1"], @@ -186,20 +188,23 @@ def gantt( scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) - scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if color_id not in marker_data_dict: + marker_data_dict[color_id] = copy.deepcopy(marker_data_template) + marker_data_dict[color_id]["marker"]["color"] = color_id + marker_data_dict[color_id]["legendgroup"] = color_id + + marker_data_dict[color_id]["x"].append(tasks[index]["x0"]) + marker_data_dict[color_id]["x"].append(tasks[index]["x1"]) + marker_data_dict[color_id]["y"].append(groupID) + marker_data_dict[color_id]["y"].append(groupID) if "description" in tasks[index]: - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) del tasks[index]["description"] else: - scatter_data_dict["centers"]["text"].append(None) - scatter_data_dict["centers"]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) color_index += 1 @@ -239,9 +244,13 @@ def gantt( ), ) - fig = dict( - data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout - ) + data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)] + data += [marker_data_dict[k] for k in sorted(marker_data_dict)] + + # fig = dict( + # data=data, layout=layout + # ) + fig = go.Figure(data=data, layout=layout) return fig @@ -285,6 +294,8 @@ def gantt_colorscale( # create a scatter trace for every task group scatter_data_dict = dict() + # create scatter traces for the start- and endpoints + marker_data_dict = dict() if show_hover_fill: hoverinfo = "name" @@ -298,16 +309,18 @@ def gantt_colorscale( "fill": "toself", "showlegend": False, "hoverinfo": hoverinfo, + "legendgroup": "" } - scatter_data_dict["centers"] = { + marker_data_template = { "x": [], "y": [], "mode": "markers", "text": [], - "marker": dict(color=[], size=1), + "marker": dict(color="", size=1, opacity=0), "name": "", "showlegend": False, + "legendgroup": "", } index_vals = [] @@ -369,6 +382,7 @@ def gantt_colorscale( scatter_data_dict[color_id]["fillcolor"] = color_id scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) + scatter_data_dict[color_id]["legendgroup"] = color_id # relabel colors with 'rgb' colors = clrs.color_parser(colors, clrs.label_rgb) @@ -381,7 +395,7 @@ def gantt_colorscale( ) scatter_data_dict[color_id]["y"].append(None) - xs, ys = get_corner_points( + xs, ys = _get_corner_points( tasks[index]["x0"], tasks[index]["y0"], tasks[index]["x1"], @@ -392,23 +406,28 @@ def gantt_colorscale( scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) - scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if color_id not in marker_data_dict: + marker_data_dict[color_id] = copy.deepcopy(marker_data_template) + marker_data_dict[color_id]["marker"]["color"] = color_id + marker_data_dict[color_id]["legendgroup"] = color_id + + marker_data_dict[color_id]["x"].append(tasks[index]["x0"]) + marker_data_dict[color_id]["x"].append(tasks[index]["x1"]) + marker_data_dict[color_id]["y"].append(groupID) + marker_data_dict[color_id]["y"].append(groupID) if "description" in tasks[index]: - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) del tasks[index]["description"] else: - scatter_data_dict["centers"]["text"].append(None) - scatter_data_dict["centers"]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) + # add colorbar to one of the traces randomly just for display if show_colorbar is True: - scatter_data_dict["centers"]["marker"].update( + k = list(marker_data_dict.keys())[0] + marker_data_dict[k]["marker"].update( dict( colorscale=[[0, colors[0]], [1, colors[1]]], showscale=True, @@ -474,6 +493,7 @@ def gantt_colorscale( scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) scatter_data_dict[color_id]["fillcolor"] = color_id + scatter_data_dict[color_id]["legendgroup"] = color_id scatter_data_dict[color_id]["name"] = str(chart[index][index_col]) # relabel colors with 'rgb' @@ -487,7 +507,7 @@ def gantt_colorscale( ) scatter_data_dict[color_id]["y"].append(None) - xs, ys = get_corner_points( + xs, ys = _get_corner_points( tasks[index]["x0"], tasks[index]["y0"], tasks[index]["x1"], @@ -498,26 +518,39 @@ def gantt_colorscale( scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) - scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if color_id not in marker_data_dict: + marker_data_dict[color_id] = copy.deepcopy(marker_data_template) + marker_data_dict[color_id]["marker"]["color"] = color_id + marker_data_dict[color_id]["legendgroup"] = color_id + + marker_data_dict[color_id]["x"].append(tasks[index]["x0"]) + marker_data_dict[color_id]["x"].append(tasks[index]["x1"]) + marker_data_dict[color_id]["y"].append(groupID) + marker_data_dict[color_id]["y"].append(groupID) if "description" in tasks[index]: - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) del tasks[index]["description"] else: - scatter_data_dict["centers"]["text"].append(None) - scatter_data_dict["centers"]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) if show_colorbar is True: - showlegend = True - for k in scatter_data_dict: - if k != "centers": + showlegend = True + for k in scatter_data_dict: scatter_data_dict[k]["showlegend"] = showlegend + # add colorbar to one of the traces randomly just for display + # if show_colorbar is True: + # k = list(marker_data_dict.keys())[0] + # marker_data_dict[k]["marker"].update( + # dict( + # colorscale=[[0, colors[0]], [1, colors[1]]], + # showscale=True, + # cmax=100, + # cmin=0, + # ) + # ) layout = dict( title=title, @@ -553,9 +586,13 @@ def gantt_colorscale( ), ) - fig = dict( - data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout - ) + data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)] + data += [marker_data_dict[k] for k in sorted(marker_data_dict)] + + # fig = dict( + # data=data, layout=layout + # ) + fig = go.Figure(data=data, layout=layout) return fig @@ -600,6 +637,8 @@ def gantt_dict( # create a scatter trace for every task group scatter_data_dict = dict() + # create scatter traces for the start- and endpoints + marker_data_dict = dict() if show_hover_fill: hoverinfo = "name" @@ -612,16 +651,17 @@ def gantt_dict( "mode": "none", "fill": "toself", "hoverinfo": hoverinfo, + "legendgroup": "" } - scatter_data_dict["centers"] = { + marker_data_template = { "x": [], "y": [], "mode": "markers", "text": [], - "marker": dict(color=[], size=1), + "marker": dict(color="", size=1, opacity=0), "name": "", - "showlegend": False, + "showlegend": False } index_vals = [] @@ -670,6 +710,7 @@ def gantt_dict( if color_id not in scatter_data_dict: scatter_data_dict[color_id] = copy.deepcopy(scatter_data_template) + scatter_data_dict[color_id]["legendgroup"] = color_id scatter_data_dict[color_id]["fillcolor"] = color_id # if there are already values append the gap @@ -680,7 +721,7 @@ def gantt_dict( ) scatter_data_dict[color_id]["y"].append(None) - xs, ys = get_corner_points( + xs, ys = _get_corner_points( tasks[index]["x0"], tasks[index]["y0"], tasks[index]["x1"], @@ -691,20 +732,23 @@ def gantt_dict( scatter_data_dict[color_id]["y"] += ys # append dummy markers for showing start and end of interval - scatter_data_dict["centers"]["x"].append(tasks[index]["x0"]) - scatter_data_dict["centers"]["x"].append(tasks[index]["x1"]) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["y"].append(groupID) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) - scatter_data_dict["centers"]["marker"]["color"].append(color_id) + if color_id not in marker_data_dict: + marker_data_dict[color_id] = copy.deepcopy(marker_data_template) + marker_data_dict[color_id]["marker"]["color"] = color_id + marker_data_dict[color_id]["legendgroup"] = color_id + + marker_data_dict[color_id]["x"].append(tasks[index]["x0"]) + marker_data_dict[color_id]["x"].append(tasks[index]["x1"]) + marker_data_dict[color_id]["y"].append(groupID) + marker_data_dict[color_id]["y"].append(groupID) if "description" in tasks[index]: - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) - scatter_data_dict["centers"]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) + marker_data_dict[color_id]["text"].append(tasks[index]["description"]) del tasks[index]["description"] else: - scatter_data_dict["centers"]["text"].append(None) - scatter_data_dict["centers"]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) + marker_data_dict[color_id]["text"].append(None) if show_colorbar is True: showlegend = True @@ -746,9 +790,13 @@ def gantt_dict( ), ) - fig = dict( - data=[scatter_data_dict[k] for k in sorted(scatter_data_dict)], layout=layout - ) + data = [scatter_data_dict[k] for k in sorted(scatter_data_dict)] + data += [marker_data_dict[k] for k in sorted(marker_data_dict)] + + # fig = dict( + # data=data, layout=layout + # ) + fig = go.Figure(data=data, layout=layout) return fig diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 9ddc6edb4e6..2d009798059 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -2042,103 +2042,121 @@ def test_df_dataframe_all_args(self): test_gantt_chart = ff.create_gantt(df) - exp_gantt_chart = { - "layout": { - "showlegend": False, - "yaxis": { - "range": [-1, 3], - "zeroline": False, - "ticktext": ["Job A", "Job B"], - "tickvals": [0, 1], - "autorange": False, - "showgrid": False, - }, - "title": "Gantt Chart", - "height": 600, - "shapes": [], - "width": 900, - "xaxis": { - "zeroline": False, - "rangeselector": { - "buttons": [ - { - "count": 7, - "step": "day", - "stepmode": "backward", - "label": "1w", - }, - { - "count": 1, - "step": "month", - "stepmode": "backward", - "label": "1m", - }, - { - "count": 6, - "step": "month", - "stepmode": "backward", - "label": "6m", - }, - { - "count": 1, - "step": "year", - "stepmode": "todate", - "label": "YTD", - }, - { - "count": 1, - "step": "year", - "stepmode": "backward", - "label": "1y", - }, - {"step": "all"}, - ] + exp_gantt_chart = go.Figure( + **{ + "data": [ + { + "x": ("2009-03-05", "2009-04-15", "2009-04-15", "2009-03-05"), + "y": [0.8, 0.8, 1.2, 1.2], + "mode": "none", + "fill": "toself", + "hoverinfo": "name", + "fillcolor": "rgb(255, 127, 14)", + "name": "Job B", + "legendgroup": "rgb(255, 127, 14)", }, - "type": "date", - "showgrid": False, - }, - "hovermode": "closest", - }, - "data": [ - { + { + "x": ("2009-01-01", "2009-02-30", "2009-02-30", "2009-01-01"), + "y": [-0.2, -0.2, 0.2, 0.2], + "mode": "none", + "fill": "toself", + "hoverinfo": "name", + "fillcolor": "rgb(31, 119, 180)", + "name": "Job A", + "legendgroup": "rgb(31, 119, 180)", + }, + { + "x": ("2009-03-05", "2009-04-15"), + "y": [1, 1], + "mode": "markers", + "text": [None, None], + "marker": { + "color": "rgb(255, 127, 14)", + "size": 1, + "opacity": 0, + }, + "name": "", + "showlegend": False, + "legendgroup": "rgb(255, 127, 14)", + }, + { + "x": ("2009-01-01", "2009-02-30"), + "y": [0, 0], + "mode": "markers", + "text": [None, None], + "marker": { + "color": "rgb(31, 119, 180)", + "size": 1, + "opacity": 0, + }, + "name": "", + "showlegend": False, + "legendgroup": "rgb(31, 119, 180)", + }, + ], + "layout": { + "title": "Gantt Chart", "showlegend": False, - "name": "", - "text": [None, None, None, None], - "marker": { - "color": [ - "rgb(31, 119, 180)", - "rgb(31, 119, 180)", - "rgb(255, 127, 14)", - "rgb(255, 127, 14)", - ], - "size": 1, + "height": 600, + "width": 900, + "shapes": [], + "hovermode": "closest", + "yaxis": { + "showgrid": False, + "ticktext": ["Job A", "Job B"], + "tickvals": [0, 1], + "range": [-1, 3], + "autorange": False, + "zeroline": False, + }, + "xaxis": { + "showgrid": False, + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "label": "1w", + "step": "day", + "stepmode": "backward", + }, + { + "count": 1, + "label": "1m", + "step": "month", + "stepmode": "backward", + }, + { + "count": 6, + "label": "6m", + "step": "month", + "stepmode": "backward", + }, + { + "count": 1, + "label": "YTD", + "step": "year", + "stepmode": "todate", + }, + { + "count": 1, + "label": "1y", + "step": "year", + "stepmode": "backward", + }, + {"step": "all"}, + ] + }, + "type": "date", }, - "mode": "markers", - "y": [0, 0, 1, 1], - "x": ["2009-01-01", "2009-02-30", "2009-03-05", "2009-04-15"], - }, - { - "name": "Job B", - "fillcolor": "rgb(255, 127, 14)", - "mode": "none", - "hoverinfo": "name", - "y": [0.8, 0.8, 1.2, 1.2], - "x": ["2009-03-05", "2009-04-15", "2009-04-15", "2009-03-05"], - "fill": "toself", - }, - { - "name": "Job A", - "fillcolor": "rgb(31, 119, 180)", - "mode": "none", - "hoverinfo": "name", - "y": [-0.2, -0.2, 0.2, 0.2], - "x": ["2009-01-01", "2009-02-30", "2009-02-30", "2009-01-01"], - "fill": "toself", }, - ], - } + } + ) - self.assert_fig_equal(test_gantt_chart, exp_gantt_chart) + self.assert_fig_equal(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) + self.assert_fig_equal(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) + self.assert_fig_equal(test_gantt_chart["data"][2], exp_gantt_chart["data"][2]) + self.assert_fig_equal(test_gantt_chart["data"][3], exp_gantt_chart["data"][3]) class TestViolin(NumpyTestUtilsMixin, TestCaseNoTemplate): diff --git a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py index 6b50b300be7..35b9fed4c10 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_tools/test_figure_factory.py @@ -1554,7 +1554,7 @@ def test_table_with_index(self): self.assert_fig_equal(index_table["layout"], exp_index_table["layout"]) -class TestGantt(TestCase): +class TestGantt(TestCaseNoTemplate, NumpyTestUtilsMixin): def test_validate_gantt(self): # validate the basic gantt inputs @@ -1809,160 +1809,171 @@ def test_gannt_groups_and_descriptions(self): group_tasks=True, ) - exp_gantt_chart = { - "layout": { - "showlegend": True, - "yaxis": { - "range": [-1, 4], - "zeroline": False, - "ticktext": ["Task C", "Task B", "Task A"], - "tickvals": [0, 1, 2], - "autorange": False, - "showgrid": False, - }, - "title": "Gantt Chart", - "height": 600, - "shapes": [], - "width": 900, - "xaxis": { - "zeroline": False, - "rangeselector": { - "buttons": [ - { - "count": 7, - "step": "day", - "stepmode": "backward", - "label": "1w", - }, - { - "count": 1, - "step": "month", - "stepmode": "backward", - "label": "1m", - }, - { - "count": 6, - "step": "month", - "stepmode": "backward", - "label": "6m", - }, - { - "count": 1, - "step": "year", - "stepmode": "todate", - "label": "YTD", - }, - { - "count": 1, - "step": "year", - "stepmode": "backward", - "label": "1y", - }, - {"step": "all"}, - ] + exp_gantt_chart = graph_objs.Figure( + **{ + "layout": { + "showlegend": True, + "yaxis": { + "range": [-1, 4], + "zeroline": False, + "ticktext": ["Task C", "Task B", "Task A"], + "tickvals": [0, 1, 2], + "autorange": False, + "showgrid": False, + }, + "title": "Gantt Chart", + "height": 600, + "shapes": [], + "width": 900, + "xaxis": { + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "step": "day", + "stepmode": "backward", + "label": "1w", + }, + { + "count": 1, + "step": "month", + "stepmode": "backward", + "label": "1m", + }, + { + "count": 6, + "step": "month", + "stepmode": "backward", + "label": "6m", + }, + { + "count": 1, + "step": "year", + "stepmode": "todate", + "label": "YTD", + }, + { + "count": 1, + "step": "year", + "stepmode": "backward", + "label": "1y", + }, + {"step": "all"}, + ] + }, + "type": "date", + "showgrid": False, }, - "type": "date", - "showgrid": False, + "hovermode": "closest", }, - "hovermode": "closest", - }, - "data": [ - { - "showlegend": False, - "name": "", - "text": [ - "Task A - 1", - "Task A - 1", - "Task B - 1", - "Task B - 1", - "Task C - 1", - "Task C - 1", - "Task C - 2", - "Task C - 2", - "Task A - 2", - "Task A - 2", - ], - "marker": { - "color": [ - "rgb(220, 0, 0)", - "rgb(220, 0, 0)", - "rgb(170, 14, 200)", - "rgb(170, 14, 200)", - "rgb(255, 230, 41)", - "rgb(255, 230, 41)", - "rgb(255, 230, 41)", - "rgb(255, 230, 41)", - "rgb(220, 0, 0)", - "rgb(220, 0, 0)", + "data": [ + { + "legendgroup": "rgb(170, 14, 200)", + "name": "TB", + "fillcolor": "rgb(170, 14, 200)", + "mode": "none", + "hoverinfo": "name", + "y": [0.8, 0.8, 1.2, 1.2], + "x": ["2008-12-06", "2009-03-15", "2009-03-15", "2008-12-06"], + "fill": "toself", + }, + { + "legendgroup": "rgb(220, 0, 0)", + "name": "TA", + "fillcolor": "rgb(220, 0, 0)", + "mode": "none", + "hoverinfo": "name", + "y": [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], + "x": [ + "2008-10-05", + "2009-04-15", + "2009-04-15", + "2008-10-05", + "2008-10-05", + "2009-04-20", + "2009-05-30", + "2009-05-30", + "2009-04-20", ], - "size": 1, + "fill": "toself", }, - "mode": "markers", - "y": [2, 2, 1, 1, 0, 0, 0, 0, 2, 2], - "x": [ - "2008-10-05", - "2009-04-15", - "2008-12-06", - "2009-03-15", - "2008-09-07", - "2009-03-15", - "2009-05-08", - "2009-04-15", - "2009-04-20", - "2009-05-30", - ], - }, - { - "name": "TB", - "fillcolor": "rgb(170, 14, 200)", - "mode": "none", - "hoverinfo": "name", - "y": [0.8, 0.8, 1.2, 1.2], - "x": ["2008-12-06", "2009-03-15", "2009-03-15", "2008-12-06"], - "fill": "toself", - }, - { - "name": "TA", - "fillcolor": "rgb(220, 0, 0)", - "mode": "none", - "hoverinfo": "name", - "y": [1.8, 1.8, 2.2, 2.2, None, 1.8, 1.8, 2.2, 2.2], - "x": [ - "2008-10-05", - "2009-04-15", - "2009-04-15", - "2008-10-05", - "2008-10-05", - "2009-04-20", - "2009-05-30", - "2009-05-30", - "2009-04-20", - ], - "fill": "toself", - }, - { - "name": "TC", - "fillcolor": "rgb(255, 230, 41)", - "mode": "none", - "hoverinfo": "name", - "y": [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], - "x": [ - "2008-09-07", - "2009-03-15", - "2009-03-15", - "2008-09-07", - "2008-09-07", - "2009-05-08", - "2009-04-15", - "2009-04-15", - "2009-05-08", - ], - "fill": "toself", - }, - ], - } + { + "legendgroup": "rgb(255, 230, 41)", + "name": "TC", + "fillcolor": "rgb(255, 230, 41)", + "mode": "none", + "hoverinfo": "name", + "y": [-0.2, -0.2, 0.2, 0.2, None, -0.2, -0.2, 0.2, 0.2], + "x": [ + "2008-09-07", + "2009-03-15", + "2009-03-15", + "2008-09-07", + "2008-09-07", + "2009-05-08", + "2009-04-15", + "2009-04-15", + "2009-05-08", + ], + "fill": "toself", + }, + { + "showlegend": False, + "legendgroup": "rgb(170, 14, 200)", + "name": "", + "text": ["Task B - 1", "Task B - 1"], + "y": [1, 1], + "mode": "markers", + "marker": { + "opacity": 0, + "color": "rgb(170, 14, 200)", + "size": 1, + }, + "x": ["2008-12-06", "2009-03-15"], + }, + { + "showlegend": False, + "legendgroup": "rgb(220, 0, 0)", + "name": "", + "text": [ + "Task A - 1", + "Task A - 1", + "Task A - 2", + "Task A - 2", + ], + "y": [2, 2, 2, 2], + "mode": "markers", + "marker": {"opacity": 0, "color": "rgb(220, 0, 0)", "size": 1}, + "x": ["2008-10-05", "2009-04-15", "2009-04-20", "2009-05-30"], + }, + { + "showlegend": False, + "legendgroup": "rgb(255, 230, 41)", + "name": "", + "text": [ + "Task C - 1", + "Task C - 1", + "Task C - 2", + "Task C - 2", + ], + "y": [0, 0, 0, 0], + "mode": "markers", + "marker": { + "opacity": 0, + "color": "rgb(255, 230, 41)", + "size": 1, + }, + "x": ["2008-09-07", "2009-03-15", "2009-05-08", "2009-04-15"], + }, + ], + } + ) - self.assertDictEqual(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) + self.assert_fig_equal(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) + self.assert_fig_equal(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) + self.assert_fig_equal(test_gantt_chart["data"][2], exp_gantt_chart["data"][2]) + self.assert_fig_equal(test_gantt_chart["data"][3], exp_gantt_chart["data"][3]) def test_gantt_all_args(self): @@ -1996,111 +2007,126 @@ def test_gantt_all_args(self): width=500, ) - exp_gantt_chart = { - "layout": { - "showlegend": False, - "yaxis": { - "range": [-1, 3], - "zeroline": False, - "ticktext": ["Run", "Fast"], - "tickvals": [0, 1], - "autorange": False, - "showgrid": True, - }, - "title": "Title", - "height": 500, - "shapes": [], - "width": 500, - "xaxis": { - "zeroline": False, - "rangeselector": { - "buttons": [ - { - "count": 7, - "step": "day", - "stepmode": "backward", - "label": "1w", - }, - { - "count": 1, - "step": "month", - "stepmode": "backward", - "label": "1m", - }, - { - "count": 6, - "step": "month", - "stepmode": "backward", - "label": "6m", - }, - { - "count": 1, - "step": "year", - "stepmode": "todate", - "label": "YTD", - }, - { - "count": 1, - "step": "year", - "stepmode": "backward", - "label": "1y", - }, - {"step": "all"}, - ] + exp_gantt_chart = graph_objs.Figure( + **{ + "data": [ + { + "x": ["2011-01-01", "2012-06-05", "2012-06-05", "2011-01-01"], + "y": [0.5, 0.5, 1.5, 1.5], + "mode": "none", + "fill": "toself", + "showlegend": False, + "hoverinfo": "name", + "legendgroup": "rgb(166.25, 167.5, 208.0)", + "fillcolor": "rgb(166.25, 167.5, 208.0)", + "name": "25", }, - "type": "date", - "showgrid": True, - }, - "hovermode": "closest", - }, - "data": [ - { - "showlegend": False, - "name": "", - "text": [None, None, None, None], - "marker": { - "color": [ - "rgb(220.0, 220.0, 220.0)", - "rgb(220.0, 220.0, 220.0)", - "rgb(166.25, 167.5, 208.0)", - "rgb(166.25, 167.5, 208.0)", - ], - "size": 1, + { + "x": ["2010-01-01", "2011-02-02", "2011-02-02", "2010-01-01"], + "y": [-0.5, -0.5, 0.5, 0.5], + "mode": "none", + "fill": "toself", + "showlegend": False, + "hoverinfo": "name", + "legendgroup": "rgb(220.0, 220.0, 220.0)", + "fillcolor": "rgb(220.0, 220.0, 220.0)", + "name": "0", }, - "mode": "markers", - "y": [0, 0, 1, 1], - "x": ["2010-01-01", "2011-02-02", "2011-01-01", "2012-06-05"], - }, - { - "showlegend": False, - "name": "25", - "fillcolor": "rgb(166.25, 167.5, 208.0)", - "mode": "none", - "hoverinfo": "name", - "y": [0.5, 0.5, 1.5, 1.5], - "x": ["2011-01-01", "2012-06-05", "2012-06-05", "2011-01-01"], - "fill": "toself", - }, - { + { + "x": ["2011-01-01", "2012-06-05"], + "y": [1, 1], + "mode": "markers", + "text": [None, None], + "marker": { + "color": "rgb(166.25, 167.5, 208.0)", + "size": 1, + "opacity": 0, + }, + "name": "", + "showlegend": False, + "legendgroup": "rgb(166.25, 167.5, 208.0)", + }, + { + "x": ["2010-01-01", "2011-02-02"], + "y": [0, 0], + "mode": "markers", + "text": [None, None], + "marker": { + "color": "rgb(220.0, 220.0, 220.0)", + "size": 1, + "opacity": 0, + }, + "name": "", + "showlegend": False, + "legendgroup": "rgb(220.0, 220.0, 220.0)", + }, + ], + "layout": { + "title": "Title", "showlegend": False, - "name": "0", - "fillcolor": "rgb(220.0, 220.0, 220.0)", - "mode": "none", - "hoverinfo": "name", - "y": [-0.5, -0.5, 0.5, 0.5], - "x": ["2010-01-01", "2011-02-02", "2011-02-02", "2010-01-01"], - "fill": "toself", + "height": 500, + "width": 500, + "shapes": [], + "hovermode": "closest", + "yaxis": { + "showgrid": True, + "ticktext": ["Run", "Fast"], + "tickvals": [0, 1], + "range": [-1, 3], + "autorange": False, + "zeroline": False, + }, + "xaxis": { + "showgrid": True, + "zeroline": False, + "rangeselector": { + "buttons": [ + { + "count": 7, + "label": "1w", + "step": "day", + "stepmode": "backward", + }, + { + "count": 1, + "label": "1m", + "step": "month", + "stepmode": "backward", + }, + { + "count": 6, + "label": "6m", + "step": "month", + "stepmode": "backward", + }, + { + "count": 1, + "label": "YTD", + "step": "year", + "stepmode": "todate", + }, + { + "count": 1, + "label": "1y", + "step": "year", + "stepmode": "backward", + }, + {"step": "all"}, + ] + }, + "type": "date", + }, }, - ], - } + } + ) - self.assertEqual(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) + self.assert_fig_equal(test_gantt_chart["data"][0], exp_gantt_chart["data"][0]) - self.assertEqual(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) + self.assert_fig_equal(test_gantt_chart["data"][1], exp_gantt_chart["data"][1]) - self.assertEqual(test_gantt_chart["data"][2], exp_gantt_chart["data"][2]) + self.assert_fig_equal(test_gantt_chart["data"][2], exp_gantt_chart["data"][2]) - self.assertEqual(test_gantt_chart["layout"], exp_gantt_chart["layout"]) + self.assert_fig_equal(test_gantt_chart["layout"], exp_gantt_chart["layout"]) class Test2D_Density(TestCaseNoTemplate, NumpyTestUtilsMixin): From 49528edf62182d92c0dbe4e77293f950ee767c35 Mon Sep 17 00:00:00 2001 From: csaba Date: Sun, 28 Jul 2019 14:34:52 +0200 Subject: [PATCH 19/21] reformat w black --- .../python/plotly/plotly/figure_factory/_gantt.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index 93d518ba159..ca0a182f766 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -127,7 +127,7 @@ def gantt( "text": [], "marker": dict(color="", size=1, opacity=0), "name": "", - "showlegend": False + "showlegend": False, } # create the list of task names @@ -309,7 +309,7 @@ def gantt_colorscale( "fill": "toself", "showlegend": False, "hoverinfo": hoverinfo, - "legendgroup": "" + "legendgroup": "", } marker_data_template = { @@ -537,9 +537,9 @@ def gantt_colorscale( marker_data_dict[color_id]["text"].append(None) if show_colorbar is True: - showlegend = True - for k in scatter_data_dict: - scatter_data_dict[k]["showlegend"] = showlegend + showlegend = True + for k in scatter_data_dict: + scatter_data_dict[k]["showlegend"] = showlegend # add colorbar to one of the traces randomly just for display # if show_colorbar is True: # k = list(marker_data_dict.keys())[0] @@ -651,7 +651,7 @@ def gantt_dict( "mode": "none", "fill": "toself", "hoverinfo": hoverinfo, - "legendgroup": "" + "legendgroup": "", } marker_data_template = { @@ -661,7 +661,7 @@ def gantt_dict( "text": [], "marker": dict(color="", size=1, opacity=0), "name": "", - "showlegend": False + "showlegend": False, } index_vals = [] From 228bdcf301ecc9edf43d50739893f870a06f47f1 Mon Sep 17 00:00:00 2001 From: csaba Date: Thu, 15 Aug 2019 18:46:27 +0200 Subject: [PATCH 20/21] default values for height and width of Gantt-chart are replaced with None the created figure is now responsive --- packages/python/plotly/plotly/figure_factory/_gantt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index ca0a182f766..e15c2daaa21 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -810,8 +810,8 @@ def create_gantt( bar_width=0.2, showgrid_x=False, showgrid_y=False, - height=600, - width=900, + height=None, + width=None, tasks=None, task_names=None, data=None, From 83ed3adf0536fa77a27e64a0776af7eb3cc0092d Mon Sep 17 00:00:00 2001 From: csaba Date: Sat, 17 Aug 2019 15:48:08 +0200 Subject: [PATCH 21/21] default height is set to 600 --- packages/python/plotly/plotly/figure_factory/_gantt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index e15c2daaa21..8af7a435381 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -810,7 +810,7 @@ def create_gantt( bar_width=0.2, showgrid_x=False, showgrid_y=False, - height=None, + height=600, width=None, tasks=None, task_names=None,