annofabcli 1.102.1__py3-none-any.whl → 1.103.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/annotation/annotation_query.py +9 -29
- annofabcli/annotation/change_annotation_attributes.py +6 -14
- annofabcli/annotation/change_annotation_properties.py +5 -12
- annofabcli/annotation/copy_annotation.py +4 -10
- annofabcli/annotation/delete_annotation.py +10 -26
- annofabcli/annotation/dump_annotation.py +1 -4
- annofabcli/annotation/import_annotation.py +16 -40
- annofabcli/annotation/list_annotation.py +1 -4
- annofabcli/annotation/merge_segmentation.py +5 -15
- annofabcli/annotation/remove_segmentation_overlap.py +8 -29
- annofabcli/annotation/restore_annotation.py +3 -9
- annofabcli/annotation_specs/add_attribute_restriction.py +2 -8
- annofabcli/annotation_specs/attribute_restriction.py +2 -10
- annofabcli/annotation_specs/export_annotation_specs.py +1 -3
- annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +3 -10
- annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +4 -10
- annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +1 -3
- annofabcli/annotation_specs/list_annotation_specs_attribute.py +7 -18
- annofabcli/annotation_specs/list_annotation_specs_choice.py +3 -8
- annofabcli/annotation_specs/list_annotation_specs_history.py +0 -1
- annofabcli/annotation_specs/list_annotation_specs_label.py +3 -8
- annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +4 -9
- annofabcli/annotation_specs/list_attribute_restriction.py +3 -9
- annofabcli/annotation_specs/put_label_color.py +1 -6
- annofabcli/comment/delete_comment.py +3 -9
- annofabcli/comment/list_all_comment.py +2 -4
- annofabcli/comment/list_comment.py +1 -4
- annofabcli/comment/put_comment.py +4 -13
- annofabcli/comment/put_comment_simply.py +2 -6
- annofabcli/comment/put_inspection_comment.py +2 -6
- annofabcli/comment/put_inspection_comment_simply.py +3 -6
- annofabcli/comment/put_onhold_comment.py +2 -6
- annofabcli/comment/put_onhold_comment_simply.py +2 -4
- annofabcli/common/cli.py +5 -43
- annofabcli/common/download.py +8 -25
- annofabcli/common/image.py +5 -9
- annofabcli/common/utils.py +1 -3
- annofabcli/common/visualize.py +2 -4
- annofabcli/filesystem/draw_annotation.py +8 -20
- annofabcli/filesystem/filter_annotation.py +7 -24
- annofabcli/filesystem/mask_user_info.py +3 -6
- annofabcli/filesystem/merge_annotation.py +2 -6
- annofabcli/input_data/change_input_data_name.py +3 -7
- annofabcli/input_data/copy_input_data.py +6 -14
- annofabcli/input_data/delete_input_data.py +7 -24
- annofabcli/input_data/delete_metadata_key_of_input_data.py +5 -16
- annofabcli/input_data/list_all_input_data.py +5 -14
- annofabcli/input_data/list_all_input_data_merged_task.py +8 -23
- annofabcli/input_data/list_input_data.py +5 -16
- annofabcli/input_data/put_input_data.py +7 -19
- annofabcli/input_data/update_metadata_of_input_data.py +6 -14
- annofabcli/instruction/list_instruction_history.py +0 -1
- annofabcli/instruction/upload_instruction.py +1 -4
- annofabcli/job/list_job.py +1 -2
- annofabcli/job/list_last_job.py +1 -3
- annofabcli/organization/list_organization.py +0 -1
- annofabcli/organization_member/change_organization_member.py +1 -3
- annofabcli/organization_member/delete_organization_member.py +2 -6
- annofabcli/organization_member/invite_organization_member.py +1 -3
- annofabcli/organization_member/list_organization_member.py +0 -1
- annofabcli/project/change_organization_of_project.py +257 -0
- annofabcli/project/change_project_status.py +2 -2
- annofabcli/project/copy_project.py +2 -7
- annofabcli/project/diff_projects.py +4 -16
- annofabcli/project/list_project.py +0 -1
- annofabcli/project/put_project.py +2 -6
- annofabcli/project/subcommand_project.py +2 -0
- annofabcli/project_member/change_project_members.py +2 -2
- annofabcli/project_member/copy_project_members.py +2 -7
- annofabcli/project_member/drop_project_members.py +1 -3
- annofabcli/project_member/invite_project_members.py +1 -3
- annofabcli/project_member/list_users.py +0 -1
- annofabcli/project_member/put_project_members.py +4 -12
- annofabcli/stat_visualization/mask_visualization_dir.py +6 -16
- annofabcli/stat_visualization/merge_visualization_dir.py +6 -18
- annofabcli/stat_visualization/summarize_whole_performance_csv.py +3 -7
- annofabcli/stat_visualization/write_graph.py +5 -15
- annofabcli/stat_visualization/write_performance_rating_csv.py +4 -12
- annofabcli/statistics/list_annotation_area.py +3 -7
- annofabcli/statistics/list_annotation_attribute.py +6 -15
- annofabcli/statistics/list_annotation_attribute_filled_count.py +9 -23
- annofabcli/statistics/list_annotation_count.py +18 -44
- annofabcli/statistics/list_annotation_duration.py +14 -40
- annofabcli/statistics/list_video_duration.py +2 -3
- annofabcli/statistics/list_worktime.py +0 -1
- annofabcli/statistics/scatter.py +3 -9
- annofabcli/statistics/summarize_task_count.py +7 -12
- annofabcli/statistics/summarize_task_count_by_task_id_group.py +3 -11
- annofabcli/statistics/summarize_task_count_by_user.py +1 -5
- annofabcli/statistics/visualization/dataframe/annotation_count.py +1 -3
- annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +3 -9
- annofabcli/statistics/visualization/dataframe/productivity_per_date.py +11 -23
- annofabcli/statistics/visualization/dataframe/project_performance.py +1 -3
- annofabcli/statistics/visualization/dataframe/task.py +2 -5
- annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +6 -20
- annofabcli/statistics/visualization/dataframe/user_performance.py +29 -88
- annofabcli/statistics/visualization/dataframe/whole_performance.py +4 -10
- annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +17 -49
- annofabcli/statistics/visualization/dataframe/worktime_per_date.py +3 -9
- annofabcli/statistics/visualization/filtering_query.py +2 -6
- annofabcli/statistics/visualization/project_dir.py +9 -26
- annofabcli/statistics/visualization/visualization_source_files.py +3 -10
- annofabcli/statistics/visualize_annotation_count.py +7 -21
- annofabcli/statistics/visualize_annotation_duration.py +7 -17
- annofabcli/statistics/visualize_statistics.py +17 -52
- annofabcli/statistics/visualize_video_duration.py +8 -19
- annofabcli/supplementary/delete_supplementary_data.py +7 -23
- annofabcli/supplementary/list_supplementary_data.py +1 -1
- annofabcli/supplementary/put_supplementary_data.py +5 -15
- annofabcli/task/cancel_acceptance.py +3 -4
- annofabcli/task/change_operator.py +3 -11
- annofabcli/task/change_status_to_break.py +1 -1
- annofabcli/task/change_status_to_on_hold.py +5 -18
- annofabcli/task/complete_tasks.py +8 -25
- annofabcli/task/copy_tasks.py +2 -3
- annofabcli/task/delete_metadata_key_of_task.py +2 -6
- annofabcli/task/delete_tasks.py +7 -25
- annofabcli/task/list_all_tasks.py +2 -4
- annofabcli/task/list_tasks.py +2 -6
- annofabcli/task/list_tasks_added_task_history.py +7 -21
- annofabcli/task/put_tasks.py +2 -3
- annofabcli/task/put_tasks_by_count.py +3 -7
- annofabcli/task/reject_tasks.py +7 -19
- annofabcli/task/update_metadata_of_task.py +1 -1
- annofabcli/task_history/list_all_task_history.py +2 -5
- annofabcli/task_history/list_task_history.py +0 -1
- annofabcli/task_history_event/list_all_task_history_event.py +4 -11
- annofabcli/task_history_event/list_worktime.py +4 -14
- {annofabcli-1.102.1.dist-info → annofabcli-1.103.0.dist-info}/METADATA +1 -1
- annofabcli-1.103.0.dist-info/RECORD +215 -0
- annofabcli-1.102.1.dist-info/RECORD +0 -214
- {annofabcli-1.102.1.dist-info → annofabcli-1.103.0.dist-info}/WHEEL +0 -0
- {annofabcli-1.102.1.dist-info → annofabcli-1.103.0.dist-info}/entry_points.txt +0 -0
- {annofabcli-1.102.1.dist-info → annofabcli-1.103.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -66,15 +66,9 @@ class WritingGraph:
|
|
|
66
66
|
inspector_per_date_obj = InspectorProductivityPerDate.from_df_wrapper(task_worktime_list)
|
|
67
67
|
acceptor_per_date_obj = AcceptorProductivityPerDate.from_df_wrapper(task_worktime_list)
|
|
68
68
|
|
|
69
|
-
self.output_project_dir.write_performance_line_graph_per_date(
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
self.output_project_dir.write_performance_line_graph_per_date(
|
|
73
|
-
inspector_per_date_obj, phase=TaskPhase.INSPECTION, user_id_list=self.user_id_list
|
|
74
|
-
)
|
|
75
|
-
self.output_project_dir.write_performance_line_graph_per_date(
|
|
76
|
-
acceptor_per_date_obj, phase=TaskPhase.ACCEPTANCE, user_id_list=self.user_id_list
|
|
77
|
-
)
|
|
69
|
+
self.output_project_dir.write_performance_line_graph_per_date(annotator_per_date_obj, phase=TaskPhase.ANNOTATION, user_id_list=self.user_id_list)
|
|
70
|
+
self.output_project_dir.write_performance_line_graph_per_date(inspector_per_date_obj, phase=TaskPhase.INSPECTION, user_id_list=self.user_id_list)
|
|
71
|
+
self.output_project_dir.write_performance_line_graph_per_date(acceptor_per_date_obj, phase=TaskPhase.ACCEPTANCE, user_id_list=self.user_id_list)
|
|
78
72
|
|
|
79
73
|
def main(self) -> None:
|
|
80
74
|
try:
|
|
@@ -103,9 +97,7 @@ class WritingGraph:
|
|
|
103
97
|
logger.warning("'日毎の生産量と生産性.csv'から生成できるグラフの出力に失敗しました。", exc_info=True)
|
|
104
98
|
|
|
105
99
|
try:
|
|
106
|
-
self.output_project_dir.write_whole_productivity_line_graph_per_annotation_started_date(
|
|
107
|
-
self.project_dir.read_whole_productivity_per_first_annotation_started_date()
|
|
108
|
-
)
|
|
100
|
+
self.output_project_dir.write_whole_productivity_line_graph_per_annotation_started_date(self.project_dir.read_whole_productivity_per_first_annotation_started_date())
|
|
109
101
|
except Exception:
|
|
110
102
|
logger.warning("'教師付者_教師付開始日list.csv'から生成できるグラフの出力に失敗しました。", exc_info=True)
|
|
111
103
|
|
|
@@ -130,9 +122,7 @@ def create_custom_production_volume_list(cli_value: str) -> list[ProductionVolum
|
|
|
130
122
|
def main(args: argparse.Namespace) -> None:
|
|
131
123
|
user_id_list = get_list_from_args(args.user_id) if args.user_id is not None else None
|
|
132
124
|
|
|
133
|
-
custom_production_volume_list = (
|
|
134
|
-
create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
|
|
135
|
-
)
|
|
125
|
+
custom_production_volume_list = create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
|
|
136
126
|
|
|
137
127
|
task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
|
|
138
128
|
input_project_dir = ProjectDir(args.dir, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
|
|
@@ -171,12 +171,8 @@ class CollectingPerformanceInfo:
|
|
|
171
171
|
quality_indicator_by_directory: Optional[QualityIndicatorByDirectory] = None,
|
|
172
172
|
threshold_infos_by_directory: Optional[ThresholdInfoSettings] = None,
|
|
173
173
|
) -> None:
|
|
174
|
-
self.quality_indicator = (
|
|
175
|
-
|
|
176
|
-
)
|
|
177
|
-
self.productivity_indicator = (
|
|
178
|
-
productivity_indicator if productivity_indicator is not None else ProductivityIndicator("actual_worktime_hour/annotation_count")
|
|
179
|
-
)
|
|
174
|
+
self.quality_indicator = quality_indicator if quality_indicator is not None else QualityIndicator("pointed_out_inspection_comment_count/annotation_count")
|
|
175
|
+
self.productivity_indicator = productivity_indicator if productivity_indicator is not None else ProductivityIndicator("actual_worktime_hour/annotation_count")
|
|
180
176
|
self.threshold_info = threshold_info if threshold_info is not None else ThresholdInfo()
|
|
181
177
|
self.threshold_infos_by_directory = threshold_infos_by_directory if threshold_infos_by_directory is not None else {}
|
|
182
178
|
self.productivity_indicator_by_directory = productivity_indicator_by_directory if productivity_indicator_by_directory is not None else {}
|
|
@@ -324,9 +320,7 @@ class CollectingPerformanceInfo:
|
|
|
324
320
|
if not p_project_dir.is_dir():
|
|
325
321
|
continue
|
|
326
322
|
|
|
327
|
-
custom_production_volume_list = (
|
|
328
|
-
custom_production_volume_list_by_directory.get(p_project_dir.name) if custom_production_volume_list_by_directory is not None else None
|
|
329
|
-
)
|
|
323
|
+
custom_production_volume_list = custom_production_volume_list_by_directory.get(p_project_dir.name) if custom_production_volume_list_by_directory is not None else None
|
|
330
324
|
project_title = p_project_dir.name
|
|
331
325
|
project_dir = ProjectDir(
|
|
332
326
|
p_project_dir,
|
|
@@ -593,9 +587,7 @@ class WritePerformanceRatingCsv(CommandLineWithoutWebapi):
|
|
|
593
587
|
user_id_list = get_list_from_args(args.user_id) if args.user_id is not None else None
|
|
594
588
|
df_user = create_user_df(target_dir)
|
|
595
589
|
custom_production_volume_by_directory = (
|
|
596
|
-
create_custom_production_volume_by_directory(args.custom_production_volume_by_directory)
|
|
597
|
-
if args.custom_production_volume_by_directory is not None
|
|
598
|
-
else None
|
|
590
|
+
create_custom_production_volume_by_directory(args.custom_production_volume_by_directory) if args.custom_production_volume_by_directory is not None else None
|
|
599
591
|
)
|
|
600
592
|
result = CollectingPerformanceInfo(
|
|
601
593
|
productivity_indicator=ProductivityIndicator(args.productivity_indicator),
|
|
@@ -238,14 +238,10 @@ class ListAnnotationArea(CommandLine):
|
|
|
238
238
|
|
|
239
239
|
if project_id is not None:
|
|
240
240
|
if args.temp_dir is not None:
|
|
241
|
-
download_and_print_annotation_area(
|
|
242
|
-
project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path
|
|
243
|
-
)
|
|
241
|
+
download_and_print_annotation_area(project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path)
|
|
244
242
|
else:
|
|
245
243
|
with tempfile.TemporaryDirectory() as str_temp_dir:
|
|
246
|
-
download_and_print_annotation_area(
|
|
247
|
-
project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path
|
|
248
|
-
)
|
|
244
|
+
download_and_print_annotation_area(project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path)
|
|
249
245
|
else:
|
|
250
246
|
assert annotation_path is not None
|
|
251
247
|
print_annotation_area(
|
|
@@ -293,7 +289,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
293
289
|
parser.add_argument(
|
|
294
290
|
"--latest",
|
|
295
291
|
action="store_true",
|
|
296
|
-
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
292
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
297
293
|
)
|
|
298
294
|
|
|
299
295
|
parser.add_argument(
|
|
@@ -69,9 +69,7 @@ class AnnotationAttribute(pydantic.BaseModel):
|
|
|
69
69
|
attributes: dict[str, Union[str, int, bool]]
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def get_annotation_attribute_list_from_annotation_json(
|
|
73
|
-
simple_annotation: dict[str, Any], *, target_labels: Collection[str] | None = None
|
|
74
|
-
) -> list[AnnotationAttribute]:
|
|
72
|
+
def get_annotation_attribute_list_from_annotation_json(simple_annotation: dict[str, Any], *, target_labels: Collection[str] | None = None) -> list[AnnotationAttribute]:
|
|
75
73
|
"""
|
|
76
74
|
1個のアノテーションJSONに対して、アノテーションの属性情報を取得します。
|
|
77
75
|
|
|
@@ -207,9 +205,7 @@ class ListAnnotationAttribute(CommandLine):
|
|
|
207
205
|
|
|
208
206
|
downloading_obj = DownloadingFile(self.service)
|
|
209
207
|
|
|
210
|
-
def download_and_print_annotation_attribute_list(
|
|
211
|
-
project_id: str, temp_dir: Path, *, is_latest: bool, annotation_path: Optional[Path]
|
|
212
|
-
) -> None:
|
|
208
|
+
def download_and_print_annotation_attribute_list(project_id: str, temp_dir: Path, *, is_latest: bool, annotation_path: Optional[Path]) -> None:
|
|
213
209
|
if annotation_path is None:
|
|
214
210
|
annotation_path = temp_dir / f"{project_id}__annotation.zip"
|
|
215
211
|
downloading_obj.download_annotation_zip(
|
|
@@ -225,16 +221,12 @@ class ListAnnotationAttribute(CommandLine):
|
|
|
225
221
|
|
|
226
222
|
if project_id is not None:
|
|
227
223
|
if args.temp_dir is not None:
|
|
228
|
-
download_and_print_annotation_attribute_list(
|
|
229
|
-
project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path
|
|
230
|
-
)
|
|
224
|
+
download_and_print_annotation_attribute_list(project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path)
|
|
231
225
|
else:
|
|
232
226
|
# `NamedTemporaryFile`を使わない理由: Windowsで`PermissionError`が発生するため
|
|
233
227
|
# https://qiita.com/yuji38kwmt/items/c6f50e1fc03dafdcdda0 参考
|
|
234
228
|
with tempfile.TemporaryDirectory() as str_temp_dir:
|
|
235
|
-
download_and_print_annotation_attribute_list(
|
|
236
|
-
project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path
|
|
237
|
-
)
|
|
229
|
+
download_and_print_annotation_attribute_list(project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path)
|
|
238
230
|
else:
|
|
239
231
|
assert annotation_path is not None
|
|
240
232
|
annotation_attribute_list = get_annotation_attribute_list_from_annotation_zipdir_path(
|
|
@@ -276,14 +268,13 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
276
268
|
type=str,
|
|
277
269
|
nargs="+",
|
|
278
270
|
required=False,
|
|
279
|
-
help="出力対象のアノテーションのラベル名(英語)を指定します。指定しない場合はラベル名で絞り込みません。"
|
|
280
|
-
" ``file://`` を先頭に付けると、ラベル名の一覧が記載されたファイルを指定できます。",
|
|
271
|
+
help="出力対象のアノテーションのラベル名(英語)を指定します。指定しない場合はラベル名で絞り込みません。 ``file://`` を先頭に付けると、ラベル名の一覧が記載されたファイルを指定できます。",
|
|
281
272
|
)
|
|
282
273
|
|
|
283
274
|
parser.add_argument(
|
|
284
275
|
"--latest",
|
|
285
276
|
action="store_true",
|
|
286
|
-
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
277
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
287
278
|
)
|
|
288
279
|
|
|
289
280
|
parser.add_argument(
|
|
@@ -316,14 +316,12 @@ class AnnotationCountCsvByAttribute:
|
|
|
316
316
|
Args:
|
|
317
317
|
selective_attribute_value_max_count: 選択肢系の属性の値の個数の上限。これを超えた場合は、非選択肢系属性(トラッキングIDやアノテーションリンクなど)とみなす
|
|
318
318
|
|
|
319
|
-
"""
|
|
319
|
+
"""
|
|
320
320
|
|
|
321
321
|
def __init__(self, selective_attribute_value_max_count: int = 20) -> None:
|
|
322
322
|
self.selective_attribute_value_max_count = selective_attribute_value_max_count
|
|
323
323
|
|
|
324
|
-
def _value_columns(
|
|
325
|
-
self, annotation_count_list: Collection[HasAnnotationAttributeCounts], *, prior_attribute_columns: Optional[list[tuple[str, str, str]]]
|
|
326
|
-
) -> list[tuple[str, str, str]]:
|
|
324
|
+
def _value_columns(self, annotation_count_list: Collection[HasAnnotationAttributeCounts], *, prior_attribute_columns: Optional[list[tuple[str, str, str]]]) -> list[tuple[str, str, str]]:
|
|
327
325
|
"""
|
|
328
326
|
CSVの数値列を取得します。
|
|
329
327
|
"""
|
|
@@ -441,9 +439,7 @@ def get_frame_no_map(task_json_path: Path) -> dict[tuple[str, str], int]:
|
|
|
441
439
|
|
|
442
440
|
|
|
443
441
|
def get_attribute_columns(attribute_names: list[tuple[str, str]]) -> list[tuple[str, str, str]]:
|
|
444
|
-
attribute_columns = [
|
|
445
|
-
(label_name, attribute_name, value_type) for label_name, attribute_name in attribute_names for value_type in ["filled", "empty"]
|
|
446
|
-
]
|
|
442
|
+
attribute_columns = [(label_name, attribute_name, value_type) for label_name, attribute_name in attribute_names for value_type in ["filled", "empty"]]
|
|
447
443
|
return attribute_columns
|
|
448
444
|
|
|
449
445
|
|
|
@@ -451,9 +447,7 @@ class ListAnnotationAttributeFilledCountMain:
|
|
|
451
447
|
def __init__(self, service: annofabapi.Resource) -> None:
|
|
452
448
|
self.service = service
|
|
453
449
|
|
|
454
|
-
def print_annotation_count_csv_by_input_data(
|
|
455
|
-
self, annotation_count_list: list[AnnotationCountByInputData], output_file: Path, *, attribute_names: Optional[list[tuple[str, str]]]
|
|
456
|
-
) -> None:
|
|
450
|
+
def print_annotation_count_csv_by_input_data(self, annotation_count_list: list[AnnotationCountByInputData], output_file: Path, *, attribute_names: Optional[list[tuple[str, str]]]) -> None:
|
|
457
451
|
attribute_columns: Optional[list[tuple[str, str, str]]] = None
|
|
458
452
|
if attribute_names is not None:
|
|
459
453
|
attribute_columns = get_attribute_columns(attribute_names)
|
|
@@ -461,9 +455,7 @@ class ListAnnotationAttributeFilledCountMain:
|
|
|
461
455
|
df = AnnotationCountCsvByAttribute().create_df_by_input_data(annotation_count_list, prior_attribute_columns=attribute_columns)
|
|
462
456
|
print_csv(df, output_file)
|
|
463
457
|
|
|
464
|
-
def print_annotation_count_csv_by_task(
|
|
465
|
-
self, annotation_count_list: list[AnnotationCountByTask], output_file: Path, *, attribute_names: Optional[list[tuple[str, str]]]
|
|
466
|
-
) -> None:
|
|
458
|
+
def print_annotation_count_csv_by_task(self, annotation_count_list: list[AnnotationCountByTask], output_file: Path, *, attribute_names: Optional[list[tuple[str, str]]]) -> None:
|
|
467
459
|
attribute_columns: Optional[list[tuple[str, str, str]]] = None
|
|
468
460
|
if attribute_names is not None:
|
|
469
461
|
attribute_columns = get_attribute_columns(attribute_names)
|
|
@@ -493,9 +485,7 @@ class ListAnnotationAttributeFilledCountMain:
|
|
|
493
485
|
|
|
494
486
|
frame_no_map = get_frame_no_map(task_json_path) if task_json_path is not None else None
|
|
495
487
|
|
|
496
|
-
annotation_count_list_by_input_data = ListAnnotationCounterByInputData(
|
|
497
|
-
frame_no_map=frame_no_map, target_attribute_names=target_attribute_names
|
|
498
|
-
).get_annotation_count_list(
|
|
488
|
+
annotation_count_list_by_input_data = ListAnnotationCounterByInputData(frame_no_map=frame_no_map, target_attribute_names=target_attribute_names).get_annotation_count_list(
|
|
499
489
|
annotation_path,
|
|
500
490
|
target_task_ids=target_task_ids,
|
|
501
491
|
task_query=task_query,
|
|
@@ -504,9 +494,7 @@ class ListAnnotationAttributeFilledCountMain:
|
|
|
504
494
|
if group_by == GroupBy.INPUT_DATA_ID:
|
|
505
495
|
logger.info(f"{len(annotation_count_list_by_input_data)} 件の入力データに含まれるアノテーション数の情報を出力します。")
|
|
506
496
|
if output_format == FormatArgument.CSV:
|
|
507
|
-
self.print_annotation_count_csv_by_input_data(
|
|
508
|
-
annotation_count_list_by_input_data, output_file=output_file, attribute_names=target_attribute_names
|
|
509
|
-
)
|
|
497
|
+
self.print_annotation_count_csv_by_input_data(annotation_count_list_by_input_data, output_file=output_file, attribute_names=target_attribute_names)
|
|
510
498
|
|
|
511
499
|
elif output_format in [FormatArgument.PRETTY_JSON, FormatArgument.JSON]:
|
|
512
500
|
json_is_pretty = output_format == FormatArgument.PRETTY_JSON
|
|
@@ -520,9 +508,7 @@ class ListAnnotationAttributeFilledCountMain:
|
|
|
520
508
|
annotation_count_list_by_task = convert_annotation_count_list_by_input_data_to_by_task(annotation_count_list_by_input_data)
|
|
521
509
|
logger.info(f"{len(annotation_count_list_by_task)} 件のタスクに含まれるアノテーション数の情報を出力します。")
|
|
522
510
|
if output_format == FormatArgument.CSV:
|
|
523
|
-
self.print_annotation_count_csv_by_task(
|
|
524
|
-
annotation_count_list_by_task, output_file=output_file, attribute_names=target_attribute_names
|
|
525
|
-
)
|
|
511
|
+
self.print_annotation_count_csv_by_task(annotation_count_list_by_task, output_file=output_file, attribute_names=target_attribute_names)
|
|
526
512
|
|
|
527
513
|
elif output_format in [FormatArgument.PRETTY_JSON, FormatArgument.JSON]:
|
|
528
514
|
json_is_pretty = output_format == FormatArgument.PRETTY_JSON
|
|
@@ -669,7 +655,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
669
655
|
parser.add_argument(
|
|
670
656
|
"--latest",
|
|
671
657
|
action="store_true",
|
|
672
|
-
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
658
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
673
659
|
)
|
|
674
660
|
|
|
675
661
|
parser.set_defaults(subcommand_func=main)
|
|
@@ -219,13 +219,9 @@ class ListAnnotationCounterByInputData:
|
|
|
219
219
|
|
|
220
220
|
annotation_count_by_label = collections.Counter([e["label"] for e in details])
|
|
221
221
|
if self.target_labels is not None:
|
|
222
|
-
annotation_count_by_label = collections.Counter(
|
|
223
|
-
{label: count for label, count in annotation_count_by_label.items() if label in self.target_labels}
|
|
224
|
-
)
|
|
222
|
+
annotation_count_by_label = collections.Counter({label: count for label, count in annotation_count_by_label.items() if label in self.target_labels})
|
|
225
223
|
if self.non_target_labels is not None:
|
|
226
|
-
annotation_count_by_label = collections.Counter(
|
|
227
|
-
{label: count for label, count in annotation_count_by_label.items() if label not in self.non_target_labels}
|
|
228
|
-
)
|
|
224
|
+
annotation_count_by_label = collections.Counter({label: count for label, count in annotation_count_by_label.items() if label not in self.non_target_labels})
|
|
229
225
|
|
|
230
226
|
attributes_list: list[AttributeValueKey] = []
|
|
231
227
|
for detail in details:
|
|
@@ -413,10 +409,9 @@ class AttributeCountCsv:
|
|
|
413
409
|
Args:
|
|
414
410
|
selective_attribute_value_max_count: 選択肢系の属性の値の個数の上限。これを超えた場合は、非選択肢系属性(トラッキングIDやアノテーションリンクなど)とみなす
|
|
415
411
|
|
|
416
|
-
"""
|
|
412
|
+
"""
|
|
417
413
|
|
|
418
|
-
def __init__(self, selective_attribute_value_max_count: int = 20
|
|
419
|
-
self.csv_format = csv_format
|
|
414
|
+
def __init__(self, selective_attribute_value_max_count: int = 20) -> None:
|
|
420
415
|
self.selective_attribute_value_max_count = selective_attribute_value_max_count
|
|
421
416
|
|
|
422
417
|
def _only_selective_attribute(self, columns: list[AttributeValueKey]) -> list[AttributeValueKey]:
|
|
@@ -429,23 +424,13 @@ class AttributeCountCsv:
|
|
|
429
424
|
for label, attribute_name, _ in columns:
|
|
430
425
|
attribute_name_list.append((label, attribute_name))
|
|
431
426
|
|
|
432
|
-
non_selective_attribute_names = {
|
|
433
|
-
key for key, value in collections.Counter(attribute_name_list).items() if value > self.selective_attribute_value_max_count
|
|
434
|
-
}
|
|
427
|
+
non_selective_attribute_names = {key for key, value in collections.Counter(attribute_name_list).items() if value > self.selective_attribute_value_max_count}
|
|
435
428
|
if len(non_selective_attribute_names) > 0:
|
|
436
|
-
logger.debug(
|
|
437
|
-
f"以下の属性は値の個数が{self.selective_attribute_value_max_count}を超えていたため、集計しません。 :: {non_selective_attribute_names}"
|
|
438
|
-
)
|
|
429
|
+
logger.debug(f"以下の属性は値の個数が{self.selective_attribute_value_max_count}を超えていたため、集計しません。 :: {non_selective_attribute_names}")
|
|
439
430
|
|
|
440
|
-
return [
|
|
441
|
-
(label, attribute_name, attribute_value)
|
|
442
|
-
for (label, attribute_name, attribute_value) in columns
|
|
443
|
-
if (label, attribute_name) not in non_selective_attribute_names
|
|
444
|
-
]
|
|
431
|
+
return [(label, attribute_name, attribute_value) for (label, attribute_name, attribute_value) in columns if (label, attribute_name) not in non_selective_attribute_names]
|
|
445
432
|
|
|
446
|
-
def _value_columns(
|
|
447
|
-
self, counter_list: Collection[AnnotationCounter], prior_attribute_columns: Optional[list[AttributeValueKey]]
|
|
448
|
-
) -> list[AttributeValueKey]:
|
|
433
|
+
def _value_columns(self, counter_list: Collection[AnnotationCounter], prior_attribute_columns: Optional[list[AttributeValueKey]]) -> list[AttributeValueKey]:
|
|
449
434
|
all_attr_key_set = {attr_key for c in counter_list for attr_key in c.annotation_count_by_attribute}
|
|
450
435
|
if prior_attribute_columns is not None:
|
|
451
436
|
remaining_columns = sorted(all_attr_key_set - set(prior_attribute_columns))
|
|
@@ -511,7 +496,7 @@ class AttributeCountCsv:
|
|
|
511
496
|
# `task_id`列など`basic_columns`も`fillna`対象だが、nanではないはずので問題ない
|
|
512
497
|
df.fillna(0, inplace=True)
|
|
513
498
|
|
|
514
|
-
print_csv(df, output=str(output_file)
|
|
499
|
+
print_csv(df, output=str(output_file))
|
|
515
500
|
|
|
516
501
|
def print_csv_by_input_data(
|
|
517
502
|
self,
|
|
@@ -555,7 +540,7 @@ class AttributeCountCsv:
|
|
|
555
540
|
value_columns = self._value_columns(counter_list, prior_attribute_columns)
|
|
556
541
|
df = df.fillna(dict.fromkeys(value_columns, 0))
|
|
557
542
|
|
|
558
|
-
print_csv(df, output=str(output_file)
|
|
543
|
+
print_csv(df, output=str(output_file))
|
|
559
544
|
|
|
560
545
|
|
|
561
546
|
class LabelCountCsv:
|
|
@@ -565,9 +550,6 @@ class LabelCountCsv:
|
|
|
565
550
|
|
|
566
551
|
"""
|
|
567
552
|
|
|
568
|
-
def __init__(self, csv_format: Optional[dict[str, Any]] = None) -> None:
|
|
569
|
-
self.csv_format = csv_format
|
|
570
|
-
|
|
571
553
|
def _value_columns(self, counter_list: Collection[AnnotationCounter], prior_label_columns: Optional[list[str]]) -> list[str]:
|
|
572
554
|
all_attr_key_set = {attr_key for c in counter_list for attr_key in c.annotation_count_by_label}
|
|
573
555
|
if prior_label_columns is not None:
|
|
@@ -615,7 +597,7 @@ class LabelCountCsv:
|
|
|
615
597
|
# NaNを0に変換する
|
|
616
598
|
# `basic_columns`は必ずnanではないので、すべての列に対してfillnaを実行しても問題ないはず
|
|
617
599
|
df.fillna(0, inplace=True)
|
|
618
|
-
print_csv(df, output=str(output_file)
|
|
600
|
+
print_csv(df, output=str(output_file))
|
|
619
601
|
|
|
620
602
|
def print_csv_by_input_data(
|
|
621
603
|
self,
|
|
@@ -658,7 +640,7 @@ class LabelCountCsv:
|
|
|
658
640
|
value_columns = self._value_columns(counter_list, prior_label_columns)
|
|
659
641
|
df = df.fillna(dict.fromkeys(value_columns, 0))
|
|
660
642
|
|
|
661
|
-
print_csv(df, output=str(output_file)
|
|
643
|
+
print_csv(df, output=str(output_file))
|
|
662
644
|
|
|
663
645
|
|
|
664
646
|
class AnnotationSpecs:
|
|
@@ -693,9 +675,7 @@ class AnnotationSpecs:
|
|
|
693
675
|
result = [to_label_name(label) for label in self._labels_v1]
|
|
694
676
|
duplicated_labels = [key for key, value in collections.Counter(result).items() if value > 1]
|
|
695
677
|
if len(duplicated_labels) > 0:
|
|
696
|
-
logger.warning(
|
|
697
|
-
f"アノテーション仕様のラベル英語名が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_labels}"
|
|
698
|
-
)
|
|
678
|
+
logger.warning(f"アノテーション仕様のラベル英語名が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_labels}")
|
|
699
679
|
return result
|
|
700
680
|
|
|
701
681
|
def attribute_name_keys(
|
|
@@ -734,9 +714,7 @@ class AnnotationSpecs:
|
|
|
734
714
|
|
|
735
715
|
duplicated_attribute_names = [key for key, value in collections.Counter(result).items() if value > 1]
|
|
736
716
|
if len(duplicated_attribute_names) > 0:
|
|
737
|
-
logger.warning(
|
|
738
|
-
f"アノテーション仕様の属性情報(ラベル英語名、属性英語名)が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_attribute_names}" # noqa: E501
|
|
739
|
-
)
|
|
717
|
+
logger.warning(f"アノテーション仕様の属性情報(ラベル英語名、属性英語名)が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_attribute_names}")
|
|
740
718
|
|
|
741
719
|
return result
|
|
742
720
|
|
|
@@ -776,7 +754,7 @@ class AnnotationSpecs:
|
|
|
776
754
|
duplicated_attributes = [key for key, value in collections.Counter(target_attribute_value_keys).items() if value > 1]
|
|
777
755
|
if len(duplicated_attributes) > 0:
|
|
778
756
|
logger.warning(
|
|
779
|
-
f"アノテーション仕様の属性情報(ラベル英語名、属性英語名、選択肢英語名)が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_attributes}"
|
|
757
|
+
f"アノテーション仕様の属性情報(ラベル英語名、属性英語名、選択肢英語名)が重複しています。アノテーション個数が正しく算出できない可能性があります。:: {duplicated_attributes}"
|
|
780
758
|
)
|
|
781
759
|
|
|
782
760
|
return target_attribute_value_keys
|
|
@@ -874,9 +852,7 @@ class ListAnnotationCountMain:
|
|
|
874
852
|
non_selective_attribute_name_keys = annotation_specs.non_selective_attribute_name_keys()
|
|
875
853
|
|
|
876
854
|
frame_no_map = self.get_frame_no_map(task_json_path) if task_json_path is not None else None
|
|
877
|
-
counter_by_input_data = ListAnnotationCounterByInputData(
|
|
878
|
-
non_target_attribute_names=non_selective_attribute_name_keys, frame_no_map=frame_no_map
|
|
879
|
-
)
|
|
855
|
+
counter_by_input_data = ListAnnotationCounterByInputData(non_target_attribute_names=non_selective_attribute_name_keys, frame_no_map=frame_no_map)
|
|
880
856
|
counter_list_by_input_data = counter_by_input_data.get_annotation_counter_list(
|
|
881
857
|
annotation_path,
|
|
882
858
|
target_task_ids=target_task_ids,
|
|
@@ -957,9 +933,7 @@ class ListAnnotationCountMain:
|
|
|
957
933
|
non_selective_attribute_name_keys = None
|
|
958
934
|
|
|
959
935
|
frame_no_map = self.get_frame_no_map(task_json_path) if task_json_path is not None else None
|
|
960
|
-
counter_list_by_input_data = ListAnnotationCounterByInputData(
|
|
961
|
-
non_target_attribute_names=non_selective_attribute_name_keys, frame_no_map=frame_no_map
|
|
962
|
-
).get_annotation_counter_list(
|
|
936
|
+
counter_list_by_input_data = ListAnnotationCounterByInputData(non_target_attribute_names=non_selective_attribute_name_keys, frame_no_map=frame_no_map).get_annotation_counter_list(
|
|
963
937
|
annotation_path,
|
|
964
938
|
target_task_ids=target_task_ids,
|
|
965
939
|
task_query=task_query,
|
|
@@ -1198,7 +1172,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
1198
1172
|
parser.add_argument(
|
|
1199
1173
|
"--latest",
|
|
1200
1174
|
action="store_true",
|
|
1201
|
-
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
1175
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
1202
1176
|
)
|
|
1203
1177
|
|
|
1204
1178
|
parser.set_defaults(subcommand_func=main)
|
|
@@ -203,14 +203,10 @@ class ListAnnotationDurationByInputData:
|
|
|
203
203
|
annotation_duration_by_label[detail["label"]] += calculate_annotation_duration_second(detail)
|
|
204
204
|
|
|
205
205
|
if self.target_labels is not None:
|
|
206
|
-
annotation_duration_by_label = {
|
|
207
|
-
label: duration for label, duration in annotation_duration_by_label.items() if label in self.target_labels
|
|
208
|
-
}
|
|
206
|
+
annotation_duration_by_label = {label: duration for label, duration in annotation_duration_by_label.items() if label in self.target_labels}
|
|
209
207
|
|
|
210
208
|
if self.non_target_labels is not None:
|
|
211
|
-
annotation_duration_by_label = {
|
|
212
|
-
label: duration for label, duration in annotation_duration_by_label.items() if label not in self.non_target_labels
|
|
213
|
-
}
|
|
209
|
+
annotation_duration_by_label = {label: duration for label, duration in annotation_duration_by_label.items() if label not in self.non_target_labels}
|
|
214
210
|
|
|
215
211
|
annotation_duration_by_attribute: dict[AttributeValueKey, float] = defaultdict(float)
|
|
216
212
|
for detail in range_details:
|
|
@@ -307,7 +303,7 @@ class AnnotationDurationCsvByAttribute:
|
|
|
307
303
|
Args:
|
|
308
304
|
selective_attribute_value_max_count: 選択肢系の属性の値の個数の上限。これを超えた場合は、非選択肢系属性(トラッキングIDやアノテーションリンクなど)とみなす
|
|
309
305
|
|
|
310
|
-
"""
|
|
306
|
+
"""
|
|
311
307
|
|
|
312
308
|
def __init__(self, selective_attribute_value_max_count: int = 20) -> None:
|
|
313
309
|
self.selective_attribute_value_max_count = selective_attribute_value_max_count
|
|
@@ -322,23 +318,13 @@ class AnnotationDurationCsvByAttribute:
|
|
|
322
318
|
for label, attribute_name, _ in columns:
|
|
323
319
|
attribute_name_list.append((label, attribute_name))
|
|
324
320
|
|
|
325
|
-
non_selective_attribute_names = {
|
|
326
|
-
key for key, value in collections.Counter(attribute_name_list).items() if value > self.selective_attribute_value_max_count
|
|
327
|
-
}
|
|
321
|
+
non_selective_attribute_names = {key for key, value in collections.Counter(attribute_name_list).items() if value > self.selective_attribute_value_max_count}
|
|
328
322
|
if len(non_selective_attribute_names) > 0:
|
|
329
|
-
logger.debug(
|
|
330
|
-
f"以下の属性は値の個数が{self.selective_attribute_value_max_count}を超えていたため、集計しません。 :: {non_selective_attribute_names}"
|
|
331
|
-
)
|
|
323
|
+
logger.debug(f"以下の属性は値の個数が{self.selective_attribute_value_max_count}を超えていたため、集計しません。 :: {non_selective_attribute_names}")
|
|
332
324
|
|
|
333
|
-
return [
|
|
334
|
-
(label, attribute_name, attribute_value)
|
|
335
|
-
for (label, attribute_name, attribute_value) in columns
|
|
336
|
-
if (label, attribute_name) not in non_selective_attribute_names
|
|
337
|
-
]
|
|
325
|
+
return [(label, attribute_name, attribute_value) for (label, attribute_name, attribute_value) in columns if (label, attribute_name) not in non_selective_attribute_names]
|
|
338
326
|
|
|
339
|
-
def _value_columns(
|
|
340
|
-
self, annotation_duration_list: Collection[AnnotationDuration], prior_attribute_columns: Optional[list[AttributeValueKey]]
|
|
341
|
-
) -> list[AttributeValueKey]:
|
|
327
|
+
def _value_columns(self, annotation_duration_list: Collection[AnnotationDuration], prior_attribute_columns: Optional[list[AttributeValueKey]]) -> list[AttributeValueKey]:
|
|
342
328
|
all_attr_key_set = {attr_key for c in annotation_duration_list for attr_key in c.annotation_duration_second_by_attribute}
|
|
343
329
|
if prior_attribute_columns is not None:
|
|
344
330
|
remaining_columns = sorted(all_attr_key_set - set(prior_attribute_columns))
|
|
@@ -482,9 +468,7 @@ class ListAnnotationDurationMain:
|
|
|
482
468
|
def __init__(self, service: annofabapi.Resource) -> None:
|
|
483
469
|
self.service = service
|
|
484
470
|
|
|
485
|
-
def print_annotation_duration_csv(
|
|
486
|
-
self, annotation_duration_list: list[AnnotationDuration], csv_type: CsvType, output_file: Path, *, annotation_specs: Optional[AnnotationSpecs]
|
|
487
|
-
) -> None:
|
|
471
|
+
def print_annotation_duration_csv(self, annotation_duration_list: list[AnnotationDuration], csv_type: CsvType, output_file: Path, *, annotation_specs: Optional[AnnotationSpecs]) -> None:
|
|
488
472
|
if csv_type == CsvType.LABEL:
|
|
489
473
|
# ラベル名の列順が、アノテーション仕様にあるラベル名の順番に対応するようにする。
|
|
490
474
|
label_columns: Optional[list[str]] = None
|
|
@@ -522,9 +506,7 @@ class ListAnnotationDurationMain:
|
|
|
522
506
|
annotation_specs = AnnotationSpecs(self.service, project_id, annotation_type=DefaultAnnotationType.RANGE.value)
|
|
523
507
|
non_selective_attribute_name_keys = annotation_specs.non_selective_attribute_name_keys()
|
|
524
508
|
|
|
525
|
-
annotation_duration_list = ListAnnotationDurationByInputData(
|
|
526
|
-
non_target_attribute_names=non_selective_attribute_name_keys
|
|
527
|
-
).get_annotation_duration_list(
|
|
509
|
+
annotation_duration_list = ListAnnotationDurationByInputData(non_target_attribute_names=non_selective_attribute_name_keys).get_annotation_duration_list(
|
|
528
510
|
annotation_path,
|
|
529
511
|
input_data_json_path=input_data_json_path,
|
|
530
512
|
target_task_ids=target_task_ids,
|
|
@@ -535,9 +517,7 @@ class ListAnnotationDurationMain:
|
|
|
535
517
|
|
|
536
518
|
if arg_format == FormatArgument.CSV:
|
|
537
519
|
assert csv_type is not None
|
|
538
|
-
self.print_annotation_duration_csv(
|
|
539
|
-
annotation_duration_list, output_file=output_file, csv_type=csv_type, annotation_specs=annotation_specs
|
|
540
|
-
)
|
|
520
|
+
self.print_annotation_duration_csv(annotation_duration_list, output_file=output_file, csv_type=csv_type, annotation_specs=annotation_specs)
|
|
541
521
|
|
|
542
522
|
elif arg_format in [FormatArgument.PRETTY_JSON, FormatArgument.JSON]:
|
|
543
523
|
json_is_pretty = arg_format == FormatArgument.PRETTY_JSON
|
|
@@ -577,9 +557,7 @@ class ListAnnotationDuration(CommandLine):
|
|
|
577
557
|
super().validate_project(project_id, project_member_roles=[ProjectMemberRole.OWNER, ProjectMemberRole.TRAINING_DATA_USER])
|
|
578
558
|
project, _ = self.service.api.get_project(project_id)
|
|
579
559
|
if project["input_data_type"] != InputDataType.MOVIE.value:
|
|
580
|
-
logger.warning(
|
|
581
|
-
f"project_id='{project_id}'であるプロジェクトは、動画プロジェクトでないので、出力される区間アノテーションの長さはすべて0秒になります。"
|
|
582
|
-
)
|
|
560
|
+
logger.warning(f"project_id='{project_id}'であるプロジェクトは、動画プロジェクトでないので、出力される区間アノテーションの長さはすべて0秒になります。")
|
|
583
561
|
|
|
584
562
|
annotation_path = Path(args.annotation) if args.annotation is not None else None
|
|
585
563
|
|
|
@@ -622,16 +600,12 @@ class ListAnnotationDuration(CommandLine):
|
|
|
622
600
|
|
|
623
601
|
if project_id is not None:
|
|
624
602
|
if args.temp_dir is not None:
|
|
625
|
-
download_and_print_annotation_duration(
|
|
626
|
-
project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path
|
|
627
|
-
)
|
|
603
|
+
download_and_print_annotation_duration(project_id=project_id, temp_dir=args.temp_dir, is_latest=args.latest, annotation_path=annotation_path)
|
|
628
604
|
else:
|
|
629
605
|
# `NamedTemporaryFile`を使わない理由: Windowsで`PermissionError`が発生するため
|
|
630
606
|
# https://qiita.com/yuji38kwmt/items/c6f50e1fc03dafdcdda0 参考
|
|
631
607
|
with tempfile.TemporaryDirectory() as str_temp_dir:
|
|
632
|
-
download_and_print_annotation_duration(
|
|
633
|
-
project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path
|
|
634
|
-
)
|
|
608
|
+
download_and_print_annotation_duration(project_id=project_id, temp_dir=Path(str_temp_dir), is_latest=args.latest, annotation_path=annotation_path)
|
|
635
609
|
else:
|
|
636
610
|
assert annotation_path is not None
|
|
637
611
|
main_obj.print_annotation_duration(
|
|
@@ -694,7 +668,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
694
668
|
parser.add_argument(
|
|
695
669
|
"--latest",
|
|
696
670
|
action="store_true",
|
|
697
|
-
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
671
|
+
help="``--annotation`` を指定しないとき、最新のアノテーションzipを参照します。このオプションを指定すると、アノテーションzipを更新するのに数分待ちます。",
|
|
698
672
|
)
|
|
699
673
|
|
|
700
674
|
parser.add_argument(
|
|
@@ -71,7 +71,7 @@ class ListVideoDuration(CommandLine):
|
|
|
71
71
|
def validate(self, args: argparse.Namespace) -> bool:
|
|
72
72
|
if args.project_id is None and (args.input_data_json is None or args.task_json is None):
|
|
73
73
|
print( # noqa: T201
|
|
74
|
-
f"{self.COMMON_MESSAGE} argument --project_id: '--input_data_json'または'--task_json'が未指定のときは、'--project_id' を指定してください。",
|
|
74
|
+
f"{self.COMMON_MESSAGE} argument --project_id: '--input_data_json'または'--task_json'が未指定のときは、'--project_id' を指定してください。",
|
|
75
75
|
file=sys.stderr,
|
|
76
76
|
)
|
|
77
77
|
return False
|
|
@@ -171,8 +171,7 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
171
171
|
"--input_data_json",
|
|
172
172
|
type=Path,
|
|
173
173
|
required=False,
|
|
174
|
-
help="入力データ情報が記載されたJSONファイルのパスを指定します。\
|
|
175
|
-
"JSONファイルは ``$ annofabcli input_data download`` コマンドで取得できます。",
|
|
174
|
+
help="入力データ情報が記載されたJSONファイルのパスを指定します。\nJSONファイルは ``$ annofabcli input_data download`` コマンドで取得できます。",
|
|
176
175
|
)
|
|
177
176
|
|
|
178
177
|
parser.add_argument(
|
annofabcli/statistics/scatter.py
CHANGED
|
@@ -142,15 +142,11 @@ class ScatterGraph:
|
|
|
142
142
|
if legend_label == "":
|
|
143
143
|
legend_label = "none"
|
|
144
144
|
|
|
145
|
-
self._scatter_glyphs[legend_label] = self.figure.scatter(
|
|
146
|
-
x=x_column_name, y=y_column_name, source=source, legend_label=legend_label, color=color, muted_alpha=0.2, size=6
|
|
147
|
-
)
|
|
145
|
+
self._scatter_glyphs[legend_label] = self.figure.scatter(x=x_column_name, y=y_column_name, source=source, legend_label=legend_label, color=color, muted_alpha=0.2, size=6)
|
|
148
146
|
|
|
149
147
|
# 1点ごとに`text`で名前を表示している理由:
|
|
150
148
|
# `add_multi_choice_widget_for_searching_user`関数で追加したMultiChoice Widgetで、名前の表示スタイルを変更するため
|
|
151
|
-
for x, y, username, user_id in zip(
|
|
152
|
-
source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]
|
|
153
|
-
):
|
|
149
|
+
for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]):
|
|
154
150
|
self.text_glyphs[user_id] = self.figure.text(
|
|
155
151
|
x=x,
|
|
156
152
|
y=y,
|
|
@@ -204,9 +200,7 @@ class ScatterGraph:
|
|
|
204
200
|
|
|
205
201
|
# 1点ごとに`text`で名前を表示している理由:
|
|
206
202
|
# `add_multi_choice_widget_for_searching_user`関数で追加したMultiChoice Widgetで、名前の表示スタイルを変更するため
|
|
207
|
-
for x, y, username, user_id in zip(
|
|
208
|
-
source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]
|
|
209
|
-
):
|
|
203
|
+
for x, y, username, user_id in zip(source.data[x_column_name], source.data[y_column_name], source.data[username_column_name], source.data[user_id_column_name]):
|
|
210
204
|
self.text_glyphs[user_id] = self.figure.text(
|
|
211
205
|
x=x,
|
|
212
206
|
y=y,
|