# Analyzers Baseline - Claude Guidelines

Baseline implementation for blockchain analytics feature extraction and pattern detection.

---

## Quick Reference

### Run Scripts in Docker

**Use WSL for Docker and git commands on Windows:**

```bash
wsl bash -c "cd /mnt/c/work12/chainswarm/analyzers-baseline && docker run --rm -it -v \$(pwd):/app -w /app --network host ghcr.io/chainswarm/subnet-base:latest python src/chainswarm_analyzers_baseline/scripts/run_features.py --help"
```

### Credentials

**ClickHouse:** `192.168.50.234` / `user` / `password1234` / db: `torus` or `bittensor`

### Coding Rules

- Use loguru for logging
- Conventional commits: `feat:`, `fix:`, `docs:`
- Keep changes minimal and focused
- **Update CHANGELOG.md** after fixing bugs or adding features

---

## Architecture

```
src/chainswarm_analyzers_baseline/
  ├── adapters/           ← Data loading (parquet, etc.)
  ├── backends/           ← Algorithm dispatch (cuGraph GPU + Rust CPU)
  ├── graph/              ← Graph data structure (nx.DiGraph)
  ├── features/           ← Feature extraction
  ├── patterns/           ← Pattern detection
  ├── aggregates/         ← Aggregation logic
  ├── pipeline/           ← Processing pipeline
  ├── protocols/          ← Interface definitions
  ├── config/             ← Configuration
  └── scripts/            ← Entry point scripts
      ├── run_features.py
      └── run_patterns.py
```

**Note:** NetworkX is used only for the graph data structure. All graph algorithms run on cuGraph (GPU) or Rust (petgraph + rayon).

## Algorithm Backends

All graph algorithms use optimized backends - NO pure Python/NetworkX computation:

**GPU Backend (cuGraph):**
- Louvain community detection (33x faster than NetworkX)
- PageRank centrality (9x faster)
- Triangle counting (10x faster)
- Betweenness centrality (19x faster)

**Rust Backend (petgraph + rayon):**
- Strongly Connected Components (9x faster than NetworkX)
- BFS / multi-source BFS (parallel)
- Simple cycle enumeration
- Layering path detection

**Usage:**
```python
from chainswarm_analyzers_baseline.backends import AlgorithmDispatcher

dispatcher = AlgorithmDispatcher(G)  # G is nx.DiGraph
sccs = dispatcher.strongly_connected_components()  # Runs on Rust
communities = dispatcher.louvain()  # Runs on GPU
```

## Key Components

### Adapters (`adapters/`)

Load data from various sources:

- `parquet.py` - Read Parquet files exported from data-pipeline

```python
from chainswarm_analyzers_baseline.adapters.parquet import load_flows
flows = load_flows("path/to/flows.parquet")
```

### Graph Builder (`graph/builder.py`)

Builds graph data structure from money flows. Returns nx.DiGraph which is loaded into Rust/GPU backends by AlgorithmDispatcher:

```python
from chainswarm_analyzers_baseline.graph.builder import build_graph
G = build_graph(flows)
```

Node attributes:

- Address properties
- Temporal patterns (hourly_pattern, weekly_pattern)
- Aggregate statistics

Edge attributes:

- Transaction count
- Total value
- Temporal patterns

### Feature Extraction (`features/`)

`address_feature_analyzer.py` - Computes features for each address:

- Degree metrics (in/out degree)
- Temporal behavior patterns
- Value distribution statistics
- Network centrality measures

### Pattern Detection (`patterns/`)

Detects behavioral patterns:

- Cyclic patterns
- Burst activity
- Unusual timing
- Value anomalies

## Entry Points

### Features Script

```bash
python scripts/run_features.py \
  --input /data/flows.parquet \
  --output /data/features.parquet
```

### Patterns Script

```bash
python scripts/run_patterns.py \
  --input /data/flows.parquet \
  --output /data/patterns.parquet
```

## Data Requirements

### Input (flows.parquet)

Required columns:

| Column | Type | Description |
| ------ | ---- | ----------- |
| `from_address` | string | Sender address |
| `to_address` | string | Receiver address |
| `amount` | float | Transfer value |
| `hourly_pattern` | array[24] | Activity per hour |
| `weekly_pattern` | array[7] | Activity per day |
| `tx_count` | int | Number of transactions |

### Output (features.parquet)

Features per address including:

- Basic stats (degree, volume)
- Temporal features (peak hours, active days)
- Graph features (centrality, clustering)

## Common Issues

### Empty Temporal Arrays

If `hourly_pattern` or `weekly_pattern` is empty `[]`:

```
IndexError: index 0 is out of bounds for axis 0 with size 0
  at address_feature_analyzer.py
```

**Root cause:** Data-pipeline export not computing patterns for synthetic flows.

**Fix:** Ensure data-pipeline exports always include computed temporal patterns.

### Missing Columns

Verify input data has all required columns:

```python
import pandas as pd
df = pd.read_parquet("flows.parquet")
required = ['from_address', 'to_address', 'amount', 'hourly_pattern', 'weekly_pattern']
missing = [c for c in required if c not in df.columns]
print(f"Missing: {missing}")
```

## Running in Docker

```bash
docker run --rm -it -v "$(pwd)":/app -w /app --network host \
  ghcr.io/chainswarm/subnet-base:latest \
  python src/chainswarm_analyzers_baseline/scripts/run_features.py \
    --input /data/flows.parquet \
    --output /data/features.parquet
```

## Testing

```bash
pytest tests/
```

Key test files:

- `tests/test_graph_builder.py` - Graph construction
- `tests/test_feature_analyzer.py` - Feature extraction
- `tests/test_adapters.py` - Data loading

## Benchmarking

The evaluation framework runs these scripts with resource limits:

- CPU limit (configurable)
- Memory limit (configurable)
- Time limit (configurable)

Ensure scripts complete within limits for tournament scoring.
