123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import multiprocessing as mp
- from multiprocessing import Pipe, Value, current_process, Array
- import matplotlib
- import matplotlib.pyplot as plt
- # import matplotlib.animation as animation
- from matplotlib.animation import FuncAnimation
- import logging
- from colorlog import ColoredFormatter
- import numpy as np
- import time
- LOGFORMAT = "%(log_color)s %(asctime)s [%(filename)-12.12s] [%(lineno)4d] [%(processName)-12.12s] [%(threadName)-12.12s] [%(levelname)-7.7s] %(message)s"
- logging.root.setLevel(logging.INFO)
- formatter = ColoredFormatter(LOGFORMAT)
- stream = logging.StreamHandler()
- stream.setLevel(logging.INFO)
- stream.setFormatter(formatter)
- log = logging.getLogger('pythonConfig')
- log.setLevel(logging.INFO)
- log.addHandler(stream)
- def static_vars(**kwargs):
- def decorate(func):
- for k in kwargs:
- setattr(func, k, kwargs[k])
- return func
- return decorate
- def plot_feedback(audio_feedback_run, freq, audio_fb_target):
- """Plot feedback in real time. Uses normalized frequency and audio_fb_target to plot target."""
- log.info("Starting visual feedback")
- # config_file = 'paradigm.yaml'
- # config = self._read_config(config_file)
- # config = config.feedback
-
- fig = plt.figure(10, figsize=(4, 4), facecolor='black')
- ax = fig.add_subplot(1, 1, 1)
- ax.set_facecolor((0.02, 0.02, 0.02))
- target_x = 0.1
- target_w = 0.8
-
-
- cursor_x = 0.2
- cursor_y = 0.5 # variable
- cursor_w = 0.6
- cursor_h = 0.05
-
- target_ra = ax.add_patch(plt.Rectangle((target_x, 0), target_w, 0.1, fill=True, edgecolor=None, facecolor=(.7, .2, .4), linewidth=0, zorder=1))
- cursor_ra = ax.add_patch(plt.Rectangle((cursor_x, 0.5), cursor_w, cursor_h, fill=True, facecolor=(.4, .5, 1.0), linewidth=0, zorder=10))
-
- plt.show(False)
- plt.draw()
-
- def init_plot():
- ax.set_clip_on(False)
- ax.get_xaxis().set_ticks([])
- ax.get_yaxis().set_ticks([])
- ax.set_xlim(0, 1)
- ax.set_ylim(0, 1)
- for n,s in ax.spines.items():
- s.set_color((.2,.2,.2))
-
- return (cursor_ra, target_ra)
-
-
- @static_vars(is_plotting=False)
- def update_plot(i):
- if (not update_plot.is_plotting) and audio_feedback_run.value == 1:
- update_plot.is_plotting = True
- cursor_ra.set_visible(True)
- target_ra.set_visible(True)
- init_plot()
- elif update_plot.is_plotting and (audio_feedback_run.value == 0):
- update_plot.is_plotting = False
- cursor_ra.set_visible(False)
- target_ra.set_visible(False)
-
-
- if update_plot.is_plotting:
-
- cursor_y = freq.value - cursor_h/2.0
- target_y = audio_fb_target[1]
- target_h = audio_fb_target[2] - audio_fb_target[1]
- if (audio_fb_target[1] <= freq.value) and (freq.value <= audio_fb_target[2]):
- target_ra.set_fc((.3,1.0,.6))
- else:
- target_ra.set_fc((.7, .2, .4))
-
- cursor_ra.set_y(cursor_y)
- target_ra.set_y(target_y)
- target_ra.set_height(target_h)
-
- log.info(f'cursor_y: {cursor_y}, target_y: {target_y}, target_h: {target_h}')
-
-
- return (cursor_ra, target_ra)
-
- ani = FuncAnimation(fig, update_plot, frames=None,
- init_func=init_plot, blit=True, interval=250)
- plt.show()
-
-
- # background1 = fig.canvas.copy_from_bbox(ax.bbox)
- # fig.canvas.draw()
- # ax.draw_artist(cursor_ra)
- # ax.draw_artist(target_ra)
-
- # plt.show()
- # plt.pause(0.01)
- #
- # while True:
- # target_counter = 0
- #
- # while audio_feedback_run.value == 1:
- # # fig.canvas.restore_region(background1)
- #
- #
- #
- # update_plot(cursor_y, target_y, target_h)
- # log.info(f"fr: {freq.value}, pos: {cursor_y}")
- # # ax.draw_artist(cursor_ra)
- # # ax.draw_artist(target_ra)
- # # fig.canvas.blit(ax.bbox)
- #
- # # fig.canvas.update()
- # # fig.canvas.flush_events()
- # fig.canvas.draw()
- #
- # time.sleep(0.1)
- #
- # # time.sleep(1./params.plot.fps)
- # pass
- # time.sleep(0.1)
- def setup():
- audio_fb_freq = Value('d', 0.0) # Normalized audio feedback activity [0, 1]
- audio_fb_target = Array('d', 3) # Target for normalized audio feedback activity [0, 1]. Give upper and lower bound
- audio_feedback_run = Value('i',1) # 0: baseline, 1: stimulus, 2:response
- vfeedback_p = mp.Process(name='vfeedback', target=plot_feedback, args=(audio_feedback_run, audio_fb_freq, audio_fb_target))
- vfeedback_p.daemon = True # kill visualization if main app terminates
- vfeedback_p.start()
- return (audio_fb_freq, audio_fb_target, audio_feedback_run)
- if __name__ == '__main__':
- audio_fb_freq, audio_fb_target, audio_feedback_run = setup()
- audio_fb_target[0] = .5
- audio_fb_target[1] = .4
- audio_fb_target[2] = .6
- while True:
- norm_rate = audio_fb_freq.value
- norm_rate += (np.random.random() - 0.5) * 0.2
- norm_rate = np.maximum(np.minimum(norm_rate, 1), 0)
- audio_fb_freq.value = norm_rate
-
- td = (np.random.random() - 0.5) * 0.2
- audio_fb_target[1] += td
- audio_fb_target[2] += td
-
- if np.random.random() < 0.1:
- audio_feedback_run.value = 1-audio_feedback_run.value
-
- # log.info(f'fr: {audio_fb_freq.value}')
- time.sleep(0.25)
-
|