Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/experiment_manager #10

Merged
merged 23 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4e99290
feat: ExperimentManager added
ihsanKisi Apr 18, 2024
1233736
refactor: Updated the filter logic to reflect latest changes
ihsanKisi Apr 18, 2024
6a37753
docs: added the module explanation to experiment_manager
ihsanKisi Apr 25, 2024
58840cf
test: add tests for experiment_manager
ihsanKisi Apr 25, 2024
2b13ed9
refactor: git ignore file is updated to remove .pyc files in the commits
ihsanKisi Apr 25, 2024
90b05c0
refactor: minimum python version is set to 3.9 as before
ihsanKisi Apr 25, 2024
36e139d
add experiment filtering support with buttons, add enums for experime…
ihsanKisi May 2, 2024
22a561e
Merge branch 'develop' into feat-experiment-manager
aiakide May 7, 2024
272980d
fix: Remove __pycache__
aiakide May 7, 2024
ea889f2
refactor: generalize the state class
ihsanKisi May 16, 2024
dcd9931
refactor: resolve conflicts
ihsanKisi May 16, 2024
a2aa72b
rebase continuesrefacotor: add the rest of the conflicting files
ihsanKisi May 16, 2024
4274c65
rebasing the branchmerge conflicts are resolvedadd experiment filteri…
ihsanKisi May 2, 2024
c85d10a
conflicts resolvedrefactor: generalize the state class
ihsanKisi May 16, 2024
3cb75f4
fix: solve table items not loading and exclude lambda expression from…
ihsanKisi May 16, 2024
ba8cb1c
fix: Update dependencies (libsass installation error)
aiakide May 23, 2024
df9858f
Merge branch 'develop' into feat-experiment-manager
aiakide May 23, 2024
42e38d8
refactor: move the button component to buttons module for clarity (#18)
ihsanKisi May 28, 2024
6459f58
refactor: update file names according to the convention
ihsanKisi May 28, 2024
dc76823
Merge branch 'feat-experiment-management' into feat-experiment-manager
aiakide May 28, 2024
664e9d0
refactor: clean up the code, poetry update, and updating the file nam…
ihsanKisi May 28, 2024
98c8f7e
refactor: update docstrings
ihsanKisi May 28, 2024
bd1d8bf
refactor: update file name
ihsanKisi May 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
poetry.toml
.venv


**/__pycache__/

.DS_Store
Binary file added nicemldashboard/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file added nicemldashboard/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 2 additions & 2 deletions nicemldashboard/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
from nicemldashboard.pages.home import home
from nicemldashboard.utils.settings import Settings

app.add_static_files("/fonts", "nicemldashboard/assets/fonts")
app.add_static_files("/fonts", "assets/fonts")


class Dashboard:
"""
Main dashboard application for a NiceML Dashboard.
"""

def __init__(self, settings_path: str = ".niceml/settings.yml"):
def __init__(self, settings_path: str = "../.niceml/settings.yml"):
"""
Initialize the Dashboard.

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
42 changes: 42 additions & 0 deletions nicemldashboard/experiment/experiment_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
This module provides an experiment manager. Currently, experiment manager
supports filtering experiments by their properties.
"""
import logging
from typing import List

from nicemldashboard.experiment.experiment import Experiment


class ExperimentManager:
"""
Allows filtering experiments by making the filter_by method available
"""

def __init__(self, experiments: List[Experiment]):
"""
Initializes an ExperimentManager with the provided list of experiments.
"""
self.experiments = experiments

def filter_by(self, **filters) -> List[Experiment]:
"""
Filters the experiment list after filtering with the provided filters
:param filters:
:return:
"""
filtered_experiments = self.experiments.copy()
for key, value in filters.items():
try:
filtered_experiments = [
exp
for exp in filtered_experiments
if getattr(exp, key, None) == value
]
except TypeError as e:
# Log the error message with details of which experiment and filter caused it.
logging.error(
f"Incomparable types between attribute '{key}' with value '{value}' "
f"and filter value '{value}': {e}"
)
return filtered_experiments
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions nicemldashboard/pages/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from nicemldashboard.basecomponents.sidebar import sidebar
from nicemldashboard.basecomponents.table import experiment_runs_table
from nicemldashboard.experiment.utils import get_random_experiments
from nicemldashboard.experiment.experiment_manager import ExperimentManager
from nicemldashboard.experiment.type import ExperimentType


@ui.page("/")
Expand All @@ -25,7 +27,9 @@ def home():
ui.add_style("nicemldashboard/assets/style.scss")

experiments = get_random_experiments(experiment_count=20)
experiment_manager = ExperimentManager(experiments)

experiments = experiment_manager.filter_by(experiment_type=ExperimentType.OBJ_DET)
sidebar()
with ui.grid().classes("content"):
with ui.card().style("width:100%"):
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
664 changes: 342 additions & 322 deletions poetry.lock

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions tests/unit/nicemldashboard/experiment/test_experiment_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import pytest
from nicemldashboard.experiment.experiment_manager import ExperimentManager
from nicemldashboard.experiment.utils import get_random_experiments


@pytest.fixture
def experiments():
return get_random_experiments(50, seed=42)


@pytest.fixture
def experiment_manager(experiments):
return ExperimentManager(experiments)


def test_filter_by_name(experiment_manager, experiments):
name_to_test = experiments[0].name
filtered = experiment_manager.filter_by(name=name_to_test)
assert len(filtered) == 1

non_filtered_experiments = [exp for exp in experiments if exp.name != name_to_test]
assert all(exp.name != name_to_test for exp in non_filtered_experiments)


def test_filter_by_id(experiment_manager, experiments):
id_to_test = experiments[0].experiment_id
filtered = experiment_manager.filter_by(experiment_id=id_to_test)
assert len(filtered) == 1

non_filtered_experiments = [
exp for exp in experiments if exp.experiment_id != id_to_test
]
assert all(exp.experiment_id != id_to_test for exp in non_filtered_experiments)


def test_filter_by_experiment_type(experiment_manager, experiments):
experiment_type_to_test = experiments[0].experiment_type
filtered = experiment_manager.filter_by(experiment_type=experiment_type_to_test)
assert all(exp.experiment_type == experiment_type_to_test for exp in filtered)

experiments_not_filtered = [exp for exp in experiments if exp not in filtered]
assert all(
exp.experiment_type != experiment_type_to_test
for exp in experiments_not_filtered
)


def test_filter_by_nonexistent_field(experiment_manager):
filtered = experiment_manager.filter_by(nonexistent_field="dummy")
assert len(filtered) == 0


def test_filter_by_multiple_fields_name_and_id(experiment_manager, experiments):
first_experiment = experiments[0]
filtered = experiment_manager.filter_by(
name=first_experiment.name, experiment_id=first_experiment.experiment_id
)
assert len(filtered) == 1
experiments_not_filtered = [exp for exp in experiments if exp not in filtered]
assert all(
exp.name != first_experiment.name
and exp.experiment_id != first_experiment.experiment_id
for exp in experiments_not_filtered
)


def test_filter_by_multiple_fields_experiment_type_and_git_version(
experiment_manager, experiments
):
first_experiment = experiments[0]
filtered = experiment_manager.filter_by(
experiment_type=first_experiment.experiment_type,
git_version=first_experiment.git_version,
)
assert all(
exp.experiment_type == first_experiment.experiment_type for exp in filtered
)
assert all(exp.git_version == first_experiment.git_version for exp in filtered)

experiments_not_filtered = [exp for exp in experiments if exp not in filtered]
assert all(
not (
exp.experiment_type == first_experiment.experiment_type
and exp.git_version == first_experiment.git_version
)
for exp in experiments_not_filtered
)


def test_filter_with_no_criteria(experiment_manager, experiments):
filtered = experiment_manager.filter_by()
assert len(filtered) == len(experiments)
assert filtered == experiments