def calcBonds( coords, symbols, dim=None, maxAtomRadius=None, bondMargin=0.2, boxMargin=1.0 ): """Calculate the bonds for the fragments. This is done at the start when the only coordinates are those in the fragment. """ close = closeAtoms(coords, symbols, dim, maxAtomRadius, boxMargin) v1 = [] v2 = [] for idxAtom1, idxAtom2 in close: v1.append(coords[idxAtom1]) v2.append(coords[idxAtom2]) distances = xyz_core.distance(np.array(v1), np.array(v2), dim=dim) bonds = [] for i, (idxAtom1, idxAtom2) in enumerate(close): bond_length = bondLength(symbols[idxAtom1], symbols[idxAtom2]) if bond_length < 0: continue logger.debug( "Dist:length {1}({0})-{3}({2}) {4} {5}".format( symbols[idxAtom1], idxAtom1, symbols[idxAtom2], idxAtom2, distances[i], bond_length, ) ) if bond_length - bondMargin < distances[i] < bond_length + bondMargin: bonds.append((idxAtom1, idxAtom2)) # We sort the bonds on return so that results are deterministic and can be tested return sorted(bonds)
def _calcRadius(self): """Calculate a simple size metric of the block so that we can screen for whether two blocks are within touching distance Assumes centroid already calculated """ distances = [] self._maxAtomRadius = 0.0 for f in self.fragments: for coord in f.iterCoord(): distances.append(xyz_core.distance(self._centroid, coord)) self._maxAtomRadius = max(f.maxAtomRadius(), self._maxAtomRadius) assert distances imax = np.argmax(distances) dist = distances[imax] # Add on the radius of the largest atom self._radius = dist + self.maxAtomRadius() return
def setEndGroups(self, endGroupTypes, endGroups, capAtoms, dihedralAtoms, uwAtoms): self._endGroups = [] self._maxBonds = {} self._endGroupBonded = {} for i, e in enumerate(endGroups): eg = ab_endgroup.EndGroup() eg.fragment = self eg._endGroupType = endGroupTypes[i] eg.fragmentEndGroupIdx = e eg.fragmentCapIdx = capAtoms[i] eg.fragmentDihedralIdx = dihedralAtoms[i] eg.fragmentUwIdx = uwAtoms[i] eg.capBondLength = xyz_core.distance( self._coords[eg.fragmentCapIdx], self._coords[eg.fragmentEndGroupIdx]) if eg.type() not in self._maxBonds: self._maxBonds[eg.type()] = None if eg.type() not in self._endGroupBonded: self._endGroupBonded[eg.type()] = 0 # sanity check assert (eg.fragmentCapIdx in self._bonded[eg.fragmentEndGroupIdx] ), "capAtom {0} is not bonded to endGroup {1}".format( eg.fragmentCapIdx, eg.fragmentEndGroupIdx) if eg.fragmentDihedralIdx != -1: assert ( eg.fragmentDihedralIdx in self._bonded[eg.fragmentEndGroupIdx] ), "dihedral Atom {0} is not bonded to endGroup {1}".format( eg.fragmentDihedralIdx, eg.fragmentEndGroupIdx) if eg.fragmentUwIdx != -1: assert (eg.fragmentUwIdx in self._bonded[eg.fragmentEndGroupIdx] ), "uwAtom {0} is not bonded to endGroup {1}".format( eg.fragmentUwIdx, eg.fragmentEndGroupIdx) self._endGroups.append(eg) # sanity check - make sure no endGroup is the cap Atom for another endGroup eg = set([e.fragmentEndGroupIdx for e in self._endGroups]) caps = set([e.fragmentCapIdx for e in self._endGroups]) assert (len(eg.intersection(caps)) == 0 ), "Cap atom for one endGroup is another endGroup!" return
def calcBondsHACK(coords, symbols, bondMargin=0.2): """HACK FOR NETWORK""" bonds = [] for i, coord1 in enumerate(coords): symbol1 = symbols[i] for j, coord2 in enumerate(coords): if j < i: continue symbol2 = symbols[j] dist = xyz_core.distance(coord1, coord2) if symbol1 == "j" and symbol2 == "C": bond_length = 4.31 elif symbol2 == "j" and symbol1 == "C": bond_length = 4.31 else: bond_length = bondLength(symbol1, symbol2) # print "GOT ",symbol1,symbol2,bond_length, dist if bond_length - bondMargin < dist < bond_length + bondMargin: # print "BONDING" bonds.append((i, j)) return bonds
def _calcRadius(self): """ Calculate a simple size metric of the block so that we can screen for whether two blocks are within touching distance First try a simple approach with a loop just to get a feel for things - Find the largest distance between any atom and the center of geometry - Get the covalent radius of that atom - return that distance + radius + buffer Should move to use scipy as detailed here: http://stackoverflow.com/questions/6430091/efficient-distance-calculation-between-n-points-and-a-reference-in-numpy-scipy """ distances = [ xyz_core.distance(self._centroid, coord) for coord in self._coords ] imax = np.argmax(distances) dist = distances[imax] self._radius = dist + self.maxAtomRadius( ) # Add on the radius of the largest atom return
def writeCml( cmlFilename, coords, symbols, bonds=None, atomTypes=None, cell=None, pruneBonds=False, prettyPrint=False, ): assert len(coords) == len(symbols) if pruneBonds: assert cell is not None pcoords = [] # need to save periodic coordinates root = ET.Element("molecule") root.attrib["xmlns"] = "http://www.xml-cml.org/schema" root.attrib["xmlns:cml"] = "http://www.xml-cml.org/dict/cml" root.attrib["xmlns:units"] = "http://www.xml-cml.org/units/units" root.attrib["xmlns:xsd"] = "http://www.w3c.org/2001/XMLSchema" root.attrib["xmlns:iupac"] = "http://www.iupac.org" root.attrib["id"] = "mymolecule" if cell is not None: # First set up the cell crystal = ET.SubElement(root, "crystal") crystalANode = ET.SubElement(crystal, "scalar") crystalBNode = ET.SubElement(crystal, "scalar") crystalCNode = ET.SubElement(crystal, "scalar") crystalAlphaNode = ET.SubElement(crystal, "scalar") crystalBetaNode = ET.SubElement(crystal, "scalar") crystalGammaNode = ET.SubElement(crystal, "scalar") crystalANode.attrib["title"] = "a" crystalBNode.attrib["title"] = "b" crystalCNode.attrib["title"] = "c" crystalAlphaNode.attrib["title"] = "alpha" crystalBetaNode.attrib["title"] = "beta" crystalGammaNode.attrib["title"] = "gamma" crystalANode.attrib["units"] = "units:angstrom" crystalBNode.attrib["units"] = "units:angstrom" crystalCNode.attrib["units"] = "units:angstrom" crystalAlphaNode.attrib["units"] = "units:degree" crystalBetaNode.attrib["units"] = "units:degree" crystalGammaNode.attrib["units"] = "units:degree" crystalANode.text = str(cell[0]) crystalBNode.text = str(cell[1]) crystalCNode.text = str(cell[2]) # Only support orthorhombic? cells crystalAlphaNode.text = "90" crystalBetaNode.text = "90" crystalGammaNode.text = "90" if atomTypes: assert len(atomTypes) == len(coords) # Need to collate atomTypes - sorted to ensure consistency for testing for atype in sorted(set(atomTypes)): atomTypeNode = ET.SubElement(root, "atomType") atomTypeNode.attrib["name"] = atype atomTypeNode.attrib["title"] = atype # Now atom data atomArrayNode = ET.SubElement(root, "atomArray") for i, coord in enumerate(coords): atomNode = ET.SubElement(atomArrayNode, "atom") atomNode.attrib["id"] = "a{0}".format(i) atomNode.attrib["elementType"] = symbols[i] if cell is not None: coord, _ = xyz_core.wrapCoord3(coord, cell, center=False) if pruneBonds: pcoords.append(coord) x, y, z = coord atomNode.attrib["x3"] = "{:.12}".format(x) atomNode.attrib["y3"] = "{:.12}".format(y) atomNode.attrib["z3"] = "{:.12}".format(z) if atomTypes: # Now add atomType as child node referring to the atomType atomTypeNode = ET.SubElement(atomNode, "atomType") atomTypeNode.attrib["ref"] = atomTypes[i] if len(bonds): # Now do bonds if pruneBonds: # Hack to get vis working # Calculate all bond distances distances = xyz_core.distance( [pcoords[b1] for b1, b2 in bonds], [pcoords[b2] for b1, b2 in bonds] ) # Complete hack - just see if it's longer then 0.5 the cell A distance - assumes cubic cell bonds = [b for i, b in enumerate(bonds) if distances[i] <= cell[0] * 0.5] bondArrayNode = ET.SubElement(root, "bondArray") for b in bonds: bondNode = ET.SubElement(bondArrayNode, "bond") bondNode.attrib["atomRefs2"] = "a{0} a{1}".format(b[0], b[1]) bondNode.attrib["order"] = "1" cmlFilename = os.path.abspath(cmlFilename) if prettyPrint: estring = xml.dom.minidom.parseString(ET.tostring(root)) with open(cmlFilename, "w") as w: w.write(estring.toprettyxml()) else: tree = ET.ElementTree(root) tree.write(cmlFilename, encoding="utf-8", xml_declaration=True) return cmlFilename