scanpath-studio 0.31.2__tar.gz → 0.32.1__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 (146) hide show
  1. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/MANIFEST.in +1 -1
  2. {scanpath_studio-0.31.2/scanpath_studio.egg-info → scanpath_studio-0.32.1}/PKG-INFO +5 -2
  3. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/README.md +4 -1
  4. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/pyproject.toml +1 -1
  5. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/__init__.py +1 -1
  6. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/aggregation.py +16 -1
  7. scanpath_studio-0.32.1/scanpath_studio/annotations.py +1135 -0
  8. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/api.py +247 -58
  9. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/app.py +2155 -1435
  10. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/cli.py +254 -72
  11. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/code_snippet.py +262 -41
  12. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/compare_source.py +6 -2
  13. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/computations.py +38 -19
  14. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/constants.py +52 -11
  15. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/controls.py +794 -133
  16. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/data.py +1508 -86
  17. scanpath_studio-0.32.1/scanpath_studio/dataset_table.py +252 -0
  18. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/datasets.py +160 -43
  19. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/debug_log.py +59 -18
  20. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/export.py +315 -127
  21. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/eyegenbench.py +9 -4
  22. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/illustration.py +28 -10
  23. scanpath_studio-0.32.1/scanpath_studio/loading.py +926 -0
  24. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/menu.py +45 -114
  25. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/metadata.py +506 -41
  26. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/persistence.py +192 -69
  27. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/plots.py +410 -32
  28. scanpath_studio-0.32.1/scanpath_studio/progress.py +351 -0
  29. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/ia.csv +0 -1308
  30. scanpath_studio-0.32.1/scanpath_studio/sample_data/ia.parquet +0 -0
  31. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/session_keys.py +94 -27
  32. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/styles.py +445 -108
  33. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/tabs.py +1324 -386
  34. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/tour.py +35 -26
  35. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/update_sample_data.py +69 -3
  36. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/url_state.py +224 -97
  37. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/utils.py +141 -24
  38. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/wizard.py +308 -55
  39. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/wizard_shell.py +14 -4
  40. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1/scanpath_studio.egg-info}/PKG-INFO +5 -2
  41. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio.egg-info/SOURCES.txt +6 -0
  42. scanpath_studio-0.31.2/scanpath_studio/annotations.py +0 -404
  43. scanpath_studio-0.31.2/scanpath_studio/sample_data/ia.parquet +0 -0
  44. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/LICENSE +0 -0
  45. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/NOTICE +0 -0
  46. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/__main__.py +0 -0
  47. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/alignment.py +0 -0
  48. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/animation_export.py +0 -0
  49. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/assets/scanpath_studio_title_logo.png +0 -0
  50. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/authoring.py +0 -0
  51. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/authoring_component.py +0 -0
  52. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/easter_egg.py +0 -0
  53. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/experimental_setup.py +0 -0
  54. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/export_status.py +0 -0
  55. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/eyegenbench_geometry.py +0 -0
  56. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/fields.py +0 -0
  57. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/html_embed.py +0 -0
  58. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/measures.py +0 -0
  59. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/model_scanpaths.py +0 -0
  60. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/multipart.py +0 -0
  61. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/onestop_shard.py +0 -0
  62. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/preprocessing.py +0 -0
  63. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/fixations.csv +0 -0
  64. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/fixations.parquet +0 -0
  65. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_a.png +0 -0
  66. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_b.png +0 -0
  67. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_c.png +0 -0
  68. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__answer_d.png +0 -0
  69. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__paragraph.png +0 -0
  70. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_1_Ele__question.png +0 -0
  71. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_a.png +0 -0
  72. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_b.png +0 -0
  73. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_c.png +0 -0
  74. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__answer_d.png +0 -0
  75. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__paragraph.png +0 -0
  76. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_2_Ele__question.png +0 -0
  77. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_a.png +0 -0
  78. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_b.png +0 -0
  79. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_c.png +0 -0
  80. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__answer_d.png +0 -0
  81. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__paragraph.png +0 -0
  82. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_3_Adv__question.png +0 -0
  83. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_a.png +0 -0
  84. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_b.png +0 -0
  85. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_c.png +0 -0
  86. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__answer_d.png +0 -0
  87. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__paragraph.png +0 -0
  88. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_4_Adv__question.png +0 -0
  89. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_a.png +0 -0
  90. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_b.png +0 -0
  91. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_c.png +0 -0
  92. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__answer_d.png +0 -0
  93. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__paragraph.png +0 -0
  94. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_5_Adv__question.png +0 -0
  95. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_a.png +0 -0
  96. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_b.png +0 -0
  97. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_c.png +0 -0
  98. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__answer_d.png +0 -0
  99. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__paragraph.png +0 -0
  100. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_1_6_Ele__question.png +0 -0
  101. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_a.png +0 -0
  102. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_b.png +0 -0
  103. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_c.png +0 -0
  104. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__answer_d.png +0 -0
  105. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__paragraph.png +0 -0
  106. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_1_Adv__question.png +0 -0
  107. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_a.png +0 -0
  108. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_b.png +0 -0
  109. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_c.png +0 -0
  110. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__answer_d.png +0 -0
  111. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__paragraph.png +0 -0
  112. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_2_Adv__question.png +0 -0
  113. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_a.png +0 -0
  114. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_b.png +0 -0
  115. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_c.png +0 -0
  116. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__answer_d.png +0 -0
  117. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__paragraph.png +0 -0
  118. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_3_Adv__question.png +0 -0
  119. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_a.png +0 -0
  120. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_b.png +0 -0
  121. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_c.png +0 -0
  122. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__answer_d.png +0 -0
  123. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__paragraph.png +0 -0
  124. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_4_Ele__question.png +0 -0
  125. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_a.png +0 -0
  126. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_b.png +0 -0
  127. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_c.png +0 -0
  128. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__answer_d.png +0 -0
  129. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__paragraph.png +0 -0
  130. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_5_Ele__question.png +0 -0
  131. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_a.png +0 -0
  132. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_b.png +0 -0
  133. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_c.png +0 -0
  134. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__answer_d.png +0 -0
  135. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__paragraph.png +0 -0
  136. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/2_2_6_Ele__question.png +0 -0
  137. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/images/manifest.csv +0 -0
  138. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/raw_gaze.csv +0 -0
  139. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/sample_data/raw_gaze.parquet +0 -0
  140. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/similarity.py +0 -0
  141. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio/synthetic.py +0 -0
  142. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio.egg-info/dependency_links.txt +0 -0
  143. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio.egg-info/entry_points.txt +0 -0
  144. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio.egg-info/requires.txt +0 -0
  145. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/scanpath_studio.egg-info/top_level.txt +0 -0
  146. {scanpath_studio-0.31.2 → scanpath_studio-0.32.1}/setup.cfg +0 -0
@@ -5,5 +5,5 @@ recursive-include scanpath_studio/sample_data *.csv
5
5
  recursive-include scanpath_studio/sample_data *.parquet
6
6
  recursive-include scanpath_studio/sample_data *.png
7
7
  # ENG-61: the suite needs the whole repository (streamlit_app.py, docs/,
8
- # CITATION.cff, tracker/), so a partial copy in the sdist could never run.
8
+ # CITATION.cff), so a partial copy in the sdist could never run.
9
9
  prune tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanpath-studio
3
- Version: 0.31.2
3
+ Version: 0.32.1
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: Keren Gruteke Klein, Maya Grossman, Ella Lion, Deborah N. Jakobi, David R. Reich, Lena Jäger, Yevgeni Berzak
6
6
  Author-email: Omer Shubi <lacclab.technion@gmail.com>
@@ -83,7 +83,7 @@ paper.
83
83
  ```
84
84
 
85
85
  - **As a desktop app:** [Windows](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-windows-x86_64.zip) ·
86
- [macOS (Apple silicon)](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-macos-arm64.tar.gz) ·
86
+ [macOS (Apple silicon)](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-macos-arm64.dmg) ·
87
87
  [Linux](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-linux-x86_64.tar.gz).
88
88
 
89
89
  The pip and desktop installs keep your data on your own machine; the hosted demo
@@ -180,6 +180,9 @@ covers setup, the checks that gate CI, and how work is tracked in
180
180
  the architectural map. To preview the docs site locally, run
181
181
  `pip install -e ".[docs]"` and then `mkdocs serve`.
182
182
 
183
+ Taking part means following the
184
+ [Code of Conduct](https://github.com/lacclab/scanpath-studio/blob/main/CODE_OF_CONDUCT.md).
185
+
183
186
  ## Citation
184
187
 
185
188
  A paper is in preparation. Until then, cite the software by its DOI,
@@ -29,7 +29,7 @@ paper.
29
29
  ```
30
30
 
31
31
  - **As a desktop app:** [Windows](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-windows-x86_64.zip) ·
32
- [macOS (Apple silicon)](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-macos-arm64.tar.gz) ·
32
+ [macOS (Apple silicon)](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-macos-arm64.dmg) ·
33
33
  [Linux](https://github.com/lacclab/scanpath-studio/releases/latest/download/ScanpathStudio-linux-x86_64.tar.gz).
34
34
 
35
35
  The pip and desktop installs keep your data on your own machine; the hosted demo
@@ -126,6 +126,9 @@ covers setup, the checks that gate CI, and how work is tracked in
126
126
  the architectural map. To preview the docs site locally, run
127
127
  `pip install -e ".[docs]"` and then `mkdocs serve`.
128
128
 
129
+ Taking part means following the
130
+ [Code of Conduct](https://github.com/lacclab/scanpath-studio/blob/main/CODE_OF_CONDUCT.md).
131
+
129
132
  ## Citation
130
133
 
131
134
  A paper is in preparation. Until then, cite the software by its DOI,
@@ -177,7 +177,7 @@ ignore = [
177
177
  # each already carrying a comment saying why the failure is ignorable.
178
178
  "S110", "S112",
179
179
  # Naive local timestamps are correct here: these stamp a local recovery
180
- # cache and a local tracker, both single-machine by design. Making them
180
+ # cache, single-machine by design. Making them
181
181
  # tz-aware would imply a portability this data does not have.
182
182
  "DTZ005", "DTZ006",
183
183
  # Fires on scripts with a shebang that are run via `python <script>`; the
@@ -40,7 +40,7 @@ __all__ = [
40
40
  "save_figure_layers",
41
41
  "trial_summary",
42
42
  ]
43
- __version__ = "0.31.2"
43
+ __version__ = "0.32.1"
44
44
 
45
45
  # Public headless API (see api.py / datasets.py / eyegenbench.py). Resolved lazily so
46
46
  # `import scanpath_studio` stays cheap and doesn't pull in pandas/plotly/
@@ -1343,12 +1343,27 @@ def group_mask(frame: pd.DataFrame, spec: Mapping[str, Sequence]) -> pd.Series:
1343
1343
  (compared as strings). Unifies both group-definition modes: a *field split*
1344
1344
  is two specs over the same column with disjoint values, while *independent
1345
1345
  filter sets* are specs with several columns. An empty spec selects all rows.
1346
+
1347
+ A key may also be a **tuple of columns**, whose values are tuples: a
1348
+ composite key the row must match as a whole (AN-31 — a trial-metadata
1349
+ cohort is a set of ``(participant_id, trial_id)`` readings, which two
1350
+ independent column constraints cannot express: reader p1's trial t1 and
1351
+ reader p2's trial t2 are not p1's t2). Like a single column, a composite key
1352
+ a frame does not fully carry constrains nothing on that frame.
1346
1353
  """
1347
1354
  if frame is None or frame.empty:
1348
1355
  return pd.Series([], dtype=bool)
1349
1356
  mask = pd.Series(True, index=frame.index)
1350
1357
  for col, vals in (spec or {}).items():
1351
- if col in frame.columns and vals:
1358
+ if not vals:
1359
+ continue
1360
+ if isinstance(col, tuple):
1361
+ if not set(col) <= set(frame.columns):
1362
+ continue
1363
+ allowed = {tuple(str(part) for part in v) for v in vals}
1364
+ keys = pd.MultiIndex.from_arrays([frame[c].astype(str) for c in col])
1365
+ mask &= keys.isin(allowed)
1366
+ elif col in frame.columns:
1352
1367
  allowed = {str(v) for v in vals}
1353
1368
  mask &= frame[col].astype(str).isin(allowed)
1354
1369
  return mask