Skip to content

Commit c1ca120

Browse files
committed
v0.2.0 update
1 parent c388db1 commit c1ca120

File tree

10 files changed

+355
-674
lines changed

10 files changed

+355
-674
lines changed

.github/workflows/publish.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
test_pypi:
9+
description: 'Publish to Test PyPI instead of PyPI'
10+
required: false
11+
default: false
12+
type: boolean
13+
14+
jobs:
15+
publish:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
id-token: write # Required for trusted publishing
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.11'
28+
29+
- name: Install build dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
python -m pip install build twine
33+
34+
- name: Build package
35+
run: python -m build
36+
37+
- name: Check package
38+
run: python -m twine check dist/*
39+
40+
- name: Publish to Test PyPI
41+
if: ${{ github.event.inputs.test_pypi == 'true' }}
42+
uses: pypa/gh-action-pypi-publish@release/v1
43+
with:
44+
repository-url: https://test.pypi.org/legacy/
45+
print-hash: true
46+
47+
- name: Publish to PyPI
48+
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
49+
uses: pypa/gh-action-pypi-publish@release/v1
50+
with:
51+
print-hash: true

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.2.0] - 2025-12-06
9+
10+
### Changed
11+
12+
- **BREAKING**: Minimum Python version raised to 3.11
13+
- **Dependencies**: Updated ngraph to >=0.12.0
14+
15+
## [0.1.0] - Previous Release
16+
17+
Initial release of NetLab metrics and analysis tools.

LICENSE

Lines changed: 73 additions & 599 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,30 @@
11
# NetLab Development Makefile
22

3-
.PHONY: help dev install check check-ci lint format test qt clean build check-dist publish-test publish info
3+
.PHONY: help venv clean-venv dev install check check-ci lint format test qt build clean check-dist publish-test publish info hooks check-python
44

55
.DEFAULT_GOAL := help
66

7-
VENV_BIN := $(PWD)/netlab-venv/bin
8-
PYTHON := $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,python3)
7+
# --------------------------------------------------------------------------
8+
# Python interpreter detection
9+
# --------------------------------------------------------------------------
10+
# VENV_BIN: path to local virtualenv bin directory
11+
VENV_BIN := $(PWD)/venv/bin
12+
13+
# PY_BEST: scan for newest supported Python (used when creating new venvs)
14+
# Supports 3.11-3.13 to match common CI matrix
15+
PY_BEST := $(shell for v in 3.13 3.12 3.11; do command -v python$$v >/dev/null 2>&1 && { echo python$$v; exit 0; }; done; command -v python3 2>/dev/null || command -v python 2>/dev/null)
16+
17+
# PY_PATH: active python3/python on PATH (respects CI setup-python and activated venvs)
18+
PY_PATH := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null)
19+
20+
# PYTHON: interpreter used for all commands
21+
# 1. Use local venv if present
22+
# 2. Otherwise use active python on PATH (important for CI)
23+
# 3. Fall back to best available version
24+
# 4. Final fallback to 'python3' literal for clear error messages
25+
PYTHON ?= $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,$(if $(PY_PATH),$(PY_PATH),$(if $(PY_BEST),$(PY_BEST),python3)))
26+
27+
# Derived tool commands (always use -m to ensure correct environment)
928
PIP := $(PYTHON) -m pip
1029
PYTEST := $(PYTHON) -m pytest
1130
RUFF := $(PYTHON) -m ruff
@@ -15,12 +34,14 @@ help:
1534
@echo "🔧 NetLab Development Commands"
1635
@echo ""
1736
@echo "Setup & Installation:"
18-
@echo " make install - Install package for usage (no dev dependencies)"
37+
@echo " make venv - Create a local virtualenv (./venv)"
1938
@echo " make dev - Full development environment (package + dev deps + hooks)"
39+
@echo " make install - Install package for usage (no dev dependencies)"
40+
@echo " make clean-venv - Remove virtual environment"
2041
@echo ""
2142
@echo "Code Quality & Testing:"
22-
@echo " make check - Run lint + tests"
23-
@echo " make check-ci - Run non-mutating checks and tests (CI entrypoint)"
43+
@echo " make check - Run pre-commit (auto-fix) + tests, then lint"
44+
@echo " make check-ci - Run non-mutating lint + tests (CI entrypoint)"
2445
@echo " make lint - Run only linting (non-mutating: ruff + pyright)"
2546
@echo " make format - Auto-format code with ruff"
2647
@echo " make test - Run tests with coverage"
@@ -35,19 +56,56 @@ help:
3556
@echo ""
3657
@echo "Utilities:"
3758
@echo " make info - Show project information"
59+
@echo " make hooks - Run pre-commit on all files"
60+
@echo " make check-python - Check if venv Python matches best available"
3861

3962
dev:
4063
@echo "🚀 Setting up development environment..."
41-
@bash dev/setup-dev.sh
64+
@if [ ! -x "$(VENV_BIN)/python" ]; then \
65+
if [ -z "$(PY_BEST)" ]; then \
66+
echo "❌ Error: No Python interpreter found (python3 or python)"; \
67+
exit 1; \
68+
fi; \
69+
echo "🐍 Creating virtual environment with $(PY_BEST) ..."; \
70+
$(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }; \
71+
if [ ! -x "$(VENV_BIN)/python" ]; then \
72+
echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \
73+
exit 1; \
74+
fi; \
75+
$(VENV_BIN)/python -m pip install -U pip setuptools wheel; \
76+
fi
77+
@echo "📦 Installing dev dependencies..."
78+
@$(VENV_BIN)/python -m pip install -e .'[dev]'
79+
@echo "🔗 Installing pre-commit hooks..."
80+
@$(VENV_BIN)/python -m pre_commit install --install-hooks
81+
@echo "✅ Dev environment ready. Activate with: source venv/bin/activate"
82+
@$(MAKE) check-python
83+
84+
venv:
85+
@echo "🐍 Creating virtual environment in ./venv ..."
86+
@if [ -z "$(PY_BEST)" ]; then \
87+
echo "❌ Error: No Python interpreter found (python3 or python)"; \
88+
exit 1; \
89+
fi
90+
@$(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }
91+
@if [ ! -x "$(VENV_BIN)/python" ]; then \
92+
echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \
93+
exit 1; \
94+
fi
95+
@$(VENV_BIN)/python -m pip install -U pip setuptools wheel
96+
@echo "✅ venv ready. Activate with: source venv/bin/activate"
97+
98+
clean-venv:
99+
@rm -rf venv/
42100

43101
install:
44102
@echo "📦 Installing package for usage (no dev dependencies)..."
45103
@$(PIP) install -e .
46104

47105
check:
48106
@echo "🔍 Running complete code quality checks and tests..."
49-
@$(MAKE) lint
50107
@PYTHON=$(PYTHON) bash dev/run-checks.sh
108+
@$(MAKE) lint
51109

52110
check-ci:
53111
@echo "🔍 Running CI checks (non-mutating lint + tests)..."
@@ -83,14 +141,13 @@ build:
83141

84142
clean:
85143
@echo "🧹 Cleaning build artifacts and cache files..."
86-
@rm -rf build/
87-
@rm -rf dist/
88-
@rm -rf *.egg-info/
89-
@find . -type f -name "*.pyc" -delete
90-
@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
91-
@find . -type f -name "*.pyo" -delete
92-
@find . -type f -name "*~" -delete
93-
@find . -type f -name "*.orig" -delete
144+
@rm -rf build/ dist/ *.egg-info/
145+
@rm -rf .pytest_cache .ruff_cache .mypy_cache htmlcov .coverage coverage.xml coverage-*.xml .benchmarks .pytest-benchmark || true
146+
@find . -path "./venv" -prune -o -type f -name "*.pyc" -delete 2>/dev/null || true
147+
@find . -path "./venv" -prune -o -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
148+
@find . -path "./venv" -prune -o -type f -name "*.pyo" -delete 2>/dev/null || true
149+
@find . -path "./venv" -prune -o -type f -name "*~" -delete 2>/dev/null || true
150+
@find . -path "./venv" -prune -o -type f -name "*.orig" -delete 2>/dev/null || true
94151
@echo "✅ Cleanup complete!"
95152

96153
check-dist:
@@ -125,7 +182,9 @@ info:
125182
@echo "============================="
126183
@echo ""
127184
@echo "🐍 Python Environment:"
128-
@echo " Python version: $$($(PYTHON) --version)"
185+
@echo " Python (active): $$($(PYTHON) --version)"
186+
@echo " Python (best): $$($(PY_BEST) --version 2>/dev/null || echo 'missing')"
187+
@$(MAKE) check-python
129188
@echo " Package version: $$($(PYTHON) -c 'import importlib.metadata as m; print(m.version("netlab"))' 2>/dev/null || echo 'Not installed')"
130189
@echo " Virtual environment: $$(echo $$VIRTUAL_ENV | sed 's|.*/||' || echo 'None active')"
131190
@echo ""
@@ -136,3 +195,17 @@ info:
136195
@echo " Pyright: $$($(PYTHON) -m pyright --version 2>/dev/null | head -1 || echo 'Not installed')"
137196
@echo " Build: $$($(PYTHON) -m build --version 2>/dev/null | sed 's/build //' | sed 's/ (.*//' || echo 'Not installed')"
138197
@echo " Twine: $$($(PYTHON) -m twine --version 2>/dev/null | grep -o 'twine version [0-9.]*' | cut -d' ' -f3 || echo 'Not installed')"
198+
199+
hooks:
200+
@echo "🔗 Running pre-commit on all files..."
201+
@$(PRECOMMIT) run --all-files || (echo "Some pre-commit hooks failed. Fix and re-run." && exit 1)
202+
203+
check-python:
204+
@if [ -x "$(VENV_BIN)/python" ]; then \
205+
VENV_VER=$$($(VENV_BIN)/python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \
206+
BEST_VER=$$($(PY_BEST) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \
207+
if [ -n "$$VENV_VER" ] && [ -n "$$BEST_VER" ] && [ "$$VENV_VER" != "$$BEST_VER" ]; then \
208+
echo "⚠️ WARNING: venv Python ($$VENV_VER) != best available Python ($$BEST_VER)"; \
209+
echo " Run 'make clean-venv && make dev' to recreate venv if desired"; \
210+
fi; \
211+
fi

README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# NetLab
2+
3+
Metrics aggregation and statistical analysis for [NetGraph](https://github.com/networmix/NetGraph) simulation results.
4+
5+
## Overview
6+
7+
NetLab processes NetGraph workflow outputs (JSON artifacts) to compute statistical metrics across random seeds and failure scenarios. Provides CLI and Python API for batch analysis, cross-seed aggregation, and visualization.
8+
9+
## Features
10+
11+
### Metrics
12+
13+
- **BAC (Bandwidth Availability Curve)**: Delivered bandwidth quantiles, availability at thresholds, AUC normalization
14+
- **Latency**: Stretch distributions (p50/p99), tail degradation ratios, SLO compliance, WES (Weighted Excess Stretch)
15+
- **IterationOps**: Per-iteration SPF calls, flows created, reoptimization calls, placement iterations
16+
- **SPS (Structural Pair Survivability)**: Fraction of src-dst pairs meeting demand under failures
17+
- **MSD (Maximum Supported Demand)**: Alpha-star multiplier for traffic matrix scaling capacity
18+
- **CostPower**: CapEx/Power totals, USD/Watt per Gbit (offered and at p99.9 reliability)
19+
20+
### Cross-Seed Analysis
21+
22+
- Positional alignment of time-series data by iteration index
23+
- Median and IQR (interquartile range) computation
24+
- Variable-length series handling with NaN padding
25+
26+
### Visualization
27+
28+
- Cross-seed plots with median curves and IQR bands
29+
- Baseline-normalized delta comparisons
30+
- Statistical significance heatmaps (p-values)
31+
32+
## Installation
33+
34+
```bash
35+
pip install netlab
36+
```
37+
38+
From source:
39+
40+
```bash
41+
git clone https://github.com/networmix/NetLab
42+
cd NetLab
43+
make dev
44+
```
45+
46+
## Usage
47+
48+
### CLI
49+
50+
```bash
51+
# Compute metrics for scenarios
52+
netlab metrics tests/data/scenarios/
53+
54+
# With summary tables and plots
55+
netlab metrics tests/data/scenarios/ --summary
56+
57+
# Filter specific scenarios
58+
netlab metrics tests/data/scenarios/ --only small_clos,small_dragonfly
59+
60+
# Skip plot generation
61+
netlab metrics tests/data/scenarios/ --no-plots
62+
```
63+
64+
### Python API
65+
66+
```python
67+
from metrics.bac import compute_bac_metrics
68+
from metrics.aggregate import summarize_across_seeds
69+
70+
# Compute BAC for a workflow step
71+
bac = compute_bac_metrics(iterations, offered_bw, step_name="max_demand")
72+
print(f"p99 availability: {bac['q_pct'][0.99]:.2%}")
73+
74+
# Aggregate across seeds
75+
summary = summarize_across_seeds(series_by_seed, label="latency_p99")
76+
```
77+
78+
## Repository Structure
79+
80+
```
81+
metrics/ # Core metrics modules
82+
bac.py # Bandwidth availability
83+
latency.py # Latency percentiles
84+
iterops.py # Iteration analysis
85+
aggregate.py # Cross-seed aggregation
86+
plot_*.py # Visualization
87+
netlab/ # CLI
88+
cli.py # Command-line interface
89+
metrics_cmd.py # Metrics command implementation
90+
tests/ # Test suite
91+
lib/ # Config files
92+
```
93+
94+
## Development
95+
96+
```bash
97+
make dev # Setup environment
98+
make check # Tests and linting
99+
make test # Tests only
100+
make lint # Linting only
101+
```
102+
103+
## Requirements
104+
105+
- Python 3.11+
106+
- Dependencies: numpy, pandas, matplotlib, seaborn, scipy, rich, ngraph
107+
108+
## License
109+
110+
AGPL-3.0-or-later

dev/setup-dev.sh

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)