Skip to content

Commit

Permalink
Merge pull request #192 from automl/190-working-directory-unintuitive…
Browse files Browse the repository at this point in the history
…-selection-of-runs

190 working directory unintuitive selection of runs
  • Loading branch information
mwever authored Nov 4, 2024
2 parents 58d6801 + 4147a5a commit 9b35ab8
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 27 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Version 1.3.3

## Converters
- Add for each converter a method to check whether a run is valid.
- Change rst docs of converters.

## General Layout
- Fix navigation and button problems in general layout.
- Change general layout to be more intuitiv.

# Version 1.3.2

## Features
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ DeepCAVE comes with some pre-evaluated runs to get a feeling for what DeepCAVE c

If you cloned the repository from GitHub via `git clone https://github.com/automl/DeepCAVE.git`,
you can try out some examples by exploring the `logs` directory inside the DeepCAVE dashboard.
For example, if you navigate to `logs/DeepCAVE`, you can view the run `mnist_pytorch` if you hit
the `+` button left to it.
For example, if you navigate to `logs/DeepCAVE/mnist_pytorch`, you can view its runs if you hit
the `+` button left to them.


## Features
Expand Down
60 changes: 42 additions & 18 deletions deepcave/layouts/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ def callback(run_paths: List[str]):
# Add text to go to parent directory
new_element = html.Div(
[
dbc.Button(
"+", id={"type": "general-dynamic-add-run", "index": -1}, disabled=True
html.I(
className="fas fa-folder-open fa-lg",
id={"type": "general-dynamic-add-run", "index": -1},
style={"pointer-events": "none"},
),
dbc.Button(
"..",
Expand All @@ -161,23 +163,45 @@ def callback(run_paths: List[str]):

for i, run_path in enumerate(run_paths):
run_name = run_handler.get_run_name(run_path)
new_element = html.Div(
[
dbc.Button("+", id={"type": "general-dynamic-add-run", "index": i}),
dbc.Button(
run_name,
id={"type": "general-dynamic-change-directory", "index": i},
color="link",
),
dcc.Store(
id={"type": "general-dynamic-available-run-path", "index": i},
data=run_path,
),
],
className="mb-1",
)
children.append(new_element)

is_run = run_handler.is_run(run_path)
# Differenciate between run and directory for visibility and usability reasons
if is_run:
new_element = html.Div(
[
dbc.Button(
"+", id={"type": "general-dynamic-add-run", "index": i}, size="sm"
),
dbc.Button(
run_name,
id={"type": "general-dynamic-change-directory", "index": i},
color="light",
disabled=True,
),
dcc.Store(
id={"type": "general-dynamic-available-run-path", "index": i},
data=run_path,
),
],
className="mb-1",
)
else:
new_element = html.Div(
[
html.I(className="fas fa-folder fa-lg"),
dbc.Button(
run_name,
id={"type": "general-dynamic-change-directory", "index": i},
color="link",
),
dcc.Store(
id={"type": "general-dynamic-available-run-path", "index": i},
data=run_path,
),
],
className="mb-1",
)
children.append(new_element)
if len(children) == 0:
return html.Div("No runs found.")

Expand Down
23 changes: 23 additions & 0 deletions deepcave/runs/converters/amltk.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from typing import Optional, Sequence, Union

import os
import re
from pathlib import Path

Expand Down Expand Up @@ -215,3 +216,25 @@ def from_path(cls, path: Union[Path, str]) -> "AMLTKRun":
)

return run

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid amltk run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "/history.parquet") and os.path.isfile(
path_name + "/configspace.json"
):
return True
return False
21 changes: 21 additions & 0 deletions deepcave/runs/converters/bohb.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from typing import Any, Dict, Union

import os
from pathlib import Path

from ConfigSpace.configuration_space import ConfigurationSpace
Expand Down Expand Up @@ -177,3 +178,23 @@ def from_path(cls, path: Union[Path, str]) -> "BOHBRun":
)

return run

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid bohb run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "/configspace.json"):
return True
return False
22 changes: 22 additions & 0 deletions deepcave/runs/converters/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,25 @@ def _extract_additional(
additional = data.drop(hyperparameters + costs_metrics + budgets + seeds + meta)
additional = dict(additional)
return {key: value if pd.notna(value) else None for key, value in additional.items()}

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid dataframe run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "/trials.csv") and os.path.isfile(
path_name + "/configspace.csv"
):
return True
return False
21 changes: 21 additions & 0 deletions deepcave/runs/converters/deepcave.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from typing import Union

import os
from pathlib import Path

from deepcave.runs.run import Run
Expand Down Expand Up @@ -92,3 +93,23 @@ def from_path(cls, path: Path) -> "DeepCAVERun":
The DeepCAVE run.
"""
return DeepCAVERun(path.stem, path=Path(path))

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid deepcave run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "history.jsonl"):
return True
return False
22 changes: 22 additions & 0 deletions deepcave/runs/converters/optuna.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,25 @@ def from_path(cls, path: Union[Path, str]) -> "OptunaRun":
)

return run

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid optuna run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
path = Path(path_name)
pickle_files = list(path.glob("*.pkl"))
if len(pickle_files) != 1:
return False
return True
23 changes: 23 additions & 0 deletions deepcave/runs/converters/smac3v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from typing import Optional, Union

import json
import os
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -217,3 +218,25 @@ def from_path(cls, path: Union[Path, str]) -> "SMAC3v1Run":
)

return run

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid smac3v1 run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "/runhistory.json") and os.path.isfile(
path_name + "/configspace.json"
):
return True
return False
23 changes: 23 additions & 0 deletions deepcave/runs/converters/smac3v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from typing import Union

import json
import os
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -216,3 +217,25 @@ def from_path(cls, path: Union[Path, str]) -> "SMAC3v2Run":
)

return run

@classmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid smac3v2 run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
if os.path.isfile(path_name + "/runhistory.json") and os.path.isfile(
path_name + "/configspace.json"
):
return True
return False
20 changes: 20 additions & 0 deletions deepcave/runs/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,23 @@ def get_runs(self, include_groups: bool = False) -> List[AbstractRun]:
runs += list(self.groups.values())

return runs

def is_run(self, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
for run_class in self.available_run_classes:
if run_class.is_valid_run(path_name):
return True
return False
19 changes: 19 additions & 0 deletions deepcave/runs/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,25 @@ def from_path(cls, path: Path) -> "Run":
"""
pass

@classmethod
@abstractmethod
def is_valid_run(cls, path_name: str) -> bool:
"""
Check whether the path name belongs to a valid run.
Parameters
----------
path_name: str
The path to check.
Returns
-------
bool
True if path is valid run.
False otherwise.
"""
pass

@property
def id(self) -> str:
"""
Expand Down
8 changes: 7 additions & 1 deletion docs/converters/bohb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ To load an BOHB run into DeepCAVE, it is necessary to install HpBandSter, e.g. v

.. code-block:: bash
pip install deepcave[bohb]
pip install deepcave[bohb]
To be able to load it correctly into DeepCAVE, you need to save the configuration space as a ConfigSpace JSON file:

.. code-block:: python
"configspace.json"
Loading

0 comments on commit 9b35ab8

Please sign in to comment.