@sjcrh/proteinpaint-client 2.208.0 → 2.210.0

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 (940) hide show
  1. package/dist/2dmaf-43QBND66.js +1367 -0
  2. package/dist/AggMatrixInput-X7NGFUHH.js +406 -0
  3. package/dist/AggregateMatrix-M4HRI4PX.js +41 -0
  4. package/dist/AppHeader-QBRQN6PM.js +830 -0
  5. package/dist/BoxPlot-V6SPSEQ2.js +1211 -0
  6. package/dist/CorrelationVolcano-UFPCYC77.js +617 -0
  7. package/dist/Cuminc-KXGXGLKZ.js +1219 -0
  8. package/dist/DE-K2YXHOOW.js +89 -0
  9. package/dist/DEinput-O6LBFAAH.js +501 -0
  10. package/dist/DEinput-O6LBFAAH.js.map +7 -0
  11. package/dist/DM-C7VN3RWB.js +90 -0
  12. package/dist/DifferentialAnalysis-A2BU4WB3.js +239 -0
  13. package/dist/DifferentialAnalysis-A2BU4WB3.js.map +7 -0
  14. package/dist/Disco-HECQVKXG.js +3389 -0
  15. package/dist/Disco.UI-XF2GEKRW.js +243 -0
  16. package/dist/DmrPlot-TVXVXOHL.js +362 -0
  17. package/dist/DmrPlot-TVXVXOHL.js.map +7 -0
  18. package/dist/GB-66ZGJ5ST.js +1428 -0
  19. package/dist/GB-66ZGJ5ST.js.map +7 -0
  20. package/dist/GSEA-Z4YPI4HY.js +875 -0
  21. package/dist/GSEA-Z4YPI4HY.js.map +7 -0
  22. package/dist/GeneExpInput-VBIZZV27.js +42 -0
  23. package/dist/Geomap-UIIOLRFA.js +84 -0
  24. package/dist/HicApp-73ESVNBA.js +2245 -0
  25. package/dist/IDCViewer-RBYN5A4P.js +10812 -0
  26. package/dist/NumBinaryEditor-DJLSNSLE.js +279 -0
  27. package/dist/NumBinaryEditor.unit.spec-LCJHL3XM.js +312 -0
  28. package/dist/NumContEditor-SVLDJ2ML.js +105 -0
  29. package/dist/NumContEditor.unit.spec-JDMSK4HY.js +164 -0
  30. package/dist/NumCustomBinEditor-BI63AH3R.js +33 -0
  31. package/dist/NumCustomBinEditor.unit.spec-5433G7Y2.js +397 -0
  32. package/dist/NumDiscreteEditor-LEZTGXAV.js +170 -0
  33. package/dist/NumDiscreteEditor.unit.spec-5OEORHJ4.js +233 -0
  34. package/dist/NumRegularBinEditor-EXWHIWPM.js +33 -0
  35. package/dist/NumRegularBinEditor.unit.spec-QY25Z2TT.js +278 -0
  36. package/dist/NumSplineEditor-XPPMYYAD.js +210 -0
  37. package/dist/NumSplineEditor.unit.spec-GOGBKWMN.js +224 -0
  38. package/dist/NumericDensity-RKY2IQ72.js +33 -0
  39. package/dist/NumericDensity.unit.spec-5ZM6ICXM.js +418 -0
  40. package/dist/NumericHandler-FXF3M5M3.js +34 -0
  41. package/dist/NumericHandler.unit.spec-M2OQTBJX.js +214 -0
  42. package/dist/ProteomeInput-TMZ3THRL.js +388 -0
  43. package/dist/Regression-GQGAATHG.js +1416 -0
  44. package/dist/Regression-GQGAATHG.js.map +7 -0
  45. package/dist/RunChart2-7GNDWRKC.js +749 -0
  46. package/dist/SC-R2I2EMHA.js +1183 -0
  47. package/dist/SC-R2I2EMHA.js.map +7 -0
  48. package/dist/Violin-GKKEB55L.js +1081 -0
  49. package/dist/Violin-GKKEB55L.js.map +7 -0
  50. package/dist/Volcano-HRG5EFWH.js +2443 -0
  51. package/dist/Volcano-HRG5EFWH.js.map +7 -0
  52. package/dist/Wsi-OHRCGYYD.js +629 -0
  53. package/dist/adSandbox-H56B25WR.js +33 -0
  54. package/dist/animatedBubbleChart-7SXFHU4J.js +547 -0
  55. package/dist/app-22JCSULA.js +42 -0
  56. package/dist/app-RGZJB6LN.js +32 -0
  57. package/dist/app.js +14 -14
  58. package/dist/bam-HA65TRGX.js +876 -0
  59. package/dist/barchart-6XO75OMA.js +42 -0
  60. package/dist/barchart2-6E5BIRHD.js +309 -0
  61. package/dist/block-43KNTXZ5.js +6250 -0
  62. package/dist/block-43KNTXZ5.js.map +7 -0
  63. package/dist/block.init-TPU5QIPA.js +33 -0
  64. package/dist/block.mds.expressionrank-QZDRFXCH.js +354 -0
  65. package/dist/block.mds.geneboxplot-64QVBK5Q.js +823 -0
  66. package/dist/block.mds.junction-I4J6VXNT.js +1539 -0
  67. package/dist/block.mds.svcnv-GDQMSQFF.js +6796 -0
  68. package/dist/block.svg-2MZFT5QP.js +159 -0
  69. package/dist/block.tk.aicheck-2MKHF6LX.js +278 -0
  70. package/dist/block.tk.ase-CLYGKFTS.js +360 -0
  71. package/dist/block.tk.bam-XTR4QA5Z.js +1901 -0
  72. package/dist/block.tk.bedgraphdot-A2P2CXRU.js +379 -0
  73. package/dist/block.tk.bigwig.ui-YZH6JXEO.js +206 -0
  74. package/dist/block.tk.hicstraw-QBK5VWGU.js +818 -0
  75. package/dist/block.tk.junction-5DEVBA7G.js +2358 -0
  76. package/dist/block.tk.junction.textmatrixui-7TTQMO6W.js +194 -0
  77. package/dist/block.tk.ld-PRIVUPKL.js +94 -0
  78. package/dist/block.tk.menu-JGBRFSS3.js +1024 -0
  79. package/dist/block.tk.pgv-KQJCJMVD.js +938 -0
  80. package/dist/brainImaging-4SLVJ2HV.js +555 -0
  81. package/dist/brainRegions-BDIVM2SG.js +217 -0
  82. package/dist/bubbleHeatmap-ORKFJNEQ.js +378 -0
  83. package/dist/cellTypeBubbleHeatmap-VOHLI4P7.js +278 -0
  84. package/dist/chunk-26N3B2JO.js +194 -0
  85. package/dist/chunk-2HNJF5ZI.js +240 -0
  86. package/dist/chunk-2LNGHIOC.js +281 -0
  87. package/dist/chunk-3FEP6B5T.js +119 -0
  88. package/dist/chunk-3SCQGODD.js +274 -0
  89. package/dist/chunk-47STLK7K.js +518 -0
  90. package/dist/chunk-4G73CMUL.js +38 -0
  91. package/dist/chunk-4XYQG3XU.js +276 -0
  92. package/dist/chunk-53XNEXR6.js +34 -0
  93. package/dist/chunk-55FABQU2.js +24955 -0
  94. package/dist/chunk-55FABQU2.js.map +7 -0
  95. package/dist/chunk-5UB5H7A3.js +123 -0
  96. package/dist/chunk-6FYQYTV6.js +141 -0
  97. package/dist/chunk-6RP6CR4Q.js +182 -0
  98. package/dist/chunk-A5D37SIL.js +103 -0
  99. package/dist/chunk-ADRFQ5AL.js +102 -0
  100. package/dist/chunk-AUZ63NKJ.js +70 -0
  101. package/dist/chunk-B563DUNQ.js +217 -0
  102. package/dist/chunk-B563DUNQ.js.map +7 -0
  103. package/dist/chunk-BK6UDL7F.js +339 -0
  104. package/dist/chunk-CFZ2ZW3E.js +382 -0
  105. package/dist/chunk-CKOU3P27.js +26 -0
  106. package/dist/chunk-CT4IG5IR.js +339 -0
  107. package/dist/chunk-D6UBH77N.js +1731 -0
  108. package/dist/chunk-DS4GLMJL.js +170 -0
  109. package/dist/chunk-DSBRHWZ7.js +2853 -0
  110. package/dist/chunk-DX35MKPR.js +272 -0
  111. package/dist/chunk-EDZJ3VNZ.js +54 -0
  112. package/dist/chunk-F47A4CVK.js +1339 -0
  113. package/dist/chunk-FSLOUTTK.js +37 -0
  114. package/dist/chunk-FSLOUTTK.js.map +7 -0
  115. package/dist/chunk-G4H34RNK.js +446 -0
  116. package/dist/chunk-G7RUMSHL.js +263 -0
  117. package/dist/chunk-GXFS25SK.js +480 -0
  118. package/dist/chunk-I25LKYC4.js +379 -0
  119. package/dist/chunk-I25LKYC4.js.map +7 -0
  120. package/dist/chunk-IAB2PRIH.js +396 -0
  121. package/dist/chunk-IAB2PRIH.js.map +7 -0
  122. package/dist/chunk-IBT6WRY6.js +692 -0
  123. package/dist/chunk-IJ7AIDEO.js +302 -0
  124. package/dist/chunk-JBFVJHZN.js +1233 -0
  125. package/dist/chunk-JDVBUIEU.js +56 -0
  126. package/dist/chunk-JTANDSTD.js +54 -0
  127. package/dist/chunk-K7RW5TPU.js +4375 -0
  128. package/dist/chunk-KIAMLQ7S.js +424 -0
  129. package/dist/chunk-KIAMLQ7S.js.map +7 -0
  130. package/dist/chunk-LBCIXRI2.js +49 -0
  131. package/dist/chunk-MNXL2UV5.js +98 -0
  132. package/dist/chunk-NDOKW2HJ.js +31 -0
  133. package/dist/chunk-NI5CVN43.js +203 -0
  134. package/dist/chunk-NOBXDQDU.js +397 -0
  135. package/dist/chunk-NQNVLZOA.js +6360 -0
  136. package/dist/chunk-NULFGPE3.js +158 -0
  137. package/dist/chunk-OUIXGM3K.js +299 -0
  138. package/dist/chunk-P4LGA36F.js +14 -0
  139. package/dist/chunk-PU5FQWAY.js +55 -0
  140. package/dist/chunk-PZ2OSHBF.js +56 -0
  141. package/dist/chunk-QBNDPW7O.js +5071 -0
  142. package/dist/chunk-QD75Q5LM.js +59 -0
  143. package/dist/chunk-R5PKBL7V.js +80 -0
  144. package/dist/chunk-R5PKBL7V.js.map +7 -0
  145. package/dist/chunk-RFSOP75Z.js +1988 -0
  146. package/dist/chunk-RFSOP75Z.js.map +7 -0
  147. package/dist/chunk-RI65SIN3.js +626 -0
  148. package/dist/chunk-RPGLLO4T.js +2676 -0
  149. package/dist/chunk-RXNZK7MF.js +134 -0
  150. package/dist/chunk-S2ICJ3RZ.js +550 -0
  151. package/dist/chunk-SB36AUG7.js +1614 -0
  152. package/dist/chunk-SB36AUG7.js.map +7 -0
  153. package/dist/chunk-SFHG6H2D.js +129 -0
  154. package/dist/chunk-TQ2DVEQO.js +783 -0
  155. package/dist/chunk-U6BJ4ZNU.js +176 -0
  156. package/dist/chunk-UXD6G6G4.js +178 -0
  157. package/dist/chunk-VA57CUC7.js +2146 -0
  158. package/dist/chunk-VA57CUC7.js.map +7 -0
  159. package/dist/chunk-VH5W6ODW.js +294 -0
  160. package/dist/chunk-VROF55EH.js +255 -0
  161. package/dist/chunk-VROF55EH.js.map +7 -0
  162. package/dist/chunk-VWA7BYSV.js +217 -0
  163. package/dist/chunk-X37BRSGS.js +102 -0
  164. package/dist/chunk-XQYDXA47.js +562 -0
  165. package/dist/chunk-XXPUZVS4.js +237 -0
  166. package/dist/chunk-XXPUZVS4.js.map +7 -0
  167. package/dist/chunk-Y7V5AIUH.js +468 -0
  168. package/dist/chunk-YBNIOGUE.js +243 -0
  169. package/dist/chunk-YEYMNF7V.js +2327 -0
  170. package/dist/chunk-YJ74QATP.js +1278 -0
  171. package/dist/chunk-ZG2HCGAO.js +2784 -0
  172. package/dist/chunk-ZZN7ZD7J.js +54 -0
  173. package/dist/cohort-6OCRQQ2S.js +70 -0
  174. package/dist/condition-SZVXH3VU.js +327 -0
  175. package/dist/controls-MO6ZND76.js +34 -0
  176. package/dist/controls.config-P4MSTGL4.js +34 -0
  177. package/dist/correlation-NMI3CM3T.js +95 -0
  178. package/dist/customdata.inputui-VCHSCA65.js +284 -0
  179. package/dist/dataDownload-VQHOTQ5D.js +329 -0
  180. package/dist/databrowser.ui-ZFOCAG32.js +425 -0
  181. package/dist/dictionary-S5YCFUWH.js +113 -0
  182. package/dist/dnaMethylation-MQZLZRGT.js +33 -0
  183. package/dist/dnaMethylation.integration.spec-H546EBUO.js +198 -0
  184. package/dist/dofetch-QZIYSC7H.js +48 -0
  185. package/dist/e2pca-XOXOS3PN.js +344 -0
  186. package/dist/ep-U6KRL7FR.js +1249 -0
  187. package/dist/expclust.gdc.spec-HCK65C63.js +302 -0
  188. package/dist/facet-DCC25KJO.js +519 -0
  189. package/dist/gb-TIFWFD4Y.js +81 -0
  190. package/dist/geneExpClustering-6DQEOTOY.js +244 -0
  191. package/dist/geneExpression-EASRAN6B.js +310 -0
  192. package/dist/geneExpression-G4YMDCBH.js +33 -0
  193. package/dist/geneExpression.unit.spec-XVEJYMPX.js +128 -0
  194. package/dist/geneExpression.unit.spec-XVEJYMPX.js.map +7 -0
  195. package/dist/geneORA-6UBS5GSC.js +273 -0
  196. package/dist/geneRanking-UXXYWHNB.js +548 -0
  197. package/dist/geneVariant-SZRJOXVC.js +289 -0
  198. package/dist/geneVariant-SZRJOXVC.js.map +7 -0
  199. package/dist/geneVariant-TKFKARZK.js +36 -0
  200. package/dist/geneVariant.integration.spec-PXMAYJN3.js +503 -0
  201. package/dist/geneVariant.integration.spec-PXMAYJN3.js.map +7 -0
  202. package/dist/genefusion.ui-TJLYXSVL.js +303 -0
  203. package/dist/geneset-YTBDLEIH.js +203 -0
  204. package/dist/genomeBrowser.spec-ZO4LFIXE.js +276 -0
  205. package/dist/grin2-FC4VYU54.js +949 -0
  206. package/dist/grin2-FC4VYU54.js.map +7 -0
  207. package/dist/grin2-LIFKBMVK.js +70 -0
  208. package/dist/hierCluster-56EGAPOR.js +59 -0
  209. package/dist/hierCluster-DR5NWCXA.js +55 -0
  210. package/dist/hierCluster.config-NACE3FH2.js +36 -0
  211. package/dist/hierCluster.integration.spec-PEEXPAS6.js +483 -0
  212. package/dist/hierCluster.interactivity-OCBGLUJM.js +49 -0
  213. package/dist/hierCluster.renderers-JNQUSAP4.js +19 -0
  214. package/dist/imagePlot-GR4JNUGG.js +156 -0
  215. package/dist/importPlot-4R4BSPVD.js +8 -0
  216. package/dist/isoformExpression-ST5ZW2NE.js +35 -0
  217. package/dist/isoformExpression.unit.spec-PPFC5Z7N.js +237 -0
  218. package/dist/junction-7AKZHOHV.js +36 -0
  219. package/dist/junction.customTerm-TMV43R7Z.js +16 -0
  220. package/dist/junction.unit.spec-SZUJXRQ2.js +182 -0
  221. package/dist/launch.adhoc-RWJQUOJ6.js +37 -0
  222. package/dist/leftlabel.sample-WRHLVQAQ.js +258 -0
  223. package/dist/lollipop-ZZWXTM23.js +166 -0
  224. package/dist/maf-N4XPZTQU.js +455 -0
  225. package/dist/maftimeline-2FBS6RWS.js +587 -0
  226. package/dist/matrix-5KEQPB5H.js +59 -0
  227. package/dist/matrix-RJUNXB5N.js +54 -0
  228. package/dist/matrix.cells-WXTPOJYB.js +26 -0
  229. package/dist/matrix.config-ZZFLLD6Z.js +37 -0
  230. package/dist/matrix.data-3PQ73GVJ.js +23 -0
  231. package/dist/matrix.groups-U6CKS6WW.js +26 -0
  232. package/dist/matrix.integration.spec-T53PMVHC.js +3160 -0
  233. package/dist/matrix.integration.spec-T53PMVHC.js.map +7 -0
  234. package/dist/matrix.interactivity-3LDZV3F7.js +37 -0
  235. package/dist/matrix.layout-MINLYQCA.js +39 -0
  236. package/dist/matrix.legend-6GSDFZHS.js +20 -0
  237. package/dist/matrix.renderers-5BKOXDE3.js +34 -0
  238. package/dist/matrix.serieses-6FCFIFAQ.js +19 -0
  239. package/dist/matrix.sort-EHVVYDZ3.js +26 -0
  240. package/dist/matrix.sort.unit.spec-BCWE4AFX.js +468 -0
  241. package/dist/matrix.sorterUi-WL5I6S3K.js +16 -0
  242. package/dist/matrix.sorterUi.unit.spec-XJR5KXRL.js +338 -0
  243. package/dist/matrix.unit.spec-TUCKPE26.js +150 -0
  244. package/dist/mavb-GWSNRBLM.js +727 -0
  245. package/dist/mds.fimo-OMAQRSMW.js +513 -0
  246. package/dist/mds.samplescatterplot-4UW3CC45.js +1545 -0
  247. package/dist/mds.survivalplot-2CJYJBD2.js +477 -0
  248. package/dist/multivalue-G44MHEYI.js +83 -0
  249. package/dist/numericDictTermCluster-5BDRGVQG.js +63 -0
  250. package/dist/oncomatrix-ZTVO23ZH.js +290 -0
  251. package/dist/oncomatrix.spec-2QVK2A3Q.js +443 -0
  252. package/dist/plot.2dvaf-CL5YUXKH.js +372 -0
  253. package/dist/plot.app-4ANKPSNP.js +36 -0
  254. package/dist/plot.barplot-BMGDNZRA.js +97 -0
  255. package/dist/plot.boxplot-GMLQCDP6.js +146 -0
  256. package/dist/plot.brainImaging-RZXX3NUZ.js +51 -0
  257. package/dist/plot.disco-3MD4J4C7.js +99 -0
  258. package/dist/plot.ssgq-ZC4UYKOT.js +134 -0
  259. package/dist/plot.vaf2cov-4DHFMYQV.js +253 -0
  260. package/dist/polar2-TMB5EITR.js +232 -0
  261. package/dist/profileForms-GD7BIOOD.js +941 -0
  262. package/dist/profilePlot-CZLK5E74.js +49 -0
  263. package/dist/proteinView-FEEEXLKT.js +1357 -0
  264. package/dist/proteomeCohortCompare-NVLJ2FXX.js +912 -0
  265. package/dist/pseudbulk.unit.spec-GHQZPNAH.js +86 -0
  266. package/dist/pseudobulk-G5UQIRKL.js +35 -0
  267. package/dist/qualitative-EAUUCKU5.js +38 -0
  268. package/dist/radar2-CJQ2L6KE.js +327 -0
  269. package/dist/radarFacility2-BLVRZE4V.js +335 -0
  270. package/dist/rememberedGvQ.unit.spec-DYRO2LO5.js +211 -0
  271. package/dist/render-KKAQPH6Y.js +33 -0
  272. package/dist/report-OSOJHTSD.js +217 -0
  273. package/dist/sampleView-WB74RLD7.js +43 -0
  274. package/dist/samplelst-ZKXV5WOD.js +106 -0
  275. package/dist/samplematrix-WJFYMWLT.js +2193 -0
  276. package/dist/sc-RBRBUCLR.js +81 -0
  277. package/dist/scatter-5K3QTIDK.js +88 -0
  278. package/dist/scatter-SM7GQENM.js +925 -0
  279. package/dist/selectGenomeWithTklst-ZZUJ7AQ7.js +129 -0
  280. package/dist/singleCellCellType-LCF2JNZ2.js +33 -0
  281. package/dist/singleCellCellType.unit.spec-T6DYH4BC.js +154 -0
  282. package/dist/singleCellGeneExpression-2XUYTH4C.js +33 -0
  283. package/dist/singleCellGeneExpression.unit.spec-SMRCLOF4.js +148 -0
  284. package/dist/singleCellNumericValue-57I33FZT.js +33 -0
  285. package/dist/singleCellNumericValue.unit.spec-4YNB4OEV.js +416 -0
  286. package/dist/singleCellPlot-L6TKQHGD.js +48 -0
  287. package/dist/singlecell-LZKR3UDV.js +81 -0
  288. package/dist/singlecell-UKN2VCXQ.js +1566 -0
  289. package/dist/snp-3LJITU5B.js +33 -0
  290. package/dist/snp.unit.spec-ZQNU6XRM.js +171 -0
  291. package/dist/snplocus-OME7UQBW.js +203 -0
  292. package/dist/spliceevent.a53ss.diagram-C32IEFMU.js +146 -0
  293. package/dist/spliceevent.exonskip.diagram-CZ7MVRLK.js +278 -0
  294. package/dist/spliceevent.noeventdiagram-ZO6R3776.js +455 -0
  295. package/dist/ssGSEA-BGPQ2PFY.js +33 -0
  296. package/dist/ssGSEA.unit.spec-U7TBUSSK.js +83 -0
  297. package/dist/stattable-FISGQCED.js +117 -0
  298. package/dist/studyCatalog-UHFUT2CJ.js +414 -0
  299. package/dist/summarizeCnvGeneexp-OVZO6KIB.js +158 -0
  300. package/dist/summarizeGeneexpSurvival-KVQ4JGWK.js +105 -0
  301. package/dist/summarizeMutationCnv-RAKGHNLE.js +159 -0
  302. package/dist/summarizeMutationDiagnosis-LGCINAGG.js +35 -0
  303. package/dist/summarizeMutationSurvival-J7H7L4FX.js +99 -0
  304. package/dist/summary-2632JZXH.js +44 -0
  305. package/dist/summary.integration.spec-5WBS2ZRP.js +409 -0
  306. package/dist/summaryInput-BH6C3ATV.js +242 -0
  307. package/dist/sunburst-AMRR2IHM.js +278 -0
  308. package/dist/survival-2RNJQVFS.js +1248 -0
  309. package/dist/survival-WYCH4QOQ.js +53 -0
  310. package/dist/survival.integration.spec-7IFPY4I4.js +613 -0
  311. package/dist/svgraph-YQWS52ZJ.js +1382 -0
  312. package/dist/svmr-NRN6LGKK.js +3837 -0
  313. package/dist/table-3QOMV2NN.js +197 -0
  314. package/dist/termCollection-2ZJ7TJGO.js +33 -0
  315. package/dist/termCollection-3MCVR7BA.js +252 -0
  316. package/dist/termCollection.unit.spec-QYOEA3X6.js +299 -0
  317. package/dist/termCollectionFractionSelection-5AH6EF4L.js +42 -0
  318. package/dist/termCollectionFractionSelection.unit.spec-WPGW4WJN.js +188 -0
  319. package/dist/tk-DQ7D5UEO.js +41 -0
  320. package/dist/tk-ONKYBG6R.js +1121 -0
  321. package/dist/tp.ui-C7BTMHEI.js +1454 -0
  322. package/dist/tvs.dt-PLRMK7OT.js +34 -0
  323. package/dist/tvs.dtcnv.categorical-IZUY2AQO.js +35 -0
  324. package/dist/tvs.dtcnv.continuous-ENV3RHHA.js +67 -0
  325. package/dist/tvs.dtfusion-2DVCV6AM.js +35 -0
  326. package/dist/tvs.dtitd-XNDIRQYU.js +35 -0
  327. package/dist/tvs.dtsnvindel-4D3G7XSF.js +35 -0
  328. package/dist/tvs.dtsv-QYMIMC4Z.js +35 -0
  329. package/dist/tvs.numeric-M5LH3PRH.js +20 -0
  330. package/dist/tvs.samplelst-2KEU2ZWB.js +98 -0
  331. package/dist/tvs.termCollection-FEY746V5.js +124 -0
  332. package/dist/vocabulary-BR4NJDPS.js +36 -0
  333. package/dist/wsi.direct-JWDUNHIO.js +8343 -0
  334. package/package.json +3 -3
  335. package/dist/2dmaf-PN5YS362.js +0 -1367
  336. package/dist/AggMatrixInput-NJHU4FU2.js +0 -406
  337. package/dist/AggregateMatrix-IBWOJWOC.js +0 -41
  338. package/dist/AppHeader-XV6S7GG5.js +0 -830
  339. package/dist/BoxPlot-ZIVA55SK.js +0 -1211
  340. package/dist/CorrelationVolcano-33I4FC44.js +0 -617
  341. package/dist/Cuminc-WKY35UGV.js +0 -1219
  342. package/dist/DE-E256DHID.js +0 -89
  343. package/dist/DEinput-YU3W72K7.js +0 -499
  344. package/dist/DEinput-YU3W72K7.js.map +0 -7
  345. package/dist/DM-W7PXTIKY.js +0 -90
  346. package/dist/DifferentialAnalysis-SHMQHWJL.js +0 -236
  347. package/dist/DifferentialAnalysis-SHMQHWJL.js.map +0 -7
  348. package/dist/Disco-OZY5GW2Z.js +0 -3389
  349. package/dist/Disco.UI-NRALEYXK.js +0 -243
  350. package/dist/DmrPlot-QKUX5XUW.js +0 -637
  351. package/dist/DmrPlot-QKUX5XUW.js.map +0 -7
  352. package/dist/GB-ZYH7PGHT.js +0 -1391
  353. package/dist/GB-ZYH7PGHT.js.map +0 -7
  354. package/dist/GSEA-VQTD4MLY.js +0 -851
  355. package/dist/GSEA-VQTD4MLY.js.map +0 -7
  356. package/dist/GeneExpInput-XEFUTLFU.js +0 -42
  357. package/dist/Geomap-GEK7UEDU.js +0 -84
  358. package/dist/HicApp-ZY7UHV5H.js +0 -2245
  359. package/dist/IDCViewer-YNKG4V46.js +0 -10812
  360. package/dist/NumBinaryEditor-NEL727DX.js +0 -279
  361. package/dist/NumBinaryEditor.unit.spec-GCGZMJYF.js +0 -312
  362. package/dist/NumContEditor-IM6RRDGU.js +0 -105
  363. package/dist/NumContEditor.unit.spec-B5AJXANS.js +0 -164
  364. package/dist/NumCustomBinEditor-EZT5DRKP.js +0 -33
  365. package/dist/NumCustomBinEditor.unit.spec-KLUDS6TH.js +0 -397
  366. package/dist/NumDiscreteEditor-2M6Q5AAZ.js +0 -170
  367. package/dist/NumDiscreteEditor.unit.spec-2JYZYJUX.js +0 -233
  368. package/dist/NumRegularBinEditor-AQDHA2PU.js +0 -33
  369. package/dist/NumRegularBinEditor.unit.spec-62BYFNYG.js +0 -278
  370. package/dist/NumSplineEditor-6Y5TZSTO.js +0 -210
  371. package/dist/NumSplineEditor.unit.spec-S65AV5EK.js +0 -224
  372. package/dist/NumericDensity-5ES4SDWZ.js +0 -33
  373. package/dist/NumericDensity.unit.spec-J6KZSE2P.js +0 -418
  374. package/dist/NumericHandler-ZTLDPP2F.js +0 -34
  375. package/dist/NumericHandler.unit.spec-BZFBVHGU.js +0 -214
  376. package/dist/ProteomeInput-IKEXPCGV.js +0 -388
  377. package/dist/Regression-6F6YP3AX.js +0 -1416
  378. package/dist/Regression-6F6YP3AX.js.map +0 -7
  379. package/dist/RunChart2-CVRPXQH5.js +0 -749
  380. package/dist/SC-FPXVXBXF.js +0 -1175
  381. package/dist/SC-FPXVXBXF.js.map +0 -7
  382. package/dist/Violin-BAS6DQHL.js +0 -1081
  383. package/dist/Violin-BAS6DQHL.js.map +0 -7
  384. package/dist/Volcano-FCCWUMX7.js +0 -1649
  385. package/dist/Volcano-FCCWUMX7.js.map +0 -7
  386. package/dist/Wsi-3YTFABWG.js +0 -629
  387. package/dist/adSandbox-QYIG6637.js +0 -33
  388. package/dist/animatedBubbleChart-X53PR73H.js +0 -547
  389. package/dist/app-HJLTRZPI.js +0 -32
  390. package/dist/app-MGY6A4DM.js +0 -42
  391. package/dist/bam-VRQHRCP5.js +0 -876
  392. package/dist/barchart-TWMOUZFL.js +0 -42
  393. package/dist/barchart2-CV7RMMRG.js +0 -309
  394. package/dist/block-L53P4UGQ.js +0 -6249
  395. package/dist/block-L53P4UGQ.js.map +0 -7
  396. package/dist/block.init-XYOJTXKP.js +0 -33
  397. package/dist/block.mds.expressionrank-77FSBDHA.js +0 -354
  398. package/dist/block.mds.geneboxplot-4TSYV4WS.js +0 -823
  399. package/dist/block.mds.junction-P4MYDET6.js +0 -1539
  400. package/dist/block.mds.svcnv-CYOFAS2T.js +0 -6796
  401. package/dist/block.svg-IT3ELCF4.js +0 -159
  402. package/dist/block.tk.aicheck-GULHJLV5.js +0 -278
  403. package/dist/block.tk.ase-RW5YL6HN.js +0 -360
  404. package/dist/block.tk.bam-MPGQW6KB.js +0 -1901
  405. package/dist/block.tk.bedgraphdot-EYRY374P.js +0 -379
  406. package/dist/block.tk.bigwig.ui-BKSXCDNM.js +0 -206
  407. package/dist/block.tk.hicstraw-76PV6NM3.js +0 -818
  408. package/dist/block.tk.junction-Z52QHQJQ.js +0 -2358
  409. package/dist/block.tk.junction.textmatrixui-K32OOTZC.js +0 -194
  410. package/dist/block.tk.ld-DDGLRHPO.js +0 -94
  411. package/dist/block.tk.menu-MO6TESKI.js +0 -1024
  412. package/dist/block.tk.pgv-AKLKKSEP.js +0 -938
  413. package/dist/brainImaging-KSTJQJAB.js +0 -555
  414. package/dist/brainRegions-WCRMMSK4.js +0 -217
  415. package/dist/bubbleHeatmap-4YOQ3BAB.js +0 -378
  416. package/dist/cellTypeBubbleHeatmap-O6YZ2RW4.js +0 -278
  417. package/dist/chunk-3GUVLDUS.js +0 -299
  418. package/dist/chunk-3PQDD5HM.js +0 -446
  419. package/dist/chunk-3WYUHDDP.js +0 -1986
  420. package/dist/chunk-3WYUHDDP.js.map +0 -7
  421. package/dist/chunk-4C7MA5Q3.js +0 -158
  422. package/dist/chunk-4EZLVENZ.js +0 -1612
  423. package/dist/chunk-4EZLVENZ.js.map +0 -7
  424. package/dist/chunk-4PB5ZEOB.js +0 -102
  425. package/dist/chunk-5IMFPVGT.js +0 -119
  426. package/dist/chunk-6DPELKO5.js +0 -518
  427. package/dist/chunk-6HGTVMZM.js +0 -54
  428. package/dist/chunk-72P6O537.js +0 -1731
  429. package/dist/chunk-74C6G6JD.js +0 -397
  430. package/dist/chunk-A7TXS6JR.js +0 -276
  431. package/dist/chunk-AAJXHERO.js +0 -123
  432. package/dist/chunk-AVS4IXEA.js +0 -692
  433. package/dist/chunk-BFXZBZEV.js +0 -176
  434. package/dist/chunk-BGVGN73F.js +0 -480
  435. package/dist/chunk-BL7EYUZC.js +0 -6360
  436. package/dist/chunk-BPGZUNLL.js +0 -274
  437. package/dist/chunk-CPIPN5F6.js +0 -141
  438. package/dist/chunk-D5MSWPAZ.js +0 -217
  439. package/dist/chunk-DFT2PAIU.js +0 -243
  440. package/dist/chunk-DMWOK4DS.js +0 -178
  441. package/dist/chunk-E7NVJ44Z.js +0 -263
  442. package/dist/chunk-EMMGUSJB.js +0 -54
  443. package/dist/chunk-G3CCQOLH.js +0 -240
  444. package/dist/chunk-GGQVDHYF.js +0 -379
  445. package/dist/chunk-GGQVDHYF.js.map +0 -7
  446. package/dist/chunk-GMRIEUBW.js +0 -408
  447. package/dist/chunk-GMRIEUBW.js.map +0 -7
  448. package/dist/chunk-GPZYAJQH.js +0 -2676
  449. package/dist/chunk-GS6ZMPKP.js +0 -272
  450. package/dist/chunk-GUXKLMLM.js +0 -102
  451. package/dist/chunk-HELEV3LT.js +0 -2853
  452. package/dist/chunk-HKKTNIMX.js +0 -339
  453. package/dist/chunk-HKSRIEWJ.js +0 -26
  454. package/dist/chunk-IELQ3HMN.js +0 -70
  455. package/dist/chunk-IISNWG4X.js +0 -103
  456. package/dist/chunk-J7KB2MH3.js +0 -34
  457. package/dist/chunk-JEJV7V7M.js +0 -2327
  458. package/dist/chunk-JIZ3B32T.js +0 -626
  459. package/dist/chunk-KAY2ODXX.js +0 -38
  460. package/dist/chunk-KJM6PLXM.js +0 -5071
  461. package/dist/chunk-KTKZSYIH.js +0 -24
  462. package/dist/chunk-KTKZSYIH.js.map +0 -7
  463. package/dist/chunk-KZHF3MQX.js +0 -1278
  464. package/dist/chunk-MC674TS2.js +0 -194
  465. package/dist/chunk-MLKQZ3RL.js +0 -1339
  466. package/dist/chunk-MSSPT5YM.js +0 -550
  467. package/dist/chunk-N6IWVSFP.js +0 -4375
  468. package/dist/chunk-NBGVEZNX.js +0 -56
  469. package/dist/chunk-OBBR4UYN.js +0 -54
  470. package/dist/chunk-PQA3C2NY.js +0 -294
  471. package/dist/chunk-QJ2VBXFB.js +0 -134
  472. package/dist/chunk-QJ3HYZH3.js +0 -24772
  473. package/dist/chunk-QJ3HYZH3.js.map +0 -7
  474. package/dist/chunk-QP7EJXSU.js +0 -55
  475. package/dist/chunk-QUHXX7JE.js +0 -56
  476. package/dist/chunk-REPQKF5L.js +0 -182
  477. package/dist/chunk-SHXJW27D.js +0 -2784
  478. package/dist/chunk-SUNDNTVY.js +0 -302
  479. package/dist/chunk-SYPSS3JQ.js +0 -387
  480. package/dist/chunk-SYPSS3JQ.js.map +0 -7
  481. package/dist/chunk-TSI4W6XO.js +0 -98
  482. package/dist/chunk-TXIQ5PHR.js +0 -468
  483. package/dist/chunk-U45R6QNT.js +0 -562
  484. package/dist/chunk-UMZJQWWK.js +0 -1233
  485. package/dist/chunk-VMRO6DMC.js +0 -2140
  486. package/dist/chunk-VMRO6DMC.js.map +0 -7
  487. package/dist/chunk-VO7Q4WMM.js +0 -55
  488. package/dist/chunk-VO7Q4WMM.js.map +0 -7
  489. package/dist/chunk-VWGRKOVJ.js +0 -170
  490. package/dist/chunk-WCTKHF5T.js +0 -197
  491. package/dist/chunk-WCTKHF5T.js.map +0 -7
  492. package/dist/chunk-WOMERKMR.js +0 -31
  493. package/dist/chunk-WXX2YD4Q.js +0 -59
  494. package/dist/chunk-X44AR557.js +0 -382
  495. package/dist/chunk-XEU5HXOY.js +0 -783
  496. package/dist/chunk-XGYQZHNX.js +0 -281
  497. package/dist/chunk-XOND7UIK.js +0 -49
  498. package/dist/chunk-XRMUUWLS.js +0 -339
  499. package/dist/chunk-XTOGCXPD.js +0 -129
  500. package/dist/chunk-Y5BBFDC3.js +0 -14
  501. package/dist/chunk-Z2FSHODI.js +0 -203
  502. package/dist/cohort-JWIQOO7U.js +0 -70
  503. package/dist/condition-ZUAQYF5C.js +0 -327
  504. package/dist/controls-ZPQ6SXD2.js +0 -34
  505. package/dist/controls.config-NELL5HY5.js +0 -34
  506. package/dist/correlation-2X76UI3K.js +0 -95
  507. package/dist/customdata.inputui-V6QIGFRP.js +0 -284
  508. package/dist/dataDownload-NSDY4MSL.js +0 -329
  509. package/dist/databrowser.ui-DDLFQB6K.js +0 -425
  510. package/dist/dictionary-WSDD6TFI.js +0 -113
  511. package/dist/dnaMethylation-3IM4OACZ.js +0 -33
  512. package/dist/dnaMethylation.integration.spec-5CSJA67S.js +0 -198
  513. package/dist/dofetch-GZ7POIBV.js +0 -48
  514. package/dist/e2pca-AX7U2DOI.js +0 -344
  515. package/dist/ep-UKACHFJU.js +0 -1249
  516. package/dist/expclust.gdc.spec-46HDKH2Q.js +0 -302
  517. package/dist/facet-3EONZDDE.js +0 -519
  518. package/dist/gb-W7GX5NWS.js +0 -81
  519. package/dist/geneExpClustering-PJA6Y5GW.js +0 -244
  520. package/dist/geneExpression-EMLVPVNK.js +0 -310
  521. package/dist/geneExpression-JMGYBT53.js +0 -33
  522. package/dist/geneExpression.unit.spec-DDZVZJVC.js +0 -128
  523. package/dist/geneExpression.unit.spec-DDZVZJVC.js.map +0 -7
  524. package/dist/geneORA-CIAFQQWB.js +0 -273
  525. package/dist/geneRanking-JRAU6FMJ.js +0 -548
  526. package/dist/geneVariant-3DZTWQFG.js +0 -36
  527. package/dist/geneVariant-YWURIZ72.js +0 -286
  528. package/dist/geneVariant-YWURIZ72.js.map +0 -7
  529. package/dist/geneVariant.integration.spec-V3KECZMM.js +0 -489
  530. package/dist/geneVariant.integration.spec-V3KECZMM.js.map +0 -7
  531. package/dist/genefusion.ui-AO3TUDTL.js +0 -303
  532. package/dist/geneset-RCIP2GZH.js +0 -203
  533. package/dist/genomeBrowser.spec-7PZCNBL3.js +0 -276
  534. package/dist/grin2-EUBCNH4Q.js +0 -70
  535. package/dist/grin2-YYBB5XJK.js +0 -1137
  536. package/dist/grin2-YYBB5XJK.js.map +0 -7
  537. package/dist/hierCluster-AV5NO2GW.js +0 -59
  538. package/dist/hierCluster-W2MVN34V.js +0 -55
  539. package/dist/hierCluster.config-4MBWG6RZ.js +0 -36
  540. package/dist/hierCluster.integration.spec-JUIBIUKH.js +0 -483
  541. package/dist/hierCluster.interactivity-6PJE64PF.js +0 -49
  542. package/dist/hierCluster.renderers-RWDQ5SHY.js +0 -19
  543. package/dist/imagePlot-XLDQNUJA.js +0 -156
  544. package/dist/importPlot-7FISAQKR.js +0 -8
  545. package/dist/isoformExpression-WOQAOVZS.js +0 -35
  546. package/dist/isoformExpression.unit.spec-BMEGJNCO.js +0 -237
  547. package/dist/junction-6NO36IPU.js +0 -36
  548. package/dist/junction.customTerm-N6JAOWZO.js +0 -16
  549. package/dist/junction.unit.spec-UKGSQHO4.js +0 -182
  550. package/dist/launch.adhoc-42PUNEA6.js +0 -37
  551. package/dist/leftlabel.sample-EXAUDPSB.js +0 -258
  552. package/dist/lollipop-4ASTA5HO.js +0 -166
  553. package/dist/maf-HPXANL3M.js +0 -455
  554. package/dist/maftimeline-2SXFX3HF.js +0 -587
  555. package/dist/matrix-DX4W5XMX.js +0 -59
  556. package/dist/matrix-S34ITAPJ.js +0 -54
  557. package/dist/matrix.cells-BLULUGSZ.js +0 -26
  558. package/dist/matrix.config-Z3LWYH74.js +0 -37
  559. package/dist/matrix.data-73HY7Y2V.js +0 -23
  560. package/dist/matrix.groups-NOUMYNFY.js +0 -26
  561. package/dist/matrix.integration.spec-VTXYJ46U.js +0 -3160
  562. package/dist/matrix.integration.spec-VTXYJ46U.js.map +0 -7
  563. package/dist/matrix.interactivity-YHDIO5A2.js +0 -37
  564. package/dist/matrix.layout-25HYKUF2.js +0 -39
  565. package/dist/matrix.legend-IMK7DH4V.js +0 -20
  566. package/dist/matrix.renderers-3RZRN6HO.js +0 -34
  567. package/dist/matrix.serieses-ZTVHQ7QA.js +0 -19
  568. package/dist/matrix.sort-EDXHT6NZ.js +0 -26
  569. package/dist/matrix.sort.unit.spec-LSNY7PHU.js +0 -468
  570. package/dist/matrix.sorterUi-3DRNHG5Z.js +0 -16
  571. package/dist/matrix.sorterUi.unit.spec-GNIIWGRJ.js +0 -338
  572. package/dist/matrix.unit.spec-7A6ZFRXI.js +0 -150
  573. package/dist/mavb-M5AXPLYX.js +0 -727
  574. package/dist/mds.fimo-QE5OFA22.js +0 -513
  575. package/dist/mds.samplescatterplot-664EOHX2.js +0 -1545
  576. package/dist/mds.survivalplot-H4TJD44D.js +0 -477
  577. package/dist/multivalue-JD3CNQJR.js +0 -83
  578. package/dist/numericDictTermCluster-XPKEYXD7.js +0 -63
  579. package/dist/oncomatrix-TX5PZQ76.js +0 -290
  580. package/dist/oncomatrix.spec-6X2WAHL7.js +0 -443
  581. package/dist/plot.2dvaf-5OHUFTMK.js +0 -372
  582. package/dist/plot.app-XIVVJHWG.js +0 -36
  583. package/dist/plot.barplot-PSODLAXD.js +0 -97
  584. package/dist/plot.boxplot-W3ASYFOG.js +0 -146
  585. package/dist/plot.brainImaging-JGDLKLR7.js +0 -51
  586. package/dist/plot.disco-TPMXTTZK.js +0 -99
  587. package/dist/plot.ssgq-KIZIOZIF.js +0 -134
  588. package/dist/plot.vaf2cov-MSMW72IY.js +0 -253
  589. package/dist/polar2-LA4MSRRN.js +0 -232
  590. package/dist/profileForms-BJRNB2ZF.js +0 -941
  591. package/dist/profilePlot-DDO53C4T.js +0 -49
  592. package/dist/proteinView-NFUR42XQ.js +0 -1357
  593. package/dist/proteomeCohortCompare-OZVF3X66.js +0 -912
  594. package/dist/pseudbulk.unit.spec-RY72JF7A.js +0 -86
  595. package/dist/pseudobulk-UVT5G2VL.js +0 -35
  596. package/dist/qualitative-X3VXNC7X.js +0 -38
  597. package/dist/radar2-RTVUJ3AN.js +0 -327
  598. package/dist/radarFacility2-ZGLZ5AKM.js +0 -335
  599. package/dist/rememberedGvQ.unit.spec-RLLLWU5M.js +0 -211
  600. package/dist/render-LR5BOYW6.js +0 -33
  601. package/dist/report-37W5OXUM.js +0 -217
  602. package/dist/sampleView-BDC2WPH7.js +0 -43
  603. package/dist/samplelst-V2EIVZC5.js +0 -106
  604. package/dist/samplematrix-XOSKILUL.js +0 -2193
  605. package/dist/sc-ZVZPWQY7.js +0 -81
  606. package/dist/scatter-2ZE5MCYH.js +0 -88
  607. package/dist/scatter-ZOWFPGIS.js +0 -925
  608. package/dist/selectGenomeWithTklst-EF7WYEAJ.js +0 -129
  609. package/dist/singleCellCellType-TKCGC3G3.js +0 -33
  610. package/dist/singleCellCellType.unit.spec-JZ6UHC5F.js +0 -154
  611. package/dist/singleCellGeneExpression-I2INGXGI.js +0 -33
  612. package/dist/singleCellGeneExpression.unit.spec-KL77FSHZ.js +0 -148
  613. package/dist/singleCellNumericValue-2X5NCEHL.js +0 -33
  614. package/dist/singleCellNumericValue.unit.spec-OUDBX5MY.js +0 -416
  615. package/dist/singleCellPlot-Q6INE54V.js +0 -48
  616. package/dist/singlecell-5N2P5ZAT.js +0 -81
  617. package/dist/singlecell-NPSWMNI3.js +0 -1566
  618. package/dist/snp-2WPJYPDE.js +0 -33
  619. package/dist/snp.unit.spec-PPWIIOX6.js +0 -171
  620. package/dist/snplocus-T3HZFZWA.js +0 -203
  621. package/dist/spliceevent.a53ss.diagram-APCF4LV5.js +0 -146
  622. package/dist/spliceevent.exonskip.diagram-TT5JGBSC.js +0 -278
  623. package/dist/spliceevent.noeventdiagram-CPXQSX3Z.js +0 -455
  624. package/dist/ssGSEA-FSX6P7HA.js +0 -33
  625. package/dist/ssGSEA.unit.spec-TXYT665R.js +0 -83
  626. package/dist/stattable-BD64SFYV.js +0 -117
  627. package/dist/studyCatalog-6BOWO4PO.js +0 -414
  628. package/dist/summarizeCnvGeneexp-AMLYJIPU.js +0 -158
  629. package/dist/summarizeGeneexpSurvival-IDM7T333.js +0 -105
  630. package/dist/summarizeMutationCnv-R6SYSJQC.js +0 -159
  631. package/dist/summarizeMutationDiagnosis-XZJ4JLW2.js +0 -35
  632. package/dist/summarizeMutationSurvival-ABJ5RL4L.js +0 -99
  633. package/dist/summary-NVYCTE6P.js +0 -44
  634. package/dist/summary.integration.spec-SSLTLVNW.js +0 -409
  635. package/dist/summaryInput-SJOZETRP.js +0 -242
  636. package/dist/sunburst-RU5ZPJKW.js +0 -278
  637. package/dist/survival-BHJQMXKI.js +0 -53
  638. package/dist/survival-DVG6Y2FV.js +0 -1248
  639. package/dist/survival.integration.spec-OJUPTY5N.js +0 -613
  640. package/dist/svgraph-ETFA4GRX.js +0 -1382
  641. package/dist/svmr-AI3RU4JK.js +0 -3837
  642. package/dist/table-YCTSMLQL.js +0 -197
  643. package/dist/termCollection-GMKEZR6D.js +0 -252
  644. package/dist/termCollection-VEVKKJZD.js +0 -33
  645. package/dist/termCollection.unit.spec-EU6YCEPX.js +0 -299
  646. package/dist/termCollectionFractionSelection-UBS74X36.js +0 -42
  647. package/dist/termCollectionFractionSelection.unit.spec-Y5OJFGDD.js +0 -188
  648. package/dist/tk-HMF4HCNV.js +0 -1121
  649. package/dist/tk-W6Z4FJMW.js +0 -41
  650. package/dist/tp.ui-NECRDJCS.js +0 -1454
  651. package/dist/tvs.dt-2JEH3F35.js +0 -34
  652. package/dist/tvs.dtcnv.categorical-YBXKEBR2.js +0 -35
  653. package/dist/tvs.dtcnv.continuous-AD3SJ6BY.js +0 -67
  654. package/dist/tvs.dtfusion-ODI3CLQS.js +0 -35
  655. package/dist/tvs.dtitd-V3LYLPJY.js +0 -35
  656. package/dist/tvs.dtsnvindel-R3V5LTNL.js +0 -35
  657. package/dist/tvs.dtsv-ZQLKEDLJ.js +0 -35
  658. package/dist/tvs.numeric-22AHXO5K.js +0 -20
  659. package/dist/tvs.samplelst-G25A7HM6.js +0 -98
  660. package/dist/tvs.termCollection-WLVCWDEJ.js +0 -124
  661. package/dist/vocabulary-6K537FJM.js +0 -36
  662. package/dist/wsi.direct-SNPPQPVO.js +0 -8343
  663. /package/dist/{2dmaf-PN5YS362.js.map → 2dmaf-43QBND66.js.map} +0 -0
  664. /package/dist/{AggMatrixInput-NJHU4FU2.js.map → AggMatrixInput-X7NGFUHH.js.map} +0 -0
  665. /package/dist/{AggregateMatrix-IBWOJWOC.js.map → AggregateMatrix-M4HRI4PX.js.map} +0 -0
  666. /package/dist/{AppHeader-XV6S7GG5.js.map → AppHeader-QBRQN6PM.js.map} +0 -0
  667. /package/dist/{BoxPlot-ZIVA55SK.js.map → BoxPlot-V6SPSEQ2.js.map} +0 -0
  668. /package/dist/{CorrelationVolcano-33I4FC44.js.map → CorrelationVolcano-UFPCYC77.js.map} +0 -0
  669. /package/dist/{Cuminc-WKY35UGV.js.map → Cuminc-KXGXGLKZ.js.map} +0 -0
  670. /package/dist/{DE-E256DHID.js.map → DE-K2YXHOOW.js.map} +0 -0
  671. /package/dist/{DM-W7PXTIKY.js.map → DM-C7VN3RWB.js.map} +0 -0
  672. /package/dist/{Disco-OZY5GW2Z.js.map → Disco-HECQVKXG.js.map} +0 -0
  673. /package/dist/{Disco.UI-NRALEYXK.js.map → Disco.UI-XF2GEKRW.js.map} +0 -0
  674. /package/dist/{GeneExpInput-XEFUTLFU.js.map → GeneExpInput-VBIZZV27.js.map} +0 -0
  675. /package/dist/{Geomap-GEK7UEDU.js.map → Geomap-UIIOLRFA.js.map} +0 -0
  676. /package/dist/{HicApp-ZY7UHV5H.js.map → HicApp-73ESVNBA.js.map} +0 -0
  677. /package/dist/{IDCViewer-YNKG4V46.js.map → IDCViewer-RBYN5A4P.js.map} +0 -0
  678. /package/dist/{NumBinaryEditor-NEL727DX.js.map → NumBinaryEditor-DJLSNSLE.js.map} +0 -0
  679. /package/dist/{NumBinaryEditor.unit.spec-GCGZMJYF.js.map → NumBinaryEditor.unit.spec-LCJHL3XM.js.map} +0 -0
  680. /package/dist/{NumContEditor-IM6RRDGU.js.map → NumContEditor-SVLDJ2ML.js.map} +0 -0
  681. /package/dist/{NumContEditor.unit.spec-B5AJXANS.js.map → NumContEditor.unit.spec-JDMSK4HY.js.map} +0 -0
  682. /package/dist/{NumCustomBinEditor-EZT5DRKP.js.map → NumCustomBinEditor-BI63AH3R.js.map} +0 -0
  683. /package/dist/{NumCustomBinEditor.unit.spec-KLUDS6TH.js.map → NumCustomBinEditor.unit.spec-5433G7Y2.js.map} +0 -0
  684. /package/dist/{NumDiscreteEditor-2M6Q5AAZ.js.map → NumDiscreteEditor-LEZTGXAV.js.map} +0 -0
  685. /package/dist/{NumDiscreteEditor.unit.spec-2JYZYJUX.js.map → NumDiscreteEditor.unit.spec-5OEORHJ4.js.map} +0 -0
  686. /package/dist/{NumRegularBinEditor-AQDHA2PU.js.map → NumRegularBinEditor-EXWHIWPM.js.map} +0 -0
  687. /package/dist/{NumRegularBinEditor.unit.spec-62BYFNYG.js.map → NumRegularBinEditor.unit.spec-QY25Z2TT.js.map} +0 -0
  688. /package/dist/{NumSplineEditor-6Y5TZSTO.js.map → NumSplineEditor-XPPMYYAD.js.map} +0 -0
  689. /package/dist/{NumSplineEditor.unit.spec-S65AV5EK.js.map → NumSplineEditor.unit.spec-GOGBKWMN.js.map} +0 -0
  690. /package/dist/{NumericDensity-5ES4SDWZ.js.map → NumericDensity-RKY2IQ72.js.map} +0 -0
  691. /package/dist/{NumericDensity.unit.spec-J6KZSE2P.js.map → NumericDensity.unit.spec-5ZM6ICXM.js.map} +0 -0
  692. /package/dist/{NumericHandler-ZTLDPP2F.js.map → NumericHandler-FXF3M5M3.js.map} +0 -0
  693. /package/dist/{NumericHandler.unit.spec-BZFBVHGU.js.map → NumericHandler.unit.spec-M2OQTBJX.js.map} +0 -0
  694. /package/dist/{ProteomeInput-IKEXPCGV.js.map → ProteomeInput-TMZ3THRL.js.map} +0 -0
  695. /package/dist/{RunChart2-CVRPXQH5.js.map → RunChart2-7GNDWRKC.js.map} +0 -0
  696. /package/dist/{Wsi-3YTFABWG.js.map → Wsi-OHRCGYYD.js.map} +0 -0
  697. /package/dist/{adSandbox-QYIG6637.js.map → adSandbox-H56B25WR.js.map} +0 -0
  698. /package/dist/{animatedBubbleChart-X53PR73H.js.map → animatedBubbleChart-7SXFHU4J.js.map} +0 -0
  699. /package/dist/{app-HJLTRZPI.js.map → app-22JCSULA.js.map} +0 -0
  700. /package/dist/{app-MGY6A4DM.js.map → app-RGZJB6LN.js.map} +0 -0
  701. /package/dist/{bam-VRQHRCP5.js.map → bam-HA65TRGX.js.map} +0 -0
  702. /package/dist/{barchart-TWMOUZFL.js.map → barchart-6XO75OMA.js.map} +0 -0
  703. /package/dist/{barchart2-CV7RMMRG.js.map → barchart2-6E5BIRHD.js.map} +0 -0
  704. /package/dist/{block.init-XYOJTXKP.js.map → block.init-TPU5QIPA.js.map} +0 -0
  705. /package/dist/{block.mds.expressionrank-77FSBDHA.js.map → block.mds.expressionrank-QZDRFXCH.js.map} +0 -0
  706. /package/dist/{block.mds.geneboxplot-4TSYV4WS.js.map → block.mds.geneboxplot-64QVBK5Q.js.map} +0 -0
  707. /package/dist/{block.mds.junction-P4MYDET6.js.map → block.mds.junction-I4J6VXNT.js.map} +0 -0
  708. /package/dist/{block.mds.svcnv-CYOFAS2T.js.map → block.mds.svcnv-GDQMSQFF.js.map} +0 -0
  709. /package/dist/{block.svg-IT3ELCF4.js.map → block.svg-2MZFT5QP.js.map} +0 -0
  710. /package/dist/{block.tk.aicheck-GULHJLV5.js.map → block.tk.aicheck-2MKHF6LX.js.map} +0 -0
  711. /package/dist/{block.tk.ase-RW5YL6HN.js.map → block.tk.ase-CLYGKFTS.js.map} +0 -0
  712. /package/dist/{block.tk.bam-MPGQW6KB.js.map → block.tk.bam-XTR4QA5Z.js.map} +0 -0
  713. /package/dist/{block.tk.bedgraphdot-EYRY374P.js.map → block.tk.bedgraphdot-A2P2CXRU.js.map} +0 -0
  714. /package/dist/{block.tk.bigwig.ui-BKSXCDNM.js.map → block.tk.bigwig.ui-YZH6JXEO.js.map} +0 -0
  715. /package/dist/{block.tk.hicstraw-76PV6NM3.js.map → block.tk.hicstraw-QBK5VWGU.js.map} +0 -0
  716. /package/dist/{block.tk.junction-Z52QHQJQ.js.map → block.tk.junction-5DEVBA7G.js.map} +0 -0
  717. /package/dist/{block.tk.junction.textmatrixui-K32OOTZC.js.map → block.tk.junction.textmatrixui-7TTQMO6W.js.map} +0 -0
  718. /package/dist/{block.tk.ld-DDGLRHPO.js.map → block.tk.ld-PRIVUPKL.js.map} +0 -0
  719. /package/dist/{block.tk.menu-MO6TESKI.js.map → block.tk.menu-JGBRFSS3.js.map} +0 -0
  720. /package/dist/{block.tk.pgv-AKLKKSEP.js.map → block.tk.pgv-KQJCJMVD.js.map} +0 -0
  721. /package/dist/{brainImaging-KSTJQJAB.js.map → brainImaging-4SLVJ2HV.js.map} +0 -0
  722. /package/dist/{brainRegions-WCRMMSK4.js.map → brainRegions-BDIVM2SG.js.map} +0 -0
  723. /package/dist/{bubbleHeatmap-4YOQ3BAB.js.map → bubbleHeatmap-ORKFJNEQ.js.map} +0 -0
  724. /package/dist/{cellTypeBubbleHeatmap-O6YZ2RW4.js.map → cellTypeBubbleHeatmap-VOHLI4P7.js.map} +0 -0
  725. /package/dist/{chunk-MC674TS2.js.map → chunk-26N3B2JO.js.map} +0 -0
  726. /package/dist/{chunk-G3CCQOLH.js.map → chunk-2HNJF5ZI.js.map} +0 -0
  727. /package/dist/{chunk-XGYQZHNX.js.map → chunk-2LNGHIOC.js.map} +0 -0
  728. /package/dist/{chunk-5IMFPVGT.js.map → chunk-3FEP6B5T.js.map} +0 -0
  729. /package/dist/{chunk-BPGZUNLL.js.map → chunk-3SCQGODD.js.map} +0 -0
  730. /package/dist/{chunk-6DPELKO5.js.map → chunk-47STLK7K.js.map} +0 -0
  731. /package/dist/{chunk-KAY2ODXX.js.map → chunk-4G73CMUL.js.map} +0 -0
  732. /package/dist/{chunk-A7TXS6JR.js.map → chunk-4XYQG3XU.js.map} +0 -0
  733. /package/dist/{chunk-J7KB2MH3.js.map → chunk-53XNEXR6.js.map} +0 -0
  734. /package/dist/{chunk-AAJXHERO.js.map → chunk-5UB5H7A3.js.map} +0 -0
  735. /package/dist/{chunk-CPIPN5F6.js.map → chunk-6FYQYTV6.js.map} +0 -0
  736. /package/dist/{chunk-REPQKF5L.js.map → chunk-6RP6CR4Q.js.map} +0 -0
  737. /package/dist/{chunk-IISNWG4X.js.map → chunk-A5D37SIL.js.map} +0 -0
  738. /package/dist/{chunk-4PB5ZEOB.js.map → chunk-ADRFQ5AL.js.map} +0 -0
  739. /package/dist/{chunk-IELQ3HMN.js.map → chunk-AUZ63NKJ.js.map} +0 -0
  740. /package/dist/{chunk-HKKTNIMX.js.map → chunk-BK6UDL7F.js.map} +0 -0
  741. /package/dist/{chunk-X44AR557.js.map → chunk-CFZ2ZW3E.js.map} +0 -0
  742. /package/dist/{chunk-HKSRIEWJ.js.map → chunk-CKOU3P27.js.map} +0 -0
  743. /package/dist/{chunk-XRMUUWLS.js.map → chunk-CT4IG5IR.js.map} +0 -0
  744. /package/dist/{chunk-72P6O537.js.map → chunk-D6UBH77N.js.map} +0 -0
  745. /package/dist/{chunk-VWGRKOVJ.js.map → chunk-DS4GLMJL.js.map} +0 -0
  746. /package/dist/{chunk-HELEV3LT.js.map → chunk-DSBRHWZ7.js.map} +0 -0
  747. /package/dist/{chunk-GS6ZMPKP.js.map → chunk-DX35MKPR.js.map} +0 -0
  748. /package/dist/{chunk-6HGTVMZM.js.map → chunk-EDZJ3VNZ.js.map} +0 -0
  749. /package/dist/{chunk-MLKQZ3RL.js.map → chunk-F47A4CVK.js.map} +0 -0
  750. /package/dist/{chunk-3PQDD5HM.js.map → chunk-G4H34RNK.js.map} +0 -0
  751. /package/dist/{chunk-E7NVJ44Z.js.map → chunk-G7RUMSHL.js.map} +0 -0
  752. /package/dist/{chunk-BGVGN73F.js.map → chunk-GXFS25SK.js.map} +0 -0
  753. /package/dist/{chunk-AVS4IXEA.js.map → chunk-IBT6WRY6.js.map} +0 -0
  754. /package/dist/{chunk-SUNDNTVY.js.map → chunk-IJ7AIDEO.js.map} +0 -0
  755. /package/dist/{chunk-UMZJQWWK.js.map → chunk-JBFVJHZN.js.map} +0 -0
  756. /package/dist/{chunk-NBGVEZNX.js.map → chunk-JDVBUIEU.js.map} +0 -0
  757. /package/dist/{chunk-OBBR4UYN.js.map → chunk-JTANDSTD.js.map} +0 -0
  758. /package/dist/{chunk-N6IWVSFP.js.map → chunk-K7RW5TPU.js.map} +0 -0
  759. /package/dist/{chunk-XOND7UIK.js.map → chunk-LBCIXRI2.js.map} +0 -0
  760. /package/dist/{chunk-TSI4W6XO.js.map → chunk-MNXL2UV5.js.map} +0 -0
  761. /package/dist/{chunk-WOMERKMR.js.map → chunk-NDOKW2HJ.js.map} +0 -0
  762. /package/dist/{chunk-Z2FSHODI.js.map → chunk-NI5CVN43.js.map} +0 -0
  763. /package/dist/{chunk-74C6G6JD.js.map → chunk-NOBXDQDU.js.map} +0 -0
  764. /package/dist/{chunk-BL7EYUZC.js.map → chunk-NQNVLZOA.js.map} +0 -0
  765. /package/dist/{chunk-4C7MA5Q3.js.map → chunk-NULFGPE3.js.map} +0 -0
  766. /package/dist/{chunk-3GUVLDUS.js.map → chunk-OUIXGM3K.js.map} +0 -0
  767. /package/dist/{chunk-Y5BBFDC3.js.map → chunk-P4LGA36F.js.map} +0 -0
  768. /package/dist/{chunk-QP7EJXSU.js.map → chunk-PU5FQWAY.js.map} +0 -0
  769. /package/dist/{chunk-QUHXX7JE.js.map → chunk-PZ2OSHBF.js.map} +0 -0
  770. /package/dist/{chunk-KJM6PLXM.js.map → chunk-QBNDPW7O.js.map} +0 -0
  771. /package/dist/{chunk-WXX2YD4Q.js.map → chunk-QD75Q5LM.js.map} +0 -0
  772. /package/dist/{chunk-JIZ3B32T.js.map → chunk-RI65SIN3.js.map} +0 -0
  773. /package/dist/{chunk-GPZYAJQH.js.map → chunk-RPGLLO4T.js.map} +0 -0
  774. /package/dist/{chunk-QJ2VBXFB.js.map → chunk-RXNZK7MF.js.map} +0 -0
  775. /package/dist/{chunk-MSSPT5YM.js.map → chunk-S2ICJ3RZ.js.map} +0 -0
  776. /package/dist/{chunk-XTOGCXPD.js.map → chunk-SFHG6H2D.js.map} +0 -0
  777. /package/dist/{chunk-XEU5HXOY.js.map → chunk-TQ2DVEQO.js.map} +0 -0
  778. /package/dist/{chunk-BFXZBZEV.js.map → chunk-U6BJ4ZNU.js.map} +0 -0
  779. /package/dist/{chunk-DMWOK4DS.js.map → chunk-UXD6G6G4.js.map} +0 -0
  780. /package/dist/{chunk-PQA3C2NY.js.map → chunk-VH5W6ODW.js.map} +0 -0
  781. /package/dist/{chunk-D5MSWPAZ.js.map → chunk-VWA7BYSV.js.map} +0 -0
  782. /package/dist/{chunk-GUXKLMLM.js.map → chunk-X37BRSGS.js.map} +0 -0
  783. /package/dist/{chunk-U45R6QNT.js.map → chunk-XQYDXA47.js.map} +0 -0
  784. /package/dist/{chunk-TXIQ5PHR.js.map → chunk-Y7V5AIUH.js.map} +0 -0
  785. /package/dist/{chunk-DFT2PAIU.js.map → chunk-YBNIOGUE.js.map} +0 -0
  786. /package/dist/{chunk-JEJV7V7M.js.map → chunk-YEYMNF7V.js.map} +0 -0
  787. /package/dist/{chunk-KZHF3MQX.js.map → chunk-YJ74QATP.js.map} +0 -0
  788. /package/dist/{chunk-SHXJW27D.js.map → chunk-ZG2HCGAO.js.map} +0 -0
  789. /package/dist/{chunk-EMMGUSJB.js.map → chunk-ZZN7ZD7J.js.map} +0 -0
  790. /package/dist/{cohort-JWIQOO7U.js.map → cohort-6OCRQQ2S.js.map} +0 -0
  791. /package/dist/{condition-ZUAQYF5C.js.map → condition-SZVXH3VU.js.map} +0 -0
  792. /package/dist/{controls-ZPQ6SXD2.js.map → controls-MO6ZND76.js.map} +0 -0
  793. /package/dist/{controls.config-NELL5HY5.js.map → controls.config-P4MSTGL4.js.map} +0 -0
  794. /package/dist/{correlation-2X76UI3K.js.map → correlation-NMI3CM3T.js.map} +0 -0
  795. /package/dist/{customdata.inputui-V6QIGFRP.js.map → customdata.inputui-VCHSCA65.js.map} +0 -0
  796. /package/dist/{dataDownload-NSDY4MSL.js.map → dataDownload-VQHOTQ5D.js.map} +0 -0
  797. /package/dist/{databrowser.ui-DDLFQB6K.js.map → databrowser.ui-ZFOCAG32.js.map} +0 -0
  798. /package/dist/{dictionary-WSDD6TFI.js.map → dictionary-S5YCFUWH.js.map} +0 -0
  799. /package/dist/{dnaMethylation-3IM4OACZ.js.map → dnaMethylation-MQZLZRGT.js.map} +0 -0
  800. /package/dist/{dnaMethylation.integration.spec-5CSJA67S.js.map → dnaMethylation.integration.spec-H546EBUO.js.map} +0 -0
  801. /package/dist/{dofetch-GZ7POIBV.js.map → dofetch-QZIYSC7H.js.map} +0 -0
  802. /package/dist/{e2pca-AX7U2DOI.js.map → e2pca-XOXOS3PN.js.map} +0 -0
  803. /package/dist/{ep-UKACHFJU.js.map → ep-U6KRL7FR.js.map} +0 -0
  804. /package/dist/{expclust.gdc.spec-46HDKH2Q.js.map → expclust.gdc.spec-HCK65C63.js.map} +0 -0
  805. /package/dist/{facet-3EONZDDE.js.map → facet-DCC25KJO.js.map} +0 -0
  806. /package/dist/{gb-W7GX5NWS.js.map → gb-TIFWFD4Y.js.map} +0 -0
  807. /package/dist/{geneExpClustering-PJA6Y5GW.js.map → geneExpClustering-6DQEOTOY.js.map} +0 -0
  808. /package/dist/{geneExpression-EMLVPVNK.js.map → geneExpression-EASRAN6B.js.map} +0 -0
  809. /package/dist/{geneExpression-JMGYBT53.js.map → geneExpression-G4YMDCBH.js.map} +0 -0
  810. /package/dist/{geneORA-CIAFQQWB.js.map → geneORA-6UBS5GSC.js.map} +0 -0
  811. /package/dist/{geneRanking-JRAU6FMJ.js.map → geneRanking-UXXYWHNB.js.map} +0 -0
  812. /package/dist/{geneVariant-3DZTWQFG.js.map → geneVariant-TKFKARZK.js.map} +0 -0
  813. /package/dist/{genefusion.ui-AO3TUDTL.js.map → genefusion.ui-TJLYXSVL.js.map} +0 -0
  814. /package/dist/{geneset-RCIP2GZH.js.map → geneset-YTBDLEIH.js.map} +0 -0
  815. /package/dist/{genomeBrowser.spec-7PZCNBL3.js.map → genomeBrowser.spec-ZO4LFIXE.js.map} +0 -0
  816. /package/dist/{grin2-EUBCNH4Q.js.map → grin2-LIFKBMVK.js.map} +0 -0
  817. /package/dist/{hierCluster-AV5NO2GW.js.map → hierCluster-56EGAPOR.js.map} +0 -0
  818. /package/dist/{hierCluster-W2MVN34V.js.map → hierCluster-DR5NWCXA.js.map} +0 -0
  819. /package/dist/{hierCluster.config-4MBWG6RZ.js.map → hierCluster.config-NACE3FH2.js.map} +0 -0
  820. /package/dist/{hierCluster.integration.spec-JUIBIUKH.js.map → hierCluster.integration.spec-PEEXPAS6.js.map} +0 -0
  821. /package/dist/{hierCluster.interactivity-6PJE64PF.js.map → hierCluster.interactivity-OCBGLUJM.js.map} +0 -0
  822. /package/dist/{hierCluster.renderers-RWDQ5SHY.js.map → hierCluster.renderers-JNQUSAP4.js.map} +0 -0
  823. /package/dist/{imagePlot-XLDQNUJA.js.map → imagePlot-GR4JNUGG.js.map} +0 -0
  824. /package/dist/{importPlot-7FISAQKR.js.map → importPlot-4R4BSPVD.js.map} +0 -0
  825. /package/dist/{isoformExpression-WOQAOVZS.js.map → isoformExpression-ST5ZW2NE.js.map} +0 -0
  826. /package/dist/{isoformExpression.unit.spec-BMEGJNCO.js.map → isoformExpression.unit.spec-PPFC5Z7N.js.map} +0 -0
  827. /package/dist/{junction-6NO36IPU.js.map → junction-7AKZHOHV.js.map} +0 -0
  828. /package/dist/{junction.customTerm-N6JAOWZO.js.map → junction.customTerm-TMV43R7Z.js.map} +0 -0
  829. /package/dist/{junction.unit.spec-UKGSQHO4.js.map → junction.unit.spec-SZUJXRQ2.js.map} +0 -0
  830. /package/dist/{launch.adhoc-42PUNEA6.js.map → launch.adhoc-RWJQUOJ6.js.map} +0 -0
  831. /package/dist/{leftlabel.sample-EXAUDPSB.js.map → leftlabel.sample-WRHLVQAQ.js.map} +0 -0
  832. /package/dist/{lollipop-4ASTA5HO.js.map → lollipop-ZZWXTM23.js.map} +0 -0
  833. /package/dist/{maf-HPXANL3M.js.map → maf-N4XPZTQU.js.map} +0 -0
  834. /package/dist/{maftimeline-2SXFX3HF.js.map → maftimeline-2FBS6RWS.js.map} +0 -0
  835. /package/dist/{matrix-DX4W5XMX.js.map → matrix-5KEQPB5H.js.map} +0 -0
  836. /package/dist/{matrix-S34ITAPJ.js.map → matrix-RJUNXB5N.js.map} +0 -0
  837. /package/dist/{matrix.cells-BLULUGSZ.js.map → matrix.cells-WXTPOJYB.js.map} +0 -0
  838. /package/dist/{matrix.config-Z3LWYH74.js.map → matrix.config-ZZFLLD6Z.js.map} +0 -0
  839. /package/dist/{matrix.data-73HY7Y2V.js.map → matrix.data-3PQ73GVJ.js.map} +0 -0
  840. /package/dist/{matrix.groups-NOUMYNFY.js.map → matrix.groups-U6CKS6WW.js.map} +0 -0
  841. /package/dist/{matrix.interactivity-YHDIO5A2.js.map → matrix.interactivity-3LDZV3F7.js.map} +0 -0
  842. /package/dist/{matrix.layout-25HYKUF2.js.map → matrix.layout-MINLYQCA.js.map} +0 -0
  843. /package/dist/{matrix.legend-IMK7DH4V.js.map → matrix.legend-6GSDFZHS.js.map} +0 -0
  844. /package/dist/{matrix.renderers-3RZRN6HO.js.map → matrix.renderers-5BKOXDE3.js.map} +0 -0
  845. /package/dist/{matrix.serieses-ZTVHQ7QA.js.map → matrix.serieses-6FCFIFAQ.js.map} +0 -0
  846. /package/dist/{matrix.sort-EDXHT6NZ.js.map → matrix.sort-EHVVYDZ3.js.map} +0 -0
  847. /package/dist/{matrix.sort.unit.spec-LSNY7PHU.js.map → matrix.sort.unit.spec-BCWE4AFX.js.map} +0 -0
  848. /package/dist/{matrix.sorterUi-3DRNHG5Z.js.map → matrix.sorterUi-WL5I6S3K.js.map} +0 -0
  849. /package/dist/{matrix.sorterUi.unit.spec-GNIIWGRJ.js.map → matrix.sorterUi.unit.spec-XJR5KXRL.js.map} +0 -0
  850. /package/dist/{matrix.unit.spec-7A6ZFRXI.js.map → matrix.unit.spec-TUCKPE26.js.map} +0 -0
  851. /package/dist/{mavb-M5AXPLYX.js.map → mavb-GWSNRBLM.js.map} +0 -0
  852. /package/dist/{mds.fimo-QE5OFA22.js.map → mds.fimo-OMAQRSMW.js.map} +0 -0
  853. /package/dist/{mds.samplescatterplot-664EOHX2.js.map → mds.samplescatterplot-4UW3CC45.js.map} +0 -0
  854. /package/dist/{mds.survivalplot-H4TJD44D.js.map → mds.survivalplot-2CJYJBD2.js.map} +0 -0
  855. /package/dist/{multivalue-JD3CNQJR.js.map → multivalue-G44MHEYI.js.map} +0 -0
  856. /package/dist/{numericDictTermCluster-XPKEYXD7.js.map → numericDictTermCluster-5BDRGVQG.js.map} +0 -0
  857. /package/dist/{oncomatrix-TX5PZQ76.js.map → oncomatrix-ZTVO23ZH.js.map} +0 -0
  858. /package/dist/{oncomatrix.spec-6X2WAHL7.js.map → oncomatrix.spec-2QVK2A3Q.js.map} +0 -0
  859. /package/dist/{plot.2dvaf-5OHUFTMK.js.map → plot.2dvaf-CL5YUXKH.js.map} +0 -0
  860. /package/dist/{plot.app-XIVVJHWG.js.map → plot.app-4ANKPSNP.js.map} +0 -0
  861. /package/dist/{plot.barplot-PSODLAXD.js.map → plot.barplot-BMGDNZRA.js.map} +0 -0
  862. /package/dist/{plot.boxplot-W3ASYFOG.js.map → plot.boxplot-GMLQCDP6.js.map} +0 -0
  863. /package/dist/{plot.brainImaging-JGDLKLR7.js.map → plot.brainImaging-RZXX3NUZ.js.map} +0 -0
  864. /package/dist/{plot.disco-TPMXTTZK.js.map → plot.disco-3MD4J4C7.js.map} +0 -0
  865. /package/dist/{plot.ssgq-KIZIOZIF.js.map → plot.ssgq-ZC4UYKOT.js.map} +0 -0
  866. /package/dist/{plot.vaf2cov-MSMW72IY.js.map → plot.vaf2cov-4DHFMYQV.js.map} +0 -0
  867. /package/dist/{polar2-LA4MSRRN.js.map → polar2-TMB5EITR.js.map} +0 -0
  868. /package/dist/{profileForms-BJRNB2ZF.js.map → profileForms-GD7BIOOD.js.map} +0 -0
  869. /package/dist/{profilePlot-DDO53C4T.js.map → profilePlot-CZLK5E74.js.map} +0 -0
  870. /package/dist/{proteinView-NFUR42XQ.js.map → proteinView-FEEEXLKT.js.map} +0 -0
  871. /package/dist/{proteomeCohortCompare-OZVF3X66.js.map → proteomeCohortCompare-NVLJ2FXX.js.map} +0 -0
  872. /package/dist/{pseudbulk.unit.spec-RY72JF7A.js.map → pseudbulk.unit.spec-GHQZPNAH.js.map} +0 -0
  873. /package/dist/{pseudobulk-UVT5G2VL.js.map → pseudobulk-G5UQIRKL.js.map} +0 -0
  874. /package/dist/{qualitative-X3VXNC7X.js.map → qualitative-EAUUCKU5.js.map} +0 -0
  875. /package/dist/{radar2-RTVUJ3AN.js.map → radar2-CJQ2L6KE.js.map} +0 -0
  876. /package/dist/{radarFacility2-ZGLZ5AKM.js.map → radarFacility2-BLVRZE4V.js.map} +0 -0
  877. /package/dist/{rememberedGvQ.unit.spec-RLLLWU5M.js.map → rememberedGvQ.unit.spec-DYRO2LO5.js.map} +0 -0
  878. /package/dist/{render-LR5BOYW6.js.map → render-KKAQPH6Y.js.map} +0 -0
  879. /package/dist/{report-37W5OXUM.js.map → report-OSOJHTSD.js.map} +0 -0
  880. /package/dist/{sampleView-BDC2WPH7.js.map → sampleView-WB74RLD7.js.map} +0 -0
  881. /package/dist/{samplelst-V2EIVZC5.js.map → samplelst-ZKXV5WOD.js.map} +0 -0
  882. /package/dist/{samplematrix-XOSKILUL.js.map → samplematrix-WJFYMWLT.js.map} +0 -0
  883. /package/dist/{sc-ZVZPWQY7.js.map → sc-RBRBUCLR.js.map} +0 -0
  884. /package/dist/{scatter-2ZE5MCYH.js.map → scatter-5K3QTIDK.js.map} +0 -0
  885. /package/dist/{scatter-ZOWFPGIS.js.map → scatter-SM7GQENM.js.map} +0 -0
  886. /package/dist/{selectGenomeWithTklst-EF7WYEAJ.js.map → selectGenomeWithTklst-ZZUJ7AQ7.js.map} +0 -0
  887. /package/dist/{singleCellCellType-TKCGC3G3.js.map → singleCellCellType-LCF2JNZ2.js.map} +0 -0
  888. /package/dist/{singleCellCellType.unit.spec-JZ6UHC5F.js.map → singleCellCellType.unit.spec-T6DYH4BC.js.map} +0 -0
  889. /package/dist/{singleCellGeneExpression-I2INGXGI.js.map → singleCellGeneExpression-2XUYTH4C.js.map} +0 -0
  890. /package/dist/{singleCellGeneExpression.unit.spec-KL77FSHZ.js.map → singleCellGeneExpression.unit.spec-SMRCLOF4.js.map} +0 -0
  891. /package/dist/{singleCellNumericValue-2X5NCEHL.js.map → singleCellNumericValue-57I33FZT.js.map} +0 -0
  892. /package/dist/{singleCellNumericValue.unit.spec-OUDBX5MY.js.map → singleCellNumericValue.unit.spec-4YNB4OEV.js.map} +0 -0
  893. /package/dist/{singleCellPlot-Q6INE54V.js.map → singleCellPlot-L6TKQHGD.js.map} +0 -0
  894. /package/dist/{singlecell-5N2P5ZAT.js.map → singlecell-LZKR3UDV.js.map} +0 -0
  895. /package/dist/{singlecell-NPSWMNI3.js.map → singlecell-UKN2VCXQ.js.map} +0 -0
  896. /package/dist/{snp-2WPJYPDE.js.map → snp-3LJITU5B.js.map} +0 -0
  897. /package/dist/{snp.unit.spec-PPWIIOX6.js.map → snp.unit.spec-ZQNU6XRM.js.map} +0 -0
  898. /package/dist/{snplocus-T3HZFZWA.js.map → snplocus-OME7UQBW.js.map} +0 -0
  899. /package/dist/{spliceevent.a53ss.diagram-APCF4LV5.js.map → spliceevent.a53ss.diagram-C32IEFMU.js.map} +0 -0
  900. /package/dist/{spliceevent.exonskip.diagram-TT5JGBSC.js.map → spliceevent.exonskip.diagram-CZ7MVRLK.js.map} +0 -0
  901. /package/dist/{spliceevent.noeventdiagram-CPXQSX3Z.js.map → spliceevent.noeventdiagram-ZO6R3776.js.map} +0 -0
  902. /package/dist/{ssGSEA-FSX6P7HA.js.map → ssGSEA-BGPQ2PFY.js.map} +0 -0
  903. /package/dist/{ssGSEA.unit.spec-TXYT665R.js.map → ssGSEA.unit.spec-U7TBUSSK.js.map} +0 -0
  904. /package/dist/{stattable-BD64SFYV.js.map → stattable-FISGQCED.js.map} +0 -0
  905. /package/dist/{studyCatalog-6BOWO4PO.js.map → studyCatalog-UHFUT2CJ.js.map} +0 -0
  906. /package/dist/{summarizeCnvGeneexp-AMLYJIPU.js.map → summarizeCnvGeneexp-OVZO6KIB.js.map} +0 -0
  907. /package/dist/{summarizeGeneexpSurvival-IDM7T333.js.map → summarizeGeneexpSurvival-KVQ4JGWK.js.map} +0 -0
  908. /package/dist/{summarizeMutationCnv-R6SYSJQC.js.map → summarizeMutationCnv-RAKGHNLE.js.map} +0 -0
  909. /package/dist/{summarizeMutationDiagnosis-XZJ4JLW2.js.map → summarizeMutationDiagnosis-LGCINAGG.js.map} +0 -0
  910. /package/dist/{summarizeMutationSurvival-ABJ5RL4L.js.map → summarizeMutationSurvival-J7H7L4FX.js.map} +0 -0
  911. /package/dist/{summary-NVYCTE6P.js.map → summary-2632JZXH.js.map} +0 -0
  912. /package/dist/{summary.integration.spec-SSLTLVNW.js.map → summary.integration.spec-5WBS2ZRP.js.map} +0 -0
  913. /package/dist/{summaryInput-SJOZETRP.js.map → summaryInput-BH6C3ATV.js.map} +0 -0
  914. /package/dist/{sunburst-RU5ZPJKW.js.map → sunburst-AMRR2IHM.js.map} +0 -0
  915. /package/dist/{survival-DVG6Y2FV.js.map → survival-2RNJQVFS.js.map} +0 -0
  916. /package/dist/{survival-BHJQMXKI.js.map → survival-WYCH4QOQ.js.map} +0 -0
  917. /package/dist/{survival.integration.spec-OJUPTY5N.js.map → survival.integration.spec-7IFPY4I4.js.map} +0 -0
  918. /package/dist/{svgraph-ETFA4GRX.js.map → svgraph-YQWS52ZJ.js.map} +0 -0
  919. /package/dist/{svmr-AI3RU4JK.js.map → svmr-NRN6LGKK.js.map} +0 -0
  920. /package/dist/{table-YCTSMLQL.js.map → table-3QOMV2NN.js.map} +0 -0
  921. /package/dist/{termCollection-VEVKKJZD.js.map → termCollection-2ZJ7TJGO.js.map} +0 -0
  922. /package/dist/{termCollection-GMKEZR6D.js.map → termCollection-3MCVR7BA.js.map} +0 -0
  923. /package/dist/{termCollection.unit.spec-EU6YCEPX.js.map → termCollection.unit.spec-QYOEA3X6.js.map} +0 -0
  924. /package/dist/{termCollectionFractionSelection-UBS74X36.js.map → termCollectionFractionSelection-5AH6EF4L.js.map} +0 -0
  925. /package/dist/{termCollectionFractionSelection.unit.spec-Y5OJFGDD.js.map → termCollectionFractionSelection.unit.spec-WPGW4WJN.js.map} +0 -0
  926. /package/dist/{tk-W6Z4FJMW.js.map → tk-DQ7D5UEO.js.map} +0 -0
  927. /package/dist/{tk-HMF4HCNV.js.map → tk-ONKYBG6R.js.map} +0 -0
  928. /package/dist/{tp.ui-NECRDJCS.js.map → tp.ui-C7BTMHEI.js.map} +0 -0
  929. /package/dist/{tvs.dt-2JEH3F35.js.map → tvs.dt-PLRMK7OT.js.map} +0 -0
  930. /package/dist/{tvs.dtcnv.categorical-YBXKEBR2.js.map → tvs.dtcnv.categorical-IZUY2AQO.js.map} +0 -0
  931. /package/dist/{tvs.dtcnv.continuous-AD3SJ6BY.js.map → tvs.dtcnv.continuous-ENV3RHHA.js.map} +0 -0
  932. /package/dist/{tvs.dtfusion-ODI3CLQS.js.map → tvs.dtfusion-2DVCV6AM.js.map} +0 -0
  933. /package/dist/{tvs.dtitd-V3LYLPJY.js.map → tvs.dtitd-XNDIRQYU.js.map} +0 -0
  934. /package/dist/{tvs.dtsnvindel-R3V5LTNL.js.map → tvs.dtsnvindel-4D3G7XSF.js.map} +0 -0
  935. /package/dist/{tvs.dtsv-ZQLKEDLJ.js.map → tvs.dtsv-QYMIMC4Z.js.map} +0 -0
  936. /package/dist/{tvs.numeric-22AHXO5K.js.map → tvs.numeric-M5LH3PRH.js.map} +0 -0
  937. /package/dist/{tvs.samplelst-G25A7HM6.js.map → tvs.samplelst-2KEU2ZWB.js.map} +0 -0
  938. /package/dist/{tvs.termCollection-WLVCWDEJ.js.map → tvs.termCollection-FEY746V5.js.map} +0 -0
  939. /package/dist/{vocabulary-6K537FJM.js.map → vocabulary-BR4NJDPS.js.map} +0 -0
  940. /package/dist/{wsi.direct-SNPPQPVO.js.map → wsi.direct-JWDUNHIO.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../plots/volcano/promoterLabel.ts", "../plots/volcano/viewModel/VolcanoViewModel.ts", "../plots/volcano/groupColors.ts", "../plots/volcano/interactions/VolcanoInteractions.ts", "../plots/volcano/interactions/geneBodyLossDE.ts", "../plots/volcano/interactions/dmrGeneLink.ts", "../plots/volcano/view/VolcanoPlotView.ts", "../plots/volcano/VolcanoControlInputs.ts", "../plots/volcano/Volcano.ts"],
4
+ "sourcesContent": ["import type { DiffMethEntry } from '#types'\nimport { DMR_SCAN_ELEMENT_TYPE } from '#types'\n\n/** Display label for a differential methylation promoter.\n *\n * promoter_id is built at ingest as `<gene>.p<n>_<chr>:<start>-<stop>` (or\n * `<gene>_<chr>:<start>-<stop>` when the gene has a single promoter) \u2014 see\n * utils/dnaMeth/build_element_matrix.py. It is an identifier, not a label: it\n * is the highlight key and the handle for the DMR drill-down, so it is never\n * rewritten, only formatted for display.\n *\n * Every place this is shown already has a separate Gene(s) column, making the\n * gene prefix pure duplication. What is left that a reader actually needs is\n * which TSS of the gene it is, plus a copy-pasteable region:\n *\n * NKAP.p4_chrX:119943104-119945251 -> p4 \u00B7 chrX:119943104-119945251\n *\n * Coordinates are printed unformatted so the region can be copied straight into\n * a genome browser or a tabix query.\n *\n * Coordinates come from the entry's own chr/start/stop fields rather than by\n * re-parsing the id, so a gene symbol containing '_' or ':' cannot corrupt them.\n * Only the `p<n>` segment is recovered from the id, and only when the id really\n * has that shape \u2014 anything unexpected falls back to the raw id unchanged.\n */\n/** Noun for the rows of a differential methylation result, for counts and column\n * headers: \"35,584 DM promoters\" is wrong when the run tested eQTM blocks.\n *\n * Derived from the selected element class rather than from the server response, so\n * it needs no extra plumbing: the picker already knows which class was requested,\n * and an absent or 'promoter' value is the legacy single-matrix case.\n *\n * Deliberately not a lookup keyed by every possible class name. Dataset configs can\n * declare arbitrary keys, so an unrecognised one falls back to the neutral\n * \"elements\" instead of mislabelling rows as promoters. Add a case here only for a\n * class whose singular/plural reads badly as the generic term.\n */\nexport function elementNoun(elementType?: string): { one: string; many: string } {\n\tswitch (elementType) {\n\t\tcase undefined:\n\t\tcase '':\n\t\tcase 'promoter':\n\t\t\treturn { one: 'Promoter', many: 'promoters' }\n\t\t/* Two different promoter DEFINITIONS, deliberately given distinct nouns. 'promoter' is\n\t\tthe TSS -1500/+500 window (Bibikova 2011 / Sandoval 2011 -- the 450K array's\n\t\tTSS1500+TSS200 categories); 'promoter_pls' is the ENCODE cCRE promoter-like element,\n\t\t~349 bp, i.e. the CpG-island core with the shores removed. They cover different numbers\n\t\tof genes and their hit counts are NOT comparable, so the UI must never call both\n\t\t\"promoters\". */\n\t\tcase 'promoter_pls':\n\t\t\treturn { one: 'cCRE promoter', many: 'cCRE promoters' }\n\t\tcase 'eqtm_block':\n\t\t\treturn { one: 'eQTM block', many: 'eQTM blocks' }\n\t\tcase 'enhancer':\n\t\t\treturn { one: 'Enhancer', many: 'enhancers' }\n\t\t/* Distal and proximal are separate ENCODE classes and separate hypotheses -- dELS are\n\t\tthe intronic/intergenic enhancers where myeloma hypermethylation concentrates, pELS sit\n\t\twithin 2 kb of a TSS and behave more promoter-like. There are 4.5x as many dELS, so their\n\t\thit counts are not comparable to each other either. Naming them apart keeps a reader from\n\t\treading two runs as the same analysis. */\n\t\tcase 'enhancer_distal':\n\t\t\treturn { one: 'Distal enhancer', many: 'distal enhancers' }\n\t\tcase 'enhancer_proximal':\n\t\t\treturn { one: 'Proximal enhancer', many: 'proximal enhancers' }\n\t\t// de novo regions called by the genome scan, not an annotated class at all\n\t\tcase DMR_SCAN_ELEMENT_TYPE:\n\t\t\treturn { one: 'DMR', many: 'DMRs' }\n\t\tdefault:\n\t\t\treturn { one: 'Element', many: 'elements' }\n\t}\n}\n\nexport function formatPromoterLabel(d: Partial<DiffMethEntry> | undefined): string {\n\tif (!d) return ''\n\tconst id = d.promoter_id || ''\n\tconst { chr, start, stop } = d as DiffMethEntry\n\t// without coordinates there is nothing better to show than the id itself\n\tif (!chr || !Number.isFinite(start) || !Number.isFinite(stop)) return id\n\n\tconst region = `${chr}:${start}-${stop}`\n\n\t/* Match the promoter index only when it sits immediately before the trailing\n\t `_<chr>:<start>-<stop>`, so a gene literally named e.g. \"ABC.p2\" cannot be\n\t mistaken for an index. Genes with one promoter carry no index at all. */\n\tconst idx = id.match(/\\.(p\\d+)_[^_]*:\\d+-\\d+$/)\n\treturn idx ? `${idx[1]} \u00B7 ${region}` : region\n}\n", "import type {\n\tVolcanoPlotDimensions,\n\tVolcanoPlotConfig,\n\tVolcanoPValueTableData,\n\tVolcanoViewData,\n\tDataPointEntry\n} from '../VolcanoTypes'\nimport type { ValidatedVolcanoSettings } from '../settings/Settings'\nimport type { DEFullResponse, DmrScanSummary } from '#types'\nimport { bplen } from '#shared/common.js'\nimport { scaleLinear } from 'd3-scale'\nimport { roundValueAuto } from '#shared/roundValue.js'\nimport { getSampleNum } from '../settings/defaults'\nimport { formatPromoterLabel, elementNoun } from '../promoterLabel'\nimport { getGroupColors } from '../colors'\nimport { DATermTypes as tt, enabledTermTypes } from '../../diffAnalysis/enabledTermTypes'\n\n/* Group names are user-supplied and can be arbitrarily long, so they are shortened before going\ninto any label. Shared by the two group labels above the plot and by the delta-beta axis label,\nso the two shorten identically rather than drifting apart. */\nfunction shortenGroupName(name: string) {\n\tif (name.length >= 25) return name.substring(0, 20) + '...'\n\treturn name\n}\n\nexport class VolcanoViewModel {\n\tconfig: any\n\tdataType: string\n\tresponse: DEFullResponse\n\tpValueTable: VolcanoPValueTableData\n\tsettings: any\n\ttermType: string\n\tviewData: VolcanoViewData\n\tnumSignificant = 0\n\tnumNonSignificant = 0\n\t/** The significant count split by direction, from the server so it reflects every\n\t * significant row rather than the maxInteractiveDots-capped `dots`. */\n\tnumSignificantUp = 0\n\tnumSignificantDown = 0\n\t/** Present only when the \"element class\" was the de novo DMR scan. */\n\tscan?: DmrScanSummary\n\t/** One p per row (DAP's FDR, a scan's smoothed FDR or background p) rather than original +\n\t * adjusted. Decides the column set, the tooltip rows and the axis name. */\n\tsinglePValue: boolean\n\tpValueLabel: string\n\tminLogFoldChange = 0\n\tmaxLogFoldChange = 0\n\t//Used for the y axis domain\n\tminLogPValue = 0\n\tmaxLogPValue = 0\n\t//Unpadded extents \u2014 used for the visible axis labels/ticks (only span real data)\n\tminLogFoldChangeAxis = 0\n\tmaxLogFoldChangeAxis = 0\n\tminLogPValueAxis = 0\n\tmaxLogPValueAxis = 0\n\t//Dot radius in pixels (from server) \u2014 overlay rings size to match the PNG\n\tdotRadiusPx = 2\n\t//Used in place of 0 p values that cannot be log transformed\n\tminNonZeroPValue = 10e-10\n\t//The x coord flush with the left side of the plot\n\tplotX: number\n\treadonly offset = 10\n\treadonly bottomPad = 60\n\treadonly horizPad = 70\n\treadonly topPad = 40\n\t/** Interactive rows returned by the server: threshold-passing dots, sorted by\n\t * significance. The full scatter lives in `response.volcanoPng`. */\n\tdataRows: DataPointEntry[]\n\n\tconstructor(config: VolcanoPlotConfig, response: DEFullResponse, settings: ValidatedVolcanoSettings) {\n\t\tthis.config = config\n\t\tthis.response = response\n\t\tthis.plotX = this.horizPad + this.offset * 2\n\n\t\tthis.dataRows = response.data.dots as DataPointEntry[]\n\n\t\t// Shared helper (colors.ts) so the SVG overlay and the server PNG paint\n\t\t// each side in the exact same hex.\n\t\tconst { caseColor, controlColor } = getGroupColors(this.config)\n\t\tconst barplot = { colorNegative: controlColor, colorPositive: caseColor }\n\n\t\t/* Assigned before setPValueLabel(), which reads it: DAP is labelled off the term type, and\n\t\twith the assignment further down every DAP label read \"adjusted p-value\" for data that is an\n\t\tFDR. */\n\t\tthis.termType = config.termType\n\t\tthis.scan = (response as any).scan\n\t\tthis.singlePValue = config.termType == tt.PROTEOME_DAP || !!this.scan\n\t\tthis.pValueLabel = this.setPValueLabel(settings)\n\n\t\tthis.pValueTable = {\n\t\t\tcolumns: [\n\t\t\t\t// a scan's effect size is delta-beta; the fold change is a difference of logits\n\t\t\t\t{ label: this.scan ? '\u0394\u03B2' : 'log\u2082(fold-change)', barplot, sortable: true },\n\t\t\t\t// DAP files carry a single FDR (adjusted p-value) and a scan a single p; other term\n\t\t\t\t// types report both a raw and an adjusted p-value.\n\t\t\t\t...(this.singlePValue\n\t\t\t\t\t? [{ label: this.pValueLabel, sortable: true }]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{ label: 'Original p-value', sortable: true },\n\t\t\t\t\t\t\t{ label: 'Adjusted p-value', sortable: true }\n\t\t\t\t\t ])\n\t\t\t],\n\t\t\t/** Filled in setPointData(), one row per threshold-passing dot. Populated even when the\n\t\t\t * table is hidden \u2014 the download reads it. */\n\t\t\trows: [],\n\t\t\trowKeys: new Map(),\n\t\t\theight: settings.height + this.topPad\n\t\t}\n\t\tthis.settings = settings\n\t\tthis.dataType = this.setDataType()\n\n\t\tthis.setMinMaxValues()\n\n\t\tconst plotDim = this.setPlotDimensions()\n\t\tthis.setPTableColumns()\n\t\tconst pointData = this.setPointData(plotDim, controlColor, caseColor)\n\n\t\t// sort by effect size, for the rendered table and the downloaded one alike; it is the one\n\t\t// column drawn as a bar\n\t\tconst foldChangeIdx = this.pValueTable.columns.findIndex(c => c.barplot)\n\t\tthis.pValueTable.rows.sort((a: any, b: any) => b[foldChangeIdx].value - a[foldChangeIdx].value)\n\n\t\tthis.viewData = {\n\t\t\timages: response.images || [],\n\t\t\ttermInfo: this.setTermInfo(plotDim),\n\t\t\tplotDim,\n\t\t\tpointData,\n\t\t\tpValueTableData: this.pValueTable,\n\t\t\tstatsData: this.setStatsData(),\n\t\t\tscan: this.scan,\n\t\t\tpValueLabel: this.pValueLabel,\n\t\t\tsinglePValue: this.singlePValue,\n\t\t\tnumSignificantUp: this.numSignificantUp,\n\t\t\tnumSignificantDown: this.numSignificantDown,\n\t\t\txOffset: this.response.data.xOffset ?? 0,\n\t\t\tcentered: !!this.response.data.centered,\n\t\t\tprovenance: this.setProvenance(),\n\t\t\tuserActions: this.setUserActions(),\n\t\t\tdeltaBetaAxisLabel: this.setDeltaBetaAxisLabel(),\n\t\t\tvolcanoPng: response.data.volcanoPng,\n\t\t\tplotExtent: response.data.plotExtent\n\t\t}\n\t}\n\n\t/* The delta-beta axis used to read \"\u0394\u03B2 (case \u2212 control)\". Those are positional roles, not\n\tnames, so the plot showed the size of an effect but not its direction -- you had to already\n\tknow which group landed in which slot, or open a downloaded file and read the provenance line.\n\tName the groups instead, in subtraction order (case first), so the axis states what it plots.\n\n\tReturns undefined when the group names are not available; the view falls back to the old\n\twording rather than rendering a broken label. */\n\tsetDeltaBetaAxisLabel(): string | undefined {\n\t\tconst groups = this.config?.samplelst?.groups\n\t\tconst control = groups?.[0]?.name\n\t\tconst cases = groups?.[1]?.name\n\t\tif (!control || !cases) return undefined\n\t\t/* A centred axis must say so on the axis itself. The plot looks identical to an\n\t\tuncentred one apart from a small shift, so a reader who does not know the origin moved\n\t\twould take a dot at 0 to mean \"no change\" when it means \"typical\". */\n\t\tconst centered = this.response.data.centered ? ' \u2212 median' : ''\n\t\treturn `\u0394\u03B2${centered} (${shortenGroupName(cases)} \u2212 ${shortenGroupName(control)})`\n\t}\n\n\t/** What the y axis and the p column are called. Named here once so the axis, the table header,\n\t * the hover rows and the multi-hit table cannot disagree. */\n\tsetPValueLabel(settings: ValidatedVolcanoSettings): string {\n\t\tif (this.termType == tt.PROTEOME_DAP) return 'FDR'\n\t\tif (this.scan) return this.scan.backgroundCorrection ? 'p vs matched background' : 'smoothed FDR'\n\t\treturn `${settings.pValueType} p-value`\n\t}\n\n\tsetDataType() {\n\t\tif (this.termType == tt.GENE_EXPRESSION) return 'genes'\n\t\t/* Methylation rows are only promoters when the promoter class was tested. With an\n\t\telement class selected they are eQTM blocks or cCREs, and calling them promoters\n\t\tmisreports what was analysed in the stats panel, the row count, and the p-value\n\t\ttable header. Taken from the selected class rather than the server response so no\n\t\textra field has to be plumbed through. */\n\t\tif (this.termType == tt.DNA_METHYLATION) return elementNoun(this.settings?.elementType).many\n\t\tif (this.termType == tt.SINGLECELL_CELLTYPE) return 'genes'\n\t\tif (this.termType == tt.PROTEOME_DAP) return 'proteins'\n\t\tif (this.termType == tt.SINGLECELL_GENE_EXPRESSION) return 'cells'\n\t\tthrow new Error(`Unknown termType: ${this.termType}`)\n\t}\n\n\tsetMinMaxValues() {\n\t\t// The server-drawn PNG owns the axes; we adopt its extents verbatim so\n\t\t// overlay circles land on their counterparts in the PNG. Also adopt the\n\t\t// server's minNonZeroPValue so p=0 rows are capped at the same y position\n\t\t// the PNG used.\n\t\tconst ext = this.response.data.plotExtent\n\t\t// Padded extents \u2014 used for positioning overlay dots & PNG (so dots near\n\t\t// the real-data edge stay fully visible).\n\t\tthis.minLogFoldChange = ext.xMin\n\t\tthis.maxLogFoldChange = ext.xMax\n\t\tthis.minLogPValue = ext.yMin\n\t\tthis.maxLogPValue = ext.yMax\n\t\t// Unpadded extents \u2014 used only for the visible axis ticks/labels.\n\t\tthis.minLogFoldChangeAxis = ext.xMinUnpadded\n\t\tthis.maxLogFoldChangeAxis = ext.xMaxUnpadded\n\t\tthis.minLogPValueAxis = ext.yMinUnpadded\n\t\tthis.maxLogPValueAxis = ext.yMaxUnpadded\n\t\tthis.dotRadiusPx = ext.dotRadiusPx\n\t\tif (ext.minNonZeroPValue > 0) this.minNonZeroPValue = ext.minNonZeroPValue\n\t}\n\n\tsetPlotDimensions() {\n\t\t// Trust the server's authoritative PNG dimensions for the plot rect.\n\t\t// (Recomputing as `settings.width + 2*dotRadiusPx` is wrong when rust's\n\t\t// `pad_px = ceil(2*dot_radius)` rounds up for non-integer dot_radius \u2014\n\t\t// the SVG plot rect would scale the PNG and break pixel_x/pixel_y\n\t\t// alignment with the rasterized dots.)\n\t\tconst ext = this.response.data.plotExtent\n\t\tconst plotW = ext.pixelWidth\n\t\tconst plotH = ext.pixelHeight\n\n\t\t// Positioning scales \u2014 padded data range covers the full plot rect.\n\t\t// Used for overlay dot placement, the PNG image, and the fold-change line.\n\t\tconst xPlotScale = scaleLinear().domain([this.minLogFoldChange, this.maxLogFoldChange]).range([0, plotW])\n\t\tconst yPlotScale = scaleLinear().domain([this.minLogPValue, this.maxLogPValue]).range([plotH, 0])\n\n\t\t// Visible axis scales \u2014 unpadded domain mapped onto the matching pixel\n\t\t// subrange of the padded plot, so axis ticks land exactly at their data\n\t\t// values in the PNG (mirror of manhattan's yAxisScale).\n\t\tconst xScale = scaleLinear()\n\t\t\t.domain([this.minLogFoldChangeAxis, this.maxLogFoldChangeAxis])\n\t\t\t.range([xPlotScale(this.minLogFoldChangeAxis), xPlotScale(this.maxLogFoldChangeAxis)])\n\t\tconst yScale = scaleLinear()\n\t\t\t.domain([this.minLogPValueAxis, this.maxLogPValueAxis])\n\t\t\t.range([yPlotScale(this.minLogPValueAxis), yPlotScale(this.maxLogPValueAxis)])\n\n\t\treturn {\n\t\t\tsvg: {\n\t\t\t\t//20 is for the term info above the plot\n\t\t\t\theight: plotH + this.topPad + this.bottomPad * 2 + this.offset * 3,\n\t\t\t\twidth: plotW + this.horizPad * 2\n\t\t\t},\n\t\t\ttop: {\n\t\t\t\tx: this.plotX,\n\t\t\t\ty: 5\n\t\t\t},\n\t\t\txAxisLabel: {\n\t\t\t\tx: this.horizPad + plotW / 2 + this.offset,\n\t\t\t\ty: this.topPad + plotH + this.bottomPad + this.offset\n\t\t\t},\n\t\t\txScale: {\n\t\t\t\tscale: xScale,\n\t\t\t\tx: this.plotX,\n\t\t\t\ty: plotH + this.topPad + this.offset * 2\n\t\t\t},\n\t\t\tyAxisLabel: {\n\t\t\t\ttext: `-log10(${this.pValueLabel})`,\n\t\t\t\tx: this.horizPad / 3,\n\t\t\t\ty: this.topPad + plotH / 2\n\t\t\t},\n\t\t\tyScale: {\n\t\t\t\tscale: yScale,\n\t\t\t\tx: this.horizPad,\n\t\t\t\ty: this.topPad\n\t\t\t},\n\t\t\tplot: {\n\t\t\t\theight: plotH,\n\t\t\t\twidth: plotW,\n\t\t\t\tx: this.plotX,\n\t\t\t\ty: this.topPad\n\t\t\t},\n\t\t\tlogFoldChangeLine: {\n\t\t\t\tx: xPlotScale(0) + this.plotX,\n\t\t\t\ty1: this.topPad,\n\t\t\t\ty2: plotH + this.offset * 4\n\t\t\t},\n\t\t\txPlotScale,\n\t\t\tyPlotScale\n\t\t}\n\t}\n\n\tsetTermInfo(\n\t\tplotDim: VolcanoPlotDimensions\n\t\t// caseColor: string,\n\t\t// controlColor: string\n\t) {\n\t\tif (!enabledTermTypes.has(this.termType as any)) return\n\n\t\tif (this.termType == tt.PROTEOME_DAP) {\n\t\t\t// FIXME this shouldn't be needed. there should be a way for caller to supply names for each group, and avoid this special logic and SINGLECELL_CELLTYPE\n\t\t\treturn {\n\t\t\t\ty: plotDim.top.y + 10,\n\t\t\t\tfirst: {\n\t\t\t\t\tlabel: shortenGroupName(`Control (${this.response.sample_size1})`),\n\t\t\t\t\tx: 0\n\t\t\t\t},\n\t\t\t\tsecond: {\n\t\t\t\t\tlabel: shortenGroupName(`Case (${this.response.sample_size2})`),\n\t\t\t\t\tx: this.settings.width\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.termType == tt.SINGLECELL_CELLTYPE) {\n\t\t\t/* quick fix - this only works for gdc's precomputed DE genes (selected cluster vs rest of cells)\n\t\t\tthis won't work for dynamic DE (user-selected cluster A vs cluster B)\n\t\t\tthus not okay to hardcode `Not in` here\n\t\t\t!! FIXME !!\n\t\t\tsc should come up with actual names, and cell counts, for precompute/dynamic groups\n\t\t\t*/\n\t\t\tconst groupLabel = `${this.config.termId} ${this.config.categoryName}`\n\t\t\treturn {\n\t\t\t\ty: plotDim.top.y + 10,\n\t\t\t\tfirst: {\n\t\t\t\t\tlabel: shortenGroupName(`Not in ${groupLabel}`),\n\t\t\t\t\tx: 0\n\t\t\t\t},\n\t\t\t\tsecond: {\n\t\t\t\t\tlabel: shortenGroupName(groupLabel),\n\t\t\t\t\tx: this.settings.width\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t//Set slightly above the plot\n\t\t\ty: plotDim.top.y + 10,\n\t\t\tfirst: {\n\t\t\t\t// color: controlColor || this.settings.defaultSignColor,\n\t\t\t\tlabel: shortenGroupName(`${this.config.samplelst.groups[0].name} (${this.response.sample_size1})`),\n\t\t\t\tx: 0\n\t\t\t\t// rectX: this.settings.width/2 - 10,\n\t\t\t},\n\t\t\tsecond: {\n\t\t\t\t// color: caseColor || this.settings.defaultSignColor,\n\t\t\t\tlabel: shortenGroupName(`${this.config.samplelst.groups[1].name} (${this.response.sample_size2})`),\n\t\t\t\tx: this.settings.width\n\t\t\t\t// rectX: this.settings.width/2 + 10,\n\t\t\t}\n\t\t}\n\t}\n\n\tsetPointData(_plotDim: VolcanoPlotDimensions, controlColor: string, caseColor: string) {\n\t\t// Use the server-supplied radius so SVG overlay rings sit exactly on top\n\t\t// of the PNG rings. The view's renderDataPoints draws them at stroke-width\n\t\t// 1 to match the rust PNG's stroke geometry.\n\t\tconst radius = this.dotRadiusPx\n\t\t// rebuilt from scratch on every call, like pointData below -- appending would double the rows\n\t\t// if this ever ran twice on one view model\n\t\tthis.pValueTable.rows = []\n\t\tthis.pValueTable.rowKeys.clear()\n\t\tconst dataCopy: any = structuredClone(this.dataRows)\n\t\tfor (const d of dataCopy) {\n\t\t\tconst highlightKey = this.termType === tt.DNA_METHYLATION ? d.promoter_id : d.gene_name\n\t\t\td.highlighted = this.config?.highlightedData?.includes(highlightKey)\n\t\t\t// Every row in response.data passed the server's thresholds by definition.\n\t\t\td.significant = true\n\t\t\tthis.getGenesColor(d, d.significant, controlColor, caseColor)\n\t\t\tif (d.significant) {\n\t\t\t\tthis.numSignificant++\n\t\t\t\t// DAP and the scan carry a single p (in original_p_value); keep the row cells in\n\t\t\t\t// lock-step with the column set built in the constructor.\n\t\t\t\tconst row = this.singlePValue\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{ value: roundValueAuto(this.scan ? d.delta_beta : d.fold_change) },\n\t\t\t\t\t\t\t{ value: roundValueAuto(d.original_p_value) }\n\t\t\t\t\t ]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{ value: roundValueAuto(d.fold_change) },\n\t\t\t\t\t\t\t{ value: roundValueAuto(d.original_p_value) },\n\t\t\t\t\t\t\t{ value: d.adjusted_p_value != undefined ? roundValueAuto(d.adjusted_p_value) : '' }\n\t\t\t\t\t ]\n\t\t\t\tif (this.termType == tt.DNA_METHYLATION) {\n\t\t\t\t\t/* Two splices, in this order, mirroring setPTableColumns exactly: the beta cells\n\t\t\t\t\tgo in after fold-change (index 1) while it is still at index 0, then the\n\t\t\t\t\tPromoter/Gene prefix shifts everything right. Swapping the order puts \u0394\u03B2 under the\n\t\t\t\t\twrong header. */\n\t\t\t\t\tif (this.scan) {\n\t\t\t\t\t\trow.splice(\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t// fold_change carries the peak per-CpG delta-beta on a scan row\n\t\t\t\t\t\t\t{ value: roundValueAuto(d.fold_change) },\n\t\t\t\t\t\t\t{ value: d.no_cpgs },\n\t\t\t\t\t\t\t{ value: d.stop - d.start },\n\t\t\t\t\t\t\t...(this.scan.backgroundCorrection ? [{ value: d.excess == null ? '' : roundValueAuto(d.excess) }] : [])\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow.splice(\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t{ value: roundValueAuto((d as any).delta_beta) },\n\t\t\t\t\t\t\t{ value: roundValueAuto((d as any).mean_beta_control) },\n\t\t\t\t\t\t\t{ value: roundValueAuto((d as any).mean_beta_case) }\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\trow.splice(0, 0, { value: formatPromoterLabel(d as any) }, { value: d.gene_name || '' })\n\t\t\t\t} else if (this.termType == tt.PROTEOME_DAP) {\n\t\t\t\t\trow.splice(0, 0, { value: d.gene_name || '' }, { value: d.gene || '' })\n\t\t\t\t} else {\n\t\t\t\t\trow.splice(0, 0, { value: d.gene_name || '' })\n\t\t\t\t}\n\t\t\t\t/* Always collected, whether or not the table is displayed: \"Download p-value table\"\n\t\t\t\treads these rows, and gating them on showPValueTable made that download emit a\n\t\t\t\theader with no rows. `row` above is built either way, so this only adds the push. */\n\t\t\t\tthis.pValueTable.rows.push(row)\n\t\t\t\t/* Record the dot identity for this row. The methylation Promoter cell shows a\n\t\t\t\tformatted label (formatPromoterLabel), so row[0].value can no longer be used to\n\t\t\t\tfind the dot -- hover/click highlighting must go through this map instead. Reuses\n\t\t\t\tthe same highlightKey compared against config.highlightedData above, so the three\n\t\t\t\tstay in lock-step by construction. */\n\t\t\t\tthis.pValueTable.rowKeys.set(row, highlightKey)\n\t\t\t} else {\n\t\t\t\tthis.numNonSignificant++\n\t\t\t}\n\t\t\t// Use the exact pixel coords plotters used to rasterize this dot in\n\t\t\t// the PNG (echoed back from rust per-point). Translating by plotX /\n\t\t\t// topPad shifts from inner-plot pixel space to SVG-absolute coords.\n\t\t\t// This is the manhattan trick \u2014 guarantees the SVG overlay ring lands\n\t\t\t// on the rasterized PNG dot regardless of float-vs-int conventions.\n\t\t\td.x = d.pixel_x + this.plotX\n\t\t\td.y = d.pixel_y + this.topPad\n\t\t\td.radius = radius\n\t\t}\n\t\t// Use the server's pre-truncation count so stats are correct even when\n\t\t// dots was capped by maxInteractiveDots.\n\t\tthis.numSignificant = this.response.data.totalSignificantRows\n\t\tthis.numNonSignificant = Math.max(0, this.response.data.totalRows - this.numSignificant)\n\t\tthis.numSignificantUp = this.response.data.totalSignificantUp ?? 0\n\t\tthis.numSignificantDown = this.response.data.totalSignificantDown ?? 0\n\t\t//Sort so the highlighted points appear on top\n\t\tdataCopy.sort((a: any, b: any) => a.highlighted - b.highlighted)\n\t\treturn dataCopy\n\t}\n\n\tgetGenesColor(d: DataPointEntry, significant: boolean, controlColor: string, caseColor: string) {\n\t\tif (!d.gene_name && this.termType != tt.DNA_METHYLATION)\n\t\t\tthrow new Error(`Missing gene_name in data: ${JSON.stringify(d)}`)\n\t\tif (significant) {\n\t\t\t/* The value the server classified and drew: delta-beta on the \u0394\u03B2 axis, less the median when\n\t\t\tcentred. Colouring from raw fold_change painted a point between 0 and a positive median as\n\t\t\t\"up\" over a PNG dot the server had drawn as \"down\". */\n\t\t\tconst x =\n\t\t\t\tthis.termType == tt.DNA_METHYLATION && this.settings.xAxis === 'delta_beta'\n\t\t\t\t\t? (d as any).delta_beta - (this.response.data.xOffset ?? 0)\n\t\t\t\t\t: d.fold_change\n\t\t\tif (controlColor && caseColor) d.color = x > 0 ? caseColor : controlColor\n\t\t\telse d.color = this.settings.defaultSignColor\n\t\t} else d.color = this.settings.defaultNonSignColor\n\t}\n\n\t/** One line describing what produced this result: which groups, how many samples actually\n\t * entered the model, and every setting that changes the numbers.\n\t *\n\t * This exists because an exported table is the artifact that outlives the session. Re-running\n\t * a contrast months later and getting different counts is impossible to diagnose when the\n\t * original run's group sizes and options were never written down anywhere -- the file, the\n\t * screenshot and the memory of it all look identical regardless of how it was configured.\n\t * Only settings that can change the result are listed; cosmetic ones are deliberately left\n\t * out so the line stays readable and a difference in it always means a real difference. */\n\tsetProvenance(): string {\n\t\tconst s = this.settings\n\t\tconst parts: string[] = []\n\n\t\tif (this.config.samplelst?.groups?.length == 2) {\n\t\t\tconst [g1, g2] = this.config.samplelst.groups\n\t\t\t// The sizes reported by the server are post-filtering -- what the model actually used,\n\t\t\t// not what the group nominally contained.\n\t\t\tparts.push(`group1 (control) \"${g1.name}\" n=${this.response.sample_size1}`)\n\t\t\tparts.push(`group2 (case) \"${g2.name}\" n=${this.response.sample_size2}`)\n\t\t}\n\n\t\tconst conf = this.config.confounderTws?.map((t: any) => t?.term?.name || t?.term?.id).filter(Boolean)\n\t\tparts.push(`confounders: ${conf?.length ? conf.join(' + ') : 'none'}`)\n\n\t\tif (this.termType == tt.DNA_METHYLATION) {\n\t\t\t/* Recorded FIRST because it is the only setting that changes what was tested rather\n\t\t\tthan how: promoters, cCRE promoters, eQTM blocks and the full cCRE set are different\n\t\t\tfeatures with different coordinates and wildly different test counts, so two exports\n\t\t\tare not comparable without it. Everything else here was already recorded; this was\n\t\t\tthe one missing field, which made a saved p-value table impossible to attribute to a\n\t\t\tmatrix after the fact. */\n\t\t\tparts.push(`element class: ${s.elementType || 'promoter'}`)\n\t\t\t// Which effect size the run was thresholded on. Two exports with the same p cutoff but\n\t\t\t// different axes are not comparable, and nothing else in the line would reveal it.\n\t\t\tparts.push(`x axis: ${s.xAxis === 'delta_beta' ? 'delta-beta' : 'log2(fold-change)'}`)\n\t\t\t/* Which reading the counts came from. Two runs of the same contrast give different\n\t\t\thyper:hypo ratios depending on this one flag, so a file without it cannot be told\n\t\t\tapart from the other run. Records the offset too, since it is a result in itself. */\n\t\t\tconst off = this.response.data.xOffset ?? 0\n\t\t\tif (this.response.data.centered)\n\t\t\t\tparts.push(`centered on median delta-beta ${off > 0 ? '+' : ''}${roundValueAuto(off)}`)\n\t\t\tif (this.scan) {\n\t\t\t\t// what was scanned and how the DMRs were selected, since the scan has no element matrix to name\n\t\t\t\tparts.push(`scan: ${s.scanChromosome || 'whole genome'}`)\n\t\t\t\tparts.push(`background correction: ${s.backgroundCorrection ? 'yes' : 'no'}`)\n\t\t\t\tparts.push(`min CpGs per DMR: ${s.minCpgs}`)\n\t\t\t} else parts.push(`min samples per group: ${s.minSamplesPerGroup}`)\n\t\t\tparts.push(`exclude sex chromosomes: ${s.excludeSexChr ? 'yes' : 'no'}`)\n\t\t} else if (this.termType == tt.GENE_EXPRESSION) {\n\t\t\tparts.push(`method: ${s.method}`)\n\t\t}\n\n\t\t// Name the effect-size measure the cutoff was applied to, not just its number \u2014 the\n\t\t// threshold moves to deltaBetaCutoff when the axis does, and \"0.1\" alone is ambiguous.\n\t\tconst onDeltaBeta = this.termType == tt.DNA_METHYLATION && s.xAxis === 'delta_beta'\n\t\tconst effect = onDeltaBeta ? `|delta-beta| > ${s.deltaBetaCutoff}` : `|log2(fold-change)| > ${s.foldChangeCutoff}`\n\t\tparts.push(`significance: ${s.pValueType} p < ${roundValueAuto(Math.pow(10, -s.pValue))}, ${effect}`)\n\n\t\treturn parts.join('; ')\n\t}\n\n\tsetStatsData() {\n\t\tconst tableRows: { label: string; value: number | string }[] = [\n\t\t\t{\n\t\t\t\tlabel: `Percentage of significant ${this.dataType}`,\n\t\t\t\tvalue: roundValueAuto((this.numSignificant * 100) / (this.numSignificant + this.numNonSignificant))\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: `Number of significant ${this.dataType}`,\n\t\t\t\tvalue: this.numSignificant\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: `Number of total ${this.dataType}`,\n\t\t\t\tvalue: this.numSignificant + this.numNonSignificant\n\t\t\t}\n\t\t]\n\t\tif (this.termType == tt.GENE_EXPRESSION || this.termType == tt.DNA_METHYLATION) {\n\t\t\ttableRows.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: this.config.samplelst.groups[0].name + ' sample size (control group)',\n\t\t\t\t\tvalue: this.response.sample_size1\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: this.config.samplelst.groups[1].name + ' sample size (case group)',\n\t\t\t\t\tvalue: this.response.sample_size2\n\t\t\t\t}\n\t\t\t)\n\t\t} else if (this.termType == tt.PROTEOME_DAP) {\n\t\t\ttableRows.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Control sample size',\n\t\t\t\t\tvalue: this.response.sample_size1\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Case sample size',\n\t\t\t\t\tvalue: this.response.sample_size2\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\n\t\tif (this.response.bcv !== undefined && this.response.bcv !== null) {\n\t\t\ttableRows.push({\n\t\t\t\tlabel: 'Biological coefficient of variation',\n\t\t\t\tvalue: roundValueAuto(this.response.bcv)\n\t\t\t})\n\t\t}\n\t\tif (this.scan) tableRows.push(...this.setScanStats(this.scan))\n\t\treturn tableRows\n\t}\n\n\t/* The whole-scan facts, every one of them over the scan as returned -- before the volcano's\n\tthresholds -- and over the same set of DMRs (those meeting the CpG floor), so no two lines here\n\thave different denominators. The counts the thresholds select are the three rows above. */\n\tsetScanStats(s: DmrScanSummary) {\n\t\tconst rows: { label: string; value: number | string }[] = [\n\t\t\t{ label: 'Chromosomes scanned', value: s.chromosomes.length },\n\t\t\t{ label: 'CpGs analyzed', value: s.totalProbesAnalyzed },\n\t\t\t{ label: 'DMRs called', value: s.called },\n\t\t\t{ label: `DMRs with ${s.minCpgs}+ CpGs`, value: s.kept },\n\t\t\t{ label: 'Hypermethylated', value: s.hyper },\n\t\t\t{ label: 'Hypomethylated', value: s.hypo }\n\t\t]\n\t\tif (s.width)\n\t\t\trows.push({\n\t\t\t\tlabel: 'DMR width, median (IQR)',\n\t\t\t\tvalue: `${bplen(s.width.median)} (${bplen(s.width.q1)} \u2013 ${bplen(s.width.q3)})`\n\t\t\t})\n\t\t/* Stated even when it dropped nothing, so \"no artifact regions here\" reads differently from\n\t\t\"no mask was applied\". These DMRs never reached the browser. */\n\t\tif (s.regionMask)\n\t\t\trows.push({\n\t\t\t\tlabel: `DMRs removed by artifact mask (${s.regionMask.sources.join(', ')}; \u2265${Math.round(\n\t\t\t\t\ts.regionMask.overlapFrac * 100\n\t\t\t\t)}% masked)`,\n\t\t\t\tvalue: s.regionMask.dmrsDropped\n\t\t\t})\n\t\t/* The backdrop every DMR is read against. Measured over every value the fits read, not over\n\t\tthe DMRs, so it is independent of the result it qualifies: where the whole genome shifts,\n\t\tpart of every region's difference is this number rather than anything local. */\n\t\tconst gm = s.globalMethylation\n\t\tif (gm) {\n\t\t\tconst [g1, g2] = this.config.samplelst?.groups?.map((g: any) => g.name) || ['group 1', 'group 2']\n\t\t\t/* Named for what was scanned. One chromosome makes these chromosome-wide numbers, and\n\t\t\t\"genome-wide\" would overstate every one of them. */\n\t\t\tconst one = s.chromosomes.length == 1 ? s.chromosomes[0] : null\n\t\t\tconst meanLabel = (g: string) => (one ? `${g} mean \u03B2 on ${one}` : `${g} genome-wide mean \u03B2`)\n\t\t\trows.push(\n\t\t\t\t{ label: meanLabel(g1), value: gm.controlMeanBeta.toFixed(4) },\n\t\t\t\t{ label: meanLabel(g2), value: gm.caseMeanBeta.toFixed(4) },\n\t\t\t\t{\n\t\t\t\t\tlabel: one ? `\u03B2 shift on ${one} (case \u2212 control)` : 'Genome-wide \u03B2 shift (case \u2212 control)',\n\t\t\t\t\tvalue: `${gm.shift >= 0 ? '+' : ''}${gm.shift.toFixed(4)}`\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t\t/* A survival rate is only readable against its denominator, and the unscored are not a\n\t\trandom sample -- they are the widest and most CpG-dense regions, which intergenic space\n\t\tcannot match -- so the unscored count is a row of its own rather than folded away. */\n\t\tconst bc = s.backgroundCorrection\n\t\tif (bc) {\n\t\t\trows.push(\n\t\t\t\t{ label: 'Intergenic background windows sampled', value: bc.windows },\n\t\t\t\t{ label: `DMRs scored against background (matched on ${bc.matchedOn.join(' and ')})`, value: bc.scored },\n\t\t\t\t{ label: 'DMRs unscored: stratum too thin (not plotted)', value: bc.unscored },\n\t\t\t\t{\n\t\t\t\t\tlabel: 'DMRs moving more than matched background (p < 0.05)',\n\t\t\t\t\tvalue: `${bc.significant.toLocaleString()} of ${bc.scored.toLocaleString()} (${(\n\t\t\t\t\t\t(100 * bc.significant) /\n\t\t\t\t\t\tMath.max(1, bc.scored)\n\t\t\t\t\t).toFixed(1)}%)`\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t\tif (s.geneBodyLoss)\n\t\t\trows.push({\n\t\t\t\t// the correction adds the background gate, so the label must say which set this is\n\t\t\t\tlabel: s.backgroundCorrection\n\t\t\t\t\t? 'Gene-body loss regions beating background \u2192 genes'\n\t\t\t\t\t: 'Gene-body loss regions \u2192 genes',\n\t\t\t\tvalue: `${s.geneBodyLoss.regions.toLocaleString()} \u2192 ${s.geneBodyLoss.genes.length.toLocaleString()}`\n\t\t\t})\n\t\t/* How much of the measured methylome moved. Sits beside the DMR counts because the two say\n\t\tdifferent things: a DMR count is a count of regions that passed a threshold, and on a cohort\n\t\tthat drifted genome-wide that count is large whether or not much changed anywhere. The binned\n\t\tprofile is the metric the methylome literature compares cohorts with, so these rows are the\n\t\tnumbers a reader would quote from that figure. */\n\t\tconst pf = s.profileSummary\n\t\tif (pf) {\n\t\t\tconst pct = (v: number) => `${(100 * v).toFixed(1)}%`\n\t\t\trows.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: `Methylome profile: ${pf.bins.toLocaleString()} bins measured`,\n\t\t\t\t\tvalue: `${pct(pf.fractionHyper)} hyper`\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Methylome profile: per-bin \u0394\u03B2, median (IQR)',\n\t\t\t\t\tvalue: `${pf.median >= 0 ? '+' : ''}${pf.median.toFixed(4)} (${pf.q1.toFixed(4)} \u2013 ${pf.q3.toFixed(4)})`\n\t\t\t\t},\n\t\t\t\t{ label: 'Methylome profile: bins moving |\u0394\u03B2| > 0.05', value: pct(pf.fractionBeyond05) },\n\t\t\t\t{ label: 'Methylome profile: bins moving |\u0394\u03B2| > 0.10', value: pct(pf.fractionBeyond10) }\n\t\t\t)\n\t\t}\n\t\t/* What the scan cost, measured on the run that produced this result (a cached answer keeps\n\t\tthe original run's figures). One row each for the numbers a deployment is sized by: memory\n\t\tper worker, memory for the pool, cores, and how the time split between the workers and Node. */\n\t\tconst r = s.resources\n\t\tif (r) {\n\t\t\tconst top = r.perChromosome[0]\n\t\t\trows.push(\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Compute: workers \u00D7 threads',\n\t\t\t\t\tvalue: `${r.workers} \u00D7 ${r.threadsPerWorker} (${r.workers * r.threadsPerWorker} core${\n\t\t\t\t\t\tr.workers * r.threadsPerWorker == 1 ? '' : 's'\n\t\t\t\t\t})`\n\t\t\t\t},\n\t\t\t\t{ label: 'Compute: wall time', value: `${(r.wallMs / 1000).toFixed(1)} s` },\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Compute: peak memory per worker',\n\t\t\t\t\tvalue: `${Math.round(r.peakWorkerMemoryMb).toLocaleString()} MB${\n\t\t\t\t\t\ttop ? ` (${top.chr}, ${top.probes.toLocaleString()} CpGs)` : ''\n\t\t\t\t\t}`\n\t\t\t\t},\n\t\t\t\t{ label: 'Compute: peak memory, worker pool', value: `${Math.round(r.peakPoolMemoryMb).toLocaleString()} MB` },\n\t\t\t\t{ label: 'Compute: worker CPU time', value: `${r.workerCpuSeconds.toFixed(1)} s` },\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Compute: server process',\n\t\t\t\t\tvalue: `+${Math.round(r.nodeRssDeltaMb).toLocaleString()} MB, ${r.nodeCpuSeconds.toFixed(1)} s CPU`\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t\treturn rows\n\t}\n\n\tsetPTableColumns() {\n\t\tif (this.termType == tt.DNA_METHYLATION) {\n\t\t\t/* \u0394\u03B2 sits next to log\u2082(fold-change) so the two effect sizes read as a pair: the\n\t\t\tfold-change is a logit difference and does not say how much methylation moved, \u0394\u03B2 does.\n\t\t\tThe group means follow because a \u0394\u03B2 of 0.2 means something different at 0.1\u21920.3 than at\n\t\t\t0.7\u21920.9. Insert at 1 (after fold-change) BEFORE the Promoter/Gene prefix shifts indices \u2014\n\t\t\tsetPointData splices its cells in the same order for the same reason. */\n\t\t\tif (this.scan) {\n\t\t\t\t/* A DMR is a called region, so what a row needs is its extent and its evidence -- the\n\t\t\t\tpeak CpG's delta-beta, how many CpGs, how wide -- plus, corrected, how far it moved\n\t\t\t\tbeyond its matched background. There are no two group means to show. */\n\t\t\t\tthis.pValueTable.columns.splice(\n\t\t\t\t\t1,\n\t\t\t\t\t0,\n\t\t\t\t\t{ label: 'Peak \u0394\u03B2', sortable: true },\n\t\t\t\t\t{ label: 'CpGs', sortable: true },\n\t\t\t\t\t{ label: 'Width (bp)', sortable: true },\n\t\t\t\t\t...(this.scan.backgroundCorrection ? [{ label: 'Excess \u0394\u03B2', sortable: true }] : [])\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthis.pValueTable.columns.splice(\n\t\t\t\t\t1,\n\t\t\t\t\t0,\n\t\t\t\t\t{ label: '\u0394\u03B2', sortable: true },\n\t\t\t\t\t{ label: 'Mean \u03B2 (group 1)', sortable: true },\n\t\t\t\t\t{ label: 'Mean \u03B2 (group 2)', sortable: true }\n\t\t\t\t)\n\t\t\t}\n\t\t\t/* This column header is what lands in the downloaded p-value table, so a block\n\t\t\trun exported a column titled \"Promoter\" holding block coordinates. */\n\t\t\tthis.pValueTable.columns.splice(\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t{ label: elementNoun(this.settings?.elementType).one, sortable: true },\n\t\t\t\t{ label: 'Gene(s)', sortable: true }\n\t\t\t)\n\t\t} else if (this.termType == tt.PROTEOME_DAP) {\n\t\t\tthis.pValueTable.columns.splice(0, 0, { label: 'Identifier', sortable: true }, { label: 'Gene', sortable: true })\n\t\t} else {\n\t\t\tthis.pValueTable.columns.splice(0, 0, { label: 'Gene Name', sortable: true })\n\t\t}\n\t}\n\n\tsetUserActions() {\n\t\tconst userActions = {\n\t\t\tnoShow: new Set<string>()\n\t\t}\n\t\t// the scan resolves its own two groups and fits no covariates\n\t\tif (this.scan) userActions.noShow.add('Confounding factors')\n\t\tif (this.termType == tt.GENE_EXPRESSION) {\n\t\t\tif (this.settings.method == 'edgeR' && getSampleNum(this.config) > 100) {\n\t\t\t\tuserActions.noShow.add('Confounding factors')\n\t\t\t}\n\t\t\tif (this.settings.method == 'wilcoxon') userActions.noShow.add('Confounding factors')\n\t\t}\n\t\treturn userActions\n\t}\n}\n", "/* The colours the user picked for the two groups, carried through to every plot launched from a\ndifferential analysis.\n\nGroups get their colour in the group picker, and that colour is what the reader has already learned\nthe groups by -- on the picker, on the sample-count line, and on the volcano's axis labels. A\ndownstream plot that re-colours them makes the reader re-learn which group is which at every hop,\nand silently invites reading a green curve in one panel as the same thing as a green curve in\nanother. */\n\n/** Per-group colour from the samplelst term, or undefined where the term carries none.\n *\n * Undefined rather than a fallback on purpose: the receiving plot has its own tuned defaults, and\n * substituting an arbitrary colour here would override them with something no one chose. Callers\n * spread the result, so an absent colour leaves the default in place. */\nexport function groupColors(config: any): { group1?: string; group2?: string } {\n\tconst g = config?.samplelst?.groups\n\tif (!g?.length) return {}\n\tconst values = config?.tw?.term?.values\n\t/* Two places carry the same colour: the samplelst term keyed by group name, and the group\n\titself. getSamplelstTW writes both from the picker, so either is correct -- reading both means a\n\tcaller holding only one of the shapes still gets the colours. */\n\tconst pick = (i: number) => values?.[g[i]?.name]?.color || g[i]?.color\n\tconst out: { group1?: string; group2?: string } = {}\n\tconst c1 = pick(0)\n\tconst c2 = pick(1)\n\tif (c1) out.group1 = c1\n\tif (c2) out.group2 = c2\n\treturn out\n}\n", "import type { MassAppApi } from '#mass/types/mass'\nimport { groupColors } from '../groupColors'\nimport { downloadTable, fileDateStamp, GeneSetEditUI, MultiTermWrapperEditUI } from '#dom'\nimport { to_svg } from '#src/client'\nimport type { VolcanoDom, VolcanoPlotConfig } from '../VolcanoTypes'\nimport { PROTEOME_DAP, DNA_METHYLATION, GENE_EXPRESSION, DMR_SCAN_ELEMENT_TYPE } from '#types'\nimport type { DmrScanSummary } from '#types'\nimport { CCRE_TRACK_NAME } from '#plots/dmr/viewModel/DmrViewModel.ts'\nimport { getGEunit } from '#tw/geneExpression'\nimport { getDNAMethUnit, getDNAMethTermName } from '#tw/dnaMethylation'\nimport { elementNoun } from '../promoterLabel'\n\nexport class VolcanoInteractions {\n\tapp: MassAppApi\n\tdom: VolcanoDom\n\tid: string\n\tpValueTableData: any\n\tdata: any\n\t/** Significant rows before maxInteractiveDots capped them. When this exceeds the rows on\n\t * screen, the download re-fetches the uncapped set via fetchAllRows(). */\n\ttotalSignificantRows: number\n\t/** Groups, sample sizes and result-affecting settings, written into downloads. */\n\tprovenance: string\n\t/** Re-requests the current contrast with the maxInteractiveDots cap lifted and returns the\n\t * full significance table, formatted by the same view model the on-screen table uses.\n\t * Set by Volcano.main() after each fetch; absent until the first response arrives. */\n\tfetchAllRows?: () => Promise<{ rows: any[]; columns: any[] }>\n\n\tconstructor(app: MassAppApi, id: string, dom: VolcanoDom) {\n\t\tthis.app = app\n\t\tthis.dom = dom\n\t\tthis.id = id\n\t\tthis.pValueTableData = []\n\t\tthis.data = []\n\t\tthis.totalSignificantRows = 0\n\t\tthis.provenance = ''\n\t}\n\n\t/** Launches a multi-term select tree\n\t * On submit, dispatches a plot_edit action with the new confounders */\n\tasync confoundersMenu() {\n\t\tconst state = this.app.getState()\n\t\tconst config = state.plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tif (config.termType !== GENE_EXPRESSION && config.termType !== DNA_METHYLATION) return\n\n\t\t/** Find terms used to create the groups and disable in the\n\t\t * termsetting UI. Prevents users from trying to control for\n\t\t * variables used to create the groups.*/\n\t\tconst allowedGroupNames = new Set([config.samplelst.groups[0].name, config.samplelst.groups[1].name])\n\t\tconst grpTerms: Set<string> = new Set(\n\t\t\t(this.app?.vocabApi?.state.groups || [])\n\t\t\t\t.filter(g => allowedGroupNames.has(g.name))\n\t\t\t\t.flatMap(g =>\n\t\t\t\t\tg.filter.lst.flatMap(f => {\n\t\t\t\t\t\tif (f.tvs?.term) return f.tvs.term\n\t\t\t\t\t\telse return f.lst.map(l => l.tvs.term)\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t)\n\t\tconst disable_terms: any[] = grpTerms.size ? Array.from(grpTerms) : []\n\t\tconst maxNum = config.settings.volcano.method == 'edgeR' ? 1 : 2\n\n\t\tconst ui = new MultiTermWrapperEditUI({\n\t\t\tapp: this.app,\n\t\t\tcallback: async (tws: any) => {\n\t\t\t\tthis.dom.actionsTip.hide()\n\t\t\t\tawait this.app.dispatch({\n\t\t\t\t\ttype: 'plot_edit',\n\t\t\t\t\tid: this.id,\n\t\t\t\t\tconfig: { confounderTws: tws }\n\t\t\t\t})\n\t\t\t},\n\t\t\tholder: this.dom.actionsTip.d as any,\n\t\t\theaderText: 'Select confounders',\n\t\t\tmaxNum,\n\t\t\tstate,\n\t\t\ttwList: config.confounderTws,\n\t\t\tdisable_terms\n\t\t})\n\t\tawait ui.renderUI()\n\t}\n\n\tdownload(termType: string) {\n\t\tthis.dom.actionsTip.clear().showunder(this.dom.controls.select('div').node())\n\t\tconst opts = [\n\t\t\t{\n\t\t\t\ttext: 'Download plot',\n\t\t\t\tcallback: () => {\n\t\t\t\t\tconst svg = this.dom.holder.select('svg').node() as Node\n\t\t\t\t\tto_svg(svg, `Differential ${termType} analysis volcano`, { apply_dom_styles: true })\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\t// DAP volcanoes report a single FDR rather than a p-value.\n\t\t\t\ttext: termType === PROTEOME_DAP ? 'Download FDR table' : 'Download p-value table',\n\t\t\t\tcallback: (itemDiv: any) => this.downloadPvalueTable(termType, itemDiv)\n\t\t\t}\n\t\t]\n\t\tfor (const opt of opts) {\n\t\t\tconst itemDiv = this.dom.actionsTip.d.append('div').attr('class', 'sja_menuoption').text(opt.text)\n\t\t\titemDiv.on('click', () => opt.callback(itemDiv))\n\t\t}\n\t}\n\n\t/* The interactive table only holds the most-significant maxInteractiveDots rows, because the\n\tdot overlay has to stay responsive. The download has no such constraint, so it should be the\n\tCOMPLETE set of significant rows: when the two differ, re-request with the cap lifted and write\n\tthose rows instead.\n\n\tThat second request is cheap. volcanoRender is deliberately not part of the DA cache key (see\n\tdmKeyInputs in server/routes/termdb.diffMeth.ts), so lifting the cap re-uses the cached R result\n\tand pays only for a re-render.\n\n\tIf the re-request fails the download still happens, with the capped rows and a note saying so --\n\tlosing the file entirely would be a worse outcome than a disclosed subset. */\n\tasync downloadPvalueTable(termType: string, itemDiv?: any) {\n\t\t// name the file after what is in it and when it was run -- these downloads pile up in\n\t\t// one folder across cohorts and reruns\n\t\tconst date = fileDateStamp()\n\t\tconst label = termType === PROTEOME_DAP ? 'fdr' : 'p-value'\n\t\tlet { rows, columns } = this.pValueTableData\n\t\tlet subsetNote: string | undefined\n\n\t\t/* Without a note, nothing in a capped file reveals that \"how many were significant\" is\n\t\tunanswerable from it. Only reachable now when the full fetch is unavailable or fails. */\n\t\tconst cappedNote = (reason: string) =>\n\t\t\t`Top ${rows.length.toLocaleString()} of ${this.totalSignificantRows.toLocaleString()} significant results, ` +\n\t\t\t`selected by adjusted p-value and sorted by fold-change. This file is not the complete result set (${reason}).`\n\n\t\tif (this.totalSignificantRows > rows.length) {\n\t\t\tif (!this.fetchAllRows) subsetNote = cappedNote('complete set unavailable')\n\t\t\telse {\n\t\t\t\t// a full table can be tens of thousands of rows; say something before the wait\n\t\t\t\tconst restore = itemDiv?.text()\n\t\t\t\titemDiv?.text(`Preparing ${this.totalSignificantRows.toLocaleString()} rows...`)\n\t\t\t\ttry {\n\t\t\t\t\tconst full = await this.fetchAllRows()\n\t\t\t\t\trows = full.rows\n\t\t\t\t\tcolumns = full.columns\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tsubsetNote = cappedNote(`could not retrieve the complete set: ${e?.message || e}`)\n\t\t\t\t} finally {\n\t\t\t\t\tif (restore) itemDiv?.text(restore)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* Provenance rides along with the rows. Comparing two exports months apart is\n\t\totherwise guesswork: differing counts could be a code change, a settings change or a\n\t\tdifferent group definition, and nothing in the file distinguishes them.\n\t\tJoined with ' | ' rather than a newline because downloadTable collapses newlines to\n\t\tkeep the note on one '#' line -- writing '\\n' here would look intentional and quietly\n\t\tbecome a space. */\n\t\tconst note = [subsetNote, this.provenance && `Run: ${this.provenance}`].filter(Boolean).join(' | ')\n\t\tdownloadTable(rows, columns, `${label}-table-${date}.tsv`, note || undefined)\n\t}\n\n\tasync highlightDataPoint(value: string) {\n\t\tconst config = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tconst highlightedData = config.highlightedData.includes(value)\n\t\t\t? config.highlightedData.filter(d => d !== value)\n\t\t\t: [...config.highlightedData, value]\n\t\tawait this.app.dispatch({\n\t\t\ttype: 'plot_edit',\n\t\t\tid: this.id,\n\t\t\tconfig: { highlightedData }\n\t\t})\n\t}\n\n\t/** When clicking on a data point, launches the box plot in a separate sandbox\n\t * For geneExpression, value == gene symbol */\n\tlaunchBoxPlot(value: string) {\n\t\tconst config = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tconst values = {}\n\t\tfor (const group of config.samplelst.groups) {\n\t\t\tvalues[group.name] = {\n\t\t\t\tkey: group.name,\n\t\t\t\tlabel: group.name,\n\t\t\t\tlist: group.values\n\t\t\t}\n\t\t}\n\t\t/** Gene variant and expression terms do not have an id\n\t\t * need to be handled separately.\n\t\t * TODO: In the future with more use cases, simplify this logic. */\n\t\tconst setTerm = () => {\n\t\t\tif (config.termType == GENE_EXPRESSION) {\n\t\t\t\treturn {\n\t\t\t\t\tq: { mode: 'continuous' },\n\t\t\t\t\tterm: {\n\t\t\t\t\t\tgene: value,\n\t\t\t\t\t\tname: value,\n\t\t\t\t\t\ttype: config.termType\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else return config.term\n\t\t}\n\t\tthis.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: {\n\t\t\t\tchartType: 'summary',\n\t\t\t\tchildType: 'boxplot',\n\t\t\t\tterm: setTerm(),\n\t\t\t\tterm2: {\n\t\t\t\t\tq: { groups: config.tw.q.groups, type: 'custom-samplelst' },\n\t\t\t\t\tterm: config.tw.term\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Launch a violin plot for a gene expression data point. */\n\tlaunchViolinGeneExp(value: string) {\n\t\tconst config = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tthis.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: {\n\t\t\t\tchartType: 'summary',\n\t\t\t\tchildType: 'violin',\n\t\t\t\tterm: {\n\t\t\t\t\tq: { mode: 'continuous' },\n\t\t\t\t\tterm: {\n\t\t\t\t\t\tgene: value,\n\t\t\t\t\t\tname: value,\n\t\t\t\t\t\ttype: config.termType\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tterm2: {\n\t\t\t\t\tq: { groups: config.tw.q.groups, type: 'custom-samplelst' },\n\t\t\t\t\tterm: config.tw.term\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tlaunchGeneSetEdit() {\n\t\tconst plotConfig = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tconst holder = this.dom.actionsTip.d.append('div').style('padding', '5px') as any\n\t\tconst limitedGenesList =\n\t\t\tplotConfig.termType === DNA_METHYLATION ? this.data.map(d => d.promoter_id) : this.data.map(d => d.gene_name)\n\t\tnew GeneSetEditUI({\n\t\t\tholder,\n\t\t\tgenome: this.app.opts.genome,\n\t\t\tvocabApi: this.app.vocabApi,\n\t\t\tlimitedGenesList,\n\t\t\tgeneList: plotConfig.highlightedData.map(d => {\n\t\t\t\treturn { gene: d } //Formatted to Gene type in GeneSetEditUI\n\t\t\t}),\n\t\t\tcustomInputs: [\n\t\t\t\t{\n\t\t\t\t\tlabel: 'Cancel highlight',\n\t\t\t\t\tgetDisplayStyle: () => (plotConfig.highlightedData.length > 0 ? '' : 'none'),\n\t\t\t\t\tshowInput: async () => {\n\t\t\t\t\t\tawait this.app.dispatch({\n\t\t\t\t\t\t\ttype: 'plot_edit',\n\t\t\t\t\t\t\tid: this.id,\n\t\t\t\t\t\t\tconfig: { highlightedData: [] }\n\t\t\t\t\t\t})\n\t\t\t\t\t\tthis.dom.actionsTip.hide()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\tcallback: async result => {\n\t\t\t\tconst highlightedData = result.geneList.map(d => d.gene)\n\t\t\t\tawait this.app.dispatch({\n\t\t\t\t\ttype: 'plot_edit',\n\t\t\t\t\tid: this.id,\n\t\t\t\t\tconfig: { highlightedData }\n\t\t\t\t})\n\t\t\t\tthis.dom.actionsTip.hide()\n\t\t\t}\n\t\t})\n\t}\n\n\t/** When clicking on a DM data point, dispatches a DMR plot that runs DMRCate\n\t * analysis and renders a genome browser Block with DMR regions on their own\n\t * track. */\n\tasync launchDmr(\n\t\td: { chr: string; start: number; stop: number; promoterId?: string },\n\t\t/** DMR-plot settings to override, e.g. pad: 0 for a region that is already its own context */\n\t\tdmrSettings: Record<string, any> = {}\n\t) {\n\t\tconst config = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\n\t\t/* Shared with the batch drill-down's launcher so the two cannot drift. Absent colours are\n\t\tomitted rather than replaced: the DMR plot's own defaults are tuned, where the red/blue this\n\t\tused to substitute was neither chosen nor legible next to the hyper/hypo bars. */\n\t\tconst colors = groupColors(config)\n\n\t\tconst label = d.promoterId || `${d.chr}:${d.start}-${d.stop}`\n\t\tconst dmrConfig: any = {\n\t\t\tchartType: 'dmr',\n\t\t\theaderText: `DMR: ${label}`,\n\t\t\tcoordinateOverride: { chr: d.chr, start: d.start, stop: d.stop },\n\t\t\tgroup1: config.samplelst.groups[0].values || [],\n\t\t\tgroup2: config.samplelst.groups[1].values || [],\n\t\t\tgroup1Name: config.samplelst.groups[0].name,\n\t\t\tgroup2Name: config.samplelst.groups[1].name,\n\t\t\t/* Which element matrix to drill into, for a dataset whose methylation is element-level\n\t\t\tonly. The server ignores it when the dataset has a CpG-level matrix, which is finer. The\n\t\t\tscan is not a matrix, so a region opened from a scan names none and the server picks. */\n\t\t\telementType:\n\t\t\t\tconfig?.settings?.volcano?.elementType == DMR_SCAN_ELEMENT_TYPE\n\t\t\t\t\t? undefined\n\t\t\t\t\t: config?.settings?.volcano?.elementType,\n\t\t\tsettings: { colors, ...dmrSettings }\n\t\t}\n\n\t\tthis.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: dmrConfig\n\t\t})\n\t}\n\n\t/* Open a genome browser on a scan's DMR, with the scan's own DMRs as a track. The region view\n\tre-fits the chromosome to draw its DMR track; a scan has already called every DMR and cached\n\tthem, so the browser names the cached scan (scanDmrTrack) and fetches the DMRs of whatever\n\tchromosome is on screen from it -- including after the reader types another position into the\n\tsearch box. Opened on the DMR with room either side. */\n\tasync launchScanGenomeBrowser(d: { chr: string; start: number; stop: number }, scan: DmrScanSummary) {\n\t\tconst tracks: any[] = []\n\t\t// the regulatory context the region view also switches on, by the genome's own declaration\n\t\tconst ccre = (this.app.opts.genome?.tracks || []).find((t: any) => t.name == CCRE_TRACK_NAME)\n\t\tif (ccre) tracks.push(structuredClone(ccre))\n\t\tconst pad = Math.max(5000, d.stop - d.start)\n\t\tthis.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: {\n\t\t\t\tchartType: 'genomeBrowser',\n\t\t\t\tgeneSearchResult: { chr: d.chr, start: Math.max(0, d.start - pad), stop: d.stop + pad },\n\t\t\t\t// the CpG floor the scan was rendered with, so the track shows the DMRs the volcano counts\n\t\t\t\tscanDmrTrack: { cacheId: scan.cacheId, minCpgs: scan.minCpgs },\n\t\t\t\ttracks\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Launch a violin/box plot for a DNA methylation promoter.\n\t * Creates a methylation term using the promoter's chr/start/stop coordinates.\n\t * The tw handler fills in id and unit from termdbConfig. */\n\tlaunchDNAMethViolin(d: { chr: string; start: number; stop: number; gene_name?: string; promoter_id?: string }) {\n\t\tconst config = this.app.getState().plots.find((p: VolcanoPlotConfig) => p.id === this.id)\n\t\tconst genomicFeatureType = d.promoter_id ? 'promoter' : 'gene'\n\t\tconst featureName = genomicFeatureType === 'gene' ? d.gene_name?.split(',')[0]?.trim() || '' : ''\n\t\tconst term: any = {\n\t\t\tgenomicFeatureType,\n\t\t\tfeatureName,\n\t\t\ttype: DNA_METHYLATION,\n\t\t\tchr: d.chr,\n\t\t\tstart: d.start,\n\t\t\tstop: d.stop\n\t\t}\n\t\t/* Name the term after the element class actually tested. Every class carries its id in\n\t\tpromoter_id, so genomicFeatureType is 'promoter' for a distal enhancer too and the sandbox\n\t\theader read \"Promoter Average M-value (chr9:...)\" for something that is not a promoter.\n\t\tBuilt here, where the selected class is known, rather than left to the tw fill step, which\n\t\tonly sees the term. */\n\t\tif (genomicFeatureType === 'promoter') {\n\t\t\tconst noun = elementNoun(config?.settings?.volcano?.elementType).one\n\t\t\tconst unit = getDNAMethUnit(genomicFeatureType, this.app.vocabApi)\n\t\t\tterm.unit = unit\n\t\t\tterm.name = getDNAMethTermName(term, unit, noun)\n\t\t}\n\t\tthis.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: {\n\t\t\t\tchartType: 'summary',\n\t\t\t\tchildType: 'violin',\n\t\t\t\tterm: {\n\t\t\t\t\tq: { mode: 'continuous' },\n\t\t\t\t\tterm\n\t\t\t\t},\n\t\t\t\tterm2: {\n\t\t\t\t\tq: { groups: config.tw.q.groups, type: 'custom-samplelst' },\n\t\t\t\t\tterm: config.tw.term\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tasync launchDEGClustering() {\n\t\t//Sort the DEG rows by q-value in ascending order\n\t\tconst geneIndex = this.pValueTableData.columns.findIndex(col => col.label === 'Gene Name')\n\t\tconst adjustedPValIndex = this.pValueTableData.columns.findIndex(col => col.label === 'Adjusted p-value')\n\t\tconst rowsSorted = [...this.pValueTableData.rows].sort((a, b) => {\n\t\t\tconst aQVal = Number(a[adjustedPValIndex].value)\n\t\t\tconst bQVal = Number(b[adjustedPValIndex].value)\n\t\t\treturn aQVal - bQVal\n\t\t})\n\n\t\t// Launch hierCluster for up to 100 DEGs with the smallest q-values\n\t\tconst geneList = rowsSorted.slice(0, 100).map(r => ({ gene: r[geneIndex].value }))\n\n\t\tconst tws = geneList.map(d => {\n\t\t\tconst gene = d.gene\n\t\t\tconst unit = getGEunit(this.app.vocabApi)\n\t\t\tconst name = `${gene} ${unit}`\n\t\t\tconst term = { gene, name, type: GENE_EXPRESSION }\n\t\t\treturn { term, q: {} }\n\t\t})\n\n\t\tconst group = { lst: tws, type: 'hierCluster' }\n\t\tconst customVariable = this.app.getState().plots.find((p: any) => p.id === this.id).tw\n\t\tconst annotationGroup = { lst: [customVariable] }\n\t\tconst config = {\n\t\t\tchartType: 'hierCluster',\n\t\t\ttermgroups: [group, annotationGroup],\n\t\t\tdataType: GENE_EXPRESSION,\n\t\t\tfilter: {\n\t\t\t\tin: true,\n\t\t\t\tjoin: '',\n\t\t\t\ttype: 'tvslst',\n\t\t\t\tlst: [{ type: 'tvs', tvs: { term: customVariable.term } }]\n\t\t\t}\n\t\t}\n\t\tawait this.app.dispatch({\n\t\t\ttype: 'plot_create',\n\t\t\tconfig: structuredClone(config)\n\t\t})\n\t}\n}\n", "import { dofetch3 } from '#common/dofetch'\nimport { renderTable, sayerror } from '#dom'\nimport { bplen } from '#shared/common.js'\nimport { getGroupColors } from '../colors'\nimport { HYPO_COLOR } from '../../dmr/settings/defaults'\nimport type { DmrScanSummary } from '#types'\nimport { getDefaultVolcanoSettings } from '../settings/defaults'\n\n/* Do the genes losing gene-body methylation also lose expression?\n\nGene-body methylation tracks transcription, so a scan finding loss concentrated in gene bodies\npredicts those genes are expressed lower in the same patients. This is the first question in the\nvolcano that reaches function rather than another methylation-adjacent annotation, and it is\nanswerable here because the two groups that defined the scan also define the expression contrast.\n\nThe gene set comes from the server with the scan (DmrScanSummary.geneBodyLoss): hypomethylated\nDMRs overlapping a gene BODY -- a region clipping only a promoter relates to transcription the\nother way round -- and, when the background correction is on, also beating matched background.\nThe test itself is termdb/dmrGeneDE, which compares\nhit genes to non-hits within gene-length strata; see that route for why length matching is the\ntest and not a caveat. */\nexport async function geneBodyLossTest(\n\t/** the volcano's actions menu; rendered into and hidden when a plot is launched from it */\n\ttip: any,\n\tconfig: any,\n\tvocab: { genome: string; dslabel: string },\n\tscan: DmrScanSummary,\n\tapp: any\n) {\n\tconst gb = scan.geneBodyLoss!\n\tconst holder = tip.d\n\t/* The cohort the scan compared, expanded and matched server-side. The plot state's list can still\n\thold a \"Not in\" group as {in:false} carrying the included group's values, which DE reads as two\n\toverlapping groups (\"Common elements found\"). */\n\tconst groups = (scan.matchedSamplelst || config?.samplelst)?.groups\n\tif (!groups || groups.length != 2) {\n\t\tsayerror(holder.append('div'), 'Two sample groups are required.')\n\t\treturn\n\t}\n\tconst div = holder.append('div').style('padding', '10px').style('max-width', '900px')\n\tconst wait = div.append('div').style('color', '#777').text('Running differential expression\u2026')\n\t/* The same DE the volcano launched below will run: same method, count filters, CPM cutoff and\n\tcohort filter. Left to the route's defaults the test picked its engine from group size and got\n\tWilcoxon while the volcano ran edgeR, so the fold changes behind the length-matched difference\n\tand the dots on the plot came from different methods. Aligned, the two share one cached run. */\n\tconst de = getDefaultVolcanoSettings({}, { termType: 'geneExpression' }) as any\n\ttry {\n\t\tconst res: any = await dofetch3('termdb/dmrGeneDE', {\n\t\t\tbody: {\n\t\t\t\tgenome: vocab.genome,\n\t\t\t\tdslabel: vocab.dslabel,\n\t\t\t\t// `in` is part of the DE cache key, so it must travel or the two runs get separate entries\n\t\t\t\tsamplelst: { groups: groups.map((g: any) => ({ name: g.name, in: g.in, values: g.values })) },\n\t\t\t\tgenes: gb.genes,\n\t\t\t\tmethod: de.method,\n\t\t\t\tmin_count: de.minCount,\n\t\t\t\tmin_total_count: de.minTotalCount,\n\t\t\t\tcpm_cutoff: de.cpmCutoff,\n\t\t\t\tfilter: app.getState().termfilter?.filter,\n\t\t\t\tfilter0: app.getState().termfilter?.filter0\n\t\t\t}\n\t\t})\n\t\twait.remove()\n\t\tif (res?.error) {\n\t\t\tsayerror(div.append('div'), res.error)\n\t\t\treturn\n\t\t}\n\t\trenderGeneDE(div, res, gb.regions, config, scan, app, tip)\n\t} catch (e: any) {\n\t\twait.remove()\n\t\tsayerror(div.append('div'), e?.message || String(e))\n\t}\n}\n\nfunction renderGeneDE(div: any, res: any, nRegions: number, config: any, scan: DmrScanSummary, app: any, tip: any) {\n\tconst gb = scan.geneBodyLoss!\n\t/* The DE volcano runs on the patients the methylation was measured on, not on everyone with RNA:\n\tthe server did the same for the test above, so the two agree on who was compared, and a\n\tdifference between the methylation and expression readings cannot be the extra patients. */\n\tconst samplelst = scan.matchedSamplelst || config.samplelst\n\tconst nMatched = samplelst.groups.reduce((n: number, g: any) => n + g.values.length, 0)\n\tconst dir = res.weightedDiff < 0 ? 'lower' : 'higher'\n\t/* The same contrast as a differential-expression volcano, with the gene-body loss genes\n\thighlighted. The stratified difference below is the test; the volcano is where a reader sees the\n\tset against every other gene, and it is the existing DE plot on the same two groups, so nothing\n\tis drawn here that the volcano already draws. Highlighting applies to the significant dots the\n\tvolcano returns, so hit genes that are not DE simply are not marked. */\n\tdiv\n\t\t.append('button')\n\t\t.attr('class', 'sja_menuoption')\n\t\t.attr('data-testid', 'sjpp-geneBodyLoss-deVolcano')\n\t\t.style('margin', '0 0 8px')\n\t\t.style('padding', '3px 6px')\n\t\t.text(\n\t\t\t`Open as differential expression volcano on the ${nMatched.toLocaleString()} samples with methylation, ` +\n\t\t\t\t`${gb.genes.length.toLocaleString()} genes highlighted`\n\t\t)\n\t\t.on('click', () => {\n\t\t\ttip.hide()\n\t\t\tapp.dispatch({\n\t\t\t\ttype: 'plot_create',\n\t\t\t\tconfig: structuredClone({\n\t\t\t\t\tchartType: 'differentialAnalysis',\n\t\t\t\t\ttermType: 'geneExpression',\n\t\t\t\t\tstate: config.state,\n\t\t\t\t\tsamplelst,\n\t\t\t\t\ttw: config.tw,\n\t\t\t\t\thighlightedData: gb.genes,\n\t\t\t\t\t/* The default highlight is orange-yellow, which on a case group drawn in orange makes\n\t\t\t\t\tthe highlighted hits and the up-regulated genes one blob. Use the colour the\n\t\t\t\t\tmethylation figures give to LOSS instead: these genes are highlighted because they\n\t\t\t\t\tlost gene-body methylation, so the fill says the same thing there and here. */\n\t\t\t\t\tsettings: { volcano: { defaultHighlightColor: HYPO_COLOR } }\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\tdiv\n\t\t.append('div')\n\t\t.style('font-weight', 'bold')\n\t\t.style('padding', '4px 0')\n\t\t.text(\n\t\t\t`Genes under a gene-body loss region are expressed ${dir} in the case group: ` +\n\t\t\t\t`${res.weightedDiff >= 0 ? '+' : ''}${res.weightedDiff.toFixed(3)} log\u2082 fold change ` +\n\t\t\t\t`within matched gene length (p = ${res.p < 0.001 ? res.p.toExponential(1) : res.p.toFixed(4)}).`\n\t\t)\n\t/* Length matching is the test, not a caveat: the most frequently hit genes are the longest, and\n\tlong genes move differently for reasons unrelated to methylation. So the comparison is made\n\tinside length strata and the null permutes labels within them. */\n\tdiv\n\t\t.append('div')\n\t\t.style('color', '#777')\n\t\t.style('font-size', '.92em')\n\t\t.text(\n\t\t\t`${nRegions.toLocaleString()} regions \u2192 ${res.genesRequested.toLocaleString()} genes; ` +\n\t\t\t\t`${res.nHit.toLocaleString()} compared against ${res.nOther.toLocaleString()} genes of matched length ` +\n\t\t\t\t`across ${res.strata.length} strata. ${res.genesNotInDE.toLocaleString()} were not tested by DE ` +\n\t\t\t\t`(low count or absent from the expression matrix) and ${res.unmatchedHits.toLocaleString()} fell in ` +\n\t\t\t\t`strata too thin to match. Comparing hits to all other genes instead would recover gene length.`\n\t\t)\n\t/* The individual genes. The stratified difference above says the SET moves; this says which\n\tmembers did, using DE's own p rather than the permutation p, which is a property of the set and\n\tnot of any gene in it. */\n\tif (res.sigCount) {\n\t\tdiv\n\t\t\t.append('div')\n\t\t\t.style('padding', '8px 0 2px')\n\t\t\t.style('font-weight', 'bold')\n\t\t\t.text(\n\t\t\t\t`${res.sigCount.toLocaleString()} of these genes are differentially expressed on their own ` +\n\t\t\t\t\t`(p < 0.05), ${res.sigDown.toLocaleString()} of them down.`\n\t\t\t)\n\t\t/* Bars rather than numbers. Length on a log axis: the set runs from 4 kb to 2 Mb, so a\n\t\tlinear bar would draw every gene under 100 kb as a sliver. Fold change coloured by the group\n\t\tit favours, the same two colours the volcano paints its dots with. */\n\t\tconst { caseColor, controlColor } = getGroupColors(config)\n\t\trenderTable({\n\t\t\tdiv: div.append('div'),\n\t\t\tcolumns: [\n\t\t\t\t{ label: 'Gene' },\n\t\t\t\t{ label: 'Length (log\u2081\u2080 bp)', barplot: { axisWidth: 90, colorPositive: '#999', tickCount: 3 } },\n\t\t\t\t{ label: 'log\u2082FC', barplot: { axisWidth: 110, colorNegative: controlColor, colorPositive: caseColor } },\n\t\t\t\t{ label: res.topGenes[0]?.adjusted ? 'Adjusted p' : 'p', align: 'right' }\n\t\t\t],\n\t\t\trows: res.topGenes.map((g: any) => [\n\t\t\t\t{ value: g.gene },\n\t\t\t\t{ value: g.len ? Number(Math.log10(g.len).toFixed(2)) : NaN },\n\t\t\t\t{ value: Number(g.fc.toFixed(3)) },\n\t\t\t\t{ value: Number(g.p.toPrecision(2)) }\n\t\t\t]),\n\t\t\tshowLines: true,\n\t\t\tmaxHeight: '26vh',\n\t\t\tdownload: { fileName: 'gene-body-loss-genes.tsv' }\n\t\t})\n\t\tif (res.sigCount > res.topGenes.length)\n\t\t\tdiv\n\t\t\t\t.append('div')\n\t\t\t\t.style('color', '#777')\n\t\t\t\t.style('font-size', '.9em')\n\t\t\t\t.text(`Showing the ${res.topGenes.length} most significant of ${res.sigCount.toLocaleString()}.`)\n\t}\n\tdiv.append('div').style('padding', '10px 0 2px').style('font-weight', 'bold').text('By gene length')\n\trenderTable({\n\t\tdiv: div.append('div'),\n\t\tcolumns: [\n\t\t\t{ label: 'Gene length' },\n\t\t\t{ label: 'Genes hit', align: 'right' },\n\t\t\t{ label: 'Matched', align: 'right' },\n\t\t\t{ label: 'Median log\u2082FC, hit', align: 'right' },\n\t\t\t{ label: 'Median log\u2082FC, matched', align: 'right' },\n\t\t\t{ label: 'Difference', align: 'right' }\n\t\t],\n\t\trows: res.strata.map((s: any) => [\n\t\t\t{ value: `${bplen(s.lenFrom)} \u2013 ${bplen(s.lenTo)}` },\n\t\t\t{ value: s.nHit.toLocaleString() },\n\t\t\t{ value: s.nOther.toLocaleString() },\n\t\t\t{ value: Number(s.medianHit.toFixed(3)) },\n\t\t\t{ value: Number(s.medianOther.toFixed(3)) },\n\t\t\t{ value: Number(s.diff.toFixed(3)) }\n\t\t]),\n\t\tshowLines: true,\n\t\tmaxHeight: '26vh',\n\t\tdownload: { fileName: 'gene-body-loss-expression.tsv' }\n\t})\n}\n", "import { dofetch3 } from '#common/dofetch'\nimport { renderTable, sayerror, table2col } from '#dom'\nimport { bplen } from '#shared/common.js'\nimport type { DmrScanSummary } from '#types'\nimport { getDefaultVolcanoSettings } from '../settings/defaults'\n\n/* The genes a scan's DMRs touch, whether their expression moved the way the DMR's position predicts,\nand what PubMed has on that gene's methylation-expression relationship.\n\nLinking and classification are the server's (termdb/dmrGeneLink, utils/dmrGeneLink.ts): promoter\nmethylation and expression should move in opposite directions, gene-body methylation and expression\nin the same one. Literature is fetched per gene on a row click (termdb/dmrLiterature) because\nE-utilities rate-limits a table-wide lookup. */\nexport async function dmrGeneLinkPanel(\n\ttip: any,\n\tconfig: any,\n\tvocab: { genome: string; dslabel: string },\n\tscan: DmrScanSummary,\n\tapp: any\n) {\n\tconst div = tip.d.append('div').style('padding', '10px').style('max-width', '1000px')\n\tconst wait = div\n\t\t.append('div')\n\t\t.style('color', '#777')\n\t\t.text('Linking DMRs to genes and running differential expression\u2026')\n\t// the same DE the volcano and the gene-body test run, so all three share one cached result\n\tconst de = getDefaultVolcanoSettings({}, { termType: 'geneExpression' }) as any\n\tconst state = app.getState()\n\tlet res: any\n\ttry {\n\t\tres = await dofetch3('termdb/dmrGeneLink', {\n\t\t\tbody: {\n\t\t\t\tgenome: vocab.genome,\n\t\t\t\tdslabel: vocab.dslabel,\n\t\t\t\tcacheId: scan.cacheId,\n\t\t\t\tminCpgs: scan.minCpgs,\n\t\t\t\t/* The cohort the scan compared, expanded and matched server-side. The plot state's list can still\n\t\t\t\thold a \"Not in\" group as {in:false} carrying the included group's values, which DE reads as two\n\t\t\t\toverlapping groups. */\n\t\t\t\tsamplelst: {\n\t\t\t\t\tgroups: (scan.matchedSamplelst || config.samplelst).groups.map((g: any) => ({\n\t\t\t\t\t\tname: g.name,\n\t\t\t\t\t\tin: g.in,\n\t\t\t\t\t\tvalues: g.values\n\t\t\t\t\t}))\n\t\t\t\t},\n\t\t\t\tmethod: de.method,\n\t\t\t\tmin_count: de.minCount,\n\t\t\t\tmin_total_count: de.minTotalCount,\n\t\t\t\tcpm_cutoff: de.cpmCutoff,\n\t\t\t\tfilter: state.termfilter?.filter,\n\t\t\t\tfilter0: state.termfilter?.filter0\n\t\t\t}\n\t\t})\n\t} catch (e: any) {\n\t\tres = { error: e?.message || String(e) }\n\t}\n\twait.remove()\n\tif (res.error) return sayerror(div.append('div'), res.error)\n\n\tdiv\n\t\t.append('div')\n\t\t.style('font-weight', 'bold')\n\t\t.text(\n\t\t\t`${res.genes.toLocaleString()} genes touched by DMRs of ${\n\t\t\t\tscan.minCpgs\n\t\t\t}+ CpGs (${res.links.toLocaleString()} gene-context links), ` +\n\t\t\t\t`read against ${res.deMethod || 'differential'} expression on the samples with methylation`\n\t\t)\n\tdiv\n\t\t.append('div')\n\t\t.style('color', '#777')\n\t\t.style('font-size', '.92em')\n\t\t.style('padding', '2px 0 6px')\n\t\t.text(\n\t\t\t`Promoter = within ${bplen(\n\t\t\t\t2000\n\t\t\t)} of the TSS; body = the rest of the gene. Concordant: promoter \u0394\u03B2 and expression change in ` +\n\t\t\t\t`opposite directions, or gene-body \u0394\u03B2 and expression in the same direction (expression adjusted p < 0.05).`\n\t\t)\n\tconst summary = table2col({ holder: div.append('div') })\n\tfor (const context of ['promoter', 'body']) {\n\t\tconst s = res.summary[context] || {}\n\t\tconst [td1, td2] = summary.addRow()\n\t\ttd1.text(context == 'promoter' ? 'Promoter DMRs' : 'Gene-body DMRs')\n\t\ttd2.text(\n\t\t\t['concordant', 'discordant', 'no expression change', 'not tested']\n\t\t\t\t.map(k => `${k}: ${(s[k] || 0).toLocaleString()}`)\n\t\t\t\t.join(' \u00B7 ')\n\t\t)\n\t}\n\n\tconst rows = res.rows\n\tconst litDiv = div.append('div')\n\t// renderTable sorts the cell arrays in place, so a clicked index is looked up through them\n\tconst recordOf = new Map<any[], any>()\n\tconst tableRows = rows.map((r: any) => {\n\t\tconst cells = [\n\t\t\t{ value: r.gene },\n\t\t\t{ value: r.context },\n\t\t\t{ value: `${r.dmr.chr}:${r.dmr.start}-${r.dmr.stop}` },\n\t\t\t{ value: Number(r.dmr.deltaBeta.toFixed(3)) },\n\t\t\t{ value: r.dmr.cpgs },\n\t\t\t{ value: r.nDmrs },\n\t\t\t{ value: r.fc == null ? '' : Number(r.fc.toFixed(3)) },\n\t\t\t{ value: r.p == null ? '' : Number(r.p.toPrecision(2)) },\n\t\t\t{ value: r.relationship }\n\t\t]\n\t\trecordOf.set(cells, r)\n\t\treturn cells\n\t})\n\trenderTable({\n\t\tdiv: div.append('div'),\n\t\tcolumns: [\n\t\t\t{ label: 'Gene' },\n\t\t\t{ label: 'Context' },\n\t\t\t{ label: 'Strongest DMR' },\n\t\t\t{ label: '\u0394\u03B2', sortable: true },\n\t\t\t{ label: 'CpGs', sortable: true },\n\t\t\t{ label: 'DMRs', sortable: true },\n\t\t\t{ label: 'Expression log\u2082FC', sortable: true },\n\t\t\t{ label: 'Expression p', sortable: true },\n\t\t\t{ label: 'Relationship' }\n\t\t],\n\t\trows: tableRows,\n\t\tshowLines: true,\n\t\tmaxHeight: '40vh',\n\t\theader: { allowSort: true },\n\t\tnoRadioBtn: true,\n\t\tdownload: { fileName: 'dmr-gene-links.tsv' },\n\t\t// a click asks PubMed about that row's gene in that row's context\n\t\tnoButtonCallback: (i: number) => showLiterature(litDiv, vocab, recordOf.get(tableRows[i]), disease)\n\t})\n\tif (rows.length < res.links)\n\t\tdiv\n\t\t\t.append('div')\n\t\t\t.style('color', '#777')\n\t\t\t.style('font-size', '.9em')\n\t\t\t.text(`Showing the first ${rows.length.toLocaleString()} of ${res.links.toLocaleString()} links.`)\n\tconst hint = litDiv.append('div').style('color', '#777').style('padding', '6px 0')\n\thint.append('span').text('Click a row for PubMed articles on that gene and mechanism, optionally within a disease: ')\n\tconst disease = hint.append('input').attr('type', 'text').attr('placeholder', 'e.g. myeloma').style('width', '120px')\n}\n\nasync function showLiterature(\n\tholder: any,\n\tvocab: { genome: string; dslabel: string },\n\tr: any,\n\t/** this panel's disease-context box, read at each lookup */\n\tdisease: any\n) {\n\t// keep the hint row (and its typed disease) at the top; replace only the previous results\n\tholder.selectAll('.sjpp-dmr-lit').remove()\n\tconst out = holder.append('div').attr('class', 'sjpp-dmr-lit')\n\tconst head = out.append('div').style('padding', '8px 0 2px').style('font-weight', 'bold')\n\tconst d = String(disease?.property('value') || '').trim()\n\tconst within = d ? ` in ${d}` : ''\n\thead.text(`PubMed: ${r.gene}, ${r.context} methylation and expression${within}\u2026`)\n\tconst res: any = await dofetch3('termdb/dmrLiterature', {\n\t\tbody: { genome: vocab.genome, dslabel: vocab.dslabel, gene: r.gene, context: r.context, disease: d }\n\t}).catch((e: any) => ({ error: e?.message || String(e) }))\n\tholder = out\n\tif (res.error) return sayerror(holder.append('div'), res.error)\n\thead.text(\n\t\t`PubMed: ${r.gene}, ${r.context} methylation and expression${within} (${res.count.toLocaleString()} article${\n\t\t\tres.count == 1 ? '' : 's'\n\t\t}` +\n\t\t\t`${res.count > res.articles.length ? `, ${res.articles.length} most relevant shown` : ''}; this link is ${\n\t\t\t\tr.relationship\n\t\t\t})`\n\t)\n\tif (!res.articles.length) {\n\t\tholder\n\t\t\t.append('div')\n\t\t\t.style('color', '#777')\n\t\t\t.text('No articles match. The link may be unreported rather than unsupported.')\n\t\treturn\n\t}\n\tconst ul = holder.append('ul').style('margin', '2px 0')\n\tfor (const a of res.articles) {\n\t\tconst li = ul.append('li')\n\t\tli.append('span').text(`${a.title} ${a.journal} ${a.year}. `)\n\t\tli.append('a')\n\t\t\t.attr('href', a.doi ? `https://doi.org/${a.doi}` : `https://pubmed.ncbi.nlm.nih.gov/${a.pmid}/`)\n\t\t\t.attr('target', '_blank')\n\t\t\t.text(a.doi ? `doi:${a.doi}` : `PMID ${a.pmid}`)\n\t}\n}\n", "import { axisstyle, table2col, renderTable, DataPointInteractions, drawHoverShapes, type ActionMenuItem } from '#dom'\nimport { axisBottom, axisLeft, rgb, select, selectAll } from 'd3'\nimport type { DataPointEntry, VolcanoDom, VolcanoPlotDimensions, VolcanoViewData } from '../VolcanoTypes'\nimport type { VolcanoPlotDom } from './VolcanoPlotDom'\nimport type { VolcanoInteractions } from '../interactions/VolcanoInteractions'\nimport { DATermTypes as tt } from '../../diffAnalysis/enabledTermTypes'\nimport { roundValueAuto } from '#shared/roundValue.js'\nimport type { ValidatedVolcanoSettings } from '../settings/Settings'\nimport { formatPromoterLabel, elementNoun } from '../promoterLabel'\nimport { plotManhattan, manhattanLayoutDefaults } from '#plots/manhattan/manhattan.ts'\nimport { HYPER_COLOR, HYPO_COLOR } from '#shared/dmrColors.js'\nimport { geneBodyLossTest } from '../interactions/geneBodyLossDE'\nimport { dmrGeneLinkPanel } from '../interactions/dmrGeneLink'\nimport { bplen } from '#shared/common.js'\n\n/** One of the scan's three figures, for mirroring a hover across them. Items are matched by genomic\n * overlap, not by id: a DMR is the same DMR on the volcano and the Manhattan, and on the profile the\n * bin containing it. */\ntype LinkedPlot = {\n\tpoints: any[]\n\thighlight: (dots: any[]) => void\n\tregion: (d: any) => { chr: string; start: number; stop: number }\n}\n\nexport class VolcanoPlotView {\n\tdom: VolcanoDom\n\tinteractions: VolcanoInteractions\n\tsettings: any\n\ttermType: string\n\tvolcanoDom: VolcanoPlotDom\n\tviewData!: VolcanoViewData\n\t/** volcano, scan Manhattan and profile side by side; the p-value table follows them */\n\trow: any\n\tlinked: LinkedPlot[] = []\n\n\tconstructor(dom: VolcanoDom, interactions: VolcanoInteractions, termType: string) {\n\t\tthis.dom = dom\n\t\tthis.interactions = interactions\n\t\tthis.termType = termType\n\t\tconst actions = this.dom.holder\n\t\t\t.append('div')\n\t\t\t.attr('id', 'sjpp-volcano-actions')\n\t\t\t.style('display', 'block')\n\t\t\t.style('z-index', 1)\n\t\t\t.style('position', 'relative')\n\t\tthis.row = this.dom.holder\n\t\t\t.append('div')\n\t\t\t.attr('id', 'sjpp-volcano-row')\n\t\t\t.style('display', 'flex')\n\t\t\t.style('align-items', 'flex-start')\n\t\tconst svg = this.row\n\t\t\t.append('svg')\n\t\t\t.style('display', 'inline-block')\n\t\t\t.attr('id', 'sjpp-volcano-svg')\n\t\t\t.style('vertical-align', 'top')\n\t\tthis.volcanoDom = {\n\t\t\tactions,\n\t\t\tsvg,\n\t\t\tpValueTable: undefined,\n\t\t\ttop: undefined,\n\t\t\txAxis: undefined,\n\t\t\txAxisLabel: undefined,\n\t\t\tyAxis: undefined,\n\t\t\tyAxisLabel: undefined,\n\t\t\tplot: undefined\n\t\t} as Partial<VolcanoPlotDom> as VolcanoPlotDom\n\t}\n\n\trender(settings: ValidatedVolcanoSettings, viewData: VolcanoViewData) {\n\t\tthis.settings = settings\n\t\tthis.viewData = viewData\n\t\tthis.linked = []\n\t\tconst plotDim = this.viewData.plotDim\n\n\t\tthis.initDom()\n\n\t\tthis.renderUserActions()\n\t\tthis.renderPlot(plotDim)\n\t\trenderDataPoints(this)\n\t\tthis.renderFoldChangeLine(plotDim)\n\t\tthis.attachInteractions(plotDim)\n\t\tif (this.settings.showPValueTable) this.renderPValueTable()\n\t\tif (this.viewData.scan?.manhattan) this.renderScanManhattan()\n\t}\n\n\tinitDom() {\n\t\tthis.volcanoDom.actions.selectAll('*').remove()\n\t\tthis.volcanoDom.svg.selectAll('*').remove()\n\n\t\tconst svg = this.volcanoDom.svg\n\t\tthis.volcanoDom.top = svg.append('g').attr('id', 'sjpp-volcano-top')\n\t\tthis.volcanoDom.xAxis = svg.append('g').attr('id', 'sjpp-volcano-xAxis')\n\t\tthis.volcanoDom.yAxis = svg.append('g').attr('id', 'sjpp-volcano-yAxis')\n\t\tthis.volcanoDom.xAxisLabel = svg.append('text').attr('id', 'sjpp-volcano-xAxisLabel').attr('text-anchor', 'middle')\n\t\tthis.volcanoDom.yAxisLabel = svg.append('text').attr('id', 'sjpp-volcano-yAxisLabel').attr('text-anchor', 'middle')\n\t\tthis.volcanoDom.plot = svg.append('g').attr('id', 'sjpp-volcano-plot')\n\n\t\t// Always clear the previous p-value table div before deciding whether\n\t\t// to recreate it. Without this, toggling showPValueTable off leaves\n\t\t// the old div in dom.holder (the table never closes), and toggling\n\t\t// it on repeatedly appends additional divs.\n\t\tthis.dom.holder.select('#sjpp-volcano-pValueTable').remove()\n\t\t// same lifecycle as the p-value table: redrawn from each response, never left stale\n\t\tthis.dom.holder.select('#sjpp-volcano-scanManhattan').remove()\n\n\t\tif (!this.settings.showPValueTable) return\n\t\tthis.volcanoDom.pValueTable = this.row\n\t\t\t.append('div')\n\t\t\t.attr('id', 'sjpp-volcano-pValueTable')\n\t\t\t.attr('data-testid', 'sjpp-volcano-pValueTable')\n\t\t\t.style('display', 'inline-block')\n\t\t\t.style('vertical-align', 'top')\n\t}\n\n\trenderUserActions() {\n\t\t//Images may have a large margin. Hide the overflow.\n\t\tthis.dom.actionsTip.d.style('overflow', 'hidden')\n\t\tthis.volcanoDom.actions.style('margin-left', '20px').style('padding', '5px')\n\t\tthis.addActionButton('Confounding factors', [tt.GENE_EXPRESSION, tt.DNA_METHYLATION], () =>\n\t\t\tthis.interactions.confoundersMenu()\n\t\t)\n\t\tthis.addActionButton('Highlight genes', [tt.GENE_EXPRESSION, tt.SINGLECELL_CELLTYPE, tt.DNA_METHYLATION], () =>\n\t\t\tthis.interactions.launchGeneSetEdit()\n\t\t)\n\t\tthis.addActionButton(\n\t\t\t'Statistics',\n\t\t\t[tt.GENE_EXPRESSION, tt.SINGLECELL_CELLTYPE, tt.DNA_METHYLATION],\n\t\t\t() => {\n\t\t\t\tthis.renderStatsMenu()\n\t\t\t},\n\t\t\t{ whenOpen: 'Hide statistics' }\n\t\t)\n\t\t/* The expression test on the genes under gene-body loss regions. Offered on either reading:\n\t\tthe correction narrows the set to regions that moved more than their stratum drifts, and\n\t\twithout it the DMR's own smoothed FDR is the evidence -- both are answerable questions, and\n\t\tgating the button on the correction made the uncorrected scan a dead end. */\n\t\tconst gb = this.viewData.scan?.geneBodyLoss\n\t\tif (gb?.genes.length) {\n\t\t\tthis.addActionButton(\n\t\t\t\t`Expression of ${gb.genes.length.toLocaleString()} gene-body loss genes`,\n\t\t\t\t[tt.DNA_METHYLATION],\n\t\t\t\t() =>\n\t\t\t\t\tgeneBodyLossTest(\n\t\t\t\t\t\tthis.dom.actionsTip,\n\t\t\t\t\t\tthis.interactions.app.getState().plots.find((p: any) => p.id == this.interactions.id),\n\t\t\t\t\t\tthis.interactions.app.vocabApi.vocab,\n\t\t\t\t\t\tthis.viewData.scan!,\n\t\t\t\t\t\tthis.interactions.app\n\t\t\t\t\t)\n\t\t\t)\n\t\t}\n\t\tif (this.viewData.scan?.cacheId) {\n\t\t\tthis.addActionButton('Genes, expression and literature', [tt.DNA_METHYLATION], () =>\n\t\t\t\tdmrGeneLinkPanel(\n\t\t\t\t\tthis.dom.actionsTip,\n\t\t\t\t\tthis.interactions.app.getState().plots.find((p: any) => p.id == this.interactions.id),\n\t\t\t\t\tthis.interactions.app.vocabApi.vocab,\n\t\t\t\t\tthis.viewData.scan!,\n\t\t\t\t\tthis.interactions.app\n\t\t\t\t)\n\t\t\t)\n\t\t}\n\t\t/* Must match the label the view model built from the same helper, otherwise the\n\t\tfind() below silently misses and the count disappears from the action bar. */\n\t\tconst dmNoun = elementNoun(this.settings?.elementType)\n\t\t/* The view model builds exactly one \"Number of significant <noun>\" row, the noun following the\n\t\tterm type. Matching a hardcoded \"genes\" missed proteomics (\"proteins\") entirely, so its caption\n\t\tand direction split never rendered. */\n\t\tconst SIG_PREFIX = 'Number of significant '\n\t\tconst sigRow = this.viewData.statsData.find(d => d.label.startsWith(SIG_PREFIX))\n\t\t// stats values may be formatted strings now (scan rows); the count row is always a number\n\t\tconst numSigGenes = Number(sigRow?.value ?? 0)\n\t\tif (numSigGenes) {\n\t\t\t// grouped: these run to five and six figures, and \"84302\" vs \"8430\" is hard to tell apart at a glance\n\t\t\tconst n = numSigGenes.toLocaleString()\n\t\t\t/* Direction split next to the total. Both counts are the server's, taken over every\n\t\t\tsignificant row rather than the maxInteractiveDots-capped dots list -- the strongest\n\t\t\thits are not direction-balanced, so counting what reached the browser would misreport\n\t\t\tthe ratio. Named for the CASE group, matching the x-axis subtraction order, so the\n\t\t\tlabel reads the same way round as the plot. */\n\t\t\tconst isDM = this.termType == tt.DNA_METHYLATION\n\t\t\tconst up = this.viewData.numSignificantUp\n\t\t\tconst down = this.viewData.numSignificantDown\n\t\t\tconst split =\n\t\t\t\tup + down > 0\n\t\t\t\t\t? ` (${up.toLocaleString()} ${isDM ? 'hyper' : 'up'} / ${down.toLocaleString()} ${isDM ? 'hypo' : 'down'})`\n\t\t\t\t\t: ''\n\t\t\t/* Name the centring in the caption, with the offset it removed. Both counts are then\n\t\t\tself-describing wherever the line is read or screenshotted, and the raw and centred\n\t\t\tnumbers cannot be confused for each other. */\n\t\t\tconst off = this.viewData.xOffset\n\t\t\tconst centered = this.viewData.centered ? `, centered on median \u0394\u03B2 ${off > 0 ? '+' : ''}${off.toFixed(3)}` : ''\n\t\t\t/* A DMR is differentially methylated by definition, so \"DM DMRs\" would say it twice. Expression\n\t\t\tkeeps \"DE genes\"; any other term type names what the stats row counted. */\n\t\t\tconst noun = isDM\n\t\t\t\t? this.viewData.scan\n\t\t\t\t\t? dmNoun.many\n\t\t\t\t\t: `DM ${dmNoun.many}`\n\t\t\t\t: this.termType == tt.GENE_EXPRESSION\n\t\t\t\t? 'DE genes'\n\t\t\t\t: `significant ${sigRow!.label.slice(SIG_PREFIX.length)}`\n\t\t\tconst sigText = `${n} ${noun}` + split + centered + ':'\n\t\t\tthis.volcanoDom.actions.append('span').text(sigText).style('margin-left', '10px').style('font-weight', 'bold')\n\n\t\t\tconst pValueTableButtonText = this.settings.showPValueTable ? 'Hide p-value table' : 'Show p-value table'\n\t\t\tthis.addActionButton(\n\t\t\t\tpValueTableButtonText,\n\t\t\t\t[tt.GENE_EXPRESSION, tt.SINGLECELL_CELLTYPE, tt.DNA_METHYLATION],\n\t\t\t\tasync () => {\n\t\t\t\t\t/** TODO: This is very slow to render. Need to optimize rendering\n\t\t\t\t\t * and server response to increase performance.*/\n\t\t\t\t\tconst showTable = !this.settings.showPValueTable\n\t\t\t\t\tawait this.interactions.app.dispatch({\n\t\t\t\t\t\ttype: 'plot_edit',\n\t\t\t\t\t\tid: this.interactions.id,\n\t\t\t\t\t\tconfig: { settings: { volcano: { showPValueTable: showTable } } }\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t\tif (numSigGenes && numSigGenes >= 3) {\n\t\t\t// Launch hierCluster for DEGs between the two groups\n\t\t\tthis.addActionButton(\n\t\t\t\t`Hierarchical clustering of ${numSigGenes > 100 ? 'top 100' : numSigGenes} DE genes`,\n\t\t\t\t[tt.GENE_EXPRESSION],\n\t\t\t\tasync () => {\n\t\t\t\t\tawait this.interactions.launchDEGClustering()\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t}\n\n\t/** Use the termTypes arr to render the buttons in a consistent order.\n\t *\n\t * Pass `opts.whenOpen` to make the button a toggle: clicking once opens\n\t * the actionsTip with the callback's content and swaps the button text\n\t * to `whenOpen` (\"Hide statistics\", etc.); clicking again hides the tip\n\t * and restores the original text. The text also restores when the tip\n\t * closes via Esc or outside-click (Menu.onHide hook), and when another\n\t * action button hijacks the tip (the loop below resets all toggles\n\t * before showing the new content). */\n\taddActionButton(text: string, termTypes: string[], callback: any, opts?: { whenOpen?: string }) {\n\t\tif (this.viewData.userActions.noShow.has(text)) return\n\t\tif (!termTypes.includes(this.termType)) return\n\t\tconst button = this.volcanoDom.actions\n\t\t\t.append('button')\n\t\t\t.attr('class', 'sja_menuoption')\n\t\t\t.style('margin', '3px')\n\t\t\t.style('padding', '3px')\n\t\t\t.text(text)\n\t\t\t.on('click', async () => {\n\t\t\t\tconst whenOpen = opts?.whenOpen\n\t\t\t\tif (whenOpen && button.text() === whenOpen) {\n\t\t\t\t\t// Toggle close: tip is currently showing this button's\n\t\t\t\t\t// content. Hide it; onHide resets the label and untags\n\t\t\t\t\t// the button so the body's mousedown handler will treat\n\t\t\t\t\t// it as outside the tip again.\n\t\t\t\t\tthis.dom.actionsTip.hide()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Reset any other toggle buttons whose tip content we're\n\t\t\t\t// about to overwrite. Tagging via data-attr keeps the state\n\t\t\t\t// on the DOM node so we don't need a class field.\n\t\t\t\tthis.volcanoDom.actions.selectAll('button[data-volcano-toggle-open=\"1\"]').each(function () {\n\t\t\t\t\tconst b = select(this as HTMLButtonElement)\n\t\t\t\t\tconst closed = b.attr('data-volcano-toggle-closed')\n\t\t\t\t\tif (closed) b.text(closed).attr('data-volcano-toggle-open', null)\n\t\t\t\t\t;(this as any).parent_menu = undefined\n\t\t\t\t\tconst eh = (this as any).__volcanoEscHandler\n\t\t\t\t\tif (eh) {\n\t\t\t\t\t\tdocument.removeEventListener('keydown', eh)\n\t\t\t\t\t\t;(this as any).__volcanoEscHandler = undefined\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tthis.dom.actionsTip.clear().showunder(button.node())\n\t\t\t\tif (whenOpen) {\n\t\t\t\t\tbutton.text(whenOpen).attr('data-volcano-toggle-open', '1').attr('data-volcano-toggle-closed', text)\n\t\t\t\t\t// Tag the button as a \"parent_menu\" of the tip so Menu's\n\t\t\t\t\t// body-mousedown outside-click handler skips it (see\n\t\t\t\t\t// menu.js, body.on('mousedown.menu') \u2014 checks\n\t\t\t\t\t// event.target.parent_menu === this.dnode). Without this,\n\t\t\t\t\t// clicking the toggle button to close would fire the\n\t\t\t\t\t// body handler first \u2192 tip hides + onHide resets label \u2192\n\t\t\t\t\t// the click handler then sees the closed label and\n\t\t\t\t\t// reopens, repainting instead of closing.\n\t\t\t\t\t;(button.node() as any).parent_menu = this.dom.actionsTip.dnode\n\t\t\t\t\t// Menu has a built-in keyup Escape handler on its own div,\n\t\t\t\t\t// but it only fires when the tip itself has keyboard\n\t\t\t\t\t// focus \u2014 typically lost the moment the user moves their\n\t\t\t\t\t// mouse over plot content. Attach a document-level\n\t\t\t\t\t// listener for the lifetime of the open toggle so Esc\n\t\t\t\t\t// closes from anywhere. Removed in both cleanup paths\n\t\t\t\t\t// (onHide below + the toggle-reset loop above).\n\t\t\t\t\tconst escHandler = (e: KeyboardEvent) => {\n\t\t\t\t\t\tif (e.key === 'Escape') this.dom.actionsTip.hide()\n\t\t\t\t\t}\n\t\t\t\t\tdocument.addEventListener('keydown', escHandler)\n\t\t\t\t\t;(button.node() as any).__volcanoEscHandler = escHandler\n\t\t\t\t\tthis.dom.actionsTip.onHide = () => {\n\t\t\t\t\t\tbutton.text(text).attr('data-volcano-toggle-open', null)\n\t\t\t\t\t\t;(button.node() as any).parent_menu = undefined\n\t\t\t\t\t\tdocument.removeEventListener('keydown', escHandler)\n\t\t\t\t\t\t;(button.node() as any).__volcanoEscHandler = undefined\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Clear any stale onHide left by a previous toggle button\n\t\t\t\t\t// so an outside-click after this non-toggle open doesn't\n\t\t\t\t\t// reset the wrong button.\n\t\t\t\t\tthis.dom.actionsTip.onHide = undefined\n\t\t\t\t}\n\t\t\t\tawait callback()\n\t\t\t})\n\t}\n\n\trenderPlot(plotDim: VolcanoPlotDimensions) {\n\t\tthis.volcanoDom.svg.attr('width', plotDim.svg.width).attr('height', plotDim.svg.height)\n\n\t\tthis.renderTermInfo(plotDim)\n\n\t\tthis.volcanoDom.yAxisLabel.attr(\n\t\t\t'transform',\n\t\t\t`translate(${plotDim.yAxisLabel.x}, ${plotDim.yAxisLabel.y}) rotate(-90)`\n\t\t)\n\t\tthis.setSvgSubscriptLabel(this.volcanoDom.yAxisLabel, '-log', '10', `(${this.viewData.pValueLabel})`)\n\n\t\tthis.volcanoDom.xAxisLabel.attr('transform', `translate(${plotDim.xAxisLabel.x}, ${plotDim.xAxisLabel.y})`)\n\t\t/* The axis must name what it is actually plotting. Delta-beta has no subscript, so it is\n\t\twritten as plain text rather than forced through the log-subscript helper. */\n\t\tif (this.termType === tt.DNA_METHYLATION && this.settings.xAxis === 'delta_beta') {\n\t\t\tthis.volcanoDom.xAxisLabel.selectAll('*').remove()\n\t\t\t/* Prefer the group-named form built by the view model (\"\u0394\u03B2 (NSD2 Higher \u2212 NSD2 Lower)\"):\n\t\t\tcase/control are slot names, so the role-based wording does not say which direction a\n\t\t\tpositive value points. Fall back to it only when the names are unavailable. */\n\t\t\tthis.volcanoDom.xAxisLabel.text(this.viewData.deltaBetaAxisLabel || '\u0394\u03B2 (case \u2212 control)')\n\t\t} else {\n\t\t\tthis.volcanoDom.xAxisLabel.text(null)\n\t\t\tthis.setSvgSubscriptLabel(this.volcanoDom.xAxisLabel, 'log', '2', '(fold-change)')\n\t\t}\n\n\t\tthis.renderScale(plotDim.xScale)\n\t\tthis.renderScale(plotDim.yScale, true)\n\n\t\t// Server-rendered PNG of the full scatter (every dot, non-interactive).\n\t\t// Drawn first so overlay circles + the border rect sit on top. The volcano\n\t\t// binary emits a borderless image whose data extent matches the client's\n\t\t// scales, so placing it over the plot rect aligns dot-for-dot.\n\t\tif (this.viewData.volcanoPng) {\n\t\t\tthis.volcanoDom.plot\n\t\t\t\t.append('image')\n\t\t\t\t.attr('href', `data:image/png;base64,${this.viewData.volcanoPng}`)\n\t\t\t\t.attr('x', plotDim.plot.x)\n\t\t\t\t.attr('y', plotDim.plot.y)\n\t\t\t\t.attr('width', plotDim.plot.width)\n\t\t\t\t.attr('height', plotDim.plot.height)\n\t\t\t\t.attr('preserveAspectRatio', 'none')\n\t\t}\n\t}\n\n\trenderTermInfo(plotDim) {\n\t\tif (this.viewData.termInfo == undefined) return\n\t\tthis.volcanoDom.top.attr('transform', `translate(${plotDim.top.x}, ${plotDim.top.y})`)\n\n\t\tconst y = this.viewData.termInfo.y\n\t\tconst addLabel = term => {\n\t\t\treturn (\n\t\t\t\tthis.volcanoDom.top\n\t\t\t\t\t.append('text')\n\t\t\t\t\t.attr('font-size', '0.9em')\n\t\t\t\t\t.attr('transform', `translate(${term.x}, ${y + 10})`)\n\t\t\t\t\t// .attr('text-anchor', 'start')\n\t\t\t\t\t.text(term.label)\n\t\t\t)\n\t\t}\n\n\t\t// const addRect = (term) => {\n\t\t// \tthis.volcanoDom.top.append('rect')\n\t\t// \t\t.attr('width', 10)\n\t\t// \t\t.attr('height', 10)\n\t\t// \t\t.attr('transform', `translate(${term.rectX}, ${y})`)\n\t\t// \t\t.attr('fill', term.color)\n\t\t// }\n\n\t\tconst firstTerm = this.viewData.termInfo.first\n\t\taddLabel(firstTerm)\n\t\t// addRect(firstTerm)\n\n\t\tconst secondTerm = this.viewData.termInfo.second\n\t\t// addRect(secondTerm)\n\t\tconst secondLabel = addLabel(secondTerm)\n\t\tsecondLabel.attr('text-anchor', 'end')\n\t}\n\n\trenderScale(scale: any, isLeft = false) {\n\t\tconst scaleG = this.volcanoDom[isLeft ? 'yAxis' : 'xAxis']\n\t\t\t.append('g')\n\t\t\t.attr('transform', `translate(${scale.x}, ${scale.y})`)\n\t\t\t.call(isLeft ? axisLeft(scale.scale) : axisBottom(scale.scale))\n\n\t\taxisstyle({\n\t\t\taxis: scaleG,\n\t\t\tcolor: 'black',\n\t\t\tshowline: true\n\t\t})\n\t}\n\n\trenderFoldChangeLine(plotDim: VolcanoPlotDimensions) {\n\t\t//logFoldChangeLine\n\t\tthis.volcanoDom.plot\n\t\t\t.append('line')\n\t\t\t.attr('stroke', '#ccc')\n\t\t\t.attr('shape-rendering', 'crispEdges')\n\t\t\t.attr('x1', plotDim.logFoldChangeLine.x)\n\t\t\t.attr('x2', plotDim.logFoldChangeLine.x)\n\t\t\t.attr('y1', plotDim.logFoldChangeLine.y1)\n\t\t\t.attr('y2', plotDim.logFoldChangeLine.y2)\n\t}\n\n\trenderStatsMenu() {\n\t\t//Render any images. viewModel returns the response array of images or []\n\t\tfor (const img of this.viewData.images || []) {\n\t\t\tthis.dom.actionsTip.d\n\t\t\t\t.append('img')\n\t\t\t\t.style('display', 'inline-block')\n\t\t\t\t.style('margin-left', '10px')\n\t\t\t\t.style('margin-top', '-30px')\n\t\t\t\t.attr('width', 450)\n\t\t\t\t.attr('height', 450)\n\t\t\t\t.attr('src', img.src)\n\t\t}\n\t\tconst tableHolder = this.dom.actionsTip.d\n\t\t\t.append('div')\n\t\t\t//Show the stats table underneath the images if > 1 image or to the right if only 1 image\n\t\t\t.style('display', this.viewData.images.length == 1 ? 'inline-block' : 'block')\n\t\t\t//Top margin is roughly inline with image however the margins are set by server\n\t\t\t//Likewise the image margins are undetectable.\n\t\t\t//This is a roughly satistifes the different image margin scenarios.\n\t\t\t.style('margin', `${this.viewData.images.length == 1 ? `40px 10px` : `0px 0px`} 0px 5px`)\n\t\t\t.style('vertical-align', 'top')\n\t\tconst table = table2col({ holder: tableHolder })\n\t\tfor (const d of this.viewData.statsData) {\n\t\t\tconst [td1, td2] = table.addRow()\n\t\t\ttd1.text(d.label)\n\t\t\t/* Group the counts, but only the counts: statsData also carries a percentage that the\n\t\t\tview model already put through roundValueAuto(), and toLocaleString() would re-round it\n\t\t\tto three decimals. Integer test rather than a per-label check so a row added later is\n\t\t\tformatted correctly without touching this. */\n\t\t\ttd2.style('text-align', 'end').text(Number.isInteger(d.value) ? d.value.toLocaleString() : d.value)\n\t\t}\n\t}\n\n\t/* Where the DMRs are, along the whole genome: every kept DMR in the server's PNG, hyper above\n\tthe line and hypo below, height = evidence; the most significant thousand are live. A dot is\n\tthe same DMR the volcano shows, so hover and click give the volcano's own rows and actions --\n\tthe violin of that region and the region view, a genome browser with the called DMRs, the\n\tper-CpG group means and the genes. Same lifecycle as the p-value table: redrawn from each\n\tresponse, never left stale. */\n\t/** What the scan covered, for the figure titles: the chromosome when that is all of it, and \"the\n\t * genome\" otherwise. A one-chromosome scan describing itself as genome-wide overstates every\n\t * number under it, which is what a dev host holding a subset of CpG shards produces. */\n\tprivate scanSpan(): string {\n\t\tconst chrs = this.viewData.scan?.chromosomes || []\n\t\treturn chrs.length == 1 ? chrs[0] : 'the genome'\n\t}\n\n\trenderScanManhattan() {\n\t\tconst { manhattan } = this.viewData.scan!\n\t\t// beside the volcano, ahead of the p-value table (insert before a missing node appends)\n\t\tconst div = this.row\n\t\t\t.insert('div', '#sjpp-volcano-pValueTable')\n\t\t\t.attr('id', 'sjpp-volcano-scanManhattan')\n\t\t\t.attr('data-testid', 'sjpp-volcano-scanManhattan')\n\t\t\t.style('display', 'block')\n\t\t\t.style('margin', '0 0 0 20px')\n\t\t// a Manhattan point carries the row's fields; the volcano's tooltip and actions read a row\n\t\tconst asRow = (d: any): DataPointEntry =>\n\t\t\t({\n\t\t\t\tpromoter_id: `${d.chrom}:${d.start}-${d.stop}`,\n\t\t\t\tgene_name: d.gene_name,\n\t\t\t\tchr: d.chrom,\n\t\t\t\tstart: d.start,\n\t\t\t\tstop: d.stop,\n\t\t\t\tdelta_beta: d.delta_beta,\n\t\t\t\tfold_change: d.fold_change,\n\t\t\t\toriginal_p_value: d.p,\n\t\t\t\tadjusted_p_value: d.p,\n\t\t\t\tno_cpgs: d.no_cpgs,\n\t\t\t\texcess: d.excess\n\t\t\t} as any)\n\t\t// the case group, whose direction the colours name; the scan carries the groups it ran on\n\t\tconst g2 = this.viewData.scan!.matchedSamplelst?.groups?.[1]?.name || 'case group'\n\t\tconst link: LinkedPlot = {\n\t\t\tpoints: [],\n\t\t\thighlight: () => {},\n\t\t\tregion: d => ({ chr: d.chrom, start: d.start, stop: d.stop })\n\t\t}\n\t\tconst handle = plotManhattan(\n\t\t\tdiv,\n\t\t\t{ png: manhattan!.png, plotData: manhattan!.plotData },\n\t\t\t{\n\t\t\t\t...manhattanLayoutDefaults,\n\t\t\t\tplotWidth: manhattan!.plotWidth,\n\t\t\t\tplotHeight: manhattan!.plotHeight,\n\t\t\t\t// the server already picked N per direction; the client must not re-cap by |y|\n\t\t\t\tinteractiveDotsCap: manhattan!.plotData.points.length,\n\t\t\t\tmaxTooltipGenes: this.settings.maxTooltipGenes,\n\t\t\t\tlegendItemWidth: 130\n\t\t\t},\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\t// names the chromosome when that is all the scan covered, rather than \"the genome\"\n\t\t\t\ttitle: `DMRs along ${this.scanSpan()}, direction in ${g2} (top ${manhattan!.interactive.toLocaleString()} per direction interactive)`,\n\t\t\t\t// short, because it runs down a 300 px axis: the legend and title say what the sign means\n\t\t\t\tyAxisLabel: `\u00B1log\u2081\u2080(${this.viewData.pValueLabel.replace('smoothed ', '')})`,\n\t\t\t\tlegend: [\n\t\t\t\t\t{ label: 'Hypermethylated', color: HYPER_COLOR, hollow: true },\n\t\t\t\t\t{ label: 'Hypomethylated', color: HYPO_COLOR, hollow: true }\n\t\t\t\t],\n\t\t\t\titemNoun: 'DMR',\n\t\t\t\trenderSingleHoverTooltip: (d, container) => {\n\t\t\t\t\tconst table = table2col({ holder: container.append('table') })\n\t\t\t\t\tthis.addTooltipRows(asRow(d), table)\n\t\t\t\t\tif (d.no_cpgs != null) addTooltipRow(table, 'CpGs', d.no_cpgs)\n\t\t\t\t},\n\t\t\t\tbuildMultiHitTableData: dots => this.buildMultiHitTable(dots.map(asRow)),\n\t\t\t\tgetActions: d => this.getActionMenuOpts(asRow(d)),\n\t\t\t\tgetRowKey: d => `${d.chrom}:${d.start}-${d.stop}`,\n\t\t\t\tonHover: dots => this.mirrorHover(link, dots)\n\t\t\t}\n\t\t)\n\t\tthis.linked.push(Object.assign(link, handle))\n\t\tthis.renderMethylationProfile(this.viewData.scan!.matchedSamplelst?.groups?.[0]?.name || 'control group', g2)\n\t}\n\n\t/* The genome-wide methylation profile, under the DMR plot: mean beta per group in 100 kb bins,\n\tdrawn as the per-bin difference. The DMR plot above shows the regions that passed a threshold;\n\tthis shows every bin that was measured, which is what says whether the methylome shifted a\n\tlittle everywhere or a lot in a few places.\n\n\tSame component and the same hover/click layer as the DMR plot, on the bins that moved most in\n\teach direction: 29,000 dots in a band cannot be read by eye, so a dot has to be able to say\n\twhich 100 kb it is, what each group's mean beta there was, and how many CpGs that rests on.\n\tClicking opens the browser on the bin -- the question a standout bin raises is which of the\n\tscan's DMRs are inside it, and that is the view that answers it. */\n\tprivate renderMethylationProfile(controlName: string, caseName: string) {\n\t\tconst profile = this.viewData.scan?.profile\n\t\tif (!profile) return\n\t\tconst div = this.dom.holder\n\t\t\t.select('#sjpp-volcano-scanManhattan')\n\t\t\t.append('div')\n\t\t\t.attr('data-testid', 'sjpp-volcano-methylationProfile')\n\t\t\t.style('display', 'block')\n\t\t\t/* Pulled up into the trailing space the component reserves below every plot for a\n\t\t\tlegend this one does not have. The two figures share one x axis and are read together,\n\t\t\tso a gap the height of the profile itself reads as two unrelated pictures. */\n\t\t\t.style('margin-top', '-70px')\n\t\t// the bin's own span, from the start the point carries and the fixed bin width\n\t\tconst region = (d: any) => ({ chr: d.chrom, start: d.pos, stop: d.pos + profile.binBp })\n\t\tconst label = (d: any) => `${d.chrom}:${(d.pos + 1).toLocaleString()}-${(d.pos + profile.binBp).toLocaleString()}`\n\t\tconst link: LinkedPlot = { points: [], highlight: () => {}, region }\n\t\tconst handle = plotManhattan(\n\t\t\tdiv,\n\t\t\t{ png: profile.png, plotData: profile.plotData },\n\t\t\t{\n\t\t\t\t...manhattanLayoutDefaults,\n\t\t\t\tplotWidth: profile.plotWidth,\n\t\t\t\tplotHeight: profile.plotHeight,\n\t\t\t\t/* The radius the PNG was drawn at, not the shared default of 2: the hover layer is\n\t\t\t\tplaced in the PNG's own pixel space, and a 1 px mismatch in the padding stretches\n\t\t\t\tthe image against the dot coordinates the server computed. */\n\t\t\t\tpngDotRadius: profile.dotRadius,\n\t\t\t\t// the server already picked N per direction; the client must not re-cap by |y|\n\t\t\t\tinteractiveDotsCap: profile.plotData.points.length,\n\t\t\t\t/* More rows than the volcano's 5. At 100 kb there are ~29,000 bins over 1,000 px, so\n\t\t\t\ta cursor covers a median of 7 live bins on MMRF however tight the hit radius -- the\n\t\t\t\tdots genuinely overlap at this scale. 8 shows the whole neighbourhood on a typical\n\t\t\t\thover instead of 5 of it. */\n\t\t\t\tmaxTooltipGenes: 8,\n\t\t\t\tshowLegend: false,\n\t\t\t\tshowDownload: false\n\t\t\t},\n\t\t\tundefined,\n\t\t\t{\n\t\t\t\t/* The width drawn, not the width requested: the server reports back what it binned at,\n\t\t\t\tand a reader quoting the figure needs the two to agree. The interactive count is the\n\t\t\t\tlive dot count rather than the per-direction rule, because at a coarse width the rule\n\t\t\t\treaches every bin and \"top 1,000 per direction\" would read as a restriction. */\n\t\t\t\ttitle:\n\t\t\t\t\t`${this.scanSpan() == 'the genome' ? 'Methylome-wide' : `${this.scanSpan()}-wide`} profile: ` +\n\t\t\t\t\t`mean \u0394\u03B2 per ${bplen(profile.binBp)} bin in ${caseName} ` +\n\t\t\t\t\t`(${profile.interactive.toLocaleString()} of ${profile.bins.toLocaleString()} bins interactive)`,\n\t\t\t\tyAxisLabel: '\u0394\u03B2 per bin',\n\t\t\t\titemNoun: 'bin',\n\t\t\t\trenderSingleHoverTooltip: (d, container) => {\n\t\t\t\t\tconst table = table2col({ holder: container.append('table') })\n\t\t\t\t\taddTooltipRow(table, 'Region', label(d))\n\t\t\t\t\t// with capping off, the plotted y is the difference itself\n\t\t\t\t\taddTooltipRow(table, '\u0394\u03B2', roundValueAuto(d.y))\n\t\t\t\t\taddTooltipRow(table, `Mean \u03B2, ${controlName}`, roundValueAuto(d.control))\n\t\t\t\t\taddTooltipRow(table, `Mean \u03B2, ${caseName}`, roundValueAuto(d.case))\n\t\t\t\t\taddTooltipRow(table, 'CpGs measured', d.n_probes.toLocaleString())\n\t\t\t\t},\n\t\t\t\tbuildMultiHitTableData: dots => ({\n\t\t\t\t\tcolumns: [{ label: 'Region' }, { label: '\u0394\u03B2', sortable: true }, { label: 'CpGs', sortable: true }],\n\t\t\t\t\trows: dots.map(d => [{ value: label(d) }, { value: roundValueAuto(d.y) }, { value: d.n_probes }])\n\t\t\t\t}),\n\t\t\t\tgetActions: d => [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: 'Genome browser',\n\t\t\t\t\t\tonClick: async () => await this.interactions.launchScanGenomeBrowser(region(d), this.viewData.scan!)\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tgetRowKey: d => label(d),\n\t\t\t\tonHover: dots => this.mirrorHover(link, dots)\n\t\t\t}\n\t\t)\n\t\tthis.linked.push(Object.assign(link, handle))\n\t}\n\n\t/* Ring, on every other figure, the live dots overlapping what the cursor is on. Only live dots can\n\tbe ringed -- the rest are pixels in a PNG -- so a hovered DMR outside another figure's interactive\n\ttop N has nothing to light up there. */\n\tprivate mirrorHover(src: LinkedPlot, dots: any[]) {\n\t\tconst hovered = dots.map(src.region)\n\t\tfor (const p of this.linked) {\n\t\t\tif (p === src) continue\n\t\t\tp.highlight(\n\t\t\t\thovered.length\n\t\t\t\t\t? p.points.filter(d => {\n\t\t\t\t\t\t\tconst r = p.region(d)\n\t\t\t\t\t\t\treturn hovered.some(h => h.chr == r.chr && h.start < r.stop && r.start < h.stop)\n\t\t\t\t\t })\n\t\t\t\t\t: []\n\t\t\t)\n\t\t}\n\t}\n\n\trenderPValueTable() {\n\t\tif (!this.settings.showPValueTable) return\n\t\t// Cap rendered rows to prevent browser OOM with large datasets (e.g. 30k+ significant promoters).\n\t\t// The full data is still available in pValueTableData.rows for export/search.\n\t\tconst maxTableRows = 5000\n\t\tconst allRows = this.viewData.pValueTableData.rows\n\t\tconst rows = allRows.length > maxTableRows ? allRows.slice(0, maxTableRows) : allRows\n\t\tif (allRows.length > maxTableRows) {\n\t\t\tthis.volcanoDom.pValueTable\n\t\t\t\t.append('div')\n\t\t\t\t.style('padding', '5px 10px')\n\t\t\t\t.style('font-size', '.8em')\n\t\t\t\t.style('color', '#666')\n\t\t\t\t.text(\n\t\t\t\t\t`Showing top ${maxTableRows.toLocaleString()} of ${allRows.length.toLocaleString()} significant results (sorted by fold-change)`\n\t\t\t\t)\n\t\t}\n\t\trenderTable({\n\t\t\tcolumns: this.viewData.pValueTableData.columns,\n\t\t\trows,\n\t\t\tdiv: this.volcanoDom.pValueTable,\n\t\t\tshowLines: true,\n\t\t\tmaxHeight: `${this.viewData.pValueTableData.height}px`,\n\t\t\tresize: true,\n\t\t\theader: { allowSort: true },\n\t\t\tnoRadioBtn: true,\n\t\t\tnoButtonCallback: (i: number) => {\n\t\t\t\t//On click, persistently highlight the data point\n\t\t\t\t// if (this.termType != GENE_EXPRESSION) return\n\t\t\t\t// Index into the same array handed to renderTable: it sorts rows in place, so\n\t\t\t\t// the unsliced pValueTableData.rows would be misindexed once a header is sorted.\n\t\t\t\tconst key = this.viewData.pValueTableData.rowKeys.get(rows[i])\n\t\t\t\tif (!key) return\n\t\t\t\tthis.interactions.highlightDataPoint(key)\n\t\t\t},\n\t\t\thoverEffects: (tr, row) => {\n\t\t\t\t//May restrict termTypes later\n\t\t\t\t// if (this.termType != GENE_EXPRESSION) return\n\t\t\t\t//Highlight the data point when hovering over the table row\n\t\t\t\t//Previously highlighted data points are not affected\n\t\t\t\tconst circles = this.volcanoDom.plot.selectAll('circle').nodes()\n\t\t\t\tconst key = this.viewData.pValueTableData.rowKeys.get(row)\n\t\t\t\tconst dataKey = this.termType === tt.DNA_METHYLATION ? 'promoter_id' : 'gene_name'\n\t\t\t\tconst circle = circles.find((d: any) => d.__data__[dataKey] == key) as any\n\t\t\t\tif (!circle || circle.__data__.highlighted) return\n\n\t\t\t\t/** Circles may render behind several other circles, making it hard\n\t\t\t\t * to see the highlight. Clone the circle to appear on top of the\n\t\t\t\t * elements, then destroy. */\n\t\t\t\tlet clone\n\t\t\t\ttr.on('mouseover', () => {\n\t\t\t\t\tif (circle.__data__.highlighted || clone) return\n\t\t\t\t\tclone = this.volcanoDom.plot.node()?.appendChild(circle.cloneNode(true))\n\t\t\t\t\tclone.setAttribute('fill-opacity', 0.9)\n\t\t\t\t})\n\t\t\t\ttr.on('mouseleave', () => {\n\t\t\t\t\tif (!clone) return\n\t\t\t\t\tclone.remove()\n\t\t\t\t\tclone = null\n\t\t\t\t})\n\t\t\t\t//All other circles appear dimmed on hover\n\t\t\t\tthis.volcanoDom.pValueTable.on('mouseover', () => {\n\t\t\t\t\tselectAll(circles).attr('stroke-opacity', 0.075)\n\t\t\t\t})\n\t\t\t\tthis.volcanoDom.pValueTable.on('mouseleave', () => {\n\t\t\t\t\tselectAll(circles).attr('stroke-opacity', (d: any) => (d.significant ? 0.35 : 0.2))\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n\n\tsetSvgSubscriptLabel(textElem: any, prefix: string, subscript: string, suffix: string) {\n\t\ttextElem.text(null)\n\t\ttextElem.append('tspan').text(prefix)\n\t\ttextElem.append('tspan').attr('baseline-shift', 'sub').attr('font-size', '0.7em').text(subscript)\n\t\ttextElem.append('tspan').text(suffix)\n\t}\n\n\tprivate attachInteractions(plotDim: VolcanoPlotDimensions) {\n\t\tconst points = this.viewData.pointData as DataPointEntry[]\n\t\tif (!points || points.length === 0) return\n\n\t\tconst dotRadiusPx = this.viewData.plotExtent.dotRadiusPx\n\t\tconst hitRadius = dotRadiusPx + 3\n\t\t// Inset by stroke-width/2 so the orange fill stops at the dot's stroke inner edge.\n\t\tconst highlightRadius = Math.max(0.5, dotRadiusPx - 0.5)\n\t\tconst highlightColor = this.settings.defaultHighlightColor\n\n\t\t// Hover-ring layer \u2014 visual only, never intercepts mouse events.\n\t\tconst hoverLayer = this.volcanoDom.plot.append('g').attr('id', 'sjpp-volcano-hover').style('pointer-events', 'none')\n\n\t\t// Cover rect \u2014 last child of plot group so it sits on top of dots,\n\t\t// hover rings, and the fold-change line.\n\t\tconst cover = this.volcanoDom.plot\n\t\t\t.append('rect')\n\t\t\t.attr('id', 'sjpp-volcano-cover')\n\t\t\t.attr('x', plotDim.plot.x)\n\t\t\t.attr('y', plotDim.plot.y)\n\t\t\t.attr('width', plotDim.plot.width)\n\t\t\t.attr('height', plotDim.plot.height)\n\t\t\t.attr('fill', 'transparent')\n\t\t\t.style('pointer-events', 'all')\n\t\t\t.style('cursor', 'default')\n\n\t\t// Circle as an SVG path so it can flow through the generic\n\t\t// `drawHoverShapes` helper (which renders `<path>` elements).\n\t\tconst circlePath = (r: number) => `M${r},0 A${r},${r} 0 1,1 ${-r},0 A${r},${r} 0 1,1 ${r},0 Z`\n\n\t\t// a scan's DMRs are also on the two genome-wide figures; a hover on any one rings them in all\n\t\tconst link: LinkedPlot | undefined = this.viewData.scan\n\t\t\t? {\n\t\t\t\t\tpoints,\n\t\t\t\t\tregion: d => ({ chr: d.chr, start: d.start, stop: d.stop }),\n\t\t\t\t\thighlight: dots => {\n\t\t\t\t\t\tdrawHoverShapes(\n\t\t\t\t\t\t\tlinkedLayer,\n\t\t\t\t\t\t\tdots.map(d => ({\n\t\t\t\t\t\t\t\tpath: circlePath(dotRadiusPx + 2),\n\t\t\t\t\t\t\t\ttransform: `translate(${d.x},${d.y})`,\n\t\t\t\t\t\t\t\tstroke: 'black',\n\t\t\t\t\t\t\t\tstrokeWidth: 2\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t }\n\t\t\t: undefined\n\t\tconst linkedLayer = this.volcanoDom.plot.append('g').style('pointer-events', 'none')\n\t\tif (link) this.linked.push(link)\n\n\t\tnew DataPointInteractions<DataPointEntry>({\n\t\t\tcover,\n\t\t\thoverLayer,\n\t\t\thoverTip: this.dom.tip,\n\t\t\tpoints,\n\t\t\t// Quadtree in cover-local space \u2014 d.x/d.y are SVG-absolute, so subtract\n\t\t\t// the plot rect's origin once when building the tree.\n\t\t\tgetX: d => d.x - plotDim.plot.x,\n\t\t\tgetY: d => d.y - plotDim.plot.y,\n\t\t\thitRadius,\n\t\t\ttoHoverSpec: d => ({\n\t\t\t\tpath: circlePath(highlightRadius),\n\t\t\t\t// Hover layer lives in the same coord space as the dots (SVG-absolute),\n\t\t\t\t// so translate by d.x/d.y \u2014 NOT the cover-local pair.\n\t\t\t\ttransform: `translate(${d.x},${d.y})`,\n\t\t\t\tfill: highlightColor,\n\t\t\t\tfillOpacity: 0.9,\n\t\t\t\tstroke: 'none'\n\t\t\t}),\n\t\t\tmaxTooltipRows: this.settings.maxTooltipGenes,\n\t\t\t...(link ? { onHover: dots => this.mirrorHover(link, dots) } : {}),\n\t\t\titemNoun: 'gene',\n\t\t\trenderSingleHoverTooltip: (d, container) => {\n\t\t\t\tconst table = table2col({ holder: container.append('table') })\n\t\t\t\tthis.addTooltipRows(d, table)\n\t\t\t},\n\t\t\tbuildMultiHitTableData: dots => this.buildMultiHitTable(dots),\n\t\t\tgetActions: d => this.getActionMenuOpts(d),\n\t\t\trenderSingleHitInfo: (d, container) => {\n\t\t\t\tconst tbl = table2col({ holder: container.append('table') })\n\t\t\t\tthis.addTooltipRows(d, tbl)\n\t\t\t},\n\t\t\tgetRowKey: d => d.gene_name\n\t\t}).attach()\n\t}\n\n\t/** Whether the effect size on show is delta-beta rather than log2 fold-change. Methylation\n\t * fold-change is a difference of logits: it ranks elements correctly but says nothing about\n\t * how much methylation moved, so it must not be what a reader is handed next to a delta-beta\n\t * axis. Read by both hover paths -- the single-point tooltip and the multi-point table -- so\n\t * the two cannot disagree about which number they show. */\n\tprivate get onDeltaBeta() {\n\t\treturn this.termType === tt.DNA_METHYLATION && this.settings.xAxis === 'delta_beta'\n\t}\n\n\tprivate buildMultiHitTable(dots: DataPointEntry[]): { columns: any[]; rows: any[] } {\n\t\tconst isDM = this.termType === tt.DNA_METHYLATION\n\t\tconst isDAP = this.termType === tt.PROTEOME_DAP\n\t\tconst effectLabel = this.onDeltaBeta ? '\u0394\u03B2' : 'log\u2082(FC)'\n\t\tconst pValueType = this.settings.pValueType\n\t\t// a single p (DAP's FDR, a scan's p) lives in original_p_value whatever the p-value type says\n\t\tconst { pValueLabel, singlePValue } = this.viewData\n\t\tconst pLabel = pValueLabel.charAt(0).toUpperCase() + pValueLabel.slice(1)\n\t\tconst pField = (singlePValue ? 'original_p_value' : `${pValueType}_p_value`) as\n\t\t\t| 'original_p_value'\n\t\t\t| 'adjusted_p_value'\n\t\tconst columns = isDM\n\t\t\t? [\n\t\t\t\t\t{ label: elementNoun(this.settings?.elementType).one },\n\t\t\t\t\t{ label: 'Gene(s)' },\n\t\t\t\t\t{ label: effectLabel, sortable: true },\n\t\t\t\t\t{ label: pLabel, sortable: true }\n\t\t\t ]\n\t\t\t: isDAP\n\t\t\t? [\n\t\t\t\t\t{ label: 'Identifier' },\n\t\t\t\t\t{ label: 'Gene' },\n\t\t\t\t\t{ label: effectLabel, sortable: true },\n\t\t\t\t\t{ label: pLabel, sortable: true }\n\t\t\t ]\n\t\t\t: [{ label: 'Gene' }, { label: effectLabel, sortable: true }, { label: pLabel, sortable: true }]\n\t\tconst rows = dots.map(d => {\n\t\t\t// must match effectLabel above, or the column header names one number and the cell holds another\n\t\t\tconst fc = { value: roundValueAuto(this.onDeltaBeta ? (d as any).delta_beta : d.fold_change) }\n\t\t\tconst pval = { value: roundValueAuto(d[pField]) }\n\t\t\tif (isDM) {\n\t\t\t\treturn [{ value: formatPromoterLabel(d as any) }, { value: d.gene_name || '' }, fc, pval]\n\t\t\t}\n\t\t\tif (isDAP) {\n\t\t\t\treturn [{ value: d.gene_name || '' }, { value: (d as any).gene || '' }, fc, pval]\n\t\t\t}\n\t\t\treturn [{ value: d.gene_name || '' }, fc, pval]\n\t\t})\n\t\treturn { columns, rows }\n\t}\n\n\t/** Per-data-point action menu items (Violin / DMR / Box-plot). Used by\n\t * both the single-gene click flow and the multi-gene click-menu rows so\n\t * the launchers stay in lock-step. */\n\tprivate getActionMenuOpts(d: DataPointEntry): ActionMenuItem[] {\n\t\tconst termType = this.termType\n\t\tconst interactions = this.interactions\n\t\tconst all = [\n\t\t\t{\n\t\t\t\tlabel: 'Violin plot',\n\t\t\t\tisVisible: () => termType === tt.DNA_METHYLATION || termType === tt.GENE_EXPRESSION,\n\t\t\t\tonClick: async () => {\n\t\t\t\t\tif (termType === tt.DNA_METHYLATION) interactions.launchDNAMethViolin(d as any)\n\t\t\t\t\tif (termType === tt.GENE_EXPRESSION) interactions.launchViolinGeneExp(d.gene_name)\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\t/* A scan has already called every DMR: the browser shows them from the cache, beside\n\t\t\t\tthe genes and cCREs, where the region view would re-fit the chromosome to draw the same\n\t\t\t\ttrack. The region view stays for the element classes, whose hits are not yet DMRs. */\n\t\t\t\tlabel: 'Genome browser',\n\t\t\t\tisVisible: () => termType === tt.DNA_METHYLATION && !!this.viewData.scan,\n\t\t\t\tonClick: async () => {\n\t\t\t\t\tconst dm = d as DataPointEntry & { chr: string; start: number; stop: number }\n\t\t\t\t\tawait interactions.launchScanGenomeBrowser(dm, this.viewData.scan!)\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'DMR analysis',\n\t\t\t\tisVisible: () => termType === tt.DNA_METHYLATION && !this.viewData.scan,\n\t\t\t\tonClick: async () => {\n\t\t\t\t\tconst dm = d as DataPointEntry & {\n\t\t\t\t\t\tchr: string\n\t\t\t\t\t\tstart: number\n\t\t\t\t\t\tstop: number\n\t\t\t\t\t\tpromoter_id?: string\n\t\t\t\t\t\tgene_name?: string\n\t\t\t\t\t}\n\t\t\t\t\tawait interactions.launchDmr({\n\t\t\t\t\t\tchr: dm.chr,\n\t\t\t\t\t\tstart: dm.start,\n\t\t\t\t\t\tstop: dm.stop,\n\t\t\t\t\t\tpromoterId: dm.promoter_id\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Box plot',\n\t\t\t\tisVisible: () => termType === tt.GENE_EXPRESSION,\n\t\t\t\tonClick: async () => {\n\t\t\t\t\tinteractions.launchBoxPlot(d.gene_name)\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t\treturn all.filter(o => o.isVisible()).map(({ label, onClick }) => ({ label, onClick }))\n\t}\n\n\t/** Populates a `table2col` instance with the standard volcano hover rows\n\t * (gene/promoter, fold-change, original + adjusted p-values). */\n\tprivate addTooltipRows(d: DataPointEntry, table: any) {\n\t\tif (this.termType === tt.DNA_METHYLATION) {\n\t\t\tif ('promoter_id' in d)\n\t\t\t\taddTooltipRow(table, elementNoun(this.settings?.elementType).one, formatPromoterLabel(d as any))\n\t\t\tif (d.gene_name) addTooltipRow(table, 'Gene(s)', d.gene_name)\n\t\t} else if (this.termType === tt.PROTEOME_DAP) {\n\t\t\taddTooltipRow(table, 'Identifier', d.gene_name)\n\t\t\tif ('gene' in d) addTooltipRow(table, 'Gene', (d as any).gene)\n\t\t} else {\n\t\t\taddTooltipRow(table, 'Gene name', d.gene_name)\n\t\t}\n\t\t// report the effect size the plot is actually drawing -- see the onDeltaBeta getter\n\t\tif (this.onDeltaBeta) {\n\t\t\taddTooltipRow(table, '\u0394\u03B2', roundValueAuto((d as any).delta_beta))\n\t\t} else {\n\t\t\taddTooltipRow(table, 'log<sub>2</sub>(fold-change)', roundValueAuto(d.fold_change))\n\t\t}\n\t\tif (this.viewData.singlePValue) {\n\t\t\t// DAP carries a single FDR, a scan a single p; both are stored in original_p_value\n\t\t\taddTooltipRow(table, this.viewData.pValueLabel, roundValueAuto(d.original_p_value))\n\t\t} else {\n\t\t\taddTooltipRow(table, 'Original p-value', roundValueAuto(d.original_p_value))\n\t\t\tif (d.adjusted_p_value != undefined) addTooltipRow(table, 'Adjusted p-value', roundValueAuto(d.adjusted_p_value))\n\t\t}\n\t}\n}\n\nfunction addTooltipRow(table: any, text: string, value: number | string) {\n\tconst [td1, td2] = table.addRow()\n\ttd1.html(text)\n\ttd2.text(value)\n}\n\nfunction renderDataPoints(self: any) {\n\t// Visual-only circles. The cover rect added in setupOverlayInteractions\n\t// drives all hover/click \u2014 we strip pointer-events here so events fall\n\t// through to the cover. The p-value table hover-clone effect at\n\t// renderPValueTable() still finds these via selectAll('circle').\n\tself.volcanoDom.plot\n\t\t.selectAll('circle')\n\t\t.data(self.viewData.pointData)\n\t\t.enter()\n\t\t.append('circle')\n\t\t.attr('stroke', (d: DataPointEntry) => rgb(d.color).formatHex())\n\t\t.attr('stroke-opacity', (d: DataPointEntry) => (d.significant ? 0.35 : 0.2))\n\t\t// Match the rust PNG's stroke-width (1) so the overlay ring sits\n\t\t// exactly on top of the rasterized dot.\n\t\t.attr('stroke-width', 1)\n\t\t.attr('fill', self.settings.defaultHighlightColor)\n\t\t.attr('fill-opacity', (d: DataPointEntry) => (d.highlighted ? 0.9 : 0))\n\t\t.attr('cx', (d: DataPointEntry) => d.x)\n\t\t.attr('cy', (d: DataPointEntry) => d.y)\n\t\t.attr('r', (d: DataPointEntry) => d.radius)\n\t\t.style('pointer-events', 'none')\n}\n", "import type { ControlInputEntry } from '#mass/types/mass'\nimport type { VolcanoPlotConfig } from './VolcanoTypes'\nimport { getSampleNum } from './settings/defaults'\nimport { PROTEOME_DAP, DNA_METHYLATION, GENE_EXPRESSION, SINGLECELL_CELLTYPE, DMR_SCAN_ELEMENT_TYPE } from '#types'\n\n/** Handles settings the controls in the menu based on the app\n * termType.\n *\n * Add additional term type specific controls similar to\n * addGeneExpressionControlInputs(), called in\n * getVolcanoControlInputs(). Add the type to settings/Settings.ts\n *\n * If control should show for multiple but not all term types,\n * then use the getDisplayStyle arg in the control object.\n * //getDisplayStyle: () => {}\n *\n * Preferably, keep all the display (e.g. colors, sizes, etc.) controls\n * at the bottom of the list or at least together\n */\n\n/** Whether the plot's current element class is the de novo DMR scan. Read from the live plot\n * config the controls are re-rendered with, not the config captured at construction, so the scan\n * knobs appear and disappear as the class picker changes. */\nconst isScan = (plot: any) => plot?.settings?.volcano?.elementType == DMR_SCAN_ELEMENT_TYPE\n\nexport class VolcanoControlInputs {\n\tconfig: any\n\tsampleNum?: number\n\t/** term type used to determine which controls to show */\n\ttermType: string\n\t/** control inputs for controls init */\n\tinputs: ControlInputEntry[]\n\t/** Regulatory-element classes this dataset can test, from\n\t * termdbConfig.queries.dnaMethylation.elementTypes. Empty or single-entry means\n\t * there is nothing to choose between, and the element picker stays hidden. */\n\telementTypes: { key: string; label: string }[]\n\t/** Major chromosomes of the genome, for the DMR scan's region picker. */\n\tchromosomes: string[]\n\tconstructor(\n\t\tconfig: VolcanoPlotConfig,\n\t\ttermType: string,\n\t\telementTypes?: { key: string; label: string }[],\n\t\tchromosomes?: string[]\n\t) {\n\t\tthis.config = config\n\t\tif (this.config.termType == GENE_EXPRESSION) this.sampleNum = getSampleNum(config)\n\t\tthis.termType = termType\n\t\tthis.elementTypes = elementTypes || []\n\t\tthis.chromosomes = chromosomes || []\n\t\t//Populated with the default controls for the volcano plot\n\t\tthis.inputs = [\n\t\t\t{\n\t\t\t\t// DAP volcanoes threshold a single FDR (adjusted p-value); other term types\n\t\t\t\t// threshold a p-value.\n\t\t\t\tlabel: this.config.termType == PROTEOME_DAP ? 'FDR significance (-log\u2081\u2080)' : 'P value significance (-log\u2081\u2080)',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'pValue',\n\t\t\t\ttitle:\n\t\t\t\t\tthis.config.termType == PROTEOME_DAP\n\t\t\t\t\t\t? 'The FDR threshold to determine statistical significance'\n\t\t\t\t\t\t: 'The p-value threshold to determine statistical significance',\n\t\t\t\tmin: 0,\n\t\t\t\t// 5e-324 is the smallest positive number greater than 0 representable\n\t\t\t\t// in IEEE 64-bit floating point (i.e. javascripts native Number.MIN_VALUE)\n\t\t\t\t// -Math.log10(5e-324) = 323.3\n\t\t\t\tmax: 323.3,\n\t\t\t\tstep: 1\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'P value',\n\t\t\t\ttype: 'radio',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'pValueType',\n\t\t\t\ttitle: 'Toggle between original and adjusted pvalues for volcano plot',\n\t\t\t\t// DAP files carry only a single FDR, and a DMR scan a single p, so there is nothing to\n\t\t\t\t// toggle between\n\t\t\t\tgetDisplayStyle: (plot: any) => (this.config.termType == PROTEOME_DAP || isScan(plot) ? 'none' : ''),\n\t\t\t\toptions: [\n\t\t\t\t\t{ label: 'Adjusted', value: 'adjusted' },\n\t\t\t\t\t{ label: 'Original', value: 'original' }\n\t\t\t\t]\n\t\t\t},\n\t\t\t/* Hidden for differential methylation: a DM run plots and thresholds on delta-beta,\n\t\t\tso a log2 cutoff would set a limit in units the plot never shows. Every other term\n\t\t\ttype still gets it. */\n\t\t\t...(this.termType === DNA_METHYLATION\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'Fold change (log\u2082)',\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\tchartType: 'volcano',\n\t\t\t\t\t\t\tsettingsKey: 'foldChangeCutoff',\n\t\t\t\t\t\t\ttitle: 'The fold change threshold to determine biological significance',\n\t\t\t\t\t\t\tmin: -10,\n\t\t\t\t\t\t\tmax: 10\n\t\t\t\t\t\t}\n\t\t\t\t ]),\n\t\t\t{\n\t\t\t\tlabel: 'Max interactive dots',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'maxInteractiveDots',\n\t\t\t\ttitle:\n\t\t\t\t\t'Cap on the number of top-significant points the server returns as interactive overlay circles. The PNG still shows every dot.',\n\t\t\t\tmin: 0,\n\t\t\t\tmax: 20000,\n\t\t\t\tstep: 100\n\t\t\t},\n\t\t\t//Preferably, keep all the display (e.g. colors, sizes, etc.) controls\n\t\t\t//at the bottom of the list or at least together\n\t\t\t{\n\t\t\t\tlabel: 'Plot height',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'height',\n\t\t\t\ttitle: 'Height of the plot in pixels',\n\t\t\t\tmin: 300,\n\t\t\t\tmax: 1000\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Plot width',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'width',\n\t\t\t\ttitle: 'Width of the plot in pixels',\n\t\t\t\tmin: 300,\n\t\t\t\tmax: 1000\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Significant value color',\n\t\t\t\ttype: 'color',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\ttitle: 'Default color for significant data points.',\n\t\t\t\tsettingsKey: 'defaultSignColor',\n\t\t\t\tgetDisplayStyle: () => {\n\t\t\t\t\tif (this.config.termType == SINGLECELL_CELLTYPE) return 'none'\n\t\t\t\t\tconst controlColor = this.config.tw?.term?.values?.[this.config.samplelst.groups[0].name]?.color\n\t\t\t\t\tconst caseColor = this.config.tw?.term?.values?.[this.config.samplelst.groups[1].name].color\n\t\t\t\t\tif (controlColor && caseColor) return 'none'\n\t\t\t\t\telse return ''\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Non-significant value color',\n\t\t\t\ttype: 'color',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\ttitle: 'Default color for non-significant data points.',\n\t\t\t\tsettingsKey: 'defaultNonSignColor'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Highlight color',\n\t\t\t\ttype: 'color',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\ttitle: 'Default color for highlighted data points.',\n\t\t\t\tsettingsKey: 'defaultHighlightColor'\n\t\t\t}\n\t\t]\n\n\t\tthis.setVolcanoControlInputs()\n\t}\n\n\t/** Add more term type specific controls here. */\n\tsetVolcanoControlInputs() {\n\t\tthis.addGeneExpControlInputs()\n\t\tthis.addDNAMethControlInputs()\n\t\tthis.addSingleCellCTControlInputs()\n\t}\n\n\taddGeneExpControlInputs() {\n\t\tif (this.termType !== GENE_EXPRESSION) return\n\t\tconst geInputs = [\n\t\t\t{\n\t\t\t\tlabel: 'Minimum read count',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'minCount',\n\t\t\t\ttitle: 'The smallest number of reads required for a gene to be considered in the analysis',\n\t\t\t\tmin: 0,\n\t\t\t\tmax: 10000\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Minimum total read count',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'minTotalCount',\n\t\t\t\ttitle: 'The smallest total number of reads required for a gene to be considered in the analysis',\n\t\t\t\tmin: 0,\n\t\t\t\tmax: 10000\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'CPM cutoff',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'cpmCutoff',\n\t\t\t\ttitle: 'The minimum normalized expression threshold to retain only genes with sufficient expression',\n\t\t\t\tmin: 0\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Method',\n\t\t\t\ttype: 'radio',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'method',\n\t\t\t\ttitle: 'Toggle between analysis methods',\n\t\t\t\toptions: this.getMethodOptions()\n\t\t\t}\n\t\t\t// {\n\t\t\t// \tlabel: 'Rank Genes by',\n\t\t\t// \ttype: 'radio',\n\t\t\t// \tchartType: 'volcano',\n\t\t\t// \tsettingsKey: 'rankBy',\n\t\t\t// \ttitle: 'Rank genes by either the absolute value of the fold change or the variance',\n\t\t\t// \toptions: [\n\t\t\t// \t\t{ label: 'abs(Fold Change)', value: 'abs(foldChange)' },\n\t\t\t// \t\t{ label: 'Variance', value: 'variance' }\n\t\t\t// \t],\n\t\t\t// \t//TODO: will enable this feature when there is backhand support\n\t\t\t// \tgetDisplayStyle: () => 'none'\n\t\t\t// }\n\t\t]\n\n\t\tthis.inputs.splice(0, 0, ...geInputs)\n\t}\n\n\taddDNAMethControlInputs() {\n\t\tif (this.termType !== DNA_METHYLATION) return\n\t\tconst scanOnly = (plot: any) => (isScan(plot) ? '' : 'none')\n\t\tconst notScan = (plot: any) => (isScan(plot) ? 'none' : '')\n\t\tconst dmInputs: any[] = [\n\t\t\t/* Element class comes FIRST because it is categorically different from the\n\t\t\tcontrols below it: those tune how the test is run, this one changes what is\n\t\t\tbeing tested. Promoters, eQTM blocks, and cCRE classes are different genomic\n\t\t\tfeatures with different coordinates and different test counts, so switching\n\t\t\tproduces a different analysis rather than a refined one.\n\n\t\t\tHidden unless the dataset offers a genuine choice -- a single class means\n\t\t\tthere is nothing to pick, and a dataset using the legacy promoter-only config\n\t\t\tgets no new UI at all. */\n\t\t\t...(this.elementTypes.length > 1\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'Element class',\n\t\t\t\t\t\t\ttype: 'dropdown',\n\t\t\t\t\t\t\tchartType: 'volcano',\n\t\t\t\t\t\t\tsettingsKey: 'elementType',\n\t\t\t\t\t\t\toptions: this.elementTypes.map(e => ({ value: e.key, label: e.label })),\n\t\t\t\t\t\t\ttitle:\n\t\t\t\t\t\t\t\t'Which regulatory elements to test. This changes the features being analysed, not just the thresholds: promoters are TSS windows (-1500/+500 bp, the 450K array definition), cCRE promoters are the ~349 bp ENCODE promoter-like elements (the CpG-island core, no shores), eQTM blocks are runs of CpGs whose methylation correlates with a gene, and the other cCRE classes are ENCODE enhancer and CTCF annotations. Hit counts are not comparable across classes because the number of tests and the genes covered both differ. Narrow elements recover focal signal that a wide window averages away; wide windows do better on broad marks.'\n\t\t\t\t\t\t}\n\t\t\t\t ]\n\t\t\t\t: []),\n\t\t\t/* The scan's own knobs, shown only while the scan is the selected class. The chromosome\n\t\t\tpicker is a plain dropdown rather than the region search box: string2pos() turns a bare\n\t\t\t\"chr20\" into a 20kb window at the chromosome midpoint, which would silently scan 0.005% of\n\t\t\tthe target. chrM is left out -- 16.5 kb of circular DNA that cannot carry a domain. */\n\t\t\t{\n\t\t\t\tlabel: 'Scan',\n\t\t\t\ttype: 'dropdown',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'scanChromosome',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\toptions: [\n\t\t\t\t\t{ value: '', label: 'Whole genome' },\n\t\t\t\t\t...this.chromosomes.filter(c => c != 'chrM' && c != 'chrMT').map(c => ({ value: c, label: c }))\n\t\t\t\t],\n\t\t\t\ttitle:\n\t\t\t\t\t'Call DMRs de novo across the whole genome, or across one chromosome. A whole-genome scan takes about 45 seconds the first time and is cached after that.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Correct for background drift',\n\t\t\t\ttype: 'checkbox',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'backgroundCorrection',\n\t\t\t\tboxLabel: '',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\ttitle:\n\t\t\t\t\t'Score each DMR against width- and CpG-density-matched intergenic background instead of against zero, so the y axis asks \"did this region move MORE than a region like it drifts\" rather than \"did it move\". On a cohort whose whole genome shifts, the two questions have different answers -- on MMRF NSD2-high the hyper:hypo direction inverts. DMRs whose stratum holds too little background to score are counted in Statistics but not plotted. Roughly doubles the scan time.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Min CpGs per DMR',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'minCpgs',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 1000,\n\t\t\t\ttitle:\n\t\t\t\t\t'Drop DMRs called from fewer CpGs. Two-CpG calls carry the largest effect sizes and no direction (51.5% hyper on MMRF chr1, a coin flip, against 58% for 10+ CpG calls), so a \u0394\u03B2-sorted table would lead with the rows that mean least. Applied to the cached scan, so changing it redraws rather than refits.'\n\t\t\t},\n\t\t\t/* DMRcate's region-shape knobs. Unlike the CpG floor these change the fit's output, so each\n\t\t\tone refits the scan (and gets its own cache entry). */\n\t\t\t{\n\t\t\t\tlabel: 'DMR bandwidth \u03BB (bp)',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'lambda',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\tmin: 50,\n\t\t\t\tmax: 100_000,\n\t\t\t\tstep: 50,\n\t\t\t\ttitle:\n\t\t\t\t\t'DMRcate lambda. Two things at once: the width of the Gaussian kernel that smooths per-CpG statistics along the genome, and the largest gap allowed between significant CpGs chained into one DMR. Larger values merge nearby signal into fewer, wider DMRs and recover broad domains; smaller values split them into narrow, focal regions. DMRcate recommends 1000 bp for CpG-resolution data. Changing it refits the scan (about 45 seconds genome-wide).'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'DMR kernel scaling C',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'C',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\tmin: 0.5,\n\t\t\t\tmax: 50,\n\t\t\t\tstep: 0.5,\n\t\t\t\ttitle:\n\t\t\t\t\t'DMRcate C: the kernel standard deviation is lambda / C. A larger C gives a narrower kernel, so each CpG borrows evidence from fewer neighbours: sharper boundaries and more, smaller DMRs, at the cost of power in sparse regions. A smaller C smooths further. DMRcate recommends 2. Changing it refits the scan.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Per-CpG FDR cutoff',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'fdrCutoff',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\tmin: 0.0001,\n\t\t\t\tmax: 0.5,\n\t\t\t\tstep: 0.01,\n\t\t\t\ttitle:\n\t\t\t\t\t\"The FDR a CpG's smoothed statistic must pass to take part in a DMR. Raising it lets weaker CpGs join, which extends DMRs and bridges gaps between them; lowering it keeps only the strongest CpGs, giving shorter, fewer DMRs. DMRcate's default is 0.05. This is not the volcano's significance threshold, which is applied afterwards to each DMR. Changing it refits the scan.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t/* Display width for the methylome-wide profile only. The metric is the 100 kb bin and\n\t\t\t\tthe Statistics rows stay on it whatever this says -- this is here because 29,000 dots\n\t\t\t\tover 1,000 px overlap however small the dot, so the native figure reads as a band. */\n\t\t\t\tlabel: 'Profile bin width',\n\t\t\t\ttype: 'dropdown',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'profileBinBp',\n\t\t\t\tgetDisplayStyle: scanOnly,\n\t\t\t\toptions: [\n\t\t\t\t\t{ value: 100_000, label: '100 Kb (native)' },\n\t\t\t\t\t{ value: 500_000, label: '500 Kb' },\n\t\t\t\t\t{ value: 1_000_000, label: '1 Mb' },\n\t\t\t\t\t{ value: 5_000_000, label: '5 Mb' }\n\t\t\t\t],\n\t\t\t\t// a <select> hands back its value as a string; the setting is a width in bp\n\t\t\t\tprocessInput: (v: string) => Number(v),\n\t\t\t\ttitle:\n\t\t\t\t\t'How wide a bin the methylome-wide profile draws. 100 kb is the width the metric is computed and reported at (Zhou 2018); the coarser widths average neighbouring bins into one dot, weighted by the CpGs each rests on, so a genome-wide shift is legible instead of hidden in a band of overlapping dots. Display only: the Statistics rows and the fraction-of-bins-moved figures stay on the 100 kb bins, and changing this redraws the cached scan rather than refitting it. The most extreme 1,000 bins per direction stay hoverable at any width.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Min samples per group',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'minSamplesPerGroup',\n\t\t\t\ttitle: 'Minimum non-NA samples required per group for a promoter to be tested',\n\t\t\t\t// the scan resolves its own groups (3+ per group, fixed) and has no per-element NA filter\n\t\t\t\tgetDisplayStyle: notScan,\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 100\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Exclude sex chromosomes',\n\t\t\t\ttype: 'checkbox',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'excludeSexChr',\n\t\t\t\tboxLabel: '',\n\t\t\t\t// the scan honours it too: scanChromosomes() drops chrX/chrY from a whole-genome scan\n\t\t\t\ttitle:\n\t\t\t\t\t'Drop chrX and chrY (promoters, elements, or whole chromosomes from a DMR scan). Recommended for mixed-sex cohorts \u2014 X-inactivation makes chrX methylation strongly sex-dependent, so a sex-imbalanced comparison reports sex rather than the grouping variable. On a scan, autosomal DMRs are unchanged (each chromosome is fitted on its own); gene links and gene set enrichment lose the X-linked genes.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Center \u0394\u03B2 on median',\n\t\t\t\ttype: 'checkbox',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'centerDeltaBeta',\n\t\t\t\tboxLabel: '',\n\t\t\t\t// the background correction is the scan's version of this question\n\t\t\t\tgetDisplayStyle: notScan,\n\t\t\t\ttitle:\n\t\t\t\t\t'Move the \u0394\u03B2 origin to the median across all tested elements, so 0 is the typical element rather than no change. Use it to ask \"which elements moved MORE than the typical one\" \u2014 at a symmetric cutoff, a contrast whose whole distribution sits off zero clears the hyper threshold more easily than the hypo one, which skews the hyper:hypo ratio on its own. Leave it off to ask \"which elements gained or lost methylation\", since a genuine genome-wide shift is itself a result and centering would subtract it. The \u0394\u03B2 values in the table and its download are unaffected either way.'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Min \u0394\u03B2',\n\t\t\t\ttype: 'number',\n\t\t\t\tchartType: 'volcano',\n\t\t\t\tsettingsKey: 'deltaBetaCutoff',\n\t\t\t\ttitle:\n\t\t\t\t\t'Effect-size cutoff for differential methylation, applied to \u0394\u03B2. 0.1 is a 10-percentage-point change in methylation, the conventional floor for calling a region differentially methylated. Kept separate from the log\u2082 cutoff because the two are not interchangeable.',\n\t\t\t\tmin: 0,\n\t\t\t\tmax: 1,\n\t\t\t\tstep: 0.01\n\t\t\t}\n\t\t]\n\t\tthis.inputs.splice(0, 0, ...dmInputs)\n\t}\n\n\taddSingleCellCTControlInputs() {\n\t\tif (this.termType !== SINGLECELL_CELLTYPE) return\n\n\t\tconst scctInputs = []\n\n\t\tthis.inputs.splice(0, 0, ...scctInputs)\n\t}\n\n\tgetMethodOptions() {\n\t\tif (this.termType !== GENE_EXPRESSION) return\n\t\tconst settings = this.config.settings.volcano\n\t\tconst features = JSON.parse(sessionStorage.getItem('optionalFeatures') as string)\n\t\tif (features?.runDE_methods?.length) {\n\t\t\tconst opts: { label: string; value: string }[] = []\n\t\t\tfor (const m of features.runDE_methods) {\n\t\t\t\topts.push({ label: m, value: m.toLowerCase() })\n\t\t\t}\n\t\t\treturn opts\n\t\t}\n\t\tif (this.sampleNum! < settings!.sampleNumCutoff) {\n\t\t\treturn [\n\t\t\t\t{ label: 'edgeR', value: 'edgeR' },\n\t\t\t\t{ label: 'Wilcoxon', value: 'wilcoxon' },\n\t\t\t\t{ label: 'Limma', value: 'limma' }\n\t\t\t]\n\t\t} else return [{ label: 'Wilcoxon', value: 'wilcoxon' }]\n\t}\n}\n", "import type { MassState, BasePlotConfig } from '#mass/types/mass'\nimport { getCompInit, copyMerge, type RxComponent, type AppApi, type ComponentApi } from '#rx'\nimport { PlotBase } from '../PlotBase'\nimport { fillTermWrapper } from '#termsetting'\nimport { Menu, sayerror } from '#dom'\nimport { controlsInit } from '../controls'\nimport { getDefaultVolcanoSettings, validateVolcanoSettings } from './settings/defaults'\nimport type { VolcanoOpts, VolcanoDom } from './VolcanoTypes'\nimport { VolcanoModel } from './model/VolcanoModel'\nimport { VolcanoViewModel } from './viewModel/VolcanoViewModel'\nimport { VolcanoInteractions } from './interactions/VolcanoInteractions'\nimport { VolcanoPlotView } from './view/VolcanoPlotView'\nimport { VolcanoControlInputs } from './VolcanoControlInputs'\nimport { getCombinedTermFilter } from '#filter'\nimport { GENE_EXPRESSION, SINGLECELL_CELLTYPE, DNA_METHYLATION, DMR_SCAN_ELEMENT_TYPE } from '#types'\nimport { uiLabel } from '#shared'\n\n/* Below this many samples in the smaller group, the wilcoxon p-values are worth a caveat.\nrust/src/stats_functions.rs only runs the exact test when both groups are under 50 AND no value is\ntied; rna-seq counts always tie on zero, so every run takes the normal approximation. Its tie\ncorrection shrinks sigma as the tied block grows, and for a gene that is zero in nearly every sample\n-- a Y gene in a 99% female cohort, say -- that inflates z far past what the group sizes can\nactually support (observed: p = 1e-81 from 14 vs 1356, where the exact test floor is 1e-33).\n20 is the conventional floor for the normal approximation; the tie inflation is worse.\nponytail: gated on group size alone, which catches the case that motivated it. Catching a\ntie-dominated gene in an otherwise well-sized cohort needs per-gene tie counts back from rust. */\nconst MIN_WILCOXON_GROUP_SIZE = 20\n\nexport class Volcano extends PlotBase implements RxComponent {\n\tstatic type = 'volcano'\n\ttype: string\n\tcomponents: { controls: any }\n\tdom: VolcanoDom\n\tinteractions?: VolcanoInteractions\n\tmodel!: VolcanoModel\n\tview!: VolcanoPlotView\n\ttermType: string\n\n\tconstructor(opts: VolcanoOpts, api: ComponentApi) {\n\t\tsuper(opts, api)\n\t\tif (this.opts.parentId) this.parentId = this.opts.parentId\n\t\tthis.type = Volcano.type\n\t\tthis.components = {\n\t\t\tcontrols: {}\n\t\t}\n\n\t\tthis.termType = opts.termType\n\t\tconst holder = opts.holder\n\t\t\t.classed('sjpp-volcano-main', true)\n\t\t\t.attr('data-testid', `sjpp-volcano-main-${opts.termType}`)\n\t\t//Either allow a node to be passed or create a new div\n\t\tconst controls = typeof opts.controls == 'object' ? opts.controls : holder || (holder as any).append('div')\n\t\tconst error = opts.holder\n\t\t\t.append('div')\n\t\t\t.attr('id', 'sjpp-volcano-error')\n\t\t\t.attr('data-testid', `sjpp-volcano-error-${opts.termType}`)\n\t\t\t.style('opacity', 0.75) as any\n\t\tthis.dom = {\n\t\t\tholder,\n\t\t\tcontrols,\n\t\t\terror,\n\t\t\twait: holder\n\t\t\t\t.append('div')\n\t\t\t\t.attr('id', 'sjpp-volcano-wait')\n\t\t\t\t.attr('data-testid', `sjpp-volcano-wait-${opts.termType}`)\n\t\t\t\t.style('opacity', 0.75)\n\t\t\t\t.style('padding', '20px')\n\t\t\t\t.text('Loading...') as any,\n\t\t\ttip: new Menu({ padding: '' }),\n\t\t\tactionsTip: new Menu({ padding: '' })\n\t\t}\n\t}\n\n\tgetState(appState: MassState) {\n\t\tconst config: any = appState.plots.find((p: BasePlotConfig) => p.id === this.id)\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t`No plot with id='${this.id}' found. Did you set this.id before this.api = getComponentApi(this)?`\n\t\t\t)\n\t\t}\n\t\tconst parentConfig: any = this.parentId && appState.plots.find(p => p.id === this.parentId)\n\t\tconst termfilter = getCombinedTermFilter(appState, config.filter || parentConfig?.filter)\n\n\t\treturn {\n\t\t\tconfig: Object.assign({}, config, {\n\t\t\t\tsettings: {\n\t\t\t\t\tvolcano: config.settings.volcano\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttermfilter\n\t\t}\n\t}\n\n\tasync setControls() {\n\t\tconst plotConfig = this.app.getState().plots.find((p: any) => p.id === this.id)\n\t\tconst controls = new VolcanoControlInputs(\n\t\t\tplotConfig,\n\t\t\tthis.termType,\n\t\t\tthis.app.vocabApi.termdbConfig?.queries?.dnaMethylation?.elementTypes,\n\t\t\tthis.app.opts.genome?.majorchrorder\n\t\t)\n\n\t\tthis.components.controls = await controlsInit({\n\t\t\tapp: this.app,\n\t\t\tid: this.id,\n\t\t\tholder: this.dom.controls.style('display', 'inline-block'),\n\t\t\tinputs: controls.inputs\n\t\t})\n\n\t\tthis.components.controls.on('downloadClick.volcano', () => this.interactions!.download(this.termType))\n\t\tif (plotConfig.chartType == 'differentialAnalysis')\n\t\t\tthis.components.controls.on('helpClick.differentialAnalysis', () =>\n\t\t\t\t//Opens the page for the differential analysis wiki\n\t\t\t\t//Can't put in parent as DA does not have a controls component\n\t\t\t\twindow.open('https://github.com/stjude/proteinpaint/wiki/Differential-analysis')\n\t\t\t)\n\t}\n\n\tasync init() {\n\t\tthis.interactions = new VolcanoInteractions(this.app, this.id, this.dom)\n\t\tthis.model = new VolcanoModel(this, this.termType)\n\t\tthis.view = new VolcanoPlotView(this.dom, this.interactions, this.termType)\n\t\tawait this.setControls()\n\t}\n\n\tasync main() {\n\t\tif (!this.interactions) throw new Error('Volcano Interactions not initialized')\n\t\tif (!this.model) throw new Error('Volcano Model not initialized')\n\t\tif (!this.view) throw new Error('Volcano View not initialized')\n\n\t\tconst config = structuredClone(this.state.config)\n\t\t//TODO: Fix this to use parentId instead\n\t\tif (config.chartType != this.type && config.childType != this.type) return\n\n\t\tconst settings = config.settings.volcano\n\t\ttry {\n\t\t\t/* A genome scan is ~45 seconds of server work with nothing on the wire until it finishes;\n\t\t\ta bare \"Loading...\" is indistinguishable from a hung request. */\n\t\t\tthis.dom.wait.text(\n\t\t\t\tsettings.elementType == DMR_SCAN_ELEMENT_TYPE\n\t\t\t\t\t? 'Scanning for DMRs... a whole-genome scan takes about 45 seconds the first time, and is cached after that.'\n\t\t\t\t\t: 'Loading...'\n\t\t\t)\n\t\t\t//Only show Loading for data requests that take longer than 500ms\n\t\t\tconst showWait = setTimeout(() => {\n\t\t\t\tthis.dom.wait.style('display', 'block')\n\t\t\t}, 500)\n\n\t\t\t/** Fetch data */\n\t\t\tconst response = await this.model.getData(config, settings)\n\t\t\tthis.dom.error.text('')\n\t\t\tif (!response || response.error || !response.data || !response.data.volcanoPng || !response.data.totalRows) {\n\t\t\t\tconst msg = response?.error || 'No data returned from server'\n\t\t\t\tif (response?.code === 'CACHE_BUSY') {\n\t\t\t\t\tif (window.confirm(msg)) this.main()\n\t\t\t\t} else sayerror(this.dom.error, msg)\n\t\t\t\tclearTimeout(showWait)\n\t\t\t\tthis.dom.wait.style('display', 'none')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t/** Format response into an object for rendering */\n\t\t\tconst viewModel = new VolcanoViewModel(config, response, settings)\n\t\t\t//Pass table data for downloading\n\t\t\tthis.interactions.pValueTableData = viewModel.viewData.pValueTableData\n\t\t\tthis.interactions.data = response.data.dots\n\t\t\t//pre-cap count, so the download knows whether the on-screen rows are a subset\n\t\t\tthis.interactions.totalSignificantRows = response.data.totalSignificantRows\n\t\t\t//groups, sample sizes and settings, so a downloaded table records how it was produced\n\t\t\tthis.interactions.provenance = viewModel.viewData.provenance\n\t\t\t/* Lets the download write every significant row while the interactive table keeps only\n\t\t\tthe most-significant maxInteractiveDots (the dot overlay does not scale past that).\n\t\t\tmaxInteractiveDots null tells renderVolcano to keep them all; it is not part of the DA\n\t\t\tcache key, so this re-uses the cached analysis and only re-renders. Rebuilt on each\n\t\t\tresponse so it closes over the current config/settings rather than a stale pair. */\n\t\t\tthis.interactions.fetchAllRows = async () => {\n\t\t\t\tconst full = await new VolcanoModel(this, this.termType).getData(config, {\n\t\t\t\t\t...settings,\n\t\t\t\t\tmaxInteractiveDots: null\n\t\t\t\t})\n\t\t\t\tif (!full || full.error || !full.data?.dots) throw new Error(full?.error || 'no rows returned')\n\t\t\t\treturn new VolcanoViewModel(config, full, settings).viewData.pValueTableData\n\t\t\t}\n\n\t\t\t/** Render formatted data */\n\t\t\tthis.view.render(settings, viewModel.viewData)\n\n\t\t\t/* Non-fatal notes on how to read the result. Both can apply at once, so they are collected\n\t\t\tand shown together rather than one overwriting the other. */\n\t\t\tconst notes: string[] = []\n\t\t\tif (!response.data.dots.length) notes.push('No points passed the significance thresholds.')\n\t\t\tconst smallestGroup = Math.min(response.sample_size1, response.sample_size2)\n\t\t\tif (settings.method == 'wilcoxon' && smallestGroup < MIN_WILCOXON_GROUP_SIZE) {\n\t\t\t\t// gdc users are the most likely readers of this sentence, and gdc calls them cases\n\t\t\t\tconst samplesLabel = uiLabel(this.app.vocabApi.termdbConfig?.uiLabels, 'samples', 'samples')\n\t\t\t\tnotes.push(\n\t\t\t\t\t`The smaller group has ${smallestGroup.toLocaleString()} ${samplesLabel}. Wilcoxon p-values are ` +\n\t\t\t\t\t\t`approximated here, and a gene that is zero in most ${samplesLabel} can be assigned a p-value far ` +\n\t\t\t\t\t\t`smaller than its group sizes can support. Rank these results by fold change rather than by ` +\n\t\t\t\t\t\t`p-value magnitude, and do not compare the p-values against another analysis.`\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (notes.length) this.dom.error.text(notes.join(' ')).style('color', '#555')\n\n\t\t\tclearTimeout(showWait)\n\t\t\tthis.dom.wait.style('display', 'none')\n\t\t} catch (e: any) {\n\t\t\tif (e instanceof Error) console.error(e.message || e)\n\t\t\telse if (e.stack) console.log(e.stack)\n\t\t\tthrow e\n\t\t}\n\t}\n}\n\nexport const volcanoInit = getCompInit(Volcano)\nexport const componentInit = volcanoInit\n\nexport async function getPlotConfig(opts: any, app: AppApi) {\n\tif (!opts.termType) throw new Error('.termType is required')\n\n\tconst config = {\n\t\tsettings: {\n\t\t\t// app is passed through so the defaults can read the dataset's preferred starting\n\t\t\t// element class from termdbConfig; opts alone does not carry it\n\t\t\tvolcano: getDefaultVolcanoSettings(opts.overrides, { ...opts, app })\n\t\t},\n\t\thighlightedData: opts.highlightedData || [],\n\t\ttermType: opts.termType\n\t}\n\n\t//Define Gene Expression and DNA Methylation config. Both run confounder-adjusted\n\t//two-group analyses off a samplelst, so both need their confounder tws filled here\n\t//-- otherwise a session rehydrated with confounders already set carries unfilled tws.\n\tif (opts.termType == GENE_EXPRESSION || opts.termType == DNA_METHYLATION) {\n\t\tif (opts.confounderTws) {\n\t\t\ttry {\n\t\t\t\tfor (const tw of opts.confounderTws) {\n\t\t\t\t\tawait fillTermWrapper(tw, app.vocabApi)\n\t\t\t\t}\n\t\t\t} catch (e: any) {\n\t\t\t\tconsole.error(e.message || e)\n\t\t\t\tthrow new Error(`Volcano getPlotConfig() failed to fill confounder term wrappers: ${e}`)\n\t\t\t}\n\t\t}\n\t\tObject.assign(config, {\n\t\t\tconfounderTws: opts.confounderTws || [],\n\t\t\tsamplelst: opts.samplelst\n\t\t})\n\t}\n\n\t//Define Single Cell Cell Type config\n\tif (opts.termType == SINGLECELL_CELLTYPE) {\n\t\tObject.assign(config, {\n\t\t\t//TODO: Fix this logic\n\t\t\tsample: opts.experimentID || opts.sample || opts.samples?.[0]?.experiments[0]?.experimentID,\n\t\t\ttermId: app.vocabApi.termdbConfig.queries.singleCell.DEgenes.termId,\n\t\t\t//TODO: 'Cluster' is a fallback for development\n\t\t\t//Should require opts.categoryName in the future\n\t\t\tcategoryName: opts.categoryName || 'Cluster'\n\t\t})\n\t}\n\n\t//Validate user submitted unavailable/inappropriate settings\n\tvalidateVolcanoSettings(config, opts)\n\n\treturn copyMerge(config, opts)\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }