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
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)