miscs (Interro02) : horizontal cutting resolution
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import copy
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from copienator import EvaluationWorkspace, atomic_write_json
|
||||
from copienator.annotation_data import GroupCoordinates, _scaled_result
|
||||
from copienator.annotation_actions import apply_checkbox_actions
|
||||
from copienator.commands import annotating, correction
|
||||
from copienator.feedback_boxes import valid_feedback_box
|
||||
|
||||
|
||||
class FeedbackBoxTests(unittest.TestCase):
|
||||
def test_checkbox_for_promoted_feedback_deletes_the_correct_comment(self):
|
||||
feedback = [{"text": "Invalid local", "box_2d": [753, 680, 287, 946]},
|
||||
{"text": "Existing global", "box_2d": None}]
|
||||
apply_checkbox_actions({"Ex 5": {"result": {"feedback": feedback}}},
|
||||
[{"label": "Ex 5", "type": "del_global", "index": 0}], lambda _: None)
|
||||
self.assertTrue(feedback[0]["to_delete"])
|
||||
self.assertNotIn("to_delete", feedback[1])
|
||||
|
||||
def test_bad_boxes_keep_their_comment_as_global_feedback_without_mutating_data(self):
|
||||
for box in ([753, 680, 287, 946], [10, 50, 20, 30], [10, 20, 10, 30],
|
||||
[1, 2, 3], [None, 0, 10, 20], [float("nan"), 0, 10, 20]):
|
||||
with self.subTest(box=box):
|
||||
result = {"score": 2, "feedback": [{"text": "Important comment", "box_2d": box}]}
|
||||
original_box = result["feedback"][0]["box_2d"]
|
||||
scaled = _scaled_result(result, GroupCoordinates(2415, 3297, 1655, 3297))
|
||||
callback = Mock()
|
||||
render = Mock(return_value=Image.new("RGBA", (200, 40), "white"))
|
||||
with patch.object(annotating, "render_score_text", return_value=Image.new("RGBA", (200, 40))):
|
||||
image, _ = annotating.compose_label_image(Image.new("RGBA", (800, 100)), "Ex 5", scaled,
|
||||
2415, render_fn=render, draw_callback=callback)
|
||||
self.assertIsNotNone(image)
|
||||
render.assert_called_once_with("Important comment", unittest.mock.ANY)
|
||||
self.assertFalse(any(call.args[0] == "local_rect" for call in callback.call_args_list))
|
||||
self.assertIs(result["feedback"][0]["box_2d"], original_box)
|
||||
|
||||
def test_valid_boxes_remain_local(self):
|
||||
result = {"feedback": [{"text": "Local", "box_2d": [10, 20, 30, 40]}]}
|
||||
before = copy.deepcopy(result)
|
||||
callback = Mock()
|
||||
with patch.object(annotating, "render_score_text", return_value=Image.new("RGBA", (200, 40))):
|
||||
annotating.compose_label_image(Image.new("RGBA", (800, 100)), "Ex 5", result, 0,
|
||||
render_fn=Mock(return_value=Image.new("RGBA", (200, 40))),
|
||||
draw_callback=callback)
|
||||
self.assertTrue(any(call.args[0] == "local_rect" for call in callback.call_args_list))
|
||||
self.assertEqual(result, before)
|
||||
self.assertTrue(valid_feedback_box([10, 20, 30, 40]))
|
||||
|
||||
def test_invalid_auxiliary_response_loses_only_its_rectangle(self):
|
||||
returned = [{"text": "Keep this", "box_2d": [753, 680, 287, 946]}]
|
||||
with patch.object(correction.prompting, "request_for_box_correction", return_value=([], {})), patch.object(
|
||||
correction, "call_gemini_with_retries", return_value=json.dumps(returned)
|
||||
):
|
||||
feedback = correction.correct_boxes_with_gemini("26", "Ex 5", Path("unused.pdf"), [], 0, 1000, 1, 1000)
|
||||
self.assertEqual(feedback, [{"text": "Keep this", "box_2d": None}])
|
||||
|
||||
def test_correction_requests_repair_for_inverted_boxes_and_falls_back_without_losing_comments(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
group = root / "Par label" / "Ex 5" / "Group_1.jpg"
|
||||
group.parent.mkdir(parents=True)
|
||||
group.touch()
|
||||
atomic_write_json(group.with_suffix(".json"), [["26", 0, 1000, 1, "Ex 5"]])
|
||||
args = correction.build_parser().parse_args([str(root)])
|
||||
correction.configure_runtime(EvaluationWorkspace(root), [(str(group), "Ex 5")], args, api_client=Mock())
|
||||
response = [{"id": "26", "result": {"score": 2, "error": "", "feedback": [
|
||||
{"text": "First", "box_2d": [753, 680, 287, 946]},
|
||||
{"text": "Second", "box_2d": [100, 900, 200, 100]}]}}]
|
||||
with patch.object(correction.prompting, "generate_request", return_value=([], {})), patch.object(
|
||||
correction, "correct_boxes_with_gemini", side_effect=RuntimeError("repair failed")
|
||||
) as repair:
|
||||
correction.process_single_task((str(group), "Ex 5"), json.dumps(response))
|
||||
repair.assert_called_once()
|
||||
feedback = correction.results["Ex 5"][0][0]["result"]["feedback"]
|
||||
self.assertEqual([f["text"] for f in feedback], ["First", "Second"])
|
||||
self.assertTrue(all(f["box_2d"] is None for f in feedback))
|
||||
Reference in New Issue
Block a user