Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
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)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
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))