Exemplo n.º 1
0
 def align_rigid_bodies_states(self):
     """
         Aligns the set of structures considered for DOMINO sampling.
         The function:
             1) reads the possible reference frames that the
                 rb_states_table stores for each rigid body. This table
                 must be filled before using this function. Usually it is
                 filled with the results from a previous Monte Carlo sampling.
                 If the solutions from Monte Carlo seem to have the same structure
                 but they are not aligned to each other, this function can
                 help setting better starting positions to use with DOMINO.
             2) Gets the first state for each of the rigid bodies and sets
                a reference structure using such states.
             3) Aligns all the rest of the structures respect to the reference
             4) Replaces the values of the reference frames stored in the
                rb_states_table with the new values obtained from the alignments.
                It does it for all states of a rigid body.
         @note: If this function is applied, the parameters "anchor" and "fixed"
            are ignored, as they are superseded by the use of the alignments
            calculated here.
     """
     log.debug("Align the configurations read from the database before "
               "running DOMINO")
     rb_states = []
     n_states = []
     for rb in self.components_rbs:
         ps = self.rb_states_table.get_particle_states(rb)
         n = ps.get_number_of_particle_states()
         if n == 0:
             raise ValueError(
                 "There are no particle states for %s" %
                 rb.get_name())
         n_states.append(n)
         rb_states.append(ps)
     # coordinates of the first configuration (there is at least one for all
     # the rbs)
     for rb, states in zip(self.components_rbs, rb_states):
         states.load_particle_state(0, rb)
     reference_coords = get_coordinates(self.components_rbs)
     aligned_transformations = [[] for rb in self.components_rbs]
     for i in range(1, max(n_states)):
         log.debug("Aligning rigid bodies configuration %s" % i)
         # load the configuration
         for j in range(len(self.components_rbs)):
             # if there are no more particle states for this rigid body, use
             # the last
             state_index = min(i, n_states[j] - 1)
             rb_states[j].load_particle_state(
                 state_index,
                 self.components_rbs[j])
         coords = get_coordinates(self.components_rbs)
         T = alg.get_transformation_aligning_first_to_second(
             coords, reference_coords)
         for j, rb in enumerate(self.components_rbs):
             t = rb.get_reference_frame().get_transformation_to()
             new_t = alg.compose(T, t)
             aligned_transformations[j].append(new_t)
     # set the new possible transformations
     for i, rb in enumerate(self.components_rbs):
         self.set_rb_states(rb, aligned_transformations[i])
Exemplo n.º 2
0
    def get_restraints_for_native(self, restraints_names):
        """
            Get values of the restraints for the native structure
            @param restraints_names Names of the restraints requested
            @return a list with the values of all scores, and the total score
        """
        saved = [rb.get_reference_frame() for rb in self.components_rbs]
        # Set the state of the model to native
        for rb, rn in zip(self.components_rbs, self.native_rbs):
            # remove sub-rigid bodies
            rb_members = [m for m in rb.get_members()
                          if not core.RigidBody.get_is_setup(m.get_particle())]
            rn_members = [m for m in rn.get_members()
                          if not core.RigidBody.get_is_setup(m.get_particle())]
            rb_coords = [m.get_coordinates() for m in rb_members]
            rn_coords = [m.get_coordinates() for m in rn_members]

            # align and put rb in the position of rn
            if len(rn_coords) != len(rb_coords):
                raise ValueError("Mismatch in the number of members. "
                                 "Reference %d Aligned %d " % (len(rn_coords), len(rb_coords)))
            T = alg.get_transformation_aligning_first_to_second(rb_coords,
                                                                rn_coords)
            t = rb.get_reference_frame().get_transformation_to()
            new_t = alg.compose(T, t)
            rb.set_reference_frame(alg.ReferenceFrame3D(new_t))
        scores = []
        for name in restraints_names:
            scores.append(self.restraints[name].evaluate(False))
        total_score = sum(scores)
        representation.set_reference_frames(self.components_rbs, saved)
        return scores, total_score
Exemplo n.º 3
0
    def get_restraints_for_native(self, restraints_names):
        """
            Get values of the restraints for the native structure
            @param restraints_names Names of the restraints requested
            @return a list with the values of all scores, and the total score
        """
        saved = [rb.get_reference_frame() for rb in self.components_rbs]
        # Set the state of the model to native
        for rb, rn in zip(self.components_rbs, self.native_rbs):
            # remove sub-rigid bodies
            rb_members = [m for m in rb.get_members()
                          if not core.RigidBody.get_is_setup(m.get_particle())]
            rn_members = [m for m in rn.get_members()
                          if not core.RigidBody.get_is_setup(m.get_particle())]
            rb_coords = [m.get_coordinates() for m in rb_members]
            rn_coords = [m.get_coordinates() for m in rn_members]

            # align and put rb in the position of rn
            if len(rn_coords) != len(rb_coords):
                raise ValueError("Mismatch in the number of members. "
                                 "Reference %d Aligned %d " % (len(rn_coords), len(rb_coords)))
            T = alg.get_transformation_aligning_first_to_second(rb_coords,
                                                                rn_coords)
            t = rb.get_reference_frame().get_transformation_to()
            new_t = alg.compose(T, t)
            rb.set_reference_frame(alg.ReferenceFrame3D(new_t))
        scores = []
        for name in restraints_names:
            scores.append(self.restraints[name].evaluate(False))
        total_score = sum(scores)
        representation.set_reference_frames(self.components_rbs, saved)
        return scores, total_score
Exemplo n.º 4
0
def align_centroids_using_pca(ref_frames, ref_frames_reference):
    """
        Align the centroids of 2 sets of rigid bodyes using PCA using their
        reference frames. returns the best rmsd and the ref_frames to get it.
    """
    if(len(ref_frames) != len(ref_frames_reference)):
        raise ValueError("The number of reference frames must be the same")
    Ts1 = [r.get_transformation_to() for r in ref_frames]
    vs1 = [T.get_translation() for T in Ts1]
    Ts2 = [r.get_transformation_to() for r in ref_frames_reference]
    vs2 = [T.get_translation() for T in Ts2]

    # align with PCA
    pc1 = alg.get_principal_components(vs1)
    pc2 = alg.get_principal_components(vs2)
    pcTs = alg.get_alignments_from_first_to_second(pc1, pc2)
    best_refs = []
    best_rmsd = 1e5
    for j, pcT in enumerate(pcTs):
        new_Ts1 = [alg.compose(pcT, T) for T in Ts1]
        new_vs1 = [T.get_translation() for T in new_Ts1]
        r = atom.get_rmsd(new_vs1, vs2)
        if(r < best_rmsd):
            best_rmsd = r
            best_refs = [alg.ReferenceFrame3D(T) for T in new_Ts1]
    return best_rmsd, best_refs
Exemplo n.º 5
0
def get_reference_frames_from_chain_alignment(reference_rbs, reference_index,
                                              rbs_to_align, index_to_align):
    """
        Align the rigid bodies rbs_to_align to the the reference frames of
        reference_rbs. The rb with index_to_align is aligned to the reference rb
        with reference_index. The function returns the reference frames to
        apply to the rbs_to_align.
    """
    ref_coords = \
        [m.get_coordinates()
         for m in reference_rbs[reference_index].get_members()]
    coords = [m.get_coordinates()
              for m in rbs_to_align[index_to_align].get_members()]
    if(len(coords) != len(ref_coords)):
        raise ValueError(
            "Mismatch in the number of members. Reference %d Aligned %d " % (
                len(ref_coords), len(coords)))
    T = alg.get_transformation_aligning_first_to_second(coords, ref_coords)
    new_refs = []
    for rb in rbs_to_align:
#        log.debug("aligning ... %s",rb)
        t = rb.get_reference_frame().get_transformation_to()
        new_t = alg.compose(T, t)
        new_refs.append(alg.ReferenceFrame3D(new_t))
    return new_refs
Exemplo n.º 6
0
 def move_xlinks(self, ):
     """
         Function equivalent to move_one_xlink() for the case where there
         are more than one cross-link restraints available.
         Puts the ligand residues as close as possible to the receptor
         residues
     """
     rec_residues = [x[0] for x in self.xlinks]
     lig_residues = [x[1] for x in self.xlinks]
     rec_coords = [self.get_residue_coordinates(self.h_receptor, x)
                                                     for x in rec_residues]
     lig_coords = [self.get_residue_coordinates(self.h_ligand, x)
                                                     for x in lig_residues]
     log.debug( "Receptor residues before moving %s", rec_coords)
     log.debug( "Ligand residues before moving %s", lig_coords)
     ref = self.rb_ligand.get_reference_frame()
     # new coords for the ligand aminoacids
     Tr = alg.get_transformation_aligning_first_to_second(lig_coords,
                                                          rec_coords)
     T = ref.get_transformation_to()
     newT = alg.compose(Tr, T)
     self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT))
     moved_lig_coords = [self.get_residue_coordinates(self.h_ligand, x)
                                                     for x in lig_residues]
     log.debug( "Ligand residues after moving %s", moved_lig_coords)
Exemplo n.º 7
0
    def move_xlinks(self, ):
        """
            Function equivalent to move_one_xlink() for the case where there
            are more than one cross-link restraints available.
            Puts the ligand residues as close as possible to the receptor
            residues
        """
        rec_coords = []
        lig_coords = []
        for xl in self.xlinks_list:
            c = self.get_residue_coordinates(self.h_receptor, xl.first_chain,
                                             xl.first_residue)
            rec_coords.append(c)
            c = self.get_residue_coordinates(self.h_ligand, xl.second_chain,
                                             xl.second_residue)
            lig_coords.append(c)
        log.debug("Receptor residues before moving %s", rec_coords)
        log.debug("Ligand residues before moving %s", lig_coords)
        ref = self.rb_ligand.get_reference_frame()
        Tr = alg.get_transformation_aligning_first_to_second(lig_coords,
                                                             rec_coords)
        T = ref.get_transformation_to()
        newT = alg.compose(Tr, T)
        self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT))

        moved_lig_coords = []
        for xl in self.xlinks_list:
            c = self.get_residue_coordinates(self.h_ligand, xl.second_chain,
                                             xl.second_residue)
            moved_lig_coords.append(c)
        log.debug("Ligand residues after moving %s", moved_lig_coords)
Exemplo n.º 8
0
    def move_xlinks(self, ):
        """
            Function equivalent to move_one_xlink() for the case where there
            are more than one cross-link restraints available.
            Puts the ligand residues as close as possible to the receptor
            residues
        """
        rec_coords = []
        lig_coords = []
        for xl in self.xlinks_list:
            c = self.get_residue_coordinates(self.h_receptor, xl.first_chain,
                                             xl.first_residue)
            rec_coords.append(c)
            c = self.get_residue_coordinates(self.h_ligand, xl.second_chain,
                                             xl.second_residue)
            lig_coords.append(c)
        log.debug("Receptor residues before moving %s", rec_coords)
        log.debug("Ligand residues before moving %s", lig_coords)
        ref = self.rb_ligand.get_reference_frame()
        Tr = alg.get_transformation_aligning_first_to_second(
            lig_coords, rec_coords)
        T = ref.get_transformation_to()
        newT = alg.compose(Tr, T)
        self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT))

        moved_lig_coords = []
        for xl in self.xlinks_list:
            c = self.get_residue_coordinates(self.h_ligand, xl.second_chain,
                                             xl.second_residue)
            moved_lig_coords.append(c)
        log.debug("Ligand residues after moving %s", moved_lig_coords)
Exemplo n.º 9
0
 def align_rigid_bodies_states(self):
     """
         Aligns the set of structures considered for DOMINO sampling.
         The function:
             1) reads the possible reference frames that the
                 rb_states_table stores for each rigid body. This table
                 must be filled before using this function. Usually it is
                 filled with the results from a previous Monte Carlo sampling.
                 If the solutions from Monte Carlo seem to have the same structure
                 but they are not aligned to each other, this function can
                 help setting better starting positions to use with DOMINO.
             2) Gets the first state for each of the rigid bodies and sets
                a reference structure using such states.
             3) Aligns all the rest of the structures respect to the reference
             4) Replaces the values of the reference frames stored in the
                rb_states_table with the new values obtained from the alignments.
                It does it for all states of a rigid body.
         @note: If this function is applied, the parameters "anchor" and "fixed"
            are ignored, as they are superseded by the use of the alignments
            calculated here.
     """
     log.debug("Align the configurations read from the database before "
               "running DOMINO")
     rb_states = []
     n_states = []
     for rb in self.components_rbs:
         ps = self.rb_states_table.get_particle_states(rb)
         n = ps.get_number_of_particle_states()
         if n == 0:
             raise ValueError(
                 "There are no particle states for %s" %
                 rb.get_name())
         n_states.append(n)
         rb_states.append(ps)
     # coordinates of the first configuration (there is at least one for all
     # the rbs)
     for rb, states in zip(self.components_rbs, rb_states):
         states.load_particle_state(0, rb)
     reference_coords = get_coordinates(self.components_rbs)
     aligned_transformations = [[] for rb in self.components_rbs]
     for i in range(1, max(n_states)):
         log.debug("Aligning rigid bodies configuration %s" % i)
         # load the configuration
         for j in range(len(self.components_rbs)):
             # if there are no more particle states for this rigid body, use
             # the last
             state_index = min(i, n_states[j] - 1)
             rb_states[j].load_particle_state(
                 state_index,
                 self.components_rbs[j])
         coords = get_coordinates(self.components_rbs)
         T = alg.get_transformation_aligning_first_to_second(
             coords, reference_coords)
         for j, rb in enumerate(self.components_rbs):
             t = rb.get_reference_frame().get_transformation_to()
             new_t = alg.compose(T, t)
             aligned_transformations[j].append(new_t)
     # set the new possible transformations
     for i, rb in enumerate(self.components_rbs):
         self.set_rb_states(rb, aligned_transformations[i])
Exemplo n.º 10
0
def get_docked_reference_frames(relative_transforms, rb_lig):
    Tinitial = rb_lig.get_reference_frame().get_transformation_to()
    docked_ref_frames = []
    for Trelative in relative_transforms:
        Tdock = alg.compose(Trelative, Tinitial)
        docked_rf = alg.ReferenceFrame3D(Tdock)
        docked_ref_frames.append(docked_rf)
    return docked_ref_frames
Exemplo n.º 11
0
def get_internal_transform(Thex, rb_receptor, rb_ligand):
    """
        Get the internal transform (Ti) resulting from applying
        the transformation Thex (from HEX) that docks the ligand.
        The relationship betwen the reference frame of the ligand docked
        (Tdock)  and the internal transformation (Ti) respect to the receptor
        (Trec) is Tdock = Trec * Tinternal

        @param Thex HEX transformation
        @param rb_receptor Rigid body of the receptor
        @param rb_ligand Rigid body of the ligand
        @return The internal transformation
    """
    Trb = rb_ligand.get_reference_frame().get_transformation_to()
    Trec = rb_receptor.get_reference_frame().get_transformation_to()
    Tdock = alg.compose(Thex, Trb)
    Ti = alg.compose(Trec.get_inverse(), Tdock)
    return Ti
Exemplo n.º 12
0
def apply_rotation_around_centroid(rb,rot):
    """
        Rotates the reference frame of a rigid body around the centroid
    """
    c = rb.get_coordinates()
    ref = rb.get_reference_frame()
    R = ref.get_transformation_to().get_rotation()
    R2 = alg.compose(rot, R)
    T = alg.Transformation3D(R2, c)
    ref = alg.ReferenceFrame3D(T)
    rb.set_reference_frame(ref)
Exemplo n.º 13
0
def apply_rotation_around_centroid(rb, rot):
    """
        Rotates the reference frame of a rigid body around the centroid
    """
    c = rb.get_coordinates()
    ref = rb.get_reference_frame()
    R = ref.get_transformation_to().get_rotation()
    R2 = alg.compose(rot, R)
    T = alg.Transformation3D(R2, c)
    ref = alg.ReferenceFrame3D(T)
    rb.set_reference_frame(ref)
Exemplo n.º 14
0
def apply_random_transform(rb, max_trans=100):
    """
        Apply a random transformation to the rigid body and change the reference
        frame
    """
    bb = alg.BoundingBox3D(alg.Vector3D(-max_trans, -max_trans, -max_trans),
                           alg.Vector3D(max_trans, max_trans, max_trans))
    Trand = alg.Transformation3D(alg.get_random_rotation_3d(),
                                 alg.get_random_vector_in(bb))
    ref = rb.get_reference_frame()
    Tr = ref.get_transformation_to()
    T = alg.compose(Trand, Tr)
    rb.set_reference_frame(alg.ReferenceFrame3D(T))
Exemplo n.º 15
0
def get_docked_reference_frames(hex_transforms, rb_ligand):
    """
        @param hex_transforms A list of HEX transformations
        @param rb_ligand The rigid body of the ligand
        @return The reference frames that the rigid body of the ligand has
        when docked. The docked reference frame has transformation:
            Tdock = Thex * Tinitial
    """
    Trb = rb_ligand.get_reference_frame().get_transformation_to()
    docked_ref_frames = []
    for Thex in hex_transforms:
        Tdock = alg.compose(Thex, Trb)
        docked_rf = alg.ReferenceFrame3D(Tdock)
        docked_ref_frames.append(docked_rf)
    return docked_ref_frames
Exemplo n.º 16
0
def get_orientations_nearby(rotation, n, f):
    """
        Rotations nearby a given one. They are got intepolating with
        the rotations of the uniform coverage. The parameter f
        (0 <= f <= 1) must be close to 0 to get orientations
        that are close to the given orientation
        - Values from 0.1 (tight cluster) to 0.4 (loose)
          seem to be ok
        n - number of rotations requested
    """
    log.debug("Computing nearby rotations around %s", rotation)
    unif = alg.get_uniform_cover_rotations_3d(n)
    id_rot = alg.get_identity_rotation_3d()
    oris = []
    for rot in unif:
        r = alg.get_interpolated(rot, id_rot, f)
        r = alg.compose(r, rotation )
        oris.append(r)
    return oris
Exemplo n.º 17
0
def get_orientations_nearby(rotation, n, f):
    """
        Rotations nearby a given one. They are got intepolating with
        the rotations of the uniform coverage. The parameter f
        (0 <= f <= 1) must be close to 0 to get orientations
        that are close to the given orientation
        - Values from 0.1 (tight cluster) to 0.4 (loose)
          seem to be ok
        n - number of rotations requested
    """
    log.debug("Computing nearby rotations around %s", rotation)
    unif = alg.get_uniform_cover_rotations_3d(n)
    id_rot = alg.get_identity_rotation_3d()
    oris = []
    for rot in unif:
        r = alg.get_interpolated(rot, id_rot, f)
        r = alg.compose(r, rotation)
        oris.append(r)
    return oris
Exemplo n.º 18
0
    sel = atom.ATOMPDBSelector()
    m = IMP.Model()
    h_receptor =  atom.read_pdb(args.fn_receptor, m, sel)
    rb_receptor = atom.create_rigid_body(h_receptor)
    h_ligand =  atom.read_pdb(args.fn_ligand, m, sel)
    rb_ligand = atom.create_rigid_body(h_ligand)
    if args.dock:
        check_for_hexdock()
        if not args.fn_transforms or not args.fn_internal_transforms:
            raise IOError("Docking requires the --int and --hex arguments")
        hex_docking = HexDocking()
        hex_docking.dock(args.fn_receptor, args.fn_ligand, args.fn_transforms)
        # read the HEX file of solutions and get the internal transformations
        # giving the relative orientation of the ligand respect to the receptor
        Ts = read_hex_transforms(args.fn_transforms)
        rb_receptor = atom.create_rigid_body(h_receptor)
        Tis = [get_internal_transform(T, rb_receptor, rb_ligand) for T in Ts]
        io.write_transforms(Tis, args.fn_internal_transforms)
    elif args.write:
        # To write the positions correctly, the script requires that the
        # ligand file is the same that was used for the docking
        Tinternal = io.read_transforms(args.fn_internal_transforms)
        max_number = min(args.write, len(Tinternal))
        Trec = rb_receptor.get_reference_frame().get_transformation_to()
        for i in range(max_number):
            Tdock = alg.compose(Trec, Tinternal[i])
            ref = alg.ReferenceFrame3D(Tdock)
            rb_ligand.set_reference_frame(ref)
            atom.write_pdb(h_ligand,"docked-%03d.pdb" % i)
Exemplo n.º 19
0
    rigid_bodies.append(rbd)
    print "chain has",rbd.get_number_of_members(), \
                          "atoms","coordinates: ",rbd.get_coordinates()
    native_chain_centers.append(rbd.get_coordinates())

bb=alg.BoundingBox3D(alg.Vector3D(-25, -40,-60),
                         alg.Vector3D( 25,  40, 60))
# rotate and translate the chains
for rbd in rigid_bodies:
    # rotation
    rotation= alg.get_random_rotation_3d()
    transformation1=alg.get_rotation_about_point(rbd.get_coordinates(),rotation)
    # translation
    transformation2=alg.Transformation3D(alg.get_random_vector_in(bb))
    # Apply
    final_transformation = alg.compose(transformation1,transformation2)
    core.transform(rbd,final_transformation)
print "Writing transformed assembly"
atom.write_pdb (prot,"1z5s-transformed.pdb")

# set distance restraints measusring some distances between rigid bodies
# for the solution.
d01 = alg.get_distance(native_chain_centers[0],native_chain_centers[1])
r01 = core.DistanceRestraint(core.Harmonic(d01,1),chains[0],chains[1])
r01.set_name("distance 0-1")
d12 = alg.get_distance(native_chain_centers[1],native_chain_centers[2])
r12 = core.DistanceRestraint(core.Harmonic(d12,1),chains[1],chains[2])
r12.set_name("distance 1-2")
d23 = alg.get_distance(native_chain_centers[2],native_chain_centers[3])
r23 = core.DistanceRestraint(core.Harmonic(d23,1),chains[2],chains[3])
r23.set_name("distance 2-3")
Exemplo n.º 20
0
def get_internal_transform3(Trelative, rb_rec, rb_lig):
    Trb = rb_lig.get_reference_frame().get_transformation_to()
    Trec = rb_rec.get_reference_frame().get_transformation_to()
    Tdock = alg.compose(Trelative, Trb)
    Ti = alg.compose(Trec.get_inverse(), Tdock)
    return Ti
Exemplo n.º 21
0
def create_dockings_from_xlinks(exp):
    """
        Perform dockings that satisfy the cross-linking restraints.
        1) Based on the number of restraints, creates an order for the
           docking between pairs of subunits, favouring the subunits with
           more crosslinks to be the "receptors"
        2) Moves the subunits that are going to be docked to a position that
           satisfies the x-linking restraints. There is no guarantee that this
           position is correct. Its purpose is to help the docking
           algorithm with a clue of the proximity/orientation between subunits
        3) Performs docking between the subunits
        4) Filters the results of the docking that are not consistent with
           the cross-linking restraints
        5) Computes the relative transformations between the rigid bodies
           of the subunits that have been docked
        @param exp Class with the parameters for the experiment
    """
    log.info("Creating initial assembly from xlinks and docking")
    import docking_related as dock
    import buildxlinks as bx
    m = DominoModel.DominoModel()
    m.set_assembly_components(exp.fn_pdbs, exp.names)
    set_xlink_restraints(exp, m)
    order = bx.DockOrder()
    order.set_xlinks(m.xlinks)
    docking_pairs = order.get_docking_order()

    if hasattr(exp, "have_hexdock"):
        if not exp.have_hexdock:
            return

    for rec, lig in docking_pairs:
        pair_xlinks = m.xlinks.get_xlinks_for_pair((rec,lig))
        log.debug("Xlinks for the pair %s %s %s",rec, lig, pair_xlinks)
        h_receptor = representation.get_component(m.assembly, rec)
        h_ligand = representation.get_component(m.assembly, lig)
        rb_receptor = representation.get_rigid_body(m.components_rbs,
                                         representation.get_rb_name(rec))
        rb_ligand = representation.get_rigid_body(m.components_rbs,
                                         representation.get_rb_name(lig))
        initial_ref = rb_ligand.get_reference_frame()
        # move to the initial docking position
        mv = bx.InitialDockingFromXlinks()
        mv.set_xlinks(pair_xlinks)
        mv.set_hierarchies(h_receptor, h_ligand)
        mv.set_rigid_bodies(rb_receptor, rb_ligand)
        mv.move_ligand()
        fn_initial_docking = "%s-%s_initial_docking.pdb" % (rec,lig)
        mv.write_ligand(fn_initial_docking)
        # dock
        hex_docking = dock.HexDocking()
        receptor_index = exp.names.index(rec)
        fn_transforms = "hex_solutions_%s-%s.txt" % (rec, lig)
        fn_docked = "%s-%s_hexdock.pdb" % (rec, lig)
        hex_docking.dock(exp.fn_pdbs[receptor_index],
                         fn_initial_docking, fn_transforms, fn_docked, False)

        sel = atom.ATOMPDBSelector()
        new_m = IMP.Model()
        # After reading the file with the initial solution, the reference frame
        # for the rigid body of the ligand is not necessarily the  same one
        # that it had when saved.
        # Thus reading the file again ensures  consisten results when
        # using the HEXDOCK transforms
        new_h_ligand =  atom.read_pdb(fn_initial_docking, new_m, sel)
        new_rb_ligand = atom.create_rigid_body(new_h_ligand)
        Tlig = new_rb_ligand.get_reference_frame().get_transformation_to()
        fn_filtered = "hex_solutions_%s-%s_filtered.txt" % (rec, lig)
        # h_ligand contains the coordinates of the ligand after moving it
        # to the initial position for the docking
        dock.filter_docking_results(h_receptor, new_h_ligand, pair_xlinks,
                                            fn_transforms, fn_filtered)
        # transforms to apply to the ligand as it is in the file
        # fn_initial_docking
        Thex = dock.read_hex_transforms(fn_filtered)
        Trec = rb_receptor.get_reference_frame().get_transformation_to()
        Tinternal = []
        for i,T in enumerate(Thex):
            Tdock = alg.compose(T, Tlig)
            ref = alg.ReferenceFrame3D(Tdock)
            new_rb_ligand.set_reference_frame(ref)
            # internal transformation. The relationship is Tdock = Trec * Ti
            Ti = alg.compose(Trec.get_inverse(), Tdock)
            Tinternal.append(Ti)
        fn_relative = "relative_positions_%s-%s.txt" % (rec, lig)
        io.write_transforms(Tinternal, fn_relative)
        rb_ligand.set_reference_frame(initial_ref)