<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _fit_spatial(noise, noise_temporal, mask, template, spatial_sd, temporal_sd, noise_dict, fit_thresh, fit_delta, iterations, ):
 """ Fit the noise model to match the SNR of the data Parameters noise : multidimensional array, float Initial estimate of the noise noise_temporal : multidimensional array, float The temporal noise that was generated by _generate_temporal_noise tr_duration : float What is the duration, in seconds, of each TR? template : 3d array, float A continuous (0 -> 1) volume describing the likelihood a voxel is in the brain. This can be used to contrast the brain and non brain. mask : 3d array, binary The mask of the brain volume, distinguishing brain from non-brain spatial_sd : float What is the standard deviation in space of the noise volume to be generated temporal_sd : float What is the standard deviation in time of the noise volume to be generated noise_dict : dict A dictionary specifying the types of noise in this experiment. The noise types interact in important ways. First, all noise types ending with sigma (e.g. motion sigma) are mixed together in _generate_temporal_noise. These values describe the proportion of mixing of these elements. However critically, SFNR is the parameter that describes how much noise these components contribute to the brain. If you set the noise dict to matched then it will fit the parameters to match the participant as best as possible. fit_thresh : float What proportion of the target parameter value is sufficient error to warrant finishing fit search. fit_delta : float How much are the parameters attenuated during the fitting process, in terms of the proportion of difference between the target parameter and the actual parameter iterations : int The first element is how many steps of fitting the SFNR and SNR values will be performed. Usually converges after < 5. The second element is the number of iterations for the AR fitting. This is much more time consuming (has to make a new timecourse on each iteration) so be careful about setting this appropriately. Returns ------- noise : multidimensional array, float Generates the noise volume given these parameters """


    # Pull out information that is needed
    dim_tr = noise.shape
    base = template * noise_dict['max_activity']
    base = base.reshape(dim_tr[0], dim_tr[1], dim_tr[2], 1)
    mean_signal = (base[mask > 0]).mean()
    target_snr = noise_dict['snr']

    # Iterate through different parameters to fit SNR and SFNR
    spat_sd_orig = np.copy(spatial_sd)
    iteration = 0
    for iteration in list(range(iterations)):

        # Calculate the new metrics
        new_snr = _calc_snr(noise, mask)

        # Calculate the difference between the real and simulated data
        diff_snr = abs(new_snr - target_snr) / target_snr

        # If the AR is sufficiently close then break the loop
        if diff_snr < fit_thresh:
            logger.info('Terminated SNR fit after ' + str(
                iteration) + ' iterations.')
            break

        # Convert the SFNR and SNR
        spat_sd_new = mean_signal / new_snr

        # Update the variable
        spatial_sd -= ((spat_sd_new - spat_sd_orig) * fit_delta)

        # Prevent these going out of range
        if spatial_sd < 0 or np.isnan(spatial_sd):
            spatial_sd = 10e-3

        # Set up the machine noise
        noise_system = _generate_noise_system(dimensions_tr=dim_tr,
                                              spatial_sd=spatial_sd,
                                              temporal_sd=temporal_sd,
                                              )

        # Sum up the noise of the brain
        noise = base + (noise_temporal * temporal_sd) + noise_system

        # Reject negative values (only happens outside of the brain)
        noise[noise < 0] = 0

    # Failed to converge
    if iterations == 0:
        logger.info('No fitting iterations were run')
    elif iteration == iterations:
        logger.warning('SNR failed to converge.')

    # Return the updated noise
    return noise, spatial_sd