Loading...
No commits yet
Not committed History
Blame
Makefile • 16.6 KB
# ============================================
# SciTeX Template Research - Makefile
# ============================================
# Scientific research project workflow automation
# Location: /Makefile
#
# Key Features:
# - Script execution and pipeline management
# - Dependency installation and environment setup
# - Output cleaning and data management
# - Code formatting and quality checks
# - Testing automation
#
# Usage:
#   make help                      # Show this help
#   make install                   # Install dependencies
#   make run-mnist                 # Run MNIST example pipeline
#   make clean                     # Clean outputs
#   make format                    # Format code
#   make test                      # Run tests

.PHONY: \
	help \
	install \
	install-dev \
	setup \
	setup-writer \
	run-mnist \
	run-mnist-download \
	run-mnist-plot-digits \
	run-mnist-plot-umap \
	run-mnist-clf-svm \
	run-mnist-conf-mat \
	clean \
	clean-mnist \
	clean-outputs \
	clean-data \
	clean-logs \
	clean-all \
	clean-python \
	clean-writer \
	test \
	test-verbose \
	test-sync \
	format \
	format-python \
	format-shell \
	lint \
	lint-python \
	check \
	info \
	tree \
	verify \
	show-config

.DEFAULT_GOAL := help

# ============================================
# Configuration
# ============================================
PYTHON := python3
PIP := pip3
SCRIPTS_DIR := scripts
MNIST_DIR := $(SCRIPTS_DIR)/mnist
CONFIG_DIR := config
DATA_DIR := data
TESTS_DIR := tests
SCITEX_DIR := scitex
WRITER_DIR := $(SCITEX_DIR)/writer

# Colors
GREEN := \033[0;32m
YELLOW := \033[0;33m
RED := \033[0;31m
CYAN := \033[0;36m
BLUE := \033[0;34m
NC := \033[0m

# ============================================
# Help
# ============================================
help:
	@echo ""
	@echo "$(GREEN)############################################################$(NC)"
	@echo "$(GREEN)#      SciTeX Template Research - Makefile                  $(NC)"
	@echo "$(GREEN)############################################################$(NC)"
	@echo ""
	@echo "$(CYAN)Setup & Installation:$(NC)"
	@echo "  make install                       # Install Python dependencies"
	@echo "  make install-dev                   # Install dev dependencies (testing, linting)"
	@echo "  make setup                         # Complete setup (install + verify)"
	@echo "  make setup-writer                  # Clone writer template project (example_paper)"
	@echo ""
	@echo "$(CYAN)Running Scripts:$(NC)"
	@echo "  make run-mnist                     # Run complete MNIST pipeline"
	@echo "  make run-mnist-download            # Download MNIST data"
	@echo "  make run-mnist-plot-digits         # Plot MNIST digits"
	@echo "  make run-mnist-plot-umap           # Create UMAP visualization"
	@echo "  make run-mnist-clf-svm             # Train SVM classifier"
	@echo "  make run-mnist-conf-mat            # Plot confusion matrix"
	@echo ""
	@echo "$(CYAN)Cleaning:$(NC)"
	@echo "  make clean                         # Clean script outputs"
	@echo "  make clean-mnist                   # Clean MNIST outputs only"
	@echo "  make clean-outputs                 # Clean all *_out directories"
	@echo "  make clean-data                    # Clean generated data files"
	@echo "  make clean-logs                    # Clean log files"
	@echo "  make clean-writer                  # Remove writer projects (use with caution!)"
	@echo "  make clean-all                     # Clean everything (outputs + data + cache)"
	@echo "  make clean-python                  # Clean Python cache files"
	@echo ""
	@echo "$(CYAN)Code Quality:$(NC)"
	@echo "  make format                        # Format all code (Python + Shell)"
	@echo "  make format-python                 # Format Python with ruff"
	@echo "  make format-shell                  # Format shell with shfmt + shellcheck"
	@echo "  make lint                          # Lint code with ruff"
	@echo "  make check                         # Run format + lint + test"
	@echo ""
	@echo "$(CYAN)Testing:$(NC)"
	@echo "  make test                          # Run all tests"
	@echo "  make test-verbose                  # Run tests with verbose output"
	@echo "  make test-sync                     # Sync test structure with scripts"
	@echo ""
	@echo "$(CYAN)Information:$(NC)"
	@echo "  make info                          # Show project information"
	@echo "  make tree                          # Show project structure"
	@echo "  make verify                        # Verify installation and config"
	@echo "  make show-config                   # Display configuration files (requires yq)"
	@echo ""

# ============================================
# Installation & Setup
# ============================================
install:
	@echo "$(CYAN)Installing Python dependencies...$(NC)"
	@if [ -f requirements.txt ]; then \
		$(PIP) install -r requirements.txt; \
		echo "$(GREEN)Dependencies installed$(NC)"; \
	else \
		echo "$(RED)requirements.txt not found$(NC)"; \
		exit 1; \
	fi

install-dev:
	@echo "$(CYAN)Installing development dependencies...$(NC)"
	@$(PIP) install pytest pytest-cov ruff black isort mypy
	@echo "$(GREEN)Development dependencies installed$(NC)"

setup: install
	@echo "$(CYAN)Setting up project...$(NC)"
	@mkdir -p $(DATA_DIR)
	@mkdir -p $(DATA_DIR)/mnist/figures
	@mkdir -p $(DATA_DIR)/mnist/models
	@mkdir -p $(DATA_DIR)/mnist/raw
	@echo "$(GREEN)Project setup complete$(NC)"
	@$(MAKE) verify
	@echo ""
	@echo "$(YELLOW)To create a writer project, run:$(NC)"
	@echo "  make setup-writer"
	@echo "  $(YELLOW)or manually:$(NC) scitex writer clone $(WRITER_DIR)/your_paper_name"
	@echo ""

setup-writer:
	@echo "$(CYAN)Setting up writer project...$(NC)"
	@if [ -d "$(WRITER_DIR)/example_paper" ]; then \
		echo "$(YELLOW)Writer project already exists at $(WRITER_DIR)/example_paper$(NC)"; \
		echo "$(YELLOW)To create a new project, use:$(NC)"; \
		echo "  scitex writer clone $(WRITER_DIR)/your_paper_name"; \
		echo ""; \
		echo "$(YELLOW)Git strategies available:$(NC)"; \
		echo "  --git-strategy child   (default: independent git repo)"; \
		echo "  --git-strategy parent  (track in main repo)"; \
		echo "  --git-strategy origin  (preserve template history)"; \
		echo "  --git-strategy none    (no git initialization)"; \
	else \
		echo "$(CYAN)Cloning writer template to $(WRITER_DIR)/example_paper...$(NC)"; \
		scitex writer clone $(WRITER_DIR)/example_paper; \
		echo "$(GREEN)Writer project created successfully!$(NC)"; \
		echo ""; \
		echo "$(CYAN)To compile the manuscript:$(NC)"; \
		echo "  cd $(WRITER_DIR)/example_paper"; \
		echo "  scitex writer compile manuscript"; \
		echo ""; \
		echo "$(YELLOW)Note: Uses 'child' git strategy (independent repository)$(NC)"; \
		echo "$(YELLOW)To use parent repo instead:$(NC)"; \
		echo "  scitex writer clone $(WRITER_DIR)/your_paper --git-strategy parent"; \
		echo ""; \
	fi

verify:
	@echo "$(CYAN)Verifying installation...$(NC)"
	@echo ""
	@echo "$(CYAN)Python version:$(NC)"
	@$(PYTHON) --version
	@echo ""
	@echo "$(CYAN)Checking required packages:$(NC)"
	@for pkg in scitex torch torchvision scikit-learn umap-learn seaborn numpy pandas matplotlib; do \
		if $(PYTHON) -c "import $$pkg" 2>/dev/null; then \
			echo "  $(GREEN)[OK]$(NC) $$pkg"; \
		else \
			echo "  $(RED)[MISSING]$(NC) $$pkg"; \
		fi; \
	done
	@echo ""
	@echo "$(CYAN)Checking configuration files:$(NC)"
	@for cfg in PATH.yaml MNIST.yaml; do \
		if [ -f $(CONFIG_DIR)/$$cfg ]; then \
			echo "  $(GREEN)[OK]$(NC) $$cfg"; \
		else \
			echo "  $(YELLOW)[WARNING]$(NC) $$cfg $(YELLOW)(missing)$(NC)"; \
		fi; \
	done
	@echo ""

# ============================================
# Running MNIST Scripts
# ============================================
run-mnist: run-mnist-download run-mnist-plot-digits run-mnist-plot-umap run-mnist-clf-svm run-mnist-conf-mat
	@echo ""
	@echo "$(GREEN)MNIST pipeline complete!$(NC)"
	@echo ""
	@echo "$(CYAN)Results available in:$(NC)"
	@echo "  - $(DATA_DIR)/mnist/figures/"
	@echo "  - $(MNIST_DIR)/*_out/"

run-mnist-download:
	@echo "$(CYAN)Downloading MNIST dataset...$(NC)"
	@cd $(MNIST_DIR) && $(PYTHON) 01_download.py
	@echo "$(GREEN)Download complete$(NC)"

run-mnist-plot-digits:
	@echo "$(CYAN)Plotting MNIST digits...$(NC)"
	@cd $(MNIST_DIR) && $(PYTHON) 02_plot_digits.py
	@echo "$(GREEN)Plots generated$(NC)"

run-mnist-plot-umap:
	@echo "$(CYAN)Creating UMAP visualization...$(NC)"
	@cd $(MNIST_DIR) && $(PYTHON) 03_plot_umap_space.py
	@echo "$(GREEN)UMAP visualization complete$(NC)"

run-mnist-clf-svm:
	@echo "$(CYAN)Training SVM classifier...$(NC)"
	@cd $(MNIST_DIR) && $(PYTHON) 04_clf_svm.py
	@echo "$(GREEN)SVM training complete$(NC)"

run-mnist-conf-mat:
	@echo "$(CYAN)Plotting confusion matrix...$(NC)"
	@cd $(MNIST_DIR) && $(PYTHON) 05_plot_conf_mat.py
	@echo "$(GREEN)Confusion matrix generated$(NC)"

# ============================================
# Cleaning
# ============================================
clean: clean-outputs clean-logs clean-python
	@echo "$(GREEN)Cleaned outputs and logs$(NC)"

clean-mnist:
	@echo "$(YELLOW)Cleaning MNIST outputs...$(NC)"
	@rm -rf $(MNIST_DIR)/*_out/
	@echo "$(GREEN)MNIST outputs cleaned$(NC)"

clean-outputs:
	@echo "$(YELLOW)Cleaning all script outputs...$(NC)"
	@find $(SCRIPTS_DIR) -type d -name "*_out" -exec rm -rf {} + 2>/dev/null || true
	@echo "$(GREEN)All outputs cleaned$(NC)"

clean-data:
	@echo "$(RED)WARNING: This will delete all generated data files!$(NC)"
	@printf "Type 'yes' to confirm: "; \
	read confirm; \
	if [ "$$confirm" = "yes" ]; then \
		echo "$(YELLOW)Cleaning data directory...$(NC)"; \
		rm -rf $(DATA_DIR)/mnist/*.npy 2>/dev/null || true; \
		rm -rf $(DATA_DIR)/mnist/*.pkl 2>/dev/null || true; \
		rm -rf $(DATA_DIR)/mnist/figures/*.jpg 2>/dev/null || true; \
		rm -rf $(DATA_DIR)/mnist/figures/*.csv 2>/dev/null || true; \
		rm -rf $(DATA_DIR)/mnist/models/*.pkl 2>/dev/null || true; \
		echo "$(GREEN)Data cleaned$(NC)"; \
	else \
		echo "$(YELLOW)Cancelled$(NC)"; \
	fi

clean-logs:
	@echo "$(YELLOW)Cleaning log files...$(NC)"
	@find $(SCRIPTS_DIR) -type f -name "*.log" -delete 2>/dev/null || true
	@find $(SCRIPTS_DIR) -type d -name "RUNNING" -exec rm -rf {}/logs \; 2>/dev/null || true
	@find $(SCRIPTS_DIR) -type d -name "FINISHED_SUCCESS" -exec rm -rf {}/*/logs \; 2>/dev/null || true
	@find $(SCRIPTS_DIR) -type d -name "FINISHED_FAILED" -exec rm -rf {}/*/logs \; 2>/dev/null || true
	@echo "$(GREEN)Logs cleaned$(NC)"

clean-all: clean-outputs clean-data clean-logs clean-python
	@echo "$(RED)WARNING: This will delete ALL generated files!$(NC)"
	@printf "Type 'DELETE ALL' to confirm: "; \
	read confirm; \
	if [ "$$confirm" = "DELETE ALL" ]; then \
		echo "$(YELLOW)Deep cleaning...$(NC)"; \
		rm -rf $(DATA_DIR)/mnist/raw/* 2>/dev/null || true; \
		echo "$(GREEN)Complete cleanup done$(NC)"; \
	else \
		echo "$(YELLOW)Cancelled$(NC)"; \
	fi

clean-python:
	@echo "$(YELLOW)Cleaning Python cache files...$(NC)"
	@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
	@find . -type f -name "*.pyc" -delete 2>/dev/null || true
	@find . -type f -name "*.pyo" -delete 2>/dev/null || true
	@find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
	@find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
	@find . -type d -name ".ruff_cache" -exec rm -rf {} + 2>/dev/null || true
	@find . -type d -name ".mypy_cache" -exec rm -rf {} + 2>/dev/null || true
	@echo "$(GREEN)Python cache cleaned$(NC)"

clean-writer:
	@echo "$(RED)WARNING: This will DELETE all writer projects!$(NC)"
	@echo "$(RED)Each writer project is an independent git repository.$(NC)"
	@echo "$(RED)Make sure you have pushed any uncommitted changes!$(NC)"
	@printf "Type 'DELETE WRITER PROJECTS' to confirm: "; \
	read confirm; \
	if [ "$$confirm" = "DELETE WRITER PROJECTS" ]; then \
		echo "$(YELLOW)Removing all writer projects...$(NC)"; \
		if [ -d "$(WRITER_DIR)" ]; then \
			rm -rf $(WRITER_DIR)/*/; \
			echo "$(GREEN)Writer projects removed$(NC)"; \
		else \
			echo "$(YELLOW)No writer directory found$(NC)"; \
		fi; \
	else \
		echo "$(YELLOW)Cancelled$(NC)"; \
	fi

# ============================================
# Testing
# ============================================
test:
	@echo "$(CYAN)Running tests...$(NC)"
	@if command -v pytest >/dev/null 2>&1; then \
		pytest $(TESTS_DIR) -q; \
	else \
		echo "$(YELLOW)pytest not installed. Run: make install-dev$(NC)"; \
		exit 1; \
	fi

test-verbose:
	@echo "$(CYAN)Running tests (verbose)...$(NC)"
	@if command -v pytest >/dev/null 2>&1; then \
		pytest $(TESTS_DIR) -v; \
	else \
		echo "$(YELLOW)pytest not installed. Run: make install-dev$(NC)"; \
		exit 1; \
	fi

test-sync:
	@echo "$(CYAN)Synchronizing test structure with scripts...$(NC)"
	@$(TESTS_DIR)/sync_tests_with_scripts.sh
	@echo "$(GREEN)Test synchronization complete$(NC)"

# ============================================
# Code Quality
# ============================================
format: format-python format-shell
	@echo ""
	@echo "$(GREEN)All formatting and linting complete!$(NC)"

format-python:
	@echo "$(CYAN)Formatting Python code with ruff...$(NC)"
	@if command -v ruff >/dev/null 2>&1; then \
		ruff format $(SCRIPTS_DIR) $(TESTS_DIR) --quiet || echo "$(YELLOW)Ruff formatting completed with warnings$(NC)"; \
		echo "$(GREEN)Python formatting complete$(NC)"; \
	else \
		echo "$(RED)Ruff not found. Install with: pip install ruff$(NC)"; \
		exit 1; \
	fi

format-shell:
	@echo "$(CYAN)Formatting and linting shell scripts...$(NC)"
	@if command -v shfmt >/dev/null 2>&1; then \
		find $(SCRIPTS_DIR) -name "*.sh" \
			! -path "*/node_modules/*" \
			! -path "*/.venv/*" \
			-exec shfmt -w -i 4 -bn -ci -sr {} + \
			2>&1 || echo "$(YELLOW)shfmt formatting completed with warnings$(NC)"; \
		echo "$(GREEN)Shell formatting complete!$(NC)"; \
	else \
		echo "$(YELLOW)shfmt not found. Install with: go install mvdan.cc/sh/v3/cmd/shfmt@latest$(NC)"; \
		echo "$(YELLOW)Skipping shell formatting...$(NC)"; \
	fi
	@if command -v shellcheck >/dev/null 2>&1; then \
		find $(SCRIPTS_DIR) -name "*.sh" \
			! -path "*/node_modules/*" \
			! -path "*/.venv/*" \
			-exec shellcheck --severity=error {} + \
			2>&1 || echo "$(RED)ShellCheck found errors$(NC)"; \
		echo "$(GREEN)Shell linting complete!$(NC)"; \
	else \
		echo "$(YELLOW)shellcheck not found. Install with: sudo apt-get install shellcheck$(NC)"; \
		echo "$(YELLOW)Skipping shell linting...$(NC)"; \
	fi

lint: lint-python

lint-python:
	@echo "$(CYAN)Linting Python code with ruff...$(NC)"
	@if command -v ruff >/dev/null 2>&1; then \
		ruff check $(SCRIPTS_DIR) $(TESTS_DIR) --quiet || echo "$(RED)Ruff found issues$(NC)"; \
		echo "$(GREEN)Linting complete$(NC)"; \
	else \
		echo "$(RED)Ruff not found. Install with: pip install ruff$(NC)"; \
		exit 1; \
	fi

check: format lint test
	@echo ""
	@echo "$(GREEN)All checks passed!$(NC)"

# ============================================
# Information & Diagnostics
# ============================================
info:
	@echo "$(CYAN)Project Information:$(NC)"
	@echo ""
	@echo "  $(CYAN)Project:$(NC) SciTeX Template Research"
	@echo "  $(CYAN)Python:$(NC) $$($(PYTHON) --version 2>&1)"
	@echo "  $(CYAN)Scripts:$(NC) $$(find $(SCRIPTS_DIR) -name "*.py" | wc -l) Python files"
	@echo "  $(CYAN)Config:$(NC) $$(ls -1 $(CONFIG_DIR)/*.yaml 2>/dev/null | wc -l) YAML files"
	@echo ""
	@echo "  $(CYAN)MNIST Scripts:$(NC)"
	@echo "    - $$(ls -1 $(MNIST_DIR)/*.py 2>/dev/null | wc -l) scripts"
	@echo "    - $$(ls -1d $(MNIST_DIR)/*_out 2>/dev/null | wc -l) output directories"
	@echo ""
	@if [ -d $(DATA_DIR)/mnist/figures ]; then \
		echo "  $(CYAN)Generated Figures:$(NC) $$(ls -1 $(DATA_DIR)/mnist/figures/*.jpg 2>/dev/null | wc -l)"; \
	fi
	@if [ -d $(DATA_DIR)/mnist/models ]; then \
		echo "  $(CYAN)Saved Models:$(NC) $$(ls -1 $(DATA_DIR)/mnist/models/*.pkl 2>/dev/null | wc -l)"; \
	fi

tree:
	@echo "$(CYAN)Project Structure:$(NC)"
	@if command -v tree >/dev/null 2>&1; then \
		tree -L 3 -I '__pycache__|*.pyc|.git|.venv|*.egg-info|.pytest_cache|.ruff_cache|.mypy_cache' -C; \
	else \
		echo "$(YELLOW)tree command not found. Install with: sudo apt-get install tree$(NC)"; \
		ls -R; \
	fi

show-config:
	@echo "$(CYAN)Configuration Files:$(NC)"
	@echo ""
	@if command -v yq >/dev/null 2>&1; then \
		for cfg in $(CONFIG_DIR)/*.yaml; do \
			if [ -f "$$cfg" ]; then \
				echo "$(GREEN)$$cfg:$(NC)"; \
				yq -C '.' "$$cfg" 2>/dev/null || cat "$$cfg"; \
				echo ""; \
			fi; \
		done; \
	else \
		echo "$(YELLOW)yq not installed. Showing raw YAML files:$(NC)"; \
		echo "$(YELLOW)(Install yq for colored output: sudo apt-get install yq or brew install yq)$(NC)"; \
		echo ""; \
		for cfg in $(CONFIG_DIR)/*.yaml; do \
			if [ -f "$$cfg" ]; then \
				echo "$(GREEN)$$cfg:$(NC)"; \
				cat "$$cfg"; \
				echo ""; \
			fi; \
		done; \
	fi

# ============================================
# Utility Targets
# ============================================
.SILENT: help install verify

# EOF