def putAtomsInMolecule(crystal, alist=None, name=None): """Place atoms from a crystal into a molecule inside the crystal. Selected atoms are put into a new Molecule object, which is then placed inside of the Crystal. The atoms are then removed from the crystal. The molecule is placed at the center of mass of the moved atoms. crystal -- The crystal containing the atoms. alist -- A list of indices or names identifying the atoms. If alist is None (default), all atoms from the crystal are placed into a molecule. name -- A name for the molecule. If name is None (default), the name m_cname will be given, where cname is substituted for the crystal's name. Raises TypeError if idxlist identifies a non-atom. """ c = crystal if name is None: name = "m_%s" % c.GetName() if alist is None: alist = range(c.GetNbScatterer()) from pyobjcryst.molecule import Molecule from pyobjcryst.atom import Atom m = Molecule(c, name) # center of mass cx = cy = cz = 0.0 # mapping fractional coords back into [0, 1) from math import floor f = lambda v: v - floor(v) scat = [] for id in alist: s = c.GetScatt(id) if not isinstance(s, Atom): raise TypeError("identifier '%s' does not specify an Atom") sp = s.GetScatteringPower() scat.append(s) x, y, z = map(f, [s.X, s.Y, s.Z]) x, y, z = c.FractionalToOrthonormalCoords(x, y, z) m.AddAtom(x, y, z, sp, s.GetName()) cx += x cy += y cz += z # Adjust center of mass cx /= len(alist) cy /= len(alist) cz /= len(alist) # Remove scatterers from the crystal for s in scat: c.RemoveScatterer(s) # Put the molecule at the CoM m.X, m.Y, m.Z = c.OrthonormalToFractionalCoords(cx, cy, cz) # Add the molecule to the crystal c.AddScatterer(m) m.UpdateScattCompList() return
nphcrystal = loadCrystal('naphthalene.cif') nphmol = Molecule(nphcrystal, "naphthalene") numatoms = nphcrystal.GetNbScatterer() atoms = [nphcrystal.GetScatterer(i) for i in range(numatoms)] xyzf = np.array([(a.X, a.Y, a.Z) for a in atoms]) xyzc = np.array( [nphcrystal.FractionalToOrthonormalCoords(x, y, z) for x, y, z in xyzf]) xyzcmol = xyzc - xyzc.mean(axis=0) spC1 = nphcrystal.GetScatteringPower('C1') for a, (xc, yc, zc) in zip(atoms, xyzcmol): nphmol.AddAtom(xc, yc, zc, spC1, a.GetName()) nphcrystal.RemoveScatterer(a) molposition = xyzf.mean(axis=0) nphcrystal.AddScatterer(nphmol) nphmol.X, nphmol.Y, nphmol.Z = xyzf.mean(axis=0) pdfcntb = PDFContribution('pdfcntb') pdfcntb.loadData('naphthalene.gr') pdfcntb.qdamp = 0.06 pdfcntb.setCalculationRange(1.1, 25) pdfcntb.addStructure('nphmol', nphmol, periodic=False) pdfcntb.addStructure('widecrystal', nphcrystal, periodic=True) pdfcntb.addStructure('widemolecule', nphcrystal, periodic=False) pdfcntb.widecrystal._calc.peakwidthmodel = ConstantPeakWidth() pdfcntb.widemolecule._calc.peakwidthmodel = ConstantPeakWidth() from naphthalene_functions import fixpeakwidthparameters fixpeakwidthparameters(pdfcntb) pdfcntb.setEquation('scale * (nphmol + widecrystal - widemolecule)')
def putAtomsInMolecule(crystal, alist=None, name=None): """Place atoms from a crystal into a molecule inside the crystal. Selected atoms are put into a new Molecule object, which is then placed inside of the Crystal. The atoms are then removed from the crystal. The molecule is placed at the center of mass of the moved atoms. crystal -- The crystal containing the atoms. alist -- A list of indices or names identifying the atoms. If alist is None (default), all atoms from the crystal are placed into a molecule. name -- A name for the molecule. If name is None (default), the name m_cname will be given, where cname is substituted for the crystal's name. Raises TypeError if idxlist identifies a non-atom. """ c = crystal if name is None: name = "m_%s" % c.GetName() if alist is None: alist = range(c.GetNbScatterer()) from pyobjcryst.molecule import Molecule from pyobjcryst.atom import Atom m = Molecule(c, name) # center of mass cx = cy = cz = 0.0 # mapping fractional coords back into [0, 1) from math import floor f = lambda v: v - floor(v) scat = [] for idx in alist: s = c.GetScatt(idx) if not isinstance(s, Atom): raise TypeError("identifier '%s' does not specify an Atom") sp = s.GetScatteringPower() scat.append(s) x, y, z = map(f, [s.X, s.Y, s.Z]) x, y, z = c.FractionalToOrthonormalCoords(x, y, z) m.AddAtom(x, y, z, sp, s.GetName()) cx += x cy += y cz += z # Adjust center of mass cx /= len(alist) cy /= len(alist) cz /= len(alist) # Remove scatterers from the crystal for s in scat: c.RemoveScatterer(s) # Put the molecule at the CoM m.X, m.Y, m.Z = c.OrthonormalToFractionalCoords(cx, cy, cz) # Add the molecule to the crystal c.AddScatterer(m) m.UpdateScattCompList() return
nphcrystal = loadCrystal('naphthalene.cif') nphmol = Molecule(nphcrystal, "naphthalene") numatoms = nphcrystal.GetNbScatterer() atoms = [nphcrystal.GetScatterer(i) for i in range(numatoms)] xyzf = np.array([(a.X, a.Y, a.Z) for a in atoms]) xyzc = np.array([nphcrystal.FractionalToOrthonormalCoords(x, y, z) for x, y, z in xyzf]) xyzcmol = xyzc - xyzc.mean(axis=0) spC1 = nphcrystal.GetScatteringPower('C1') for a, (xc, yc, zc) in zip(atoms, xyzcmol): nphmol.AddAtom(xc, yc, zc, spC1, a.GetName()) nphcrystal.RemoveScatterer(a) molposition = xyzf.mean(axis=0) nphcrystal.AddScatterer(nphmol) nphmol.X, nphmol.Y, nphmol.Z = xyzf.mean(axis=0) pdfcntb = PDFContribution('pdfcntb') pdfcntb.loadData('naphthalene.gr') pdfcntb.qdamp = 0.06 pdfcntb.setCalculationRange(1.1, 25) pdfcntb.addStructure('nphmol', nphmol, periodic=False) pdfcntb.addStructure('widecrystal', nphcrystal, periodic=True) pdfcntb.addStructure('widemolecule', nphcrystal, periodic=False) pdfcntb.widecrystal._calc.peakwidthmodel = ConstantPeakWidth() pdfcntb.widemolecule._calc.peakwidthmodel = ConstantPeakWidth() from naphthalene_functions import fixpeakwidthparameters fixpeakwidthparameters(pdfcntb) pdfcntb.setEquation('scale * (nphmol + widecrystal - widemolecule)')