예제 #1
0
파일: eqeq.py 프로젝트: WilmerLab/EQeq
def run(structure, input_type="cif", output_type="cif", l=1.2, h_i0=-2.0,
        charge_precision=3, method="ewald", m_r=2, m_k=2, eta=50.0,
        ionization_data_path=DEFAULT_IONIZATION_PATH,
        charge_data_path=DEFAULT_CHARGE_PATH):
    """Runs EQeq on the inputted structure, returning charge data.

    Args:
        structure: Either a filename or data encoding a chemical.
        input_type: (Optional) Specifies input type. Can be anything supported
            by openbabel, as well as "json"
        output_type: (Optional) Specifies the output type. Currently, options
            are "cif", "mol", "pdb", "car", "json", "list", and "files". The
            first four return modified chemical data formats, "list" returns
            a Python object, "json" is that object serialized, and "files"
            saves files of all possible output types.
        l: (Optional) Lambda, the dielectric screening parameter.
        h_i0: (Optional) The electron affinity of hydrogen.
        charge_precision: (Optional) Number of decimals to use for charges.
        method: (Optional) Method to use. Can be "direct" (default),
            "nonperiodic", or "ewald".
        m_r: (Optional) Number of unit cells to consider in "real space". This
            is measured radially, so m_r = 1 evaluates 27 unit cells.
        m_k: (Optional) Number of unit cells to consider in "frequency space".
            This is measured radially, so m_k = 1 evaluates 27 unit cells.
        eta: (Optional) Ewald splitting parameter
        ionization_data_path: (Optional) A path to the file containing ion-
            ization data. By default, assumes the data is in the EQeq folder
            and saved as "ionizationdata.dat".
        charge_data_path: (Optional) A path to the file containing charge-
            center data. By default, assumes the data is in the EQeq folder
            and saved as "chargecenters.dat".
    Returns:
        A string representing the charged crystal. Returns nothing if the
        output type is set to "files"
    """
    # Error handling on string params. Should spare users some annoyance.
    o, m = output_type.lower(), method.lower()
    if o not in ["cif", "pdb", "car", "mol", "json", "list", "files"]:
        raise NotImplementedError("Output format '%s' is not supported!" % o)
    if m not in ["direct", "nonperiodic", "ewald"]:
        raise NotImplementedError("Method '%s' is not supported!" % m)
    # If linked to openbabel, use it to handle json interconversion externally
    if input_type != "cif":
        structure = format_converter.convert(structure, input_type, "cif")
    structure = structure.replace("\t", "  ")
    # Calls libeqeq.so's run method, returning a string of data
    result = eqeq.run(structure, ("json" if output_type == "list" else
                      output_type), l, h_i0, charge_precision, method, m_r,
                      m_k, eta, ionization_data_path, charge_data_path)
    if output_type == "list":
        return json.loads(result)
    # This option appends atoms in json/object data with a "charge" attribute
    if output_type == "json":
        obj = format_converter.convert(structure, "cif", "object")
        result = json.loads(result)
        for atom, charge in zip(obj["atoms"], result):
            atom["charge"] = charge
        result = json.dumps(obj)
    return result
예제 #2
0
def convert(data, in_format, out_format, pretty=True, add_h=False):
    """Converts between two inputted chemical formats."""
    # Decide on a json formatter depending on desired prettiness
    dumps = json.dumps if pretty else json.compress

    # Not doing this can cause segfaults in the underlying openbabel C++
    if not IS_PY3:
        in_format.encode("ascii")
        out_format.encode("ascii")
        data.encode("ascii", "replace")

    # If it's a json string, load it. NOTE: This is a custom chemical format
    if in_format == "json" and isinstance(data, str if IS_PY3 else basestring):
        data = json.loads(data)

    # These use the open babel library to interconvert, with additions for json
    mol = (json_to_pybel(data) if in_format == "json" else
           pybel.readstring(in_format, data))

    # Infer structure in cases where the input format has no specification
    # or the specified structure is small
    if not mol.OBMol.HasNonZeroCoords() or len(mol.atoms) < 50:
        mol.make3D(steps=500)
    mol.OBMol.Center()

    if add_h:
        mol.addh()

    return (dumps(pybel_to_json(mol)) if out_format == "json"
            else mol.write(out_format))
예제 #3
0
def convert(data, in_format, out_format, pretty=True, add_h=False):
    """Converts between two inputted chemical formats."""
    # Decide on a json formatter depending on desired prettiness
    dumps = json.dumps if pretty else json.compress

    # If it's a json string, load it. NOTE: This is a custom chemical format
    if in_format == "json" and isinstance(data, basestring):
        data = json.loads(data)

    # These use the open babel library to interconvert, with additions for json
    mol = (json_to_pybel(data) if in_format == "json" else
           pybel.readstring(in_format.encode("ascii"),
                            data.encode("ascii", "replace")))

    # Infer structure in cases where the input format has no specification
    # or the specified structure is small
    if not mol.OBMol.HasNonZeroCoords() or len(mol.atoms) < 50:
        mol.make3D(steps=500)
    mol.OBMol.Center()

    if add_h:
        mol.addh()

    return (dumps(pybel_to_json(mol)) if out_format == "json"
            else mol.write(out_format.encode("ascii")))
예제 #4
0
def convert(data, in_format, out_format, pretty=False):
    """Converts between two inputted chemical formats.

    Args:
        data: A string representing the chemical file to be converted. If the
            `in_format` is "json", this can also be a Python object
        in_format: The format of the `data` string. Can be "json" or any format
            recognized by Open Babel
        out_format: The format to convert to. Can be "json" or any format
            recognized by Open Babel
        pretty: (Optional) If True and `out_format` is "json", will pretty-
            print the output for human readability
    Returns:
        A string representing the inputted `data` in the specified `out_format`
    """

    # Decide on a json formatter depending on desired prettiness
    dumps = json.dumps if pretty else json.compress

    # If it's a json string, load it
    if in_format == "json" and isinstance(data, basestring):
        data = json.loads(data)

    # A little "hack" to format inputted json
    if in_format == "json" and out_format == "json":
        return json.dumps(data)

    # These are converted manually to retain crystallographic information
    if in_format == "json" and out_format == "cif":
        return json_to_cif(data)

    # These use the open babel library to interconvert, with additions for json
    mol = (json_to_pybel(data) if in_format == "json" else
           pybel.readstring(in_format.encode("ascii"),
                            "".join(i for i in data if ord(i) < 128)
                            .encode("ascii")))

    # Infer structure in cases where the input format has no specification
    if not mol.OBMol.HasNonZeroCoords():
        mol.make3D()
    mol.OBMol.Center()

    # EQeq takes a specific cif format that openbabel does not output.
    # This manually overrides that.
    if out_format == "cif":
        return json_to_cif(pybel_to_json(mol))

    if out_format == "object":
        return pybel_to_json(mol)
    elif out_format == "json":
        return dumps(pybel_to_json(mol))
    else:
        return mol.write(out_format)
예제 #5
0
def convert(data, in_format, out_format, pretty=False):
    """Converts between two inputted chemical formats.

    Args:
        data: A string representing the chemical file to be converted. If the
            `in_format` is "json", this can also be a Python object
        in_format: The format of the `data` string. Can be "json" or any format
            recognized by Open Babel
        out_format: The format to convert to. Can be "json" or any format
            recognized by Open Babel
        pretty: (Optional) If True and `out_format` is "json", will pretty-
            print the output for human readability
    Returns:
        A string representing the inputted `data` in the specified `out_format`
    """

    # Decide on a json formatter depending on desired prettiness
    dumps = json.dumps if pretty else json.compress

    # If it's a json string, load it
    if in_format == "json" and isinstance(data, basestring):
        data = json.loads(data)

    # A little "hack" to format inputted json
    if in_format == "json" and out_format == "json":
        return json.dumps(data)

    # These are converted manually to retain crystallographic information
    if in_format == "json" and out_format == "cif":
        return json_to_cif(data)

    # These use the open babel library to interconvert, with additions for json
    mol = (json_to_pybel(data) if in_format == "json" else pybel.readstring(
        in_format.encode("ascii"), "".join(i for i in data
                                           if ord(i) < 128).encode("ascii")))

    # Infer structure in cases where the input format has no specification
    if not mol.OBMol.HasNonZeroCoords():
        mol.make3D()
    mol.OBMol.Center()

    # EQeq takes a specific cif format that openbabel does not output.
    # This manually overrides that.
    if out_format == "cif":
        return json_to_cif(pybel_to_json(mol))

    if out_format == "object":
        return pybel_to_json(mol)
    elif out_format == "json":
        return dumps(pybel_to_json(mol))
    else:
        return mol.write(out_format)
예제 #6
0
def convert(data, in_format, out_format, filename=None, pretty=False):
    """Converts between two inputted chemical formats.

    Args:
        data: A string representing the chemical file to be converted. If the
            `in_format` is "json", this can also be a Python object
        in_format: The format of the `data` string. Can be "json" or any format
            recognized by Open Babel
        out_format: The format to convert to. Can be "json" or any format
            recognized by Open Babel
        filename: (Optional) The name of the file containing `data`. This is
            used primarily to encode data saved in the file naming scheme of
            the old building-block format
        pretty: (Optional) If True and `out_format` is "json", will pretty-
            print the output for human readability
    Returns:
        A string representing the inputted `data` in the specified `out_format`
    """

    # Decide on a json formatter depending on desired prettiness
    dumps = json.dumps if pretty else json.compress

    # If it's a json string, load it
    if in_format == "json" and isinstance(data, basestring):
        data = json.loads(data)

    # A little "hack" to format inputted json
    if in_format == "json" and out_format == "json":
        return json.dumps(data)

    # These use the open babel library to interconvert, with additions for json
    mol = (json_to_pybel(data) if in_format == "json" else
           pybel.readstring(in_format.encode("ascii"),
                            "".join(i for i in data if ord(i) < 128)
                            .encode("ascii")))

    # Infer structure in cases where the input format has no specification
    if not mol.OBMol.HasNonZeroCoords():
        mol.make3D()
    mol.OBMol.Center()

    return (dumps(pybel_to_json(mol, name=filename)) if out_format == "json"
            else mol.write(out_format.encode("ascii")))
예제 #7
0
파일: eqeq.py 프로젝트: solccp/EQeq
def run(structure,
        input_type="cif",
        output_type="cif",
        l=1.2,
        h_i0=-2.0,
        charge_precision=3,
        method="ewald",
        m_r=2,
        m_k=2,
        eta=50.0,
        ionization_data_path=DEFAULT_IONIZATION_PATH,
        charge_data_path=DEFAULT_CHARGE_PATH):
    """Runs EQeq on the inputted structure, returning charge data.

    Args:
        structure: Either a filename or data encoding a chemical.
        input_type: (Optional) Specifies input type. Can be anything supported
            by openbabel, as well as "json"
        output_type: (Optional) Specifies the output type. Currently, options
            are "cif", "mol", "pdb", "car", "json", "list", and "files". The
            first four return modified chemical data formats, "list" returns
            a Python object, "json" is that object serialized, and "files"
            saves files of all possible output types.
        l: (Optional) Lambda, the dielectric screening parameter.
        h_i0: (Optional) The electron affinity of hydrogen.
        charge_precision: (Optional) Number of decimals to use for charges.
        method: (Optional) Method to use. Can be "direct" (default),
            "nonperiodic", or "ewald".
        m_r: (Optional) Number of unit cells to consider in "real space". This
            is measured radially, so m_r = 1 evaluates 27 unit cells.
        m_k: (Optional) Number of unit cells to consider in "frequency space".
            This is measured radially, so m_k = 1 evaluates 27 unit cells.
        eta: (Optional) Ewald splitting parameter
        ionization_data_path: (Optional) A path to the file containing ion-
            ization data. By default, assumes the data is in the EQeq folder
            and saved as "ionizationdata.dat".
        charge_data_path: (Optional) A path to the file containing charge-
            center data. By default, assumes the data is in the EQeq folder
            and saved as "chargecenters.dat".
    Returns:
        A string representing the charged crystal. Returns nothing if the
        output type is set to "files"
    """
    # Error handling on string params. Should spare users some annoyance.
    o, m = output_type.lower(), method.lower()
    if o not in ["cif", "pdb", "car", "mol", "json", "list", "files"]:
        raise NotImplementedError("Output format '%s' is not supported!" % o)
    if m not in ["direct", "nonperiodic", "ewald"]:
        raise NotImplementedError("Method '%s' is not supported!" % m)
    # If linked to openbabel, use it to handle json interconversion externally
    if input_type != "cif":
        structure = format_converter.convert(structure, input_type, "cif")
    structure = structure.replace("\t", "  ")
    # Calls libeqeq.so's run method, returning a string of data
    result = eqeq.run(structure,
                      ("json" if output_type == "list" else output_type), l,
                      h_i0, charge_precision, method, m_r, m_k, eta,
                      ionization_data_path, charge_data_path)
    if output_type == "list":
        return json.loads(result)
    # This option appends atoms in json/object data with a "charge" attribute
    if output_type == "json":
        obj = format_converter.convert(structure, "cif", "object")
        result = json.loads(result)
        for atom, charge in zip(obj["atoms"], result):
            atom["charge"] = charge
        result = json.dumps(obj)
    return result