From 3bc5fd5c6a4cc302c90d6ed96c1193e10271caa1 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Thu, 21 Nov 2024 12:31:39 -0500 Subject: [PATCH 01/26] add a new message for image metadata --- ros/angel_msgs/CMakeLists.txt | 1 + ros/angel_msgs/msg/ImageMetadata.msg | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 ros/angel_msgs/msg/ImageMetadata.msg diff --git a/ros/angel_msgs/CMakeLists.txt b/ros/angel_msgs/CMakeLists.txt index 692667a4e..eb5c103d9 100644 --- a/ros/angel_msgs/CMakeLists.txt +++ b/ros/angel_msgs/CMakeLists.txt @@ -34,6 +34,7 @@ set( message_files msg/HandJointPosesUpdate.msg msg/HeadsetAudioData.msg msg/HeadsetPoseData.msg + msg/ImageMetadata.msg msg/InterpretedAudioUserIntent.msg msg/InterpretedAudioUserEmotion.msg msg/JointKeypoints.msg diff --git a/ros/angel_msgs/msg/ImageMetadata.msg b/ros/angel_msgs/msg/ImageMetadata.msg new file mode 100644 index 000000000..12e2a940d --- /dev/null +++ b/ros/angel_msgs/msg/ImageMetadata.msg @@ -0,0 +1,13 @@ +# +# An image metadata message +# + +# Header should represent when this message was published not the image. +std_msgs/Header header + +# Timestamp of when the image was created. +builtin_interfaces/Time image_source_stamp + +# pixel size of the image +uint32 height +uint32 width From 8d67026502355da0a09e7dcf510a09ea4defad2c Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Thu, 21 Nov 2024 12:32:27 -0500 Subject: [PATCH 02/26] use new message in image_metadata_relay.py --- .../data_publishers/image_metadata_relay.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ros/angel_system_nodes/angel_system_nodes/data_publishers/image_metadata_relay.py b/ros/angel_system_nodes/angel_system_nodes/data_publishers/image_metadata_relay.py index 72fcec7f3..b16972cf9 100644 --- a/ros/angel_system_nodes/angel_system_nodes/data_publishers/image_metadata_relay.py +++ b/ros/angel_system_nodes/angel_system_nodes/data_publishers/image_metadata_relay.py @@ -5,10 +5,11 @@ from rclpy.callback_groups import MutuallyExclusiveCallbackGroup from rclpy.node import Node -from sensor_msgs.msg import Image, CameraInfo +from sensor_msgs.msg import Image from angel_utils import declare_and_get_parameters, RateTracker from angel_utils import make_default_main +from angel_msgs.msg import ImageMetadata PARAM_INPUT_TOPIC = "image_topic" @@ -37,22 +38,24 @@ def __init__(self): callback_group=MutuallyExclusiveCallbackGroup(), ) self._pub = self.create_publisher( - CameraInfo, + ImageMetadata, param_values[PARAM_OUTPUT_TOPIC], 1, callback_group=MutuallyExclusiveCallbackGroup(), ) def input_callback(self, msg: Image) -> None: - new_msg = CameraInfo() - new_msg.header = msg.header + new_msg = ImageMetadata() + new_msg.image_source_stamp = msg.header.stamp new_msg.height = msg.height new_msg.width = msg.width + new_msg.header.stamp = self.get_clock().now().to_msg() self._pub.publish(new_msg) self._rate_tracker.tick() self.get_logger().info( - f"[input_callback] CameraInfo message with TS={msg.header.stamp}, " + f"[input_callback] ImageMetadata message with TS={new_msg.header.stamp}, " + f"source TS={new_msg.image_source_stamp}, " f"image size {msg.width}x{msg.height}, " f"rate={self._rate_tracker.get_rate_avg()} Hz", ) From e304d898041fd06f29414c029cff30dfb1e406ba Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Thu, 21 Nov 2024 12:33:27 -0500 Subject: [PATCH 03/26] change latency tracker to use new msg --- .../angel_system_nodes/latency_tracker.py | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py b/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py index 5c515f50c..c148949eb 100644 --- a/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py +++ b/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py @@ -5,7 +5,8 @@ from rclpy.node import Node from angel_system.utils.event import WaitAndClearEvent -from angel_utils.conversion import time_to_float +from angel_utils.conversion import time_to_float, time_to_int +from builtin_interfaces.msg import Time from angel_msgs.msg import ObjectDetection2dSet, HandJointPosesUpdate, ActivityDetection from angel_utils import ( @@ -14,7 +15,7 @@ make_default_main, ) from std_msgs.msg import String as ros2_string -from sensor_msgs.msg import CameraInfo +from angel_msgs.msg import ImageMetadata class LatencyTracker(Node): @@ -59,23 +60,23 @@ def __init__(self): # Single slot for latest image message to process detection over. # This should be written by the image topic subscriber callback, and # read from the runtime loop once per iteration. - self._cur_image_msg_lock = Lock() self._cur_det_msg_lock = Lock() self._cur_pose_msg_lock = Lock() self._cur_act_msg_lock = Lock() + self._image_lookup_lock = Lock() self._rate_tracker = RateTracker() - self._img_time = None self._det = None self._pose = None self._act = None + self._image_lookup = {} ########################################## # Initialize ROS hooks log.info("Setting up ROS subscriptions and publishers...") self._img_ts_subscriber = self.create_subscription( - CameraInfo, + ImageMetadata, self._image_md_topic, self.img_md_callback, 1, @@ -151,31 +152,37 @@ def rt_loop(self): msg = ros2_string() - # get latency from image source stamp vs det_msg's + # get latency from image source stamp vs the time the message was created det_lat = None if self._det: with self._cur_det_msg_lock: det_msg = self._det dt_time = time_to_float(det_msg.header.stamp) - img_time = time_to_float(det_msg.source_stamp) - det_lat = dt_time - img_time + img_time = self.get_msg_time_from_source(det_msg.source_stamp) + det_lat = dt_time - time_to_float(img_time) + pose_lat = None if self._pose: with self._cur_pose_msg_lock: pose_msg = self._pose ps_time = time_to_float(pose_msg.header.stamp) - img_time = time_to_float(pose_msg.source_stamp) - pose_lat = ps_time - img_time + img_time = self.get_msg_time_from_source(pose_msg.source_stamp) + pose_lat = ps_time - time_to_float(img_time) + act_lat_start = None act_lat_end = None if self._act: with self._cur_act_msg_lock: act_msg = self._act act_time = time_to_float(act_msg.header.stamp) - img_time = time_to_float(act_msg.source_stamp_start_frame) - act_lat_start = act_time - img_time - img_time = time_to_float(act_msg.source_stamp_end_frame) - act_lat_end = act_time - img_time + img_time = self.get_msg_time_from_source( + act_msg.source_stamp_start_frame + ) + act_lat_start = act_time - time_to_float(img_time) + img_time = self.get_msg_time_from_source( + act_msg.source_stamp_end_frame + ) + act_lat_end = act_time - time_to_float(img_time) # save the info to the message data = { @@ -198,7 +205,7 @@ def rt_loop(self): self._rate_tracker.tick() log.info(f"Latency Rate: {self._rate_tracker.get_rate_avg()} Hz") - def img_md_callback(self, msg: CameraInfo) -> None: + def img_md_callback(self, msg: ImageMetadata) -> None: """ Capture a detection source image timestamp message. """ @@ -206,8 +213,8 @@ def img_md_callback(self, msg: CameraInfo) -> None: if self._enable_trace_logging: log.info(f"Received image with TS: {msg.header.stamp}") - with self._cur_image_msg_lock: - self._img_time = msg.header.stamp + with self._image_lookup_lock: + self._image_lookup[time_to_int(msg.image_source_stamp)] = msg.header.stamp self._rt_awake_evt.set() def det_callback(self, msg: ObjectDetection2dSet) -> None: @@ -222,6 +229,10 @@ def act_callback(self, msg: ActivityDetection) -> None: with self._cur_act_msg_lock: self._act = msg + def get_msg_time_from_source(self, source_stamp: Time) -> Time: + with self._image_lookup_lock: + return self._image_lookup.get(time_to_int(source_stamp)) + def destroy_node(self): print("Stopping runtime") self.rt_stop() From 101d1efbee3239cfda6e244367a24455d7011a30 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Thu, 21 Nov 2024 12:34:07 -0500 Subject: [PATCH 04/26] update nodes that used CameraInfo to use the new ImageMetadata message instead --- .../activity_classifier_tcn.py | 11 ++++++----- .../data_publishers/hl2ss_ros_bridge.py | 10 ++++++---- .../python/angel_utils/activity_classification.py | 12 ++++++------ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/ros/angel_system_nodes/angel_system_nodes/activity_classification/activity_classifier_tcn.py b/ros/angel_system_nodes/angel_system_nodes/activity_classification/activity_classifier_tcn.py index 9ec7e9a22..d5d9795d2 100644 --- a/ros/angel_system_nodes/angel_system_nodes/activity_classification/activity_classifier_tcn.py +++ b/ros/angel_system_nodes/angel_system_nodes/activity_classification/activity_classifier_tcn.py @@ -29,7 +29,7 @@ FramePoses, ) from tcn_hpl.models.ptg_module import PTGLitModule -from sensor_msgs.msg import CameraInfo +from angel_msgs.msg import ImageMetadata from angel_system.activity_classification.tcn_hpl.predict import ( ResultsCollector, @@ -254,7 +254,7 @@ def __init__(self): # runtime-thread allocation. # This is intentionally before runtime-loop initialization. self._img_ts_subscriber = self.create_subscription( - CameraInfo, + ImageMetadata, self._img_md_topic, self.img_md_callback, 1, @@ -385,12 +385,13 @@ def _thread_populate_from_coco(self, input_coco_path: Path) -> None: log.info(f"Queuing from COCO: n_dets={n_dets}, image_ts={image_ts}") self.det_callback(det_msg) # self.pose_callback(det_msg) - new_msg = CameraInfo() - new_msg.header.stamp = image_ts + new_msg = ImageMetadata() + new_msg.image_source_stamp = image_ts # set the image width and height from the image in the dataset img = dset.imgs[image_id] new_msg.width = img.get("width") new_msg.height = img.get("height") + new_msg.header.stamp = self.get_clock().now().to_msg() self.img_md_callback(new_msg) # Wait until `image_ts` was considered in the runtime loop before @@ -406,7 +407,7 @@ def _thread_populate_from_coco(self, input_coco_path: Path) -> None: log.info("Completed COCO file object yielding") self._rt_active.clear() - def img_md_callback(self, msg: CameraInfo) -> None: + def img_md_callback(self, msg: ImageMetadata) -> None: """ Capture a detection source image timestamp message. """ diff --git a/ros/angel_system_nodes/angel_system_nodes/data_publishers/hl2ss_ros_bridge.py b/ros/angel_system_nodes/angel_system_nodes/data_publishers/hl2ss_ros_bridge.py index beebf75df..ff1d2d389 100644 --- a/ros/angel_system_nodes/angel_system_nodes/data_publishers/hl2ss_ros_bridge.py +++ b/ros/angel_system_nodes/angel_system_nodes/data_publishers/hl2ss_ros_bridge.py @@ -9,7 +9,7 @@ ) import numpy as np from rclpy.node import Node -from sensor_msgs.msg import Image, CameraInfo +from sensor_msgs.msg import Image from shape_msgs.msg import ( Mesh, MeshTriangle, @@ -21,6 +21,7 @@ HeadsetAudioData, HeadsetPoseData, SpatialMesh, + ImageMetadata, ) from angel_utils import declare_and_get_parameters, RateTracker from angel_utils import make_default_main @@ -122,7 +123,7 @@ def __init__(self): Image, self._image_topic, 1 ) self.ros_frame_md_publisher = self.create_publisher( - CameraInfo, self._image_md_topic, 1 + ImageMetadata, self._image_md_topic, 1 ) self.connect_hl2ss_pv() log.info("PV client connected!") @@ -377,10 +378,11 @@ def pv_publisher(self) -> None: # Publish the image msg self.ros_frame_publisher.publish(image_msg) - new_msg = CameraInfo() - new_msg.header = image_msg.header + new_msg = ImageMetadata() + new_msg.image_source_stamp = image_msg.header.stamp new_msg.height = image_msg.height new_msg.width = image_msg.width + new_msg.header.stamp = self.get_clock().now().to_msg() self.ros_frame_md_publisher.publish(new_msg) # Publish the corresponding headset pose msg diff --git a/ros/angel_utils/python/angel_utils/activity_classification.py b/ros/angel_utils/python/angel_utils/activity_classification.py index cc01e0c99..a85c47470 100644 --- a/ros/angel_utils/python/angel_utils/activity_classification.py +++ b/ros/angel_utils/python/angel_utils/activity_classification.py @@ -15,11 +15,11 @@ # ROS Message types from builtin_interfaces.msg import Time -from sensor_msgs.msg import CameraInfo from angel_msgs.msg import ( HandJointPosesUpdate, ObjectDetection2dSet, + ImageMetadata, ) from angel_system.utils.matching import descending_match_with_tolerance @@ -44,7 +44,7 @@ class InputWindow: # Buffer for patient poses patient_joint_kps: List[Optional[HandJointPosesUpdate]] # Buffer for the image metadata - camera_info: List[Optional[CameraInfo]] + camera_info: List[Optional[ImageMetadata]] def __len__(self): return len(self.frames) @@ -147,7 +147,7 @@ class InputBuffer: ) # buffer for camera info - camera_info: Deque[CameraInfo] = field( + camera_info: Deque[ImageMetadata] = field( default_factory=deque, init=False, repr=False ) @@ -186,7 +186,7 @@ def latest_time(self) -> Time: def queue_image( self, img_mat: npt.NDArray[np.uint8], - camera_msg: CameraInfo, + img_meta_msg: ImageMetadata, image_frame_number: int, ) -> bool: """ @@ -195,7 +195,7 @@ def queue_image( not newer than the current latest frame. """ # get the timestamp from the image header - img_header_stamp = camera_msg.header.stamp + img_header_stamp = img_meta_msg.image_source_stamp # self.get_logger_fn().info(f"image header stamp: {img_header_stamp}") # self.get_logger_fn().info(f"self.frames[-1][0] header stamp: {self.frames[-1][0]}") with self.__state_lock: @@ -212,7 +212,7 @@ def queue_image( # save the image frame self.frames.append((img_header_stamp, img_mat, image_frame_number)) # save the camera info - self.camera_info.append(camera_msg) + self.camera_info.append(img_meta_msg) return True def queue_hand_pose(self, msg: HandJointPosesUpdate) -> bool: From 6b412c49a90e5b3b69798507d35826c2d0517602 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 10:19:05 -0500 Subject: [PATCH 05/26] fix for camera_info messages --- .../python/angel_utils/activity_classification.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ros/angel_utils/python/angel_utils/activity_classification.py b/ros/angel_utils/python/angel_utils/activity_classification.py index a85c47470..c7eecabad 100644 --- a/ros/angel_utils/python/angel_utils/activity_classification.py +++ b/ros/angel_utils/python/angel_utils/activity_classification.py @@ -394,11 +394,7 @@ def get_window( frames=window_frames, obj_dets=window_dets, patient_joint_kps=window_joint_kps, - camera_info=[ - ci - for ci in self.camera_info - if ci.header.stamp in window_frame_times - ], + camera_info=[ci for ci in self.camera_info], ) return output From f85ecaf7d75858aa65b18e7fe07e188ab4bf000c Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 10:19:54 -0500 Subject: [PATCH 06/26] fix for naming of output file based on the name of the video - this replaces the full path with just the video name --- .../global_step_prediction/global_step_predictor.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/angel_system/global_step_prediction/global_step_predictor.py b/angel_system/global_step_prediction/global_step_predictor.py index d27fd704a..c557f1992 100644 --- a/angel_system/global_step_prediction/global_step_predictor.py +++ b/angel_system/global_step_prediction/global_step_predictor.py @@ -927,7 +927,13 @@ def plot_gt_vs_predicted_plus_activations(self, step_gts, fname_suffix=None): plt.legend() if not fname_suffix: - fname_suffix = f"vid{vid_id}" + fname_suffix = "vid_unknown" + + # check for a long path in the fname_suffix + if "/" in fname_suffix: + # get just the end part of the path + fname_suffix = fname_suffix.split("/")[-1] + recipe_type = self.determine_recipe_from_gt_first_step(step_gts) title = f"plot_pred_vs_gt_{recipe_type}_{fname_suffix}.png" plt.title(title) From b43e5cf24ce75efa923e688c96214252de6c9e97 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 10:34:33 -0500 Subject: [PATCH 07/26] fix for no match --- .../angel_system_nodes/latency_tracker.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py b/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py index c148949eb..04609cf7b 100644 --- a/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py +++ b/ros/angel_system_nodes/angel_system_nodes/latency_tracker.py @@ -159,7 +159,8 @@ def rt_loop(self): det_msg = self._det dt_time = time_to_float(det_msg.header.stamp) img_time = self.get_msg_time_from_source(det_msg.source_stamp) - det_lat = dt_time - time_to_float(img_time) + if img_time is not None: + det_lat = dt_time - time_to_float(img_time) pose_lat = None if self._pose: @@ -167,7 +168,8 @@ def rt_loop(self): pose_msg = self._pose ps_time = time_to_float(pose_msg.header.stamp) img_time = self.get_msg_time_from_source(pose_msg.source_stamp) - pose_lat = ps_time - time_to_float(img_time) + if img_time is not None: + pose_lat = ps_time - time_to_float(img_time) act_lat_start = None act_lat_end = None @@ -178,11 +180,13 @@ def rt_loop(self): img_time = self.get_msg_time_from_source( act_msg.source_stamp_start_frame ) - act_lat_start = act_time - time_to_float(img_time) + if img_time is not None: + act_lat_start = act_time - time_to_float(img_time) img_time = self.get_msg_time_from_source( act_msg.source_stamp_end_frame ) - act_lat_end = act_time - time_to_float(img_time) + if img_time is not None: + act_lat_end = act_time - time_to_float(img_time) # save the info to the message data = { From a4eb9e671e0195b34d41d24f4ebc061e82d6b32e Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 10:58:02 -0500 Subject: [PATCH 08/26] add configs to play imagery from bags --- tmux/demos/medical/Kitware-M2-bag.yml | 159 +++++++++++++++++++++++++ tmux/demos/medical/Kitware-R18-bag.yml | 159 +++++++++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 tmux/demos/medical/Kitware-M2-bag.yml create mode 100644 tmux/demos/medical/Kitware-R18-bag.yml diff --git a/tmux/demos/medical/Kitware-M2-bag.yml b/tmux/demos/medical/Kitware-M2-bag.yml new file mode 100644 index 000000000..d7de45bbc --- /dev/null +++ b/tmux/demos/medical/Kitware-M2-bag.yml @@ -0,0 +1,159 @@ +# +# System configuration to run the ANGEL system for the Kitware system with the +# Kitware HL2 ARUI app. +# +# This configuration is for the M2 tourniquet task. +# + +name: kitware-m2 +root: <%= ENV["ANGEL_WORKSPACE_DIR"] %> + +# Optional tmux socket +# socket_name: foo + +# Note that the pre and post options have been deprecated and will be replaced by +# project hooks. + +# Project hooks + +# Runs on project start, always +# on_project_start: command +on_project_start: | + export ROS_NAMESPACE=${ROS_NAMESPACE:-/kitware} + export HL2_IP=${HL2_IP:-192.168.4.2} + export CONFIG_DIR=${ANGEL_WORKSPACE_DIR}/config + export NODE_CONFIG_DIR=${ANGEL_WORKSPACE_DIR}/src/angel_system_nodes/configs + export MODEL_DIR=${ANGEL_WORKSPACE_DIR}/model_files + + # Changing the domain ID was important at KHQ to unblock perceived network + # congestion slowdowns to message sending. + export ROS_DOMAIN_ID=77 + + # Set the frame-rate to be used by multiple sources. This should be in frames + # per second (Hz). + export FRAME_RATE=15 + +# Run on project start, the first time +# on_project_first_start: command + +# Run on project start, after the first time +# on_project_restart: command + +# Run on project exit ( detaching from tmux session ) +# on_project_exit: command + +# Run on project stop +# on_project_stop: command + +# Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions. +# pre_window: rbenv shell 2.0.0-p247 + +# Pass command line options to tmux. Useful for specifying a different tmux.conf. +# tmux_options: -f ~/.tmux.mac.conf +tmux_options: -f <%= ENV["ANGEL_WORKSPACE_DIR"] %>/tmux/tmux.conf + +windows: + - sensor_input_bag: + layout: even-vertical + panes: + # Read sensor input from bag file. + - sensor_input: echo ros2 bag play ${ANGEL_WORKSPACE_DIR}/ros_bags/... + - run_image_metadata: ros2 run angel_system_nodes image_metadata_relay --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p output_topic:=PVFramesBGR_md + - run_latency_node: ros2 run angel_system_nodes latency_tracker --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_topic:=activity_topic + -p latency_topic:=latency + - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ROS_IP:=0.0.0.0 + + - pose_estimation: ros2 run angel_system_nodes pose_estimator --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p det_topic:=pose_dets + -p pose_topic:=PatientPose + -p det_net_checkpoint:=${MODEL_DIR}/pose_estimation/pose_det_model.pth + -p pose_net_checkpoint:=${MODEL_DIR}/pose_estimation/pose_model.pth + -p det_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/medic_pose.yaml + -p pose_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/ViTPose_base_medic_casualty_256x192.py + -p cuda_device_id:=0 + + - object_and_hand_detection: ros2 run angel_system_nodes object_and_hand_detector --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p det_topic:=ObjectDetections2d + -p object_net_checkpoint:=${MODEL_DIR}/object_detector/m2_det.pt + -p inference_img_size:=768 + -p hand_net_checkpoint:=${MODEL_DIR}/object_detector/hands_model.pt + -p cuda_device_id:=0 + + - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/m2.yaml + -p model_weights:=${MODEL_DIR}/activity_classifier/m2_tcn.ckpt + -p model_config:=${MODEL_DIR}/activity_classifier/m2_config.yaml + -p act_topic:=activity_topic + -p pose_repeat_rate:=7.5 + -p window_leads_with_objects:=true + -p model_device:=0 + + - task_monitor: + layout: even-vertical + panes: + - gsp: ros2 run angel_system_nodes global_step_predictor --ros-args + -r __ns:=${ROS_NAMESPACE} + -p config_file:=${CONFIG_DIR}/tasks/medical/multi-task-config-medical-m2.yaml + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/m2.yaml + -p task_state_topic:=TaskUpdates + -p task_error_topic:=ARUISystemNotifications + -p system_command_topic:=SystemCommands + -p det_topic:=activity_topic + -p model_file:=${MODEL_DIR}/task_monitor/global_step_predictor_act_avgs_m2.npy + -p thresh_frame_count:=3 + -p deactivate_thresh_frame_count:=10 + -p threshold_multiplier_weak:=0.00 + -p threshold_frame_count_weak:=3 + -p step_mode:=granular + -p query_task_graph_topic:=query_task_graph + - echo: sleep 0.5 && ros2 topic echo --no-arr "${ROS_NAMESPACE}/TaskUpdates" + + - engineering-ui: + layout: even-vertical + panes: + - simple_2d_overlay: ros2 run angel_utils Simple2dDetectionOverlay --ros-args + -r __ns:=${ROS_NAMESPACE} + -p topic_input_images:=PVFramesBGR + -p topic_input_det_2d:=ObjectDetections2d + -p topic_input_joints:=PatientPose + -p topic_output_images:=pv_image_detections_2d + -p filter_top_k:=5 + -p max_image_history_seconds:=2.0 + -p publish_latency_seconds:=0.15 + - websocket: ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9090 + - engineering_ui_server: node ros/angel_utils/multi_task_demo_ui/index.js + --namespace=${ROS_NAMESPACE} + --image_topic=pv_image_detections_2d/compressed + --query_task_graph_topic=query_task_graph + --task_updates_topic=TaskUpdates + --activity_detections_topic=activity_topic + --task_errors_topic=ARUISystemNotifications + + - feedback_generator: ros2 run angel_system_nodes feedback_generator --ros-args + -r __ns:=${ROS_NAMESPACE} + -p activity_detector_topic:=activity_topic + -p object_detection_topic:=ObjectDetections3d + -p task_monitor_topic:=TaskUpdates + -p arui_update_topic:=AruiUpdates + -p interp_user_intent_topic:=UserIntentPredicted + -p system_text_response_topic:=SystemTextResponse + -p system_notification_topic:=ARUISystemNotifications + -p task_error_topic:=ARUISystemNotifications diff --git a/tmux/demos/medical/Kitware-R18-bag.yml b/tmux/demos/medical/Kitware-R18-bag.yml new file mode 100644 index 000000000..f53a724de --- /dev/null +++ b/tmux/demos/medical/Kitware-R18-bag.yml @@ -0,0 +1,159 @@ +# +# System configuration to run the ANGEL system for the Kitware system with the +# Kitware HL2 ARUI app. +# +# This configuration is for the R18 Chest Seal task. +# + +name: kitware-r18 +root: <%= ENV["ANGEL_WORKSPACE_DIR"] %> + +# Optional tmux socket +# socket_name: foo + +# Note that the pre and post options have been deprecated and will be replaced by +# project hooks. + +# Project hooks + +# Runs on project start, always +# on_project_start: command +on_project_start: | + export ROS_NAMESPACE=${ROS_NAMESPACE:-/kitware} + export HL2_IP=${HL2_IP:-192.168.4.2} + export CONFIG_DIR=${ANGEL_WORKSPACE_DIR}/config + export NODE_CONFIG_DIR=${ANGEL_WORKSPACE_DIR}/src/angel_system_nodes/configs + export MODEL_DIR=${ANGEL_WORKSPACE_DIR}/model_files + + # Changing the domain ID was important at KHQ to unblock perceived network + # congestion slowdowns to message sending. + export ROS_DOMAIN_ID=77 + + # Set the frame-rate to be used by multiple sources. This should be in frames + # per second (Hz). + export FRAME_RATE=15 + +# Run on project start, the first time +# on_project_first_start: command + +# Run on project start, after the first time +# on_project_restart: command + +# Run on project exit ( detaching from tmux session ) +# on_project_exit: command + +# Run on project stop +# on_project_stop: command + +# Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions. +# pre_window: rbenv shell 2.0.0-p247 + +# Pass command line options to tmux. Useful for specifying a different tmux.conf. +# tmux_options: -f ~/.tmux.mac.conf +tmux_options: -f <%= ENV["ANGEL_WORKSPACE_DIR"] %>/tmux/tmux.conf + +windows: + - sensor_input_bag: + layout: even-vertical + panes: + # Read sensor input from bag file. + - sensor_input: echo ros2 bag play ${ANGEL_WORKSPACE_DIR}/ros_bags/rosbag2-bbn_lab_data-r18-positive-30424_NE_recordings-R18_5-TEST_SET/ + - run_image_metadata: ros2 run angel_system_nodes image_metadata_relay --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p output_topic:=PVFramesBGR_md + - run_latency_node: ros2 run angel_system_nodes latency_tracker --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_topic:=activity_topic + -p latency_topic:=latency + - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ROS_IP:=0.0.0.0 + + - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml + -p model_weights:=${MODEL_DIR}/activity_classifier/r18_tcn.ckpt + -p model_config:=${MODEL_DIR}/activity_classifier/r18_config.yaml + -p act_topic:=activity_topic + -p pose_repeat_rate:=7.5 + -p window_leads_with_objects:=true + -p model_device:=0 + + - object_and_hand_detection: ros2 run angel_system_nodes object_and_hand_detector --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p det_topic:=ObjectDetections2d + -p object_net_checkpoint:=${MODEL_DIR}/object_detector/r18_det.pt + -p inference_img_size:=768 + -p hand_net_checkpoint:=${MODEL_DIR}/object_detector/hands_model.pt + -p cuda_device_id:=0 + + - pose_estimation: ros2 run angel_system_nodes pose_estimator --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_topic:=PVFramesBGR + -p det_topic:=pose_dets + -p pose_topic:=PatientPose + -p det_net_checkpoint:=${MODEL_DIR}/pose_estimation/pose_det_model.pth + -p pose_net_checkpoint:=${MODEL_DIR}/pose_estimation/pose_model.pth + -p det_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/medic_pose.yaml + -p pose_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/ViTPose_base_medic_casualty_256x192.py + -p cuda_device_id:=0 + + - task_monitor: + layout: even-vertical + panes: + - gsp: ros2 run angel_system_nodes global_step_predictor --ros-args + -r __ns:=${ROS_NAMESPACE} + -p config_file:=${CONFIG_DIR}/tasks/medical/multi-task-config-medical-r18.yaml + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml + -p task_state_topic:=TaskUpdates + -p task_error_topic:=ARUISystemNotifications + -p system_command_topic:=SystemCommands + -p det_topic:=activity_topic + -p model_file:=${MODEL_DIR}/task_monitor/global_step_predictor_act_avgs_R18.npy + -p thresh_frame_count:=3 + -p deactivate_thresh_frame_count:=5 + -p threshold_multiplier_weak:=0.00 + -p threshold_frame_count_weak:=3 + -p step_mode:=granular + -p query_task_graph_topic:=query_task_graph + - echo: sleep 0.5 && ros2 topic echo --no-arr "${ROS_NAMESPACE}/TaskUpdates" + + - engineering-ui: + layout: even-vertical + panes: + - simple_2d_overlay: ros2 run angel_utils Simple2dDetectionOverlay --ros-args + -r __ns:=${ROS_NAMESPACE} + -p topic_input_images:=PVFramesBGR + -p topic_input_det_2d:=ObjectDetections2d + -p topic_input_joints:=PatientPose + -p topic_output_images:=pv_image_detections_2d + -p filter_top_k:=5 + -p max_image_history_seconds:=2.0 + -p publish_latency_seconds:=0.15 + - websocket: ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9090 + - engineering_ui_server: node ros/angel_utils/multi_task_demo_ui/index.js + --namespace=${ROS_NAMESPACE} + --image_topic=pv_image_detections_2d/compressed + --query_task_graph_topic=query_task_graph + --task_updates_topic=TaskUpdates + --activity_detections_topic=activity_topic + --task_errors_topic=ARUISystemNotifications + + - feedback_generator: ros2 run angel_system_nodes feedback_generator --ros-args + -r __ns:=${ROS_NAMESPACE} + -p activity_detector_topic:=activity_topic + -p object_detection_topic:=ObjectDetections3d + -p task_monitor_topic:=TaskUpdates + -p arui_update_topic:=AruiUpdates + -p interp_user_intent_topic:=UserIntentPredicted + -p system_text_response_topic:=SystemTextResponse + -p system_notification_topic:=ARUISystemNotifications + -p task_error_topic:=ARUISystemNotifications From 44b0593b44ef005b569c9e4fab3a65e547012214 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 10:59:13 -0500 Subject: [PATCH 09/26] adjust configs to always run the datahub --- tmux/demos/medical/Kitware-M2.yml | 47 +++++++++++-------------- tmux/demos/medical/Kitware-R18.yml | 56 +++++++++++------------------- tmux/record/record_ros_bag.yml | 5 ++- 3 files changed, 44 insertions(+), 64 deletions(-) diff --git a/tmux/demos/medical/Kitware-M2.yml b/tmux/demos/medical/Kitware-M2.yml index ae4287073..68740d86b 100644 --- a/tmux/demos/medical/Kitware-M2.yml +++ b/tmux/demos/medical/Kitware-M2.yml @@ -5,7 +5,7 @@ # This configuration is for the M2 tourniquet task. # -name: Kitware-M2-Tourniquet +name: kitware-m2 root: <%= ENV["ANGEL_WORKSPACE_DIR"] %> # Optional tmux socket @@ -56,8 +56,23 @@ windows: - sensor_input_bag: layout: even-vertical panes: - # Read sensor input from bag file. - - sensor_input: echo ros2 bag play ${ANGEL_WORKSPACE_DIR}/ros_bags/... + # Read sensor input from the hololens + # the image size is set to 1280x720 because of the pose estimation node: + # https://github.com/PTG-Kitware/angel_system/blob/master/ros/angel_system_nodes/angel_system_nodes/pose_estimation/pose_estimator.py#L211 + - hl2ss_bridge: ros2 run angel_system_nodes hl2ss_ros_bridge --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ip_addr:=${HL2_IP} + -p image_topic:=PVFramesBGR + -p image_md_topic:=PVFramesBGR_md + -p hand_pose_topic:=HandJointPoseData + -p audio_topic:=HeadsetAudioData + -p sm_topic:=SpatialMapData + -p head_pose_topic:=HeadsetPoseData + -p pv_width:=1280 + -p pv_height:=720 + -p pv_framerate:=15 + -p sm_freq:=5 + -p rm_depth_AHAT:=disable - run_image_metadata: ros2 run angel_system_nodes image_metadata_relay --ros-args -r __ns:=${ROS_NAMESPACE} -p image_topic:=PVFramesBGR @@ -69,29 +84,9 @@ windows: -p pose_topic:=PatientPose -p activity_topic:=activity_topic -p latency_topic:=latency - -# - sensor_input_stream: -# layout: even-vertical -# panes: -# # Read sensor input from a HoloLens2 unit using HL2SS. -# - hl2ss_bridge: ros2 run angel_system_nodes hl2ss_ros_bridge --ros-args -# -r __ns:=${ROS_NAMESPACE} -# -p ip_addr:=${HL2_IP} -# -p image_topic:=PVFramesBGR -# -p image_md_topic:=PVFramesBGR_md -# -p hand_pose_topic:=disable -# -p audio_topic:=disable -# -p sm_topic:=disable -# -p head_pose_topic:=disable -# -p pv_width:=1280 -# -p pv_height:=720 -# -p pv_framerate:=${FRAME_RATE} -# -p sm_freq:=5 -# -p rm_depth_AHAT:=disable -# # Enable sending ROS2 messages to receiving agents in an HoloLens2 app. -# - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -# -r __ns:=${ROS_NAMESPACE} -# -p ROS_IP:=0.0.0.0 + - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ROS_IP:=0.0.0.0 - pose_estimation: ros2 run angel_system_nodes pose_estimator --ros-args -r __ns:=${ROS_NAMESPACE} diff --git a/tmux/demos/medical/Kitware-R18.yml b/tmux/demos/medical/Kitware-R18.yml index 881b16395..ca7855d16 100644 --- a/tmux/demos/medical/Kitware-R18.yml +++ b/tmux/demos/medical/Kitware-R18.yml @@ -5,7 +5,7 @@ # This configuration is for the R18 Chest Seal task. # -name: kitware-R18-Chest-Seal +name: kitware-r18 root: <%= ENV["ANGEL_WORKSPACE_DIR"] %> # Optional tmux socket @@ -56,10 +56,23 @@ windows: - sensor_input_bag: layout: even-vertical panes: - # Read sensor input from bag file. - # May have to use: --remap /kitware/image_0:=/kitware/PVFramesBGR -# - sensor_input: echo ros2 bag play ${ANGEL_WORKSPACE_DIR}/ros_bags/rosbag2-bbn_lab_data-r18-positive-seal_videos-seal_2-TEST_SET/ - - sensor_input: echo ros2 bag play ${ANGEL_WORKSPACE_DIR}/ros_bags/rosbag2-bbn_lab_data-r18-positive-30424_NE_recordings-R18_5-TEST_SET/ + # Read sensor input from the hololens + # the image size is set to 1280x720 because of the pose estimation node: + # https://github.com/PTG-Kitware/angel_system/blob/master/ros/angel_system_nodes/angel_system_nodes/pose_estimation/pose_estimator.py#L211 + - hl2ss_bridge: ros2 run angel_system_nodes hl2ss_ros_bridge --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ip_addr:=${HL2_IP} + -p image_topic:=PVFramesBGR + -p image_md_topic:=PVFramesBGR_md + -p hand_pose_topic:=HandJointPoseData + -p audio_topic:=HeadsetAudioData + -p sm_topic:=SpatialMapData + -p head_pose_topic:=HeadsetPoseData + -p pv_width:=1280 + -p pv_height:=720 + -p pv_framerate:=15 + -p sm_freq:=5 + -p rm_depth_AHAT:=disable - run_image_metadata: ros2 run angel_system_nodes image_metadata_relay --ros-args -r __ns:=${ROS_NAMESPACE} -p image_topic:=PVFramesBGR @@ -71,36 +84,9 @@ windows: -p pose_topic:=PatientPose -p activity_topic:=activity_topic -p latency_topic:=latency - -# - sensor_input_stream: -# layout: even-vertical -# panes: -# # Read sensor input from a HoloLens2 unit using HL2SS. -# - sensor_input: echo ros2 run angel_system_nodes hl2ss_ros_bridge --ros-args -# -r __ns:=${ROS_NAMESPACE} -# -p ip_addr:=${HL2_IP} -# -p image_topic:=PVFramesBGR -# -p image_md_topic:=PVFramesBGR_md -# -p hand_pose_topic:=disable -# -p audio_topic:=HeadsetAudioData -# -p sm_topic:=disable -# -p head_pose_topic:=disable -# -p pv_width:=1280 -# -p pv_height:=720 -# -p pv_framerate:=${FRAME_RATE} -# -p sm_freq:=5 -# -p rm_depth_AHAT:=disable -# # Enable sending ROS2 messages to receiving agents in an HoloLens2 app. -# - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -# -r __ns:=${ROS_NAMESPACE} -# -p ROS_IP:=0.0.0.0 -# - run_latency_node: ros2 run angel_system_nodes latency_tracker --ros-args -# -r __ns:=${ROS_NAMESPACE} -# -p image_md_topic:=PVFramesBGR_md -# -p det_topic:=ObjectDetections2d -# -p pose_topic:=PatientPose -# -p activity_topic:=activity_topic -# -p latency_topic:=latency + - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args + -r __ns:=${ROS_NAMESPACE} + -p ROS_IP:=0.0.0.0 - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args -r __ns:=${ROS_NAMESPACE} diff --git a/tmux/record/record_ros_bag.yml b/tmux/record/record_ros_bag.yml index 9c0affb7b..dc66cbca0 100644 --- a/tmux/record/record_ros_bag.yml +++ b/tmux/record/record_ros_bag.yml @@ -58,9 +58,8 @@ windows: - sensor_input: layout: even-vertical panes: - - datahub: ros2 run ros_tcp_endpoint default_server_endpoint --ros-args - -r __ns:=${ROS_NAMESPACE} - -p ROS_IP:=0.0.0.0 + # the image size is set to 1280x720 because of the pose estimation node: + # https://github.com/PTG-Kitware/angel_system/blob/master/ros/angel_system_nodes/angel_system_nodes/pose_estimation/pose_estimator.py#L211 - hl2ss_bridge: ros2 run angel_system_nodes hl2ss_ros_bridge --ros-args -r __ns:=${ROS_NAMESPACE} -p ip_addr:=${HL2_IP} From 6bebf83b964034ab506ba583379baeb1cc92f171 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 11:41:01 -0500 Subject: [PATCH 10/26] move the tcn node to the same position as other configs --- tmux/demos/medical/Kitware-R18-bag.yml | 26 +++++++++++++------------- tmux/demos/medical/Kitware-R18.yml | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tmux/demos/medical/Kitware-R18-bag.yml b/tmux/demos/medical/Kitware-R18-bag.yml index f53a724de..799198d0f 100644 --- a/tmux/demos/medical/Kitware-R18-bag.yml +++ b/tmux/demos/medical/Kitware-R18-bag.yml @@ -73,19 +73,6 @@ windows: -r __ns:=${ROS_NAMESPACE} -p ROS_IP:=0.0.0.0 - - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args - -r __ns:=${ROS_NAMESPACE} - -p image_md_topic:=PVFramesBGR_md - -p det_topic:=ObjectDetections2d - -p pose_topic:=PatientPose - -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml - -p model_weights:=${MODEL_DIR}/activity_classifier/r18_tcn.ckpt - -p model_config:=${MODEL_DIR}/activity_classifier/r18_config.yaml - -p act_topic:=activity_topic - -p pose_repeat_rate:=7.5 - -p window_leads_with_objects:=true - -p model_device:=0 - - object_and_hand_detection: ros2 run angel_system_nodes object_and_hand_detector --ros-args -r __ns:=${ROS_NAMESPACE} -p image_topic:=PVFramesBGR @@ -106,6 +93,19 @@ windows: -p pose_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/ViTPose_base_medic_casualty_256x192.py -p cuda_device_id:=0 + - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml + -p model_weights:=${MODEL_DIR}/activity_classifier/r18_tcn.ckpt + -p model_config:=${MODEL_DIR}/activity_classifier/r18_config.yaml + -p act_topic:=activity_topic + -p pose_repeat_rate:=7.5 + -p window_leads_with_objects:=true + -p model_device:=0 + - task_monitor: layout: even-vertical panes: diff --git a/tmux/demos/medical/Kitware-R18.yml b/tmux/demos/medical/Kitware-R18.yml index ca7855d16..d8599ba63 100644 --- a/tmux/demos/medical/Kitware-R18.yml +++ b/tmux/demos/medical/Kitware-R18.yml @@ -88,19 +88,6 @@ windows: -r __ns:=${ROS_NAMESPACE} -p ROS_IP:=0.0.0.0 - - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args - -r __ns:=${ROS_NAMESPACE} - -p image_md_topic:=PVFramesBGR_md - -p det_topic:=ObjectDetections2d - -p pose_topic:=PatientPose - -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml - -p model_weights:=${MODEL_DIR}/activity_classifier/r18_tcn.ckpt - -p model_config:=${MODEL_DIR}/activity_classifier/r18_config.yaml - -p act_topic:=activity_topic - -p pose_repeat_rate:=7.5 - -p window_leads_with_objects:=true - -p model_device:=0 - - object_and_hand_detection: ros2 run angel_system_nodes object_and_hand_detector --ros-args -r __ns:=${ROS_NAMESPACE} -p image_topic:=PVFramesBGR @@ -121,6 +108,19 @@ windows: -p pose_config:=${ANGEL_WORKSPACE_DIR}/python-tpl/TCN_HPL/tcn_hpl/data/utils/pose_generation/configs/ViTPose_base_medic_casualty_256x192.py -p cuda_device_id:=0 + - activity_classifier: ros2 run angel_system_nodes activity_classifier_tcn --ros-args + -r __ns:=${ROS_NAMESPACE} + -p image_md_topic:=PVFramesBGR_md + -p det_topic:=ObjectDetections2d + -p pose_topic:=PatientPose + -p activity_config_file:=${CONFIG_DIR}/activity_labels/medical/r18.yaml + -p model_weights:=${MODEL_DIR}/activity_classifier/r18_tcn.ckpt + -p model_config:=${MODEL_DIR}/activity_classifier/r18_config.yaml + -p act_topic:=activity_topic + -p pose_repeat_rate:=7.5 + -p window_leads_with_objects:=true + -p model_device:=0 + - task_monitor: layout: even-vertical panes: From 51e31b2e0c6eb036d4f4d183c36d70ee869ff430 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 11:41:29 -0500 Subject: [PATCH 11/26] update the ansible provisioning for the tcn models --- ansible/roles/provision-files/vars/main.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ansible/roles/provision-files/vars/main.yml b/ansible/roles/provision-files/vars/main.yml index f14d133da..201325654 100644 --- a/ansible/roles/provision-files/vars/main.yml +++ b/ansible/roles/provision-files/vars/main.yml @@ -71,11 +71,11 @@ girder_file_downloads: sha512: e6b382f5ba3d4d7f17d29caa3f6ea06dd5db24fee3bf59b12ff748d58b1b064c374741c805ee7c07a2a6950761a38e5398f3707ed3e83d7d53218972c57d12a2 dest: "{{ stage_dirs.object_detector }}/m2_det.pt" # Activity classifier - - file_id: 671bff2983e1acbfd87e723f - sha512: 5165219f60e3a160a8ec51f0446db4ec23ed70c399df66f482a233566e177d1f8cf044fc6ccc5227f5c748cbe6d2f17143109e791a139dfc2225d75de67829b2 + - file_id: 673f69bef4ba555b2ab8ae15 + sha512: 91d69908ef49b4a43dd344ae36a1c11eda6afb9b15dd748292435343087e08a3b1c22347efe592d7f078669d52a3dc496ca605ba4463997878151973e4885e77 dest: "{{ stage_dirs.activity_classifier }}/m2_tcn.ckpt" - - file_id: 672543fcca1110761bd32f7d - sha512: aef3ab3f8927f83b7ecad3cc28ea7b42e662d5c11740df1015542df6740db3633a7829187e9f5a35b4a66ebfeb48756c6598e4b7e6f68cc1ae90912fd71e31dd + - file_id: 673f69b3f4ba555b2ab8ae12 + sha512: 68bea2bd8748cc2ad55ca8784d45b9b0c9f21bd3cbca9d8983d158281adf15197d52a2582477ff1ac79ece0ce9187eb466056d407cb3e54894c3f9fd47dc5e41 dest: "{{ stage_dirs.activity_classifier }}/m2_config.yaml" # Global Step predictor model - file_id: 6723f3d283e1acbfd87e7269 @@ -122,11 +122,11 @@ girder_file_downloads: sha512: 7183385f8eaca85997725a107a76034de2bd4a59c1434b4bdb7c1ac8931cf4b68a53f6e736734643386364b9f0856de795a14965b6a02bc5eb5891252e6a73c9 dest: "{{ stage_dirs.object_detector }}/r18_det.pt" # Activity classifier - - file_id: 672cf299ca1110761bd32ffd - sha512: 0bfd4c5a1f254120758b9802eefef8933bfebf80837bd61445c3c26228edaefa34f0ed81178670538426983a93d60198f1be82a767e350b26d4fb3d081972b0d + - file_id: 673f6e62f4ba555b2ab8ae35 + sha512: e731dad0d0688ede4fc1b04b7c6c67478971ab97da062813ec04571daca07f413aa4775c385c3e8b28a8f5f50f8157e68547d45d033ab4bb0926935ad39e7f26 dest: "{{ stage_dirs.activity_classifier }}/r18_tcn.ckpt" - - file_id: 672cf437ca1110761bd33009 - sha512: d99c484071f22661425a9673ff351db90ce2fba40f2faa56f0b388deb2d0cdcc96931a2627e5aec45ab5a4624c9ab04da23b63364dd6eb1d5641a90701737006 + - file_id: 673f6e58f4ba555b2ab8ae32 + sha512: 09a4c97e79c34ac95c95a4c63370b928527a98b9bab233aa12e4b14cfa95e0bb5a09bad90d19715ab656d17281ba5fbaa719647a5545bf2447ae584da5bd8d6a dest: "{{ stage_dirs.activity_classifier }}/r18_config.yaml" # Global Step predictor model - file_id: 66464bf9687336214e7cdeae From ebd2adf5e4a13e5935dcf0eb9e118134c0e9bec1 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Mon, 25 Nov 2024 11:44:58 -0500 Subject: [PATCH 12/26] update provisioning for the gsp --- ansible/roles/provision-files/vars/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ansible/roles/provision-files/vars/main.yml b/ansible/roles/provision-files/vars/main.yml index 201325654..332aefeb6 100644 --- a/ansible/roles/provision-files/vars/main.yml +++ b/ansible/roles/provision-files/vars/main.yml @@ -78,8 +78,8 @@ girder_file_downloads: sha512: 68bea2bd8748cc2ad55ca8784d45b9b0c9f21bd3cbca9d8983d158281adf15197d52a2582477ff1ac79ece0ce9187eb466056d407cb3e54894c3f9fd47dc5e41 dest: "{{ stage_dirs.activity_classifier }}/m2_config.yaml" # Global Step predictor model - - file_id: 6723f3d283e1acbfd87e7269 - sha512: fb676aae6f768498df860bbf4a1621ee8403cba96a1b9acc088f5f23671c57ca1f06f6c535fa8b0eb5074c7fed56e8ff5a7f990e2893f3759662c76137db1746 + - file_id: 673f74eff4ba555b2ab8ae3e + sha512: 437f5557ff3670c75118d7699964ece42d3480502a71888de62c53c6998b42a297fb7b21ea0bc6bfc4da59e64f9730b69d61d55b5f2c9dd73d93eeee682d60de dest: "{{ stage_dirs.task_monitor }}/global_step_predictor_act_avgs_m2.npy" # ---- M3 ---- @@ -129,8 +129,8 @@ girder_file_downloads: sha512: 09a4c97e79c34ac95c95a4c63370b928527a98b9bab233aa12e4b14cfa95e0bb5a09bad90d19715ab656d17281ba5fbaa719647a5545bf2447ae584da5bd8d6a dest: "{{ stage_dirs.activity_classifier }}/r18_config.yaml" # Global Step predictor model - - file_id: 66464bf9687336214e7cdeae - sha512: bc7884c258cb8704372dd69a3e7d999eaf70d716d271982077c7216ef27ab01219ef1e488f6f9669e11a7e8aa6ffb9d8e07d74edc47294f90cc9e6a723f5a822 + - file_id: 673f8cbcf4ba555b2ab8ae42 + sha512: 4198d861961886b05b85dd178004ea2ca54ce4625bd9ea37a18f000f1090e8646e5838c1577090b799662e0cae779558f857b6a568c115f79bbca6d021a446f7 dest: "{{ stage_dirs.task_monitor }}/global_step_predictor_act_avgs_R18.npy" # List of git repositories to check out at a specific ref and then archive. From fe9057da44e5298465826d8a8f06d2b097aae6d2 Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Tue, 3 Dec 2024 17:43:54 -0500 Subject: [PATCH 13/26] Added new class-wise and mean F1 metric --- .../.global_step_predictor.py.swp | Bin 0 -> 73728 bytes .../global_step_predictor.py | 29 ++++++++++++++++++ .../global_step_prediction/run_expirement.py | 21 +++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 angel_system/global_step_prediction/.global_step_predictor.py.swp diff --git a/angel_system/global_step_prediction/.global_step_predictor.py.swp b/angel_system/global_step_prediction/.global_step_predictor.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..5f317b329722833b814929091600af7b3c754245 GIT binary patch literal 73728 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 Date: Tue, 3 Dec 2024 17:44:31 -0500 Subject: [PATCH 14/26] rm swap file --- .../.global_step_predictor.py.swp | Bin 73728 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 angel_system/global_step_prediction/.global_step_predictor.py.swp diff --git a/angel_system/global_step_prediction/.global_step_predictor.py.swp b/angel_system/global_step_prediction/.global_step_predictor.py.swp deleted file mode 100644 index 5f317b329722833b814929091600af7b3c754245..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73728 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 Date: Thu, 5 Dec 2024 08:35:04 -0500 Subject: [PATCH 15/26] Update K-R18 to not skip steps --- tmux/demos/medical/Kitware-R18.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmux/demos/medical/Kitware-R18.yml b/tmux/demos/medical/Kitware-R18.yml index d8599ba63..3e7e36d60 100644 --- a/tmux/demos/medical/Kitware-R18.yml +++ b/tmux/demos/medical/Kitware-R18.yml @@ -134,9 +134,9 @@ windows: -p det_topic:=activity_topic -p model_file:=${MODEL_DIR}/task_monitor/global_step_predictor_act_avgs_R18.npy -p thresh_frame_count:=3 - -p deactivate_thresh_frame_count:=5 - -p threshold_multiplier_weak:=0.00 - -p threshold_frame_count_weak:=3 + -p deactivate_thresh_frame_count:=8 + -p threshold_multiplier_weak:=1.0 + -p threshold_frame_count_weak:=8 -p step_mode:=granular -p query_task_graph_topic:=query_task_graph - echo: sleep 0.5 && ros2 topic echo --no-arr "${ROS_NAMESPACE}/TaskUpdates" From f562da272d6d898daa86f0b85a85c4c9cb6ddcc5 Mon Sep 17 00:00:00 2001 From: Paul Tunison Date: Thu, 12 Dec 2024 14:00:01 -0500 Subject: [PATCH 16/26] Add more activity configs for new tasks --- config/activity_labels/medical/a8.yaml | 25 +++++++++++++++++++++++++ config/activity_labels/medical/m4.yaml | 6 +++--- config/activity_labels/medical/r16.yaml | 25 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 config/activity_labels/medical/a8.yaml create mode 100644 config/activity_labels/medical/r16.yaml diff --git a/config/activity_labels/medical/a8.yaml b/config/activity_labels/medical/a8.yaml new file mode 100644 index 000000000..b4c5175cd --- /dev/null +++ b/config/activity_labels/medical/a8.yaml @@ -0,0 +1,25 @@ +version: "1" +title: "NPA" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + - id: 1 + label: "select-tube" + full_str: "Select NPA tube that best fits casualty." + - id: 2 + label: "position-head" + full_str: "Place casualty into 'sniffing position' with head tilted back and nostrils exposed." + - id: 3 + label: "cover-with-lube" + full_str: "Cover NPA with lube." + - id: 4 + label: "insert-npa" + full_str: "Insert NPA perpendicular to casualty nostril until flange meets tip of nose, rotating along the way." + - id: 5 + label: "look-listen-feel" + full_str: "Look, listen, and feel for airway compliance." diff --git a/config/activity_labels/medical/m4.yaml b/config/activity_labels/medical/m4.yaml index 71a868e49..c700cb90f 100644 --- a/config/activity_labels/medical/m4.yaml +++ b/config/activity_labels/medical/m4.yaml @@ -10,10 +10,10 @@ labels: full_str: "background" - id: 1 label: "apply-pressure" - full_str: "Apply direct hand pressure." + full_str: "Apply direct hand pressure to the wound." - id: 2 label: "open-pack" - full_str: "Open dressing packaging." + full_str: "Open gauze packaging." - id: 3 label: "apply-dress-w-pressure" - full_str: "Apply dressing with pressure point directly over wound site." + full_str: "Pack the wound." diff --git a/config/activity_labels/medical/r16.yaml b/config/activity_labels/medical/r16.yaml new file mode 100644 index 000000000..639c5f0bc --- /dev/null +++ b/config/activity_labels/medical/r16.yaml @@ -0,0 +1,25 @@ +version: "1" +title: "Ventilate (BVM)" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + - id: 1 + label: "position-head" + full_str: "Place casualty into 'sniffing position' with head tilted back and nostrils exposed." + - id: 2 + label: "open-packaging" + full_str: "Open the BVM packaging." + - id: 3 + label: "attach-mask" + full_str: "Attach mask to BVM and expand BVM to full size." + - id: 4 + label: "place-mask" + full_str: "Place mask over patient’s mouth in proper orientation." + - id: 5 + label: "squeeze-bvm" + full_str: "Squeeze BVM while holding mask to patient’s mouth." From 82a0501cc797195dec9e4ebf24eef9f06202df88 Mon Sep 17 00:00:00 2001 From: Paul Tunison Date: Thu, 12 Dec 2024 16:54:56 -0500 Subject: [PATCH 17/26] Update kwcoco version to recent version with patched union functionality --- poetry.lock | 393 +++++++++++++--------------------------------------- 1 file changed, 98 insertions(+), 295 deletions(-) diff --git a/poetry.lock b/poetry.lock index 59c7e7b0f..b33199011 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "absl-py" @@ -350,17 +350,6 @@ tests = ["attrs[tests-no-zope]", "zope-interface"] tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] -[[package]] -name = "autocommand" -version = "2.2.2" -description = "A library to create a command-line program from a function" -optional = false -python-versions = ">=3.7" -files = [ - {file = "autocommand-2.2.2-py3-none-any.whl", hash = "sha256:710afe251075e038e19e815e25f8155cabe02196cfb545b2185e0d9c8b2b0459"}, - {file = "autocommand-2.2.2.tar.gz", hash = "sha256:878de9423c5596491167225c2a455043c3130fb5b7286ac83443d45e74955f34"}, -] - [[package]] name = "av" version = "12.0.0" @@ -1076,34 +1065,35 @@ files = [ [[package]] name = "delayed-image" -version = "0.2.13" +version = "0.4.2" description = "The delayed_image module" optional = false python-versions = ">=3.6" files = [ - {file = "delayed_image-0.2.13-py3-none-any.whl", hash = "sha256:d1207fe8ee3278d106b9492c1cd3cb05812f157c362d81398af92fd65b75bc36"}, + {file = "delayed_image-0.4.2-py3-none-any.whl", hash = "sha256:3f5c45e3cb12722610f31c213824a7c55c3d84e6ed36d2f76946dac525422724"}, + {file = "delayed_image-0.4.2.tar.gz", hash = "sha256:369a76b82161f60545734b048231672148b38307f0a9abc9734da8a2725be447"}, ] [package.dependencies] affine = ">=2.3.0" -kwarray = ">=0.6.7" -kwimage = ">=0.9.24" +kwarray = ">=0.6.19" +kwimage = ">=0.11.0" networkx = {version = ">=2.7", markers = "python_version < \"3.11\" and python_version >= \"3.8\""} -numpy = {version = ">=1.19.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} -ubelt = ">=1.3.3" +numpy = {version = ">=1.19.3", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} +ubelt = ">=1.3.6" [package.extras] -all = ["affine (>=2.3.0)", "coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "kwarray (>=0.6.7)", "kwimage (>=0.9.24)", "lark (>=1.1.2)", "lark-cython (>=0.0.12)", "networkx (>=2.2.0,<=2.5.1)", "networkx (>=2.6.2)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.2)", "numpy (>=1.19.2)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "ubelt (>=1.3.3)", "xarray (>=0.16.0)", "xdoctest (>=1.1.1)"] -all-strict = ["affine (==2.3.0)", "coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "kwarray (==0.6.7)", "kwimage (==0.9.24)", "lark (==1.1.2)", "lark-cython (==0.0.12)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "ubelt (==1.3.3)", "xarray (==0.16.0)", "xdoctest (==1.1.1)"] -graphics = ["opencv-python (>=3.1.0.0)", "opencv-python (>=3.1.0.2)", "opencv-python (>=3.1.0.5)", "opencv-python (>=3.4.13.47)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=4.5.4.58)", "opencv-python (>=4.5.5.64)"] -graphics-strict = ["opencv-python (==3.1.0.0)", "opencv-python (==3.1.0.2)", "opencv-python (==3.1.0.5)", "opencv-python (==3.4.13.47)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==4.5.4.58)", "opencv-python (==4.5.5.64)"] -headless = ["opencv-python-headless (>=3.4.13.47)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)"] -headless-strict = ["opencv-python-headless (==3.4.13.47)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)"] +all = ["affine (>=2.3.0)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "kwarray (>=0.6.19)", "kwimage (>=0.11.0)", "lark (>=1.1.2)", "lark-cython (>=0.0.12)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "pytest (>=6.2.5)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "ubelt (>=1.3.6)", "xarray (>=0.16.0)", "xdoctest (>=1.1.5)"] +all-strict = ["affine (==2.3.0)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "kwarray (==0.6.19)", "kwimage (==0.11.0)", "lark (==1.1.2)", "lark-cython (==0.0.12)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "pytest (==6.2.5)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "ubelt (==1.3.6)", "xarray (==0.16.0)", "xdoctest (==1.1.5)"] +graphics = ["opencv-python (>=3.4.15.55)", "opencv-python (>=4.5.4.58)", "opencv-python (>=4.5.5.64)"] +graphics-strict = ["opencv-python (==3.4.15.55)", "opencv-python (==4.5.4.58)", "opencv-python (==4.5.5.64)"] +headless = ["opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)"] +headless-strict = ["opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)"] optional = ["lark (>=1.1.2)", "lark-cython (>=0.0.12)", "xarray (>=0.16.0)"] optional-strict = ["lark (==1.1.2)", "lark-cython (==0.0.12)", "xarray (==0.16.0)"] -runtime-strict = ["affine (==2.3.0)", "kwarray (==0.6.7)", "kwimage (==0.9.24)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "ubelt (==1.3.3)"] -tests = ["coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "xdoctest (>=1.1.1)"] -tests-strict = ["coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "xdoctest (==1.1.1)"] +runtime-strict = ["affine (==2.3.0)", "kwarray (==0.6.19)", "kwimage (==0.11.0)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "ubelt (==1.3.6)"] +tests = ["coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "pytest (>=6.2.5)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "xdoctest (>=1.1.5)"] +tests-strict = ["coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "pytest (==6.2.5)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "xdoctest (==1.1.5)"] [[package]] name = "detectron2" @@ -1941,25 +1931,6 @@ zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] -[[package]] -name = "inflect" -version = "7.0.0" -description = "Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words" -optional = false -python-versions = ">=3.8" -files = [ - {file = "inflect-7.0.0-py3-none-any.whl", hash = "sha256:9544afed6182176e43955c44b1acdaed30f9b2b56c16d1fc5b222d98218b546e"}, - {file = "inflect-7.0.0.tar.gz", hash = "sha256:63da9325ad29da81ec23e055b41225795ab793b4ecb483be5dc1fa363fd4717e"}, -] - -[package.dependencies] -pydantic = ">=1.9.1" -typing-extensions = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pygments", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - [[package]] name = "iniconfig" version = "2.0.0" @@ -2092,155 +2063,6 @@ files = [ [package.dependencies] arrow = ">=0.15.0" -[[package]] -name = "jaraco-classes" -version = "3.3.1" -description = "Utility functions for Python class constructs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.classes-3.3.1-py3-none-any.whl", hash = "sha256:86b534de565381f6b3c1c830d13f931d7be1a75f0081c57dff615578676e2206"}, - {file = "jaraco.classes-3.3.1.tar.gz", hash = "sha256:cb28a5ebda8bc47d8c8015307d93163464f9f2b91ab4006e09ff0ce07e8bfb30"}, -] - -[package.dependencies] -more-itertools = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "jaraco-collections" -version = "5.0.0" -description = "Collection objects similar to those in stdlib by jaraco" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.collections-5.0.0-py3-none-any.whl", hash = "sha256:a693d06b12718656921d79ba4f665f905014da09b35aa3deef43be4f14fdaa0d"}, - {file = "jaraco.collections-5.0.0.tar.gz", hash = "sha256:1680e8d09f295f625c7ba926880175a26fdbe7092b4c76d198e30476b21cfe68"}, -] - -[package.dependencies] -"jaraco.text" = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "jaraco-context" -version = "4.3.0" -description = "Context managers by jaraco" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jaraco.context-4.3.0-py3-none-any.whl", hash = "sha256:5d9e95ca0faa78943ed66f6bc658dd637430f16125d86988e77844c741ff2f11"}, - {file = "jaraco.context-4.3.0.tar.gz", hash = "sha256:4dad2404540b936a20acedec53355bdaea223acb88fd329fa6de9261c941566e"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[[package]] -name = "jaraco-functools" -version = "4.0.0" -description = "Functools like those found in stdlib" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.functools-4.0.0-py3-none-any.whl", hash = "sha256:daf276ddf234bea897ef14f43c4e1bf9eefeac7b7a82a4dd69228ac20acff68d"}, - {file = "jaraco.functools-4.0.0.tar.gz", hash = "sha256:c279cb24c93d694ef7270f970d499cab4d3813f4e08273f95398651a634f0925"}, -] - -[package.dependencies] -more-itertools = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["jaraco.classes", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "jaraco-structures" -version = "2.2.0" -description = "Data structures by jaraco" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.structures-2.2.0-py3-none-any.whl", hash = "sha256:d77cc1b43119b58ce3b0d1a395b577a110afa38f2fe7d1cf308362bc47d7c5da"}, - {file = "jaraco.structures-2.2.0.tar.gz", hash = "sha256:93004c2ff4b721a3d3f248b6f5557c31e94a07607e58d9e97dc4b81ce0df7679"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "jaraco-text" -version = "3.12.0" -description = "Module for text manipulation" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.text-3.12.0-py3-none-any.whl", hash = "sha256:1472f5a04a4cf77a0a3867495c24736ed9dc406070634934455323fa3a2c63de"}, - {file = "jaraco.text-3.12.0.tar.gz", hash = "sha256:389e25c8d4b32e9715bf530596fab0f5cd3aa47296e43969392e18a541af592c"}, -] - -[package.dependencies] -autocommand = "*" -importlib-resources = {version = "*", markers = "python_version < \"3.9\""} -inflect = "*" -"jaraco.context" = ">=4.1" -"jaraco.functools" = "*" -more-itertools = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pathlib2", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "jaraco-ui" -version = "2.3.0" -description = "User-Interface tools (mainly command-line)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "jaraco.ui-2.3.0-py3-none-any.whl", hash = "sha256:9d609ea57a4bd3a85e0b8603526bb0a9016667d956a52cd236b0f4e090864fd7"}, - {file = "jaraco.ui-2.3.0.tar.gz", hash = "sha256:afaced6efda5c9715c17be9750687c283ff9ace5fb42d9a1997bedb46f6a8a1a"}, -] - -[package.dependencies] -"jaraco.classes" = "*" -"jaraco.text" = "*" - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["pytest (>=3.5,!=3.7.3)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-enabler", "pytest-flake8", "pytest-mypy"] - -[[package]] -name = "jaraco-windows" -version = "5.8.0" -description = "Windows Routines by Jason R. Coombs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.windows-5.8.0-py3-none-any.whl", hash = "sha256:2fa49ef411c14fd2e59b6879ec68b225608ec125eb121c882847131c027d0ddc"}, - {file = "jaraco.windows-5.8.0.tar.gz", hash = "sha256:9215675639e80f96190203b66c37f56479ee68e20841aa4bca309208dd2d8e10"}, -] - -[package.dependencies] -"jaraco.collections" = "*" -"jaraco.structures" = ">=1.1.1" -"jaraco.text" = "*" -"jaraco.ui" = "*" -more-itertools = "*" -path = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "pywin32", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - [[package]] name = "jedi" version = "0.19.1" @@ -2746,12 +2568,13 @@ files = [ [[package]] name = "kwarray" -version = "0.6.18" +version = "0.7.1" description = "The kwarray module" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "kwarray-0.6.18-py3-none-any.whl", hash = "sha256:e3ea15d4a75b2c999da59ce592be3041f645b5ddcfd10fb73f5b6b65f20e7e28"}, + {file = "kwarray-0.7.1-py3-none-any.whl", hash = "sha256:378eacfeeae27ee967eaa15c49f5141c8ce1f0cf869c1aea8139bf216c6d7f4b"}, + {file = "kwarray-0.7.1.tar.gz", hash = "sha256:80c76a27516a1f371d53c783938e1ebc19588167c8e31725939e6e43bb69cead"}, ] [package.dependencies] @@ -2760,78 +2583,91 @@ packaging = ">=21.3" ubelt = ">=1.2.3" [package.extras] -all = ["coverage (>=4.4.0)", "coverage (>=5.2.1)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=2.0.0)", "nptyping (>=2.4.0)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.19.3,<2.0)", "numpy (>=1.19.3,<2.0)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.3)", "packaging (>=21.3)", "pandas (>=1.0.0)", "pandas (>=1.2.0)", "pandas (>=1.3.5)", "pandas (>=1.4.0)", "pandas (>=1.4.0)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "scipy (>=1.11.2)", "scipy (>=1.2.1)", "scipy (>=1.6.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "torch (>=1.11.0)", "torch (>=1.6.0)", "torch (>=1.9.0)", "torch (>=2.0.0)", "torch (>=2.2.0)", "ubelt (>=1.2.3)", "xdoctest (>=1.1.3)"] -all-strict = ["coverage (==4.4.0)", "coverage (==5.2.1)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==2.0.0)", "nptyping (==2.4.0)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.3)", "packaging (==21.3)", "pandas (==1.0.0)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "pandas (==2.1.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scipy (==1.11.2)", "scipy (==1.2.1)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "torch (==1.11.0)", "torch (==1.6.0)", "torch (==1.9.0)", "torch (==2.0.0)", "torch (==2.2.0)", "ubelt (==1.2.3)", "xdoctest (==1.1.3)"] +all = ["coverage (>=4.4.0)", "coverage (>=5.2.1)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=2.0.0)", "nptyping (>=2.4.0)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "numpy (>=2.1.0)", "packaging (>=21.3)", "packaging (>=21.3)", "pandas (>=1.0.0)", "pandas (>=1.2.0)", "pandas (>=1.3.5)", "pandas (>=1.4.0)", "pandas (>=1.4.0)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "pandas (>=2.2.3)", "pytest (>=4.6.0)", "pytest (>=6.2.5)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "scipy (>=1.11.2)", "scipy (>=1.14.1)", "scipy (>=1.2.1)", "scipy (>=1.6.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "torch (>=1.11.0)", "torch (>=1.6.0)", "torch (>=1.9.0)", "torch (>=2.0.0)", "torch (>=2.2.0)", "torch (>=2.5.0)", "ubelt (>=1.2.3)", "xdoctest (>=1.1.3)"] +all-strict = ["coverage (==4.4.0)", "coverage (==5.2.1)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==2.0.0)", "nptyping (==2.4.0)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "numpy (==2.1.0)", "packaging (==21.3)", "packaging (==21.3)", "pandas (==1.0.0)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "pandas (==2.1.1)", "pandas (==2.2.3)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scipy (==1.11.2)", "scipy (==1.14.1)", "scipy (==1.2.1)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "torch (==1.11.0)", "torch (==1.6.0)", "torch (==1.9.0)", "torch (==2.0.0)", "torch (==2.2.0)", "torch (==2.5.0)", "ubelt (==1.2.3)", "xdoctest (==1.1.3)"] docs = ["Pygments (>=2.9.0)", "kwplot[headless] (>=0.4.15)", "myst-parser (>=0.18.0)", "sphinx (>=5.0.1)", "sphinx-autoapi (>=1.8.4)", "sphinx-autobuild (>=2021.3.14)", "sphinx-reredirects (>=0.0.1)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-napoleon (>=0.7)", "xdoctest (>=1.1.2)"] docs-strict = ["Pygments (==2.9.0)", "kwplot[headless] (==0.4.15)", "myst-parser (==0.18.0)", "sphinx (==5.0.1)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-reredirects (==0.0.1)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)", "xdoctest (==1.1.2)"] -optional = ["nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=2.0.0)", "nptyping (>=2.4.0)", "pandas (>=1.0.0)", "pandas (>=1.2.0)", "pandas (>=1.3.5)", "pandas (>=1.4.0)", "pandas (>=1.4.0)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "scipy (>=1.11.2)", "scipy (>=1.2.1)", "scipy (>=1.6.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "torch (>=1.11.0)", "torch (>=1.6.0)", "torch (>=1.9.0)", "torch (>=2.0.0)", "torch (>=2.2.0)"] -optional-strict = ["nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==2.0.0)", "nptyping (==2.4.0)", "pandas (==1.0.0)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "pandas (==2.1.1)", "scipy (==1.11.2)", "scipy (==1.2.1)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "torch (==1.11.0)", "torch (==1.6.0)", "torch (==1.9.0)", "torch (==2.0.0)", "torch (==2.2.0)"] -runtime = ["numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.19.3,<2.0)", "numpy (>=1.19.3,<2.0)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.3)", "ubelt (>=1.2.3)"] -runtime-strict = ["numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.3)", "ubelt (==1.2.3)"] -tests = ["coverage (>=4.4.0)", "coverage (>=5.2.1)", "packaging (>=21.3)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "xdoctest (>=1.1.3)"] -tests-strict = ["coverage (==4.4.0)", "coverage (==5.2.1)", "packaging (==21.3)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "xdoctest (==1.1.3)"] +linting = ["flake8 (>=5.0.0)"] +linting-strict = ["flake8 (==5.0.0)"] +optional = ["nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=1.4.4)", "nptyping (>=2.0.0)", "nptyping (>=2.4.0)", "pandas (>=1.0.0)", "pandas (>=1.2.0)", "pandas (>=1.3.5)", "pandas (>=1.4.0)", "pandas (>=1.4.0)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "pandas (>=2.2.3)", "scipy (>=1.11.2)", "scipy (>=1.14.1)", "scipy (>=1.2.1)", "scipy (>=1.6.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "torch (>=1.11.0)", "torch (>=1.6.0)", "torch (>=1.9.0)", "torch (>=2.0.0)", "torch (>=2.2.0)", "torch (>=2.5.0)"] +optional-strict = ["nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==1.4.4)", "nptyping (==2.0.0)", "nptyping (==2.4.0)", "pandas (==1.0.0)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "pandas (==2.1.1)", "pandas (==2.2.3)", "scipy (==1.11.2)", "scipy (==1.14.1)", "scipy (==1.2.1)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "torch (==1.11.0)", "torch (==1.6.0)", "torch (==1.9.0)", "torch (==2.0.0)", "torch (==2.2.0)", "torch (==2.5.0)"] +runtime = ["numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "numpy (>=2.1.0)", "packaging (>=21.3)", "ubelt (>=1.2.3)"] +runtime-strict = ["numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "numpy (==2.1.0)", "packaging (==21.3)", "ubelt (==1.2.3)"] +tests = ["coverage (>=4.4.0)", "coverage (>=5.2.1)", "packaging (>=21.3)", "pytest (>=4.6.0)", "pytest (>=6.2.5)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "xdoctest (>=1.1.3)"] +tests-strict = ["coverage (==4.4.0)", "coverage (==5.2.1)", "packaging (==21.3)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "xdoctest (==1.1.3)"] [[package]] name = "kwcoco" -version = "0.7.8" +version = "0.8.6" description = "The kwcoco module and cli for image datasets" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "kwcoco-0.7.8-py3-none-any.whl", hash = "sha256:a5bb2c7765f0c47d966681fd9c1610bcd417c9e57f5cb13e6acf0935fa077a2c"}, + {file = "kwcoco-0.8.6-py3-none-any.whl", hash = "sha256:e43ab830759023d98a5d9445d9d9588344b59b6e8df835efaa6be08344d57f59"}, + {file = "kwcoco-0.8.6.tar.gz", hash = "sha256:f2b3e40c4e1a230c22960a3d85a94cb685fd4f87858a5174e3d9bac265a53e26"}, ] [package.dependencies] -delayed-image = ">=0.2.7" +delayed_image = ">=0.4.2" jsonschema = ">=3.2.0" -kwarray = ">=0.6.12" -kwimage = ">=0.9.19" -networkx = {version = ">=2.7", markers = "python_version < \"3.11\" and python_version >= \"3.8\""} -numpy = {version = ">=1.19.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} +kwarray = ">=0.6.19" +kwimage = ">=0.11.1" +networkx = {version = ">=2.8", markers = "python_version < \"3.11\" and python_version >= \"3.8\""} +numpy = {version = ">=1.19.3", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} packaging = ">=21.3" -pandas = {version = ">=1.4.0", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} -parse = ">=1.14.0" +pandas = {version = ">=1.4.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} +parse = ">=1.19.0" psutil = {version = ">=5.6.3", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} +rich = ">=12.3.0" safer = ">=4.4.1" scikit-learn = {version = ">=1.0.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} scipy = {version = ">=1.8.0", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} -scriptconfig = ">=0.7.7" +scriptconfig = ">=0.7.10" sortedcontainers = ">=2.3.0" -ubelt = ">=1.3.3" +ubelt = ">=1.3.6" uritools = ">=3.0.0" -xarray = ">=0.16.0" - -[package.extras] -all = ["affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.2.1)", "delayed-image (>=0.2.7)", "ijson (>=3.1.4)", "jq (>=1.1.3)", "jq (>=1.1.3)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.3.0)", "jsonschema (>=3.2.0)", "kwarray (>=0.6.12)", "kwimage (>=0.9.19)", "kwimage-ext (>=0.2.0)", "kwimage-ext (>=0.2.1)", "kwplot (>=0.4.13)", "kwutil (>=0.2.4)", "lark (>=1.1.2)", "lark-cython (>=0.0.12)", "matplotlib (>=3.1.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.5.0)", "matplotlib (>=3.5.0)", "networkx (>=2.2.0,<=2.5.1)", "networkx (>=2.6.2)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.2)", "numpy (>=1.19.2)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "packaging (>=21.3)", "pandas (>=1.1.4)", "pandas (>=1.2.0)", "pandas (>=1.3.5)", "pandas (>=1.4.0)", "pandas (>=1.4.0)", "pandas (>=1.5.0)", "parse (>=1.14.0)", "psutil (>=5.0.1)", "psutil (>=5.4.6)", "psutil (>=5.6.3)", "psutil (>=5.7.3)", "psutil (>=5.9.1)", "psutil (>=5.9.1)", "psycopg2-binary (>=2.7.3.2)", "psycopg2-binary (>=2.7.5)", "psycopg2-binary (>=2.8.4)", "psycopg2-binary (>=2.8.6)", "psycopg2-binary (>=2.9.1)", "psycopg2-binary (>=2.9.5)", "pytest (>=6.2.4)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "rich (>=12.3.0)", "rich-argparse (>=1.1.0)", "safer (>=4.4.1)", "scikit-learn (>=0.24.1)", "scikit-learn (>=0.24.1)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.1.0)", "scikit-learn (>=1.1.3)", "scipy (>=1.5.4)", "scipy (>=1.6.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "scriptconfig (>=0.7.7)", "seaborn (>=0.9.0)", "sortedcontainers (>=2.3.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.26)", "sqlalchemy-utils (>=0.40.0)", "timerit (>=0.3.0)", "ubelt (>=1.3.3)", "ujson (>=5.2.0)", "uritools (>=3.0.0)", "xarray (>=0.16.0)", "xdoctest (>=1.1.3)"] -all-strict = ["affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.2.1)", "delayed-image (==0.2.7)", "ijson (==3.1.4)", "jq (==1.1.3)", "jq (==1.1.3)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.3.0)", "jsonschema (==3.2.0)", "kwarray (==0.6.12)", "kwimage (==0.9.19)", "kwimage-ext (==0.2.0)", "kwimage-ext (==0.2.1)", "kwplot (==0.4.13)", "kwutil (==0.2.4)", "lark (==1.1.2)", "lark-cython (==0.0.12)", "matplotlib (==3.1.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.5.0)", "matplotlib (==3.5.0)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "packaging (==21.3)", "pandas (==1.1.4)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "parse (==1.14.0)", "psutil (==5.0.1)", "psutil (==5.4.6)", "psutil (==5.6.3)", "psutil (==5.7.3)", "psutil (==5.9.1)", "psutil (==5.9.1)", "psycopg2-binary (==2.7.3.2)", "psycopg2-binary (==2.7.5)", "psycopg2-binary (==2.8.4)", "psycopg2-binary (==2.8.6)", "psycopg2-binary (==2.9.1)", "psycopg2-binary (==2.9.5)", "pytest (==6.2.4)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "rich (==12.3.0)", "rich-argparse (==1.1.0)", "safer (==4.4.1)", "scikit-learn (==0.24.1)", "scikit-learn (==0.24.1)", "scikit-learn (==1.0.2)", "scikit-learn (==1.0.2)", "scikit-learn (==1.1.0)", "scikit-learn (==1.1.3)", "scipy (==1.5.4)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "scriptconfig (==0.7.7)", "seaborn (==0.9.0)", "sortedcontainers (==2.3.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.26)", "sqlalchemy-utils (==0.40.0)", "timerit (==0.3.0)", "ubelt (==1.3.3)", "ujson (==5.2.0)", "uritools (==3.0.0)", "xarray (==0.16.0)", "xdoctest (==1.1.3)"] -graphics = ["opencv-python (>=3.1.0.0)", "opencv-python (>=3.1.0.2)", "opencv-python (>=3.1.0.5)", "opencv-python (>=3.4.13.47)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=4.5.4.58)", "opencv-python (>=4.5.5.64)"] -graphics-strict = ["opencv-python (==3.1.0.0)", "opencv-python (==3.1.0.2)", "opencv-python (==3.1.0.5)", "opencv-python (==3.4.13.47)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==4.5.4.58)", "opencv-python (==4.5.5.64)"] -headless = ["opencv-python-headless (>=3.4.13.47)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)"] -headless-strict = ["opencv-python-headless (==3.4.13.47)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)"] -optional = ["affine (>=2.3.0)", "colormath (>=3.0.0)", "ijson (>=3.1.4)", "jq (>=1.1.3)", "jq (>=1.1.3)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.3.0)", "kwimage-ext (>=0.2.0)", "kwimage-ext (>=0.2.1)", "kwplot (>=0.4.13)", "kwutil (>=0.2.4)", "lark (>=1.1.2)", "lark-cython (>=0.0.12)", "matplotlib (>=3.1.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.5.0)", "matplotlib (>=3.5.0)", "rich (>=12.3.0)", "rich-argparse (>=1.1.0)", "seaborn (>=0.9.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.26)", "ujson (>=5.2.0)"] -optional-strict = ["affine (==2.3.0)", "colormath (==3.0.0)", "ijson (==3.1.4)", "jq (==1.1.3)", "jq (==1.1.3)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.3.0)", "kwimage-ext (==0.2.0)", "kwimage-ext (==0.2.1)", "kwplot (==0.4.13)", "kwutil (==0.2.4)", "lark (==1.1.2)", "lark-cython (==0.0.12)", "matplotlib (==3.1.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.5.0)", "matplotlib (==3.5.0)", "rich (==12.3.0)", "rich-argparse (==1.1.0)", "seaborn (==0.9.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.26)", "ujson (==5.2.0)"] -postgresql = ["psycopg2-binary (>=2.7.3.2)", "psycopg2-binary (>=2.7.5)", "psycopg2-binary (>=2.8.4)", "psycopg2-binary (>=2.8.6)", "psycopg2-binary (>=2.9.1)", "psycopg2-binary (>=2.9.5)", "sqlalchemy-utils (>=0.40.0)"] -postgresql-strict = ["psycopg2-binary (==2.7.3.2)", "psycopg2-binary (==2.7.5)", "psycopg2-binary (==2.8.4)", "psycopg2-binary (==2.8.6)", "psycopg2-binary (==2.9.1)", "psycopg2-binary (==2.9.5)", "sqlalchemy-utils (==0.40.0)"] -runtime-strict = ["delayed-image (==0.2.7)", "jsonschema (==3.2.0)", "kwarray (==0.6.12)", "kwimage (==0.9.19)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "packaging (==21.3)", "pandas (==1.1.4)", "pandas (==1.2.0)", "pandas (==1.3.5)", "pandas (==1.4.0)", "pandas (==1.4.0)", "pandas (==1.5.0)", "parse (==1.14.0)", "psutil (==5.0.1)", "psutil (==5.4.6)", "psutil (==5.6.3)", "psutil (==5.7.3)", "psutil (==5.9.1)", "psutil (==5.9.1)", "safer (==4.4.1)", "scikit-learn (==0.24.1)", "scikit-learn (==0.24.1)", "scikit-learn (==1.0.2)", "scikit-learn (==1.0.2)", "scikit-learn (==1.1.0)", "scikit-learn (==1.1.3)", "scipy (==1.5.4)", "scipy (==1.6.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "scriptconfig (==0.7.7)", "sortedcontainers (==2.3.0)", "ubelt (==1.3.3)", "uritools (==3.0.0)", "xarray (==0.16.0)"] -tests = ["coverage (>=5.2.1)", "pytest (>=6.2.4)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "timerit (>=0.3.0)", "xdoctest (>=1.1.3)"] -tests-strict = ["coverage (==5.2.1)", "pytest (==6.2.4)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "timerit (==0.3.0)", "xdoctest (==1.1.3)"] +xarray = {version = ">=0.17.0", markers = "python_version < \"3.12\" and python_version >= \"3.8\""} + +[package.extras] +all = ["affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.2.1)", "delayed_image (>=0.4.2)", "ijson (>=3.1.4)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.7.0)", "jq (>=1.7.0)", "jsonschema (>=3.2.0)", "kwarray (>=0.6.19)", "kwgis (>=0.1.0)", "kwimage (>=0.11.1)", "kwimage_ext (>=0.2.0)", "kwimage_ext (>=0.2.1)", "kwplot (>=0.5.2)", "kwutil (>=0.3.3)", "lark (>=1.1.2)", "lark_cython (>=0.0.12)", "matplotlib (>=3.6.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "networkx (>=2.8)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.3)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "parse (>=1.19.0)", "psutil (>=5.6.3)", "psutil (>=5.7.3)", "psutil (>=5.9.1)", "psutil (>=5.9.6)", "psycopg2-binary (>=2.8.4)", "psycopg2-binary (>=2.8.6)", "psycopg2-binary (>=2.9.1)", "psycopg2-binary (>=2.9.5)", "psycopg2-binary (>=2.9.9)", "pytest (>=6.2.4)", "pytest-cov (>=2.12.1)", "rich (>=12.3.0)", "rich_argparse (>=1.1.0)", "safer (>=4.4.1)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.1.0)", "scikit-learn (>=1.1.3)", "scikit-learn (>=1.3.1)", "scipy (>=1.11.2)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "scriptconfig (>=0.7.10)", "seaborn (>=0.11.2)", "seaborn (>=0.13.2)", "sortedcontainers (>=2.3.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.26)", "sqlalchemy (>=1.4.41)", "sqlalchemy (>=2.0.21)", "sqlalchemy_utils (>=0.40.0)", "timerit (>=0.3.0)", "ubelt (>=1.3.6)", "ujson (>=5.2.0)", "uritools (>=3.0.0)", "xarray (>=0.17.0)", "xarray (>=2023.10.0)", "xdoctest (>=1.1.5)"] +all-strict = ["affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.2.1)", "delayed_image (==0.4.2)", "ijson (==3.1.4)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.7.0)", "jq (==1.7.0)", "jsonschema (==3.2.0)", "kwarray (==0.6.19)", "kwgis (==0.1.0)", "kwimage (==0.11.1)", "kwimage_ext (==0.2.0)", "kwimage_ext (==0.2.1)", "kwplot (==0.5.2)", "kwutil (==0.3.3)", "lark (==1.1.2)", "lark_cython (==0.0.12)", "matplotlib (==3.6.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "networkx (==2.8)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.3)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.5.0)", "pandas (==2.1.1)", "parse (==1.19.0)", "psutil (==5.6.3)", "psutil (==5.7.3)", "psutil (==5.9.1)", "psutil (==5.9.6)", "psycopg2-binary (==2.8.4)", "psycopg2-binary (==2.8.6)", "psycopg2-binary (==2.9.1)", "psycopg2-binary (==2.9.5)", "psycopg2-binary (==2.9.9)", "pytest (==6.2.4)", "pytest-cov (==2.12.1)", "rich (==12.3.0)", "rich_argparse (==1.1.0)", "safer (==4.4.1)", "scikit-learn (==1.0.2)", "scikit-learn (==1.0.2)", "scikit-learn (==1.1.0)", "scikit-learn (==1.1.3)", "scikit-learn (==1.3.1)", "scipy (==1.11.2)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "scriptconfig (==0.7.10)", "seaborn (==0.11.2)", "seaborn (==0.13.2)", "sortedcontainers (==2.3.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.26)", "sqlalchemy (==1.4.41)", "sqlalchemy (==2.0.21)", "sqlalchemy_utils (==0.40.0)", "timerit (==0.3.0)", "ubelt (==1.3.6)", "ujson (==5.2.0)", "uritools (==3.0.0)", "xarray (==0.17.0)", "xarray (==2023.10.0)", "xdoctest (==1.1.5)"] +docs = ["Pygments (>=2.9.0)", "affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.2.1)", "delayed_image (>=0.4.2)", "docutils (>=0.20.1)", "ijson (>=3.1.4)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.7.0)", "jq (>=1.7.0)", "jsonschema (>=3.2.0)", "kwarray (>=0.6.19)", "kwgis (>=0.1.0)", "kwimage (>=0.11.1)", "kwimage_ext (>=0.2.0)", "kwimage_ext (>=0.2.1)", "kwplot", "kwplot (>=0.5.2)", "kwutil (>=0.3.3)", "lark (>=1.1.2)", "lark_cython (>=0.0.12)", "matplotlib (>=3.6.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "myst_parser (>=0.18.0)", "networkx (>=2.8)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)", "packaging (>=21.3)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "parse (>=1.19.0)", "psutil (>=5.6.3)", "psutil (>=5.7.3)", "psutil (>=5.9.1)", "psutil (>=5.9.6)", "pytest (>=6.2.4)", "pytest-cov (>=2.12.1)", "rich (>=12.3.0)", "rich_argparse (>=1.1.0)", "safer (>=4.4.1)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.1.0)", "scikit-learn (>=1.1.3)", "scikit-learn (>=1.3.1)", "scipy (>=1.11.2)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "scriptconfig (>=0.7.10)", "seaborn (>=0.11.2)", "seaborn (>=0.13.2)", "six", "sortedcontainers (>=2.3.0)", "sphinx (>=5.0.1)", "sphinx-autoapi (>=1.8.4)", "sphinx-autobuild (>=2021.3.14)", "sphinx-jsonschema (>=1.19.1)", "sphinx-reredirects (>=0.0.1)", "sphinx_rtd_theme (>=1.0.0)", "sphinxcontrib-napoleon (>=0.7)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.26)", "sqlalchemy (>=1.4.41)", "sqlalchemy (>=2.0.21)", "timerit (>=0.3.0)", "ubelt (>=1.3.6)", "ujson (>=5.2.0)", "uritools (>=3.0.0)", "xarray (>=0.17.0)", "xarray (>=2023.10.0)", "xdoctest (>=1.1.5)"] +docs-strict = ["Pygments (==2.9.0)", "affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.2.1)", "delayed_image (==0.4.2)", "docutils (==0.20.1)", "ijson (==3.1.4)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.7.0)", "jq (==1.7.0)", "jsonschema (==3.2.0)", "kwarray (==0.6.19)", "kwgis (==0.1.0)", "kwimage (==0.11.1)", "kwimage_ext (==0.2.0)", "kwimage_ext (==0.2.1)", "kwplot", "kwplot (==0.5.2)", "kwutil (==0.3.3)", "lark (==1.1.2)", "lark_cython (==0.0.12)", "matplotlib (==3.6.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "myst_parser (==0.18.0)", "networkx (==2.8)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)", "packaging (==21.3)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.5.0)", "pandas (==2.1.1)", "parse (==1.19.0)", "psutil (==5.6.3)", "psutil (==5.7.3)", "psutil (==5.9.1)", "psutil (==5.9.6)", "pytest (==6.2.4)", "pytest-cov (==2.12.1)", "rich (==12.3.0)", "rich_argparse (==1.1.0)", "safer (==4.4.1)", "scikit-learn (==1.0.2)", "scikit-learn (==1.0.2)", "scikit-learn (==1.1.0)", "scikit-learn (==1.1.3)", "scikit-learn (==1.3.1)", "scipy (==1.11.2)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "scriptconfig (==0.7.10)", "seaborn (==0.11.2)", "seaborn (==0.13.2)", "six", "sortedcontainers (==2.3.0)", "sphinx (==5.0.1)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-jsonschema (==1.19.1)", "sphinx-reredirects (==0.0.1)", "sphinx_rtd_theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.26)", "sqlalchemy (==1.4.41)", "sqlalchemy (==2.0.21)", "timerit (==0.3.0)", "ubelt (==1.3.6)", "ujson (==5.2.0)", "uritools (==3.0.0)", "xarray (==0.17.0)", "xarray (==2023.10.0)", "xdoctest (==1.1.5)"] +gdal = ["GDAL (>=3.4.1)", "GDAL (>=3.5.2)", "GDAL (>=3.7.2)"] +gdal-strict = ["GDAL (==3.4.1)", "GDAL (==3.5.2)", "GDAL (==3.7.2)"] +graphics = ["opencv-python (>=3.4.15.55)", "opencv-python (>=4.5.4.58)", "opencv-python (>=4.5.5.64)"] +graphics-strict = ["opencv-python (==3.4.15.55)", "opencv-python (==4.5.4.58)", "opencv-python (==4.5.5.64)"] +headless = ["opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)"] +headless-strict = ["opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)"] +linting = ["flake8 (>=5.0.0)"] +linting-strict = ["flake8 (==5.0.0)"] +optional = ["affine (>=2.3.0)", "colormath (>=3.0.0)", "ijson (>=3.1.4)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.2.2)", "jq (>=1.7.0)", "jq (>=1.7.0)", "kwgis (>=0.1.0)", "kwimage_ext (>=0.2.0)", "kwimage_ext (>=0.2.1)", "kwplot (>=0.5.2)", "kwutil (>=0.3.3)", "lark (>=1.1.2)", "lark_cython (>=0.0.12)", "matplotlib (>=3.6.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "matplotlib (>=3.8.2)", "rich_argparse (>=1.1.0)", "seaborn (>=0.11.2)", "seaborn (>=0.13.2)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.0)", "sqlalchemy (>=1.4.26)", "sqlalchemy (>=1.4.41)", "sqlalchemy (>=2.0.21)", "ujson (>=5.2.0)"] +optional-strict = ["affine (==2.3.0)", "colormath (==3.0.0)", "ijson (==3.1.4)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.2.2)", "jq (==1.7.0)", "jq (==1.7.0)", "kwgis (==0.1.0)", "kwimage_ext (==0.2.0)", "kwimage_ext (==0.2.1)", "kwplot (==0.5.2)", "kwutil (==0.3.3)", "lark (==1.1.2)", "lark_cython (==0.0.12)", "matplotlib (==3.6.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "matplotlib (==3.8.2)", "rich_argparse (==1.1.0)", "seaborn (==0.11.2)", "seaborn (==0.13.2)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.0)", "sqlalchemy (==1.4.26)", "sqlalchemy (==1.4.41)", "sqlalchemy (==2.0.21)", "ujson (==5.2.0)"] +postgresql = ["psycopg2-binary (>=2.8.4)", "psycopg2-binary (>=2.8.6)", "psycopg2-binary (>=2.9.1)", "psycopg2-binary (>=2.9.5)", "psycopg2-binary (>=2.9.9)", "sqlalchemy_utils (>=0.40.0)"] +postgresql-strict = ["psycopg2-binary (==2.8.4)", "psycopg2-binary (==2.8.6)", "psycopg2-binary (==2.9.1)", "psycopg2-binary (==2.9.5)", "psycopg2-binary (==2.9.9)", "sqlalchemy_utils (==0.40.0)"] +runtime = ["delayed_image (>=0.4.2)", "jsonschema (>=3.2.0)", "kwarray (>=0.6.19)", "kwimage (>=0.11.1)", "networkx (>=2.8)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.3)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.4.2)", "pandas (>=1.5.0)", "pandas (>=2.1.1)", "parse (>=1.19.0)", "psutil (>=5.6.3)", "psutil (>=5.7.3)", "psutil (>=5.9.1)", "psutil (>=5.9.6)", "rich (>=12.3.0)", "safer (>=4.4.1)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.0.2)", "scikit-learn (>=1.1.0)", "scikit-learn (>=1.1.3)", "scikit-learn (>=1.3.1)", "scipy (>=1.11.2)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.8.0)", "scipy (>=1.9.2)", "scriptconfig (>=0.7.10)", "sortedcontainers (>=2.3.0)", "ubelt (>=1.3.6)", "uritools (>=3.0.0)", "xarray (>=0.17.0)", "xarray (>=2023.10.0)"] +runtime-strict = ["delayed_image (==0.4.2)", "jsonschema (==3.2.0)", "kwarray (==0.6.19)", "kwimage (==0.11.1)", "networkx (==2.8)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.3)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.4.2)", "pandas (==1.5.0)", "pandas (==2.1.1)", "parse (==1.19.0)", "psutil (==5.6.3)", "psutil (==5.7.3)", "psutil (==5.9.1)", "psutil (==5.9.6)", "rich (==12.3.0)", "safer (==4.4.1)", "scikit-learn (==1.0.2)", "scikit-learn (==1.0.2)", "scikit-learn (==1.1.0)", "scikit-learn (==1.1.3)", "scikit-learn (==1.3.1)", "scipy (==1.11.2)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.8.0)", "scipy (==1.9.2)", "scriptconfig (==0.7.10)", "sortedcontainers (==2.3.0)", "ubelt (==1.3.6)", "uritools (==3.0.0)", "xarray (==0.17.0)", "xarray (==2023.10.0)"] +tests = ["coverage (>=5.2.1)", "pytest (>=6.2.4)", "pytest-cov (>=2.12.1)", "timerit (>=0.3.0)", "xdoctest (>=1.1.5)"] +tests-strict = ["coverage (==5.2.1)", "pytest (==6.2.4)", "pytest-cov (==2.12.1)", "timerit (==0.3.0)", "xdoctest (==1.1.5)"] [[package]] name = "kwimage" -version = "0.9.25" +version = "0.11.1" description = "The kwimage module" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "kwimage-0.9.25-py3-none-any.whl", hash = "sha256:b4cba2b3f72abfde3d8ee271137f849cc38c1fe5b2a103e85e43e60b37dcfed9"}, + {file = "kwimage-0.11.1-py3-none-any.whl", hash = "sha256:a1eb771ea57642c3f40ede2d307aa4994d42cf70b9b91f7e1c1bb4cd930c5a46"}, + {file = "kwimage-0.11.1.tar.gz", hash = "sha256:a142fcb1ae3e8dc806400dd02b71e8b33e70c1c2d4ef5822b97d1a86f3b06110"}, ] [package.dependencies] affine = ">=2.3.0" distinctipy = {version = ">=1.2.1", markers = "python_version < \"4.0\" and python_version >= \"3.8\""} -kwarray = ">=0.6.7" +kwarray = ">=0.6.19" +lazy-loader = ">=0.3" networkx = {version = ">=2.7", markers = "python_version < \"3.11\" and python_version >= \"3.8\""} -numpy = {version = ">=1.19.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} +numpy = {version = ">=1.19.3", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} parse = ">=1.14.0" Pillow = {version = ">=8.0.0", markers = "python_version < \"3.10\" and python_version >= \"3.6\""} scikit-image = {version = ">=0.17.2", markers = "python_version < \"3.9\" and python_version >= \"3.8\""} @@ -2840,27 +2676,24 @@ shapely = {version = ">=1.7.1", markers = "python_version < \"3.9\" and python_v ubelt = ">=1.3.3" [package.extras] -all = ["Cython (>=0.25.2)", "Cython (>=0.28.3)", "Cython (>=0.29.23)", "Cython (>=0.29.23)", "Cython (>=0.29.25)", "Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "PyTurboJPEG", "affine (>=2.3.0)", "cffi (>=1.14.5)", "cffi (>=1.14.5)", "cffi (>=1.14.5)", "cffi (>=1.15.0)", "cffi (>=1.15.0)", "cffi (>=1.7.0)", "cffi (>=1.7.0)", "cffi (>=1.7.0)", "cmake (>=3.21.3)", "colormath (>=3.0.0)", "coverage (>=5.3.1)", "distinctipy (>=1.2.1)", "distinctipy (>=1.2.1,<1.3.2)", "itk-io (>=5.1.2)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.3.0)", "itk-io (>=5.3.0)", "kwarray (>=0.6.7)", "kwimage-ext (>=0.2.1)", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.3.3)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "networkx (>=2.2.0,<=2.5.1)", "networkx (>=2.6.2)", "networkx (>=2.7)", "networkx (>=2.8)", "ninja (>=1.10.0)", "ninja (>=1.10.0)", "numpy (>=1.19.2)", "numpy (>=1.19.2)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "parse (>=1.14.0)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "scikit-build (>=0.11.0)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "timerit (>=0.3.0)", "torch (>=1.11.0)", "torch (>=1.13.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)", "ubelt (>=0.10.1)", "ubelt (>=1.3.3)", "xdoctest (>=1.1.3)"] -all-strict = ["Cython (==0.25.2)", "Cython (==0.28.3)", "Cython (==0.29.23)", "Cython (==0.29.23)", "Cython (==0.29.25)", "Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "PyTurboJPEG", "affine (==2.3.0)", "cffi (==1.14.5)", "cffi (==1.14.5)", "cffi (==1.14.5)", "cffi (==1.15.0)", "cffi (==1.15.0)", "cffi (==1.7.0)", "cffi (==1.7.0)", "cffi (==1.7.0)", "cmake (==3.21.3)", "colormath (==3.0.0)", "coverage (==5.3.1)", "distinctipy (==1.2.1)", "distinctipy (==1.2.1)", "itk-io (==5.1.2)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.3.0)", "itk-io (==5.3.0)", "kwarray (==0.6.7)", "kwimage-ext (==0.2.1)", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.3.3)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "ninja (==1.10.0)", "ninja (==1.10.0)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "parse (==1.14.0)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "scikit-build (==0.11.0)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "timerit (==0.3.0)", "torch (==1.11.0)", "torch (==1.13.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)", "ubelt (==0.10.1)", "ubelt (==1.3.3)", "xdoctest (==1.1.3)"] -build = ["Cython (>=0.25.2)", "Cython (>=0.28.3)", "Cython (>=0.29.23)", "Cython (>=0.29.23)", "Cython (>=0.29.25)", "cffi (>=1.14.5)", "cffi (>=1.14.5)", "cffi (>=1.14.5)", "cffi (>=1.15.0)", "cffi (>=1.15.0)", "cffi (>=1.7.0)", "cffi (>=1.7.0)", "cffi (>=1.7.0)", "cmake (>=3.21.3)", "ninja (>=1.10.0)", "ninja (>=1.10.0)", "numpy (>=1.19.2)", "scikit-build (>=0.11.0)", "ubelt (>=0.10.1)"] -build-strict = ["Cython (==0.25.2)", "Cython (==0.28.3)", "Cython (==0.29.23)", "Cython (==0.29.23)", "Cython (==0.29.25)", "cffi (==1.14.5)", "cffi (==1.14.5)", "cffi (==1.14.5)", "cffi (==1.15.0)", "cffi (==1.15.0)", "cffi (==1.7.0)", "cffi (==1.7.0)", "cffi (==1.7.0)", "cmake (==3.21.3)", "ninja (==1.10.0)", "ninja (==1.10.0)", "numpy (==1.19.2)", "scikit-build (==0.11.0)", "ubelt (==0.10.1)"] -docs = ["Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "PyTurboJPEG", "Pygments (>=2.9.0)", "affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.3.1)", "distinctipy (>=1.2.1)", "distinctipy (>=1.2.1,<1.3.2)", "itk-io (>=5.1.2)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.3.0)", "itk-io (>=5.3.0)", "kwarray (>=0.6.7)", "kwimage-ext (>=0.2.1)", "kwplot", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.3.3)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "myst-parser (>=0.18.0)", "networkx (>=2.2.0,<=2.5.1)", "networkx (>=2.6.2)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.2)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "opencv-python-headless (>=3.4.13.47)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)", "parse (>=1.14.0)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "six", "sphinx (>=5.0.1)", "sphinx-autoapi (>=1.8.4)", "sphinx-autobuild (>=2021.3.14)", "sphinx-reredirects (>=0.0.1)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-napoleon (>=0.7)", "sympy", "timerit (>=0.3.0)", "torch (>=1.11.0)", "torch (>=1.13.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)", "ubelt (>=1.3.3)", "xdoctest (>=1.1.3)"] -docs-strict = ["Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "PyTurboJPEG", "Pygments (==2.9.0)", "affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.3.1)", "distinctipy (==1.2.1)", "distinctipy (==1.2.1)", "itk-io (==5.1.2)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.3.0)", "itk-io (==5.3.0)", "kwarray (==0.6.7)", "kwimage-ext (==0.2.1)", "kwplot", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.3.3)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "myst-parser (==0.18.0)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "opencv-python-headless (==3.4.13.47)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)", "parse (==1.14.0)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "six", "sphinx (==5.0.1)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-reredirects (==0.0.1)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)", "sympy", "timerit (==0.3.0)", "torch (==1.11.0)", "torch (==1.13.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)", "ubelt (==1.3.3)", "xdoctest (==1.1.3)"] -gdal = ["GDAL (>=3.4.1)", "GDAL (>=3.4.1)", "GDAL (>=3.5.2)"] -gdal-strict = ["GDAL (==3.4.1)", "GDAL (==3.4.1)", "GDAL (==3.5.2)"] -gdal-strict-strict = ["GDAL (==3.4.1)", "GDAL (==3.4.1)", "GDAL (==3.5.2)"] +all = ["Pillow (>=10.0.0)", "Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "PyTurboJPEG", "affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=7.2.7)", "distinctipy (>=1.2.1)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "kwarray (>=0.6.19)", "kwimage-ext (>=0.2.1)", "lazy-loader (>=0.3)", "matplotlib (>=3.1.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "matplotlib (>=3.7.3)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "parse (>=1.14.0)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scikit-image (>=0.22.0)", "scipy (>=1.11.2)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "shapely (>=2.0.2)", "timerit (>=0.3.0)", "torch (>=1.11.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)", "torch (>=2.0.0)", "torch (>=2.2.0)", "ubelt (>=1.3.3)", "xdoctest (>=1.1.5)"] +all-strict = ["Pillow (==10.0.0)", "Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "PyTurboJPEG", "affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==7.2.7)", "distinctipy (==1.2.1)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "kwarray (==0.6.19)", "kwimage-ext (==0.2.1)", "lazy-loader (==0.3)", "matplotlib (==3.1.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "matplotlib (==3.7.3)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "parse (==1.14.0)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scikit-image (==0.22.0)", "scipy (==1.11.2)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "shapely (==2.0.2)", "timerit (==0.3.0)", "torch (==1.11.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)", "torch (==2.0.0)", "torch (==2.2.0)", "ubelt (==1.3.3)", "xdoctest (==1.1.5)"] +docs = ["Pillow (>=10.0.0)", "Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "PyTurboJPEG", "Pygments (>=2.9.0)", "affine (>=2.3.0)", "colormath (>=3.0.0)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=7.2.7)", "distinctipy (>=1.2.1)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "kwarray (>=0.6.19)", "kwimage-ext (>=0.2.1)", "kwplot", "lazy-loader (>=0.3)", "matplotlib (>=3.1.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "matplotlib (>=3.7.3)", "myst-parser (>=0.18.0)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "opencv-python-headless (>=3.4.13.47)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)", "parse (>=1.14.0)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scikit-image (>=0.22.0)", "scipy (>=1.11.2)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "shapely (>=2.0.2)", "six", "sphinx (>=5.0.1)", "sphinx-autoapi (>=1.8.4)", "sphinx-autobuild (>=2021.3.14)", "sphinx-reredirects (>=0.0.1)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-napoleon (>=0.7)", "sympy", "timerit (>=0.3.0)", "torch (>=1.11.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)", "torch (>=2.0.0)", "torch (>=2.2.0)", "ubelt (>=1.3.3)", "xdoctest (>=1.1.5)"] +docs-strict = ["Pillow (==10.0.0)", "Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "PyTurboJPEG", "Pygments (==2.9.0)", "affine (==2.3.0)", "colormath (==3.0.0)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==7.2.7)", "distinctipy (==1.2.1)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "kwarray (==0.6.19)", "kwimage-ext (==0.2.1)", "kwplot", "lazy-loader (==0.3)", "matplotlib (==3.1.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "matplotlib (==3.7.3)", "myst-parser (==0.18.0)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "opencv-python-headless (==3.4.13.47)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)", "parse (==1.14.0)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scikit-image (==0.22.0)", "scipy (==1.11.2)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "shapely (==2.0.2)", "six", "sphinx (==5.0.1)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-reredirects (==0.0.1)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)", "sympy", "timerit (==0.3.0)", "torch (==1.11.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)", "torch (==2.0.0)", "torch (==2.2.0)", "ubelt (==1.3.3)", "xdoctest (==1.1.5)"] +gdal = ["GDAL (>=3.4.1)", "GDAL (>=3.4.1)", "GDAL (>=3.5.2)", "GDAL (>=3.7.2)"] +gdal-strict = ["GDAL (==3.4.1)", "GDAL (==3.4.1)", "GDAL (==3.5.2)", "GDAL (==3.7.2)"] graphics = ["opencv-python (>=3.1.0.0)", "opencv-python (>=3.1.0.2)", "opencv-python (>=3.1.0.5)", "opencv-python (>=3.4.13.47)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=3.4.15.55)", "opencv-python (>=4.5.4.58)", "opencv-python (>=4.5.5.64)"] graphics-strict = ["opencv-python (==3.1.0.0)", "opencv-python (==3.1.0.2)", "opencv-python (==3.1.0.5)", "opencv-python (==3.4.13.47)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==3.4.15.55)", "opencv-python (==4.5.4.58)", "opencv-python (==4.5.5.64)"] headless = ["opencv-python-headless (>=3.4.13.47)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.15.55)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=3.4.2.16)", "opencv-python-headless (>=4.5.4.58)", "opencv-python-headless (>=4.5.5.64)"] headless-strict = ["opencv-python-headless (==3.4.13.47)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.15.55)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==3.4.2.16)", "opencv-python-headless (==4.5.4.58)", "opencv-python-headless (==4.5.5.64)"] -optional = ["PyTurboJPEG", "colormath (>=3.0.0)", "itk-io (>=5.1.2)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.2.1)", "itk-io (>=5.3.0)", "itk-io (>=5.3.0)", "kwimage-ext (>=0.2.1)", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.1.0)", "matplotlib (>=3.3.3)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "torch (>=1.11.0)", "torch (>=1.13.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)"] -optional-strict = ["PyTurboJPEG", "colormath (==3.0.0)", "itk-io (==5.1.2)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.2.1)", "itk-io (==5.3.0)", "itk-io (==5.3.0)", "kwimage-ext (==0.2.1)", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.1.0)", "matplotlib (==3.3.3)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "torch (==1.11.0)", "torch (==1.13.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)"] +optional = ["PyTurboJPEG", "colormath (>=3.0.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-filtering (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "itk-io (>=5.4.0)", "kwimage-ext (>=0.2.1)", "matplotlib (>=3.1.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.4.0)", "matplotlib (>=3.5.0)", "matplotlib (>=3.6.2)", "matplotlib (>=3.7.3)", "torch (>=1.11.0)", "torch (>=1.7.0)", "torch (>=1.7.0)", "torch (>=1.7.1)", "torch (>=1.7.1)", "torch (>=2.0.0)", "torch (>=2.2.0)"] +optional-strict = ["PyTurboJPEG", "colormath (==3.0.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-filtering (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "itk-io (==5.4.0)", "kwimage-ext (==0.2.1)", "matplotlib (==3.1.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.4.0)", "matplotlib (==3.5.0)", "matplotlib (==3.6.2)", "matplotlib (==3.7.3)", "torch (==1.11.0)", "torch (==1.7.0)", "torch (==1.7.0)", "torch (==1.7.1)", "torch (==1.7.1)", "torch (==2.0.0)", "torch (==2.2.0)"] problematic = ["gdal (>=3.3.0)", "imgaug"] problematic-strict = ["gdal (==3.3.0)", "imgaug"] -runtime = ["Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "affine (>=2.3.0)", "distinctipy (>=1.2.1)", "distinctipy (>=1.2.1,<1.3.2)", "kwarray (>=0.6.7)", "networkx (>=2.2.0,<=2.5.1)", "networkx (>=2.6.2)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.2)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.2,<2.0)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "parse (>=1.14.0)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "ubelt (>=1.3.3)"] -runtime-strict = ["Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "affine (==2.3.0)", "distinctipy (==1.2.1)", "distinctipy (==1.2.1)", "kwarray (==0.6.7)", "networkx (==2.2.0)", "networkx (==2.6.2)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "parse (==1.14.0)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "ubelt (==1.3.3)"] -tests = ["coverage (>=5.3.1)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "timerit (>=0.3.0)", "xdoctest (>=1.1.3)"] -tests-strict = ["coverage (==5.3.1)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "timerit (==0.3.0)", "xdoctest (==1.1.3)"] +runtime = ["Pillow (>=10.0.0)", "Pillow (>=8.0.0)", "Pillow (>=9.1.0)", "Pillow (>=9.2.0)", "affine (>=2.3.0)", "distinctipy (>=1.2.1)", "kwarray (>=0.6.19)", "lazy-loader (>=0.3)", "networkx (>=2.7)", "networkx (>=2.8)", "numpy (>=1.19.3)", "numpy (>=1.19.3)", "numpy (>=1.21.6)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "parse (>=1.14.0)", "scikit-image (>=0.17.2)", "scikit-image (>=0.18.0)", "scikit-image (>=0.19.0)", "scikit-image (>=0.20.0)", "scikit-image (>=0.22.0)", "scipy (>=1.11.2)", "scipy (>=1.5.3)", "scipy (>=1.5.3)", "scipy (>=1.5.4)", "scipy (>=1.5.4)", "scipy (>=1.7.2)", "scipy (>=1.9.2)", "shapely (>=1.7.1)", "shapely (>=1.7.1)", "shapely (>=1.8.2)", "shapely (>=1.8.5)", "shapely (>=2.0.2)", "ubelt (>=1.3.3)"] +runtime-strict = ["Pillow (==10.0.0)", "Pillow (==8.0.0)", "Pillow (==9.1.0)", "Pillow (==9.2.0)", "affine (==2.3.0)", "distinctipy (==1.2.1)", "kwarray (==0.6.19)", "lazy-loader (==0.3)", "networkx (==2.7)", "networkx (==2.8)", "numpy (==1.19.3)", "numpy (==1.19.3)", "numpy (==1.21.6)", "numpy (==1.23.2)", "numpy (==1.26.0)", "parse (==1.14.0)", "scikit-image (==0.17.2)", "scikit-image (==0.18.0)", "scikit-image (==0.19.0)", "scikit-image (==0.20.0)", "scikit-image (==0.22.0)", "scipy (==1.11.2)", "scipy (==1.5.3)", "scipy (==1.5.3)", "scipy (==1.5.4)", "scipy (==1.5.4)", "scipy (==1.7.2)", "scipy (==1.9.2)", "shapely (==1.7.1)", "shapely (==1.7.1)", "shapely (==1.8.2)", "shapely (==1.8.5)", "shapely (==2.0.2)", "ubelt (==1.3.3)"] +tests = ["coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=7.2.7)", "pytest (>=6.2.5)", "pytest-cov (>=2.0.0,<2.6.0)", "pytest-cov (>=2.12.1)", "timerit (>=0.3.0)", "xdoctest (>=1.1.5)"] +tests-strict = ["coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==7.2.7)", "pytest (==6.2.5)", "pytest-cov (==2.0.0)", "pytest-cov (==2.12.1)", "timerit (==0.3.0)", "xdoctest (==1.1.5)"] [[package]] name = "langchain" @@ -3418,17 +3251,6 @@ url = "https://github.com/periakiva/mmpose.git" reference = "exp" resolved_reference = "866d6ff38402db428dc0e8b0fac807290e9c6ba4" -[[package]] -name = "more-itertools" -version = "10.2.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.8" -files = [ - {file = "more-itertools-10.2.0.tar.gz", hash = "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1"}, - {file = "more_itertools-10.2.0-py3-none-any.whl", hash = "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684"}, -] - [[package]] name = "moviepy" version = "1.0.3" @@ -3882,7 +3704,9 @@ description = "CUDA Runtime native Libraries" optional = false python-versions = ">=3" files = [ + {file = "nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6116fad3e049e04791c0256a9778c16237837c08b27ed8c8401e2e45de8d60cd"}, {file = "nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_aarch64.whl", hash = "sha256:d461264ecb429c84c8879a7153499ddc7b19b5f8d84c204307491989a365588e"}, + {file = "nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba3b56a4f896141e25e19ab287cd71e52a6a0f4b29d0d31609f60e3b4d5219b7"}, {file = "nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a84d15d5e1da416dd4774cb42edf5e954a3e60cc945698dc1d5be02321c44dc8"}, {file = "nvidia_cuda_runtime_cu12-12.6.77-py3-none-win_amd64.whl", hash = "sha256:86c58044c824bf3c173c49a2dbc7a6c8b53cb4e4dca50068be0bf64e9dab3f7f"}, ] @@ -4127,21 +3951,6 @@ files = [ qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] testing = ["docopt", "pytest (<6.0.0)"] -[[package]] -name = "path" -version = "16.10.0" -description = "A module wrapper for os.path" -optional = false -python-versions = ">=3.8" -files = [ - {file = "path-16.10.0-py3-none-any.whl", hash = "sha256:902afa16e63943c1d6f14d9f74a6603beaa56980807e0234098256fd0ac33fed"}, - {file = "path-16.10.0.tar.gz", hash = "sha256:b32b22b76fe810a8ded6d136268cc8b6698ae7c47c29b94a9ea12623f3051e46"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["appdirs", "more-itertools", "packaging", "pygments", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "pywin32"] - [[package]] name = "pathspec" version = "0.12.1" @@ -6835,30 +6644,24 @@ files = [ [[package]] name = "ubelt" -version = "1.3.5" +version = "1.3.6" description = "A Python utility belt containing simple tools, a stdlib like feel, and extra batteries" optional = false python-versions = ">=3.6" files = [ - {file = "ubelt-1.3.5-py3-none-any.whl", hash = "sha256:23e7ac788b05fa797d01c12fc74942355de51f575ed038eeaa8a545fda3c24f7"}, - {file = "ubelt-1.3.5.tar.gz", hash = "sha256:c981c5fbce5c8bcebf02564d25b9bd984aba0efbee215de5fbd354ed64c9ee65"}, + {file = "ubelt-1.3.6-py3-none-any.whl", hash = "sha256:2a38f260e7f3c25d3618f653d5c900230dc5af56bf0bc1ff85cfdbe9d0c88f0f"}, + {file = "ubelt-1.3.6.tar.gz", hash = "sha256:327a516a1fc95595096727ae3ae879379bc56fc11fb945857b971ef85a74f698"}, ] -[package.dependencies] -"jaraco.windows" = {version = ">=3.9.1", markers = "platform_system == \"Windows\""} -pydantic = {version = "<2.0", markers = "platform_system == \"Windows\" and platform_python_implementation == \"PyPy\""} - [package.extras] -all = ["Pygments (>=2.2.0)", "colorama (>=0.4.3)", "coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=7.3.0)", "jaraco.windows (>=3.9.1)", "numpy (>=1.12.0,<2.0.0)", "numpy (>=1.14.5,<2.0.0)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.1)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.0)", "pydantic (<2.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "python-dateutil (>=2.8.1)", "requests (>=2.25.1)", "xdoctest (>=1.1.2)", "xxhash (>=1.3.0)", "xxhash (>=1.3.0)", "xxhash (>=1.4.3)", "xxhash (>=2.0.2)", "xxhash (>=3.0.0)", "xxhash (>=3.2.0)", "xxhash (>=3.4.1)"] -all-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==7.3.0)", "jaraco.windows (==3.9.1)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.0)", "pydantic (<2.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "python-dateutil (==2.8.1)", "requests (==2.25.1)", "xdoctest (==1.1.2)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)", "xxhash (==3.4.1)"] +all = ["Pygments (>=2.2.0)", "colorama (>=0.4.3)", "coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=7.3.0)", "jaraco.windows (>=3.9.1)", "numpy (>=1.12.0,<2.0.0)", "numpy (>=1.14.5,<2.0.0)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.1)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.0)", "pydantic (<2.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest (>=8.1.1)", "pytest (>=8.1.1)", "pytest (>=8.1.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "pytest-timeout (>=2.3.1)", "python-dateutil (>=2.8.1)", "requests (>=2.25.1)", "xdoctest (>=1.1.3)", "xxhash (>=1.3.0)", "xxhash (>=1.3.0)", "xxhash (>=1.4.3)", "xxhash (>=2.0.2)", "xxhash (>=3.0.0)", "xxhash (>=3.2.0)", "xxhash (>=3.4.1)"] +all-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==7.3.0)", "jaraco.windows (==3.9.1)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.0)", "pydantic (<2.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==8.1.1)", "pytest (==8.1.1)", "pytest (==8.1.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "pytest-timeout (==2.3.1)", "python-dateutil (==2.8.1)", "requests (==2.25.1)", "xdoctest (==1.1.3)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)", "xxhash (==3.4.1)"] docs = ["Pygments (>=2.9.0)", "myst-parser (>=0.16.1)", "sphinx (>=4.3.2)", "sphinx-autoapi (>=1.8.4)", "sphinx-autobuild (>=2021.3.14)", "sphinx-reredirects (>=0.0.1)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-napoleon (>=0.7)"] docs-strict = ["Pygments (==2.9.0)", "myst-parser (==0.16.1)", "sphinx (==4.3.2)", "sphinx-autoapi (==1.8.4)", "sphinx-autobuild (==2021.3.14)", "sphinx-reredirects (==0.0.1)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)"] -optional = ["Pygments (>=2.2.0)", "colorama (>=0.4.3)", "numpy (>=1.12.0,<2.0.0)", "numpy (>=1.14.5,<2.0.0)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.1)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.0)", "python-dateutil (>=2.8.1)", "xxhash (>=1.3.0)", "xxhash (>=1.3.0)", "xxhash (>=1.4.3)", "xxhash (>=2.0.2)", "xxhash (>=3.0.0)", "xxhash (>=3.2.0)", "xxhash (>=3.4.1)"] -optional-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.0)", "python-dateutil (==2.8.1)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)", "xxhash (==3.4.1)"] -runtime = ["jaraco.windows (>=3.9.1)", "pydantic (<2.0)"] -runtime-strict = ["jaraco.windows (==3.9.1)", "pydantic (<2.0)"] -tests = ["coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=7.3.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "requests (>=2.25.1)", "xdoctest (>=1.1.2)"] -tests-strict = ["coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==7.3.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "requests (==2.25.1)", "xdoctest (==1.1.2)"] +optional = ["Pygments (>=2.2.0)", "colorama (>=0.4.3)", "jaraco.windows (>=3.9.1)", "numpy (>=1.12.0,<2.0.0)", "numpy (>=1.14.5,<2.0.0)", "numpy (>=1.19.2)", "numpy (>=1.19.3)", "numpy (>=1.21.1)", "numpy (>=1.23.2)", "numpy (>=1.26.0)", "packaging (>=21.0)", "pydantic (<2.0)", "python-dateutil (>=2.8.1)", "xxhash (>=1.3.0)", "xxhash (>=1.3.0)", "xxhash (>=1.4.3)", "xxhash (>=2.0.2)", "xxhash (>=3.0.0)", "xxhash (>=3.2.0)", "xxhash (>=3.4.1)"] +optional-strict = ["Pygments (==2.2.0)", "colorama (==0.4.3)", "jaraco.windows (==3.9.1)", "numpy (==1.12.0)", "numpy (==1.14.5)", "numpy (==1.19.2)", "numpy (==1.19.3)", "numpy (==1.21.1)", "numpy (==1.23.2)", "numpy (==1.26.0)", "packaging (==21.0)", "pydantic (<2.0)", "python-dateutil (==2.8.1)", "xxhash (==1.3.0)", "xxhash (==1.3.0)", "xxhash (==1.4.3)", "xxhash (==2.0.2)", "xxhash (==3.0.0)", "xxhash (==3.2.0)", "xxhash (==3.4.1)"] +tests = ["coverage (>=4.3.4)", "coverage (>=4.5)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=5.3.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=6.1.1)", "coverage (>=7.3.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=4.6.11)", "pytest (>=4.6.0,<=6.1.2)", "pytest (>=6.2.5)", "pytest (>=8.1.1)", "pytest (>=8.1.1)", "pytest (>=8.1.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.8.1)", "pytest-cov (>=2.9.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=1.4.2)", "pytest-timeout (>=2.3.1)", "requests (>=2.25.1)", "xdoctest (>=1.1.3)"] +tests-strict = ["coverage (==4.3.4)", "coverage (==4.5)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==5.3.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==6.1.1)", "coverage (==7.3.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest (==8.1.1)", "pytest (==8.1.1)", "pytest (==8.1.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "pytest-timeout (==1.4.2)", "pytest-timeout (==2.3.1)", "requests (==2.25.1)", "xdoctest (==1.1.3)"] types = ["autoflake (>=1.4)", "mypy", "yapf (>=0.32.0)"] types-strict = ["autoflake (==1.4)", "mypy", "yapf (==0.32.0)"] From 6144a7746bf6fef418efa0ec1b13f7b2c6a6c089 Mon Sep 17 00:00:00 2001 From: Joseph VanPelt Date: Fri, 13 Dec 2024 13:05:13 -0500 Subject: [PATCH 18/26] add r19.yaml --- config/activity_labels/medical/r19.yaml | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 config/activity_labels/medical/r19.yaml diff --git a/config/activity_labels/medical/r19.yaml b/config/activity_labels/medical/r19.yaml new file mode 100644 index 000000000..ec4d643bf --- /dev/null +++ b/config/activity_labels/medical/r19.yaml @@ -0,0 +1,28 @@ +version: "1" +title: "Needle_Chest_Decomp" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + - id: 1 + label: "locate-insertion-site" + full_str: "Locate insertion site at the second intercostal space at the midclavicular line." + - id: 2 + label: "wipe-insertion-site" + full_str: "Wipe the insertion site with an alcohol wipe." + - id: 3 + label: "prepare-catheter-and-needle" + full_str: "Prepare catheter and needle." + - id: 4 + label: "insert-needle" + full_str: "Insert needle into insertion site." + - id: 5 + label: "remove-needle" + full_str: "Remove needle, keeping catheter inside the patient." + - id: 6 + label: "apply-tape" + full_str: "Apply tape around catheter to secure it in place." From 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Tue, 24 Dec 2024 16:30:13 -0500 Subject: [PATCH 19/26] working F1 and SMD metrics --- .../global_step_predictor.py | 21 ++++-- .../global_step_prediction/run_expirement.py | 71 +++++++++++++++++-- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/angel_system/global_step_prediction/global_step_predictor.py b/angel_system/global_step_prediction/global_step_predictor.py index 36c934d2f..afdaa91a5 100644 --- a/angel_system/global_step_prediction/global_step_predictor.py +++ b/angel_system/global_step_prediction/global_step_predictor.py @@ -951,26 +951,33 @@ def save_TP_FP_FN_per_class(self, step_gts): Output form: TP, FP, FN, where each is an N-dimensional vector, where N = number of step classes. """ - step_gts = [float(i) for i in step_gts][24:] assert len(self.trackers) == 1 for i, tracker in enumerate(self.trackers): #import ipdb; ipdb.set_trace() step_predictions = tracker["granular_step_prediction_history"] - if len(step_predictions) * 1.8 < len(step_gts): - # This must be a 30Hz video, not 15Hz. Take every other GT frame. - step_gts = [a for ind, a in enumerate(step_gts) if i%2==0] TP = np.zeros(len(self.avg_probs)) FP = np.zeros(len(self.avg_probs)) FN = np.zeros(len(self.avg_probs)) for ind in range(len(self.avg_probs)): # i = the index we'll get TP, FN, and FP for. - _TP = len([a for j, a in enumerate(step_predictions) if a == ind and step_gts[j] == ind]) + _TP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] == ind]) TP[ind] = _TP - _FP = len([a for j, a in enumerate(step_predictions) if a == ind and step_gts[j] != ind]) + _FP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] != ind]) FP[ind] = _FP - _FN = len([a for j, a in enumerate(step_predictions) if a != ind and step_gts[j] == ind]) + _FN = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a != ind and step_gts[j] == ind]) FN[ind] = _FN return TP, FP, FN + def get_single_tracker_pred_history(self): + """ + Get a single tracker's prediction history. + For now, this is only functional in the case of a single tracker instance + being initialized. + + Output: + - list: prediction history. Length = number of frames processed. + """ + assert len(self.trackers) == 1 + return self.trackers[0]["granular_step_prediction_history"] def sanitize_str(self, str_: str): """ diff --git a/angel_system/global_step_prediction/run_expirement.py b/angel_system/global_step_prediction/run_expirement.py index 35cd5f7bb..32ca3edfb 100644 --- a/angel_system/global_step_prediction/run_expirement.py +++ b/angel_system/global_step_prediction/run_expirement.py @@ -32,11 +32,18 @@ def run_inference_all_vids( all_vid_ids = np.unique(np.asarray(coco_test.images().lookup("video_id"))) avg_probs = None preds, gt = [], [] + avg_smd, avg_smd_normd = np.array([]), np.array([]) + mean_F1s = np.array([]) for vid_id in all_vid_ids: print(f"vid_id {vid_id}===========================") act_path = code_dir / "config/activity_labels/medical" / f"{medical_task}.yaml" + # Get framerate + framerate = round(coco_test.videos(video_ids=[vid_id]).peek()['framerate']) + # Assuming FR = 15 or 30 + assert framerate in [15, 30], f"framerate rounded to {framerate}" + step_predictor = GlobalStepPredictor( recipe_types=[f"{medical_task}"], activity_config_fpath=act_path.as_posix(), @@ -46,8 +53,8 @@ def run_inference_all_vids( / "config/tasks/medical" / f"{medical_task}.yaml" }, - # threshold_multiplier=0.3, - # threshold_frame_count=2 + threshold_multiplier=0.6, + threshold_frame_count=5 ) if avg_probs is not None: @@ -76,6 +83,15 @@ def run_inference_all_vids( # All N activity confs x each video frame activity_confs = test_video_dset.annots().get("prob") activity_gts = truth_video_dset.annots().get("category_id") + # If framerate is 30, take every other frame. + if framerate == 30: + # This must be a 30Hz video, not 15Hz. Take every other GT frame. + print(f"halve gt for {vid_id}. Len = {len(activity_gts)}") + activity_gts = [a for ind, a in enumerate(activity_gts) if ind%2==0] + print(f"new len = {len(activity_gts)}") + # ...and cut out the first 25 frames. + activity_gts = activity_gts[25:] + def get_unique(activity_ids): """ @@ -106,7 +122,12 @@ def get_unique(activity_ids): print(f"unique broad steps: {get_unique(broad_step_gts)}") - _TP, _FP, _FN = step_predictor.save_TP_FP_FN_per_class(granular_step_gts) + # activity_gt_maxes[i] set to max step so far at index i. + activity_gt_maxes = activity_gts.copy() + for ind in range(1, len(activity_gts)): + activity_gt_maxes[ind] = max(activity_gts[:ind]) + + _TP, _FP, _FN = step_predictor.save_TP_FP_FN_per_class(activity_gt_maxes) if 'TP' in locals(): TP += _TP FP += _FP @@ -118,12 +139,51 @@ def get_unique(activity_ids): class_F1s, mean_F1 = compute_class_f1s_and_mean_f1(TP,FP,FN) print(f"class-wise F1s: {class_F1s}\nmean F1: {mean_F1}") + mean_F1s = np.append(mean_F1s, mean_F1) + + pred_history = step_predictor.get_single_tracker_pred_history() + smds, smds_normd = get_start_moment_distances(pred_history, activity_gt_maxes) + + avg_smd = np.append(avg_smd, np.mean(smds)) + avg_smd_normd = np.append(avg_smd_normd, np.mean(smds_normd)) + + print(f"smds (# frames): {smds}, normalized:{smds_normd}") + try: + print(f"avg frame-wise smd:{avg_smd[-1]}, normalized: {avg_smd_normd[-1]}") + except: + import ipdb; ipdb.set_trace() + _ = step_predictor.plot_gt_vs_predicted_one_recipe( - granular_step_gts, + activity_gts, recipe_type, fname_suffix=f"{str(vid_id)}_granular_{extra_output_suffix}", granular_or_broad="granular", ) + print("########## OVERALL") + print(f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}") + print(f"overall mean F1: {np.mean(mean_F1s)}") + +def get_start_moment_distances(pred_history, activity_gt_maxes): + """ + Get the distance between ground truth & predictions of the starting frame of + each step. + + Outputs: + - smds: list of length equal to number + """ + num_classes = max(activity_gt_maxes) + vid_length = len(activity_gt_maxes) + smds = np.zeros(num_classes) + smds_normd = np.zeros(num_classes) + for i in range(num_classes): + if i+1 in pred_history: + smds[i] = abs(np.where(pred_history == i+1)[0][0] - activity_gt_maxes.index(i+1)) + smds_normd[i] = smds[i] / vid_length + else: + smds[i] = vid_length + smds_normd[i] = 1 + return smds, smds_normd + def compute_class_f1s_and_mean_f1(TP,FP,FN): F1s = np.zeros(len(TP)) @@ -131,10 +191,9 @@ def compute_class_f1s_and_mean_f1(TP,FP,FN): for i in range(len(TP)): F1s[i] = 2*TP[i] / (2*TP[i] + FP[i] + FN[i]) # mean F1 - mean_F1 = 2*np.sum(TP) / (2*np.sum(TP) + np.sum(FP) + np.sum(FN)) + mean_F1 = 2*np.sum(TP[:-1]) / (2*np.sum(TP[:-1]) + np.sum(FP[:-1]) + np.sum(FN[:-1])) return F1s, mean_F1 - @click.command(context_settings={"help_option_names": ["-h", "--help"]}) @click.argument( "medical_task", From 064ed96dfcffe8dd87d385daa887e23c5d0e6dd5 Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Tue, 3 Dec 2024 17:43:54 -0500 Subject: [PATCH 20/26] Added new class-wise and mean F1 metric --- .../.global_step_predictor.py.swp | Bin 0 -> 73728 bytes .../global_step_predictor.py | 29 ++++++++++++++++++ .../global_step_prediction/run_expirement.py | 21 +++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 angel_system/global_step_prediction/.global_step_predictor.py.swp diff --git a/angel_system/global_step_prediction/.global_step_predictor.py.swp b/angel_system/global_step_prediction/.global_step_predictor.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..5f317b329722833b814929091600af7b3c754245 GIT binary patch literal 73728 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 Date: Tue, 3 Dec 2024 17:44:31 -0500 Subject: [PATCH 21/26] rm swap file --- .../.global_step_predictor.py.swp | Bin 73728 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 angel_system/global_step_prediction/.global_step_predictor.py.swp diff --git a/angel_system/global_step_prediction/.global_step_predictor.py.swp b/angel_system/global_step_prediction/.global_step_predictor.py.swp deleted file mode 100644 index 5f317b329722833b814929091600af7b3c754245..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73728 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 Date: Tue, 24 Dec 2024 16:30:13 -0500 Subject: [PATCH 22/26] working F1 and SMD metrics --- .../global_step_predictor.py | 21 ++++-- .../global_step_prediction/run_expirement.py | 71 +++++++++++++++++-- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/angel_system/global_step_prediction/global_step_predictor.py b/angel_system/global_step_prediction/global_step_predictor.py index ce5a49085..f3767f0c6 100644 --- a/angel_system/global_step_prediction/global_step_predictor.py +++ b/angel_system/global_step_prediction/global_step_predictor.py @@ -957,26 +957,33 @@ def save_TP_FP_FN_per_class(self, step_gts): Output form: TP, FP, FN, where each is an N-dimensional vector, where N = number of step classes. """ - step_gts = [float(i) for i in step_gts][24:] assert len(self.trackers) == 1 for i, tracker in enumerate(self.trackers): #import ipdb; ipdb.set_trace() step_predictions = tracker["granular_step_prediction_history"] - if len(step_predictions) * 1.8 < len(step_gts): - # This must be a 30Hz video, not 15Hz. Take every other GT frame. - step_gts = [a for ind, a in enumerate(step_gts) if i%2==0] TP = np.zeros(len(self.avg_probs)) FP = np.zeros(len(self.avg_probs)) FN = np.zeros(len(self.avg_probs)) for ind in range(len(self.avg_probs)): # i = the index we'll get TP, FN, and FP for. - _TP = len([a for j, a in enumerate(step_predictions) if a == ind and step_gts[j] == ind]) + _TP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] == ind]) TP[ind] = _TP - _FP = len([a for j, a in enumerate(step_predictions) if a == ind and step_gts[j] != ind]) + _FP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] != ind]) FP[ind] = _FP - _FN = len([a for j, a in enumerate(step_predictions) if a != ind and step_gts[j] == ind]) + _FN = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a != ind and step_gts[j] == ind]) FN[ind] = _FN return TP, FP, FN + def get_single_tracker_pred_history(self): + """ + Get a single tracker's prediction history. + For now, this is only functional in the case of a single tracker instance + being initialized. + + Output: + - list: prediction history. Length = number of frames processed. + """ + assert len(self.trackers) == 1 + return self.trackers[0]["granular_step_prediction_history"] def sanitize_str(self, str_: str): """ diff --git a/angel_system/global_step_prediction/run_expirement.py b/angel_system/global_step_prediction/run_expirement.py index 35cd5f7bb..32ca3edfb 100644 --- a/angel_system/global_step_prediction/run_expirement.py +++ b/angel_system/global_step_prediction/run_expirement.py @@ -32,11 +32,18 @@ def run_inference_all_vids( all_vid_ids = np.unique(np.asarray(coco_test.images().lookup("video_id"))) avg_probs = None preds, gt = [], [] + avg_smd, avg_smd_normd = np.array([]), np.array([]) + mean_F1s = np.array([]) for vid_id in all_vid_ids: print(f"vid_id {vid_id}===========================") act_path = code_dir / "config/activity_labels/medical" / f"{medical_task}.yaml" + # Get framerate + framerate = round(coco_test.videos(video_ids=[vid_id]).peek()['framerate']) + # Assuming FR = 15 or 30 + assert framerate in [15, 30], f"framerate rounded to {framerate}" + step_predictor = GlobalStepPredictor( recipe_types=[f"{medical_task}"], activity_config_fpath=act_path.as_posix(), @@ -46,8 +53,8 @@ def run_inference_all_vids( / "config/tasks/medical" / f"{medical_task}.yaml" }, - # threshold_multiplier=0.3, - # threshold_frame_count=2 + threshold_multiplier=0.6, + threshold_frame_count=5 ) if avg_probs is not None: @@ -76,6 +83,15 @@ def run_inference_all_vids( # All N activity confs x each video frame activity_confs = test_video_dset.annots().get("prob") activity_gts = truth_video_dset.annots().get("category_id") + # If framerate is 30, take every other frame. + if framerate == 30: + # This must be a 30Hz video, not 15Hz. Take every other GT frame. + print(f"halve gt for {vid_id}. Len = {len(activity_gts)}") + activity_gts = [a for ind, a in enumerate(activity_gts) if ind%2==0] + print(f"new len = {len(activity_gts)}") + # ...and cut out the first 25 frames. + activity_gts = activity_gts[25:] + def get_unique(activity_ids): """ @@ -106,7 +122,12 @@ def get_unique(activity_ids): print(f"unique broad steps: {get_unique(broad_step_gts)}") - _TP, _FP, _FN = step_predictor.save_TP_FP_FN_per_class(granular_step_gts) + # activity_gt_maxes[i] set to max step so far at index i. + activity_gt_maxes = activity_gts.copy() + for ind in range(1, len(activity_gts)): + activity_gt_maxes[ind] = max(activity_gts[:ind]) + + _TP, _FP, _FN = step_predictor.save_TP_FP_FN_per_class(activity_gt_maxes) if 'TP' in locals(): TP += _TP FP += _FP @@ -118,12 +139,51 @@ def get_unique(activity_ids): class_F1s, mean_F1 = compute_class_f1s_and_mean_f1(TP,FP,FN) print(f"class-wise F1s: {class_F1s}\nmean F1: {mean_F1}") + mean_F1s = np.append(mean_F1s, mean_F1) + + pred_history = step_predictor.get_single_tracker_pred_history() + smds, smds_normd = get_start_moment_distances(pred_history, activity_gt_maxes) + + avg_smd = np.append(avg_smd, np.mean(smds)) + avg_smd_normd = np.append(avg_smd_normd, np.mean(smds_normd)) + + print(f"smds (# frames): {smds}, normalized:{smds_normd}") + try: + print(f"avg frame-wise smd:{avg_smd[-1]}, normalized: {avg_smd_normd[-1]}") + except: + import ipdb; ipdb.set_trace() + _ = step_predictor.plot_gt_vs_predicted_one_recipe( - granular_step_gts, + activity_gts, recipe_type, fname_suffix=f"{str(vid_id)}_granular_{extra_output_suffix}", granular_or_broad="granular", ) + print("########## OVERALL") + print(f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}") + print(f"overall mean F1: {np.mean(mean_F1s)}") + +def get_start_moment_distances(pred_history, activity_gt_maxes): + """ + Get the distance between ground truth & predictions of the starting frame of + each step. + + Outputs: + - smds: list of length equal to number + """ + num_classes = max(activity_gt_maxes) + vid_length = len(activity_gt_maxes) + smds = np.zeros(num_classes) + smds_normd = np.zeros(num_classes) + for i in range(num_classes): + if i+1 in pred_history: + smds[i] = abs(np.where(pred_history == i+1)[0][0] - activity_gt_maxes.index(i+1)) + smds_normd[i] = smds[i] / vid_length + else: + smds[i] = vid_length + smds_normd[i] = 1 + return smds, smds_normd + def compute_class_f1s_and_mean_f1(TP,FP,FN): F1s = np.zeros(len(TP)) @@ -131,10 +191,9 @@ def compute_class_f1s_and_mean_f1(TP,FP,FN): for i in range(len(TP)): F1s[i] = 2*TP[i] / (2*TP[i] + FP[i] + FN[i]) # mean F1 - mean_F1 = 2*np.sum(TP) / (2*np.sum(TP) + np.sum(FP) + np.sum(FN)) + mean_F1 = 2*np.sum(TP[:-1]) / (2*np.sum(TP[:-1]) + np.sum(FP[:-1]) + np.sum(FN[:-1])) return F1s, mean_F1 - @click.command(context_settings={"help_option_names": ["-h", "--help"]}) @click.argument( "medical_task", From 93ea2f2c3bebe88f4a0858ce4dc9c02e55da986e Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Wed, 25 Dec 2024 19:00:19 -0500 Subject: [PATCH 23/26] add percent of completed videos per task --- .../global_step_prediction/run_expirement.py | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/angel_system/global_step_prediction/run_expirement.py b/angel_system/global_step_prediction/run_expirement.py index 32ca3edfb..d5beedf65 100644 --- a/angel_system/global_step_prediction/run_expirement.py +++ b/angel_system/global_step_prediction/run_expirement.py @@ -9,6 +9,7 @@ import matplotlib.pyplot as plt import seaborn as sns from sklearn.metrics import confusion_matrix +import math from angel_system.global_step_prediction.global_step_predictor import ( GlobalStepPredictor, @@ -34,6 +35,7 @@ def run_inference_all_vids( preds, gt = [], [] avg_smd, avg_smd_normd = np.array([]), np.array([]) mean_F1s = np.array([]) + tasks_completed = np.array([]) for vid_id in all_vid_ids: print(f"vid_id {vid_id}===========================") @@ -142,10 +144,12 @@ def get_unique(activity_ids): mean_F1s = np.append(mean_F1s, mean_F1) pred_history = step_predictor.get_single_tracker_pred_history() - smds, smds_normd = get_start_moment_distances(pred_history, activity_gt_maxes) + smds, smds_normd, task_completed = get_start_moment_distances(pred_history, activity_gt_maxes) + tasks_completed = np.append(tasks_completed, task_completed) - avg_smd = np.append(avg_smd, np.mean(smds)) - avg_smd_normd = np.append(avg_smd_normd, np.mean(smds_normd)) + if not math.isnan(compute_mean_smd(smds)): + avg_smd = np.append(avg_smd, compute_mean_smd(smds)) + avg_smd_normd = np.append(avg_smd_normd, compute_mean_smd(smds_normd)) print(f"smds (# frames): {smds}, normalized:{smds_normd}") try: @@ -161,6 +165,7 @@ def get_unique(activity_ids): ) print("########## OVERALL") print(f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}") + print(f"tasks completed: {np.sum(tasks_completed)} / {len(tasks_completed)}") print(f"overall mean F1: {np.mean(mean_F1s)}") def get_start_moment_distances(pred_history, activity_gt_maxes): @@ -175,14 +180,26 @@ def get_start_moment_distances(pred_history, activity_gt_maxes): vid_length = len(activity_gt_maxes) smds = np.zeros(num_classes) smds_normd = np.zeros(num_classes) + task_completed = 1 for i in range(num_classes): if i+1 in pred_history: smds[i] = abs(np.where(pred_history == i+1)[0][0] - activity_gt_maxes.index(i+1)) smds_normd[i] = smds[i] / vid_length else: - smds[i] = vid_length - smds_normd[i] = 1 - return smds, smds_normd + smds[i] = -1 + smds_normd[i] = -1 + if i+1 == num_classes: + task_completed = 0 + return smds, smds_normd, task_completed + +def compute_mean_smd(smd_array): + """ + Compute mean starting moment difference. If a task was not completed, + the incomplete steps are not factored in here. + """ + + mask = smd_array >= 0 + return np.mean(smd_array[mask]) def compute_class_f1s_and_mean_f1(TP,FP,FN): From e90ed73b8944d3281785e693afe0cd7e8aca2f7d Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Wed, 25 Dec 2024 19:05:17 -0500 Subject: [PATCH 24/26] Needed new gsp configs --- config/tasks/medical/a8.yaml | 31 +++++++++++++++++++++++++++++++ config/tasks/medical/m4.yaml | 23 +++++++++++++++++++++++ config/tasks/medical/r16.yaml | 31 +++++++++++++++++++++++++++++++ config/tasks/medical/r19.yaml | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 config/tasks/medical/a8.yaml create mode 100644 config/tasks/medical/m4.yaml create mode 100644 config/tasks/medical/r16.yaml create mode 100644 config/tasks/medical/r19.yaml diff --git a/config/tasks/medical/a8.yaml b/config/tasks/medical/a8.yaml new file mode 100644 index 000000000..1160f1268 --- /dev/null +++ b/config/tasks/medical/a8.yaml @@ -0,0 +1,31 @@ +version: "1" +title: "NPA" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + activity_ids: [0] + - id: 1 + label: "select-tube" + full_str: "Select NPA tube that best fits casualty." + activity_ids: [1] + - id: 2 + label: "position-head" + full_str: "Place casualty into 'sniffing position' with head tilted back and nostrils exposed." + activity_ids: [2] + - id: 3 + label: "cover-with-lube" + full_str: "Cover NPA with lube." + activity_ids: [3] + - id: 4 + label: "insert-npa" + full_str: "Insert NPA perpendicular to casualty nostril until flange meets tip of nose, rotating along the way." + activity_ids: [4] + - id: 5 + label: "look-listen-feel" + full_str: "Look, listen, and feel for airway compliance." + activity_ids: [5] diff --git a/config/tasks/medical/m4.yaml b/config/tasks/medical/m4.yaml new file mode 100644 index 000000000..1eec1ab01 --- /dev/null +++ b/config/tasks/medical/m4.yaml @@ -0,0 +1,23 @@ +version: "1" +title: "Wound Packing" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + activity_ids: [0] + - id: 1 + label: "apply-pressure" + full_str: "Apply direct hand pressure to the wound." + activity_ids: [1] + - id: 2 + label: "open-pack" + full_str: "Open gauze packaging." + activity_ids: [2] + - id: 3 + label: "apply-dress-w-pressure" + full_str: "Pack the wound." + activity_ids: [3] diff --git a/config/tasks/medical/r16.yaml b/config/tasks/medical/r16.yaml new file mode 100644 index 000000000..ac4565c2b --- /dev/null +++ b/config/tasks/medical/r16.yaml @@ -0,0 +1,31 @@ +version: "1" +title: "Ventilate (BVM)" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + activity_ids: [0] + - id: 1 + label: "position-head" + full_str: "Place casualty into 'sniffing position' with head tilted back and nostrils exposed." + activity_ids: [1] + - id: 2 + label: "open-packaging" + full_str: "Open the BVM packaging." + activity_ids: [2] + - id: 3 + label: "attach-mask" + full_str: "Attach mask to BVM and expand BVM to full size." + activity_ids: [3] + - id: 4 + label: "place-mask" + full_str: "Place mask over patient’s mouth in proper orientation." + activity_ids: [4] + - id: 5 + label: "squeeze-bvm" + full_str: "Squeeze BVM while holding mask to patient’s mouth." + activity_ids: [5] diff --git a/config/tasks/medical/r19.yaml b/config/tasks/medical/r19.yaml new file mode 100644 index 000000000..38cd2d1a3 --- /dev/null +++ b/config/tasks/medical/r19.yaml @@ -0,0 +1,35 @@ +version: "1" +title: "Needle_Chest_Decomp" +labels: + # Item: + # - id: Integer identification number of the label. + # - label: Short human-readable semantic string to succinctly represent the + # label. + - id: 0 + label: "background" + full_str: "background" + activity_ids: [0] + - id: 1 + label: "locate-insertion-site" + full_str: "Locate insertion site at the second intercostal space at the midclavicular line." + activity_ids: [1] + - id: 2 + label: "wipe-insertion-site" + full_str: "Wipe the insertion site with an alcohol wipe." + activity_ids: [2] + - id: 3 + label: "prepare-catheter-and-needle" + full_str: "Prepare catheter and needle." + activity_ids: [3] + - id: 4 + label: "insert-needle" + full_str: "Insert needle into insertion site." + activity_ids: [4] + - id: 5 + label: "remove-needle" + full_str: "Remove needle, keeping catheter inside the patient." + activity_ids: [5] + - id: 6 + label: "apply-tape" + full_str: "Apply tape around catheter to secure it in place." + activity_ids: [6] From 87fbf859b28e83102bd034f55ddc5abea30709a9 Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Wed, 25 Dec 2024 19:11:25 -0500 Subject: [PATCH 25/26] staging merge conflicts --- .../global_step_prediction/run_expirement.py | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/angel_system/global_step_prediction/run_expirement.py b/angel_system/global_step_prediction/run_expirement.py index d5d2821a3..d5beedf65 100644 --- a/angel_system/global_step_prediction/run_expirement.py +++ b/angel_system/global_step_prediction/run_expirement.py @@ -35,10 +35,7 @@ def run_inference_all_vids( preds, gt = [], [] avg_smd, avg_smd_normd = np.array([]), np.array([]) mean_F1s = np.array([]) -<<<<<<< HEAD tasks_completed = np.array([]) -======= ->>>>>>> 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 for vid_id in all_vid_ids: print(f"vid_id {vid_id}===========================") @@ -147,19 +144,12 @@ def get_unique(activity_ids): mean_F1s = np.append(mean_F1s, mean_F1) pred_history = step_predictor.get_single_tracker_pred_history() -<<<<<<< HEAD smds, smds_normd, task_completed = get_start_moment_distances(pred_history, activity_gt_maxes) tasks_completed = np.append(tasks_completed, task_completed) if not math.isnan(compute_mean_smd(smds)): avg_smd = np.append(avg_smd, compute_mean_smd(smds)) avg_smd_normd = np.append(avg_smd_normd, compute_mean_smd(smds_normd)) -======= - smds, smds_normd = get_start_moment_distances(pred_history, activity_gt_maxes) - - avg_smd = np.append(avg_smd, np.mean(smds)) - avg_smd_normd = np.append(avg_smd_normd, np.mean(smds_normd)) ->>>>>>> 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 print(f"smds (# frames): {smds}, normalized:{smds_normd}") try: @@ -175,10 +165,7 @@ def get_unique(activity_ids): ) print("########## OVERALL") print(f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}") -<<<<<<< HEAD print(f"tasks completed: {np.sum(tasks_completed)} / {len(tasks_completed)}") -======= ->>>>>>> 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 print(f"overall mean F1: {np.mean(mean_F1s)}") def get_start_moment_distances(pred_history, activity_gt_maxes): @@ -193,16 +180,12 @@ def get_start_moment_distances(pred_history, activity_gt_maxes): vid_length = len(activity_gt_maxes) smds = np.zeros(num_classes) smds_normd = np.zeros(num_classes) -<<<<<<< HEAD task_completed = 1 -======= ->>>>>>> 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 for i in range(num_classes): if i+1 in pred_history: smds[i] = abs(np.where(pred_history == i+1)[0][0] - activity_gt_maxes.index(i+1)) smds_normd[i] = smds[i] / vid_length else: -<<<<<<< HEAD smds[i] = -1 smds_normd[i] = -1 if i+1 == num_classes: @@ -217,11 +200,6 @@ def compute_mean_smd(smd_array): mask = smd_array >= 0 return np.mean(smd_array[mask]) -======= - smds[i] = vid_length - smds_normd[i] = 1 - return smds, smds_normd ->>>>>>> 7c524b3c2c8e0d3b3952bf4f2cc97ba28aa00560 def compute_class_f1s_and_mean_f1(TP,FP,FN): From aa6849ca94db00cdb67711739bbf7f8e2919d5a0 Mon Sep 17 00:00:00 2001 From: cameron-a-johnson Date: Wed, 25 Dec 2024 19:18:40 -0500 Subject: [PATCH 26/26] black reformat --- .../global_step_predictor.py | 27 ++++++++++-- .../global_step_prediction/run_expirement.py | 44 ++++++++++++------- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/angel_system/global_step_prediction/global_step_predictor.py b/angel_system/global_step_prediction/global_step_predictor.py index f3767f0c6..fe095df5e 100644 --- a/angel_system/global_step_prediction/global_step_predictor.py +++ b/angel_system/global_step_prediction/global_step_predictor.py @@ -959,20 +959,39 @@ def save_TP_FP_FN_per_class(self, step_gts): """ assert len(self.trackers) == 1 for i, tracker in enumerate(self.trackers): - #import ipdb; ipdb.set_trace() + # import ipdb; ipdb.set_trace() step_predictions = tracker["granular_step_prediction_history"] TP = np.zeros(len(self.avg_probs)) FP = np.zeros(len(self.avg_probs)) FN = np.zeros(len(self.avg_probs)) for ind in range(len(self.avg_probs)): # i = the index we'll get TP, FN, and FP for. - _TP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] == ind]) + _TP = len( + [ + a + for j, a in enumerate(step_predictions[: len(step_gts)]) + if a == ind and step_gts[j] == ind + ] + ) TP[ind] = _TP - _FP = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a == ind and step_gts[j] != ind]) + _FP = len( + [ + a + for j, a in enumerate(step_predictions[: len(step_gts)]) + if a == ind and step_gts[j] != ind + ] + ) FP[ind] = _FP - _FN = len([a for j, a in enumerate(step_predictions[:len(step_gts)]) if a != ind and step_gts[j] == ind]) + _FN = len( + [ + a + for j, a in enumerate(step_predictions[: len(step_gts)]) + if a != ind and step_gts[j] == ind + ] + ) FN[ind] = _FN return TP, FP, FN + def get_single_tracker_pred_history(self): """ Get a single tracker's prediction history. diff --git a/angel_system/global_step_prediction/run_expirement.py b/angel_system/global_step_prediction/run_expirement.py index d5beedf65..55f84d5af 100644 --- a/angel_system/global_step_prediction/run_expirement.py +++ b/angel_system/global_step_prediction/run_expirement.py @@ -42,7 +42,7 @@ def run_inference_all_vids( act_path = code_dir / "config/activity_labels/medical" / f"{medical_task}.yaml" # Get framerate - framerate = round(coco_test.videos(video_ids=[vid_id]).peek()['framerate']) + framerate = round(coco_test.videos(video_ids=[vid_id]).peek()["framerate"]) # Assuming FR = 15 or 30 assert framerate in [15, 30], f"framerate rounded to {framerate}" @@ -56,7 +56,7 @@ def run_inference_all_vids( / f"{medical_task}.yaml" }, threshold_multiplier=0.6, - threshold_frame_count=5 + threshold_frame_count=5, ) if avg_probs is not None: @@ -89,12 +89,11 @@ def run_inference_all_vids( if framerate == 30: # This must be a 30Hz video, not 15Hz. Take every other GT frame. print(f"halve gt for {vid_id}. Len = {len(activity_gts)}") - activity_gts = [a for ind, a in enumerate(activity_gts) if ind%2==0] + activity_gts = [a for ind, a in enumerate(activity_gts) if ind % 2 == 0] print(f"new len = {len(activity_gts)}") # ...and cut out the first 25 frames. activity_gts = activity_gts[25:] - def get_unique(activity_ids): """ Get unique list indexes without sorting the list. @@ -130,7 +129,7 @@ def get_unique(activity_ids): activity_gt_maxes[ind] = max(activity_gts[:ind]) _TP, _FP, _FN = step_predictor.save_TP_FP_FN_per_class(activity_gt_maxes) - if 'TP' in locals(): + if "TP" in locals(): TP += _TP FP += _FP FN += _FN @@ -138,13 +137,15 @@ def get_unique(activity_ids): TP = _TP FP = _FP FN = _FN - class_F1s, mean_F1 = compute_class_f1s_and_mean_f1(TP,FP,FN) + class_F1s, mean_F1 = compute_class_f1s_and_mean_f1(TP, FP, FN) print(f"class-wise F1s: {class_F1s}\nmean F1: {mean_F1}") mean_F1s = np.append(mean_F1s, mean_F1) pred_history = step_predictor.get_single_tracker_pred_history() - smds, smds_normd, task_completed = get_start_moment_distances(pred_history, activity_gt_maxes) + smds, smds_normd, task_completed = get_start_moment_distances( + pred_history, activity_gt_maxes + ) tasks_completed = np.append(tasks_completed, task_completed) if not math.isnan(compute_mean_smd(smds)): @@ -155,7 +156,9 @@ def get_unique(activity_ids): try: print(f"avg frame-wise smd:{avg_smd[-1]}, normalized: {avg_smd_normd[-1]}") except: - import ipdb; ipdb.set_trace() + import ipdb + + ipdb.set_trace() _ = step_predictor.plot_gt_vs_predicted_one_recipe( activity_gts, @@ -164,17 +167,20 @@ def get_unique(activity_ids): granular_or_broad="granular", ) print("########## OVERALL") - print(f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}") + print( + f"Overall average smd: {np.mean(avg_smd)}. Normalized: {np.mean(avg_smd_normd)}" + ) print(f"tasks completed: {np.sum(tasks_completed)} / {len(tasks_completed)}") print(f"overall mean F1: {np.mean(mean_F1s)}") + def get_start_moment_distances(pred_history, activity_gt_maxes): """ Get the distance between ground truth & predictions of the starting frame of each step. Outputs: - - smds: list of length equal to number + - smds: list of length equal to number """ num_classes = max(activity_gt_maxes) vid_length = len(activity_gt_maxes) @@ -182,16 +188,19 @@ def get_start_moment_distances(pred_history, activity_gt_maxes): smds_normd = np.zeros(num_classes) task_completed = 1 for i in range(num_classes): - if i+1 in pred_history: - smds[i] = abs(np.where(pred_history == i+1)[0][0] - activity_gt_maxes.index(i+1)) + if i + 1 in pred_history: + smds[i] = abs( + np.where(pred_history == i + 1)[0][0] - activity_gt_maxes.index(i + 1) + ) smds_normd[i] = smds[i] / vid_length else: smds[i] = -1 smds_normd[i] = -1 - if i+1 == num_classes: + if i + 1 == num_classes: task_completed = 0 return smds, smds_normd, task_completed + def compute_mean_smd(smd_array): """ Compute mean starting moment difference. If a task was not completed, @@ -202,15 +211,18 @@ def compute_mean_smd(smd_array): return np.mean(smd_array[mask]) -def compute_class_f1s_and_mean_f1(TP,FP,FN): +def compute_class_f1s_and_mean_f1(TP, FP, FN): F1s = np.zeros(len(TP)) # class-wise F1s: for i in range(len(TP)): - F1s[i] = 2*TP[i] / (2*TP[i] + FP[i] + FN[i]) + F1s[i] = 2 * TP[i] / (2 * TP[i] + FP[i] + FN[i]) # mean F1 - mean_F1 = 2*np.sum(TP[:-1]) / (2*np.sum(TP[:-1]) + np.sum(FP[:-1]) + np.sum(FN[:-1])) + mean_F1 = ( + 2 * np.sum(TP[:-1]) / (2 * np.sum(TP[:-1]) + np.sum(FP[:-1]) + np.sum(FN[:-1])) + ) return F1s, mean_F1 + @click.command(context_settings={"help_option_names": ["-h", "--help"]}) @click.argument( "medical_task",