-
Notifications
You must be signed in to change notification settings - Fork 118
(4->3) Add GUI Elements for Interacting With RecordingSession
#1283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
roomrys
wants to merge
68
commits into
liezl/asc-initial-update-instances-across-views
Choose a base branch
from
liezl/add-gui-elements-for-sessions
base: liezl/asc-initial-update-instances-across-views
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
(4->3) Add GUI Elements for Interacting With RecordingSession
#1283
roomrys
wants to merge
68
commits into
liezl/asc-initial-update-instances-across-views
from
liezl/add-gui-elements-for-sessions
+3,070
−444
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…iezl/iuiav-fix-(de)-serialization
…ps://github.com/talmolab/sleap into liezl/iuiav-fix-(de)-serialization
…ps://github.com/talmolab/sleap into liezl/iuiav-fix-(de)-serialization
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## liezl/asc-initial-update-instances-across-views #1283 +/- ##
===================================================================================
+ Coverage 73.99% 74.26% +0.27%
===================================================================================
Files 135 135
Lines 24923 25465 +542
===================================================================================
+ Hits 18441 18912 +471
- Misses 6482 6553 +71 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…elements-for-sessions
…iezl/iuiav-fix-(de)-serialization
…elements-for-sessions
RecordingSessionRecordingSession
…iezl/iuiav-fix-(de)-serialization
…elements-for-sessions
Base automatically changed from
liezl/iuiav-fix-(de)-serialization
to
liezl/asc-initial-update-instances-across-views
September 29, 2023 20:22
RecordingSessionRecordingSession
…ps://github.com/talmolab/sleap into liezl/add-gui-elements-for-sessions
9771ff5 to
2c9ea0c
Compare
* Set the video state to unlinked video state --------- Co-authored-by: roomrys <[email protected]>
* Add TODO comment * Add visual indicator for current camera * Add change to print Camcorder.name * Ensure session state is updated as first callback of video state --------- Co-authored-by: Jvshen <[email protected]> Co-authored-by: Liezl Maree <[email protected]>
* created logics for automatic addition of videos * not display import messages when no videos are found in the directory * Update test_commands.py * deleted unnecessary codes and manual testing worked perfectly * Split up ask and do methods based on GUI interaction * Find video paths using calibration only * Add fixture for calibration directory * Test automatic addition of videos --------- Co-authored-by: roomrys <[email protected]>
* Modify switch_frame function to stay on same frame if video has enough frames * Simplify logic --------- Co-authored-by: roomrys <[email protected]>
* Add id property to RecordingSession * Add small test
…1825) * overrided the activateSelected function for cameras table * video is switched whenever an item in the CamerasTable is double-clicked * Handle case when camera is None --------- Co-authored-by: roomrys <[email protected]>
* Link videos to cameras when add session * Typehinting * Add checks on input argument types * Test CommandContext.linkVideoToSession * Add test to link video to session when add session
* Test that points are always updated if predicted or not visible * Always update points if predicted or not visible
* Move compute_oks function to utils (avoid circular import) * Update InstanceGroup score when update_points * Add score to InstanceGroup repr * Add score to InstanceGroup table * (De)Serialize new score attribute * Add more docs on score attribute * Test score attribute
* Add editing feature for InstanceGroup.name * Add changes for editing feature for InstanceGroup.name * Add changes for editing feature for InstanceGroup.name * Lint * Add minimal test --------- Co-authored-by: roomrys <[email protected]>
* Enforce projection bounds * Test projection_bounds propert of RecordingSession * Test upsert_points method of FrameGroup * Only return bounds for cams_to_include * Expose invisible_as_nan argument to FrameGroup.numpy * Ensure that numpy array is filled with float values in FrameGroup.upsert_points * Add a cached RecordingSession._projection_bounds attribute * Add a tests for the cached projection_bounds * Lint
* Add connect callback to instance group * Add QtInstance instead of InstanceGroup * Add changes for review * Handle case when select is neither Instance, int, nor InstanceGroup --------- Co-authored-by: roomrys <[email protected]>
This problem goes deeper than expected and needs a Pull Request
* Add Color by Instance Group preference saving * Replaced color_by_instance_group with distinctly_color to align with the existing View > Apply Distinct Colors To submenu * Use updated preference for GUI state * Rename GUI facing "instance_groups" to "instance groups" --------- Co-authored-by: roomrys <[email protected]>
Update "instance" state as "frame_idx" callback
4 tasks
* Check if predicted instance is removed that it's not referenced * Add manual test for removing predicted instance * Add comment for develop merge --------- Co-authored-by: Liezl Maree <[email protected]>
* Do not sort keys when loading calibration toml * Test that cameras are loaded in original order
) * Add cv2 * Add undistorted input and implementation for undistorting points * Add undistorted input to FrameGroup numpy * Add undistort to docstring * Change name * Add undistort to docstring * Move numpy test out of InstanceGroup * Add test for undistorted points for Instance_Group numpy method * Move test for FrameGroup numpy as its own test * Add test for undistorted points for FrameGroup numpy method * Remove unrelated tests --------- Co-authored-by: roomrys <[email protected]>
* Add pred_as_nan input to decide whether we want to save predicted values * If pred_as_nan is false we save the predicted values and if true, we set the predictions to NaN * Test triangulate session with `triangulate_predictions` set to `True` and `False` * Add triangulate_predictions input * Add triangulate_predictions to params * Test triangulateSession command with triangulate_predictions set to True and False * change capitalization --------- Co-authored-by: Liezl Maree <[email protected]>
* Allow general iou threshold for pre culling * Add pre_cull_iou_threshold to sleap-track * Document pre_cull_general_iou_threshold * Set default values for previously positional args * Sort imports * Test cull_frame_instances * Pass in the arguments we want to test with * Refactor cull_frame_instances * Test integration with make_tracker_by_name * Update docstrings and add typehinting * Comment nms_fast * Re-order/factor nms_fast * Test CLI integration * Fix bug in logic where bool(0.0) == False * Type hint and doc string
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This is a pretty large PR that aims to do a few high-level GUI tasks:
SessionsDock(for all/mostRecordingSession-related GUI items)RecordingSessions table toSessionsDock#1654 (@vaibhavtrip29)CamerasTabletoSessionsDock#1671 (@AdvaithRavishankar)UnlinkedVideosTabletoSessionsDock#1720 (@7174Andy)Instanceto anInstanceGroup#1747 (@ramizhajj1)InstanceGroupoption #1760 (@7174Andy)See the subsections below for more detailed mini-tasks:
Add SesssionsDock
SessionsDockwhich has a button for triangulation (and checkbox for auto-triangulation)SessionsDockto GUIGuiStateforauto_triangulate == True)Allow navigate between views
Alt+VandAlt+Shift+Vand store in shortcuts.yamlOnly update "incomplete" nodes
Add
RecordingSessiontable toSessionsDock(#1654)The overall goal here is to add a new table to the
SessionsDockthat displays allRecordingSessions in theSessionsDock.main_window.label.sessions: List[RecordingSession]list. The widget should be a table that displays theRecordingSessions hash (eventually name), number ofRecordingSession.cameras: List[Camcorder], and number ofRecordingSession.videos: List[Video](see Figure 1). ThisSessionsTablewill be used to dynamically populate ourCamerasTablelater on.GenericTableModelto create a new model calledSessionsTableModelwith the class attributeproperties = ("id", "videos", "cameras")(similar toVideosTableModel)SessionsTableModel.item_to_data(self, obj: List[RecordingSession], item: RecordingSession)which returns the following dictionary:{id: item.__hash__(), videos: len(item.videos), cameras: len(item.cameras)}(similar toVideosTableModel.item_to_data)sessions_model_type = SessionsTableModelattribute toSessionsDock(similar toSkeletonDock.nodes_model_type) and pass into themodel_typelist forsuper().__init__SessionsDock.create_modelsmethod (or append to it if it already exists) that sets aSessionsDock.sessions_model = SessionsDock.sessions_model_type(items=main_window.state["labels"].sessions, context=main_window.commands)and returns a list of all models created (seeSkeletonDock.create_models)SessionsDock.create_tablesmethod (or append to it if it already exists) that sets aSessionsDock.sessions_table = GenericTableView(state=..., row_name="session", ...)and returns a list of all tables created (seeSkeletonDock.create_tables)RecordingSessionSessionsDock.lay_everything_outmethod, add theSessionsDock.sessions_tableto theSessionsDock.wgt_layout: QVBoxLayout(see theInstancesDock.lay_everything_out).sessionsoption toUpdateTopic: EnumMainWindow.on_data_updateadd (or append to) theif _has_topic(UpdateTopic.sessions)that updates the items to display in theSessionsTable(seevideo_dock.tableupdate)Test the
SessionsTableTests for the
SessionsTablewill be added totests/gui/test_dataviews.py.RecordingSessionis returned when we select a specific row of the table (see existing test for inspiration)RecordingSessioninlabels.sessions, theRecordingSessionin the table is updated as wellTest the
SessionsTableas part of theSessionsDockTests for the
SessionsDockwill be added totests/gui/widgets/test_docks.py.GuiState(see existing test)Figure 1: Depiction of all tables to add, including
SessionsTable,CamerasTable, andUnlinkedVideosTable.Add
CamerasTabletoSessionsDockThe overall goal is to add
Camcorder/Videoassignment table to theSessionsDockthat is linked to theSessionsTablecreated above. ThisCamerasTablewill have two columns. One column will display theCamcorder.names of allCamcorders in theRecordingSession.cameras: List[Camcorder]list. The second column will show whichVideos are assigned to the adjacentCamcorder.nameby displaying the returned value ofRecordingSession.get_video(Camcorder)(or""ifNone).GenericTableModelto create a new model calledCamerasTableModelwithproperties = ("camera", "video")CamerasTableModel.object_to_items(self, obj: RecordingSession)which returns the list ofCamcorders inobj.cameras: List[Camcorder]CamerasTableModel.item_to_data(self, obj: RecordingSession, item: Camcorder)which returns the following dictionary:{camera: item.name, video: obj.get_video(item)}cameras_model_type = CamerasTableModelattribute toSessionsDock(similar toSkeletonDock.nodes_model_type) and pass into themodel_typelist forsuper().__init__SessionsDock.create_modelsmethod (or append to it if it already exists) that sets aSessionsDock.cameras_model = SessionsDock.sessions_model_type(items=main_window.state["selected_session"], context=main_window.commands)and returns a list of all models created (seeSkeletonDock.create_models)SessionsDock.create_tablesmethod (or append to it if it already exists) that sets aSessionsDock.cameras_table = GenericTableView(state=..., row_name="camera", ...)and returns a list of all tables created (seeSkeletonDock.create_tables)CommandContext.unlink_video_from_cameramethod to un-link aVideofrom aCamcorderCommandContext.unlink_video_from_cameramethodCamcorderfor theCamerasTableSessionsDock.lay_everything_outmethod, add theSessionsDock.cameras_tableto theSessionsDock.wgt_layout: QVBoxLayout(see theInstancesDock.lay_everything_out).sessionsoption toUpdateTopic: Enumif not already thereMainWindow.on_data_updateadd (or append to) theif _has_topic(UpdateTopic.sessions)that updates the items to display in theCamerasTable(seevideo_dock.tableupdate)Test the
CamerasTableTests for the
CamerasTablewill be added totests/gui/test_dataviews.py. These tests will only test the functionality of the table as it's own entity.Camcorderis returned when we select a specific row of the table (see existing test for inspiration)Camcorderinlabels.sessions, theCamcorderin the table is updated as wellTest the
CamerasTableas part of theSessionsDockTests for the
SessionsDockwill be added totests/gui/widgets/test_docks.py.GuiState(see existing test)Add
UnlinkedVideosTabletoSessionsDockVery similar steps to
SessionsTableandCamerasTable(to be filled in), except for these few items:{linked: ..., unlinked: ...}toLabelsDataCachethat remembers which videos are linked/unlinked to aRecordingSessioninlabels.sessions(this dictionary will be used for the items in theUnlinkedVideosTable)CommandContext.link_video_to_cameramethod to link aVideoto aRecordingSessionCommandContextmethod created above)Assign
Instanceto anInstanceGroup(waiting on 3a-3f to be merged)sessionsMenunamed "Sessions" (similar to thetracksMenu)self.inst_groups_menuattribute to theMainWindowthat adds a menu to thesessionsMenucalled "Set Instance Group" (similar toself.track_menu)self.inst_groups_menuwhenhas_selected_instance == True(similar toself.track_menu)MainWindow._update_sessions_menumethod that takes inselfandframe_idx, then retrieves thesession: Optional[RecordingSession] = self.state["session"]and theframe_group: FrameGroup = session.frame_groups[frame_idx]. First clear theself.inst_groups_menu. Then, enumerate through allinstance_groupsinframe_group.instance_groups: List[InstanceGroup]. For the first 9InstanceGroups use thekey_command = Qt.SHIFT + Qt.Key_0 + inst_group_ind + 1(otherwise use a defaultkey_command = ""). For allinstance_groups, add aself.inst_groups_menuaction with nameinstance_group.name, callbacklambda x=instance_group: self.commands.setInstanceGroup(x), and shortcut ofkey_command. Outside the enumeration, add a"New Instance Group"action to theself.inst_groups_menuwith name"New Instance Group", callbackself.commands.addInstanceGroup, and hotkeyQt.SHIFT + Qt.Key_0. Very similar toMainWindow._update_track_menu.CommandContext.setInstanceGroup(self, instance_group: Optional[InstanceGroup])method that executes theSetSelectedInstanceGroupclass with inputinstance_group=instance_group(seeCommandContext.setInstanceTrack).CommandContext.addInstanceGroup(self)method that executes theAddInstanceGroupclass (seeCommandContext.addTrack).sleap/gui/commands.pyadd aSetSelectedInstanceGroupclass that subclassesEditCommand. Add aSetSelectedInstanceGroup.do_action(context, params)staticmethod that first retrieves theselected_instance = context.state[selected_instance],frame_idx: int = context.state["frame_idx"],video: Video = context.state["video"],session: RecordingSession = context.state["session"],frame_group: FrameGroup = session.frame_groups.get(frame_idx, None), andcamera = session.get_camera(video=video). You will need to useframe_group = session.new_frame_group(frame_idx=frame_idx)ifframe_group is None. Then, useframe_group.add_instance(instance=selected_instance, camera=camera, instance_group=instance_group)to add theselected_instanceto theinstance_group(andframe_group). Similar to theSetSelectedInstanceTrackclass.sleap/gui/commands.pyadd aAddInstanceGroupclass that subclassesEditCommand. Add aAddInstanceGroup.do_action(context, params)staticmethod that first retrieves theframe_idx: int = context.state["frame_idx"],session: RecordingSession = context.state["session"], andframe_group: FrameGroup = session.frame_groups[frame_idx]. Then, useframe_group.add_instance_group(instance_group=None)to create and add a new emptyInstanceGroupto theframe_group. Similar to theAddTrackclass.Using the workflow above (but with less detailed write-up), please also:
Figure 2: GUI elements for assigning
Instances toInstanceGroups will be similar to how we assignInstances toTracks.Types of changes
Does this address any currently open issues?
[list open issues here]
Outside contributors checklist
Thank you for contributing to SLEAP!
❤️