def run_two_stage_resp( esp_data: EspData, respin1: Respin, respin2: Respin, initial_charges: Optional[List[Charge]] = None, generate_esout: bool = False, save_intermediates_to: Optional[str] = None) -> List[Charge]: """Apply the two-stage procedure to fit RESP charges This function takes the two "respin" files, as this is the simplest way to provide information about equivalence as well as methyl and methylene groups. Another interface is possible where this information is provided directly and may be provided in the future. Parameters ---------- esp_data : EspData See `run_resp` function parameter respin1 : Respin Instructions for 1st stage RESP fitting. respin2 : Respin Instructions for 2nd stage RESP fitting. initial_charges : Optional[typing.List[Charge]], optional See `run_resp` function parameter generate_esout : bool, optional See `run_resp` function parameter save_intermediates_to : Optional[str], optional See `run_resp` function parameter Returns ------- typing.List[Charge] The fitted two-stage RESP charges. """ # Some verification of respin file compatibility should be performed. total_charge = respin1.charge molecule = respin1.molecule get_calc_dir: Callable[[int], Optional[str]] = lambda stage: ( f"{save_intermediates_to}/stage_{stage}" if save_intermediates_to is not None else None) respin1_generated = prepare_respin( RespStage1RespinGenerator(respin1.ivary), total_charge, molecule, read_charges=initial_charges is not None) resp1_charges = run_resp(esp_data, respin1, initial_charges, generate_esout, get_calc_dir(1)) respin2_generated = prepare_respin(RespStage2RespinGenerator( respin2.ivary), total_charge, molecule, read_charges=True) return run_resp(esp_data, respin2, resp1_charges, generate_esout, get_calc_dir(2))
def test_defaults(self) -> None: generated = prepare_respin(respin_generator=RespStage1RespinGenerator( self.ivary), total_charge=0, molecule=self.molecule) self.assertAlmostEqualRecursive(self.expected_respin, generated)
def test_with_total_charge(self) -> None: generated = prepare_respin(respin_generator=RespStage1RespinGenerator( self.ivary), total_charge=1, molecule=self.molecule) expected = deepcopy(self.expected_respin) expected.charge = 1 self.assertAlmostEqualRecursive(expected, generated)
def test_with_read_charges(self) -> None: generated = prepare_respin(respin_generator=RespStage1RespinGenerator( self.ivary), total_charge=0, molecule=self.molecule, read_charges=True) expected = deepcopy(self.expected_respin) expected.cntrl.iqopt = 2 self.assertAlmostEqualRecursive(expected, generated)
def test_with_title_and_subtitles(self) -> None: generated = prepare_respin(respin_generator=RespStage1RespinGenerator( self.ivary), total_charge=0, molecule=self.molecule, title="Custom title", subtitle="Custom subtitle") expected = deepcopy(self.expected_respin) expected.title = "Custom title" expected.subtitle = "Custom subtitle" self.assertAlmostEqualRecursive(expected, generated)
def fit_with_frozen_atoms( esp_data: EspData, equivalence: Equivalence, molecule: Molecule[Atom], frozen_atoms: List[int], total_charge: int, initial_charges: List[Charge], generate_esout: bool = False, save_intermediates_to: Optional[str] = None) -> List[Charge]: """Fit hydrogen atom charges to the provided ESP subject to equivalence relations Parameters ---------- esp_data : EspData See `run_resp` function parameter equivalence : Equivalence The chemical equivalence relations between atoms of the molecule. molecule : Molecule[Atom] The molecule which charges are being fitted. Only atom identities are required. frozen_atoms : List[int] List of zero-based indices of atoms in the molecule which charges should not be fitted but fixed at the values provided in `initial_charges` argument. total_charge : int The total charge of the molecule. initial_charges : typing.List[Charge] Initial charges to be used for the fitting. Charges on atoms specified in the `frozen_atoms` arguments will be fixed at the provided values. generate_esout : bool, optional See `run_resp` function parameter save_intermediates_to : Optional[str], optional See `run_resp` function parameter Returns ------- typing.List[Charge] The charges fitted to the provided ESP subject to equivalence relations, except where the charges were frozen at initial values. """ respin_generator = FrozenAtomsRespinGenerator(equivalence, frozen_atoms) respin = prepare_respin(respin_generator, total_charge, molecule, read_charges=True) return run_resp(esp_data, respin, initial_charges, generate_esout, save_intermediates_to)
def test_fitting_with_frozen_atoms(self) -> None: respin = Respin( title= "Respin file prepared by `repESP` to perform fitting with selected atom charges frozen.", cntrl=Respin.Cntrl(iqopt=2, ihfree=0, qwt=0.0), subtitle="Resp charges for organic molecule", charge=0, molecule=Molecule( [Atom(atomic_number) for atomic_number in [6, 1, 1, 1, 1]]), ivary=Respin.Ivary([-1, 0, 2, -1, 2])) generated = prepare_respin(respin_generator=FrozenAtomsRespinGenerator( Equivalence([None, None, 1, 1, 1]), frozen_atoms=[0, 3]), total_charge=0, molecule=respin.molecule) self.assertAlmostEqualRecursive(respin, generated)
def test_equivalencing(self) -> None: respin = Respin( title= "Respin file prepared by `repESP` to perform atom equivalencing.", cntrl=Respin.Cntrl(ihfree=0, qwt=0.0), subtitle="Resp charges for organic molecule", charge=0, molecule=Molecule( [Atom(atomic_number) for atomic_number in [6, 1, 1, 1, 1]]), ivary=Respin.Ivary([0, 0, 2, 2, 2])) generated = prepare_respin( respin_generator=EquivalenceOnlyRespinGenerator( Equivalence([None, None, 1, 1, 1])), total_charge=0, molecule=respin.molecule) self.assertAlmostEqualRecursive(respin, generated)
def test_fitting_hydrogens_only(self) -> None: respin = Respin( title= "Respin file prepared by `repESP` to perform fitting of hydrogen atoms.", cntrl=Respin.Cntrl(iqopt=2, ihfree=0, qwt=0.0), subtitle="Resp charges for organic molecule", charge=0, molecule=Molecule( [Atom(atomic_number) for atomic_number in [6, 1, 1, 1, 1]]), ivary=Respin.Ivary([-1, 0, 2, 2, 2])) generated = prepare_respin( respin_generator=FitHydrogensOnlyRespinGenerator( Equivalence([None, None, 1, 1, 1]), respin.molecule), total_charge=0, molecule=respin.molecule) self.assertAlmostEqualRecursive(respin, generated)
def fit_hydrogens_only( esp_data: EspData, equivalence: Equivalence, molecule: Molecule[Atom], total_charge: int, initial_charges: List[Charge], generate_esout: bool = False, save_intermediates_to: Optional[str] = None) -> List[Charge]: """Fit hydrogen atom charges to the provided ESP subject to equivalence relations Parameters ---------- esp_data : EspData See `run_resp` function parameter equivalence : Equivalence The chemical equivalence relations between atoms of the molecule. molecule : Molecule[Atom] The molecule which charges are being fitted. Only atom identities are required. total_charge : int The total charge of the molecule. initial_charges : typing.List[Charge] Initial charges to be used for the fitting. Charges on atoms other than hydrogen atoms will be fixed at the provided values. generate_esout : bool, optional See `run_resp` function parameter save_intermediates_to : Optional[str], optional See `run_resp` function parameter Returns ------- typing.List[Charge] The hydrogen charges fitted to the provided ESP subject to equivalence relations. Other charges have values fixed at values from `initial_charges`. """ respin_generator = FitHydrogensOnlyRespinGenerator(equivalence, molecule) respin = prepare_respin(respin_generator, total_charge, molecule, read_charges=True) return run_resp(esp_data, respin, initial_charges, generate_esout, save_intermediates_to)
def fit_with_equivalencing( esp_data: EspData, equivalence: Equivalence, molecule: Molecule[Atom], total_charge: int, initial_charges: Optional[List[Charge]] = None, generate_esout: bool = False, save_intermediates_to: Optional[str] = None) -> List[Charge]: """Fit charges to the provided ESP subject to equivalence relations Parameters ---------- esp_data : EspData See `run_resp` function parameter equivalence : Equivalence The chemical equivalence relations between atoms of the molecule. molecule : Molecule[Atom] The molecule which charges are being fitted. Only atom identities are required. total_charge : int The total charge of the molecule. initial_charges : Optional[typing.List[Charge]], optional See `run_resp` function parameter generate_esout : bool, optional See `run_resp` function parameter save_intermediates_to : Optional[str], optional See `run_resp` function parameter Returns ------- typing.List[Charge] The charges fitted to the provided ESP subject to equivalence relations. """ respin_generator = EquivalenceOnlyRespinGenerator(equivalence) respin = prepare_respin(respin_generator, total_charge, molecule, read_charges=initial_charges is not None) return run_resp(esp_data, respin, initial_charges, generate_esout, save_intermediates_to)