From 6145d52034bac5a189608c0912ad76ada49bec9a Mon Sep 17 00:00:00 2001
From: Philipp Ruessmann
Date: Wed, 1 Dec 2021 10:12:23 +0000
Subject: [PATCH 1/2] Remove parsed files from retrieved folder that have a
dedicated output node
This uses the retrieve_temporary list and the corresponding changes to the parser
---
aiida_spirit/calculations.py | 13 ++++--
aiida_spirit/parsers.py | 86 ++++++++++++++++++++++++------------
2 files changed, 67 insertions(+), 32 deletions(-)
diff --git a/aiida_spirit/calculations.py b/aiida_spirit/calculations.py
index 6fe6d3d..8f0a49e 100644
--- a/aiida_spirit/calculations.py
+++ b/aiida_spirit/calculations.py
@@ -184,7 +184,11 @@ def prepare_for_submission(self, folder):
# this should be a list of the filenames we expect when spirit ran
# i.e. the files we specify here will be copied back to the file repository
+ # note that the retlist_tmp contains only files which are only needed in parsing
+ # but are then not kept in the file repository (e.g. magnetization arrays which are
+ # stored as numy arrays instead of also keeping the raw text files)
retlist = _RETLIST.copy()
+ retlist_tmp = []
if 'pinning' in self.inputs:
# also retreive the pinning file
retlist += ['pinning.txt']
@@ -194,17 +198,18 @@ def prepare_for_submission(self, folder):
run_opts = self.inputs.run_options.get_dict()
if run_opts['simulation_method'].upper() == 'LLG':
- retlist += ['spirit_Image-00_Energy-archive.txt',
- 'spirit_Image-00_Spins-final.ovf',
- 'spirit_Image-00_Spins-initial.ovf']
+ retlist_tmp += ['spirit_Image-00_Energy-archive.txt',
+ 'spirit_Image-00_Spins-final.ovf',
+ 'spirit_Image-00_Spins-initial.ovf']
elif run_opts['simulation_method'].upper() == 'MC':
- retlist += ['output_mc.txt']
+ retlist_tmp += ['output_mc.txt']
# from the input we can specify additional files that should be retrieved
if 'add_to_retrieved' in self.inputs:
retlist += self.inputs.add_to_retrieved.get_list()
calcinfo.retrieve_list = retlist
+ calcinfo.retrieve_temporary_list = retlist_tmp
return calcinfo
diff --git a/aiida_spirit/parsers.py b/aiida_spirit/parsers.py
index abff620..165542e 100644
--- a/aiida_spirit/parsers.py
+++ b/aiida_spirit/parsers.py
@@ -4,6 +4,7 @@
Register parsers via the "aiida.parsers" entry point in setup.json.
"""
+import pathlib
import numpy as np
from aiida.engine import ExitCode
from aiida.parsers.parser import Parser
@@ -54,6 +55,14 @@ def parse(self, **kwargs):
# parse information from output file (number of iterations, convergence info, ...)
retrieved_dict = self.parse_retrieved()
+ # parse files in temporary folder
+ # these files are not kept in the file repository but become numy arrays and are stored as ArrayData output nodes
+ retrieved_temporary_folder = kwargs.get('retrieved_temporary_folder',
+ None)
+ if retrieved_temporary_folder is not None:
+ retrieved_dict = self.parse_temporary_retrieved(
+ retrieved_dict, retrieved_temporary_folder)
+
for key, value in retrieved_dict.items():
self.out(key, value)
@@ -70,17 +79,27 @@ def parse(self, **kwargs):
return ExitCode(0)
- def _retrieve_if_found(self, filename, *args, **kwargs):
- """Retrieves a file and loads it with `np.loadtxt`.
+ def _parse_if_found(self, filename, *args, folder=None, **kwargs):
+ """Parses a file and loads it with `np.loadtxt`.
The `*args` and `**kwargs` are passed to `np.loadtxt`.
If the file is not found it returns None."""
- retrieved = self.retrieved
- if filename in retrieved.list_object_names():
- with retrieved.open(filename, 'r') as _f:
- return np.loadtxt(_f, *args, **kwargs)
+ if folder is None:
+ folder = self.retrieved
+ if filename in folder.list_object_names():
+ with folder.open(filename, 'r') as _f:
+ return np.loadtxt(_f, *args, **kwargs)
+ else:
+ return self._file_not_found(filename)
else:
- self.logger.info('{} not found!'.format(filename))
- return None
+ filenames = [f.name for f in folder.glob('*')]
+ if filename in filenames:
+ with (folder / filename).open('r') as _f:
+ return np.loadtxt(_f, *args, **kwargs)
+ else:
+ return self._file_not_found(filename)
+
+ def _file_not_found(self, filename):
+ self.logger.info('{} not found!'.format(filename))
def parse_retrieved(self): # pylint: disable=too-many-locals
"""Parse the output from the retrieved and create aiida nodes"""
@@ -96,26 +115,45 @@ def parse_retrieved(self): # pylint: disable=too-many-locals
output_node = Dict(dict=out_dict)
# parse output files
+ self.logger.info('Parsing atom types')
+ atyp = self._parse_if_found(_ATOM_TYPES)
+
+ # Write dictionary of retrieved quantities
+ _retrieved_dict = {'output_parameters': output_node}
+
+ # collect arrays in ArrayData
+ if atyp is not None:
+ atypes = ArrayData()
+ atypes.set_array('atom_types', atyp)
+ atypes.extras['description'] = {
+ 'atom_types': 'list of atom types for all positions',
+ }
+ _retrieved_dict.update({'atom_types': atypes})
+
+ return _retrieved_dict
+
+ def parse_temporary_retrieved(self, _retrieved_dict,
+ retrieved_temporary_folder):
+ """Parse files that are defined in the retrieve_temporary_list"""
+ retrieved_temporary_folder = pathlib.Path(retrieved_temporary_folder)
+
self.logger.info('Parsing energy archive')
- energ = self._retrieve_if_found('spirit_Image-00_Energy-archive.txt',
- skiprows=1)
+ energ = self._parse_if_found('spirit_Image-00_Energy-archive.txt',
+ folder=retrieved_temporary_folder,
+ skiprows=1)
self.logger.info('Parsing initial magnetization')
- m_init = self._retrieve_if_found('spirit_Image-00_Spins-initial.ovf')
+ m_init = self._parse_if_found('spirit_Image-00_Spins-initial.ovf',
+ folder=retrieved_temporary_folder)
self.logger.info('Parsing final magnetization')
- m_final = self._retrieve_if_found('spirit_Image-00_Spins-final.ovf')
-
- self.logger.info('Parsing atom types')
- atyp = self._retrieve_if_found(_ATOM_TYPES)
+ m_final = self._parse_if_found('spirit_Image-00_Spins-final.ovf',
+ folder=retrieved_temporary_folder)
self.logger.info('Parsing MC output')
- out_mc = self._retrieve_if_found('output_mc.txt')
+ out_mc = self._parse_if_found('output_mc.txt',
+ folder=retrieved_temporary_folder)
- # Write dictionary of retrieved quantities
- _retrieved_dict = {'output_parameters': output_node}
-
- # collect arrays in ArrayData
if m_init is not None and m_final is not None:
mag = ArrayData()
mag.set_array(
@@ -136,14 +174,6 @@ def parse_retrieved(self): # pylint: disable=too-many-locals
}
_retrieved_dict.update({'energies': energies})
- if atyp is not None:
- atypes = ArrayData()
- atypes.set_array('atom_types', atyp)
- atypes.extras['description'] = {
- 'atom_types': 'list of atom types for all positions',
- }
- _retrieved_dict.update({'atom_types': atypes})
-
# Only add mc if it is found
if out_mc is not None:
output_mc = ArrayData()
From c992fb42bf33d0d026671c7df23e02ff15f41f32 Mon Sep 17 00:00:00 2001
From: Philipp Ruessmann
Date: Wed, 1 Dec 2021 10:17:18 +0000
Subject: [PATCH 2/2] Bumb version number to v0.2.0
---
aiida_spirit/__init__.py | 2 +-
setup.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/aiida_spirit/__init__.py b/aiida_spirit/__init__.py
index e065f3c..d8bee6a 100644
--- a/aiida_spirit/__init__.py
+++ b/aiida_spirit/__init__.py
@@ -5,4 +5,4 @@
AiiDA plugin for the spirit code
"""
-__version__ = '0.1.0'
+__version__ = '0.2.0'
diff --git a/setup.json b/setup.json
index e05a024..455d33c 100644
--- a/setup.json
+++ b/setup.json
@@ -12,7 +12,7 @@
"Natural Language :: English",
"Framework :: AiiDA"
],
- "version": "0.1.0",
+ "version": "0.2.0",
"entry_points": {
"aiida.calculations": [
"spirit = aiida_spirit.calculations:SpiritCalculation"