def _run(self, molName): self.molName = molName logger.info('Molecule: {}'.format(self.molName)) molFile = os.path.join(home('test-charge'), self.molName + '.mol2') self.mol = Molecule(molFile) self.new_mols = {} self.extras = {} self.new_mols['Gasteiger'] = fitGasteigerCharges(self.mol) try: self.new_mols['AM1-BCC'] = fitChargesWithAntechamber(self.mol, type='bcc') except: pass qm = Psi4() qm.theory = 'B3LYP' qm.basis = '6-311++G**' workDir = os.path.join('tmp', self.molName) os.makedirs(workDir, exist_ok=True) for factor in [-10, -5, -4, -3, -2, -1]: logger.info('Factor: {}'.format(factor)) key = 'ESP b {}'.format(factor) np.random.seed(20181114) # Make ESP grid generation deterministic self.new_mols[key], self.extras[key] = fitESPCharges(self.mol, qm, workDir, restraint_factor=10**factor)
def _fit_initial_charges(mol, args, atom_types): from htmd.charge import fitGasteigerCharges from htmd.parameterization.util import guessBondType logger.info('=== Initial atomic charge fitting ===') if args.charge_type == 'None': logger.info('Initial atomic charges are taken from {}'.format( args.filename)) elif args.charge_type in ('Gasteiger', 'AM1-BCC', 'ESP'): if args.min_type == 'mm': logger.info('Method: Gasteiger') # TODO move to _prepare_molecule if np.any(mol.bondtype == "un"): logger.info('Guessing bond types') mol = guessBondType(mol) mol = fitGasteigerCharges(mol, atom_types=atom_types) # Print the initial charges logger.info('Initial atomic charges:') for name, charge in zip(mol.name, mol.charge): logger.info(' {:4s}: {:6.3f}'.format(name, charge)) logger.info('Molecular charge: {:6.3f}'.format(np.sum(mol.charge))) charge = int(round(np.sum(mol.charge))) if args.charge != charge: raise RuntimeError( 'Molecular charge is set to {}, but Gasteiger atomic charges add up to {}.' .format(args.charge, charge)) elif args.min_type in ('None', 'qm'): logger.info('Initial atomic charges are not required') else: raise AssertionError() else: raise AssertionError() return mol
def _fit_charges(mol, args, qm, atom_types): from htmd.charge import fitGasteigerCharges, fitChargesWithAntechamber, fitESPCharges, symmetrizeCharges from htmd.parameterization.util import guessBondType, getFixedChargeAtomIndices, getDipole, _qm_method_name from htmd.parameterization.detect import detectEquivalentAtoms logger.info('=== Atomic charge fitting ===') logger.info('Method: {}'.format(args.charge_type)) if args.charge_type == 'None': # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning('Flag --fix-charge does not have effect!') logger.info('Atomic charges are taken from {}'.format(args.filename)) elif args.charge_type == 'Gasteiger': # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning('Flag --fix-charge does not have effect!') # TODO move to _prepare_molecule if np.any(mol.bondtype == "un"): logger.info('Guessing bond types') mol = guessBondType(mol) mol = fitGasteigerCharges(mol, atom_types=atom_types) charge = int(round(np.sum(mol.charge))) if args.charge != charge: raise RuntimeError( 'Molecular charge is set to {}, but Gasteiger atomic charges add up to {}.' .format(args.charge, charge)) elif args.charge_type == 'AM1-BCC': # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning('Flag --fix-charge does not have effect!') mol = fitChargesWithAntechamber(mol, type='bcc', molCharge=args.charge) mol = symmetrizeCharges(mol) elif args.charge_type == 'ESP': # Detect equivalent atom groups logger.info('Equivalent atom groups:') atom_groups = [ group for group in detectEquivalentAtoms(mol)[0] if len(group) > 1 ] for atom_group in atom_groups: logger.info(' {}'.format(', '.join(mol.name[list(atom_group)]))) # Select the atoms with fixed charges fixed_atom_indices = getFixedChargeAtomIndices(mol, args.fix_charge) # Create an ESP directory espDir = os.path.join(args.outdir, "esp", _qm_method_name(qm)) os.makedirs(espDir, exist_ok=True) charge = int(round(np.sum(mol.charge))) if args.charge != charge: logger.warning( 'Molecular charge is set to {}, but atomic charges add up to {}' ''.format(args.charge, charge)) if len(args.fix_charge) > 0: raise RuntimeError( 'Flag --fix-charge cannot be used when atomic charges are inconsistent with passed ' 'molecular charge {}'.format(args.charge)) mol.charge[:] = args.charge / mol.numAtoms # Set random number generator seed if args.seed: np.random.seed(args.seed) # Fit ESP charges mol, extra = fitESPCharges(mol, qm, espDir, fixed=fixed_atom_indices) # Print QM dipole logger.info( 'QM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}'.format( *extra['qm_dipole'])) else: raise ValueError() # Print MM dipole mm_dipole = getDipole(mol) logger.info('MM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}'.format( *mm_dipole)) # Print the new charges logger.info('Atomic charges:') for name, charge in zip(mol.name, mol.charge): logger.info(' {:4s}: {:6.3f}'.format(name, charge)) logger.info('Molecular charge: {:6.3f}'.format(np.sum(mol.charge))) return mol