event_window

This module defines the EventWindow class, a tkinter Toplevel window used to display timestamps and other details for experiment event data (licks, motor movments) in a table format using a ttk.Treeview element.

  1"""
  2This module defines the EventWindow class, a tkinter Toplevel window used to display timestamps
  3and other details for experiment event data (licks, motor movments) in a table format using a ttk.Treeview element.
  4"""
  5
  6import tkinter as tk
  7from tkinter import ttk
  8
  9#### USED FOR TYPE HINTS ####
 10from models.event_data import EventData
 11#### USED FOR TYPE HINTS ####
 12
 13from views.gui_common import GUIUtils
 14
 15
 16class EventWindow(tk.Toplevel):
 17    """
 18    This class represents a Toplevel window that displays experiment event data using a ttk.Treeview widget.
 19    It pulls in data from an `models.event_data` `EventData` instance and is updated as new events occur.
 20    After creation, window is hidden and can be shown using the `show`() method.
 21
 22    Attributes
 23    ----------
 24    - **event_data** (*EventData*): A reference to the data model instance (`models.event_data.EventData`)
 25      that holds the event DataFrame containing the data to be displayed.
 26    - **last_item** (*int*): Tracks the index of the last row added from the DataFrame to the Treeview.
 27      This is used to efficiently update the table by only adding new rows.
 28    - **licks_frame** (*tk.Frame*): The main tkinter Frame widget within the window that contains the Treeview table.
 29    - **timestamped_events** (*ttk.Treeview*): The Treeview widget used to display the event data in a table format.
 30
 31    Methods
 32    -------
 33    - `show`()
 34        Updates the table with the latest data from the `event_data` model and makes the window visible (deiconifies it).
 35    - `update_table`()
 36        Efficiently adds new rows from the event DataFrame (held by `event_data`) to the Treeview display. It only adds rows
 37        that haven't been added previously, based on the `last_item` attribute.
 38    - `build_table`()
 39        Creates the main frame (`licks_frame`) and the `ttk.Treeview` widget (`timestamped_events`). Configures the Treeview columns
 40        and headings based on the columns present in the `event_data.event_dataframe`.
 41    """
 42
 43    # inject the event dataframe when we create the class so we have access to that data
 44    def __init__(self, event_data: EventData) -> None:
 45        """
 46        Initialize the EventWindow. Sets up the window title, icon, key bindings (Ctrl+W to hide),
 47        and the close protocol (also hides the window). It builds the table structure and initially
 48        hides the window using `withdraw()`.
 49
 50        Parameters
 51        ----------
 52        - **event_data** (*EventData*): An instance of the `models.event_data.EventData` model containing the
 53          event DataFrame to be displayed.
 54        """
 55        super().__init__()
 56        # reference to event model
 57        self.event_data = event_data
 58
 59        self.title("Experiment Event Data")
 60        self.bind("<Control-w>", lambda event: self.withdraw())
 61
 62        # Bind closing the window to self.withdraw() to hide the window but not destroy it
 63        self.protocol("WM_DELETE_WINDOW", lambda: self.withdraw())
 64
 65        window_icon_path = GUIUtils.get_window_icon_path()
 66        GUIUtils.set_program_icon(self, icon_path=window_icon_path)
 67
 68        # init last_item in the table to zero we haven't added anything into the table
 69        # this is used to efficiently update the table when program is running
 70        self.last_item = 0
 71
 72        self.build_table()
 73
 74        self.withdraw()
 75
 76    def show(self):
 77        """
 78        Updates the table with the latest event data and makes the window visible.
 79        Calls `update_table()` first, then `deiconify()` to show the window.
 80        """
 81        self.update_table()
 82        self.deiconify()
 83
 84    def update_table(self):
 85        """
 86        Updates the Treeview widget by adding only the new rows from the event DataFrame
 87        since the last update. It uses `self.last_item` to determine the starting index
 88        for adding new rows, ensuring efficient updates without reprocessing existing entries.
 89        """
 90        # df we are working with is self.event_data.event_dataframe, get rid of self prefix and such to save room
 91        df = self.event_data.event_dataframe
 92        # num rows in that df currently
 93        len_event_df = len(df)
 94
 95        last_item = self.last_item
 96
 97        # Insert data from the DataFrame. iterrows() returns an iterator over the rows of a df of form (index, series (of data))
 98        for i in range(last_item, len_event_df):
 99            row_content = df.iloc[i]
100
101            item_iid = f"item {i}"
102
103            self.timestamped_events.insert(
104                "", tk.END, iid=item_iid, values=list(row_content)
105            )
106        # update the last item with the LAST item that was added on this iteration, next time we will start
107        # the loop with this, so that we don't unneccesarily update entries already there
108        self.last_item = len(df)
109
110    def build_table(self) -> None:
111        """
112        Creates the main frame (`licks_frame`) and the `ttk.Treeview` widget (`timestamped_events`)
113        used to display the event data. Configures the Treeview columns and headings based on the
114        columns present in the `event_data.event_dataframe`. Calls `update_table()` to initially
115        populate the table.
116        """
117        self.licks_frame = tk.Frame(self)
118        self.licks_frame.grid(row=0, column=0, sticky="nsew")
119
120        # Create a Treeview widget
121        # show='headings' ensures we only see columns with headings defined
122        self.timestamped_events = ttk.Treeview(
123            self.licks_frame, show="headings", height=25
124        )
125
126        self.timestamped_events["columns"] = list(
127            self.event_data.event_dataframe.columns
128        )
129
130        # Configure the names of the colums to reflect the heaader labels
131        for col in self.timestamped_events["columns"]:
132            self.timestamped_events.heading(col, text=col)
133
134        self.update_table()
135
136        self.timestamped_events.pack(fill="both", expand=True)
class EventWindow(tkinter.Toplevel):
 17class EventWindow(tk.Toplevel):
 18    """
 19    This class represents a Toplevel window that displays experiment event data using a ttk.Treeview widget.
 20    It pulls in data from an `models.event_data` `EventData` instance and is updated as new events occur.
 21    After creation, window is hidden and can be shown using the `show`() method.
 22
 23    Attributes
 24    ----------
 25    - **event_data** (*EventData*): A reference to the data model instance (`models.event_data.EventData`)
 26      that holds the event DataFrame containing the data to be displayed.
 27    - **last_item** (*int*): Tracks the index of the last row added from the DataFrame to the Treeview.
 28      This is used to efficiently update the table by only adding new rows.
 29    - **licks_frame** (*tk.Frame*): The main tkinter Frame widget within the window that contains the Treeview table.
 30    - **timestamped_events** (*ttk.Treeview*): The Treeview widget used to display the event data in a table format.
 31
 32    Methods
 33    -------
 34    - `show`()
 35        Updates the table with the latest data from the `event_data` model and makes the window visible (deiconifies it).
 36    - `update_table`()
 37        Efficiently adds new rows from the event DataFrame (held by `event_data`) to the Treeview display. It only adds rows
 38        that haven't been added previously, based on the `last_item` attribute.
 39    - `build_table`()
 40        Creates the main frame (`licks_frame`) and the `ttk.Treeview` widget (`timestamped_events`). Configures the Treeview columns
 41        and headings based on the columns present in the `event_data.event_dataframe`.
 42    """
 43
 44    # inject the event dataframe when we create the class so we have access to that data
 45    def __init__(self, event_data: EventData) -> None:
 46        """
 47        Initialize the EventWindow. Sets up the window title, icon, key bindings (Ctrl+W to hide),
 48        and the close protocol (also hides the window). It builds the table structure and initially
 49        hides the window using `withdraw()`.
 50
 51        Parameters
 52        ----------
 53        - **event_data** (*EventData*): An instance of the `models.event_data.EventData` model containing the
 54          event DataFrame to be displayed.
 55        """
 56        super().__init__()
 57        # reference to event model
 58        self.event_data = event_data
 59
 60        self.title("Experiment Event Data")
 61        self.bind("<Control-w>", lambda event: self.withdraw())
 62
 63        # Bind closing the window to self.withdraw() to hide the window but not destroy it
 64        self.protocol("WM_DELETE_WINDOW", lambda: self.withdraw())
 65
 66        window_icon_path = GUIUtils.get_window_icon_path()
 67        GUIUtils.set_program_icon(self, icon_path=window_icon_path)
 68
 69        # init last_item in the table to zero we haven't added anything into the table
 70        # this is used to efficiently update the table when program is running
 71        self.last_item = 0
 72
 73        self.build_table()
 74
 75        self.withdraw()
 76
 77    def show(self):
 78        """
 79        Updates the table with the latest event data and makes the window visible.
 80        Calls `update_table()` first, then `deiconify()` to show the window.
 81        """
 82        self.update_table()
 83        self.deiconify()
 84
 85    def update_table(self):
 86        """
 87        Updates the Treeview widget by adding only the new rows from the event DataFrame
 88        since the last update. It uses `self.last_item` to determine the starting index
 89        for adding new rows, ensuring efficient updates without reprocessing existing entries.
 90        """
 91        # df we are working with is self.event_data.event_dataframe, get rid of self prefix and such to save room
 92        df = self.event_data.event_dataframe
 93        # num rows in that df currently
 94        len_event_df = len(df)
 95
 96        last_item = self.last_item
 97
 98        # Insert data from the DataFrame. iterrows() returns an iterator over the rows of a df of form (index, series (of data))
 99        for i in range(last_item, len_event_df):
100            row_content = df.iloc[i]
101
102            item_iid = f"item {i}"
103
104            self.timestamped_events.insert(
105                "", tk.END, iid=item_iid, values=list(row_content)
106            )
107        # update the last item with the LAST item that was added on this iteration, next time we will start
108        # the loop with this, so that we don't unneccesarily update entries already there
109        self.last_item = len(df)
110
111    def build_table(self) -> None:
112        """
113        Creates the main frame (`licks_frame`) and the `ttk.Treeview` widget (`timestamped_events`)
114        used to display the event data. Configures the Treeview columns and headings based on the
115        columns present in the `event_data.event_dataframe`. Calls `update_table()` to initially
116        populate the table.
117        """
118        self.licks_frame = tk.Frame(self)
119        self.licks_frame.grid(row=0, column=0, sticky="nsew")
120
121        # Create a Treeview widget
122        # show='headings' ensures we only see columns with headings defined
123        self.timestamped_events = ttk.Treeview(
124            self.licks_frame, show="headings", height=25
125        )
126
127        self.timestamped_events["columns"] = list(
128            self.event_data.event_dataframe.columns
129        )
130
131        # Configure the names of the colums to reflect the heaader labels
132        for col in self.timestamped_events["columns"]:
133            self.timestamped_events.heading(col, text=col)
134
135        self.update_table()
136
137        self.timestamped_events.pack(fill="both", expand=True)

This class represents a Toplevel window that displays experiment event data using a ttk.Treeview widget. It pulls in data from an models.event_data EventData instance and is updated as new events occur. After creation, window is hidden and can be shown using the show() method.

Attributes

  • event_data (EventData): A reference to the data model instance (models.event_data.EventData) that holds the event DataFrame containing the data to be displayed.
  • last_item (int): Tracks the index of the last row added from the DataFrame to the Treeview. This is used to efficiently update the table by only adding new rows.
  • licks_frame (tk.Frame): The main tkinter Frame widget within the window that contains the Treeview table.
  • timestamped_events (ttk.Treeview): The Treeview widget used to display the event data in a table format.

Methods

  • show() Updates the table with the latest data from the event_data model and makes the window visible (deiconifies it).
  • update_table() Efficiently adds new rows from the event DataFrame (held by event_data) to the Treeview display. It only adds rows that haven't been added previously, based on the last_item attribute.
  • build_table() Creates the main frame (licks_frame) and the ttk.Treeview widget (timestamped_events). Configures the Treeview columns and headings based on the columns present in the event_data.event_dataframe.
EventWindow(event_data: models.event_data.EventData)
45    def __init__(self, event_data: EventData) -> None:
46        """
47        Initialize the EventWindow. Sets up the window title, icon, key bindings (Ctrl+W to hide),
48        and the close protocol (also hides the window). It builds the table structure and initially
49        hides the window using `withdraw()`.
50
51        Parameters
52        ----------
53        - **event_data** (*EventData*): An instance of the `models.event_data.EventData` model containing the
54          event DataFrame to be displayed.
55        """
56        super().__init__()
57        # reference to event model
58        self.event_data = event_data
59
60        self.title("Experiment Event Data")
61        self.bind("<Control-w>", lambda event: self.withdraw())
62
63        # Bind closing the window to self.withdraw() to hide the window but not destroy it
64        self.protocol("WM_DELETE_WINDOW", lambda: self.withdraw())
65
66        window_icon_path = GUIUtils.get_window_icon_path()
67        GUIUtils.set_program_icon(self, icon_path=window_icon_path)
68
69        # init last_item in the table to zero we haven't added anything into the table
70        # this is used to efficiently update the table when program is running
71        self.last_item = 0
72
73        self.build_table()
74
75        self.withdraw()

Initialize the EventWindow. Sets up the window title, icon, key bindings (Ctrl+W to hide), and the close protocol (also hides the window). It builds the table structure and initially hides the window using withdraw().

Parameters

  • event_data (EventData): An instance of the models.event_data.EventData model containing the event DataFrame to be displayed.
event_data
last_item
def show(self):
77    def show(self):
78        """
79        Updates the table with the latest event data and makes the window visible.
80        Calls `update_table()` first, then `deiconify()` to show the window.
81        """
82        self.update_table()
83        self.deiconify()

Updates the table with the latest event data and makes the window visible. Calls update_table() first, then deiconify() to show the window.

def update_table(self):
 85    def update_table(self):
 86        """
 87        Updates the Treeview widget by adding only the new rows from the event DataFrame
 88        since the last update. It uses `self.last_item` to determine the starting index
 89        for adding new rows, ensuring efficient updates without reprocessing existing entries.
 90        """
 91        # df we are working with is self.event_data.event_dataframe, get rid of self prefix and such to save room
 92        df = self.event_data.event_dataframe
 93        # num rows in that df currently
 94        len_event_df = len(df)
 95
 96        last_item = self.last_item
 97
 98        # Insert data from the DataFrame. iterrows() returns an iterator over the rows of a df of form (index, series (of data))
 99        for i in range(last_item, len_event_df):
100            row_content = df.iloc[i]
101
102            item_iid = f"item {i}"
103
104            self.timestamped_events.insert(
105                "", tk.END, iid=item_iid, values=list(row_content)
106            )
107        # update the last item with the LAST item that was added on this iteration, next time we will start
108        # the loop with this, so that we don't unneccesarily update entries already there
109        self.last_item = len(df)

Updates the Treeview widget by adding only the new rows from the event DataFrame since the last update. It uses self.last_item to determine the starting index for adding new rows, ensuring efficient updates without reprocessing existing entries.

def build_table(self) -> None:
111    def build_table(self) -> None:
112        """
113        Creates the main frame (`licks_frame`) and the `ttk.Treeview` widget (`timestamped_events`)
114        used to display the event data. Configures the Treeview columns and headings based on the
115        columns present in the `event_data.event_dataframe`. Calls `update_table()` to initially
116        populate the table.
117        """
118        self.licks_frame = tk.Frame(self)
119        self.licks_frame.grid(row=0, column=0, sticky="nsew")
120
121        # Create a Treeview widget
122        # show='headings' ensures we only see columns with headings defined
123        self.timestamped_events = ttk.Treeview(
124            self.licks_frame, show="headings", height=25
125        )
126
127        self.timestamped_events["columns"] = list(
128            self.event_data.event_dataframe.columns
129        )
130
131        # Configure the names of the colums to reflect the heaader labels
132        for col in self.timestamped_events["columns"]:
133            self.timestamped_events.heading(col, text=col)
134
135        self.update_table()
136
137        self.timestamped_events.pack(fill="both", expand=True)

Creates the main frame (licks_frame) and the ttk.Treeview widget (timestamped_events) used to display the event data. Configures the Treeview columns and headings based on the columns present in the event_data.event_dataframe. Calls update_table() to initially populate the table.