Ejemplo n.º 1
0
    def __next__(self):
        """Load the next molecule from the SDF file

           This method is part of the iterator protocol.
        """
        while True:
            title = next(self.f)
            if len(title) == 0:
                raise StopIteration
            else:
                title = title.strip()
            next(self.f)  # skip line
            next(self.f)  # skip empty line
            words = next(self.f).split()
            if len(words) < 2:
                raise FileFormatError(
                    "Expecting at least two numbers at fourth line.")
            try:
                num_atoms = int(words[0])
                num_bonds = int(words[1])
            except ValueError:
                raise FileFormatError(
                    "Expecting at least two numbers at fourth line.")

            numbers = np.zeros(num_atoms, int)
            coordinates = np.zeros((num_atoms, 3), float)
            for i in range(num_atoms):
                words = next(self.f).split()
                if len(words) < 4:
                    raise FileFormatError(
                        "Expecting at least four words on an atom line.")
                try:
                    coordinates[i, 0] = float(words[0])
                    coordinates[i, 1] = float(words[1])
                    coordinates[i, 2] = float(words[2])
                except ValueError:
                    raise FileFormatError(
                        "Coordinates must be floating point numbers.")
                atom = periodic[words[3]]
                if atom is None:
                    raise FileFormatError("Unrecognized atom symbol: %s" %
                                          words[3])
                numbers[i] = atom.number
            coordinates *= angstrom

            edges = []
            orders = np.zeros(num_bonds, int)
            for i in range(num_bonds):
                words = next(self.f).split()
                if len(words) < 3:
                    raise FileFormatError(
                        "Expecting at least three numbers on a bond line.")
                try:
                    edges.append((int(words[0]) - 1, int(words[1]) - 1))
                    orders[i] = int(words[2])
                except ValueError:
                    raise FileFormatError(
                        "Expecting at least three numbers on a bond line.")

            formal_charges = np.zeros(len(numbers), int)

            line = next(self.f)
            while line != "M  END\n":
                if line.startswith("M  CHG"):
                    words = line[6:].split(
                    )[1:]  # drop the first number which is the number of charges
                    i = 0
                    while i < len(words) - 1:
                        try:
                            formal_charges[int(words[i]) - 1] = int(words[i +
                                                                          1])
                        except ValueError:
                            raise FileFormatError(
                                "Expecting only integer formal charges.")
                        i += 2
                line = next(self.f)

            # Read on to the next molecule
            for line in self.f:
                if line == "$$$$\n":
                    break

            molecule = Molecule(numbers, coordinates, title)
            molecule.formal_charges = formal_charges
            molecule.formal_charges.setflags(write=False)
            molecule.graph = MolecularGraph(edges, numbers, orders)
            return molecule
Ejemplo n.º 2
0
    def next(self):
        """Load the next molecule from the SDF file

           This method is part of the iterator protocol.
        """
        while True:
            title = self.f.next()
            if len(title) == 0:
                raise StopIteration
            else:
                title = title.strip()
            self.f.next() # skip line
            self.f.next() # skip empty line
            words = self.f.next().split()
            if len(words) < 2:
                raise FileFormatError("Expecting at least two numbers at fourth line.")
            try:
                num_atoms = int(words[0])
                num_bonds = int(words[1])
            except ValueError:
                raise FileFormatError("Expecting at least two numbers at fourth line.")

            numbers = numpy.zeros(num_atoms, int)
            coordinates = numpy.zeros((num_atoms, 3), float)
            for i in xrange(num_atoms):
                words = self.f.next().split()
                if len(words) < 4:
                    raise FileFormatError("Expecting at least four words on an atom line.")
                try:
                    coordinates[i, 0] = float(words[0])
                    coordinates[i, 1] = float(words[1])
                    coordinates[i, 2] = float(words[2])
                except ValueError:
                    raise FileFormatError("Coordinates must be floating point numbers.")
                atom = periodic[words[3]]
                if atom is None:
                    raise FileFormatError("Unrecognized atom symbol: %s" % words[3])
                numbers[i] = atom.number
            coordinates *= angstrom

            edges = []
            orders = numpy.zeros(num_bonds, int)
            for i in xrange(num_bonds):
                words = self.f.next().split()
                if len(words) < 3:
                    raise FileFormatError("Expecting at least three numbers on a bond line.")
                try:
                    edges.append((int(words[0])-1, int(words[1])-1))
                    orders[i] = int(words[2])
                except ValueError:
                    raise FileFormatError("Expecting at least three numbers on a bond line.")

            formal_charges = numpy.zeros(len(numbers), int)

            line = self.f.next()
            while line != "M  END\n":
                if line.startswith("M  CHG"):
                    words = line[6:].split()[1:] # drop the first number which is the number of charges
                    i = 0
                    while i < len(words)-1:
                        try:
                            formal_charges[int(words[i])-1] = int(words[i+1])
                        except ValueError:
                            raise FileFormatError("Expecting only integer formal charges.")
                        i += 2
                line = self.f.next()

            # Read on to the next molecule
            for line in self.f:
                if line == "$$$$\n":
                    break

            molecule = Molecule(numbers, coordinates, title)
            molecule.formal_charges = formal_charges
            molecule.formal_charges.setflags(write=False)
            molecule.graph = MolecularGraph(edges, numbers, orders)
            return molecule