def create_aiida_dos_data(retrieved): """ Creates :py:class:`aiida.orm.XyData` object containing the standard DOS components from the `banddos.hdf` file of the calculation :param retrieved: :py:class:`aiida.orm.FolderData` for the DOS calculation :returns: :py:class:`aiida.orm.XyData` containing all standard DOS components :raises: ExitCode 300, banddos.hdf file is missing :raises: ExitCode 310, banddos.hdf reading failed """ from masci_tools.io.parsers.hdf5 import HDF5Reader, HDF5TransformationError from masci_tools.io.parsers.hdf5.recipes import FleurDOS #only standard DOS for now from aiida.engine import ExitCode if 'banddos.hdf' in retrieved.list_object_names(): try: with retrieved.open('banddos.hdf', 'rb') as f: with HDF5Reader(f) as reader: data, attributes = reader.read(recipe=FleurDOS) except (HDF5TransformationError, ValueError) as exc: return ExitCode(310, message=f'banddos.hdf reading failed with: {exc}') else: return ExitCode(300, message='banddos.hdf file not in the retrieved files') dos = XyData() dos.set_x(data['energy_grid'], 'energy', x_units='eV') names = [key for key in data if key != 'energy_grid'] arrays = [entry for key, entry in data.items() if key != 'energy_grid'] units = ['1/eV'] * len(names) dos.set_y(arrays, names, y_units=units) dos.label = 'output_banddos_wc_dos' dos.description = ( 'Contains XyData for the density of states calculation with total, interstitial, atom and orbital weights' ) return dos
def parse_cummulants(self, **kwargs): """Parser for the cummulants file """ import pandas as pd # Check if the file is present try: self.retrieved except NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER cummu_filename = self.node.get_option('cummu_filename') files_retrieved = self.retrieved.list_object_names() files_expected = [cummu_filename] if not set(files_expected) <= set(files_retrieved): self.logger.error("Found files '{}', expected to find '{}'".format( files_retrieved, files_expected)) return self.exit_codes.ERROR_MISSING_OUTPUT_FILES self.logger.info("Parsing '{}'".format(cummu_filename)) try: cummu = pd.read_csv(cummu_filename, delim_whitespace=True) except OSError: return self.exit_codes.ERROR_READING_OUTPUT_FILE _t_units = "iterations" if cummu.columns.values[0] == "Time": _t_units = "seconds" _cummu_units = [ r"\mu_B", r"\mu_B^2", r"\mu_B^4", " ", " ", " ", "mRy", "mRy", "mRy" ] cummu_data = XyData() cummu_data.set_x(cummu.iloc[:, 0], cummu.columns.values[0], _t_units) cummu_data.set_y(cummu.iloc[:, 1:], cummu.columns.values[1:], _cummu_units) cummu_dict = dict() for col_name in cummu.columns.values[1:]: cummu_dict[col_name] = cummu[col_name].values[-1] self.out("cummulants_final", Dict(dict=cummu_dict)) self.out("cummulants", cummu_data) return ExitCode(0)
def parse_averages(self, **kwargs): """Parser for the average magnetization file """ import pandas as pd # Check if the file is present try: self.retrieved except NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER averages_filename = self.node.get_option('averages_filename') files_retrieved = self.retrieved.list_object_names() files_expected = [averages_filename] # Check if the averages file is in the list of retrieved files # Note: set(A) <= set(B) checks whether A is a subset of B if not set(files_expected) <= set(files_retrieved): self.logger.error("Found files '{}', expected to find '{}'".format( files_retrieved, files_expected)) return self.exit_codes.ERROR_MISSING_OUTPUT_FILES # add the averages file to the node self.logger.info("Parsing '{}'".format(averages_filename)) try: m_ave = pd.read_csv(averages_filename, delim_whitespace=True) except OSError: return self.exit_codes.ERROR_READING_OUTPUT_FILE _t_units = "iterations" if m_ave.columns.values[0] == "Time[s]": _t_units = "seconds" _m_units = r"\mu_B" * (len(m_ave.columns) - 1) ave_data = XyData() ave_data.set_x(m_ave.iloc[:, 0], m_ave.columns.values[0], _t_units) ave_data.set_y(m_ave.iloc[:, 1:], m_ave.columns.values[1:], _m_units) m_ave_dict = dict() for col_name in m_ave.columns.values[1:]: m_ave_dict[col_name] = m_ave[col_name].values[-1] self.out("final_averages", Dict(dict=m_ave_dict)) self.out("averages", ave_data) return ExitCode(0)
def parse_energies(self, **kwargs): """Parser for the total energy file """ import pandas as pd # Check if the file is present try: self.retrieved except NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER energies_filename = self.node.get_option('totenergy_filename') files_retrieved = self.retrieved.list_object_names() files_expected = [energies_filename] if not set(files_expected) <= set(files_retrieved): self.logger.error("Found files '{}', expected to find '{}'".format( files_retrieved, files_expected)) return self.exit_codes.ERROR_MISSING_OUTPUT_FILES self.logger.info("Parsing '{}'".format(energies_filename)) try: ene = pd.read_csv(energies_filename, delim_whitespace=True) except OSError: return self.exit_codes.ERROR_READING_OUTPUT_FILE _t_units = "iterations" if ene.columns.values[0] == "Time": _t_units = "seconds" _ene_units = "mRy" * (len(ene.columns) - 1) ene_data = XyData() ene_data.set_x(ene.iloc[:, 0], ene.columns.values[0], _t_units) ene_data.set_y(ene.iloc[:, 1:], ene.columns.values[1:], _ene_units) ene_dict = dict() for col_name in ene.columns.values[1:]: ene_dict[col_name] = ene[col_name].values[-1] self.out("final_energies", Dict(dict=ene_dict)) self.out("energies", ene_data) return ExitCode(0)
def parse(self, **kwargs): """Parses the datafolder, stores results. 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) # 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: out_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) job_done = False for i in range(len(out_file)): line = out_file[-i] if 'JOB DONE' in line: job_done = True break if not job_done: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_INCOMPLETE) # Parse basic info and warnings, and output them as output_parmeters parsed_data, logs = parse_output_base(out_file, 'PROJWFC') self.emit_logs(logs) self.out('output_parameters', Dict(dict=parsed_data)) # check and read pdos_tot file out_filenames = out_folder.list_object_names() try: pdostot_filename = fnmatch.filter(out_filenames, '*pdos_tot*')[0] with out_folder.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] dos = pdostot_array[:, 1] except (OSError, KeyError): return self.exit(self.exit_codes.ERROR_READING_PDOSTOT_FILE) # check and read all of the individual pdos_atm files 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: pdos_atm_array_dict[name] = np.atleast_2d( np.genfromtxt(pdosatm_file)) # finding the bands and projections # we create a dictionary the progressively accumulates more info out_info_dict = {} out_info_dict['out_file'] = out_file out_info_dict['energy'] = energy out_info_dict['pdos_atm_array_dict'] = pdos_atm_array_dict try: new_nodes_list = self._parse_bands_and_projections(out_info_dict) except QEOutputParsingError as err: self.logger.error( 'Error parsing bands and projections: {}'.format(err)) return self.exit(self.exit_codes.ERROR_PARSING_PROJECTIONS) for linkname, node in new_nodes_list: self.out(linkname, node) Dos_out = XyData() Dos_out.set_x(energy, 'Energy', 'eV') Dos_out.set_y(dos, 'Dos', 'states/eV') self.out('Dos', Dos_out)
def parse_averages_proj(self, **kwargs): """Parse the projected type magnetic averages file """ import pandas as pd # Check if the file is present try: self.retrieved except NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER ave_proj_type_filename = self.node.get_option('ave_proj_type_filename') files_retrieved = self.retrieved.list_object_names() files_expected = [ave_proj_type_filename] if not set(files_expected) <= set(files_retrieved): self.logger.error("Found files '{}', expected to find '{}'".format( files_retrieved, files_expected)) return self.exit_codes.ERROR_MISSING_OUTPUT_FILES self.logger.info("Parsing '{}'".format(ave_proj_type_filename)) try: ave_proj_type = pd.read_csv(ave_proj_type_filename, delim_whitespace=True) except OSError: return self.exit_codes.ERROR_READING_OUTPUT_FILE ave_proj_type_dict = dict() num_types = ave_proj_type['Proj'].max() for col_name in ave_proj_type.columns.values[1:]: ave_proj_type_dict[col_name] = dict() for ii in range(1, num_types + 1): ave_proj_type_dict[col_name][ii] =\ ave_proj_type[col_name].values[-ii] _t_units = "iterations" if ave_proj_type.columns.values[0] == "Time[s]": _t_units = "seconds" _mom_units = r"\mu_B" * (len(ave_proj_type.columns) - 2) ave_proj_type_data = [None] * num_types for ii in range(1, num_types + 1): ave_proj_type_data[ii - 1] = XyData() ave_proj_type_data[ii - 1].\ set_x(ave_proj_type.iloc[:,0], ave_proj_type.columns.values[0], _t_units) ave_proj_type_data[ii - 1].\ set_y(ave_proj_type.iloc[:,2:][ave_proj_type.iloc[1] == ii], ave_proj_type.columns.values[2:], _mom_units) self.out("projected averages " + str(ii), ave_proj_type_data[ii - 1]) self.out("final projected averages", Dict(dict=ave_proj_type_dict)) return ExitCode(0)
def parse(self, **kwargs): """Parses the datafolder, stores results. 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) # 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: out_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_READ) job_done = False for i in range(len(out_file)): line = out_file[-i] if 'JOB DONE' in line: job_done = True break if not job_done: return self.exit(self.exit_codes.ERROR_OUTPUT_STDOUT_INCOMPLETE) # 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: dos_file = fil.readlines() except OSError: return self.exit(self.exit_codes.ERROR_READING_DOS_FILE) # end of initial checks array_names = [[], []] array_units = [[], []] array_names[0] = ['dos_energy', 'dos', 'integrated_dos'] # When spin is not displayed array_names[1] = [ 'dos_energy', 'dos_spin_up', 'dos_spin_down', 'integrated_dos' ] # When spin is displayed array_units[0] = ['eV', 'states/eV', 'states'] # When spin is not displayed array_units[1] = ['eV', 'states/eV', 'states/eV', 'states'] # When spin is displayed # grabs parsed data from aiida.dos # TODO: should I catch any QEOutputParsingError from parse_raw_dos, # log an error and return an exit code? array_data, spin = parse_raw_dos(dos_file, array_names, array_units) energy_units = 'eV' dos_units = 'states/eV' int_dos_units = 'states' xy_data = XyData() xy_data.set_x(array_data['dos_energy'], 'dos_energy', energy_units) y_arrays = [] y_names = [] y_units = [] y_arrays += [array_data['integrated_dos']] y_names += ['integrated_dos'] y_units += ['states'] if spin: y_arrays += [array_data['dos_spin_up']] y_arrays += [array_data['dos_spin_down']] y_names += ['dos_spin_up'] y_names += ['dos_spin_down'] y_units += ['states/eV'] * 2 else: y_arrays += [array_data['dos']] y_names += ['dos'] y_units += ['states/eV'] xy_data.set_y(y_arrays, y_names, y_units) parsed_data, logs = parse_output_base(out_file, 'DOS') self.emit_logs(logs) self.out('output_dos', xy_data) self.out('output_parameters', Dict(dict=parsed_data))