Import requests
library for http request and define API endpoints
import requests
import pprint
import sys
import ase.io
try:# catch module change from Python2->3
import io
except:
import StringIO as io
API = 'http://api.catalysis-hub.org'
SEARCH_ENDPOINT = API + '/apps/prototypeSearch/facet_search/'
PROTOTYPE_ENDPOINT = API + '/apps/prototypeSearch/prototype/'
STRUCTURE_ENDPOINT = API + '/apps/prototypeSearch/get_structure/'
The prototype App uses 3 API endpoints for searching and retrieving structures. Below we go through a practical example of how to use them together. The request
is a very user friendly module to make HTTP requests from python. If you don't have it installed, you can change that with pip install requests --user
Let's make use of the facet_search API to find all materials with a given composition
r = requests.post(SEARCH_ENDPOINT, json={
"search_terms": "stoichiometry:AB2",
"limit": 1000,
})
len(r.json()['prototypes'])
462
We can learn about other possible arguments by inspecting the 'input' field of the result
r.json()['input']
{'facet_filters': [], 'limit': 1000, 'offset': 0, 'search_terms': ['stoichiometry:AB2']}
To see how many structures of this composition are in each repository, we look at the repositories facet.
r.json()['repositories']
[['AFLOW', 50442], ['COD', 2888], ['OQMD', 533], ['MaterialsProject', 477], ['AMCSD', 66]]
The facet lists are ordered by frequency by default. There are of course all the other facets, that are also in the GUI.
r.json().keys()
dict_keys(['input', 'n_atoms', 'n_compounds', 'n_prototypes', 'n_species', 'n_wyckoffs', 'prototypes', 'repositories', 'spacegroups', 'stoichiometries', 'time'])
To narrow down the result, we look, e.g. only at the AB2 structures in OQMD
r = requests.post(SEARCH_ENDPOINT, json={
"search_terms": "stoichiometry:AB2 repository:OQMD",
"limit": 1000,
})
r.json()
{'input': {'facet_filters': [], 'limit': 1000, 'offset': 0, 'search_terms': ['stoichiometry:AB2', 'repository:OQMD']}, 'n_atoms': [[3, 533]], 'n_compounds': 533, 'n_prototypes': 533, 'n_species': [[2, 533]], 'n_wyckoffs': [[2, 519], [3, 14]], 'prototypes': [['AB2_a_e_139', 111], ['AB2_a_d_191', 105], ['AB2_a_c_225', 97], ['AB2_a_d_164', 68], ['AB2_a_i_12', 44], ['AB2_a_c_166', 32], ['AB2_a_i_69', 9], ['AB2_a_j_65', 8], ['AB2_a_a2_160', 8], ['AB2_a_i_71', 8], ['AB2_a_k_21', 6], ['AB2_a_c_42', 5], ['AB2_a_d_139', 5], ['AB2_a_e_123', 4], ['AB2_a_h_187', 3], ['AB2_a_h_123', 3], ['AB2_a_bc_216', 2], ['AB2_a_c_5', 2], ['AB2_a_g_115', 2], ['AB2_a_c_38', 1], ['AB2_a_a2_8', 1], ['AB2_a_e_191', 1], ['AB2_a_ab_38', 1], ['AB2_a_i_65', 1], ['AB2_a_e_38', 1], ['AB2_a_m_10', 1], ['AB2_a_bc_156', 1], ['AB2_a_j_71', 1], ['AB2_a_a2_1', 1], ['AB2_a_n_10', 1]], 'repositories': [['OQMD', 533]], 'spacegroups': [[139, 116], [191, 106], [225, 97], [164, 68], [12, 44], [166, 32], [71, 9], [65, 9], [69, 9], [160, 8], [123, 7], [21, 6], [42, 5], [38, 3], [187, 3], [216, 2], [115, 2], [5, 2], [10, 2], [156, 1], [1, 1], [8, 1]], 'stoichiometries': [['AB2', 533]], 'time': 1.216792106628418}
Some prototypes are apparently more frequent than others. So let's have a look at the structures in the AB2_a_d_191
prototype. To this end we use the prototype API.
r = requests.post(PROTOTYPE_ENDPOINT, json={
"prototype": "AB2_a_d_191",
"search_terms": "repository:OQMD"
})
len(r.json()['prototypes'])
105
So, let's say we want to do some specific manipulation on structures. To this end it will be handy to turn it into ASE atoms objects.
structures = []
for prototype in r.json()['prototypes'][:10]:
sys.stdout.write('.')
r_structure = requests.post(STRUCTURE_ENDPOINT, json=prototype)
cif = r_structure.json()['structure']
with io.StringIO() as cif_file:
cif_file.write(cif)
cif_file.seek(0)
structures.append(
ase.io.read(cif_file, format='cif')
)
..........
structures
[Atoms(symbols='B2Mg', pbc=True, cell=[[3.8347, 0.0, 0.0], [-1.9173499999999992, 3.320947615892188, 0.0], [0.0, 0.0, 3.50909]]), Atoms(symbols='Bi2Tl', pbc=True, cell=[[7.10897, 0.0, 0.0], [-3.5544849999999983, 6.156548614741462, 0.0], [0.0, 0.0, 3.38233]]), Atoms(symbols='B2W', pbc=True, cell=[[3.78488, 0.0, 0.0], [-1.892439999999999, 3.2778022302756464, 0.0], [0.0, 0.0, 3.35748]]), Atoms(symbols='EuHg2', pbc=True, cell=[[6.26501, 0.0, 0.0], [-3.1325049999999988, 5.4256578149635475, 0.0], [0.0, 0.0, 3.58463]]), Atoms(symbols='CaHg2', pbc=True, cell=[[6.19862, 0.0, 0.0], [-3.0993149999999985, 5.368171048660336, 0.0], [0.0, 0.0, 3.54152]]), Atoms(symbols='B2V', pbc=True, cell=[[3.73867, 0.0, 0.0], [-1.869329999999999, 3.23777453611273, 0.0], [0.0, 0.0, 3.03155]]), Atoms(symbols='B2V', pbc=True, cell=[[3.74283, 0.0, 0.0], [-1.8714099999999991, 3.2413772017924734, 0.0], [0.0, 0.0, 3.01813]]), Atoms(symbols='TiU2', pbc=True, cell=[[5.95252, 0.0, 0.0], [-2.9762599999999986, 5.155033536534948, 0.0], [0.0, 0.0, 2.80189]]), Atoms(symbols='Au2Ba', pbc=True, cell=[[6.05807, 0.0, 0.0], [-3.0290349999999986, 5.246442517904395, 0.0], [0.0, 0.0, 4.18078]]), Atoms(symbols='Hg2Y', pbc=True, cell=[[6.10075, 0.0, 0.0], [-3.0503799999999988, 5.283413142391953, 0.0], [0.0, 0.0, 3.47105]])]
Voila!
Ok, should be admitted, that doing n
HTTP round trips for n
structures is not ideal. We are working on that.