def test_two_stage_resp(self) -> None: respin2 = Respin( title="File generated for unit tests only (can been removed).", cntrl=Respin.Cntrl( iqopt=2, qwt=0.001, ), 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]) ) charges = run_two_stage_resp( self.esp_data, self.respin, respin2 ) self.assertListsAlmostEqual( charges, # Expected values from resp calculations done a while back [-0.317454, 0.079364, 0.079364, 0.079364, 0.079364] )
def test_getting_equivalence_from_two_stage_resp_ivary(self) -> None: # MeSO4 [S O O (bridging) O C H H H] ivary1 = Respin.Ivary([0, 0, 0, 2, 2, 0, 0, 0, 0]) ivary2 = Respin.Ivary([-1, -1, -1, -1, -1, 0, 0, 7, 7]) equivalence = get_equivalence_from_two_stage_resp_ivary(ivary1, ivary2) expected = Equivalence([None, None, None, 1, 1, None, None, 6, 6]) self.assertListEqual(equivalence.values, expected.values)
def test_ivary_init_validates_values(self) -> None: Respin.Ivary([0, 0, 1, -1, 2]) with self.assertRaises(ValueError): Respin.Ivary([0, 0, 2, -99, 2]) with self.assertRaises(ValueError): Respin.Ivary([6, 0, 2, 2, 2])
def setUp(self) -> None: self.respin = Respin( title="RESP input of type '2' generated by the repESP program", cntrl=Respin.Cntrl(ihfree=1, ioutopt=1, qwt=0.001, iqopt=2), 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]))
def test_getting_equivalence_from_ivary(self) -> None: equivalence = _get_equivalence_from_ivary(Respin.Ivary([0, 0, 2, 2, 2])) self.assertListEqual(equivalence.values, [None, None, 1, 1, 1]) with self.assertRaises(ValueError): _get_equivalence_from_ivary(Respin.Ivary([0, 0, 2, -1, 2])) with self.assertRaises(ValueError): _get_equivalence_from_ivary(Respin.Ivary([6, 0, 2, 2, 2]))
def setUp(self) -> None: # First stage RESP self.expected_respin = Respin( title="Respin file prepared by `repESP` to perform RESP stage 1.", cntrl=Respin.Cntrl(qwt=0.0005), 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, 0, 0, 0])) self.ivary = self.expected_respin.ivary self.molecule = self.expected_respin.molecule
def get_ivary(self) -> Respin.Ivary: return Respin.Ivary([ -1 if i in self.frozen_atoms else ivary for i, ivary in enumerate( Respin.Ivary.from_equivalence(self.equivalence).values ) ])
def get_ivary(self) -> Respin.Ivary: return Respin.Ivary([ -1 if atom.atomic_number != 1 else ivary for atom, ivary in zip( self.molecule.atoms, Respin.Ivary.from_equivalence(self.equivalence).values ) ])
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 setUp(self) -> None: with open("data/methane/methane_mk.esp", 'r') as f: self.esp_data = EspData.from_gaussian(parse_gaussian_esp(f)) # First stage RESP self.respin = Respin( title="File generated for unit tests only (can been removed).", cntrl=Respin.Cntrl( ihfree=1, ioutopt=1, qwt=0.0005, ), 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, 0, 0, 0]) ) self.result_charges = run_resp( self.esp_data, self.respin )
def from_methyl_and_methylene( cls: Type[RespStage2RespinGeneratorT], equivalence: Equivalence, methyl_methylene_mask: List[bool] ) -> RespStage2RespinGeneratorT: """See documentation in base class (`RespRespinGenerator`)""" return cls(Respin.Ivary([ ivary_from_equivalence_value if is_methyl_or_methylene else -1 for ivary_from_equivalence_value, is_methyl_or_methylene in zip_exact( Respin.Ivary.from_equivalence(equivalence).values, methyl_methylene_mask ) ]))
def get_cntrl(self) -> Respin.Cntrl: return Respin.Cntrl( qwt=0.0005 )
def get_cntrl(self) -> Respin.Cntrl: return Respin.Cntrl( iqopt=2, qwt=0.001 )
def test_ivary_from_equivalence(self) -> None: self.assertListEqual( Respin.Ivary([0, 0, 1, 2, 2]).values, Respin.Ivary.from_equivalence(Equivalence([None, None, 0, 1, 1])).values)
def get_cntrl(self) -> Respin.Cntrl: return Respin.Cntrl( iqopt=2, ihfree=0, # Not just hydrogens... qwt=0.0 # ...because there are no restraints. )
def prepare_respin( respin_generator: RespinGenerator, total_charge: int, molecule: Molecule[Atom], title: Optional[str]=None, subtitle: Optional[str]=None, read_charges: bool=False ) -> Respin: """Create ``resp`` program instructions based on input options This function allows to create ``resp`` program instructions from higher-level abstractions. Parameters ---------- respin_generator : RespinGenerator An object implementing the `RespinGenerator` interface. This object expresses a given type of charge fitting through instructions understood by ``resp``. Implementations of this interface for common fitting types are provided in this module. total_charge : int The total charge of the molecule. molecule : Molecule[Atom] The molecule which charges are being fitted. Only atom identities are required. title : Optional[str], optional The title for the optimization. If set to None (default), a default title will be used, referencing the `repESP` library and the type of the fitting as given by the `respin_generator` used. subtitle : Optional[str], optional The subttitle for the fitted structure. If set to None (default), a default generic subtitle will be used. read_charges : bool, optional If this option is set to True, ``resp`` will require initial charges for the fitting. Defaults to False. .. note:: It is the responsibility of the `respin_generator` to instruct ``resp`` to read initial charges when they affect the result of the optimization. This parameter should only be used when the user wishes to aid the optimization by supplying an initial guess. .. It could also be used in case the ``resp`` algorithm converges to different charges depending on the initial charges but I am not aware of such an issue with the ``resp`` algorithm). Returns ------- Respin An object representing the fitting instructions for the ``resp`` program. """ cntrl = respin_generator.get_cntrl() if read_charges: cntrl.iqopt = 2 default_title = f"Respin file prepared by `repESP` to perform {respin_generator.resp_type()}." default_subtitle = "Resp charges for organic molecule" return Respin( title=title if title is not None else default_title, cntrl=cntrl, subtitle=subtitle if subtitle is not None else default_subtitle, charge=total_charge, molecule=molecule, ivary=respin_generator.get_ivary() )