vdjtools 2.1.0__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. {vdjtools-2.1.0 → vdjtools-2.2.0}/PKG-INFO +22 -13
  2. {vdjtools-2.1.0 → vdjtools-2.2.0}/README.md +21 -12
  3. {vdjtools-2.1.0 → vdjtools-2.2.0}/include/vdjtools/model.hpp +7 -0
  4. {vdjtools-2.1.0 → vdjtools-2.2.0}/pyproject.toml +1 -1
  5. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/__init__.py +1 -1
  6. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/biomarker/fisher.py +9 -9
  7. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/biomarker/metaclonotype.py +7 -7
  8. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/cli/__init__.py +2 -2
  9. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/features/kmer.py +5 -5
  10. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/features/physchem.py +12 -11
  11. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/io/__init__.py +18 -4
  12. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/io/batch.py +43 -2
  13. vdjtools-2.2.0/python/vdjtools/io/convert.py +395 -0
  14. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/io/read.py +13 -13
  15. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/io/schema.py +18 -15
  16. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/generate.py +5 -5
  17. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/native.py +43 -0
  18. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/reference.py +95 -4
  19. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/stitch.py +1 -1
  20. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/cluster.py +2 -2
  21. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/fuzzy.py +10 -10
  22. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/metrics.py +4 -4
  23. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/similarity.py +13 -13
  24. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/tcrnet.py +7 -7
  25. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/track.py +2 -2
  26. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/correct.py +7 -7
  27. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/decontaminate.py +3 -3
  28. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/filter.py +7 -7
  29. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/pool.py +13 -13
  30. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/sc/__init__.py +3 -0
  31. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/sc/pair.py +9 -9
  32. vdjtools-2.2.0/python/vdjtools/sc/pgen.py +90 -0
  33. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/sc/read.py +15 -15
  34. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/spectratype.py +4 -4
  35. vdjtools-2.2.0/skills/vdjtools/SKILL.md +99 -0
  36. {vdjtools-2.1.0 → vdjtools-2.2.0}/src/_bindings.cpp +8 -0
  37. {vdjtools-2.1.0 → vdjtools-2.2.0}/src/core.cpp +1 -1
  38. {vdjtools-2.1.0 → vdjtools-2.2.0}/src/pgen.cpp +39 -0
  39. {vdjtools-2.1.0 → vdjtools-2.2.0}/.gitignore +0 -0
  40. {vdjtools-2.1.0 → vdjtools-2.2.0}/CMakeLists.txt +0 -0
  41. {vdjtools-2.1.0 → vdjtools-2.2.0}/LICENSE +0 -0
  42. {vdjtools-2.1.0 → vdjtools-2.2.0}/environment.yml +0 -0
  43. {vdjtools-2.1.0 → vdjtools-2.2.0}/include/vdjtools/core.hpp +0 -0
  44. {vdjtools-2.1.0 → vdjtools-2.2.0}/include/vdjtools/inext.hpp +0 -0
  45. {vdjtools-2.1.0 → vdjtools-2.2.0}/notebooks/model_explorer.py +0 -0
  46. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/biomarker/__init__.py +0 -0
  47. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/cli/__main__.py +0 -0
  48. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/features/__init__.py +0 -0
  49. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/io/cohort.py +0 -0
  50. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/__init__.py +0 -0
  51. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/d2_del.parquet +0 -0
  52. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/d2_gene.parquet +0 -0
  53. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/d_del.parquet +0 -0
  54. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/d_gene.parquet +0 -0
  55. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/dd_dinucl.parquet +0 -0
  56. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/dd_ins.parquet +0 -0
  57. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/dj_dinucl.parquet +0 -0
  58. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/dj_ins.parquet +0 -0
  59. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/genes_d.parquet +0 -0
  60. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/genes_j.parquet +0 -0
  61. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/genes_v.parquet +0 -0
  62. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/j_5_del.parquet +0 -0
  63. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/j_choice.parquet +0 -0
  64. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/manifest.json +0 -0
  65. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/n_d.parquet +0 -0
  66. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/v_3_del.parquet +0 -0
  67. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/v_choice.parquet +0 -0
  68. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/vd_dinucl.parquet +0 -0
  69. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGH/vd_ins.parquet +0 -0
  70. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/genes_j.parquet +0 -0
  71. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/genes_v.parquet +0 -0
  72. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/j_5_del.parquet +0 -0
  73. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/j_choice.parquet +0 -0
  74. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/manifest.json +0 -0
  75. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/v_3_del.parquet +0 -0
  76. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/v_choice.parquet +0 -0
  77. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/vj_dinucl.parquet +0 -0
  78. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGK/vj_ins.parquet +0 -0
  79. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/genes_j.parquet +0 -0
  80. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/genes_v.parquet +0 -0
  81. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/j_5_del.parquet +0 -0
  82. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/j_choice.parquet +0 -0
  83. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/manifest.json +0 -0
  84. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/v_3_del.parquet +0 -0
  85. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/v_choice.parquet +0 -0
  86. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/vj_dinucl.parquet +0 -0
  87. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/IGL/vj_ins.parquet +0 -0
  88. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/genes_j.parquet +0 -0
  89. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/genes_v.parquet +0 -0
  90. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/j_5_del.parquet +0 -0
  91. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/j_choice.parquet +0 -0
  92. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/manifest.json +0 -0
  93. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/v_3_del.parquet +0 -0
  94. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/v_choice.parquet +0 -0
  95. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/vj_dinucl.parquet +0 -0
  96. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRA/vj_ins.parquet +0 -0
  97. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/d2_del.parquet +0 -0
  98. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/d2_gene.parquet +0 -0
  99. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/d_del.parquet +0 -0
  100. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/d_gene.parquet +0 -0
  101. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/dd_dinucl.parquet +0 -0
  102. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/dd_ins.parquet +0 -0
  103. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/dj_dinucl.parquet +0 -0
  104. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/dj_ins.parquet +0 -0
  105. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/genes_d.parquet +0 -0
  106. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/genes_j.parquet +0 -0
  107. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/genes_v.parquet +0 -0
  108. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/j_5_del.parquet +0 -0
  109. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/j_choice.parquet +0 -0
  110. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/manifest.json +0 -0
  111. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/n_d.parquet +0 -0
  112. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/v_3_del.parquet +0 -0
  113. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/v_choice.parquet +0 -0
  114. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/vd_dinucl.parquet +0 -0
  115. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRB/vd_ins.parquet +0 -0
  116. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/d2_del.parquet +0 -0
  117. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/d2_gene.parquet +0 -0
  118. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/d_del.parquet +0 -0
  119. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/d_gene.parquet +0 -0
  120. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/dd_dinucl.parquet +0 -0
  121. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/dd_ins.parquet +0 -0
  122. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/dj_dinucl.parquet +0 -0
  123. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/dj_ins.parquet +0 -0
  124. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/genes_d.parquet +0 -0
  125. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/genes_j.parquet +0 -0
  126. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/genes_v.parquet +0 -0
  127. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/j_5_del.parquet +0 -0
  128. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/j_choice.parquet +0 -0
  129. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/manifest.json +0 -0
  130. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/n_d.parquet +0 -0
  131. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/v_3_del.parquet +0 -0
  132. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/v_choice.parquet +0 -0
  133. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/vd_dinucl.parquet +0 -0
  134. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRD/vd_ins.parquet +0 -0
  135. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/genes_j.parquet +0 -0
  136. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/genes_v.parquet +0 -0
  137. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/j_5_del.parquet +0 -0
  138. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/j_choice.parquet +0 -0
  139. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/manifest.json +0 -0
  140. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/v_3_del.parquet +0 -0
  141. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/v_choice.parquet +0 -0
  142. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/vj_dinucl.parquet +0 -0
  143. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/learned/TRG/vj_ins.parquet +0 -0
  144. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/d_del.parquet +0 -0
  145. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/d_gene.parquet +0 -0
  146. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/dj_dinucl.parquet +0 -0
  147. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/dj_ins.parquet +0 -0
  148. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/genes_d.parquet +0 -0
  149. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/genes_j.parquet +0 -0
  150. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/genes_v.parquet +0 -0
  151. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/j_5_del.parquet +0 -0
  152. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/j_choice.parquet +0 -0
  153. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/manifest.json +0 -0
  154. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/n_d.parquet +0 -0
  155. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/v_3_del.parquet +0 -0
  156. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/v_choice.parquet +0 -0
  157. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/vd_dinucl.parquet +0 -0
  158. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGH/vd_ins.parquet +0 -0
  159. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/genes_j.parquet +0 -0
  160. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/genes_v.parquet +0 -0
  161. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/j_5_del.parquet +0 -0
  162. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/j_choice.parquet +0 -0
  163. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/manifest.json +0 -0
  164. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/v_3_del.parquet +0 -0
  165. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/v_choice.parquet +0 -0
  166. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/vj_dinucl.parquet +0 -0
  167. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGK/vj_ins.parquet +0 -0
  168. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/genes_j.parquet +0 -0
  169. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/genes_v.parquet +0 -0
  170. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/j_5_del.parquet +0 -0
  171. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/j_choice.parquet +0 -0
  172. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/manifest.json +0 -0
  173. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/v_3_del.parquet +0 -0
  174. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/v_choice.parquet +0 -0
  175. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/vj_dinucl.parquet +0 -0
  176. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/IGL/vj_ins.parquet +0 -0
  177. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/genes_j.parquet +0 -0
  178. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/genes_v.parquet +0 -0
  179. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/j_5_del.parquet +0 -0
  180. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/j_choice.parquet +0 -0
  181. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/manifest.json +0 -0
  182. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/v_3_del.parquet +0 -0
  183. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/v_choice.parquet +0 -0
  184. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/vj_dinucl.parquet +0 -0
  185. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRA/vj_ins.parquet +0 -0
  186. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/d_del.parquet +0 -0
  187. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/d_gene.parquet +0 -0
  188. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/dj_dinucl.parquet +0 -0
  189. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/dj_ins.parquet +0 -0
  190. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/genes_d.parquet +0 -0
  191. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/genes_j.parquet +0 -0
  192. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/genes_v.parquet +0 -0
  193. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/j_5_del.parquet +0 -0
  194. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/j_choice.parquet +0 -0
  195. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/manifest.json +0 -0
  196. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/n_d.parquet +0 -0
  197. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/v_3_del.parquet +0 -0
  198. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/v_choice.parquet +0 -0
  199. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/vd_dinucl.parquet +0 -0
  200. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRB/vd_ins.parquet +0 -0
  201. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/d_del.parquet +0 -0
  202. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/d_gene.parquet +0 -0
  203. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/dj_dinucl.parquet +0 -0
  204. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/dj_ins.parquet +0 -0
  205. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/genes_d.parquet +0 -0
  206. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/genes_j.parquet +0 -0
  207. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/genes_v.parquet +0 -0
  208. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/j_5_del.parquet +0 -0
  209. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/j_choice.parquet +0 -0
  210. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/manifest.json +0 -0
  211. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/n_d.parquet +0 -0
  212. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/v_3_del.parquet +0 -0
  213. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/v_choice.parquet +0 -0
  214. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/vd_dinucl.parquet +0 -0
  215. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRD/vd_ins.parquet +0 -0
  216. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/genes_j.parquet +0 -0
  217. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/genes_v.parquet +0 -0
  218. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/j_5_del.parquet +0 -0
  219. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/j_choice.parquet +0 -0
  220. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/manifest.json +0 -0
  221. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/v_3_del.parquet +0 -0
  222. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/v_choice.parquet +0 -0
  223. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/vj_dinucl.parquet +0 -0
  224. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/_bundled/olga/TRG/vj_ins.parquet +0 -0
  225. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/analyze.py +0 -0
  226. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/bundled.py +0 -0
  227. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/data.py +0 -0
  228. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/dd.py +0 -0
  229. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/events.py +0 -0
  230. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/infer.py +0 -0
  231. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/io.py +0 -0
  232. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/model.py +0 -0
  233. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/pgen.py +0 -0
  234. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/model/schema.py +0 -0
  235. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/overlap/__init__.py +0 -0
  236. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/__init__.py +0 -0
  237. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/batch.py +0 -0
  238. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/downsample.py +0 -0
  239. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/preprocess/join.py +0 -0
  240. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/py.typed +0 -0
  241. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/resources/.gitkeep +0 -0
  242. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/resources/aa_property_table.txt +0 -0
  243. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/sc/anndata.py +0 -0
  244. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/sc/cluster_eval.py +0 -0
  245. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/__init__.py +0 -0
  246. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/diversity.py +0 -0
  247. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/inext.py +0 -0
  248. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/rarefaction.py +0 -0
  249. {vdjtools-2.1.0 → vdjtools-2.2.0}/python/vdjtools/stats/usage.py +0 -0
  250. {vdjtools-2.1.0 → vdjtools-2.2.0}/src/inext.cpp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: vdjtools
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: TCR/BCR repertoire analysis — Pgen/generation/inference, diversity, overlap, biomarkers (Python + C++)
5
5
  Keywords: immunology,tcr,bcr,airr,repertoire,pgen,olga,igor,bioinformatics
6
6
  Author-Email: Mikhail Shugay <mikhail.shugay@gmail.com>
@@ -86,10 +86,12 @@ Built on the antigenomics ecosystem:
86
86
  [vdjmatch](https://github.com/antigenomics/vdjmatch) (overlap + TCRnet),
87
87
  [arda](https://github.com/antigenomics/arda) (AIRR annotation + markup repair).
88
88
 
89
- > **Status: v2.0.0 pre-release under active development** (latest: `v2.0.0-alpha.2` the native
90
- > V(D)J model engine). Install a pre-release with `pip install --pre vdjtools`. The legacy v1.x tool
91
- > lives on the [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and
92
- > its releases remain available under the repository tags (`v0.0.1` `1.2.1`).
89
+ > **Status: `v2.2.0`** the native V(D)J model engine plus the full analytics suite (diversity,
90
+ > overlap/TCRnet, preprocessing, biomarkers, single-cell), CDR features, and legacy-format ingestion
91
+ > (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR). Clonotype columns follow the AIRR
92
+ > **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
93
+ > [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
94
+ > remain available under the repository tags (`v0.0.1` … `1.2.1`).
93
95
 
94
96
  ## Install
95
97
 
@@ -129,6 +131,7 @@ model = load_bundled("TRB", source="olga") # or source="learned" (fit to rea
129
131
  native.pgen_nt(model, "TGTGCCAGCAGC...") # nucleotide generation probability (native C++)
130
132
  native.pgen_aa(model, "CASSLAPGATNEKLFF") # amino-acid Pgen (codon-marginalised)
131
133
  native.pgen_aa(model, "CASSLAPGATNEKLFF", mismatches=1) # + the whole Hamming-1 ball
134
+ native.pgen_aa_batch(model, seqs, mismatches=1, threads=0) # Pgen over many CDR3s, thread-parallel (~11×)
132
135
  generate(model, 1000) # sample a repertoire -> polars DataFrame
133
136
  ```
134
137
 
@@ -179,25 +182,31 @@ several times faster, and the built-in models keep the resident set small. Singl
179
182
  | sequence generation | **~32 000 seq/s** | — |
180
183
 
181
184
  Nucleotide Pgen (via the same transfer-matrix DP as the aa path — an in-frame CDR3 is an aa query with
182
- one codon fixed per position) is exact vs OLGA across all loci; the EM E-step parallelises over reads (~6.7× on 8
183
- threads); diversity/rarefaction run on a native iNEXT kernel (bootstrap + parallel batch). Memory
185
+ one codon fixed per position) is exact vs OLGA across all loci. Batched Pgen / 1-mismatch over many
186
+ CDR3s parallelises over sequences (`native.pgen_aa_batch`, **~11× on 16 cores**, bitwise-identical to
187
+ the serial result); the EM E-step parallelises over reads (~6.7× on 8 threads); diversity/rarefaction
188
+ run on a native iNEXT kernel (bootstrap + parallel batch). Memory
184
189
  stays light — **~63 MB** resident for `import vdjtools` plus one loaded model, **~123 MB** with all
185
190
  seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
186
191
  suites (`RUN_BENCHMARK=1`).
187
192
 
188
- ## Capabilities (rolling out by phase — see [ROADMAP.md](ROADMAP.md))
193
+ ## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
189
194
 
195
+ - **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
196
+ readers for native vdjtools, AIRR Rearrangement TSV, and Parquet, plus format-detecting converters
197
+ for MiXcr (v1/2 + v3/4), MiGec, Adaptive immunoSEQ (v1/v2), IMGT/HighV-QUEST, Vidjil, and RTCR
198
+ ([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
190
199
  - **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
191
- 1-mismatch, V/J-agnostic), sequence generation, and EM inference, all in a native (pybind11)
192
- core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal tables,
193
- read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
200
+ 1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
201
+ native (pybind11) core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal
202
+ tables, read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
194
203
  precomputed OLGA + real-data-learned models bundled ([`load_bundled`](python/vdjtools/model/bundled.py)).
195
204
  - **Stats** — diversity (Chao1/Shannon/Simpson/…), spectratype, V/J/VJ usage.
196
205
  - **Features** — CDR physicochemical profiles, k-mer / V+k-mer summaries.
197
- - **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree).
206
+ - **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree), similarity-aware overlap, clustering.
198
207
  - **Preprocess** — downsampling, error-correction, VJ-usage batch-effect correction, pooling/joining.
199
208
  - **Biomarker** — incidence-based association (Fisher) vs HLA / condition / chain-pairing; metaclonotypes.
200
- - **Single-cell** — AIRR Cell / 10x interoperability.
209
+ - **Single-cell** — AIRR Cell / 10x interoperability, chain pairing + QC, and paired α/β Pgen.
201
210
 
202
211
  ## License
203
212
 
@@ -27,10 +27,12 @@ Built on the antigenomics ecosystem:
27
27
  [vdjmatch](https://github.com/antigenomics/vdjmatch) (overlap + TCRnet),
28
28
  [arda](https://github.com/antigenomics/arda) (AIRR annotation + markup repair).
29
29
 
30
- > **Status: v2.0.0 pre-release under active development** (latest: `v2.0.0-alpha.2` the native
31
- > V(D)J model engine). Install a pre-release with `pip install --pre vdjtools`. The legacy v1.x tool
32
- > lives on the [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and
33
- > its releases remain available under the repository tags (`v0.0.1` `1.2.1`).
30
+ > **Status: `v2.2.0`** the native V(D)J model engine plus the full analytics suite (diversity,
31
+ > overlap/TCRnet, preprocessing, biomarkers, single-cell), CDR features, and legacy-format ingestion
32
+ > (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR). Clonotype columns follow the AIRR
33
+ > **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
34
+ > [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
35
+ > remain available under the repository tags (`v0.0.1` … `1.2.1`).
34
36
 
35
37
  ## Install
36
38
 
@@ -70,6 +72,7 @@ model = load_bundled("TRB", source="olga") # or source="learned" (fit to rea
70
72
  native.pgen_nt(model, "TGTGCCAGCAGC...") # nucleotide generation probability (native C++)
71
73
  native.pgen_aa(model, "CASSLAPGATNEKLFF") # amino-acid Pgen (codon-marginalised)
72
74
  native.pgen_aa(model, "CASSLAPGATNEKLFF", mismatches=1) # + the whole Hamming-1 ball
75
+ native.pgen_aa_batch(model, seqs, mismatches=1, threads=0) # Pgen over many CDR3s, thread-parallel (~11×)
73
76
  generate(model, 1000) # sample a repertoire -> polars DataFrame
74
77
  ```
75
78
 
@@ -120,25 +123,31 @@ several times faster, and the built-in models keep the resident set small. Singl
120
123
  | sequence generation | **~32 000 seq/s** | — |
121
124
 
122
125
  Nucleotide Pgen (via the same transfer-matrix DP as the aa path — an in-frame CDR3 is an aa query with
123
- one codon fixed per position) is exact vs OLGA across all loci; the EM E-step parallelises over reads (~6.7× on 8
124
- threads); diversity/rarefaction run on a native iNEXT kernel (bootstrap + parallel batch). Memory
126
+ one codon fixed per position) is exact vs OLGA across all loci. Batched Pgen / 1-mismatch over many
127
+ CDR3s parallelises over sequences (`native.pgen_aa_batch`, **~11× on 16 cores**, bitwise-identical to
128
+ the serial result); the EM E-step parallelises over reads (~6.7× on 8 threads); diversity/rarefaction
129
+ run on a native iNEXT kernel (bootstrap + parallel batch). Memory
125
130
  stays light — **~63 MB** resident for `import vdjtools` plus one loaded model, **~123 MB** with all
126
131
  seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
127
132
  suites (`RUN_BENCHMARK=1`).
128
133
 
129
- ## Capabilities (rolling out by phase — see [ROADMAP.md](ROADMAP.md))
134
+ ## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
130
135
 
136
+ - **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
137
+ readers for native vdjtools, AIRR Rearrangement TSV, and Parquet, plus format-detecting converters
138
+ for MiXcr (v1/2 + v3/4), MiGec, Adaptive immunoSEQ (v1/v2), IMGT/HighV-QUEST, Vidjil, and RTCR
139
+ ([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
131
140
  - **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
132
- 1-mismatch, V/J-agnostic), sequence generation, and EM inference, all in a native (pybind11)
133
- core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal tables,
134
- read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
141
+ 1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
142
+ native (pybind11) core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal
143
+ tables, read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
135
144
  precomputed OLGA + real-data-learned models bundled ([`load_bundled`](python/vdjtools/model/bundled.py)).
136
145
  - **Stats** — diversity (Chao1/Shannon/Simpson/…), spectratype, V/J/VJ usage.
137
146
  - **Features** — CDR physicochemical profiles, k-mer / V+k-mer summaries.
138
- - **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree).
147
+ - **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree), similarity-aware overlap, clustering.
139
148
  - **Preprocess** — downsampling, error-correction, VJ-usage batch-effect correction, pooling/joining.
140
149
  - **Biomarker** — incidence-based association (Fisher) vs HLA / condition / chain-pairing; metaclonotypes.
141
- - **Single-cell** — AIRR Cell / 10x interoperability.
150
+ - **Single-cell** — AIRR Cell / 10x interoperability, chain pairing + QC, and paired α/β Pgen.
142
151
 
143
152
  ## License
144
153
 
@@ -64,6 +64,13 @@ double pgen_aa(const PackedModel& m, const std::string& aa, int v_idx, int j_idx
64
64
  // via the inclusion-exclusion identity over per-position wildcards. v_idx/j_idx as above.
65
65
  double pgen_aa_hamming1(const PackedModel& m, const std::string& aa, int v_idx, int j_idx);
66
66
 
67
+ // Batch aa Pgen over many sequences, parallelized across sequences (mismatches: 0 = exact,
68
+ // 1 = Hamming-1 ball). Bitwise-identical to the per-sequence calls. Per-sequence v/j indices;
69
+ // empty v_idxs/j_idxs → all -1 (gene-agnostic). nthreads=0 → auto (hw-2).
70
+ std::vector<double> pgen_aa_batch(const PackedModel& m, const std::vector<std::string>& seqs,
71
+ const std::vector<int>& v_idxs, const std::vector<int>& j_idxs,
72
+ int mismatches, int nthreads);
73
+
67
74
  // EM soft counts — one accumulator per event realization, laid out like the PackedModel prob
68
75
  // arrays so the Python M-step can renormalize them directly.
69
76
  struct Counts {
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "vdjtools" # if the PyPI name is taken, fall back to a distinct dist name (cf. arda -> arda-mapper)
7
- version = "2.1.0"
7
+ version = "2.2.0"
8
8
  description = "TCR/BCR repertoire analysis — Pgen/generation/inference, diversity, overlap, biomarkers (Python + C++)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -13,5 +13,5 @@ vdjmatch/seqtree) until a feature that needs them is used.
13
13
  """
14
14
  from ._core import hamming
15
15
 
16
- __version__ = "2.1.0"
16
+ __version__ = "2.2.0"
17
17
  __all__ = ["hamming", "__version__"]
@@ -15,8 +15,8 @@ doi:10.1038/ng.3822). A feature is public if it is present in ``>= min_incidence
15
15
 
16
16
  Two axes are exposed as first-class options:
17
17
 
18
- - **V/J match requirement** — the ``key`` tuple. ``(cdr3_aa,)`` matches on CDR3 alone;
19
- ``(cdr3_aa, v_call)`` also requires the V gene; ``(cdr3_aa, v_call, j_call)`` (the
18
+ - **V/J match requirement** — the ``key`` tuple. ``(junction_aa,)`` matches on CDR3 alone;
19
+ ``(junction_aa, v_call)`` also requires the V gene; ``(junction_aa, v_call, j_call)`` (the
20
20
  default, Emerson's definition) requires both.
21
21
  - **exact vs 1-mismatch CDR3 matching** — ``match``. ``"exact"`` groups on the literal
22
22
  key (pure polars, no extra deps). ``"1mm"`` first groups near-variant keys into
@@ -71,8 +71,8 @@ def fisher_association(
71
71
  phenotype: One row per subject with ``sample_id`` and the binary ``pheno_col``
72
72
  (bool / 0-1); subjects with a null label are dropped from both classes.
73
73
  pheno_col: Name of the binary phenotype column in ``phenotype``.
74
- key: Feature key — a subset of ``(cdr3_aa, v_call, j_call)`` (must include
75
- ``cdr3_aa``). This is the **V/J match requirement**.
74
+ key: Feature key — a subset of ``(junction_aa, v_call, j_call)`` (must include
75
+ ``junction_aa``). This is the **V/J match requirement**.
76
76
  match: ``"exact"`` (literal key) or ``"1mm"`` (group near-variants into
77
77
  metaclonotypes first; needs the ``[overlap]`` extra).
78
78
  min_incidence: Minimum number of subjects a feature must appear in to be tested.
@@ -90,7 +90,7 @@ def fisher_association(
90
90
  Hochberg) and ``direction`` (``"enriched"``/``"depleted"``), sorted by ``p_value``.
91
91
 
92
92
  Raises:
93
- ValueError: If ``alternative``/``match`` is unrecognised, ``key`` omits ``cdr3_aa``,
93
+ ValueError: If ``alternative``/``match`` is unrecognised, ``key`` omits ``junction_aa``,
94
94
  or the phenotype has only one class after dropping unknowns.
95
95
  """
96
96
  if alternative not in _ALTERNATIVES:
@@ -98,8 +98,8 @@ def fisher_association(
98
98
  if match not in ("exact", "1mm"):
99
99
  raise ValueError(f"match must be 'exact' or '1mm'; got {match!r}")
100
100
  key = tuple(key)
101
- if S.CDR3_AA not in key:
102
- raise ValueError(f"key must include {S.CDR3_AA!r}; got {key}")
101
+ if S.JUNCTION_AA not in key:
102
+ raise ValueError(f"key must include {S.JUNCTION_AA!r}; got {key}")
103
103
 
104
104
  lf = cohort.lazy()
105
105
 
@@ -115,9 +115,9 @@ def fisher_association(
115
115
  raise ValueError("phenotype has only one class after dropping unknown labels")
116
116
 
117
117
  # Feature engineering: productive filter + allele stripping on the key's V/J columns.
118
- lf = lf.filter(pl.col(S.CDR3_AA).is_not_null())
118
+ lf = lf.filter(pl.col(S.JUNCTION_AA).is_not_null())
119
119
  if productive_only:
120
- lf = lf.filter(~pl.col(S.CDR3_AA).str.contains(r"[*_]"))
120
+ lf = lf.filter(~pl.col(S.JUNCTION_AA).str.contains(r"[*_]"))
121
121
  if strip_allele:
122
122
  for c in (S.V_CALL, S.J_CALL):
123
123
  if c in key:
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
 
18
18
  import polars as pl
19
19
 
20
- from ..io.schema import CDR3_AA, J_CALL, V_CALL
20
+ from ..io.schema import JUNCTION_AA, J_CALL, V_CALL
21
21
 
22
22
  _VDJMATCH_HINT = (
23
23
  "vdjmatch is required for vdjtools.biomarker.metaclonotype; install the extra with "
@@ -39,12 +39,12 @@ def metaclonotypes(clonotypes: pl.DataFrame, *, scope: str = "1,0,0,1",
39
39
  threads: int = 0) -> pl.DataFrame:
40
40
  """Group unique clonotype keys into metaclonotypes by CDR3 edit-scope neighbourhood.
41
41
 
42
- Two keys share a ``meta_id`` iff their ``cdr3_aa`` are within ``scope`` **and** they
42
+ Two keys share a ``meta_id`` iff their ``junction_aa`` are within ``scope`` **and** they
43
43
  share a V call (when ``match_v``) and a J call (when ``match_j``). Grouping is
44
44
  single-linkage (connected components of the neighbour graph).
45
45
 
46
46
  Args:
47
- clonotypes: A clonotype frame; must carry ``cdr3_aa`` and, when the corresponding
47
+ clonotypes: A clonotype frame; must carry ``junction_aa`` and, when the corresponding
48
48
  ``match_*`` flag is set, ``v_call`` / ``j_call``.
49
49
  scope: vdjmatch edit-distance scope ``"subs,ins,dels,total"`` (default one
50
50
  substitution, length-preserving). ``"0,0,0,0"`` reduces to exact grouping.
@@ -53,7 +53,7 @@ def metaclonotypes(clonotypes: pl.DataFrame, *, scope: str = "1,0,0,1",
53
53
  threads: Worker threads for the native search (``0`` = all cores).
54
54
 
55
55
  Returns:
56
- The distinct grouping keys (``cdr3_aa`` plus ``v_call``/``j_call`` as applicable)
56
+ The distinct grouping keys (``junction_aa`` plus ``v_call``/``j_call`` as applicable)
57
57
  with an added ``meta_id`` column (compact 0-based integer, singletons included).
58
58
 
59
59
  Raises:
@@ -67,8 +67,8 @@ def metaclonotypes(clonotypes: pl.DataFrame, *, scope: str = "1,0,0,1",
67
67
  if match_j and J_CALL in clonotypes.columns:
68
68
  group_cols.append(J_CALL)
69
69
 
70
- uniq = (clonotypes.select([CDR3_AA, *group_cols])
71
- .drop_nulls(CDR3_AA)
70
+ uniq = (clonotypes.select([JUNCTION_AA, *group_cols])
71
+ .drop_nulls(JUNCTION_AA)
72
72
  .unique(maintain_order=True)
73
73
  .with_row_index("_gid"))
74
74
  n = uniq.height
@@ -94,7 +94,7 @@ def metaclonotypes(clonotypes: pl.DataFrame, *, scope: str = "1,0,0,1",
94
94
  # union-find over the returned positional pairs. No partition (CDR3-only) => one pass.
95
95
  groups = uniq.group_by(group_cols, maintain_order=True) if group_cols else [((), uniq)]
96
96
  for _, sub in groups:
97
- cdr3s = sub[CDR3_AA].to_list()
97
+ cdr3s = sub[JUNCTION_AA].to_list()
98
98
  if len(cdr3s) < 2:
99
99
  continue
100
100
  gids = sub["_gid"].to_list()
@@ -26,7 +26,7 @@ app = typer.Typer(
26
26
  help="vdjtools — TCR/BCR repertoire analysis: Pgen, sequence generation, diversity, overlap.",
27
27
  )
28
28
 
29
- _SEQ_COLS = ("cdr3_aa", "junction_aa", "cdr3aa", "cdr3_nt", "cdr3nt", "cdr3", "junction")
29
+ _SEQ_COLS = ("junction_aa", "junction_nt", "cdr3_aa", "cdr3_nt", "cdr3aa", "cdr3nt", "cdr3", "junction")
30
30
 
31
31
 
32
32
  # ---------------------------------------------------------------------------- helpers
@@ -165,7 +165,7 @@ def generate(
165
165
  ) -> None:
166
166
  """Sample recombined sequences from a model — like ``olga-generate_sequences``.
167
167
 
168
- Emits ``cdr3_nt, cdr3_aa, v_call, d_call, d2_call, j_call, productive`` (``d2_call`` is the
168
+ Emits ``junction_nt, junction_aa, v_call, d_call, d2_call, j_call, productive`` (``d2_call`` is the
169
169
  tandem D on the learned D-bearing loci; null otherwise).
170
170
  """
171
171
  from vdjtools.model.generate import generate as _generate
@@ -1,6 +1,6 @@
1
1
  """CDR3 amino-acid k-mer profiles and joint V + k-mer + C feature summaries.
2
2
 
3
- K-mers are overlapping sliding windows over ``cdr3_aa``. Each k-mer occurrence
3
+ K-mers are overlapping sliding windows over ``junction_aa``. Each k-mer occurrence
4
4
  carries its clonotype's weight (reads, unique, or frequency); weights are summed.
5
5
  """
6
6
  from __future__ import annotations
@@ -9,7 +9,7 @@ import polars as pl
9
9
 
10
10
  from ..io.schema import (
11
11
  C_CALL,
12
- CDR3_AA,
12
+ JUNCTION_AA,
13
13
  LOCUS,
14
14
  V_CALL,
15
15
  add_locus,
@@ -19,17 +19,17 @@ from ..io.schema import (
19
19
 
20
20
 
21
21
  def _explode_kmers(df: pl.DataFrame, k: int) -> pl.DataFrame:
22
- """Explode each clonotype's ``cdr3_aa`` into overlapping k-mers (column ``kmer``).
22
+ """Explode each clonotype's ``junction_aa`` into overlapping k-mers (column ``kmer``).
23
23
 
24
24
  Rows whose CDR3 is shorter than ``k`` (or null) contribute no k-mers.
25
25
  """
26
26
  if k < 1:
27
27
  raise ValueError(f"k must be >= 1; got {k}")
28
- df = df.with_columns(pl.col(CDR3_AA).str.len_chars().alias("_len"))
28
+ df = df.with_columns(pl.col(JUNCTION_AA).str.len_chars().alias("_len"))
29
29
  df = df.filter(pl.col("_len") >= k) # shorter/null CDR3s yield no k-mers
30
30
  df = df.with_columns(pl.int_ranges(0, pl.col("_len") - k + 1).alias("_pos"))
31
31
  df = df.explode("_pos", empty_as_null=True)
32
- df = df.with_columns(pl.col(CDR3_AA).str.slice(pl.col("_pos"), k).alias("kmer"))
32
+ df = df.with_columns(pl.col(JUNCTION_AA).str.slice(pl.col("_pos"), k).alias("kmer"))
33
33
  return df.drop("_len", "_pos")
34
34
 
35
35
 
@@ -4,12 +4,13 @@ For each clonotype the mean of a property over the residues of a chosen CDR3 reg
4
4
  is computed, then averaged (weighted by reads/frequency, or unweighted) within a
5
5
  group (e.g. per V-J pairing, or per locus).
6
6
 
7
- Region definitions (over ``cdr3_aa``, length ``L``):
8
- ``all`` — the entire CDR3.
9
- ``trimmed`` — ``cdr3_aa[3:-3]`` (conserved-anchor-trimmed core); clonotypes with
10
- ``L <= 6`` have an empty core and are skipped for this region.
11
- ``center`` the middle five residues ``cdr3_aa[L//2-2 : L//2+3]``; clonotypes
12
- with ``L < 5`` are skipped for this region.
7
+ Region definitions (over ``junction_aa``, length ``L``):
8
+
9
+ * ``all`` — the entire CDR3.
10
+ * ``trimmed`` ``junction_aa[3:-3]`` (conserved-anchor-trimmed core); clonotypes with
11
+ ``L <= 6`` have an empty core and are skipped for this region.
12
+ * ``center`` the middle five residues ``junction_aa[L//2-2 : L//2+3]``; clonotypes
13
+ with ``L < 5`` are skipped for this region.
13
14
  """
14
15
  from __future__ import annotations
15
16
 
@@ -19,7 +20,7 @@ from importlib import resources
19
20
 
20
21
  import polars as pl
21
22
 
22
- from ..io.schema import CDR3_AA, LOCUS, add_locus, weight_expr
23
+ from ..io.schema import JUNCTION_AA, LOCUS, add_locus, weight_expr
23
24
 
24
25
  #: Default property subset: Kidera-factor-free physicochemistry + the 10 Kidera factors.
25
26
  DEFAULT_PROPERTIES = (
@@ -49,16 +50,16 @@ def load_property_table() -> pl.DataFrame:
49
50
 
50
51
  def _region_expr(region: str) -> pl.Expr:
51
52
  """Return the CDR3-region substring expression (null where the region is empty)."""
52
- length = pl.col(CDR3_AA).str.len_chars()
53
+ length = pl.col(JUNCTION_AA).str.len_chars()
53
54
  if region == "all":
54
- return pl.col(CDR3_AA)
55
+ return pl.col(JUNCTION_AA)
55
56
  if region == "trimmed":
56
57
  return (pl.when(length > 6)
57
- .then(pl.col(CDR3_AA).str.slice(3, length - 6))
58
+ .then(pl.col(JUNCTION_AA).str.slice(3, length - 6))
58
59
  .otherwise(None))
59
60
  if region == "center":
60
61
  return (pl.when(length >= 5)
61
- .then(pl.col(CDR3_AA).str.slice(length // 2 - 2, 5))
62
+ .then(pl.col(JUNCTION_AA).str.slice(length // 2 - 2, 5))
62
63
  .otherwise(None))
63
64
  raise ValueError(f"region must be 'all', 'trimmed' or 'center'; got {region!r}")
64
65
 
@@ -5,11 +5,19 @@ Readers return the canonical clonotype frame defined in :mod:`vdjtools.io.schema
5
5
  from . import schema
6
6
  from .batch import iter_samples, read, read_metadata, read_samples, sniff_format
7
7
  from .cohort import ingest_cohort, scan_cohort
8
+ from .convert import (
9
+ read_imgt,
10
+ read_immunoseq,
11
+ read_migec,
12
+ read_mixcr,
13
+ read_rtcr,
14
+ read_vidjil,
15
+ )
8
16
  from .read import read_airr, read_parquet, read_vdjtools
9
17
  from .schema import (
10
18
  C_CALL,
11
- CDR3_AA,
12
- CDR3_NT,
19
+ JUNCTION_AA,
20
+ JUNCTION_NT,
13
21
  COLUMNS,
14
22
  COUNT,
15
23
  D_CALL,
@@ -30,6 +38,12 @@ __all__ = [
30
38
  "read_airr",
31
39
  "read_vdjtools",
32
40
  "read_parquet",
41
+ "read_mixcr",
42
+ "read_migec",
43
+ "read_immunoseq",
44
+ "read_imgt",
45
+ "read_vidjil",
46
+ "read_rtcr",
33
47
  "read_metadata",
34
48
  "read_samples",
35
49
  "iter_samples",
@@ -46,8 +60,8 @@ __all__ = [
46
60
  "D_CALL",
47
61
  "J_CALL",
48
62
  "C_CALL",
49
- "CDR3_AA",
50
- "CDR3_NT",
63
+ "JUNCTION_AA",
64
+ "JUNCTION_NT",
51
65
  "COUNT",
52
66
  "FREQ",
53
67
  "LOCUS",
@@ -6,14 +6,23 @@ metadata table into one long clonotype frame (or a per-sample dict).
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
+ import gzip
9
10
  import os
10
11
  from pathlib import Path
11
12
 
12
13
  import polars as pl
13
14
 
15
+ from . import convert
14
16
  from .read import read_airr, read_parquet, read_vdjtools
15
17
  from .schema import COLUMNS, LOCUS
16
18
 
19
+ # Legacy third-party formats (vdjtools.io.convert), keyed by the fmt string used below.
20
+ _CONVERTERS = {
21
+ "mixcr": convert.read_mixcr, "migec": convert.read_migec,
22
+ "immunoseq": convert.read_immunoseq, "imgt": convert.read_imgt,
23
+ "vidjil": convert.read_vidjil, "rtcr": convert.read_rtcr,
24
+ }
25
+
17
26
 
18
27
  def _header_columns(path: str | os.PathLike) -> list[str]:
19
28
  """Return the (lower-cased) header column names of a TSV without reading rows."""
@@ -21,6 +30,15 @@ def _header_columns(path: str | os.PathLike) -> list[str]:
21
30
  return [c.lower() for c in cols]
22
31
 
23
32
 
33
+ def _peek(path: str | os.PathLike, n: int = 8) -> str:
34
+ """Return the first ``n`` characters (gzip-transparent), for JSON detection."""
35
+ with open(path, "rb") as fb:
36
+ gz = fb.read(2) == b"\x1f\x8b"
37
+ opener = gzip.open if gz else open
38
+ with opener(path, "rt", errors="ignore") as f:
39
+ return f.read(n)
40
+
41
+
24
42
  def sniff_format(path: str | os.PathLike) -> str:
25
43
  """Detect a clonotype file's format from its header.
26
44
 
@@ -39,10 +57,26 @@ def sniff_format(path: str | os.PathLike) -> str:
39
57
  """
40
58
  if Path(path).suffix.lower() in (".parquet", ".pq"):
41
59
  return "parquet"
60
+ if Path(path).suffix.lower() in (".vidjil", ".json") or _peek(path).lstrip()[:1] == "{":
61
+ return "vidjil" # Vidjil .vidjil JSON
42
62
  cols = set(_header_columns(path))
63
+ # Specific third-party formats first (their signature columns don't collide with each other).
64
+ if "v-gene and allele" in cols and "junction" in cols:
65
+ return "imgt"
66
+ if "cdr3 nucleotide sequence" in cols and "v segments" in cols:
67
+ return "migec"
68
+ if "number of reads" in cols and "junction nucleotide sequence" in cols:
69
+ return "rtcr"
70
+ if cols & {"all v hits", "allvhitswithscore"} and \
71
+ cols & {"n. seq. cdr3", "nseqcdr3", "nseqimputedcdr3"}:
72
+ return "mixcr"
73
+ if "count (templates/reads)" in cols or ({"rearrangement", "amino_acid"} <= cols
74
+ and "v_gene" in cols):
75
+ return "immunoseq"
76
+ # Native vdjtools / migmap (cdr3nt/cdr3aa headers) and AIRR Rearrangement.
43
77
  if "cdr3aa" in cols or {"count", "cdr3nt"} <= cols:
44
78
  return "vdjtools"
45
- if cols & {"v_call", "junction_aa", "cdr3_aa"}:
79
+ if cols & {"v_call", "junction_aa", "junction_nt", "cdr3_aa"}:
46
80
  return "airr"
47
81
  raise ValueError(f"unrecognised clonotype format; header columns: {sorted(cols)}")
48
82
 
@@ -72,7 +106,14 @@ def read(path: str | os.PathLike, fmt: str = "auto",
72
106
  return read_airr(path, n_rows=n_rows)
73
107
  if fmt == "parquet":
74
108
  return read_parquet(path, n_rows=n_rows)
75
- raise ValueError(f"fmt must be 'auto', 'vdjtools', 'airr' or 'parquet'; got {fmt!r}")
109
+ if fmt == "vidjil":
110
+ return convert.read_vidjil(path) # whole-JSON reader (no row cap)
111
+ if fmt in _CONVERTERS:
112
+ return _CONVERTERS[fmt](path, n_rows=n_rows)
113
+ raise ValueError(
114
+ f"fmt must be 'auto', 'vdjtools', 'airr', 'parquet', or a legacy format "
115
+ f"({', '.join(sorted(_CONVERTERS))}); got {fmt!r}"
116
+ )
76
117
 
77
118
 
78
119
  def read_metadata(path: str | os.PathLike) -> pl.DataFrame: