Ejemplo n.º 1
0
def parse_resp_esp(f: TextIO) -> EspData:
    """Parse a file in the .esp file format defined by ``resp``

    Parameters
    ----------
    f : TextIO
        File object opened in read mode containing the .esp file to be parsed.

    Raises
    ------
    InputFormatError
        Raised when the file does not follow the expected format.

    Returns
    -------
    EspData
        A dataclass representing the information in the given .esp file.
    """

    atom_and_point_count = get_line(f).split()

    if len(atom_and_point_count) != 2:
        raise InputFormatError(
            "Expected atom and point counts on the first line of .esp file in the `resp` format"
        )

    atom_count = int(atom_and_point_count[0])
    point_count = int(atom_and_point_count[1])

    atoms_coords = [Coords(get_line(f).split()) for _ in range(atom_count)]

    mesh_coords: List[Coords] = []
    esp_values: List[Esp] = []

    for _ in range(point_count):
        val, *coords = get_line(f).split()
        mesh_coords.append(Coords(coords))
        esp_values.append(Esp(val))

    field = Field(
        Mesh(
            mesh_coords
        ),
        esp_values
    )

    return EspData(
        atoms_coords,
        field
    )
Ejemplo n.º 2
0
    def points(self) -> Iterator[Coords]:
        """Coordinates of points of which the mesh consists

        The order of iteration is the same as the order of values in a Gaussian
        "cube" file. Values of `z` are incremented first, then all values of
        `y`, and finally all values of `x`. This is best described with the
        following pseudocode::

            for x in x_values:
                for y in y_values:
                    for z in z_values:
                        yield (x, y, z)

        Yields
        ------
        Iterator[Coords]
            Iterator over the point coordinates
        """
        for i in range(self.axes[0].point_count):
            for j in range(self.axes[1].point_count):
                for k in range(self.axes[2].point_count):
                    yield Coords(
                        (Dist(self.origin[0] + i * self.axes[0].vector[0]),
                         Dist(self.origin[1] + j * self.axes[1].vector[1]),
                         Dist(self.origin[2] + k * self.axes[2].vector[2])))
Ejemplo n.º 3
0
 def parse_axis(line: str) -> GridMesh.Axis:
     # `cubegen` documentation, which contains the only definition of
     # the cube format, specifies that a negative `point_count` may be used
     # in the *input* to signify atomic units. However, this is not an
     # option in the output of `cubegen` and values are always in atomic units.
     point_count, *vector_components = line.split()
     return GridMesh.Axis(Coords(vector_components), int(point_count))
Ejemplo n.º 4
0
def _parse_atom(line: str) -> AtomWithCoordsAndCharge:
    line_split = line.split()
    return AtomWithCoordsAndCharge.from_symbol(
        line_split[0],
        Coords(tuple(coord.replace('D', 'E') for coord in line_split[1:4])),
        Charge(line_split[4].replace('D', 'E'))
    )
Ejemplo n.º 5
0
def _parse_grid_prelude(line: str) -> _GridPrelude:
    line_split = line.split()
    if len(line_split) in (4, 5):
        atom_count, *origin_coords = line_split[:4]
        nval = line_split[4] if len(line_split) == 5 else "1"
    else:
        raise InputFormatError(
            f"Cube file incorrectly formatted! Expected four or five fields "
            "(atom count, 3*origin coordinates, [NVal]) on line 3, found "
            "{len(line_split)} fields.")

    return _GridPrelude(int(atom_count), Coords(origin_coords), int(nval))
Ejemplo n.º 6
0
def _parse_esp_points(f: TextIO) -> Field[Esp]:
    points = []
    values = []
    for line in f:
        line_split = [val.replace('D', 'E') for val in line.split()]
        points.append(Coords(line_split[1:4]))
        values.append(Esp(line_split[0]))

    return Field(
        Mesh(points),
        values
    )
Ejemplo n.º 7
0
def _parse_atom(line: str) -> AtomWithCoordsAndCharge:
    atomic_number, cube_charge, *coords = line.split()
    return AtomWithCoordsAndCharge(int(atomic_number), Coords(coords),
                                   Charge(cube_charge))