OTAnalytics 0.7.4__tar.gz → 0.7.5__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 (700) hide show
  1. otanalytics-0.7.5/.github/workflows/system-test.yml +34 -0
  2. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/test.yml +1 -1
  3. {otanalytics-0.7.4 → otanalytics-0.7.5}/.gitignore +6 -0
  4. {otanalytics-0.7.4 → otanalytics-0.7.5}/.pre-commit-config.yaml +4 -0
  5. otanalytics-0.7.5/CONTEXT.md +56 -0
  6. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/dummy_viewmodel.py +164 -67
  7. otanalytics-0.7.5/OTAnalytics/adapter_ui/file_export_dto.py +31 -0
  8. otanalytics-0.7.5/OTAnalytics/adapter_ui/local_file_providers.py +57 -0
  9. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/ui_factory.py +1 -1
  10. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/view_model.py +4 -1
  11. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/analysis/traffic_counting.py +6 -3
  12. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/analysis/traffic_counting_specification.py +12 -5
  13. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/application.py +75 -13
  14. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/config.py +9 -0
  15. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/config_specification.py +1 -1
  16. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/datastore.py +6 -51
  17. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/eventlist.py +12 -0
  18. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/export_formats/event_list.py +2 -0
  19. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/export_formats/road_user_assignments.py +4 -0
  20. otanalytics-0.7.5/OTAnalytics/application/export_path_builder.py +54 -0
  21. otanalytics-0.7.5/OTAnalytics/application/files.py +19 -0
  22. otanalytics-0.7.5/OTAnalytics/application/key_prefix.py +34 -0
  23. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/parser/cli_parser.py +1 -1
  24. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/parser/config_parser.py +23 -0
  25. otanalytics-0.7.5/OTAnalytics/application/parser/track_parser.py +54 -0
  26. otanalytics-0.7.5/OTAnalytics/application/progress.py +195 -0
  27. otanalytics-0.7.5/OTAnalytics/application/project_location.py +43 -0
  28. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/resources/resource_manager.py +25 -0
  29. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/run_configuration.py +1 -1
  30. otanalytics-0.7.5/OTAnalytics/application/startup_config.py +54 -0
  31. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/state.py +28 -0
  32. otanalytics-0.7.5/OTAnalytics/application/upload_otconfig.py +24 -0
  33. otanalytics-0.7.5/OTAnalytics/application/use_cases/ask_for_load_window.py +47 -0
  34. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/config.py +24 -3
  35. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/config_has_changed.py +4 -1
  36. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/export_events.py +24 -2
  37. otanalytics-0.7.5/OTAnalytics/application/use_cases/flow_repository.py +116 -0
  38. otanalytics-0.7.5/OTAnalytics/application/use_cases/load_otconfig.py +130 -0
  39. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/load_otflow.py +5 -6
  40. otanalytics-0.7.5/OTAnalytics/application/use_cases/load_track_files.py +188 -0
  41. otanalytics-0.7.5/OTAnalytics/application/use_cases/provide_input_files.py +35 -0
  42. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/quick_save_configuration.py +2 -2
  43. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/reset_state.py +4 -0
  44. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/road_user_assignment_export.py +53 -12
  45. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/suggest_save_path.py +58 -5
  46. otanalytics-0.7.5/OTAnalytics/application/use_cases/track_export.py +31 -0
  47. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/track_statistics_export.py +47 -13
  48. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/event.py +26 -0
  49. otanalytics-0.7.5/OTAnalytics/domain/georeference.py +56 -0
  50. otanalytics-0.7.5/OTAnalytics/domain/load_window.py +65 -0
  51. otanalytics-0.7.5/OTAnalytics/domain/progress.py +161 -0
  52. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track.py +12 -0
  53. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track_dataset/filtered_track_dataset.py +3 -0
  54. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track_dataset/track_dataset.py +33 -0
  55. otanalytics-0.7.5/OTAnalytics/domain/transfer_mode.py +8 -0
  56. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/filter_polars_track_dataset.py +11 -0
  57. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/polars_track_store.py +225 -13
  58. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/python_track_store.py +19 -0
  59. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/track_geometry_store/polars_geometry_store.py +367 -120
  60. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/track_store.py +37 -0
  61. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/argparse_cli_parser.py +8 -6
  62. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/convert_ottrk_to_feathers.py +27 -2
  63. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/export.py +55 -16
  64. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/feathers_parser.py +22 -88
  65. otanalytics-0.7.5/OTAnalytics/plugin_parser/georeference_parsing.py +30 -0
  66. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/otconfig_parser.py +118 -39
  67. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/ottrk_dataformat.py +15 -0
  68. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/otvision_parser.py +13 -6
  69. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/pandas_parser.py +8 -0
  70. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/road_user_assignment_export.py +11 -6
  71. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/streaming_parser.py +2 -5
  72. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/track_export.py +31 -51
  73. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/track_statistics_export.py +25 -16
  74. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/eventlist_exporter/eventlist_exporter.py +38 -17
  75. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/track_visualization/track_viz.py +7 -0
  76. otanalytics-0.7.5/OTAnalytics/plugin_s3/cleanup.py +58 -0
  77. otanalytics-0.7.5/OTAnalytics/plugin_s3/config/env_vars.py +76 -0
  78. otanalytics-0.7.5/OTAnalytics/plugin_s3/config/parsing.py +126 -0
  79. otanalytics-0.7.5/OTAnalytics/plugin_s3/config/s3.py +33 -0
  80. otanalytics-0.7.5/OTAnalytics/plugin_s3/download.py +37 -0
  81. otanalytics-0.7.5/OTAnalytics/plugin_s3/download_objects.py +106 -0
  82. otanalytics-0.7.5/OTAnalytics/plugin_s3/filename_timestamp.py +44 -0
  83. otanalytics-0.7.5/OTAnalytics/plugin_s3/list_objects.py +45 -0
  84. otanalytics-0.7.5/OTAnalytics/plugin_s3/otconfig_upload.py +15 -0
  85. otanalytics-0.7.5/OTAnalytics/plugin_s3/project_location.py +37 -0
  86. otanalytics-0.7.5/OTAnalytics/plugin_s3/s3_file_providers.py +267 -0
  87. otanalytics-0.7.5/OTAnalytics/plugin_s3/select_objects.py +45 -0
  88. otanalytics-0.7.5/OTAnalytics/plugin_s3/store.py +47 -0
  89. otanalytics-0.7.5/OTAnalytics/plugin_s3/upload.py +46 -0
  90. otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv/track_dataset_writer.py +42 -0
  91. otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv/writers/domain.py +30 -0
  92. otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv/writers/pandas.py +44 -0
  93. otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv/writers/polars.py +43 -0
  94. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/application_starter.py +38 -0
  95. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/base_application.py +57 -9
  96. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/cli.py +66 -44
  97. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/ctk_ui_factory.py +20 -21
  98. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/helpers.py +12 -2
  99. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_export_counts.py +76 -10
  100. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_export_file.py +56 -14
  101. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/gui_application.py +30 -2
  102. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_application.py +155 -3
  103. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/dialogs/export_counts_dialog.py +101 -36
  104. otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/dialogs/file_chooser_dialog.py +279 -0
  105. otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/dialogs/load_window_dialog.py +128 -0
  106. otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/nicegui/progressbar.py +215 -0
  107. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/remarks_form/container.py +0 -1
  108. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters_form/container.py +41 -6
  109. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/ui_factory.py +41 -9
  110. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/visualization/counts/counts_plotter.py +3 -1
  111. otanalytics-0.7.5/OTAnalytics/version.py +1 -0
  112. {otanalytics-0.7.4 → otanalytics-0.7.5}/PKG-INFO +3 -2
  113. {otanalytics-0.7.4 → otanalytics-0.7.5}/pyproject.toml +12 -1
  114. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/conftest.py +13 -1
  115. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_export_track_statistics.py +2 -1
  116. otanalytics-0.7.5/tests/acceptance/test_load_from_s3.py +234 -0
  117. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_project_information.py +2 -1
  118. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/benchmark/test_benchmark_otanalytics.py +3 -2
  119. otanalytics-0.7.5/tests/data/track_statistics_reference.csv +2 -0
  120. otanalytics-0.7.5/tests/integration/OTAnalytics/plugin_s3/test_load_from_rustfs.py +252 -0
  121. otanalytics-0.7.5/tests/system/OTAnalytics/plugin_ui/test_cli.py +209 -0
  122. otanalytics-0.7.5/tests/unit/OTAnalytics/adapter_ui/test_dummy_viewmodel_loading.py +118 -0
  123. otanalytics-0.7.5/tests/unit/OTAnalytics/adapter_ui/test_dummy_viewmodel_otconfig.py +254 -0
  124. otanalytics-0.7.5/tests/unit/OTAnalytics/adapter_ui/test_dummy_viewmodel_save_otconfig.py +99 -0
  125. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/adapter_ui/test_helpers.py +27 -0
  126. otanalytics-0.7.5/tests/unit/OTAnalytics/adapter_ui/test_local_file_providers.py +94 -0
  127. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/analysis/test_traffic_counting.py +13 -4
  128. otanalytics-0.7.5/tests/unit/OTAnalytics/application/parser/test_track_parser.py +156 -0
  129. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_current_key_prefix.py +58 -0
  130. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_datastore.py +2 -6
  131. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_eventlist.py +95 -0
  132. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_export_path_builder.py +46 -0
  133. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_key_prefix.py +54 -0
  134. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_progress.py +191 -0
  135. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_project_location.py +57 -0
  136. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_run_configuration.py +2 -2
  137. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_startup_config.py +68 -0
  138. otanalytics-0.7.5/tests/unit/OTAnalytics/application/test_upload_otconfig.py +30 -0
  139. otanalytics-0.7.5/tests/unit/OTAnalytics/application/use_cases/test_config.py +154 -0
  140. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_config_has_changed.py +5 -0
  141. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_flow_repository.py +59 -7
  142. otanalytics-0.7.5/tests/unit/OTAnalytics/application/use_cases/test_load_otconfig.py +343 -0
  143. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_load_otflow.py +8 -8
  144. otanalytics-0.7.5/tests/unit/OTAnalytics/application/use_cases/test_load_track_files.py +704 -0
  145. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_quick_save_configuration.py +17 -17
  146. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_reset_state.py +13 -0
  147. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_road_user_assignment_export.py +3 -2
  148. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_suggest_save_path.py +1 -1
  149. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_event.py +56 -0
  150. otanalytics-0.7.5/tests/unit/OTAnalytics/domain/test_georeference.py +54 -0
  151. otanalytics-0.7.5/tests/unit/OTAnalytics/domain/test_load_window.py +83 -0
  152. otanalytics-0.7.5/tests/unit/OTAnalytics/domain/test_track.py +35 -0
  153. otanalytics-0.7.5/tests/unit/OTAnalytics/domain/test_transfer_mode.py +26 -0
  154. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/track_dataset/test_filtered_track_dataset.py +8 -0
  155. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_cli/test_cli_application.py +16 -0
  156. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_datastore/test_filter_polars_track_store.py +50 -0
  157. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_datastore/test_polars_track_store.py +1535 -0
  158. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_datastore/test_python_track_store.py +119 -1
  159. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_datastore/test_track_store.py +195 -0
  160. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_datastore/track_geometry_store/test_polars_geometry_store.py +1604 -0
  161. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_intersect_parallelization/__init__.py +0 -0
  162. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/__init__.py +0 -0
  163. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz/__init__.py +0 -0
  164. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/__init__.py +0 -0
  165. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/conftest.py +32 -0
  166. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_convert_ottrk_to_feathers.py +68 -0
  167. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_export.py +34 -27
  168. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_feathers_parser.py +212 -31
  169. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_georeference_parsing.py +23 -0
  170. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_otconfig_key_prefix.py +162 -0
  171. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_otconfig_parser.py +104 -3
  172. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_otconfig_substitution.py +186 -0
  173. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_otvision_parser.py +56 -0
  174. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_pandas_parser.py +87 -0
  175. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_road_user_assignment_export.py +163 -0
  176. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_parser/test_track_export.py +176 -0
  177. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_progress/__init__.py +0 -0
  178. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_prototypes/__init__.py +0 -0
  179. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_prototypes/test_eventlist_exporter.py +89 -0
  180. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_prototypes/track_visualization/__init__.py +0 -0
  181. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/__init__.py +0 -0
  182. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/config/__init__.py +0 -0
  183. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/config/test_env_vars.py +49 -0
  184. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/config/test_parsing.py +186 -0
  185. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_cleanup.py +108 -0
  186. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_download.py +58 -0
  187. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_download_objects.py +218 -0
  188. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_filename_timestamp.py +55 -0
  189. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_list_objects.py +126 -0
  190. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_otconfig_upload.py +36 -0
  191. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_project_location.py +72 -0
  192. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_read_video_name.py +130 -0
  193. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_s3_file_providers.py +321 -0
  194. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_select_objects.py +96 -0
  195. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_s3/test_upload.py +61 -0
  196. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/__init__.py +0 -0
  197. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/__init__.py +0 -0
  198. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/conftest.py +8 -0
  199. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/test_domain.py +116 -0
  200. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/test_pandas.py +113 -0
  201. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/test_polars.py +108 -0
  202. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_track_export/csv/test_track_dataset_writer.py +91 -0
  203. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/__init__.py +0 -0
  204. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/dialogs/test_file_chooser_dialog.py +2 -1
  205. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/dialogs/test_load_window_dialog.py +201 -0
  206. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/nicegui/test_progressbar.py +279 -0
  207. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/remarks_form/__init__.py +0 -0
  208. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/remarks_form/test_container.py +84 -0
  209. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters_form/__init__.py +0 -0
  210. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters_form/test_container.py +85 -0
  211. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/test_ui_factory.py +66 -0
  212. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_cli.py +157 -13
  213. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_export_counts_dialog.py +90 -40
  214. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_file_chooser_dialog.py +144 -10
  215. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/test_nicegui_application.py +126 -0
  216. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/test_nicegui_preload.py +64 -0
  217. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/visualization/__init__.py +0 -0
  218. otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_ui/visualization/counts/__init__.py +0 -0
  219. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/visualization/counts/test_counts_plotter.py +7 -2
  220. otanalytics-0.7.5/tests/unit/__init__.py +0 -0
  221. otanalytics-0.7.5/tests/utils/__init__.py +0 -0
  222. otanalytics-0.7.5/tests/utils/app_environment.py +67 -0
  223. otanalytics-0.7.5/tests/utils/builders/__init__.py +0 -0
  224. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/event_builder.py +4 -0
  225. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/road_user_assignment.py +4 -0
  226. otanalytics-0.7.5/tests/utils/builders/s3_config_builder.py +34 -0
  227. otanalytics-0.7.5/tests/utils/builders/s3_store_builder.py +21 -0
  228. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/track_builder.py +4 -0
  229. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/playwright_helpers.py +59 -12
  230. otanalytics-0.7.5/tests/utils/progress.py +24 -0
  231. otanalytics-0.7.5/tests/utils/rustfs_container.py +62 -0
  232. {otanalytics-0.7.4 → otanalytics-0.7.5}/uv.lock +572 -302
  233. otanalytics-0.7.4/OTAnalytics/adapter_ui/file_export_dto.py +0 -8
  234. otanalytics-0.7.4/OTAnalytics/application/progress.py +0 -95
  235. otanalytics-0.7.4/OTAnalytics/application/use_cases/flow_repository.py +0 -101
  236. otanalytics-0.7.4/OTAnalytics/application/use_cases/load_otconfig.py +0 -76
  237. otanalytics-0.7.4/OTAnalytics/application/use_cases/load_track_files.py +0 -76
  238. otanalytics-0.7.4/OTAnalytics/application/use_cases/track_export.py +0 -57
  239. otanalytics-0.7.4/OTAnalytics/domain/progress.py +0 -84
  240. otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/dialogs/file_chooser_dialog.py +0 -155
  241. otanalytics-0.7.4/OTAnalytics/version.py +0 -1
  242. otanalytics-0.7.4/tests/unit/OTAnalytics/application/test_progress.py +0 -53
  243. otanalytics-0.7.4/tests/unit/OTAnalytics/application/use_cases/test_config.py +0 -54
  244. otanalytics-0.7.4/tests/unit/OTAnalytics/application/use_cases/test_load_otconfig.py +0 -164
  245. otanalytics-0.7.4/tests/unit/OTAnalytics/application/use_cases/test_load_track_files.py +0 -244
  246. otanalytics-0.7.4/tests/unit/OTAnalytics/application/use_cases/test_track_export.py +0 -49
  247. otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_datastore/test_polars_track_store.py +0 -626
  248. otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_datastore/track_geometry_store/test_polars_geometry_store.py +0 -733
  249. otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_parser/test_road_user_assignment_export.py +0 -82
  250. otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_parser/test_track_export.py +0 -59
  251. otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_prototypes/test_eventlist_exporter.py +0 -15
  252. {otanalytics-0.7.4 → otanalytics-0.7.5}/.editorconfig +0 -0
  253. {otanalytics-0.7.4 → otanalytics-0.7.5}/.flake8 +0 -0
  254. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/dependabot.yml +0 -0
  255. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/acceptance-test.yml +0 -0
  256. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/benchmark.yml +0 -0
  257. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/build-nightly.yml +0 -0
  258. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/build-release.yml +0 -0
  259. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/linter.yml +0 -0
  260. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/regression-test.yml +0 -0
  261. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/release-pypi.yml +0 -0
  262. {otanalytics-0.7.4 → otanalytics-0.7.5}/.github/workflows/release-testpypi.yml +0 -0
  263. {otanalytics-0.7.4 → otanalytics-0.7.5}/.junie/guidelines.md +0 -0
  264. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Scalene-CLI (benchmark).run.xml +0 -0
  265. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Scalene-CLI.run.xml +0 -0
  266. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-CLI (benchmark files).run.xml +0 -0
  267. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-CLI.run.xml +0 -0
  268. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-GUI (mit Benchmarkdaten).run.xml +0 -0
  269. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-GUI (mit Testdaten).run.xml +0 -0
  270. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-GUI.run.xml +0 -0
  271. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/Start-WebUI (mit Testdaten).run.xml +0 -0
  272. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/pytest-acceptance-tests.run.xml +0 -0
  273. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/pytest-benchmark-tests.run.xml +0 -0
  274. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/pytest-in-tests.run.xml +0 -0
  275. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/pytest-regression-tests.run.xml +0 -0
  276. {otanalytics-0.7.4 → otanalytics-0.7.5}/.run/pytest-unit-tests.run.xml +0 -0
  277. {otanalytics-0.7.4 → otanalytics-0.7.5}/.shellcheckrc +0 -0
  278. {otanalytics-0.7.4 → otanalytics-0.7.5}/.vscode/launch.json +0 -0
  279. {otanalytics-0.7.4 → otanalytics-0.7.5}/.vscode/settings.json +0 -0
  280. {otanalytics-0.7.4 → otanalytics-0.7.5}/.yamllint.yaml +0 -0
  281. {otanalytics-0.7.4 → otanalytics-0.7.5}/LICENSE +0 -0
  282. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/__init__.py +0 -0
  283. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/__main__.py +0 -0
  284. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_intersect/__init__.py +0 -0
  285. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/__init__.py +0 -0
  286. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_button_quick_save_config.py +0 -0
  287. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_canvas.py +0 -0
  288. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame.py +0 -0
  289. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_canvas.py +0 -0
  290. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_filter.py +0 -0
  291. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_offset.py +0 -0
  292. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_project.py +0 -0
  293. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_remark.py +0 -0
  294. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_track_plotting.py +0 -0
  295. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_frame_track_statistics.py +0 -0
  296. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_main_window.py +0 -0
  297. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_progressbar_popup.py +0 -0
  298. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/abstract_treeview_interface.py +0 -0
  299. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/cancel_export_counts.py +0 -0
  300. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/cancel_export_file.py +0 -0
  301. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/default_values.py +0 -0
  302. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/dto.py +0 -0
  303. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/file_selection_cancelled.py +0 -0
  304. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/flow_adapter.py +0 -0
  305. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/flow_dto.py +0 -0
  306. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/helpers.py +0 -0
  307. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/info_box.py +0 -0
  308. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/message_box.py +0 -0
  309. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/text_resources.py +0 -0
  310. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_ui/ui_texts.py +0 -0
  311. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_visualization/__init__.py +0 -0
  312. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/adapter_visualization/color_provider.py +0 -0
  313. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/__init__.py +0 -0
  314. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/analysis/__init__.py +0 -0
  315. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/analysis/intersect.py +0 -0
  316. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/analysis/road_user_assignment.py +0 -0
  317. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/exception.py +0 -0
  318. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/export_formats/__init__.py +0 -0
  319. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/export_formats/export_mode.py +0 -0
  320. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/export_formats/track_statistics.py +0 -0
  321. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/geometry.py +0 -0
  322. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/logger.py +0 -0
  323. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/parser/__init__.py +0 -0
  324. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/parser/deserializer.py +0 -0
  325. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/parser/flow_parser.py +0 -0
  326. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/playback.py +0 -0
  327. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/plotting.py +0 -0
  328. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/project.py +0 -0
  329. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/resources/__init__.py +0 -0
  330. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/track_filter.py +0 -0
  331. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/track_input_source.py +0 -0
  332. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/ui/__init__.py +0 -0
  333. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/ui/frame_control.py +0 -0
  334. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/__init__.py +0 -0
  335. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/add_new_remark.py +0 -0
  336. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/apply_cli_cuts.py +0 -0
  337. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/assignment_repository.py +0 -0
  338. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/clear_repositories.py +0 -0
  339. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/create_events.py +0 -0
  340. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/create_intersection_events.py +0 -0
  341. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/create_road_user_assignments.py +0 -0
  342. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/cut_tracks_with_sections.py +0 -0
  343. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/editor/__init__.py +0 -0
  344. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/editor/section_editor.py +0 -0
  345. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/event_repository.py +0 -0
  346. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/filter_visualization.py +0 -0
  347. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/flow_statistics.py +0 -0
  348. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/generate_flows.py +0 -0
  349. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/get_current_project.py +0 -0
  350. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/get_current_remark.py +0 -0
  351. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/highlight_intersections.py +0 -0
  352. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/inside_cutting_section.py +0 -0
  353. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/intersection_repository.py +0 -0
  354. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/number_of_tracks_to_be_validated.py +0 -0
  355. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/preload_input_files.py +0 -0
  356. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/reset_application.py +0 -0
  357. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/reset_project_config.py +0 -0
  358. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/revert_cuts.py +0 -0
  359. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/save_otflow.py +0 -0
  360. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/section_repository.py +0 -0
  361. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/start_new_project.py +0 -0
  362. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/track_repository.py +0 -0
  363. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/track_statistics.py +0 -0
  364. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/update_count_plots.py +0 -0
  365. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/update_project.py +0 -0
  366. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/application/use_cases/video_repository.py +0 -0
  367. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/assets/OpenTrafficCam_800.png +0 -0
  368. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/__init__.py +0 -0
  369. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/common.py +0 -0
  370. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/date.py +0 -0
  371. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/files.py +0 -0
  372. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/filter.py +0 -0
  373. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/flow.py +0 -0
  374. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/geometry.py +0 -0
  375. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/intersect.py +0 -0
  376. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/observer.py +0 -0
  377. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/otc_classes.py +0 -0
  378. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/remark.py +0 -0
  379. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/section.py +0 -0
  380. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/tls8plus1_classes.py +0 -0
  381. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track_dataset/__init__.py +0 -0
  382. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track_id_provider.py +0 -0
  383. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/track_repository.py +0 -0
  384. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/types.py +0 -0
  385. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/domain/video.py +0 -0
  386. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/helpers/__init__.py +0 -0
  387. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/helpers/file_helpers.py +0 -0
  388. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/helpers/time_profiling.py +0 -0
  389. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_cli/__init__.py +0 -0
  390. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_cli/cli_application.py +0 -0
  391. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/__init__.py +0 -0
  392. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/filter_pandas_track_store.py +0 -0
  393. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/get_current_frame_track_segments.py +0 -0
  394. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/pandas_track_dataset_factory.py +0 -0
  395. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/polars_track_id_set.py +0 -0
  396. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/track_geometry_store/__init__.py +0 -0
  397. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_datastore/track_geometry_store/shapely_store.py +0 -0
  398. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_filter/__init__.py +0 -0
  399. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_filter/dataframe_filter.py +0 -0
  400. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_filter/pandas_track_id.py +0 -0
  401. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/__init__.py +0 -0
  402. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/shapely/__init__.py +0 -0
  403. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/shapely/mapping.py +0 -0
  404. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/simple/__init__.py +0 -0
  405. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/simple/cut_tracks_with_sections.py +0 -0
  406. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect/simple_intersect.py +0 -0
  407. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect_parallelization/__init__.py +0 -0
  408. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect_parallelization/multiprocessing.py +0 -0
  409. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_intersect_parallelization/sequential.py +0 -0
  410. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/__init__.py +0 -0
  411. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/calculation_strategy.py +0 -0
  412. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/metric_rates_builder.py +0 -0
  413. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz/__init__.py +0 -0
  414. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz/metric_rates.py +0 -0
  415. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz/number_of_tracks_to_be_validated.py +0 -0
  416. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_number_of_tracks_to_be_validated/tracks_as_dataframe_provider.py +0 -0
  417. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/__init__.py +0 -0
  418. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/dataformat_versions.py +0 -0
  419. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_parser/json_parser.py +0 -0
  420. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_progress/__init__.py +0 -0
  421. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_progress/lazy_tqdm_progressbar.py +0 -0
  422. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_progress/multiprocessing_progress.py +0 -0
  423. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_progress/tqdm_progressbar.py +0 -0
  424. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/__init__.py +0 -0
  425. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/event_visualization.py +0 -0
  426. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/eventlist_exporter/__init__.py +0 -0
  427. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/track_visualization/__init__.py +0 -0
  428. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/track_visualization/cv2_image.py +0 -0
  429. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/track_visualization/numpy_image.py +0 -0
  430. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_prototypes/track_visualization/pil_image.py +0 -0
  431. {otanalytics-0.7.4/OTAnalytics/plugin_track_input_source → otanalytics-0.7.5/OTAnalytics/plugin_s3}/__init__.py +0 -0
  432. {otanalytics-0.7.4/OTAnalytics/plugin_ui → otanalytics-0.7.5/OTAnalytics/plugin_s3/config}/__init__.py +0 -0
  433. {otanalytics-0.7.4/OTAnalytics/plugin_ui/customtkinter_gui → otanalytics-0.7.5/OTAnalytics/plugin_track_export}/__init__.py +0 -0
  434. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui → otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv}/__init__.py +0 -0
  435. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/dialogs → otanalytics-0.7.5/OTAnalytics/plugin_track_export/csv/writers}/__init__.py +0 -0
  436. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/forms → otanalytics-0.7.5/OTAnalytics/plugin_track_input_source}/__init__.py +0 -0
  437. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_track_input_source/single_batch.py +0 -0
  438. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_track_input_source/template.py +0 -0
  439. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/nicegui → otanalytics-0.7.5/OTAnalytics/plugin_ui}/__init__.py +0 -0
  440. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/ctk_application.py +0 -0
  441. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements → otanalytics-0.7.5/OTAnalytics/plugin_ui/customtkinter_gui}/__init__.py +0 -0
  442. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/abstract_ctk_canvas.py +0 -0
  443. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/abstract_ctk_frame.py +0 -0
  444. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/button_quick_save_config.py +0 -0
  445. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/canvas_observer.py +0 -0
  446. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/constants.py +0 -0
  447. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/custom_containers.py +0 -0
  448. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_analysis.py +0 -0
  449. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_bbox_offset.py +0 -0
  450. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_canvas.py +0 -0
  451. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_configuration.py +0 -0
  452. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_date_filter_control.py +0 -0
  453. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_files.py +0 -0
  454. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_filter.py +0 -0
  455. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_flows.py +0 -0
  456. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_project.py +0 -0
  457. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_remarks.py +0 -0
  458. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_sections.py +0 -0
  459. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_track_plotting.py +0 -0
  460. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_track_statistics.py +0 -0
  461. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_tracks.py +0 -0
  462. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/frame_videos.py +0 -0
  463. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/gui.py +0 -0
  464. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/line_section.py +0 -0
  465. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/messagebox.py +0 -0
  466. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/scrollable_xy_frame.py +0 -0
  467. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/state.py +0 -0
  468. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/style.py +0 -0
  469. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_flows.py +0 -0
  470. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_progress.py +0 -0
  471. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_sections.py +0 -0
  472. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/toplevel_template.py +0 -0
  473. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/treeview_template.py +0 -0
  474. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/customtkinter_gui/utility_widgets.py +0 -0
  475. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/intersection_repository.py +0 -0
  476. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/nicegui/theme → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui}/__init__.py +0 -0
  477. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/config.py +0 -0
  478. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/page_builders → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/dialogs}/__init__.py +0 -0
  479. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/dialogs/edit_flow_dialog.py +0 -0
  480. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/dialogs/edit_section_dialog.py +0 -0
  481. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/dialogs/file_picker.py +0 -0
  482. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/endpoints.py +0 -0
  483. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/file_utils.py +0 -0
  484. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/forms}/__init__.py +0 -0
  485. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/forms/offset_slider_form.py +0 -0
  486. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/add_track_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/nicegui}/__init__.py +0 -0
  487. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/constants.py +0 -0
  488. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/add_video_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements}/__init__.py +0 -0
  489. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements/button_form.py +0 -0
  490. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements/dialog.py +0 -0
  491. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements/forms.py +0 -0
  492. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/elements/table.py +0 -0
  493. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/nicegui_webserver.py +0 -0
  494. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/page_builder.py +0 -0
  495. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/circle.py +0 -0
  496. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/circle_resources.py +0 -0
  497. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/line.py +0 -0
  498. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/line_resources.py +0 -0
  499. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/polyline.py +0 -0
  500. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/section_resources.py +0 -0
  501. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/analysis_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/nicegui/theme}/__init__.py +0 -0
  502. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/theme/color.py +0 -0
  503. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/theme/global_theme.py +0 -0
  504. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/theme/nicegui_layout_components.py +0 -0
  505. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/nicegui/validation.py +0 -0
  506. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/page_builders}/__init__.py +0 -0
  507. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/page_builders/main_page_builder.py +0 -0
  508. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/configuration_bar → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages}/__init__.py +0 -0
  509. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/remarks_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/add_track_form}/__init__.py +0 -0
  510. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/add_track_form/add_tracks_form.py +0 -0
  511. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/add_track_form/container.py +0 -0
  512. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/add_track_form/visualization_offset_slider_form.py +0 -0
  513. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/sections_and_flow_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/add_video_form}/__init__.py +0 -0
  514. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/add_video_form/container.py +0 -0
  515. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/svz_metadata_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/analysis_form}/__init__.py +0 -0
  516. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/analysis_form/container.py +0 -0
  517. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/track_statistics_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form}/__init__.py +0 -0
  518. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form/canvas_form.py +0 -0
  519. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form/container.py +0 -0
  520. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form/files_form.py +0 -0
  521. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/configuration_bar}/__init__.py +0 -0
  522. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/configuration_bar/container.py +0 -0
  523. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/configuration_bar/project_form.py +0 -0
  524. {otanalytics-0.7.4/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_layers_form → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/remarks_form}/__init__.py +0 -0
  525. {otanalytics-0.7.4/OTAnalytics/plugin_ui/utils → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/sections_and_flow_form}/__init__.py +0 -0
  526. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/sections_and_flow_form/container.py +0 -0
  527. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/sections_and_flow_form/flow_form.py +0 -0
  528. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/sections_and_flow_form/sections_form.py +0 -0
  529. {otanalytics-0.7.4/OTAnalytics/plugin_ui/visualization → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/svz_metadata_form}/__init__.py +0 -0
  530. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/svz_metadata_form/svz_metadata_form.py +0 -0
  531. {otanalytics-0.7.4/OTAnalytics/plugin_ui/visualization/counts → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/track_statistics_form}/__init__.py +0 -0
  532. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/track_statistics_form/container.py +0 -0
  533. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters.py +0 -0
  534. {otanalytics-0.7.4/tests → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_filters_form}/__init__.py +0 -0
  535. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_layers.py +0 -0
  536. {otanalytics-0.7.4/tests/acceptance → otanalytics-0.7.5/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_layers_form}/__init__.py +0 -0
  537. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_layers_form/container.py +0 -0
  538. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/visualization_layers_form/layers_form.py +0 -0
  539. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/pages/workspace.py +0 -0
  540. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/nicegui_gui/test_constants.py +0 -0
  541. {otanalytics-0.7.4/tests/benchmark → otanalytics-0.7.5/OTAnalytics/plugin_ui/utils}/__init__.py +0 -0
  542. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/utils/asyncio_helper.py +0 -0
  543. {otanalytics-0.7.4/tests/regression → otanalytics-0.7.5/OTAnalytics/plugin_ui/visualization}/__init__.py +0 -0
  544. {otanalytics-0.7.4/tests/unit/OTAnalytics → otanalytics-0.7.5/OTAnalytics/plugin_ui/visualization/counts}/__init__.py +0 -0
  545. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_ui/visualization/visualization.py +0 -0
  546. {otanalytics-0.7.4 → otanalytics-0.7.5}/OTAnalytics/plugin_video_processing/video_reader.py +0 -0
  547. {otanalytics-0.7.4 → otanalytics-0.7.5}/README.md +0 -0
  548. {otanalytics-0.7.4 → otanalytics-0.7.5}/clean-up-repository.sh +0 -0
  549. {otanalytics-0.7.4 → otanalytics-0.7.5}/config.yml +0 -0
  550. {otanalytics-0.7.4 → otanalytics-0.7.5}/convert_ottrk_to_feather.py +0 -0
  551. {otanalytics-0.7.4 → otanalytics-0.7.5}/install.cmd +0 -0
  552. {otanalytics-0.7.4 → otanalytics-0.7.5}/install.sh +0 -0
  553. {otanalytics-0.7.4 → otanalytics-0.7.5}/install_dev.cmd +0 -0
  554. {otanalytics-0.7.4 → otanalytics-0.7.5}/install_dev.sh +0 -0
  555. {otanalytics-0.7.4 → otanalytics-0.7.5}/requirements.txt +0 -0
  556. {otanalytics-0.7.4 → otanalytics-0.7.5}/scripts/check_clean_architecture.py +0 -0
  557. {otanalytics-0.7.4 → otanalytics-0.7.5}/start_gui.cmd +0 -0
  558. {otanalytics-0.7.4 → otanalytics-0.7.5}/start_gui.sh +0 -0
  559. {otanalytics-0.7.4/tests/unit/OTAnalytics/adapter_intersect → otanalytics-0.7.5/tests}/__init__.py +0 -0
  560. {otanalytics-0.7.4/tests/unit/OTAnalytics/application → otanalytics-0.7.5/tests/acceptance}/__init__.py +0 -0
  561. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_create_important_test_data.py +0 -0
  562. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_filters_navigation_buttons.py +0 -0
  563. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_sections_and_flows.py +0 -0
  564. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_tracks_add_and_display.py +0 -0
  565. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/acceptance/test_video_import_and_display.py +0 -0
  566. {otanalytics-0.7.4/tests/unit/OTAnalytics/application/analysis → otanalytics-0.7.5/tests/benchmark}/__init__.py +0 -0
  567. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/conftest.py +0 -0
  568. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Sample_FR20_2020-01-01_00-00-00.ottrk +0 -0
  569. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.mp4 +0 -0
  570. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otconfig +0 -0
  571. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.otflow +0 -0
  572. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Cyclist_FR20_2020-01-01_00-00-00.ottrk +0 -0
  573. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.mp4 +0 -0
  574. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/Testvideo_Cars-Truck_FR20_2020-01-01_00-00-00.ottrk +0 -0
  575. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/all_tracks.png +0 -0
  576. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/highlight_tracks_assigned_to_flows.png +0 -0
  577. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/highlight_tracks_intersecting_sections.png +0 -0
  578. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/highlight_tracks_not_assigned_to_flows.png +0 -0
  579. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/highlight_tracks_not_intersecting_sections.png +0 -0
  580. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/offset_before.png +0 -0
  581. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/start_end_all.png +0 -0
  582. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/start_end_assigned_to_flows.png +0 -0
  583. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/start_end_intersecting_sections.png +0 -0
  584. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/start_end_not_assigned_to_flows.png +0 -0
  585. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/acceptance/start_end_not_intersecting_sections.png +0 -0
  586. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/cyclists_2025-12-19_10-18-43.otconfig +0 -0
  587. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/section.json.bz2.otflow +0 -0
  588. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/sections_created_test_file.otconfig +0 -0
  589. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/test_name.otconfig +0 -0
  590. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/data/trucks_2025-12-19_10-19-22.otconfig +0 -0
  591. {otanalytics-0.7.4/tests/unit/OTAnalytics/application/resources → otanalytics-0.7.5/tests/integration/OTAnalytics}/__init__.py +0 -0
  592. {otanalytics-0.7.4/tests/unit/OTAnalytics/application/ui → otanalytics-0.7.5/tests/integration/OTAnalytics/plugin_s3}/__init__.py +0 -0
  593. {otanalytics-0.7.4/tests/unit/OTAnalytics/application/use_cases → otanalytics-0.7.5/tests/integration}/__init__.py +0 -0
  594. {otanalytics-0.7.4/tests/unit/OTAnalytics/domain → otanalytics-0.7.5/tests/regression}/__init__.py +0 -0
  595. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/regression/test_regression_otanalytics.py +0 -0
  596. {otanalytics-0.7.4/tests/unit/OTAnalytics/domain/track_dataset → otanalytics-0.7.5/tests/system/OTAnalytics}/__init__.py +0 -0
  597. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_datastore → otanalytics-0.7.5/tests/system/OTAnalytics/plugin_ui}/__init__.py +0 -0
  598. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_datastore/track_geometry_store → otanalytics-0.7.5/tests/system}/__init__.py +0 -0
  599. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_filter → otanalytics-0.7.5/tests/unit/OTAnalytics}/__init__.py +0 -0
  600. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_intersect → otanalytics-0.7.5/tests/unit/OTAnalytics/adapter_intersect}/__init__.py +0 -0
  601. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/adapter_intersect/test_mapping.py +0 -0
  602. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_intersect/shapely → otanalytics-0.7.5/tests/unit/OTAnalytics/application}/__init__.py +0 -0
  603. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_intersect/simple → otanalytics-0.7.5/tests/unit/OTAnalytics/application/analysis}/__init__.py +0 -0
  604. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/analysis/test_road_user_assignment.py +0 -0
  605. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_intersect_parallelization → otanalytics-0.7.5/tests/unit/OTAnalytics/application/parser}/__init__.py +0 -0
  606. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated → otanalytics-0.7.5/tests/unit/OTAnalytics/application/resources}/__init__.py +0 -0
  607. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/resources/test_resource_manager.py +0 -0
  608. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_helpers.py +0 -0
  609. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_plotting.py +0 -0
  610. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_project.py +0 -0
  611. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_state.py +0 -0
  612. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/test_track_filter.py +0 -0
  613. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz → otanalytics-0.7.5/tests/unit/OTAnalytics/application/ui}/__init__.py +0 -0
  614. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/ui/test_frame_control.py +0 -0
  615. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_parser → otanalytics-0.7.5/tests/unit/OTAnalytics/application/use_cases}/__init__.py +0 -0
  616. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_apply_cli_cuts.py +0 -0
  617. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_clear_repositories.py +0 -0
  618. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_create_events.py +0 -0
  619. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_create_intersection_events.py +0 -0
  620. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_event_repository.py +0 -0
  621. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_filter_visualization.py +0 -0
  622. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_flows_statistics.py +0 -0
  623. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_generate_flows.py +0 -0
  624. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_get_current_project.py +0 -0
  625. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_get_road_user_assignments.py +0 -0
  626. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_highlight_intersections.py +0 -0
  627. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_inside_cutting_section.py +0 -0
  628. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_intersection_repository.py +0 -0
  629. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_preload_input_files.py +0 -0
  630. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_reset_application.py +0 -0
  631. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_reset_project_config.py +0 -0
  632. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_revert_cuts.py +0 -0
  633. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_save_otflow.py +0 -0
  634. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_section_repository.py +0 -0
  635. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_start_new_project.py +0 -0
  636. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_track_repository.py +0 -0
  637. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_track_statistics.py +0 -0
  638. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_track_statistics_export.py +0 -0
  639. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_update_count_plots.py +0 -0
  640. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_update_project.py +0 -0
  641. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/application/use_cases/test_video_repository.py +0 -0
  642. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_progress → otanalytics-0.7.5/tests/unit/OTAnalytics/domain}/__init__.py +0 -0
  643. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_date.py +0 -0
  644. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_files.py +0 -0
  645. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_filter.py +0 -0
  646. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_flow.py +0 -0
  647. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_geometry.py +0 -0
  648. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_observer.py +0 -0
  649. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_section.py +0 -0
  650. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_track_repository.py +0 -0
  651. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/test_video.py +0 -0
  652. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_prototypes → otanalytics-0.7.5/tests/unit/OTAnalytics/domain/track_dataset}/__init__.py +0 -0
  653. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/track_dataset/conftest.py +0 -0
  654. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/domain/track_dataset/test_track_dataset.py +0 -0
  655. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_prototypes/track_visualization → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_cli}/__init__.py +0 -0
  656. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_ui → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_datastore}/__init__.py +0 -0
  657. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_datastore/test_filter_pandas_track_store.py +0 -0
  658. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_ui/visualization → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_datastore/track_geometry_store}/__init__.py +0 -0
  659. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_datastore/track_geometry_store/test_shapely_store.py +0 -0
  660. {otanalytics-0.7.4/tests/unit/OTAnalytics/plugin_ui/visualization/counts → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_filter}/__init__.py +0 -0
  661. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_filter/test_dataframe_filter.py +0 -0
  662. {otanalytics-0.7.4/tests/unit → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_intersect}/__init__.py +0 -0
  663. {otanalytics-0.7.4/tests/utils → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_intersect/shapely}/__init__.py +0 -0
  664. {otanalytics-0.7.4/tests/utils/builders → otanalytics-0.7.5/tests/unit/OTAnalytics/plugin_intersect/simple}/__init__.py +0 -0
  665. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_intersect/simple/test_cut_tracks_with_sections.py +0 -0
  666. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_intersect/test_intersect.py +0 -0
  667. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_intersect_parallelization/test_multiprocessing.py +0 -0
  668. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_intersect_parallelization/test_sequential.py +0 -0
  669. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/conftest.py +0 -0
  670. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/svz/test_number_of_tracks_to_be_validated.py +0 -0
  671. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/test_calculation_strategy.py +0 -0
  672. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_number_of_tracks_to_be_validated/test_tracks_as_dataframe_provider.py +0 -0
  673. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_argparse_cli_parser.py +0 -0
  674. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_json_parser.py +0 -0
  675. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_parser/test_streaming_parser.py +0 -0
  676. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_progress/test_multiprocessing_progress.py +0 -0
  677. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_prototypes/track_visualization/test_track_viz.py +0 -0
  678. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/conftest.py +0 -0
  679. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/dialogs/test_file_extension_filtering.py +0 -0
  680. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/dialogs/test_file_picker.py +0 -0
  681. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/test_circle.py +0 -0
  682. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/test_line.py +0 -0
  683. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/nicegui/svg/test_polyline.py +0 -0
  684. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/nicegui_gui/pages/canvas_and_files_form/test_canvas_form.py +0 -0
  685. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_edit_flow_dialog.py +0 -0
  686. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_edit_section_dialog.py +0 -0
  687. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_flow_form.py +0 -0
  688. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_intersection_repository.py +0 -0
  689. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_sections_form.py +0 -0
  690. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_ui/test_svz_metadata_form.py +0 -0
  691. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/unit/OTAnalytics/plugin_video_processing/test_video_reader.py +0 -0
  692. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/assertions.py +0 -0
  693. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/constants.py +0 -0
  694. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/otanalytics_builders.py +0 -0
  695. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/ottrk_file_input_source.py +0 -0
  696. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/run_configuration.py +0 -0
  697. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/track_dataset_provider.py +0 -0
  698. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/builders/track_segment_builder.py +0 -0
  699. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/state.py +0 -0
  700. {otanalytics-0.7.4 → otanalytics-0.7.5}/tests/utils/ui_helpers.py +0 -0
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: System Test With Pytest
3
+
4
+ on:
5
+ # Run tests each time a PR is opened or changed.
6
+ # Allow other Workflows (e.g., build workflows) to call this workflow.
7
+ pull_request:
8
+ workflow_call:
9
+
10
+ permissions: read-all
11
+
12
+ jobs:
13
+ test:
14
+ name: Execute system tests across various operating systems and Python versions.
15
+ strategy:
16
+ matrix:
17
+ os: [ubuntu-latest, windows-latest]
18
+ py: ["3.12"]
19
+ fail-fast: true
20
+ runs-on: ${{ matrix.os }}
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v6
24
+ - name: Set up Python ${{ matrix.py }}
25
+ uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.py }}
28
+ - name: Run Python System Tests
29
+ uses: platomo/test-python-app-action@v4
30
+ timeout-minutes: 60
31
+ with:
32
+ py-version: ${{ matrix.py }}
33
+ package-path: OTAnalytics
34
+ test-path: tests/system
@@ -25,7 +25,7 @@ jobs:
25
25
  uses: actions/setup-python@v6
26
26
  with:
27
27
  python-version: ${{ matrix.py }}
28
- - name: Run Python Tests
28
+ - name: Run Python Unit Tests
29
29
  uses: platomo/test-python-app-action@v4
30
30
  timeout-minutes: 60
31
31
  with:
@@ -3,6 +3,12 @@ data/
3
3
  !tests/data
4
4
  tests/data/OTCamera19_FR20_2023-05-24*
5
5
  tests/scripts/
6
+ .envrc
7
+ # Where S3_USER_SOURCE stages downloaded tracks and videos while running
8
+ .cache-otanalytics/
9
+
10
+ # Anthropic Claude
11
+ .claude/rules/shared
6
12
 
7
13
  # Byte-compiled / optimized / DLL files
8
14
  __pycache__/
@@ -47,6 +47,7 @@ repos:
47
47
  - interrogate==1.7.0
48
48
  - isort==6.0.1
49
49
  - matplotlib==3.10.0
50
+ - minio==7.2.20
50
51
  - more-itertools==10.7.0
51
52
  - mypy==1.16.1
52
53
  - nicegui==2.24.1
@@ -66,8 +67,11 @@ repos:
66
67
  - pytest-timeout==2.4.0
67
68
  - pytest==8.3.4
68
69
  - starlette==0.49.1
70
+ - testcontainers==4.13.1
69
71
  - twine==6.2.0
70
72
  - types-PyYAML
73
+ - types-aioboto3
74
+ - types-aiobotocore-s3==2.26.0
71
75
  - types-flake8
72
76
  - types-openpyxl
73
77
  - types-pillow
@@ -0,0 +1,56 @@
1
+ # OTAnalytics
2
+
3
+ Traffic analysis on road user trajectories: OTAnalytics loads Tracks recorded by
4
+ OTVision, lets a user define Sections and Flows over them, and counts the road
5
+ users crossing those Sections.
6
+
7
+ ## Language
8
+
9
+ ### Obtaining input files
10
+
11
+ **Transfer Mode**:
12
+ Where an OTAnalytics instance obtains its Track and Video files — the local
13
+ filesystem, or an S3 bucket. Fixed for the lifetime of the process by the
14
+ startup configuration; it is not something a user switches while working.
15
+ _Avoid_: storage backend, data source (both suggest a per-load choice).
16
+
17
+ **Startup Configuration**:
18
+ The environment variables naming the Transfer Mode and, in S3 mode, the bucket
19
+ and credentials. Fixed for the lifetime of the process. Deliberately not a file.
20
+ Says what a deployment may authenticate to, never which project it holds: the
21
+ Key Prefix comes from the **otconfig** instead, because that is per-project and
22
+ varies per lease. Credentials must never travel in an otconfig, since users save
23
+ and share those files.
24
+ _Avoid_: config file (there isn't one, and it invites confusion with otconfig).
25
+
26
+ **Key Prefix**:
27
+ The S3 prefix a project's Tracks and Videos live under, covering one camera or
28
+ site. A property of the project, declared by its otconfig, and required there in
29
+ S3 mode — so opening a different project moves where an instance reads from,
30
+ within the one configured bucket. Until a project is loaded there is no Key
31
+ Prefix and nothing can be listed.
32
+ _Avoid_: path, folder (S3 has neither); startup configuration (it is per-project,
33
+ unlike the bucket and credentials).
34
+
35
+ **User Source**:
36
+ The local directory that downloaded objects are written into, mirroring their S3
37
+ keys, so that a Track file and its Video land side by side. Named after
38
+ OTCloud's `S3_USER_SOURCE` for cross-repo consistency, though the name conveys
39
+ little on its own. Its contents do not survive a restart.
40
+ _Avoid_: cache (implies reuse across runs, which there is none of).
41
+
42
+ **Load Window**:
43
+ The start and end time a user selects to decide which Tracks and Videos to load.
44
+ Bounded by a configured maximum duration, because continuous processing produces
45
+ far more data than can be held at once. An over-long selection is _clamped_ —
46
+ its end snaps to the maximum and the user is told — never rejected.
47
+ _Avoid_: time range, date range (`DateRange` already means the filter applied to
48
+ already-loaded Tracks, which is a different thing).
49
+
50
+ **Track File Provider** / **Video File Provider**:
51
+ What a request for input files is asked of. Each implementation owns its own way
52
+ of asking the user, so nothing downstream knows where files came from: the local
53
+ one opens a file chooser, the S3 one asks for a Load Window and downloads. This
54
+ is the seam that makes the Transfer Mode interchangeable.
55
+ _Avoid_: file loader, importer (both suggest they also parse, which they do not —
56
+ they only obtain paths).
@@ -3,7 +3,7 @@ import functools
3
3
  from datetime import datetime
4
4
  from pathlib import Path
5
5
  from time import sleep
6
- from typing import Any, Dict, Iterable, List, Optional
6
+ from typing import Any, Iterable, Optional, Sequence
7
7
 
8
8
  from OTAnalytics.adapter_ui.abstract_button_quick_save_config import (
9
9
  AbstractButtonQuickSaveConfig,
@@ -33,6 +33,7 @@ from OTAnalytics.adapter_ui.default_values import (
33
33
  RELATIVE_SECTION_OFFSET,
34
34
  SUPPORTED_FORMATS,
35
35
  )
36
+ from OTAnalytics.adapter_ui.file_export_dto import ExportFileDto
36
37
  from OTAnalytics.adapter_ui.flow_adapter import (
37
38
  GeometricCenterCalculator,
38
39
  InnerSegmentsCenterCalculator,
@@ -61,6 +62,7 @@ from OTAnalytics.application.application import (
61
62
  )
62
63
  from OTAnalytics.application.config import (
63
64
  CONTEXT_FILE_TYPE_EVENTS,
65
+ CONTEXT_FILE_TYPE_ROAD_USER_ASSIGNMENTS,
64
66
  CONTEXT_FILE_TYPE_TRACK_STATISTICS,
65
67
  CUTTING_SECTION_MARKER,
66
68
  OTCONFIG_FILE_TYPE,
@@ -68,7 +70,10 @@ from OTAnalytics.application.config import (
68
70
  )
69
71
  from OTAnalytics.application.export_formats.export_mode import OVERWRITE
70
72
  from OTAnalytics.application.logger import logger
71
- from OTAnalytics.application.parser.config_parser import StartDateMissing
73
+ from OTAnalytics.application.parser.config_parser import (
74
+ StartDateMissing,
75
+ SubstitutedFile,
76
+ )
72
77
  from OTAnalytics.application.parser.flow_parser import FlowParser
73
78
  from OTAnalytics.application.playback import SkipTime
74
79
  from OTAnalytics.application.project import (
@@ -88,6 +93,7 @@ from OTAnalytics.application.project import (
88
93
  SvzMetadata,
89
94
  WeatherType,
90
95
  )
96
+ from OTAnalytics.application.project_location import UnsupportedProjectLocation
91
97
  from OTAnalytics.application.use_cases.config import ConfigValidationError
92
98
  from OTAnalytics.application.use_cases.config_has_changed import NoExistingConfigFound
93
99
  from OTAnalytics.application.use_cases.cut_tracks_with_sections import CutTracksDto
@@ -97,11 +103,17 @@ from OTAnalytics.application.use_cases.editor.section_editor import (
97
103
  UpdateSectionCoordinates,
98
104
  )
99
105
  from OTAnalytics.application.use_cases.export_events import (
106
+ EventExportSpecification,
100
107
  EventListExporter,
101
108
  ExporterNotFoundError,
102
109
  )
103
110
  from OTAnalytics.application.use_cases.flow_repository import FlowAlreadyExists
104
111
  from OTAnalytics.application.use_cases.generate_flows import FlowNameGenerator
112
+ from OTAnalytics.application.use_cases.load_otconfig import UnableToLoadOtconfigFile
113
+ from OTAnalytics.application.use_cases.provide_input_files import (
114
+ ProvideTrackFiles,
115
+ ProvideVideoFiles,
116
+ )
105
117
  from OTAnalytics.application.use_cases.quick_save_configuration import (
106
118
  NoExistingFileToSave,
107
119
  )
@@ -109,6 +121,7 @@ from OTAnalytics.application.use_cases.road_user_assignment_export import (
109
121
  ExportSpecification,
110
122
  )
111
123
  from OTAnalytics.application.use_cases.save_otflow import NoSectionsToSave
124
+ from OTAnalytics.application.use_cases.suggest_save_path import SavePathSuggestion
112
125
  from OTAnalytics.application.use_cases.track_statistics_export import (
113
126
  TrackStatisticsExportSpecification,
114
127
  )
@@ -140,12 +153,27 @@ from OTAnalytics.domain.types import EventType
140
153
  from OTAnalytics.domain.video import Video, VideoListObserver
141
154
 
142
155
  MESSAGE_CONFIGURATION_NOT_SAVED = "The configuration has not been saved.\n"
143
- SUPPORTED_VIDEO_FILE_TYPES = [".mp4", ".avi", ".mkv", ".mov"]
156
+ MESSAGE_CONFIGURATION_NOT_LOADED = "The configuration has not been loaded.\n"
157
+ MESSAGE_CONFIGURATION_FILES_SUBSTITUTED = (
158
+ "The configuration references files that were not found.\n"
159
+ )
144
160
  LINE_SECTION: str = "line_section"
145
161
  TO_SECTION = "to_section"
146
162
  FROM_SECTION = "from_section"
147
163
 
148
164
 
165
+ def _explain(cause: BaseException) -> str:
166
+ """Name the underlying failure, not the wrapper.
167
+
168
+ `UnableToLoadOtconfigFile` carries a fixed string and keeps the real reason
169
+ in `__cause__`, so reporting the wrapper alone tells the user nothing they
170
+ can act on.
171
+ """
172
+ if cause.__cause__ is not None:
173
+ return f"{cause} {cause.__cause__}"
174
+ return f"{cause}"
175
+
176
+
149
177
  class MissingInjectedInstanceError(Exception):
150
178
  """Raise when no instance of an object was injected before referencing it"""
151
179
 
@@ -310,9 +338,13 @@ class DummyViewModel(
310
338
  show_svz: bool,
311
339
  add_new_section: AddNewSection,
312
340
  update_section_coordinates: UpdateSectionCoordinates,
341
+ provide_track_files: ProvideTrackFiles,
342
+ provide_video_files: ProvideVideoFiles,
313
343
  ) -> None:
314
344
  self._application = application
315
345
  self._ui_factory = ui_factory
346
+ self._provide_track_files = provide_track_files
347
+ self._provide_video_files = provide_video_files
316
348
  self._flow_parser: FlowParser = flow_parser
317
349
  self._name_generator = name_generator
318
350
  self._event_list_export_formats = event_list_export_formats
@@ -553,24 +585,7 @@ class DummyViewModel(
553
585
  self._update_enabled_video_buttons()
554
586
 
555
587
  async def add_video(self) -> None:
556
- # Generate extension_options dynamically from SUPPORTED_VIDEO_FILE_TYPES
557
- extension_options: Dict[str, Optional[List[str]]] = {}
558
-
559
- # Convert "*.ext" format to ".ext" format for extension_options
560
- clean_extensions = [ext for ext in SUPPORTED_VIDEO_FILE_TYPES]
561
-
562
- # Add "All File Endings" option with all supported extensions
563
- extension_options["All File Endings"] = clean_extensions
564
-
565
- # Add individual extension options
566
- for ext in clean_extensions:
567
- extension_options[ext] = [ext]
568
-
569
- video_files = await self._ui_factory.askopenfilenames(
570
- title="Load video files",
571
- filetypes=[("video file", SUPPORTED_VIDEO_FILE_TYPES)],
572
- extension_options=extension_options,
573
- )
588
+ video_files = await self._provide_video_files.provide()
574
589
  if not video_files:
575
590
  return
576
591
  logger().info(f"Video files to load: {video_files}")
@@ -611,19 +626,25 @@ class DummyViewModel(
611
626
  self.frame_project.update(name=project.name, start_date=project.start_date)
612
627
 
613
628
  async def save_otconfig(self) -> None:
614
- suggested_save_path = self._application.suggest_save_path(OTCONFIG_FILE_TYPE)
629
+ save_suggestion = self._application.suggest_save_path(OTCONFIG_FILE_TYPE)
630
+ if self._application.get_current_key_prefix() is not None:
631
+ # A project that names a location was opened by an operator naming
632
+ # it, not chosen from a picker (OP#10323 decision 1), so it always
633
+ # re-saves to its own name and place with no new UI.
634
+ await self._save_otconfig(save_suggestion.file_path)
635
+ return
615
636
  configuration_file = await self._ui_factory.ask_for_save_file_path(
616
637
  title="Save configuration as",
617
638
  filetypes=[(f"{OTCONFIG_FILE_TYPE} file", f"*.{OTCONFIG_FILE_TYPE}")],
618
639
  defaultextension=f".{OTCONFIG_FILE_TYPE}",
619
- initialfile=suggested_save_path.name,
620
- initialdir=suggested_save_path.parent,
640
+ initialfile=save_suggestion.file_path.name,
641
+ initialdir=save_suggestion.save_directory,
621
642
  )
622
643
  if not configuration_file:
623
644
  return
624
- self._save_otconfig(configuration_file)
645
+ await self._save_otconfig(configuration_file)
625
646
 
626
- def _save_otconfig(self, otconfig_file: Path) -> None:
647
+ async def _save_otconfig(self, otconfig_file: Path) -> None:
627
648
  # Ensure the file has the correct extension
628
649
  otconfig_file_str = ensure_file_extension_is_present(
629
650
  str(otconfig_file), [f"*.{OTCONFIG_FILE_TYPE}"], f".{OTCONFIG_FILE_TYPE}"
@@ -632,7 +653,7 @@ class DummyViewModel(
632
653
 
633
654
  logger().info(f"Config file to save: {otconfig_file}")
634
655
  try:
635
- self._application.save_otconfig(otconfig_file)
656
+ await self._application.save_otconfig(otconfig_file)
636
657
  except NoSectionsToSave:
637
658
  message = (
638
659
  f"{MESSAGE_CONFIGURATION_NOT_SAVED}"
@@ -692,9 +713,9 @@ class DummyViewModel(
692
713
  )
693
714
  if not otconfig_file:
694
715
  return
695
- self._load_otconfig(otconfig_file)
716
+ await self._load_otconfig(otconfig_file)
696
717
 
697
- def _load_otconfig(self, otconfig_file: Path) -> None:
718
+ async def _load_otconfig(self, otconfig_file: Path) -> None:
698
719
  proceed = self._ui_factory.info_box(
699
720
  message=(
700
721
  "This will load a stored configuration from file. \n"
@@ -707,10 +728,73 @@ class DummyViewModel(
707
728
  if proceed.canceled:
708
729
  return
709
730
  logger().info(f"{OTCONFIG_FILE_TYPE} file to load: {otconfig_file}")
710
- self._application.load_otconfig(file=Path(otconfig_file))
731
+ try:
732
+ await self._application.load_otconfig_async(file=Path(otconfig_file))
733
+ except (
734
+ UnableToLoadOtconfigFile,
735
+ UnsupportedProjectLocation,
736
+ OSError,
737
+ ) as cause:
738
+ # A file the config references is missing, the config contradicts
739
+ # itself, or its data lives where this installation cannot read it.
740
+ # All are the user's to act on, so name the cause.
741
+ self._report_load_failure(_explain(cause))
742
+ return
743
+ except Exception as cause:
744
+ # The boundary of a user action: without this, a malformed config
745
+ # reaches the browser as a traceback. The traceback still logs.
746
+ logger().exception("Failed to load configuration file", exc_info=cause)
747
+ self._report_load_failure("An unexpected error occurred.")
748
+ return
711
749
  self.show_current_project()
712
750
  self.update_svz_metadata_view()
713
751
 
752
+ def report_substituted_files(
753
+ self, substitutions: Sequence[SubstitutedFile]
754
+ ) -> None:
755
+ """Tell the user which references were rebound while loading.
756
+
757
+ The parser resolves a missing reference to a same-named file beside the
758
+ otconfig. The names match but the contents need not: re-detected or
759
+ re-tracked output reuses the filename with different detections. So the
760
+ project is loaded, and the user is told what it actually holds.
761
+ """
762
+ if not substitutions:
763
+ return
764
+ rebound = "\n".join(
765
+ f"• '{substitution.requested}' → '{substitution.used}'"
766
+ for substitution in substitutions
767
+ )
768
+ self._tell_user(
769
+ f"{MESSAGE_CONFIGURATION_FILES_SUBSTITUTED}"
770
+ f"The files below were not found where the configuration says, so a "
771
+ f"file of the same name next to the configuration was loaded "
772
+ f"instead. Check that this is the data you meant:\n{rebound}"
773
+ )
774
+
775
+ def _report_load_failure(self, reason: str) -> None:
776
+ self._tell_user(f"{MESSAGE_CONFIGURATION_NOT_LOADED}{reason}")
777
+
778
+ def _tell_user(self, message: str) -> None:
779
+ """Log a message and show it if the ui can be reached.
780
+
781
+ Reporting must never break what it reports on. Nicegui resolves the
782
+ client through the slot stack and raises when that stack is empty, so
783
+ `info_box` fails whenever no browser is attached — during the startup
784
+ preload of a `--config` file, for one. Left unguarded, reporting a
785
+ substitution there would propagate out of the parse and stop the server
786
+ from starting. The log is the guarantee; the box is best effort.
787
+ """
788
+ logger().warning(message)
789
+ try:
790
+ self._ui_factory.info_box(
791
+ message=message, initial_position=self._get_window_position()
792
+ )
793
+ except Exception as cause:
794
+ logger().exception(
795
+ "Could not show this message to the user", exc_info=cause
796
+ )
797
+
714
798
  def set_tracks_frame(self, frame: AbstractFrame) -> None:
715
799
  self._frame_tracks = frame
716
800
 
@@ -815,17 +899,11 @@ class DummyViewModel(
815
899
 
816
900
  @action
817
901
  async def load_tracks(self) -> None:
818
- track_files = await self._ui_factory.askopenfilenames(
819
- title="Load track files",
820
- filetypes=[
821
- ("tracks file", "*.ottrk"),
822
- ],
823
- )
902
+ track_files = await self._provide_track_files.provide()
824
903
  if not track_files:
825
904
  return
826
905
  logger().info(f"Tracks files to load: {track_files}")
827
- track_paths = [Path(file) for file in track_files]
828
- self._application.add_tracks_of_files(track_files=track_paths)
906
+ await self._application.add_tracks_of_files_async(track_files=track_files)
829
907
 
830
908
  async def load_configuration(self) -> None: # sourcery skip: avoid-builtin-shadow
831
909
  # INFO: Current behavior: Overwrites existing sections
@@ -844,7 +922,7 @@ class DummyViewModel(
844
922
  elif configuration_file.suffix == f".{OTFLOW_FILE_TYPE}":
845
923
  self._load_otflow(configuration_file)
846
924
  elif configuration_file.suffix == f".{OTCONFIG_FILE_TYPE}":
847
- self._load_otconfig(configuration_file)
925
+ await self._load_otconfig(configuration_file)
848
926
  else:
849
927
  raise ValueError("Configuration file to load has unknown file extension")
850
928
 
@@ -870,7 +948,13 @@ class DummyViewModel(
870
948
  self.refresh_items_on_canvas()
871
949
 
872
950
  async def save_configuration(self) -> None:
873
- suggested_save_path = self._application.suggest_save_path(OTCONFIG_FILE_TYPE)
951
+ save_suggestion = self._application.suggest_save_path(OTCONFIG_FILE_TYPE)
952
+ if self._application.get_current_key_prefix() is not None:
953
+ # A project that names a location is always an otconfig and always
954
+ # re-saves to its own name and place with no new UI (OP#10323
955
+ # decision 1 & 5).
956
+ await self._save_otconfig(save_suggestion.file_path)
957
+ return
874
958
  configuration_file = await self._ui_factory.ask_for_save_file_path(
875
959
  title="Save configuration as",
876
960
  filetypes=[
@@ -878,8 +962,8 @@ class DummyViewModel(
878
962
  (f"{OTFLOW_FILE_TYPE} file", f"*.{OTFLOW_FILE_TYPE}"),
879
963
  ],
880
964
  defaultextension=f".{OTCONFIG_FILE_TYPE}",
881
- initialfile=suggested_save_path.name,
882
- initialdir=suggested_save_path.parent,
965
+ initialfile=save_suggestion.file_path.name,
966
+ initialdir=save_suggestion.save_directory,
883
967
  )
884
968
  if not configuration_file.stem:
885
969
  return
@@ -895,13 +979,13 @@ class DummyViewModel(
895
979
  if configuration_file.suffix == f".{OTFLOW_FILE_TYPE}":
896
980
  self._save_otflow(configuration_file)
897
981
  elif configuration_file.suffix == f".{OTCONFIG_FILE_TYPE}":
898
- self._save_otconfig(configuration_file)
982
+ await self._save_otconfig(configuration_file)
899
983
  else:
900
984
  raise ValueError("Configuration file to save has unknown file extension")
901
985
 
902
986
  async def quick_save_configuration(self) -> None:
903
987
  try:
904
- self._application.quick_save_configuration()
988
+ await self._application.quick_save_configuration()
905
989
  except NoExistingFileToSave:
906
990
  await self.save_configuration()
907
991
 
@@ -1389,33 +1473,40 @@ class DummyViewModel(
1389
1473
  for key, exporter in self._event_list_export_formats.items()
1390
1474
  }
1391
1475
  try:
1392
- event_list_exporter, file = await self._configure_event_exporter(
1476
+ event_list_exporter, export_config = await self._configure_event_exporter(
1393
1477
  export_format_extensions
1394
1478
  )
1395
- self._application.export_events(Path(file), event_list_exporter)
1479
+ specification = EventExportSpecification(
1480
+ export_directory=export_config.export_directory,
1481
+ export_filename_stem=export_config.file_stem,
1482
+ export_mode=OVERWRITE,
1483
+ )
1484
+ self._application.export_events(specification, event_list_exporter)
1396
1485
  logger().info(
1397
- f"Exporting eventlist using {event_list_exporter.get_name()} to {file}"
1486
+ f"Exporting eventlist using {event_list_exporter.get_name()} to "
1487
+ f"{export_config.as_file_path()}"
1398
1488
  )
1399
1489
  except CancelExportFile:
1400
1490
  logger().info("User canceled configuration of export")
1401
1491
 
1402
1492
  async def _configure_event_exporter(
1403
1493
  self, export_format_extensions: dict[str, str]
1404
- ) -> tuple[EventListExporter, Path]:
1494
+ ) -> tuple[EventListExporter, ExportFileDto]:
1405
1495
  export_config = await self._ui_factory.configure_export_file(
1406
1496
  title="Export events",
1407
1497
  export_format_extensions=export_format_extensions,
1408
- initial_file_stem=CONTEXT_FILE_TYPE_EVENTS,
1498
+ context_file_type=CONTEXT_FILE_TYPE_EVENTS,
1409
1499
  viewmodel=self,
1410
1500
  )
1411
- file = export_config.file
1412
- export_format = export_config.export_format
1413
- event_list_exporter = self._event_list_export_formats.get(export_format, None)
1501
+ event_list_exporter = self._event_list_export_formats.get(
1502
+ export_config.export_format, None
1503
+ )
1414
1504
  if event_list_exporter is None:
1415
1505
  raise ExporterNotFoundError(
1416
1506
  f"{event_list_exporter} is not a valid export format"
1417
1507
  )
1418
- return event_list_exporter, file
1508
+
1509
+ return event_list_exporter, export_config
1419
1510
 
1420
1511
  def set_track_offset(self, offset_x: float, offset_y: float) -> None:
1421
1512
  start_msg_popup = self._ui_factory.minimal_info_box(
@@ -1697,18 +1788,20 @@ class DummyViewModel(
1697
1788
  export_config = await self._ui_factory.configure_export_file(
1698
1789
  title="Export road user assignments",
1699
1790
  export_format_extensions=export_formats,
1700
- initial_file_stem="road_user_assignments",
1791
+ context_file_type=CONTEXT_FILE_TYPE_ROAD_USER_ASSIGNMENTS,
1701
1792
  viewmodel=self,
1702
1793
  )
1703
1794
  logger().debug(export_config)
1704
- save_path = export_config.file
1705
- export_format = export_config.export_format
1706
-
1707
1795
  export_specification = ExportSpecification(
1708
- save_path, export_format, OVERWRITE
1796
+ export_directory=export_config.export_directory,
1797
+ export_filename_stem=export_config.file_stem,
1798
+ format=export_config.export_format,
1799
+ export_mode=OVERWRITE,
1709
1800
  )
1710
1801
  self._application.export_road_user_assignments(export_specification)
1711
- logger().info(f"Exporting road user assignments to {save_path}")
1802
+ logger().info(
1803
+ f"Exporting road user assignments to {export_config.as_file_path()}"
1804
+ )
1712
1805
  except CancelExportFile:
1713
1806
  logger().info("User canceled configuration of export")
1714
1807
 
@@ -1776,7 +1869,9 @@ class DummyViewModel(
1776
1869
  def update_remark_view(self, _: Any = None) -> None:
1777
1870
  self.frame_remark.load_remark()
1778
1871
 
1779
- def get_save_path_suggestion(self, file_type: str, context_file_type: str) -> Path:
1872
+ def get_save_path_suggestion(
1873
+ self, file_type: str, context_file_type: str
1874
+ ) -> SavePathSuggestion:
1780
1875
  return self._application.suggest_save_path(file_type, context_file_type)
1781
1876
 
1782
1877
  def set_frame_track_statistics(self, frame: AbstractFrameTrackStatistics) -> None:
@@ -1808,17 +1903,19 @@ class DummyViewModel(
1808
1903
  export_config = await self._ui_factory.configure_export_file(
1809
1904
  title="Export track statistics",
1810
1905
  export_format_extensions=export_formats,
1811
- initial_file_stem=CONTEXT_FILE_TYPE_TRACK_STATISTICS,
1906
+ context_file_type=CONTEXT_FILE_TYPE_TRACK_STATISTICS,
1812
1907
  viewmodel=self,
1813
1908
  )
1814
1909
  logger().debug(export_config)
1815
- save_path = export_config.file
1816
- export_format = export_config.export_format
1817
-
1818
1910
  export_specification = TrackStatisticsExportSpecification(
1819
- save_path, export_format, OVERWRITE
1911
+ export_directory=export_config.export_directory,
1912
+ export_filename_stem=export_config.file_stem,
1913
+ format=export_config.export_format,
1914
+ export_mode=OVERWRITE,
1915
+ )
1916
+ destination = self._application.export_track_statistics(
1917
+ export_specification
1820
1918
  )
1821
- self._application.export_track_statistics(export_specification)
1822
- logger().info(f"Exporting track statistics to {save_path}")
1919
+ logger().info(f"Exporting track statistics to {destination}")
1823
1920
  except CancelExportFile:
1824
1921
  logger().info("User canceled configuration of export")
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class ExportFileDto:
7
+ """
8
+ Data transfer object for file export information.
9
+
10
+ Attributes:
11
+ export_directory (Path): The directory where the file will be exported.
12
+ file_stem (str): The stem of the file name (without extension).
13
+ export_format (str): The format of the exported file. The file extension.
14
+ """
15
+
16
+ export_directory: Path
17
+ file_stem: str
18
+ export_format_extension: str
19
+ export_format: str
20
+
21
+ @classmethod
22
+ def from_file_path(cls, file_path: Path, export_format: str) -> "ExportFileDto":
23
+ return cls(
24
+ export_directory=file_path.parent,
25
+ file_stem=file_path.stem,
26
+ export_format_extension=file_path.suffix,
27
+ export_format=export_format,
28
+ )
29
+
30
+ def as_file_path(self) -> Path:
31
+ return self.export_directory / f"{self.file_stem}{self.export_format_extension}"
@@ -0,0 +1,57 @@
1
+ """Local-filesystem implementations of the input file providers."""
2
+
3
+ from pathlib import Path
4
+
5
+ from OTAnalytics.adapter_ui.ui_factory import UiFactory
6
+ from OTAnalytics.application.config import SUPPORTED_VIDEO_FILE_TYPES
7
+ from OTAnalytics.application.use_cases.provide_input_files import (
8
+ ProvideTrackFiles,
9
+ ProvideVideoFiles,
10
+ )
11
+
12
+ ALL_FILE_ENDINGS = "All File Endings"
13
+
14
+
15
+ class LocalTrackFileProvider(ProvideTrackFiles):
16
+ """Asks the user to pick ottrk files from the local filesystem.
17
+
18
+ Args:
19
+ ui_factory (UiFactory): builds the file chooser for the active front-end.
20
+ """
21
+
22
+ def __init__(self, ui_factory: UiFactory) -> None:
23
+ self._ui_factory = ui_factory
24
+
25
+ async def provide(self) -> list[Path]:
26
+ return await self._ui_factory.askopenfilenames(
27
+ title="Load track files",
28
+ filetypes=[("tracks file", "*.ottrk")],
29
+ )
30
+
31
+
32
+ class LocalVideoFileProvider(ProvideVideoFiles):
33
+ """Asks the user to pick video files from the local filesystem.
34
+
35
+ Args:
36
+ ui_factory (UiFactory): builds the file chooser for the active front-end.
37
+ """
38
+
39
+ def __init__(self, ui_factory: UiFactory) -> None:
40
+ self._ui_factory = ui_factory
41
+
42
+ async def provide(self) -> list[Path]:
43
+ return await self._ui_factory.askopenfilenames(
44
+ title="Load video files",
45
+ filetypes=[("video file", SUPPORTED_VIDEO_FILE_TYPES)],
46
+ extension_options=_video_extension_options(),
47
+ )
48
+
49
+
50
+ def _video_extension_options() -> dict[str, list[str] | None]:
51
+ """One entry offering every supported type, then one per type."""
52
+ options: dict[str, list[str] | None] = {
53
+ ALL_FILE_ENDINGS: list(SUPPORTED_VIDEO_FILE_TYPES)
54
+ }
55
+ for extension in SUPPORTED_VIDEO_FILE_TYPES:
56
+ options[extension] = [extension]
57
+ return options