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
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)
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 )