def test_get_contour_info_nonfinite_removed(value: float) -> None:

    study = prepare_study_with_trials(value_for_first_trial=value)
    info = _get_contour_info(study, params=["param_b", "param_d"])
    assert info == _ContourInfo(
        sorted_params=["param_b", "param_d"],
        sub_plot_infos=[[
            _SubContourInfo(
                xaxis=_AxisInfo(
                    name="param_b",
                    range=(-0.05, 1.05),
                    is_log=False,
                    is_cat=False,
                    indices=[-0.05, 0.0, 1.0, 1.05],
                    values=[0.0, 1.0],
                ),
                yaxis=_AxisInfo(
                    name="param_d",
                    range=(1.9, 4.1),
                    is_log=False,
                    is_cat=False,
                    indices=[1.9, 2.0, 4.0, 4.1],
                    values=[4.0, 2.0],
                ),
                z_values={
                    (1, 2): 2.0,
                    (2, 1): 1.0
                },
            )
        ]],
        reverse_scale=True,
        target_name="Objective Value",
    )
def test_get_contour_info_mixture_category_types() -> None:

    study = _create_study_mixture_category_types()
    info = _get_contour_info(study)
    assert info == _ContourInfo(
        sorted_params=["param_a", "param_b"],
        sub_plot_infos=[[
            _SubContourInfo(
                xaxis=_AxisInfo(
                    name="param_a",
                    range=(-0.05, 1.05),
                    is_log=False,
                    is_cat=True,
                    indices=["100", "None"],
                    values=["None", "100"],
                ),
                yaxis=_AxisInfo(
                    name="param_b",
                    range=(100.95, 102.05),
                    is_log=False,
                    is_cat=False,
                    indices=[100.95, 101, 102, 102.05],
                    values=[101.0, 102.0],
                ),
                z_values={
                    (0, 2): 0.5,
                    (1, 1): 0.0
                },
            )
        ]],
        reverse_scale=True,
        target_name="Objective Value",
    )
def test_get_contour_info_2_params() -> None:
    params = ["param_a", "param_b"]
    study = prepare_study_with_trials()
    info = _get_contour_info(study, params=params)
    assert info == _ContourInfo(
        sorted_params=params,
        sub_plot_infos=[[
            _SubContourInfo(
                xaxis=_AxisInfo(
                    name="param_a",
                    range=(0.925, 2.575),
                    is_log=False,
                    is_cat=False,
                    indices=[0.925, 1.0, 2.5, 2.575],
                    values=[1.0, None, 2.5],
                ),
                yaxis=_AxisInfo(
                    name="param_b",
                    range=(-0.1, 2.1),
                    is_log=False,
                    is_cat=False,
                    indices=[-0.1, 0.0, 1.0, 2.0, 2.1],
                    values=[2.0, 0.0, 1.0],
                ),
                z_values={
                    (1, 3): 0.0,
                    (2, 2): 1.0
                },
            )
        ]],
        reverse_scale=True,
        target_name="Objective Value",
    )
def test_generate_contour_plot_for_few_observations(params: List[str]) -> None:
    study = create_study(direction="minimize")
    study.add_trial(
        create_trial(
            values=[0.0],
            params={
                "param_a": 1.0,
                "param_b": 2.0
            },
            distributions={
                "param_a": FloatDistribution(0.0, 3.0),
                "param_b": FloatDistribution(0.0, 3.0),
            },
        ))
    study.add_trial(
        create_trial(
            values=[2.0],
            params={"param_b": 0.0},
            distributions={"param_b": FloatDistribution(0.0, 3.0)},
        ))

    info = _get_contour_info(study, params=params)
    assert info == _ContourInfo(
        sorted_params=sorted(params),
        sub_plot_infos=[[
            _SubContourInfo(
                xaxis=_AxisInfo(
                    name=sorted(params)[0],
                    range=(1.0, 1.0),
                    is_log=False,
                    is_cat=False,
                    indices=[1.0],
                    values=[1.0, None],
                ),
                yaxis=_AxisInfo(
                    name=sorted(params)[1],
                    range=(-0.1, 2.1),
                    is_log=False,
                    is_cat=False,
                    indices=[-0.1, 0.0, 2.0, 2.1],
                    values=[2.0, 0.0],
                ),
                z_values={},
            )
        ]],
        reverse_scale=True,
        target_name="Objective Value",
    )
def test_get_contour_info_log_scale_and_str_category_2_params() -> None:

    # If the search space has two parameters, plot_contour generates a single plot.
    study = _create_study_with_log_scale_and_str_category_2d()
    info = _get_contour_info(study)
    assert info == _ContourInfo(
        sorted_params=["param_a", "param_b"],
        sub_plot_infos=[[
            _SubContourInfo(
                xaxis=_AxisInfo(
                    name="param_a",
                    range=(math.pow(10, -6.05), math.pow(10, -4.95)),
                    is_log=True,
                    is_cat=False,
                    indices=[
                        math.pow(10, -6.05), 1e-6, 1e-5,
                        math.pow(10, -4.95)
                    ],
                    values=[1e-6, 1e-5],
                ),
                yaxis=_AxisInfo(
                    name="param_b",
                    range=(-0.05, 1.05),
                    is_log=False,
                    is_cat=True,
                    indices=["100", "101"],
                    values=["101", "100"],
                ),
                z_values={
                    (1, 1): 0.0,
                    (2, 0): 1.0
                },
            )
        ]],
        reverse_scale=True,
        target_name="Objective Value",
    )