annofabcli 1.111.2__py3-none-any.whl → 1.113.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- annofabcli/__main__.py +1 -2
- annofabcli/annotation/annotation_query.py +10 -10
- annofabcli/annotation/change_annotation_attributes.py +10 -10
- annofabcli/annotation/change_annotation_attributes_per_annotation.py +4 -5
- annofabcli/annotation/change_annotation_properties.py +14 -14
- annofabcli/annotation/copy_annotation.py +6 -6
- annofabcli/annotation/create_classification_annotation.py +7 -7
- annofabcli/annotation/delete_annotation.py +9 -9
- annofabcli/annotation/download_annotation_zip.py +1 -3
- annofabcli/annotation/dump_annotation.py +8 -8
- annofabcli/annotation/import_annotation.py +13 -13
- annofabcli/annotation/list_annotation.py +9 -9
- annofabcli/annotation/list_annotation_count.py +2 -3
- annofabcli/annotation/merge_segmentation.py +6 -6
- annofabcli/annotation/remove_segmentation_overlap.py +5 -5
- annofabcli/annotation/restore_annotation.py +7 -7
- annofabcli/annotation/subcommand_annotation.py +1 -2
- annofabcli/annotation_specs/add_attribute_restriction.py +4 -5
- annofabcli/annotation_specs/attribute_restriction.py +8 -8
- annofabcli/annotation_specs/export_annotation_specs.py +4 -5
- annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +3 -4
- annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +3 -4
- annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +3 -4
- annofabcli/annotation_specs/list_annotation_specs_attribute.py +9 -10
- annofabcli/annotation_specs/list_annotation_specs_choice.py +9 -10
- annofabcli/annotation_specs/list_annotation_specs_history.py +3 -3
- annofabcli/annotation_specs/list_annotation_specs_label.py +8 -9
- annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +10 -11
- annofabcli/annotation_specs/list_attribute_restriction.py +2 -4
- annofabcli/annotation_specs/list_label_color.py +2 -3
- annofabcli/annotation_specs/put_label_color.py +3 -4
- annofabcli/annotation_specs/subcommand_annotation_specs.py +1 -3
- annofabcli/annotation_zip/list_annotation_3d_bounding_box.py +365 -0
- annofabcli/annotation_zip/list_annotation_bounding_box_2d.py +37 -38
- annofabcli/annotation_zip/list_polygon_annotation.py +390 -0
- annofabcli/annotation_zip/list_polyline_annotation.py +402 -0
- annofabcli/annotation_zip/list_range_annotation.py +25 -15
- annofabcli/annotation_zip/list_single_point_annotation.py +25 -34
- annofabcli/annotation_zip/subcommand_annotation_zip.py +7 -2
- annofabcli/annotation_zip/validate_annotation.py +8 -7
- annofabcli/comment/delete_comment.py +4 -6
- annofabcli/comment/download_comment_json.py +4 -6
- annofabcli/comment/list_all_comment.py +5 -6
- annofabcli/comment/list_comment.py +3 -4
- annofabcli/comment/put_comment.py +9 -10
- annofabcli/comment/put_comment_simply.py +5 -6
- annofabcli/comment/put_inspection_comment.py +1 -3
- annofabcli/comment/put_inspection_comment_simply.py +1 -3
- annofabcli/comment/put_onhold_comment.py +1 -3
- annofabcli/comment/put_onhold_comment_simply.py +1 -3
- annofabcli/comment/subcommand_comment.py +1 -3
- annofabcli/common/bokeh.py +4 -4
- annofabcli/common/cli.py +18 -17
- annofabcli/common/download.py +28 -29
- annofabcli/common/facade.py +37 -38
- annofabcli/common/image.py +14 -14
- annofabcli/common/utils.py +8 -8
- annofabcli/common/visualize.py +13 -13
- annofabcli/experimental/list_out_of_range_annotation_for_movie.py +3 -4
- annofabcli/experimental/subcommand_experimental.py +1 -3
- annofabcli/filesystem/draw_annotation.py +27 -27
- annofabcli/filesystem/filter_annotation.py +9 -10
- annofabcli/filesystem/mask_user_info.py +15 -15
- annofabcli/filesystem/merge_annotation.py +9 -9
- annofabcli/filesystem/subcommand_filesystem.py +1 -3
- annofabcli/input_data/copy_input_data.py +8 -9
- annofabcli/input_data/delete_input_data.py +3 -3
- annofabcli/input_data/delete_metadata_key_of_input_data.py +3 -5
- annofabcli/input_data/download_input_data_json.py +4 -6
- annofabcli/input_data/list_all_input_data.py +9 -9
- annofabcli/input_data/list_all_input_data_merged_task.py +5 -5
- annofabcli/input_data/list_input_data.py +5 -5
- annofabcli/input_data/put_input_data.py +6 -6
- annofabcli/input_data/put_input_data_with_zip.py +3 -4
- annofabcli/input_data/subcommand_input_data.py +1 -3
- annofabcli/input_data/update_input_data.py +6 -8
- annofabcli/input_data/update_metadata_of_input_data.py +3 -5
- annofabcli/instruction/copy_instruction.py +5 -6
- annofabcli/instruction/download_instruction.py +5 -6
- annofabcli/instruction/list_instruction_history.py +3 -3
- annofabcli/instruction/subcommand_instruction.py +1 -3
- annofabcli/instruction/upload_instruction.py +3 -4
- annofabcli/job/delete_job.py +2 -3
- annofabcli/job/list_job.py +5 -5
- annofabcli/job/list_last_job.py +4 -4
- annofabcli/job/subcommand_job.py +1 -3
- annofabcli/job/wait_job.py +4 -5
- annofabcli/my_account/get_my_account.py +2 -3
- annofabcli/my_account/subcommand_my_account.py +1 -3
- annofabcli/organization/list_organization.py +2 -3
- annofabcli/organization/subcommand_organization.py +1 -3
- annofabcli/organization_member/change_organization_member.py +3 -4
- annofabcli/organization_member/delete_organization_member.py +3 -4
- annofabcli/organization_member/invite_organization_member.py +1 -3
- annofabcli/organization_member/list_organization_member.py +3 -3
- annofabcli/organization_member/subcommand_organization_member.py +1 -3
- annofabcli/project/change_organization_of_project.py +4 -4
- annofabcli/project/change_project_status.py +4 -4
- annofabcli/project/copy_project.py +5 -5
- annofabcli/project/create_project.py +8 -8
- annofabcli/project/diff_projects.py +4 -5
- annofabcli/project/list_project.py +5 -5
- annofabcli/project/put_project.py +2 -3
- annofabcli/project/subcommand_project.py +1 -2
- annofabcli/project/update_configuration.py +4 -4
- annofabcli/project/update_project.py +6 -8
- annofabcli/project_member/change_project_members.py +8 -8
- annofabcli/project_member/copy_project_members.py +4 -4
- annofabcli/project_member/drop_project_members.py +2 -3
- annofabcli/project_member/invite_project_members.py +1 -3
- annofabcli/project_member/list_users.py +2 -3
- annofabcli/project_member/put_project_members.py +6 -6
- annofabcli/project_member/subcommand_project_member.py +1 -3
- annofabcli/stat_visualization/mask_visualization_dir.py +8 -9
- annofabcli/stat_visualization/merge_visualization_dir.py +6 -7
- annofabcli/stat_visualization/subcommand_stat_visualization.py +1 -2
- annofabcli/stat_visualization/summarize_whole_performance_csv.py +1 -2
- annofabcli/stat_visualization/write_graph.py +2 -3
- annofabcli/stat_visualization/write_performance_rating_csv.py +20 -27
- annofabcli/statistics/histogram.py +5 -6
- annofabcli/statistics/linegraph.py +13 -14
- annofabcli/statistics/list_annotation_area.py +38 -13
- annofabcli/statistics/list_annotation_attribute.py +9 -10
- annofabcli/statistics/list_annotation_attribute_filled_count.py +30 -31
- annofabcli/statistics/list_annotation_count.py +57 -58
- annofabcli/statistics/list_annotation_duration.py +33 -34
- annofabcli/statistics/list_video_duration.py +4 -5
- annofabcli/statistics/list_worktime.py +4 -4
- annofabcli/statistics/scatter.py +9 -8
- annofabcli/statistics/subcommand_statistics.py +1 -4
- annofabcli/statistics/summarize_task_count.py +4 -6
- annofabcli/statistics/summarize_task_count_by_task_id_group.py +2 -4
- annofabcli/statistics/summarize_task_count_by_user.py +1 -3
- annofabcli/statistics/visualization/dataframe/annotation_count.py +5 -4
- annofabcli/statistics/visualization/dataframe/annotation_duration.py +2 -3
- annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +15 -17
- annofabcli/statistics/visualization/dataframe/productivity_per_date.py +17 -19
- annofabcli/statistics/visualization/dataframe/project_performance.py +3 -12
- annofabcli/statistics/visualization/dataframe/task.py +11 -12
- annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +9 -10
- annofabcli/statistics/visualization/dataframe/user_performance.py +21 -19
- annofabcli/statistics/visualization/dataframe/whole_performance.py +3 -4
- annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +12 -14
- annofabcli/statistics/visualization/dataframe/worktime_per_date.py +11 -13
- annofabcli/statistics/visualization/filtering_query.py +7 -7
- annofabcli/statistics/visualization/project_dir.py +27 -14
- annofabcli/statistics/visualize_annotation_count.py +22 -23
- annofabcli/statistics/visualize_annotation_duration.py +21 -22
- annofabcli/statistics/visualize_statistics.py +36 -33
- annofabcli/statistics/visualize_video_duration.py +18 -20
- annofabcli/supplementary/delete_supplementary_data.py +5 -5
- annofabcli/supplementary/list_supplementary_data.py +4 -4
- annofabcli/supplementary/put_supplementary_data.py +9 -9
- annofabcli/supplementary/subcommand_supplementary.py +1 -3
- annofabcli/task/cancel_acceptance.py +16 -17
- annofabcli/task/change_operator.py +10 -12
- annofabcli/task/change_status_to_break.py +7 -9
- annofabcli/task/change_status_to_on_hold.py +10 -12
- annofabcli/task/complete_tasks.py +17 -18
- annofabcli/task/copy_tasks.py +3 -5
- annofabcli/task/delete_metadata_key_of_task.py +4 -6
- annofabcli/task/delete_tasks.py +7 -7
- annofabcli/task/download_task_json.py +4 -6
- annofabcli/task/list_all_tasks.py +8 -8
- annofabcli/task/list_all_tasks_added_task_history.py +14 -13
- annofabcli/task/list_tasks.py +7 -7
- annofabcli/task/list_tasks_added_task_history.py +10 -10
- annofabcli/task/put_tasks.py +5 -6
- annofabcli/task/put_tasks_by_count.py +2 -3
- annofabcli/task/reject_tasks.py +18 -20
- annofabcli/task/subcommand_task.py +1 -3
- annofabcli/task/update_metadata_of_task.py +5 -6
- annofabcli/task_history/download_task_history_json.py +4 -6
- annofabcli/task_history/list_all_task_history.py +6 -7
- annofabcli/task_history/list_task_history.py +4 -5
- annofabcli/task_history/subcommand_task_history.py +1 -3
- annofabcli/task_history_event/download_task_history_event_json.py +4 -6
- annofabcli/task_history_event/list_all_task_history_event.py +7 -7
- annofabcli/task_history_event/list_worktime.py +17 -16
- annofabcli/task_history_event/subcommand_task_history_event.py +1 -2
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/METADATA +9 -15
- annofabcli-1.113.0.dist-info/RECORD +231 -0
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/WHEEL +1 -1
- annofabcli-1.111.2.dist-info/RECORD +0 -228
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/entry_points.txt +0 -0
- {annofabcli-1.111.2.dist-info → annofabcli-1.113.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,12 +8,10 @@ from __future__ import annotations
|
|
|
8
8
|
import datetime
|
|
9
9
|
import logging
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
11
|
+
from typing import Any
|
|
12
12
|
|
|
13
13
|
import annofabapi
|
|
14
|
-
import bokeh
|
|
15
14
|
import bokeh.layouts
|
|
16
|
-
import bokeh.palettes
|
|
17
15
|
import pandas
|
|
18
16
|
from bokeh.models.ui import UIElement
|
|
19
17
|
from bokeh.plotting import ColumnDataSource
|
|
@@ -250,9 +248,9 @@ class WorktimePerDate:
|
|
|
250
248
|
project_id: str,
|
|
251
249
|
actual_worktime: ActualWorktime,
|
|
252
250
|
*,
|
|
253
|
-
task_history_event_json:
|
|
254
|
-
start_date:
|
|
255
|
-
end_date:
|
|
251
|
+
task_history_event_json: Path | None = None,
|
|
252
|
+
start_date: str | None = None,
|
|
253
|
+
end_date: str | None = None,
|
|
256
254
|
) -> WorktimePerDate:
|
|
257
255
|
"""
|
|
258
256
|
|
|
@@ -371,8 +369,8 @@ class WorktimePerDate:
|
|
|
371
369
|
self,
|
|
372
370
|
output_file: Path,
|
|
373
371
|
*,
|
|
374
|
-
target_user_id_list:
|
|
375
|
-
metadata:
|
|
372
|
+
target_user_id_list: list[str] | None = None,
|
|
373
|
+
metadata: dict[str, Any] | None = None,
|
|
376
374
|
) -> None:
|
|
377
375
|
"""
|
|
378
376
|
作業時間の累積値をプロットする。
|
|
@@ -468,7 +466,7 @@ class WorktimePerDate:
|
|
|
468
466
|
username = df_subset.iloc[0]["username"]
|
|
469
467
|
|
|
470
468
|
line_count += 1
|
|
471
|
-
for line_graph, (x_column, y_column) in zip(line_graph_list, columns_list):
|
|
469
|
+
for line_graph, (x_column, y_column) in zip(line_graph_list, columns_list, strict=False):
|
|
472
470
|
line_graph.add_line(
|
|
473
471
|
source=source,
|
|
474
472
|
x_column=x_column,
|
|
@@ -510,10 +508,10 @@ class WorktimePerDate:
|
|
|
510
508
|
|
|
511
509
|
def mask_user_info(
|
|
512
510
|
self,
|
|
513
|
-
to_replace_for_user_id:
|
|
514
|
-
to_replace_for_username:
|
|
515
|
-
to_replace_for_account_id:
|
|
516
|
-
to_replace_for_biography:
|
|
511
|
+
to_replace_for_user_id: dict[str, str] | None = None,
|
|
512
|
+
to_replace_for_username: dict[str, str] | None = None,
|
|
513
|
+
to_replace_for_account_id: dict[str, str] | None = None,
|
|
514
|
+
to_replace_for_biography: dict[str, str] | None = None,
|
|
517
515
|
) -> WorktimePerDate:
|
|
518
516
|
"""
|
|
519
517
|
引数から渡された情報を元に、インスタンス変数`df`内のユーザー情報をマスクして、新しいインスタンスを返します。
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from collections.abc import Collection
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from annofabapi.dataclass.task import Task as DcTask
|
|
9
9
|
from annofabapi.models import Task
|
|
@@ -21,13 +21,13 @@ class FilteringQuery:
|
|
|
21
21
|
絞り込み条件
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
task_query:
|
|
25
|
-
start_date:
|
|
26
|
-
end_date:
|
|
27
|
-
ignored_task_ids:
|
|
24
|
+
task_query: TaskQuery | None = None
|
|
25
|
+
start_date: str | None = None
|
|
26
|
+
end_date: str | None = None
|
|
27
|
+
ignored_task_ids: Collection[str] | None = None
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def _get_first_annotation_started_datetime(sub_task_history_list: list[dict[str, Any]]) ->
|
|
30
|
+
def _get_first_annotation_started_datetime(sub_task_history_list: list[dict[str, Any]]) -> str | None:
|
|
31
31
|
"""
|
|
32
32
|
1個のタスクのタスク履歴一覧から、最初に教師付フェーズを作業した日時を取得します。
|
|
33
33
|
"""
|
|
@@ -40,7 +40,7 @@ def _get_first_annotation_started_datetime(sub_task_history_list: list[dict[str,
|
|
|
40
40
|
return task_history_list_with_annotation_phase[0]["started_datetime"]
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def filter_task_histories(task_histories: dict[str, list[dict[str, Any]]], *, start_date:
|
|
43
|
+
def filter_task_histories(task_histories: dict[str, list[dict[str, Any]]], *, start_date: str | None = None, end_date: str | None = None) -> dict[str, list[dict[str, Any]]]:
|
|
44
44
|
"""
|
|
45
45
|
タスク履歴を絞り込みます。
|
|
46
46
|
|
|
@@ -4,7 +4,7 @@ import json
|
|
|
4
4
|
import logging
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any
|
|
8
8
|
|
|
9
9
|
from annofabapi.models import TaskPhase
|
|
10
10
|
from dataclasses_json import DataClassJsonMixin
|
|
@@ -36,13 +36,9 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
36
36
|
|
|
37
37
|
Args:
|
|
38
38
|
project_dir: ``annofabcli statistics visualize``コマンドによって出力されたプロジェクトディレクトリ
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- acceptance_completed: 受入フェーズの完了状態
|
|
43
|
-
- acceptance_reached: 受入フェーズに到達
|
|
44
|
-
- inspection_reached: 検査フェーズまたは受入フェーズに到達
|
|
45
|
-
- annotation_started: 教師付フェーズが着手された
|
|
39
|
+
task_completion_criteria: タスクの完了条件
|
|
40
|
+
metadata: プロジェクトIDや絞り込み条件などの情報が含まれるメタデータ。この情報はグラフに埋め込まれます。
|
|
41
|
+
custom_production_volume_list: 独自の生産量に関する列情報のリスト
|
|
46
42
|
"""
|
|
47
43
|
|
|
48
44
|
FILENAME_WHOLE_PERFORMANCE = "全体の生産性と品質.csv"
|
|
@@ -61,8 +57,8 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
61
57
|
project_dir: Path,
|
|
62
58
|
task_completion_criteria: TaskCompletionCriteria,
|
|
63
59
|
*,
|
|
64
|
-
metadata:
|
|
65
|
-
custom_production_volume_list:
|
|
60
|
+
metadata: dict[str, Any] | None = None,
|
|
61
|
+
custom_production_volume_list: list[ProductionVolumeColumn] | None = None,
|
|
66
62
|
) -> None:
|
|
67
63
|
self.project_dir = project_dir
|
|
68
64
|
self.task_completion_criteria = task_completion_criteria
|
|
@@ -130,7 +126,7 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
130
126
|
obj: AbstractPhaseCumulativeProductivity,
|
|
131
127
|
phase: TaskPhase,
|
|
132
128
|
*,
|
|
133
|
-
user_id_list:
|
|
129
|
+
user_id_list: list[str] | None = None,
|
|
134
130
|
minimal_output: bool = False,
|
|
135
131
|
) -> None:
|
|
136
132
|
"""
|
|
@@ -179,7 +175,7 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
179
175
|
phase_name = self.get_phase_name_for_filename(phase)
|
|
180
176
|
obj.to_csv(self.project_dir / Path(f"{phase_name}者_{phase_name}開始日list.csv"))
|
|
181
177
|
|
|
182
|
-
def write_performance_line_graph_per_date(self, obj: AbstractPhaseProductivityPerDate, phase: TaskPhase, *, user_id_list:
|
|
178
|
+
def write_performance_line_graph_per_date(self, obj: AbstractPhaseProductivityPerDate, phase: TaskPhase, *, user_id_list: list[str] | None = None) -> None:
|
|
183
179
|
"""
|
|
184
180
|
指定したフェーズの開始日ごとの作業時間や生産性情報を、折れ線グラフとして出力します。
|
|
185
181
|
"""
|
|
@@ -396,7 +392,7 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
396
392
|
"""`ユーザ_日付list-作業時間.csvを書き込む"""
|
|
397
393
|
obj.to_csv(self.project_dir / self.FILENAME_WORKTIME_PER_DATE_USER)
|
|
398
394
|
|
|
399
|
-
def write_worktime_line_graph(self, obj: WorktimePerDate, user_id_list:
|
|
395
|
+
def write_worktime_line_graph(self, obj: WorktimePerDate, user_id_list: list[str] | None = None) -> None:
|
|
400
396
|
"""横軸が日付、縦軸がユーザごとの作業時間である折れ線グラフを出力します。"""
|
|
401
397
|
obj.plot_cumulatively(self.project_dir / "line-graph/累積折れ線-横軸_日-縦軸_作業時間.html", target_user_id_list=user_id_list, metadata=self.metadata)
|
|
402
398
|
|
|
@@ -429,7 +425,7 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
429
425
|
"""
|
|
430
426
|
print_json(obj.to_dict(encode_json=True), output=self.project_dir / self.FILENAME_MERGE_INFO, is_pretty=True)
|
|
431
427
|
|
|
432
|
-
def read_metadata(self) ->
|
|
428
|
+
def read_metadata(self) -> dict[str, Any] | None:
|
|
433
429
|
"""
|
|
434
430
|
`project_info`または`merge_info`の内容をメタデータとして読み込む。
|
|
435
431
|
どちらも存在しない場合はNoneを返す。
|
|
@@ -448,6 +444,17 @@ class ProjectDir(DataClassJsonMixin):
|
|
|
448
444
|
|
|
449
445
|
return None
|
|
450
446
|
|
|
447
|
+
def get_project_title(self) -> str:
|
|
448
|
+
"""
|
|
449
|
+
`project_info`に記載されているプジェクトのタイトルを返します。
|
|
450
|
+
ただし`self.is_merged()`がTrueの場合は、`project_info`が存在しないので空文字を返します。
|
|
451
|
+
"""
|
|
452
|
+
if self.is_merged():
|
|
453
|
+
return ""
|
|
454
|
+
|
|
455
|
+
project_info = self.read_project_info()
|
|
456
|
+
return project_info.project_title
|
|
457
|
+
|
|
451
458
|
|
|
452
459
|
@dataclass
|
|
453
460
|
class ProjectInfo(DataClassJsonMixin):
|
|
@@ -464,6 +471,12 @@ class ProjectInfo(DataClassJsonMixin):
|
|
|
464
471
|
query: FilteringQuery
|
|
465
472
|
"""集計対象を絞り込むためのクエリ"""
|
|
466
473
|
|
|
474
|
+
production_volume_include_labels: list[str] | None = None
|
|
475
|
+
"""生産量に含める「アノテーション仕様のラベル名(英語)」のリスト。Noneの場合、すべてのラベルを含む。"""
|
|
476
|
+
|
|
477
|
+
production_volume_exclude_labels: list[str] | None = None
|
|
478
|
+
"""生産量から除外する「アノテーション仕様のラベル名(英語)」のリスト。Noneの場合、除外しない。"""
|
|
479
|
+
|
|
467
480
|
|
|
468
481
|
@dataclass
|
|
469
482
|
class MergingInfo(DataClassJsonMixin):
|
|
@@ -10,7 +10,7 @@ from collections import defaultdict
|
|
|
10
10
|
from collections.abc import Collection, Sequence
|
|
11
11
|
from functools import partial
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from typing import Any
|
|
13
|
+
from typing import Any
|
|
14
14
|
|
|
15
15
|
import bokeh
|
|
16
16
|
import numpy
|
|
@@ -20,7 +20,6 @@ from bokeh.models import LayoutDOM
|
|
|
20
20
|
from bokeh.models.widgets.markups import Div
|
|
21
21
|
from bokeh.plotting import figure
|
|
22
22
|
|
|
23
|
-
import annofabcli
|
|
24
23
|
import annofabcli.common.cli
|
|
25
24
|
from annofabcli.common.bokeh import convert_1d_figure_list_to_2d, create_pretext_from_metadata
|
|
26
25
|
from annofabcli.common.cli import (
|
|
@@ -56,11 +55,11 @@ def _get_y_axis_label(group_by: GroupBy) -> str:
|
|
|
56
55
|
raise RuntimeError(f"group_by='{group_by}'が対象外です。")
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
def convert_to_2d_figure_list(figures_dict: dict[tuple[str, str], list[figure]], *, ncols: int = 4) -> list[list[
|
|
58
|
+
def convert_to_2d_figure_list(figures_dict: dict[tuple[str, str], list[figure]], *, ncols: int = 4) -> list[list[LayoutDOM | None]]:
|
|
60
59
|
"""
|
|
61
60
|
grid layout用に2次元のfigureリストに変換する。
|
|
62
61
|
"""
|
|
63
|
-
row_list: list[list[
|
|
62
|
+
row_list: list[list[LayoutDOM | None]] = []
|
|
64
63
|
|
|
65
64
|
for (label_name, attribute_name), figure_list in figures_dict.items():
|
|
66
65
|
row_list.append([Div(text=f"<h3>ラベル名='{label_name}', 属性名='{attribute_name}'</h3>")])
|
|
@@ -68,7 +67,7 @@ def convert_to_2d_figure_list(figures_dict: dict[tuple[str, str], list[figure]],
|
|
|
68
67
|
for i in range(math.ceil(len(figure_list) / ncols)):
|
|
69
68
|
start = i * ncols
|
|
70
69
|
end = (i + 1) * ncols
|
|
71
|
-
row: list[
|
|
70
|
+
row: list[LayoutDOM | None] = []
|
|
72
71
|
row.extend(figure_list[start:end])
|
|
73
72
|
if len(row) < ncols:
|
|
74
73
|
row.extend([None] * (ncols - len(row)))
|
|
@@ -101,11 +100,11 @@ def plot_label_histogram(
|
|
|
101
100
|
group_by: GroupBy,
|
|
102
101
|
output_file: Path,
|
|
103
102
|
*,
|
|
104
|
-
prior_keys:
|
|
105
|
-
bin_width:
|
|
103
|
+
prior_keys: list[str] | None = None,
|
|
104
|
+
bin_width: int | None = None,
|
|
106
105
|
exclude_empty_value: bool = False,
|
|
107
106
|
arrange_bin_edge: bool = False,
|
|
108
|
-
metadata:
|
|
107
|
+
metadata: dict[str, Any] | None = None,
|
|
109
108
|
) -> None:
|
|
110
109
|
"""
|
|
111
110
|
ラベルごとのアノテーション数のヒストグラムを出力する。
|
|
@@ -152,7 +151,7 @@ def plot_label_histogram(
|
|
|
152
151
|
|
|
153
152
|
max_annotation_count = df.max(numeric_only=True).max()
|
|
154
153
|
|
|
155
|
-
figure_list_2d: list[list[
|
|
154
|
+
figure_list_2d: list[list[LayoutDOM | None]] = [
|
|
156
155
|
[
|
|
157
156
|
Div(text="<h3>アノテーション数の分布(ラベル名ごと)</h3>"),
|
|
158
157
|
]
|
|
@@ -203,11 +202,11 @@ def plot_attribute_histogram( # noqa: PLR0915
|
|
|
203
202
|
group_by: GroupBy,
|
|
204
203
|
output_file: Path,
|
|
205
204
|
*,
|
|
206
|
-
prior_keys:
|
|
207
|
-
bin_width:
|
|
205
|
+
prior_keys: list[AttributeValueKey] | None = None,
|
|
206
|
+
bin_width: int | None = None,
|
|
208
207
|
exclude_empty_value: bool = False,
|
|
209
208
|
arrange_bin_edge: bool = False,
|
|
210
|
-
metadata:
|
|
209
|
+
metadata: dict[str, Any] | None = None,
|
|
211
210
|
) -> None:
|
|
212
211
|
"""
|
|
213
212
|
属性値ごとのアノテーション数のヒストグラムを出力する。
|
|
@@ -256,7 +255,7 @@ def plot_attribute_histogram( # noqa: PLR0915
|
|
|
256
255
|
|
|
257
256
|
max_annotation_count = df.max(numeric_only=True).max()
|
|
258
257
|
|
|
259
|
-
figure_list_2d: list[list[
|
|
258
|
+
figure_list_2d: list[list[LayoutDOM | None]] = [
|
|
260
259
|
[
|
|
261
260
|
Div(text="<h3>アノテーション数の分布(属性値ごと)</h3>"),
|
|
262
261
|
]
|
|
@@ -322,10 +321,10 @@ class VisualizeAnnotationCount(CommandLine):
|
|
|
322
321
|
annotation_path: Path,
|
|
323
322
|
output_dir: Path,
|
|
324
323
|
*,
|
|
325
|
-
bin_width:
|
|
326
|
-
project_id:
|
|
327
|
-
target_task_ids:
|
|
328
|
-
task_query:
|
|
324
|
+
bin_width: int | None = None,
|
|
325
|
+
project_id: str | None = None,
|
|
326
|
+
target_task_ids: Collection[str] | None = None,
|
|
327
|
+
task_query: TaskQuery | None = None,
|
|
329
328
|
exclude_empty_value: bool = False,
|
|
330
329
|
arrange_bin_edge: bool = False,
|
|
331
330
|
) -> None:
|
|
@@ -333,8 +332,8 @@ class VisualizeAnnotationCount(CommandLine):
|
|
|
333
332
|
attributes_count_html = output_dir / "attributes_count.html"
|
|
334
333
|
|
|
335
334
|
# 集計対象の属性を、選択肢系の属性にする
|
|
336
|
-
annotation_specs:
|
|
337
|
-
non_selective_attribute_name_keys:
|
|
335
|
+
annotation_specs: AnnotationSpecs | None = None
|
|
336
|
+
non_selective_attribute_name_keys: list[AttributeNameKey] | None = None
|
|
338
337
|
if project_id is not None:
|
|
339
338
|
annotation_specs = AnnotationSpecs(self.service, project_id)
|
|
340
339
|
non_selective_attribute_name_keys = annotation_specs.non_selective_attribute_name_keys()
|
|
@@ -361,8 +360,8 @@ class VisualizeAnnotationCount(CommandLine):
|
|
|
361
360
|
else:
|
|
362
361
|
raise RuntimeError(f"group_by='{group_by}'が対象外です。")
|
|
363
362
|
|
|
364
|
-
label_keys:
|
|
365
|
-
attribute_value_keys:
|
|
363
|
+
label_keys: list[str] | None = None
|
|
364
|
+
attribute_value_keys: list[AttributeValueKey] | None = None
|
|
366
365
|
if annotation_specs is not None:
|
|
367
366
|
label_keys = annotation_specs.label_keys()
|
|
368
367
|
attribute_value_keys = annotation_specs.selective_attribute_value_keys()
|
|
@@ -406,7 +405,7 @@ class VisualizeAnnotationCount(CommandLine):
|
|
|
406
405
|
if not self.validate(args):
|
|
407
406
|
sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
|
|
408
407
|
|
|
409
|
-
project_id:
|
|
408
|
+
project_id: str | None = args.project_id
|
|
410
409
|
if project_id is not None:
|
|
411
410
|
super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
|
|
412
411
|
|
|
@@ -534,7 +533,7 @@ def main(args: argparse.Namespace) -> None:
|
|
|
534
533
|
VisualizeAnnotationCount(service, facade, args).main()
|
|
535
534
|
|
|
536
535
|
|
|
537
|
-
def add_parser(subparsers:
|
|
536
|
+
def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
|
|
538
537
|
subcommand_name = "visualize_annotation_count"
|
|
539
538
|
subcommand_help = "各ラベル、各属性値のアノテーション数をヒストグラムで可視化します。"
|
|
540
539
|
description = "各ラベル、各属性値のアノテーション数をヒストグラムで可視化したファイルを出力します。"
|
|
@@ -9,7 +9,7 @@ from collections.abc import Collection, Sequence
|
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from functools import partial
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any
|
|
12
|
+
from typing import Any
|
|
13
13
|
|
|
14
14
|
import bokeh
|
|
15
15
|
import numpy
|
|
@@ -19,7 +19,6 @@ from bokeh.models import LayoutDOM
|
|
|
19
19
|
from bokeh.models.widgets.markups import Div
|
|
20
20
|
from bokeh.plotting import figure
|
|
21
21
|
|
|
22
|
-
import annofabcli
|
|
23
22
|
import annofabcli.common.cli
|
|
24
23
|
from annofabcli.common.bokeh import convert_1d_figure_list_to_2d, create_pretext_from_metadata
|
|
25
24
|
from annofabcli.common.cli import (
|
|
@@ -56,11 +55,11 @@ def plot_annotation_duration_histogram_by_label( # noqa: PLR0915
|
|
|
56
55
|
output_file: Path,
|
|
57
56
|
*,
|
|
58
57
|
time_unit: TimeUnit,
|
|
59
|
-
bin_width:
|
|
60
|
-
prior_keys:
|
|
58
|
+
bin_width: float | None = None,
|
|
59
|
+
prior_keys: list[str] | None = None,
|
|
61
60
|
exclude_empty_value: bool = False,
|
|
62
61
|
arrange_bin_edge: bool = False,
|
|
63
|
-
metadata:
|
|
62
|
+
metadata: dict[str, Any] | None = None,
|
|
64
63
|
) -> None:
|
|
65
64
|
"""
|
|
66
65
|
ラベルごとの区間アノテーションの長さのヒストグラムを出力します。
|
|
@@ -88,7 +87,7 @@ def plot_annotation_duration_histogram_by_label( # noqa: PLR0915
|
|
|
88
87
|
df = df / 60
|
|
89
88
|
return df
|
|
90
89
|
|
|
91
|
-
def get_histogram_range(df: pandas.DataFrame) ->
|
|
90
|
+
def get_histogram_range(df: pandas.DataFrame) -> tuple[float, float] | None:
|
|
92
91
|
if arrange_bin_edge:
|
|
93
92
|
return (
|
|
94
93
|
df.min(numeric_only=True).min(),
|
|
@@ -101,7 +100,7 @@ def plot_annotation_duration_histogram_by_label( # noqa: PLR0915
|
|
|
101
100
|
|
|
102
101
|
max_duration = df.max(numeric_only=True).max()
|
|
103
102
|
|
|
104
|
-
figure_list_2d: list[list[
|
|
103
|
+
figure_list_2d: list[list[LayoutDOM | None]] = [
|
|
105
104
|
[
|
|
106
105
|
Div(text="<h3>区間アノテーションの長さの分布(ラベル名ごと)</h3>"),
|
|
107
106
|
]
|
|
@@ -165,11 +164,11 @@ def plot_annotation_duration_histogram_by_attribute( # noqa: PLR0915
|
|
|
165
164
|
output_file: Path,
|
|
166
165
|
*,
|
|
167
166
|
time_unit: TimeUnit,
|
|
168
|
-
bin_width:
|
|
169
|
-
prior_keys:
|
|
167
|
+
bin_width: float | None = None,
|
|
168
|
+
prior_keys: list[AttributeValueKey] | None = None,
|
|
170
169
|
exclude_empty_value: bool = False,
|
|
171
170
|
arrange_bin_edge: bool = False,
|
|
172
|
-
metadata:
|
|
171
|
+
metadata: dict[str, Any] | None = None,
|
|
173
172
|
) -> None:
|
|
174
173
|
"""
|
|
175
174
|
属性値ごとの区間アノテーションの長さのヒストグラムを出力します。
|
|
@@ -198,7 +197,7 @@ def plot_annotation_duration_histogram_by_attribute( # noqa: PLR0915
|
|
|
198
197
|
df = df / 60
|
|
199
198
|
return df
|
|
200
199
|
|
|
201
|
-
def get_histogram_range(df: pandas.DataFrame) ->
|
|
200
|
+
def get_histogram_range(df: pandas.DataFrame) -> tuple[float, float] | None:
|
|
202
201
|
if arrange_bin_edge:
|
|
203
202
|
return (
|
|
204
203
|
df.min(numeric_only=True).min(),
|
|
@@ -224,7 +223,7 @@ def plot_annotation_duration_histogram_by_attribute( # noqa: PLR0915
|
|
|
224
223
|
max_duration = df.max(numeric_only=True).max()
|
|
225
224
|
x_axis_label = "区間アノテーションの長さ[分]" if time_unit == TimeUnit.MINUTE else "区間アノテーションの長さ[秒]"
|
|
226
225
|
|
|
227
|
-
figure_list_2d: list[list[
|
|
226
|
+
figure_list_2d: list[list[LayoutDOM | None]] = [
|
|
228
227
|
[
|
|
229
228
|
Div(text="<h3>区間アノテーションの長さの分布(属性値ごと)</h3>"),
|
|
230
229
|
]
|
|
@@ -290,10 +289,10 @@ class VisualizeAnnotationDuration(CommandLine):
|
|
|
290
289
|
output_dir: Path,
|
|
291
290
|
time_unit: TimeUnit,
|
|
292
291
|
*,
|
|
293
|
-
bin_width:
|
|
294
|
-
project_id:
|
|
295
|
-
target_task_ids:
|
|
296
|
-
task_query:
|
|
292
|
+
bin_width: int | None = None,
|
|
293
|
+
project_id: str | None = None,
|
|
294
|
+
target_task_ids: Collection[str] | None = None,
|
|
295
|
+
task_query: TaskQuery | None = None,
|
|
297
296
|
exclude_empty_value: bool = False,
|
|
298
297
|
arrange_bin_edge: bool = False,
|
|
299
298
|
) -> None:
|
|
@@ -301,8 +300,8 @@ class VisualizeAnnotationDuration(CommandLine):
|
|
|
301
300
|
duration_by_attribute_html = output_dir / "annotation_duration_by_attribute.html"
|
|
302
301
|
|
|
303
302
|
# 集計対象の属性を、選択肢系の属性にする
|
|
304
|
-
annotation_specs:
|
|
305
|
-
non_selective_attribute_name_keys:
|
|
303
|
+
annotation_specs: AnnotationSpecs | None = None
|
|
304
|
+
non_selective_attribute_name_keys: list[AttributeNameKey] | None = None
|
|
306
305
|
if project_id is not None:
|
|
307
306
|
annotation_specs = AnnotationSpecs(self.service, project_id, annotation_type=DefaultAnnotationType.RANGE.value)
|
|
308
307
|
non_selective_attribute_name_keys = annotation_specs.non_selective_attribute_name_keys()
|
|
@@ -315,8 +314,8 @@ class VisualizeAnnotationDuration(CommandLine):
|
|
|
315
314
|
task_query=task_query,
|
|
316
315
|
)
|
|
317
316
|
|
|
318
|
-
label_keys:
|
|
319
|
-
attribute_value_keys:
|
|
317
|
+
label_keys: list[str] | None = None
|
|
318
|
+
attribute_value_keys: list[AttributeValueKey] | None = None
|
|
320
319
|
if annotation_specs is not None:
|
|
321
320
|
label_keys = annotation_specs.label_keys()
|
|
322
321
|
attribute_value_keys = annotation_specs.selective_attribute_value_keys()
|
|
@@ -359,7 +358,7 @@ class VisualizeAnnotationDuration(CommandLine):
|
|
|
359
358
|
if not self.validate(args):
|
|
360
359
|
sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
|
|
361
360
|
|
|
362
|
-
project_id:
|
|
361
|
+
project_id: str | None = args.project_id
|
|
363
362
|
if project_id is not None:
|
|
364
363
|
super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
|
|
365
364
|
project, _ = self.service.api.get_project(project_id)
|
|
@@ -487,7 +486,7 @@ def main(args: argparse.Namespace) -> None:
|
|
|
487
486
|
VisualizeAnnotationDuration(service, facade, args).main()
|
|
488
487
|
|
|
489
488
|
|
|
490
|
-
def add_parser(subparsers:
|
|
489
|
+
def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
|
|
491
490
|
subcommand_name = "visualize_annotation_duration"
|
|
492
491
|
subcommand_help = "ラベルごとまたは属性値ごとに区間アノテーションの長さをヒストグラムで可視化したファイルを出力します。"
|
|
493
492
|
epilog = "オーナロールまたはアノテーションユーザロールを持つユーザで実行してください。"
|
|
@@ -6,9 +6,10 @@ import json
|
|
|
6
6
|
import logging.handlers
|
|
7
7
|
import sys
|
|
8
8
|
import tempfile
|
|
9
|
+
from collections.abc import Callable
|
|
9
10
|
from multiprocessing import Pool
|
|
10
11
|
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
12
|
+
from typing import Any
|
|
12
13
|
|
|
13
14
|
import annofabapi
|
|
14
15
|
import pandas
|
|
@@ -74,13 +75,13 @@ class WriteCsvGraph:
|
|
|
74
75
|
project_dir: ProjectDir,
|
|
75
76
|
actual_worktime: ActualWorktime,
|
|
76
77
|
*,
|
|
77
|
-
annotation_count:
|
|
78
|
-
input_data_count:
|
|
79
|
-
custom_production_volume:
|
|
78
|
+
annotation_count: AnnotationCount | None = None,
|
|
79
|
+
input_data_count: InputDataCount | None = None,
|
|
80
|
+
custom_production_volume: CustomProductionVolume | None = None,
|
|
80
81
|
minimal_output: bool = False,
|
|
81
82
|
output_only_text: bool = False,
|
|
82
|
-
production_volume_include_labels:
|
|
83
|
-
production_volume_exclude_labels:
|
|
83
|
+
production_volume_include_labels: list[str] | None = None,
|
|
84
|
+
production_volume_exclude_labels: list[str] | None = None,
|
|
84
85
|
include_annotation_duration_seconds: bool = False,
|
|
85
86
|
include_video_duration_minutes: bool = False,
|
|
86
87
|
) -> None:
|
|
@@ -101,9 +102,9 @@ class WriteCsvGraph:
|
|
|
101
102
|
self.include_annotation_duration_seconds = include_annotation_duration_seconds
|
|
102
103
|
self.include_video_duration_minutes = include_video_duration_minutes
|
|
103
104
|
|
|
104
|
-
self.task:
|
|
105
|
-
self.worktime_per_date:
|
|
106
|
-
self.task_worktime_obj:
|
|
105
|
+
self.task: Task | None = None
|
|
106
|
+
self.worktime_per_date: WorktimePerDate | None = None
|
|
107
|
+
self.task_worktime_obj: TaskWorktimeByPhaseUser | None = None
|
|
107
108
|
|
|
108
109
|
def _catch_exception(self, function: Callable[..., Any]) -> Callable[..., Any]:
|
|
109
110
|
"""
|
|
@@ -156,7 +157,7 @@ class WriteCsvGraph:
|
|
|
156
157
|
|
|
157
158
|
return self.task
|
|
158
159
|
|
|
159
|
-
def _prepare_custom_production_volume(self) ->
|
|
160
|
+
def _prepare_custom_production_volume(self) -> CustomProductionVolume | None:
|
|
160
161
|
"""カスタム生産量の準備を行う"""
|
|
161
162
|
custom_production_volume = self.custom_production_volume
|
|
162
163
|
|
|
@@ -170,7 +171,7 @@ class WriteCsvGraph:
|
|
|
170
171
|
|
|
171
172
|
return custom_production_volume
|
|
172
173
|
|
|
173
|
-
def _add_annotation_duration(self, custom_production_volume:
|
|
174
|
+
def _add_annotation_duration(self, custom_production_volume: CustomProductionVolume | None) -> CustomProductionVolume:
|
|
174
175
|
"""区間アノテーションの長さを生産量に追加する"""
|
|
175
176
|
logger.debug(f"project_id='{self.project_id}' :: 区間アノテーションの長さ('annotation_duration_minute')を計算します。")
|
|
176
177
|
annotation_duration_obj = AnnotationDuration.from_annotation_zip(
|
|
@@ -198,7 +199,7 @@ class WriteCsvGraph:
|
|
|
198
199
|
# CustomProductionVolumeが存在しない場合、新規作成
|
|
199
200
|
return CustomProductionVolume(annotation_duration_obj.df, custom_production_volume_list=[annotation_duration_column])
|
|
200
201
|
|
|
201
|
-
def _add_video_duration(self, custom_production_volume:
|
|
202
|
+
def _add_video_duration(self, custom_production_volume: CustomProductionVolume | None) -> CustomProductionVolume:
|
|
202
203
|
"""動画の長さ(分)を生産量に追加する"""
|
|
203
204
|
logger.debug(f"project_id='{self.project_id}' :: 動画の長さ('video_duration_minute')を計算します。")
|
|
204
205
|
video_duration_by_task_id = self.visualize_source_files.get_video_duration_minutes_by_task_id()
|
|
@@ -297,7 +298,7 @@ class WriteCsvGraph:
|
|
|
297
298
|
if not self.output_only_text:
|
|
298
299
|
self.project_dir.write_user_performance_scatter_plot(user_performance)
|
|
299
300
|
|
|
300
|
-
def write_cumulative_linegraph_by_user(self, user_id_list:
|
|
301
|
+
def write_cumulative_linegraph_by_user(self, user_id_list: list[str] | None = None) -> None:
|
|
301
302
|
"""ユーザごとの累積折れ線グラフをプロットする。"""
|
|
302
303
|
task_worktime_obj = self._get_task_worktime_obj()
|
|
303
304
|
annotator_obj = AnnotatorCumulativeProductivity.from_df_wrapper(task_worktime_obj)
|
|
@@ -309,7 +310,7 @@ class WriteCsvGraph:
|
|
|
309
310
|
self.project_dir.write_cumulative_line_graph(inspector_obj, phase=TaskPhase.INSPECTION, user_id_list=user_id_list, minimal_output=self.minimal_output)
|
|
310
311
|
self.project_dir.write_cumulative_line_graph(acceptor_obj, phase=TaskPhase.ACCEPTANCE, user_id_list=user_id_list, minimal_output=self.minimal_output)
|
|
311
312
|
|
|
312
|
-
def write_worktime_per_date(self, user_id_list:
|
|
313
|
+
def write_worktime_per_date(self, user_id_list: list[str] | None = None) -> None:
|
|
313
314
|
"""日ごとの作業時間情報を出力する。"""
|
|
314
315
|
worktime_per_date_obj = self._get_worktime_per_date()
|
|
315
316
|
|
|
@@ -328,7 +329,7 @@ class WriteCsvGraph:
|
|
|
328
329
|
self.project_dir.write_whole_productivity_line_graph_per_date(productivity_per_completed_date_obj)
|
|
329
330
|
self.project_dir.write_whole_productivity_line_graph_per_annotation_started_date(productivity_per_started_date_obj)
|
|
330
331
|
|
|
331
|
-
def write_user_productivity_per_date(self, user_id_list:
|
|
332
|
+
def write_user_productivity_per_date(self, user_id_list: list[str] | None = None) -> None:
|
|
332
333
|
"""ユーザごとの日ごとの生産性情報を出力する。"""
|
|
333
334
|
task_worktime_obj = self._get_task_worktime_obj()
|
|
334
335
|
|
|
@@ -362,14 +363,14 @@ class VisualizingStatisticsMain:
|
|
|
362
363
|
# その他
|
|
363
364
|
download_latest: bool = False,
|
|
364
365
|
is_get_task_histories_one_of_each: bool = False,
|
|
365
|
-
actual_worktime:
|
|
366
|
-
annotation_count:
|
|
367
|
-
input_data_count:
|
|
368
|
-
custom_production_volume:
|
|
369
|
-
user_ids:
|
|
366
|
+
actual_worktime: ActualWorktime | None = None,
|
|
367
|
+
annotation_count: AnnotationCount | None = None,
|
|
368
|
+
input_data_count: InputDataCount | None = None,
|
|
369
|
+
custom_production_volume: CustomProductionVolume | None = None,
|
|
370
|
+
user_ids: list[str] | None = None,
|
|
370
371
|
not_download_visualization_source_files: bool = False,
|
|
371
|
-
production_volume_include_labels:
|
|
372
|
-
production_volume_exclude_labels:
|
|
372
|
+
production_volume_include_labels: list[str] | None = None,
|
|
373
|
+
production_volume_exclude_labels: list[str] | None = None,
|
|
373
374
|
) -> None:
|
|
374
375
|
self.service = service
|
|
375
376
|
self.facade = AnnofabApiFacade(service)
|
|
@@ -400,6 +401,8 @@ class VisualizingStatisticsMain:
|
|
|
400
401
|
measurement_datetime=annofabapi.utils.str_now(),
|
|
401
402
|
task_completion_criteria=self.task_completion_criteria,
|
|
402
403
|
query=self.filtering_query,
|
|
404
|
+
production_volume_include_labels=self.production_volume_include_labels,
|
|
405
|
+
production_volume_exclude_labels=self.production_volume_exclude_labels,
|
|
403
406
|
)
|
|
404
407
|
return project_summary
|
|
405
408
|
|
|
@@ -501,7 +504,7 @@ class VisualizingStatisticsMain:
|
|
|
501
504
|
self,
|
|
502
505
|
project_id: str,
|
|
503
506
|
root_output_dir: Path,
|
|
504
|
-
) ->
|
|
507
|
+
) -> Path | None:
|
|
505
508
|
try:
|
|
506
509
|
output_project_dir = root_output_dir / project_id
|
|
507
510
|
self.visualize_statistics(
|
|
@@ -518,7 +521,7 @@ class VisualizingStatisticsMain:
|
|
|
518
521
|
project_id_list: list[str],
|
|
519
522
|
root_output_dir: Path,
|
|
520
523
|
*,
|
|
521
|
-
parallelism:
|
|
524
|
+
parallelism: int | None = None,
|
|
522
525
|
) -> list[Path]:
|
|
523
526
|
output_project_dir_list: list[Path] = []
|
|
524
527
|
|
|
@@ -581,11 +584,11 @@ class VisualizeStatistics(CommandLine):
|
|
|
581
584
|
temp_dir: Path,
|
|
582
585
|
filtering_query: FilteringQuery,
|
|
583
586
|
task_completion_criteria: TaskCompletionCriteria,
|
|
584
|
-
user_id_list:
|
|
587
|
+
user_id_list: list[str] | None,
|
|
585
588
|
actual_worktime: ActualWorktime,
|
|
586
|
-
annotation_count:
|
|
587
|
-
input_data_count:
|
|
588
|
-
custom_production_volume:
|
|
589
|
+
annotation_count: AnnotationCount | None,
|
|
590
|
+
input_data_count: InputDataCount | None,
|
|
591
|
+
custom_production_volume: CustomProductionVolume | None,
|
|
589
592
|
download_latest: bool, # noqa: FBT001
|
|
590
593
|
is_get_task_histories_one_of_each: bool, # noqa: FBT001
|
|
591
594
|
minimal_output: bool, # noqa: FBT001
|
|
@@ -593,9 +596,9 @@ class VisualizeStatistics(CommandLine):
|
|
|
593
596
|
not_download_visualization_source_files: bool, # noqa: FBT001
|
|
594
597
|
project_id_list: list[str],
|
|
595
598
|
root_output_dir: Path,
|
|
596
|
-
parallelism:
|
|
597
|
-
production_volume_include_labels:
|
|
598
|
-
production_volume_exclude_labels:
|
|
599
|
+
parallelism: int | None,
|
|
600
|
+
production_volume_include_labels: list[str] | None = None,
|
|
601
|
+
production_volume_exclude_labels: list[str] | None = None,
|
|
599
602
|
) -> None:
|
|
600
603
|
main_obj = VisualizingStatisticsMain(
|
|
601
604
|
service=self.service,
|
|
@@ -650,7 +653,7 @@ class VisualizeStatistics(CommandLine):
|
|
|
650
653
|
task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
|
|
651
654
|
|
|
652
655
|
dict_task_query = annofabcli.common.cli.get_json_from_args(args.task_query)
|
|
653
|
-
task_query:
|
|
656
|
+
task_query: TaskQuery | None = None
|
|
654
657
|
if dict_task_query is not None:
|
|
655
658
|
task_query = TaskQuery.from_dict(dict_task_query)
|
|
656
659
|
logger.warning("引数 '--task_query' は非推奨です。代わりに '--task_completion_criteria' を指定してください。")
|
|
@@ -906,7 +909,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
906
909
|
parser.set_defaults(subcommand_func=main)
|
|
907
910
|
|
|
908
911
|
|
|
909
|
-
def add_parser(subparsers:
|
|
912
|
+
def add_parser(subparsers: argparse._SubParsersAction | None = None) -> argparse.ArgumentParser:
|
|
910
913
|
subcommand_name = "visualize"
|
|
911
914
|
subcommand_help = "生産性に関するCSVファイルやグラフを出力します。"
|
|
912
915
|
description = "生産性に関するCSVファイルやグラフを出力します。"
|