Exemple #1
0
def setup_conformation_restraints(template,
                                  targets,
                                  windows,
                                  attach_fractions,
                                  structure,
                                  resname,
                                  fc=6.0):
    conformational_restraints = []
    host_residues = len(structure[":{}".format(resname.upper())].residues)
    first_host_residue = structure[":{}".format(
        resname.upper())].residues[0].number + 1

    for n in range(first_host_residue, host_residues + first_host_residue):
        if n + 1 < host_residues + first_host_residue:
            next_residue = n + 1
        else:
            next_residue = first_host_residue

        for (index, atoms), target in zip(enumerate(template), targets):

            conformational_restraint_atoms = []
            if index == 0:
                conformational_restraint_atoms.append(f":{n}@{atoms[0]}")
                conformational_restraint_atoms.append(f":{n}@{atoms[1]}")
                conformational_restraint_atoms.append(f":{n}@{atoms[2]}")
                conformational_restraint_atoms.append(
                    f":{next_residue}@{atoms[3]}")
            else:
                conformational_restraint_atoms.append(f":{n}@{atoms[0]}")
                conformational_restraint_atoms.append(f":{n}@{atoms[1]}")
                conformational_restraint_atoms.append(
                    f":{next_residue}@{atoms[2]}")
                conformational_restraint_atoms.append(
                    f":{next_residue}@{atoms[3]}")

            this = DAT_restraint()
            this.auto_apr = True
            this.amber_index = True
            this.topology = structure
            this.mask1 = conformational_restraint_atoms[0]
            this.mask2 = conformational_restraint_atoms[1]
            this.mask3 = conformational_restraint_atoms[2]
            this.mask4 = conformational_restraint_atoms[3]

            this.attach["fraction_list"] = attach_fractions
            this.attach["target"] = target
            this.attach["fc_final"] = fc
            this.pull["target_final"] = target
            this.pull["num_windows"] = windows[1]

            this.release["fraction_list"] = attach_fractions[::-1]
            this.release["target"] = target
            this.release["fc_final"] = fc

            this.initialize()
            conformational_restraints.append(this)
    return conformational_restraints
Exemple #2
0
def setup_guest_restraints(
    anchor_atoms,
    windows,
    structure,
    attach_fractions,
    distance_fc=5.0,
    angle_fc=100.0,
    pull_initial=6.0,
    pull_final=24.0,
):
    guest_restraints = []

    guest_restraint_atoms = [
        [anchor_atoms["D1"], anchor_atoms["G1"]],
        [anchor_atoms["D2"], anchor_atoms["D1"], anchor_atoms["G1"]],
        [anchor_atoms["D1"], anchor_atoms["G1"], anchor_atoms["G2"]],
    ]
    guest_restraint_targets = {
        "initial": [pull_initial, 180.0, 180.0],
        "final": [pull_final, 180.0, 180.0],
    }

    for index, atoms in enumerate(guest_restraint_atoms):
        if len(atoms) > 2:
            angle = True
        else:
            angle = False
        this = DAT_restraint()
        this.auto_apr = True
        this.amber_index = True
        this.topology = structure
        this.mask1 = atoms[0]
        this.mask2 = atoms[1]
        if angle:
            this.mask3 = atoms[2]
            this.attach["fc_final"] = angle_fc
            this.release["fc_final"] = angle_fc
        else:
            this.attach["fc_final"] = distance_fc
            this.release["fc_final"] = angle_fc
        this.attach["target"] = guest_restraint_targets["initial"][index]
        this.attach["fraction_list"] = attach_fractions

        this.pull["target_final"] = guest_restraint_targets["final"][index]
        this.pull["num_windows"] = windows[1]

        this.release["target"] = guest_restraint_targets["final"][index]
        # Keep the guest restraints on during release.
        this.release["fraction_list"] = [1.0] * windows[2]

        this.initialize()

        guest_restraints.append(this)
    return guest_restraints
Exemple #3
0
def test_save_and_load_list_restraint(clean_files):
    """ Test we can save and load a list of restraints """
    rest1 = DAT_restraint()
    rest1.amber_index = True
    rest1.continuous_apr = False
    rest1.auto_apr = False
    rest1.topology = os.path.join(os.path.dirname(__file__),
                                  "../data/cb6-but/cb6-but-notcentered.pdb")
    rest1.mask1 = ":CB6@O,O2,O4,O6,O8,O10"
    rest1.mask2 = ":BUT@C3"
    rest1.attach["target"] = 3.0
    rest1.attach["num_windows"] = 4
    rest1.attach["fc_initial"] = 0.0
    rest1.attach["fc_final"] = 3.0
    rest1.pull["fc"] = rest1.attach["fc_final"]
    rest1.pull["num_windows"] = 4
    rest1.pull["target_initial"] = rest1.attach["target"]
    rest1.pull["target_final"] = 6.0
    rest1.release["target"] = rest1.pull["target_final"]
    rest1.release["num_windows"] = rest1.attach["num_windows"]
    rest1.release["fc_initial"] = rest1.attach["fc_initial"]
    rest1.release["fc_final"] = rest1.attach["fc_final"]
    rest1.initialize()

    rest2 = DAT_restraint()
    rest2.amber_index = True
    rest2.continuous_apr = False
    rest2.auto_apr = False
    rest2.topology = os.path.join(os.path.dirname(__file__),
                                  "../data/cb6-but/cb6-but-notcentered.pdb")
    rest2.mask1 = ":CB6@O,O2,O4,O6,O8,O10"
    rest2.mask2 = ":BUT@C3"
    rest2.mask3 = ":BUT@C"
    rest2.attach["target"] = 180.0
    rest2.attach["num_windows"] = 4
    rest2.attach["fc_final"] = 75.0
    rest2.pull["fc"] = rest2.attach["fc_final"]
    rest2.pull["num_windows"] = 4
    rest2.pull["target_final"] = 180.0
    rest2.release["target"] = rest2.pull["target_final"]
    rest2.release["num_windows"] = rest2.attach["num_windows"]
    rest2.release["fc_final"] = rest2.attach["fc_final"]
    rest2.initialize()

    save_restraints([rest1, rest2], os.path.join("tmp", "restraints.json"))
    restraints = load_restraints(os.path.join("tmp", "restraints.json"))
    assert rest1 == restraints[0]
    assert rest2 == restraints[1]
Exemple #4
0
def setup_guest_restraints(
    anchor_atoms,
    windows,
    structure,
    distance_fc=5.0,
    angle_fc=100.0,
):
    guest_restraints = []

    guest_restraint_atoms = [
        [anchor_atoms["D1"], anchor_atoms["G1"]],
        [anchor_atoms["D2"], anchor_atoms["D1"], anchor_atoms["G1"]],
        [anchor_atoms["D1"], anchor_atoms["G1"], anchor_atoms["G2"]],
    ]
    guest_restraint_targets = {
        "initial": [6.0, 180.0, 180.0],
        "final": [24.0, 180.0, 180.0],
    }

    for index, atoms in enumerate(guest_restraint_atoms):
        if len(atoms) > 2:
            angle = True
        else:
            angle = False
        this = DAT_restraint()
        this.auto_apr = False
        this.amber_index = True
        this.topology = structure
        this.mask1 = atoms[0]
        this.mask2 = atoms[1]
        if angle:
            this.mask3 = atoms[2]
            this.attach["fc_final"] = angle_fc
        else:
            this.attach["fc_final"] = distance_fc
        this.attach["target"] = guest_restraint_targets["initial"][index]
        this.attach["fraction_list"] = attach_fractions

        this.initialize()

        guest_restraints.append(this)
    print(f"There are {len(guest_restraints)} guest restraints")
    return guest_restraints
Exemple #5
0
    def build_guest_restraints(
        cls,
        coordinate_path: str,
        attach_lambdas: List[float],
        n_pull_windows: Optional[int],
        restraint_schemas: List[Dict[str, Any]],
        use_amber_indices: bool = False,
    ) -> List[DAT_restraint]:
        """A method to convert a set of guest restraints defined by their 'schemas'
        into corresponding ``DAT_restraint``objects.

        Each 'schema' should be a dictionary with:
            * an ``atoms`` entry with a value of the atom selection make which specifies
              which atoms the restraint will apply to

        and additionally a nested ``attach`` and ``pull`` dictionary with

            * a ``force_constant`` entry which specifies the force constant of the
              restraint.
            * a ``target`` entry which specifies the target value of the restraint.

        These 'schemas` map directly to the 'restraints -> guest -> restraint'
        dictionaries specified in the `taproom` guest YAML files.

        Parameters
        ----------
        coordinate_path
            The path to the coordinate file which the restraints will be applied to.
            This should contain either the host or the complex, the dummy atoms and
            and solvent.
        attach_lambdas
            The values 'lambda' being used during the attach phase of the APR
            calculation.
        n_pull_windows
            The total number of pull windows being used in the APR calculation.
        restraint_schemas
            The list of dictionaries which provide the settings to use for each
            wall restraint to add.
        use_amber_indices
            Whether to use amber based (i.e. starting from 1) restraint indices or
            OpenMM based (i.e. starting from 0) indices.

        Returns
        -------
            The constructed wall restraint objects.
        """

        restraints = []

        for restraint_schema in restraint_schemas:

            mask = restraint_schema["atoms"].split()

            guest_restraint = DAT_restraint()
            guest_restraint.auto_apr = True
            guest_restraint.continuous_apr = False
            guest_restraint.amber_index = use_amber_indices
            guest_restraint.topology = coordinate_path
            guest_restraint.mask1 = mask[0]
            guest_restraint.mask2 = mask[1]
            guest_restraint.mask3 = mask[2] if len(mask) > 2 else None
            guest_restraint.mask4 = mask[3] if len(mask) > 3 else None

            guest_restraint.attach["target"] = restraint_schema["attach"]["target"]
            guest_restraint.attach["fc_final"] = restraint_schema["attach"][
                "force_constant"
            ]
            guest_restraint.attach["fraction_list"] = attach_lambdas

            if n_pull_windows:

                guest_restraint.pull["target_final"] = restraint_schema["pull"][
                    "target"
                ]
                guest_restraint.pull["num_windows"] = n_pull_windows

            guest_restraint.initialize()
            restraints.append(guest_restraint)

        return restraints
Exemple #6
0
    def build_symmetry_restraints(
        cls,
        coordinate_path: str,
        n_attach_windows: int,
        restraint_schemas: List[Dict[str, Any]],
        use_amber_indices: bool = False,
    ) -> List[DAT_restraint]:
        """A method to convert a set of symmetry restraints defined by their 'schemas'
        into corresponding ``DAT_restraint``objects.

        Each 'schema' should be a dictionary with:

            * an ``atoms`` entry with a value of the atom selection make which specifies
              which atoms the restraint will apply to
            * a ``force_constant`` entry which specifies the force constant of the
              restraint.

        These 'schemas` map directly to the 'restraints -> symmetry_correction
        -> restraint' dictionaries specified in the `taproom` guest YAML files.

        Parameters
        ----------
        coordinate_path
            The path to the coordinate file which the restraints will be applied to.
            This should contain either the host or the complex, the dummy atoms and
            and solvent.
        n_attach_windows
            The total number of attach windows being used in the APR calculation.
        restraint_schemas
            The list of dictionaries which provide the settings to use for each
            symmetry restraint to add.
        use_amber_indices
            Whether to use amber based (i.e. starting from 1) restraint indices or
            OpenMM based (i.e. starting from 0) indices.

        Returns
        -------
            The constructed symmetry restraint objects.
        """

        restraints = []

        for restraint_schema in restraint_schemas:

            restraint = DAT_restraint()
            restraint.auto_apr = True
            restraint.continuous_apr = False
            restraint.amber_index = use_amber_indices
            restraint.topology = coordinate_path
            restraint.mask1 = restraint_schema["atoms"].split()[0]
            restraint.mask2 = restraint_schema["atoms"].split()[1]
            restraint.mask3 = restraint_schema["atoms"].split()[2]

            restraint.attach["fc_final"] = restraint_schema["force_constant"]
            restraint.attach["fraction_list"] = [1.0] * n_attach_windows

            # This target should be overridden by the custom values.
            restraint.attach["target"] = 999.99
            restraint.custom_restraint_values["r2"] = 91
            restraint.custom_restraint_values["r3"] = 91

            # 0 force constant between 91 degrees and 180 degrees.
            restraint.custom_restraint_values["rk3"] = 0.0
            restraint.initialize()

            restraints.append(restraint)

        return restraints
Exemple #7
0
                       structure=True)

    guest_restraints = []
    for index, atoms in enumerate(guest_restraint_atoms):
        if len(atoms) > 2:
            angle = True
        else:
            angle = False
        this = DAT_restraint()
        this.auto_apr = True
        this.amber_index = True
        this.topology = hg
        this.mask1 = atoms[0]
        this.mask2 = atoms[1]
        if angle:
            this.mask3 = atoms[2]
            this.attach['fc_final'] = guest_restraint_angle_fc
        else:
            this.attach['fc_final'] = guest_restraint_distance_fc
        this.attach['target'] = guest_restraint_targets[index]
        this.attach['fraction_list'] = attach_fractions

        this.pull['target_final'] = guest_restraint_target_final[index]
        this.pull['num_windows'] = windows[1]
        this.initialize()

        guest_restraints.append(this)

    structure = pt.load(
        os.path.join(complx, 'AMBER', 'APR', 'windows', 'a000',
                     'solvate.rst7'),
Exemple #8
0
def setup_guest_wall_restraints(template,
                                targets,
                                structure,
                                windows,
                                resname,
                                angle_fc=500.0,
                                distance_fc=50.0):

    guest_wall_restraints = []
    host_residues = len(structure[":{}".format(resname.upper())].residues)
    first_host_residue = structure[":{}".format(
        resname.upper())].residues[0].number + 1

    for n in range(first_host_residue, host_residues + first_host_residue):
        for (index, atoms), target in zip(enumerate(template[0:2]),
                                          targets[0:2]):
            guest_wall_restraint_atoms = []
            guest_wall_restraint_atoms.append(f":{n}@{atoms[0]}")
            guest_wall_restraint_atoms.append(f"{atoms[1]}")

            this = DAT_restraint()
            this.auto_apr = False
            this.amber_index = True
            this.topology = structure
            this.mask1 = guest_wall_restraint_atoms[0]
            this.mask2 = guest_wall_restraint_atoms[1]
            this.attach["fc_initial"] = distance_fc
            this.attach["fc_final"] = distance_fc
            this.custom_restraint_values["rk2"] = 50.0
            this.custom_restraint_values["rk3"] = 50.0
            this.custom_restraint_values["r1"] = 0.0
            this.custom_restraint_values["r2"] = 0.0

            this.attach["target"] = target
            this.attach["num_windows"] = windows[0]

            this.initialize()
            guest_wall_restraints.append(this)
            print("Added guest wall distance restraint.")

    # Add a single angle restraint!
    guest_wall_restraint_atoms = []
    guest_wall_restraint_atoms.append(f"{template[2][0]}")
    guest_wall_restraint_atoms.append(f"{template[2][1]}")
    guest_wall_restraint_atoms.append(f"{template[2][2]}")
    target = targets[2]

    this = DAT_restraint()
    this.auto_apr = False
    this.amber_index = True
    this.topology = structure
    this.mask1 = guest_wall_restraint_atoms[0]
    this.mask2 = guest_wall_restraint_atoms[1]

    this.mask3 = guest_wall_restraint_atoms[2]
    this.attach["fc_initial"] = angle_fc
    this.attach["fc_final"] = angle_fc
    this.custom_restraint_values["rk2"] = 500.0
    this.custom_restraint_values["rk3"] = 0.0

    this.attach["target"] = target
    this.attach["num_windows"] = windows[0]

    this.initialize()
    guest_wall_restraints.append(this)
    print("Added guest wall angle restraint.")

    print(f"There are {len(guest_wall_restraints)} guest wall restraints")
    return guest_wall_restraints
def test_evaluator_analyze(clean_files):
    input_pdb = os.path.join(os.path.dirname(__file__),
                             "../data/cb6-but/vac.pdb")
    structure = pmd.load_file(input_pdb, structure=True)

    guest_atom_indices = []
    for atom in structure.topology.atoms():
        if atom.residue.name == "BUT":
            guest_atom_indices.append(atom.index)

    host_guest_structure = Setup.prepare_complex_structure(
        input_pdb,
        guest_atom_indices,
        ":BUT@C :BUT@C3",
        24.0,
        0,
        46,
    )
    Setup.add_dummy_atoms_to_structure(
        host_guest_structure,
        [
            np.array([0, 0, 0]),
            np.array([0, 0, -3.0]),
            np.array([0, 2.2, -5.2]),
        ],
        np.zeros(3),
    )

    # Distance restraint
    rest1 = DAT_restraint()
    rest1.continuous_apr = True
    rest1.amber_index = True
    rest1.topology = host_guest_structure
    rest1.mask1 = ":DM1"
    rest1.mask2 = ":BUT@C"
    rest1.attach["target"] = 6.0
    rest1.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest1.attach["fc_final"] = 5.0
    rest1.pull["fc"] = rest1.attach["fc_final"]
    rest1.pull["target_initial"] = rest1.attach["target"]
    rest1.pull["target_final"] = 24.0
    rest1.pull["num_windows"] = 19
    rest1.initialize()

    # Angle 1 restraint
    rest2 = DAT_restraint()
    rest2.continuous_apr = True
    rest2.amber_index = True
    rest2.topology = input_pdb
    rest2.mask1 = ":DM2"
    rest2.mask2 = ":DM1"
    rest2.mask3 = ":BUT@C"
    rest2.attach["target"] = 180.0
    rest2.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest2.attach["fc_final"] = 100.0
    rest2.pull["fc"] = rest2.attach["fc_final"]
    rest2.pull["target_initial"] = rest2.attach["target"]
    rest2.pull["target_final"] = rest2.attach["target"]
    rest2.pull["num_windows"] = 19
    rest2.initialize()

    # Angle 2
    rest3 = DAT_restraint()
    rest3.continuous_apr = True
    rest3.amber_index = True
    rest3.topology = input_pdb
    rest3.mask1 = ":DM1"
    rest3.mask2 = ":BUT@C"
    rest3.mask3 = ":BUT@C3"
    rest3.attach["target"] = 180.0
    rest3.attach["fraction_list"] = [0.00, 0.04, 0.181, 0.496, 1.000]
    rest3.attach["fc_final"] = 100.0
    rest3.pull["fc"] = rest2.attach["fc_final"]
    rest3.pull["target_initial"] = rest2.attach["target"]
    rest3.pull["target_final"] = rest2.attach["target"]
    rest3.pull["num_windows"] = 19
    rest3.initialize()

    temperature = 298.15
    guest_restraints = [rest1, rest2, rest3]
    ref_state_work = Analyze.compute_ref_state_work(temperature,
                                                    guest_restraints)
    assert pytest.approx(ref_state_work, abs=1e-3) == -7.14151

    fe_sym = Analyze.symmetry_correction(n_microstates=1, temperature=298.15)
    assert fe_sym == 0.0
    fe_sym = Analyze.symmetry_correction(n_microstates=2, temperature=298.15)
    assert pytest.approx(fe_sym, abs=1e-3) == -0.410679
Exemple #10
0
    def initialize_restraints(self, structure="output.pdb"):

        if self.guest != "release":

            windows = [
                self.host_yaml["calculation"]["windows"]["attach"],
                self.host_yaml["calculation"]["windows"]["pull"],
                None,
            ]
        else:
            windows = [
                None, None, self.host_yaml["calculation"]["windows"]["release"]
            ]

        static_restraints = []
        for restraint in self.host_yaml["restraints"]["static"]:

            static = static_DAT_restraint(
                restraint_mask_list=restraint["restraint"]["atoms"].split(),
                num_window_list=windows,
                ref_structure=str(structure),
                force_constant=restraint["restraint"]["force_constant"],
                amber_index=False if self.backend == "openmm" else True,
            )
            static_restraints.append(static)

        conformational_restraints = []
        if self.host_yaml["restraints"]["conformational"]:

            for conformational in self.host_yaml["restraints"][
                    "conformational"]:

                mask = conformational["restraint"]["atoms"].split()

                conformational_restraint = DAT_restraint()
                conformational_restraint.auto_apr = True
                conformational_restraint.continuous_apr = True
                conformational_restraint.amber_index = False if self.backend == "openmm" else True
                conformational_restraint.topology = str(structure)
                conformational_restraint.mask1 = mask[0]
                conformational_restraint.mask2 = mask[1]
                conformational_restraint.mask3 = mask[2] if len(
                    mask) > 2 else None
                conformational_restraint.mask4 = mask[3] if len(
                    mask) > 3 else None

                if self.guest != "release":

                    conformational_restraint.attach["target"] = conformational[
                        "restraint"]["target"]
                    conformational_restraint.attach[
                        "fc_final"] = conformational["restraint"][
                            "force_constant"]
                    conformational_restraint.attach[
                        "fraction_list"] = self.host_yaml["calculation"][
                            "lambda"]["attach"]

                    conformational_restraint.pull[
                        "target_final"] = conformational["restraint"]["target"]
                    conformational_restraint.pull["num_windows"] = windows[1]

                else:

                    conformational_restraint.auto_apr = False
                    conformational_restraint.continuous_apr = False

                    conformational_restraint.release[
                        "target"] = conformational["restraint"]["target"]
                    conformational_restraint.release[
                        "fc_final"] = conformational["restraint"][
                            "force_constant"]
                    conformational_restraint.release[
                        "fraction_list"] = self.host_yaml["calculation"][
                            "lambda"]["release"]

                conformational_restraint.initialize()
                conformational_restraints.append(conformational_restraint)
        else:
            logger.debug("Skipping conformational restraints...")

        symmetry_restraints = []
        if self.guest != "release" and "symmetry_correction" in self.guest_yaml:
            for symmetry in self.guest_yaml["symmetry_correction"][
                    "restraints"]:
                symmetry_restraint = DAT_restraint()
                symmetry_restraint.auto_apr = True
                symmetry_restraint.continuous_apr = True
                symmetry_restraint.amber_index = False if self.backend == "openmm" else True
                symmetry_restraint.topology = str(structure)
                symmetry_restraint.mask1 = symmetry["atoms"].split()[0]
                symmetry_restraint.mask2 = symmetry["atoms"].split()[1]
                symmetry_restraint.mask3 = symmetry["atoms"].split()[2]

                symmetry_restraint.attach["fc_final"] = symmetry[
                    "force_constant"]
                symmetry_restraint.attach["fraction_list"] = [1.0] * len(
                    self.host_yaml["calculation"]["lambda"]["attach"])
                # This target should be overridden by the custom values.
                symmetry_restraint.attach["target"] = 999.99
                symmetry_restraint.custom_restraint_values["r2"] = 91
                symmetry_restraint.custom_restraint_values["r3"] = 91
                # 0 force constant between 91 degrees and 180 degrees.
                symmetry_restraint.custom_restraint_values["rk3"] = 0.0
                symmetry_restraint.initialize()

                symmetry_restraints.append(symmetry_restraint)

        else:
            logger.debug("Skipping symmetry restraints...")

        wall_restraints = []
        if self.guest != "release" and "wall_restraints" in self.guest_yaml[
                'restraints']:
            for wall in self.guest_yaml["restraints"]["wall_restraints"]:
                wall_restraint = DAT_restraint()
                wall_restraint.auto_apr = True
                wall_restraint.continuous_apr = True
                wall_restraint.amber_index = False if self.backend == "openmm" else True
                wall_restraint.topology = str(structure)
                wall_restraint.mask1 = wall["restraint"]["atoms"].split()[0]
                wall_restraint.mask2 = wall["restraint"]["atoms"].split()[1]

                wall_restraint.attach["fc_final"] = wall["restraint"][
                    "force_constant"]
                wall_restraint.attach["fraction_list"] = [1.0] * len(
                    self.host_yaml["calculation"]["lambda"]["attach"])
                wall_restraint.attach["target"] = wall["restraint"]["target"]
                # Minimum distance is 0 Angstrom
                wall_restraint.custom_restraint_values["r1"] = 0
                wall_restraint.custom_restraint_values["r2"] = 0
                # Harmonic force constant beyond target distance.
                wall_restraint.custom_restraint_values["rk2"] = wall[
                    "restraint"]["force_constant"]
                wall_restraint.custom_restraint_values["rk3"] = wall[
                    "restraint"]["force_constant"]
                wall_restraint.initialize()

                wall_restraints.append(wall_restraint)

        else:
            logger.debug("Skipping wall restraints...")

        guest_restraints = []
        for restraint in [] if not hasattr(
                self,
                'guest_yaml') else self.guest_yaml["restraints"]["guest"]:
            mask = restraint["restraint"]["atoms"].split()

            guest_restraint = DAT_restraint()
            guest_restraint.auto_apr = True
            guest_restraint.continuous_apr = True
            guest_restraint.amber_index = False if self.backend == "openmm" else True
            guest_restraint.topology = str(structure)
            guest_restraint.mask1 = mask[0]
            guest_restraint.mask2 = mask[1]
            guest_restraint.mask3 = mask[2] if len(mask) > 2 else None
            guest_restraint.mask4 = mask[3] if len(mask) > 3 else None

            guest_restraint.attach["target"] = restraint["restraint"][
                "attach"]["target"]
            guest_restraint.attach["fc_final"] = restraint["restraint"][
                "attach"]["force_constant"]
            guest_restraint.attach["fraction_list"] = self.host_yaml[
                "calculation"]["lambda"]["attach"]

            guest_restraint.pull["target_final"] = restraint["restraint"][
                "pull"]["target"]
            guest_restraint.pull["num_windows"] = windows[1]

            guest_restraint.initialize()
            guest_restraints.append(guest_restraint)

        return (
            static_restraints,
            conformational_restraints,
            symmetry_restraints,
            wall_restraints,
            guest_restraints,
        )