borders_and_annotations.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. from view.python_core.utils.colors import mpl_color_to_PIL
  2. from .mark_stimulus import get_stimulus_marker
  3. from .frame_time import get_time_string_adder
  4. from .static_border import get_static_border_adder_3D
  5. from view.python_core.utils.pil_helpers import numpy_to_pil_image, pil_image_to_numpy
  6. from view.python_core.utils.fonts import resolve_font_file, get_maximum_font_size_by_width
  7. class BordersAndAnnotations(object):
  8. def __init__(self, flags, frame_size, data_sampling_period, pulsed_stimuli_handler,
  9. colormap, fg_color_for_mpl, bg_color_for_mpl):
  10. fg_color_for_pil = mpl_color_to_PIL(fg_color_for_mpl)
  11. bg_color_for_pil = mpl_color_to_PIL(bg_color_for_mpl)
  12. self.data_sampling_period = data_sampling_period
  13. font_name = flags["mv_fontName"]
  14. font_file = resolve_font_file(font_name)
  15. # font size suggestion based on possible time strings and the flag mv_displayTime
  16. time_font_size_suggestion_full = get_maximum_font_size_by_width(
  17. maximum_width=frame_size[0], font_name=font_file, text="00 m 00.000 s")
  18. if flags["mv_displayTime"] > 0:
  19. time_font_size_suggestion = max(int(flags["mv_displayTime"] * time_font_size_suggestion_full), 8)
  20. else:
  21. time_font_size_suggestion = time_font_size_suggestion_full
  22. # initialization of stimulus_marker will provide a suggestion for font size in stimulus_marker.font_size
  23. # if stimulus marker does not use a font, stimulus_marker.font_size will be None
  24. self.stimulus_marker = get_stimulus_marker(
  25. mv_markStimulus=flags["mv_markStimulus"],
  26. left_xgap=flags["mv_xgap"],
  27. mv_ygap=flags["mv_ygap"],
  28. color_for_pil=fg_color_for_pil,
  29. pulsed_stimuli_handler=pulsed_stimuli_handler,
  30. font_file=font_file,
  31. frame_size=frame_size,
  32. )
  33. # make a decision on font size based on time string, considering stimulus string if required
  34. if self.stimulus_marker.font_size is not None:
  35. font_size_suggestion = max(min(time_font_size_suggestion, self.stimulus_marker.font_size), 8)
  36. else:
  37. font_size_suggestion = time_font_size_suggestion
  38. self.stimulus_marker.font_size = font_size_suggestion
  39. self.static_border_adder, revised_right_xgap = get_static_border_adder_3D(
  40. flags=flags,
  41. fg_color_for_mpl=fg_color_for_mpl,
  42. bg_color_for_mpl=bg_color_for_mpl,
  43. colormap=colormap,
  44. frame_size=frame_size,
  45. font_file=font_file,
  46. font_size=font_size_suggestion)
  47. self.time_string_adder = get_time_string_adder(
  48. mv_display_time=flags["mv_displayTime"],
  49. mv_suppress_ms=flags["mv_suppressMilliseconds"],
  50. color_for_pil=fg_color_for_pil,
  51. right_xgap=revised_right_xgap,
  52. mv_ygap=flags["mv_ygap"],
  53. pulsed_stimuli_handler=pulsed_stimuli_handler,
  54. font_file=font_file,
  55. font_size=font_size_suggestion
  56. )
  57. def add(self, frame_data, frame_number, static_frame):
  58. frame_data_with_border = self.static_border_adder.composite(frame_data, static_frame)
  59. frame_time = self.data_sampling_period * (frame_number - 1)
  60. pil_image = numpy_to_pil_image(frame_data_with_border)
  61. pil_image_with_time = self.time_string_adder.add(pil_image, frame_time)
  62. pil_image_with_time_stimulus = self.stimulus_marker.mark(pil_image_with_time, frame_time)
  63. annotated_frame_data = pil_image_to_numpy(pil_image_with_time_stimulus)
  64. return annotated_frame_data