def METHOD_NAME(
    self, parameters: NDArrays, config: Dict[str, Scalar]
) -> Tuple[NDArrays, int, Dict[str, Scalar]]:
    """Train the provided parameters using the locally held dataset.
    This method first updates the local model using the original parameters
    provided. It then calculates the update by subtracting the original
    parameters from the updated model. The update is then clipped by an L2
    norm and Gaussian noise is added if specified by the configuration.
    The update is then applied to the original parameters to obtain the
    updated parameters which are returned along with the number of examples
    used and metrics computed during the fitting process.
    Parameters
    ----------
    parameters : NDArrays
        The current (global) model parameters.
    config : Dict[str, Scalar]
        Configuration parameters which allow the
        server to influence training on the client. It can be used to
        communicate arbitrary values from the server to the client, for
        example, to set the number of (local) training epochs.
    Returns
    -------
    parameters : NDArrays
        The locally updated model parameters.
    num_examples : int
        The number of examples used for training.
    metrics : Dict[str, Scalar]
        A dictionary mapping arbitrary string keys to values of type
        bool, bytes, float, int, or str. It can be used to communicate
        arbitrary values back to the server.
    Raises
    ------
    Exception
        If any required configuration parameters are not provided or are of
        the wrong type.
    """
    original_params = copy.deepcopy(parameters)
    # Getting the updated model from the wrapped client
    updated_params, num_examples, metrics = self.client.METHOD_NAME(parameters, config)
    # Update = updated model - original model
    update = [np.subtract(x, y) for (x, y) in zip(updated_params, original_params)]
    if "dpfedavg_clip_norm" not in config:
        raise Exception("Clipping threshold not supplied by the server.")
    if not isinstance(config["dpfedavg_clip_norm"], float):
        raise Exception("Clipping threshold should be a floating point value.")
    # Clipping
    update, clipped = clip_by_l2(update, config["dpfedavg_clip_norm"])
    if "dpfedavg_noise_stddev" in config:
        if not isinstance(config["dpfedavg_noise_stddev"], float):
            raise Exception(
                "Scale of noise to be added should be a floating point value."
            )
        # Noising
        update = add_gaussian_noise(update, config["dpfedavg_noise_stddev"])
    for i, _ in enumerate(original_params):
        updated_params[i] = original_params[i] + update[i]
    # Calculating value of norm indicator bit, required for adaptive clipping
    if "dpfedavg_adaptive_clip_enabled" in config:
        if not isinstance(config["dpfedavg_adaptive_clip_enabled"], bool):
            raise Exception(
                "dpfedavg_adaptive_clip_enabled should be a boolean-valued flag."
            )
        metrics["dpfedavg_norm_bit"] = not clipped
    return updated_params, num_examples, metrics