def endElement(self, name): #print "END", name if name == 'molecule': if len(self.current_numbers) > 0: self.current_coordinates = np.array(self.current_coordinates)*angstrom molecule = Molecule(self.current_numbers, self.current_coordinates, self.current_title) molecule.extra = self.current_extra molecule.atoms_extra = self.current_atoms_extra name_to_index = {} for counter, name in enumerate(self.current_atom_names): name_to_index[name] = counter edges = set() current_bonds_extra = {} for name1, name2, extra in self.current_bonds: i1 = name_to_index.get(name1) i2 = name_to_index.get(name2) if i1 is not None and i2 is not None: edge = frozenset([i1, i2]) if len(extra) > 0: current_bonds_extra[edge] = extra edges.add(edge) molecule.bonds_extra = current_bonds_extra if len(edges) == 0: molecule.graph = None else: molecule.graph = MolecularGraph(edges, self.current_numbers) del self.current_atom_names del self.current_bonds self.molecules.append(molecule) self.current_title = None
def endElement(self, name): #print "END", name if name == 'molecule': if len(self.current_numbers) > 0: self.current_coordinates = numpy.array(self.current_coordinates)*angstrom molecule = Molecule(self.current_numbers, self.current_coordinates, self.current_title) molecule.extra = self.current_extra molecule.atoms_extra = self.current_atoms_extra name_to_index = {} for counter, name in enumerate(self.current_atom_names): name_to_index[name] = counter pairs = set() current_bonds_extra = {} for name1, name2, extra in self.current_bonds: i1 = name_to_index.get(name1) i2 = name_to_index.get(name2) if i1 is not None and i2 is not None: pair = frozenset([i1,i2]) if len(extra) > 0: current_bonds_extra[pair] = extra pairs.add(pair) molecule.bonds_extra = current_bonds_extra if len(pairs) == 0: molecule.graph = None else: molecule.graph = MolecularGraph(pairs, self.current_numbers) del self.current_atom_names del self.current_bonds self.molecules.append(molecule) self.current_title = None
def collect_molecules(self, parent, universe=None): Atom = context.application.plugins.get_node("Atom") Bond = context.application.plugins.get_node("Bond") Frame = context.application.plugins.get_node("Frame") if universe == None: universe = parent atom_to_index = {} atoms_extra = {} counter = 0 numbers = [] coordinates = [] for child in parent.children: if isinstance(child, Atom): atom_to_index[child] = counter if len(child.extra) > 0: atoms_extra[counter] = child.extra counter += 1 numbers.append(child.number) coordinates.append(child.get_frame_relative_to(universe).t) if len(numbers) > 0: molecule = Molecule(numbers, coordinates, parent.name) molecule.extra = parent.extra molecule.atoms_extra = atoms_extra molecule.bonds_extra = {} pairs = set([]) for child in parent.children: if isinstance(child, Bond): atoms = child.get_targets() pair = frozenset([atom_to_index[atoms[0]], atom_to_index[atoms[1]]]) if len(child.extra) > 0: molecule.bonds_extra[pair] = child.extra pairs.add(pair) if len(pairs) > 0: molecule.graph = MolecularGraph(pairs, molecule.numbers) else: molecule.graph = None result = [molecule] else: result = [] for child in parent.children: if isinstance(child, Frame): result.extend(self.collect_molecules(child, universe)) return result
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