scanpath-studio 0.27.2__tar.gz → 0.28.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scanpath_studio-0.27.2/scanpath_studio.egg-info → scanpath_studio-0.28.0}/PKG-INFO +3 -2
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/README.md +1 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/pyproject.toml +27 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/__init__.py +1 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/annotations.py +0 -12
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/api.py +28 -5
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/app.py +393 -134
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/authoring.py +34 -6
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/cli.py +42 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/constants.py +32 -44
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/controls.py +625 -120
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/data.py +76 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/export.py +34 -40
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/measures.py +0 -13
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/plots.py +140 -27
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/preprocessing.py +65 -21
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/session_keys.py +20 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/styles.py +119 -13
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/tabs.py +941 -370
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/tour.py +51 -22
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/url_state.py +106 -2
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/utils.py +28 -10
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0/scanpath_studio.egg-info}/PKG-INFO +3 -2
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio.egg-info/SOURCES.txt +3 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio.egg-info/requires.txt +1 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_apptest.py +412 -11
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_apptest_flows.py +119 -18
- scanpath_studio-0.28.0/tests/test_authoring.py +73 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_cli.py +24 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_composite_selection.py +1 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_data.py +113 -2
- scanpath_studio-0.28.0/tests/test_debug_log.py +127 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_desktop_icon.py +2 -3
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_disclosure.py +4 -2
- scanpath_studio-0.28.0/tests/test_experimental_setup.py +64 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_mode_parity.py +88 -2
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_persistence.py +0 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_preprocessing.py +99 -0
- scanpath_studio-0.28.0/tests/test_saccade_class_filter.py +241 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_security_fixes.py +2 -2
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_session_key_contract.py +16 -2
- scanpath_studio-0.28.0/tests/test_slider_number_callbacks.py +127 -0
- scanpath_studio-0.28.0/tests/test_stimulus_panel.py +396 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_tour.py +48 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_trial_sort.py +3 -3
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_viz_palette.py +19 -14
- scanpath_studio-0.28.0/tests/test_widget_value_sync.py +294 -0
- scanpath_studio-0.27.2/tests/test_authoring.py +0 -26
- scanpath_studio-0.27.2/tests/test_experimental_setup.py +0 -22
- scanpath_studio-0.27.2/tests/test_stimulus_panel.py +0 -209
- scanpath_studio-0.27.2/tests/test_widget_value_sync.py +0 -191
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/LICENSE +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/MANIFEST.in +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/NOTICE +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/__main__.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/aggregation.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/alignment.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/animation_export.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/datasets.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/debug_log.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/experimental_setup.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/html_embed.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/illustration.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/model_scanpaths.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/onestop_shard.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/persistence.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/fixations.csv +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/fixations.parquet +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/ia.csv +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/ia.parquet +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_1_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_2_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_3_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_4_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_5_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_1_6_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_1_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_2_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_3_Adv__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_4_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_5_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_a.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_b.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_c.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_d.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__paragraph.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/2_2_6_Ele__question.png +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/images/manifest.csv +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/raw_gaze.csv +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/sample_data/raw_gaze.parquet +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/similarity.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/synthetic.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/update_sample_data.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio/wizard.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio.egg-info/dependency_links.txt +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio.egg-info/entry_points.txt +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/scanpath_studio.egg-info/top_level.txt +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/setup.cfg +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_aggregation.py +1 -1
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_alignment.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_analysis_figures.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_animation_export.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_annotations.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_api.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_app.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_arc_saccades.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_builder_parity.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_citation.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_cli_drift.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_column_mapping.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_compare_ordering.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_dataset_support.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_deployment_gate.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_empty_states.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_export.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_export_naming.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_filters.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_fix_range_scope.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_illustration.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_measures.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_model_scanpaths.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_multiple_comparison_ui.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_multipleye_enrichment.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_numeric_sliders.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_onestop_shard.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_plot_config_restore.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_plots.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_raw_gaze_filters.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_raw_gaze_sample.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_remap.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_share_drift.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_similarity.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_smoke.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_synthetic.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_theme.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_tracker_server.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_upload_guard.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_wizard_helpers.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_word_box_geometry.py +0 -0
- {scanpath_studio-0.27.2 → scanpath_studio-0.28.0}/tests/test_word_id_offset.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scanpath-studio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.28.0
|
|
4
4
|
Summary: Interactive Streamlit workbench for visualizing eye-tracking-while-reading scanpaths, computing reading measures, and exporting figures and tabular data.
|
|
5
5
|
Author-email: "Omer Shubi (LACC Lab, Technion)" <lacclab.technion@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -44,7 +44,7 @@ Requires-Python: >=3.11
|
|
|
44
44
|
Description-Content-Type: text/markdown
|
|
45
45
|
License-File: LICENSE
|
|
46
46
|
License-File: NOTICE
|
|
47
|
-
Requires-Dist: streamlit>=1.
|
|
47
|
+
Requires-Dist: streamlit>=1.61.1
|
|
48
48
|
Requires-Dist: pandas>=2.3.3
|
|
49
49
|
Requires-Dist: plotly>=6.5.2
|
|
50
50
|
Requires-Dist: numpy>=2.4.1
|
|
@@ -72,6 +72,7 @@ Dynamic: license-file
|
|
|
72
72
|
[](https://scanpath-studio.streamlit.app)
|
|
73
73
|
[](https://lacclab.github.io/scanpath-studio/)
|
|
74
74
|
[](https://github.com/lacclab/scanpath-studio/actions/workflows/ci.yml)
|
|
75
|
+
[](https://lacclab.github.io/scanpath-studio/coverage/)
|
|
75
76
|
[](LICENSE)
|
|
76
77
|
|
|
77
78
|
An interactive workbench for visualizing **eye-tracking-while-reading** data.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
[](https://scanpath-studio.streamlit.app)
|
|
6
6
|
[](https://lacclab.github.io/scanpath-studio/)
|
|
7
7
|
[](https://github.com/lacclab/scanpath-studio/actions/workflows/ci.yml)
|
|
8
|
+
[](https://lacclab.github.io/scanpath-studio/coverage/)
|
|
8
9
|
[](LICENSE)
|
|
9
10
|
|
|
10
11
|
An interactive workbench for visualizing **eye-tracking-while-reading** data.
|
|
@@ -25,7 +25,7 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Scientific/Engineering :: Visualization",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"streamlit>=1.
|
|
28
|
+
"streamlit>=1.61.1",
|
|
29
29
|
"pandas>=2.3.3",
|
|
30
30
|
"plotly>=6.5.2",
|
|
31
31
|
"numpy>=2.4.1",
|
|
@@ -92,3 +92,29 @@ include = ["scanpath_studio"]
|
|
|
92
92
|
"sample_data/images/*.png",
|
|
93
93
|
"sample_data/images/*.csv",
|
|
94
94
|
]
|
|
95
|
+
|
|
96
|
+
[tool.coverage.run]
|
|
97
|
+
source = ["scanpath_studio"]
|
|
98
|
+
# Two one-shot data-prep scripts, deliberately untested and deliberately not
|
|
99
|
+
# counted. Both are run by hand, once per data refresh, against corpora that are
|
|
100
|
+
# not in the repo and cannot be in CI: `onestop_shard` needs the ~15 GB OneStop
|
|
101
|
+
# lacclab CSVs, `update_sample_data` needs the full OneStop release to
|
|
102
|
+
# regenerate the bundled demo. Testing them would mean mocking the file layout
|
|
103
|
+
# they exist to walk, which pins the mock rather than the script (ENG-37).
|
|
104
|
+
omit = [
|
|
105
|
+
"scanpath_studio/onestop_shard.py",
|
|
106
|
+
"scanpath_studio/update_sample_data.py",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.coverage.report]
|
|
110
|
+
# A floor, not a target: it fails the build when a change drops coverage
|
|
111
|
+
# meaningfully, without turning every PR into a coverage negotiation. Raise it
|
|
112
|
+
# when the real number has been comfortably above for a while.
|
|
113
|
+
fail_under = 89
|
|
114
|
+
show_missing = true
|
|
115
|
+
exclude_also = [
|
|
116
|
+
"if TYPE_CHECKING:",
|
|
117
|
+
"raise NotImplementedError",
|
|
118
|
+
"if __name__ == .__main__.:",
|
|
119
|
+
"@(abc\\.)?abstractmethod",
|
|
120
|
+
]
|
|
@@ -27,7 +27,7 @@ __all__ = [
|
|
|
27
27
|
"load_multipleye",
|
|
28
28
|
"load_onestop",
|
|
29
29
|
]
|
|
30
|
-
__version__ = "0.
|
|
30
|
+
__version__ = "0.28.0"
|
|
31
31
|
|
|
32
32
|
# Public headless API (see api.py / datasets.py). Resolved lazily so
|
|
33
33
|
# `import scanpath_studio` stays cheap and doesn't pull in pandas/plotly/
|
|
@@ -141,18 +141,6 @@ def known_tags() -> List[str]:
|
|
|
141
141
|
return sorted(tags)
|
|
142
142
|
|
|
143
143
|
|
|
144
|
-
def starred_keys() -> Set[Key]:
|
|
145
|
-
return {k for k, v in _store().items() if v.get("star")}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def keys_with_tag(tag: str) -> Set[Key]:
|
|
149
|
-
return {k for k, v in _store().items() if tag in v.get("tags", [])}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def annotated_count() -> int:
|
|
153
|
-
return len(_store())
|
|
154
|
-
|
|
155
|
-
|
|
156
144
|
def current_records() -> List[dict]:
|
|
157
145
|
"""All annotations as a flat record list — for embedding in a saved config."""
|
|
158
146
|
return store_to_records(_store())
|
|
@@ -63,17 +63,19 @@ from .constants import ( # noqa: E402
|
|
|
63
63
|
DEFAULT_SACCADE_WIDTH,
|
|
64
64
|
FONT_FAMILY,
|
|
65
65
|
PALETTES,
|
|
66
|
+
SACCADE_CLASS_ORDER,
|
|
66
67
|
SACCADE_COLOR,
|
|
67
68
|
UNIFORM_COLOR_FIELD,
|
|
68
69
|
palette_settings,
|
|
69
70
|
)
|
|
71
|
+
from .export import annotate_figure # noqa: E402
|
|
70
72
|
from .plots import ( # noqa: E402
|
|
71
73
|
animation_autoplay_frame_duration,
|
|
72
74
|
animation_autoplay_post_script,
|
|
73
|
-
make_scanpath_animation,
|
|
74
|
-
make_scanpath_figure,
|
|
75
75
|
make_difference_profile_figure,
|
|
76
76
|
make_distribution_figure,
|
|
77
|
+
make_scanpath_animation,
|
|
78
|
+
make_scanpath_figure,
|
|
77
79
|
make_word_profile_figure,
|
|
78
80
|
split_scanpath_layers,
|
|
79
81
|
)
|
|
@@ -161,6 +163,12 @@ CANONICAL_FIGURE_DEFAULTS: dict = dict(
|
|
|
161
163
|
saccade_color_mode="Uniform",
|
|
162
164
|
saccade_class_colors=None,
|
|
163
165
|
saccade_type_legend=True,
|
|
166
|
+
# VIZ-31: the reading-class filter — which classes are drawn at all, as
|
|
167
|
+
# opposed to what colour they are drawn in. Spelled out as the full list
|
|
168
|
+
# rather than the equivalent `None` so this matches what the app's
|
|
169
|
+
# all-selected multiselect resolves to key-for-key; the builder treats a
|
|
170
|
+
# complete list as "no filter" and skips the classification pass.
|
|
171
|
+
saccade_classes=list(SACCADE_CLASS_ORDER),
|
|
164
172
|
saccade_render_mode="Straight",
|
|
165
173
|
fixation_snap_to_word=False,
|
|
166
174
|
# VIZ-17 uniform fixation colour · VIZ-15 marker shape — the flat colour and
|
|
@@ -923,7 +931,7 @@ def _expand_palette(overrides: dict) -> dict:
|
|
|
923
931
|
any colour the caller also passes explicitly wins over it::
|
|
924
932
|
|
|
925
933
|
sps.plot_scanpath(w, f, palette="Print / greyscale")
|
|
926
|
-
sps.plot_scanpath(w, f, palette="
|
|
934
|
+
sps.plot_scanpath(w, f, palette="Default (colourblind-safe)", saccade_color="#000")
|
|
927
935
|
|
|
928
936
|
The palette itself isn't a figure kwarg, so it's consumed here rather than
|
|
929
937
|
forwarded. Raises on an unknown name — a silent fallback to the default
|
|
@@ -1082,6 +1090,8 @@ def plot_scanpath(
|
|
|
1082
1090
|
fix_index_range: Optional[Tuple[int, int]] = None,
|
|
1083
1091
|
illustration: bool = False,
|
|
1084
1092
|
illustration_label: str = "auto",
|
|
1093
|
+
title: str = "",
|
|
1094
|
+
caption: str = "",
|
|
1085
1095
|
**figure_overrides,
|
|
1086
1096
|
) -> go.Figure:
|
|
1087
1097
|
"""Build the canonical scanpath figure for one trial.
|
|
@@ -1106,6 +1116,11 @@ def plot_scanpath(
|
|
|
1106
1116
|
the app's fixation-index window. It is applied before the drift correction,
|
|
1107
1117
|
like the app.
|
|
1108
1118
|
|
|
1119
|
+
``title`` / ``caption`` (EXP-5) stamp a title/caption band onto the figure
|
|
1120
|
+
without shrinking the plot area, exactly like the rail's *Title & caption on
|
|
1121
|
+
the figure* control — literal text here, not the rail's ``{trial_id}``-style
|
|
1122
|
+
pattern, since the caller already knows which trial this is.
|
|
1123
|
+
|
|
1109
1124
|
Remaining keywords override the app's defaults and are forwarded to
|
|
1110
1125
|
:func:`plots.make_scanpath_figure` (e.g. ``show_heatmap=False``,
|
|
1111
1126
|
``color_by="pass_index"``, ``x_field="order_in_trial"``); an unknown keyword
|
|
@@ -1177,7 +1192,7 @@ def plot_scanpath(
|
|
|
1177
1192
|
_require_normalized(raw_gaze, "raw_gaze")
|
|
1178
1193
|
raw_gaze = _data.filter_raw_gaze(raw_gaze, [pid], [tid])
|
|
1179
1194
|
settings.setdefault("show_raw_gaze", True)
|
|
1180
|
-
|
|
1195
|
+
fig = make_scanpath_figure(
|
|
1181
1196
|
trial_words,
|
|
1182
1197
|
trial_fixations,
|
|
1183
1198
|
canvas_width=int(canvas_size[0]),
|
|
@@ -1189,6 +1204,8 @@ def plot_scanpath(
|
|
|
1189
1204
|
raw_gaze=raw_gaze,
|
|
1190
1205
|
**settings,
|
|
1191
1206
|
)
|
|
1207
|
+
annotate_figure(fig, title=title, caption=caption)
|
|
1208
|
+
return fig
|
|
1192
1209
|
|
|
1193
1210
|
|
|
1194
1211
|
def animate_scanpath(
|
|
@@ -1203,6 +1220,8 @@ def animate_scanpath(
|
|
|
1203
1220
|
playback_speed: float = 1.0,
|
|
1204
1221
|
autoplay: bool = True,
|
|
1205
1222
|
fix_index_range: Optional[Tuple[int, int]] = None,
|
|
1223
|
+
title: str = "",
|
|
1224
|
+
caption: str = "",
|
|
1206
1225
|
**animation_overrides,
|
|
1207
1226
|
) -> go.Figure:
|
|
1208
1227
|
"""Build the animated scanpath replay for one trial.
|
|
@@ -1230,6 +1249,8 @@ def animate_scanpath(
|
|
|
1230
1249
|
matches the static figure. ``palette=`` (VIZ-18) works here too; the colours
|
|
1231
1250
|
it implies that the animation doesn't support are dropped rather than
|
|
1232
1251
|
raising, since the caller named a look, not those individual keys.
|
|
1252
|
+
|
|
1253
|
+
``title`` / ``caption`` (EXP-5) — same as :func:`plot_scanpath`.
|
|
1233
1254
|
"""
|
|
1234
1255
|
valid = set(_ANIMATION_FIGURE_PARAMS)
|
|
1235
1256
|
explicit = set(animation_overrides) - {"palette"}
|
|
@@ -1256,7 +1277,7 @@ def animate_scanpath(
|
|
|
1256
1277
|
trial_fixations = _apply_fix_index_range(trial_fixations, fix_index_range, pid, tid)
|
|
1257
1278
|
if canvas_size is None:
|
|
1258
1279
|
canvas_size = _data.compute_canvas_size(trial_words, trial_fixations)
|
|
1259
|
-
|
|
1280
|
+
fig = make_scanpath_animation(
|
|
1260
1281
|
trial_words,
|
|
1261
1282
|
trial_fixations,
|
|
1262
1283
|
canvas_width=int(canvas_size[0]),
|
|
@@ -1267,6 +1288,8 @@ def animate_scanpath(
|
|
|
1267
1288
|
autoplay=autoplay,
|
|
1268
1289
|
**animation_overrides,
|
|
1269
1290
|
)
|
|
1291
|
+
annotate_figure(fig, title=title, caption=caption)
|
|
1292
|
+
return fig
|
|
1270
1293
|
|
|
1271
1294
|
|
|
1272
1295
|
def save_figure(
|