def remote_convolution_frame(frame, kernel_path, host_id):

    """
    This function ...
    :param frame:
    :param kernel_path:
    :param host_id:
    :return:
    """

    # Check whether the frame is constant. If it is, we don't have to convolve!
    if frame.is_constant(): return frame.copy()

    # Check whether we are already connected to the specified remote host
    if host_id in connected_remotes and connected_remotes[host_id] is not None:
        remote = connected_remotes[host_id]
    else:

        # Debugging
        log.debug("Logging in to remote host ...")

        # Create a remote instance for the specified host ID
        remote = Remote()
        remote.setup(host_id)

    # Debugging
    log.debug("Creating temporary directory remotely ...")

    # Create a temporary directory to do the convolution
    remote_home_directory = remote.home_directory
    remote_temp_path = fs.join(remote_home_directory, time.unique_name("convolution"))
    remote.create_directory(remote_temp_path)

    # Debugging
    log.debug("Creating local temporary directory ...")

    # Create a temporary directory locally to contain the frames
    local_temp_path = fs.join(fs.home(), time.unique_name("convolution"))
    fs.create_directory(local_temp_path)

    # Debugging
    log.debug("Writing the frame to the temporary directory ...")

    # Write the frame
    local_frame_path = fs.join(local_temp_path, frame.name + ".fits")
    frame.save(local_frame_path)

    # Debugging
    #log.debug("Writing the kernel to the temporary directory ...")

    # Write the kernel
    #local_kernel_path = fs.join(local_temp_path, "kernel.fits")
    #kernel.save(local_kernel_path)

    # Debugging
    log.debug("Uploading the frame to the remote directory ...")

    # Upload the frame file
    remote_frame_path = fs.join(remote_temp_path, frame.name)
    remote.upload(local_frame_path, remote_temp_path, new_name=frame.name, compress=True, show_output=True)

    # Debugging
    #log.debug("Uploading the kernel to the remote directory ...")

    # Upload the kernel FITS file to the remote directory
    #remote_kernel_path = fs.join(remote_temp_path, "kernel.fits")
    #remote.upload(local_kernel_path, remote_temp_path, new_name="kernel.fits", compress=True, show_output=True)

    # Debugging
    log.debug("Uploading the kernel to the remote directory ...")

    # Upload the kernel FITS file to the remote directory
    remote_kernel_path = fs.join(remote_temp_path, "kernel.fits")
    remote.upload(kernel_path, remote_temp_path, new_name="kernel.fits", compress=True, show_output=True)

    # Debugging
    log.debug("Creating a python script to perform the convolution remotely ...")

    # Create the script
    local_script_path = fs.join(local_temp_path, "convolve.py")
    script_file = open(local_script_path, 'w')

    script_file.write("#!/usr/bin/env python\n")
    script_file.write("# -*- coding: utf8 -*-\n")
    script_file.write("\n")
    script_file.write("# Import the relevant PTS classes and modules\n")
    script_file.write("from pts.magic.core.frame import Frame\n")
    script_file.write("from pts.core.tools.logging import log\n")
    script_file.write("\n")
    script_file.write("# Inform the user\n")
    script_file.write("log.info('Opening the kernel frame ...')\n")
    script_file.write("\n")
    script_file.write("# Open the kernel frame\n")
    script_file.write("kernel = Frame.from_file('" + remote_kernel_path + "')\n")
    script_file.write("\n")
    script_file.write("# Inform the user\n")
    script_file.write("log.info('Opening the frame ...')\n")
    script_file.write("\n")
    script_file.write("# Open the frame\n")
    script_file.write("frame = Frame.from_file('" + remote_frame_path + "')\n")
    script_file.write("\n")
    script_file.write("# Inform the user\n")
    script_file.write("log.info('Convolving the frame ...')\n")
    script_file.write("\n")
    script_file.write("# Do the convolution and save the result\n")
    script_file.write("convolved = frame.convolved(kernel, allow_huge=True)\n")
    script_file.write("convolved.save('" + remote_frame_path + "')\n") # overwrite the frame

    # Write to disk
    script_file.close()

    # Debugging
    log.debug("Uploading the python script ...")

    # Upload the script file
    remote_script_path = fs.join(remote_temp_path, "convolve.py")
    remote.upload(local_script_path, remote_temp_path, new_name="convolve.py", show_output=True)

    # Debugging
    log.debug("Executing the script remotely ...")

    # Execute the script file remotely
    remote.execute("python " + remote_script_path, output=False, show_output=True)

    # Debugging
    log.debug("Downloading the result ...")

    # Determine the name of the local frame file
    frame_file_name = fs.name(remote_frame_path)

    # Debugging
    log.debug("Downloading the " + fs.strip_extension(frame_file_name) + " frame ...")

    # Download
    remote.download(remote_frame_path, local_temp_path, new_name=frame_file_name, compress=True, show_output=True)

    # Remove the temporary directory on the remote's filesystem
    remote.remove_directory(remote_temp_path)

    # Load the convolved frame
    convolved = Frame.from_file(local_frame_path)

    # Remove the local temporary directory
    fs.remove_directory(local_temp_path)

    # Return the convolved frame
    return convolved