Using published data from httk as a client¶
This closes the loop. Once data is published (see Publishing the data), someone external — or future you — consumes it with httk₂ itself. httk₂ ships a read-only OPTIMADE client that presents a remote service through exactly the same search DSL you use on a local store, so a query you already wrote works unchanged against a published endpoint.
A remote store you can search¶
OptimadeStore(base_url) is the synchronous, read-only client. It discovers the
service schema, then hands you the ordinary store.searcher() interface:
from httk.atomistic import OptimadeStructure, UnitcellStructureView
from httk.serve.optimade import OptimadeStore
with OptimadeStore(base_url) as store:
search = store.searcher()
structure = search.variable(OptimadeStructure)
search.add(
structure.elements.has("Ca")
& structure.elements.has("Ti")
& structure.elements.has("O")
)
for row in search.results(structure=structure):
remote = row.structure
loaded = UnitcellStructureView(remote)
print(remote.id, loaded.elements, loaded.nsites)
The element filter is an OPTIMADE list query, so the same code works against any
compatible provider — just point base_url elsewhere. Use
providers.optimade.org to discover endpoints.
In httk v1
httk v1 had no OPTIMADE client at all — httk.optimade was server-side only.
Consuming someone else’s database meant downloading files and re-ingesting them
by hand. This whole page describes a capability that did not exist in v1.
Recognized rows are typed¶
A recognized structures endpoint yields typed OptimadeStructure rows that
retain the exact remote resource. UnitcellStructureView(optimade_structure)
expands one lazily into the ordinary httk atomistic interface — the conversion
happens only when a structural property is requested. For a single known entry
URL, httk.core.fetch(url, kind="optimade") grabs it directly.
The searcher DSL you knew from v1’s httk.db is exactly what runs against the
remote endpoint. A variable/add/output query you wrote for your own store
works against a published one; only the store you open is different.
Federating and caching¶
To search several endpoints at once, httk.store.FederatedStore({...}) combines
already-open stores into one read-only, source-major union under a single
searcher. Manage the connections yourself — the federation borrows them.
Remote reads never write local state. To keep a fetched entry for offline work, save it into your own store explicitly:
from httk.store import Backend, SqlStore
cache = SqlStore(Backend.sqlite("optimade-cache.sqlite"), entry_records={})
sid = cache.save(remote)
offline = cache.fetch(type(remote), sid)
Caching is an explicit local operation, never an implicit OPTIMADE writeback.