Contributing to RegressionLabο
Thank you for your interest in contributing to RegressionLab! This guide will help you get started with contributing code, documentation, or other improvements to the project.
Ways to Contributeο
There are many ways to contribute to RegressionLab:
π Report bugs: Help us identify issues.
π‘ Suggest features: Share your ideas for improvements.
π Improve documentation: Fix typos, add examples, clarify explanations.
π§ Fix bugs: Submit patches for known issues.
β¨ Add features: Implement new functionality.
π§ͺ Write tests: Improve code coverage.
π Add translations: Support more languages.
π Add equations: Contribute new fitting functions.
π¨ Improve UI/UX: Enhance user experience.
Getting Startedο
1. Fork and Cloneο
# Fork the repository on GitHub (click "Fork" button)
# Clone your fork
git clone https://github.com/DOKOS-TAYOS/RegressionLab.git
cd RegressionLab
# Add upstream remote
git remote add upstream https://github.com/DOKOS-TAYOS/RegressionLab.git
2. Set Up Development Environmentο
# Create virtual environment
python -m venv .venv
# Activate virtual environment
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows
# Install dependencies including development tools (pytest, ruff, black, mypy, pre-commit)
pip install -r requirements-dev.txt
# Or install from pyproject.toml with dev extras:
# pip install -e ".[dev]"
# Install the package in editable mode (if not already done by the line above)
pip install -e .
3. Create a Branchο
# Update main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/your-feature-name
# or for bug fixes:
git checkout -b fix/issue-description
Branch Naming Conventions:
feature/- New features.fix/- Bug fixes.docs/- Documentation updates.refactor/- Code refactoring.test/- Adding or updating tests.
Development Guidelinesο
Code Styleο
RegressionLab follows PEP 8 with some project-specific conventions:
1. Line Lengthο
Maximum 100 characters per line.
For long strings, use implicit concatenation or
textwrap.
# Good
message = (
"This is a very long message that spans "
"multiple lines for better readability."
)
# Bad
message = "This is a very long message that spans multiple lines for better readability."
2. Type Hintsο
Always include type hints for function signatures:
from typing import Optional, Tuple
from numpy.typing import NDArray
import numpy as np
def process_data(
data: NDArray[np.floating],
threshold: float = 0.5,
normalize: bool = True
) -> Tuple[NDArray[np.floating], float]:
"""Process data with optional normalization."""
...
3. Docstringsο
Use Google-style docstrings:
def fit_curve(data: pd.DataFrame, equation: str) -> Tuple[np.ndarray, float]:
"""
Fit a curve to the provided data.
This function performs nonlinear least squares fitting using
scipy.optimize.curve_fit with automatic initial parameter estimation.
Args:
data: DataFrame containing x, y, and optional uncertainty columns
equation: Name of the equation to fit (e.g., 'linear_function')
Returns:
Tuple containing:
- Fitted parameters as ndarray
- R-squared value as float
Raises:
FittingError: If the fitting algorithm fails to converge
ValueError: If equation name is not recognized
Examples:
>>> data = pd.DataFrame({'x': [1, 2, 3], 'y': [2, 4, 6]})
>>> params, r2 = fit_curve(data, 'linear_function')
>>> params
array([2.0])
>>> r2
1.0
"""
...
4. Importsο
Organize imports in three groups, separated by blank lines:
# Standard library
import os
import sys
from pathlib import Path
from typing import Optional, List
# Third-party packages
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit
# Local imports
from config import AVAILABLE_EQUATION_TYPES
from fitting.fitting_utils import generic_fit
from utils.exceptions import FittingError
from utils.logger import get_logger
5. Naming Conventionsο
Functions/variables:
snake_caseClasses:
PascalCaseConstants:
UPPER_SNAKE_CASEPrivate members:
_leading_underscore
# Good
MAX_ITERATIONS = 1000
class DataLoader:
def __init__(self):
self._cache = {}
def load_file(self, file_path: str) -> pd.DataFrame:
...
def _parse_header(self, line: str) -> List[str]:
...
Testingο
Writing Testsο
Location: Place tests in
tests/directoryNaming: Test files should match source files:
test_<module>.pyStructure: Use pytest conventions
# tests/test_fitting_functions.py
import numpy as np
import pandas as pd
import pytest
from fitting.fitting_functions import func_lineal, ajlineal
class TestFuncLineal:
"""Tests for func_lineal mathematical function."""
def test_scalar_input(self):
"""Test with scalar input."""
result = func_lineal(5.0, 2.0)
assert result == 10.0
def test_array_input(self):
"""Test with array input."""
t = np.array([1, 2, 3])
result = func_lineal(t, 2.0)
expected = np.array([2, 4, 6])
np.testing.assert_array_equal(result, expected)
@pytest.mark.parametrize("t,m,expected", [
(0, 5, 0),
(3, 2, 6),
(-2, 4, -8),
])
def test_various_inputs(self, t, m, expected):
"""Test with various parameter combinations."""
assert func_lineal(t, m) == expected
class TestAjlineal:
"""Tests for ajlineal fitting function."""
def test_perfect_linear_fit(self):
"""Test fitting with perfect linear data."""
x = np.linspace(0, 10, 50)
y = 3.0 * x # Perfect linear relationship
data = pd.DataFrame({'x': x, 'y': y})
param_text, y_fitted, equation, r_squared = ajlineal(data, 'x', 'y')
# RΒ² should be nearly 1 for perfect fit
assert r_squared > 0.9999
# Fitted values should match original data
np.testing.assert_array_almost_equal(y_fitted, y, decimal=10)
def test_noisy_data(self):
"""Test fitting with noisy data."""
np.random.seed(42) # Reproducibility
x = np.linspace(0, 10, 100)
y = 2.5 * x + np.random.normal(0, 0.5, 100)
data = pd.DataFrame({'x': x, 'y': y})
param_text, y_fitted, equation, r_squared = ajlineal(data, 'x', 'y')
# Should still get good fit despite noise
assert r_squared > 0.95
def test_with_uncertainties(self):
"""Test fitting with uncertainty columns."""
x = np.linspace(0, 10, 50)
y = 3.0 * x
data = pd.DataFrame({
'x': x,
'y': y,
'ux': np.ones_like(x) * 0.1,
'uy': np.ones_like(y) * 0.2
})
param_text, y_fitted, equation, r_squared = ajlineal(data, 'x', 'y')
assert r_squared > 0.99
def test_raises_on_invalid_data(self):
"""Test that appropriate errors are raised for invalid data."""
with pytest.raises(KeyError):
# Missing column
data = pd.DataFrame({'x': [1, 2, 3]})
ajlineal(data, 'x', 'y')
Running Testsο
# Run all tests
pytest tests/
# Or: python tests/run_tests.py
# Or use launcher: bin\run_tests.bat (Windows) / bin/run_tests.sh (Linux/macOS)
# Run specific test file
pytest tests/test_fitting_functions.py
# Run specific test
pytest tests/test_fitting_functions.py::TestFuncLineal::test_scalar_input
# Run with coverage
pytest tests/ --cov=src --cov-report=html
# Run with verbose output
pytest tests/ -v
# Run tests in parallel (requires pytest-xdist)
pytest tests/ -n auto
Check coverage:
pytest tests/ --cov=src --cov-report=term-missing
Adding New Fitting Functionsο
See Extending RegressionLab for detailed guide.
Summary:
Add mathematical and fitting functions in
src/fitting/functions/(e.g.special.py,polynomials.py)Export the fit function from
src/fitting/functions/__init__.py, then register insrc/config/equations.yaml(add entry withfunction,formula,format,param_names)Add translations to
src/locales/(en.json, es.json, de.json)Write tests in
tests/test_fitting_functions.pyUpdate documentation
Adding Translationsο
To add a new language:
Create locale file:
src/locales/<language_code>.json
{
"menu": {
"normal_fitting": "Your translation",
"multiple_datasets": "Your translation"
},
"dialog": {
"select_file": "Your translation"
}
}
Update config: Add the language code to
SUPPORTED_LANGUAGE_CODESandLANGUAGE_ALIASESinsrc/config/constants.pyTest thoroughly: Check all UI elements in both interfaces
Update documentation: Add language to README and docs
Documentationο
Updating Documentationο
Documentation is in
docs/directoryUse Markdown format
Follow existing structure and style
Include code examples where appropriate
Add screenshots for UI changes (place in
docs/images/)
Building Documentationο
# Install documentation dependencies
pip install -r sphinx-docs/requirements.txt
# Build HTML documentation
cd sphinx-docs
./build_docs.sh # Linux/macOS
build_docs.bat # Windows
# View documentation
./open_docs.sh # Linux/macOS
open_docs.bat # Windows
Submitting Changesο
1. Commit Your Changesο
Write clear, descriptive commit messages:
# Good commit messages
git commit -m "Add exponential decay fitting function"
git commit -m "Fix unicode encoding issue in CSV loader"
git commit -m "Improve error message for missing uncertainty columns"
git commit -m "Update installation instructions for Windows"
# Bad commit messages (too vague)
git commit -m "Fixed stuff"
git commit -m "Update"
git commit -m "WIP"
Commit Message Format:
<type>: <short summary>
<detailed description (optional)>
<issue reference (if applicable)>
Types:
feat: New feature.fix: Bug fix.docs: Documentation changes.style: Code style changes (formatting, no logic change).refactor: Code refactoring.test: Adding or updating tests.chore: Maintenance tasks.
Example:
feat: Add logistic growth fitting function
Implements sigmoid/logistic growth curve fitting with
three parameters: carrying capacity (L), growth rate (k),
and midpoint (t0).
Closes #42
2. Push to Your Forkο
git push origin feature/your-feature-name
3. Create Pull Requestο
Go to your fork on GitHub
Click βNew Pull Requestβ
Select your branch
Fill out the pull request template:
Title: Clear, concise summary
Description: What changes were made and why
Testing: How you tested the changes
Screenshots: For UI changes
Closes: Reference any related issues
Pull Request Checklistο
Before submitting, ensure:
Code follows project style guidelines
All tests pass (
pytest tests/)New tests added for new functionality
Documentation updated (if needed)
Commit messages are clear and descriptive
No unnecessary files included (check
.gitignore)Type hints included
Docstrings added for new functions
Translations added (if UI changes)
CHANGELOG.md updated (for significant changes)
Review Processο
Automated checks: CI/CD runs tests automatically
Code review: Maintainer reviews your code
Feedback: Address any requested changes
Approval: Once approved, changes are merged
Cleanup: Delete your branch after merge
Development Setupο
Recommended Toolsο
IDE: Visual Studio Code, PyCharm, or your preference
Git Client: Command line, GitKraken, or GitHub Desktop
Python Version: 3.12 or higher
Virtual Environment: Always use virtual environments
VS Code Setupο
Recommended extensions:
Python (Microsoft)
Pylance
Python Test Explorer
GitLens
Markdown All in One
Workspace settings (.vscode/settings.json):
{
"ruff.enable": true,
"python.formatting.provider": "black",
"python.testing.pytestEnabled": true,
"editor.rulers": [100],
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}
The project uses Ruff for linting (see requirements-dev.txt and pyproject.toml optional [dev] dependencies). Ruff reads configuration from pyproject.toml. Install the Ruff extension for VS Code.
Project Structureο
Understanding the codebase:
RegressionLab/
βββ src/ # Source code
β βββ config/ # Configuration (env, theme, paths, constants, equations.yaml)
β βββ i18n.py # Internationalization
β βββ main_program.py # Tkinter entry point
β βββ fitting/ # Curve fitting (functions/, fitting_utils, workflow_controller)
β βββ frontend/ # Tkinter UI (ui_main_menu, image_utils, ui_dialogs/)
β βββ loaders/ # Data loaders, CSV/Excel
β βββ plotting/ # Plot utilities
β βββ streamlit_app/ # Streamlit web app (app.py, sections/)
β βββ locales/ # Translation JSON (en, es, de)
β βββ utils/ # Exceptions, logger, validators
βββ tests/ # Pytest suite (run_tests.py, conftest.py, test_*.py)
βββ docs/ # User documentation (Markdown)
βββ sphinx-docs/ # Sphinx sources and build scripts
βββ input/ # Sample datasets
βββ output/ # Generated plots
βββ bin/ # Launchers (run, run_streamlit, run_tests)
βββ scripts/ # Helper scripts (clean, generate_test_datasets, generate_multi_var_dataset)
βββ install.bat # Windows installation script
βββ install.sh # Linux/macOS installation script
βββ setup.bat # Windows setup script
βββ setup.sh # Linux/macOS setup script
βββ .env.example # Sample environment configuration (dotenv)
βββ .gitignore # git ignore rules
βββ requirements.txt # Python dependencies (runtime + Streamlit, Pillow)
βββ requirements-dev.txt # Developer dependencies (pytest, ruff, black, mypy, pre-commit)
βββ pyproject.toml # Project metadata, build config, and optional [dev] / [docs] deps
βββ README.md # Project overview/readme
βββ CHANGELOG.md # Project changelog
βββ LICENSE # License file
Communicationο
Asking Questionsο
GitHub Discussions: For general questions and ideas
GitHub Issues: For bug reports and feature requests
Email: For private inquiries
Reporting Bugsο
Use the GitHub issue template and include:
Title: Clear, specific description
Version: RegressionLab version
Environment: OS, Python version
Steps to reproduce: Exact steps
Expected behavior: What should happen
Actual behavior: What actually happens
Error messages: Full traceback
Sample data: If possible
Screenshots: For UI issues
Suggesting Featuresο
Use the GitHub feature request template:
Problem description: What problem does this solve?
Proposed solution: How should it work?
Alternatives: Other solutions considered
Additional context: Examples, mockups, etc.
Code of Conductο
Our Standardsο
Be respectful: Treat everyone with respect.
Be constructive: Provide helpful feedback.
Be patient: Everyone is learning.
Be professional: Keep discussions on-topic.
Unacceptable Behaviorο
Harassment or discriminatory language.
Personal attacks.
Trolling or inflammatory comments.
Publishing private information.
Other unprofessional conduct.
Enforcementο
Violations may result in:
Warning.
Temporary ban.
Permanent ban.
Report issues to: alejandro.mata.ali@gmail.com
Licenseο
By contributing to RegressionLab, you agree that your contributions will be licensed under the MIT License.
Recognitionο
Contributors may be recognized in:
A
CONTRIBUTORS.mdfile (if added to the project).Release notes.
Documentation credits.
Thank you for contributing to RegressionLab! π
Questions about contributing? Open a GitHub Discussion or email alejandro.mata.ali@gmail.com.
6. Commentsο
Use comments sparingly - prefer self-documenting code
Comments should explain why, not what
Keep comments up-to-date when code changes