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
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