def test_optimisingOverlays(self):

        pts1 = np.array([[-0.541357990208,0.840223963793,0.967951435],
			 [-0.507301547591,-0.542664198999,1.171816351],
			 [0.0255987444643,-1.38443421464,0.204678748],
			 [0.556845352422,-0.849058545788,-0.964797836],
			 [0.509212767371,0.526541086859,-1.159201955],
			 [-0.0429973264567,1.40939190877,-0.220446743]])

	pts2 = np.array([[-0.452870161944,1.0471304112,0.822046103134],
		         [0.838143143533,0.525685681579,0.978663279603],
			 [1.28692322978,-0.496230348673,0.148563133317],
			 [0.457098160295,-1.03724996618,-0.829129779641],
			 [-0.837847702903,-0.538192702582,-0.964350371592],
	        	 [-1.29144666876,0.49885692466,-0.155792364821]])

        np.testing.assert_array_almost_equal(np.mean(pts1, axis=0),
                                             np.mean(pts2, axis=0))

	from listMathsSlow import rmsd
	print rmsd(pts1, pts2)

	from listMathsSlow import overlay_points_RMSD
        originalRMSD, qRot = overlay_points_RMSD(pts1, pts2)
#	print originalRMSD
        from quaternions import quaternion_rotatn
        self.assertAlmostEqual(rmsd(pts2,
                                    np.array([quaternion_rotatn(x, qRot) for x in pts1])),
                               originalRMSD)

        from listMathsSlow import optimalZRotation
        bestRMSDZ, bestQRotZ = optimalZRotation(pts1,
                                                pts2)

        from quaternions import make_quat_rot2
        from listMathsSlow import rmsdNoRestriction

        #check with a grid that optimal Z really is about the best
        _nPts = 20
        gridOptimisedPoints = np.array([rmsd(pts2,
                                             np.array([quaternion_rotatn(x, 
                                                                         make_quat_rot2(float(i)/float(_nPts) * 2. * np.pi,
                                                                                        np.array([0., 0., 1.]))) 
                                                       for x in pts1])
                                             )
                                        for i in xrange(_nPts)])
        self.assertTrue(all([x > bestRMSDZ for x in gridOptimisedPoints]))
        self.assertTrue(bestRMSDZ + 1.e-3 > gridOptimisedPoints[3])
示例#2
0
 def functionOfOverlay(angle, pts1, pts2, allowRMSDNoRestriction):
     _quat = make_quat_rot2(angle, np.array([0., 0., 1.]))
     rotatedPts1 = np.array([quaternion_rotatn(x, _quat) for x in pts1])
     if allowRMSDNoRestriction:
         return rmsdNoRestriction(rotatedPts1, pts2)
     else:
         return rmsd(rotatedPts1, pts2)
示例#3
0
    def boundsShowSurface(self, nanocrystalSize, nanoCell, surfaceCell,
                          angleVariables):
        ''' estimate bounds for surface during plotting (wont effect calculation) 
            returns surfaceMinA, surfaceMaxA, surfaceMinB, surfaceMaxB
            (status - run this and visually inspected things, but not extended to general angles, thoroughly tested) '''

        cornersNanoCrystal = np.dot(
            np.array([[nanocrystalSize[0], 0.,
                       0.], [0., nanocrystalSize[1], 0.],
                      [nanocrystalSize[0], nanocrystalSize[1], 0.],
                      [0., 0., 0.]]), nanoCell)

        #zyz convention -- (after comparing to Stone's book) --
        #        assert(all([x==0. for x in angleVariables[1:]]))
        from quaternions import zyz_quaternion, quaternion_rotatn
        cornersNanoCrystal = np.array([
            quaternion_rotatn(
                x,
                zyz_quaternion(
                    *map(lambda x: x * np.pi / 180., angleVariables)))
            for x in cornersNanoCrystal
        ])

        #find bounds in surface cell
        boundsSurface = np.dot(cornersNanoCrystal, np.linalg.inv(surfaceCell))
        boundsSurface = np.vstack(
            [np.min(boundsSurface, axis=0),
             np.max(boundsSurface, axis=0)])

        return map(int, [
            np.floor(boundsSurface[0, 0]),
            np.ceil(boundsSurface[1, 0]),
            np.floor(boundsSurface[0, 1]),
            np.ceil(boundsSurface[1, 1])
        ])
    def rotateASEAtomsAroundCentroidQuat(self, quat):
        from quaternions import quaternion_rotatn
        oldPositions = self.aseAtoms.get_positions()
        _mean = np.mean(oldPositions, axis=0)
        oldPositions -= _mean
        newPositions = [quaternion_rotatn(x, quat) for x in oldPositions]

        for i in xrange(len(self.aseAtoms)):
            self.aseAtoms[i].position = newPositions[i] + _mean
    def calculateAxisSystem(self, atom1, atom2, atom3):
        ''' atom1 (int) is (index for) pivot, to atom2 is x, 3 -> y . Make right handed frame '''

        from quaternions import make_quat_rot2, quaternion_rotatn

        internalX = (self.aseAtoms[atom2].position - self.aseAtoms[atom1].position) /\
                     np.linalg.norm(self.aseAtoms[atom1].position - self.aseAtoms[atom2].position)
        internalY = (self.aseAtoms[atom3].position - self.aseAtoms[atom1].position) /\
                     np.linalg.norm(self.aseAtoms[atom3].position - self.aseAtoms[atom1].position)
        internalZ = np.cross(internalX, internalY) / np.linalg.norm(
            np.cross(internalX, internalY))
        _angle = np.pi / 2. - vecAngle(internalX, internalY)
        rotationQ = make_quat_rot2(_angle, internalZ)
        internalY = quaternion_rotatn(internalY, rotationQ)

        self.axisSystem = np.vstack([internalX, internalY, internalZ])
        return self.axisSystem
def makeFilesSingleMolSurface(surfaceCif,
                              nanocrystalCif,
                              surfaceDMA,
                              nanocrystalDMA,
                              nanocrystalAngles=[0., 0., 0.],
                              nanocrystalSize=[1, 1, 1],
                              freezeRotations=False,
                              manuallyRotateNanocrystal=False,
                              rotateAllAngles=False):
    ''' Writes the files needed to run orient (.in is the input) 
        Also can write other things to visualize components or composite - may be useful as check '''

    from analyseClusters import getSpeciesListCIF, Surface, splitASEAtomsToMols, Crystal
    from orientIO import NanocrystalOnSurfaceInput
    #from ccdc.io import CrystalReader
    from ioAndInterfaces import ccdcCrystalToASE
    from multipoleFile import MultipoleFile, BOHRTOANGSTROM
    from copy import deepcopy

    #variables
    #    nanocrystalAngles = [0., 0., 0.]

    #reading filenames
    moleculeFilename = 'nanoCryst.punch'

    #writing filenames
    cellFilename = 'surface.cell'
    inputFilename = 'surfaceCalc.in'

    #other filenams
    potentialFilename = 'fit4orient.pots'

    surfaceCrystal = Crystal.fromCif(surfaceCif)
    nanoCrystal = Crystal.fromCif(nanocrystalCif)

    #keep only lowest molecule along c axis
    print "%s mols in nanocrystal %s in surface" % (
        len(nanoCrystal.asymmetricMolecules),
        len(surfaceCrystal.asymmetricMolecules))
    nanoCrystal.asymmetricMolecules = [
        sorted(
            nanoCrystal.asymmetricMolecules,
            key=lambda x: np.dot(x.aseAtoms.get_center_of_mass(scaled=False),
                                 nanoCrystal.aseCell[2]))[0]
    ]
    print 'MASSIVE HACK - KEEPING BUT A SINGLE MOL'
    surfaceCrystal.asymmetricMolecules = [
        sorted(
            surfaceCrystal.asymmetricMolecules,
            key=lambda x: np.dot(x.aseAtoms.get_center_of_mass(scaled=False),
                                 surfaceCrystal.aseCell[2]))[0]
    ]

    # If doing this, rotate the nanocrystal so that the bottom molecule of surface is same orientation as it
    if manuallyRotateNanocrystal:

        from listMathsSlow import overlay_points_RMSD
        from quaternions import quaternion_rotatn

        targetAtomPositions = sorted(
            surfaceCrystal.asymmetricMolecules,
            key=lambda x: np.dot(x.aseAtoms.get_center_of_mass(
                scaled=False), surfaceCrystal.aseCell[2]
                                 ))[0].aseAtoms.get_positions()[7:13, :]

        nanoAtoms = nanoCrystal.asymmetricMolecules[0].aseAtoms.get_positions(
        )[7:13, :]
        print 'assuming numbering system such that ring of atoms is 2nd ring ->7-12', nanoAtoms.shape, targetAtomPositions.shape

        if rotateAllAngles:
            print 'dont do this - rotating all angles prevents coplanar surfaces'
            exit()
            _rmsd, _qRot = overlay_points_RMSD(
                nanoAtoms - np.mean(nanoAtoms, axis=0),
                targetAtomPositions - np.mean(targetAtomPositions, axis=0))
            assert (_rmsd < 0.1)
        else:
            #just rotate around z axis - the allowRMSDNoRestriction should not be used- just make sure atomic numbering consistent
            from listMathsSlow import optimalZRotation
            _rmsd, _qRot = optimalZRotation(
                nanoAtoms - np.mean(nanoAtoms, axis=0),
                targetAtomPositions - np.mean(targetAtomPositions, axis=0),
                allowRMSDNoRestriction=False)

        def tempDistPrint(x):
            print[np.linalg.norm(x[i + 1] - x[i]) for i in range(5)]

#        tempDistPrint(targetAtomPositions - np.mean(targetAtomPositions, axis=0))
#        tempDistPrint(np.array([quaternion_rotatn(x, _qRot) for x in nanoAtoms - np.mean(nanoAtoms, axis=0)]))

#rotate nanocrystal atoms and cell

        nanoCrystal.asymmetricMolecules[0].rotateASEAtomsAroundCentroidQuat(
            _qRot)
        nanoCrystal.aseCell = np.array(
            [quaternion_rotatn(x, _qRot) for x in nanoCrystal.aseCell])

    print "%s mols in nanocrystal %s in surface" % (
        len(nanoCrystal.asymmetricMolecules),
        len(surfaceCrystal.asymmetricMolecules))

    print "Atoms in nanoCrystal moleucules " + " ".join(
        [str(len(x.aseAtoms)) for x in nanoCrystal.asymmetricMolecules])
    print "Atoms in surface     moleucules " + " ".join(
        [str(len(x.aseAtoms)) for x in surfaceCrystal.asymmetricMolecules])

    punchSurface = MultipoleFile(fileName=surfaceDMA)
    punchNanocrystal = MultipoleFile(fileName=nanocrystalDMA)
    print "%s atoms in surfaceDMA" % (len(punchSurface.aseAtoms()))
    print "%s atoms in nanocrystalDMA" % (len(punchNanocrystal.aseAtoms()))
    #    punchSurface.writeFile('dummyPunchSurf.cif')
    #    punchNanocrystal.writeFile('dummyPunchNano.cif')

    uniqueAtomTypes = list(set(list(surfaceCrystal.uniqueElements()) +\
                               list(nanoCrystal.uniqueElements())))

    #print 'using same atoms for surface and nanocrystal'
    print 'automatically setting all H bonded to O or N to Hn type'

    inputHandler = NanocrystalOnSurfaceInput()

    #displace by c of surfaceCrystal - and add a bit
    displacementBohr = (surfaceCrystal.aseCell[2] +
                        np.array([0., 0., 3.5])) / BOHRTOANGSTROM

    variables = [['x1', displacementBohr[0], 'Bohr'],
                 ['y1', displacementBohr[1], 'Bohr'],
                 ['z1', displacementBohr[2], 'Bohr'],
                 ['alpha1', nanocrystalAngles[0], 'Degree'],
                 ['beta1', nanocrystalAngles[1], 'Degree'],
                 ['gamma1', nanocrystalAngles[2], 'Degree']]

    atomsInCell = [
        punchSurface.newPositions(m.aseAtoms.positions)
        for m in surfaceCrystal.asymmetricMolecules
    ]
    atomsInNanocrystal = [
        punchNanocrystal.newPositions(m.aseAtoms.positions)
        for m in nanoCrystal.asymmetricMolecules
    ]

    with open(moleculeFilename, 'w') as outf:
        #acidic hydrogens
        for im, m in enumerate(atomsInNanocrystal):
            m.setAtomTypes(
                dict([(x, 'Hn') for x in nanoCrystal.asymmetricMolecules[im].
                      indicesAcidicHydrogens()]))
        outf.write('\n'.join([
            x.stringFormat(header='', printTypes=True)
            for x in atomsInNanocrystal
        ]))

    print 'passing one molecule in nanocrystal as only needs cell -- clear up later'
    aseAtomsNanocrystal = nanoCrystal.asymmetricMolecules[0].aseAtoms

    with open(cellFilename, 'w') as outf:
        #acidic hydrogens
        for im, m in enumerate(atomsInCell):
            m.setAtomTypes(
                dict([(x, 'Hn') for x in surfaceCrystal.
                      asymmetricMolecules[im].indicesAcidicHydrogens()]))
        outf.write(
            inputHandler.cellAndSitesString(surfaceCrystal.aseCell,
                                            atomsInCell))

    with open(inputFilename, 'w') as outf:
        outf.write(
            inputHandler.inputString(variables=variables,
                                     moleculeFilename=moleculeFilename,
                                     potentialFile=potentialFilename,
                                     cellFile=cellFilename,
                                     nanocrystal=aseAtomsNanocrystal,
                                     surfaceCrystal=surfaceCrystal,
                                     nanocrystalSize=nanocrystalSize,
                                     atomTypes=uniqueAtomTypes,
                                     freezeRotations=freezeRotations))

    #
    # EVERYTHING BELOW HERE IS FOR MY (DHC) DEBUGGING AND LOOKING AT FILES TO CHECK THINGS - NOT USED
    #

    #write temp.xyz with all atoms
    print 'writing temporary xyz file to temp.xyz - note that this used only by DHC, not ORIENT itself'
    try:
        from ase import Atoms
    except ImportError:
        print 'Need ASE to print out temp.xyz but not important for ORIENT - ignore this'
        return
#    superSurface = deepcopy(surfaceCrystal)

#    superSurface.filledUnitCellMolecules(superCell=np.array([3,3,2]))
#    print [x[1] for x in variables[3:6]]
    nanocrystalSize = [1, 1, 1]
    print 'hack small nano'
    surfaceBounds = inputHandler.boundsShowSurface(
        nanocrystalSize, nanoCrystal.aseCell, surfaceCrystal.aseCell,
        [x[1] for x in variables[3:6]])
    print nanocrystalSize
    #    print len(superSurface.asymmetricMolecules)
    #    totalAtoms = Atoms(symbols = [x.symbol for m in superSurface.asymmetricMolecules for x in m.aseAtoms] +\
    #                           [x.symbol for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms],
    #                       positions = np.vstack([np.array([x.position for m in superSurface.asymmetricMolecules for x in m.aseAtoms]),
    #                                              displacementBohr * BOHRTOANGSTROM +\
    #                                                  np.array([x.position for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms])])
    #                       )

    #    checkSurfPunch = MultipoleFile()
    #    checkSurfPunch.initFromFile('surface.cell', _fileFormat='punch')
    #    checkSurfPunch.initFromFile('dummySurface.punch', _fileFormat='punch')
    #    checkNanoPunch = MultipoleFile()
    #    checkNanoPunch.initFromFile('nanoCryst.punch')
    #    print checkNanoPunch.atomPositions()[0]
    #    print nanoCrystal.asymmetricMolecules[0].aseAtoms[0].position
    #    print checkSurfPunch.atomPositions()[0]#
    #    print surfaceCrystal.asymmetricMolecules[0].aseAtoms[0].position
    #    tempASE = checkNanoPunch.aseAtoms()
    #    tempASE.write('nanoCheck.xyz')
    #    checkNanoPunch.writeFile('nanoCheck.xyz')
    #    tempASE = checkNanoPunch.aseAtoms()
    #    checkSurfPunch.writeFile('surfCheck.xyz')
    #    exit()
    #    print 'adding big gap'
    totalAtoms = Atoms(symbols = [x.symbol for m in surfaceCrystal.asymmetricMolecules for x in m.aseAtoms
                                           for a in xrange(surfaceBounds[0], surfaceBounds[1] + 1)
                                           for b in xrange(surfaceBounds[2], surfaceBounds[3] + 1)] +\
                                 [x.symbol for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms
                                           for a in xrange(0, nanocrystalSize[0])
                                           for b in xrange(0, nanocrystalSize[1])],
                       positions = np.vstack([np.array([x.position + np.dot(np.array([a, b, 1]), surfaceCrystal.aseCell)
                                                        for m in surfaceCrystal.asymmetricMolecules for x in m.aseAtoms
                                                        for a in xrange(surfaceBounds[0], surfaceBounds[1] + 1)
                                                        for b in xrange(surfaceBounds[2], surfaceBounds[3] + 1)]),
                                              displacementBohr * BOHRTOANGSTROM +\
#                                              np.array([0., 0., 50.]) + displacementBohr * BOHRTOANGSTROM +\
                                              np.array([x.position + np.dot(np.array([a, b, 1]), nanoCrystal.aseCell)
                                                        for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms
                                                        for a in xrange(0, nanocrystalSize[0])
                                                        for b in xrange(0, nanocrystalSize[1])])])

                       )
    #    print np.min(np.array([x.position + np.dot(np.array([a, b, 1]), surfaceCrystal.aseCell)
    #                                                        for m in surfaceCrystal.asymmetricMolecules for x in m.aseAtoms
    #                                                        for a in xrange(surfaceBounds[0], surfaceBounds[1] + 1)
    #                                                        for b in xrange(surfaceBounds[2], surfaceBounds[3] + 1)]), axis=0)
    #    print np.max(np.array([x.position + np.dot(np.array([a, b, 1]), surfaceCrystal.aseCell)
    #                                                        for m in surfaceCrystal.asymmetricMolecules for x in m.aseAtoms
    #                                                        for a in xrange(surfaceBounds[0], surfaceBounds[1] + 1)
    #                                                        for b in xrange(surfaceBounds[2], surfaceBounds[3] + 1)]), axis=0)
    #    print np.min(                                              displacementBohr * BOHRTOANGSTROM +\
    #                                              np.array([x.position + np.dot(np.array([a, b, 1]), nanoCrystal.aseCell)
    #                                                        for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms
    #                                                        for a in xrange(0, nanocrystalSize[0])
    #                                                        for b in xrange(0, nanocrystalSize[1])]), axis=0)
    #    print np.max(                                              displacementBohr * BOHRTOANGSTROM +\
    #                                              np.array([x.position + np.dot(np.array([a, b, 1]), nanoCrystal.aseCell)
    #                                                        for m in nanoCrystal.asymmetricMolecules for x in m.aseAtoms
    #                                                        for a in xrange(0, nanocrystalSize[0])
    #                                                        for b in xrange(0, nanocrystalSize[1])]), axis=0)
    #    print displacementBohr * BOHRTOANGSTROM
    #    print surfaceCrystal.aseCell[2]
    totalAtoms.write('temp.xyz')