<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _generate_noise_temporal(stimfunction_tr, tr_duration, dimensions, template, mask, noise_dict ):
 """Generate the temporal noise Generate the time course of the average brain voxel. To change the relative mixing of the noise components, change the sigma's specified below. Parameters stimfunction_tr : 1 Dimensional array This is the timecourse of the stimuli in this experiment, each element represents a TR tr_duration : int How long is a TR, in seconds dimensions : 3 length array, int What is the shape of the volume to be generated 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 : 3 dimensional array, binary The masked brain, thresholded to distinguish brain and non-brain 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. The sigma 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. Returns noise_temporal : one dimensional array, float Generates the temporal noise timecourse for these parameters """


    # Set up common parameters
    # How many TRs are there
    trs = len(stimfunction_tr)

    # What time points are sampled by a TR?
    timepoints = list(np.linspace(0, (trs - 1) * tr_duration, trs))

    # Preset the volume
    noise_volume = np.zeros((dimensions[0], dimensions[1], dimensions[2], trs))

    # Generate the drift noise
    if noise_dict['drift_sigma'] != 0:
        # Calculate the drift time course
        noise = _generate_noise_temporal_drift(trs,
                                               tr_duration,
                                               )
        # Create a volume with the drift properties
        volume = np.ones(dimensions)

        # Combine the volume and noise
        noise_volume += np.multiply.outer(volume, noise) * noise_dict[
            'drift_sigma']

    # Generate the physiological noise
    if noise_dict['physiological_sigma'] != 0:

        # Calculate the physiological time course
        noise = _generate_noise_temporal_phys(timepoints,
                                              )

        # Create a brain shaped volume with similar smoothing properties
        volume = _generate_noise_spatial(dimensions=dimensions,
                                         mask=mask,
                                         fwhm=noise_dict['fwhm'],
                                         )

        # Combine the volume and noise
        noise_volume += np.multiply.outer(volume, noise) * noise_dict[
            'physiological_sigma']

    # Generate the AR noise
    if noise_dict['auto_reg_sigma'] != 0:

        # Calculate the AR time course volume
        noise = _generate_noise_temporal_autoregression(timepoints,
                                                        noise_dict,
                                                        dimensions,
                                                        mask,
                                                        )

        # Combine the volume and noise
        noise_volume += noise * noise_dict['auto_reg_sigma']

    # Generate the task related noise
    if noise_dict['task_sigma'] != 0 and np.sum(stimfunction_tr) > 0:

        # Calculate the task based noise time course
        noise = _generate_noise_temporal_task(stimfunction_tr,
                                              )

        # Create a brain shaped volume with similar smoothing properties
        volume = _generate_noise_spatial(dimensions=dimensions,
                                         mask=mask,
                                         fwhm=noise_dict['fwhm'],
                                         )
        # Combine the volume and noise
        noise_volume += np.multiply.outer(volume, noise) * noise_dict[
            'task_sigma']

    # Finally, z score each voxel so things mix nicely
    noise_volume = stats.zscore(noise_volume, 3)

    # If it is a nan it is because you just divided by zero (since some
    # voxels are zeros in the template)
    noise_volume[np.isnan(noise_volume)] = 0

    return noise_volume