def _get_parallel_coordinate_plot(study: Study,
                                  params: Optional[List[str]] = None
                                  ) -> "go.Figure":

    layout = go.Layout(title="Parallel Coordinate Plot", )

    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]

    if len(trials) == 0:
        logger.warning("Your study does not have any completed trials.")
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is not None:
        for input_p_name in params:
            if input_p_name not in all_params:
                ValueError("Parameter {} does not exist in your study.".format(
                    input_p_name))
        all_params = set(params)
    sorted_params = sorted(list(all_params))

    dims = [{
        "label":
        "Objective Value",
        "values":
        tuple([t.value for t in trials]),
        "range":
        (min([t.value for t in trials]), max([t.value for t in trials])),
    }]  # type: List[Dict[str, Any]]
    for p_name in sorted_params:
        values = []
        for t in trials:
            if p_name in t.params:
                values.append(t.params[p_name])
        is_categorical = False
        try:
            tuple(map(float, values))
        except (TypeError, ValueError):
            vocab = defaultdict(
                lambda: len(vocab))  # type: DefaultDict[str, int]
            values = [vocab[v] for v in values]
            is_categorical = True
        dim = {
            "label":
            p_name if len(p_name) < 20 else "{}...".format(p_name[:17]),
            "values": tuple(values),
            "range": (min(values), max(values)),
        }
        if is_categorical:
            dim["tickvals"] = list(range(len(vocab)))
            dim["ticktext"] = list(sorted(vocab.items(), key=lambda x: x[1]))
        dims.append(dim)

    traces = [
        go.Parcoords(
            dimensions=dims,
            labelangle=30,
            labelside="bottom",
            line={
                "color": dims[0]["values"],
                "colorscale": "blues",
                "colorbar": {
                    "title": "Objective Value"
                },
                "showscale": True,
                "reversescale": study.direction == StudyDirection.MINIMIZE,
            },
        )
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure
def _get_parallel_coordinate_plot(study, params=None):
    # type: (Study, Optional[List[str]]) -> go.Figure

    layout = go.Layout(title='Parallel Coordinate Plot', )

    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]

    if len(trials) == 0:
        logger.warning('Your study does not have any completed trials.')
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is not None:
        for input_p_name in params:
            if input_p_name not in all_params:
                ValueError('Parameter {} does not exist in your study.'.format(
                    input_p_name))
        all_params = set(params)
    sorted_params = sorted(list(all_params))

    dims = [{
        'label':
        'Objective Value',
        'values':
        tuple([t.value for t in trials]),
        'range':
        (min([t.value for t in trials]), max([t.value for t in trials]))
    }]  # type: List[Dict[str, Any]]
    for p_name in sorted_params:
        values = []
        for t in trials:
            if p_name in t.params:
                values.append(t.params[p_name])
        is_categorical = False
        try:
            tuple(map(float, values))
        except (TypeError, ValueError):
            vocab = defaultdict(
                lambda: len(vocab))  # type: DefaultDict[str, int]
            values = [vocab[v] for v in values]
            is_categorical = True
        dim = {
            'label': p_name,
            'values': tuple(values),
            'range': (min(values), max(values))
        }
        if is_categorical:
            dim['tickvals'] = list(range(len(vocab)))
            dim['ticktext'] = list(sorted(vocab.items(), key=lambda x: x[1]))
        dims.append(dim)

    traces = [
        go.Parcoords(dimensions=dims,
                     line={
                         'color':
                         dims[0]['values'],
                         'colorscale':
                         'blues',
                         'colorbar': {
                             'title': 'Objective Value'
                         },
                         'showscale':
                         True,
                         'reversescale':
                         study.direction == StudyDirection.MINIMIZE,
                     })
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure