annofabcli 1.97.0__tar.gz → 1.98.0__tar.gz

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.
Files changed (208) hide show
  1. {annofabcli-1.97.0 → annofabcli-1.98.0}/PKG-INFO +2 -2
  2. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/__version__.py +1 -1
  3. annofabcli-1.98.0/annofabcli/annotation/merge_segmentation.py +390 -0
  4. annofabcli-1.98.0/annofabcli/annotation/remove_segmentation_overlap.py +343 -0
  5. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/subcommand_annotation.py +4 -0
  6. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/task.py +26 -7
  7. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/list_tasks_added_task_history.py +91 -8
  8. {annofabcli-1.97.0 → annofabcli-1.98.0}/pyproject.toml +2 -2
  9. {annofabcli-1.97.0 → annofabcli-1.98.0}/LICENSE +0 -0
  10. {annofabcli-1.97.0 → annofabcli-1.98.0}/README.md +0 -0
  11. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/__init__.py +0 -0
  12. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/__main__.py +0 -0
  13. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/__init__.py +0 -0
  14. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/annotation_query.py +0 -0
  15. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/change_annotation_attributes.py +0 -0
  16. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/change_annotation_properties.py +0 -0
  17. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/copy_annotation.py +0 -0
  18. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/delete_annotation.py +0 -0
  19. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/download_annotation_zip.py +0 -0
  20. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/dump_annotation.py +0 -0
  21. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/import_annotation.py +0 -0
  22. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/list_annotation.py +0 -0
  23. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/list_annotation_count.py +0 -0
  24. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation/restore_annotation.py +0 -0
  25. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/__init__.py +0 -0
  26. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/export_annotation_specs.py +0 -0
  27. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +0 -0
  28. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +0 -0
  29. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +0 -0
  30. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_annotation_specs_attribute.py +0 -0
  31. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_annotation_specs_choice.py +0 -0
  32. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_annotation_specs_history.py +0 -0
  33. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_annotation_specs_label.py +0 -0
  34. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_attribute_restriction.py +0 -0
  35. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/list_label_color.py +0 -0
  36. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/put_label_color.py +0 -0
  37. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/annotation_specs/subcommand_annotation_specs.py +0 -0
  38. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/__init__.py +0 -0
  39. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/delete_comment.py +0 -0
  40. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/download_comment_json.py +0 -0
  41. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/list_all_comment.py +0 -0
  42. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/list_comment.py +0 -0
  43. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_comment.py +0 -0
  44. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_comment_simply.py +0 -0
  45. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_inspection_comment.py +0 -0
  46. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_inspection_comment_simply.py +0 -0
  47. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_onhold_comment.py +0 -0
  48. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/put_onhold_comment_simply.py +0 -0
  49. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/subcommand_comment.py +0 -0
  50. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/comment/utils.py +0 -0
  51. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/__init__.py +0 -0
  52. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/annofab/__init__.py +0 -0
  53. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/annofab/project.py +0 -0
  54. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/bokeh.py +0 -0
  55. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/cli.py +0 -0
  56. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/dataclasses.py +0 -0
  57. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/download.py +0 -0
  58. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/enums.py +0 -0
  59. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/exceptions.py +0 -0
  60. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/facade.py +0 -0
  61. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/image.py +0 -0
  62. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/pandas.py +0 -0
  63. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/type_util.py +0 -0
  64. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/typing.py +0 -0
  65. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/utils.py +0 -0
  66. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/common/visualize.py +0 -0
  67. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/data/logging.yaml +0 -0
  68. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/experimental/__init__.py +0 -0
  69. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/experimental/list_out_of_range_annotation_for_movie.py +0 -0
  70. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/experimental/subcommand_experimental.py +0 -0
  71. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/__init__.py +0 -0
  72. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/draw_annotation.py +0 -0
  73. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/filter_annotation.py +0 -0
  74. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/mask_user_info.py +0 -0
  75. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/merge_annotation.py +0 -0
  76. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/filesystem/subcommand_filesystem.py +0 -0
  77. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/__init__.py +0 -0
  78. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/change_input_data_name.py +0 -0
  79. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/copy_input_data.py +0 -0
  80. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/delete_input_data.py +0 -0
  81. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/delete_metadata_key_of_input_data.py +0 -0
  82. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/download_input_data_json.py +0 -0
  83. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/list_all_input_data.py +0 -0
  84. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/list_all_input_data_merged_task.py +0 -0
  85. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/list_input_data.py +0 -0
  86. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/put_input_data.py +0 -0
  87. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/put_input_data_with_zip.py +0 -0
  88. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/subcommand_input_data.py +0 -0
  89. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/update_metadata_of_input_data.py +0 -0
  90. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/input_data/utils.py +0 -0
  91. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/__init__.py +0 -0
  92. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/copy_instruction.py +0 -0
  93. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/download_instruction.py +0 -0
  94. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/list_instruction_history.py +0 -0
  95. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/subcommand_instruction.py +0 -0
  96. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/instruction/upload_instruction.py +0 -0
  97. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/__init__.py +0 -0
  98. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/delete_job.py +0 -0
  99. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/list_job.py +0 -0
  100. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/list_last_job.py +0 -0
  101. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/subcommand_job.py +0 -0
  102. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/job/wait_job.py +0 -0
  103. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/my_account/__init__.py +0 -0
  104. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/my_account/get_my_account.py +0 -0
  105. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/my_account/subcommand_my_account.py +0 -0
  106. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization/__init__.py +0 -0
  107. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization/list_organization.py +0 -0
  108. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization/subcommand_organization.py +0 -0
  109. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/__init__.py +0 -0
  110. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/change_organization_member.py +0 -0
  111. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/delete_organization_member.py +0 -0
  112. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/invite_organization_member.py +0 -0
  113. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/list_organization_member.py +0 -0
  114. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/organization_member/subcommand_organization_member.py +0 -0
  115. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/__init__.py +0 -0
  116. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/change_project_status.py +0 -0
  117. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/copy_project.py +0 -0
  118. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/diff_projects.py +0 -0
  119. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/list_project.py +0 -0
  120. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/put_project.py +0 -0
  121. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project/subcommand_project.py +0 -0
  122. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/__init__.py +0 -0
  123. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/change_project_members.py +0 -0
  124. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/copy_project_members.py +0 -0
  125. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/drop_project_members.py +0 -0
  126. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/invite_project_members.py +0 -0
  127. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/list_users.py +0 -0
  128. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/put_project_members.py +0 -0
  129. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/project_member/subcommand_project_member.py +0 -0
  130. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/py.typed +0 -0
  131. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/__init__.py +0 -0
  132. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/mask_visualization_dir.py +0 -0
  133. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/merge_visualization_dir.py +0 -0
  134. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/subcommand_stat_visualization.py +0 -0
  135. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/summarize_whole_performance_csv.py +0 -0
  136. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/write_graph.py +0 -0
  137. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/stat_visualization/write_performance_rating_csv.py +0 -0
  138. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/__init__.py +0 -0
  139. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/histogram.py +0 -0
  140. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/linegraph.py +0 -0
  141. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/list_annotation_attribute.py +0 -0
  142. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/list_annotation_count.py +0 -0
  143. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/list_annotation_duration.py +0 -0
  144. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/list_video_duration.py +0 -0
  145. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/list_worktime.py +0 -0
  146. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/scatter.py +0 -0
  147. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/subcommand_statistics.py +0 -0
  148. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/summarize_task_count.py +0 -0
  149. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/summarize_task_count_by_task_id_group.py +0 -0
  150. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/summarize_task_count_by_user.py +0 -0
  151. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/__init__.py +0 -0
  152. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/__init__.py +0 -0
  153. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/actual_worktime.py +0 -0
  154. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/annotation_count.py +0 -0
  155. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +0 -0
  156. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/custom_production_volume.py +0 -0
  157. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/input_data_count.py +0 -0
  158. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/inspection_comment_count.py +0 -0
  159. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/productivity_per_date.py +0 -0
  160. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/project_performance.py +0 -0
  161. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/task_history.py +0 -0
  162. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +0 -0
  163. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/user.py +0 -0
  164. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/user_performance.py +0 -0
  165. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/whole_performance.py +0 -0
  166. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +0 -0
  167. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/dataframe/worktime_per_date.py +0 -0
  168. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/filtering_query.py +0 -0
  169. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/model.py +0 -0
  170. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/project_dir.py +0 -0
  171. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualization/visualization_source_files.py +0 -0
  172. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualize_annotation_count.py +0 -0
  173. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualize_annotation_duration.py +0 -0
  174. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualize_statistics.py +0 -0
  175. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/statistics/visualize_video_duration.py +0 -0
  176. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/supplementary/__init__.py +0 -0
  177. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/supplementary/delete_supplementary_data.py +0 -0
  178. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/supplementary/list_supplementary_data.py +0 -0
  179. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/supplementary/put_supplementary_data.py +0 -0
  180. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/supplementary/subcommand_supplementary.py +0 -0
  181. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/__init__.py +0 -0
  182. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/cancel_acceptance.py +0 -0
  183. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/change_operator.py +0 -0
  184. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/change_status_to_break.py +0 -0
  185. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/change_status_to_on_hold.py +0 -0
  186. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/complete_tasks.py +0 -0
  187. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/copy_tasks.py +0 -0
  188. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/delete_metadata_key_of_task.py +0 -0
  189. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/delete_tasks.py +0 -0
  190. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/download_task_json.py +0 -0
  191. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/list_all_tasks.py +0 -0
  192. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/list_all_tasks_added_task_history.py +0 -0
  193. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/list_tasks.py +0 -0
  194. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/put_tasks.py +0 -0
  195. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/put_tasks_by_count.py +0 -0
  196. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/reject_tasks.py +0 -0
  197. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/subcommand_task.py +0 -0
  198. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task/update_metadata_of_task.py +0 -0
  199. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history/__init__.py +0 -0
  200. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history/download_task_history_json.py +0 -0
  201. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history/list_all_task_history.py +0 -0
  202. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history/list_task_history.py +0 -0
  203. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history/subcommand_task_history.py +0 -0
  204. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history_event/__init__.py +0 -0
  205. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history_event/download_task_history_event_json.py +0 -0
  206. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history_event/list_all_task_history_event.py +0 -0
  207. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history_event/list_worktime.py +0 -0
  208. {annofabcli-1.97.0 → annofabcli-1.98.0}/annofabcli/task_history_event/subcommand_task_history_event.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annofabcli
3
- Version: 1.97.0
3
+ Version: 1.98.0
4
4
  Summary: Utility Command Line Interface for AnnoFab
5
5
  Home-page: https://github.com/kurusugawa-computer/annofab-cli
6
6
  License: MIT
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Utilities
21
21
  Requires-Dist: Pillow
22
- Requires-Dist: annofabapi (>=1.1,<2.0)
22
+ Requires-Dist: annofabapi (>=1.4.1,<2.0.0)
23
23
  Requires-Dist: bokeh (>=3.3,<3.7)
24
24
  Requires-Dist: dictdiffer
25
25
  Requires-Dist: isodate
@@ -1 +1 @@
1
- __version__ = "1.97.0" # `poetry-dynamic-versioning`を使ってGitHubのバージョンタグを取得している。変更不要
1
+ __version__ = "1.98.0" # `poetry-dynamic-versioning`を使ってGitHubのバージョンタグを取得している。変更不要
@@ -0,0 +1,390 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import copy
5
+ import logging
6
+ import multiprocessing
7
+ import sys
8
+ import tempfile
9
+ from collections.abc import Collection
10
+ from pathlib import Path
11
+ from typing import Any, Optional
12
+
13
+ import annofabapi
14
+ import numpy
15
+ from annofabapi.pydantic_models.default_annotation_type import DefaultAnnotationType
16
+ from annofabapi.pydantic_models.task_status import TaskStatus
17
+ from annofabapi.segmentation import read_binary_image, write_binary_image
18
+ from annofabapi.util.annotation_specs import AnnotationSpecsAccessor
19
+ from annofabapi.utils import can_put_annotation
20
+
21
+ import annofabcli
22
+ from annofabcli.common.cli import (
23
+ COMMAND_LINE_ERROR_STATUS_CODE,
24
+ PARALLELISM_CHOICES,
25
+ ArgumentParser,
26
+ CommandLine,
27
+ CommandLineWithConfirm,
28
+ build_annofabapi_resource_and_login,
29
+ )
30
+ from annofabcli.common.facade import AnnofabApiFacade
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ def merge_binary_image_array(binary_image_array_list: list[numpy.ndarray]) -> numpy.ndarray:
36
+ """
37
+ 塗りつぶし画像を読み込んだboolのndarrayのlistから、1個のndarrayを作成します。
38
+
39
+ Args:
40
+ binary_image_array_list: 塗りつぶし画像を読み込んだboolのndarrayのlist
41
+ """
42
+ if len(binary_image_array_list) == 0:
43
+ raise ValueError("'binary_image_array_list' must not be empty.")
44
+
45
+ merged_array = numpy.zeros_like(binary_image_array_list[0], dtype=bool)
46
+ for binary_image_array in binary_image_array_list:
47
+ merged_array = numpy.logical_or(merged_array, binary_image_array)
48
+ return merged_array
49
+
50
+
51
+ class MergeSegmentationMain(CommandLineWithConfirm):
52
+ def __init__(
53
+ self,
54
+ annofab_service: annofabapi.Resource,
55
+ *,
56
+ project_id: str,
57
+ label_ids: Collection[str],
58
+ label_names: Collection[str],
59
+ all_yes: bool,
60
+ is_force: bool,
61
+ ) -> None:
62
+ self.annofab_service = annofab_service
63
+ self.project_id = project_id
64
+ self.is_force = is_force
65
+ self.label_ids = label_ids
66
+ self.label_names = label_names
67
+
68
+ super().__init__(all_yes)
69
+
70
+ def write_merged_segmentation_file(self, details: list[dict[str, Any]], output_dir: Path) -> tuple[list[str], list[str]]:
71
+ """
72
+ `getEditorAnnotation` APIで取得した`details`から、指定したラベルに対応する塗りつぶしアノテーションを1個にまとめて、
73
+ `output_dir`に出力します。
74
+ 塗りつぶし画像のファイル名は`${annotation_id}.png`です。
75
+
76
+ Args:
77
+ details: `getEditorAnnotation` APIで取得した`details`
78
+ label_ids: 更新対象のアノテーションに対応するラベルIDのcollection
79
+ output_dir: 塗りつぶし画像の出力先のディレクトリ。
80
+
81
+ Returns:
82
+ tuple[0]: 更新対象の塗りつぶしアノテーションのannotation_idのlist(最前面のアノテーション)
83
+ tuple[1]: 削除対象の塗りつぶしアノテーションのannotation_idのlist
84
+ """
85
+
86
+ def func(label_id: str) -> tuple[Optional[str], list[str]]:
87
+ updated_annotation_id = None
88
+ deleted_annotation_id_list = []
89
+ binary_image_array_list = []
90
+ segmentation_details = [e for e in details if e["label_id"] == label_id]
91
+ if len(segmentation_details) <= 1:
92
+ return None, []
93
+
94
+ updated_annotation_id = segmentation_details[0]["annotation_id"]
95
+ deleted_annotation_id_list = [e["annotation_id"] for e in segmentation_details[1:]]
96
+ for detail in segmentation_details:
97
+ segmentation_response = self.annofab_service.wrapper.execute_http_get(detail["body"]["url"], stream=True)
98
+ segmentation_response.raw.decode_content = True
99
+ binary_image_array_list.append(read_binary_image(segmentation_response.raw))
100
+
101
+ merged_binary_image_array = merge_binary_image_array(binary_image_array_list)
102
+ output_file_path = output_dir / f"{updated_annotation_id}.png"
103
+ write_binary_image(merged_binary_image_array, output_file_path)
104
+ return updated_annotation_id, deleted_annotation_id_list
105
+
106
+ updated_annotation_id_list = []
107
+ deleted_annotation_id_list = []
108
+ for label_id in self.label_ids:
109
+ updated_annotation_id, sub_deleted_annotation_id_list = func(label_id)
110
+ if updated_annotation_id is not None:
111
+ updated_annotation_id_list.append(updated_annotation_id)
112
+
113
+ deleted_annotation_id_list.extend(sub_deleted_annotation_id_list)
114
+
115
+ return updated_annotation_id_list, deleted_annotation_id_list
116
+
117
+ def merge_segmentation_annotation(self, task_id: str, input_data_id: str, log_message_prefix: str = "") -> bool:
118
+ """
119
+ label_idに対応する複数の塗りつぶしアノテーションを1つにまとめます。
120
+
121
+ Args:
122
+ project_id: プロジェクトID
123
+ task_id: タスクID
124
+ annotation_id_list: 更新する塗りつぶし画像のannotation_idのlist
125
+ """
126
+ old_annotation, _ = self.annofab_service.api.get_editor_annotation(self.project_id, task_id, input_data_id, query_params={"v": "2"})
127
+ old_details = old_annotation["details"]
128
+ with tempfile.TemporaryDirectory() as temp_dir:
129
+ temp_dir_path = Path(temp_dir)
130
+ updated_annotation_id_list, deleted_annotation_id_list = self.write_merged_segmentation_file(old_details, temp_dir_path)
131
+ if len(updated_annotation_id_list) == 0:
132
+ assert len(deleted_annotation_id_list) == 0
133
+ logger.debug(
134
+ f"{log_message_prefix}更新対象の塗りつぶしアノテーションはなかった"
135
+ "(1個のラベルに塗りつぶしアノテーションは複数なかった)ので、スキップします。 :: "
136
+ f"task_id='{task_id}', input_data_id='{input_data_id}'"
137
+ )
138
+ return False
139
+
140
+ logger.debug(
141
+ f"{log_message_prefix}{len(updated_annotation_id_list)} 件の塗りつぶしアノテーションを更新して、"
142
+ f"{len(deleted_annotation_id_list)} 件の塗りつぶしアノテーションを削除します。 :: "
143
+ f"task_id='{task_id}', input_data_id='{input_data_id}', "
144
+ f"更新対象のannotation_id_list={updated_annotation_id_list}, "
145
+ f"削除対象のannotation_id_list={deleted_annotation_id_list}"
146
+ )
147
+ new_details = []
148
+ for detail in old_details:
149
+ annotation_id = detail["annotation_id"]
150
+ if annotation_id in deleted_annotation_id_list:
151
+ continue
152
+
153
+ new_detail = copy.deepcopy(detail)
154
+ new_detail["_type"] = "Update"
155
+ if annotation_id in updated_annotation_id_list:
156
+ with (temp_dir_path / f"{annotation_id}.png").open("rb") as f:
157
+ s3_path = self.annofab_service.wrapper.upload_data_to_s3(self.project_id, data=f, content_type="image/png")
158
+
159
+ new_detail["body"]["path"] = s3_path
160
+
161
+ else:
162
+ # 更新しない場合は、`body`をNoneにする
163
+ new_detail["body"] = None
164
+
165
+ new_details.append(new_detail)
166
+
167
+ request_body = {
168
+ "project_id": self.project_id,
169
+ "task_id": task_id,
170
+ "input_data_id": input_data_id,
171
+ "details": new_details,
172
+ "format_version": "2.0.0",
173
+ "updated_datetime": old_annotation["updated_datetime"],
174
+ }
175
+ self.annofab_service.api.put_annotation(self.project_id, task_id, input_data_id, query_params={"v": "2"}, request_body=request_body)
176
+ logger.debug(
177
+ f"{log_message_prefix}{len(updated_annotation_id_list)} 件の塗りつぶしアノテーションを更新して、"
178
+ f"{len(deleted_annotation_id_list)} 件の塗りつぶしアノテーションを削除しました。 :: "
179
+ f"task_id='{task_id}', input_data_id='{input_data_id}'"
180
+ )
181
+ return True
182
+
183
+ def merge_segmentation_annotation_for_task(self, task_id: str, *, task_index: Optional[int] = None) -> int:
184
+ """
185
+ 1個のタスクに対して、label_idに対応する複数の塗りつぶしアノテーションを1つにまとめます。
186
+
187
+ Returns:
188
+ アノテーションを更新した入力データ数(フレーム数)
189
+ """
190
+ log_message_prefix = f"{task_index + 1} 件目 :: " if task_index is not None else ""
191
+
192
+ task = self.annofab_service.wrapper.get_task_or_none(project_id=self.project_id, task_id=task_id)
193
+ if task is None:
194
+ logger.warning(f"{log_message_prefix}task_id='{task_id}'であるタスクは存在しません。")
195
+ return 0
196
+
197
+ if task["status"] in {TaskStatus.WORKING.value, TaskStatus.COMPLETE.value}:
198
+ logger.debug(
199
+ f"{log_message_prefix}task_id='{task_id}'のタスクの状態は「作業中」または「完了」であるため、"
200
+ f"アノテーションの更新をスキップします。 :: status='{task['status']}'"
201
+ )
202
+ return 0
203
+
204
+ if not self.confirm_processing(
205
+ f"task_id='{task_id}'の次のラベル名に対応する複数の塗りつぶしアノテーションを1つにまとめますか? :: {self.label_names}"
206
+ ):
207
+ return 0
208
+
209
+ # 担当者割り当て変更チェック
210
+ changed_operator = False
211
+ original_operator_account_id = task["account_id"]
212
+ if not can_put_annotation(task, self.annofab_service.api.account_id):
213
+ if self.is_force:
214
+ logger.debug(f"{log_message_prefix}task_id='{task_id}' のタスクの担当者を自分自身に変更します。")
215
+ changed_operator = True
216
+ task = self.annofab_service.wrapper.change_task_operator(
217
+ self.project_id,
218
+ task_id,
219
+ self.annofab_service.api.account_id,
220
+ last_updated_datetime=task["updated_datetime"],
221
+ )
222
+ else:
223
+ logger.debug(
224
+ f"{log_message_prefix}task_id='{task_id}' のタスクは、過去に誰かに割り当てられたタスクで、"
225
+ f"現在の担当者が自分自身でないため、アノテーションの更新をスキップします。"
226
+ f"担当者を自分自身に変更してアノテーションを更新する場合は、コマンドライン引数 '--force' を指定してください。"
227
+ )
228
+ return 0
229
+
230
+ success_input_data_count = 0
231
+ for input_data_id in task["input_data_id_list"]:
232
+ try:
233
+ result = self.merge_segmentation_annotation(task_id, input_data_id, log_message_prefix=log_message_prefix)
234
+ if result:
235
+ success_input_data_count += 1
236
+ except Exception:
237
+ logger.warning(
238
+ f"{log_message_prefix}task_id='{task_id}', input_data_id='{input_data_id}'のアノテーションの更新に失敗しました。", exc_info=True
239
+ )
240
+ continue
241
+
242
+ # 担当者を元に戻す
243
+ if changed_operator:
244
+ logger.debug(
245
+ f"{log_message_prefix}task_id='{task_id}' のタスクの担当者を、元の担当者(account_id='{original_operator_account_id}')に変更します。"
246
+ )
247
+ self.annofab_service.wrapper.change_task_operator(
248
+ self.project_id,
249
+ task_id,
250
+ original_operator_account_id,
251
+ last_updated_datetime=task["updated_datetime"],
252
+ )
253
+
254
+ return success_input_data_count
255
+
256
+ def update_segmentation_annotation_for_task_wrapper(self, tpl: tuple[int, str]) -> int:
257
+ try:
258
+ task_index, task_id = tpl
259
+ return self.merge_segmentation_annotation_for_task(task_id, task_index=task_index)
260
+ except Exception:
261
+ logger.warning(f"task_id='{task_id}' のアノテーションの更新に失敗しました。", exc_info=True)
262
+ return 0
263
+
264
+ def main(
265
+ self,
266
+ task_ids: Collection[str],
267
+ parallelism: Optional[int] = None,
268
+ ) -> None:
269
+ logger.info(f"{len(task_ids)} 件のタスクに対して、複数の塗りつぶしアノテーションを1個にまとめます。")
270
+ success_input_data_count = 0
271
+ if parallelism is not None:
272
+ with multiprocessing.Pool(parallelism) as pool:
273
+ result_count_list = pool.map(self.update_segmentation_annotation_for_task_wrapper, enumerate(task_ids))
274
+ success_input_data_count = sum(result_count_list)
275
+
276
+ else:
277
+ for task_index, task_id in enumerate(task_ids):
278
+ try:
279
+ result = self.merge_segmentation_annotation_for_task(task_id, task_index=task_index)
280
+ success_input_data_count += result
281
+ except Exception:
282
+ logger.warning(f"task_id='{task_id}' のアノテーションの更新に失敗しました。", exc_info=True)
283
+ continue
284
+
285
+ logger.info(f"{len(task_ids)} 件のタスクに含まれる入力データ {success_input_data_count} 件の塗りつぶしアノテーションを更新しました。")
286
+
287
+
288
+ class MergeSegmentation(CommandLine):
289
+ COMMON_MESSAGE = "annofabcli annotation merge_segmentation: error:"
290
+
291
+ def validate(self, args: argparse.Namespace) -> bool:
292
+ if args.parallelism is not None and not args.yes:
293
+ print( # noqa: T201
294
+ f"{self.COMMON_MESSAGE} argument --parallelism: '--parallelism'を指定するときは、'--yes' を指定してください。",
295
+ file=sys.stderr,
296
+ )
297
+ return False
298
+
299
+ return True
300
+
301
+ def main(self) -> None:
302
+ args = self.args
303
+ if not self.validate(args):
304
+ sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
305
+
306
+ project_id = args.project_id
307
+ task_id_list = annofabcli.common.cli.get_list_from_args(args.task_id)
308
+ label_name_list = annofabcli.common.cli.get_list_from_args(args.label_name)
309
+
310
+ annotation_specs, _ = self.service.api.get_annotation_specs(project_id, query_params={"v": "3"})
311
+ accessor = AnnotationSpecsAccessor(annotation_specs)
312
+ label_id_list = []
313
+ invalid_label_name_list = []
314
+ for label_name in label_name_list:
315
+ try:
316
+ label = accessor.get_label(label_name=label_name)
317
+ if label["annotation_type"] not in {DefaultAnnotationType.SEGMENTATION.value, DefaultAnnotationType.SEGMENTATION_V2.value}:
318
+ invalid_label_name_list.append(label_name)
319
+
320
+ except ValueError:
321
+ invalid_label_name_list.append(label_name)
322
+ continue
323
+
324
+ label_id_list.append(label["label_id"])
325
+
326
+ if len(invalid_label_name_list) > 0:
327
+ print( # noqa: T201
328
+ f"{self.COMMON_MESSAGE} --label_name: 次のラベル名(英語)はアノテーション仕様に存在しないか、"
329
+ f"アノテーションの種類が「塗りつぶし」ではありません。 :: {invalid_label_name_list}",
330
+ file=sys.stderr,
331
+ )
332
+ sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
333
+
334
+ main_obj = MergeSegmentationMain(
335
+ self.service,
336
+ project_id=project_id,
337
+ label_ids=label_id_list,
338
+ label_names=label_name_list,
339
+ all_yes=self.all_yes,
340
+ is_force=args.force,
341
+ )
342
+
343
+ main_obj.main(task_id_list, parallelism=args.parallelism)
344
+
345
+
346
+ def main(args: argparse.Namespace) -> None:
347
+ service = build_annofabapi_resource_and_login(args)
348
+ facade = AnnofabApiFacade(service)
349
+ MergeSegmentation(service, facade, args).main()
350
+
351
+
352
+ def parse_args(parser: argparse.ArgumentParser) -> None:
353
+ argument_parser = ArgumentParser(parser)
354
+ argument_parser.add_project_id()
355
+ argument_parser.add_task_id()
356
+
357
+ parser.add_argument(
358
+ "--label_name",
359
+ type=str,
360
+ nargs="+",
361
+ required=True,
362
+ help="変更対象のアノテーションのラベル名(英語)を指定します。",
363
+ )
364
+
365
+ parser.add_argument(
366
+ "--force",
367
+ action="store_true",
368
+ help="過去に担当者を割り当てられていて、かつ現在の担当者が自分自身でない場合、タスクの担当者を一時的に自分自身に変更してからアノテーションをコピーします。",
369
+ )
370
+
371
+ parser.add_argument(
372
+ "--parallelism",
373
+ type=int,
374
+ choices=PARALLELISM_CHOICES,
375
+ help="並列度。指定しない場合は、逐次的に処理します。指定した場合は、``--yes`` も指定してください。",
376
+ )
377
+
378
+ parser.set_defaults(subcommand_func=main)
379
+
380
+
381
+ def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
382
+ subcommand_name = "merge_segmentation"
383
+ subcommand_help = "複数の塗りつぶしアノテーションを1つにまとめます。"
384
+ description = (
385
+ "複数の塗りつぶしアノテーションを1つにまとめます。"
386
+ "ラベルの種類を「塗りつぶし(インスタンスセグメンテーション)」から「塗りつぶしv2(セマンティックセグメンテーション)」に変更する場合などに有用です。"
387
+ )
388
+ parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description)
389
+ parse_args(parser)
390
+ return parser