optimade 1.2.1 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jshintrc ADDED
@@ -0,0 +1 @@
1
+ {"esversion": 6}
package/CHANGELOG.md CHANGED
@@ -1,17 +1,31 @@
1
- # optimade changelog
1
+ # Optimade changelog
2
+
3
+ ## 2.0.3
4
+
5
+ - Bugfix release
6
+
7
+ ## 2.0.0
8
+
9
+ - Add new `npm run prefetch` logic in prefetch.js to check provider avialability,
10
+ cache provider pagination limits in `provider.attributes.query_limits`,
11
+ introduce the sorted and structured providers.json (as source) and prefetched.json (as cache)
12
+ - Add new arguments `getStructures(providerId, filter, page, limit)` for pagination
13
+ and pagination limits
14
+ - Add new logic for catching errors like
15
+ `Error: messageFromProvider { response: { errors, meta } }`
2
16
 
3
17
  ## 1.2.1
4
18
 
5
- * Fix providers prefetching
19
+ - Fix providers prefetching
6
20
 
7
21
  ## 1.2.0
8
22
 
9
- * Make batch data aggregation is optional to support per-provider progressive data receiving
23
+ - Make batch data aggregation is optional to support per-provider progressive data receiving
10
24
 
11
25
  ## 1.1.5
12
26
 
13
- * Add http request timeout
27
+ - Add http request timeout
14
28
 
15
29
  ## 1.0.0
16
30
 
17
- * First release
31
+ - First release
package/README.md CHANGED
@@ -1,26 +1,32 @@
1
1
  # Aggregating Optimade client for the online materials databases
2
2
 
3
- [![NPM version](https://img.shields.io/npm/v/optimade.svg?style=flat)](https://www.npmjs.com/package/optimade) [![NPM downloads](https://img.shields.io/npm/dm/optimade.svg?style=flat)](https://www.npmjs.com/package/optimade) [![GitHub issues](https://img.shields.io/github/issues/tilde-lab/optimade-client?style=flat)](https://github.com/tilde-lab/optimade-client/issues)
3
+ [![NPM version](https://img.shields.io/npm/v/optimade.svg?style=flat)](https://www.npmjs.com/package/optimade)
4
+ [![NPM downloads](https://img.shields.io/npm/dm/optimade.svg?style=flat)](https://www.npmjs.com/package/optimade)
5
+ [![GitHub issues](https://img.shields.io/github/issues/tilde-lab/optimade-client?style=flat)](https://github.com/tilde-lab/optimade-client/issues)
4
6
 
5
7
  ## Features
6
8
 
7
9
  - discovers all the [official Optimade databases](https://providers.optimade.org) recursively
8
10
  - caches the discovered list (`prefetched.json`) for future and boosts the retrieval performance
9
11
  - queries them all, in the browser, at the server, everywhere
12
+ - provides pagination, with the minimized number of pages
10
13
 
11
14
  ## Install
12
15
 
13
- ```bash
16
+ ```sh
14
17
  npm i optimade --save
15
18
  ```
16
19
 
17
- ```bash
20
+ ```sh
18
21
  yarn add optimade
19
22
  ```
20
23
 
21
- CDN: [UNPKG](https://unpkg.com/optimade/) | [jsDelivr](https://cdn.jsdelivr.net/npm/optimade/) (available as `window.optimade`)
24
+ CDN: [UNPKG](https://unpkg.com/optimade/) |
25
+ [jsDelivr](https://cdn.jsdelivr.net/npm/optimade/) (available as
26
+ `window.optimade`)
22
27
 
23
- If you are **not** using es6 or CDN, add to your HTML just before closing the `body` tag:
28
+ If you are **not** using ES6 or CDN, add to your HTML just before closing the
29
+ `body` tag:
24
30
 
25
31
  ```html
26
32
  <script src="/path/to/optimade/dist/index.js"></script>
@@ -30,10 +36,19 @@ If you are **not** using es6 or CDN, add to your HTML just before closing the `b
30
36
 
31
37
  ## Usage
32
38
 
33
- ```javascript
39
+ The code is generally isomorphic, however one should additionally take care of
40
+ downloading the cache or setting the CORS policy for the browsers. Concerning
41
+ the CORS, the `Optimade` class constructor accepts the `corsProxyUrl` parameter,
42
+ pointing to a running `cors-anywhere` proxy instance. This will be valid
43
+ until all the Optimade providers are supplying the header
44
+ `Access-Control-Allow-Origin $http_origin` in their responses. For the
45
+ server-side environment this is not required.
34
46
 
47
+ ### Discovery and querying
48
+
49
+ ```ts
35
50
  const optimadeClient = new Optimade({
36
- providersUrl: '/path/to/optimade/providers.json'
51
+ providersUrl: "https://providers.optimade.org/providers.json",
37
52
  });
38
53
 
39
54
  console.log(optimadeClient.providers); // { [id: string]: Provider }[]
@@ -42,13 +57,38 @@ const providersMap = await optimadeClient.getProviders(); // { [id: string]: Pro
42
57
 
43
58
  const providerIds = Object.keys(providersMap); // string[]
44
59
 
45
- const results = await optimadeClient.getStructuresAll(providerIds, YOUR_OPTIMADE_QUERY); // [Structures[], Provider][]
60
+ const results = await optimadeClient.getStructuresAll(
61
+ providerIds,
62
+ YOUR_OPTIMADE_QUERY,
63
+ ); // [StructuresResponse[], Provider][]
46
64
  ```
47
65
 
48
- Importing depends on your environment. See also the `examples` folder. The `.html` examples are suited for the browser environment, the `.js` examples are suited for the server environment.
66
+ Importing depends on your environment. See also the `examples` folder. The
67
+ `.html` examples are suited for the browser environment, the `.js` examples are
68
+ suited for the server environment.
69
+
70
+ ### Pagination
71
+
72
+ ```ts
73
+ import prefetched from 'optimade/dist/prefetched.json';
74
+
75
+ const optimadeClient = new Optimade({
76
+ providersUrl: "https://providers.optimade.org/providers.json",
77
+ });
78
+
79
+ optimadeClient.providers = prefetched.providers;
80
+ optimadeClient.apis = prefetched.apis;
81
+
82
+ const results = await optimadeClient.getStructuresAll(
83
+ providerIds,
84
+ YOUR_OPTIMADE_QUERY,
85
+ page: number,
86
+ limit: number
87
+ ); // [StructuresResponse[], Provider][]
88
+ ```
49
89
 
50
- The code is generally isomorphic, however one should additionally take care of downloading the cache or setting the CORS policy for the browsers. Concerning the CORS, the `Optimade` class constructor accepts the `corsProxyUrl` parameter, pointing to _e.g._ a running `cors-anywhere` proxy instance. This will be valid until all the Optimade providers are supplying the header `Access-Control-Allow-Origin $http_origin` in their responses. For the server-side environment this is not required.
90
+ See also the `demo` folder.
51
91
 
52
92
  ## License
53
93
 
54
- MIT &copy; [PaulMaly](https://github.com/PaulMaly), Tilde Materials Informatics
94
+ MIT &copy; [Pavel Malyshev](https://github.com/PaulMaly) and [Alexander Volkov](https://github.com/valexr), Tilde Materials Informatics
package/dist/index.d.ts CHANGED
@@ -12,8 +12,8 @@ export declare class Optimade {
12
12
  });
13
13
  getProviders(api?: Types.Api): Promise<Types.ProvidersMap | null>;
14
14
  getApis(provider: Types.Provider | string, version?: string): Promise<Types.Api | null>;
15
- getStructures(providerId: string, filter?: string): Promise<Types.Structure[] | null>;
16
- getStructuresAll(providerIds: string[], filter?: string, batch?: boolean): Promise<Promise<Types.StructuresResult>[]> | Promise<Types.StructuresResult>[];
15
+ getStructures(providerId: string, filter: string, page: number, limit: number): Promise<Types.StructuresResponse[] | Types.ResponseError>;
16
+ getStructuresAll(providerIds: string[], filter: string, page: number, limit: number, batch?: boolean): Promise<Promise<Types.StructuresResult>[]> | Promise<Types.StructuresResult>[];
17
17
  private followLinks;
18
18
  private wrapUrl;
19
19
  private isDuplicatedReq;
package/dist/index.js CHANGED
@@ -79,24 +79,44 @@
79
79
  const apis = await Optimade.getJSON(url);
80
80
  return Optimade.apiVersion(apis);
81
81
  }
82
- async getStructures(providerId, filter = '') {
82
+ async getStructures(providerId, filter = '', page = 1, limit) {
83
83
  if (!this.apis[providerId])
84
84
  return null;
85
85
  const apis = this.apis[providerId].filter(api => api.attributes.available_endpoints.includes('structures'));
86
- const structures = await allSettled(apis.map((api) => {
87
- const url = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter}` : '/structures');
88
- return Optimade.getJSON(url);
86
+ const provider = this.providers[providerId];
87
+ const structures = await allSettled(apis.map(async (api) => {
88
+ if (page <= 0)
89
+ page = 1;
90
+ const pageLimit = limit ? `&page_limit=${limit}` : '';
91
+ const pageNumber = page ? `&page_number=${page - 1}` : '';
92
+ const pageOffset = limit && page ? `&page_offset=${limit * (page - 1)}` : '';
93
+ const params = filter ? `${pageLimit + pageNumber + pageOffset}` : `?${pageLimit}`;
94
+ const url = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter + params}` : `/structures${params}`);
95
+ try {
96
+ return await Optimade.getJSON(url, {}, { Origin: 'https://cors.optimade.science', 'X-Requested-With': 'XMLHttpRequest' });
97
+ }
98
+ catch (error) {
99
+ return error;
100
+ }
89
101
  }));
90
102
  return structures.reduce((structures, structure) => {
91
- return structure ? structures.concat(structure.data) : structures;
103
+ console.dir(`optimade-client-${providerId}:`, structure);
104
+ if (structure instanceof Error || Object.keys(structure).includes('errors')) {
105
+ return structures.concat(structure);
106
+ }
107
+ else {
108
+ structure.meta.pages = Math.ceil(structure.meta.data_returned / (limit || structure.data.length));
109
+ structure.meta.limits = provider.attributes.query_limits || [10];
110
+ return structures.concat(structure);
111
+ }
92
112
  }, []);
93
113
  }
94
- getStructuresAll(providerIds, filter = '', batch = true) {
114
+ getStructuresAll(providerIds, filter = '', page = 1, limit, batch = true) {
95
115
  const results = providerIds.reduce((structures, providerId) => {
96
116
  const provider = this.providers[providerId];
97
117
  if (provider) {
98
118
  structures.push(allSettled([
99
- this.getStructures(providerId, filter),
119
+ this.getStructures(providerId, filter, page, limit),
100
120
  Promise.resolve(provider)
101
121
  ]));
102
122
  }
@@ -125,9 +145,10 @@
125
145
  }
126
146
  const res = await fetchWithTimeout(url.toString(), { headers }, timeout);
127
147
  if (!res.ok) {
128
- const err = new Error(res.statusText);
129
- err.response = res;
130
- throw err;
148
+ const err = await res.json();
149
+ const error = new Error(err.errors[0].detail);
150
+ error.response = err;
151
+ throw error;
131
152
  }
132
153
  if (res.status !== 204) {
133
154
  return await res.json();
package/dist/index.mjs CHANGED
@@ -75,24 +75,44 @@ class Optimade {
75
75
  const apis = await Optimade.getJSON(url);
76
76
  return Optimade.apiVersion(apis);
77
77
  }
78
- async getStructures(providerId, filter = '') {
78
+ async getStructures(providerId, filter = '', page = 1, limit) {
79
79
  if (!this.apis[providerId])
80
80
  return null;
81
81
  const apis = this.apis[providerId].filter(api => api.attributes.available_endpoints.includes('structures'));
82
- const structures = await allSettled(apis.map((api) => {
83
- const url = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter}` : '/structures');
84
- return Optimade.getJSON(url);
82
+ const provider = this.providers[providerId];
83
+ const structures = await allSettled(apis.map(async (api) => {
84
+ if (page <= 0)
85
+ page = 1;
86
+ const pageLimit = limit ? `&page_limit=${limit}` : '';
87
+ const pageNumber = page ? `&page_number=${page - 1}` : '';
88
+ const pageOffset = limit && page ? `&page_offset=${limit * (page - 1)}` : '';
89
+ const params = filter ? `${pageLimit + pageNumber + pageOffset}` : `?${pageLimit}`;
90
+ const url = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter + params}` : `/structures${params}`);
91
+ try {
92
+ return await Optimade.getJSON(url, {}, { Origin: 'https://cors.optimade.science', 'X-Requested-With': 'XMLHttpRequest' });
93
+ }
94
+ catch (error) {
95
+ return error;
96
+ }
85
97
  }));
86
98
  return structures.reduce((structures, structure) => {
87
- return structure ? structures.concat(structure.data) : structures;
99
+ console.dir(`optimade-client-${providerId}:`, structure);
100
+ if (structure instanceof Error || Object.keys(structure).includes('errors')) {
101
+ return structures.concat(structure);
102
+ }
103
+ else {
104
+ structure.meta.pages = Math.ceil(structure.meta.data_returned / (limit || structure.data.length));
105
+ structure.meta.limits = provider.attributes.query_limits || [10];
106
+ return structures.concat(structure);
107
+ }
88
108
  }, []);
89
109
  }
90
- getStructuresAll(providerIds, filter = '', batch = true) {
110
+ getStructuresAll(providerIds, filter = '', page = 1, limit, batch = true) {
91
111
  const results = providerIds.reduce((structures, providerId) => {
92
112
  const provider = this.providers[providerId];
93
113
  if (provider) {
94
114
  structures.push(allSettled([
95
- this.getStructures(providerId, filter),
115
+ this.getStructures(providerId, filter, page, limit),
96
116
  Promise.resolve(provider)
97
117
  ]));
98
118
  }
@@ -121,9 +141,10 @@ class Optimade {
121
141
  }
122
142
  const res = await fetchWithTimeout(url.toString(), { headers }, timeout);
123
143
  if (!res.ok) {
124
- const err = new Error(res.statusText);
125
- err.response = res;
126
- throw err;
144
+ const err = await res.json();
145
+ const error = new Error(err.errors[0].detail);
146
+ error.response = err;
147
+ throw error;
127
148
  }
128
149
  if (res.status !== 204) {
129
150
  return await res.json();
@@ -1 +1 @@
1
- {"providers":{"aflow":{"id":"aflow","type":"links","attributes":{"name":"AFLOW","description":"The AFLOW OPTIMADE endpoint","base_url":"http://aflow.org/API/optimade/","homepage":"http://aflow.org","link_type":"child"}},"cod":{"id":"cod","type":"links","attributes":{"name":"Crystallography Open Database","description":"Open-access collection of crystal structures of organic, inorganic, metal-organics compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/cod/optimade","homepage":"https://www.crystallography.net/cod","link_type":"child"}},"sssp":{"id":"sssp","type":"links","attributes":{"name":"Standard solid-state pseudopotentials (SSSP)","description":"It contains data generated from the testing protocol of the standard solid-state pseudopotentials library.\n","base_url":"https://aiida.materialscloud.org/sssplibrary/optimade","homepage":"https://materialscloud.org/explore/sssplibrary","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"2dstructures":{"id":"2dstructures","type":"links","attributes":{"name":"2D Structures","description":"Two-dimensional (2D) materials from high-throughput computational exfoliation of experimentally known compounds.","base_url":"https://aiida.materialscloud.org/2dstructures/optimade","homepage":"https://materialscloud.org/explore/2dstructures","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"2dtopo":{"id":"2dtopo","type":"links","attributes":{"name":"2D topological insulators","description":"Quantum spin Hall insulator (QSHI) candidates through DFT band structure calculations of a database with 1825 compounds.","base_url":"https://aiida.materialscloud.org/2dtopo/optimade","homepage":"https://materialscloud.org/explore/2dtopo","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"tc-applicability":{"id":"tc-applicability","type":"links","attributes":{"name":"Applicability of tail-corrections in the molecular simulations of porous materials","description":"Tail-corrections in molecular simulations for adsorption of gasses in a diverse set of nanoporous crystalline materials (zeolites, Covalent Organic Framworks (COFs), and Metal Organic Frameworks (MOFs)).","base_url":"https://aiida.materialscloud.org/tc-applicability/optimade","homepage":"https://materialscloud.org/explore/tc-applicability","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"threedd":{"id":"threedd","type":"links","attributes":{"name":"Three-dimensional crystals database","description":"Curated set of relaxed three-dimensional crystal structures based on raw CIF data from the experimantal databases MPDS, COD, and ICSD.","base_url":"https://aiida.materialscloud.org/3dd/optimade","homepage":"https://materialscloud.org/explore/3dd","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"scdm":{"id":"scdm","type":"links","attributes":{"name":"Automated high-throughput Wannierisation","description":"Validation results of an automated protocol for generating maximally-localized Wannier functions in a high-throughput framework.","base_url":"https://aiida.materialscloud.org/autowannier/optimade","homepage":"https://materialscloud.org/explore/autowannier","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"curated-cofs":{"id":"curated-cofs","type":"links","attributes":{"name":"CURATED covalent organic frameworks database","description":"Database of experimentally reported Covalent-Organic Frameworks (COFs), provided with DFT-optimized geometry and DDEC partial charges for molecular simulations.","base_url":"https://aiida.materialscloud.org/curated-cofs/optimade","homepage":"https://materialscloud.org/discover/curated-cofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"optimade-sample":{"id":"optimade-sample","type":"links","attributes":{"name":"OPTIMADE Sample Database","description":"Database with example structures for OPTIMADE tests.","base_url":"https://aiida.materialscloud.org/optimade-sample/optimade","homepage":"https://materialscloud.org/explore/optimade-sample","link_type":"child","aggregate":"test","no_aggregate_reason":null}},"stoceriaitf":{"id":"stoceriaitf","type":"links","attributes":{"name":"SrTiO3-CeO2 interfaces","description":"Refining random structure searching results of SrTiO3-CeO2 interfaces, and exploring how it can affect ionic conduction. Candidate structures of the DFT validation calculations.","base_url":"https://aiida.materialscloud.org/stoceriaitf/optimade","homepage":"https://materialscloud.org/explore/stoceriaitf","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"pyrene-mofs":{"id":"pyrene-mofs","type":"links","attributes":{"name":"Pyrene MOFs","description":"Pyrene Metal Organic Frameworks (MOFs).","base_url":"https://aiida.materialscloud.org/pyrene-mofs/optimade","homepage":"https://materialscloud.org/discover/pyrene-mofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"li-ion-conductors":{"id":"li-ion-conductors","type":"links","attributes":{"name":"Solid-state Li-ion conductors.","description":"High-throughput computational screening study for solid-state Li-ion conductors.","base_url":"https://aiida.materialscloud.org/li-ion-conductors/optimade","homepage":"https://materialscloud.org/explore/li-ion-conductors","link_type":"child","aggregate":"staging","no_aggregate_reason":null}},"tin-antimony-sulfoiodide":{"id":"tin-antimony-sulfoiodide","type":"links","attributes":{"name":"Hidden spontaneous polarisation in the chalcohalide photovoltaic Sn2SbS2I3","description":"Structural, dynamic and electronic characterisation of a novel mixed-metal chalcohalide revealing hidden symmetry breaking and spontaneous polarisation.","base_url":"https://aiida.materialscloud.org/tin-antimony-sulfoiodide/optimade","homepage":"https://materialscloud.org/explore/tin-antimony-sulfoiodide","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"mp":{"id":"mp","type":"links","attributes":{"name":"The Materials Project","description":"The Materials Project OPTIMADE endpoint","base_url":"https://optimade.materialsproject.org","homepage":"https://www.materialsproject.org","link_type":"child"}},"mpds":{"id":"mpds","type":"links","attributes":{"name":"Materials Platform for Data Science","description":"A highly curated Pauling File dataset based on ~0.5M publications and backing up Springer Materials, ICDD PDF, ASM APD, MedeA, Pearson Crystal Data, AtomWork Advanced, etc.","base_url":"https://api.mpds.io","homepage":"https://mpds.io","link_type":"child"}},"nmd":{"id":"nmd","type":"links","attributes":{"name":"novel materials discovery (NOMAD)","description":"A FAIR data sharing platform for materials science data","base_url":"https://nomad-lab.eu/prod/rae/optimade/","homepage":"https://nomad-lab.eu","link_type":"child"}},"odbx":{"id":"odbx","type":"links","attributes":{"name":"odbx","description":"The Open Database of Xtals is run by the group of Dr Andrew Morris at the universities of Birmingham and Cambridge and is constructed using the matador library.","base_url":"https://optimade.odbx.science","homepage":"https://odbx.science","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"omdb_production":{"id":"omdb_production","type":"links","attributes":{"name":"Open Materials Database (omdb) production database","description":"This is the main production version of the Open Materials Database","base_url":"http://optimade.openmaterialsdb.se","homepage":"http://openmaterialsdb.se","link_type":"child"}},"oqmd":{"id":"oqmd","type":"links","attributes":{"name":"The OQMD","description":"The Open Quantum Materials Database endpoint","base_url":"http://oqmd.org/optimade/","homepage":"http://oqmd.org","link_type":"child"}},"jarvis":{"id":"jarvis","type":"links","attributes":{"name":"JARVIS-DFT","description":"JARVIS-DFT is a materials property repository focused on density functional theory (DFT) predictions of material properties, especially for crystalline materials.","base_url":"https://jarvis.nist.gov/optimade/jarvisdft","homepage":"https://jarvis.nist.gov","link_type":"child"}},"tcod":{"id":"tcod","type":"links","attributes":{"name":"Theoretical Crystallography Open Database","description":"Open-access collection of theoretically calculated or refined crystal structures of organic, inorganic, metal-organic compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/tcod/optimade","homepage":"https://www.crystallography.net/tcod","link_type":"child"}},"twodmatpedia":{"id":"twodmatpedia","type":"links","attributes":{"name":"2DMatpedia","description":"2DMatpedia, an open computational database of two-dimensional materials from top-down and bottom-up approaches","base_url":"http://optimade.2dmatpedia.org","homepage":"http://2dmatpedia.org","link_type":"child"}}},"apis":{"aflow":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"http://aflow.org/API/optimade/v0.9/","version":"0.9.0"},{"url":"http://aflow.org/API/optimade/v1.0/","version":"1.0.0"},{"url":"http://aflow.org/API/optimade/v1.1/","version":"1.1.0"}],"formats":["json"],"entry_types_by_format":{"json":["structures","calculations"]},"available_endpoints":["structures","calculations","info","links"]},"is_index":false}],"optimade-providers":[],"cod":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://www.crystallography.net/cod/optimade/v1.0.0/","version":"1.0.0"}],"available_endpoints":["structures","info"],"entry_types_by_format":{"json":["structures"]},"formats":["json"]},"id":"/","type":"info"}],"exmpl":[],"matcloud":[],"mcloud":[],"index":[],"sssp":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/sssplibrary/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"2dstructures":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/2dstructures/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"2dtopo":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/2dtopo/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"tc-applicability":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/tc-applicability/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"threedd":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/3dd/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"scdm":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/autowannier/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"curated-cofs":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/curated-cofs/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"optimade-sample":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/optimade-sample/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"stoceriaitf":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/stoceriaitf/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"pyrene-mofs":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/pyrene-mofs/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"li-ion-conductors":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/li-ion-conductors/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"tin-antimony-sulfoiodide":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/tin-antimony-sulfoiodide/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"mp":[{"id":"/","type":"info","attributes":{"api_version":"1.0.1","available_api_versions":[{"url":"http://optimade.materialsproject.org/v1","version":"1.0.1"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"mpds":[{"type":"info","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://api.mpds.io/v1","version":"1.0.0"}],"available_endpoints":["info","links","structures","extensions/properties","extensions/phase_diagrams","extensions/phases"],"formats":["json"],"entry_types_by_format":{"json":["info","links","structures","extensions/properties","extensions/phase_diagrams","extensions/phases"]}}}],"necro":[],"nmd":[{"id":"/","type":"info","attributes":{"api_version":"1.0.1","available_api_versions":[{"url":"https://nomad-lab.eu/prod/rae/optimade/v1","version":"1.0.1"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"odbx":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://optimade.odbx.science/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"omdb":[],"omdb_production":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"http://optimade.openmaterialsdb.se/v1","version":"1.0.0"},{"url":"http://optimade.openmaterialsdb.se/v1.0.0","version":"1.0.0"},{"url":"http://optimade.openmaterialsdb.se/v1.0","version":"1.0.0"}],"available_endpoints":["info","links","structures"],"entry_types_by_format":{"json":["structures"]},"formats":["json"],"is_index":false},"id":"/","type":"info"}],"oqmd":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"http://oqmd.org/optimade/v1/","version":"1.0.0"}],"formats":["json","xml","yaml"],"entry_types_by_format":{"json":["structures"],"xml":["structures"],"yaml":["structures"]},"available_endpoints":["structures","info","links","versions"],"is_index":false}}],"jarvis":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://jarvis.nist.gov/optimade/jarvisdft/v1","version":"1.0.0"}],"formats":["json","xml","yaml"],"entry_types_by_format":{"json":["structures"],"xml":["structures"],"yaml":["structures"]},"available_endpoints":["structures","info","links","versions"],"is_index":false}}],"tcod":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://www.crystallography.net/tcod/optimade/v1.0.0/","version":"1.0.0"}],"available_endpoints":["structures","info"],"entry_types_by_format":{"json":["structures"]},"formats":["json"]},"id":"/","type":"info"}],"twodmatpedia":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"http://optimade.2dmatpedia.org/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}]}}
1
+ {"providers":{"2dstructures":{"id":"2dstructures","type":"links","attributes":{"name":"2D Structures","description":"Two-dimensional (2D) materials from high-throughput computational exfoliation of experimentally known compounds.","base_url":"https://aiida.materialscloud.org/2dstructures/optimade","homepage":"https://materialscloud.org/explore/2dstructures","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"2dtopo":{"id":"2dtopo","type":"links","attributes":{"name":"2D topological insulators","description":"Quantum spin Hall insulator (QSHI) candidates through DFT band structure calculations of a database with 1825 compounds.","base_url":"https://aiida.materialscloud.org/2dtopo/optimade","homepage":"https://materialscloud.org/explore/2dtopo","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"cod":{"id":"cod","type":"links","attributes":{"name":"Crystallography Open Database","description":"Open-access collection of crystal structures of organic, inorganic, metal-organics compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/cod/optimade","homepage":"https://www.crystallography.net/cod","link_type":"child","api_version":"1.0.0","query_limits":[10]}},"curated-cofs":{"id":"curated-cofs","type":"links","attributes":{"name":"CURATED covalent organic frameworks database","description":"Database of experimentally reported Covalent-Organic Frameworks (COFs), provided with DFT-optimized geometry and DDEC partial charges for molecular simulations.","base_url":"https://aiida.materialscloud.org/curated-cofs/optimade","homepage":"https://materialscloud.org/discover/curated-cofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"li-ion-conductors":{"id":"li-ion-conductors","type":"links","attributes":{"name":"Solid-state Li-ion conductors.","description":"High-throughput computational screening study for solid-state Li-ion conductors.","base_url":"https://aiida.materialscloud.org/li-ion-conductors/optimade","homepage":"https://materialscloud.org/explore/li-ion-conductors","link_type":"child","aggregate":"staging","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"mp":{"id":"mp","type":"links","attributes":{"name":"The Materials Project","description":"The Materials Project OPTIMADE endpoint","base_url":"https://optimade.materialsproject.org","homepage":"https://www.materialsproject.org","link_type":"child","api_version":"1.0.1","query_limits":[500]}},"mpds":{"id":"mpds","type":"links","attributes":{"name":"Materials Platform for Data Science","description":"A highly curated Pauling File dataset based on ~0.5M publications and backing up Springer Materials, ICDD PDF, ASM APD, MedeA, Pearson Crystal Data, AtomWork Advanced, etc.","base_url":"https://api.mpds.io","homepage":"https://mpds.io","link_type":"child","api_version":"1.0.0","query_limits":[5,10,100,750]}},"nmd":{"id":"nmd","type":"links","attributes":{"name":"novel materials discovery (NOMAD)","description":"A FAIR data sharing platform for materials science data","base_url":"https://nomad-lab.eu/prod/rae/optimade/","homepage":"https://nomad-lab.eu","link_type":"child","api_version":"1.0.1","query_limits":[500]}},"odbx":{"id":"odbx","type":"links","attributes":{"name":"odbx","description":"The Open Database of Xtals is run by the group of Dr Andrew Morris at the universities of Birmingham and Cambridge and is constructed using the matador library.","base_url":"https://optimade.odbx.science","homepage":"https://odbx.science","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[500]}},"optimade-sample":{"id":"optimade-sample","type":"links","attributes":{"name":"OPTIMADE Sample Database","description":"Database with example structures for OPTIMADE tests.","base_url":"https://aiida.materialscloud.org/optimade-sample/optimade","homepage":"https://materialscloud.org/explore/optimade-sample","link_type":"child","aggregate":"test","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"pyrene-mofs":{"id":"pyrene-mofs","type":"links","attributes":{"name":"Pyrene MOFs","description":"Pyrene Metal Organic Frameworks (MOFs).","base_url":"https://aiida.materialscloud.org/pyrene-mofs/optimade","homepage":"https://materialscloud.org/discover/pyrene-mofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"scdm":{"id":"scdm","type":"links","attributes":{"name":"Automated high-throughput Wannierisation","description":"Validation results of an automated protocol for generating maximally-localized Wannier functions in a high-throughput framework.","base_url":"https://aiida.materialscloud.org/autowannier/optimade","homepage":"https://materialscloud.org/explore/autowannier","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"sssp":{"id":"sssp","type":"links","attributes":{"name":"Standard solid-state pseudopotentials (SSSP)","description":"It contains data generated from the testing protocol of the standard solid-state pseudopotentials library.\n","base_url":"https://aiida.materialscloud.org/sssplibrary/optimade","homepage":"https://materialscloud.org/explore/sssplibrary","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"stoceriaitf":{"id":"stoceriaitf","type":"links","attributes":{"name":"SrTiO3-CeO2 interfaces","description":"Refining random structure searching results of SrTiO3-CeO2 interfaces, and exploring how it can affect ionic conduction. Candidate structures of the DFT validation calculations.","base_url":"https://aiida.materialscloud.org/stoceriaitf/optimade","homepage":"https://materialscloud.org/explore/stoceriaitf","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"tc-applicability":{"id":"tc-applicability","type":"links","attributes":{"name":"Applicability of tail-corrections in the molecular simulations of porous materials","description":"Tail-corrections in molecular simulations for adsorption of gasses in a diverse set of nanoporous crystalline materials (zeolites, Covalent Organic Framworks (COFs), and Metal Organic Frameworks (MOFs)).","base_url":"https://aiida.materialscloud.org/tc-applicability/optimade","homepage":"https://materialscloud.org/explore/tc-applicability","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"tcod":{"id":"tcod","type":"links","attributes":{"name":"Theoretical Crystallography Open Database","description":"Open-access collection of theoretically calculated or refined crystal structures of organic, inorganic, metal-organic compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/tcod/optimade","homepage":"https://www.crystallography.net/tcod","link_type":"child","api_version":"1.0.0","query_limits":[10]}},"threedd":{"id":"threedd","type":"links","attributes":{"name":"Three-dimensional crystals database","description":"Curated set of relaxed three-dimensional crystal structures based on raw CIF data from the experimantal databases MPDS, COD, and ICSD.","base_url":"https://aiida.materialscloud.org/3dd/optimade","homepage":"https://materialscloud.org/explore/3dd","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"tin-antimony-sulfoiodide":{"id":"tin-antimony-sulfoiodide","type":"links","attributes":{"name":"Hidden spontaneous polarisation in the chalcohalide photovoltaic Sn2SbS2I3","description":"Structural, dynamic and electronic characterisation of a novel mixed-metal chalcohalide revealing hidden symmetry breaking and spontaneous polarisation.","base_url":"https://aiida.materialscloud.org/tin-antimony-sulfoiodide/optimade","homepage":"https://materialscloud.org/explore/tin-antimony-sulfoiodide","link_type":"child","aggregate":"ok","no_aggregate_reason":null,"api_version":"1.1.0","query_limits":[100]}},"twodmatpedia":{"id":"twodmatpedia","type":"links","attributes":{"name":"2DMatpedia","description":"2DMatpedia, an open computational database of two-dimensional materials from top-down and bottom-up approaches","base_url":"http://optimade.2dmatpedia.org","homepage":"http://2dmatpedia.org","link_type":"child","api_version":"1.1.0","query_limits":[500]}}},"apis":{"2dstructures":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/2dstructures/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"2dtopo":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/2dtopo/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"aflow":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://aflow.org/API/optimade/v0.9/","version":"0.9.0"},{"url":"https://aflow.org/API/optimade/v1.0/","version":"1.0.0"},{"url":"https://aflow.org/API/optimade/v1.1/","version":"1.1.0"}],"formats":["json"],"entry_types_by_format":{"json":["structures","calculations"]},"available_endpoints":["structures","calculations","info","links"]},"is_index":false}],"cod":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://www.crystallography.net/cod/optimade/v1.0.0/","version":"1.0.0"}],"available_endpoints":["structures","info"],"entry_types_by_format":{"json":["structures"]},"formats":["json"]},"id":"/","type":"info"}],"curated-cofs":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/curated-cofs/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"jarvis":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://jarvis.nist.gov/optimade/jarvisdft/v1","version":"1.0.0"}],"formats":["json","xml","yaml"],"entry_types_by_format":{"json":["structures"],"xml":["structures"],"yaml":["structures"]},"available_endpoints":["structures","info","links","versions"],"is_index":false}}],"li-ion-conductors":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/li-ion-conductors/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"mp":[{"id":"/","type":"info","attributes":{"api_version":"1.0.1","available_api_versions":[{"url":"http://optimade.materialsproject.org/v1","version":"1.0.1"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"mpds":[{"type":"info","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://api.mpds.io/v1","version":"1.0.0"}],"available_endpoints":["structures","extensions/properties","extensions/phase_diagrams","extensions/phases"],"formats":["json"],"entry_types_by_format":{"json":["structures","extensions/properties","extensions/phase_diagrams","extensions/phases"]}}}],"nmd":[{"id":"/","type":"info","attributes":{"api_version":"1.0.1","available_api_versions":[{"url":"http://nomad-lab.eu/v1","version":"1.0.1"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"odbx":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://optimade.odbx.science/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}],"omdb_production":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"http://optimade.openmaterialsdb.se/v1","version":"1.0.0"},{"url":"http://optimade.openmaterialsdb.se/v1.0.0","version":"1.0.0"},{"url":"http://optimade.openmaterialsdb.se/v1.0","version":"1.0.0"}],"available_endpoints":["info","links","structures"],"entry_types_by_format":{"json":["structures"]},"formats":["json"],"is_index":false},"id":"/","type":"info"}],"optimade-sample":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/optimade-sample/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"oqmd":[{"type":"info","id":"/","attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"http://oqmd.org/optimade/v1/","version":"1.0.0"}],"formats":["json","xml","yaml"],"entry_types_by_format":{"json":["structures"],"xml":["structures"],"yaml":["structures"]},"available_endpoints":["structures","info","links","versions"],"is_index":false}}],"pyrene-mofs":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/pyrene-mofs/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"scdm":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/autowannier/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"sssp":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/sssplibrary/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"stoceriaitf":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/stoceriaitf/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"tc-applicability":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/tc-applicability/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"tcod":[{"attributes":{"api_version":"1.0.0","available_api_versions":[{"url":"https://www.crystallography.net/tcod/optimade/v1.0.0/","version":"1.0.0"}],"available_endpoints":["structures","info"],"entry_types_by_format":{"json":["structures"]},"formats":["json"]},"id":"/","type":"info"}],"threedd":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/3dd/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"tin-antimony-sulfoiodide":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"https://aiida.materialscloud.org/tin-antimony-sulfoiodide/optimade/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","extensions/docs","extensions/redoc","extensions/openapi.json","structures"],"entry_types_by_format":{"json":["structures"]},"is_index":false}}],"twodmatpedia":[{"id":"/","type":"info","attributes":{"api_version":"1.1.0","available_api_versions":[{"url":"http://optimade.2dmatpedia.org/v1","version":"1.1.0"}],"formats":["json"],"available_endpoints":["info","links","structures","references"],"entry_types_by_format":{"json":["structures","references"]},"is_index":false}}]}}
@@ -0,0 +1 @@
1
+ {"2dstructures":{"id":"2dstructures","type":"links","attributes":{"name":"2D Structures","description":"Two-dimensional (2D) materials from high-throughput computational exfoliation of experimentally known compounds.","base_url":"https://aiida.materialscloud.org/2dstructures/optimade","homepage":"https://materialscloud.org/explore/2dstructures","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"2dtopo":{"id":"2dtopo","type":"links","attributes":{"name":"2D topological insulators","description":"Quantum spin Hall insulator (QSHI) candidates through DFT band structure calculations of a database with 1825 compounds.","base_url":"https://aiida.materialscloud.org/2dtopo/optimade","homepage":"https://materialscloud.org/explore/2dtopo","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"aflow":{"id":"aflow","type":"links","attributes":{"name":"AFLOW","description":"The AFLOW OPTIMADE endpoint","base_url":"http://aflow.org/API/optimade/","homepage":"http://aflow.org","link_type":"child"}},"cod":{"id":"cod","type":"links","attributes":{"name":"Crystallography Open Database","description":"Open-access collection of crystal structures of organic, inorganic, metal-organics compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/cod/optimade","homepage":"https://www.crystallography.net/cod","link_type":"child"}},"curated-cofs":{"id":"curated-cofs","type":"links","attributes":{"name":"CURATED covalent organic frameworks database","description":"Database of experimentally reported Covalent-Organic Frameworks (COFs), provided with DFT-optimized geometry and DDEC partial charges for molecular simulations.","base_url":"https://aiida.materialscloud.org/curated-cofs/optimade","homepage":"https://materialscloud.org/discover/curated-cofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"jarvis":{"id":"jarvis","type":"links","attributes":{"name":"JARVIS-DFT","description":"JARVIS-DFT is a materials property repository focused on density functional theory (DFT) predictions of material properties, especially for crystalline materials.","base_url":"https://jarvis.nist.gov/optimade/jarvisdft","homepage":"https://jarvis.nist.gov","link_type":"child"}},"li-ion-conductors":{"id":"li-ion-conductors","type":"links","attributes":{"name":"Solid-state Li-ion conductors.","description":"High-throughput computational screening study for solid-state Li-ion conductors.","base_url":"https://aiida.materialscloud.org/li-ion-conductors/optimade","homepage":"https://materialscloud.org/explore/li-ion-conductors","link_type":"child","aggregate":"staging","no_aggregate_reason":null}},"mp":{"id":"mp","type":"links","attributes":{"name":"The Materials Project","description":"The Materials Project OPTIMADE endpoint","base_url":"https://optimade.materialsproject.org","homepage":"https://www.materialsproject.org","link_type":"child"}},"mpds":{"id":"mpds","type":"links","attributes":{"name":"Materials Platform for Data Science","description":"A highly curated Pauling File dataset based on ~0.5M publications and backing up Springer Materials, ICDD PDF, ASM APD, MedeA, Pearson Crystal Data, AtomWork Advanced, etc.","base_url":"https://api.mpds.io","homepage":"https://mpds.io","link_type":"child"}},"nmd":{"id":"nmd","type":"links","attributes":{"name":"novel materials discovery (NOMAD)","description":"A FAIR data sharing platform for materials science data","base_url":"https://nomad-lab.eu/prod/rae/optimade/","homepage":"https://nomad-lab.eu","link_type":"child"}},"odbx":{"id":"odbx","type":"links","attributes":{"name":"odbx","description":"The Open Database of Xtals is run by the group of Dr Andrew Morris at the universities of Birmingham and Cambridge and is constructed using the matador library.","base_url":"https://optimade.odbx.science","homepage":"https://odbx.science","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"omdb_production":{"id":"omdb_production","type":"links","attributes":{"name":"Open Materials Database (omdb) production database","description":"This is the main production version of the Open Materials Database","base_url":"http://optimade.openmaterialsdb.se","homepage":"http://openmaterialsdb.se","link_type":"child"}},"optimade-sample":{"id":"optimade-sample","type":"links","attributes":{"name":"OPTIMADE Sample Database","description":"Database with example structures for OPTIMADE tests.","base_url":"https://aiida.materialscloud.org/optimade-sample/optimade","homepage":"https://materialscloud.org/explore/optimade-sample","link_type":"child","aggregate":"test","no_aggregate_reason":null}},"oqmd":{"id":"oqmd","type":"links","attributes":{"name":"The OQMD","description":"The Open Quantum Materials Database endpoint","base_url":"http://oqmd.org/optimade/","homepage":"http://oqmd.org","link_type":"child"}},"pyrene-mofs":{"id":"pyrene-mofs","type":"links","attributes":{"name":"Pyrene MOFs","description":"Pyrene Metal Organic Frameworks (MOFs).","base_url":"https://aiida.materialscloud.org/pyrene-mofs/optimade","homepage":"https://materialscloud.org/discover/pyrene-mofs","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"scdm":{"id":"scdm","type":"links","attributes":{"name":"Automated high-throughput Wannierisation","description":"Validation results of an automated protocol for generating maximally-localized Wannier functions in a high-throughput framework.","base_url":"https://aiida.materialscloud.org/autowannier/optimade","homepage":"https://materialscloud.org/explore/autowannier","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"sssp":{"id":"sssp","type":"links","attributes":{"name":"Standard solid-state pseudopotentials (SSSP)","description":"It contains data generated from the testing protocol of the standard solid-state pseudopotentials library.\n","base_url":"https://aiida.materialscloud.org/sssplibrary/optimade","homepage":"https://materialscloud.org/explore/sssplibrary","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"stoceriaitf":{"id":"stoceriaitf","type":"links","attributes":{"name":"SrTiO3-CeO2 interfaces","description":"Refining random structure searching results of SrTiO3-CeO2 interfaces, and exploring how it can affect ionic conduction. Candidate structures of the DFT validation calculations.","base_url":"https://aiida.materialscloud.org/stoceriaitf/optimade","homepage":"https://materialscloud.org/explore/stoceriaitf","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"tc-applicability":{"id":"tc-applicability","type":"links","attributes":{"name":"Applicability of tail-corrections in the molecular simulations of porous materials","description":"Tail-corrections in molecular simulations for adsorption of gasses in a diverse set of nanoporous crystalline materials (zeolites, Covalent Organic Framworks (COFs), and Metal Organic Frameworks (MOFs)).","base_url":"https://aiida.materialscloud.org/tc-applicability/optimade","homepage":"https://materialscloud.org/explore/tc-applicability","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"tcod":{"id":"tcod","type":"links","attributes":{"name":"Theoretical Crystallography Open Database","description":"Open-access collection of theoretically calculated or refined crystal structures of organic, inorganic, metal-organic compounds and minerals, excluding biopolymers","base_url":"https://www.crystallography.net/tcod/optimade","homepage":"https://www.crystallography.net/tcod","link_type":"child"}},"threedd":{"id":"threedd","type":"links","attributes":{"name":"Three-dimensional crystals database","description":"Curated set of relaxed three-dimensional crystal structures based on raw CIF data from the experimantal databases MPDS, COD, and ICSD.","base_url":"https://aiida.materialscloud.org/3dd/optimade","homepage":"https://materialscloud.org/explore/3dd","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"tin-antimony-sulfoiodide":{"id":"tin-antimony-sulfoiodide","type":"links","attributes":{"name":"Hidden spontaneous polarisation in the chalcohalide photovoltaic Sn2SbS2I3","description":"Structural, dynamic and electronic characterisation of a novel mixed-metal chalcohalide revealing hidden symmetry breaking and spontaneous polarisation.","base_url":"https://aiida.materialscloud.org/tin-antimony-sulfoiodide/optimade","homepage":"https://materialscloud.org/explore/tin-antimony-sulfoiodide","link_type":"child","aggregate":"ok","no_aggregate_reason":null}},"twodmatpedia":{"id":"twodmatpedia","type":"links","attributes":{"name":"2DMatpedia","description":"2DMatpedia, an open computational database of two-dimensional materials from top-down and bottom-up approaches","base_url":"http://optimade.2dmatpedia.org","homepage":"http://2dmatpedia.org","link_type":"child"}}}
package/dist/types.d.ts CHANGED
@@ -19,6 +19,8 @@ export interface Meta {
19
19
  description: string;
20
20
  prefix: string;
21
21
  };
22
+ pages?: number;
23
+ limits?: number[];
22
24
  }
23
25
  export interface Links {
24
26
  base_url: string;
@@ -35,8 +37,8 @@ export interface ApiVer {
35
37
  [key: string]: string;
36
38
  }
37
39
  export interface Api {
38
- type: string;
39
40
  id: string;
41
+ type: string;
40
42
  attributes: {
41
43
  api_version: string;
42
44
  available_api_versions: ApiVer | ApiVer[];
@@ -54,6 +56,8 @@ export interface Provider {
54
56
  base_url: string | null;
55
57
  homepage?: string | null;
56
58
  link_type?: string;
59
+ query_limits?: number[];
60
+ api_version?: string;
57
61
  };
58
62
  }
59
63
  export interface Structure {
@@ -78,7 +82,7 @@ export interface InfoResponse {
78
82
  [key: string]: any;
79
83
  }
80
84
  export interface StructuresResponse {
81
- data: Structure[];
85
+ data?: Structure[];
82
86
  links?: Links;
83
87
  meta?: Meta;
84
88
  }
@@ -90,10 +94,20 @@ export interface LinksResponse {
90
94
  export interface ResponseError extends Error {
91
95
  response?: any;
92
96
  }
97
+ export interface ErrorObject {
98
+ status: string;
99
+ title: string;
100
+ detail?: string;
101
+ length?: string;
102
+ }
103
+ export interface ErrorResponse {
104
+ errors: ErrorObject;
105
+ meta: any;
106
+ }
93
107
  export declare type ProvidersMap = {
94
108
  [key: string]: Provider;
95
109
  };
96
110
  export declare type ApisMap = {
97
111
  [key: string]: Api[];
98
112
  };
99
- export declare type StructuresResult = [Promise<Structure>, Promise<Provider>][];
113
+ export declare type StructuresResult = [Promise<StructuresResponse[]>, Promise<Provider>][];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "optimade",
3
- "version": "1.2.1",
3
+ "version": "2.0.4",
4
4
  "description": "Aggregating Optimade client for the online materials databases",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/prefetch.js CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ /* jshint esversion: 6 */
4
+
3
5
  const fs = require('fs');
4
6
  const path = require('path');
5
7
  const { Optimade } = require('./dist/index');
@@ -9,19 +11,70 @@ const { AbortController } = require('node-abort-controller');
9
11
  global.AbortController = AbortController;
10
12
 
11
13
  const optimade = new Optimade({
12
- providersUrl: 'https://providers.optimade.org/providers.json'
14
+ providersUrl: 'https://providers.optimade.org/providers.json'
13
15
  });
14
16
 
15
- optimade.getProviders().then(() => {
17
+ optimade.getProviders().then(async () => {
18
+
19
+ const filteredApis = Object.entries(optimade.apis).filter(([k, v]) => v.length);
20
+ const apis = filteredApis.sort().reduce((acc, [k, v]) => {
21
+ return { ...acc, ...{ [k]: v } };
22
+ }, {});
23
+
24
+ const source = Object.keys(optimade.providers).sort().reduce(
25
+ (obj, key) => {
26
+ obj[key] = optimade.providers[key];
27
+ return obj;
28
+ }, {});
29
+
30
+ async function getQueryLimits(providers, max = 1000) {
16
31
 
17
- const data = {
18
- providers: optimade.providers,
19
- apis: optimade.apis,
20
- };
32
+ const fetchLimits = async (k, v) => {
33
+ const formula = `chemical_formula_anonymous="A2B"`;
34
+ const url = `${v.attributes.base_url}/v1/structures?filter=${formula}&page_limit=${max}`;
35
+ try {
36
+ const res = await fetch(url).then(res => res.json());
37
+ const api = res.meta && res.meta.api_version || apis[k][0].attributes.api_version;
38
+ //console.dir(res);
39
+ const detail = (e) => {
40
+ return e
41
+ ? e.length
42
+ ? e[0].detail
43
+ : e.detail
44
+ : '0';
45
+ };
46
+ const nums = detail(res.errors).match(/\d+/g).filter(n => +n < max).map(n => +n);
47
+ if (!nums.includes(0))
48
+ return {
49
+ [k]: { ...v, attributes: { ...v.attributes, api_version: api, ['query_limits']: nums } }
50
+ };
51
+ } catch (error) {
52
+ console.log(error);
53
+ }
54
+ };
21
55
 
22
- fs.writeFile(path.join(__dirname, 'dist/prefetched.json'), JSON.stringify(data), (err) => {
23
- if (err) throw err;
24
- console.log('The cache file has been saved!');
25
- });
56
+ providers = await Object.entries(providers).reduce(async (promise, [k, v]) => {
57
+ const provider = await fetchLimits(k, v);
58
+ const acc = await promise;
59
+ return { ...acc, ...provider };
60
+ }, Promise.resolve({}));
26
61
 
27
- });
62
+ //const log = { prefetched: Object.keys(providers).length, source: Object.keys(source).length };
63
+ //console.log(log);
64
+
65
+ return providers;
66
+ }
67
+
68
+ getQueryLimits(source).then(providers => {
69
+ const data = { providers, apis };
70
+ fs.writeFile(path.join(__dirname, 'dist/prefetched.json'), JSON.stringify(data), (err) => {
71
+ if (err) throw err;
72
+ console.log('The prefetched.json file has been saved!');
73
+ });
74
+ fs.writeFile(path.join(__dirname, 'dist/providers.json'), JSON.stringify(source), (err) => {
75
+ if (err) throw err;
76
+ console.log('The providers.json file has been saved!');
77
+ });
78
+ });
79
+
80
+ });
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import { allSettled, fetchWithTimeout } from './utils';
3
2
 
4
3
  import type * as Types from './types';
@@ -7,11 +6,11 @@ export { Types };
7
6
  export class Optimade {
8
7
  private providersUrl: string = '';
9
8
  private corsProxyUrl: string = '';
10
- public providers: Types.ProvidersMap | null = null;
11
- public apis: Types.ApisMap = {};
9
+ providers: Types.ProvidersMap | null = null;
10
+ apis: Types.ApisMap = {};
12
11
  private reqStack: string[] = [];
13
12
 
14
- constructor({ providersUrl = '', corsProxyUrl = '' } : {providersUrl?: string; corsProxyUrl?: string} = {} ) {
13
+ constructor({ providersUrl = '', corsProxyUrl = '' }: { providersUrl?: string; corsProxyUrl?: string; } = {}) {
15
14
  this.corsProxyUrl = corsProxyUrl;
16
15
  this.providersUrl = this.wrapUrl(providersUrl);
17
16
  }
@@ -64,31 +63,48 @@ export class Optimade {
64
63
  return Optimade.apiVersion(apis);
65
64
  }
66
65
 
67
- async getStructures(providerId: string, filter: string = ''): Promise<Types.Structure[] | null> {
66
+ async getStructures(providerId: string, filter: string = '', page: number = 1, limit: number): Promise<Types.StructuresResponse[] | Types.ResponseError> {
68
67
 
69
68
  if (!this.apis[providerId]) return null;
70
69
 
71
70
  const apis = this.apis[providerId].filter(api => api.attributes.available_endpoints.includes('structures'));
71
+ const provider = this.providers[providerId];
72
+
73
+ const structures: Types.StructuresResponse[] = await allSettled(apis.map(async (api: Types.Api) => {
74
+ if (page <= 0) page = 1;
75
+ const pageLimit = limit ? `&page_limit=${limit}` : '';
76
+ const pageNumber = page ? `&page_number=${page - 1}` : '';
77
+ const pageOffset = limit && page ? `&page_offset=${limit * (page - 1)}` : '';
78
+ const params = filter ? `${pageLimit + pageNumber + pageOffset}` : `?${pageLimit}`;
79
+ const url: string = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter + params}` : `/structures${params}`);
72
80
 
73
- const structures: Types.StructuresResponse[] = await allSettled(apis.map((api: Types.Api) => {
74
- const url: string = this.wrapUrl(Optimade.apiVersionUrl(api), filter ? `/structures?filter=${filter}` : '/structures');
75
- // TODO pagination e.g. url += (filter ? '&' : '?') + 'page_limit=100'
76
- return Optimade.getJSON(url);
81
+ try {
82
+ return await Optimade.getJSON(url, {}, { Origin: 'https://cors.optimade.science', 'X-Requested-With': 'XMLHttpRequest' });
83
+ } catch (error) {
84
+ return error;
85
+ }
77
86
  }));
78
87
 
79
- //console.log('Ready ' + providerId);
80
- return structures.reduce((structures: Types.Structure[], structure: Types.StructuresResponse | null) => {
81
- return structure ? structures.concat(structure.data) : structures;
88
+ return structures.reduce((structures: any[], structure: Types.StructuresResponse | Types.ResponseError): Types.StructuresResponse[] => {
89
+ console.dir(`optimade-client-${providerId}:`, structure);
90
+
91
+ if (structure instanceof Error || Object.keys(structure).includes('errors')) {
92
+ return structures.concat(structure);
93
+ } else {
94
+ structure.meta.pages = Math.ceil(structure.meta.data_returned / (limit || structure.data.length));
95
+ structure.meta.limits = provider.attributes.query_limits || [10];
96
+ return structures.concat(structure);
97
+ }
82
98
  }, []);
83
99
  }
84
100
 
85
- getStructuresAll(providerIds: string[], filter: string = '', batch: boolean = true): Promise<Promise<Types.StructuresResult>[]> | Promise<Types.StructuresResult>[] {
86
-
101
+ getStructuresAll(providerIds: string[], filter: string = '', page: number = 1, limit: number, batch: boolean = true): Promise<Promise<Types.StructuresResult>[]> | Promise<Types.StructuresResult>[] {
102
+
87
103
  const results = providerIds.reduce((structures: Promise<any>[], providerId: string) => {
88
104
  const provider = this.providers[providerId];
89
105
  if (provider) {
90
106
  structures.push(allSettled([
91
- this.getStructures(providerId, filter),
107
+ this.getStructures(providerId, filter, page, limit),
92
108
  Promise.resolve(provider)
93
109
  ]));
94
110
  }
@@ -127,9 +143,10 @@ export class Optimade {
127
143
  const res = await fetchWithTimeout(url.toString(), { headers }, timeout);
128
144
 
129
145
  if (!res.ok) {
130
- const err: Types.ResponseError = new Error(res.statusText);
131
- err.response = res;
132
- throw err;
146
+ const err: Types.ErrorResponse = await res.json();
147
+ const error: Types.ResponseError = new Error(err.errors[0].detail);
148
+ error.response = err;
149
+ throw error;
133
150
  }
134
151
 
135
152
  if (res.status !== 204) {
package/src/types.ts CHANGED
@@ -18,7 +18,9 @@ export interface Meta {
18
18
  name: string;
19
19
  description: string;
20
20
  prefix: string;
21
- };
21
+ },
22
+ pages?: number;
23
+ limits?: number[];
22
24
  }
23
25
 
24
26
  export interface Links {
@@ -38,8 +40,8 @@ export interface ApiVer {
38
40
  }
39
41
 
40
42
  export interface Api {
41
- type: string;
42
43
  id: string;
44
+ type: string;
43
45
  attributes: {
44
46
  api_version: string;
45
47
  available_api_versions: ApiVer | ApiVer[];
@@ -58,6 +60,8 @@ export interface Provider {
58
60
  base_url: string | null;
59
61
  homepage?: string | null;
60
62
  link_type?: string;
63
+ query_limits?: number[];
64
+ api_version?: string;
61
65
  };
62
66
  }
63
67
 
@@ -87,7 +91,7 @@ export interface InfoResponse {
87
91
  }
88
92
 
89
93
  export interface StructuresResponse {
90
- data: Structure[];
94
+ data?: Structure[];
91
95
  links?: Links;
92
96
  meta?: Meta;
93
97
  }
@@ -102,7 +106,18 @@ export interface ResponseError extends Error {
102
106
  response?: any;
103
107
  }
104
108
 
105
- export type ProvidersMap = { [key: string]: Provider }
106
- export type ApisMap = { [key: string]: Api[] }
109
+ export interface ErrorObject {
110
+ status: string;
111
+ title: string;
112
+ detail?: string;
113
+ length?: string;
114
+ }
115
+ export interface ErrorResponse {
116
+ errors: ErrorObject;
117
+ meta: any;
118
+ }
119
+
120
+ export type ProvidersMap = { [key: string]: Provider; };
121
+ export type ApisMap = { [key: string]: Api[]; };
107
122
 
108
- export type StructuresResult = [Promise<Structure>, Promise<Provider>][];
123
+ export type StructuresResult = [Promise<StructuresResponse[]>, Promise<Provider>][];
package/src/utils.ts CHANGED
@@ -14,7 +14,7 @@ export async function fetchWithTimeout(url, options = {}, timeout = 5000): Promi
14
14
 
15
15
  try {
16
16
  return await fetch(url, { ...options, signal });
17
- } catch(err) {
17
+ } catch (err) {
18
18
  if (err.name === 'AbortError') {
19
19
  throw new Error('Request timed out');
20
20
  }