Exemplo n.º 1
0
def _calculate_start_point(database, updating_options):
    """Calculate the starting point.

    Args:
        database (sqlalchemy.MetaData): Bound metadata object.
        updating_options (dict): Specification how to update the plotting data.
            It contains rollover, update_frequency, update_chunk, jump and stride.

    Returns:
        start_point (int): iteration from which to start the dashboard.

    """
    if updating_options["jump"]:
        last_entry = read_last_rows(
            database=database,
            table_name="optimization_iterations",
            n_rows=1,
            return_type="list_of_dicts",
        )
        nr_of_entries = last_entry[0]["rowid"]
        nr_to_go_back = updating_options["rollover"] * updating_options[
            "stride"]
        start_point = max(0, nr_of_entries - nr_to_go_back)
    else:
        start_point = 0
    return start_point
Exemplo n.º 2
0
def _read_optimization_iteration(database, iteration, params_treedef,
                                 registry):
    """Get information about an optimization iteration."""
    if iteration >= 0:
        rowid = iteration + 1
    else:
        last_iteration = read_last_rows(
            database=database,
            table_name="optimization_iterations",
            n_rows=1,
            return_type="list_of_dicts",
        )
        highest_rowid = last_iteration[0]["rowid"]

        # iteration is negative here!
        rowid = highest_rowid + iteration + 1

    data = read_specific_row(
        database,
        table_name="optimization_iterations",
        rowid=rowid,
        return_type="list_of_dicts",
    )

    if len(data) == 0:
        raise IndexError(f"Invalid iteration requested: {iteration}")
    else:
        data = data[0]

    params = tree_unflatten(params_treedef, data["params"], registry=registry)
    data["params"] = params

    return data
Exemplo n.º 3
0
def read_optimization_iteration(path_or_database, iteration, include_internals=False):
    """Get information about an optimization iteration.

    Args:
        path_or_database (pathlib.Path, str or sqlalchemy.MetaData)
        iteration (int): The index of the iteration that should be retrieved.
            The row_id behaves as Python list indices, i.e. ``0`` identifies the
            first iteration, ``-1`` the last one, etc.
        include_internals (bool): Whether internally used quantities like the
            internal parameter vector and the corresponding derivative etc. are included
            in the result. Default False. This should only be used by advanced users.

    Returns:
        dict: The logged information corresponding to the iteration. The keys correspond
            to database columns.

    Raises:
        KeyError: if the iteration is out of bounds.

    """
    database = load_database(**_process_path_or_database(path_or_database))
    start_params = read_start_params(database)
    if iteration >= 0:
        rowid = iteration + 1
    else:
        last_iteration = read_last_rows(
            database=database,
            table_name="optimization_iterations",
            n_rows=1,
            return_type="list_of_dicts",
        )
        highest_rowid = last_iteration[0]["rowid"]

        rowid = highest_rowid + iteration + 1

    data = read_specific_row(
        database=database,
        table_name="optimization_iterations",
        rowid=rowid,
        return_type="list_of_dicts",
    )

    if len(data) == 0:
        raise IndexError(f"Invalid iteration requested: {iteration}")
    else:
        data = data[0]

    params = start_params.copy()
    params["value"] = data.pop("external_params")
    data["params"] = params

    to_remove = ["distance_origin", "distance_ones"]
    if not include_internals:
        to_remove += ["internal_params", "internal_derivative"]
    for key in to_remove:
        if key in data:
            del data[key]

    return data
Exemplo n.º 4
0
def test_optimization_iteration_table_scalar(tmp_path, iteration_data):
    path = tmp_path / "test.db"
    database = load_database(path=path)
    make_optimization_iteration_table(database, first_eval={"output": 0.5})
    append_row(iteration_data, "optimization_iterations", database, path, False)
    res = read_last_rows(database, "optimization_iterations", 1, "list_of_dicts")
    assert isinstance(res, list) and isinstance(res[0], dict)
    res = res[0]
    assert res["rowid"] == 1
    assert_array_equal(res["params"], iteration_data["params"])

    for key in ["value", "timestamp"]:
        assert res[key] == iteration_data[key]
Exemplo n.º 5
0
def test_optimization_problem_table(tmp_path, problem_data):
    path = tmp_path / "test.db"
    database = load_database(path=path)
    make_optimization_problem_table(database)
    append_row(problem_data, "optimization_problem", database, path, False)
    res = read_last_rows(database, "optimization_problem", 1, "list_of_dicts")[0]
    assert res["rowid"] == 1
    for key, expected in problem_data.items():
        if key == "criterion":
            assert res[key](np.ones(3)) == 3
        elif isinstance(expected, np.ndarray):
            assert_array_equal(res[key], expected)
        else:
            assert res[key] == expected
Exemplo n.º 6
0
def test_read_last_rows_stride(tmp_path, iteration_data):
    path = tmp_path / "test.db"
    database = load_database(path=path)
    make_optimization_iteration_table(database, first_eval={"output": 0.5})
    for i in range(1, 11):  # sqlalchemy starts counting at 1
        iteration_data["value"] = i
        append_row(iteration_data, "optimization_iterations", database, path, False)

    res = read_last_rows(
        database=database,
        table_name="optimization_iterations",
        n_rows=3,
        return_type="dict_of_lists",
        stride=2,
    )["value"]

    expected = [6.0, 8.0, 10.0]
    assert res == expected
Exemplo n.º 7
0
def test_read_last_rows_with_step(tmp_path, iteration_data):
    path = tmp_path / "test.db"
    database = load_database(path=path)
    make_optimization_iteration_table(database, first_eval={"output": 0.5})
    for i in range(1, 11):  # sqlalchemy starts counting at 1
        iteration_data["value"] = i
        iteration_data["step"] = i % 2
        append_row(iteration_data, "optimization_iterations", database, path, False)

    res = read_last_rows(
        database=database,
        table_name="optimization_iterations",
        n_rows=20,
        return_type="dict_of_lists",
        step=0,
    )

    expected = [2, 4, 6, 8, 10]
    assert res["rowid"] == expected
Exemplo n.º 8
0
def read_start_params(path_or_database):
    """Load the start parameters DataFrame.

    Args:
        path_or_database (pathlib.Path, str or sqlalchemy.MetaData)

    Returns:
        params (pd.DataFrame): see :ref:`params`.

    """
    database = load_database(**_process_path_or_database(path_or_database))
    optimization_problem = read_last_rows(
        database=database,
        table_name="optimization_problem",
        n_rows=1,
        return_type="dict_of_lists",
    )
    start_params = optimization_problem["params"][0]
    return start_params
Exemplo n.º 9
0
def dashboard_app(
    doc,
    session_data,
    updating_options,
):
    """Create plots showing the development of the criterion and parameters.

    Args:
        doc (bokeh.Document): Argument required by bokeh.
        session_data (dict): Infos to be passed between and within apps.
            Keys of this app's entry are:
            - last_retrieved (int): last iteration currently in the ColumnDataSource.
            - database_path (str or pathlib.Path)
            - callbacks (dict): dictionary to be populated with callbacks.
        updating_options (dict): Specification how to update the plotting data.
            It contains rollover, update_frequency, update_chunk, jump and stride.

    """
    # style the Document
    template_folder = Path(__file__).resolve().parent
    # conversion to string from pathlib Path is necessary for FileSystemLoader
    env = Environment(loader=FileSystemLoader(str(template_folder)))
    doc.template = env.get_template("index.html")

    # process inputs
    database = load_database(path=session_data["database_path"])
    start_point = _calculate_start_point(database, updating_options)
    session_data["last_retrieved"] = start_point

    # build start_params DataFrame
    registry = get_registry(extended=True)
    start_params_tree = read_start_params(path_or_database=database)
    internal_params = tree_just_flatten(tree=start_params_tree, registry=registry)
    full_names = leaf_names(start_params_tree, registry=registry)

    optimization_problem = read_last_rows(
        database=database,
        table_name="optimization_problem",
        n_rows=1,
        return_type="dict_of_lists",
    )
    free_mask = optimization_problem["free_mask"][0]
    params_groups, short_names = get_params_groups_and_short_names(
        params=start_params_tree, free_mask=free_mask
    )
    start_params = pd.DataFrame(
        {
            "full_name": full_names,
            "name": short_names,
            "group": params_groups,
            "value": internal_params,
        }
    )
    start_params["id"] = _create_id_column(start_params)

    group_to_param_ids = _map_group_to_other_column(start_params, "id")
    group_to_param_names = _map_group_to_other_column(start_params, "name")
    criterion_history, params_history = _create_cds_for_dashboard(group_to_param_ids)

    # create elements
    title_text = """<h1 style="font-size:30px;">estimagic Dashboard</h1>"""
    title = Row(
        children=[
            Div(
                text=title_text,
                sizing_mode="scale_width",
            )
        ],
        name="title",
        margin=(5, 5, -20, 5),
    )
    plots = _create_initial_plots(
        criterion_history=criterion_history,
        params_history=params_history,
        group_to_param_ids=group_to_param_ids,
        group_to_param_names=group_to_param_names,
    )

    restart_button = _create_restart_button(
        doc=doc,
        database=database,
        session_data=session_data,
        start_params=start_params,
        updating_options=updating_options,
    )
    button_row = Row(
        children=[restart_button],
        name="button_row",
    )

    # add elements to bokeh Document
    grid = Column(children=[title, button_row, *plots], sizing_mode="stretch_width")
    doc.add_root(grid)

    # start the convergence plot immediately
    restart_button.active = True