progeny-selector 0.1.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 (575) hide show
  1. progeny_selector-0.1.0/.gitattributes +11 -0
  2. progeny_selector-0.1.0/.gitignore +45 -0
  3. progeny_selector-0.1.0/CHANGELOG.md +126 -0
  4. progeny_selector-0.1.0/CITATION.cff +27 -0
  5. progeny_selector-0.1.0/CODE_OF_CONDUCT.md +132 -0
  6. progeny_selector-0.1.0/CONTRIBUTING.md +45 -0
  7. progeny_selector-0.1.0/LICENSE +21 -0
  8. progeny_selector-0.1.0/PKG-INFO +147 -0
  9. progeny_selector-0.1.0/README.md +108 -0
  10. progeny_selector-0.1.0/SECURITY.md +13 -0
  11. progeny_selector-0.1.0/contract/MANIFEST.sha256 +360 -0
  12. progeny_selector-0.1.0/contract/README.md +20 -0
  13. progeny_selector-0.1.0/contract/VERSION +1 -0
  14. progeny_selector-0.1.0/contract/cases/chrom-natural-order/expected.json +169 -0
  15. progeny_selector-0.1.0/contract/cases/chrom-natural-order/genotypes.csv +9 -0
  16. progeny_selector-0.1.0/contract/cases/chrom-natural-order/samples.csv +4 -0
  17. progeny_selector-0.1.0/contract/cases/chrom-spellings/expected.json +187 -0
  18. progeny_selector-0.1.0/contract/cases/chrom-spellings/genotypes.csv +10 -0
  19. progeny_selector-0.1.0/contract/cases/chrom-spellings/samples.csv +4 -0
  20. progeny_selector-0.1.0/contract/cases/crop-barley-spellings/expected.json +96 -0
  21. progeny_selector-0.1.0/contract/cases/crop-barley-spellings/genotypes.csv +5 -0
  22. progeny_selector-0.1.0/contract/cases/crop-barley-spellings/options.json +3 -0
  23. progeny_selector-0.1.0/contract/cases/crop-barley-spellings/samples.csv +4 -0
  24. progeny_selector-0.1.0/contract/cases/crop-common-bean-spellings/expected.json +96 -0
  25. progeny_selector-0.1.0/contract/cases/crop-common-bean-spellings/genotypes.csv +5 -0
  26. progeny_selector-0.1.0/contract/cases/crop-common-bean-spellings/options.json +3 -0
  27. progeny_selector-0.1.0/contract/cases/crop-common-bean-spellings/samples.csv +4 -0
  28. progeny_selector-0.1.0/contract/cases/crop-cotton-spellings/expected.json +96 -0
  29. progeny_selector-0.1.0/contract/cases/crop-cotton-spellings/genotypes.csv +5 -0
  30. progeny_selector-0.1.0/contract/cases/crop-cotton-spellings/options.json +3 -0
  31. progeny_selector-0.1.0/contract/cases/crop-cotton-spellings/samples.csv +4 -0
  32. progeny_selector-0.1.0/contract/cases/crop-cowpea-spellings/expected.json +97 -0
  33. progeny_selector-0.1.0/contract/cases/crop-cowpea-spellings/genotypes.csv +5 -0
  34. progeny_selector-0.1.0/contract/cases/crop-cowpea-spellings/options.json +3 -0
  35. progeny_selector-0.1.0/contract/cases/crop-cowpea-spellings/samples.csv +4 -0
  36. progeny_selector-0.1.0/contract/cases/crop-maize-spellings/expected.json +96 -0
  37. progeny_selector-0.1.0/contract/cases/crop-maize-spellings/genotypes.csv +5 -0
  38. progeny_selector-0.1.0/contract/cases/crop-maize-spellings/options.json +3 -0
  39. progeny_selector-0.1.0/contract/cases/crop-maize-spellings/samples.csv +4 -0
  40. progeny_selector-0.1.0/contract/cases/crop-oat-spellings/expected.json +97 -0
  41. progeny_selector-0.1.0/contract/cases/crop-oat-spellings/genotypes.csv +5 -0
  42. progeny_selector-0.1.0/contract/cases/crop-oat-spellings/options.json +3 -0
  43. progeny_selector-0.1.0/contract/cases/crop-oat-spellings/samples.csv +4 -0
  44. progeny_selector-0.1.0/contract/cases/crop-pea-spellings/expected.json +97 -0
  45. progeny_selector-0.1.0/contract/cases/crop-pea-spellings/genotypes.csv +5 -0
  46. progeny_selector-0.1.0/contract/cases/crop-pea-spellings/options.json +3 -0
  47. progeny_selector-0.1.0/contract/cases/crop-pea-spellings/samples.csv +4 -0
  48. progeny_selector-0.1.0/contract/cases/crop-peanut-spellings/expected.json +97 -0
  49. progeny_selector-0.1.0/contract/cases/crop-peanut-spellings/genotypes.csv +5 -0
  50. progeny_selector-0.1.0/contract/cases/crop-peanut-spellings/options.json +3 -0
  51. progeny_selector-0.1.0/contract/cases/crop-peanut-spellings/samples.csv +4 -0
  52. progeny_selector-0.1.0/contract/cases/crop-rice-spellings/expected.json +96 -0
  53. progeny_selector-0.1.0/contract/cases/crop-rice-spellings/genotypes.csv +5 -0
  54. progeny_selector-0.1.0/contract/cases/crop-rice-spellings/options.json +3 -0
  55. progeny_selector-0.1.0/contract/cases/crop-rice-spellings/samples.csv +4 -0
  56. progeny_selector-0.1.0/contract/cases/crop-sorghum-spellings/expected.json +96 -0
  57. progeny_selector-0.1.0/contract/cases/crop-sorghum-spellings/genotypes.csv +5 -0
  58. progeny_selector-0.1.0/contract/cases/crop-sorghum-spellings/options.json +3 -0
  59. progeny_selector-0.1.0/contract/cases/crop-sorghum-spellings/samples.csv +4 -0
  60. progeny_selector-0.1.0/contract/cases/crop-soybean-data-store-spellings/expected.json +96 -0
  61. progeny_selector-0.1.0/contract/cases/crop-soybean-data-store-spellings/genotypes.csv +5 -0
  62. progeny_selector-0.1.0/contract/cases/crop-soybean-data-store-spellings/options.json +3 -0
  63. progeny_selector-0.1.0/contract/cases/crop-soybean-data-store-spellings/samples.csv +4 -0
  64. progeny_selector-0.1.0/contract/cases/crop-soybean-spellings/expected.json +96 -0
  65. progeny_selector-0.1.0/contract/cases/crop-soybean-spellings/genotypes.csv +5 -0
  66. progeny_selector-0.1.0/contract/cases/crop-soybean-spellings/options.json +3 -0
  67. progeny_selector-0.1.0/contract/cases/crop-soybean-spellings/samples.csv +4 -0
  68. progeny_selector-0.1.0/contract/cases/crop-sunflower-spellings/expected.json +173 -0
  69. progeny_selector-0.1.0/contract/cases/crop-sunflower-spellings/genotypes.csv +9 -0
  70. progeny_selector-0.1.0/contract/cases/crop-sunflower-spellings/options.json +3 -0
  71. progeny_selector-0.1.0/contract/cases/crop-sunflower-spellings/samples.csv +4 -0
  72. progeny_selector-0.1.0/contract/cases/crop-wheat-spellings/expected.json +96 -0
  73. progeny_selector-0.1.0/contract/cases/crop-wheat-spellings/genotypes.csv +5 -0
  74. progeny_selector-0.1.0/contract/cases/crop-wheat-spellings/options.json +3 -0
  75. progeny_selector-0.1.0/contract/cases/crop-wheat-spellings/samples.csv +4 -0
  76. progeny_selector-0.1.0/contract/cases/err-coded-unknown-cell/expected-error.json +4 -0
  77. progeny_selector-0.1.0/contract/cases/err-coded-unknown-cell/genotypes.csv +3 -0
  78. progeny_selector-0.1.0/contract/cases/err-coded-unknown-cell/samples.csv +5 -0
  79. progeny_selector-0.1.0/contract/cases/err-duplicate-marker/expected-error.json +4 -0
  80. progeny_selector-0.1.0/contract/cases/err-duplicate-marker/genotypes.csv +3 -0
  81. progeny_selector-0.1.0/contract/cases/err-duplicate-marker/samples.csv +4 -0
  82. progeny_selector-0.1.0/contract/cases/err-hapmap-hash-before-header/expected-error.json +4 -0
  83. progeny_selector-0.1.0/contract/cases/err-hapmap-hash-before-header/genotypes.hmp.txt +3 -0
  84. progeny_selector-0.1.0/contract/cases/err-hapmap-hash-before-header/samples.csv +4 -0
  85. progeny_selector-0.1.0/contract/cases/err-hapmap-latin1-byte/expected-error.json +4 -0
  86. progeny_selector-0.1.0/contract/cases/err-hapmap-latin1-byte/genotypes.hmp.txt +3 -0
  87. progeny_selector-0.1.0/contract/cases/err-hapmap-latin1-byte/samples.csv +4 -0
  88. progeny_selector-0.1.0/contract/cases/err-hapmap-nbsp-line-before-header/expected-error.json +4 -0
  89. progeny_selector-0.1.0/contract/cases/err-hapmap-nbsp-line-before-header/genotypes.hmp.txt +3 -0
  90. progeny_selector-0.1.0/contract/cases/err-hapmap-nbsp-line-before-header/samples.csv +4 -0
  91. progeny_selector-0.1.0/contract/cases/err-hapmap-plus/expected-error.json +4 -0
  92. progeny_selector-0.1.0/contract/cases/err-hapmap-plus/genotypes.hmp.txt +2 -0
  93. progeny_selector-0.1.0/contract/cases/err-hapmap-plus/samples.csv +4 -0
  94. progeny_selector-0.1.0/contract/cases/err-hapmap-single-b/expected-error.json +4 -0
  95. progeny_selector-0.1.0/contract/cases/err-hapmap-single-b/genotypes.hmp.txt +2 -0
  96. progeny_selector-0.1.0/contract/cases/err-hapmap-single-b/samples.csv +4 -0
  97. progeny_selector-0.1.0/contract/cases/err-hapmap-unknown-cell/expected-error.json +4 -0
  98. progeny_selector-0.1.0/contract/cases/err-hapmap-unknown-cell/genotypes.hmp.txt +2 -0
  99. progeny_selector-0.1.0/contract/cases/err-hapmap-unknown-cell/samples.csv +4 -0
  100. progeny_selector-0.1.0/contract/cases/err-markers-latin1-byte/expected-error.json +4 -0
  101. progeny_selector-0.1.0/contract/cases/err-markers-latin1-byte/genotypes.csv +3 -0
  102. progeny_selector-0.1.0/contract/cases/err-markers-latin1-byte/markers.csv +3 -0
  103. progeny_selector-0.1.0/contract/cases/err-markers-latin1-byte/samples.csv +4 -0
  104. progeny_selector-0.1.0/contract/cases/err-markers-unterminated-quote/expected-error.json +4 -0
  105. progeny_selector-0.1.0/contract/cases/err-markers-unterminated-quote/genotypes.csv +3 -0
  106. progeny_selector-0.1.0/contract/cases/err-markers-unterminated-quote/markers.csv +3 -0
  107. progeny_selector-0.1.0/contract/cases/err-markers-unterminated-quote/samples.csv +4 -0
  108. progeny_selector-0.1.0/contract/cases/err-nucleotide-pair-stray/expected-error.json +4 -0
  109. progeny_selector-0.1.0/contract/cases/err-nucleotide-pair-stray/genotypes.csv +2 -0
  110. progeny_selector-0.1.0/contract/cases/err-nucleotide-pair-stray/samples.csv +4 -0
  111. progeny_selector-0.1.0/contract/cases/err-nucleotide-single-h/expected-error.json +4 -0
  112. progeny_selector-0.1.0/contract/cases/err-nucleotide-single-h/genotypes.csv +2 -0
  113. progeny_selector-0.1.0/contract/cases/err-nucleotide-single-h/samples.csv +4 -0
  114. progeny_selector-0.1.0/contract/cases/err-nucleotide-unknown-cell/expected-error.json +4 -0
  115. progeny_selector-0.1.0/contract/cases/err-nucleotide-unknown-cell/genotypes.csv +2 -0
  116. progeny_selector-0.1.0/contract/cases/err-nucleotide-unknown-cell/samples.csv +4 -0
  117. progeny_selector-0.1.0/contract/cases/err-nucleotide-xx/expected-error.json +4 -0
  118. progeny_selector-0.1.0/contract/cases/err-nucleotide-xx/genotypes.csv +2 -0
  119. progeny_selector-0.1.0/contract/cases/err-nucleotide-xx/samples.csv +4 -0
  120. progeny_selector-0.1.0/contract/cases/err-nucleotide-zero/expected-error.json +4 -0
  121. progeny_selector-0.1.0/contract/cases/err-nucleotide-zero/genotypes.csv +2 -0
  122. progeny_selector-0.1.0/contract/cases/err-nucleotide-zero/samples.csv +4 -0
  123. progeny_selector-0.1.0/contract/cases/err-position-fraction/expected-error.json +4 -0
  124. progeny_selector-0.1.0/contract/cases/err-position-fraction/genotypes.csv +3 -0
  125. progeny_selector-0.1.0/contract/cases/err-position-fraction/samples.csv +4 -0
  126. progeny_selector-0.1.0/contract/cases/err-profile-ambiguous-het/expected-error.json +4 -0
  127. progeny_selector-0.1.0/contract/cases/err-profile-ambiguous-het/genotypes.csv +2 -0
  128. progeny_selector-0.1.0/contract/cases/err-profile-ambiguous-het/options.json +3 -0
  129. progeny_selector-0.1.0/contract/cases/err-profile-ambiguous-het/samples.csv +4 -0
  130. progeny_selector-0.1.0/contract/cases/err-profile-none-half-missing-pair/expected-error.json +4 -0
  131. progeny_selector-0.1.0/contract/cases/err-profile-none-half-missing-pair/genotypes.csv +2 -0
  132. progeny_selector-0.1.0/contract/cases/err-profile-none-half-missing-pair/options.json +3 -0
  133. progeny_selector-0.1.0/contract/cases/err-profile-none-half-missing-pair/samples.csv +4 -0
  134. progeny_selector-0.1.0/contract/cases/err-profile-none-two-missing-pair/expected-error.json +4 -0
  135. progeny_selector-0.1.0/contract/cases/err-profile-none-two-missing-pair/genotypes.csv +2 -0
  136. progeny_selector-0.1.0/contract/cases/err-profile-none-two-missing-pair/options.json +3 -0
  137. progeny_selector-0.1.0/contract/cases/err-profile-none-two-missing-pair/samples.csv +4 -0
  138. progeny_selector-0.1.0/contract/cases/err-profile-nucleotide-on-coded/expected-error.json +4 -0
  139. progeny_selector-0.1.0/contract/cases/err-profile-nucleotide-on-coded/genotypes.csv +3 -0
  140. progeny_selector-0.1.0/contract/cases/err-profile-nucleotide-on-coded/options.json +3 -0
  141. progeny_selector-0.1.0/contract/cases/err-profile-nucleotide-on-coded/samples.csv +4 -0
  142. progeny_selector-0.1.0/contract/cases/err-profile-with-vcf/expected-error.json +4 -0
  143. progeny_selector-0.1.0/contract/cases/err-profile-with-vcf/genotypes.vcf +7 -0
  144. progeny_selector-0.1.0/contract/cases/err-profile-with-vcf/options.json +3 -0
  145. progeny_selector-0.1.0/contract/cases/err-profile-with-vcf/samples.csv +4 -0
  146. progeny_selector-0.1.0/contract/cases/err-sample-missing/expected-error.json +4 -0
  147. progeny_selector-0.1.0/contract/cases/err-sample-missing/genotypes.csv +3 -0
  148. progeny_selector-0.1.0/contract/cases/err-sample-missing/samples.csv +5 -0
  149. progeny_selector-0.1.0/contract/cases/err-samples-hash-row/expected-error.json +4 -0
  150. progeny_selector-0.1.0/contract/cases/err-samples-hash-row/genotypes.csv +3 -0
  151. progeny_selector-0.1.0/contract/cases/err-samples-hash-row/samples.csv +4 -0
  152. progeny_selector-0.1.0/contract/cases/err-samples-latin1-byte/expected-error.json +4 -0
  153. progeny_selector-0.1.0/contract/cases/err-samples-latin1-byte/genotypes.csv +3 -0
  154. progeny_selector-0.1.0/contract/cases/err-samples-latin1-byte/samples.csv +4 -0
  155. progeny_selector-0.1.0/contract/cases/err-two-recurrent-parents/expected-error.json +4 -0
  156. progeny_selector-0.1.0/contract/cases/err-two-recurrent-parents/genotypes.csv +3 -0
  157. progeny_selector-0.1.0/contract/cases/err-two-recurrent-parents/samples.csv +4 -0
  158. progeny_selector-0.1.0/contract/cases/err-unknown-role/expected-error.json +4 -0
  159. progeny_selector-0.1.0/contract/cases/err-unknown-role/genotypes.csv +3 -0
  160. progeny_selector-0.1.0/contract/cases/err-unknown-role/samples.csv +4 -0
  161. progeny_selector-0.1.0/contract/cases/err-vcf-gt-empty-side/expected-error.json +4 -0
  162. progeny_selector-0.1.0/contract/cases/err-vcf-gt-empty-side/genotypes.vcf +4 -0
  163. progeny_selector-0.1.0/contract/cases/err-vcf-gt-empty-side/samples.csv +4 -0
  164. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exceeds-alt/expected-error.json +4 -0
  165. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exceeds-alt/genotypes.vcf +4 -0
  166. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exceeds-alt/samples.csv +4 -0
  167. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exponent/expected-error.json +4 -0
  168. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exponent/genotypes.vcf +4 -0
  169. progeny_selector-0.1.0/contract/cases/err-vcf-gt-exponent/samples.csv +4 -0
  170. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-phase/expected-error.json +4 -0
  171. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-phase/genotypes.vcf +4 -0
  172. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-phase/samples.csv +4 -0
  173. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-zero/expected-error.json +4 -0
  174. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-zero/genotypes.vcf +4 -0
  175. progeny_selector-0.1.0/contract/cases/err-vcf-gt-leading-zero/samples.csv +4 -0
  176. progeny_selector-0.1.0/contract/cases/err-vcf-gt-negative/expected-error.json +4 -0
  177. progeny_selector-0.1.0/contract/cases/err-vcf-gt-negative/genotypes.vcf +4 -0
  178. progeny_selector-0.1.0/contract/cases/err-vcf-gt-negative/samples.csv +4 -0
  179. progeny_selector-0.1.0/contract/cases/err-vcf-gt-triploid/expected-error.json +4 -0
  180. progeny_selector-0.1.0/contract/cases/err-vcf-gt-triploid/genotypes.vcf +4 -0
  181. progeny_selector-0.1.0/contract/cases/err-vcf-gt-triploid/samples.csv +4 -0
  182. progeny_selector-0.1.0/contract/cases/err-vcf-gt-underscore/expected-error.json +4 -0
  183. progeny_selector-0.1.0/contract/cases/err-vcf-gt-underscore/genotypes.vcf +4 -0
  184. progeny_selector-0.1.0/contract/cases/err-vcf-gt-underscore/samples.csv +4 -0
  185. progeny_selector-0.1.0/contract/cases/err-vcf-gzip-latin1-byte/expected-error.json +4 -0
  186. progeny_selector-0.1.0/contract/cases/err-vcf-gzip-latin1-byte/genotypes.vcf.gz +0 -0
  187. progeny_selector-0.1.0/contract/cases/err-vcf-gzip-latin1-byte/samples.csv +4 -0
  188. progeny_selector-0.1.0/contract/cases/err-vcf-hash-line-after-header/expected-error.json +4 -0
  189. progeny_selector-0.1.0/contract/cases/err-vcf-hash-line-after-header/genotypes.vcf +5 -0
  190. progeny_selector-0.1.0/contract/cases/err-vcf-hash-line-after-header/samples.csv +4 -0
  191. progeny_selector-0.1.0/contract/cases/err-vcf-latin1-byte/expected-error.json +4 -0
  192. progeny_selector-0.1.0/contract/cases/err-vcf-latin1-byte/genotypes.vcf +4 -0
  193. progeny_selector-0.1.0/contract/cases/err-vcf-latin1-byte/samples.csv +4 -0
  194. progeny_selector-0.1.0/contract/cases/err-vcf-overlong-byte/expected-error.json +4 -0
  195. progeny_selector-0.1.0/contract/cases/err-vcf-overlong-byte/genotypes.vcf +4 -0
  196. progeny_selector-0.1.0/contract/cases/err-vcf-overlong-byte/samples.csv +4 -0
  197. progeny_selector-0.1.0/contract/cases/err-vcf-position-float/expected-error.json +4 -0
  198. progeny_selector-0.1.0/contract/cases/err-vcf-position-float/genotypes.vcf +3 -0
  199. progeny_selector-0.1.0/contract/cases/err-vcf-position-float/samples.csv +4 -0
  200. progeny_selector-0.1.0/contract/cases/err-vcf-second-header/expected-error.json +4 -0
  201. progeny_selector-0.1.0/contract/cases/err-vcf-second-header/genotypes.vcf +5 -0
  202. progeny_selector-0.1.0/contract/cases/err-vcf-second-header/samples.csv +4 -0
  203. progeny_selector-0.1.0/contract/cases/err-vcf-surrogate-byte/expected-error.json +4 -0
  204. progeny_selector-0.1.0/contract/cases/err-vcf-surrogate-byte/genotypes.vcf +4 -0
  205. progeny_selector-0.1.0/contract/cases/err-vcf-surrogate-byte/samples.csv +4 -0
  206. progeny_selector-0.1.0/contract/cases/err-vcf-truncated-sequence-at-eof/expected-error.json +4 -0
  207. progeny_selector-0.1.0/contract/cases/err-vcf-truncated-sequence-at-eof/genotypes.vcf +4 -0
  208. progeny_selector-0.1.0/contract/cases/err-vcf-truncated-sequence-at-eof/samples.csv +4 -0
  209. progeny_selector-0.1.0/contract/cases/err-wide-latin1-byte/expected-error.json +4 -0
  210. progeny_selector-0.1.0/contract/cases/err-wide-latin1-byte/genotypes.csv +3 -0
  211. progeny_selector-0.1.0/contract/cases/err-wide-latin1-byte/samples.csv +4 -0
  212. progeny_selector-0.1.0/contract/cases/hapmap-blank-lines-skipped/expected.json +58 -0
  213. progeny_selector-0.1.0/contract/cases/hapmap-blank-lines-skipped/genotypes.hmp.txt +6 -0
  214. progeny_selector-0.1.0/contract/cases/hapmap-blank-lines-skipped/samples.csv +4 -0
  215. progeny_selector-0.1.0/contract/cases/hapmap-half-missing-pair/expected.json +89 -0
  216. progeny_selector-0.1.0/contract/cases/hapmap-half-missing-pair/genotypes.hmp.txt +5 -0
  217. progeny_selector-0.1.0/contract/cases/hapmap-half-missing-pair/samples.csv +5 -0
  218. progeny_selector-0.1.0/contract/cases/hapmap-iupac/expected.json +166 -0
  219. progeny_selector-0.1.0/contract/cases/hapmap-iupac/genotypes.hmp.txt +7 -0
  220. progeny_selector-0.1.0/contract/cases/hapmap-iupac/samples.csv +6 -0
  221. progeny_selector-0.1.0/contract/cases/hapmap-missing-na-dot/expected.json +102 -0
  222. progeny_selector-0.1.0/contract/cases/hapmap-missing-na-dot/genotypes.hmp.txt +6 -0
  223. progeny_selector-0.1.0/contract/cases/hapmap-missing-na-dot/samples.csv +5 -0
  224. progeny_selector-0.1.0/contract/cases/hapmap-position-whole-float/expected.json +58 -0
  225. progeny_selector-0.1.0/contract/cases/hapmap-position-whole-float/genotypes.hmp.txt +3 -0
  226. progeny_selector-0.1.0/contract/cases/hapmap-position-whole-float/samples.csv +4 -0
  227. progeny_selector-0.1.0/contract/cases/hapmap-two-missing-pair/expected.json +73 -0
  228. progeny_selector-0.1.0/contract/cases/hapmap-two-missing-pair/genotypes.hmp.txt +4 -0
  229. progeny_selector-0.1.0/contract/cases/hapmap-two-missing-pair/samples.csv +5 -0
  230. progeny_selector-0.1.0/contract/cases/markers-blank-rows-skipped/expected.json +58 -0
  231. progeny_selector-0.1.0/contract/cases/markers-blank-rows-skipped/genotypes.csv +3 -0
  232. progeny_selector-0.1.0/contract/cases/markers-blank-rows-skipped/markers.csv +5 -0
  233. progeny_selector-0.1.0/contract/cases/markers-blank-rows-skipped/samples.csv +4 -0
  234. progeny_selector-0.1.0/contract/cases/markers-override-partial-cm/expected.json +94 -0
  235. progeny_selector-0.1.0/contract/cases/markers-override-partial-cm/genotypes.csv +5 -0
  236. progeny_selector-0.1.0/contract/cases/markers-override-partial-cm/markers.csv +4 -0
  237. progeny_selector-0.1.0/contract/cases/markers-override-partial-cm/samples.csv +4 -0
  238. progeny_selector-0.1.0/contract/cases/profile-axiom-wide/expected.json +55 -0
  239. progeny_selector-0.1.0/contract/cases/profile-axiom-wide/genotypes.csv +3 -0
  240. progeny_selector-0.1.0/contract/cases/profile-axiom-wide/options.json +3 -0
  241. progeny_selector-0.1.0/contract/cases/profile-axiom-wide/samples.csv +4 -0
  242. progeny_selector-0.1.0/contract/cases/profile-dart-wide/expected.json +55 -0
  243. progeny_selector-0.1.0/contract/cases/profile-dart-wide/genotypes.csv +3 -0
  244. progeny_selector-0.1.0/contract/cases/profile-dart-wide/options.json +3 -0
  245. progeny_selector-0.1.0/contract/cases/profile-dart-wide/samples.csv +4 -0
  246. progeny_selector-0.1.0/contract/cases/profile-kasp-wide/expected.json +55 -0
  247. progeny_selector-0.1.0/contract/cases/profile-kasp-wide/genotypes.csv +3 -0
  248. progeny_selector-0.1.0/contract/cases/profile-kasp-wide/options.json +3 -0
  249. progeny_selector-0.1.0/contract/cases/profile-kasp-wide/samples.csv +4 -0
  250. progeny_selector-0.1.0/contract/cases/profile-soybase-report-hapmap/expected.json +73 -0
  251. progeny_selector-0.1.0/contract/cases/profile-soybase-report-hapmap/genotypes.hmp.txt +4 -0
  252. progeny_selector-0.1.0/contract/cases/profile-soybase-report-hapmap/options.json +3 -0
  253. progeny_selector-0.1.0/contract/cases/profile-soybase-report-hapmap/samples.csv +4 -0
  254. progeny_selector-0.1.0/contract/cases/profile-soybase-report-wide/expected.json +55 -0
  255. progeny_selector-0.1.0/contract/cases/profile-soybase-report-wide/genotypes.csv +3 -0
  256. progeny_selector-0.1.0/contract/cases/profile-soybase-report-wide/options.json +3 -0
  257. progeny_selector-0.1.0/contract/cases/profile-soybase-report-wide/samples.csv +4 -0
  258. progeny_selector-0.1.0/contract/cases/profile-tassel-half-missing-pair/expected.json +57 -0
  259. progeny_selector-0.1.0/contract/cases/profile-tassel-half-missing-pair/genotypes.csv +3 -0
  260. progeny_selector-0.1.0/contract/cases/profile-tassel-half-missing-pair/options.json +3 -0
  261. progeny_selector-0.1.0/contract/cases/profile-tassel-half-missing-pair/samples.csv +5 -0
  262. progeny_selector-0.1.0/contract/cases/profile-tassel-two-missing-pair/expected.json +57 -0
  263. progeny_selector-0.1.0/contract/cases/profile-tassel-two-missing-pair/genotypes.csv +3 -0
  264. progeny_selector-0.1.0/contract/cases/profile-tassel-two-missing-pair/options.json +3 -0
  265. progeny_selector-0.1.0/contract/cases/profile-tassel-two-missing-pair/samples.csv +5 -0
  266. progeny_selector-0.1.0/contract/cases/profile-tassel-wide/expected.json +52 -0
  267. progeny_selector-0.1.0/contract/cases/profile-tassel-wide/genotypes.csv +3 -0
  268. progeny_selector-0.1.0/contract/cases/profile-tassel-wide/options.json +3 -0
  269. progeny_selector-0.1.0/contract/cases/profile-tassel-wide/samples.csv +4 -0
  270. progeny_selector-0.1.0/contract/cases/samples-blank-rows-skipped/expected.json +58 -0
  271. progeny_selector-0.1.0/contract/cases/samples-blank-rows-skipped/genotypes.csv +3 -0
  272. progeny_selector-0.1.0/contract/cases/samples-blank-rows-skipped/samples.csv +7 -0
  273. progeny_selector-0.1.0/contract/cases/samples-manifest-defaults/expected.json +69 -0
  274. progeny_selector-0.1.0/contract/cases/samples-manifest-defaults/genotypes.csv +3 -0
  275. progeny_selector-0.1.0/contract/cases/samples-manifest-defaults/samples.csv +5 -0
  276. progeny_selector-0.1.0/contract/cases/samples-midfield-quote-literal/expected.json +58 -0
  277. progeny_selector-0.1.0/contract/cases/samples-midfield-quote-literal/genotypes.csv +3 -0
  278. progeny_selector-0.1.0/contract/cases/samples-midfield-quote-literal/markers.csv +3 -0
  279. progeny_selector-0.1.0/contract/cases/samples-midfield-quote-literal/samples.csv +4 -0
  280. progeny_selector-0.1.0/contract/cases/samples-quoted-fields/expected.json +58 -0
  281. progeny_selector-0.1.0/contract/cases/samples-quoted-fields/genotypes.csv +3 -0
  282. progeny_selector-0.1.0/contract/cases/samples-quoted-fields/samples.csv +4 -0
  283. progeny_selector-0.1.0/contract/cases/samples-quoted-newline/expected.json +58 -0
  284. progeny_selector-0.1.0/contract/cases/samples-quoted-newline/genotypes.csv +3 -0
  285. progeny_selector-0.1.0/contract/cases/samples-quoted-newline/samples.csv +5 -0
  286. progeny_selector-0.1.0/contract/cases/vcf-basic/expected.json +104 -0
  287. progeny_selector-0.1.0/contract/cases/vcf-basic/genotypes.vcf +7 -0
  288. progeny_selector-0.1.0/contract/cases/vcf-basic/samples.csv +5 -0
  289. progeny_selector-0.1.0/contract/cases/vcf-bgzip-two-members-eof/expected.json +73 -0
  290. progeny_selector-0.1.0/contract/cases/vcf-bgzip-two-members-eof/genotypes.vcf.gz +0 -0
  291. progeny_selector-0.1.0/contract/cases/vcf-bgzip-two-members-eof/samples.csv +4 -0
  292. progeny_selector-0.1.0/contract/cases/vcf-bgzip-utf8-split-across-members/expected.json +73 -0
  293. progeny_selector-0.1.0/contract/cases/vcf-bgzip-utf8-split-across-members/genotypes.vcf.gz +0 -0
  294. progeny_selector-0.1.0/contract/cases/vcf-bgzip-utf8-split-across-members/samples.csv +4 -0
  295. progeny_selector-0.1.0/contract/cases/vcf-blank-lines-skipped/expected.json +58 -0
  296. progeny_selector-0.1.0/contract/cases/vcf-blank-lines-skipped/genotypes.vcf +8 -0
  297. progeny_selector-0.1.0/contract/cases/vcf-blank-lines-skipped/samples.csv +4 -0
  298. progeny_selector-0.1.0/contract/cases/vcf-gt-haploid-and-missing/expected.json +133 -0
  299. progeny_selector-0.1.0/contract/cases/vcf-gt-haploid-and-missing/genotypes.vcf +9 -0
  300. progeny_selector-0.1.0/contract/cases/vcf-gt-haploid-and-missing/samples.csv +4 -0
  301. progeny_selector-0.1.0/contract/cases/vcf-gt-multiallelic-index/expected.json +40 -0
  302. progeny_selector-0.1.0/contract/cases/vcf-gt-multiallelic-index/genotypes.vcf +3 -0
  303. progeny_selector-0.1.0/contract/cases/vcf-gt-multiallelic-index/samples.csv +4 -0
  304. progeny_selector-0.1.0/contract/cases/vcf-gzip-one-member/expected.json +73 -0
  305. progeny_selector-0.1.0/contract/cases/vcf-gzip-one-member/genotypes.vcf.gz +0 -0
  306. progeny_selector-0.1.0/contract/cases/vcf-gzip-one-member/samples.csv +4 -0
  307. progeny_selector-0.1.0/contract/cases/vcf-id-dot-crlf/expected.json +76 -0
  308. progeny_selector-0.1.0/contract/cases/vcf-id-dot-crlf/genotypes.vcf +5 -0
  309. progeny_selector-0.1.0/contract/cases/vcf-id-dot-crlf/samples.csv +4 -0
  310. progeny_selector-0.1.0/contract/cases/vcf-position-digits-id/expected.json +58 -0
  311. progeny_selector-0.1.0/contract/cases/vcf-position-digits-id/genotypes.vcf +4 -0
  312. progeny_selector-0.1.0/contract/cases/vcf-position-digits-id/samples.csv +4 -0
  313. progeny_selector-0.1.0/contract/cases/wide-blank-lines-skipped/expected.json +58 -0
  314. progeny_selector-0.1.0/contract/cases/wide-blank-lines-skipped/genotypes.csv +6 -0
  315. progeny_selector-0.1.0/contract/cases/wide-blank-lines-skipped/samples.csv +4 -0
  316. progeny_selector-0.1.0/contract/cases/wide-coded-blank-line-before-header/expected.json +58 -0
  317. progeny_selector-0.1.0/contract/cases/wide-coded-blank-line-before-header/genotypes.csv +4 -0
  318. progeny_selector-0.1.0/contract/cases/wide-coded-blank-line-before-header/samples.csv +4 -0
  319. progeny_selector-0.1.0/contract/cases/wide-coded-parents-absent/expected.json +85 -0
  320. progeny_selector-0.1.0/contract/cases/wide-coded-parents-absent/genotypes.csv +5 -0
  321. progeny_selector-0.1.0/contract/cases/wide-coded-parents-absent/samples.csv +6 -0
  322. progeny_selector-0.1.0/contract/cases/wide-empty-row-skipped/expected.json +58 -0
  323. progeny_selector-0.1.0/contract/cases/wide-empty-row-skipped/genotypes.csv +4 -0
  324. progeny_selector-0.1.0/contract/cases/wide-empty-row-skipped/samples.csv +4 -0
  325. progeny_selector-0.1.0/contract/cases/wide-half-missing-pair/expected.json +89 -0
  326. progeny_selector-0.1.0/contract/cases/wide-half-missing-pair/genotypes.csv +5 -0
  327. progeny_selector-0.1.0/contract/cases/wide-half-missing-pair/samples.csv +5 -0
  328. progeny_selector-0.1.0/contract/cases/wide-hash-row-is-data/expected.json +58 -0
  329. progeny_selector-0.1.0/contract/cases/wide-hash-row-is-data/genotypes.csv +3 -0
  330. progeny_selector-0.1.0/contract/cases/wide-hash-row-is-data/samples.csv +4 -0
  331. progeny_selector-0.1.0/contract/cases/wide-nucleotide-comma/expected.json +117 -0
  332. progeny_selector-0.1.0/contract/cases/wide-nucleotide-comma/genotypes.csv +5 -0
  333. progeny_selector-0.1.0/contract/cases/wide-nucleotide-comma/samples.csv +6 -0
  334. progeny_selector-0.1.0/contract/cases/wide-nucleotide-iupac/expected.json +154 -0
  335. progeny_selector-0.1.0/contract/cases/wide-nucleotide-iupac/genotypes.csv +7 -0
  336. progeny_selector-0.1.0/contract/cases/wide-nucleotide-iupac/samples.csv +5 -0
  337. progeny_selector-0.1.0/contract/cases/wide-nucleotide-tab-crlf-bom/expected.json +98 -0
  338. progeny_selector-0.1.0/contract/cases/wide-nucleotide-tab-crlf-bom/genotypes.tsv +5 -0
  339. progeny_selector-0.1.0/contract/cases/wide-nucleotide-tab-crlf-bom/samples.csv +5 -0
  340. progeny_selector-0.1.0/contract/cases/wide-position-whole-float/expected.json +94 -0
  341. progeny_selector-0.1.0/contract/cases/wide-position-whole-float/genotypes.csv +5 -0
  342. progeny_selector-0.1.0/contract/cases/wide-position-whole-float/markers.csv +5 -0
  343. progeny_selector-0.1.0/contract/cases/wide-position-whole-float/samples.csv +4 -0
  344. progeny_selector-0.1.0/contract/cases/wide-tab-blank-line-before-header/expected.json +58 -0
  345. progeny_selector-0.1.0/contract/cases/wide-tab-blank-line-before-header/genotypes.csv +6 -0
  346. progeny_selector-0.1.0/contract/cases/wide-tab-blank-line-before-header/samples.csv +4 -0
  347. progeny_selector-0.1.0/contract/cases/wide-two-missing-pair/expected.json +73 -0
  348. progeny_selector-0.1.0/contract/cases/wide-two-missing-pair/genotypes.csv +4 -0
  349. progeny_selector-0.1.0/contract/cases/wide-two-missing-pair/samples.csv +5 -0
  350. progeny_selector-0.1.0/contract/cases/wide-utf8-non-ascii-ids/expected.json +58 -0
  351. progeny_selector-0.1.0/contract/cases/wide-utf8-non-ascii-ids/genotypes.csv +3 -0
  352. progeny_selector-0.1.0/contract/cases/wide-utf8-non-ascii-ids/samples.csv +4 -0
  353. progeny_selector-0.1.0/contract/crops/barley.json +29 -0
  354. progeny_selector-0.1.0/contract/crops/common-bean.json +39 -0
  355. progeny_selector-0.1.0/contract/crops/cotton.json +67 -0
  356. progeny_selector-0.1.0/contract/crops/cowpea.json +43 -0
  357. progeny_selector-0.1.0/contract/crops/maize.json +36 -0
  358. progeny_selector-0.1.0/contract/crops/oat.json +57 -0
  359. progeny_selector-0.1.0/contract/crops/pea.json +34 -0
  360. progeny_selector-0.1.0/contract/crops/peanut.json +62 -0
  361. progeny_selector-0.1.0/contract/crops/rice.json +41 -0
  362. progeny_selector-0.1.0/contract/crops/sorghum.json +35 -0
  363. progeny_selector-0.1.0/contract/crops/soybean.json +57 -0
  364. progeny_selector-0.1.0/contract/crops/sunflower.json +54 -0
  365. progeny_selector-0.1.0/contract/crops/wheat.json +57 -0
  366. progeny_selector-0.1.0/contract/data-contract.md +97 -0
  367. progeny_selector-0.1.0/contract/profiles/axiom.json +10 -0
  368. progeny_selector-0.1.0/contract/profiles/dart.json +10 -0
  369. progeny_selector-0.1.0/contract/profiles/kasp.json +12 -0
  370. progeny_selector-0.1.0/contract/profiles/soybase-report.json +12 -0
  371. progeny_selector-0.1.0/contract/profiles/tassel.json +12 -0
  372. progeny_selector-0.1.0/docs/README.md +13 -0
  373. progeny_selector-0.1.0/docs/accessibility.md +81 -0
  374. progeny_selector-0.1.0/docs/adr/0001-python-core-shiny-ui-shinylive.md +36 -0
  375. progeny_selector-0.1.0/docs/adr/0002-input-data-contract.md +27 -0
  376. progeny_selector-0.1.0/docs/adr/0003-hosting-local-shiny-and-shinylive-pages.md +30 -0
  377. progeny_selector-0.1.0/docs/adr/0004-mit-license.md +19 -0
  378. progeny_selector-0.1.0/docs/adr/0005-criteria-file-yaml.md +25 -0
  379. progeny_selector-0.1.0/docs/adr/0006-parent-of-origin-and-rpp-definitions.md +33 -0
  380. progeny_selector-0.1.0/docs/adr/0007-hard-filters-before-composite-score.md +29 -0
  381. progeny_selector-0.1.0/docs/adr/0008-screen-testing-and-extras.md +21 -0
  382. progeny_selector-0.1.0/docs/adr/0009-shinylive-export-staging.md +25 -0
  383. progeny_selector-0.1.0/docs/adr/0010-contract-1.1-alignment.md +25 -0
  384. progeny_selector-0.1.0/docs/adr/0011-foreground-run-rule.md +35 -0
  385. progeny_selector-0.1.0/docs/adr/0012-family-donor-outlier.md +40 -0
  386. progeny_selector-0.1.0/docs/adr/0013-contract-1.3-lines-and-rows.md +27 -0
  387. progeny_selector-0.1.0/docs/adr/0014-contract-1.4-token-profiles.md +30 -0
  388. progeny_selector-0.1.0/docs/adr/0015-assembly-selector-and-map-warnings.md +43 -0
  389. progeny_selector-0.1.0/docs/adr/0016-results-schema-freeze.md +45 -0
  390. progeny_selector-0.1.0/docs/adr/0017-duplicate-flag.md +62 -0
  391. progeny_selector-0.1.0/docs/adr/0018-two-generation-round-trip.md +34 -0
  392. progeny_selector-0.1.0/docs/adr/0019-soybean-input-tooling.md +53 -0
  393. progeny_selector-0.1.0/docs/adr/0020-contract-1.5-crop-schemes.md +29 -0
  394. progeny_selector-0.1.0/docs/adr/0021-measured-limits.md +63 -0
  395. progeny_selector-0.1.0/docs/adr/0022-streaming-vcf-parse.md +148 -0
  396. progeny_selector-0.1.0/docs/adr/0023-accessibility-baseline.md +90 -0
  397. progeny_selector-0.1.0/docs/adr/0024-brapi-allele-matrix-loader.md +154 -0
  398. progeny_selector-0.1.0/docs/adr/0025-core-sample-chunking.md +140 -0
  399. progeny_selector-0.1.0/docs/adr/0026-contract-1.6-half-missing-pair.md +29 -0
  400. progeny_selector-0.1.0/docs/adr/0027-contract-1.7-crop-schemes.md +29 -0
  401. progeny_selector-0.1.0/docs/adr/0028-contract-1.8-two-missing-pair.md +25 -0
  402. progeny_selector-0.1.0/docs/adr/0029-contract-1.9-sunflower-scheme.md +25 -0
  403. progeny_selector-0.1.0/docs/adr/0030-contract-1.10-vcf-gt-grammar.md +43 -0
  404. progeny_selector-0.1.0/docs/adr/0031-contract-1.11-utf8-text.md +51 -0
  405. progeny_selector-0.1.0/docs/adr/0032-contract-1.12-soybean-data-store-names.md +27 -0
  406. progeny_selector-0.1.0/docs/adr/0033-results-schema-1.2-cap-and-end-rule.md +46 -0
  407. progeny_selector-0.1.0/docs/adr/0034-purdy-generation-labels.md +28 -0
  408. progeny_selector-0.1.0/docs/adr/0035-release-decisions-and-provenance.md +52 -0
  409. progeny_selector-0.1.0/docs/adr/0036-first-public-release-packaging.md +34 -0
  410. progeny_selector-0.1.0/docs/data-formats.md +208 -0
  411. progeny_selector-0.1.0/docs/glossary.md +120 -0
  412. progeny_selector-0.1.0/docs/handoffs/2026-09-21-m3-planning.md +135 -0
  413. progeny_selector-0.1.0/docs/keyboard-walkthrough.md +75 -0
  414. progeny_selector-0.1.0/docs/legacy-readme.md +50 -0
  415. progeny_selector-0.1.0/docs/limits.md +86 -0
  416. progeny_selector-0.1.0/docs/reference-repos.md +63 -0
  417. progeny_selector-0.1.0/docs/soybean-inputs.md +63 -0
  418. progeny_selector-0.1.0/docs/tutorial.md +191 -0
  419. progeny_selector-0.1.0/pyproject.toml +84 -0
  420. progeny_selector-0.1.0/scripts/bench_pipeline.py +320 -0
  421. progeny_selector-0.1.0/scripts/bench_shinylive.py +163 -0
  422. progeny_selector-0.1.0/scripts/build_shinylive.py +113 -0
  423. progeny_selector-0.1.0/scripts/changelog_section.py +86 -0
  424. progeny_selector-0.1.0/scripts/check_contract.py +118 -0
  425. progeny_selector-0.1.0/scripts/kasp_to_wide.py +289 -0
  426. progeny_selector-0.1.0/scripts/make_fixture.py +998 -0
  427. progeny_selector-0.1.0/scripts/read_results.R +181 -0
  428. progeny_selector-0.1.0/scripts/song2016_map.py +308 -0
  429. progeny_selector-0.1.0/scripts/soysnp50k_nils.py +236 -0
  430. progeny_selector-0.1.0/scripts/soysnp_positions.py +266 -0
  431. progeny_selector-0.1.0/src/progeny_selector/__init__.py +11 -0
  432. progeny_selector-0.1.0/src/progeny_selector/__main__.py +6 -0
  433. progeny_selector-0.1.0/src/progeny_selector/_version.py +6 -0
  434. progeny_selector-0.1.0/src/progeny_selector/app/__init__.py +6 -0
  435. progeny_selector-0.1.0/src/progeny_selector/app/app.py +57 -0
  436. progeny_selector-0.1.0/src/progeny_selector/app/present.py +201 -0
  437. progeny_selector-0.1.0/src/progeny_selector/app/screens/__init__.py +1 -0
  438. progeny_selector-0.1.0/src/progeny_selector/app/screens/compare.py +285 -0
  439. progeny_selector-0.1.0/src/progeny_selector/app/screens/export.py +112 -0
  440. progeny_selector-0.1.0/src/progeny_selector/app/screens/load.py +293 -0
  441. progeny_selector-0.1.0/src/progeny_selector/app/screens/navigate.py +132 -0
  442. progeny_selector-0.1.0/src/progeny_selector/app/screens/qc.py +125 -0
  443. progeny_selector-0.1.0/src/progeny_selector/app/screens/rank.py +111 -0
  444. progeny_selector-0.1.0/src/progeny_selector/app/screens/select.py +97 -0
  445. progeny_selector-0.1.0/src/progeny_selector/cli.py +369 -0
  446. progeny_selector-0.1.0/src/progeny_selector/config.py +39 -0
  447. progeny_selector-0.1.0/src/progeny_selector/constants.py +219 -0
  448. progeny_selector-0.1.0/src/progeny_selector/core/__init__.py +5 -0
  449. progeny_selector-0.1.0/src/progeny_selector/core/avoid.py +27 -0
  450. progeny_selector-0.1.0/src/progeny_selector/core/background.py +117 -0
  451. progeny_selector-0.1.0/src/progeny_selector/core/chrom.py +141 -0
  452. progeny_selector-0.1.0/src/progeny_selector/core/classify.py +113 -0
  453. progeny_selector-0.1.0/src/progeny_selector/core/drag.py +120 -0
  454. progeny_selector-0.1.0/src/progeny_selector/core/foreground.py +209 -0
  455. progeny_selector-0.1.0/src/progeny_selector/core/generation.py +124 -0
  456. progeny_selector-0.1.0/src/progeny_selector/core/genetic_map.py +79 -0
  457. progeny_selector-0.1.0/src/progeny_selector/core/navigation.py +84 -0
  458. progeny_selector-0.1.0/src/progeny_selector/core/pipeline.py +384 -0
  459. progeny_selector-0.1.0/src/progeny_selector/core/qc.py +327 -0
  460. progeny_selector-0.1.0/src/progeny_selector/core/score.py +179 -0
  461. progeny_selector-0.1.0/src/progeny_selector/core/selection.py +71 -0
  462. progeny_selector-0.1.0/src/progeny_selector/core/similarity.py +126 -0
  463. progeny_selector-0.1.0/src/progeny_selector/core/strip.py +95 -0
  464. progeny_selector-0.1.0/src/progeny_selector/examples/__init__.py +87 -0
  465. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc2f1/criteria.yaml +23 -0
  466. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc2f1/genotypes.vcf +504 -0
  467. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc2f1/markers.csv +501 -0
  468. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc2f1/samples.csv +43 -0
  469. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc3f1/genotypes.vcf +504 -0
  470. progeny_selector-0.1.0/src/progeny_selector/examples/synthetic_bc3f1/samples.csv +43 -0
  471. progeny_selector-0.1.0/src/progeny_selector/io/__init__.py +93 -0
  472. progeny_selector-0.1.0/src/progeny_selector/io/brapi.py +630 -0
  473. progeny_selector-0.1.0/src/progeny_selector/io/calls.py +167 -0
  474. progeny_selector-0.1.0/src/progeny_selector/io/criteria.py +305 -0
  475. progeny_selector-0.1.0/src/progeny_selector/io/crops.py +450 -0
  476. progeny_selector-0.1.0/src/progeny_selector/io/delimited.py +164 -0
  477. progeny_selector-0.1.0/src/progeny_selector/io/export.py +302 -0
  478. progeny_selector-0.1.0/src/progeny_selector/io/hapmap.py +96 -0
  479. progeny_selector-0.1.0/src/progeny_selector/io/manifest.py +149 -0
  480. progeny_selector-0.1.0/src/progeny_selector/io/position.py +58 -0
  481. progeny_selector-0.1.0/src/progeny_selector/io/profiles.py +243 -0
  482. progeny_selector-0.1.0/src/progeny_selector/io/vcf.py +215 -0
  483. progeny_selector-0.1.0/src/progeny_selector/io/wide_csv.py +102 -0
  484. progeny_selector-0.1.0/src/progeny_selector/model/__init__.py +29 -0
  485. progeny_selector-0.1.0/src/progeny_selector/model/criteria.py +217 -0
  486. progeny_selector-0.1.0/src/progeny_selector/model/dataset.py +213 -0
  487. progeny_selector-0.1.0/src/progeny_selector/provenance.py +100 -0
  488. progeny_selector-0.1.0/tests/__init__.py +0 -0
  489. progeny_selector-0.1.0/tests/conftest.py +45 -0
  490. progeny_selector-0.1.0/tests/e2e/__init__.py +0 -0
  491. progeny_selector-0.1.0/tests/e2e/conftest.py +39 -0
  492. progeny_selector-0.1.0/tests/e2e/helpers.py +26 -0
  493. progeny_selector-0.1.0/tests/e2e/test_a11y.py +129 -0
  494. progeny_selector-0.1.0/tests/e2e/test_criteria_editor.py +140 -0
  495. progeny_selector-0.1.0/tests/e2e/test_export_manifest.py +110 -0
  496. progeny_selector-0.1.0/tests/e2e/test_focus_order.py +52 -0
  497. progeny_selector-0.1.0/tests/e2e/test_keyboard_walkthrough.py +81 -0
  498. progeny_selector-0.1.0/tests/e2e/test_load_screen.py +26 -0
  499. progeny_selector-0.1.0/tests/e2e/test_load_upload_names.py +81 -0
  500. progeny_selector-0.1.0/tests/e2e/test_navigate_gaps.py +106 -0
  501. progeny_selector-0.1.0/tests/e2e/test_navigate_rank.py +163 -0
  502. progeny_selector-0.1.0/tests/e2e/test_qc_compare.py +159 -0
  503. progeny_selector-0.1.0/tests/e2e/test_reload.py +57 -0
  504. progeny_selector-0.1.0/tests/e2e/test_select_top_n.py +43 -0
  505. progeny_selector-0.1.0/tests/e2e/test_selection_notes.py +85 -0
  506. progeny_selector-0.1.0/tests/e2e/test_shinylive_export.py +162 -0
  507. progeny_selector-0.1.0/tests/fixtures/brapi/README.md +24 -0
  508. progeny_selector-0.1.0/tests/fixtures/brapi/allelematrix.v0.c0.json +149 -0
  509. progeny_selector-0.1.0/tests/fixtures/brapi/allelematrix.v0.c1.json +121 -0
  510. progeny_selector-0.1.0/tests/fixtures/brapi/allelematrix.v1.c0.json +141 -0
  511. progeny_selector-0.1.0/tests/fixtures/brapi/allelematrix.v1.c1.json +115 -0
  512. progeny_selector-0.1.0/tests/fixtures/brapi/callsets.p0.json +59 -0
  513. progeny_selector-0.1.0/tests/fixtures/brapi/callsets.p1.json +41 -0
  514. progeny_selector-0.1.0/tests/fixtures/brapi/criteria.yaml +20 -0
  515. progeny_selector-0.1.0/tests/fixtures/brapi/samples.csv +9 -0
  516. progeny_selector-0.1.0/tests/fixtures/brapi/variants-nopos.p0.json +315 -0
  517. progeny_selector-0.1.0/tests/fixtures/brapi/variants.p0.json +197 -0
  518. progeny_selector-0.1.0/tests/fixtures/brapi/variants.p1.json +183 -0
  519. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/README.md +5 -0
  520. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/criteria.yaml +23 -0
  521. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/expected_results.csv +41 -0
  522. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/genotypes.vcf +504 -0
  523. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/markers.csv +501 -0
  524. progeny_selector-0.1.0/tests/fixtures/synthetic_bc2f1/samples.csv +43 -0
  525. progeny_selector-0.1.0/tests/fixtures/synthetic_bc3f1/README.md +35 -0
  526. progeny_selector-0.1.0/tests/fixtures/synthetic_bc3f1/expected_results.csv +41 -0
  527. progeny_selector-0.1.0/tests/fixtures/synthetic_bc3f1/genotypes.vcf +504 -0
  528. progeny_selector-0.1.0/tests/fixtures/synthetic_bc3f1/samples.csv +43 -0
  529. progeny_selector-0.1.0/tests/test_assembly_resolution.py +93 -0
  530. progeny_selector-0.1.0/tests/test_bench_generator.py +55 -0
  531. progeny_selector-0.1.0/tests/test_brapi.py +618 -0
  532. progeny_selector-0.1.0/tests/test_changelog_section.py +144 -0
  533. progeny_selector-0.1.0/tests/test_check_contract.py +73 -0
  534. progeny_selector-0.1.0/tests/test_chrom_assembly.py +55 -0
  535. progeny_selector-0.1.0/tests/test_classify.py +67 -0
  536. progeny_selector-0.1.0/tests/test_cli_app.py +33 -0
  537. progeny_selector-0.1.0/tests/test_cli_select_top.py +52 -0
  538. progeny_selector-0.1.0/tests/test_compare_view.py +115 -0
  539. progeny_selector-0.1.0/tests/test_contract_cases.py +131 -0
  540. progeny_selector-0.1.0/tests/test_core_memory.py +277 -0
  541. progeny_selector-0.1.0/tests/test_criteria_hardening.py +151 -0
  542. progeny_selector-0.1.0/tests/test_criteria_roundtrip.py +177 -0
  543. progeny_selector-0.1.0/tests/test_crops.py +741 -0
  544. progeny_selector-0.1.0/tests/test_docs_commands.py +34 -0
  545. progeny_selector-0.1.0/tests/test_duplicates.py +240 -0
  546. progeny_selector-0.1.0/tests/test_examples.py +97 -0
  547. progeny_selector-0.1.0/tests/test_export_text.py +94 -0
  548. progeny_selector-0.1.0/tests/test_generation_purdy.py +76 -0
  549. progeny_selector-0.1.0/tests/test_genetic_map.py +55 -0
  550. progeny_selector-0.1.0/tests/test_github_templates.py +50 -0
  551. progeny_selector-0.1.0/tests/test_io.py +700 -0
  552. progeny_selector-0.1.0/tests/test_kasp_to_wide.py +241 -0
  553. progeny_selector-0.1.0/tests/test_map_warnings.py +153 -0
  554. progeny_selector-0.1.0/tests/test_navigation.py +82 -0
  555. progeny_selector-0.1.0/tests/test_next_generation.py +153 -0
  556. progeny_selector-0.1.0/tests/test_present.py +144 -0
  557. progeny_selector-0.1.0/tests/test_profiles.py +293 -0
  558. progeny_selector-0.1.0/tests/test_provenance.py +144 -0
  559. progeny_selector-0.1.0/tests/test_qc_family_outlier.py +191 -0
  560. progeny_selector-0.1.0/tests/test_qc_table.py +86 -0
  561. progeny_selector-0.1.0/tests/test_ranking_staged.py +103 -0
  562. progeny_selector-0.1.0/tests/test_ranking_staged_pipeline.py +72 -0
  563. progeny_selector-0.1.0/tests/test_readme_links.py +41 -0
  564. progeny_selector-0.1.0/tests/test_results_schema.py +337 -0
  565. progeny_selector-0.1.0/tests/test_round_trip.py +238 -0
  566. progeny_selector-0.1.0/tests/test_run_rule.py +334 -0
  567. progeny_selector-0.1.0/tests/test_smoke_pipeline.py +207 -0
  568. progeny_selector-0.1.0/tests/test_song2016_map.py +259 -0
  569. progeny_selector-0.1.0/tests/test_soysnp50k_nils.py +231 -0
  570. progeny_selector-0.1.0/tests/test_soysnp_positions.py +113 -0
  571. progeny_selector-0.1.0/tests/test_status_metrics.py +195 -0
  572. progeny_selector-0.1.0/tests/test_strip.py +176 -0
  573. progeny_selector-0.1.0/tests/test_utf8.py +194 -0
  574. progeny_selector-0.1.0/tests/test_vcf_streaming.py +247 -0
  575. progeny_selector-0.1.0/tests/test_version.py +45 -0
@@ -0,0 +1,11 @@
1
+ # Normalise line endings: the repository is LF everywhere, so a regenerated
2
+ # fixture on Windows matches the committed files.
3
+ * text=auto eol=lf
4
+
5
+ # The data contract (contract/) is mirrored byte for byte from backcross and hashed
6
+ # in MANIFEST.sha256; its text is LF on every checkout, its case files are the generator's
7
+ # bytes verbatim (some are CRLF by design), and its gzip and bgzip cases are never normalised.
8
+ contract/** text eol=lf
9
+ contract/cases/** -text
10
+ *.gz binary
11
+ *.bgz binary
@@ -0,0 +1,45 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+ .pytest_cache/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ htmlcov/
14
+
15
+ # shinylive export
16
+ site/
17
+ # written only into the staged copy by scripts/build_shinylive.py (docs/adr/0035)
18
+ src/progeny_selector/_build_commit.txt
19
+
20
+ # local environment
21
+ .env
22
+ .env.local
23
+
24
+ # local Claude Code tooling (token-economy kit hooks), never committed
25
+ .claude/
26
+
27
+ # editors and OS
28
+ .vscode/
29
+ .idea/
30
+ .DS_Store
31
+
32
+ # genotype data is never committed; the synthetic fixture is the only exception
33
+ data/
34
+ *.vcf
35
+ *.vcf.gz
36
+ *.hmp.txt
37
+ results*.csv
38
+ selected*.csv
39
+ !tests/fixtures/**
40
+ !contract/**
41
+ # the shipped examples (package data, written by scripts/make_fixture.py): *.vcf is ignored
42
+ # globally, and hatchling excludes VCS-ignored files from the sdist and wheel by default, so
43
+ # without this line the package data would be missing from both git and the wheel
44
+ !src/progeny_selector/examples/**
45
+ src/progeny_selector/examples/**/__pycache__/
@@ -0,0 +1,126 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file. The format follows Keep a Changelog 1.1.0 (https://keepachangelog.com/en/1.1.0/) and the project uses Semantic Versioning (https://semver.org/spec/v2.0.0.html).
4
+
5
+ ## [Unreleased]
6
+
7
+ Nothing yet.
8
+
9
+ ## [0.1.0] - 2026-09-29
10
+
11
+ The first public release. It implements input data contract 1.12.0, shared with backcross, and writes results.csv and selected.csv under results_schema 1.2.0. The sibling backcross v0.1.0 was released the same day (https://github.com/piercetaylor/backcross/releases/tag/v0.1.0; docs/adr/0035 Q6).
12
+
13
+ ### Added
14
+
15
+ - Continuous integration covers Python 3.11, 3.12 and 3.13, plus Windows and macOS. A `package` job validates CITATION.cff, builds the sdist and wheel, runs `twine check`, and runs the example end to end from the installed wheel in a fresh environment. A tag-triggered release workflow publishes to PyPI by trusted publishing and creates the GitHub release from this file's section.
16
+ - `progeny-selector app [--host] [--port] [--no-browser]` starts the browser interface from an installed package, and the Load screen has a "Load example (synthetic BC2F1)" button, which also works in the Shinylive site.
17
+ - `progeny-selector example [--out DIR] [--name synthetic_bc2f1|synthetic_bc3f1|all] [--force]` writes the synthetic BC2F1 and BC3F1 example datasets, which now ship inside the package, so the quickstart runs without a checkout. The command refuses to overwrite existing files unless given `--force`.
18
+ - `progeny-selector --version` prints the installed version, read from one source (`src/progeny_selector/_version.py`).
19
+ - Single-cross Purdy generation labels are read for the backcross count: `RP*3/DONOR`, `3*RP/DONOR`, `DONOR/RP*3` and `DONOR/3*RP` (a recurrent-parent dose n of 2 or more is BC(n-1), n = 1 the F1). Such a line gets an expected RPP and no longer carries `generation_unparsed`; its `expected_het` is `NA` and `het_rate_deviates` and `possible_self_or_outcross` are not evaluated, since the label states no filial generation. Write the BCnFm label (`BC2F1`) to keep those checks (docs/adr/0034).
20
+ - `scripts/kasp_to_wide.py` names up to five distinct unrecognised call strings, with their counts, in its stderr summary, so a vendor token the converter does not know is visible rather than only counted. `?`, `NTC` and empty are documented as the missing tokens seen in real exports; `Uncallable`, `Missing`, `Bad` and `Dupe` stay accepted as assumed aliases (docs/soybean-inputs.md).
21
+
22
+ - The shared input contract mirror is version 1.12.0: the soybean scheme also reads the SoyBase / LIS Data Store names of Williams 82 (`glyma.Wm82.gnmN.Gm01`, `glyma.Wm82.gnm5.Chr01`) and the V1.1 spelling `GLYMAchr_01` (canonical record: backcross docs/adr/0027; mirror record docs/adr/0032).
23
+ - The shared input contract mirror is version 1.11.0: every text input is UTF-8 (canonical record: backcross docs/adr/0026; mirror record docs/adr/0031). A byte sequence that is not well-formed UTF-8 in the genotype file (plain, gzip or bgzip), samples.csv or markers.csv now raises `DataContractError` naming the file, the physical line and the byte position (`{path}: line N: not valid UTF-8 (byte 0xHH at position P)`), where a raw `UnicodeDecodeError` escaped before; criteria.yaml raises `CriteriaError`, and the results.csv read by `select` a `DataContractError`, with the same message. A byte-order mark stays ignored.
24
+ - The shared input contract mirror is version 1.10.0: a VCF GT outside the grammar (a sign, an exponent, an underscore, whitespace, a leading zero, an empty side, three alleles, the VCF 4.4 leading phase indicator, or an allele index above 127 or outside REF,ALT) is the error `genotypes.invalid_gt`, naming the line and the value, where before it was misread or raised a raw Python exception; an empty GT, which raised a ValueError, and a sample field that ends before its GT sub-field, which raised an IndexError, are now read as missing (canonical record: backcross docs/adr/0025; mirror record docs/adr/0030).
25
+ - Accessibility review against WCAG 2.2 AA: axe-core runs on every screen in the browser tests, a Tab walk from the Load screen never lands focus on an element with no layout box, statuses carry text as well as colour; docs/accessibility.md records the method and the known exceptions (docs/adr/0023).
26
+
27
+ - Load a variant set from a BrAPI v2.1 server on the command line (`rank` and `validate` with `--brapi-url` and `--variant-set`, token from the environment variable named by `--brapi-token-env`); `brapi-callsets` writes the call-set table so samples.csv is built from the server's own ids; roles still come from samples.csv (docs/adr/0024).
28
+
29
+ - The shared input contract mirror is version 1.6.0: a genotype cell pairing one of A, C, G, T with one of `N`, `-`, `.`, in either order and in all three spellings, is read as missing in HapMap and in nucleotide-mode wide CSV, which `io.calls` already did and does not change (canonical record: backcross docs/adr/0021). A pair of two missing characters (`N/N`, `..`) was left undefined by 1.6.0 and is defined by 1.8.0 below.
30
+
31
+ - The shared input contract mirror is version 1.7.0: `--crop` and the Load screen add cowpea, pea and peanut chromosome schemes (canonical record: backcross docs/adr/0022; mirror record docs/adr/0027). Pea needs a `chr` or `chromosome` prefix or a matching `LG` suffix and keeps a bare `1`-`7` as written, because published pea tables use bare digits for two numberings; peanut's `A01`/`B01`, `Aradu.` and `Araip.` spellings are kept as written. Sunflower stayed deferred then and followed as contract 1.9.0 below.
32
+
33
+ - The shared input contract mirror is version 1.8.0: a genotype cell pairing two of `N`, `-`, `.`, in any order and in all three spellings (`N/N`, `N-`, `./N`, `..`, `-|N`), is read as missing in HapMap and in nucleotide-mode wide CSV, which `io.calls` already did and does not change (canonical record: backcross docs/adr/0023; mirror record docs/adr/0028). A pair with `X` that is not itself a missing token (`X/X`, `XN`) stays an error; under a `base: none` token profile (`dart`, `axiom`, `kasp`) such a cell is an error unless the profile lists it, as `axiom` lists `--`; and a wide CSV holding such a cell that is not itself a missing token is read as nucleotide by `auto` detection.
34
+
35
+ - The shared input contract mirror is version 1.9.0: `--crop` and the Load screen add a sunflower chromosome scheme (canonical record: backcross docs/adr/0024; mirror record docs/adr/0029). Its canonical names are bare `1`-`17`, and `Ha412HOChr01` (HA412-HOv2.0), `HanXRQChr01` (HanXRQr2.0-SUNRISE), `chr1`, `chromosome-1`, `01` and `1` are all read as `1`, because the two assemblies share the LG1-LG17 numbering (XRQ and HA412-HO v1 by their map anchoring, HA412-HOv2 by a whole-genome alignment against XRQ; backcross docs/adr/0024 gives the evidence and its weakest link); unplaced scaffolds (`HanXRQChr00c001`), organelles, accessions (`NC_035433.2`, `CM007890.2`), the `LG` prefix and HA412-HO v1.1 names (`Ha1`) are kept as written.
36
+
37
+ - Navigate offers a "(no generation)" choice for individuals without a generation; the Rank caption names an unassigned family or generation; the Navigate reload guard has a browser test.
38
+ - `scripts/bench_pipeline.py` and `scripts/bench_shinylive.py` measure wall-clock and peak memory on generated datasets; `docs/limits.md` records the measured limits for CPython and Shinylive (docs/adr/0021).
39
+
40
+ - Crop selector (contract 1.5.0, docs/adr/0020): soybean (default), maize, rice, sorghum, wheat, barley, oat, common bean and cotton chromosome schemes; a chosen crop normalizes and orders chromosome names, resolves target regions and selects chromosome lengths by that crop's convention, so a maize `chr1` is no longer read as `Gm01` and a maize target `chr7` resolves. `--crop ID` on the CLI and a Crop select on the Load screen.
41
+
42
+ - `scripts/soysnp_positions.py` builds a SoySNP50K/6K position table across Wm82 assemblies from SoyBase GFF3s; `scripts/kasp_to_wide.py` converts an LGC long-format KASP export to the wide CSV contract.
43
+ - Selection list: editable notes written to selected.csv. Validate: background model, units, assembly, rank mode and duplicate pairs. Export: placeholder rows per selected individual. docs/keyboard-walkthrough.md.
44
+ - `select --per-selected N`; a synthetic BC3F1 fixture generated from the BC2F1 selection proves next_samples.csv loads unchanged as the next generation (docs/adr/0018).
45
+ - Advisory QC flag `possible_duplicate` and duplicate pairs in `validate` (docs/adr/0017). IBS is measured over the informative markers called in both individuals, and a pair is reported only when they share calls at half or more of the markers used, so a sample with almost no calls is no longer a duplicate of everyone it overlaps. The fixture pins weighted RPP and staged ranks computed independently.
46
+ - `ranking: {mode: staged}` orders survivors lexicographically (docs/adr/0007); `assembly` selects the chromosome-length table (Wm82.a1, a2, a4 or none; docs/adr/0015). Warnings now report a cM request the map cannot honour, chromosomes without an assembly length, and marker positions beyond the assembly length.
47
+ - `scripts/read_results.R` reads results.csv with readr and explicit column types; CI verifies it on the fixture and on an empty results file.
48
+ - Token profiles (contract 1.4.0 mirrored, docs/adr/0014; backcross docs/adr/0019): the Load screen, the CLI (`--profile`) and backcross read HapMap and wide-CSV cells under a named vocabulary, `tassel`, `soybase-report` (H heterozygous, U missing), `dart` (0/1/2/-), `axiom` (AA/AB/BB, NoCall, or 0/1/2) or `kasp` (X:X/X:Y/?), or a JSON file of the same shape. results.csv and selected.csv gain a trailing `token_profile` column; readers by position keep their columns. A profile with a VCF, or with a wide CSV or HapMap read as A/B/H, is an error, as is an `H` at a marker with an indel allele; a profile file is always recorded as `custom:<id>`; the Load screen's custom profile can be cleared and disables the select while set; error kinds `genotypes.ambiguous_heterozygote` and `genotypes.profile_format`.
49
+ - Package scaffold with a pure compute core, boundary parsers, CLI and a Shiny for Python screen shell.
50
+ - Parsers for VCF 4.2+ (plain, gzip, bgzip), HapMap, wide CSV (nucleotide and A/B/H), samples.csv, markers.csv and criteria.yaml, with boundary validation.
51
+ - Parent-of-origin classification; foreground status for marker, region and flanking-marker loci; avoid-locus status; recurrent-parent proportion (count and map-weighted, per chromosome, carrier and non-carrier); donor-segment bounds and flank recombinant flags; identity-by-state to each parent; QC metrics and flags; hard filters, composite score, ranking with fixed tie-breaks; top-N selection and next-generation projection.
52
+ - results.csv, selected.csv and next-round manifest writers; `progeny-selector validate | rank | select` commands.
53
+ - Synthetic BC2F1 fixture (2 parents, 40 progeny in 2 families, 500 markers, planted target, avoid locus, contaminant, high-missing individual) with generator and expected results; unit and smoke tests.
54
+ - PLAN.md, data-format and reference-repository documents, MADR decision records, CI workflow.
55
+ - Navigate screen: family and generation tree with breadcrumbs that filter the Rank grid. Rank grid shows pass, fail and unknown chips and recombinant flags per locus.
56
+ - Validate screen: QC table with flagged rows highlighted and the reasons markers were uninformative. Compare screen: side-by-side statuses, per-chromosome RPP, drag bounds and Okabe-Ito chromosome strips.
57
+ - Criteria can be edited on the Load screen, re-applied without reloading genotypes, and downloaded as criteria.yaml. Downloads no longer write temporary files.
58
+ - The Shinylive static export includes the package and is smoke-tested in CI with the fixture; it deploys to GitHub Pages when ENABLE_PAGES is set.
59
+ - `scripts/soysnp50k_nils.py` converts one backcross-derived NIL family from the SoyBase SoySNP50K VCF and PATRIOT's pedigree file into a genotype file and samples.csv for this tool. It streams the 144 MB VCF, strips SoyBase's chromosome prefix, and drops scaffold and malformed records.
60
+ - The shared input contract, version 1.1.0, mirrored byte for byte from isoline-browser under `contract/` and checked by `tests/test_contract_cases.py`, which loads every case through `load_dataset` and verifies the manifest hashes (docs/adr/0010).
61
+ - Foreground `rule: run` for region targets, with `min_run`, `anchor_bp` and `tolerate_isolated`: a target passes only on a contiguous run of donor calls through the anchor, so scattered array calls no longer pass a wide window (docs/adr/0011).
62
+ - Advisory QC flag `family_donor_outlier`: an individual whose donor fraction (count model) lies above its family median by more than 2.5 robust scales (1.4826 x MAD, floor 0.01), in families of at least 6; it does not exclude (docs/adr/0012).
63
+ - `scripts/check_contract.py`, a per-commit gate that recomputes `contract/MANIFEST.sha256` and, given `../isoline-browser`, byte-compares the mirror with the canonical copy.
64
+
65
+ ### Changed
66
+
67
+ - shiny and pandas are core dependencies, and the `app` extra is gone: `pip install progeny-selector` installs everything the browser interface needs. The `select --top N` help now says it keeps up to N per family, and that `--overall` keeps the N best overall.
68
+ - results.csv and selected.csv are schema 1.2.0 (docs/adr/0033, docs/adr/0035). results.csv gains six columns directly after `crop`, before the per-target, per-avoid and per-chromosome columns: `call_set_db_id`, `sample_db_id`, `background_max_marker_coverage`, `tool`, `tool_version`, `tool_commit`, so its fixed prefix is 41 names (42 in the header of an empty file). selected.csv gains five after `crop`: `call_set_db_id`, `sample_db_id`, `tool`, `tool_version`, `tool_commit`. `call_set_db_id` and `sample_db_id` are the BrAPI ids a line was loaded from and an empty cell for data loaded from files. `background_max_marker_coverage` is the coverage cap the weighted model applied, in `background_unit`, and `NA` under `model: count`. `tool` is `progeny-selector`, `tool_version` the version that wrote the file, and `tool_commit` the commit it was built from (`g` and seven hex digits, `-dirty` when tracked files differ from that commit; untracked files do not count), `NA` when the commit is unknown, as for an installed wheel. A script that reads the per-chromosome columns by position after `crop` must move to the new position or select them by name; `scripts/read_results.R` reads the new columns, and `select` still reads a results.csv written before 1.2.0.
69
+ - Weighted RPP changes for runs in bp: the first marker's outer side on a chromosome is min(position, cap/2) whether or not an assembly length is known (it was cap/2 when no length was known), and the default bp cap is 2,000,000 (was 4,000,000). `rpp_total`, `rpp_carrier`, `rpp_noncarrier` and every `rpp_<chrom>` move on existing bp datasets under `model: weighted`; re-rank before comparing with earlier results, or set `background.max_marker_coverage: 4000000` to keep the old cap. Values in cM are unchanged (docs/adr/0033).
70
+ - Duplicate pairs carry `n_overlap`, the number of markers called in both lines that the IBS was measured over; `validate` and the Validate screen print it beside the IBS. When the most advanced parsed generation is BC6 or later, the run warns that `possible_duplicate` cannot separate duplicates from siblings, whose expected IBS is then within 0.005 of the 0.995 threshold (docs/adr/0017, amendment 2026-09-27).
71
+
72
+ - Classification, RPP and IBS to a parent compute in blocks of 64 sample columns, so analysis temporaries are set by the marker count alone: 83 MB for `rpp` at 50,000 markers, measured the same at 100 individuals and at 2,000, where before the cost scaled with the call count and reaches about 3.2 GB at 50,000 x 2,000 by arithmetic from the measured per-call figure (docs/adr/0025). Results are bit-identical.
73
+
74
+ - `read_vcf` reads the file in two passes and fills a preallocated matrix instead of stacking a list of rows, so the parse peak falls from 3.6x to 2.0x the genotype matrix on a file of 50,000 markers by 200 individuals (68.4 MiB to 38.4 MiB, measured on the reference machine); what remains beyond the matrix is the marker and allele tables, about 450 bytes a record, so the saving is largest on the sample-heavy files where the matrix dominates (docs/adr/0022). A truncated `.gz` is now a contract error naming the file, reported ahead of any row error in the same file. Results are unchanged.
75
+
76
+ - results.csv schema 1.1.0: a fixed `crop` column after `results_schema` and before `token_profile`, which stays last (docs/adr/0016); selected.csv gains it in the same position and `scripts/read_results.R` reads it. Under any crop but soybean a chromosome ends at its last marker, because the chromosome length tables are Williams 82's; the per-chromosome "assembly gives no length" warning says so.
77
+
78
+ - **BREAKING CHANGE:** results.csv schema 1.0.0: missing cells are `NA`, the header is written with no results, new columns `background_model`, `background_unit`, `rank_mode`, `assembly`, `results_schema`; `het_rate`, `expected_het` and `expected_rpp` never print `nan`. selected.csv gains `results_schema` and writes `NA` for missing family or generation (docs/adr/0016). next_samples.csv is unchanged: empty cells, no schema column. A chromosome whose name would collide with `rpp_total`, `rpp_carrier` or `rpp_noncarrier` is now an error naming the chromosome.
79
+ - Contract 1.3.0 mirrored (docs/adr/0013): a blank line before the header is skipped in HapMap, wide CSV, samples.csv and markers.csv; the delimiter is sniffed from the first non-blank line; a blank line holds only spaces and tabs; a quoted field left open at the end of a delimited file, a `#` line after a VCF `#CHROM` line and an unparseable markers.csv `cm` are errors naming the line; line breaks inside quoted fields are read as LF; error kinds `genotypes.column_count` and `delimited.unterminated_quote`.
80
+ - Data contract 1.2.1 (wording only): the sibling browser tool is now called Backcross.
81
+
82
+ - Contract 1.2.0, a minor version (docs/adr/0010, amended 2026-09-14): VCF POS must be decimal digits; a VCF record with ID `.` is named from the parsed POS. A position written as a whole-valued float or in exponent notation (`1000.0`, `1e3`, `1.9E+07`) is read as that integer in HapMap, wide CSV and markers.csv; a fractional `pos_bp` in wide CSV or markers.csv is now an error naming the line and value instead of being truncated, a non-integer VCF `POS` is a `DataContractError` instead of an uncaught `ValueError`, an empty `marker_id` in a wide CSV is an error, and wide-CSV and markers.csv errors name the physical line even after skipped rows.
83
+ - Loaders aligned with contract 1.1.0 (docs/adr/0010): samples.csv, markers.csv and wide CSV may be tab-delimited and quoted; `line_name` is optional; genotype columns not in samples.csv are dropped and samples load in manifest order; a VCF record with ID `.` is named from CHROM as written (`chr13_19000000`, not `Gm13_19000000`); chromosome names accept the `LG` prefix and space or `-` separators, no longer accept `ch6`, and non-soybean names order naturally (`scaffold_2` before `scaffold_10`); `?` is no longer a missing token anywhere, and in HapMap and nucleotide wide CSV a single character outside A, C, G, T and the IUPAC codes (`?`, `B`, `H`, `0`, `+`) is an error naming the line and cell rather than a missing call; the HapMap missing tokens are exactly the contract's eleven (`X`, `XX` added, `?` removed); A/B/H auto-detection reads the whole file instead of its first 200 rows; a leading byte-order mark is accepted on every input.
84
+
85
+ ### Fixed
86
+
87
+ - `scripts/kasp_to_wide.py` reads a sectioned KASP service-lab export (`Statistics`, `SNPs`, then `Data`) from the first row carrying `SubjectID`, `SNPID` and `Call`; it took the first row as the header, so a real export failed as an undetectable grid (docs/adr/0019, amendment of 2026-09-27).
88
+ - `validate` reports how many duplicate-pair candidates it skipped because the two lines share too few called markers ("N pairs skipped: fewer than M markers called in both lines"), where it dropped them silently before (Q14, the silent-skip half). The reload-guard end-to-end test now waits for the breadcrumb's settled state and fails on an empty mutation history, so it can no longer pass vacuously.
89
+ - The Load screen reads a genotype upload named `.vcf.gz`, `.vcf.bgz`, `.hmp.txt` or `.hmp.gz`. Shiny stores an upload under its last suffix only, so such a file reached the reader as `0.gz` or `0.txt` and failed with "cannot infer genotype format" or a wide-CSV header error; the screen now restores the upload's own name before reading it, and errors in samples.csv, markers.csv and criteria.yaml name the user's file.
90
+
91
+ - The next-round manifest refuses an empty next-generation label in `io.export`, so `select --next-generation ""` is a usage error and the Export screen shows the refusal and writes no file, where both previously wrote ids like `BC2F1-F1-001--001` and a blank `generation` column; a padded label is trimmed, and a refused write no longer leaves an empty file behind.
92
+ - results.csv and the Validate screen record the chromosome-length table the run used, and not the criteria.yaml text. A maize run with an unset `assembly` recorded `Wm82.a4` while using no length table at all, and now records `none` (docs/adr/0015, amendment 2026-09-22).
93
+ - An unset criteria.yaml `assembly` means whatever the crop implies: `Wm82.a4` under soybean, `none` under every other crop. An explicit `Wm82.*` under a non-soybean crop is refused naming the key, and an explicit `none` is accepted under any crop. A downloaded criteria.yaml writes an unset key as `assembly: null` and stays reusable across crops.
94
+
95
+ - Weighted RPP: a chromosome whose markers run past the assembly length now weighs its terminal markers like a chromosome with no recorded length at all, instead of giving the terminal marker zero outer weight (docs/adr/0015, amendment 2026-09-21).
96
+ - `scripts/kasp_to_wide.py` accepts `A:G` and `G:A` for the same sample and SNP as one call instead of a conflict.
97
+ - Clearing a numeric field no longer breaks the screen: Export still downloads next_samples.csv and the Selection list's "Add top N per family" adds nothing instead of failing.
98
+ - The next-round manifest refuses a placeholder-row count below 1 in `io.export` rather than only in the CLI, so the Export screen shows the refusal and writes no file where it previously downloaded a manifest holding the two parents and no progeny.
99
+
100
+ - Genotype files named `.vcf.bgz` now load, as documented; `.bcf`, which was never documented and was read as text, is rejected.
101
+
102
+ ### Removed
103
+
104
+ - The unused `core.classify.rpp_contribution`, a second copy of the table `constants.RPP_LOOKUP` carries (the follow-up docs/adr/0025 recorded).
105
+
106
+ ### Documentation
107
+
108
+ - The README is rewritten for breeders: install with pip or pipx, run the shipped example, launch the interface, what each output means, what `--top` keeps, and the known limitations. docs/tutorial.md walks through one run of the example on the command line and in the interface, docs/glossary.md defines the terms (RPP, carrier chromosome, linkage drag, the six genotype states, ranking modes, possible_duplicate), and docs/README.md indexes the documentation. CITATION.cff says how to cite the software.
109
+ - Replace the milestone-heavy landing page with a concise workflow and fixture example; preserve the previous README in `docs/legacy-readme.md`.
110
+
111
+ ### Known limitations
112
+
113
+ 1. `possible_duplicate` is raw pairwise identity by state of at least 0.995 over informative markers, and it does not consider family. It is advisory only ([ADR 0017](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0017-duplicate-flag.md)).
114
+ 2. The two-generation round trip is verified on synthetic data only. No real linked BC(n) to BC(n+1) dataset has been run.
115
+ 3. The browser site has no BrAPI source. BrAPI is command-line only until a server sends CORS headers for the site's origin ([ADR 0024](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0024-brapi-allele-matrix-loader.md)).
116
+ 4. One donor per analysis. An intercross or pyramiding population is not ranked ([contract](https://github.com/piercetaylor/progeny-selector/blob/main/contract/data-contract.md), [ADR 0002](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0002-input-data-contract.md)).
117
+ 5. Chromosome-length tables exist for soybean only (Wm82.a1, Wm82.a2 and Wm82.a4). Under any other crop a chromosome ends at its last marker ([ADR 0020](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0020-contract-1.5-crop-schemes.md)).
118
+ 6. The default cap of 2 Mb on base-pair coverage is a soybean translation of 10 cM. Set `background.max_marker_coverage` for other crops ([ADR 0033](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0033-results-schema-1.2-cap-and-end-rule.md)).
119
+ 7. A VCF 4.4 leading phase indicator in GT is rejected as `genotypes.invalid_gt` (contract 1.10.0).
120
+ 8. Accessibility: selecting several rows in the Rank grid needs a mouse; three axe rules are recorded exceptions; there is no screen-reader, Firefox, Safari or 320 px reflow testing ([accessibility review](https://github.com/piercetaylor/progeny-selector/blob/main/docs/accessibility.md)).
121
+ 9. Purdy labels: single crosses only, and no heterozygosity checks, because the label carries no filial generation ([ADR 0034](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0034-purdy-generation-labels.md)).
122
+ 10. The long-format KASP header names are unconfirmed against a real LGC export ([ADR 0019](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0019-soybean-input-tooling.md)).
123
+ 11. CI runs the browser tests on Linux only; Windows and macOS run the unit tests.
124
+
125
+ [Unreleased]: https://github.com/piercetaylor/progeny-selector/compare/v0.1.0...HEAD
126
+ [0.1.0]: https://github.com/piercetaylor/progeny-selector/releases/tag/v0.1.0
@@ -0,0 +1,27 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ type: software
4
+ title: "progeny-selector: marker-assisted backcross progeny ranking and selection"
5
+ authors:
6
+ - family-names: Taylor
7
+ given-names: Pierce
8
+ license: MIT
9
+ repository-code: "https://github.com/piercetaylor/progeny-selector"
10
+ url: "https://piercetaylor.github.io/progeny-selector/"
11
+ version: 0.1.0
12
+ date-released: '2026-09-29'
13
+ keywords:
14
+ - plant breeding
15
+ - marker-assisted backcrossing
16
+ - progeny selection
17
+ - recurrent parent genome
18
+ - soybean
19
+ references:
20
+ - type: software
21
+ title: Backcross
22
+ authors:
23
+ - family-names: Taylor
24
+ given-names: Pierce
25
+ repository-code: "https://github.com/piercetaylor/backcross"
26
+ url: "https://piercetaylor.github.io/backcross/"
27
+ notes: "Sibling tool; both read input data contract 1.12.0"
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ the maintainer, through a GitHub issue or the repository's private reporting form.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
@@ -0,0 +1,45 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ Python 3.11 or later. The package installs shiny and pandas; the extras are `dev` (pytest, pytest-cov, ruff, mypy), `e2e` (pytest-playwright and axe-playwright-python) and `export` (shinylive).
6
+
7
+ - `dev`: `pip install -e ".[dev]"` is enough for the per-commit gates below. A pull request must pass them.
8
+ - `e2e`: the browser tests under `tests/e2e/`. Install with `pip install -e ".[dev,e2e]"`, run `playwright install chromium` once, then `pytest -m e2e`. Plain `pytest` excludes these tests.
9
+ - `export`: shinylive, for the static Shinylive export. No per-commit gate needs it.
10
+
11
+ Local venv recipe (Windows): `py -3.12 -m venv .venv`, then `.venv\Scripts\python -m pip install -e ".[dev,export,e2e]"` and `.venv\Scripts\python -m playwright install chromium`.
12
+
13
+ After changing `src/progeny_selector/_version.py`, re-run `pip install -e .` so `tests/test_version.py` sees the new metadata.
14
+
15
+ ## Gates
16
+
17
+ All must pass before a pull request:
18
+
19
+ ```
20
+ ruff check .
21
+ ruff format --check .
22
+ mypy
23
+ pytest
24
+ python scripts/check_contract.py
25
+ python scripts/make_fixture.py
26
+ git diff --exit-code -- tests/fixtures src/progeny_selector/examples
27
+ ```
28
+
29
+ The generator is deterministic, so regenerating the fixture must leave `tests/fixtures` and `src/progeny_selector/examples` unchanged. Edit the generator, never the generated files.
30
+
31
+ ## Conventions
32
+
33
+ Commits follow Conventional Commits 1.0.0 (`feat(core): ...`, `fix(io): ...`, `docs: ...`, `test: ...`, `chore: ...`; `!` or a `BREAKING CHANGE:` footer for changes to the data contract or the results columns). Versions follow SemVer 2.0.0; docs/data-formats.md is part of the public interface. CHANGELOG.md follows Keep a Changelog 1.1.0; add a line under Unreleased with every user-visible change. Decisions are MADR files in docs/adr/, numbered sequentially; supersede rather than edit an accepted record.
34
+
35
+ ## Code rules
36
+
37
+ Everything in src/progeny_selector/core is pure: numpy arrays and dataclasses in, arrays and dataclasses out; no file I/O, no Shiny, no pandas. Validation happens once at the boundary (src/progeny_selector/io) and raises DataContractError or CriteriaError with the file, line and column. The UI (src/progeny_selector/app) calls `run_analysis` and renders rows; it computes nothing. Colours come only from `constants.STATE_COLORS` and `STATUS_COLORS` (Okabe-Ito). Every module starts with a docstring stating its responsibility and interface.
38
+
39
+ ## Data
40
+
41
+ Never commit genotype data other than the synthetic fixture; .gitignore excludes *.vcf, *.vcf.gz and *.hmp.txt outside tests/fixtures/.
42
+
43
+ ## Releasing
44
+
45
+ Releases are made by the maintainer only: set the version in `src/progeny_selector/_version.py`, CHANGELOG.md and CITATION.cff, push a `v<version>` tag, and `.github/workflows/release.yml` builds, publishes to PyPI by trusted publishing and creates the GitHub release with the CHANGELOG section as notes.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pierce Taylor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.5
2
+ Name: progeny-selector
3
+ Version: 0.1.0
4
+ Summary: Marker-assisted backcross progeny ranking and selection: foreground, background, linkage drag, avoid loci, composite scores.
5
+ Project-URL: Homepage, https://github.com/piercetaylor/progeny-selector
6
+ Project-URL: Documentation, https://github.com/piercetaylor/progeny-selector/blob/main/docs/README.md
7
+ Project-URL: Repository, https://github.com/piercetaylor/progeny-selector
8
+ Project-URL: Issues, https://github.com/piercetaylor/progeny-selector/issues
9
+ Project-URL: Changelog, https://github.com/piercetaylor/progeny-selector/blob/main/CHANGELOG.md
10
+ Project-URL: Browser app, https://piercetaylor.github.io/progeny-selector/
11
+ Author: Pierce Taylor
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Keywords: genotype,marker-assisted backcrossing,plant breeding,selection,soybean
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: numpy>=1.26
25
+ Requires-Dist: pandas>=2.2
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: shiny>=1.4
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
31
+ Requires-Dist: pytest>=8; extra == 'dev'
32
+ Requires-Dist: ruff>=0.6; extra == 'dev'
33
+ Provides-Extra: e2e
34
+ Requires-Dist: axe-playwright-python>=0.1; extra == 'e2e'
35
+ Requires-Dist: pytest-playwright>=0.5; extra == 'e2e'
36
+ Provides-Extra: export
37
+ Requires-Dist: shinylive>=0.8; extra == 'export'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # progeny-selector
41
+
42
+ progeny-selector ranks candidates in marker-assisted backcross breeding. It checks target and avoid loci, estimates recurrent-parent recovery and donor-segment bounds, applies quality flags and selection criteria, and exports ranked results, selections, and a manifest for the next generation. The analysis runs as a Python package and command-line tool, with a Shiny interface for local use or a browser-hosted site.
43
+
44
+ Status: version 0.1.0; see [CHANGELOG.md](https://github.com/piercetaylor/progeny-selector/blob/main/CHANGELOG.md) and [Known limitations](#known-limitations).
45
+
46
+ ## Install
47
+
48
+ Python 3.11 or newer is required.
49
+
50
+ ```sh
51
+ python -m pip install progeny-selector
52
+ ```
53
+
54
+ or, to keep it out of your other Python projects:
55
+
56
+ ```sh
57
+ pipx install progeny-selector
58
+ ```
59
+
60
+ On Windows, use `py -3 -m pip install progeny-selector`. If the `progeny-selector` command is not found afterwards, run `py -3 -m progeny_selector ...` instead, or install with pipx (`py -3 -m pip install --user pipx && py -3 -m pipx ensurepath`).
61
+
62
+ ## Open the interface
63
+
64
+ ```sh
65
+ progeny-selector app
66
+ ```
67
+
68
+ This opens a browser tab at http://127.0.0.1:8000/. Options: `--port`, `--host` and `--no-browser`. Press Ctrl+C in the terminal to stop it.
69
+
70
+ Or use the [browser site](https://piercetaylor.github.io/progeny-selector/): files are processed in the tab and never uploaded. Both offer **Load example (synthetic BC2F1)** on the Load screen.
71
+
72
+ ## Run the example
73
+
74
+ ```sh
75
+ progeny-selector example --out example
76
+ progeny-selector validate --genotypes example/synthetic_bc2f1/genotypes.vcf --samples example/synthetic_bc2f1/samples.csv --markers example/synthetic_bc2f1/markers.csv --criteria example/synthetic_bc2f1/criteria.yaml
77
+ progeny-selector rank --genotypes example/synthetic_bc2f1/genotypes.vcf --samples example/synthetic_bc2f1/samples.csv --markers example/synthetic_bc2f1/markers.csv --criteria example/synthetic_bc2f1/criteria.yaml --out results.csv
78
+ progeny-selector select --results results.csv --top 3 --out selected.csv --next-manifest next_samples.csv --next-generation BC3F1 --samples example/synthetic_bc2f1/samples.csv
79
+ ```
80
+
81
+ The example has 500 markers, 2 parents and 40 BC2F1 progeny in 2 families; 11 of the 40 pass the hard filters. It is synthetic, and its rankings are test cases, not breeding recommendations.
82
+
83
+ For a step-by-step walk through the same data, see the [tutorial](https://github.com/piercetaylor/progeny-selector/blob/main/docs/tutorial.md).
84
+
85
+ ## What the outputs mean
86
+
87
+ `results.csv` has one row per individual:
88
+
89
+ - `rank_overall` and `rank_in_family`, `passes_filters` and `exclusion_reason`, and `composite_score`.
90
+ - `rpp_total`, `rpp_carrier` and `rpp_noncarrier`: recurrent-parent recovery overall, on chromosomes that carry a target locus, and on those that do not.
91
+ - `drag_total_est` and `drag_total_max`, with `drag_unit` naming the unit of both.
92
+ - `missing_rate` and `qc_flags`.
93
+ - One status column per target and avoid locus, and one `rpp_<chromosome>` column per chromosome.
94
+ - `results_schema` names the column layout. `background_model`, `background_unit`, `background_max_marker_coverage`, `assembly` and `crop` record how the numbers were computed.
95
+
96
+ `selected.csv` holds the chosen individuals, with a `notes` column. `next_samples.csv` is a `samples.csv` for the next genotyping round.
97
+
98
+ Further reading: the [tutorial](https://github.com/piercetaylor/progeny-selector/blob/main/docs/tutorial.md), the [glossary](https://github.com/piercetaylor/progeny-selector/blob/main/docs/glossary.md), and [selection and output formats](https://github.com/piercetaylor/progeny-selector/blob/main/docs/data-formats.md).
99
+
100
+ ### What `--top N` selects
101
+
102
+ `select --top N` keeps every passing individual ranked N or better within its family, so up to N per family. With `--overall` it keeps the N best overall instead. Ranks are dense (tied individuals share a rank and the next rank follows without a gap), so ties can return more than N.
103
+
104
+ On the example, `--top 3` writes 6 rows: 3 in family F1 and 3 in F2. `--top 3 --overall` writes 3. The Selection screen's "add top N per family" does the same as `--top N`.
105
+
106
+ ## Your own data
107
+
108
+ - Genotypes: VCF, HapMap or wide CSV, each optionally gzip- or bgzip-compressed (`.gz`, `.bgz`); the file extension selects the format. Every call is diploid. On the command line, a BrAPI v2.1 server can be the source instead (`--brapi-url`, `--variant-set`, `--brapi-token-env`).
109
+ - `samples.csv`: columns `sample_id` and `role` are required; `line_name`, `generation`, `family_id` and `notes` are optional. `role` is `recurrent_parent`, `donor_parent`, `candidate` or `progeny`. The file needs exactly one recurrent parent, exactly one donor parent, and at least one candidate or progeny.
110
+ - `criteria.yaml`: the top-level keys are `name`, `targets`, `avoid`, `flank_window`, `flank_unit`, `assembly`, `background`, `ranking`, `weights` and `filters`. Unknown keys are an error.
111
+ - `markers.csv` (optional): `marker_id`, `chrom` and `pos_bp` are required; `cm` is optional and enables cM-weighted recovery and cM segment bounds. Positions here override those in the genotype file.
112
+ - Crop: `--crop` selects one of 13 chromosome-naming schemes (soybean, maize, rice, sorghum, wheat, barley, oat, common bean, cotton, cowpea, pea, peanut, sunflower). Soybean is the default. The `assembly` key in `criteria.yaml` (`Wm82.a1`, `Wm82.a2`, `Wm82.a4` or `none`) sets the chromosome-length table used for chromosome ends.
113
+ - `--profile` chooses how HapMap and wide CSV cell values are read: one of the built-in token profiles (`tassel`, `soybase-report`, `dart`, `axiom`, `kasp`) or your own JSON file.
114
+
115
+ Details: the [input contract](https://github.com/piercetaylor/progeny-selector/blob/main/contract/data-contract.md), [selection and output formats](https://github.com/piercetaylor/progeny-selector/blob/main/docs/data-formats.md), and [soybean inputs](https://github.com/piercetaylor/progeny-selector/blob/main/docs/soybean-inputs.md).
116
+
117
+ ## Known limitations
118
+
119
+ 1. `possible_duplicate` is raw pairwise identity by state of at least 0.995 over informative markers, and it does not consider family. It is advisory only ([ADR 0017](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0017-duplicate-flag.md)).
120
+ 2. The two-generation round trip is verified on synthetic data only. No real linked BC(n) to BC(n+1) dataset has been run.
121
+ 3. The browser site has no BrAPI source. BrAPI is command-line only until a server sends CORS headers for the site's origin ([ADR 0024](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0024-brapi-allele-matrix-loader.md)).
122
+ 4. One donor per analysis. An intercross or pyramiding population is not ranked ([contract](https://github.com/piercetaylor/progeny-selector/blob/main/contract/data-contract.md), [ADR 0002](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0002-input-data-contract.md)).
123
+ 5. Chromosome-length tables exist for soybean only (Wm82.a1, Wm82.a2 and Wm82.a4). Under any other crop a chromosome ends at its last marker ([ADR 0020](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0020-contract-1.5-crop-schemes.md)).
124
+ 6. The default cap of 2 Mb on base-pair coverage is a soybean translation of 10 cM. Set `background.max_marker_coverage` for other crops ([ADR 0033](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0033-results-schema-1.2-cap-and-end-rule.md)).
125
+ 7. A VCF 4.4 leading phase indicator in GT is rejected as `genotypes.invalid_gt` (contract 1.10.0).
126
+ 8. Accessibility: selecting several rows in the Rank grid needs a mouse; three axe rules are recorded exceptions; there is no screen-reader, Firefox, Safari or 320 px reflow testing ([accessibility review](https://github.com/piercetaylor/progeny-selector/blob/main/docs/accessibility.md)).
127
+ 9. Purdy labels: single crosses only, and no heterozygosity checks, because the label carries no filial generation ([ADR 0034](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0034-purdy-generation-labels.md)).
128
+ 10. The long-format KASP header names are unconfirmed against a real LGC export ([ADR 0019](https://github.com/piercetaylor/progeny-selector/blob/main/docs/adr/0019-soybean-input-tooling.md)).
129
+ 11. CI runs the browser tests on Linux only; Windows and macOS run the unit tests.
130
+
131
+ ## Verification
132
+
133
+ From a source checkout, `ruff check .`, `ruff format --check .`, `mypy` and `pytest -q` check the package. Browser and static-export checks, and the real-data verification with its limits, are described in [the plan](https://github.com/piercetaylor/progeny-selector/blob/main/PLAN.md). Measured run time and memory at several dataset sizes: [limits](https://github.com/piercetaylor/progeny-selector/blob/main/docs/limits.md). The WCAG 2.2 AA review is in the [accessibility review](https://github.com/piercetaylor/progeny-selector/blob/main/docs/accessibility.md). Design decisions are in [docs/adr](https://github.com/piercetaylor/progeny-selector/tree/main/docs/adr).
134
+
135
+ ## Related tool
136
+
137
+ [backcross](https://github.com/piercetaylor/backcross) is the sibling browser-based tool. backcross characterises finished near-isogenic lines; progeny-selector ranks progeny during the programme. Both read input data contract 1.12.0, so genotype, samples.csv and markers.csv files move between them unchanged. The two tools release v0.1.0 on the same day, and each release note links the other's.
138
+
139
+ ## Citing
140
+
141
+ Cite the software with [CITATION.cff](https://github.com/piercetaylor/progeny-selector/blob/main/CITATION.cff). GitHub shows a Cite this repository button for it. A Zenodo DOI is added after the first release. In plain text:
142
+
143
+ Taylor, P. (2026). progeny-selector (version 0.1.0) [Computer software]. https://github.com/piercetaylor/progeny-selector
144
+
145
+ ## Licence
146
+
147
+ MIT. See [LICENSE](https://github.com/piercetaylor/progeny-selector/blob/main/LICENSE).