frame_time.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import pandas as pd
  2. import numpy as np
  3. from view.python_core.utils.pil_helpers import add_string
  4. import logging
  5. class DisplayTimeFormatterFull(object):
  6. def __init__(self, frame_time):
  7. super().__init__()
  8. if frame_time < pd.Timedelta(0):
  9. self.prefix = "-"
  10. frame_time = -frame_time
  11. else:
  12. self.prefix = ""
  13. total_seconds = frame_time.total_seconds()
  14. minutes = int(np.floor(total_seconds / 60))
  15. self.seconds = total_seconds - (minutes * 60)
  16. if minutes > 0:
  17. self.minutes_string = f"{minutes} m "
  18. else:
  19. self.minutes_string = ""
  20. def format(self):
  21. return f"{self.prefix}{self.minutes_string}{self.seconds:6.3f} s"
  22. class DisplayTimeWithoutMS(DisplayTimeFormatterFull):
  23. def __init__(self, frame_time):
  24. super().__init__(frame_time)
  25. def format(self):
  26. return f"{self.prefix}{self.minutes_string}{self.seconds:2.0f} s"
  27. class TimeStringAdderBlank(object):
  28. def __init__(self):
  29. super().__init__()
  30. self.font_size = None
  31. def add(self, pil_image, frame_time):
  32. return pil_image
  33. class TimeStringAdder(TimeStringAdderBlank):
  34. def __init__(self, time_formatter, mv_ygap, right_xgap,
  35. color_for_pil, pulsed_stimuli_handler, font_file, font_size):
  36. super().__init__()
  37. self.time_formatter = time_formatter
  38. self.mv_ygap = mv_ygap
  39. self.right_xgap = right_xgap
  40. self.color_for_pil = color_for_pil
  41. stim_pulse_start_times = pulsed_stimuli_handler.get_pulse_start_times()
  42. if len(stim_pulse_start_times):
  43. self.offset = -stim_pulse_start_times.min()
  44. else:
  45. self.offset = pd.Timedelta(0)
  46. logging.getLogger("VIEW").info("Since no stimulii were specified, first frame of the movie will have a display time of 0")
  47. self.font_file = font_file
  48. self.font_size = font_size
  49. def add(self, pil_image, frame_time):
  50. time_y_pos = pil_image.height - self.mv_ygap + int(0.1 * self.font_size)
  51. frame_time_to_show = frame_time + self.offset
  52. frame_time_string = self.time_formatter(frame_time_to_show).format()
  53. pil_image = add_string(pil_image, text=frame_time_string,
  54. position=(pil_image.width - self.right_xgap, time_y_pos + int(0.25 * self.font_size)),
  55. font_size=self.font_size, fill_color_for_pil=self.color_for_pil,
  56. horizontal_alignment="right", vertical_alignment="top", font_file=self.font_file)
  57. return pil_image
  58. def get_time_string_adder(mv_display_time, mv_suppress_ms, right_xgap, mv_ygap, color_for_pil,
  59. pulsed_stimuli_handler, font_file, font_size):
  60. if mv_suppress_ms:
  61. time_formatter = DisplayTimeWithoutMS
  62. else:
  63. time_formatter = DisplayTimeFormatterFull
  64. if mv_display_time > 0:
  65. return TimeStringAdder(
  66. mv_ygap=mv_ygap, time_formatter=time_formatter,
  67. right_xgap=right_xgap,
  68. color_for_pil=color_for_pil,
  69. pulsed_stimuli_handler=pulsed_stimuli_handler, font_file=font_file,
  70. font_size=font_size)
  71. else:
  72. return TimeStringAdderBlank()