136 lines
4.0 KiB
Python
136 lines
4.0 KiB
Python
#A* -------------------------------------------------------------------
|
|
#B* This file contains source code for the PyMOL computer program
|
|
#C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
|
|
#D* -------------------------------------------------------------------
|
|
#E* It is unlawful to modify or remove this copyright notice.
|
|
#F* -------------------------------------------------------------------
|
|
#G* Please see the accompanying LICENSE file for further information.
|
|
#H* -------------------------------------------------------------------
|
|
#I* Additional authors of this source file include:
|
|
#-*
|
|
#-*
|
|
#-*
|
|
#Z* -------------------------------------------------------------------
|
|
|
|
import copy
|
|
|
|
|
|
def combine_fragments(*arg,**kw):
|
|
'''
|
|
merge_fragments(target,source1,source2,source3,...)
|
|
|
|
WARNING: This is not how you *should* combine fragments,
|
|
rather this is just a convenient kludge for getting
|
|
something remotely realistic in a big hurry.
|
|
|
|
NOTE: atom names must be unique throughout -- especially
|
|
including the "capping" atoms used during the ab-initio
|
|
calculations (you can use PyMOL to rename these if they
|
|
happen to coincide).
|
|
'''
|
|
|
|
if 'net_charge' in kw:
|
|
net_charge = kw['net_charge']
|
|
else:
|
|
net_charge = None
|
|
if len(arg)<1:
|
|
raise TypeError('invalid arguments')
|
|
dst = copy.deepcopy(arg[0])
|
|
frg_lst = arg[1:]
|
|
n_frg = len(frg_lst)
|
|
n_dst_atm = len(dst.atom)
|
|
|
|
# create dictionary/indices for shared atoms
|
|
|
|
n_tot = 0
|
|
dst_dict = {}
|
|
for a in dst.atom:
|
|
sig = a.name
|
|
dst_dict[sig] = n_tot
|
|
n_tot = n_tot + 1
|
|
|
|
# create fragment membership list for destination atoms
|
|
|
|
members = []
|
|
for a in range(n_tot):
|
|
members.append([])
|
|
|
|
# create indices for unique atoms
|
|
|
|
for fragment in frg_lst:
|
|
c = 0
|
|
for a in fragment.atom:
|
|
sig = a.name
|
|
if sig in dst_dict:
|
|
a.chg_index = dst_dict[sig]
|
|
members[a.chg_index].append(fragment)
|
|
else:
|
|
# find an attached atom that *is* in the destination structure
|
|
attached_index = None
|
|
for b in fragment.bond:
|
|
attached = None
|
|
if b.index[0]==c:
|
|
attached = fragment.atom[b.index[1]]
|
|
elif b.index[1]==c:
|
|
attached = fragment.atom[b.index[0]]
|
|
if attached is not None:
|
|
if attached.name in dst_dict:
|
|
attached_index = dst_dict[attached.name]
|
|
break
|
|
a.chg_index = n_tot
|
|
if attached_index is not None:
|
|
a.attached_index = attached_index
|
|
n_tot = n_tot + 1
|
|
c = c + 1
|
|
|
|
# create array for charges
|
|
|
|
chg = []
|
|
for a in range(n_frg):
|
|
chg.append([0.0] * n_tot)
|
|
|
|
# now load and count measurements
|
|
|
|
cnt = [0] * n_tot
|
|
c = 0
|
|
for fragment in frg_lst:
|
|
for a in fragment.atom:
|
|
index = a.chg_index
|
|
if (index < n_dst_atm):
|
|
chg[c][index] = chg[c][index] + a.partial_charge
|
|
cnt[index] = cnt[index] + 1
|
|
else:
|
|
aindex = a.attached_index
|
|
chg[c][aindex] = chg[c][aindex] + a.partial_charge
|
|
c = c + 1
|
|
|
|
# now compute average charges for each destination atom
|
|
|
|
avg = []
|
|
for index in range(n_dst_atm):
|
|
if cnt[index]:
|
|
tmp_lst = []
|
|
for a in chg:
|
|
tmp_lst.append(a[index])
|
|
avg.append(sum(tmp_lst)/cnt[index])
|
|
else:
|
|
avg.append(0.0)
|
|
|
|
# correct total charge
|
|
|
|
chg_sum = sum(avg)
|
|
|
|
print("chg_sum",chg_sum)
|
|
if net_charge is not None:
|
|
chg_diff = net_charge - chg_sum
|
|
chg_adjust = chg_diff / n_dst_atm
|
|
else:
|
|
chg_adjust = 0.0
|
|
|
|
c = 0
|
|
for a in dst.atom:
|
|
a.partial_charge = avg[c] + chg_adjust
|
|
c = c + 1
|
|
|
|
return dst
|