def __init__(self,
                 width: int,
                 height: int,
                 generator: StaticNoiseGenerator = None):
        super(SingleNoiseGenerator, self).__init__(width, height)

        generator = generator if generator is not None else PinkNoise(
            width, height)

        self.frame = generator.get_next_frame()
    def __init__(self,
                 width: int,
                 height: int,
                 generator: StaticNoiseGenerator = None,
                 sequence_length=2,
                 reverse_return=True):
        super(CircularNoiseGenerator, self).__init__(width, height)

        generator = generator if generator is not None else PinkNoise(
            width, height)
        self.frame_sequence = [
            generator.get_next_frame() for _ in range(sequence_length)
        ]

        self.seq_index = 0
        self.direction = +1
        self.start_over = reverse_return
Beispiel #3
0
    def __init__(self,
                 width: int,
                 height: int,
                 generator: StaticNoiseGenerator = None,
                 interpolation: Callable[[ndarray, ndarray, float],
                                         ndarray] = interpolate,
                 period=1.):
        super(ContinuousNoiseGenerator, self).__init__(width, height)

        self.generator = generator if generator is not None else PinkNoise(
            width, height)
        self.interpolation = interpolation

        self.origin = self.generator.get_next_frame()
        self.goal = self.generator.get_next_frame()

        self.period = period
        self.currentTime = 0.0
Beispiel #4
0
def main():
    ch_dir('2_ssim_precision')

    for x_position_update, patch_shift_x in position_updates.items():
        for y_position_update, patch_shift_y in position_updates.items():
            exp_name = f'ssim_precision_x_{x_position_update}_y_{y_position_update}'
            output_name = construct_file_name(exp_name)
            with open(output_name + '.log', 'w') as f:
                f.writelines([
                    f'Log file for experiment {output_name}\n',
                    'The experiment presents one big gabor patch in pink noise scene.\n'
                    f'New pink noise is generated every {base_period:.2f} s\n',
                    f'\nExperiment settings:\n',
                    f'Scene dimensions: {base_size}\n',
                    f'Length [s]: {length}\n',
                    f'FPS: {fps}\n',
                    f'PPD: {ppd}\n',
                    f'Contrast: {base_contrast:.2f}\n',
                    f'Patch position: {base_position}\n',
                    f'Position update (x, y) [s^-1]: {(patch_shift_x, patch_shift_y)}\n',
                ])

            base_noise = ContinuousNoiseGenerator(base_size,
                                                  base_size,
                                                  PinkNoise(
                                                      base_size, base_size),
                                                  period=base_period)

            patch_generator = GaborGenerator(patch_size_deg=patch_size_deg,
                                             ppd=ppd)
            noise_with_gabor = PatchedNoiseGenerator(
                base_size,
                base_size,
                base_noise,
                [(patch_generator,
                  get_position_updater(
                      (patch_shift_x, patch_shift_y), base_position))],
                contrast=base_contrast)

            field_names = []
            output_generators = []

            field_names.extend([
                'ssim_gabor_noise_vs_gabor', 'ssim_noise_vs_gabor',
                'ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             patch_generator.get_normalized_patch(), alpha,
                             beta, gamma),
                lambda: ssim(base_noise.get_next_frame(0),
                             patch_generator.get_normalized_patch(), alpha,
                             beta, gamma),
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             base_noise.get_next_frame(0), alpha, beta, gamma),
            ])

            field_names.extend([
                'cw_ssim_gabor_noise_vs_gabor', 'cw_ssim_noise_vs_gabor',
                'cw_ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: cw_ssim(noise_with_gabor.get_next_frame(0),
                                patch_generator.get_normalized_patch(), alpha,
                                beta, gamma),
                lambda: cw_ssim(base_noise.get_next_frame(0),
                                patch_generator.get_normalized_patch(), alpha,
                                beta, gamma),
                lambda: cw_ssim(noise_with_gabor.get_next_frame(
                    0), base_noise.get_next_frame(0), alpha, beta, gamma),
            ])

            generate_experiment_output(output_name=output_name,
                                       generator=noise_with_gabor,
                                       fields=field_names,
                                       outputs=output_generators)
Beispiel #5
0
def run_experiment(
    exp_name,
    theta_speed: int = None,
    phase_speed: int = None,
    freq_speed: int = None,
):
    width = height = scene_size

    base_noise = ContinuousNoiseGenerator(width,
                                          height,
                                          PinkNoise(width, height),
                                          period=period)
    update_list = [] if theta_speed is None else [
        *get_patch_value_updates('theta', theta_speed),
        *get_patch_value_updates('phase', phase_speed),
        *get_patch_value_updates('freq', freq_speed, initial_value=6),
    ]
    patch_generator = GaborGenerator(patch_size_deg=patch_size_deg,
                                     ppd=ppd,
                                     update_list=update_list)
    noise_with_gabor = PatchedNoiseGenerator(
        width,
        height,
        base_noise, [(patch_generator,
                      get_position_updater(patch_position=patch_position))],
        contrast=contrast)

    patch_size = patch_size_deg * ppd

    # TODO: tmp variable to be used in later check
    diff_noise = None
    if 'ssim' in exp_name:
        if 'true' in exp_name:

            def get_ssim(window):
                return ssim(window,
                            patch_generator.get_normalized_patch(),
                            alpha=0,
                            beta=-0.5,
                            gamma=0.5)
        else:
            patch_comparator = PatchComparator(patch_size_deg,
                                               ppd,
                                               detect_gabor=True,
                                               granularity=granularities)

            def get_ssim(window):
                return patch_comparator.get_best_ssim_match(window)

        def get_window_ssim(x1, x2, y1, y2):
            window = noise_with_gabor.get_next_frame(0)[x1:x2, y1:y2]

            if window.shape != (patch_size, patch_size):
                x = y = 0
                if window.shape[0] < patch_size and x1 == 0:
                    x = patch_size // 2
                if window.shape[1] < patch_size and y1 == 0:
                    y = patch_size // 2

                window = value_fill(window,
                                    x,
                                    y, (patch_size, patch_size),
                                    value=0)

            return get_ssim(window)

        heat_map = HeatMapGenerator(
            noise_with_gabor,
            window_size=patch_size,
            aggregate_function=transform_to_probabilistic_distribution,
            process_function=get_window_ssim)

    else:

        def get_window_diff(x1, x2, y1, y2, diff_mean):
            movement = np.abs(
                diff_noise.get_next_frame(0)[x1:x2, y1:y2].mean() - diff_mean)
            return movement

        def get_scene_properties():
            return {
                'diff_mean': diff_noise.get_next_frame(0).mean(),
            }

        if 'pure' in exp_name:
            diff_noise = PureDifferenceNoiseGenerator(noise_with_gabor)
        elif 'avg' in exp_name:
            diff_noise = AvgDifferenceNoiseGenerator(noise_with_gabor, period)
        else:
            diff_noise = DifferenceNoiseGenerator(noise_with_gabor, period)

        heat_map = HeatMapGenerator(
            diff_noise,
            window_size=patch_size,
            aggregate_function=transform_to_probabilistic_distribution,
            compute_cached_values=get_scene_properties,
            process_function=get_window_diff)

    output_name = construct_file_name(exp_name)
    with open(output_name + '.log', 'w') as f:
        f.writelines([
            f'Log file for experiment {output_name}',
            f'The experiment presents one gabor patch in pink noise scene. '
            f'New pink noise is generated every {period:.2f} s',
            f'PPD: {ppd}',
            f'Experiment settings:',
            f'Scene dimensions: {scene_size}',
            f'Length [s]: {length}',
            f'Contrast: {contrast:.2f}',
            f'Patch position: {patch_position}',
            f'Patch size [deg]: {patch_size_deg}',
            f'Position update (x, y) [s^-1]: {patch_shift}',
            f'Theta update [s^-1]: {theta_speed or 0:.2f}',
            f'Phase update [s^-1]: {phase_speed or 0:.2f}',
            f'Frequency update [s^-1]: {freq_speed or 0:.2f}',
        ])

    secondary_outputs = [('original', noise_with_gabor.get_next_frame)]
    if diff_noise is not None:
        secondary_outputs.append(('diff', diff_noise.get_next_frame))

    video_output = VideoOutput(heat_map.get_next_frame,
                               width,
                               height,
                               secondary_outputs=secondary_outputs,
                               FPS=fps,
                               length=length,
                               video_name=output_name + ".avi")

    video_output.run()
    video_output.__del__()
def run_experiment(size=500,
                   length=10,
                   ppd=60,
                   fps=30,
                   exp_name='test',
                   live=True,
                   output_diff=False,
                   delimiter=';',
                   gabor=True,
                   alpha=1,
                   beta=1,
                   gamma=1,
                   theta_speed: int = None,
                   phase_speed: int = None,
                   freq_speed: int = None,
                   patch_position=(0, 0),
                   patch_shift_x=0,
                   patch_shift_y=0,
                   contrast=0.5,
                   period=1,
                   output_values: [str] = None,
                   granularity=0):
    width = height = size

    if 'run' in exp_name:
        base_noise = RunningPinkNoise(width, height, period=period * length)
    elif 'v2' in exp_name:
        base_noise = PinkNoise2(width, height, length=length, deg=1 / 100)
    else:
        base_noise = ContinuousNoiseGenerator(width,
                                              height,
                                              PinkNoise(width, height),
                                              period=period)

    patch_constructor = get_patch_generator(gabor)
    patch_generator = patch_constructor(patch_size_deg=size / ppd,
                                        ppd=ppd,
                                        update_list=get_patch_value_updates(
                                            theta_speed, phase_speed,
                                            freq_speed))
    noise_with_gabor = PatchedNoiseGenerator(
        width,
        height,
        base_noise, [(patch_generator,
                      get_position_updater(
                          (patch_shift_x, patch_shift_y), patch_position))],
        contrast=contrast)

    if output_diff:
        diff_noise = DifferenceNoiseGenerator(noise_with_gabor, period)
    else:
        diff_noise = None

    output_name = construct_file_name(exp_name)
    with open(output_name + '.log', 'w') as f:
        f.writelines([
            f'Log file for experiment {output_name}\n',
            f'The experiment presents one big {"gabor" if gabor else "plaid"} patch in pink noise scene.\n'
            f'New pink noise is generated every {period:.2f} s\n',
            f'\nExperiment settings:\n',
            f'Scene dimensions: {size}\n',
            f'Length [s]: {length}\n',
            f'FPS: {fps}\n',
            f'PPD: {ppd}\n',
            f'Contrast: {contrast:.2f}\n',
            f'Patch position: {patch_position}\n',
            f'Position update (x, y) [s^-1]: {(patch_shift_x, patch_shift_y)}\n',
            f'Theta update [s^-1]: {theta_speed or 0:.2f}\n',
            f'Phase update [s^-1]: {phase_speed or 0:.2f}\n',
            f'Frequency update [s^-1]: {freq_speed or 0:.2f}\n',
        ])

    output_values = [] if output_values is None else output_values
    fieldnames = []
    output_generators = []
    for output_value in output_values:
        output_value = output_value.lower()
        if output_value == 'luminance':
            fieldnames.extend([
                'compare_lum_gabor_noise_vs_gabor',
                'compare_lum_noise_vs_gabor',
                'compare_lum_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: luminance_comparison(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: luminance_comparison(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: luminance_comparison(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])
        elif output_value == 'contrast':
            fieldnames.extend([
                'compare_con_gabor_noise_vs_gabor',
                'compare_con_noise_vs_gabor',
                'compare_con_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: contrast_comparison(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: contrast_comparison(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: contrast_comparison(noise_with_gabor.get_next_frame(0),
                                            base_noise.get_next_frame(0)),
            ])
        elif output_value == 'structure':
            fieldnames.extend([
                'compare_str_gabor_noise_vs_gabor',
                'compare_str_noise_vs_gabor',
                'compare_str_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: structural_similarity(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: structural_similarity(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: structural_similarity(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])
        elif output_value == 'cw_structure':
            fieldnames.extend([
                'compare_cw_str_gabor_noise_vs_gabor',
                'compare_cw_str_noise_vs_gabor',
                'compare_cw_str_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: phase_invariant_similarity(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: phase_invariant_similarity(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: phase_invariant_similarity(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])
        elif output_value == 'ssim':
            fieldnames.extend([
                'ssim_gabor_noise_vs_gabor', 'ssim_noise_vs_gabor',
                'ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             patch_generator.get_normalized_patch(), alpha,
                             beta, gamma),
                lambda: ssim(base_noise.get_next_frame(0),
                             patch_generator.get_normalized_patch(), alpha,
                             beta, gamma),
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             base_noise.get_next_frame(0), alpha, beta, gamma),
            ])
        elif output_value == 'cw_ssim':
            fieldnames.extend([
                'cw_ssim_gabor_noise_vs_gabor', 'cw_ssim_noise_vs_gabor',
                'cw_ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: cw_ssim(noise_with_gabor.get_next_frame(0),
                                patch_generator.get_normalized_patch(), alpha,
                                beta, gamma),
                lambda: cw_ssim(base_noise.get_next_frame(0),
                                patch_generator.get_normalized_patch(), alpha,
                                beta, gamma),
                lambda: cw_ssim(noise_with_gabor.get_next_frame(
                    0), base_noise.get_next_frame(0), alpha, beta, gamma),
            ])
        elif output_value == 'pattern_search_ssim' and granularity:
            simple_patch_comparator = PatchComparator(size / ppd,
                                                      ppd,
                                                      gabor,
                                                      granularity=granularity,
                                                      alpha=alpha,
                                                      beta=beta,
                                                      gamma=gamma)

            fieldnames.extend([
                'simple_ssim_gabor_noise_vs_patch_search',
                'simple_ssim_noise_vs_patch_search',
                'simple_ssim_gabor_noise_vs_noise',
            ])
            output_generators.extend([
                lambda: simple_patch_comparator.get_best_ssim_match(
                    noise_with_gabor.get_next_frame(0)),
                lambda: simple_patch_comparator.get_best_ssim_match(
                    base_noise.get_next_frame(0)),
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             base_noise.get_next_frame(0), alpha, beta, gamma)
            ])
        elif output_value == 'pattern_search_cw_ssim' and granularity:
            complex_patch_comparator = PatchComparator(size / ppd,
                                                       ppd,
                                                       gabor,
                                                       granularity=granularity,
                                                       alpha=alpha,
                                                       beta=beta,
                                                       gamma=gamma,
                                                       simple=False)
            fieldnames.extend([
                'cw_ssim_gabor_noise_vs_patch_search',
                'cw_ssim_noise_vs_patch_search',
                'cw_ssim_gabor_noise_vs_noise',
            ])
            output_generators.extend([
                lambda: complex_patch_comparator.get_best_ssim_match(
                    noise_with_gabor.get_next_frame(0)),
                lambda: complex_patch_comparator.get_best_ssim_match(
                    base_noise.get_next_frame(0)),
                lambda: cw_ssim(noise_with_gabor.get_next_frame(
                    0), base_noise.get_next_frame(0), alpha, beta, gamma),
            ])
        elif output_value == 'diff' and output_diff:
            fieldnames.extend([
                'diff_gabor_noise_max',
                'diff_gabor_noise_min',
                'diff_gabor_noise_mean',
            ])
            # noinspection PyArgumentList
            output_generators.extend([
                lambda: diff_noise.get_next_frame(0).max(),
                lambda: diff_noise.get_next_frame(0).min(),
                lambda: diff_noise.get_next_frame(0).mean(),
            ])
        else:
            raise ValueError(f'{output_value} is not a valid output value')

    noise_generator = NoiseGeneratorWithCSVOutput(
        generator=diff_noise or noise_with_gabor,
        file_name=output_name + ".csv",
        field_names=fieldnames,
        output_generators=output_generators)

    if live:
        output = PygletOutput(noise_generator.get_next_frame, width, height)
    else:
        secondary_outputs = [('original', noise_with_gabor.get_next_frame)
                             ] if output_diff else []
        output = VideoOutput(noise_generator.get_next_frame,
                             width,
                             height,
                             secondary_outputs=secondary_outputs,
                             FPS=fps,
                             length=length,
                             video_name=output_name + ".avi")

    output.run()
    hasattr(output, '__del__') and output.__del__()
    noise_generator.__del__()
Beispiel #7
0
def main():
    ch_dir('1_simple_poc')

    for contrast_setting, contrast in contrast_settings.items():
        for position_setting, patch_position in position_settings.items():
            exp_name = f'{contrast_setting}_{position_setting}_patch'

            output_name = construct_file_name(exp_name)
            with open(output_name + '.log', 'w') as f:
                f.writelines([
                    f'Log file for experiment {output_name}\n',
                    'The experiment presents one big gabor patch in pink noise scene.\n'
                    f'New pink noise is generated every {base_period:.2f} s\n',
                    f'\nExperiment settings:\n',
                    f'Scene dimensions: {base_size}\n',
                    f'Length [s]: {length}\n',
                    f'FPS: {fps}\n',
                    f'PPD: {ppd}\n',
                    f'Contrast: {contrast:.2f}\n',
                    f'Patch position: {patch_position}\n',
                ])

            base_noise = ContinuousNoiseGenerator(base_size,
                                                  base_size,
                                                  PinkNoise(
                                                      base_size, base_size),
                                                  period=base_period)

            patch_generator = GaborGenerator(patch_size_deg=patch_size_deg,
                                             ppd=ppd)
            noise_with_gabor = PatchedNoiseGenerator(
                base_size,
                base_size,
                base_noise, [(patch_generator, lambda dt: patch_position)],
                contrast=contrast)

            field_names = []
            output_generators = []

            field_names.extend([
                'compare_lum_gabor_noise_vs_gabor',
                'compare_lum_noise_vs_gabor',
                'compare_lum_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: luminance_comparison(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: luminance_comparison(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: luminance_comparison(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])

            field_names.extend([
                'compare_con_gabor_noise_vs_gabor',
                'compare_con_noise_vs_gabor',
                'compare_con_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: contrast_comparison(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: contrast_comparison(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: contrast_comparison(noise_with_gabor.get_next_frame(0),
                                            base_noise.get_next_frame(0)),
            ])

            field_names.extend([
                'compare_str_gabor_noise_vs_gabor',
                'compare_str_noise_vs_gabor',
                'compare_str_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: structural_similarity(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: structural_similarity(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: structural_similarity(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])

            field_names.extend([
                'compare_cw_str_gabor_noise_vs_gabor',
                'compare_cw_str_noise_vs_gabor',
                'compare_cw_str_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: phase_invariant_similarity(
                    noise_with_gabor.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: phase_invariant_similarity(
                    base_noise.get_next_frame(0),
                    patch_generator.get_normalized_patch()),
                lambda: phase_invariant_similarity(
                    noise_with_gabor.get_next_frame(0),
                    base_noise.get_next_frame(0)),
            ])

            generate_experiment_output(output_name=output_name,
                                       generator=noise_with_gabor,
                                       fields=field_names,
                                       outputs=output_generators)
Beispiel #8
0
period = 1

ppd = 30
patch_size_deg = 2
contrast = 0.5
patch_shift = (0, 0)

if __name__ == '__main__':
    args = get_command_line_args()
    width = height = args['size']
    patch_position = args['patch_position']

    base_noise = ContinuousNoiseGenerator(width,
                                          height,
                                          PinkNoise(width, height),
                                          period=period)
    # base_noise = PinkNoise2(width, height)
    # base_noise = RunningPinkNoise(width, height, period * 20)
    patch_generator = GaborGenerator(
        patch_size_deg=patch_size_deg,
        ppd=ppd,
        theta=90,
        # update_list=get_patch_value_updates(args['theta_speed'], args['phase_speed'], args['freq_speed']))
        update_list=get_patch_value_updates('phase', -pi / 10))
    noise_with_gabor = PatchedNoiseGenerator(
        width,
        height,
        base_noise, [(patch_generator,
                      get_position_updater(patch_shift=patch_shift,
                                           patch_position=patch_position))],
    Inter = 'interpolated'
    Pink = 'pink'
    Run = 'running'
    White = 'white'


if __name__ == '__main__':
    # parser = argparse.ArgumentParser()
    # parser.add_argument("--noise", default=Noises.Inter.value, type=str)
    # noise_type = parser.parse_args().noise

    ch_dir('spectra')
    # for noise_type in [Noises.Run.value]:
    for noise_type in (noise.value for noise in Noises):
        if noise_type == Noises.Inter.value:
            noise = ContinuousNoiseGenerator(base_size, base_size, PinkNoise(base_size, base_size), period=base_period)
        elif noise_type == Noises.Pink.value:
            # Beware! PinkNoise2 is fixed in time length so running it for for longer than 5 s will crash the app
            noise = PinkNoise2(base_size, base_size, length=length)
        elif noise_type == Noises.Run.value:
            noise = RunningPinkNoise(base_size, base_size, base_period * 5)
        elif noise_type == Noises.White.value:
            noise = ContinuousNoiseGenerator(base_size, base_size, WhiteNoise(base_size, base_size), period=base_period)
        else:
            raise ValueError(f'{noise_type} is not a recognized noise type')


        def get_spectra(dt):
            frame = noise.get_next_frame(dt) - .5
            # frame = (np.ones((base_size, base_size))-0.5)
def main():
    ch_dir('3_changing_gabor_adv_detection')

    for update_type, update_options in patch_updates.items():
        for granularity, granularity_value in granularities.items():
            update_speed = update_options['middle']
            exp_name = f'patch_{update_type}_granularity_{granularity}'

            output_name = construct_file_name(exp_name)
            with open(output_name + '.log', 'w') as f:
                f.writelines([f'Log file for experiment {output_name}\n',
                              'The experiment presents one big gabor patch in pink noise scene.\n'
                              f'New pink noise is generated every {base_period:.2f} s\n',

                              f'\nExperiment settings:\n',
                              f'Scene dimensions: {base_size}\n',
                              f'Length [s]: {length}\n',
                              f'FPS: {fps}\n',
                              f'PPD: {ppd}\n',
                              f'Contrast: {base_contrast:.2f}\n',
                              f'{update_type} update [s^-1]: {update_speed}\n',
                              ])

            base_noise = ContinuousNoiseGenerator(base_size, base_size, PinkNoise(base_size, base_size),
                                                  period=base_period)

            patch_generator = GaborGenerator(patch_size_deg=patch_size_deg, ppd=ppd,
                                             update_list=get_patch_value_updates(update_type, update_speed,
                                                                                 initial_value=6
                                                                                 if update_type == 'freq'
                                                                                 else 0))
            noise_with_gabor = PatchedNoiseGenerator(base_size, base_size, base_noise,
                                                     [(patch_generator, lambda dt: base_position)],
                                                     contrast=base_contrast)

            field_names = []
            output_generators = []

            field_names.extend([
                'ssim_gabor_noise_vs_gabor',
                'ssim_noise_vs_gabor',
                'ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             patch_generator.get_normalized_patch(),
                             alpha, beta, gamma),
                lambda: ssim(base_noise.get_next_frame(0),
                             patch_generator.get_normalized_patch(),
                             alpha, beta, gamma),
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             base_noise.get_next_frame(0),
                             alpha, beta, gamma),
            ])

            field_names.extend([
                'simple_ssim_gabor_noise_vs_patch_search',
                'simple_ssim_noise_vs_patch_search',
                'simple_ssim_gabor_noise_vs_noise',
            ])
            simple_patch_comparator = PatchComparator(patch_size_deg, ppd, granularity=granularity_value,
                                                      alpha=alpha, beta=beta, gamma=gamma)
            output_generators.extend([
                lambda: simple_patch_comparator.get_best_ssim_match(noise_with_gabor.get_next_frame(0)),
                lambda: simple_patch_comparator.get_best_ssim_match(base_noise.get_next_frame(0)),
                lambda: ssim(noise_with_gabor.get_next_frame(0),
                             base_noise.get_next_frame(0),
                             alpha, beta, gamma)
            ])

            field_names.extend([
                'cw_ssim_gabor_noise_vs_gabor',
                'cw_ssim_noise_vs_gabor',
                'cw_ssim_gabor_noise_vs_noise'
            ])
            output_generators.extend([
                lambda: cw_ssim(noise_with_gabor.get_next_frame(0),
                                patch_generator.get_normalized_patch(),
                                alpha, beta, gamma),
                lambda: cw_ssim(base_noise.get_next_frame(0),
                                patch_generator.get_normalized_patch(),
                                alpha, beta, gamma),
                lambda: cw_ssim(noise_with_gabor.get_next_frame(0),
                                base_noise.get_next_frame(0),
                                alpha, beta, gamma),
            ])

            field_names.extend([
                'cw_ssim_gabor_noise_vs_patch_search',
                'cw_ssim_noise_vs_patch_search',
                'cw_ssim_gabor_noise_vs_noise',
            ])
            complex_patch_comparator = PatchComparator(patch_size_deg, ppd, granularity=granularity_value,
                                                       alpha=alpha, beta=beta, gamma=gamma, simple=False)
            output_generators.extend([
                lambda: complex_patch_comparator.get_best_ssim_match(noise_with_gabor.get_next_frame(0)),
                lambda: complex_patch_comparator.get_best_ssim_match(base_noise.get_next_frame(0)),
                lambda: cw_ssim(noise_with_gabor.get_next_frame(0),
                                base_noise.get_next_frame(0),
                                alpha, beta, gamma),
            ])

            generate_experiment_output(output_name=output_name,
                                       generator=noise_with_gabor,
                                       fields=field_names,
                                       outputs=output_generators)
def run_experiment(exp_name, env, patch, position, methods=None):
    methods = methods if methods is not None else all_methods

    base_noise = SingleNoiseGenerator(width, height, PinkNoise(width, height)) \
        if env == 'S' else ContinuousNoiseGenerator(width, height, PinkNoise(width, height), period=period)

    update_list = [] if patch == 'S' else [
        *get_patch_value_updates('theta', patch_updates['theta']['middle']),
        *get_patch_value_updates('phase', patch_updates['phase']['middle']),
        *get_patch_value_updates('freq', patch_updates['freq']['slow'], initial_value=6),
    ]
    patch_generator = GaborGenerator(
        patch_size_deg=patch_size_deg,
        ppd=ppd,
        update_list=update_list)
    patch_shift = (0, 0) if position == 'S' else shift_value
    patch_position_updater = get_position_updater(patch_shift=patch_shift,
                                                  patch_position=patch_position)
    noise_with_gabor = PatchedNoiseGenerator(width, height, base_noise,
                                             [(patch_generator, patch_position_updater)],
                                             contrast=contrast)

    output_name = construct_file_name(exp_name)
    with open(output_name + '.log', 'w') as f:
        f.writelines([f'Log file for experiment {output_name}',
                      f'The experiment presents one gabor patch in pink noise scene.'
                      f'Scene: {"static" if env == "S" else "dynamic"}'
                      f'Position: {"static" if position == "S" else "dynamic"}'
                      f'Patch: {"static" if patch == "S" else "dynamic"}'
                      ])

    # The type is needed so PyCharm won't complain later
    secondary_outputs: List[Tuple[str, Callable[[int], ndarray]]] = []
    for method in methods:
        try:
            heat_map = add_noise(method,
                                 secondary_outputs=secondary_outputs,
                                 base_noise=noise_with_gabor,
                                 get_patch=patch_generator.get_normalized_patch
                                 )
        except ValueError:
            print('Invalid noise type added')
        else:
            secondary_outputs.append((f'{method}_heat', heat_map.get_next_frame))

    def update_all(dt=1):
        frame = noise_with_gabor.get_next_frame(dt)

        # Update secondary outputs that won't be updated by the VideoOutput
        for _, update_sec_output in secondary_outputs:
            update_sec_output(dt)

        return frame

    video_output = VideoOutput(update_all, width, height, secondary_outputs=secondary_outputs,
                               FPS=fps, length=length, video_name=output_name + ".avi")

    video_output.run()
    video_output.__del__()

    return output_name