Source code for httk.optimade.httk_execute_query

#!/usr/bin/env python
#
#    The high-throughput toolkit (httk)
#    Copyright (C) 2012-2020 Rickard Armiento
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

from httk.optimade.optimade_filter_to_httk import optimade_filter_to_httk
from httk.optimade.httk_entries import httk_recognized_prefixes

_field_map = {
    'Structure': {
        'type': lambda x,y: "structures",
        'id': lambda x,y: x.db.sid,
        'structure_features': lambda x,y: [],
        'lattice_vectors': lambda x,y: x.uc_basis.to_floats(),
        'elements': lambda x,y: sorted(list(set(x.formula_symbols))),
        'nelements': lambda x,y: x.number_of_elements,
        'chemical_formula_descriptive': lambda x,y: x.formula,
        'dimension_types': lambda x,y: [1 if el else 0 for el in [True, True, True]],
        'nperiodic_dimensions': lambda x,y: list([True, True, True]).count(True),
        #TODO: Sort out what is wrong with x.pbc
    }
}

[docs]class HttkResults(object): def __init__(self, searcher, response_fields, unknown_response_fields, limit, offset): self.searcher = searcher self.cur = iter(searcher) self.limit = limit self.response_fields = response_fields self.unknown_response_fields = unknown_response_fields self._count = 0 self.offset = offset self.more_data_available = True
[docs] def count(self): return self.searcher.count()
def __iter__(self): return self def __next__(self): try: while self.offset > 0: next(self.cur) self.offset -= 1 row = next(self.cur)[0][0] result = dict() for field in self.unknown_response_fields: result[field] = None for field in self.response_fields: if field in _field_map[type(row).__name__]: result[field] = _field_map[type(row).__name__][field](row, field) elif field.startswith(httk_recognized_prefixes): for prefix in httk_recognized_prefixes: if field.startswith(prefix): field = field[len(prefix):] break result[field]=getattr(row,field) else: raise Exception("Unexpected field requested:"+str(field)) except StopIteration: self.more_data_available = False self.cur.close() self.cur = None raise StopIteration if self.limit is not None and self._count == self.limit: self.more_data_available = True self.cur.close() self.cur = None raise StopIteration self._count += 1 return result def __del__(self): if self.cur is not None: self.cur.close() # Python 2 compability
[docs] def next(self): return self.__next__()
[docs]def httk_execute_query(store, entries, response_fields, unknown_response_fields, response_limit, response_offset, optimade_filter_ast=None, debug=False): searcher = store.searcher() searcher = optimade_filter_to_httk(optimade_filter_ast, entries, searcher) if response_limit is not None: # We need one more than asked for to know if there is more data. searcher.set_limit(response_limit+1) if response_offset is not None: searcher.add_offset(response_offset) # Offset (and limit, but it doesn't matter) is already handled by the searcher. return HttkResults(searcher, response_fields, unknown_response_fields, response_limit, 0)
if __name__ == "__main__": import os, sys from pprint import pprint from parse_optimade_filter import parse_optimade_filter import httk, httk.db backend = httk.db.backend.Sqlite('../../../Tutorial/tutorial_data/tutorial.sqlite') store = httk.db.store.SqlStore(backend) # This represents the query being received (later to be received via a web URL query) tables = ["structures"] response_fields = ["id", "chemical_formula_descriptive", "_httk_formula", "elements"] if len(sys.argv) >= 2: input_string = sys.argv[1] else: input_string ='nelements=3' #input_string ='elements HAS ALL "Ga","Ti" AND (nelements=3 OR nelements=2)' filter_ast = parse_optimade_filter(input_string, verbosity=0) sys.stdout.write("==== FILTER STRING PARSE RESULT:\n") pprint(filter_ast) sys.stdout.write("====\n") filter_ast = parse_optimade_filter(input_string) response_limit = 50 response_offset = 0 result = httk_execute_query(store, tables, response_fields, [], response_limit, response_offset, filter_ast, debug=True) print("==== END RESULT") for l in result: print(l) print("===============") #print("==== END RESULT") #for match, header in result: # print(match[0].formula) #print("===============")