File size: 8,076 Bytes
51dd783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# TopG API β€” brief for another agent

Everything needed to call the TopG structure generator. Self-contained: paste this whole file.

## What it does

TopG takes a **coordination query** β€” a description of each inequivalent metal site's local
environment β€” and returns **complete crystal structures**: space group, Wyckoff positions, free
coordinates and cell shape. It is a 4.5M-parameter conditional transformer. **No search or
refinement is involved; the output is the model's raw emission.**

It generates a **metal sublattice**, not a composition. Element identities in the returned CIF are
arbitrary palette entries and carry no chemical meaning.

## Endpoint and auth

- Space `RGPalgrave/TopG-demo` Β· base URL `https://rgpalgrave-topg-demo.hf.space`
- Endpoint **`/generate`** β€” use this one. (`/run` is the web page's own button and takes
  UI-shaped arguments.)
- **The Space is private, so every call needs a HuggingFace token** with read access to it.
  Pass it via the `HF_TOKEN` environment variable; do not hard-code it.

## Python

```python
import json, os
from gradio_client import Client            # pip install gradio_client

c = Client("RGPalgrave/TopG-demo", token=os.environ["HF_TOKEN"])
r = c.predict(json.dumps({
    "sites": [
        {"H": "4/mmm", "cs": [4, 2], "ratios": [1.0, 1.15], "orbit_size": 2},
        {"H": "mmm",   "cs": [2, 4], "ratios": [1.0, 1.02], "orbit_size": 2}
    ],
    "n_atoms": 4, "model": "H_pq0", "candidates": 8, "seed": 0,
    "score": True, "cif": True
}), api_name="/generate")
r = json.loads(r) if isinstance(r, str) else r
```

## curl

POST returns an `event_id`; GET streams the result.

```bash
EV=$(curl -s -X POST "https://rgpalgrave-topg-demo.hf.space/gradio_api/call/generate" \
  -H "Authorization: Bearer $HF_TOKEN" -H "Content-Type: application/json" \
  -d '{"data":["{\"sites\":[{\"H\":\"m-3m\",\"cs\":[6,12],\"ratios\":[1.0,1.414],\"orbit_size\":4}],\"n_atoms\":4}"]}' \
  | python -c "import sys,json;print(json.load(sys.stdin)['event_id'])")
curl -s -N "https://rgpalgrave-topg-demo.hf.space/gradio_api/call/generate/$EV" \
  -H "Authorization: Bearer $HF_TOKEN" | grep -m1 '^data:'
```

## Request fields

| field | required | meaning |
|---|---|---|
| `sites` | **yes** | one object per *inequivalent* site (below). 1–12 of them |
| `n_atoms` | no | metal atoms in the **conventional** cell, 1–192. Defaults to the sum of `orbit_size`. **Orbit sizes must sum to it** β€” a mismatch is accepted but returns a `warning` and usually few or no structures |
| `model` | no | `H_pq0` (default), `H_pq1`, `H_pq2`, `I_full0`, `I_full1`, `I_full2` |
| `candidates` | no | beams to draw, default 8. More candidates β†’ more distinct structures, linear cost |
| `seed` | no | default 0 |
| `score` | no | default `true`; scores each structure against the query. The slow part for large cells. `false` returns `best_rung: null` |
| `cif` | no | default `true`; `false` omits CIF text |

Each entry of `sites`:

| field | meaning |
|---|---|
| `H` | site symmetry, Hermann–Mauguin (table below) |
| `cs` | coordination sequence β€” metal neighbours in each successive shell, e.g. `[4, 2]` |
| `ratios` | each shell's distance **relative to the nearest**, so `ratios[0]` is always `1.0` |
| `orbit_size` | atoms this site contributes to the conventional cell |

`cs` and `ratios` must be the same length: **1 to 6 shells**. Fewer than 6 is a *partial query* β€”
supported, and easier for the model β€” but **use an `H_pq` model for it**. `I_full` is trained on
full-depth queries only and collapses on short ones (~10% vs ~50% skeleton accuracy).

## Accepted site symmetries (36)

Any symmetry may be used in any query; the row says where it actually occurs among the 230 space groups.

| system | site symmetries |
|---|---|
| triclinic | `1` `-1` |
| monoclinic | `1` `-1` `2` `m` `2/m` |
| orthorhombic | `1` `-1` `2` `m` `2/m` `222` `2mm` `m2m` `mm2` `mmm` |
| tetragonal | `1` `-1` `2` `m` `-4` `2/m` `222` `2mm` `4` `m2m` `-42m` `-4m2` `4/m` `422` `4mm` `mmm` `4/mmm` |
| trigonal | `1` `-1` `2` `m` `3` `2/m` `-3` `32` `3m` `-3m` |
| hexagonal | `1` `-1` `2` `m` `3` `2/m` `222` `2mm` `m2m` `mm2` `-3` `-6` `32` `3m` `6` `mmm` `-3m` `-62m` `-6m2` `6/m` `622` `6mm` `6/mmm` |
| cubic | `1` `2` `m` `3` `-4` `2/m` `222` `2mm` `4` `mm2` `-3` `32` `3m` `-42m` `-4m2` `4/m` `422` `4mm` `mmm` `-3m` `23` `4/mmm` `-43m` `432` `m-3` `m-3m` |

**Not usable:** `312` `31m` `321` `3m1` `-31m` `-3m1` β€” these are in the model's vocabulary but occur in no Wyckoff table, so no
training example ever contained one. The API rejects them; use the form without the axis suffix
(`321`β†’`32`, `3m1`β†’`3m`, `-3m1`β†’`-3m`).

## Response

```json
{"ok": true,
 "query": {"n_atoms": 4, "k": 2, "depth": 2, "sites": [...]},
 "candidates_built": 8, "distinct_structures": 2, "warning": null,
 "provenance": {"model": "H_pq0", "tokenizer_fingerprint": "e1db473d06e14c82",
                "device": "cpu", "note": "pure model output; no search or refinement"},
 "structures": [
   {"rank": 1, "space_group": 139, "crystal_system": "tetragonal",
    "orbits": "2a  2b", "cell_shape": "c_over_a=1.4714",
    "best_rung": "r0_2sh_noratio", "times_drawn": 6, "cif": "# generated using pymatgen..."}
 ]}
```

Errors never raise β€” they return `{"ok": false, "error": "..."}`, with `expected` carrying the
schema when the payload was malformed.

- `structures` are **deduplicated** and ranked: scored hits first, then by `times_drawn`.
- `times_drawn` is how many of the `candidates` beams produced that same structure β€” a rough
  confidence signal, not a probability.
- `cell_shape` lists only the **free** shape parameters of the crystal system (cubic none;
  tetragonal/trigonal/hexagonal `c_over_a`; orthorhombic 2, monoclinic 3, triclinic 5).
  **No absolute length is emitted** β€” a scale-free query cannot determine one, so the CIF's absolute
  cell size is a placeholder and only ratios are meaningful.
- The **CIF is written in P1** with every atom explicit, so the file says `P 1` while `space_group`
  gives the real symmetry. The symmetry is in the coordinates.

## `best_rung` β€” how well a structure answers the query

Nested criteria, each stricter than the last. `null` means it passed none.

| rung | shells checked | distance tolerance |
|---|---|---|
| `r0_2sh_noratio` | 2 | ignored |
| `r1_3sh_noratio` | 3 | ignored |
| `r2_3sh_t04` | 3 | 4% |
| `r2a_3sh_t08` | 3 | 8% |
| `r5_6sh_noratio` | 6 | ignored |
| **`r3_6sh_t04`** | **6** | **4%** β€” the project's historical criterion |
| `r3a_6sh_t08` | 6 | 8% |
| `r3b_6sh_t15` | 6 | 15% |

## How much to trust the output

Measured on a frozen, skeleton-disjoint evaluation set; pure model, no search:

- The **discrete** answer (space group + Wyckoff labels + N) is exactly right **~54–59%** of the time.
- The **geometry** meets the strict `r3_6sh_t04` criterion **~2–3%** of the time, and essentially
  never above ~9 free parameters. **Treat returned coordinates as a starting point, not an answer.**
- A *perfect* model would score **95.67%**, not 100% β€” that is the emission grid's own ceiling.
- A structure passing no rung still answers the query approximately; `best_rung` says which
  criterion it actually meets.

## Gotchas

- **`seed` reproduces within one deployment, not across environments.** The same seed on this Space
  and on a local checkout gives the same structures but different draw counts, because the Python
  and torch builds differ. Do not use `seed` as a portable identifier.
- **The first call after the Space wakes is slow** β€” it downloads the checkpoint once, then caches.
  A small query (N ≀ 8, 8 candidates) then takes a few seconds.
- Cost grows with **cell size**, not with hardware; the model is too small for a GPU to help.
  For N > 40 send `"score": false`.
- Sites are **inequivalent sites, not atoms**: `k` is the number of orbits, `n_atoms` the number of
  atoms, and `orbit_size` links them.

Model card: `RGPalgrave/TopG` Β· code and full record: <https://github.com/rgpalgrave/TopG>