Metadata-Version: 2.4
Name: graphcoherence
Version: 0.1.0
Summary: Global coherence dynamics on networks — Python client for the GraphCoherence API
Author-email: David Martin Venti <david.martin@cognitive-engineering.dev>
License: Proprietary
Project-URL: Homepage, https://cognitive-engineering.dev
Project-URL: Documentation, https://cognitive-engineering.dev/graphcoherence/app/api-docs
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Provides-Extra: pandas
Requires-Dist: pandas>=1.5; extra == "pandas"
Provides-Extra: networkx
Requires-Dist: networkx>=2.8; extra == "networkx"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: responses>=0.23; extra == "dev"
Requires-Dist: networkx>=2.8; extra == "dev"
Requires-Dist: pandas>=1.5; extra == "dev"
Dynamic: license-file

# graphcoherence

Global coherence dynamics on networks — the official Python client for the
**GraphCoherence API**.

`graphcoherence` is a **thin HTTP client**. All computation (coherence-index
sweeps, phase diagrams, spectral analysis, bridge / criticality ranking, Ricci
curvature, liquefaction) runs **server-side** on the GraphCoherence compute
engine. The client only normalizes your graph to the wire format, calls the
API (`/api/gc/v1/*`), and returns typed results. No numpy/scipy/networkx
compute happens locally.

## Install

```bash
pip install graphcoherence
# optional extras
pip install "graphcoherence[pandas]"     # .to_dataframe()
pip install "graphcoherence[networkx]"   # nx.Graph input + .to_networkx()
```

## Authentication

Get an API key (`gc_...`) from https://cognitive-engineering.dev/pricing.

Provide it in any of these ways (checked in this order):

1. Environment variable:
   ```bash
   export GRAPHCOHERENCE_API_KEY=gc_your_key
   ```
2. Config file `~/.graphcoherence/config`:
   ```ini
   [default]
   api_key = gc_your_key
   ```
3. Explicitly in code:
   ```python
   import graphcoherence
   graphcoherence.configure(api_key="gc_your_key")
   ```

## Quickstart

```python
import graphcoherence as gc

# Analyze from an edge list (tuples or lists both work)
result = gc.analyze(edges=[(0, 1), (1, 2), (0, 2)])
print(result.coherence_index)     # global Coherence Index
print(result.always_fragile_ratio)
df = result.to_dataframe()        # one row per edge (needs [pandas])

# Analyze from a networkx graph (needs [networkx])
import networkx as nx
G = nx.karate_club_graph()
result = gc.analyze(graph=G)

# Live edge classification at a coupling value C (no DB write)
prev = gc.preview([(0, 1), (1, 2), (0, 2)], C=0.5)
for edge in prev.edge_results:
    print(edge["edge_key"], edge["state"])

# Bridge / always-fragile analysis
br = gc.bridge(edges=[(0, 1), (1, 2), (2, 3)])
print(br.bridge_count, br.bridge_ratio)

# Rank the most critical edges (intervention targets)
crit = gc.criticality(graph=G, top_n=10)
for e in crit.edges:
    print(e["rank"], e["edge_key"], e["ecs"])

# Spectral analysis
spec = gc.spectral(graph=G)
print(spec.lambda2, spec.eigenvalues[:5])
```

### Using an explicit client

```python
from graphcoherence import GCClient

client = GCClient(api_key="gc_your_key")
result = client.analyze(edges=[(0, 1), (1, 2), (0, 2)])
```

## Input formats

Every graph-taking method accepts, interchangeably:

- `edges=[(0, 1), (1, 2)]` — tuples or `[[0, 1], [1, 2]]` lists
- `graph=G` — a `networkx.Graph` (requires `graphcoherence[networkx]`)
- `graph_data="..."` + `graph_format="json"|"csv"` — a pre-formatted string
- `edges="path/to/edges.csv"` — a CSV file path, or raw CSV content string

Internally these normalize to the JSON format the API expects:
`{"edges": [{"source": u, "target": v}, ...]}`.

## NetworkX interop

```python
import networkx as nx
import graphcoherence as gc

G = nx.karate_club_graph()
result = gc.analyze(graph=G)

# Rebuild a graph carrying per-edge attributes (tri, state, ricci, ...)
H = result.to_networkx()
print(H[0][1])   # {'tri': ..., 'state': ..., 'ricci': ...}
```

## Error handling

```python
from graphcoherence import (
    GCError, AuthError, RateLimitError, EdgeLimitError, InvalidInputError
)

try:
    gc.analyze(edges=[(0, 1)])
except EdgeLimitError as e:
    print("Graph too large for your tier:", e)
except RateLimitError as e:
    print("Slow down:", e)
except AuthError as e:
    print("Check your key:", e)
except InvalidInputError as e:
    print("Bad input:", e)
except GCError as e:
    print("Something went wrong:", e)
```

## Links

- API docs: https://cognitive-engineering.dev/graphcoherence/app/api-docs
- Pricing / API keys: https://cognitive-engineering.dev/pricing

## License

Proprietary. Copyright (c) 2026 Cognitive Engineering / David Martin Venti.
