From 70d6bee6a2e05bd09ba94306b26aeb673a8c6f0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:12:27 +0000 Subject: [PATCH 1/3] Initial plan From ca8fbedc557997173684183d7c71d5e88d9f7e71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:17:51 +0000 Subject: [PATCH 2/3] Fix MOT tracking label visibility at image top - Add check to reposition labels inside/below bbox when at image top - Labels now always visible regardless of bbox position - Apply fix to both basenode.py and draw_util.py - Add comprehensive tests for label visibility Co-authored-by: hackolite <826027+hackolite@users.noreply.github.com> --- node/OverlayNode/draw_util/draw_util.py | 18 +- node/basenode.py | 18 +- tests/test_mot_label_visibility.py | 256 ++++++++++++++++++++++++ 3 files changed, 288 insertions(+), 4 deletions(-) create mode 100644 tests/test_mot_label_visibility.py diff --git a/node/OverlayNode/draw_util/draw_util.py b/node/OverlayNode/draw_util/draw_util.py index b794cec5..49e3e9ec 100644 --- a/node/OverlayNode/draw_util/draw_util.py +++ b/node/OverlayNode/draw_util/draw_util.py @@ -673,10 +673,17 @@ def draw_multi_object_tracking_info( # トラックID、スコア score = '%.2f' % score text = 'TID:%s(%s)' % (str(int(track_id_dict[id])), str(score)) + + # Position text above bbox if there's space, otherwise inside/below + tid_y_pos = y1 - vertical_offset_1 + if tid_y_pos < 0: + # Not enough space above, put it inside the box + tid_y_pos = y1 + vertical_offset_1 + image = cv2.putText( image, text, - (x1, y1 - vertical_offset_1), + (x1, tid_y_pos), cv2.FONT_HERSHEY_SIMPLEX, font_scale, color, @@ -685,10 +692,17 @@ def draw_multi_object_tracking_info( # クラスID text = 'CID:%s(%s)' % (str(int(class_id)), class_names[int(class_id)]) + + # Position text above bbox if there's space, otherwise inside/below + cid_y_pos = y1 - vertical_offset_2 + if cid_y_pos < 0: + # Not enough space above, put it below TID text + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + image = cv2.putText( image, text, - (x1, y1 - vertical_offset_2), + (x1, cid_y_pos), cv2.FONT_HERSHEY_SIMPLEX, font_scale, color, diff --git a/node/basenode.py b/node/basenode.py index f8474729..080fd131 100644 --- a/node/basenode.py +++ b/node/basenode.py @@ -959,10 +959,17 @@ def draw_multi_object_tracking_info( score = "%.2f" % score text = "TID:%s(%s)" % (str(int(track_id_dict[id])), str(score)) + + # Position text above bbox if there's space, otherwise inside/below + tid_y_pos = y1 - vertical_offset_1 + if tid_y_pos < 0: + # Not enough space above, put it inside the box + tid_y_pos = y1 + vertical_offset_1 + image = cv2.putText( image, text, - (x1, y1 - vertical_offset_1), + (x1, tid_y_pos), cv2.FONT_HERSHEY_SIMPLEX, font_scale, color, @@ -971,10 +978,17 @@ def draw_multi_object_tracking_info( class_name = self.get_class_name(class_id, class_names) text = "CID:%s(%s)" % (str(int(class_id)), class_name) + + # Position text above bbox if there's space, otherwise inside/below + cid_y_pos = y1 - vertical_offset_2 + if cid_y_pos < 0: + # Not enough space above, put it below TID text + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + image = cv2.putText( image, text, - (x1, y1 - vertical_offset_2), + (x1, cid_y_pos), cv2.FONT_HERSHEY_SIMPLEX, font_scale, color, diff --git a/tests/test_mot_label_visibility.py b/tests/test_mot_label_visibility.py new file mode 100644 index 00000000..bdc2d0c3 --- /dev/null +++ b/tests/test_mot_label_visibility.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Test to verify that MOT tracking labels are always visible, +even when bounding boxes are at the top of the image. + +This is a simplified unit test that tests the positioning logic directly. +""" +import unittest +import sys +import os + +# Add parent directory to path +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +class TestMOTLabelPositioningLogic(unittest.TestCase): + """Test the label positioning logic to ensure visibility""" + + def test_label_positioning_at_top_of_image(self): + """Test that labels are repositioned when bbox is at the top""" + # Simulate the positioning logic from the fix + image_height = 480 + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + vertical_offset_2 = int(12 * (font_scale / 0.5)) + + # Test case 1: Bbox at y1 = 0 (very top) + y1 = 0 + tid_y_pos = y1 - vertical_offset_1 + + # Should be negative, so we reposition inside + self.assertLess(tid_y_pos, 0, "Original position should be negative") + + # Apply fix logic + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + + self.assertGreater(tid_y_pos, 0, "Fixed TID position should be positive") + self.assertLess(tid_y_pos, image_height, "Fixed TID position should be within image") + + # Test CID position + cid_y_pos = y1 - vertical_offset_2 + self.assertLess(cid_y_pos, 0, "Original CID position should be negative") + + if cid_y_pos < 0: + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + + self.assertGreater(cid_y_pos, 0, "Fixed CID position should be positive") + self.assertLess(cid_y_pos, image_height, "Fixed CID position should be within image") + self.assertGreater(cid_y_pos, tid_y_pos, "CID should be below TID when repositioned") + + def test_label_positioning_with_small_y1(self): + """Test label positioning when bbox is close to top (y1 < offset)""" + image_height = 720 + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + vertical_offset_2 = int(12 * (font_scale / 0.5)) + + # Small y1 value + y1 = 10 + tid_y_pos = y1 - vertical_offset_1 + + # Should be negative since y1 < vertical_offset_1 + self.assertLess(tid_y_pos, 0, "Original position should be negative") + + # Apply fix + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + + self.assertGreater(tid_y_pos, 0, "Fixed position should be positive") + self.assertEqual(tid_y_pos, y1 + vertical_offset_1, "Should be positioned inside bbox") + + def test_label_positioning_with_sufficient_space(self): + """Test that labels stay above bbox when there's sufficient space""" + image_height = 720 + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + vertical_offset_2 = int(12 * (font_scale / 0.5)) + + # Bbox with enough space above (y1 = 100) + y1 = 100 + tid_y_pos = y1 - vertical_offset_1 + + # Should be positive (no fix needed) + self.assertGreater(tid_y_pos, 0, "Position should be positive with sufficient space") + + # No fix should be applied + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + + # Should remain above the bbox + self.assertEqual(tid_y_pos, y1 - vertical_offset_1, "Should stay above bbox") + + # Same for CID + cid_y_pos = y1 - vertical_offset_2 + self.assertGreater(cid_y_pos, 0, "CID position should be positive") + + if cid_y_pos < 0: + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + + self.assertEqual(cid_y_pos, y1 - vertical_offset_2, "CID should stay above bbox") + + def test_label_positioning_at_exact_threshold(self): + """Test label positioning when y1 equals vertical_offset""" + image_height = 720 + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + + # y1 exactly at threshold + y1 = vertical_offset_1 + tid_y_pos = y1 - vertical_offset_1 + + # Should be exactly 0 + self.assertEqual(tid_y_pos, 0, "Position should be 0 at threshold") + + # Fix should be applied since 0 is not acceptable (would be at image edge) + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + + # With our fix checking < 0, position 0 won't be adjusted + # This is acceptable as position 0 is technically visible (at top edge) + # But in practice, bboxes at exactly offset are rare + + def test_multiple_image_sizes(self): + """Test label positioning logic across different image sizes""" + test_heights = [360, 480, 720, 1080, 1440] + + for image_height in test_heights: + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + vertical_offset_2 = int(12 * (font_scale / 0.5)) + + # Test at top (y1 = 0) + y1 = 0 + tid_y_pos = y1 - vertical_offset_1 + cid_y_pos = y1 - vertical_offset_2 + + # Apply fix + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + if cid_y_pos < 0: + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + + # Verify fix works for all sizes + self.assertGreater(tid_y_pos, 0, + f"TID should be visible for height {image_height}") + self.assertGreater(cid_y_pos, 0, + f"CID should be visible for height {image_height}") + self.assertLess(tid_y_pos, image_height, + f"TID should be within image for height {image_height}") + self.assertLess(cid_y_pos, image_height, + f"CID should be within image for height {image_height}") + + def test_label_ordering_when_repositioned(self): + """Test that TID and CID maintain proper ordering when repositioned""" + image_height = 720 + font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) + vertical_offset_1 = int(36 * (font_scale / 0.5)) + vertical_offset_2 = int(12 * (font_scale / 0.5)) + + # Bbox at top where both labels need repositioning + y1 = 0 + + # Original positions (both negative) + tid_y_pos = y1 - vertical_offset_1 + cid_y_pos = y1 - vertical_offset_2 + + # Apply fix + if tid_y_pos < 0: + tid_y_pos = y1 + vertical_offset_1 + if cid_y_pos < 0: + cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 + + # When repositioned inside, CID should be below TID + self.assertGreater(cid_y_pos, tid_y_pos, + "When repositioned, CID should be below TID") + + # The spacing should be approximately vertical_offset_2 + spacing = cid_y_pos - tid_y_pos + self.assertAlmostEqual(spacing, vertical_offset_2, delta=1, + msg="Spacing between TID and CID should be maintained") + + +class TestImplementationInFiles(unittest.TestCase): + """Test that the implementation is present in the actual files""" + + def test_basenode_has_visibility_fix(self): + """Test that basenode.py has the visibility fix""" + basenode_path = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + 'node', + 'basenode.py' + ) + + with open(basenode_path, 'r') as f: + content = f.read() + + # Check for the fix logic + self.assertIn('tid_y_pos = y1 - vertical_offset_1', content, + "Should calculate tid_y_pos") + self.assertIn('if tid_y_pos < 0:', content, + "Should check if tid_y_pos is negative") + self.assertIn('tid_y_pos = y1 + vertical_offset_1', content, + "Should reposition tid_y_pos when negative") + + self.assertIn('cid_y_pos = y1 - vertical_offset_2', content, + "Should calculate cid_y_pos") + self.assertIn('if cid_y_pos < 0:', content, + "Should check if cid_y_pos is negative") + self.assertIn('cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2', content, + "Should reposition cid_y_pos when negative") + + # Check that positioning uses the new variables + self.assertIn('(x1, tid_y_pos)', content, + "Should use tid_y_pos for positioning") + self.assertIn('(x1, cid_y_pos)', content, + "Should use cid_y_pos for positioning") + + def test_draw_util_has_visibility_fix(self): + """Test that draw_util.py has the visibility fix""" + draw_util_path = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + 'node', + 'OverlayNode', + 'draw_util', + 'draw_util.py' + ) + + with open(draw_util_path, 'r') as f: + content = f.read() + + # Check for the fix logic + self.assertIn('tid_y_pos = y1 - vertical_offset_1', content, + "Should calculate tid_y_pos") + self.assertIn('if tid_y_pos < 0:', content, + "Should check if tid_y_pos is negative") + self.assertIn('tid_y_pos = y1 + vertical_offset_1', content, + "Should reposition tid_y_pos when negative") + + self.assertIn('cid_y_pos = y1 - vertical_offset_2', content, + "Should calculate cid_y_pos") + self.assertIn('if cid_y_pos < 0:', content, + "Should check if cid_y_pos is negative") + self.assertIn('cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2', content, + "Should reposition cid_y_pos when negative") + + # Check that positioning uses the new variables + self.assertIn('(x1, tid_y_pos)', content, + "Should use tid_y_pos for positioning") + self.assertIn('(x1, cid_y_pos)', content, + "Should use cid_y_pos for positioning") + + +if __name__ == '__main__': + unittest.main() From c49667dd40677122ff79177ece8c460ca5754c7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:23:03 +0000 Subject: [PATCH 3/3] Improve label positioning with margin for edge cases - Add 5-pixel margin to prevent labels at y=0 edge - Update all tests to reflect margin-based positioning - Address code review feedback for edge case handling Co-authored-by: hackolite <826027+hackolite@users.noreply.github.com> --- node/OverlayNode/draw_util/draw_util.py | 6 ++- node/basenode.py | 6 ++- tests/test_mot_label_visibility.py | 62 ++++++++++++++----------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/node/OverlayNode/draw_util/draw_util.py b/node/OverlayNode/draw_util/draw_util.py index 49e3e9ec..f271f0a4 100644 --- a/node/OverlayNode/draw_util/draw_util.py +++ b/node/OverlayNode/draw_util/draw_util.py @@ -675,8 +675,10 @@ def draw_multi_object_tracking_info( text = 'TID:%s(%s)' % (str(int(track_id_dict[id])), str(score)) # Position text above bbox if there's space, otherwise inside/below + # Use margin of 5 pixels to avoid text being cut off at image edge + margin = 5 tid_y_pos = y1 - vertical_offset_1 - if tid_y_pos < 0: + if tid_y_pos < margin: # Not enough space above, put it inside the box tid_y_pos = y1 + vertical_offset_1 @@ -695,7 +697,7 @@ def draw_multi_object_tracking_info( # Position text above bbox if there's space, otherwise inside/below cid_y_pos = y1 - vertical_offset_2 - if cid_y_pos < 0: + if cid_y_pos < margin: # Not enough space above, put it below TID text cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 diff --git a/node/basenode.py b/node/basenode.py index 080fd131..57861063 100644 --- a/node/basenode.py +++ b/node/basenode.py @@ -961,8 +961,10 @@ def draw_multi_object_tracking_info( text = "TID:%s(%s)" % (str(int(track_id_dict[id])), str(score)) # Position text above bbox if there's space, otherwise inside/below + # Use margin of 5 pixels to avoid text being cut off at image edge + margin = 5 tid_y_pos = y1 - vertical_offset_1 - if tid_y_pos < 0: + if tid_y_pos < margin: # Not enough space above, put it inside the box tid_y_pos = y1 + vertical_offset_1 @@ -981,7 +983,7 @@ def draw_multi_object_tracking_info( # Position text above bbox if there's space, otherwise inside/below cid_y_pos = y1 - vertical_offset_2 - if cid_y_pos < 0: + if cid_y_pos < margin: # Not enough space above, put it below TID text cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 diff --git a/tests/test_mot_label_visibility.py b/tests/test_mot_label_visibility.py index bdc2d0c3..1d854627 100644 --- a/tests/test_mot_label_visibility.py +++ b/tests/test_mot_label_visibility.py @@ -24,6 +24,7 @@ def test_label_positioning_at_top_of_image(self): font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) vertical_offset_1 = int(36 * (font_scale / 0.5)) vertical_offset_2 = int(12 * (font_scale / 0.5)) + margin = 5 # Test case 1: Bbox at y1 = 0 (very top) y1 = 0 @@ -33,7 +34,7 @@ def test_label_positioning_at_top_of_image(self): self.assertLess(tid_y_pos, 0, "Original position should be negative") # Apply fix logic - if tid_y_pos < 0: + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 self.assertGreater(tid_y_pos, 0, "Fixed TID position should be positive") @@ -43,7 +44,7 @@ def test_label_positioning_at_top_of_image(self): cid_y_pos = y1 - vertical_offset_2 self.assertLess(cid_y_pos, 0, "Original CID position should be negative") - if cid_y_pos < 0: + if cid_y_pos < margin: cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 self.assertGreater(cid_y_pos, 0, "Fixed CID position should be positive") @@ -56,6 +57,7 @@ def test_label_positioning_with_small_y1(self): font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) vertical_offset_1 = int(36 * (font_scale / 0.5)) vertical_offset_2 = int(12 * (font_scale / 0.5)) + margin = 5 # Small y1 value y1 = 10 @@ -65,7 +67,7 @@ def test_label_positioning_with_small_y1(self): self.assertLess(tid_y_pos, 0, "Original position should be negative") # Apply fix - if tid_y_pos < 0: + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 self.assertGreater(tid_y_pos, 0, "Fixed position should be positive") @@ -77,6 +79,7 @@ def test_label_positioning_with_sufficient_space(self): font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) vertical_offset_1 = int(36 * (font_scale / 0.5)) vertical_offset_2 = int(12 * (font_scale / 0.5)) + margin = 5 # Bbox with enough space above (y1 = 100) y1 = 100 @@ -86,7 +89,7 @@ def test_label_positioning_with_sufficient_space(self): self.assertGreater(tid_y_pos, 0, "Position should be positive with sufficient space") # No fix should be applied - if tid_y_pos < 0: + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 # Should remain above the bbox @@ -96,7 +99,7 @@ def test_label_positioning_with_sufficient_space(self): cid_y_pos = y1 - vertical_offset_2 self.assertGreater(cid_y_pos, 0, "CID position should be positive") - if cid_y_pos < 0: + if cid_y_pos < margin: cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 self.assertEqual(cid_y_pos, y1 - vertical_offset_2, "CID should stay above bbox") @@ -106,6 +109,7 @@ def test_label_positioning_at_exact_threshold(self): image_height = 720 font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) vertical_offset_1 = int(36 * (font_scale / 0.5)) + margin = 5 # y1 exactly at threshold y1 = vertical_offset_1 @@ -114,17 +118,18 @@ def test_label_positioning_at_exact_threshold(self): # Should be exactly 0 self.assertEqual(tid_y_pos, 0, "Position should be 0 at threshold") - # Fix should be applied since 0 is not acceptable (would be at image edge) - if tid_y_pos < 0: + # Fix should be applied since 0 < margin + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 - # With our fix checking < 0, position 0 won't be adjusted - # This is acceptable as position 0 is technically visible (at top edge) - # But in practice, bboxes at exactly offset are rare + # Position should now be inside the box + self.assertEqual(tid_y_pos, y1 + vertical_offset_1, + "Position should be repositioned inside box when at margin threshold") def test_multiple_image_sizes(self): """Test label positioning logic across different image sizes""" test_heights = [360, 480, 720, 1080, 1440] + margin = 5 for image_height in test_heights: font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) @@ -137,9 +142,9 @@ def test_multiple_image_sizes(self): cid_y_pos = y1 - vertical_offset_2 # Apply fix - if tid_y_pos < 0: + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 - if cid_y_pos < 0: + if cid_y_pos < margin: cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 # Verify fix works for all sizes @@ -158,6 +163,7 @@ def test_label_ordering_when_repositioned(self): font_scale = max(0.3, min(1.0, (image_height / 720.0) * 0.5)) vertical_offset_1 = int(36 * (font_scale / 0.5)) vertical_offset_2 = int(12 * (font_scale / 0.5)) + margin = 5 # Bbox at top where both labels need repositioning y1 = 0 @@ -167,9 +173,9 @@ def test_label_ordering_when_repositioned(self): cid_y_pos = y1 - vertical_offset_2 # Apply fix - if tid_y_pos < 0: + if tid_y_pos < margin: tid_y_pos = y1 + vertical_offset_1 - if cid_y_pos < 0: + if cid_y_pos < margin: cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2 # When repositioned inside, CID should be below TID @@ -197,19 +203,21 @@ def test_basenode_has_visibility_fix(self): content = f.read() # Check for the fix logic + self.assertIn('margin = 5', content, + "Should define margin for edge detection") self.assertIn('tid_y_pos = y1 - vertical_offset_1', content, "Should calculate tid_y_pos") - self.assertIn('if tid_y_pos < 0:', content, - "Should check if tid_y_pos is negative") + self.assertIn('if tid_y_pos < margin:', content, + "Should check if tid_y_pos is less than margin") self.assertIn('tid_y_pos = y1 + vertical_offset_1', content, - "Should reposition tid_y_pos when negative") + "Should reposition tid_y_pos when too close to edge") self.assertIn('cid_y_pos = y1 - vertical_offset_2', content, "Should calculate cid_y_pos") - self.assertIn('if cid_y_pos < 0:', content, - "Should check if cid_y_pos is negative") + self.assertIn('if cid_y_pos < margin:', content, + "Should check if cid_y_pos is less than margin") self.assertIn('cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2', content, - "Should reposition cid_y_pos when negative") + "Should reposition cid_y_pos when too close to edge") # Check that positioning uses the new variables self.assertIn('(x1, tid_y_pos)', content, @@ -231,19 +239,21 @@ def test_draw_util_has_visibility_fix(self): content = f.read() # Check for the fix logic + self.assertIn('margin = 5', content, + "Should define margin for edge detection") self.assertIn('tid_y_pos = y1 - vertical_offset_1', content, "Should calculate tid_y_pos") - self.assertIn('if tid_y_pos < 0:', content, - "Should check if tid_y_pos is negative") + self.assertIn('if tid_y_pos < margin:', content, + "Should check if tid_y_pos is less than margin") self.assertIn('tid_y_pos = y1 + vertical_offset_1', content, - "Should reposition tid_y_pos when negative") + "Should reposition tid_y_pos when too close to edge") self.assertIn('cid_y_pos = y1 - vertical_offset_2', content, "Should calculate cid_y_pos") - self.assertIn('if cid_y_pos < 0:', content, - "Should check if cid_y_pos is negative") + self.assertIn('if cid_y_pos < margin:', content, + "Should check if cid_y_pos is less than margin") self.assertIn('cid_y_pos = y1 + vertical_offset_1 + vertical_offset_2', content, - "Should reposition cid_y_pos when negative") + "Should reposition cid_y_pos when too close to edge") # Check that positioning uses the new variables self.assertIn('(x1, tid_y_pos)', content,