예제 #1
0
    def parse_with_retrieved(self, retrieved):
        """
        Receives in input a dictionary of retrieved nodes.
        Does all the logic here. Checks presents of files.
        Calls routines to parse them and returns parameter nodes and sucess.

        :return successful: Bool, if overall parsing was successful or not
        :return new_nodes_list: list of tuples of two (linkname, Dataobject),
                                nodes to be stored by AiiDA

        """

        ####### init some variables ######

        successful = True

        has_xml_outfile = False
        has_dos_file = False
        has_bands_file = False
        has_new_xmlinp_file = False

        dos_file = None
        band_file = None
        new_nodes_list = []

        ######### Check presents of files ######

        # select the folder object
        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        self.logger.info("file list {}".format(list_of_files))

        # has output xml file, otherwise error
        if self._calc._OUTXML_FILE_NAME not in list_of_files:
            successful = False
            self.logger.error("XML out not found '{}'".format(
                self._calc._OUTXML_FILE_NAME))
        else:
            has_xml_outfile = True

        # check if all files expected are there for the calculation
        #print self._should_retrieve
        for filel in self._should_retrieve:
            if filel not in list_of_files:
                successful = False
                self.logger.warning(
                    "'{}' file not found in retrived folder, it"
                    " was probable not created by fleur".format(filel))

        # check if something was written to the error file
        if self._calc._ERROR_FILE_NAME in list_of_files:
            errorfile = os.path.join(out_folder.get_abs_path('.'),
                                     self._calc._ERROR_FILE_NAME)
            # read
            error_file_lines = ''
            try:
                with open(errorfile, 'r') as efile:
                    error_file_lines = efile.read(
                    )  # Note: read(), not readlines()
            except IOError:
                self.logger.error(
                    "Failed to open error file: {}.".format(errorfile))

            # if not empty, has_error equals True, parse error.
            if error_file_lines:
                self.logger.warning(
                    "The following was written into std error and piped to {} : \n {}"
                    "".format(self._calc._ERROR_FILE_NAME, error_file_lines))

                if 'OK' in error_file_lines:  # if judft-error # TODO maybe change.
                    successful = True
                else:
                    successful = False

        if successful == False:
            return successful, ()

        #what about other files?
        #check input dict

        if self._calc._DOS_FILE_NAME in list_of_files:
            has_dos = True
        if self._calc._BAND_FILE_NAME in list_of_files:
            has_bands = True

        #if a new inp.xml file was created (new stucture)
        if self._calc._NEW_XMlINP_FILE_NAME in list_of_files:
            self.logger.error("new inp.xml file found in retrieved folder")
            has_new_xmlinp_file = True
        # add files which should also be there in addition to default_files.

        ################################
        ####### Parse the files ########

        if has_xml_outfile:
            # get outfile path and call xml out parser
            outxmlfile = os.path.join(out_folder.get_abs_path('.'),
                                      self._calc._OUTXML_FILE_NAME)
            simpledata, complexdata, parser_info, success = parse_xmlout_file(
                outxmlfile)

            # Call routines for output node creation
            if simpledata:
                outputdata = dict(simpledata.items() + parser_info.items())
                outxml_params = ParameterData(dict=outputdata)
                link_name = self.get_linkname_outparams(
                )  # accessible via c.res
                new_nodes_list.append((link_name, outxml_params))

            if complexdata:
                parameter_data = dict(complexdata.items() +
                                      parser_info.items())
                outxml_params_complex = ParameterData(dict=parameter_data)
                link_name = self.get_linkname_outparams_complex()
                new_nodes_list.append((link_name, outxml_params_complex))

            #greate new fleurinpData object if needed

            #fleurinp_Data = FleurinpData(files= [inpxmlfile])
            #, symoutfile, enparafile])
            #self.logger.info('FleurinpData initialized')
            #self.logger.info
            #link_name_fleurinp = 'fleurinpData'

            # return it to the execmanager / maybe later not
            #new_nodes_list.append((link_name_fleurinp, fleurinp_Data))

            # load old fleurinpdata

            # if structure changed, create new fleurinpdata of new inp.xml file.
            # and parse the structure

        # optional parse other files

        # DOS
        if has_dos_file:
            dos_file = os.path.join(out_folder.get_abs_path('.'),
                                    self._calc._DOS_FILE_NAME)
            #if dos_file is not None:
            try:
                with open(dos_file, 'r') as dosf:
                    dos_lines = dosf.read()  # Note: read() and not readlines()
            except IOError:
                raise FleurOutputParsingError(
                    "Failed to open DOS file: {}.".format(dos_file))
            dos_data = parse_dos_file(dos_lines)  #, number_of_atom_types)

            # save array

        # Bands
        if has_bands_file:
            # TODO be carefull there might be two files.
            band_file = os.path.join(out_folder.get_abs_path('.'),
                                     self._calc._BAND_FILE_NAME)

            #if band_file is not None:
            try:
                with open(band_file, 'r') as bandf:
                    bands_lines = bandf.read(
                    )  # Note: read() and not readlines()
            except IOError:
                raise FleurOutputParsingError(
                    "Failed to open bandstructure file: {}."
                    "".format(band_file))
            bands_data = parse_bands_file(bands_lines)

            # save array
        if has_new_xmlinp_file:
            new_inpxmlfile = os.path.join(out_folder.get_abs_path('.'),
                                          self._calc._NEW_XMlINP_FILE_NAME)
            new_fleurinpData = FleurinpData()
            new_fleurinpData.set_file(new_inpxmlfile, dst_filename='inp.xml')
            self.logger.info('New FleurinpData initialized')
            link_name = 'fleurinpData'  #self.get_linkname_outparams()# accessible via c.res
            new_nodes_list.append((link_name, new_fleurinpData))

        # Spectra

        return successful, new_nodes_list
예제 #2
0
    def parse(self, **kwargs):
        """
        Takes inp.xml generated by inpgen calculation and created an FleurinpData node.

        :return: a dictionary of AiiDA nodes to be stored in the database.
        """

        try:
            output_folder = self.retrieved
        except NotExistent:
            self.logger.error('No retrieved folder found')
            return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER

        # check what is inside the folder
        list_of_files = output_folder.list_object_names()
        self.logger.info('file list {}'.format(list_of_files))

        errorfile = FleurinputgenCalculation._ERROR_FILE_NAME
        if errorfile in list_of_files:
            try:
                with output_folder.open(errorfile, 'r') as error_file:
                    error_file_lines = error_file.read()
            except IOError:
                self.logger.error(
                    'Failed to open error file: {}.'.format(errorfile))
                return self.exit_codes.ERROR_OPENING_OUTPUTS
            # if not empty, has_error equals True, prior fleur 32
            if error_file_lines:
                if isinstance(error_file_lines, type(b'')):
                    error_file_lines = error_file_lines.replace(b'\x00', b' ')
                else:
                    error_file_lines = error_file_lines.replace('\x00', ' ')
                if 'Run finished successfully' not in error_file_lines:
                    self.logger.warning(
                        'The following was written into std error and piped to {}'
                        ' : \n {}'.format(errorfile, error_file_lines))
                    self.logger.error('Inpgen calculation did not finish'
                                      ' successfully.')

        inpxml_file = FleurinputgenCalculation._INPXML_FILE_NAME
        if inpxml_file not in list_of_files:
            self.logger.error("XML inp not found '{}'".format(inpxml_file))
            return self.exit_codes.ERROR_NO_INPXML

        for file1 in self._default_files:
            if file1 not in list_of_files:
                self.logger.error(
                    "'{}' file not found in retrieved folder, it was probably "
                    'not created by inpgen'.format(file1))
                return self.exit_codes.ERROR_MISSING_RETRIEVED_FILES

        try:
            fleurinp = FleurinpData(files=[])
            fleurinp.set_file(inpxml_file, node=output_folder)
        except InputValidationError as ex:
            self.logger.error('FleurinpData initialization failed: {}'.format(
                str(ex)))
            if fleurinp.parser_info == {}:
                self.logger.error('Parser output: No Output produced')
            else:
                self.logger.error(
                    f'Parser output: {pprint.pformat(fleurinp.parser_info)}')
            return self.exit_codes.ERROR_FLEURINPDATA_INPUT_NOT_VALID
        except ValidationError as ex:
            self.logger.error('FleurinpData validation failed: {}'.format(
                str(ex)))
            return self.exit_codes.ERROR_FLEURINPDATA_NOT_VALID

        self.logger.info('FleurinpData initialized')
        self.out('fleurinpData', fleurinp)