mainWindow.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import time
  2. import queue
  3. import tkinter as tk
  4. import numpy as np
  5. from gui.popup import CalibrationPopUp
  6. from gui.graph import Graph
  7. from gui.logScreen import LogScreen
  8. import logHandler
  9. class MainWindow(tk.Frame):
  10. def __init__(self, root, conf, ac_sensor, opt_sensor):
  11. self.root = root
  12. self.conf = conf
  13. self.ac_sensor = ac_sensor
  14. self.opt_sensor = opt_sensor
  15. self.log_handler = logHandler.get_log_handler()
  16. self.popup_window = None
  17. self.log_window = None
  18. tk.Frame.__init__(self, root)
  19. # data plot at left side
  20. self.graph = Graph(self)
  21. self.graph.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
  22. # frame at right side
  23. self.controls = tk.Frame(self, borderwidth=4)
  24. self.controls.pack(fill=tk.BOTH, side=tk.RIGHT)
  25. self.controlsUpdateTime = 0
  26. self.ac_dro_val_sums = np.ndarray((4), dtype=np.float)
  27. self.ac_dro_val_count = 0
  28. self.ac_dro_x = tk.StringVar()
  29. self.ac_dro_y = tk.StringVar()
  30. self.ac_dro_t1 = tk.StringVar()
  31. self.ac_dro_t2 = tk.StringVar()
  32. self.ac_label = tk.Label(self.controls, text="Acoustic Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  33. self.ac_label.pack(side="top", fill="both", expand=False)
  34. tk.Label(self.controls, textvariable=self.ac_dro_x, anchor="nw").pack(side="top", fill="both", expand=False)
  35. tk.Label(self.controls, textvariable=self.ac_dro_y, anchor="nw").pack(side="top", fill="both", expand=False)
  36. tk.Label(self.controls, textvariable=self.ac_dro_t1, anchor="nw").pack(side="top", fill="both", expand=False)
  37. tk.Label(self.controls, textvariable=self.ac_dro_t2, anchor="nw").pack(side="top", fill="both", expand=False)
  38. self.opt_dro_val_sums = np.ndarray((4), dtype=np.float)
  39. self.opt_dro_val_count = 0
  40. self.opt_dro_x = tk.StringVar()
  41. self.opt_dro_y = tk.StringVar()
  42. self.opt_dro_offset = tk.StringVar()
  43. self.opt_dro_size = tk.StringVar()
  44. self.opt_label = tk.Label(self.controls, text="Optical Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  45. self.opt_label.pack(side="top", fill="both", expand=False)
  46. tk.Label(self.controls, textvariable=self.opt_dro_x, anchor="nw").pack(side="top", fill="both", expand=False)
  47. tk.Label(self.controls, textvariable=self.opt_dro_y, anchor="nw").pack(side="top", fill="both", expand=False)
  48. tk.Label(self.controls, textvariable=self.opt_dro_offset, anchor="nw").pack(side="top", fill="both", expand=False)
  49. tk.Label(self.controls, textvariable=self.opt_dro_size, anchor="nw").pack(side="top", fill="both", expand=False)
  50. quit_button = tk.Button(self.controls, text="Quit", command=self.root.destroy, height=2, foreground="red")
  51. quit_button.pack(side="bottom", fill="both")
  52. calibrate_button = tk.Button(self.controls, text="Calibrate AC", command=self.calibrate_ac, height=4)
  53. calibrate_button.pack(side="bottom", fill="both")
  54. clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=4)
  55. clear_button.pack(side="bottom", fill="both")
  56. logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=4)
  57. logscreen_button.pack(side="bottom", fill="both")
  58. def update(self):
  59. if not self.root.winfo_exists():
  60. return
  61. ac_positions = []
  62. # aggregate measurements
  63. while self.ac_sensor.queue.qsize() > 0:
  64. name, data = self.ac_sensor.queue.get()
  65. if name == "data":
  66. ac_positions.append(data[0:2])
  67. self.ac_dro_val_sums += data
  68. self.ac_dro_val_count += 1
  69. opt_positions = []
  70. while self.opt_sensor.queue.qsize() > 0:
  71. name, data = self.opt_sensor.queue.get()
  72. if name == "data":
  73. opt_positions.append(data[0:2])
  74. self.opt_dro_val_sums += data
  75. self.opt_dro_val_count += 1
  76. # graph shows all values as a line
  77. self.graph.update([ac_positions, opt_positions])
  78. # update status color
  79. if self.ac_sensor.dummyActive:
  80. self.ac_label.config(fg="white", bg="red")
  81. elif len(ac_positions) > 0:
  82. self.ac_label.config(fg="white", bg="green")
  83. else:
  84. self.ac_label.config(fg="black", bg="yellow")
  85. if not self.opt_sensor.success:
  86. self.opt_label.config(fg="white", bg="red")
  87. elif len(opt_positions) > 0:
  88. self.opt_label.config(fg="white", bg="green")
  89. else:
  90. self.opt_label.config(fg="black", bg="yellow")
  91. # readouts will only be updated so often
  92. if self.controlsUpdateTime + 0.4 < time.time():
  93. self.controlsUpdateTime = time.time()
  94. # they display the average of all values
  95. if self.ac_dro_val_count > 0:
  96. self.ac_dro_val_sums /= self.ac_dro_val_count
  97. else:
  98. self.ac_dro_val_sums.fill(0)
  99. self.ac_dro_x.set("X: {:.1f} mm".format(self.ac_dro_val_sums[0]))
  100. self.ac_dro_y.set("Y: {:.1f} mm".format(self.ac_dro_val_sums[1]))
  101. self.ac_dro_t1.set("t1: {:.3f} ms".format(self.ac_dro_val_sums[2]/1000))
  102. self.ac_dro_t2.set("t2: {:.3f} ms".format(self.ac_dro_val_sums[3]/1000))
  103. self.ac_dro_val_sums.fill(0)
  104. self.ac_dro_val_count = 0
  105. if self.opt_dro_val_count > 0:
  106. self.opt_dro_val_sums /= self.opt_dro_val_count
  107. else:
  108. self.opt_dro_val_sums.fill(0)
  109. self.opt_dro_x.set("X: {:.1f} mm".format(self.opt_dro_val_sums[0]))
  110. self.opt_dro_y.set("Y: {:.1f} mm".format(self.opt_dro_val_sums[1]))
  111. self.opt_dro_offset.set("offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100))
  112. self.opt_dro_size.set("size: {:.1f} %".format(self.opt_dro_val_sums[3]*100))
  113. self.opt_dro_val_sums.fill(0)
  114. self.opt_dro_val_count = 0
  115. if self.popup_window:
  116. self.popup_window.update()
  117. if self.log_window:
  118. self.log_window.update()
  119. self.root.after(30, self.update)
  120. def calibrate_ac(self):
  121. self.ac_sensor.start_calibration()
  122. if not self.popup_window or not self.pu_root.winfo_exists():
  123. # create new window
  124. self.pu_root = tk.Toplevel(self.root)
  125. self.pu_root.wm_transient(self.root)
  126. self.pu_root.wm_title("Acoustic Sensor Calibration")
  127. # make it centered
  128. x = (self.pu_root.winfo_screenwidth() - 500) / 2
  129. y = (self.pu_root.winfo_screenheight() - 200) / 2
  130. self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}')
  131. # deactivate mainWindow
  132. self.pu_root.grab_set()
  133. self.popup_window = CalibrationPopUp(self.pu_root, self.ac_sensor.calibration_state, self.conf)
  134. self.popup_window.pack(side="top", fill="both", expand=True)
  135. def open_log(self):
  136. #create new window
  137. self.log_root = tk.Toplevel(self.root)
  138. self.log_root.wm_transient(self.root)
  139. self.log_root.wm_title("Logs")
  140. #center
  141. x = (self.log_root.winfo_screenwidth() - 780) / 2
  142. y = (self.log_root.winfo_screenheight() - 400) / 2
  143. self.log_root.geometry(f'780x400+{int(x)}+{int(y)}')
  144. # deactivate mainWindow
  145. self.log_root.grab_set()
  146. self.log_window = LogScreen(self.log_root)
  147. self.log_window.pack(side="top", fill="both", expand=True)