Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A comprehensive Python project template designed specifically for research devel
- **Comprehensive Linting & Type Checking**: Pre-configured with mypy, isort, pylint, black, pydocstyle, and flake8
- **Pre-commit Hooks**: Automated code quality checks before each commit
- **CI/CD Integration**: GitHub Actions workflow for continuous integration on PRs
- **Experiment Tracking**: Ready-to-use configuration for Hydra and Weights & Biases (W&B)
- **Experiment Tracking**: Ready-to-use configuration for Hydra and Weights & Biases (W&B) (optional dependencies)

## Directory Structure

Expand Down Expand Up @@ -79,6 +79,8 @@ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

This template is designed to support reproducible research experiments using [Hydra](https://hydra.cc/) for configuration management and [Weights & Biases (W&B)](https://wandb.ai/) for experiment tracking.

> **Note**: Hydra and W&B are included as dependencies in this template for convenience, but they are **optional**. You can remove them from `pyproject.toml` if you don't need experiment tracking or configuration management features.

#### Basic Experiment Execution

Place your experiment scripts in the `experiments/` directory:
Expand Down Expand Up @@ -276,18 +278,24 @@ The GitHub Actions workflow (`.github/workflows/pr-monitor.yml`) automatically r

## Adding New Dependencies

Use uv to add new dependencies:
Use uv to add new dependencies to your project. The `uv add` command automatically installs the package and updates `pyproject.toml`:

```bash
# Add a runtime dependency
uv pip install package-name
# Then add it to pyproject.toml under [project.dependencies]
uv add package-name

# Add a development dependency
uv pip install package-name
# Then add it to pyproject.toml under [project.optional-dependencies.dev]
uv add --dev package-name

# Add a specific version
uv add "package-name>=1.0.0"

# Add multiple packages at once
uv add package1 package2 package3
```

After adding dependencies, make sure to commit the updated `pyproject.toml` to keep your project configuration in sync.

## Configuration Files

All linter and type-checker configurations are located in the `.dev-config/` directory:
Expand Down
45 changes: 45 additions & 0 deletions src/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Utility functions for the research project.

This module contains common utility functions used across experiments.
"""

from typing import Any, Dict, List


def compute_mean(values: List[float]) -> float:
"""Compute the mean of a list of values.

Args:
values: List of numerical values.

Returns:
The arithmetic mean of the input values.

Raises:
ValueError: If the input list is empty.

Example:
>>> compute_mean([1.0, 2.0, 3.0, 4.0])
2.5
"""
if not values:
raise ValueError("Cannot compute mean of empty list")
return sum(values) / len(values)


def validate_config(config: Dict[str, Any]) -> bool:
"""Validate experiment configuration.

Args:
config: Configuration dictionary to validate.

Returns:
True if configuration is valid, False otherwise.

Example:
>>> config = {"learning_rate": 0.001, "batch_size": 32}
>>> validate_config(config)
True
"""
required_keys = ["learning_rate", "batch_size"]
return all(key in config for key in required_keys)
4 changes: 3 additions & 1 deletion tests/test_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def test_compute_mean_single_value(self) -> None:

def test_compute_mean_empty_list(self) -> None:
"""Test that empty list raises ValueError."""
with pytest.raises(ValueError, match="Cannot compute mean of empty list"):
with pytest.raises(
ValueError, match="Cannot compute mean of empty list"
):
compute_mean([])


Expand Down