diff --git a/changelog.d/20240516_093233_boris_fixed_annotation_speed.md b/changelog.d/20240516_093233_boris_fixed_annotation_speed.md new file mode 100644 index 000000000000..9bb225ead8c7 --- /dev/null +++ b/changelog.d/20240516_093233_boris_fixed_annotation_speed.md @@ -0,0 +1,4 @@ +### Changed + +- Working time rounding to a minimal value of 1 hour is not applied to the annotation speed metric any more + () diff --git a/changelog.d/20240516_093537_boris_fixed_annotation_speed.md b/changelog.d/20240516_093537_boris_fixed_annotation_speed.md new file mode 100644 index 000000000000..30e4fcbca46f --- /dev/null +++ b/changelog.d/20240516_093537_boris_fixed_annotation_speed.md @@ -0,0 +1,4 @@ +### Changed + +- Total annotation speed metric renamed to Average annotation speed + () diff --git a/cvat/apps/analytics_report/report/create.py b/cvat/apps/analytics_report/report/create.py index 10cca9bb0235..36cc4a627a7e 100644 --- a/cvat/apps/analytics_report/report/create.py +++ b/cvat/apps/analytics_report/report/create.py @@ -14,17 +14,17 @@ from cvat.apps.analytics_report.models import AnalyticsReport from cvat.apps.analytics_report.report.derived_metrics import ( DerivedMetricBase, - JobTotalAnnotationSpeed, + JobAverageAnnotationSpeed, JobTotalObjectCount, ProjectAnnotationSpeed, ProjectAnnotationTime, + ProjectAverageAnnotationSpeed, ProjectObjects, - ProjectTotalAnnotationSpeed, ProjectTotalObjectCount, TaskAnnotationSpeed, TaskAnnotationTime, + TaskAverageAnnotationSpeed, TaskObjects, - TaskTotalAnnotationSpeed, TaskTotalObjectCount, ) from cvat.apps.analytics_report.report.primary_metrics import ( @@ -45,7 +45,7 @@ def get_empty_report(): JobAnnotationSpeed(None), JobAnnotationTime(None), JobTotalObjectCount(None), - JobTotalAnnotationSpeed(None), + JobAverageAnnotationSpeed(None), ] statistics = [AnalyticsReportUpdateManager._get_empty_statistics_entry(dm) for dm in metrics] @@ -369,7 +369,7 @@ def _compute_report_for_job( data_extractor=None, primary_statistics=primary_statistics[JobAnnotationSpeed.key()], ), - JobTotalAnnotationSpeed( + JobAverageAnnotationSpeed( db_job, data_extractor=None, primary_statistics=primary_statistics[JobAnnotationSpeed.key()], @@ -433,7 +433,7 @@ def _compute_report_for_task( for jr in job_reports ], ), - TaskTotalAnnotationSpeed( + TaskAverageAnnotationSpeed( db_task, data_extractor=None, primary_statistics=[ @@ -496,7 +496,7 @@ def _compute_report_for_project( for jr in job_reports ], ), - ProjectTotalAnnotationSpeed( + ProjectAverageAnnotationSpeed( db_project, data_extractor=None, primary_statistics=[ diff --git a/cvat/apps/analytics_report/report/derived_metrics/__init__.py b/cvat/apps/analytics_report/report/derived_metrics/__init__.py index f502235d1a0e..5dc81788809c 100644 --- a/cvat/apps/analytics_report/report/derived_metrics/__init__.py +++ b/cvat/apps/analytics_report/report/derived_metrics/__init__.py @@ -4,11 +4,11 @@ from .annotation_speed import ProjectAnnotationSpeed, TaskAnnotationSpeed from .annotation_time import ProjectAnnotationTime, TaskAnnotationTime +from .average_annotation_speed import ( + JobAverageAnnotationSpeed, + ProjectAverageAnnotationSpeed, + TaskAverageAnnotationSpeed, +) from .base import DerivedMetricBase from .objects import ProjectObjects, TaskObjects -from .total_annotation_speed import ( - JobTotalAnnotationSpeed, - ProjectTotalAnnotationSpeed, - TaskTotalAnnotationSpeed, -) from .total_object_count import JobTotalObjectCount, ProjectTotalObjectCount, TaskTotalObjectCount diff --git a/cvat/apps/analytics_report/report/derived_metrics/annotation_speed.py b/cvat/apps/analytics_report/report/derived_metrics/annotation_speed.py index 5835c3774e0f..d00eb0948577 100644 --- a/cvat/apps/analytics_report/report/derived_metrics/annotation_speed.py +++ b/cvat/apps/analytics_report/report/derived_metrics/annotation_speed.py @@ -12,7 +12,7 @@ class TaskAnnotationSpeed(DerivedMetricBase, JobAnnotationSpeed): - _description = "Metric shows the annotation speed in objects per hour for the Task." + _description = "Metric shows annotation speed in the task as number of objects per hour." _query = None def calculate(self): @@ -52,4 +52,4 @@ def calculate(self): class ProjectAnnotationSpeed(TaskAnnotationSpeed): - _description = "Metric shows the annotation speed in objects per hour for the Project." + _description = "Metric shows annotation speed in the project as number of objects per hour." diff --git a/cvat/apps/analytics_report/report/derived_metrics/total_annotation_speed.py b/cvat/apps/analytics_report/report/derived_metrics/average_annotation_speed.py similarity index 61% rename from cvat/apps/analytics_report/report/derived_metrics/total_annotation_speed.py rename to cvat/apps/analytics_report/report/derived_metrics/average_annotation_speed.py index ee0b24f7edae..37229ac4e32f 100644 --- a/cvat/apps/analytics_report/report/derived_metrics/total_annotation_speed.py +++ b/cvat/apps/analytics_report/report/derived_metrics/average_annotation_speed.py @@ -1,4 +1,4 @@ -# Copyright (C) 2023 CVAT.ai Corporation +# Copyright (C) 2023-2024 CVAT.ai Corporation # # SPDX-License-Identifier: MIT @@ -7,11 +7,11 @@ from .base import DerivedMetricBase -class JobTotalAnnotationSpeed(DerivedMetricBase): - _title = "Total Annotation Speed (objects per hour)" - _description = "Metric shows total annotation speed in the Job." +class JobAverageAnnotationSpeed(DerivedMetricBase): + _title = "Average Annotation Speed (objects per hour)" + _description = "Metric shows average annotation speed in the Job." _default_view = ViewChoice.NUMERIC - _key = "total_annotation_speed" + _key = "average_annotation_speed" _is_filterable_by_date = False def calculate(self): @@ -23,14 +23,12 @@ def calculate(self): total_wt += ds[1]["value"] metric = self.get_empty() - metric["total_annotation_speed"][0]["value"] = ( - total_count / max(total_wt, 1) if total_wt != 0 else 0 - ) + metric[self._key][0]["value"] = total_count / total_wt if total_wt != 0 else 0 return metric def get_empty(self): return { - "total_annotation_speed": [ + self._key: [ { "value": 0, "datetime": self._get_utc_now().strftime("%Y-%m-%dT%H:%M:%SZ"), @@ -39,8 +37,8 @@ def get_empty(self): } -class TaskTotalAnnotationSpeed(JobTotalAnnotationSpeed): - _description = "Metric shows total annotation speed in the Task." +class TaskAverageAnnotationSpeed(JobAverageAnnotationSpeed): + _description = "Metric shows average annotation speed in the Task." def calculate(self): total_count = 0 @@ -53,14 +51,14 @@ def calculate(self): total_wt += wt_entry["value"] return { - "total_annotation_speed": [ + self._key: [ { - "value": total_count / max(total_wt, 1) if total_wt != 0 else 0, + "value": total_count / total_wt if total_wt != 0 else 0, "datetime": self._get_utc_now().strftime("%Y-%m-%dT%H:%M:%SZ"), }, ] } -class ProjectTotalAnnotationSpeed(TaskTotalAnnotationSpeed): - _description = "Metric shows total annotation speed in the Project." +class ProjectAverageAnnotationSpeed(TaskAverageAnnotationSpeed): + _description = "Metric shows average annotation speed in the Project." diff --git a/cvat/apps/analytics_report/report/get.py b/cvat/apps/analytics_report/report/get.py index 73674a370880..1bc2d699f289 100644 --- a/cvat/apps/analytics_report/report/get.py +++ b/cvat/apps/analytics_report/report/get.py @@ -39,19 +39,6 @@ def _convert_datetime_to_date(statistics): return statistics -def _clamp_working_time(statistics): - affected_metrics = "annotation_speed" - for metric in statistics: - if metric["name"] not in affected_metrics: - continue - data_series = metric.get("data_series", {}) - if data_series: - for df in data_series["working_time"]: - df["value"] = max(df["value"], 1) - - return statistics - - def _get_object_report(obj_model, pk, start_date, end_date): data = {} try: @@ -65,7 +52,7 @@ def _get_object_report(obj_model, pk, start_date, end_date): statistics = _filter_statistics_by_date(db_analytics_report.statistics, start_date, end_date) statistics = _convert_datetime_to_date(statistics) - data["statistics"] = _clamp_working_time(statistics) + data["statistics"] = statistics data["created_date"] = db_analytics_report.created_date if obj_model is Job: 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 a3a0d3afbd98..03ec983297e6 100644 --- a/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py +++ b/cvat/apps/analytics_report/report/primary_metrics/annotation_speed.py @@ -54,7 +54,7 @@ def __init__( class JobAnnotationSpeed(PrimaryMetricBase): _key = "annotation_speed" _title = "Annotation speed (objects per hour)" - _description = "Metric shows the annotation speed in objects per hour." + _description = "Metric shows annotation speed in the job as number of objects per hour." _default_view = ViewChoice.HISTOGRAM _granularity = GranularityChoice.DAY _is_filterable_by_date = False diff --git a/tests/cypress/e2e/features/analytics_pipeline.js b/tests/cypress/e2e/features/analytics_pipeline.js index f8a5ba46927b..f6c96c844a19 100644 --- a/tests/cypress/e2e/features/analytics_pipeline.js +++ b/tests/cypress/e2e/features/analytics_pipeline.js @@ -52,7 +52,7 @@ context('Analytics pipeline', () => { }, ]; - const cardEntryNames = ['annotation_time', 'total_object_count', 'total_annotation_speed']; + const cardEntryNames = ['annotation_time', 'total_object_count', 'average_annotation_speed']; function checkCards() { cy.get('.cvat-analytics-card') .should('have.length', 3) @@ -61,7 +61,7 @@ context('Analytics pipeline', () => { .invoke('data', 'entry-name') .then((val) => { expect(cardEntryNames.includes(val)).to.eq(true); - if (['total_object_count', 'total_annotation_speed'].includes(val)) { + if (['total_object_count', 'average_annotation_speed'].includes(val)) { cy.wrap(card).within(() => { cy.get('.cvat-analytics-card-value').should('not.have.text', '0.0'); });