Skip to content

Commit

Permalink
Modify api template and add more module docstrings
Browse files Browse the repository at this point in the history
Modified code reference api section to not use the
template as much, and allowing each module to be generated
when it is needed in the api section. This is a tradeoff of
convencience for more customizability and a better doc design

Also added more module docstrings and improved the ones that
were already there
  • Loading branch information
madeline-scyphers committed Oct 26, 2022
1 parent 0cd4972 commit 11ee4f3
Show file tree
Hide file tree
Showing 22 changed files with 328 additions and 164 deletions.
4 changes: 2 additions & 2 deletions boa/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
from boa.metrics.modular_metric import * # noqa
from boa.runner import * # noqa
from boa.storage import * # noqa
from boa.wrapper import * # noqa
from boa.wrapper_utils import * # noqa
from boa.wrappers.wrapper import * # noqa
from boa.wrappers.wrapper_utils import * # noqa
4 changes: 2 additions & 2 deletions boa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import click

from boa.controller import Controller
from boa.wrapper_utils import cd_and_cd_back, load_jsonlike
from boa.wrappers.wrapper_utils import cd_and_cd_back, load_jsonlike


@click.command()
Expand Down Expand Up @@ -84,7 +84,7 @@ def _main(config_path, rel_to_here, experiment_dir=None):
# since we just loaded the module where the wrapper class is, we can now load it
WrapperCls = getattr(user_wrapper, wrapper_name)
else:
from boa.wrapper import BaseWrapper as WrapperCls
from boa.wrappers.wrapper import BaseWrapper as WrapperCls

controller = Controller(config_path=config_path, wrapper=WrapperCls)

Expand Down
26 changes: 26 additions & 0 deletions boa/_doc_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import inspect
from pathlib import Path

FILENAME = Path(__file__).name


def get_calling_file_path():
frames = inspect.stack()
frame = 1
while (file_path := Path(frames[frame].filename)).name == FILENAME:
frame += 1
return file_path


def add_ref_to_rel_init():
file_path = get_calling_file_path()

parent = file_path.parent
pathing_ls = []
for part in reversed(parent.parts):
pathing_ls.append(part)
if part == "boa":
break
pathing = ".".join(module for module in reversed(pathing_ls))

return f"""**See More Information Here**: :mod:`{pathing}`"""
2 changes: 1 addition & 1 deletion boa/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from boa.runner import WrappedJobRunner
from boa.storage import scheduler_to_json_file
from boa.utils import get_dictionary_from_callable
from boa.wrapper_utils import get_dt_now_as_str
from boa.wrappers.wrapper_utils import get_dt_now_as_str


class Controller:
Expand Down
2 changes: 1 addition & 1 deletion boa/metaclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ax.storage.metric_registry import CORE_METRIC_REGISTRY
from ax.storage.runner_registry import CORE_RUNNER_REGISTRY

from boa.wrapper_utils import cd_and_cd_back_dec
from boa.wrappers.wrapper_utils import cd_and_cd_back_dec

logger = logging.getLogger(__name__)

Expand Down
24 changes: 21 additions & 3 deletions boa/metrics/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
"""
.. todo::
def foo():
return "hi"


__doc__ = f"""
################################################
Metrics Overview & Advanced Usage
################################################
Coming soon!
Metrics are the objective functions we are optimizing over
or functions that we are adding in as further constraints of our problem.
Metrics can be specified in your configuration by detailing the name
of one of the predefined :mod:`Metrics <boa.metrics.metrics>` in BOA
by passing in the name of the metric into your configuration file
See :doc:`/user_guide/configuration`
{foo()}
"""

from boa.metrics.metrics import * # noqa
39 changes: 12 additions & 27 deletions boa/metrics/metric_funcs.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,15 @@
import json
import logging

import numpy as np
import scipy.stats as stats
import yaml
from sklearn.metrics import mean_squared_error

from boa._doc_utils import add_ref_to_rel_init
from boa.utils import get_dictionary_from_callable

logger = logging.getLogger(__name__)


def _metric_from_jsonlike(data, path_to_data):
for key in path_to_data:
try:
data = data[key]
except (IndexError, KeyError, TypeError) as e:
if len(e.args) >= 1:
e.args = (e.args[0] + "\nCan't load data from file because path to data is invalid!",) + e.args[1:]
raise
return data


def metric_from_json(filename, path_to_data, **kwargs):
with open(filename, "r") as f:
data = json.load(f)

return _metric_from_jsonlike(data, path_to_data)


def metric_from_yaml(filename, path_to_data, **kwargs):
with open(filename, "r") as f:
data = yaml.safe_load(f)

return _metric_from_jsonlike(data, path_to_data)


def normalized_root_mean_squared_error(y_true, y_pred, normalizer="iqr", **kwargs):
"""Normalized root mean squared error
Expand Down Expand Up @@ -73,3 +47,14 @@ def normalized_root_mean_squared_error(y_true, y_pred, normalizer="iqr", **kwarg

nrmse = rmse / norm
return nrmse


__doc__ = f"""
########################
Metric Functions
########################
Functions used for Metrics
{add_ref_to_rel_init()}
"""
45 changes: 43 additions & 2 deletions boa/metrics/metrics.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np

from boa._doc_utils import add_ref_to_rel_init
from boa.metrics.metric_funcs import (
normalized_root_mean_squared_error as normalized_root_mean_squared_error_,
)
Expand All @@ -14,6 +15,8 @@ class SklearnMetric(ModularMetric):
========
:external:py:mod:`sklearn.metrics`
for the list of metrics you can use.
:class:`.ModularMetric`
For information on all parameters various metrics in general can be supplied
"""

def __init__(self, metric_to_eval: str, *args, **kwargs):
Expand All @@ -31,6 +34,8 @@ class MeanSquaredError(SklearnMetric):
========
:external:py:func:`sklearn.metrics.mean_squared_error`
for the function parameters to guide your json attribute-value pairs needed.
:class:`.ModularMetric`
For information on all parameters various metrics in general can be supplied
"""

def __init__(self, metric_to_eval="mean_squared_error", lower_is_better=True, *args, **kwargs):
Expand Down Expand Up @@ -59,7 +64,7 @@ def __init__(
lower_is_better=True,
metric_func_kwargs=(("squared", False),),
*args,
**kwargs
**kwargs,
):
if metric_func_kwargs == (("squared", False),):
metric_func_kwargs = dict((y, x) for x, y in metric_func_kwargs)
Expand All @@ -68,7 +73,7 @@ def __init__(
lower_is_better=lower_is_better,
metric_func_kwargs=metric_func_kwargs,
*args,
**kwargs
**kwargs,
)


Expand Down Expand Up @@ -143,3 +148,39 @@ def __init__(self, metric_to_eval=normalized_root_mean_squared_error_, lower_is_

NRMSE = NormalizedRootMeanSquaredError
normalized_root_mean_squared_error = NormalizedRootMeanSquaredError


__doc__ = f"""
########################
List of Metrics
########################
List of Metrics that are already defined in BOA
Any of these Metrics can be used directly in your configuration file
Examples
========
.. code-block:: YAML
# Single objective optimization config
optimization_options:
objective_options:
objectives:
# List all of your metrics here,
# only list 1 metric for a single objective optimization
- metric: RootMeanSquaredError
.. code-block:: YAML
# MultiObjective Optimization config
optimization_options:
objective_options:
objectives:
# List all of your metrics here,
# only list multiple objectives for a multi objective optimization
- metric: RMSE
- metric: R2
{add_ref_to_rel_init()}
"""
21 changes: 16 additions & 5 deletions boa/metrics/modular_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
from ax.utils.measurement.synthetic_functions import FromBotorch, from_botorch
from sklearn.metrics import __all__ as sklearn_all

import boa.metrics.synthethic_funcs
import boa.metrics.synthetic_funcs
from boa._doc_utils import add_ref_to_rel_init
from boa.metaclasses import MetricRegister
from boa.utils import (
extract_init_args,
get_dictionary_from_callable,
serialize_init_args,
)
from boa.wrapper import BaseWrapper
from boa.wrappers.wrapper import BaseWrapper

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -80,7 +81,7 @@ def modular_sklearn_metric(**kwargs):

def get_synth_func(synthetic_metric: str):
synthetic_funcs_modules = [
boa.metrics.synthethic_funcs,
boa.metrics.synthetic_funcs,
ax.utils.measurement.synthetic_functions,
botorch.test_functions.synthetic,
]
Expand Down Expand Up @@ -162,7 +163,7 @@ class ModularMetric(NoisyFunctionMetric, metaclass=MetricRegister):
Parameters
----------
metric_to_eval : Callable
metric_to_eval : Callable | str
metric_func_kwargs : Optional[dict]
dictionary of keyword arguments to pass to the metric to eval function
noise_sd : Optional[float]
Expand All @@ -181,7 +182,7 @@ class ModularMetric(NoisyFunctionMetric, metaclass=MetricRegister):

def __init__(
self,
metric_to_eval: Callable | dict,
metric_to_eval: Callable | str,
metric_func_kwargs: Optional[dict] = None,
# param_names: list[str] = None,
noise_sd: Optional[float] = 0.0,
Expand All @@ -191,6 +192,7 @@ def __init__(
metric_type: Optional[str] = None,
**kwargs,
):
"""""" # remove init docstring from parent class to stop it showing in sphinx
if "to_eval_name" in kwargs:
self._to_eval_name = kwargs.pop("to_eval_name")
else:
Expand Down Expand Up @@ -318,3 +320,12 @@ def __repr__(self) -> str:

arg_str = " ".join(f"{k}={v}" for k, v in init_dict.items())
return f"{self.__class__.__name__}({arg_str})"


__doc__ = f"""
########################
Modular Metric
########################
{add_ref_to_rel_init()}
"""
11 changes: 11 additions & 0 deletions boa/metrics/synthethic_funcs.py → boa/metrics/synthetic_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from botorch.test_functions.synthetic import Hartmann
from torch import Tensor

from boa._doc_utils import add_ref_to_rel_init


class Hartmann4(Hartmann):
dim = 4
Expand All @@ -21,3 +23,12 @@ def optimizers(self) -> Tensor:


hartmann4 = from_botorch(Hartmann4())


__doc__ = f"""
########################
Synthetic Function
########################
{add_ref_to_rel_init()}
"""
2 changes: 1 addition & 1 deletion boa/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from boa.metaclasses import RunnerRegister
from boa.utils import serialize_init_args
from boa.wrapper import BaseWrapper
from boa.wrappers.wrapper import BaseWrapper


class WrappedJobRunner(Runner, metaclass=RunnerRegister):
Expand Down
4 changes: 2 additions & 2 deletions boa/test_scripts/run_branin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from ax.service.utils.report_utils import exp_to_df

try:
from wrappers import Wrapper
from script_wrappers import Wrapper
except ImportError:
from .wrappers import Wrapper
from .script_wrappers import Wrapper

from boa import WrappedJobRunner, get_experiment, get_scheduler

Expand Down
File renamed without changes.
Loading

0 comments on commit 11ee4f3

Please sign in to comment.