//  [python]
def cal_trans_homo(self, src_keypts, tgt_keypts, weight, is_training=False):
        eps = 1e-6
        # weight:[bs,L]
        corr_pos = torch.cat((src_keypts, tgt_keypts), dim=-1)  # [bs, num_corr, 4]
        bs, num_corr = corr_pos.shape[0], corr_pos.shape[1]
        k = num_corr

        #################################
        # construct the spatial consistency matrix
        #################################

        # normalized-distance consistency matrix
        src_dist = torch.linalg.norm((src_keypts[:, :, None, :] - src_keypts[:, None, :, :]), dim=-1)
        tgt_dist = torch.linalg.norm((tgt_keypts[:, :, None, :] - tgt_keypts[:, None, :, :]), dim=-1)
        src_dist = F.normalize(src_dist, dim=-1)  # deal scale-change case
        tgt_dist = F.normalize(tgt_dist, dim=-1)  # deal scale-change case
        dis_compatibility = (src_dist + eps) / (tgt_dist + eps)
        dis_compatibility = torch.clamp(1 - (dis_compatibility - 1) ** 2 / (self.sigma_spat ** 2), min=0)  # bs,L,l

        # normalized-distance consistency matrix
        src_angle = self.cal_angel(src_keypts, angel_k=self.angel_k)
        tgt_angle = self.cal_angel(tgt_keypts, angel_k=self.angel_k)
        angle_compatibility = torch.abs(src_angle - tgt_angle)
        angle_compatibility = torch.clamp(1 - (angle_compatibility) ** 2 / (self.sigma_angle ** 2), min=0)  # bs,L,l
        corr_compatibility = (1 - self.gama) * angle_compatibility + self.gama * dis_compatibility

        #################################
        # Power iteratation to get the inlier probability
        #################################
        corr_compatibility[:, torch.arange(corr_compatibility.shape[1]), torch.arange(corr_compatibility.shape[1])] = 0

        total_weight = self.cal_leading_eigenvector(corr_compatibility, method='power')

        total_weight = total_weight.view([bs, k]) * weight
        total_weight = total_weight / (torch.sum(total_weight, dim=-1, keepdim=True) + eps)
        #################################
        # calculate the transformation by weighted least-squares for each subsets in parallel
        #################################
        total_weight = total_weight.view([-1, k])

        # src_knn, tgt_knn = src_keypts.view([-1, k, 2]), tgt_keypts.view([-1, k, 2])
        seed_as_center = False

        if seed_as_center:
            assert ("Not codes!")
        else:
            # not use seeds as neighborhood centers.
            # src_knn = (src_keypts/ wh) * 2 - 1
            # tgt_knn = (tgt_keypts/ wh) * 2 - 1
            seedwise_trans = kornia.geometry.homography.find_homography_dlt(src_keypts, tgt_keypts, total_weight)
        return seedwise_trans, None
        # return self.homo_refinement(seedwise_trans,src_keypts,tgt_keypts,total_weight),None
        #################################

        # calculate the inlier number for each hypothesis, and find the best transformation for each point cloud pair
        #################################
        pred_position = torch.einsum('bnm,bmk->bnk', seedwise_trans[:, :2, :2],
                                     src_keypts.permute(0, 2, 1)) + seedwise_trans[:, :2, 2:3]  # [bs, num_corr, 3]

        pred_position_z = torch.einsum('bnm,bmk->bnk', seedwise_trans[:, 2:3, :2],
                                       src_keypts.permute(0, 2, 1)) + seedwise_trans[:, 2:3, 2:3]  # [bs, num_corr, 3]

        pred_position = pred_position / pred_position_z
        pred_position = pred_position.permute(0, 2, 1)

        L2_dis = torch.linalg.norm(pred_position - tgt_keypts[:, :, :], dim=-1)  # [bs, num_corr]
        seedwise_fitness = torch.mean((L2_dis < self.inlier_threshold).float(), dim=-1)  # [bs, 1]
        # seedwise_inlier_rmse = torch.sum(L2_dis * (L2_dis < config.inlier_threshold).float(), dim=1)
        batch_best_guess = seedwise_fitness

        # refine the pose by using all the inlier correspondences (done in the post-refinement step)
        final_trans = seedwise_trans
        final_labels = (L2_dis < self.inlier_threshold).float()

        return final_trans, final_labels