''' Created on 2011-1-23 @author: madlee ''' from kuai.unit import default_units from math import pi as PI SPEED_OF_LIGHT = default_units.parse(299792458, 'm/s')
def setup_model(mols, partable, par): if isinstance(mols, Molecule): mols = [(mols, 1)] elif len(mols) == 2 and isinstance(mols[0], Molecule): mols = [mols] result = Model() result.parameters = par result.mols = mols result.charges = [] result.masses = [] result.coords = [] result.atomtype = [] result.group_id = [] masses_table = partable["atom/mass"] type2id = partable["atom/type"] amu, _, _ = default_units.parse(1, "amu") angerstron, _, _ = default_units.parse(1, "A") next_group_id = 0 for m, n in mols: charges = [] masses = [] coords = [] atomtype = [] group_id = [] for a in m.atoms: if hasattr(a, "partial_charge"): charges.append(a.partial_charge) else: charges.append(0.0) if a.type in masses_table: masses.append(par[masses_table[a.type]]) else: masses.append(a.weight * amu) if hasattr(a, "group_id"): group_id.append(a.group_id) assert a.type in type2id atomtype.append(type2id[a.type]) coords.append(a.coord.x * angerstron) coords.append(a.coord.y * angerstron) coords.append(a.coord.z * angerstron) result.masses += masses * n result.coords += coords * n result.charges += charges * n result.atomtype += atomtype * n group_id_map = {} for i in group_id: group_id_map[i] = 0 gid_in_m = [i for i in group_id_map.iterkeys()] gid_in_m.sort() for i in range(len(gid_in_m)): group_id_map[gid_in_m[i]] = i for i in range(len(group_id)): group_id[i] = group_id_map[group_id[i]] for i in range(n): result.group_id += [gid + next_group_id for gid in group_id] next_group_id += len(gid_in_m) if len(result.charges) != len(result.masses): del result.charges if len(result.group_id) != len(result.masses): del result.group_id return result
def read_ppf(file): line = file.next().rstrip() if line != '#DFF:PPF': raise RuntimeError("The input file is not a valid PPF file.") line = file.next().rstrip() if not line.startswith('#PROTOCOL'): raise RuntimeError("The input file is not a valid PPF file.") tokens = line.split('=') if len(tokens) != 2: raise RuntimeError("The input file is not a valid PPF file.") type = tokens[1].strip() COULOMB_CONST, _, _ = default_units.parse(8.987551787e9, 'N m2 / C2') index = {} parameters = [0.0, COULOMB_CONST] index['forcefield']={'type':type} for line in file: tokens = parse_line(line) if tokens: if tokens[0] == 'E0': # Useless term pass elif tokens[0] == 'ATYPE': if 'atom/mass' not in index: index['atom/mass'] = {} key2par = index['atom/mass'] key = ' '.join(tokens[1]) tokens = tokens[2] assert len(tokens) == 2 par = tokens[1] par, _, _ = default_units.parse(par, 'amu') key2par[key] = len(parameters) parameters.append(par) elif tokens[0] == 'N12_6': if 'nonbond/lj12_6' not in index: index['nonbond/lj12_6'] = {} key2par = index['nonbond/lj12_6'] key = ' '.join(tokens[1]) tokens = tokens[2] assert len(tokens) == 2 key2par[key] = len(parameters) par, _, _ = default_units.parse(tokens[0], 'A') parameters.append(par) par, _, _ = default_units.parse(tokens[1], 'kcal/mol') parameters.append(par) elif tokens[0] == 'ATC': if 'atom/charge' not in index: index['atom/charge'] = {} key2par = index['atom/charge'] key = ' '.join(tokens[1]) tokens = tokens[2] assert len(tokens) == 1 key2par[key] = len(parameters) par, _, _ = default_units.parse(tokens[0], 'e') parameters.append(par) elif tokens[0] == 'BINC': if 'bond/binc' not in index: index['bond/binc'] = {} key2par = index['bond/binc'] key = tokens[1] assert len(key) == 2 if key[0] > key[1]: key[0], key[1] = key[1], key[0] reverse=True else: reverse=False key = ' '.join(key) tokens = tokens[2] assert len(tokens) == 1 key2par[key] = len(parameters) par, _, _ = default_units.parse(tokens[0], 'e') if reverse: parameters.append(-par) else: parameters.append(par) elif tokens[0] == 'BHARM': if 'bond/harmonic' not in index: index['bond/harmonic'] = {} key2par = index['bond/harmonic'] key = tokens[1] assert len(key) == 2 if key[0] > key[1]: key[0], key[1] = key[1], key[0] reverse=True else: reverse=False key = ' '.join(key) tokens = tokens[2] assert len(tokens) == 2 key2par[key] = len(parameters) par, _, _ = default_units.parse(tokens[0], 'A') parameters.append(par) par, _, _ = default_units.parse(tokens[1], 'kcal/mol/A2') parameters.append(par) elif tokens[0] == 'AHARM': if 'angle/harmonic' not in index: index['angle/harmonic'] = {} key2par = index['angle/harmonic'] key = tokens[1] assert len(key) == 3 if key[0] > key[2]: key[0], key[2] = key[2], key[0] reverse=True else: reverse=False key = ' '.join([i.strip() for i in key]) tokens = tokens[2] assert len(tokens) == 2 key2par[key] = len(parameters) par, _, _ = default_units.parse(tokens[0], 'deg') parameters.append(par) par, _, _ = default_units.parse(tokens[1], 'kcal/mol/rad2') parameters.append(par) elif tokens[0] == 'TCOSP': if 'torsion/cos_poly5' not in index: index['torsion/cos_poly5'] = {} key2par = index['torsion/cos_poly5'] key = tokens[1] assert len(key) == 4 if key[1] > key[2] or key[1] == key[2] and key[0] > key[3]: key[0], key[3] = key[3], key[0] key[1], key[2] = key[2], key[1] reverse=True else: reverse=False key = ' '.join([i.strip() for i in key]) tokens = tokens[2] assert len(tokens) % 3 == 0 key2par[key] = len(parameters) v = [0] * 5 k = [0] * 6 for i in range(0, len(tokens), 3): n = int(tokens[i+2]+.1) kI = tokens[i+1] phi = tokens[i+0] if phi > 150: assert abs(phi-180) < 1 kI = -kI else: assert abs(phi) < 1 if n % 2 == 0: kI = -kI assert v[n] == 0 v[n] = 2 * kI k[0]=v[2]+(v[1]+v[3])/2 k[1]=0.5*(3*v[3]-v[1]) k[2]=-v[2]+4*v[4] k[3]=-2*v[3] k[4]=-4*v[4] k[5]=0 for i in range(0, len(k)): k[i], _, _ = default_units.parse(k[i], 'kcal/mol') parameters += k elif tokens[0] == 'IBCOS': if 'improper_torsion/cos_poly5' not in index: index['improper_torsion/cos_poly5'] = {} key2par = index['improper_torsion/cos_poly5'] key = tokens[1] assert len(key) == 4 key = ' '.join(key) tokens = tokens[2] assert len(tokens) % 3 == 0 key2par[key] = len(parameters) v = [0] * 6 k = [0] * 6 for i in range(0, len(tokens), 3): n = int(tokens[i+2]+.1) kI = tokens[i+1] phi = tokens[i+0] if phi > 150: assert abs(phi-180) < 1 kI = -kI else: assert abs(phi) < 1 if n % 2 == 0: kI = -kI assert v[n] == 0 v[n] = 2 * kI k[0]=v[2]+(v[1]+v[3])/2 k[1]=0.5*(3*v[3]-v[1]) k[2]=-v[2]+4*v[4] k[3]=-2*v[3] k[4]=-4*v[4] k[5]=0 for i in range(0, len(k)): k[i], _, _ = default_units.parse(k[i], 'kcal/mol') parameters += k else: raise RuntimeError("The function %s is not supported yet." % tokens[0]) if type == 'AMBER': index['forcefield']['scale14/vdw'] = 0.5 index['forcefield']['scale14/columnb'] = 1 / 1.2 atomtype, newindex = combine(index['nonbond/lj12_6'], parameters, combine_arithmatic) newindex[':columnb-constant:'] = 1 index['pair-nonbond/lj12_6'] = newindex index['atom/type'] = atomtype index['pair-14/lj12_6'] = scale_vdw(newindex, parameters, 0.5, 1) columnb14 = parameters[newindex[':columnb-constant:']] / 1.2 index['pair-14/lj12_6'][':columnb-constant:'] = len(parameters) parameters.append(columnb14) else: raise RuntimeError("The force field type %s is not supported yet." % type) return index, parameters