Skip to content

Commit

Permalink
Merge pull request #141 from JuDFTteam/fix_issue_137
Browse files Browse the repository at this point in the history
Fix finding parent structure for KkrimpCalculation and `strucplot` input to `plot_kkr`
  • Loading branch information
PhilippRue authored Nov 10, 2023
2 parents 9e46c4b + 2eac151 commit 9bddcd5
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10"]
aiida: [{version: 'aiida-core==2.1.2', name: '2.1.2'}]
aiida: [{version: 'aiida-core==2.3.0', name: '2.3.0'}]
masci-tools: [{version: 'git+https://github.com/JuDFTteam/masci-tools.git@develop', name: '-masci-develop'}]
allowed-to-fail: [false]

Expand Down Expand Up @@ -125,7 +125,7 @@ jobs:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10"]
aiida: [{version: 'aiida-core==2.1.2', name: '2.1.2'}]
aiida: [{version: 'aiida-core==2.3.0', name: '2.3.0'}]
masci-tools: [{version: 'git+https://github.com/JuDFTteam/masci-tools.git@develop', name: '-masci-develop'}]
allowed-to-fail: [false]

Expand Down
4 changes: 2 additions & 2 deletions aiida_kkr/parsers/kkrimp.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def __init__(self, calc):
super(KkrimpParser, self).__init__(calc)

# pylint: disable=protected-access

def parse(self, debug=False, ignore_nan=True, **kwargs): # pylint: disable=unexpected-keyword-arg
# pylint: disable=unexpected-keyword-arg
def parse(self, debug=False, ignore_nan=True, **kwargs):
"""
Parse output data folder, store results in database.
Expand Down
6 changes: 5 additions & 1 deletion aiida_kkr/tools/find_parent.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ def get_remote(parent_folder):
try:
parent_folder_tmp = parent_folder_tmp0.get_incoming().get_node_by_label('remote_folder')
except NotExistent:
parent_folder_tmp = parent_folder_tmp0
try:
# check if GFhost_folder is there, this is the case for a KkrimpCalculation
parent_folder_tmp = parent_folder_tmp0.get_incoming().get_node_by_label('GFhost_folder')
except NotExistent:
parent_folder_tmp = parent_folder_tmp0
return parent_folder_tmp


Expand Down
81 changes: 72 additions & 9 deletions aiida_kkr/tools/plot_kkr.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,51 @@
__copyright__ = (u'Copyright (c), 2018, Forschungszentrum Jülich GmbH, '
'IAS-1/PGI-1, Germany. All rights reserved.')
__license__ = 'MIT license, see LICENSE.txt file'
__version__ = '0.7.1'
__version__ = '0.7.2'
__contributors__ = ('Philipp Rüßmann')


def get_datetime_from_str(calc, verbose=False):
"""
Return a datetime object from the last time a calculation was checked by the scheduler.
Every calculation should have the 'scheduler_lastchecktime' attribute which has the
following format: '2023-11-08T22:44:13.543215+00:00'.
This is converted to a datetime object that can be sorted.
"""
from datetime import datetime
# get last time stamp of scheduler from calculation attribute
try:
last_time_on_computer = calc.attributes['scheduler_lastchecktime']
except:
raise ValueError('Failed to get "scheduler_lastchecktime" from calculation.')
# parse date and time from string
date = last_time_on_computer.split('T')[0]
time = last_time_on_computer.split('T')[1].split('.')[0]
# change format
datetime_str = date[2:].replace('-', '/') + ' ' + time
# convert to datetime object
datetime_object = datetime.strptime(datetime_str, '%y/%m/%d %H:%M:%S')

if verbose:
print(datetime_object) # printed in default format

#return datetime object of the last time the calculation was checked
return datetime_object


def get_sorting_indices(calcs):
"""
Get the sorting index for a list of calculations.
For each calculation the datetime object of the last time the scheduler checked the
calculation is extracted. This is then sorted and the sorting index array is returned.
"""
datetimes = [get_datetime_from_str(calc) for calc in calcs]
isort = np.array(datetimes).argsort()
return isort


def remove_empty_atoms(show_empty_atoms, structure, silent=False):
# check if empty sphere need to be removed for plotting (ase structgure cannot be constructed for alloys or vacancies)
#print('in remove empty atoms:', structure.has_vacancies, ('X' in [i.kind_name for i in structure.sites]) )
Expand Down Expand Up @@ -341,6 +382,8 @@ class plot_kkr(object):
:type switch_xy: bool
:param iatom: list of atom indices which are supposed to be plotted (default: [], i.e. show all atoms)
:type iatom: list
:param debug: activate debug output
:type debug: bool
additional keyword arguments are passed onto the plotting function which allows, for example,
to change the markers used in a DOS plot to crosses via `marker='x'`
Expand All @@ -359,8 +402,17 @@ def __init__(self, nodes=None, **kwargs):
from aiida import load_profile
load_profile()

# used to keep track of structure plotting
self.sview = None

# debug mode
self.debug = False
if 'debug' in kwargs:
self.debug = kwargs.pop('debug')
print('start plot_kkr')
print('kwargs:', kwargs)

# grouping of node if a list of nodes is the input instead of a single node
groupmode = False
if type(nodes) == list:
if len(nodes) > 1:
Expand Down Expand Up @@ -1006,8 +1058,12 @@ def plot_voro_calc(self, node, **kwargs):
def plot_kkrimp_calc(self, node, return_rms=False, return_stot=False, plot_rms=True, **kwargs):
"""plot things from a kkrimp Calculation node"""

if self.debug:
print('in plot_kkrimp_calc')
print('kwargs:', kwargs)

# plot impurity cluster
if kwargs.get('strucplot', True):
if kwargs.get('strucplot', False):
if _has_ase_notebook():
self.sview = plot_imp_cluster(node, **kwargs)
else:
Expand Down Expand Up @@ -1048,7 +1104,7 @@ def plot_kkrimp_calc(self, node, return_rms=False, return_stot=False, plot_rms=T
else:
ptitle = f'pk= {node.pk}'

self.make_kkrimp_rmsplot([rms], [stot], [0], rms_goal, ptitle, **kwargs)
self.make_kkrimp_rmsplot([rms], [stot], [node], rms_goal, ptitle, **kwargs)

# now return values
return_any, return_list = False, []
Expand All @@ -1074,10 +1130,14 @@ def plot_kkrimp_sub_wc(self, node, **kwargs):
"""plot things from a kkrimp_sub_wc workflow"""
from aiida_kkr.calculations import KkrimpCalculation

if self.debug:
print('in plot_kkrimp_sub_wc')
print('kwargs:', kwargs)

impcalcs = [i.node for i in node.get_outgoing(node_class=KkrimpCalculation).all()]

# plot impurity cluster
if len(impcalcs) > 0 and kwargs.get('strucplot', True):
if len(impcalcs) > 0 and kwargs.get('strucplot', False):
if _has_ase_notebook():
self.sview = plot_imp_cluster(impcalcs[0], **kwargs)
else:
Expand All @@ -1088,10 +1148,9 @@ def plot_kkrimp_sub_wc(self, node, **kwargs):
kwargs.pop(k)

# extract rms from calculations
rms_all, pks_all, stot_all = [], [], []
rms_all, stot_all = [], []
rms_goal = None
for impcalc in impcalcs:
pks_all.append(impcalc.pk)
rms_tmp, rms_goal_tmp, stot_tmp = self.plot_kkrimp_calc(
impcalc, return_rms=True, return_stot=True, plot_rms=False
)
Expand All @@ -1108,9 +1167,9 @@ def plot_kkrimp_sub_wc(self, node, **kwargs):
else:
ptitle = f'pk= {node.pk}'

self.make_kkrimp_rmsplot(rms_all, stot_all, pks_all, rms_goal, ptitle, **kwargs)
self.make_kkrimp_rmsplot(rms_all, stot_all, impcalcs, rms_goal, ptitle, **kwargs)

def make_kkrimp_rmsplot(self, rms_all, stot_all, pks_all, rms_goal, ptitle, **kwargs):
def make_kkrimp_rmsplot(self, rms_all, stot_all, list_of_impcalcs, rms_goal, ptitle, **kwargs):
"""
plot rms and total spin moment of kkrimp calculation or series of kkrimp calculations
"""
Expand Down Expand Up @@ -1141,7 +1200,7 @@ def make_kkrimp_rmsplot(self, rms_all, stot_all, pks_all, rms_goal, ptitle, **kw
# plotting of convergence properties (rms etc.)
if len(rms_all) > 0:
# sort rms values and flatten array
reorder_rms = array(pks_all).argsort()[::-1]
reorder_rms = get_sorting_indices(list_of_impcalcs)
rms, niter_calcs, stot = [], [0], []
rms_all_sorted = [rms_all[i] for i in reorder_rms]
for i in rms_all_sorted:
Expand Down Expand Up @@ -1192,6 +1251,10 @@ def plot_kkrimp_dos_wc(self, node, **kwargs):
from masci_tools.vis.kkr_plot_dos import dosplot
from matplotlib.pyplot import show, figure, title, xticks, xlabel, axvline

if self.debug:
print('in plot_kkrimp_dos_wc')
print('kwargs:', kwargs)

interpol, all_atoms, l_channels, sum_spins, switch_xy = True, False, True, False, False
ptitle = None
if 'ptitle' in list(kwargs.keys()):
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions tests/tools/test_find_parent.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ def test_find_parent_structure():
assert voro_parent.uuid == '559b9d9b-3525-402e-9b24-ecd8b801853c'


def test_find_structure_kkrimp():
"""
find parent structure from a KkrimpCalculation
"""
import_with_migration('files/db_dump_kkrimp_out.tar.gz')
kkrimp_calc = load_node('eab8db1b-2cc7-4b85-a524-0df4ff2b7da6')

# now find voronoi parent and structure
struc, voro_parent = find_parent_structure(kkrimp_calc)

# check result
assert struc.uuid == 'e51ee6a1-bd27-4901-9612-7bac256bf117'
assert voro_parent.uuid == '559b9d9b-3525-402e-9b24-ecd8b801853c'


def test_get_calc_from_remote():
"""
find parent calc from remote
Expand Down

0 comments on commit 9bddcd5

Please sign in to comment.