def _extract_formula(args, akinds, asites): """Extract formula from the structure object.""" from aiida.orm.nodes.data.structure import (get_formula, get_symbols_string) if args.element is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not any([s in args.element for s in all_symbols]): return None if args.element_only is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not all([s in all_symbols for s in args.element_only]): return None # We want only the StructureData that have attributes if akinds is None or asites is None: return None symbol_dict = {} for k in akinds: symbols = k['symbols'] weights = k['weights'] symbol_dict[k['name']] = get_symbols_string(symbols, weights) try: symbol_list = [] for site in asites: symbol_list.append(symbol_dict[site['kind_name']]) formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' return formula
def _extract_formula(struc_pk, args, deser_data): """Extract formula.""" from aiida.orm.nodes.data.structure import (get_formula, get_symbols_string) if struc_pk is not None: # Exclude structures by the elements if args.element is not None: all_kinds = [ k['symbols'] for k in deser_data[struc_pk]['kinds'] ] all_symbols = [ item for sublist in all_kinds for item in sublist ] if not any([s in args.element for s in all_symbols]): return None if args.element_only is not None: all_kinds = [ k['symbols'] for k in deser_data[struc_pk]['kinds'] ] all_symbols = [ item for sublist in all_kinds for item in sublist ] if not all([s in all_symbols for s in args.element_only]): return None # build the formula symbol_dict = { k['name']: get_symbols_string(k['symbols'], k['weights']) for k in deser_data[struc_pk]['kinds'] } try: symbol_list = [ symbol_dict[s['kind_name']] for s in deser_data[struc_pk]['sites'] ] formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' # cycle if we imposed the filter on elements if args.element is not None or args.element_only is not None: return None else: formula = '<<UNKNOWN>>' return formula
def get_formula(self, mode="hill", separator=""): """Copy of aiida.orm.StructureData:get_formula()""" from aiida.orm.nodes.data.structure import get_symbols_string, get_formula symbol_list = [] for site in self._sites: for _kind in self._kinds: if _kind["name"] == site["kind_name"]: kind = _kind break else: raise AiidaError( f"kind with name {site['kind_name']} cannot be found amongst the kinds {self._kinds}" ) symbol_list.append(get_symbols_string(kind["symbols"], kind["weights"])) return get_formula(symbol_list, mode=mode, separator=separator)
def _extract_formula(akinds, asites, args): """ Extract formula from the structure object. :param akinds: list of kinds, e.g. [{'mass': 55.845, 'name': 'Fe', 'symbols': ['Fe'], 'weights': [1.0]}, {'mass': 15.9994, 'name': 'O', 'symbols': ['O'], 'weights': [1.0]}] :param asites: list of structure sites e.g. [{'position': [0.0, 0.0, 0.0], 'kind_name': 'Fe'}, {'position': [2.0, 2.0, 2.0], 'kind_name': 'O'}] :param args: a namespace with parsed command line parameters, here only 'element' and 'element_only' are used :type args: dict :return: a string with formula if the formula is found """ from aiida.orm.nodes.data.structure import (get_formula, get_symbols_string) if args.element is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not any([s in args.element for s in all_symbols]): return None if args.element_only is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not all([s in all_symbols for s in args.element_only]): return None # We want only the StructureData that have attributes if akinds is None or asites is None: return '<<UNKNOWN>>' symbol_dict = {} for k in akinds: symbols = k['symbols'] weights = k['weights'] symbol_dict[k['name']] = get_symbols_string(symbols, weights) try: symbol_list = [] for site in asites: symbol_list.append(symbol_dict[site['kind_name']]) formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' return formula
def structure_list(elements, raw, formula_mode, past_days, groups, all_users): """List StructureData objects.""" from aiida.orm.nodes.data.structure import StructureData, get_formula, get_symbols_string from tabulate import tabulate elements_only = False lst = data_list(StructureData, ['Id', 'Label', 'Kinds', 'Sites'], elements, elements_only, formula_mode, past_days, groups, all_users) entry_list = [] for [pid, label, akinds, asites] in lst: # If symbols are defined there is a filtering of the structures # based on the element # When QueryBuilder will support this (attribute)s filtering, # it will be pushed in the query. if elements is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not any([s in elements for s in all_symbols]): continue if elements_only: echo.echo_critical('Not implemented elements-only search') # We want only the StructureData that have attributes if akinds is None or asites is None: continue symbol_dict = {} for k in akinds: symbols = k['symbols'] weights = k['weights'] symbol_dict[k['name']] = get_symbols_string(symbols, weights) try: symbol_list = [] for site in asites: symbol_list.append(symbol_dict[site['kind_name']]) formula = get_formula(symbol_list, mode=formula_mode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' entry_list.append([str(pid), label, str(formula)]) counter = 0 struct_list_data = list() if not raw: struct_list_data.append(LIST_PROJECT_HEADERS) for entry in entry_list: for i, value in enumerate(entry): if isinstance(value, list): entry[i] = ','.join(value) for i in range(len(entry), len(LIST_PROJECT_HEADERS)): entry.append(None) counter += 1 struct_list_data.extend(entry_list) if raw: echo.echo(tabulate(struct_list_data, tablefmt='plain')) else: echo.echo(tabulate(struct_list_data, headers='firstrow')) echo.echo('\nTotal results: {}\n'.format(counter))
def get_bands_and_parents_structure(self, args): """ Returns bands and closest parent structure """ from django.db.models import Q from aiida.backends.djsite.db import models from aiida.common.utils import grouper from aiida.orm.nodes.data.structure import (get_formula, get_symbols_string) from aiida.orm import BandsData from aiida import orm user = orm.User.objects.get_default() query_group_size = 100 q_object = None if args.all_users is False: q_object = Q(user__id=user.id) else: q_object = Q() self.query_past_days(q_object, args) self.query_group(q_object, args) bands_list = models.DbNode.objects.filter(node_type__startswith=BandsData.class_node_type) \ .filter(q_object).distinct().order_by('ctime') bands_list_data = bands_list.values_list('pk', 'label', 'ctime') # split data in chunks grouped_bands_list_data = grouper(query_group_size, [(_[0], _[1], _[2]) for _ in bands_list_data]) entry_list = [] for this_chunk in grouped_bands_list_data: # gather all banddata pks pks = [_[0] for _ in this_chunk] # get the closest structures (WITHOUT DbPath) q_object = Q(node_type='data.structure.StructureData.') structure_dict = get_closest_parents(pks, q_object, chunk_size=1) struc_pks = [structure_dict[pk] for pk in pks] # query for the attributes needed for the structure formula res_attr = models.DbNode.objects.filter( id__in=struc_pks).values_list('id', 'attributes') deser_data = {} for rattr in res_attr: deser_data[rattr[0]] = rattr[1] # prepare the printout for ((bid, blabel, bdate), struc_pk) in zip(this_chunk, struc_pks): if struc_pk is not None: # Exclude structures by the elements if args.element is not None: all_kinds = [ k['symbols'] for k in deser_data[struc_pk]['kinds'] ] all_symbols = [ item for sublist in all_kinds for item in sublist ] if not any([s in args.element for s in all_symbols]): continue if args.element_only is not None: all_kinds = [ k['symbols'] for k in deser_data[struc_pk]['kinds'] ] all_symbols = [ item for sublist in all_kinds for item in sublist ] if not all( [s in all_symbols for s in args.element_only]): continue # build the formula symbol_dict = { k['name']: get_symbols_string(k['symbols'], k['weights']) for k in deser_data[struc_pk]['kinds'] } try: symbol_list = [ symbol_dict[s['kind_name']] for s in deser_data[struc_pk]['sites'] ] formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' # cycle if we imposed the filter on elements if args.element is not None or args.element_only is not None: continue else: formula = '<<UNKNOWN>>' entry_list.append([ str(bid), str(formula), bdate.strftime('%d %b %Y'), blabel ]) return entry_list
def get_bands_and_parents_structure(self, args): """ Search for bands and return bands and the closest structure that is a parent of the instance. This is the backend independent way, can be overriden for performance reason :returns: A list of sublists, each latter containing (in order): pk as string, formula as string, creation date, bandsdata-label """ import datetime from aiida.common import timezone from aiida.orm.nodes.data.structure import (get_formula, get_symbols_string) from aiida import orm qb = orm.QueryBuilder() if args.all_users is False: user = orm.User.objects.get_default() qb.append(orm.User, tag='creator', filters={'email': user.email}) else: qb.append(orm.User, tag='creator') bdata_filters = {} if args.past_days is not None: now = timezone.now() n_days_ago = now - datetime.timedelta(days=args.past_days) bdata_filters.update({'ctime': {'>=': n_days_ago}}) qb.append(orm.BandsData, tag='bdata', with_user='******', filters=bdata_filters, project=['id', 'label', 'ctime']) group_filters = {} if args.group_name is not None: group_filters.update({'name': {'in': args.group_name}}) if args.group_pk is not None: group_filters.update({'id': {'in': args.group_pk}}) if group_filters: qb.append(orm.Group, tag='group', filters=group_filters, with_node='bdata') qb.append( orm.StructureData, tag='sdata', with_descendants='bdata', # We don't care about the creator of StructureData project=['id', 'attributes.kinds', 'attributes.sites']) qb.order_by({orm.StructureData: {'ctime': 'desc'}}) list_data = qb.distinct() entry_list = [] already_visited_bdata = set() for [bid, blabel, bdate, sid, akinds, asites] in list_data.all(): # We process only one StructureData per BandsData. # We want to process the closest StructureData to # every BandsData. # We hope that the StructureData with the latest # creation time is the closest one. # This will be updated when the QueryBuilder supports # order_by by the distance of two nodes. if already_visited_bdata.__contains__(bid): continue already_visited_bdata.add(bid) if args.element is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not any([s in args.element for s in all_symbols]): continue if args.element_only is not None: all_symbols = [_['symbols'][0] for _ in akinds] if not all([s in all_symbols for s in args.element_only]): continue # We want only the StructureData that have attributes if akinds is None or asites is None: continue symbol_dict = {} for k in akinds: symbols = k['symbols'] weights = k['weights'] symbol_dict[k['name']] = get_symbols_string(symbols, weights) try: symbol_list = [] for s in asites: symbol_list.append(symbol_dict[s['kind_name']]) formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = '<<UNKNOWN>>' entry_list.append( [str(bid), str(formula), bdate.strftime('%d %b %Y'), blabel]) return entry_list