diff --git a/changelog.d/20231117_132419_andrey_fix_analytics.md b/changelog.d/20231117_132419_andrey_fix_analytics.md new file mode 100644 index 000000000000..aeb4f6ee8a5f --- /dev/null +++ b/changelog.d/20231117_132419_andrey_fix_analytics.md @@ -0,0 +1,4 @@ +### Fixed + +- Fixed calculation of annotation speed metrics for analytics reports + () diff --git a/cvat/apps/analytics_report/migrations/0002_fix_annotation_speed.py b/cvat/apps/analytics_report/migrations/0002_fix_annotation_speed.py new file mode 100644 index 000000000000..7137dee1ca2c --- /dev/null +++ b/cvat/apps/analytics_report/migrations/0002_fix_annotation_speed.py @@ -0,0 +1,49 @@ +# Generated by Django 4.2.11 on 2024-05-10 06:00 + +from django.db import migrations + + +def upgrade_report(report): + statistics = [stat for stat in report.statistics if stat["name"] == "annotation_speed"] + modified = False + + for statistic in statistics: + if len(statistic["data_series"]["object_count"]) > 2: + records_1 = list(reversed(statistic["data_series"]["object_count"])) + records_2 = records_1[1:] + for next_item, prev_item in zip(records_1, records_2): + next_item["value"] += prev_item["value"] + previous_count = 0 + for item in statistic["data_series"]["object_count"]: + item["value"] -= previous_count + previous_count += item["value"] + modified = True + + return report if modified else None + + +def forwards_func(apps, schema_editor): + AnalyticsReport = apps.get_model("analytics_report", "AnalyticsReport") + + # first upgrade all reports, related to jobs + reports = AnalyticsReport.objects.exclude(job_id=None).all() + objects_to_update = [] + for report in reports: + try: + objects_to_update.append(upgrade_report(report)) + except Exception: # nosec B110 + # I do not expect exception to happen here + # but if it happened, let's just ignore the report + pass + + objects_to_update = list(filter(lambda x: x is not None, objects_to_update)) + AnalyticsReport.objects.bulk_update(objects_to_update, fields=["statistics"], batch_size=500) + + +class Migration(migrations.Migration): + + dependencies = [ + ("analytics_report", "0001_initial"), + ] + + operations = [migrations.RunPython(forwards_func)] diff --git a/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py b/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py index b71188b38286..b8fee1465948 100644 --- a/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py +++ b/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py @@ -137,27 +137,24 @@ def get_track_count(): if statistics is not None: data_series = deepcopy(statistics["data_series"]) - last_entry_count = 0 + previous_count = 0 if data_series["object_count"]: - last_entry = data_series["object_count"][-1] - last_entry_timestamp = parser.parse(last_entry["datetime"]) + last_entry_timestamp = parser.parse(data_series["object_count"][-1]["datetime"]) if last_entry_timestamp.date() == timestamp.date(): # remove last entry, it will be re-calculated below, because of the same date data_series["object_count"] = data_series["object_count"][:-1] data_series["working_time"] = data_series["working_time"][:-1] - if len(data_series["object_count"]): - current_last_entry = data_series["object_count"][-1] - start_datetime = parser.parse(current_last_entry["datetime"]) - last_entry_count = current_last_entry["value"] - else: - last_entry_count = last_entry["value"] - start_datetime = parser.parse(last_entry["datetime"]) + for entry in data_series["object_count"]: + previous_count += entry["value"] + + if data_series["object_count"]: + start_datetime = parser.parse(data_series["object_count"][-1]["datetime"]) data_series["object_count"].append( { - "value": object_count - last_entry_count, + "value": object_count - previous_count, "datetime": timestamp_str, } )