# Project Structure

## Organization Philosophy

Domain-driven subpackage organization. Each morphometric method domain (landmark, harmonic, io, datasets, plot) is a subpackage. Implementation files are private (`_` prefixed), with public API re-exported through `__init__.py`.

## Directory Patterns

### Analysis Subpackages (`ktch/<domain>/`)
**Location**: `ktch/landmark/`, `ktch/harmonic/`
**Purpose**: Core morphometric analysis implementations
**Pattern**:
- Private implementation files: `_<method_name>.py` (e.g., `_procrustes_analysis.py`, `_elliptic_fourier_analysis.py`)
- Helper modules: `_<function>.py` (e.g., `_kernels.py`, `_kriging.py`)
- Co-located tests: `tests/test_<matching_name>.py`
- `__init__.py` re-exports public classes and functions

### I/O Module (`ktch/io/`)
**Purpose**: Read/write morphometric file formats
**Pattern**: One file per format (`_tps.py`, `_chc.py`, `_spharm_pdm.py`)

### Datasets (`ktch/datasets/`)
**Purpose**: Built-in example datasets with lazy download
**Pattern**: Loading functions `load_<type>_<name>()` in `_base.py`, per-dataset subdirectories in `data/<dataset_name>/`, descriptions in `descr/data_<dataset_name>.rst`
- **Remote data**: Large datasets (e.g., images) hosted on Cloudflare R2 with versioned registry (`_registry.py`), auto-updated via `scripts/update_registry.py`
- **Sample generation**: `_sample_generator.py` for synthetic test data

### Motion Analysis (`ktch/motion/`)
**Purpose**: Utility functions for analyzing motion (time-series of morphological properties)
**Pattern**: Currently a placeholder subpackage; follows the same private-module pattern as other analysis subpackages

### Visualization (`ktch/plot/`)
**Purpose**: Plotting functions separated from analysis logic
**Pattern**: One file per visualization domain (`_kriging.py`, `_pca.py`)

### Documentation (`doc/`)
**Purpose**: Sphinx documentation following Diataxis framework
**Pattern**: `tutorials/` (learning), `how-to/` (task-oriented), `explanation/` (concepts), `api/` (reference)

## Naming Conventions

- Modules: snake_case with `_` prefix for private (`_procrustes_analysis.py`)
- **Classes**: PascalCase, full method names (`GeneralizedProcrustesAnalysis`, `EllipticFourierAnalysis`)
- **Functions**: snake_case (`centroid_size`, `read_tps`, `tps_grid_2d_plot`)
- **Test files**: `test_<module_name>.py` mirroring source structure

## Import Organization

```python
# Standard library
import warnings

# Third-party
import numpy as np
from sklearn.base import TransformerMixin, BaseEstimator

# Local (relative within subpackage)
from ._kernels import tps_bending_energy
```

- **Within subpackages**: Relative imports (`from ._module import ...`)
- **Cross-subpackage**: Absolute imports (`from ktch.datasets import ...`)
- **Public API**: Re-exported in `__init__.py`

## Code Organization Principles

- **Sklearn contract**: Every analysis class inherits `TransformerMixin` + `BaseEstimator` and implements `fit`/`transform`
- **Separation of concerns**: Analysis logic, visualization, I/O, and data are in separate subpackages
- **Deprecation via `__getattr__`**: Moved/renamed APIs remain accessible with warnings (e.g., `outline` -> `harmonic`)
- **Test co-location**: Tests live inside each subpackage's `tests/` directory, not in a top-level `tests/` folder

---
_Document patterns, not file trees. New files following patterns shouldn't require updates_
