def METHOD_NAME(self, n_particles=50, n_iterations=250, verbose=False, threadCount=1):
    """
    :param n_particles: number of PSO particles, will be ignored if self._particle_swarm is False
    :param n_iterations: number of PSO iterations, will be ignored if self._particle_swarm is False
    :param verbose: whether to print stuff
    :param threadCount: integer; number of threads in multi-threading mode
    :return: keyword arguments that map (x_image, y_image) to the same source coordinate (source_x, source_y)
    """
    if self._particle_swarm:
        if threadCount > 1:
            pool = choose_pool(mpi=False, processes=threadCount)
        else:
            pool = None
        kwargs = self._fit_pso(n_particles, n_iterations, pool, verbose)
    else:
        kwargs = self._param_class.kwargs_lens
    kwargs_lens_final, source_penalty = self._fit_amoeba(kwargs, verbose)
    args_lens_final = self._param_class.kwargs_to_args(kwargs_lens_final)
    source_x_array, source_y_array = self.fast_rayshooting.ray_shooting_fast(
        args_lens_final
    )
    source_x, source_y = np.mean(source_x_array), np.mean(source_y_array)
    if verbose:
        print("optimization done.")
        print("Recovered source position: ", (source_x_array, source_y_array))
    return kwargs_lens_final, [source_x, source_y]