Example #1
0
    def getCovalentlyBoundFragments(self, idx):
        """ Returns list of fragments that are covalently connected to the idx fragment

            Arguments:
            ----------
            idx : the fragment index to use when looking for other covalently bound fragments

            Returns:
            --------
            A list of fragments covalently bound to the idx'th fragment.
        """
        atomids = self._fragments[idx]
        bonds = self._fragmentation.getExplicitlyBreakAtomPairs()

        other_fragment_atomids = []
        other_fragments = []

        if not self._fragmentation.doQMMMIncludeCovalent():
            return other_fragments

        print("Info: FragIt will include all fragments covalently bound in the QM region.")

        # let us find the nearby fragments that are covalently connected
        # currently, this only works with nearest neighbours
        for (l,r) in bonds:
            if l in atomids:
                other_fragment_atomids.append(r)
            if r in atomids:
                other_fragment_atomids.append(l)

        # lets find the associated fragments
        for ifg,atoms in enumerate(self._fragments):
            if len(atoms) > len(listDiff(atoms, other_fragment_atomids)):
                other_fragments.append(ifg)

        return other_fragments
Example #2
0
    def pop_qm_fragment(self):
        """ Remove the qm fragments from the fragmentation. Adds hydrogens to both the
            qm-fragment that is returned and to the neighbouring fragments if bonds were cut.
        """

        # at this point, fragments have been generated
        fragments = self._fragmentation.getFragments()

        # investigate which fragments should be included in the QM-region
        qmfrags = self._qmfrags[:]
        distance = self._fragmentation.getActiveAtomsDistance()
        qmfrags = Uniqify(self._add_fragments_to_QM(qmfrags))
        qmfrags.sort()
        qmfrags.reverse()

        qm_region_charge = 0

        fragments_for_qm_no_hydrogens = []

        # instead of removing the qm-fragment, we rather adopt a quite novel approach
        # in which we signal to the user of the API that the fragment is not to be used
        # further by setting its original atom numbers to -1
        for idx in qmfrags:
            qm_region_charge += self._qm_charges[idx]
            old_fragment = fragments.pop(idx) 
            fragments.insert(idx, [-1 for i in old_fragment])
            fragments_for_qm_no_hydrogens.insert(0,old_fragment[:])

        # for simplicity, let us just squash the qm fragments into one big fragment
        fragments_for_qm_no_hydrogens = ravel2D(fragments_for_qm_no_hydrogens)

        breaks = self._fragmentation.getExplicitlyBreakAtomPairs()
        if len(breaks) == 0:
            return (fragments_for_qm_no_hydrogens, qm_region_charge)

        # below here: add hydrogens to qm-fragment and to the rest of the capped structure
        fragment_for_qm = fragments_for_qm_no_hydrogens[:]

        # first, fix the QM-fragment, removing any bond-breaks that reside
        # inside (or bordering) the qm-fragment. if breaks are bordering,
        # add appropriate hydrogen atoms.
        lenqmfrags = len(fragments_for_qm_no_hydrogens)
        remove_breaks = []
        for ibreak, bbreak in enumerate(breaks):
            lendiff = len(listDiff(fragments_for_qm_no_hydrogens, list(bbreak)))
            difflen = lenqmfrags - lendiff

            # the break is not present in the qm-region, leave it
            if difflen == 0: continue
            # mark the ibreak'th item for removal. no hydrogens to be added
            if difflen == 2: remove_breaks.append(ibreak)
            # the break is bordering the qm-region and the mm-region
            if difflen == 1:

                for iibreak in bbreak:
                    # fix the qm-fragment first
                    if iibreak in fragments_for_qm_no_hydrogens:
                        new_atoms = self.satisfyValency(fragments_for_qm_no_hydrogens, iibreak, bbreak)
                        if len(new_atoms) > 0:
                            print("Info: FragIt adds", len(new_atoms), "atom(s) to the QM fragment.")
                            self._fragmentation._atom_names.extend(['  H '] * len(new_atoms))
                            fragment_for_qm.extend(new_atoms)

                    # then fix the fragments themselves
                    # INFO/WARNING: this is a lists of lists thing. BE CAREFULL
                    for ifragment, fragment in enumerate(fragments):
                        if iibreak in fragment:
                            new_atoms = self.satisfyValency(fragment, iibreak, bbreak)
                            print("Info: FragIt adds", len(new_atoms), "atom(s) to MM fragment", ifragment+1)
                            self._fragmentation._atom_names.extend(['  H '] * len(new_atoms))
                            fragments[ifragment].extend(new_atoms)

                # also mark the ibreak'th item for removal
                remove_breaks.append(ibreak)

        for ibreak in remove_breaks:
            self._fragmentation.popExplicitlyBreakAtomPairs(breaks[ibreak])

        #print("FRAGIT: [qm] {0}".format(fragment_for_qm))
        return (fragment_for_qm, qm_region_charge)
Example #3
0
 def test_listDiff(self):
     test_array1 = range(10)
     test_array2 = range(3,7)
     self.assertEqual( util.listDiff( test_array1, test_array2 ), [0,1,2,7,8,9] )
     self.assertRaises( ValueError, util.listDiff, test_array2, test_array1 )