def _analyse(self, mol, pdb, rtf, prm, traj, ftraj): t = Molecule(pdb) t.read(traj) t.filter('not water') t.write(ftraj) m = FFMolecule(filename=mol, rtf=rtf, prm=prm) m.read(ftraj) torsions = m.getRotatableDihedrals() # For each torsion for i in range(len(torsions)): # Create title title = '{}-{}-{}-{}'.format(m.name[torsions[i][0]], m.name[torsions[i][1]], m.name[torsions[i][2]], m.name[torsions[i][3]]) # Measure (r, theta) = self._measure_torsion(torsions[i], m.coords) self._plot_scatter(r, theta, title) self._plot_hist(theta, title)
def main_parameterize(arguments=None): args = getArgumentParser().parse_args(args=arguments) if not os.path.exists(args.filename): raise ValueError('File %s cannot be found' % args.filename) method_map = {'GAFF': FFTypeMethod.GAFF, 'GAFF2': FFTypeMethod.GAFF2, 'CGENFF': FFTypeMethod.CGenFF_2b6} methods = [method_map[method] for method in args.forcefield] # TODO: move into FFMolecule # Get RTF and PRM file names rtf, prm = None, None if args.rtf_prm: rtf, prm = args.rtf_prm # Create a queue for QM if args.queue == 'local': queue = LocalCPUQueue() elif args.queue == 'Slurm': queue = SlurmQueue(_configapp=args.code.lower()) elif args.queue == 'LSF': queue = LsfQueue(_configapp=args.code.lower()) elif args.queue == 'PBS': queue = PBSQueue() # TODO: configure elif args.queue == 'AceCloud': queue = AceCloudQueue() # TODO: configure else: raise NotImplementedError # Override default ncpus if args.ncpus: logger.info('Overriding ncpus to {}'.format(args.ncpus)) queue.ncpu = args.ncpus # Create a QM object if args.code == 'Psi4': qm = Psi4() elif args.code == 'Gaussian': qm = Gaussian() else: raise NotImplementedError # This is for debugging only! if args.fake_qm: qm = FakeQM() logger.warning('Using FakeQM') # Set up the QM object qm.theory = args.theory qm.basis = args.basis qm.solvent = args.environment qm.queue = queue # List rotatable dihedral angles if args.list: mol = FFMolecule(args.filename, method=methods[0], netcharge=args.charge, rtf=rtf, prm=prm, qm=qm, outdir=args.outdir) print('\n === Parameterizable dihedral angles of %s ===\n' % args.filename) with open('torsions.txt', 'w') as fh: for dihedral in mol.getRotatableDihedrals(): dihedral_name = '%s-%s-%s-%s' % tuple(mol.name[dihedral]) print(' '+dihedral_name) fh.write(dihedral_name+'\n') print() sys.exit(0) # Print arguments print('\n === Arguments ===\n') for key, value in vars(args).items(): print('{:>12s}: {:s}'.format(key, str(value))) print('\n === Parameterizing %s ===\n' % args.filename) for method in methods: print(" === Fitting for %s ===\n" % method.name) # Create the molecule mol = FFMolecule(args.filename, method=method, netcharge=args.charge, rtf=rtf, prm=prm, qm=qm, outdir=args.outdir) mol.printReport() # Copy the molecule to preserve initial coordinates mol_orig = mol.copy() # Update B3LYP to B3LYP-D3 # TODO: this is silent and not documented stuff if qm.theory == 'B3LYP': qm.correction = 'D3' # Update basis sets # TODO: this is silent and not documented stuff if mol.netcharge < 0 and qm.solvent == 'vacuum': if qm.basis == '6-31G*': qm.basis = '6-31+G*' if qm.basis == 'cc-pVDZ': qm.basis = 'aug-cc-pVDZ' logger.info('Changing basis sets to %s' % qm.basis) # Minimize molecule if args.minimize: print('\n == Minimizing ==\n') mol.minimize() # Fit ESP charges if args.fit_charges: print('\n == Fitting ESP charges ==\n') # Set random number generator seed if args.seed: np.random.seed(args.seed) # Select the atoms with fixed charges fixed_atom_indices = [] for fixed_atom_name in args.fix_charge: if fixed_atom_name not in mol.name: raise ValueError('Atom %s is not found. Check --fix-charge arguments' % fixed_atom_name) for aton_index in range(mol.numAtoms): if mol.name[aton_index] == fixed_atom_name: fixed_atom_indices.append(aton_index) logger.info('Charge of atom %s is fixed to %f' % (fixed_atom_name, mol.charge[aton_index])) # Fit ESP charges score, qm_dipole = mol.fitCharges(fixed=fixed_atom_indices) # Print results mm_dipole = mol.getDipole() score = np.sum((qm_dipole[:3] - mm_dipole[:3])**2) print('Charge fitting score: %f\n' % score) print('QM dipole: %f %f %f; %f' % tuple(qm_dipole)) print('MM dipole: %f %f %f; %f' % tuple(mm_dipole)) print('Dipole Chi^2 score: %f\n' % score) # Fit dihedral angle parameters if args.fit_dihedral: print('\n == Fitting dihedral angle parameters ==\n') # Set random number generator seed if args.seed: np.random.seed(args.seed) # Get all rotatable dihedrals all_dihedrals = mol.getRotatableDihedrals() # Choose which dihedrals to fit dihedrals = [] all_dihedral_names = ['-'.join(mol.name[dihedral]) for dihedral in all_dihedrals] for dihedral_name in args.dihedral: if dihedral_name not in all_dihedral_names: raise ValueError('%s is not recognized as a rotatable dihedral angle' % dihedral_name) dihedrals.append(all_dihedrals[all_dihedral_names.index(dihedral_name)]) dihedrals = dihedrals if len(dihedrals) > 0 else all_dihedrals # Set default to all dihedral angles # Fit the parameters mol.fitDihedrals(dihedrals, args.optimize_dihedral) # Output the FF parameters print('\n == Writing results ==\n') mol.writeParameters(mol_orig) # Write energy file energyFile = os.path.join(mol.outdir, 'parameters', method.name, mol.output_directory_name(), 'energies.txt') printEnergies(mol, energyFile) logger.info('Write energy file: %s' % energyFile)
def main_parameterize(arguments=None): args = getArgumentParser().parse_args(args=arguments) if not os.path.exists(args.filename): raise ValueError('File %s cannot be found' % args.filename) method_map = { 'GAFF': FFTypeMethod.GAFF, 'GAFF2': FFTypeMethod.GAFF2, 'CGENFF': FFTypeMethod.CGenFF_2b6 } methods = [method_map[method] for method in args.forcefield] # TODO: move into FFMolecule # Get RTF and PRM file names rtf, prm = None, None if args.rtf_prm: rtf, prm = args.rtf_prm # Create a queue for QM if args.queue == 'local': queue = LocalCPUQueue() elif args.queue == 'Slurm': queue = SlurmQueue(_configapp=args.code.lower()) elif args.queue == 'LSF': queue = LsfQueue(_configapp=args.code.lower()) elif args.queue == 'PBS': queue = PBSQueue() # TODO: configure elif args.queue == 'AceCloud': queue = AceCloudQueue() # TODO: configure queue.groupname = args.groupname queue.hashnames = True else: raise NotImplementedError # Override default ncpus if args.ncpus: logger.info('Overriding ncpus to {}'.format(args.ncpus)) queue.ncpu = args.ncpus if args.memory: logger.info('Overriding memory to {}'.format(args.memory)) queue.memory = args.memory # Create a QM object if args.code == 'Psi4': qm = Psi4() elif args.code == 'Gaussian': qm = Gaussian() else: raise NotImplementedError # This is for debugging only! if args.fake_qm: qm = FakeQM2() logger.warning('Using FakeQM') # Set up the QM object qm.theory = args.theory qm.basis = args.basis qm.solvent = args.environment qm.queue = queue # List rotatable dihedral angles if args.list: mol = FFMolecule(args.filename, method=methods[0], netcharge=args.charge, rtf=rtf, prm=prm, qm=qm, outdir=args.outdir) print('\n === Parameterizable dihedral angles of %s ===\n' % args.filename) with open('torsions.txt', 'w') as fh: for dihedral in mol.getRotatableDihedrals(): dihedral_name = '%s-%s-%s-%s' % tuple(mol.name[dihedral]) print(' ' + dihedral_name) fh.write(dihedral_name + '\n') print() sys.exit(0) # Print arguments print('\n === Arguments ===\n') for key, value in vars(args).items(): print('{:>12s}: {:s}'.format(key, str(value))) print('\n === Parameterizing %s ===\n' % args.filename) for method in methods: print(" === Fitting for %s ===\n" % method.name) # Create the molecule mol = FFMolecule(args.filename, method=method, netcharge=args.charge, rtf=rtf, prm=prm, qm=qm, outdir=args.outdir) mol.printReport() # Copy the molecule to preserve initial coordinates mol_orig = mol.copy() # Update B3LYP to B3LYP-D3 # TODO: this is silent and not documented stuff if qm.theory == 'B3LYP': qm.correction = 'D3' # Update basis sets # TODO: this is silent and not documented stuff if mol.netcharge < 0 and qm.solvent == 'vacuum': if qm.basis == '6-31G*': qm.basis = '6-31+G*' if qm.basis == 'cc-pVDZ': qm.basis = 'aug-cc-pVDZ' logger.info('Changing basis sets to %s' % qm.basis) # Minimize molecule if args.minimize: print('\n == Minimizing ==\n') mol.minimize() # Fit ESP charges if args.fit_charges: print('\n == Fitting ESP charges ==\n') # Set random number generator seed if args.seed: np.random.seed(args.seed) # Select the atoms with fixed charges fixed_atom_indices = [] for fixed_atom_name in args.fix_charge: if fixed_atom_name not in mol.name: raise ValueError( 'Atom %s is not found. Check --fix-charge arguments' % fixed_atom_name) for aton_index in range(mol.numAtoms): if mol.name[aton_index] == fixed_atom_name: fixed_atom_indices.append(aton_index) logger.info('Charge of atom %s is fixed to %f' % (fixed_atom_name, mol.charge[aton_index])) # Fit ESP charges _, qm_dipole = mol.fitCharges(fixed=fixed_atom_indices) # Copy the new charges to the original molecule mol_orig.charge[:] = mol.charge # Print dipoles logger.info('QM dipole: %f %f %f; %f' % tuple(qm_dipole)) mm_dipole = mol.getDipole() if np.all(np.isfinite(mm_dipole)): logger.info('MM dipole: %f %f %f; %f' % tuple(mm_dipole)) else: logger.warning( 'MM dipole cannot be computed. Check if elements are detected correctly.' ) # Fit dihedral angle parameters if args.fit_dihedral: print('\n == Fitting dihedral angle parameters ==\n') # Set random number generator seed if args.seed: np.random.seed(args.seed) # Get all rotatable dihedrals all_dihedrals = mol.getRotatableDihedrals() # Choose which dihedrals to fit dihedrals = [] all_dihedral_names = [ '-'.join(mol.name[dihedral]) for dihedral in all_dihedrals ] for dihedral_name in args.dihedral: if dihedral_name not in all_dihedral_names: raise ValueError( '%s is not recognized as a rotatable dihedral angle' % dihedral_name) dihedrals.append( all_dihedrals[all_dihedral_names.index(dihedral_name)]) dihedrals = dihedrals if len( dihedrals ) > 0 else all_dihedrals # Set default to all dihedral angles # Fit the parameters mol.fitDihedrals(dihedrals, args.optimize_dihedral) # Output the FF parameters print('\n == Writing results ==\n') mol.writeParameters(mol_orig) # Write energy file energyFile = os.path.join(mol.outdir, 'parameters', method.name, mol.output_directory_name(), 'energies.txt') printEnergies(mol, energyFile) logger.info('Write energy file: %s' % energyFile)