vdjtools 2.2.0__tar.gz → 2.2.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 (250) hide show
  1. {vdjtools-2.2.0 → vdjtools-2.2.1}/.gitignore +5 -0
  2. {vdjtools-2.2.0 → vdjtools-2.2.1}/PKG-INFO +47 -4
  3. {vdjtools-2.2.0 → vdjtools-2.2.1}/README.md +46 -3
  4. {vdjtools-2.2.0 → vdjtools-2.2.1}/pyproject.toml +1 -1
  5. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/__init__.py +1 -1
  6. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/__init__.py +4 -0
  7. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/batch.py +25 -10
  8. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/convert.py +64 -12
  9. {vdjtools-2.2.0 → vdjtools-2.2.1}/skills/vdjtools/SKILL.md +5 -3
  10. {vdjtools-2.2.0 → vdjtools-2.2.1}/src/core.cpp +1 -1
  11. {vdjtools-2.2.0 → vdjtools-2.2.1}/CMakeLists.txt +0 -0
  12. {vdjtools-2.2.0 → vdjtools-2.2.1}/LICENSE +0 -0
  13. {vdjtools-2.2.0 → vdjtools-2.2.1}/environment.yml +0 -0
  14. {vdjtools-2.2.0 → vdjtools-2.2.1}/include/vdjtools/core.hpp +0 -0
  15. {vdjtools-2.2.0 → vdjtools-2.2.1}/include/vdjtools/inext.hpp +0 -0
  16. {vdjtools-2.2.0 → vdjtools-2.2.1}/include/vdjtools/model.hpp +0 -0
  17. {vdjtools-2.2.0 → vdjtools-2.2.1}/notebooks/model_explorer.py +0 -0
  18. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/biomarker/__init__.py +0 -0
  19. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/biomarker/fisher.py +0 -0
  20. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/biomarker/metaclonotype.py +0 -0
  21. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/cli/__init__.py +0 -0
  22. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/cli/__main__.py +0 -0
  23. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/features/__init__.py +0 -0
  24. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/features/kmer.py +0 -0
  25. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/features/physchem.py +0 -0
  26. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/cohort.py +0 -0
  27. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/read.py +0 -0
  28. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/io/schema.py +0 -0
  29. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/__init__.py +0 -0
  30. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/d2_del.parquet +0 -0
  31. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/d2_gene.parquet +0 -0
  32. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/d_del.parquet +0 -0
  33. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/d_gene.parquet +0 -0
  34. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/dd_dinucl.parquet +0 -0
  35. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/dd_ins.parquet +0 -0
  36. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/dj_dinucl.parquet +0 -0
  37. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/dj_ins.parquet +0 -0
  38. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/genes_d.parquet +0 -0
  39. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/genes_j.parquet +0 -0
  40. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/genes_v.parquet +0 -0
  41. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/j_5_del.parquet +0 -0
  42. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/j_choice.parquet +0 -0
  43. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/manifest.json +0 -0
  44. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/n_d.parquet +0 -0
  45. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/v_3_del.parquet +0 -0
  46. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/v_choice.parquet +0 -0
  47. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/vd_dinucl.parquet +0 -0
  48. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGH/vd_ins.parquet +0 -0
  49. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/genes_j.parquet +0 -0
  50. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/genes_v.parquet +0 -0
  51. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/j_5_del.parquet +0 -0
  52. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/j_choice.parquet +0 -0
  53. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/manifest.json +0 -0
  54. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/v_3_del.parquet +0 -0
  55. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/v_choice.parquet +0 -0
  56. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/vj_dinucl.parquet +0 -0
  57. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGK/vj_ins.parquet +0 -0
  58. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/genes_j.parquet +0 -0
  59. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/genes_v.parquet +0 -0
  60. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/j_5_del.parquet +0 -0
  61. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/j_choice.parquet +0 -0
  62. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/manifest.json +0 -0
  63. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/v_3_del.parquet +0 -0
  64. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/v_choice.parquet +0 -0
  65. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/vj_dinucl.parquet +0 -0
  66. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/IGL/vj_ins.parquet +0 -0
  67. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/genes_j.parquet +0 -0
  68. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/genes_v.parquet +0 -0
  69. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/j_5_del.parquet +0 -0
  70. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/j_choice.parquet +0 -0
  71. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/manifest.json +0 -0
  72. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/v_3_del.parquet +0 -0
  73. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/v_choice.parquet +0 -0
  74. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/vj_dinucl.parquet +0 -0
  75. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRA/vj_ins.parquet +0 -0
  76. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/d2_del.parquet +0 -0
  77. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/d2_gene.parquet +0 -0
  78. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/d_del.parquet +0 -0
  79. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/d_gene.parquet +0 -0
  80. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/dd_dinucl.parquet +0 -0
  81. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/dd_ins.parquet +0 -0
  82. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/dj_dinucl.parquet +0 -0
  83. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/dj_ins.parquet +0 -0
  84. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/genes_d.parquet +0 -0
  85. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/genes_j.parquet +0 -0
  86. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/genes_v.parquet +0 -0
  87. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/j_5_del.parquet +0 -0
  88. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/j_choice.parquet +0 -0
  89. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/manifest.json +0 -0
  90. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/n_d.parquet +0 -0
  91. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/v_3_del.parquet +0 -0
  92. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/v_choice.parquet +0 -0
  93. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/vd_dinucl.parquet +0 -0
  94. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRB/vd_ins.parquet +0 -0
  95. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/d2_del.parquet +0 -0
  96. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/d2_gene.parquet +0 -0
  97. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/d_del.parquet +0 -0
  98. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/d_gene.parquet +0 -0
  99. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/dd_dinucl.parquet +0 -0
  100. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/dd_ins.parquet +0 -0
  101. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/dj_dinucl.parquet +0 -0
  102. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/dj_ins.parquet +0 -0
  103. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/genes_d.parquet +0 -0
  104. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/genes_j.parquet +0 -0
  105. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/genes_v.parquet +0 -0
  106. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/j_5_del.parquet +0 -0
  107. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/j_choice.parquet +0 -0
  108. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/manifest.json +0 -0
  109. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/n_d.parquet +0 -0
  110. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/v_3_del.parquet +0 -0
  111. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/v_choice.parquet +0 -0
  112. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/vd_dinucl.parquet +0 -0
  113. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRD/vd_ins.parquet +0 -0
  114. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/genes_j.parquet +0 -0
  115. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/genes_v.parquet +0 -0
  116. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/j_5_del.parquet +0 -0
  117. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/j_choice.parquet +0 -0
  118. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/manifest.json +0 -0
  119. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/v_3_del.parquet +0 -0
  120. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/v_choice.parquet +0 -0
  121. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/vj_dinucl.parquet +0 -0
  122. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/learned/TRG/vj_ins.parquet +0 -0
  123. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/d_del.parquet +0 -0
  124. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/d_gene.parquet +0 -0
  125. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/dj_dinucl.parquet +0 -0
  126. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/dj_ins.parquet +0 -0
  127. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/genes_d.parquet +0 -0
  128. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/genes_j.parquet +0 -0
  129. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/genes_v.parquet +0 -0
  130. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/j_5_del.parquet +0 -0
  131. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/j_choice.parquet +0 -0
  132. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/manifest.json +0 -0
  133. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/n_d.parquet +0 -0
  134. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/v_3_del.parquet +0 -0
  135. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/v_choice.parquet +0 -0
  136. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/vd_dinucl.parquet +0 -0
  137. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGH/vd_ins.parquet +0 -0
  138. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/genes_j.parquet +0 -0
  139. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/genes_v.parquet +0 -0
  140. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/j_5_del.parquet +0 -0
  141. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/j_choice.parquet +0 -0
  142. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/manifest.json +0 -0
  143. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/v_3_del.parquet +0 -0
  144. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/v_choice.parquet +0 -0
  145. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/vj_dinucl.parquet +0 -0
  146. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGK/vj_ins.parquet +0 -0
  147. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/genes_j.parquet +0 -0
  148. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/genes_v.parquet +0 -0
  149. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/j_5_del.parquet +0 -0
  150. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/j_choice.parquet +0 -0
  151. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/manifest.json +0 -0
  152. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/v_3_del.parquet +0 -0
  153. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/v_choice.parquet +0 -0
  154. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/vj_dinucl.parquet +0 -0
  155. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/IGL/vj_ins.parquet +0 -0
  156. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/genes_j.parquet +0 -0
  157. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/genes_v.parquet +0 -0
  158. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/j_5_del.parquet +0 -0
  159. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/j_choice.parquet +0 -0
  160. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/manifest.json +0 -0
  161. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/v_3_del.parquet +0 -0
  162. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/v_choice.parquet +0 -0
  163. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/vj_dinucl.parquet +0 -0
  164. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRA/vj_ins.parquet +0 -0
  165. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/d_del.parquet +0 -0
  166. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/d_gene.parquet +0 -0
  167. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/dj_dinucl.parquet +0 -0
  168. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/dj_ins.parquet +0 -0
  169. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/genes_d.parquet +0 -0
  170. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/genes_j.parquet +0 -0
  171. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/genes_v.parquet +0 -0
  172. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/j_5_del.parquet +0 -0
  173. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/j_choice.parquet +0 -0
  174. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/manifest.json +0 -0
  175. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/n_d.parquet +0 -0
  176. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/v_3_del.parquet +0 -0
  177. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/v_choice.parquet +0 -0
  178. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/vd_dinucl.parquet +0 -0
  179. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRB/vd_ins.parquet +0 -0
  180. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/d_del.parquet +0 -0
  181. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/d_gene.parquet +0 -0
  182. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/dj_dinucl.parquet +0 -0
  183. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/dj_ins.parquet +0 -0
  184. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/genes_d.parquet +0 -0
  185. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/genes_j.parquet +0 -0
  186. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/genes_v.parquet +0 -0
  187. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/j_5_del.parquet +0 -0
  188. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/j_choice.parquet +0 -0
  189. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/manifest.json +0 -0
  190. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/n_d.parquet +0 -0
  191. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/v_3_del.parquet +0 -0
  192. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/v_choice.parquet +0 -0
  193. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/vd_dinucl.parquet +0 -0
  194. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRD/vd_ins.parquet +0 -0
  195. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/genes_j.parquet +0 -0
  196. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/genes_v.parquet +0 -0
  197. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/j_5_del.parquet +0 -0
  198. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/j_choice.parquet +0 -0
  199. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/manifest.json +0 -0
  200. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/v_3_del.parquet +0 -0
  201. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/v_choice.parquet +0 -0
  202. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/vj_dinucl.parquet +0 -0
  203. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/_bundled/olga/TRG/vj_ins.parquet +0 -0
  204. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/analyze.py +0 -0
  205. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/bundled.py +0 -0
  206. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/data.py +0 -0
  207. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/dd.py +0 -0
  208. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/events.py +0 -0
  209. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/generate.py +0 -0
  210. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/infer.py +0 -0
  211. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/io.py +0 -0
  212. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/model.py +0 -0
  213. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/native.py +0 -0
  214. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/pgen.py +0 -0
  215. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/reference.py +0 -0
  216. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/schema.py +0 -0
  217. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/model/stitch.py +0 -0
  218. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/__init__.py +0 -0
  219. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/cluster.py +0 -0
  220. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/fuzzy.py +0 -0
  221. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/metrics.py +0 -0
  222. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/similarity.py +0 -0
  223. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/tcrnet.py +0 -0
  224. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/overlap/track.py +0 -0
  225. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/__init__.py +0 -0
  226. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/batch.py +0 -0
  227. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/correct.py +0 -0
  228. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/decontaminate.py +0 -0
  229. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/downsample.py +0 -0
  230. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/filter.py +0 -0
  231. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/join.py +0 -0
  232. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/preprocess/pool.py +0 -0
  233. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/py.typed +0 -0
  234. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/resources/.gitkeep +0 -0
  235. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/resources/aa_property_table.txt +0 -0
  236. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/__init__.py +0 -0
  237. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/anndata.py +0 -0
  238. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/cluster_eval.py +0 -0
  239. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/pair.py +0 -0
  240. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/pgen.py +0 -0
  241. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/sc/read.py +0 -0
  242. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/__init__.py +0 -0
  243. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/diversity.py +0 -0
  244. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/inext.py +0 -0
  245. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/rarefaction.py +0 -0
  246. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/spectratype.py +0 -0
  247. {vdjtools-2.2.0 → vdjtools-2.2.1}/python/vdjtools/stats/usage.py +0 -0
  248. {vdjtools-2.2.0 → vdjtools-2.2.1}/src/_bindings.cpp +0 -0
  249. {vdjtools-2.2.0 → vdjtools-2.2.1}/src/inext.cpp +0 -0
  250. {vdjtools-2.2.0 → vdjtools-2.2.1}/src/pgen.cpp +0 -0
@@ -45,3 +45,8 @@ examples/.data/
45
45
 
46
46
  # marimo session/run cache
47
47
  __marimo__/
48
+
49
+ # coverage artifacts
50
+ .coverage
51
+ .coverage.*
52
+ htmlcov/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: vdjtools
3
- Version: 2.2.0
3
+ Version: 2.2.1
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>
@@ -88,7 +88,7 @@ Built on the antigenomics ecosystem:
88
88
 
89
89
  > **Status: `v2.2.0`** — the native V(D)J model engine plus the full analytics suite (diversity,
90
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
91
+ > (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, arda). Clonotype columns follow the AIRR
92
92
  > **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
93
93
  > [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
94
94
  > remain available under the repository tags (`v0.0.1` … `1.2.1`).
@@ -167,6 +167,48 @@ vdjtools spectratype *.tsv -o spectra.tsv
167
167
  Native vdjtools and AIRR Rearrangement inputs are auto-detected; every command writes TSV to `-o`
168
168
  (or stdout, so it pipes). Run `vdjtools <command> --help` for options.
169
169
 
170
+ ## Analytics (Python API)
171
+
172
+ Every reader returns one canonical `polars` clonotype frame (AIRR **junction** columns), and every
173
+ analysis function takes and returns such frames — so results chain together and drop straight into
174
+ plotting. A tour of the analysis modules (full runnable walkthrough in the
175
+ [**User guide**](https://docs.isalgo.dev/vdjtools/usage.html)):
176
+
177
+ ```python
178
+ from vdjtools import io as vio, stats, features, overlap, preprocess
179
+
180
+ # load (auto-detects MiXcr / immunoSEQ / AIRR / native / … and converts), or a whole cohort:
181
+ sample = vio.read("clones.tsv")
182
+ cohort = vio.read_samples(vio.read_metadata("metadata.txt"), base_dir="samples/")
183
+
184
+ # diversity, rarefaction, segment usage, spectratype
185
+ stats.diversity_stats(sample) # observed, Chao1, Shannon, inverse-Simpson, d50, …
186
+ stats.inext(sample, q=(0, 1, 2)) # Hill-number rarefaction/extrapolation + bootstrap CIs
187
+ stats.segment_usage(sample, "v") # V (or "j") usage; stats.spectratype(sample)
188
+
189
+ # CDR3 physicochemistry & k-mers
190
+ features.physchem_profile(sample, region="all")
191
+
192
+ # repertoire overlap & TCRnet (fuzzy/similarity/TCRnet via the [overlap] engine)
193
+ overlap.overlap_metrics(sampleA, sampleB) # F / D / Jaccard / Morisita-Horn …
194
+ overlap.tcrnet(sample) # per-clonotype neighbourhood enrichment
195
+
196
+ # preprocessing: downsample to a common depth, error-correct, filter, pool
197
+ preprocess.downsample(sample, 100_000)
198
+ preprocess.correct(preprocess.filter_functional(sample))
199
+ ```
200
+
201
+ Incidence-based biomarkers (Fisher association, Emerson-2017 design) and single-cell paired-chain
202
+ Pgen are one call each:
203
+
204
+ ```python
205
+ from vdjtools.biomarker import fisher_association
206
+ from vdjtools import sc
207
+
208
+ fisher_association(cohort, phenotype, pheno_col="cmv") # enriched/depleted clonotypes + p-values
209
+ sc.paired_pgen(sc.pair_chains(sc.read_10x("filtered_contig_annotations.csv"))) # pgen_alpha·pgen_beta
210
+ ```
211
+
170
212
  ## Performance
171
213
 
172
214
  The Pgen / generation / EM / diversity hot paths are a native C++ (pybind11) core; everything else is
@@ -190,11 +232,12 @@ stays light — **~63 MB** resident for `import vdjtools` plus one loaded model,
190
232
  seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
191
233
  suites (`RUN_BENCHMARK=1`).
192
234
 
193
- ## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
235
+ ## Capabilities (see the [User guide](https://docs.isalgo.dev/vdjtools/usage.html), the [API reference](https://docs.isalgo.dev/vdjtools/), and [ROADMAP.md](ROADMAP.md))
194
236
 
195
237
  - **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
196
238
  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
239
+ for MiXcr (v1/2 + v3/4, incl. C-gene / BCR isotype), MiGec, Adaptive immunoSEQ (v1/v2),
240
+ IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, and arda AIRR output
198
241
  ([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
199
242
  - **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
200
243
  1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
@@ -29,7 +29,7 @@ Built on the antigenomics ecosystem:
29
29
 
30
30
  > **Status: `v2.2.0`** — the native V(D)J model engine plus the full analytics suite (diversity,
31
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
32
+ > (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, arda). Clonotype columns follow the AIRR
33
33
  > **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
34
34
  > [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
35
35
  > remain available under the repository tags (`v0.0.1` … `1.2.1`).
@@ -108,6 +108,48 @@ vdjtools spectratype *.tsv -o spectra.tsv
108
108
  Native vdjtools and AIRR Rearrangement inputs are auto-detected; every command writes TSV to `-o`
109
109
  (or stdout, so it pipes). Run `vdjtools <command> --help` for options.
110
110
 
111
+ ## Analytics (Python API)
112
+
113
+ Every reader returns one canonical `polars` clonotype frame (AIRR **junction** columns), and every
114
+ analysis function takes and returns such frames — so results chain together and drop straight into
115
+ plotting. A tour of the analysis modules (full runnable walkthrough in the
116
+ [**User guide**](https://docs.isalgo.dev/vdjtools/usage.html)):
117
+
118
+ ```python
119
+ from vdjtools import io as vio, stats, features, overlap, preprocess
120
+
121
+ # load (auto-detects MiXcr / immunoSEQ / AIRR / native / … and converts), or a whole cohort:
122
+ sample = vio.read("clones.tsv")
123
+ cohort = vio.read_samples(vio.read_metadata("metadata.txt"), base_dir="samples/")
124
+
125
+ # diversity, rarefaction, segment usage, spectratype
126
+ stats.diversity_stats(sample) # observed, Chao1, Shannon, inverse-Simpson, d50, …
127
+ stats.inext(sample, q=(0, 1, 2)) # Hill-number rarefaction/extrapolation + bootstrap CIs
128
+ stats.segment_usage(sample, "v") # V (or "j") usage; stats.spectratype(sample)
129
+
130
+ # CDR3 physicochemistry & k-mers
131
+ features.physchem_profile(sample, region="all")
132
+
133
+ # repertoire overlap & TCRnet (fuzzy/similarity/TCRnet via the [overlap] engine)
134
+ overlap.overlap_metrics(sampleA, sampleB) # F / D / Jaccard / Morisita-Horn …
135
+ overlap.tcrnet(sample) # per-clonotype neighbourhood enrichment
136
+
137
+ # preprocessing: downsample to a common depth, error-correct, filter, pool
138
+ preprocess.downsample(sample, 100_000)
139
+ preprocess.correct(preprocess.filter_functional(sample))
140
+ ```
141
+
142
+ Incidence-based biomarkers (Fisher association, Emerson-2017 design) and single-cell paired-chain
143
+ Pgen are one call each:
144
+
145
+ ```python
146
+ from vdjtools.biomarker import fisher_association
147
+ from vdjtools import sc
148
+
149
+ fisher_association(cohort, phenotype, pheno_col="cmv") # enriched/depleted clonotypes + p-values
150
+ sc.paired_pgen(sc.pair_chains(sc.read_10x("filtered_contig_annotations.csv"))) # pgen_alpha·pgen_beta
151
+ ```
152
+
111
153
  ## Performance
112
154
 
113
155
  The Pgen / generation / EM / diversity hot paths are a native C++ (pybind11) core; everything else is
@@ -131,11 +173,12 @@ stays light — **~63 MB** resident for `import vdjtools` plus one loaded model,
131
173
  seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
132
174
  suites (`RUN_BENCHMARK=1`).
133
175
 
134
- ## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
176
+ ## Capabilities (see the [User guide](https://docs.isalgo.dev/vdjtools/usage.html), the [API reference](https://docs.isalgo.dev/vdjtools/), and [ROADMAP.md](ROADMAP.md))
135
177
 
136
178
  - **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
137
179
  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
180
+ for MiXcr (v1/2 + v3/4, incl. C-gene / BCR isotype), MiGec, Adaptive immunoSEQ (v1/v2),
181
+ IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, and arda AIRR output
139
182
  ([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
140
183
  - **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
141
184
  1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
@@ -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.2.0"
7
+ version = "2.2.1"
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.2.0"
16
+ __version__ = "2.2.1"
17
17
  __all__ = ["hamming", "__version__"]
@@ -6,11 +6,13 @@ 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
8
  from .convert import (
9
+ read_arda,
9
10
  read_imgt,
10
11
  read_immunoseq,
11
12
  read_migec,
12
13
  read_mixcr,
13
14
  read_rtcr,
15
+ read_trust4,
14
16
  read_vidjil,
15
17
  )
16
18
  from .read import read_airr, read_parquet, read_vdjtools
@@ -44,6 +46,8 @@ __all__ = [
44
46
  "read_imgt",
45
47
  "read_vidjil",
46
48
  "read_rtcr",
49
+ "read_trust4",
50
+ "read_arda",
47
51
  "read_metadata",
48
52
  "read_samples",
49
53
  "iter_samples",
@@ -21,6 +21,7 @@ _CONVERTERS = {
21
21
  "mixcr": convert.read_mixcr, "migec": convert.read_migec,
22
22
  "immunoseq": convert.read_immunoseq, "imgt": convert.read_imgt,
23
23
  "vidjil": convert.read_vidjil, "rtcr": convert.read_rtcr,
24
+ "trust4": convert.read_trust4, "arda": convert.read_arda,
24
25
  }
25
26
 
26
27
 
@@ -46,14 +47,16 @@ def sniff_format(path: str | os.PathLike) -> str:
46
47
  path: Path to a clonotype table.
47
48
 
48
49
  Returns:
49
- ``"parquet"`` if the path ends in ``.parquet`` / ``.pq`` (detected by
50
- extension, without opening the file), ``"vdjtools"`` if the header looks
51
- like the native vdjtools table (``cdr3aa`` / ``count`` + ``cdr3nt``), or
52
- ``"airr"`` if it looks like AIRR Rearrangement (``v_call`` /
53
- ``junction_aa`` / ``cdr3_aa``).
50
+ The detected format string, one of: ``"parquet"`` (``.parquet`` / ``.pq``
51
+ extension), ``"vidjil"`` (``.vidjil`` / ``.json`` or a leading ``{``),
52
+ ``"imgt"``, ``"migec"``, ``"rtcr"``, ``"mixcr"``, ``"immunoseq"``, ``"trust4"``
53
+ (each by its signature header columns), ``"arda"`` (AIRR + arda's ``d2_call``),
54
+ ``"vdjtools"`` (native table / MigMap — ``cdr3aa`` / ``count`` + ``cdr3nt``), or
55
+ ``"airr"`` (AIRR Rearrangement — ``v_call`` / ``junction_aa`` / ``junction_nt`` /
56
+ ``cdr3_aa``).
54
57
 
55
58
  Raises:
56
- ValueError: If neither signature is recognised.
59
+ ValueError: If no known format signature is recognised.
57
60
  """
58
61
  if Path(path).suffix.lower() in (".parquet", ".pq"):
59
62
  return "parquet"
@@ -73,6 +76,12 @@ def sniff_format(path: str | os.PathLike) -> str:
73
76
  if "count (templates/reads)" in cols or ({"rearrangement", "amino_acid"} <= cols
74
77
  and "v_gene" in cols):
75
78
  return "immunoseq"
79
+ if "cid_full_length" in cols and "cdr3nt" in cols:
80
+ return "trust4" # TRUST4 *_report.tsv (its own cid_full_length column)
81
+ # arda AIRR output — standard AIRR names plus arda's tandem-D ``d2_call`` column;
82
+ # match before plain AIRR so it routes to read_arda (nulls arda's ``""`` empty calls).
83
+ if "d2_call" in cols and cols & {"v_call", "junction_aa", "junction", "cdr3_aa"}:
84
+ return "arda"
76
85
  # Native vdjtools / migmap (cdr3nt/cdr3aa headers) and AIRR Rearrangement.
77
86
  if "cdr3aa" in cols or {"count", "cdr3nt"} <= cols:
78
87
  return "vdjtools"
@@ -86,10 +95,14 @@ def read(path: str | os.PathLike, fmt: str = "auto",
86
95
  """Read a clonotype table, auto-detecting the format by default.
87
96
 
88
97
  Args:
89
- path: Path to a native vdjtools, AIRR Rearrangement, or Parquet table
90
- (``.gz`` ok for the text formats).
98
+ path: Path to a native vdjtools, AIRR Rearrangement, or Parquet table, or a
99
+ third-party tool export (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil,
100
+ RTCR, TRUST4, arda) — see :mod:`vdjtools.io.convert` (``.gz`` ok for the
101
+ text formats).
91
102
  fmt: ``"auto"`` (sniff the header / extension), ``"vdjtools"``, ``"airr"``,
92
- or ``"parquet"``.
103
+ ``"parquet"``, or a legacy format string (``"mixcr"``, ``"migec"``,
104
+ ``"immunoseq"``, ``"imgt"``, ``"vidjil"``, ``"rtcr"``, ``"trust4"``,
105
+ ``"arda"``).
93
106
  n_rows: If given, read at most this many data rows (preview huge files).
94
107
 
95
108
  Returns:
@@ -164,7 +177,9 @@ def iter_samples(metadata: pl.DataFrame, base_dir: str | os.PathLike,
164
177
  """
165
178
  base = Path(base_dir)
166
179
  keep = [*COLUMNS, LOCUS]
167
- reserved = {"sample_id", "file_name"}
180
+ # Exclude the canonical clonotype columns (and the reserved sample tags): a metadata column
181
+ # named e.g. ``locus`` / ``frequency`` / ``duplicate_count`` must NOT overwrite clonotype data.
182
+ reserved = {"sample_id", "file_name", *COLUMNS, LOCUS}
168
183
  meta_cols = [c for c in metadata.columns if c not in reserved and c != sample_col]
169
184
  for row in metadata.iter_rows(named=True):
170
185
  sample = row[sample_col]
@@ -5,12 +5,14 @@ gene-name normalisation and CDR3 handling were lifted verbatim from the Groovy
5
5
  ``com.antigenomics.vdjtools.io.parser`` classes) so third-party tool output can be read
6
6
  straight into the canonical AIRR-junction frame of :mod:`vdjtools.io.schema`:
7
7
 
8
- * **MiXcr** (v1/2 *and* v3/4 header dialects) — :func:`read_mixcr`
8
+ * **MiXcr** (v1/2 *and* v3/4 header dialects, incl. the C-gene / isotype hit) — :func:`read_mixcr`
9
9
  * **MiGec** — :func:`read_migec`
10
10
  * **Adaptive immunoSEQ** v1 and v2 — :func:`read_immunoseq`
11
11
  * **IMGT/HighV-QUEST** — :func:`read_imgt`
12
12
  * **Vidjil** (``.vidjil`` JSON) — :func:`read_vidjil`
13
13
  * **RTCR** — :func:`read_rtcr`
14
+ * **TRUST4** (``*_report.tsv``) — :func:`read_trust4`
15
+ * **arda** (AIRR annotation output) — :func:`read_arda`
14
16
 
15
17
  Every reader returns the canonical frame: V/D/J IMGT calls, ``junction_nt`` / ``junction_aa``
16
18
  (the AIRR junction — conserved Cys104 … Phe/Trp118 anchors **included**, matching the legacy
@@ -28,7 +30,7 @@ from pathlib import Path
28
30
  import polars as pl
29
31
 
30
32
  from . import schema
31
- from .read import _read_tsv
33
+ from .read import _read_tsv, read_airr
32
34
  from .schema import (
33
35
  C_CALL,
34
36
  COUNT,
@@ -39,20 +41,21 @@ from .schema import (
39
41
  V_CALL,
40
42
  )
41
43
 
42
- PLACEHOLDER = "."
43
-
44
44
 
45
45
  def _to_int(*cells) -> int:
46
- """First numeric cell as int (double-then-truncate); none numeric → 0.
46
+ """First cell parsing to a **positive** integer count (double-then-truncate); none → 0.
47
47
 
48
- Variadic to support the legacy count fallback (e.g. Adaptive v1 ``templates`` is often
49
- ``"null"`` and the real count lives in ``reads``).
48
+ Skips non-numeric *and* non-positive cells so the legacy count fallback fires correctly
49
+ e.g. Adaptive immunoSEQ v1 ``templates`` is often ``"null"`` **or** ``"0"`` and the real
50
+ count lives in ``reads``. A genuinely zero count is dropped downstream by :func:`_finalize`.
50
51
  """
51
52
  for x in cells:
52
53
  try:
53
- return int(float(x))
54
+ v = int(float(x))
54
55
  except (TypeError, ValueError):
55
56
  continue
57
+ if v > 0:
58
+ return v
56
59
  return 0
57
60
 
58
61
 
@@ -207,6 +210,7 @@ def read_mixcr(path: str | os.PathLike, n_rows: int | None = None) -> pl.DataFra
207
210
  v_c = _pick(lo, "all v hits", "allvhitswithscore")
208
211
  d_c = _pick(lo, "all d hits", "alldhitswithscore")
209
212
  j_c = _pick(lo, "all j hits", "alljhitswithscore")
213
+ c_c = _pick(lo, "all c hits", "allchitswithscore") # C gene / BCR isotype (v1/2 & v3/4)
210
214
  nt_c = _pick(lo, "n. seq. cdr3", "nseqcdr3", "nseqimputedcdr3")
211
215
  aa_c = _pick(lo, "aa. seq. cdr3", "aaseqcdr3", "aaseqimputedcdr3")
212
216
  if not (count_c and v_c and j_c and nt_c and aa_c):
@@ -216,7 +220,7 @@ def read_mixcr(path: str | os.PathLike, n_rows: int | None = None) -> pl.DataFra
216
220
  cnt = r[count_c]
217
221
  rows.append({
218
222
  V_CALL: extract_vdj(r[v_c]), D_CALL: extract_vdj(r[d_c]) if d_c else None,
219
- J_CALL: extract_vdj(r[j_c]),
223
+ J_CALL: extract_vdj(r[j_c]), C_CALL: extract_vdj(r[c_c]) if c_c else None,
220
224
  JUNCTION_NT: (r[nt_c] or "").upper() or None,
221
225
  JUNCTION_AA: r[aa_c], # MiXcr aa is milib-based — kept verbatim (no unify)
222
226
  COUNT: _to_int(cnt),
@@ -323,7 +327,6 @@ def read_immunoseq(path: str | os.PathLike, n_rows: int | None = None) -> pl.Dat
323
327
  vg, vf, vt = _pick(lo, "vgenename"), _pick(lo, "vfamilyname"), _pick(lo, "vfamilyties")
324
328
  dg, df_, dt = _pick(lo, "dgenename"), _pick(lo, "dfamilyname"), _pick(lo, "dfamilyties")
325
329
  jg, jf, jt = _pick(lo, "jgenename"), _pick(lo, "jfamilyname"), _pick(lo, "jfamilyties")
326
- in_frame = "in"
327
330
  else:
328
331
  count_c, count2_c = _pick(lo, "templates"), _pick(lo, "reads") # templates often "null" → reads
329
332
  full_c, aa_c, frame_c = _pick(lo, "rearrangement"), _pick(lo, "amino_acid"), _pick(lo, "frame_type")
@@ -331,7 +334,6 @@ def read_immunoseq(path: str | os.PathLike, n_rows: int | None = None) -> pl.Dat
331
334
  vg, vf, vt = _pick(lo, "v_gene"), _pick(lo, "v_family"), _pick(lo, "v_family_ties")
332
335
  dg, df_, dt = _pick(lo, "d_gene"), _pick(lo, "d_family"), _pick(lo, "d_family_ties")
333
336
  jg, jf, jt = _pick(lo, "j_gene"), _pick(lo, "j_family"), _pick(lo, "j_family_ties")
334
- in_frame = "in"
335
337
  if not (count_c and full_c and len_c and idx_c and vg and jg):
336
338
  raise ValueError(f"not an immunoSEQ table; have {raw.columns[:6]}…")
337
339
 
@@ -348,7 +350,7 @@ def read_immunoseq(path: str | os.PathLike, n_rows: int | None = None) -> pl.Dat
348
350
  nt = full[start:start + ln].upper() or None
349
351
  status = (_cell(r, frame_c) or "").strip().lower()
350
352
  aa_src = _cell(r, aa_c)
351
- if status == in_frame and aa_src:
353
+ if status == "in" and aa_src:
352
354
  junc_aa = to_unified_cdr3aa(aa_src)
353
355
  else:
354
356
  junc_aa = to_unified_cdr3aa(translate(nt)) if nt else None
@@ -393,3 +395,53 @@ def read_vidjil(path: str | os.PathLike, sample_id: int = 0) -> pl.DataFrame:
393
395
  COUNT: _to_int(cnt),
394
396
  })
395
397
  return _finalize(rows)
398
+
399
+
400
+ def read_trust4(path: str | os.PathLike, n_rows: int | None = None) -> pl.DataFrame:
401
+ """Read a TRUST4 clonotype report (``*_report.tsv``).
402
+
403
+ The TRUST4 report header is
404
+ ``#count frequency CDR3nt CDR3aa V D J C cid cid_full_length``. TRUST4's CDR3
405
+ spans the conserved Cys104 … Phe/Trp118 anchors (anchors **included**), i.e. it is the
406
+ AIRR junction, so ``CDR3nt``/``CDR3aa`` map straight to ``junction_nt``/``junction_aa``
407
+ (the ``_`` stop / ``?`` ambiguous-N markers are collapsed by :func:`to_unified_cdr3aa`).
408
+ ``V``/``D``/``J``/``C`` keep the first allele's gene (``*`` → missing); the C column is
409
+ the BCR isotype (or the TCR constant gene) when the constant region was captured. Rows
410
+ whose CDR3 nt is not clean ``ACGT`` (TRUST4 ``partial`` / ``out_of_frame`` / N-containing)
411
+ are dropped.
412
+ """
413
+ raw = _read_tsv(path, n_rows=n_rows)
414
+ lo = {c.lower().lstrip("#"): c for c in raw.columns} # first column is ``#count``
415
+ count_c = _pick(lo, "count")
416
+ nt_c, aa_c = _pick(lo, "cdr3nt"), _pick(lo, "cdr3aa")
417
+ v_c, d_c, j_c, c_c = _pick(lo, "v"), _pick(lo, "d"), _pick(lo, "j"), _pick(lo, "c")
418
+ if not (count_c and nt_c and aa_c and v_c and j_c):
419
+ raise ValueError(f"not a TRUST4 report (need count / CDR3nt+aa / V,J); have {raw.columns}")
420
+ rows = []
421
+ for r in raw.iter_rows(named=True):
422
+ nt = (r[nt_c] or "").upper()
423
+ if not _ATGC_ONLY.match(nt): # skip TRUST4 partial / out-of-frame / N-containing CDR3s
424
+ continue
425
+ rows.append({
426
+ V_CALL: extract_vdj(r[v_c]), D_CALL: extract_vdj(r[d_c]) if d_c else None,
427
+ J_CALL: extract_vdj(r[j_c]), C_CALL: extract_vdj(r[c_c]) if c_c else None,
428
+ JUNCTION_NT: nt, JUNCTION_AA: to_unified_cdr3aa(r[aa_c]),
429
+ COUNT: _to_int(r[count_c]),
430
+ })
431
+ return _finalize(rows)
432
+
433
+
434
+ def read_arda(path: str | os.PathLike, n_rows: int | None = None) -> pl.DataFrame:
435
+ """Read arda's AIRR annotation output (per-sequence ``*.airr.tsv`` or ``clones.tsv``).
436
+
437
+ arda (AIRR annotation + markup repair) writes standard AIRR Rearrangement column names,
438
+ so this delegates to :func:`~vdjtools.io.read.read_airr` — which maps
439
+ ``v_call``/``d_call``/``j_call``/``c_call`` and ``junction``/``junction_aa`` and collapses
440
+ reads to clonotypes — then nulls the literal ``""`` arda emits for an empty gene call.
441
+ arda's extra columns (``d2_call``, ``c_class``, ``mmseqs2_*``) are ignored.
442
+ """
443
+ df = read_airr(path, n_rows=n_rows)
444
+ return df.with_columns(
445
+ pl.when(pl.col(c).str.strip_chars('"') == "").then(None).otherwise(pl.col(c)).alias(c)
446
+ for c in (D_CALL, C_CALL) if c in df.columns
447
+ )
@@ -28,9 +28,11 @@ Iterating on C++: `cmake --build build/<wheel_tag>` then copy `_core.*.so` into
28
28
 
29
29
  ### `vdjtools.io` — IO, schema, format converters
30
30
  - **Readers**: `read(path, fmt="auto")` (sniffs + dispatches), `read_airr`, `read_vdjtools`,
31
- `read_parquet`; **legacy converters** `read_mixcr` (v1/2+v3/4), `read_migec`, `read_immunoseq`
32
- (Adaptive v1/v2), `read_imgt` (IMGT/HighV-QUEST), `read_vidjil` (JSON), `read_rtcr`
33
- (`vdjtools.io.convert`; ported from the legacy Groovy parsers, incl. Adaptive→IMGT gene conversion).
31
+ `read_parquet`; **converters** `read_mixcr` (v1/2+v3/4, incl. C-gene/BCR isotype), `read_migec`,
32
+ `read_immunoseq` (Adaptive v1/v2), `read_imgt` (IMGT/HighV-QUEST), `read_vidjil` (JSON),
33
+ `read_rtcr`, `read_trust4` (`*_report.tsv`), `read_arda` (arda AIRR output, delegates to
34
+ `read_airr`) (`vdjtools.io.convert`; ported from the legacy Groovy parsers + tool docs, incl.
35
+ Adaptive→IMGT gene conversion).
34
36
  - **Cohorts**: `read_metadata`, `read_samples`, `iter_samples` (streaming), `sniff_format`;
35
37
  `ingest_cohort` / `scan_cohort` (hive-partitioned Parquet, lazy).
36
38
  - **Schema**: `SCHEMA, COLUMNS`, constants `V_CALL D_CALL J_CALL C_CALL JUNCTION_AA JUNCTION_NT COUNT
@@ -11,6 +11,6 @@ int hamming(const std::string& a, const std::string& b) {
11
11
  return d;
12
12
  }
13
13
 
14
- const char* version() { return "2.2.0"; }
14
+ const char* version() { return "2.2.1"; }
15
15
 
16
16
  } // namespace vdjtools
File without changes
File without changes
File without changes