Ejemplo n.º 1
0
 def get_my_label(self, label):
     """Get the value of a label in the metadata file.
         Args:
             label <str>: Label to search for.
         Returns:
             <str>: Value of the label as a string, stripped.
     """
     myname = self.keywords['name']
     mymeta = Metadata(metafile=os.path.join(myname, "metadata.txt"))
     mylabel = mymeta.search_data(label)
     if mylabel == "":
         raise MASTError(self.__class__.__name__,
                         "No metadata for tag %s" % label)
     return mylabel[1]
Ejemplo n.º 2
0
 def get_my_label(self, label):
     """Get the value of a label in the metadata file.
         Args:
             label <str>: Label to search for.
         Returns:
             <str>: Value of the label as a string, stripped.
     """
     myname = self.keywords['name']
     mymeta = Metadata(metafile=os.path.join(myname, "metadata.txt"))
     mylabel = mymeta.search_data(label)
     if mylabel == "":
         raise MASTError(self.__class__.__name__, 
             "No metadata for tag %s" % label)
     return mylabel[1]
Ejemplo n.º 3
0
class RecipeTemplateParser(MASTObj):
    """Class for parsing the template recipe file in the input file and
        creating a "personalized" recipe file where any <sys> and <N> from
        the recipe template have been filled in according to information
        from the input file.
        Attributes:
            self.input_options <InputOptions>: Input options from input file.
            self.template_file <str>: Path to the recipe template file
            self.personal_recipe <str>: Path to the personalized recipe.
            self.ingredient_list <list of str>: List of ingredients mentioned
                                                in the recipe template file.
            self.chunks <list of list>: List of chunks
    """

    def __init__(self, **kwargs):
        MASTObj.__init__(self, ALLOWED_KEYS, **kwargs)
        self.input_options = self.keywords["inputOptions"]
        self.template_file = self.keywords["templateFile"]
        self.personal_recipe = self.keywords["personalRecipe"]
        self.ingredient_list = list()

        self.metafile = Metadata(metafile="%s/metadata.txt" % self.keywords["working_directory"])
        self.chunks = list()

    def parse(self):
        """ Parses the template recipe file and creates
            the personalized recipe file
        """
        if len(self.template_file) == 0:
            raise MASTError(self.__class__.__name__, "Recipe contents not provided!")

        if self.input_options is None:
            raise MASTError(self.__class__.__name__, "Input Options not provided!")
        if self.personal_recipe is None:
            raise MASTError(self.__class__.__name__, "Personal recipe file not provided!")

        # fetch required paramaters
        # f_ptr           = open(self.template_file, "r")
        recipe_contents = list(self.template_file)
        # print recipe_contents
        o_ptr = open(self.personal_recipe, "a")
        system_name = self.input_options.get_item("mast", "system_name", "sys")
        n_defects = self.input_options.get_item("defects", "num_defects", 0)
        d_defects = self.input_options.get_item("defects", "defects")
        n_images = self.input_options.get_item("neb", "images", 0)
        d_neblines = self.input_options.get_item("neb", "neblines", {})
        recipe_name = None

        #        print system_name, self.input_options.get_item('mast', 'system_name')
        chunkcount = 0
        mychunk = list()
        modchunk = False
        for line in recipe_contents:  # f_ptr.readlines():
            duplicate = line
            if (len(duplicate) - len(duplicate.lstrip(" "))) % 4 != 0:
                raise MASTError(
                    "parsers/recipetemplateparser",
                    "Recipe at %s contains incorrect number of whitespace chars at the beginning of the line! Please convert all indentations to the appropriate number of groups of four spaces."
                    % line,
                )
            if "\t" in line:
                raise MASTError(
                    "parsers/recipetemplateparser",
                    "The tab character exists in recipe template %s. Please convert all tabs to the appropriate number of groups of four spaces."
                    % self.template_file,
                )
            if "{begin}" in line:
                self.chunks.append(list(mychunk))
                mychunk = list()
            elif "{end}" in line:
                pass
            else:
                mychunk.append(line)
        if len(mychunk) > 0:
            self.chunks.append(list(mychunk))
        # for chunk in self.chunks:
        #    print chunk

        input_options_keys = self.input_options.get_sections()
        key = "personal_recipe"
        expandedlist = list()
        if key in input_options_keys:
            return expandedlist
        else:
            for chunk in self.chunks:
                expanded = self.parse_chunk(chunk)
                expandedlist.extend(expanded)
            o_ptr.write("$personal_recipe\n")
            o_ptr.writelines(expandedlist)
            o_ptr.write("$end\n")
            # f_ptr.close()
            o_ptr.close()
            return expandedlist
        # self.chunks[chunkcount]=dict()
        # self.chunks[chunkcount]['modify'] = modchunk
        #    #line             = line.strip()
        #    #line             = line.lower()
        #    processing_lines = []
        #    #shortcut straight copy + 6
        #    processing_lines.append(line)
        #    output_str = "\n".join(processing_lines)
        #    o_ptr.write("%s\n" % output_str)

        # f_ptr.close()
        # o_ptr.close()

    #        print 'in RecipeParser.parse():', list(set(self.ingredient_list))
    # return recipe_name
    def parse_chunk(self, chunk):
        """Parse a chunk of lines.
            Args:
                chunk <list>: List of lines
            Returns:
                expandedchunk <list>: List of lines
        """
        origchunk = list(chunk)
        expandedchunk = list()
        needsdefects = 0
        needscharges = 0
        needsphonons = 0
        needsnebs = 0
        needsscaling = 0
        for line in chunk:
            if "<N>" in line:
                needsdefects = 1
            if "<B-E>" in line:
                needsnebs = 1
            if "<P>" in line:
                needsphonons = 1
            if "<Q>" in line:
                needscharges = 1
            if "<B>" in line:
                needsnebs = 1
            if "<E>" in line:
                needsnebs = 1
            if "<S>" in line:
                needsscaling = 1
        d_scaling = self.input_options.get_item("scaling")
        d_defects = self.input_options.get_item("defects", "defects")
        d_nebs = self.input_options.get_item("neb", "nebs")

        if needsscaling == 1:
            scalingsize = d_scaling.keys()
            scalingsize.sort()
        else:
            scalingsize = ["1x1x1"]

        for size in scalingsize:
            if needsdefects == 1:
                mydefects = d_defects.keys()
                mydefects.sort()
                for defectname in mydefects:
                    for charge in d_defects[defectname]["charge"]:
                        if charge < 0:
                            mycharge = "q=n" + str(int(math.fabs(charge)))
                        else:
                            mycharge = "q=p" + str(int(charge))
                        if needsphonons == 1:
                            if len(d_defects[defectname]["phonon"].keys()) > 0:
                                phononkeys = d_defects[defectname]["phonon"].keys()
                                phononkeys.sort()
                                for phonon in phononkeys:
                                    for line in origchunk:
                                        newline = line.replace("<N>", defectname)
                                        if needscharges == 1:
                                            newline = newline.replace("<Q>", mycharge)
                                        if needsscaling == 1:
                                            newline = newline.replace("<S>", size)
                                        newline = newline.replace("<P>", phonon)
                                        expandedchunk.append(newline)
                        else:
                            for line in origchunk:
                                newline = line.replace("<N>", defectname)
                                if needscharges == 1:
                                    newline = newline.replace("<Q>", mycharge)
                                if needsscaling == 1:
                                    newline = newline.replace("<S>", size)
                                expandedchunk.append(newline)
            elif needsnebs == 1:
                nebkeys = d_nebs.keys()
                nebkeys.sort()
                for neblabel in nebkeys:
                    defbegin = neblabel.split("-")[0]
                    defend = neblabel.split("-")[1]
                    chargebegin = d_defects[defbegin]["charge"]
                    chargeend = d_defects[defend]["charge"]
                    chargeboth = set(chargebegin) & set(chargeend)
                    for charge in chargeboth:
                        if charge < 0:
                            mycharge = "q=n" + str(int(math.fabs(charge)))
                        else:
                            mycharge = "q=p" + str(int(charge))
                        if needsphonons == 1:
                            if len(d_nebs[neblabel]["phonon"].keys()) > 0:
                                phononkeys = d_nebs[neblabel]["phonon"].keys()
                                phononkeys.sort()
                                for phonon in phononkeys:
                                    for line in origchunk:
                                        newline = line.replace("<B>", defbegin)
                                        newline = newline.replace("<E>", defend)
                                        newline = newline.replace("<B-E>", neblabel)
                                        if needscharges == 1:
                                            newline = newline.replace("<Q>", mycharge)
                                        if needsscaling == 1:
                                            newline = newline.replace("<S>", size)
                                        newline = newline.replace("<P>", phonon)
                                        expandedchunk.append(newline)
                        else:
                            for line in origchunk:
                                newline = line.replace("<B>", defbegin)
                                newline = newline.replace("<E>", defend)
                                newline = newline.replace("<B-E>", neblabel)
                                if needscharges == 1:
                                    newline = newline.replace("<Q>", mycharge)
                                if needsscaling == 1:
                                    newline = newline.replace("<S>", size)
                                expandedchunk.append(newline)
            elif needsscaling == 1:
                for line in origchunk:
                    newline = line.replace("<S>", size)
                    expandedchunk.append(newline)
            else:
                expandedchunk = list(origchunk)
        return expandedchunk
        # origchunk = list(expandedchunk)
        # expandedchunk=list()
        # for defectname in self.d_defects:
        #    for line in origchunk:
        #        newline = line.replace("<N>", defectname)
        #        expandedchunk.append(line)

    def old_parsing(self):
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in linestr:
            # validate the input line
            if not line or line.startswith("#"):
                continue

            # collect recipe name
            line2 = line.split()
            if line2[0].lower() == "recipe":
                recipe_name = line2[1]

            # collect ingredents
            line2 = line.split()
            if line2[0].lower() == "ingredient":
                self.ingredient_list.append(line2[2])

            # replace line params<N>
            # step 1 : replace <sys> with system_name
            # step 2 : replace <n-n> with appropriate hop combinations
            # step 3 : replace <img-n> with appropriate image numbers
            # step 4 : replace <n> with appropriate defect numbers
            processing_lines.append(line)
            # step 1
            processing_lines = self.process_system_name(processing_lines, system_name)
            # step 4
            processing_lines = self.process_defects(processing_lines, n_defects, d_defects)
            # step 2
            processing_lines = self.process_hop_combinations(processing_lines, d_neblines)
            # step 3
            processing_lines = self.process_images(processing_lines, n_images)

            self.make_metadata_entries(processing_lines)

            self.process_phononlines(processing_lines)
            # dump the processed lines to file
            output_str = "\n".join(processing_lines)
            o_ptr.write("%s\n" % output_str)

        f_ptr.close()
        o_ptr.close()
        #        print 'in RecipeParser.parse():', list(set(self.ingredient_list))
        return recipe_name

    def process_system_name(self, processing_lines, system_name):
        """replace <sys> with the system name from the input options
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for index in xrange(len(processing_lines)):
            processing_lines[index] = processing_lines[index].replace("<sys>", system_name)
        return processing_lines

    def process_hop_combinations(self, processing_lines, d_neblines):
        """replace <n-n> with neb labels which are keys of the
           neblines dict of the input options.

            Args:
                processing_lines <list of str>: recipe lines to process.
                d_neblines <dict of str>: dictionary of NEB lines.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        new_lines = []
        eval_lines = []
        if not d_neblines:
            return processing_lines
        line = ""
        for line in processing_lines:
            if "<n-n>" in line:
                for neblabel in d_neblines.keys():
                    n_line = line.replace("<n-n>", neblabel)
                    eval_lines.append(n_line)
                    if "ingredient" in n_line and not "<" in n_line:
                        keyword = n_line.split()[1]
                        data = "neblabel: %s" % neblabel
                        self.metafile.write_data(keyword, data)
            else:
                eval_lines.append(line)
        line = ""
        for line in eval_lines:
            # print "TTM DEBUG line: ", line
            if not "neb" in line.split("_"):
                # print "TTM DEBUG line safe"
                new_lines.append(line)
            else:
                evalsplit = line.split("child")
                if len(evalsplit) == 1:
                    new_lines.append(line)
                else:
                    childsplit = evalsplit[1].split("_")
                    parsplit = evalsplit[0].split("_")
                    okay = 1
                    for neblabel in d_neblines.keys():
                        if okay == 1 and (neblabel in childsplit):
                            parlabels = neblabel.split("-")
                            # print "TTM DEBUG: parlabels: ",parlabels
                            # print "TTM DEBUG: parsplit: ",parsplit
                            if not parlabels[0] in parsplit and not (parlabels[1] in parsplit):
                                if not neblabel in parsplit:  # image static
                                    okay = 0
                    if okay == 0:
                        pass
                    else:
                        new_lines.append(line)
        return new_lines

    def process_images(self, processing_lines, n_images):
        """replace <img-n> with the equivalent number of 
           lines based on the number of images found in the
           input_options
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        new_lines = []
        if not n_images:
            return processing_lines
        for line in processing_lines:
            if "<img-n>" in line:
                for index in xrange(n_images):
                    n_line = line.replace("<img-n>", str(index + 1).zfill(2))
                    if "ingredient" in n_line and not "<" in n_line:
                        keyword = n_line.split()[1]
                        data = "name: %s" % keyword
                        self.metafile.write_data(keyword, data)
                    new_lines.append(n_line)
            else:
                new_lines.append(line)
        return new_lines

    def process_defects(self, processing_lines, n_defects, d_defects):
        """replace <N> with the equivalent number of lines
           based on the number of defects given in the
           input options

           Args:
            processing_lines <list of str>: recipe lines to proceess
            n_defects <int>: number of defected systems
            d_defects <dict>: dictionary of defects, including labels and 
                                positions.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        # import inspect
        # print 'GRJ DEBUG: %s.%s' % (self.__class__.__name__, inspect.stack()[0][3])
        # print d_defects

        # print 'GRJ DEBUG: parse_defects() working_directory =', self.keywords['working_directory']
        new_lines = list()

        if not n_defects:
            return processing_lines

        for line in processing_lines:
            # print 'GRJ DEBUG: line =', line
            if ("<n>" in line) or ("<q>" in line):
                for defect_key in d_defects.keys():
                    # print 'GRJ DEBUG: defect_key =', defect_key
                    # defect_label = defect_key.split('_')[1] #defect_1, etc.
                    def_line = line.replace("<n>", defect_key)

                    charge_list = d_defects[defect_key]["charge"]
                    # print 'GRJ DEBUG: charge_list =', charge_list
                    # print 'GRJ DEBUG: def_line before charges:', def_line
                    for charge in charge_list:
                        if charge < 0:
                            clabel = "q=n" + str(abs(charge))
                        else:
                            clabel = "q=p" + str(charge)
                        # print 'GRJ DEBUG: clabel =', clabel
                        new_def_line = def_line.replace("<q>", clabel)
                        new_lines.append(new_def_line)
                        # new_lines.append(def_line.replace('<q>', clabel))

                        if "ingredient" in def_line:
                            keyword = new_def_line.split()[1]
                            data = "defect_label: %s, charge: %i" % (defect_key, charge)
                            # print 'GRJ DEBUG: def_line, keyword, charge', new_def_line, keyword, charge
                            self.metafile.write_data(keyword, data)
            else:
                new_lines.append(line)

        return new_lines

    def process_phononlines(self, processing_lines):
        """add phonon information to the metadata. Does not change line info.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in processing_lines:
            if "ingredient" in line and "phonon_" in line:
                nameval = line.split()[1]
                [dataline, dataval] = self.metafile.search_data(nameval)
                okay = 0
                if not (dataval == None):
                    datapcs = dataval.split(",")
                    for datapc in datapcs:
                        dlabel = datapc.split(":")[0].strip()
                        dval = datapc.split(":")[1].strip()
                        if dlabel == "neblabel" or dlabel == "defect_label":
                            data = "phononlabel: %s" % dval
                            self.metafile.write_data(nameval, data)
                            okay = 1
                            break
                if okay == 0:
                    if "perfect" in line:
                        data = "phononlabel: perfect"
                        self.metafile.write_data(nameval, data)
                        okay = 1
                    else:
                        data = "phononlabel: %s" % nameval
                        self.metafile.write_data(nameval, data)
                        okay = 1
        return

    def make_metadata_entries(self, processing_lines):
        """Add metadata entry for all ingredients. 
            Does not change line information.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in processing_lines:
            if "ingredient" in line:
                nameval = line.split()[1]
                data = "name: %s" % nameval
                self.metafile.write_data(nameval, data)
        return

    def get_unique_ingredients(self):
        """fetches the ingredients names"""
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        return list(set(self.ingredient_list))
Ejemplo n.º 4
0
    def parse_ingredients_section(self, section_name, section_content,
                                  options):
        """Parses the ingredients section and populates the options.
            Section takes the form of:
                $ingredients
                begin ingredients_global
                mast_kpoints 3x3x3
                mast_xc pbe
                end

                begin singlepoint
                encut 400
                end

                begin optimize
                encut 300
                ibrion 2
                end

                $end

            mast_kpoints are parsed out as a 3 index list of integers. 
            Everything else is parsed out as a string.

            Anything in ingredients_global is then appended onto each 
            individual ingredient.
        """

        global_dict = dict()
        ingredients_dict = dict()

        for line in section_content:
            if (line.startswith('begin')):
                # Each ingredient section starts with "begin".
                # Check for this line, and initialize the individual
                # ingredient dictionary
                ingredient_name = line.split()[1]
                ingredient_dict = dict()
            elif (not (line == 'end')):
                opt = line.split()
                # print opt
                if (opt[0] == 'mast_kpoints'):
                    try:
                        kpts = map(int, opt[1].split('x'))
                        if len(opt) > 2:
                            kpts.append(opt[2])
                    except ValueError:
                        kpts = opt[1:]
                    # Second option after mast_kpoints tells where to
                    # center the k-point mesh.
                    # If it's there, we append it onto the k-point grid list.
                    ingredient_dict[opt[0]] = kpts
                elif (opt[0] == 'mast_pp_setup'):
                    psp_dict = dict()
                    for key in opt[1:]:
                        key = key.split('=')
                        ref = key[0].title()
                        val = str().join(key[1][0].upper() + key[1][1:])
                        psp_dict[ref] = val
                    ingredient_dict[opt[0]] = psp_dict
                #elif (opt[0] == 'mast_exec'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'mast_strain'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'ptemp'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'rwigs'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'mast_setmagmom'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                elif (opt[0] == 'mast_coordinates'):
                    shortsplit = opt[1].split(",")
                    filesplit = list()
                    origindir = os.getcwd()
                    metatry = os.path.join(os.getcwd(), 'metadata.txt')
                    if os.path.isfile(metatry):
                        myrecipemeta = Metadata(metafile=metatry)
                        origindir = myrecipemeta.search_data('origin_dir')[1]
                    myfiles = dirutil.walkfiles(origindir)
                    for shortname in shortsplit:
                        for fullfile in myfiles:
                            if shortname.strip() in os.path.basename(fullfile):
                                filesplit.append(fullfile)
                    if not (len(filesplit) == len(shortsplit)):
                        raise MASTError(
                            self.__class__.__name__,
                            "Not all files given by %s were found in %s." %
                            (shortsplit, origindir))
                    ingredient_dict[opt[0]] = filesplit
                else:
                    ingredient_dict[opt[0]] = ' '.join(
                        opt[1:])  #preserve whole line
                    #ingredient_dict[opt[0]] = opt[1] #old behavior took only the first part
                if (opt[0] == 'mast_program') and (opt[1] == 'vasp'
                                                   or opt[1] == 'vasp_neb'):
                    if os.getenv('VASP_PSP_DIR') == None:
                        raise MASTError(
                            self.__class__.__name__,
                            "Input file specifies program vasp, but no POTCAR directory is set in environment variable VASP_PSP_DIR"
                        )
            elif ('end' in line):
                # Each ingredient section ends with "end", if present finish
                # that current section and assign
                # the neccessary element in the ingredients dictionary and
                # create the global dictionary
                if (ingredient_name == 'ingredients_global'):
                    global_dict = ingredient_dict
                else:
                    ingredients_dict[ingredient_name] = ingredient_dict

        # Each value in ingredients_dict is a dictionary containing the relevant
        # ingredient and option(s).
        for ing_key, ing_value in ingredients_dict.items():
            options.set_item(section_name, ing_key, ing_value)

        options.set_item(section_name, 'global', global_dict)
Ejemplo n.º 5
0
    def parse_structure_section(self, section_name, section_content, options):
        """Parses the structure section and populate the options.
            Does not create the structure.

            Format is along the lines of:
                coord_type fractional

                begin coordinates
                Ga 0.000000 0.000000 0.000000
                Ga 0.500000 0.500000 0.000000
                Ga 0.000000 0.500000 0.500000
                Ga 0.500000 0.000000 0.500000
                As 0.250000 0.250000 0.250000
                As 0.750000 0.750000 0.250000
                As 0.250000 0.750000 0.750000
                As 0.750000 0.250000 0.750000
                end

                begin lattice
                2.0 0.0 0.0
                0.0 2.0 0.0
                0.0 0.0 2.0
                end

            Note that coord_type will default to "cartesian" if not specified.

        """
        # Initialize with default values
        structure_dict = STRUCTURE_KEYWORDS.copy()

        subsection_dict = dict()
        for myline in section_content:
            line = myline.split()

            if (line[0] in structure_dict):
                structure_dict[line[0]] = line[1]
            elif ('begin' in line[0]):
                subsection = line[1]
                subsection_list = list()
            elif ('end' not in line):
                lsplit = myline.split()
                lineval = list()
                for lval in lsplit:
                    lval.strip()
                    if len(lval) > 0:
                        lineval.append(lval)
                subsection_list.append(lineval)
            elif ('end' in line):
                subsection_dict[subsection] = subsection_list

        # GRJ: Since we lowercase the whole input file, and filenames may not
        # conform to this, we examine the current directory for any files that
        # may match and use that.  If there are multiple matches, we'll throw
        # an error.
        if (structure_dict['posfile']
                is not None):  # Do we have a geometry file?
            # TTM for issue #423
            posfiletry = os.path.join(os.getcwd(), structure_dict['posfile'])
            if os.path.isfile(posfiletry):
                self.logger.info("Using posfile %s in directory %s" %
                                 (structure_dict['posfile'], os.getcwd()))
            else:
                # First build a list of likely files
                origindir = os.path.dirname(self.keywords['inputfile'])
                if origindir == "":
                    origindir = os.getcwd()
                metatry = os.path.join(os.getcwd(), 'metadata.txt')
                if os.path.isfile(metatry):
                    myrecipemeta = Metadata(metafile=metatry)
                    origindir = myrecipemeta.search_data('origin_dir')[1]
                myfiles = dirutil.walkfiles(origindir)
                file_list = list()
                for myfile in myfiles:
                    if structure_dict['posfile'] in myfile:
                        file_list.append(myfile)
                if (len(file_list) > 1):
                    # If we have multiple files with the same name, but different capitalization, throw an error here
                    self.logger.warning(
                        'Found multiple files with the name %s' %
                        structure_dict['posfile'])
                    self.logger.warning('Found the files:')
                    for file in file_list:
                        self.logger.warning(file)
                    error = 'Found ambiguous file names'
                    raise MASTError(self.__class__.__name__, error)
                elif len(file_list) == 0:
                    raise MASTError(
                        self.__class__.__name__,
                        "No structure file %s found in %s" %
                        (structure_dict['posfile'], origindir))
                else:
                    structure_dict['posfile'] = file_list[0]
        # print 'in InputParser.parse_structure_section:', subsection_dict
        # TM
        element_map = dict()
        atom_list = list()
        for key, value in subsection_dict.items():
            if (key == 'coordinates'):
                value = np.array(value)
                # Here we use .title() to re-capitalize the first letter of all
                # the atomic symbols to comply with what
                # pymatgen needs
                atom_list = [val.title() for val in value[:, 0]]
                structure_dict['atom_list'] = atom_list
                coordinates = np.array(value[:, 1:], dtype='float')
                structure_dict['coordinates'] = coordinates
            if (key == 'lattice'):
                #print "VALUE: ", value
                lattice = np.array(value, dtype='float')
                structure_dict['lattice'] = lattice
            if (key == 'elementmap'):
                for elline in value:
                    elkey = elline[0].strip().upper()  #all caps
                    elname = elline[1].strip().title()  #Title case
                    element_map[elkey] = elname
                structure_dict['element_map'] = element_map
        if len(element_map) > 0 and len(atom_list) > 0:
            new_atom_list = list()
            for atomval in atom_list:
                if atomval.upper() in element_map.keys():
                    new_atom_list.append(element_map[atomval])
                else:
                    new_atom_list.append(atomval)
            structure_dict['atom_list'] = new_atom_list

        for key, value in structure_dict.items():
            options.set_item(section_name, key, value)
Ejemplo n.º 6
0
class RecipeTemplateParser(MASTObj):
    """Class for parsing the template recipe file in the input file and
        creating a "personalized" recipe file where any <sys> and <N> from
        the recipe template have been filled in according to information
        from the input file.
        Attributes:
            self.input_options <InputOptions>: Input options from input file.
            self.template_file <str>: Path to the recipe template file
            self.personal_recipe <str>: Path to the personalized recipe.
            self.ingredient_list <list of str>: List of ingredients mentioned
                                                in the recipe template file.
            self.chunks <list of list>: List of chunks
    """
    def __init__(self, **kwargs):
        MASTObj.__init__(self, ALLOWED_KEYS, **kwargs)
        self.input_options = self.keywords['inputOptions']
        self.template_file = self.keywords['templateFile']
        self.personal_recipe = self.keywords['personalRecipe']
        self.ingredient_list = list()

        self.metafile = Metadata(metafile='%s/metadata.txt' %
                                 self.keywords['working_directory'])
        self.chunks = list()

    def parse(self):
        """ Parses the template recipe file and creates
            the personalized recipe file
        """
        if len(self.template_file) == 0:
            raise MASTError(self.__class__.__name__,
                            "Recipe contents not provided!")

        if self.input_options is None:
            raise MASTError(self.__class__.__name__,
                            "Input Options not provided!")
        if self.personal_recipe is None:
            raise MASTError(self.__class__.__name__,
                            "Personal recipe file not provided!")

        #fetch required paramaters
        #f_ptr           = open(self.template_file, "r")
        recipe_contents = list(self.template_file)
        #print recipe_contents
        o_ptr = open(self.personal_recipe, "a")
        system_name = self.input_options.get_item("mast", "system_name", "sys")
        n_defects = self.input_options.get_item("defects", "num_defects", 0)
        d_defects = self.input_options.get_item("defects", "defects")
        n_images = self.input_options.get_item("neb", "images", 0)
        d_neblines = self.input_options.get_item("neb", "neblines", {})
        recipe_name = None

        #        print system_name, self.input_options.get_item('mast', 'system_name')
        chunkcount = 0
        mychunk = list()
        modchunk = False
        for line in recipe_contents:  #f_ptr.readlines():
            duplicate = line
            if ((len(duplicate) - len(duplicate.lstrip(' '))) % 4 != 0):
                raise MASTError(
                    "parsers/recipetemplateparser",
                    "Recipe at %s contains incorrect number of whitespace chars at the beginning of the line! Please convert all indentations to the appropriate number of groups of four spaces."
                    % line)
            if '\t' in line:
                raise MASTError(
                    "parsers/recipetemplateparser",
                    "The tab character exists in recipe template %s. Please convert all tabs to the appropriate number of groups of four spaces."
                    % self.template_file)
            if '{begin}' in line:
                self.chunks.append(list(mychunk))
                mychunk = list()
            elif '{end}' in line:
                pass
            else:
                mychunk.append(line)
        if len(mychunk) > 0:
            self.chunks.append(list(mychunk))
        #for chunk in self.chunks:
        #    print chunk

        input_options_keys = self.input_options.get_sections()
        key = 'personal_recipe'
        expandedlist = list()
        if key in input_options_keys:
            return expandedlist
        else:
            for chunk in self.chunks:
                expanded = self.parse_chunk(chunk)
                expandedlist.extend(expanded)
            o_ptr.write("$personal_recipe\n")
            o_ptr.writelines(expandedlist)
            o_ptr.write("$end\n")
            #f_ptr.close()
            o_ptr.close()
            return expandedlist
        #self.chunks[chunkcount]=dict()
        #self.chunks[chunkcount]['modify'] = modchunk
        #    #line             = line.strip()
        #    #line             = line.lower()
        #    processing_lines = []
        #    #shortcut straight copy + 6
        #    processing_lines.append(line)
        #    output_str = "\n".join(processing_lines)
        #    o_ptr.write("%s\n" % output_str)

        #f_ptr.close()
        #o_ptr.close()
#        print 'in RecipeParser.parse():', list(set(self.ingredient_list))
#return recipe_name

    def parse_chunk(self, chunk):
        """Parse a chunk of lines.
            Args:
                chunk <list>: List of lines
            Returns:
                expandedchunk <list>: List of lines
        """
        origchunk = list(chunk)
        expandedchunk = list()
        needsdefects = 0
        needscharges = 0
        needsphonons = 0
        needsnebs = 0
        needsscaling = 0
        for line in chunk:
            if "<N>" in line:
                needsdefects = 1
            if "<B-E>" in line:
                needsnebs = 1
            if "<P>" in line:
                needsphonons = 1
            if "<Q>" in line:
                needscharges = 1
            if "<B>" in line:
                needsnebs = 1
            if "<E>" in line:
                needsnebs = 1
            if "<S>" in line:
                needsscaling = 1
        d_scaling = self.input_options.get_item("scaling")
        d_defects = self.input_options.get_item("defects", "defects")
        d_nebs = self.input_options.get_item("neb", "nebs")

        if needsscaling == 1:
            scalingsize = d_scaling.keys()
            scalingsize.sort()
        else:
            scalingsize = ['1x1x1']

        for size in scalingsize:
            if needsdefects == 1:
                mydefects = d_defects.keys()
                mydefects.sort()
                for defectname in mydefects:
                    for charge in d_defects[defectname]['charge']:
                        if charge < 0:
                            mycharge = 'q=n' + str(int(math.fabs(charge)))
                        else:
                            mycharge = 'q=p' + str(int(charge))
                        if needsphonons == 1:
                            if len(d_defects[defectname]['phonon'].keys()) > 0:
                                phononkeys = d_defects[defectname][
                                    'phonon'].keys()
                                phononkeys.sort()
                                for phonon in phononkeys:
                                    for line in origchunk:
                                        newline = line.replace(
                                            "<N>", defectname)
                                        if needscharges == 1:
                                            newline = newline.replace(
                                                "<Q>", mycharge)
                                        if needsscaling == 1:
                                            newline = newline.replace(
                                                "<S>", size)
                                        newline = newline.replace(
                                            "<P>", phonon)
                                        expandedchunk.append(newline)
                        else:
                            for line in origchunk:
                                newline = line.replace("<N>", defectname)
                                if needscharges == 1:
                                    newline = newline.replace("<Q>", mycharge)
                                if needsscaling == 1:
                                    newline = newline.replace("<S>", size)
                                expandedchunk.append(newline)
            elif needsnebs == 1:
                nebkeys = d_nebs.keys()
                nebkeys.sort()
                for neblabel in nebkeys:
                    defbegin = neblabel.split('-')[0]
                    defend = neblabel.split('-')[1]
                    chargebegin = d_defects[defbegin]['charge']
                    chargeend = d_defects[defend]['charge']
                    chargeboth = set(chargebegin) & set(chargeend)
                    for charge in chargeboth:
                        if charge < 0:
                            mycharge = 'q=n' + str(int(math.fabs(charge)))
                        else:
                            mycharge = 'q=p' + str(int(charge))
                        if needsphonons == 1:
                            if len(d_nebs[neblabel]['phonon'].keys()) > 0:
                                phononkeys = d_nebs[neblabel]['phonon'].keys()
                                phononkeys.sort()
                                for phonon in phononkeys:
                                    for line in origchunk:
                                        newline = line.replace("<B>", defbegin)
                                        newline = newline.replace(
                                            "<E>", defend)
                                        newline = newline.replace(
                                            "<B-E>", neblabel)
                                        if needscharges == 1:
                                            newline = newline.replace(
                                                "<Q>", mycharge)
                                        if needsscaling == 1:
                                            newline = newline.replace(
                                                "<S>", size)
                                        newline = newline.replace(
                                            "<P>", phonon)
                                        expandedchunk.append(newline)
                        else:
                            for line in origchunk:
                                newline = line.replace("<B>", defbegin)
                                newline = newline.replace("<E>", defend)
                                newline = newline.replace("<B-E>", neblabel)
                                if needscharges == 1:
                                    newline = newline.replace("<Q>", mycharge)
                                if needsscaling == 1:
                                    newline = newline.replace("<S>", size)
                                expandedchunk.append(newline)
            elif needsscaling == 1:
                for line in origchunk:
                    newline = line.replace("<S>", size)
                    expandedchunk.append(newline)
            else:
                expandedchunk = list(origchunk)
        return expandedchunk
        #origchunk = list(expandedchunk)
        #expandedchunk=list()
        #for defectname in self.d_defects:
        #    for line in origchunk:
        #        newline = line.replace("<N>", defectname)
        #        expandedchunk.append(line)

    def old_parsing(self):
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in linestr:
            #validate the input line
            if not line or line.startswith('#'):
                continue

            #collect recipe name
            line2 = line.split()
            if (line2[0].lower() == 'recipe'):
                recipe_name = line2[1]

            #collect ingredents
            line2 = line.split()
            if (line2[0].lower() == 'ingredient'):
                self.ingredient_list.append(line2[2])

            #replace line params<N>
            #step 1 : replace <sys> with system_name
            #step 2 : replace <n-n> with appropriate hop combinations
            #step 3 : replace <img-n> with appropriate image numbers
            #step 4 : replace <n> with appropriate defect numbers
            processing_lines.append(line)
            #step 1
            processing_lines = self.process_system_name(
                processing_lines, system_name)
            #step 4
            processing_lines = self.process_defects(processing_lines,
                                                    n_defects, d_defects)
            #step 2
            processing_lines = self.process_hop_combinations(
                processing_lines, d_neblines)
            #step 3
            processing_lines = self.process_images(processing_lines, n_images)

            self.make_metadata_entries(processing_lines)

            self.process_phononlines(processing_lines)
            #dump the processed lines to file
            output_str = "\n".join(processing_lines)
            o_ptr.write("%s\n" % output_str)

        f_ptr.close()
        o_ptr.close()
        #        print 'in RecipeParser.parse():', list(set(self.ingredient_list))
        return recipe_name

    def process_system_name(self, processing_lines, system_name):
        """replace <sys> with the system name from the input options
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for index in xrange(len(processing_lines)):
            processing_lines[index] = processing_lines[index].replace(
                '<sys>', system_name)
        return processing_lines

    def process_hop_combinations(self, processing_lines, d_neblines):
        """replace <n-n> with neb labels which are keys of the
           neblines dict of the input options.

            Args:
                processing_lines <list of str>: recipe lines to process.
                d_neblines <dict of str>: dictionary of NEB lines.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        new_lines = []
        eval_lines = []
        if not d_neblines:
            return processing_lines
        line = ""
        for line in processing_lines:
            if "<n-n>" in line:
                for neblabel in d_neblines.keys():
                    n_line = line.replace('<n-n>', neblabel)
                    eval_lines.append(n_line)
                    if 'ingredient' in n_line and not '<' in n_line:
                        keyword = n_line.split()[1]
                        data = 'neblabel: %s' % neblabel
                        self.metafile.write_data(keyword, data)
            else:
                eval_lines.append(line)
        line = ""
        for line in eval_lines:
            #print "TTM DEBUG line: ", line
            if not 'neb' in line.split('_'):
                #print "TTM DEBUG line safe"
                new_lines.append(line)
            else:
                evalsplit = line.split('child')
                if len(evalsplit) == 1:
                    new_lines.append(line)
                else:
                    childsplit = evalsplit[1].split('_')
                    parsplit = evalsplit[0].split('_')
                    okay = 1
                    for neblabel in d_neblines.keys():
                        if okay == 1 and (neblabel in childsplit):
                            parlabels = neblabel.split('-')
                            #print "TTM DEBUG: parlabels: ",parlabels
                            #print "TTM DEBUG: parsplit: ",parsplit
                            if not parlabels[0] in parsplit and not (
                                    parlabels[1] in parsplit):
                                if not neblabel in parsplit:  #image static
                                    okay = 0
                    if okay == 0:
                        pass
                    else:
                        new_lines.append(line)
        return new_lines

    def process_images(self, processing_lines, n_images):
        """replace <img-n> with the equivalent number of 
           lines based on the number of images found in the
           input_options
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        new_lines = []
        if not n_images:
            return processing_lines
        for line in processing_lines:
            if '<img-n>' in line:
                for index in xrange(n_images):
                    n_line = line.replace('<img-n>', str(index + 1).zfill(2))
                    if 'ingredient' in n_line and not '<' in n_line:
                        keyword = n_line.split()[1]
                        data = 'name: %s' % keyword
                        self.metafile.write_data(keyword, data)
                    new_lines.append(n_line)
            else:
                new_lines.append(line)
        return new_lines

    def process_defects(self, processing_lines, n_defects, d_defects):
        """replace <N> with the equivalent number of lines
           based on the number of defects given in the
           input options

           Args:
            processing_lines <list of str>: recipe lines to proceess
            n_defects <int>: number of defected systems
            d_defects <dict>: dictionary of defects, including labels and 
                                positions.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        #import inspect
        #print 'GRJ DEBUG: %s.%s' % (self.__class__.__name__, inspect.stack()[0][3])
        #print d_defects

        #print 'GRJ DEBUG: parse_defects() working_directory =', self.keywords['working_directory']
        new_lines = list()

        if not n_defects:
            return processing_lines

        for line in processing_lines:
            #print 'GRJ DEBUG: line =', line
            if ('<n>' in line) or ('<q>' in line):
                for defect_key in d_defects.keys():
                    #print 'GRJ DEBUG: defect_key =', defect_key
                    #defect_label = defect_key.split('_')[1] #defect_1, etc.
                    def_line = line.replace("<n>", defect_key)

                    charge_list = d_defects[defect_key]['charge']
                    #print 'GRJ DEBUG: charge_list =', charge_list
                    #print 'GRJ DEBUG: def_line before charges:', def_line
                    for charge in charge_list:
                        if (charge < 0):
                            clabel = 'q=n' + str(abs(charge))
                        else:
                            clabel = 'q=p' + str(charge)
                        #print 'GRJ DEBUG: clabel =', clabel
                        new_def_line = def_line.replace('<q>', clabel)
                        new_lines.append(new_def_line)
                        #new_lines.append(def_line.replace('<q>', clabel))

                        if 'ingredient' in def_line:
                            keyword = new_def_line.split()[1]
                            data = 'defect_label: %s, charge: %i' % (
                                defect_key, charge)
                            #print 'GRJ DEBUG: def_line, keyword, charge', new_def_line, keyword, charge
                            self.metafile.write_data(keyword, data)
            else:
                new_lines.append(line)

        return new_lines

    def process_phononlines(self, processing_lines):
        """add phonon information to the metadata. Does not change line info.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in processing_lines:
            if 'ingredient' in line and 'phonon_' in line:
                nameval = line.split()[1]
                [dataline, dataval] = self.metafile.search_data(nameval)
                okay = 0
                if not (dataval == None):
                    datapcs = dataval.split(',')
                    for datapc in datapcs:
                        dlabel = datapc.split(":")[0].strip()
                        dval = datapc.split(":")[1].strip()
                        if dlabel == 'neblabel' or dlabel == 'defect_label':
                            data = 'phononlabel: %s' % dval
                            self.metafile.write_data(nameval, data)
                            okay = 1
                            break
                if okay == 0:
                    if 'perfect' in line:
                        data = 'phononlabel: perfect'
                        self.metafile.write_data(nameval, data)
                        okay = 1
                    else:
                        data = 'phononlabel: %s' % nameval
                        self.metafile.write_data(nameval, data)
                        okay = 1
        return

    def make_metadata_entries(self, processing_lines):
        """Add metadata entry for all ingredients. 
            Does not change line information.
        """
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        for line in processing_lines:
            if 'ingredient' in line:
                nameval = line.split()[1]
                data = 'name: %s' % nameval
                self.metafile.write_data(nameval, data)
        return

    def get_unique_ingredients(self):
        """fetches the ingredients names"""
        raise MASTError(self.__class__.__name__, "This function is obsolete.")
        return list(set(self.ingredient_list))
Ejemplo n.º 7
0
    def parse_ingredients_section(self, section_name, section_content, options):
        """Parses the ingredients section and populates the options.
            Section takes the form of:
                $ingredients
                begin ingredients_global
                mast_kpoints 3x3x3
                mast_xc pbe
                end

                begin singlepoint
                encut 400
                end

                begin optimize
                encut 300
                ibrion 2
                end

                $end

            mast_kpoints are parsed out as a 3 index list of integers. 
            Everything else is parsed out as a string.

            Anything in ingredients_global is then appended onto each 
            individual ingredient.
        """

        global_dict = dict()
        ingredients_dict = dict()

        for line in section_content:
            if (line.startswith('begin')):
                # Each ingredient section starts with "begin".
                # Check for this line, and initialize the individual
                # ingredient dictionary
                ingredient_name = line.split()[1]
                ingredient_dict = dict()
            elif (not (line == 'end')):
                opt = line.split()
                # print opt
                if (opt[0] == 'mast_kpoints'):
                    try: 
                        kpts = map(int, opt[1].split('x'))
                        if len(opt) > 2:
                            kpts.append(opt[2])
                    except ValueError: 
                        kpts = opt[1:]
                    # Second option after mast_kpoints tells where to 
                    # center the k-point mesh.
                    # If it's there, we append it onto the k-point grid list.
                    ingredient_dict[opt[0]] = kpts
                elif (opt[0] == 'mast_pp_setup'):
                    psp_dict = dict()
                    for key in opt[1:]:
                        key = key.split('=')
                        ref = key[0].title()
                        val = str().join(key[1][0].upper() + key[1][1:])
                        psp_dict[ref] = val
                    ingredient_dict[opt[0]] = psp_dict
                #elif (opt[0] == 'mast_exec'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'mast_strain'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'ptemp'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line 
                #elif (opt[0] == 'rwigs'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                #elif (opt[0] == 'mast_setmagmom'):
                #    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                elif (opt[0] == 'mast_coordinates'):
                    shortsplit = opt[1].split(",")
                    filesplit=list()
                    origindir = os.getcwd()
                    metatry = os.path.join(os.getcwd(), 'metadata.txt')
                    if os.path.isfile(metatry):
                        myrecipemeta = Metadata(metafile=metatry)
                        origindir = myrecipemeta.search_data('origin_dir')[1]
                    myfiles = dirutil.walkfiles(origindir)
                    for shortname in shortsplit:
                        for fullfile in myfiles:
                            if shortname.strip() in os.path.basename(fullfile):
                                filesplit.append(fullfile)
                    if not (len(filesplit) == len(shortsplit)):
                        raise MASTError(self.__class__.__name__, "Not all files given by %s were found in %s." % (shortsplit, origindir))
                    ingredient_dict[opt[0]] = filesplit
                else:
                    ingredient_dict[opt[0]] = ' '.join(opt[1:]) #preserve whole line
                    #ingredient_dict[opt[0]] = opt[1] #old behavior took only the first part
                if (opt[0] == 'mast_program') and (opt[1] == 'vasp' or opt[1] == 'vasp_neb'):
                    if os.getenv('VASP_PSP_DIR') == None:
                        raise MASTError(self.__class__.__name__, "Input file specifies program vasp, but no POTCAR directory is set in environment variable VASP_PSP_DIR")
            elif ('end' in line):
                # Each ingredient section ends with "end", if present finish 
                # that current section and assign
                # the neccessary element in the ingredients dictionary and 
                # create the global dictionary
                if (ingredient_name == 'ingredients_global'):
                    global_dict = ingredient_dict
                else:
                    ingredients_dict[ingredient_name] = ingredient_dict

        # Each value in ingredients_dict is a dictionary containing the relevant
        # ingredient and option(s).
        for ing_key, ing_value in ingredients_dict.items():
            options.set_item(section_name, ing_key, ing_value)

        options.set_item(section_name, 'global', global_dict)
Ejemplo n.º 8
0
    def parse_structure_section(self, section_name, section_content, options):
        """Parses the structure section and populate the options.
            Does not create the structure.

            Format is along the lines of:
                coord_type fractional

                begin coordinates
                Ga 0.000000 0.000000 0.000000
                Ga 0.500000 0.500000 0.000000
                Ga 0.000000 0.500000 0.500000
                Ga 0.500000 0.000000 0.500000
                As 0.250000 0.250000 0.250000
                As 0.750000 0.750000 0.250000
                As 0.250000 0.750000 0.750000
                As 0.750000 0.250000 0.750000
                end

                begin lattice
                2.0 0.0 0.0
                0.0 2.0 0.0
                0.0 0.0 2.0
                end

            Note that coord_type will default to "cartesian" if not specified.

        """
        # Initialize with default values
        structure_dict = STRUCTURE_KEYWORDS.copy() 

        subsection_dict = dict()
        for myline in section_content:
            line = myline.split()

            if (line[0] in structure_dict):
                structure_dict[line[0]] = line[1]
            elif ('begin' in line[0]):
                subsection = line[1]
                subsection_list = list()
            elif ('end' not in line):
                lsplit = myline.split()
                lineval = list()
                for lval in lsplit:
                    lval.strip()
                    if len(lval) > 0:
                        lineval.append(lval)
                subsection_list.append(lineval)
            elif ('end' in line):
                subsection_dict[subsection] = subsection_list

        # GRJ: Since we lowercase the whole input file, and filenames may not
        # conform to this, we examine the current directory for any files that
        # may match and use that.  If there are multiple matches, we'll throw
        # an error.
        if (structure_dict['posfile'] is not None): # Do we have a geometry file?
            # TTM for issue #423
            posfiletry = os.path.join(os.getcwd(), structure_dict['posfile'])
            if os.path.isfile(posfiletry):
                self.logger.info("Using posfile %s in directory %s" % (structure_dict['posfile'], os.getcwd()))
            else:
                # First build a list of likely files
                origindir = os.path.dirname(self.keywords['inputfile'])
                if origindir == "":
                    origindir = os.getcwd()
                metatry = os.path.join(os.getcwd(), 'metadata.txt')
                if os.path.isfile(metatry):
                    myrecipemeta = Metadata(metafile=metatry)
                    origindir = myrecipemeta.search_data('origin_dir')[1]
                myfiles = dirutil.walkfiles(origindir)
                file_list=list()
                for myfile in myfiles:
                    if structure_dict['posfile'] in myfile:
                        file_list.append(myfile)
                if (len(file_list) > 1):
                    # If we have multiple files with the same name, but different capitalization, throw an error here
                    self.logger.warning('Found multiple files with the name %s' % structure_dict['posfile'])
                    self.logger.warning('Found the files:')
                    for file in file_list:
                        self.logger.warning(file)
                    error='Found ambiguous file names'
                    raise MASTError(self.__class__.__name__, error)
                elif len(file_list) == 0:
                    raise MASTError(self.__class__.__name__, "No structure file %s found in %s" % (structure_dict['posfile'], origindir))
                else:
                    structure_dict['posfile'] = file_list[0]
        # print 'in InputParser.parse_structure_section:', subsection_dict
        # TM
        element_map = dict()
        atom_list = list()
        for key, value in subsection_dict.items():
            if (key == 'coordinates'):
                value = np.array(value)
                # Here we use .title() to re-capitalize the first letter of all 
                # the atomic symbols to comply with what
                # pymatgen needs
                atom_list = [val.title() for val in value[:, 0]]
                structure_dict['atom_list'] = atom_list
                coordinates = np.array(value[:, 1:], dtype='float')
                structure_dict['coordinates'] = coordinates
            if (key == 'lattice'):
                #print "VALUE: ", value
                lattice = np.array(value, dtype='float')
                structure_dict['lattice'] = lattice
            if (key == 'elementmap'):
                for elline in value:
                    elkey = elline[0].strip().upper() #all caps
                    elname = elline[1].strip().title() #Title case
                    element_map[elkey]=elname
                structure_dict['element_map'] = element_map
        if len(element_map) > 0 and len(atom_list) > 0:
            new_atom_list = list()
            for atomval in atom_list:
                if atomval.upper() in element_map.keys():
                    new_atom_list.append(element_map[atomval])
                else:
                    new_atom_list.append(atomval)
            structure_dict['atom_list'] = new_atom_list

        for key, value in structure_dict.items():
            options.set_item(section_name, key, value)