From 0165ef48acc29f223b45722989e8bb2e521b9b1d Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Fri, 9 Oct 2020 19:08:23 +0200 Subject: [PATCH] `Parsers`: remove explicit check for the retrieved folder's existence As of `aiida-core==1.4.0`, the engine itself will check for the presence of the retrieved folder. If it is missing, which is really just a bug in `aiida-core` the engine will terminate the process and not call the parser. Anyway there would be no point since there is nothing to parse. This means that now if the parser is called, it is guaranteed that the retrieve folder exists and so we no longer have to explicitly check for it. Since this is only valid from `aiida-core>=1.4` we update the dependency requirement. We also require `aiida-core>=1.4.2` because `1.4.0` and `1.4.1` contain a bug where the content of files in `local_copy_list` are copied to the repository even though they shouldn't. For this plugin this means that mostly the content of the pseudo potentials are duplicated everytime in the repository, which will bloat the repository unnecessarily. --- aiida_quantumespresso/calculations/cp.py | 2 -- aiida_quantumespresso/calculations/dos.py | 2 -- aiida_quantumespresso/calculations/matdyn.py | 2 -- aiida_quantumespresso/calculations/neb.py | 2 -- aiida_quantumespresso/calculations/ph.py | 2 -- aiida_quantumespresso/calculations/pp.py | 2 -- aiida_quantumespresso/calculations/projwfc.py | 2 -- aiida_quantumespresso/calculations/pw.py | 2 -- aiida_quantumespresso/calculations/pw2gw.py | 2 -- .../calculations/pw2wannier90.py | 2 -- aiida_quantumespresso/calculations/q2r.py | 2 -- aiida_quantumespresso/parsers/cp.py | 22 ++++++++----------- aiida_quantumespresso/parsers/dos.py | 10 +++------ aiida_quantumespresso/parsers/matdyn.py | 15 +++++-------- aiida_quantumespresso/parsers/neb.py | 19 ++++++---------- aiida_quantumespresso/parsers/ph.py | 16 +++++--------- aiida_quantumespresso/parsers/pp.py | 14 +++++------- aiida_quantumespresso/parsers/projwfc.py | 16 +++++--------- aiida_quantumespresso/parsers/pw.py | 5 ----- aiida_quantumespresso/parsers/pw2gw.py | 11 +++------- aiida_quantumespresso/parsers/pw2wannier90.py | 8 +------ aiida_quantumespresso/parsers/q2r.py | 16 +++++--------- setup.json | 2 +- 23 files changed, 51 insertions(+), 125 deletions(-) diff --git a/aiida_quantumespresso/calculations/cp.py b/aiida_quantumespresso/calculations/cp.py index 18ef5acfb..598322749 100644 --- a/aiida_quantumespresso/calculations/cp.py +++ b/aiida_quantumespresso/calculations/cp.py @@ -132,8 +132,6 @@ def define(cls, spec): spec.output('output_parameters', valid_type=orm.Dict) spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(301, 'ERROR_NO_RETRIEVED_TEMPORARY_FOLDER', message='The retrieved temporary folder could not be accessed.') spec.exit_code(303, 'ERROR_MISSING_XML_FILE', diff --git a/aiida_quantumespresso/calculations/dos.py b/aiida_quantumespresso/calculations/dos.py index 4ae2ce4df..339a76e33 100644 --- a/aiida_quantumespresso/calculations/dos.py +++ b/aiida_quantumespresso/calculations/dos.py @@ -26,8 +26,6 @@ def define(cls, spec): spec.output('output_parameters', valid_type=orm.Dict) spec.output('output_dos', valid_type=orm.XyData) spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', message='The stdout output file could not be read.') spec.exit_code(312, 'ERROR_OUTPUT_STDOUT_INCOMPLETE', diff --git a/aiida_quantumespresso/calculations/matdyn.py b/aiida_quantumespresso/calculations/matdyn.py index 22b3bb3da..1849d0db8 100644 --- a/aiida_quantumespresso/calculations/matdyn.py +++ b/aiida_quantumespresso/calculations/matdyn.py @@ -34,8 +34,6 @@ def define(cls, spec): spec.output('output_parameters', valid_type=orm.Dict) spec.output('output_phonon_bands', valid_type=orm.BandsData) spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', message='The stdout output file could not be read.') spec.exit_code(312, 'ERROR_OUTPUT_STDOUT_INCOMPLETE', diff --git a/aiida_quantumespresso/calculations/neb.py b/aiida_quantumespresso/calculations/neb.py index 471391ce7..f4c1c705e 100644 --- a/aiida_quantumespresso/calculations/neb.py +++ b/aiida_quantumespresso/calculations/neb.py @@ -76,8 +76,6 @@ def define(cls, spec): spec.output('output_mep', valid_type=orm.ArrayData, help='The original and interpolated energy profiles along the minimum-energy path (mep)') spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(303, 'ERROR_MISSING_XML_FILE', message='The required XML file is not present in the retrieved folder.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', diff --git a/aiida_quantumespresso/calculations/ph.py b/aiida_quantumespresso/calculations/ph.py index 986702695..50f32987e 100644 --- a/aiida_quantumespresso/calculations/ph.py +++ b/aiida_quantumespresso/calculations/ph.py @@ -59,8 +59,6 @@ def define(cls, spec): spec.default_output_node = 'output_parameters' # Unrecoverable errors: required retrieved files could not be read, parsed or are otherwise incomplete - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(302, 'ERROR_OUTPUT_STDOUT_MISSING', message='The retrieved folder did not contain the required stdout output file.') spec.exit_code(305, 'ERROR_OUTPUT_FILES', diff --git a/aiida_quantumespresso/calculations/pp.py b/aiida_quantumespresso/calculations/pp.py index bff542f8e..6bca201de 100644 --- a/aiida_quantumespresso/calculations/pp.py +++ b/aiida_quantumespresso/calculations/pp.py @@ -89,8 +89,6 @@ def define(cls, spec): spec.default_output_node = 'output_parameters' # Standard exceptions - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(301, 'ERROR_NO_RETRIEVED_TEMPORARY_FOLDER', message='The retrieved temporary folder could not be accessed.') spec.exit_code(302, 'ERROR_OUTPUT_STDOUT_MISSING', diff --git a/aiida_quantumespresso/calculations/projwfc.py b/aiida_quantumespresso/calculations/projwfc.py index 7a85ef884..440387236 100644 --- a/aiida_quantumespresso/calculations/projwfc.py +++ b/aiida_quantumespresso/calculations/projwfc.py @@ -45,8 +45,6 @@ def define(cls, spec): spec.output('projections', valid_type=ProjectionData, required=False) spec.output('bands', valid_type=BandsData, required=False) spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', message='The stdout output file could not be read.') spec.exit_code(312, 'ERROR_OUTPUT_STDOUT_INCOMPLETE', diff --git a/aiida_quantumespresso/calculations/pw.py b/aiida_quantumespresso/calculations/pw.py index d8e197e7f..1bfe93dfe 100644 --- a/aiida_quantumespresso/calculations/pw.py +++ b/aiida_quantumespresso/calculations/pw.py @@ -79,8 +79,6 @@ def define(cls, spec): spec.default_output_node = 'output_parameters' # Unrecoverable errors: required retrieved files could not be read, parsed or are otherwise incomplete - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(301, 'ERROR_NO_RETRIEVED_TEMPORARY_FOLDER', message='The retrieved temporary folder could not be accessed.') spec.exit_code(302, 'ERROR_OUTPUT_STDOUT_MISSING', diff --git a/aiida_quantumespresso/calculations/pw2gw.py b/aiida_quantumespresso/calculations/pw2gw.py index 49d4cd3b4..ad62ef575 100644 --- a/aiida_quantumespresso/calculations/pw2gw.py +++ b/aiida_quantumespresso/calculations/pw2gw.py @@ -37,8 +37,6 @@ def define(cls, spec): spec.output('eps', valid_type=orm.ArrayData, help='The `eps` output node containing 5 arrays `energy`, `epsX`, `epsY`, `epsZ`, `epsTOT`') - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(302, 'ERROR_OUTPUT_STDOUT_MISSING', message='The retrieved folder did not contain the required stdout output file.') spec.exit_code(305, 'ERROR_OUTPUT_FILES', diff --git a/aiida_quantumespresso/calculations/pw2wannier90.py b/aiida_quantumespresso/calculations/pw2wannier90.py index 96a336be5..32ac3f60d 100644 --- a/aiida_quantumespresso/calculations/pw2wannier90.py +++ b/aiida_quantumespresso/calculations/pw2wannier90.py @@ -31,8 +31,6 @@ def define(cls, spec): help='The output folder of a pw.x calculation') spec.output('output_parameters', valid_type=Dict) spec.default_output_node = 'output_parameters' - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', message='The stdout output file could not be read.') spec.exit_code(312, 'ERROR_OUTPUT_STDOUT_INCOMPLETE', diff --git a/aiida_quantumespresso/calculations/q2r.py b/aiida_quantumespresso/calculations/q2r.py index 4a4f57be3..b4d5d9de3 100644 --- a/aiida_quantumespresso/calculations/q2r.py +++ b/aiida_quantumespresso/calculations/q2r.py @@ -31,8 +31,6 @@ def define(cls, spec): super().define(spec) spec.input('parent_folder', valid_type=(orm.RemoteData, orm.FolderData), required=True) spec.output('force_constants', valid_type=ForceConstantsData) - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(310, 'ERROR_OUTPUT_STDOUT_READ', message='The stdout output file could not be read.') spec.exit_code(312, 'ERROR_OUTPUT_STDOUT_INCOMPLETE', diff --git a/aiida_quantumespresso/parsers/cp.py b/aiida_quantumespresso/parsers/cp.py index ebd059344..bd9cb0bb8 100644 --- a/aiida_quantumespresso/parsers/cp.py +++ b/aiida_quantumespresso/parsers/cp.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- from distutils.version import LooseVersion - import numpy -from aiida.common import NotExistent -from aiida.orm import Dict, TrajectoryData +from aiida.orm import Dict, TrajectoryData from qe_tools import CONSTANTS + from aiida_quantumespresso.parsers.parse_raw.cp import parse_cp_raw_output, parse_cp_traj_stanzas from .base import Parser @@ -18,13 +17,10 @@ def parse(self, **kwargs): Does all the logic here. """ - try: - out_folder = self.retrieved - except NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) + retrieved = self.retrieved # check what is inside the folder - list_of_files = out_folder._repository.list_object_names() + list_of_files = retrieved._repository.list_object_names() # options.metadata become attributes like this: stdout_filename = self.node.get_attribute('output_filename') @@ -44,9 +40,9 @@ def parse(self, **kwargs): # TODO: Add an error for this counter return self.exit(self.exit_codes.ERROR_MISSING_XML_FILE) - output_stdout = out_folder.get_object_content(stdout_filename) - output_xml = out_folder.get_object_content(xml_files[0]) - output_xml_counter = out_folder.get_object_content(self.node.process_class._FILE_XML_PRINT_COUNTER_BASENAME) + output_stdout = retrieved.get_object_content(stdout_filename) + output_xml = retrieved.get_object_content(xml_files[0]) + output_xml_counter = retrieved.get_object_content(self.node.process_class._FILE_XML_PRINT_COUNTER_BASENAME) out_dict, _raw_successful = parse_cp_raw_output(output_stdout, output_xml, output_xml_counter) # parse the trajectory. Units in Angstrom, picoseconds and eV. @@ -75,7 +71,7 @@ def parse(self, **kwargs): for name, extension, scale, elements in trajectories: try: - with out_folder.open(f'{self.node.process_class._PREFIX}.{extension}') as datafile: + with retrieved.open(f'{self.node.process_class._PREFIX}.{extension}') as datafile: data = [l.split() for l in datafile] # POSITIONS stored in angstrom traj_data = parse_cp_traj_stanzas( @@ -96,7 +92,7 @@ def parse(self, **kwargs): # =============== EVP trajectory ============================ try: - with out_folder.open(f'{self._node.process_class._PREFIX}.evp') as handle: + with retrieved.open(f'{self._node.process_class._PREFIX}.evp') as handle: matrix = numpy.genfromtxt(handle) # there might be a different format if the matrix has one row only try: diff --git a/aiida_quantumespresso/parsers/dos.py b/aiida_quantumespresso/parsers/dos.py index 754ea653a..5893a63d7 100644 --- a/aiida_quantumespresso/parsers/dos.py +++ b/aiida_quantumespresso/parsers/dos.py @@ -2,7 +2,6 @@ import numpy as np from aiida.orm import Dict, XyData -from aiida.common import NotExistent from aiida_quantumespresso.parsers import QEOutputParsingError from aiida_quantumespresso.parsers.parse_raw.base import parse_output_base @@ -17,15 +16,12 @@ def parse(self, **kwargs): Retrieves dos output, and some basic information from the out_file, such as warnings and wall_time """ - try: - out_folder = self.retrieved - except NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) + retrieved = self.retrieved # Read standard out try: filename_stdout = self.node.get_option('output_filename') # or get_attribute(), but this is clearer - with out_folder.open(filename_stdout, 'r') as fil: + with retrieved.open(filename_stdout, 'r') as fil: out_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) @@ -41,7 +37,7 @@ def parse(self, **kwargs): # check that the dos file is present, if it is, read it try: - with out_folder.open(self.node.process_class._DOS_FILENAME, 'r') as fil: + with retrieved.open(self.node.process_class._DOS_FILENAME, 'r') as fil: dos_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_READING_DOS_FILE) diff --git a/aiida_quantumespresso/parsers/matdyn.py b/aiida_quantumespresso/parsers/matdyn.py index 7a9132a8e..edd7e0d2b 100644 --- a/aiida_quantumespresso/parsers/matdyn.py +++ b/aiida_quantumespresso/parsers/matdyn.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- from aiida import orm -from aiida.common import exceptions from qe_tools import CONSTANTS from aiida_quantumespresso.calculations.matdyn import MatdynCalculation @@ -12,21 +11,17 @@ class MatdynParser(Parser): def parse(self, **kwargs): """Parse the retrieved files from a `MatdynCalculation`.""" - try: - output_folder = self.retrieved - except exceptions.NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) - + retrieved = self.retrieved filename_stdout = self.node.get_option('output_filename') filename_frequencies = MatdynCalculation._PHONON_FREQUENCIES_NAME - if filename_stdout not in output_folder.list_object_names(): + if filename_stdout not in retrieved.list_object_names(): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) - if 'JOB DONE' not in output_folder.get_object_content(filename_stdout): + if 'JOB DONE' not in retrieved.get_object_content(filename_stdout): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_INCOMPLETE) - if filename_frequencies not in output_folder.list_object_names(): + if filename_frequencies not in retrieved.list_object_names(): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) # Extract the kpoints from the input data and create the `KpointsData` for the `BandsData` @@ -38,7 +33,7 @@ def parse(self, **kwargs): kpoints_for_bands = orm.KpointsData() kpoints_for_bands.set_kpoints(kpoints) - parsed_data = parse_raw_matdyn_phonon_file(output_folder.get_object_content(filename_frequencies)) + parsed_data = parse_raw_matdyn_phonon_file(retrieved.get_object_content(filename_frequencies)) try: num_kpoints = parsed_data.pop('num_kpoints') diff --git a/aiida_quantumespresso/parsers/neb.py b/aiida_quantumespresso/parsers/neb.py index 3169eeb62..9a3b1876e 100644 --- a/aiida_quantumespresso/parsers/neb.py +++ b/aiida_quantumespresso/parsers/neb.py @@ -30,13 +30,8 @@ def parse(self, **kwargs): PREFIX = self.node.process_class._PREFIX - # Check that the retrieved folder is there - try: - out_folder = self.retrieved - except NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) - - list_of_files = out_folder.list_object_names() # Note: this includes folders, but not the files they contain. + retrieved = self.retrieved + list_of_files = retrieved.list_object_names() # Note: this includes folders, but not the files they contain. # The stdout is required for parsing filename_stdout = self.node.get_attribute('output_filename') @@ -62,7 +57,7 @@ def parse(self, **kwargs): # First parse the Neb output try: - stdout = out_folder.get_object_content(filename_stdout) + stdout = retrieved.get_object_content(filename_stdout) neb_out_dict, iteration_data, raw_successful = parse_raw_output_neb(stdout, neb_input_dict) # TODO: why do we ignore raw_successful ? except (OSError, QEOutputParsingError): @@ -99,7 +94,7 @@ def parse(self, **kwargs): if xml_filename in retrieved_files: xml_file_path = os.path.join(relative_output_folder, xml_filename) try: - with out_folder.open(xml_file_path) as xml_file: + with retrieved.open(xml_file_path) as xml_file: parsed_data_xml, logs_xml = parse_pw_xml(xml_file, None) except IOError: return self.exit(self.exit_codes.ERROR_OUTPUT_XML_READ) @@ -120,7 +115,7 @@ def parse(self, **kwargs): # look for pw output and parse it pw_out_file = os.path.join(f'{PREFIX}_{i + 1}', 'PW.out') try: - with out_folder.open(pw_out_file, 'r') as f: + with retrieved.open(pw_out_file, 'r') as f: pw_out_text = f.read() # Note: read() and not readlines() except IOError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) @@ -192,7 +187,7 @@ def parse(self, **kwargs): # Load the original and interpolated energy profile along the minimum-energy path (mep) try: filename = PREFIX + '.dat' - with out_folder.open(filename, 'r') as handle: + with retrieved.open(filename, 'r') as handle: mep = numpy.loadtxt(handle) except Exception: self.logger.warning(f'could not open expected output file `{filename}`.') @@ -200,7 +195,7 @@ def parse(self, **kwargs): try: filename = PREFIX + '.int' - with out_folder.open(filename, 'r') as handle: + with retrieved.open(filename, 'r') as handle: interp_mep = numpy.loadtxt(handle) except Exception: self.logger.warning(f'could not open expected output file `{filename}`.') diff --git a/aiida_quantumespresso/parsers/ph.py b/aiida_quantumespresso/parsers/ph.py index c3b1972e1..af2dc2b64 100644 --- a/aiida_quantumespresso/parsers/ph.py +++ b/aiida_quantumespresso/parsers/ph.py @@ -5,7 +5,6 @@ import traceback from aiida import orm -from aiida.common import exceptions from aiida_quantumespresso.calculations.ph import PhCalculation from aiida_quantumespresso.parsers.parse_raw.ph import parse_raw_ph_output as parse_stdout @@ -17,25 +16,22 @@ class PhParser(Parser): def parse(self, **kwargs): """Parse the retrieved files from a `PhCalculation`.""" - try: - self.retrieved - except exceptions.NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) + retrieved = self.retrieved # The stdout is required for parsing filename_stdout = self.node.get_attribute('output_filename') filename_tensor = PhCalculation._OUTPUT_XML_TENSOR_FILE_NAME - if filename_stdout not in self.retrieved.list_object_names(): + if filename_stdout not in retrieved.list_object_names(): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_MISSING) try: - stdout = self.retrieved.get_object_content(filename_stdout) + stdout = retrieved.get_object_content(filename_stdout) except (IOError, OSError): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) try: - tensor_file = self.retrieved.get_object_content(filename_tensor) + tensor_file = retrieved.get_object_content(filename_tensor) except (IOError, OSError): tensor_file = None @@ -45,11 +41,11 @@ def parse(self, **kwargs): dynmat_prefix = os.path.split(PhCalculation._OUTPUT_DYNAMICAL_MATRIX_PREFIX)[1] natural_sort = lambda string: [int(c) if c.isdigit() else c.lower() for c in re.split(r'(\d+)', string)] - for filename in sorted(self.retrieved.list_object_names(dynmat_folder), key=natural_sort): + for filename in sorted(retrieved.list_object_names(dynmat_folder), key=natural_sort): if not filename.startswith(dynmat_prefix) or filename.endswith('.freq'): continue - dynmat_files.append(self.retrieved.get_object_content(os.path.join(dynmat_folder, filename))) + dynmat_files.append(retrieved.get_object_content(os.path.join(dynmat_folder, filename))) try: parsed_data, logs = parse_stdout(stdout, tensor_file, dynmat_files) diff --git a/aiida_quantumespresso/parsers/pp.py b/aiida_quantumespresso/parsers/pp.py index a2dd0732c..227c5c68e 100644 --- a/aiida_quantumespresso/parsers/pp.py +++ b/aiida_quantumespresso/parsers/pp.py @@ -46,11 +46,7 @@ def parse(self, **kwargs): """ Parse raw files retrieved from remote dir """ - try: - self.retrieved - except exceptions.NotExistent: - return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER - + retrieved = self.retrieved retrieve_temporary_list = self.node.get_attribute('retrieve_temporary_list', None) filename_stdout = self.node.get_option('output_filename') @@ -62,11 +58,11 @@ def parse(self, **kwargs): return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_TEMPORARY_FOLDER) # The stdout is required for parsing - if filename_stdout not in self.retrieved.list_object_names(): + if filename_stdout not in retrieved.list_object_names(): return self.exit_codes.ERROR_OUTPUT_STDOUT_MISSING try: - stdout_raw = self.retrieved.get_object_content(filename_stdout) + stdout_raw = retrieved.get_object_content(filename_stdout) except (IOError, OSError): return self.exit_codes.ERROR_OUTPUT_STDOUT_READ @@ -89,8 +85,8 @@ def parse(self, **kwargs): filenames = os.listdir(retrieved_temporary_folder) file_opener = lambda filename: open(os.path.join(retrieved_temporary_folder, filename)) else: - filenames = self.retrieved.list_object_names() - file_opener = self.retrieved.open + filenames = retrieved.list_object_names() + file_opener = retrieved.open for filename in filenames: if filename.endswith(filename_suffix): diff --git a/aiida_quantumespresso/parsers/projwfc.py b/aiida_quantumespresso/parsers/projwfc.py index f473d430a..d06094cde 100644 --- a/aiida_quantumespresso/parsers/projwfc.py +++ b/aiida_quantumespresso/parsers/projwfc.py @@ -122,10 +122,9 @@ def spin_dependent_subparser(out_info_dict): :param out_info_dict: contains various technical internals useful in parsing :return: ProjectionData, BandsData parsed from out_file """ - out_file = out_info_dict['out_file'] spin_down = out_info_dict['spin_down'] - od = out_info_dict #using a shorter name for convenience + od = out_info_dict # using a shorter name for convenience # regular expressions needed for later parsing WaveFraction1_re = re.compile(r'\=(.*?)\*') # state composition 1 WaveFractionremain_re = re.compile(r'\+(.*?)\*') # state comp 2 @@ -286,15 +285,12 @@ def parse(self, **kwargs): Retrieves projwfc output, and some basic information from the out_file, such as warnings and wall_time """ # Check that the retrieved folder is there - try: - out_folder = self.retrieved - except NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) + retrieved = self.retrieved # Read standard out try: filename_stdout = self.node.get_option('output_filename') # or get_attribute(), but this is clearer - with out_folder.open(filename_stdout, 'r') as fil: + with retrieved.open(filename_stdout, 'r') as fil: out_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) @@ -314,10 +310,10 @@ def parse(self, **kwargs): self.out('output_parameters', Dict(dict=parsed_data)) # check and read pdos_tot file - out_filenames = out_folder.list_object_names() + out_filenames = retrieved.list_object_names() try: pdostot_filename = fnmatch.filter(out_filenames, '*pdos_tot*')[0] - with out_folder.open(pdostot_filename, 'r') as pdostot_file: + with retrieved.open(pdostot_filename, 'r') as pdostot_file: # Columns: Energy(eV), Ldos, Pdos pdostot_array = np.atleast_2d(np.genfromtxt(pdostot_file)) energy = pdostot_array[:, 0] @@ -329,7 +325,7 @@ def parse(self, **kwargs): pdos_atm_filenames = fnmatch.filter(out_filenames, '*pdos_atm*') pdos_atm_array_dict = {} for name in pdos_atm_filenames: - with out_folder.open(name, 'r') as pdosatm_file: + with retrieved.open(name, 'r') as pdosatm_file: pdos_atm_array_dict[name] = np.atleast_2d(np.genfromtxt(pdosatm_file)) # finding the bands and projections diff --git a/aiida_quantumespresso/parsers/pw.py b/aiida_quantumespresso/parsers/pw.py index c8ad2eb9f..019d207ec 100644 --- a/aiida_quantumespresso/parsers/pw.py +++ b/aiida_quantumespresso/parsers/pw.py @@ -27,11 +27,6 @@ def parse(self, **kwargs): self.exit_code_stdout = None self.exit_code_parser = None - try: - self.retrieved - except exceptions.NotExistent: - return self.exit(self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER)) - try: settings = self.node.inputs.settings.get_dict() except exceptions.NotExistent: diff --git a/aiida_quantumespresso/parsers/pw2gw.py b/aiida_quantumespresso/parsers/pw2gw.py index 4568dd0bb..4dc55005a 100644 --- a/aiida_quantumespresso/parsers/pw2gw.py +++ b/aiida_quantumespresso/parsers/pw2gw.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """`Parser` implementation for the `Pw2gwCalculation` calculation job class.""" +import io import numpy as np -from io import StringIO + from aiida import orm -from aiida.common import exceptions from aiida_quantumespresso.calculations.pw2gw import Pw2gwCalculation from .base import Parser @@ -22,11 +22,6 @@ def parse(self, **kwargs): self.exit_code_stdout = None self.exit_code_eps = None - try: - self.retrieved - except exceptions.NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) - # Parse the pw2gw stout file data, logs_stdout = self.parse_stdout() @@ -62,7 +57,7 @@ def parse_eps_files(self): base = name.split('.')[0] try: - data = np.loadtxt(StringIO(content)) + data = np.loadtxt(io.StringIO(content)) except ValueError: self.exit_code_eps = self.exit_codes.ERROR_OUTPUT_FILES return diff --git a/aiida_quantumespresso/parsers/pw2wannier90.py b/aiida_quantumespresso/parsers/pw2wannier90.py index ae8384b43..b4de0eee3 100644 --- a/aiida_quantumespresso/parsers/pw2wannier90.py +++ b/aiida_quantumespresso/parsers/pw2wannier90.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from aiida.common import NotExistent from aiida.orm import Dict from aiida_quantumespresso.parsers.parse_raw.base import parse_output_base @@ -15,14 +14,9 @@ def parse(self, **kwargs): Two nodes that are expected are the default 'retrieved' `FolderData` node which will store the retrieved files permanently in the repository. """ - try: - out_folder = self.retrieved - except NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) - try: filename_stdout = self.node.get_option('output_filename') # or get_attribute(), but this is clearer - with out_folder.open(filename_stdout, 'r') as fil: + with self.retrieved.open(filename_stdout, 'r') as fil: out_file = fil.read() except OSError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) diff --git a/aiida_quantumespresso/parsers/q2r.py b/aiida_quantumespresso/parsers/q2r.py index 6203368b6..1e483d2a5 100644 --- a/aiida_quantumespresso/parsers/q2r.py +++ b/aiida_quantumespresso/parsers/q2r.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from aiida.common import exceptions - from aiida_quantumespresso.calculations.q2r import Q2rCalculation from aiida_quantumespresso.data.force_constants import ForceConstantsData from .base import Parser @@ -11,24 +9,20 @@ class Q2rParser(Parser): def parse(self, **kwargs): """Parse the retrieved files from a `Q2rCalculation`.""" - try: - output_folder = self.retrieved - except exceptions.NotExistent: - return self.exit(self.exit_codes.ERROR_NO_RETRIEVED_FOLDER) - + retrieved = self.retrieved filename_stdout = self.node.get_option('output_filename') filename_force_constants = Q2rCalculation._FORCE_CONSTANTS_NAME - if filename_stdout not in output_folder.list_object_names(): + if filename_stdout not in retrieved.list_object_names(): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) - if filename_force_constants not in output_folder.list_object_names(): + if filename_force_constants not in retrieved.list_object_names(): return self.exit(self.exit_codes.ERROR_READING_FORCE_CONSTANTS_FILE) - if 'JOB DONE' not in output_folder.get_object_content(filename_stdout): + if 'JOB DONE' not in retrieved.get_object_content(filename_stdout): return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_INCOMPLETE) - with output_folder.open(filename_force_constants, 'rb') as handle: + with retrieved.open(filename_force_constants, 'rb') as handle: self.out('force_constants', ForceConstantsData(file=handle)) return diff --git a/setup.json b/setup.json index 4e1ab58d3..9aa86e49c 100644 --- a/setup.json +++ b/setup.json @@ -89,7 +89,7 @@ ] }, "install_requires": [ - "aiida_core[atomic_tools]~=1.3", + "aiida_core[atomic_tools]~=1.4,>=1.4.2", "packaging", "qe-tools~=2.0rc1", "xmlschema~=1.2",