protspace 3.2.0__tar.gz → 3.3.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 (164) hide show
  1. {protspace-3.2.0 → protspace-3.3.1}/.gitignore +1 -0
  2. {protspace-3.2.0 → protspace-3.3.1}/CHANGELOG.md +84 -0
  3. {protspace-3.2.0 → protspace-3.3.1}/PKG-INFO +1 -1
  4. {protspace-3.2.0 → protspace-3.3.1}/docs/cli.md +9 -1
  5. protspace-3.3.1/docs/styling.md +122 -0
  6. {protspace-3.2.0 → protspace-3.3.1}/notebooks/ProtSpace_Preparation.ipynb +249 -130
  7. {protspace-3.2.0 → protspace-3.3.1}/pyproject.toml +1 -1
  8. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/__init__.py +1 -1
  9. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/cli/local_data.py +1 -2
  10. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/manager.py +0 -1
  11. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/retrievers/interpro_retriever.py +0 -1
  12. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/retrievers/taxonomy_retriever.py +0 -1
  13. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/retrievers/uniprot_retriever.py +0 -1
  14. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/settings_converter.py +102 -11
  15. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/processors/base_processor.py +14 -1
  16. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/processors/local_processor.py +4 -2
  17. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/processors/uniprot_query_processor.py +0 -1
  18. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/add_annotation_style.py +74 -12
  19. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/reducers.py +81 -3
  20. protspace-3.3.1/tests/test_reducers.py +274 -0
  21. {protspace-3.2.0 → protspace-3.3.1}/uv.lock +1 -1
  22. protspace-3.2.0/docs/styling.md +0 -66
  23. {protspace-3.2.0 → protspace-3.3.1}/.dockerignore +0 -0
  24. {protspace-3.2.0 → protspace-3.3.1}/.env.example +0 -0
  25. {protspace-3.2.0 → protspace-3.3.1}/.github/SEMANTIC_RELEASE_SETUP.md +0 -0
  26. {protspace-3.2.0 → protspace-3.3.1}/.github/workflows/docker.yml +0 -0
  27. {protspace-3.2.0 → protspace-3.3.1}/.github/workflows/jekyll-gh-pages.yml +0 -0
  28. {protspace-3.2.0 → protspace-3.3.1}/.github/workflows/python.yml +0 -0
  29. {protspace-3.2.0 → protspace-3.3.1}/.github/workflows/release.yml +0 -0
  30. {protspace-3.2.0 → protspace-3.3.1}/.python-version +0 -0
  31. {protspace-3.2.0 → protspace-3.3.1}/Dockerfile +0 -0
  32. {protspace-3.2.0 → protspace-3.3.1}/LICENSE +0 -0
  33. {protspace-3.2.0 → protspace-3.3.1}/README.md +0 -0
  34. {protspace-3.2.0 → protspace-3.3.1}/data/3FTx/3FTx.csv +0 -0
  35. {protspace-3.2.0 → protspace-3.3.1}/data/3FTx/parquetbundle/3FTx_accession.csv +0 -0
  36. {protspace-3.2.0 → protspace-3.3.1}/data/3FTx/parquetbundle/3ftx_with_db_styled.parquetbundle +0 -0
  37. {protspace-3.2.0 → protspace-3.3.1}/data/3FTx/parquetbundle/styles.json +0 -0
  38. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/Pla2g2.csv +0 -0
  39. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/Pla2g2.fasta +0 -0
  40. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/Pla2g2_pdb.zip +0 -0
  41. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/protspace_files/Pla2g2.json +0 -0
  42. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/protspace_files/Pla2g2_customized.json +0 -0
  43. {protspace-3.2.0 → protspace-3.3.1}/data/Pla2g2/style.json +0 -0
  44. {protspace-3.2.0 → protspace-3.3.1}/data/toxins/protspace/projections_data.parquet +0 -0
  45. {protspace-3.2.0 → protspace-3.3.1}/data/toxins/protspace/projections_metadata.parquet +0 -0
  46. {protspace-3.2.0 → protspace-3.3.1}/data/toxins/protspace/selected_annotations.parquet +0 -0
  47. {protspace-3.2.0 → protspace-3.3.1}/data/toxins/toxins.json +0 -0
  48. {protspace-3.2.0 → protspace-3.3.1}/data/toxins/toxins.parquetbundle +0 -0
  49. {protspace-3.2.0 → protspace-3.3.1}/docs/annotations.md +0 -0
  50. {protspace-3.2.0 → protspace-3.3.1}/docs/protspace_example.png +0 -0
  51. {protspace-3.2.0 → protspace-3.3.1}/examples/Workflow.svg +0 -0
  52. {protspace-3.2.0 → protspace-3.3.1}/examples/cli/protspace_local.py +0 -0
  53. {protspace-3.2.0 → protspace-3.3.1}/examples/cli/protspace_query.py +0 -0
  54. {protspace-3.2.0 → protspace-3.3.1}/examples/image_creation.py +0 -0
  55. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/PCA2_group.svg +0 -0
  56. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/PCA2_major_group.svg +0 -0
  57. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/PCA3_group.html +0 -0
  58. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/PCA3_major_group.html +0 -0
  59. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/UMAP2_group.svg +0 -0
  60. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/UMAP2_major_group.svg +0 -0
  61. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/UMAP3_group.html +0 -0
  62. {protspace-3.2.0 → protspace-3.3.1}/examples/out/3FTx/UMAP3_major_group.html +0 -0
  63. {protspace-3.2.0 → protspace-3.3.1}/examples/out/Pla2g2/Pla2g2_dashboard.png +0 -0
  64. {protspace-3.2.0 → protspace-3.3.1}/examples/out/Pla2g2/Pla2g2_group.svg +0 -0
  65. {protspace-3.2.0 → protspace-3.3.1}/examples/out/Pla2g2/group.svg +0 -0
  66. {protspace-3.2.0 → protspace-3.3.1}/examples/out/automatic_projections/PCA_2_annotation_score.png +0 -0
  67. {protspace-3.2.0 → protspace-3.3.1}/examples/out/automatic_projections/PCA_2_protein_existence.png +0 -0
  68. {protspace-3.2.0 → protspace-3.3.1}/examples/out/automatic_projections/PCA_3_annotation_score.html +0 -0
  69. {protspace-3.2.0 → protspace-3.3.1}/examples/out/automatic_projections/PCA_3_protein_existence.html +0 -0
  70. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/prott5_umap2_brightness_category.svg +0 -0
  71. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/prott5_umap2_nr_mutations.svg +0 -0
  72. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/seq_sim_mds2_brightness_category.svg +0 -0
  73. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/seq_sim_mds2_nr_mutations.svg +0 -0
  74. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/seq_sim_umap2_brightness_category.svg +0 -0
  75. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/seq_sim_umap2_nr_mutations.svg +0 -0
  76. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/struct_sim_mds2_brightness_category.svg +0 -0
  77. {protspace-3.2.0 → protspace-3.3.1}/examples/out/gfp/struct_sim_mds2_nr_mutations.svg +0 -0
  78. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/function_umap.svg +0 -0
  79. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/product_category_umap.svg +0 -0
  80. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/sub_all_members.html +0 -0
  81. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/sub_all_members.svg +0 -0
  82. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/sub_clusterrep.html +0 -0
  83. {protspace-3.2.0 → protspace-3.3.1}/examples/out/phages/sub_clusterrep.svg +0 -0
  84. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/family_bitmap_umap.svg +0 -0
  85. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/family_evalue_umap.svg +0 -0
  86. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/order_bits_umap.svg +0 -0
  87. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/order_evalue_umap.svg +0 -0
  88. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/order_umap.png +0 -0
  89. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/order_umap.svg +0 -0
  90. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/protein_category_bits_umap.svg +0 -0
  91. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/protein_category_evalue_umap.svg +0 -0
  92. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/protein_category_umap.png +0 -0
  93. {protspace-3.2.0 → protspace-3.3.1}/examples/out/toxins/protein_category_umap.svg +0 -0
  94. {protspace-3.2.0 → protspace-3.3.1}/examples/run_interactive_mode.py +0 -0
  95. {protspace-3.2.0 → protspace-3.3.1}/notebooks/ClickThrough_GenerateEmbeddings.ipynb +0 -0
  96. {protspace-3.2.0 → protspace-3.3.1}/notebooks/Explore_ProtSpace.ipynb +0 -0
  97. {protspace-3.2.0 → protspace-3.3.1}/notebooks/PfamExplorer_ProtSpace.ipynb +0 -0
  98. {protspace-3.2.0 → protspace-3.3.1}/notebooks/Run_ProtSpace.ipynb +0 -0
  99. {protspace-3.2.0 → protspace-3.3.1}/out/images/marker_gallery.png +0 -0
  100. {protspace-3.2.0 → protspace-3.3.1}/requirements-py310.txt +0 -0
  101. {protspace-3.2.0 → protspace-3.3.1}/requirements-py311.txt +0 -0
  102. {protspace-3.2.0 → protspace-3.3.1}/requirements-py312.txt +0 -0
  103. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/app.py +0 -0
  104. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/__init__.py +0 -0
  105. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/annotated_image.png +0 -0
  106. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/custom.css +0 -0
  107. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/help_content/__init__.py +0 -0
  108. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/help_content/help_faq.md +0 -0
  109. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/help_content/help_how_it_works.md +0 -0
  110. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/help_content/help_json.md +0 -0
  111. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/help_content/help_overview.md +0 -0
  112. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/assets/rostlab_logo.png +0 -0
  113. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/cli/__init__.py +0 -0
  114. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/cli/common_args.py +0 -0
  115. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/cli/uniprot_query.py +0 -0
  116. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/core/__init__.py +0 -0
  117. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/core/config.py +0 -0
  118. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/core/constants.py +0 -0
  119. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/__init__.py +0 -0
  120. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/__init__.py +0 -0
  121. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/configuration.py +0 -0
  122. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/merging.py +0 -0
  123. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/retrievers/__init__.py +0 -0
  124. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/retrievers/base_retriever.py +0 -0
  125. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/scores.py +0 -0
  126. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/transformers/__init__.py +0 -0
  127. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/transformers/interpro_transforms.py +0 -0
  128. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/transformers/length_binning.py +0 -0
  129. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/transformers/transformer.py +0 -0
  130. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/annotations/transformers/uniprot_transforms.py +0 -0
  131. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/__init__.py +0 -0
  132. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/bundle.py +0 -0
  133. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/formatters.py +0 -0
  134. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/readers.py +0 -0
  135. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/io/writers.py +0 -0
  136. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/parsers/__init__.py +0 -0
  137. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/parsers/uniprot_parser.py +0 -0
  138. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/data/processors/__init__.py +0 -0
  139. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/main.py +0 -0
  140. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/ui/__init__.py +0 -0
  141. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/ui/callbacks.py +0 -0
  142. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/ui/layout.py +0 -0
  143. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/ui/styles.py +0 -0
  144. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/__init__.py +0 -0
  145. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/analyse_json.py +0 -0
  146. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/arrow_reader.py +0 -0
  147. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/utils/json_reader.py +0 -0
  148. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/visualization/__init__.py +0 -0
  149. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/visualization/molstar.py +0 -0
  150. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/visualization/plotting.py +0 -0
  151. {protspace-3.2.0 → protspace-3.3.1}/src/protspace/wsgi.py +0 -0
  152. {protspace-3.2.0 → protspace-3.3.1}/tests/README.md +0 -0
  153. {protspace-3.2.0 → protspace-3.3.1}/tests/__init__.py +0 -0
  154. {protspace-3.2.0 → protspace-3.3.1}/tests/test_annotation_manager.py +0 -0
  155. {protspace-3.2.0 → protspace-3.3.1}/tests/test_base_data_processor.py +0 -0
  156. {protspace-3.2.0 → protspace-3.3.1}/tests/test_config.py +0 -0
  157. {protspace-3.2.0 → protspace-3.3.1}/tests/test_interpro_annotation_retriever.py +0 -0
  158. {protspace-3.2.0 → protspace-3.3.1}/tests/test_local_data_processor.py +0 -0
  159. {protspace-3.2.0 → protspace-3.3.1}/tests/test_output_combinations.py +0 -0
  160. {protspace-3.2.0 → protspace-3.3.1}/tests/test_taxonomy_annotation_retriever.py +0 -0
  161. {protspace-3.2.0 → protspace-3.3.1}/tests/test_transformer.py +0 -0
  162. {protspace-3.2.0 → protspace-3.3.1}/tests/test_uniprot_annotation_retriever.py +0 -0
  163. {protspace-3.2.0 → protspace-3.3.1}/tests/test_uniprot_query_processor.py +0 -0
  164. {protspace-3.2.0 → protspace-3.3.1}/update_deps.sh +0 -0
@@ -1,6 +1,7 @@
1
1
  # ignore for now
2
2
  .DS_Store
3
3
  /.vscode
4
+ /.claude
4
5
  /backup
5
6
  /bin
6
7
  /docs/publication
@@ -1,6 +1,90 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v3.3.1 (2026-02-27)
5
+
6
+ ### Chores
7
+
8
+ * chore: remove dead code and redundant logging.basicConfig calls
9
+
10
+ - Remove 6 redundant logging.basicConfig() calls from library modules
11
+ (only the CLI entry point setup_logging() should configure logging)
12
+ - Remove duplicate logger assignment in reducers.py
13
+ - Replace bare print(e) with logger.error() in reducers.py
14
+ - Remove commented-out dead code in local_data.py
15
+
16
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ([`74f04f4`](https://github.com/tsenoner/protspace/commit/74f04f4aee338db09a3abcea699b3932b51ec01a))
17
+
18
+ ### Documentation
19
+
20
+ * docs(notebook): overhaul Colab UI with interactive widgets
21
+
22
+ Replace basic SelectMultiple widgets with a polished interactive UI:
23
+ - Annotation selection: checkboxes in 2-column CSS grids per category
24
+ (UniProt/InterPro/Taxonomy) with per-group and global preset buttons
25
+ - DR method selection: ToggleButtons with color feedback and tooltips
26
+ - Method parameters: bordered cards in responsive flex-wrap grid with
27
+ shared params merged (n_neighbors for UMAP/PaCMAP/LocalMAP, etc.)
28
+ - Dynamic show/hide of parameter groups based on selected methods
29
+ - Remove gene_name from selectable annotations (always auto-included)
30
+ - Add /.claude to .gitignore
31
+
32
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ([`f671715`](https://github.com/tsenoner/protspace/commit/f671715ebf13eb808e7f44567b3c0407a5accb41))
33
+
34
+ ### Fixes
35
+
36
+ * fix(reducers): robust float16 upcast, annoy fallback, suppress noisy warnings
37
+
38
+ - Upcast float16 → float32 at HDF5 load time (local_processor) with a
39
+ safety-net in base_processor, preventing overflow in all DR methods
40
+ - Add lazy annoy health check: on platforms where annoy segfaults or
41
+ returns empty results (e.g. macOS ARM64), transparently swap in an
42
+ sklearn NearestNeighbors drop-in so PaCMAP/LocalMAP keep working
43
+ - Suppress harmless sklearn RuntimeWarnings (randomized SVD overflow),
44
+ FutureWarnings, and umap UserWarnings during fit_transform
45
+ - Add LocalMAP to Colab notebook (METHODS list, parameter sliders,
46
+ intro text) — previously missing from the preparation UI
47
+
48
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ([`7c8193e`](https://github.com/tsenoner/protspace/commit/7c8193ef0ef4c2b9df3a9031dc142f77b28d9fc6))
49
+
50
+ ### Testing
51
+
52
+ * test(reducers): add comprehensive tests for all 6 DR methods
53
+
54
+ 51 tests covering PCA, t-SNE, UMAP, PaCMAP, MDS, and LocalMAP:
55
+ - Per-method: output shape (2D/3D), NaN-free, get_params, determinism
56
+ - Cross-cutting (parametrized): finite output, float dtype, no Inf
57
+ - Float16 handling: verify upcast produces correct results
58
+ - Config validation: defaults, custom values, invalid inputs
59
+ - End-to-end: all methods through BaseProcessor.process_reduction
60
+
61
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ([`85697c0`](https://github.com/tsenoner/protspace/commit/85697c00bd84885999a96bd4613eb3289bcb03bb))
62
+
63
+ ### Unknown
64
+
65
+ * Merge pull request #34 from tsenoner/stage
66
+
67
+ Robust reducers, test suite, and Colab UI overhaul ([`e1e416d`](https://github.com/tsenoner/protspace/commit/e1e416d1b51e7880b65a60c60d4d489f4f58645a))
68
+
69
+
70
+ ## v3.3.0 (2026-02-17)
71
+
72
+ ### Features
73
+
74
+ * feat(styling): add pinnedValues, __REST__ marker, and value preprocessing
75
+
76
+ Add legend ordering support to protspace-annotation-colors:
77
+ - pinnedValues for explicit control over legend order and visible categories
78
+ - __REST__ auto-fill marker to expand top values by frequency
79
+ - zOrderSort to decouple zOrder computation from stored sortMode
80
+ - Value preprocessing (pipe trimming, semicolon splitting) matching the
81
+ ProtSpace web frontend
82
+ - Auto-assign Kelly's palette colors for pinned values, __NA__ key format
83
+ - Comprehensive docs in docs/styling.md, docs/cli.md, and CLI epilog
84
+
85
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ([`530cd3c`](https://github.com/tsenoner/protspace/commit/530cd3c90cb7acbc5ea35f3974eb39d0bb74c34c))
86
+
87
+
4
88
  ## v3.2.0 (2026-02-17)
5
89
 
6
90
  ### Code Style
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: protspace
3
- Version: 3.2.0
3
+ Version: 3.3.1
4
4
  Summary: A visualisation tool for protein embeddings from pLMs
5
5
  Author-email: Tobias Senoner <tobias.senoner@tum.de>
6
6
  License-Expression: GPL-3.0
@@ -59,7 +59,7 @@ protspace-query -q 'organism_name:"Homo sapiens" AND reviewed:true' -m pca2,umap
59
59
 
60
60
  ## `protspace-annotation-colors`
61
61
 
62
- Add custom colors, shapes, and display settings to existing ProtSpace files. See [Annotation Styling](styling.md) for the full styles JSON format.
62
+ Add custom colors, shapes, legend ordering, and display settings to existing ProtSpace files. See [Annotation Styling](styling.md) for the full styles JSON format, including legend ordering with `pinnedValues`.
63
63
 
64
64
  ```bash
65
65
  # Generate a styles template (values in frequency order, empty color placeholders)
@@ -71,6 +71,14 @@ protspace-annotation-colors input.parquetbundle output.parquetbundle --annotatio
71
71
  # Apply styles from an inline JSON string
72
72
  protspace-annotation-colors input.parquetbundle output.parquetbundle --annotation_styles '{"ann": {"colors": {"val": "#FF0000"}}}'
73
73
 
74
+ # Pin specific legend entries with N/A at the end
75
+ protspace-annotation-colors input.parquetbundle output.parquetbundle --annotation_styles \
76
+ '{"ann": {"sortMode": "manual", "zOrderSort": "size-desc", "pinnedValues": ["val1", "val2", ""]}}'
77
+
78
+ # Auto-fill top values by frequency, N/A at end
79
+ protspace-annotation-colors input.parquetbundle output.parquetbundle --annotation_styles \
80
+ '{"ann": {"sortMode": "manual", "zOrderSort": "size-desc", "pinnedValues": ["__REST__", ""]}}'
81
+
74
82
  # Inspect stored settings
75
83
  protspace-annotation-colors data.parquetbundle --dump-settings
76
84
  ```
@@ -0,0 +1,122 @@
1
+ # Annotation Styling
2
+
3
+ Custom colors, shapes, and legend settings for annotation categories.
4
+
5
+ **Two approaches:**
6
+
7
+ - **Web UI** — interactive editing in [ProtSpace Web](https://protspace.app/explore), save to download the updated bundle
8
+ - **CLI** — programmatic via `protspace-annotation-colors` (see [CLI Reference](cli.md#protspace-annotation-colors))
9
+
10
+ ## Workflow
11
+
12
+ ```bash
13
+ # 1. Generate a styles template (values listed in frequency order)
14
+ protspace-annotation-colors data.parquetbundle --generate-template > styles.json
15
+
16
+ # 2. Edit styles.json — fill in colors, adjust settings
17
+
18
+ # 3. Apply styles to produce a new bundle
19
+ protspace-annotation-colors data.parquetbundle styled.parquetbundle --annotation_styles styles.json
20
+
21
+ # 4. Verify stored settings
22
+ protspace-annotation-colors styled.parquetbundle --dump-settings
23
+ ```
24
+
25
+ ## Styles JSON format
26
+
27
+ Top-level keys are annotation names. Each annotation accepts the keys below.
28
+
29
+ | Key | Type | Default | Stored | Description |
30
+ | ------------------- | -------- | ------------- | ------ | ------------------------------------------------------------------------------------------------ |
31
+ | `colors` | `{}` | — | yes | `{value: color}` — hex (`#FF0000`) or rgb (`rgb(255,0,0)`). Empty strings are ignored. |
32
+ | `shapes` | `{}` | — | yes | `{value: shape}` — one of `circle`, `square`, `diamond`, `triangle-up`, `triangle-down`, `plus`. |
33
+ | `sortMode` | string | `"size-desc"` | yes | Legend sort: `size-desc`, `size-asc`, `alpha-asc`, `alpha-desc`, `manual`. |
34
+ | `maxVisibleValues` | int | `10` | yes | Legend entries shown before the "Other" bucket. |
35
+ | `shapeSize` | int | `30` | yes | Marker size in the scatter plot. |
36
+ | `hiddenValues` | string[] | `[]` | yes | Categories hidden from the plot. |
37
+ | `selectedPaletteId` | string | `"kellys"` | yes | Color palette for categories without explicit colors. |
38
+ | `pinnedValues` | string[] | — | no | Ordered list of values for legend positions 0..N-1. See [Legend ordering](#legend-ordering). |
39
+ | `zOrderSort` | string | — | no | Sort mode for zOrder assignment only (overrides `sortMode` for zOrder computation). |
40
+
41
+ **Stored** keys are persisted in the output bundle. **Non-stored** (processing-only) keys are consumed during generation — only their effects (the resulting categories with `zOrder`, `color`, `shape`) are written.
42
+
43
+ ### N/A values
44
+
45
+ Missing values (`""`, `"<NA>"`, `"NaN"`) are normalized automatically — use any form in the styles file. In the output bundle N/A is stored with the key `__NA__` (the frontend's internal format).
46
+
47
+ ### Example: custom colors and shapes
48
+
49
+ ```json
50
+ {
51
+ "major_group": {
52
+ "maxVisibleValues": 6,
53
+ "colors": {
54
+ "Short-chain": "#63CBE5",
55
+ "Long-chain": "#24638F",
56
+ "<NA>": "#C0C0C0"
57
+ },
58
+ "shapes": {
59
+ "Short-chain": "circle",
60
+ "Long-chain": "square"
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Legend ordering
67
+
68
+ By default (`sortMode: "size-desc"`), legend items are sorted by frequency with N/A sorted by its count like any other category. To control which values appear and in what order, use `pinnedValues` with `sortMode: "manual"`.
69
+
70
+ ### How `pinnedValues` works
71
+
72
+ - Each value in the list receives a `zOrder` starting from 0. **Only pinned values** are written into the bundle's categories — the frontend treats everything else as "Other".
73
+ - `sortMode: "manual"` tells the frontend to sort legend items by `zOrder` (i.e., the order you defined).
74
+ - `maxVisibleValues` must match the number of pinned values. Example: 12 families + N/A = 13 entries requires `maxVisibleValues: 13`.
75
+ - Colors are auto-assigned from Kelly's 21 Colors of Maximum Contrast when no explicit `colors` are provided. N/A gets a lighter gray (`#DDDDDD`).
76
+ - Use `""` for N/A in `pinnedValues`.
77
+
78
+ ### `__REST__` auto-fill marker
79
+
80
+ Instead of listing every value, use `"__REST__"` as a placeholder that expands to the top values by frequency (sorted by `zOrderSort`), filling up to `maxVisibleValues`.
81
+
82
+ **Top 9 by frequency + N/A at end** (default `maxVisibleValues=10`):
83
+
84
+ ```json
85
+ {
86
+ "ec": {
87
+ "sortMode": "manual",
88
+ "zOrderSort": "size-desc",
89
+ "pinnedValues": ["__REST__", ""]
90
+ }
91
+ }
92
+ ```
93
+
94
+ **Pin specific values + auto-fill + N/A:**
95
+
96
+ ```json
97
+ {
98
+ "protein_families": {
99
+ "maxVisibleValues": 13,
100
+ "sortMode": "manual",
101
+ "zOrderSort": "size-desc",
102
+ "pinnedValues": ["familyA", "familyB", "__REST__", ""]
103
+ }
104
+ }
105
+ ```
106
+
107
+ Here `familyA` gets zOrder 0, `familyB` zOrder 1, the next 10 top-frequency values fill slots 2–11, and N/A gets slot 12.
108
+
109
+ ### `zOrderSort`
110
+
111
+ Decouples zOrder assignment from the stored `sortMode`. Useful pattern: `zOrderSort: "size-desc"` computes frequency-based zOrders, while `sortMode: "manual"` tells the frontend to display in that order. Without `zOrderSort`, zOrder assignment falls back to `sortMode`.
112
+
113
+ ## Value preprocessing
114
+
115
+ Raw annotation values are preprocessed to match the ProtSpace web frontend **before** settings are applied. **All settings (including `pinnedValues`) must use display names** (after preprocessing).
116
+
117
+ | Delimiter | Behavior | Example |
118
+ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
119
+ | Pipe `\|` | Part after `\|` is a source tag — trimmed for display. Multiple raw variants with the same display name merge into one entry with combined count. | `"familyA\|IC"` → `"familyA"` |
120
+ | Semicolon `;` | Multi-label split — each part becomes a separate entry. The protein counts toward all resulting categories. | `"familyA;familyB"` → `"familyA"` and `"familyB"` |
121
+
122
+ Combined: `"familyA|IC;familyB|SAM"` → split by `;` → `"familyA|IC"`, `"familyB|SAM"` → trim `|` → `"familyA"`, `"familyB"`.