<p align="center">
  <img src="cogiles_banner.png" alt="COGILES - Colored Graph Input Line Entry System" width="800">
</p>

<p align="center">
  <em>A SMILES-inspired string notation for colored graphs.</em>
</p>

<p align="center">
  <a href="https://pypi.org/project/cogiles/"><img src="https://img.shields.io/pypi/v/cogiles" alt="PyPI"></a>
  <a href="https://pypi.org/project/cogiles/"><img src="https://img.shields.io/pypi/pyversions/cogiles" alt="Python"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
</p>

---

COGILES lets you describe colored graph structures using a compact, human-readable string notation — then parse them into [NetworkX](https://networkx.org/) graphs, encode them back, or visualize them.

## 📦 Installation

```bash
pip install cogiles
```

To enable visualization (matplotlib + scipy):

```bash
pip install cogiles[viz]
```

## 🚀 Quickstart

```python
import cogiles

# Parse a COGILES string into a NetworkX graph
G = cogiles.parse("R(G)(B)(Y)")
print(G.number_of_nodes())  # 4
print(G.number_of_edges())  # 3

# Encode a graph back into a canonical COGILES string
s = cogiles.encode(G)
print(s)  # R(G)(B)(Y)

# Visualize a graph
fig, ax = cogiles.draw("R(G)(B)(Y)", labels="symbol")
fig.savefig("my_graph.png")
```

## 🔤 Syntax

| Syntax | Meaning | Example |
|--------|---------|---------|
| `R`, `G`, `B`, ... | Colored node (single letter) | `RGB` — chain of 3 nodes |
| `Br`, `Gr`, `Pi`, `Ol` | Two-letter colored node | `BrGr` — brown-gray chain |
| `()` | Branch from current node | `R(G)(B)` — R connected to G and B |
| `-N` | Anchor for creating cycles | `R-1RRR-1` — 4-node cycle |
| `.` | Break (disconnected component) | `RR.BB` — two separate pairs |

## 🧩 Examples

<p align="center">
  <img src="docs/examples.png" alt="COGILES example graphs" width="800">
</p>

**Star** — `R(G)(B)(Y)`: Red center connected to green, blue, and yellow.

**Cycle** — `R-1GBY-1`: A 4-node cycle using anchors.

**Branching tree** — `R(GB(C))(Y(OM))`: Nested branches with 7 colors.

**Disconnected** — `RG.BY.CM`: Three separate pairs of nodes.

## 🎨 Color Palette

COGILES provides a fixed set of 17 colors:

| Symbol | Color | Symbol | Color |
|--------|-------|--------|-------|
| `R` | Red | `O` | Orange |
| `G` | Green | `P` | Purple |
| `B` | Blue | `T` | Teal |
| `Y` | Yellow | `L` | Lime |
| `C` | Cyan | `I` | Indigo |
| `M` | Magenta | `Br` | Brown |
| `W` | White | `Gr` | Gray |
| `K` | Black | `Pi` | Pink |
| `Bl` | Black (alias) | `Ol` | Olive |

By default, encoding uses **fuzzy matching** — node colors are mapped to the nearest palette color by Euclidean distance. Use `strict=True` to raise an error on unknown colors instead:

```python
cogiles.encode(G, strict=True)  # raises CogilesEncodeError for unknown colors
```

## 📖 API Overview

| Function | Description |
|----------|-------------|
| `cogiles.parse(s)` | Parse a COGILES string into an `nx.Graph` |
| `cogiles.encode(G)` | Encode an `nx.Graph` into a canonical COGILES string |
| `cogiles.draw(G, ...)` | Visualize a graph (accepts string or `nx.Graph`) |

`draw()` supports multiple layout algorithms: `kamada_kawai` (default), `spring`, `circular`, `shell`, `spectral`, `planar`, `random`.

For more detailed examples, see the [quickstart notebook](examples/00_quickstart.ipynb).

## 🙏 Credits

Built with [NetworkX](https://networkx.org/) for graph representation and [Parsimonious](https://github.com/erikrose/parsimonious) for PEG grammar parsing.

Licensed under [MIT](LICENSE).
