httk quickstart: OPTIMADE client

OPTIMADE is a common REST API for materials databases, so the same query language and response format work across dozens of independent databases. httk-store (part of the httk2 metapackage) provides OptimadeStore, a read-only client that discovers a service and exposes it through the same query interfaces as a local httk database. The examples below need network access; they were run against public providers and the outputs shown are from the time of writing. Use providers.optimade.org to find other endpoints, then assign your chosen base URL to base_url.

Connect and discover

Point OptimadeStore at a service base URL. Version negotiation and schema discovery happen up front, so the API version and the available entry types are known immediately:

from httk.store.optimade import OptimadeStore

base_url = "https://alexandria.icams.rub.de/pbe"

store = OptimadeStore(base_url)
print("API version:", store.api_version)
for entry_type in store.entry_types:
    print("Entry type:", entry_type.name)

Running this generates the output:

API version: 1.1.0
Entry type: structures
Entry type: references

Filter remote entries

Queries use the httk-store searcher: bind a variable to an entry type, add conditions, and freeze the query with results(). The conditions are translated into the OPTIMADE filter language (chemical_formula_reduced = "ClNa" AND nsites = 2), and search.count() asks the service how many entries match, for services that report counts. Standard OPTIMADE properties and provider-specific ones (here prefixed _alexandria_) are available as attributes of the variable:

search = store.searcher()
s = search.variable(store.entry_type("structures"))
search.add((s.chemical_formula_reduced == "ClNa") & (s.nsites == 2))
for row in search.results(structure=s, nsites=s.nsites, spacegroup=s._alexandria_space_group):
    print(row.structure.id, row.nsites, row.spacegroup)

Running this generates the output:

agm003157609 2 225
agm005244656 2 221

Results are fetched page by page as you iterate, so a query over a large database only transfers the rows you consume.

Pandas-style slicing

store.slicer(...) wraps the same query machinery in a [] indexing surface; here it repeats the selection above in pandas style. A field name gives a column, comparisons give boolean masks that combine with &, |, and ~, and indexing with a mask selects the matching entries:

structures = store.slicer("structures")
selected = structures[(structures["chemical_formula_reduced"] == "ClNa") & (structures["nsites"] == 2)]
for entry in selected:
    print(entry.id, entry._alexandria_space_group, entry._alexandria_band_gap)

store.close()

Running this generates the output:

agm003157609 225 5.0101
agm005244656 221 3.9791

Load a remote structure into httk

A remote structure entry is turned into an ordinary httk structure by constructing a view, exactly as for local data. From there everything in the structures quickstart applies, e.g., saving the structure as a CIF file:

from httk.atomistic import UnitcellStructureView
from httk.core import save
from httk.store.optimade import OptimadeStore

with OptimadeStore("https://altermagnets.anyterial.se/optimade/amdb") as store:
    search = store.searcher()
    s = search.variable(store.entry_type("structures"))
    search.add(s.chemical_formula_reduced == "CrSb")
    remote = search.results(structure=s).first().structure

structure = UnitcellStructureView(remote)
print("Formula:", structure.formula)
print("Number of sites:", len(structure.sites))
print("Volume:", round(float(structure.cell.volume), 3))
save(structure, "CrSb.cif")

Running this generates the output:

Formula: CrSb
Number of sites: 4
Volume: 79.646

The conversion is lazy and keeps the exact remote resource: remote retains the complete OPTIMADE record, while the view decodes cell, sites, and species only when they are accessed.

httk identifies properties by their OPTIMADE property definitions rather than by name, so loading a remote entry as a structure requires a service that publishes property definitions (OPTIMADE v1.2 or later, such as the example above, which is served by httk-serve). Older services, such as the v1.1 provider used in the first examples, can still be discovered, filtered, and read attribute by attribute as shown above.

More

Relationship queries (s.links.<name>), following provenance between entry types, sorting, and the client's pagination and error-handling contracts are covered in the httk-store documentation. Serving your own data over OPTIMADE is described in the websites and UI quickstart.