Exemplo n.º 1
0
 def test_zopen(self):
     with zopen(os.path.join(test_dir, "myfile_gz.gz"), mode="rt") as f:
         self.assertEqual(f.read(), "HelloWorld.\n\n")
     with zopen(os.path.join(test_dir, "myfile_bz2.bz2"), mode="rt") as f:
         self.assertEqual(f.read(), "HelloWorld.\n\n")
     with zopen(os.path.join(test_dir, "myfile_bz2.bz2"), "rt") as f:
         self.assertEqual(f.read(), "HelloWorld.\n\n")
     with zopen(os.path.join(test_dir, "myfile"), mode="rt") as f:
         self.assertEqual(f.read(), "HelloWorld.\n\n")
Exemplo n.º 2
0
def read_mol(filename):
    """
    Reads a molecule based on file extension. For example, anything ending in
    a "xyz" is assumed to be a XYZ file. Supported formats include xyz,
    gaussian input (gjf|g03|g09|com|inp), Gaussian output (.out|and
    pymatgen's JSON serialized molecules. Using openbabel,
    many more extensions are supported but requires openbabel to be installed.

    Args:
        filename (str): A filename to read from.

    Returns:
        A Molecule object.
    """
    fname = os.path.basename(filename)
    if fnmatch(fname.lower(), "*.xyz*"):
        return XYZ.from_file(filename).molecule
    elif any([fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["gjf", "g03", "g09", "com", "inp"]]):
        return GaussianInput.from_file(filename).molecule
    elif any([fnmatch(fname.lower(), "*.{}*".format(r)) for r in ["out", "lis", "log"]]):
        return GaussianOutput(filename).final_structure
    elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"):
        with zopen(filename) as f:
            s = json.load(f, cls=MontyDecoder)
            if type(s) != Molecule:
                raise IOError("File does not contain a valid serialized " "molecule")
            return s
    else:
        m = re.search("\.(pdb|mol|mdl|sdf|sd|ml2|sy2|mol2|cml|mrv)", filename.lower())
        if m:
            return BabelMolAdaptor.from_file(filename, m.group(1)).pymatgen_mol

    raise ValueError("Unrecognized file extension!")
Exemplo n.º 3
0
    def atoms_string_from_file(filename):
        """
        Reads atomic shells from file such as feff.inp or ATOMS file
        The lines are arranged as follows:

        x y z   ipot    Atom Symbol   Distance   Number

        with distance being the shell radius and ipot an integer identifying
        the potential used.

        Args:
            filename: File name containing atomic coord data.

        Returns:
            Atoms string.
        """
        with zopen(filename, "r") as fobject:
            f = fobject.readlines()
            coords = 0
            atoms_str = []

            for line in f:
                if coords == 0:
                    find_atoms = line.find("ATOMS")
                    if find_atoms >= 0:
                        coords = 1
                if coords == 1:
                    atoms_str.append(line.replace("\r", ""))

        return ''.join(atoms_str)
Exemplo n.º 4
0
 def run(self):
     """
     Performs actual nwchem run.
     """
     with zopen(self.output_file, 'w') as fout:
         return subprocess.Popen(self.nwchem_cmd + [self.input_file],
                                 stdout=fout)
Exemplo n.º 5
0
 def test_potcar_map(self):
     fe_potcar = zopen(os.path.join(test_dir, "POT_GGA_PAW_PBE", "POTCAR.Fe_pv.gz")).read().decode("utf-8")
     # specify V instead of Fe - this makes sure the test won't pass if the
     # code just grabs the POTCAR from the config file (the config file would
     # grab the V POTCAR)
     potcar = Potcar(["V"], sym_potcar_map={"V": fe_potcar})
     self.assertEqual(potcar.symbols, ["Fe_pv"], "Wrong symbols read in " "for POTCAR")
Exemplo n.º 6
0
    def read(self):
        """Read all snapshots from each dump file."""
        for dumpfile in self.dumpfiles:
            with zopen(dumpfile) as f:
                snapshot = self.read_snapshot(f)
                while snapshot is not None:
                    self.trajectory.append(snapshot)
                    print(snapshot.timestep, end=' ')
                    sys.stdout.flush()
                    snapshot = self.read_snapshot(f)
        print()

        self.trajectory.sort(key=attrgetter('timestep'))
        self.trajectory.cull()

        print("read {:d} snapshots".format(self.Nsnaps))

        self.trajectory.time_selection.all()
        self.trajectory.t0_snapshot = self.trajectory[0]

        if self.dumpattrs:
            print('Dumped Atom attributes: {}'.format(self.dumpattrs2str()))
        else:
            print('No dump column assignments')

        if 'x' not in self.dumpattrs or 'y' not in self.dumpattrs or \
                'z' not in self.dumpattrs:
            print('dump scaling status unknown')
        elif self.Nsnaps > 0:
            if self.scale_original:
                self.unscale()
            elif self.scale_original is None:
                print('dump scaling status unknown')
            else:
                print('dump is already unscaled')
Exemplo n.º 7
0
    def __init__(self, filename, parse_box=True, dtype=float):
        """

        Args:
            filename (str): Filename to parse. The timestep wildcard
                ('*') is supported and the files are parsed in the
                sequence of timestep.
            parse_box (bool): Whether parse box info for each step.
                Default to True.
            dtype: np.dtype for atoms data array.

        """
        self.filename = filename
        self.parse_box = parse_box
        self.dtype = dtype

        fnames = glob.glob(self.filename)
        if len(fnames) > 1:
            pattern = r"%s" % filename.replace("*", "([0-9]+)")
            pattern = pattern.replace("\\", "\\\\")
            fnames = sorted(fnames,
                            key=lambda f: int(re.match(pattern, f).group(1)))
        steps = []
        for fname in fnames:
            with zopen(fname, "rt") as f:
                run = f.read()
            dumps = run.split("ITEM: TIMESTEP")[1:]
            steps.extend([self._parse_timestep(d) for d in dumps])
        self.steps = steps
        self.timesteps = [s["timestep"] for s in self.steps]
Exemplo n.º 8
0
    def gw_run(self):
        """
        Performs FIESTA (gw) run
        """

        if self.folder != os.getcwd():
            init_folder = os.getcwd()
            os.chdir(self.folder)

        with zopen(self.log_file, "w") as fout:
            subprocess.call(
                [
                    "mpirun",
                    "-n",
                    str(self.mpi_procs),
                    "fiesta",
                    str(self.grid[0]),
                    str(self.grid[1]),
                    str(self.grid[2]),
                ],
                stdout=fout,
            )

        if self.folder != os.getcwd():
            os.chdir(init_folder)
Exemplo n.º 9
0
def parse_lammps_dumps(file_pattern):
    """
    Generator that parses dump file(s).

    Args:
        file_pattern (str): Filename to parse. The timestep wildcard
            (e.g., dump.atom.'*') is supported and the files are parsed
            in the sequence of timestep.

    Yields:
        LammpsDump for each available snapshot.

    """
    files = glob.glob(file_pattern)
    if len(files) > 1:
        pattern = r"%s" % file_pattern.replace("*", "([0-9]+)")
        pattern = pattern.replace("\\", "\\\\")
        files = sorted(files,
                       key=lambda f: int(re.match(pattern, f).group(1)))

    for fname in files:
        with zopen(fname, "rt") as f:
            dump_cache = []
            for line in f:
                if line.startswith("ITEM: TIMESTEP"):
                    if len(dump_cache) > 0:
                        yield LammpsDump.from_string("".join(dump_cache))
                    dump_cache = [line]
                else:
                    dump_cache.append(line)
            yield LammpsDump.from_string("".join(dump_cache))
Exemplo n.º 10
0
def dumpfn(obj, fn, *args, **kwargs):
    """
    Dump to a json/yaml directly by filename instead of a File-like object.
    For YAML, PyYAML must be installed. The file type is automatically
    detected. YAML is assumed if the filename contains "yaml" (lower or upper
    case). Otherwise, json is always assumed. Furthermore, if pyyaml is
    compiled with the LibYAML library, the CDumper is automatically chosen
    for ~10x faster parsing.

    Args:
        obj (object): Object to dump.
        fn (str): filename.
        \*args: Any of the args supported by json/yaml.dump.
        \*\*kwargs: Any of the kwargs supported by json/yaml.dump.

    Returns:
        (object) Result of json.load.
    """
    with zopen(fn, "wt") as fp:
        if "yaml" in fn.lower():
            if yaml is None:
                raise RuntimeError("Loading of YAML files is not "
                                   "possible as PyYAML is not installed.")
            if "Dumper" not in kwargs:
                kwargs["Dumper"] = Dumper
            yaml.dump(obj, fp, *args, **kwargs)
        else:
            fp.write("%s" % json.dumps(obj, *args, **kwargs))
Exemplo n.º 11
0
def loadfn(fn, *args, **kwargs):
    """
    Loads json/yaml directly from a filename instead of a File-like object.
    For YAML, PyYAML must be installed. The file type is automatically
    detected. YAML is assumed if the filename contains "yaml" (lower or upper
    case). Otherwise, json is always assumed. Furthermore, if pyyaml is
    compiled with the LibYAML library, the CLoader is automatically chosen
    for ~10x faster parsing.

    Args:
        fn (str): filename
        \*args: Any of the args supported by json/yaml.load.
        \*\*kwargs: Any of the kwargs supported by json/yaml.load.

    Returns:
        (object) Result of json/yaml.load.
    """
    with zopen(fn) as fp:
        if "yaml" in fn.lower():
            if yaml is None:
                raise RuntimeError("Loading of YAML files is not "
                                   "possible as PyYAML is not installed.")
            if "Loader" not in kwargs:
                kwargs["Loader"] = Loader
            return yaml.load(fp, *args, **kwargs)
        else:
            return json.load(fp, *args, **kwargs)
Exemplo n.º 12
0
def read_structure(filename):
    """
    Reads a structure based on file extension. For example, anything ending in
    a "cif" is assumed to be a Crystallographic Information Format file.
    Supported formats include CIF, POSCAR/CONTCAR, CHGCAR, LOCPOT,
    vasprun.xml, CSSR and pymatgen's JSON serialized structures.

    Args:
        filename (str): A filename to read from.

    Returns:
        A Structure object.
    """
    fname = os.path.basename(filename)
    if fnmatch(fname.lower(), "*.cif*"):
        parser = CifParser(filename)
        return parser.get_structures(True)[0]
    elif fnmatch(fname, "POSCAR*") or fnmatch(fname, "CONTCAR*"):
        return Poscar.from_file(filename, False).structure
    elif fnmatch(fname, "CHGCAR*") or fnmatch(fname, "LOCPOT*"):
        return Chgcar.from_file(filename).structure
    elif fnmatch(fname, "vasprun*.xml*"):
        return Vasprun(filename).final_structure
    elif fnmatch(fname.lower(), "*.cssr*"):
        cssr = Cssr.from_file(filename)
        return cssr.structure
    elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"):
        with zopen(filename) as f:
            s = json.load(f, cls=PMGJSONDecoder)
            if type(s) != Structure:
                raise IOError("File does not contain a valid serialized "
                              "structure")
            return s
    raise ValueError("Unrecognized file extension!")
Exemplo n.º 13
0
def write_mol(mol, filename):
    """
    Write a molecule to a file based on file extension. For example, anything
    ending in a "xyz" is assumed to be a XYZ file. Supported formats include
    xyz, Gaussian input (gjf|g03|g09|com|inp), and pymatgen's JSON serialized
    molecules.

    Args:
        mol (Molecule/IMolecule): Molecule to write
        filename (str): A filename to write to.
    """
    fname = os.path.basename(filename)
    if fnmatch(fname.lower(), "*.xyz*"):
        return XYZ(mol).write_file(filename)
    elif any([fnmatch(fname.lower(), "*.{}*".format(r))
              for r in ["gjf", "g03", "g09", "com", "inp"]]):
        return GaussianInput(mol).write_file(filename)
    elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"):
        with zopen(filename, "wt") as f:
            return f.write(str2unicode(json.dumps(mol, cls=MontyEncoder)))
    else:
        m = re.search("\.(pdb|mol|mdl|sdf|sd|ml2|sy2|mol2|cml|mrv)",
                      filename.lower())
        if m:
            return BabelMolAdaptor(mol).write_file(filename, m.group(1))

    raise ValueError("Unrecognized file extension!")
Exemplo n.º 14
0
def write_structure(structure, filename):
    """
    Write a structure to a file based on file extension. For example, anything
    ending in a "cif" is assumed to be a Crystallographic Information Format
    file. Supported formats include CIF, POSCAR, CSSR and pymatgen's JSON
    serialized structures.

    Args:
        structure (Structure/IStructure): Structure to write
        filename (str): A filename to write to.
    """
    fname = os.path.basename(filename)
    if fnmatch(fname, "*.cif*"):
        writer = CifWriter(structure)
    elif fnmatch(fname, "POSCAR*") or fnmatch(fname, "CONTCAR*"):
        writer = Poscar(structure)
    elif fnmatch(fname.lower(), "*.cssr*"):
        writer = Cssr(structure)
    elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"):
        with zopen(filename, "wt") as f:
            f.write(str2unicode(json.dumps(structure, cls=MontyEncoder)))
            return
    else:
        raise ValueError("Unrecognized file extension!")

    writer.write_file(filename)
Exemplo n.º 15
0
    def read_excitation_energies(self):
        """
        Read a excitation energies after a TD-DFT calculation.

        Returns:

            A list: A list of tuple for each transition such as 
                    [(energie (eV), lambda (nm), oscillatory strength), ... ]
        """
        float_patt = re.compile("\s*([+-]?\d+\.\d+)")

        transitions = list()

        # read in file
        with zopen(self.filename, "r") as f:
            line = f.readline()
            td = False
            while line != "":
                if re.search("^\sExcitation energies and oscillator strengths:", line):
                    td = True
   
                if td:
                    if re.search("^\sExcited State\s*\d", line):
                        val = [float(v) for v in float_patt.findall(line)]
                        transitions.append(tuple(val[0:3]))
                line = f.readline()
        return transitions
Exemplo n.º 16
0
def store_dataframe_as_json(dataframe, filename, compression=None,
                            orient='split'):
    """Store pandas dataframe as a json file.

    Automatically encodes pymatgen objects as dictionaries.

    Args:
        dataframe (Pandas.Dataframe): A pandas dataframe.
        filename (str): Path to json file.
        compression (str or None): A compression mode. Valid options are "gz",
            "bz2", and None. Defaults to None. If the filename does not end
            in with the correct suffix it will be added automatically.
        orient (str): Determines the format in which the dictionary data is
            stored. This takes the same set of arguments as the `orient` option
            in `pandas.DataFrame.to_dict()` function. 'split' is recommended
            as it is relatively space efficient and preserves the dtype
            of the index.
    """
    if compression not in ["gz", "bz2", None]:
        raise ValueError("Supported compression formats are 'gz' and 'bz2'.")

    if compression and not filename.lower().endswith(".{}".format(compression)):
        filename = "{}.{}".format(filename, compression)

    write_type = "wb" if compression else "w"

    with zopen(filename, write_type) as f:
        data = json.dumps(dataframe.to_dict(orient=orient), cls=MontyEncoder)
        if compression:
            data = data.encode()
        f.write(data)
Exemplo n.º 17
0
    def __init__(self, are_coops=False, filename=None):
        self.are_coops = are_coops
        if filename is None:
            filename = "COOPCAR.lobster" if are_coops \
                        else "COHPCAR.lobster"

        with zopen(filename, "rt") as f:
            contents = f.read().split("\n")

        # The parameters line is the second line in a COHPCAR file. It
        # contains all parameters that are needed to map the file.
        parameters = contents[1].split()
        # Subtract 1 to skip the average
        num_bonds = int(parameters[0]) - 1
        self.efermi = float(parameters[-1])
        if int(parameters[1]) == 2:
            spins = [Spin.up, Spin.down]
            self.is_spin_polarized = True
        else:
            spins = [Spin.up]
            self.is_spin_polarized = False

        # The COHP data start in row num_bonds + 3
        data = np.array([np.array(row.split(), dtype=float)
                         for row in contents[num_bonds+3:]]).transpose()
        self.energies = data[0]

        cohp_data = {"average": {"COHP": {spin: data[1+2*s*(num_bonds+1)]
                                          for s, spin in enumerate(spins)},
                                 "ICOHP": {spin: data[2+2*s*(num_bonds+1)]
                                           for s, spin in enumerate(spins)}}}
        orb_cohp = {}
        for bond in range(num_bonds):
            bond_data = self._get_bond_data(contents[3+bond])
            label = bond_data["label"]
            orbs = bond_data["orbitals"]
            cohp = {spin: data[2*(bond+s*(num_bonds+1))+3]
                    for s, spin in enumerate(spins)}
            icohp = {spin: data[2*(bond+s*(num_bonds+1))+4]
                     for s, spin in enumerate(spins)}
            if orbs is None:
                cohp_data[label] = {"COHP": cohp, "ICOHP": icohp,
                                    "length": bond_data["length"],
                                    "sites": bond_data["sites"]}
            elif label in orb_cohp:
                orb_cohp[label].update({bond_data["orb_label"]:
                                        {"COHP": cohp, "ICOHP": icohp,
                                         "orbitals": orbs}})
            else:
                if label not in cohp_data:
                    cohp_data[label] = {"COHP": None, "ICOHP": None,
                                        "length": bond_data["length"],
                                        "sites": bond_data["sites"]}
                orb_cohp[label] = {bond_data["orb_label"]: {"COHP": cohp,
                                                            "ICOHP": icohp,
                                                            "orbitals": orbs}}

        self.orb_res_cohp = orb_cohp if orb_cohp else None
        self.cohp_data = cohp_data
Exemplo n.º 18
0
    def write_file(self, filename,cart_coords=False):
        """
        Write the input string into a file

        Option: see __str__ method
        """
        with zopen(filename, "w") as f:
            f.write(self.to_string(cart_coords))
Exemplo n.º 19
0
    def __init__(self, filename):
        self.filename = filename

        with zopen(filename) as f:
            log_bse = f.read()

        # self.job_info = self._parse_preamble(preamble)
        self.exiton = self._parse_job(log_bse)
Exemplo n.º 20
0
 def from_multi_jobs_file(cls, filename):
     # returns a list of QCInput objects
     with zopen(filename, 'rt') as f:
         # the delimiter between QChem jobs is @@@
         multi_job_strings = f.read().split("@@@")
         # list of individual QChem jobs
         input_list = [cls.from_string(i) for i in multi_job_strings]
         return input_list
Exemplo n.º 21
0
    def write_file(self, filename):
        """
        Write out an xr file.

        Args:
            filename (str): name of the file to write to.
        """
        with zopen(filename, 'wt') as f:
            f.write(str(self) + "\n")
Exemplo n.º 22
0
    def write_file(self, filename='POTENTIALS'):
        """
        Write to file.

        Args:
            filename: filename and path to write potential file to.
        """
        with zopen(filename, "wt") as f:
            f.write(str(self) + "\n")
Exemplo n.º 23
0
 def __init__(self, filename, occupancy_tolerance=1.):
     self._occupancy_tolerance = occupancy_tolerance
     if isinstance(filename, basestring):
         with zopen(filename, "r") as f:
             # We use this round-about way to clean up the CIF first.
             stream = cStringIO.StringIO(_clean_cif(f.read()))
             self._cif = CifFile.ReadCif(stream)
     else:
         self._cif = CifFile.ReadCif(filename)
Exemplo n.º 24
0
    def write_file(self, filename):
        """
        Writes XYZ to file.

        Args:
            filename: File name of output file.
        """
        with zopen(filename, "wt") as f:
            f.write(self.__str__())
Exemplo n.º 25
0
    def write_file(self, filename='ATOMS'):
        """
        Write Atoms list to file.

        Args:
           filename: path for file to be written
        """
        with zopen(filename, "wt") as f:
            f.write(str(self) + "\n")
Exemplo n.º 26
0
    def __init__(self, filename):
        self.filename = filename

        with zopen(filename) as f:
            basis_set = f.read()

        self.data = self._parse_file(basis_set)
        # compute the number of nlm orbitals per atom
        self.data.update(n_nlmo=self.set_n_nlmo())
Exemplo n.º 27
0
    def write_file(self, filename):
        """
        Write out a CSSR file.

        Args:
            filename (str): Filename to write to.
        """
        with zopen(filename, 'wt') as f:
            f.write(str(self) + "\n")
Exemplo n.º 28
0
    def write_file(self, filename='PARAMETERS'):
        """
        Write Tags to a Feff parameter tag file.

        Args:
            filename: filename and path to write to.
        """
        with zopen(filename, "wt") as f:
            f.write(self.__str__() + "\n")
Exemplo n.º 29
0
    def charge_transfer_from_file(filename1, filename2):
        """
        Get charge transfer from file.

        Args:
            filename1: name of feff.inp file for run
            filename2: ldos filename for run, assume consequetive order, .i.e.,
                ldos01.dat, ldos02.dat....

        Returns:
            dictionary of dictionaries in order of potential sites
            ({"p": 0.154, "s": 0.078, "d": 0.0, "tot": 0.232}, ...)
        """
        cht = OrderedDict()
        pot_string = FeffPot.pot_string_from_file(filename1)
        dicts = FeffPot.pot_dict_from_string(pot_string)
        pot_dict = dicts[1]

        for i in range(0, len(dicts[0]) + 1):
            if len(str(i)) == 1:
                with zopen("{}0{}.dat".format(filename2, i), "r") \
                        as fobject:
                    f = fobject.readlines()
                    s = float(f[3].split()[2])
                    p = float(f[4].split()[2])
                    d = float(f[5].split()[2])
                    f1 = float(f[6].split()[2])
                    tot = float(f[1].split()[4])
                    cht[str(i)] = {pot_dict[i]: {'s': s, 'p': p, 'd': d,
                                                 'f': f1,
                                   'tot': tot}}
            else:
                with zopen(filename2 + str(i) + ".dat", "r") as fid:
                    f = fid.readlines()
                    s = float(f[3].split()[2])
                    p = float(f[4].split()[2])
                    d = float(f[5].split()[2])
                    f1 = float(f[6].split()[2])
                    tot = float(f[1].split()[4])
                    cht[str(i)] = {pot_dict[i]: {'s': s, 'p': p, 'd': d,
                                                 'f': f1,
                                   'tot': tot}}

        return cht
Exemplo n.º 30
0
    def update_checkpoint(launchpad, launch_dir, launch_id, checkpoint):
        """
        Helper function to update checkpoint

        Args:
            launchpad (LaunchPad): LaunchPad to ping with checkpoint data
            launch_dir (str): directory in which FW_offline.json was created
            launch_id (int): launch id to update
            checkpoint (dict): checkpoint data
        """
        if launchpad:
            launchpad.ping_launch(launch_id, checkpoint=checkpoint)
        else:
            fpath = zpath("FW_offline.json")
            with zopen(fpath) as f_in:
                d = json.loads(f_in.read())
                d['checkpoint'] = checkpoint
                with zopen(fpath, "wt") as f_out:
                    f_out.write(json.dumps(d, ensure_ascii=False))
Exemplo n.º 31
0
 def from_file(cls, filename):
     with zopen(filename, "rt") as f:
         return cls.from_string(f.read())
Exemplo n.º 32
0
 def write_file(self, filename):
     """
     Write the cif file.
     """
     with zopen(filename, "wt") as f:
         f.write(self.__str__())
Exemplo n.º 33
0
 def load_data(self, filename):
     """
     Load assimilated data from a file
     """
     with zopen(filename, "rt") as f:
         self._data = json.load(f, cls=MontyDecoder)
Exemplo n.º 34
0
    def __init__(self, are_coops=False, filename=None):
        self.are_coops = are_coops
        if filename is None:
            filename = "COOPCAR.lobster" if are_coops \
                else "COHPCAR.lobster"

        with zopen(filename, "rt") as f:
            contents = f.read().split("\n")

        # The parameters line is the second line in a COHPCAR file. It
        # contains all parameters that are needed to map the file.
        parameters = contents[1].split()
        # Subtract 1 to skip the average
        num_bonds = int(parameters[0]) - 1
        self.efermi = float(parameters[-1])
        if int(parameters[1]) == 2:
            spins = [Spin.up, Spin.down]
            self.is_spin_polarized = True
        else:
            spins = [Spin.up]
            self.is_spin_polarized = False

        # The COHP data start in row num_bonds + 3
        data = np.array([
            np.array(row.split(), dtype=float)
            for row in contents[num_bonds + 3:]
        ]).transpose()
        self.energies = data[0]

        cohp_data = {
            "average": {
                "COHP": {
                    spin: data[1 + 2 * s * (num_bonds + 1)]
                    for s, spin in enumerate(spins)
                },
                "ICOHP": {
                    spin: data[2 + 2 * s * (num_bonds + 1)]
                    for s, spin in enumerate(spins)
                }
            }
        }
        orb_cohp = {}
        for bond in range(num_bonds):
            bond_data = self._get_bond_data(contents[3 + bond])
            label = bond_data["label"]
            orbs = bond_data["orbitals"]
            cohp = {
                spin: data[2 * (bond + s * (num_bonds + 1)) + 3]
                for s, spin in enumerate(spins)
            }
            icohp = {
                spin: data[2 * (bond + s * (num_bonds + 1)) + 4]
                for s, spin in enumerate(spins)
            }
            if orbs is None:
                cohp_data[label] = {
                    "COHP": cohp,
                    "ICOHP": icohp,
                    "length": bond_data["length"],
                    "sites": bond_data["sites"]
                }
            elif label in orb_cohp:
                orb_cohp[label].update({
                    bond_data["orb_label"]: {
                        "COHP": cohp,
                        "ICOHP": icohp,
                        "orbitals": orbs
                    }
                })
            else:
                if label not in cohp_data:
                    cohp_data[label] = {
                        "COHP": None,
                        "ICOHP": None,
                        "length": bond_data["length"],
                        "sites": bond_data["sites"]
                    }
                orb_cohp[label] = {
                    bond_data["orb_label"]: {
                        "COHP": cohp,
                        "ICOHP": icohp,
                        "orbitals": orbs
                    }
                }

        self.orb_res_cohp = orb_cohp if orb_cohp else None
        self.cohp_data = cohp_data
Exemplo n.º 35
0
    def __init__(
        self,
        chgcar_filename=None,
        potcar_filename=None,
        chgref_filename=None,
        parse_atomic_densities=False,
        cube_filename=None,
    ):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.

            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered

        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")

        if not (cube_filename or chgcar_filename):
            raise ValueError(
                "You must provide a file! Either a cube file or a CHGCAR")
        if cube_filename and chgcar_filename:
            raise ValueError(
                "You cannot parse a cube and a CHGCAR at the same time!")

        self.parse_atomic_densities = parse_atomic_densities

        if chgcar_filename:
            fpath = os.path.abspath(chgcar_filename)
            self.is_vasp = True
            self.chgcar = Chgcar.from_file(chgcar_filename)
            self.structure = self.chgcar.structure
            self.potcar = Potcar.from_file(
                potcar_filename) if potcar_filename is not None else None
            self.natoms = self.chgcar.poscar.natoms
            chgrefpath = os.path.abspath(
                chgref_filename) if chgref_filename else None
            self.reference_used = bool(chgref_filename)

            # List of nelects for each atom from potcar
            potcar_indices = []
            for i, v in enumerate(self.natoms):
                potcar_indices += [i] * v
            self.nelects = ([
                self.potcar[potcar_indices[i]].nelectrons
                for i in range(len(self.structure))
            ] if self.potcar else [])

        else:
            fpath = os.path.abspath(cube_filename)
            self.is_vasp = False
            self.cube = Cube(fpath)
            self.structure = self.cube.structure
            self.nelects = None
            chgrefpath = os.path.abspath(
                chgref_filename) if chgref_filename else None
            self.reference_used = bool(chgref_filename)

        tmpfile = "CHGCAR" if chgcar_filename else "CUBE"
        with ScratchDir("."):
            with zopen(fpath, "rt") as f_in:
                with open(tmpfile, "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, tmpfile]
            if chgref_filename:
                with zopen(chgrefpath, "rt") as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ["-ref", "CHGCAR_ref"]
            if parse_atomic_densities:
                args += ["-p", "all_atom"]
            with subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True) as rs:
                stdout, stderr = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError(
                    "bader exited with return code %d. Please check your bader installation."
                    % rs.returncode)

            try:
                self.version = float(stdout.split()[5])
            except ValueError:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn(
                    "Your installed version of Bader is outdated, calculation of vacuum charge may be incorrect."
                )

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ("x", "y", "z", "charge", "min_dist", "atomic_vol")
                raw.pop(0)
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge denisty for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [
                    Chgcar.from_file(f"BvAt{str(i).zfill(4)}.dat")
                    for i in range(1,
                                   len(self.chgcar.structure) + 1)
                ]

                atomic_densities = []
                # For each atom in the structure
                for atom, loc, chg in zip(
                        self.chgcar.structure,
                        self.chgcar.structure.frac_coords,
                        atom_chgcars,
                ):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data["total"]
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth,
                                    starty:starty + ywidth,
                                    startz:startz + zwidth, ]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data, prec=1e-3):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data, i, i, i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim,
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
Exemplo n.º 36
0
 def write_file(self, filename):
     with zopen(filename, "w") as f:
         f.write(self.__str__())
Exemplo n.º 37
0
 def from_file(filename):
     with zopen(filename, 'rt') as f:
         data=f.read().replace('\n','')
     return ExcitingInput.from_string(data)
Exemplo n.º 38
0
    def read_scan(self):
        """
        Read a potential energy surface from a gaussian scan calculation.

        Returns:

            A dict: {"energies": [ values ],
                     "coords": {"d1": [ values ], "A2", [ values ], ... }}

            "energies" are the energies of all points of the potential energy
            surface. "coords" are the internal coordinates used to compute the
            potential energy surface and the internal coordinates optimized,
            labelled by their name as defined in the calculation.
        """
        def floatList(l):
            """ return a list of float from a list of string """
            return [float(v) for v in l]

        scan_patt = re.compile("^\sSummary of the potential surface scan:")
        optscan_patt = re.compile(
            "^\sSummary of Optimized Potential Surface Scan")

        # data dict return
        data = {"energies": list(), "coords": dict()}

        # read in file
        with zopen(self.filename, "r") as f:
            line = f.readline()

            while line != "":
                if optscan_patt.match(line):
                    f.readline()
                    line = f.readline()
                    endScan = False
                    while not endScan:
                        data["energies"] += floatList(float_patt.findall(line))
                        line = f.readline()
                        while not re.search("(^\s+(\d+)|^\s-+)", line):
                            icname = line.split()[0].strip()
                            if icname in data["coords"]:
                                data["coords"][icname] += floatList(
                                    float_patt.findall(line))
                            else:
                                data["coords"][icname] = floatList(
                                    float_patt.findall(line))
                            line = f.readline()
                        if re.search("^\s-+", line):
                            endScan = True
                        else:
                            line = f.readline()

                elif scan_patt.match(line):
                    line = f.readline()
                    data["coords"] = {
                        icname: list()
                        for icname in line.split()[1:-1]
                    }
                    f.readline()
                    line = f.readline()
                    while not re.search("^\s-+", line):
                        values = floatList(line.split())
                        data["energies"].append(values[-1])
                        for i, icname in enumerate(data["coords"]):
                            data["coords"][icname].append(values[i + 1])
                        line = f.readline()
                else:
                    line = f.readline()

        return data
Exemplo n.º 39
0
def tasks(test_dir):
    with zopen(test_dir / "test_si_tasks.json.gz") as f:
        data = json.load(f)

    return [TaskDocument(**d) for d in data]
Exemplo n.º 40
0
    def post_process(self, dir_name, d):
        """
        Post-processing for various files other than the vasprun.xml and OUTCAR.
        Looks for files: transformations.json and custodian.json. Modify this if other
        output files need to be processed.

        Args:
            dir_name:
                The dir_name.
            d:
                Current doc generated.
        """
        logger.info("Post-processing dir:{}".format(dir_name))
        fullpath = os.path.abspath(dir_name)
        # VASP input generated by pymatgen's alchemy has a transformations.json file that tracks
        # the origin of a particular structure. If such a file is found, it is inserted into the
        # task doc as d["transformations"]
        transformations = {}
        filenames = glob.glob(os.path.join(fullpath, "transformations.json*"))
        if len(filenames) >= 1:
            with zopen(filenames[0], "rt") as f:
                transformations = json.load(f)
                try:
                    m = re.match("(\d+)-ICSD",
                                 transformations["history"][0]["source"])
                    if m:
                        d["icsd_id"] = int(m.group(1))
                except Exception as ex:
                    logger.warning(
                        "Cannot parse ICSD from transformations file.")
                    pass
        else:
            logger.warning("Transformations file does not exist.")

        other_parameters = transformations.get("other_parameters")
        new_tags = None
        if other_parameters:
            # We don't want to leave tags or authors in the
            # transformations file because they'd be copied into
            # every structure generated after this one.
            new_tags = other_parameters.pop("tags", None)
            new_author = other_parameters.pop("author", None)
            if new_author:
                d["author"] = new_author
            if not other_parameters:  # if dict is now empty remove it
                transformations.pop("other_parameters")
        d["transformations"] = transformations

        # Calculations done using custodian has a custodian.json,
        # which tracks the jobs performed and any errors detected and fixed.
        # This is useful for tracking what has actually be done to get a
        # result. If such a file is found, it is inserted into the task doc
        # as d["custodian"]
        filenames = glob.glob(os.path.join(fullpath, "custodian.json*"))
        if len(filenames) >= 1:
            custodian = []
            for fname in filenames:
                with zopen(fname, "rt") as f:
                    custodian.append(json.load(f)[0])
            d["custodian"] = custodian
        # Convert to full uri path.
        if self.use_full_uri:
            d["dir_name"] = get_uri(dir_name)
        if new_tags:
            d["tags"] = new_tags

        # Calculations using custodian generate a *.orig file for the inputs
        # This is useful to know how the calculation originally started
        # if such files are found they are inserted into orig_inputs
        filenames = glob.glob(os.path.join(fullpath, "*.orig*"))

        if len(filenames) >= 1:
            d["orig_inputs"] = {}
            for f in filenames:
                if "INCAR.orig" in f:
                    d["orig_inputs"]["incar"] = Incar.from_file(f).as_dict()
                if "POTCAR.orig" in f:
                    d["orig_inputs"]["potcar"] = Potcar.from_file(f).as_dict()
                if "KPOINTS.orig" in f:
                    d["orig_inputs"]["kpoints"] = Kpoints.from_file(
                        f).as_dict()
                if "POSCAR.orig" in f:
                    d["orig_inputs"]["poscar"] = Poscar.from_file(f).as_dict()

        filenames = glob.glob(os.path.join(fullpath, "*.json*"))
        if self.store_additional_json and filenames:
            for filename in filenames:
                key = os.path.basename(filename).split('.')[0]
                if key != "custodian" and key != "transformations":
                    with zopen(filename, "rt") as f:
                        d[key] = json.load(f)

        logger.info("Post-processed " + fullpath)
Exemplo n.º 41
0
    def __init__(self,
                 chgcar_filename,
                 potcar_filename=None,
                 chgref_filename=None,
                 parse_atomic_densities=False):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.
            potcar_filename (str): Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
            chgref_filename (str): Optional. The filename of the reference
                CHGCAR, which calculated by AECCAR0 + AECCAR2. (See
                http://theory.cm.utexas.edu/henkelman/code/bader/ for details.)
            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered

        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)
        chgrefpath = os.path.abspath(
            chgref_filename) if chgref_filename else None
        self.reference_used = True if chgref_filename else False
        self.parse_atomic_densities = parse_atomic_densities
        with ScratchDir(".") as temp_dir:
            with zopen(chgcarpath, 'rt') as f_in:
                with open("CHGCAR", "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, "CHGCAR"]
            if chgref_filename:
                with zopen(chgrefpath, 'rt') as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ['-ref', 'CHGCAR_ref']
            if parse_atomic_densities:
                args += ['-p', 'all_atom']
            rs = subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True)
            stdout, stderr = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Please check your bader installation." %
                                   rs.returncode)

            try:
                self.version = float(stdout.split()[5])
            except:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn('Your installed version of Bader is outdated, '
                              'calculation of vacuum charge may be incorrect.')

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ('x', 'y', 'z', 'charge', 'min_dist', 'atomic_vol')
                raw.pop(0)
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge denisty for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [
                    Chgcar.from_file("BvAt{}.dat".format(str(i).zfill(4)))
                    for i in range(1,
                                   len(self.chgcar.structure) + 1)
                ]

                atomic_densities = []
                # For each atom in the structure
                for atom, loc, chg in zip(self.chgcar.structure,
                                          self.chgcar.structure.frac_coords,
                                          atom_chgcars):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data['total']
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth,
                                    starty:starty + ywidth,
                                    startz:startz + zwidth]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data, prec=1e-3):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data, i, i, i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
Exemplo n.º 42
0
    def run(self, pdb_on_exception=False):
        """
        Run the rocket (check out a job from the database and execute it)

        Args:
            pdb_on_exception (bool): whether to invoke the debugger on
                a caught exception.  Default False.
        """
        all_stored_data = {}  # combined stored data for *all* the Tasks
        all_update_spec = {}  # combined update_spec for *all* the Tasks
        all_mod_spec = []  # combined mod_spec for *all* the Tasks

        lp = self.launchpad
        launch_dir = os.path.abspath(os.getcwd())
        logdir = lp.get_logdir() if lp else None
        l_logger = get_fw_logger('rocket.launcher',
                                 l_dir=logdir,
                                 stream_level='INFO')

        # check a FW job out of the launchpad
        if lp:
            m_fw, launch_id = lp.checkout_fw(self.fworker, launch_dir,
                                             self.fw_id)
        else:  # offline mode
            m_fw = Firework.from_file(os.path.join(os.getcwd(), "FW.json"))

            # set the run start time
            with open('FW_offline.json', 'r+') as f:
                d = json.loads(f.read())
                d['started_on'] = datetime.utcnow().isoformat()
                f.seek(0)
                f.write(json.dumps(d))
                f.truncate()

            launch_id = None  # we don't need this in offline mode...

        if not m_fw:
            print("No FireWorks are ready to run and match query! {}".format(
                self.fworker.query))
            return False

        final_state = None
        ping_stop = None
        btask_stops = []

        try:
            if '_launch_dir' in m_fw.spec and lp:
                prev_dir = launch_dir
                launch_dir = os.path.expandvars(m_fw.spec['_launch_dir'])
                if not os.path.abspath(launch_dir):
                    launch_dir = os.path.normpath(
                        os.path.join(os.getcwd(), launch_dir))
                # thread-safe "mkdir -p"
                try:
                    os.makedirs(launch_dir)
                except OSError as exception:
                    if exception.errno != errno.EEXIST:
                        raise
                os.chdir(launch_dir)

                if not os.path.samefile(launch_dir, prev_dir):
                    lp.change_launch_dir(launch_id, launch_dir)

                if not os.listdir(prev_dir) and REMOVE_USELESS_DIRS:
                    try:
                        os.rmdir(prev_dir)
                    except:
                        pass

            recovery = m_fw.spec.get('_recovery', None)
            if recovery:
                recovery_dir = recovery.get('_prev_dir')
                recovery_mode = recovery.get('_mode')
                starting_task = recovery.get('_task_n')
                all_stored_data.update(recovery.get('_all_stored_data'))
                all_update_spec.update(recovery.get('_all_update_spec'))
                all_mod_spec.extend(recovery.get('_all_mod_spec'))
                if lp:
                    l_logger.log(
                        logging.INFO,
                        'Recovering from task number {} in folder {}.'.format(
                            starting_task, recovery_dir))
                if recovery_mode == 'cp' and launch_dir != recovery_dir:
                    if lp:
                        l_logger.log(
                            logging.INFO,
                            'Copying data from recovery folder {} to folder {}.'
                            .format(recovery_dir, launch_dir))
                    distutils.dir_util.copy_tree(recovery_dir,
                                                 launch_dir,
                                                 update=1)

            else:
                starting_task = 0
                files_in = m_fw.spec.get("_files_in", {})
                prev_files = m_fw.spec.get("_files_prev", {})
                for f in set(files_in.keys()).intersection(prev_files.keys()):
                    # We use zopen for the file objects for transparent handling
                    # of zipped files. shutil.copyfileobj does the actual copy
                    # in chunks that avoid memory issues.
                    with zopen(prev_files[f],
                               "rb") as fin, zopen(files_in[f], "wb") as fout:
                        shutil.copyfileobj(fin, fout)

            if lp:
                message = 'RUNNING fw_id: {} in directory: {}'.\
                    format(m_fw.fw_id, os.getcwd())
                l_logger.log(logging.INFO, message)

            # write FW.json and/or FW.yaml to the directory
            if PRINT_FW_JSON:
                m_fw.to_file('FW.json', indent=4)
            if PRINT_FW_YAML:
                m_fw.to_file('FW.yaml')

            my_spec = dict(
                m_fw.spec)  # make a copy of spec, don't override original
            my_spec["_fw_env"] = self.fworker.env

            # set up heartbeat (pinging the server that we're still alive)
            ping_stop = start_ping_launch(lp, launch_id)

            # start background tasks
            if '_background_tasks' in my_spec:
                for bt in my_spec['_background_tasks']:
                    btask_stops.append(start_background_task(bt, m_fw.spec))

            # execute the Firetasks!
            for t_counter, t in enumerate(m_fw.tasks[starting_task:],
                                          start=starting_task):
                checkpoint = {
                    '_task_n': t_counter,
                    '_all_stored_data': all_stored_data,
                    '_all_update_spec': all_update_spec,
                    '_all_mod_spec': all_mod_spec
                }
                self.update_checkpoint(lp, launch_id, checkpoint)

                if lp:
                    l_logger.log(logging.INFO, "Task started: %s." % t.fw_name)

                if my_spec.get("_add_launchpad_and_fw_id"):
                    t.fw_id = m_fw.fw_id
                    if FWData().MULTIPROCESSING:
                        # hack because AutoProxy manager can't access attributes
                        t.launchpad = LaunchPad.from_dict(
                            self.launchpad.to_dict())
                    else:
                        t.launchpad = self.launchpad

                if my_spec.get("_add_fworker"):
                    t.fworker = self.fworker

                try:
                    m_action = t.run_task(my_spec)
                except BaseException as e:
                    traceback.print_exc()
                    tb = traceback.format_exc()
                    stop_backgrounds(ping_stop, btask_stops)
                    do_ping(
                        lp,
                        launch_id)  # one last ping, esp if there is a monitor
                    # If the exception is serializable, save its details
                    if pdb_on_exception:
                        pdb.post_mortem()
                    try:
                        exception_details = e.to_dict()
                    except AttributeError:
                        exception_details = None
                    except BaseException as e:
                        if lp:
                            l_logger.log(
                                logging.WARNING,
                                "Exception couldn't be serialized: %s " % e)
                        exception_details = None

                    try:
                        m_task = t.to_dict()
                    except:
                        m_task = None

                    m_action = FWAction(stored_data={
                        '_message': 'runtime error during task',
                        '_task': m_task,
                        '_exception': {
                            '_stacktrace': tb,
                            '_details': exception_details
                        }
                    },
                                        exit=True)
                    m_action = self.decorate_fwaction(m_action, my_spec, m_fw,
                                                      launch_dir)

                    if lp:
                        final_state = 'FIZZLED'
                        lp.complete_launch(launch_id, m_action, final_state)
                    else:
                        with open('FW_offline.json', 'r+') as f:
                            d = json.loads(f.read())
                            d['fwaction'] = m_action.to_dict()
                            d['state'] = 'FIZZLED'
                            d['completed_on'] = datetime.utcnow().isoformat()
                            f.seek(0)
                            f.write(json.dumps(d))
                            f.truncate()

                    return True

                # read in a FWAction from a file, in case the task is not Python and cannot return
                # it explicitly
                if os.path.exists('FWAction.json'):
                    m_action = FWAction.from_file('FWAction.json')
                elif os.path.exists('FWAction.yaml'):
                    m_action = FWAction.from_file('FWAction.yaml')

                if not m_action:
                    m_action = FWAction()

                # update the global stored data with the data to store and update from this
                # particular Task
                all_stored_data.update(m_action.stored_data)
                all_update_spec.update(m_action.update_spec)
                all_mod_spec.extend(m_action.mod_spec)

                # update spec for next task as well
                my_spec.update(m_action.update_spec)
                for mod in m_action.mod_spec:
                    apply_mod(mod, my_spec)
                if lp:
                    l_logger.log(logging.INFO,
                                 "Task completed: %s " % t.fw_name)
                if m_action.skip_remaining_tasks:
                    break

            # add job packing info if this is needed
            if FWData().MULTIPROCESSING and STORE_PACKING_INFO:
                all_stored_data[
                    'multiprocess_name'] = multiprocessing.current_process(
                    ).name

            # perform finishing operation
            stop_backgrounds(ping_stop, btask_stops)
            for b in btask_stops:
                b.set()
            do_ping(lp, launch_id)  # one last ping, esp if there is a monitor
            # last background monitors
            if '_background_tasks' in my_spec:
                for bt in my_spec['_background_tasks']:
                    if bt.run_on_finish:
                        for task in bt.tasks:
                            task.run_task(m_fw.spec)

            m_action.stored_data = all_stored_data
            m_action.mod_spec = all_mod_spec
            m_action.update_spec = all_update_spec

            m_action = self.decorate_fwaction(m_action, my_spec, m_fw,
                                              launch_dir)

            if lp:
                final_state = 'COMPLETED'
                lp.complete_launch(launch_id, m_action, final_state)
            else:
                with open('FW_offline.json', 'r+') as f:
                    d = json.loads(f.read())
                    d['fwaction'] = m_action.to_dict()
                    d['state'] = 'COMPLETED'
                    d['completed_on'] = datetime.utcnow().isoformat()
                    f.seek(0)
                    f.write(json.dumps(d))
                    f.truncate()

            return True

        except LockedWorkflowError as e:
            l_logger.log(logging.DEBUG, traceback.format_exc())
            l_logger.log(
                logging.WARNING,
                "Firework {} reached final state {} but couldn't complete the update of "
                "the database. Reason: {}\nRefresh the WF to recover the result "
                "(lpad admin refresh -i {}).".format(self.fw_id, final_state,
                                                     e, self.fw_id))
            return True

        except:
            # problems while processing the results. high probability of malformed data.
            traceback.print_exc()
            stop_backgrounds(ping_stop, btask_stops)
            # restore initial state to prevent the raise of further exceptions
            if lp:
                lp.restore_backup_data(launch_id, m_fw.fw_id)

            do_ping(lp, launch_id)  # one last ping, esp if there is a monitor
            # the action produced by the task is discarded
            m_action = FWAction(stored_data={
                '_message': 'runtime error during task',
                '_task': None,
                '_exception': {
                    '_stacktrace': traceback.format_exc(),
                    '_details': None
                }
            },
                                exit=True)

            try:
                m_action = self.decorate_fwaction(m_action, my_spec, m_fw,
                                                  launch_dir)
            except:
                traceback.print_exc()

            if lp:
                try:
                    lp.complete_launch(launch_id, m_action, 'FIZZLED')
                except LockedWorkflowError as e:
                    l_logger.log(logging.DEBUG, traceback.format_exc())
                    l_logger.log(
                        logging.WARNING,
                        "Firework {} fizzled but couldn't complete the update of the database."
                        " Reason: {}\nRefresh the WF to recover the result "
                        "(lpad admin refresh -i {}).".format(
                            self.fw_id, final_state, e, self.fw_id))
                    return True
            else:
                with open('FW_offline.json', 'r+') as f:
                    d = json.loads(f.read())
                    d['fwaction'] = m_action.to_dict()
                    d['state'] = 'FIZZLED'
                    d['completed_on'] = datetime.utcnow().isoformat()
                    f.seek(0)
                    f.write(json.dumps(d))
                    f.truncate()

            return True
Exemplo n.º 43
0
    def write_cif(self):
        """
        Generates and writes a structure file (.cif) from SPuDS output.txt 
        """
        
        def parse_spuds_out(self): 
            """
            Read SPuDS output.txt and get predicted structure info
            Returns:
                site_list: list of lists of site info 
                           list([element, multiplicity, Wycoff label,
                           x-coord, y-coord, z-coord, site occupancy])
                a_len: SPuDS a lattice length (Ang)
                b_len: SPuDS b lattice length (Ang)
                c_len: SPuDS c lattice length (Ang) 
                alp: SPuDS alpha lattice angle (deg)
                bet: SPuDS beta lattice angle (deg)
                gam: SPuDS gamma lattice angle (deg)                
                
            """
            
            a_lat,b_lat,c_lat,alp,bet,gam = None,None,None,None,None,None
            dvdr = ['***********************************'+
                    '***********************************']
            site_list = []
            with open(os.path.join(self.SPuDS_dir,'output.txt'),'r') as f:
                linecount = 0
                count = 0
                for line in f:
                    linelist = line.split()
                    if linelist == dvdr:
                        count += 1                            
                    if count == 2:
                        if len(linelist) == 4:
                            if linelist[0] == 'Space' and linelist[1] == 'group':
                                # Get dict key for retrieving symmetry operations
                                self.symops_key = " ".join([linelist[2],linelist[3]])
                        if len(linelist) == 3:
                            # Get lattice lengths (Ang)
                            if linelist[0] == 'a':
                                a_lat = linelist[2]
                            if linelist[0] == 'b':
                                b_lat = linelist[2]
                            if linelist[0] == 'c':
                                c_lat = linelist[2] 
                            # Get lattice angles (deg)
                            if linelist[0] == 'alpha':
                                alp = linelist[2]
                            if linelist[0] == 'beta':
                                bet = linelist[2]
                            if linelist[0] == 'gamma':
                                gam = linelist[2]                    
                        if len(linelist) > 3:
                            # Get site_list
                            for el in self.ellist:
                                if linelist[0] == el:                                    
                                    if el == self.Xel:
                                        # Anion should be fully occupied
                                        occup = 1.00
                                    else:
                                        # Cations can be partially occupied
                                        occup = linelist[5]                                        
                                    multsite = re.split('(\d+)',linelist[1])
                                    mult = multsite[1]
                                    wycoff = multsite[2]
                                    x = linelist[2]
                                    y = linelist[3]
                                    z = linelist[4]
                                    # Append site info to site_list
                                    site_list.append([el,mult,wycoff,
                                                        x,y,z,occup])
                    linecount += 1
                f.close()
            
            # Add count labels to site_list
            elcounts = {}
            for d in site_list:
                for el in self.ellist:
                    if d[0] == el:
                        if el not in elcounts.keys():
                            elcounts[el] = 0
                        elcounts[el] += 1  
                          
            for k,v in elcounts.items():
                count = 1
                ii = 0
                for d in site_list:
                    if d[0] == k:
                        if v > 1:
                            label = k+str(count)
                            site_list[ii].insert(0,label)
                            count += 1
                        else:
                            label = k
                            site_list[ii].insert(0,label)
                    ii += 1


            return site_list, a_lat, b_lat, c_lat, alp, bet, gam
        
        def map_lattice_menu_1(self,a_len,b_len,c_len,alp,bet,gam):
            """
            Map to .cif compatible lattice parameters from SPuDS output.txt
            Args: 
                a_len: SPuDS a lattice length (Ang)
                b_len: SPuDS b lattice length (Ang)
                c_len: SPuDS c lattice length (Ang) 
                alp: SPuDS alpha lattice angle (deg)
                bet: SPuDS beta lattice angle (deg)
                gam: SPuDS gamma lattice angle (deg)
            Returns: 
                .cif compatible lattice parameters:
                a: a lattice length (Ang)
                b: b lattice length (Ang)
                c: c lattice length (Ang)
                alpha: alpha lattice angle (deg)
                beta: beta lattice angle (deg)
                gamma: gamma lattice angle (deg)                
            """
            # Lattice angles (deg)
            if self.tilt in [3,5,10,16,17,20,21,22,23]:
                alpha = 90
                beta = 90
                gamma = 90                 
            elif self.tilt == 13:
                alpha = 90
                beta = bet
                gamma = 90
            elif self.tilt == 14:
                alpha = 90
                beta = 90
                gamma = 120 
            # Lattice lengths (Ang)    
            if self.tilt in [3,23]:
                a = a_len
                b = a_len
                c = a_len
            elif self.tilt in [5,14,16,21,22]:
                a = a_len
                b = a_len
                c = c_len
            elif self.tilt in [10,13,17,20]:
                a = a_len
                b = b_len
                c = c_len                
 
            return a,b,c,alpha,beta,gamma    
        
        def make_cif(self):
            """
            Generates a pymatgen CifFile object using structure info parsed
            from SPuDS output.txt.
            Returns:
                cf: pymatgen CifFile object
            """
            # SPuDS ouput structure info
            site_list,a_lat,b_lat,c_lat,alp,bet,gam = parse_spuds_out(self)
            # Mapped lattice parameters to .cif compatibility
            a,b,c,alpha,beta,gamma = map_lattice_menu_1(self,
                                                        a_lat,b_lat,c_lat,
                                                        alp,bet,gam) 
            symd = self.symops_dict[self.symops_key] # symops dict data         
            # Create dict of .cif parameters                   
            data = {}
            data['_cell_length_a'] = a
            data['_cell_length_b'] = b
            data['_cell_length_c'] = c
            data['_cell_angle_alpha'] = alpha
            data['_cell_angle_beta'] = beta
            data['_cell_angle_gamma'] = gamma
            data['_space_group_name_H-M_alt'] = symd['name']
            data['_symmetry_Int_tables_number'] = symd['number']
            data['_symmetry_cell_setting'] = symd['latsym']        
            data['_space_group_symop_operation_xyz'] = symd['symops']        
            data['_atom_type_symbol'] = self.ellist
            data['_atom_type_oxidation_number'] = self.oxilist
                    
            data['_atom_site_label'] = [d[0] for d in site_list]
            data['_atom_site_type_symbol'] = [d[1] for d in site_list]
            data['_atom_site_symmetry_multiplicity'] = [d[2] for d in site_list]
            data['_atom_site_Wycoff_symbol'] = [d[3] for d in site_list]
            data['_atom_site_fract_x'] = [d[4] for d in site_list]
            data['_atom_site_fract_y'] = [d[5] for d in site_list]
            data['_atom_site_fract_z'] = [d[6] for d in site_list]
            data['_atom_site_occupancy'] = [d[7] for d in site_list]
            # .cif file header
            cif_header = 'SPuDS'
            # .cif file loops
            cif_loops = [['_space_group_symop_operation_xyz'],                        
                        ['_atom_type_symbol','_atom_type_oxidation_number'],                      
                        ['_atom_site_label','_atom_site_type_symbol',
                          '_atom_site_symmetry_multiplicity',
                          '_atom_site_Wycoff_symbol','_atom_site_fract_x',
                          '_atom_site_fract_y','_atom_site_fract_z',
                          '_atom_site_occupancy']]
            # Create CifFile object
            d = OrderedDict()
            d[self.formula] = CifBlock(data,cif_loops,cif_header)
            cf = CifFile(d)
            
            return cf

        # .cif file nameing scheme
        self.cif_file = str(self.tilt)+'_'+self.formula+'.cif'
        # Generate pymatgen CifFile object
        cf = make_cif(self)
        # Write created .cif file to SPuDS_dir
        with zopen(os.path.join(self.SPuDS_dir,self.cif_file), "wt") as f:
            f.write(cf.__str__())
            f.close()
Exemplo n.º 44
0
 def write_file(self, filename="paths.dat"):
     """
     Write paths.dat.
     """
     with zopen(filename, "wt") as f:
         f.write(str(self) + "\n")
Exemplo n.º 45
0
    def _parse(self, filename):
        start_patt = re.compile(" \(Enter \S+l101\.exe\)")
        route_patt = re.compile(" #[pPnNtT]*.*")
        charge_mul_patt = re.compile("Charge\s+=\s*([-\\d]+)\s+"
                                     "Multiplicity\s+=\s*(\d+)")
        num_basis_func_patt = re.compile("([0-9]+)\s+basis functions")
        pcm_patt = re.compile("Polarizable Continuum Model")
        stat_type_patt = re.compile("imaginary frequencies")
        scf_patt = re.compile("E\(.*\)\s*=\s*([-\.\d]+)\s+")
        mp2_patt = re.compile("EUMP2\s*=\s*(.*)")
        oniom_patt = re.compile("ONIOM:\s+extrapolated energy\s*=\s*(.*)")
        termination_patt = re.compile("(Normal|Error) termination of Gaussian")
        std_orientation_patt = re.compile("Standard orientation")
        end_patt = re.compile("--+")
        orbital_patt = re.compile("Alpha\s*\S+\s*eigenvalues --(.*)")
        thermo_patt = re.compile("(Zero-point|Thermal) correction(.*)="
                                 "\s+([\d\.-]+)")

        self.properly_terminated = False
        self.is_pcm = False
        self.stationary_type = "Minimum"
        self.structures = []
        self.corrections = {}
        self.energies = []
        self.pcm = None

        coord_txt = []
        read_coord = 0
        orbitals_txt = []
        parse_stage = 0
        num_basis_found = False
        terminated = False

        with zopen(filename) as f:
            for line in f:
                if parse_stage == 0:
                    if start_patt.search(line):
                        parse_stage = 1
                    elif route_patt.search(line):
                        self.route = {}
                        for tok in line.split():
                            sub_tok = tok.strip().split("=")
                            key = sub_tok[0].upper()
                            self.route[key] = sub_tok[1].upper() \
                                if len(sub_tok) > 1 else ""
                            m = re.match("(\w+)/([^/]+)", key)
                            if m:
                                self.functional = m.group(1)
                                self.basis_set = m.group(2)
                elif parse_stage == 1:
                    if charge_mul_patt.search(line):
                        m = charge_mul_patt.search(line)
                        self.charge = int(m.group(1))
                        self.spin_mult = int(m.group(2))
                        parse_stage = 2
                elif parse_stage == 2:

                    if self.is_pcm:
                        self._check_pcm(line)

                    if "FREQ" in self.route and thermo_patt.search(line):
                        m = thermo_patt.search(line)
                        if m.group(1) == "Zero-point":
                            self.corrections["Zero-point"] = float(m.group(3))
                        else:
                            key = m.group(2).strip(" to ")
                            self.corrections[key] = float(m.group(3))

                    if read_coord:
                        if not end_patt.search(line):
                            coord_txt.append(line)
                        else:
                            read_coord = (read_coord + 1) % 4
                            if not read_coord:
                                sp = []
                                coords = []
                                for l in coord_txt[2:]:
                                    toks = l.split()
                                    sp.append(Element.from_Z(int(toks[1])))
                                    coords.append(map(float, toks[3:6]))
                                self.structures.append(Molecule(sp, coords))
                    elif termination_patt.search(line):
                        m = termination_patt.search(line)
                        if m.group(1) == "Normal":
                            self.properly_terminated = True
                        terminated = True
                    elif (not num_basis_found) and \
                            num_basis_func_patt.search(line):
                        m = num_basis_func_patt.search(line)
                        self.num_basis_func = int(m.group(1))
                        num_basis_found = True
                    elif (not self.is_pcm) and pcm_patt.search(line):
                        self.is_pcm = True
                        self.pcm = {}
                    elif "FREQ" in self.route and "OPT" in self.route and \
                            stat_type_patt.search(line):
                        self.stationary_type = "Saddle"
                    elif mp2_patt.search(line):
                        m = mp2_patt.search(line)
                        self.energies.append(float(m.group(1).replace("D",
                                                                      "E")))
                    elif oniom_patt.search(line):
                        m = oniom_patt.matcher(line)
                        self.energies.append(float(m.group(1)))
                    elif scf_patt.search(line):
                        m = scf_patt.search(line)
                        self.energies.append(float(m.group(1)))
                    elif std_orientation_patt.search(line):
                        coord_txt = []
                        read_coord = 1
                    elif orbital_patt.search(line):
                        orbitals_txt.append(line)
        if not terminated:
            raise IOError("Bad Gaussian output file.")
Exemplo n.º 46
0
 def write(self, file_name):
     with zopen(file_name, "wt") as f:
         f.write(self.get_str())