@sjcrh/proteinpaint-client 2.182.0 → 2.183.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 (1004) hide show
  1. package/dist/2dmaf-6ZTETSC5.js +1371 -0
  2. package/dist/AIProjectAdmin-ZT3XKBBT.js +830 -0
  3. package/dist/AIProjectAdmin-ZT3XKBBT.js.map +7 -0
  4. package/dist/AppHeader-U7SJPIBS.js +833 -0
  5. package/dist/BoxPlot-QGHLZ67V.js +1217 -0
  6. package/dist/BoxPlot-QGHLZ67V.js.map +7 -0
  7. package/dist/CorrelationVolcano-7SE4CTBW.js +617 -0
  8. package/dist/DE-PZ7RHPBS.js +93 -0
  9. package/dist/DEinput-UZEQIU2V.js +297 -0
  10. package/dist/DifferentialAnalysis-L6BOEYVO.js +238 -0
  11. package/dist/Disco-6FDT6KRM.js +3235 -0
  12. package/dist/Disco-6FDT6KRM.js.map +7 -0
  13. package/dist/Disco.UI-HKOUAD4P.js +242 -0
  14. package/dist/DmrPlot-3R24PTXP.js +640 -0
  15. package/dist/GB-SZVYZASR.js +1125 -0
  16. package/dist/HicApp-SEEJETVE.js +2248 -0
  17. package/dist/NumBinaryEditor-SDQFJ3FW.js +268 -0
  18. package/dist/NumBinaryEditor.unit.spec-76ZZXTYC.js +284 -0
  19. package/dist/NumContEditor-G75O4YZE.js +105 -0
  20. package/dist/NumContEditor.unit.spec-BFUZRBPL.js +167 -0
  21. package/dist/NumCustomBinEditor-ILTPHCEF.js +36 -0
  22. package/dist/NumCustomBinEditor.unit.spec-GFIYV55V.js +282 -0
  23. package/dist/NumDiscreteEditor-5K3OKUOE.js +177 -0
  24. package/dist/NumDiscreteEditor.unit.spec-NZ4KWPFK.js +200 -0
  25. package/dist/NumRegularBinEditor-7ZJ2MEMY.js +36 -0
  26. package/dist/NumRegularBinEditor.unit.spec-QGVJET65.js +225 -0
  27. package/dist/NumSplineEditor-KE4UPODZ.js +190 -0
  28. package/dist/NumSplineEditor.unit.spec-YQOOZA7S.js +197 -0
  29. package/dist/NumericDensity-RL42P4QC.js +36 -0
  30. package/dist/NumericDensity.unit.spec-Y6RMTYC7.js +219 -0
  31. package/dist/NumericHandler-4QIX324I.js +37 -0
  32. package/dist/NumericHandler.unit.spec-T6F5QYP6.js +217 -0
  33. package/dist/RunChart2-ASGCKKER.js +756 -0
  34. package/dist/RunChart2-ASGCKKER.js.map +7 -0
  35. package/dist/SC-H2YCKSBH.js +682 -0
  36. package/dist/SC-H2YCKSBH.js.map +7 -0
  37. package/dist/Volcano-QBYYJYVW.js +1185 -0
  38. package/dist/Volcano-QBYYJYVW.js.map +7 -0
  39. package/dist/WSIViewer-NDHWFVAB.js +47974 -0
  40. package/dist/WSIViewer-NDHWFVAB.js.map +7 -0
  41. package/dist/WsiSamplesPlot-CXGWPCDL.js +163 -0
  42. package/dist/adSandbox-DE4VRO4Z.js +36 -0
  43. package/dist/alphaGenome-FSIGC5ZT.js +173 -0
  44. package/dist/app-KZGKWQMU.js +47 -0
  45. package/dist/app-MQRJ7FVL.js +35 -0
  46. package/dist/app.js +22 -22
  47. package/dist/bam-BDWTA4O3.js +857 -0
  48. package/dist/barchart-4Q6LVJY4.js +45 -0
  49. package/dist/barchart.data-EXENRVMU.js +22 -0
  50. package/dist/barchart.events-XRGND6I7.js +45 -0
  51. package/dist/barchart.integration.spec-VQITP4YH.js +1675 -0
  52. package/dist/bars.renderer-S7A7I6BQ.js +12 -0
  53. package/dist/block-2MABX5QO.js +6200 -0
  54. package/dist/block-2MABX5QO.js.map +7 -0
  55. package/dist/block.init-NCNSE3HD.js +36 -0
  56. package/dist/block.mds.expressionrank-JYZARS7T.js +357 -0
  57. package/dist/block.mds.geneboxplot-FD2MCIHV.js +826 -0
  58. package/dist/block.mds.junction-LOHVQBIU.js +1543 -0
  59. package/dist/block.mds.svcnv-Z7SAYPQL.js +6799 -0
  60. package/dist/block.svg-LNJOKQNN.js +162 -0
  61. package/dist/block.tk.aicheck-IXCMMAGV.js +281 -0
  62. package/dist/block.tk.ase-WYRYFP6N.js +363 -0
  63. package/dist/block.tk.bam-EIVBNGAL.js +1904 -0
  64. package/dist/block.tk.bedgraphdot-3FHLNCU7.js +382 -0
  65. package/dist/block.tk.bigwig.ui-YDQU5PC4.js +209 -0
  66. package/dist/block.tk.hicstraw-S3ROL3CV.js +821 -0
  67. package/dist/block.tk.junction-DL7RNWX3.js +2362 -0
  68. package/dist/block.tk.junction.textmatrixui-Z6I7IEDY.js +197 -0
  69. package/dist/block.tk.ld-XHVU6L56.js +97 -0
  70. package/dist/block.tk.menu-FPLAEEFY.js +1027 -0
  71. package/dist/block.tk.pgv-6ZZ2QGNO.js +942 -0
  72. package/dist/brainImaging-VSOOMITW.js +421 -0
  73. package/dist/chat-LW23PIG5.js +148 -0
  74. package/dist/chunk-2A2KM5DU.js +117 -0
  75. package/dist/chunk-2A2KM5DU.js.map +7 -0
  76. package/dist/chunk-2K5DSRBJ.js +84 -0
  77. package/dist/chunk-2K5DSRBJ.js.map +7 -0
  78. package/dist/chunk-2LULD7RN.js +31 -0
  79. package/dist/chunk-36DYWBU7.js +514 -0
  80. package/dist/chunk-36DYWBU7.js.map +7 -0
  81. package/dist/chunk-3AGB6HL4.js +158 -0
  82. package/dist/chunk-3AVDNIDN.js +55 -0
  83. package/dist/chunk-3DCABJHB.js +381 -0
  84. package/dist/chunk-3JMB3OSC.js +102 -0
  85. package/dist/chunk-3UEMY45Y.js +215 -0
  86. package/dist/chunk-4RR4KPRJ.js +1205 -0
  87. package/dist/chunk-5HCB4HNL.js +147 -0
  88. package/dist/chunk-5RFB7TYT.js +92 -0
  89. package/dist/chunk-5UMPBVA6.js +534 -0
  90. package/dist/chunk-6C2SBTLR.js +407 -0
  91. package/dist/chunk-6ITDJ5UR.js +261 -0
  92. package/dist/chunk-6ITDJ5UR.js.map +7 -0
  93. package/dist/chunk-6LAE5AVA.js +13624 -0
  94. package/dist/chunk-77ZJGPK2.js +289 -0
  95. package/dist/chunk-77ZJGPK2.js.map +7 -0
  96. package/dist/chunk-7FKIAQ4K.js +17 -0
  97. package/dist/chunk-7FKIAQ4K.js.map +7 -0
  98. package/dist/chunk-7RN3L2BX.js +1788 -0
  99. package/dist/chunk-7RN3L2BX.js.map +7 -0
  100. package/dist/chunk-7VV43ICF.js +272 -0
  101. package/dist/chunk-A6TQGNDQ.js +421 -0
  102. package/dist/chunk-A6TQGNDQ.js.map +7 -0
  103. package/dist/chunk-A742TQD2.js +615 -0
  104. package/dist/chunk-A7E3JZ5P.js +56 -0
  105. package/dist/chunk-A7E3JZ5P.js.map +7 -0
  106. package/dist/chunk-AFLFPYJI.js +480 -0
  107. package/dist/chunk-APOHXHKH.js +526 -0
  108. package/dist/chunk-APOHXHKH.js.map +7 -0
  109. package/dist/chunk-AQ4OP4GR.js +39 -0
  110. package/dist/chunk-BAY47D5E.js +226 -0
  111. package/dist/chunk-CFHKYLDY.js +26 -0
  112. package/dist/chunk-CTAKX5CT.js +129 -0
  113. package/dist/chunk-CVBQWXLH.js +455 -0
  114. package/dist/chunk-CVBQWXLH.js.map +7 -0
  115. package/dist/chunk-D4QFQQWJ.js +170 -0
  116. package/dist/chunk-DGMK7SXX.js +203 -0
  117. package/dist/chunk-DNCSPTOQ.js +446 -0
  118. package/dist/chunk-DTDQKGIQ.js +2672 -0
  119. package/dist/chunk-E4NVHKWD.js +142 -0
  120. package/dist/chunk-E6KEZENR.js +4207 -0
  121. package/dist/chunk-EY2KBPHJ.js +261 -0
  122. package/dist/chunk-EY2KBPHJ.js.map +7 -0
  123. package/dist/chunk-FRBYOOWT.js +229 -0
  124. package/dist/chunk-FVWCYGJL.js +121 -0
  125. package/dist/chunk-HWHG63LH.js +148 -0
  126. package/dist/chunk-HWHG63LH.js.map +7 -0
  127. package/dist/chunk-HYZG6OPC.js +467 -0
  128. package/dist/chunk-HYZG6OPC.js.map +7 -0
  129. package/dist/chunk-I4IKRKYJ.js +2815 -0
  130. package/dist/chunk-IEQSUAIO.js +6364 -0
  131. package/dist/chunk-IET6P5MV.js +335 -0
  132. package/dist/chunk-IET6P5MV.js.map +7 -0
  133. package/dist/chunk-JMPSZMDD.js +52 -0
  134. package/dist/chunk-JXOL73PT.js +2784 -0
  135. package/dist/chunk-K62XUHA4.js +100 -0
  136. package/dist/chunk-KQMEJUWI.js +815 -0
  137. package/dist/chunk-L4QG7XZE.js +46 -0
  138. package/dist/chunk-L4QG7XZE.js.map +7 -0
  139. package/dist/chunk-L4YGMXLX.js +37 -0
  140. package/dist/chunk-L4YGMXLX.js.map +7 -0
  141. package/dist/chunk-LI7FE335.js +371 -0
  142. package/dist/chunk-M7W2GYSM.js +4961 -0
  143. package/dist/chunk-M7W2GYSM.js.map +7 -0
  144. package/dist/chunk-MV6O4I2B.js +441 -0
  145. package/dist/chunk-MXNSW55L.js +148 -0
  146. package/dist/chunk-NB7NLFGZ.js +228 -0
  147. package/dist/chunk-NGGWK6HX.js +302 -0
  148. package/dist/chunk-OGGFS66K.js +1087 -0
  149. package/dist/chunk-OSM7YS23.js +276 -0
  150. package/dist/chunk-OSM7YS23.js.map +7 -0
  151. package/dist/chunk-OXJ2TWDO.js +20644 -0
  152. package/dist/chunk-OXJ2TWDO.js.map +7 -0
  153. package/dist/chunk-Q7PYFSNU.js +107 -0
  154. package/dist/chunk-QMI222IJ.js +386 -0
  155. package/dist/chunk-QRIRWDIW.js +252 -0
  156. package/dist/chunk-R6L6NVEC.js +14 -0
  157. package/dist/chunk-RLTLYKHO.js +34 -0
  158. package/dist/chunk-S5ZI6N2I.js +293 -0
  159. package/dist/chunk-S7T7OZC7.js +158 -0
  160. package/dist/chunk-SEQLC4AD.js +177 -0
  161. package/dist/chunk-TEZLFSOV.js +54 -0
  162. package/dist/chunk-TFI7ZZJG.js +50 -0
  163. package/dist/chunk-TFI7ZZJG.js.map +7 -0
  164. package/dist/chunk-TV74I3Y5.js +43 -0
  165. package/dist/chunk-TV74I3Y5.js.map +7 -0
  166. package/dist/chunk-UEMTP6ZC.js +824 -0
  167. package/dist/chunk-UJU3Q7QJ.js +119 -0
  168. package/dist/chunk-V245THQC.js +2370 -0
  169. package/dist/chunk-V245THQC.js.map +7 -0
  170. package/dist/chunk-V6DLLX4N.js +176 -0
  171. package/dist/chunk-V6DLLX4N.js.map +7 -0
  172. package/dist/chunk-VIPMLSZP.js +217 -0
  173. package/dist/chunk-VQPS4SXU.js +97 -0
  174. package/dist/chunk-VQPS4SXU.js.map +7 -0
  175. package/dist/chunk-VUUZJANK.js +1150 -0
  176. package/dist/chunk-VYIO7T6J.js +82 -0
  177. package/dist/chunk-VYIO7T6J.js.map +7 -0
  178. package/dist/chunk-W345H42C.js +273 -0
  179. package/dist/chunk-W345H42C.js.map +7 -0
  180. package/dist/chunk-WGHO2NCP.js +205 -0
  181. package/dist/chunk-WGL6FIUE.js +330 -0
  182. package/dist/chunk-WGL6FIUE.js.map +7 -0
  183. package/dist/chunk-WPHOEG56.js +194 -0
  184. package/dist/chunk-WS5XVKPJ.js +470 -0
  185. package/dist/chunk-X6URQAFD.js +1271 -0
  186. package/dist/chunk-XYFDBYOY.js +1658 -0
  187. package/dist/chunk-XYFDBYOY.js.map +7 -0
  188. package/dist/chunk-Y6RCKITI.js +1155 -0
  189. package/dist/chunk-Y6RCKITI.js.map +7 -0
  190. package/dist/chunk-YALAQWX4.js +368 -0
  191. package/dist/chunk-YK5NFMHR.js +269 -0
  192. package/dist/chunk-YK5NFMHR.js.map +7 -0
  193. package/dist/chunk-YY4CKQJ6.js +95 -0
  194. package/dist/chunk-Z3KV6SC2.js +629 -0
  195. package/dist/chunk-ZGT4XP5J.js +1426 -0
  196. package/dist/chunk-ZGT4XP5J.js.map +7 -0
  197. package/dist/condition-JKQIRMMW.js +330 -0
  198. package/dist/controls-324AGOZG.js +39 -0
  199. package/dist/controls.config-TA4NNARU.js +37 -0
  200. package/dist/correlation-3Z36TKC2.js +96 -0
  201. package/dist/cuminc-4DY2CSZF.js +1147 -0
  202. package/dist/cuminc.integration.spec-SFQPLMSF.js +676 -0
  203. package/dist/customdata.inputui-IKGPEBXV.js +287 -0
  204. package/dist/customdata.inputui-IKGPEBXV.js.map +7 -0
  205. package/dist/dataDownload-3AE2N7KI.js +328 -0
  206. package/dist/dataDownload.integration.spec-DKOT6BJP.js +191 -0
  207. package/dist/databrowser.ui-ATODRS5P.js +419 -0
  208. package/dist/dictionary-WHDZBW5M.js +109 -0
  209. package/dist/dictionary-WHDZBW5M.js.map +7 -0
  210. package/dist/dnaMethylation-TVA5YMOR.js +36 -0
  211. package/dist/dnaMethylation.integration.spec-JTWQR6XY.js +165 -0
  212. package/dist/dnaMethylation.integration.spec-JTWQR6XY.js.map +7 -0
  213. package/dist/e2pca-KHVDNFEZ.js +348 -0
  214. package/dist/ep-B5GAAMNM.js +1254 -0
  215. package/dist/expclust.gdc.spec-EDPX7V6K.js +305 -0
  216. package/dist/facet-ZCSXKXIO.js +519 -0
  217. package/dist/geneExpClustering-ERNCMAED.js +246 -0
  218. package/dist/geneExpression-HUOXWETT.js +36 -0
  219. package/dist/geneExpression-X2KXJPND.js +312 -0
  220. package/dist/geneExpression.unit.spec-5QQB4ISW.js +100 -0
  221. package/dist/geneORA-B5UK77KL.js +276 -0
  222. package/dist/geneVariant-7MGUAIZ6.js +39 -0
  223. package/dist/geneVariant-FK3KZJ2K.js +37 -0
  224. package/dist/geneVariant.integration.spec-C6TYWKIC.js +196 -0
  225. package/dist/genefusion.ui-VKAINMY7.js +249 -0
  226. package/dist/geneset-673KAZVX.js +194 -0
  227. package/dist/genomeBrowser.spec-T6TQCJ3O.js +279 -0
  228. package/dist/grin2-376BD4XY.js +1554 -0
  229. package/dist/grin2-OALS75LC.js +1031 -0
  230. package/dist/gsea-25LD2LGP.js +45 -0
  231. package/dist/hierCluster-7KU3K52V.js +58 -0
  232. package/dist/hierCluster-M5VVWKQK.js +62 -0
  233. package/dist/hierCluster.config-EDO3SH2P.js +38 -0
  234. package/dist/hierCluster.integration.spec-UOX7J2XD.js +374 -0
  235. package/dist/hierCluster.interactivity-FEFZDXML.js +52 -0
  236. package/dist/hierCluster.renderers-A6MEGO2B.js +21 -0
  237. package/dist/imagePlot-FPXZ2H5Z.js +139 -0
  238. package/dist/importPlot-VKWPSFEK.js +8 -0
  239. package/dist/isoformExpression-2R2TOB6P.js +38 -0
  240. package/dist/isoformExpression.unit.spec-ZKFKOPKT.js +206 -0
  241. package/dist/isoformExpression.unit.spec-ZKFKOPKT.js.map +7 -0
  242. package/dist/jspdf.es.min-FC3BCETM.js +40 -0
  243. package/dist/launch.adhoc-242RS6DW.js +40 -0
  244. package/dist/leftlabel.sample-OJW3AE64.js +257 -0
  245. package/dist/legacyDataset-PBCPC5I7.js +119 -0
  246. package/dist/lollipop-TRQ3LK7Y.js +166 -0
  247. package/dist/maf-ZBOLN2FE.js +450 -0
  248. package/dist/maftimeline-GVX7NJP7.js +591 -0
  249. package/dist/matrix-73KRNXLM.js +57 -0
  250. package/dist/matrix-US3OXYRY.js +62 -0
  251. package/dist/matrix.cells-U7AQNEBP.js +28 -0
  252. package/dist/matrix.config-Q57D7C3F.js +39 -0
  253. package/dist/matrix.controls-AWXDRSWP.js +37 -0
  254. package/dist/matrix.data-EEIY6AO4.js +25 -0
  255. package/dist/matrix.dom-6QL3AJMW.js +11 -0
  256. package/dist/matrix.groups-CUB6UWC5.js +26 -0
  257. package/dist/matrix.integration.spec-PQH67KRM.js +3070 -0
  258. package/dist/matrix.interactivity-JW4AXAWO.js +40 -0
  259. package/dist/matrix.layout-I56KRVCO.js +42 -0
  260. package/dist/matrix.legend-42LQGAGX.js +22 -0
  261. package/dist/matrix.renderers-IX3FCNBK.js +36 -0
  262. package/dist/matrix.serieses-4B2WB526.js +21 -0
  263. package/dist/matrix.sort-BJACNR7G.js +27 -0
  264. package/dist/matrix.sort.unit.spec-3KKDKIPY.js +470 -0
  265. package/dist/matrix.sorterUi-W6XFYZY2.js +18 -0
  266. package/dist/matrix.sorterUi.unit.spec-CMJ7EBIW.js +340 -0
  267. package/dist/mavb-ROAE6WYA.js +730 -0
  268. package/dist/mds.fimo-UGK5OWCF.js +516 -0
  269. package/dist/mds.samplescatterplot-5KFUAYSB.js +1548 -0
  270. package/dist/mds.survivalplot-2EVNZUX5.js +481 -0
  271. package/dist/oncomatrix-UGFXSXQJ.js +293 -0
  272. package/dist/oncomatrix.spec-FEP7BR7L.js +446 -0
  273. package/dist/plot.2dvaf-WXGLWCOC.js +375 -0
  274. package/dist/plot.app-IZAFRTBU.js +39 -0
  275. package/dist/plot.barplot-Z4VWOPFJ.js +100 -0
  276. package/dist/plot.boxplot-QU2KZSB7.js +150 -0
  277. package/dist/plot.brainImaging-U643YIK7.js +51 -0
  278. package/dist/plot.disco-3BV6YEBC.js +101 -0
  279. package/dist/plot.disco-3BV6YEBC.js.map +7 -0
  280. package/dist/plot.dzi-DWXPOOQE.js +33 -0
  281. package/dist/plot.ssgq-GXB2GZO3.js +137 -0
  282. package/dist/plot.vaf2cov-EKRIADPB.js +257 -0
  283. package/dist/plot.wsi-E2LLE6HI.js +36 -0
  284. package/dist/polar-MZLIUXHO.js +184 -0
  285. package/dist/polar2-IUVHNQM4.js +226 -0
  286. package/dist/profile.spec-JRW6KYUI.js +78 -0
  287. package/dist/profileBarchart-N7HJMYZ5.js +265 -0
  288. package/dist/profileForms-Q5TPGPQP.js +438 -0
  289. package/dist/profilePlot-TXTUYDVE.js +52 -0
  290. package/dist/profileRadar-ICEASI7W.js +261 -0
  291. package/dist/profileRadarFacility-NFMRNJYX.js +261 -0
  292. package/dist/profileRadarFacility-NFMRNJYX.js.map +7 -0
  293. package/dist/proteinView-K3JFNORQ.js +633 -0
  294. package/dist/proteinView-K3JFNORQ.js.map +7 -0
  295. package/dist/proteomeAbundance-DE4NVBCN.js +21 -0
  296. package/dist/proteomeAbundance-LTB3QR3G.js +63 -0
  297. package/dist/qualitative-DFGWQURY.js +41 -0
  298. package/dist/regression-TTQTAEGD.js +54 -0
  299. package/dist/regression.inputs-2LU2XRGC.js +46 -0
  300. package/dist/regression.inputs.term-G57GL57T.js +46 -0
  301. package/dist/regression.inputs.values.table-JSEM3PXL.js +43 -0
  302. package/dist/regression.integration.spec-XJQJAIC3.js +782 -0
  303. package/dist/regression.integration.spec-XJQJAIC3.js.map +7 -0
  304. package/dist/regression.results-3YNM6LLQ.js +38 -0
  305. package/dist/regression.spec-S6WFCPSW.js +706 -0
  306. package/dist/report-YRAV4MY4.js +220 -0
  307. package/dist/sampleScatter.spec-MBJ4XNTX.js +200 -0
  308. package/dist/sampleView-IUR3ZEN7.js +46 -0
  309. package/dist/samplelst-C2NBFGH6.js +109 -0
  310. package/dist/samplematrix-AOK2HHSB.js +2196 -0
  311. package/dist/sc-XT3Z5XJI.js +84 -0
  312. package/dist/scatter-SAHKZRFL.js +800 -0
  313. package/dist/scatter.integration.spec-6KRDNHHH.js +1194 -0
  314. package/dist/scatter.integration.spec-6KRDNHHH.js.map +7 -0
  315. package/dist/selectGenomeWithTklst-2YVZ4JWV.js +132 -0
  316. package/dist/singleCellCellType-NFN5GQJM.js +36 -0
  317. package/dist/singleCellCellType.unit.spec-CR4IJ4DA.js +158 -0
  318. package/dist/singleCellCellType.unit.spec-CR4IJ4DA.js.map +7 -0
  319. package/dist/singleCellGeneExpression-7AQGLXTR.js +36 -0
  320. package/dist/singleCellGeneExpression.unit.spec-QYNWSV2G.js +151 -0
  321. package/dist/singleCellGeneExpression.unit.spec-QYNWSV2G.js.map +7 -0
  322. package/dist/singleCellPlot-IWFEG44C.js +51 -0
  323. package/dist/singlecell-3QNV4OMZ.js +1570 -0
  324. package/dist/singlecell-EATPLH66.js +84 -0
  325. package/dist/snp-UP7WL7WG.js +36 -0
  326. package/dist/snp.unit.spec-Y5NWQ442.js +174 -0
  327. package/dist/snplocus-WAQK2AZG.js +206 -0
  328. package/dist/spliceevent.a53ss.diagram-FFK27UIB.js +149 -0
  329. package/dist/spliceevent.exonskip.diagram-KWEF2OZJ.js +275 -0
  330. package/dist/spliceevent.noeventdiagram-PU4TI7OM.js +458 -0
  331. package/dist/ssGSEA-N6QOAVLW.js +36 -0
  332. package/dist/ssGSEA.unit.spec-KQBNZNNP.js +86 -0
  333. package/dist/summarizeCnvGeneexp-NWX4M6LZ.js +161 -0
  334. package/dist/summarizeCnvGeneexp-NWX4M6LZ.js.map +7 -0
  335. package/dist/summarizeGeneexpSurvival-N5VTE2G6.js +106 -0
  336. package/dist/summarizeGeneexpSurvival-N5VTE2G6.js.map +7 -0
  337. package/dist/summarizeMutationCnv-VV7CVAA7.js +162 -0
  338. package/dist/summarizeMutationCnv-VV7CVAA7.js.map +7 -0
  339. package/dist/summarizeMutationDiagnosis-5RHSG7L6.js +38 -0
  340. package/dist/summarizeMutationSurvival-22YYXGS5.js +97 -0
  341. package/dist/summary-P3WIKJS7.js +47 -0
  342. package/dist/summary.integration.spec-ULGRPICW.js +412 -0
  343. package/dist/summaryInput-IH4EVNF5.js +218 -0
  344. package/dist/sunburst-VJJ3UVYC.js +282 -0
  345. package/dist/sunburst-VJJ3UVYC.js.map +7 -0
  346. package/dist/survival-2ZE3N62A.js +44 -0
  347. package/dist/survival-ASCLKIII.js +56 -0
  348. package/dist/survival.integration.spec-C5YXOY77.js +787 -0
  349. package/dist/svg2pdf.es.min-CYTPRWNB.js +3157 -0
  350. package/dist/svgraph-AYR2UPNK.js +1385 -0
  351. package/dist/svmr-MOMW5DNY.js +3840 -0
  352. package/dist/table-PQB6KCEY.js +198 -0
  353. package/dist/termCollection-5AY2AWT4.js +36 -0
  354. package/dist/termCollection-OQMUUTW6.js +177 -0
  355. package/dist/termCollection.unit.spec-BUAXYIJK.js +206 -0
  356. package/dist/tk-EJLFFA5H.js +44 -0
  357. package/dist/tp.ui-WUW6A7KP.js +1457 -0
  358. package/dist/tvs.density-HSVPDDGA.js +18 -0
  359. package/dist/tvs.dt-MVJXQMNU.js +37 -0
  360. package/dist/tvs.dtcnv.categorical-FIIDWVK7.js +38 -0
  361. package/dist/tvs.dtcnv.continuous-JPQU3JA2.js +70 -0
  362. package/dist/tvs.dtfusion-BW35GOQM.js +38 -0
  363. package/dist/tvs.dtsnvindel-AEMFZ4EH.js +38 -0
  364. package/dist/tvs.dtsv-JHTU7UFD.js +38 -0
  365. package/dist/tvs.numeric-ICUGA4WY.js +21 -0
  366. package/dist/tvs.samplelst-VD2NFFFS.js +102 -0
  367. package/dist/tvs.termCollection-IKE5Q74D.js +151 -0
  368. package/dist/violin-DPMJLHQG.js +44 -0
  369. package/dist/violin.integration.spec-A4PNR4ES.js +1423 -0
  370. package/dist/violin.integration.spec-A4PNR4ES.js.map +7 -0
  371. package/dist/violin.interactivity-TS4DYUE5.js +36 -0
  372. package/dist/violin.renderer-53L4PXUT.js +38 -0
  373. package/dist/vocabulary-4MPFHKYC.js +39 -0
  374. package/package.json +3 -3
  375. package/dist/2dmaf-SLBAWGPG.js +0 -1371
  376. package/dist/AIProjectAdmin-6SH5X3AF.js +0 -830
  377. package/dist/AIProjectAdmin-6SH5X3AF.js.map +0 -7
  378. package/dist/AppHeader-MVYNRMC7.js +0 -833
  379. package/dist/BoxPlot-HLGWW3IK.js +0 -1295
  380. package/dist/BoxPlot-HLGWW3IK.js.map +0 -7
  381. package/dist/CorrelationVolcano-TZCYC3NI.js +0 -617
  382. package/dist/DE-2J2SK5UT.js +0 -93
  383. package/dist/DEinput-QM3GOQHM.js +0 -297
  384. package/dist/DifferentialAnalysis-DS7CQOT6.js +0 -238
  385. package/dist/Disco-U5I6NJUT.js +0 -3199
  386. package/dist/Disco-U5I6NJUT.js.map +0 -7
  387. package/dist/Disco.UI-J2B7GGEZ.js +0 -242
  388. package/dist/DmrPlot-D5W76QPY.js +0 -640
  389. package/dist/GB-LM5SGUG4.js +0 -1125
  390. package/dist/HicApp-YNBGAGKM.js +0 -2248
  391. package/dist/NumBinaryEditor-4QA5DQJT.js +0 -268
  392. package/dist/NumBinaryEditor.unit.spec-YWSIFTOJ.js +0 -284
  393. package/dist/NumContEditor-ZPLVZFLH.js +0 -105
  394. package/dist/NumContEditor.unit.spec-NBCFOCOX.js +0 -167
  395. package/dist/NumCustomBinEditor-TXEYRVPL.js +0 -36
  396. package/dist/NumCustomBinEditor.unit.spec-SQM63H4B.js +0 -282
  397. package/dist/NumDiscreteEditor-6C4OWX62.js +0 -177
  398. package/dist/NumDiscreteEditor.unit.spec-4HC4AGAM.js +0 -200
  399. package/dist/NumRegularBinEditor-VQAS3OXK.js +0 -36
  400. package/dist/NumRegularBinEditor.unit.spec-RGVEPB3Z.js +0 -225
  401. package/dist/NumSplineEditor-SXOJICHU.js +0 -190
  402. package/dist/NumSplineEditor.unit.spec-HF5E6ANH.js +0 -197
  403. package/dist/NumericDensity-LMLPMOSE.js +0 -36
  404. package/dist/NumericDensity.unit.spec-3ZI5EVON.js +0 -219
  405. package/dist/NumericHandler-Q6F6ANOS.js +0 -37
  406. package/dist/NumericHandler.unit.spec-E6Z5HUNZ.js +0 -217
  407. package/dist/RunChart2-XSNWNAIL.js +0 -756
  408. package/dist/RunChart2-XSNWNAIL.js.map +0 -7
  409. package/dist/SC-RA46YM57.js +0 -733
  410. package/dist/SC-RA46YM57.js.map +0 -7
  411. package/dist/Volcano-75UDYPVB.js +0 -1187
  412. package/dist/Volcano-75UDYPVB.js.map +0 -7
  413. package/dist/WSIViewer-GYUUXCSJ.js +0 -47933
  414. package/dist/WSIViewer-GYUUXCSJ.js.map +0 -7
  415. package/dist/WsiSamplesPlot-KMI5S2EL.js +0 -163
  416. package/dist/adSandbox-JTK5XEQL.js +0 -36
  417. package/dist/alphaGenome-JRAV6WIY.js +0 -173
  418. package/dist/app-JKDZL23V.js +0 -35
  419. package/dist/app-OEARXM6E.js +0 -47
  420. package/dist/bam-CYEPLBK4.js +0 -857
  421. package/dist/barchart-GG5UFDG4.js +0 -45
  422. package/dist/barchart.data-KXA66FAL.js +0 -22
  423. package/dist/barchart.events-P2USOIR7.js +0 -45
  424. package/dist/barchart.integration.spec-5QSPQQLJ.js +0 -1675
  425. package/dist/bars.renderer-T5R3UIBW.js +0 -12
  426. package/dist/block-6DVPQBSH.js +0 -6200
  427. package/dist/block-6DVPQBSH.js.map +0 -7
  428. package/dist/block.init-ZHX6DFWF.js +0 -36
  429. package/dist/block.mds.expressionrank-YMGYXXYT.js +0 -357
  430. package/dist/block.mds.geneboxplot-IAILQYX4.js +0 -826
  431. package/dist/block.mds.junction-BRNFNQMU.js +0 -1543
  432. package/dist/block.mds.svcnv-OHKC7YPO.js +0 -6799
  433. package/dist/block.svg-PNGK45HW.js +0 -162
  434. package/dist/block.tk.aicheck-SCIOJ4WN.js +0 -281
  435. package/dist/block.tk.ase-BABJ73GG.js +0 -363
  436. package/dist/block.tk.bam-LZWJ5BCQ.js +0 -1904
  437. package/dist/block.tk.bedgraphdot-7NQLC3XJ.js +0 -382
  438. package/dist/block.tk.bigwig.ui-VNY4SFD5.js +0 -209
  439. package/dist/block.tk.hicstraw-36A7VDRM.js +0 -821
  440. package/dist/block.tk.junction-D373YEMK.js +0 -2362
  441. package/dist/block.tk.junction.textmatrixui-FFII7J3X.js +0 -197
  442. package/dist/block.tk.ld-XGB6KMDO.js +0 -97
  443. package/dist/block.tk.menu-PEZANZBZ.js +0 -1027
  444. package/dist/block.tk.pgv-MU5BPTT2.js +0 -942
  445. package/dist/brainImaging-LVJON47N.js +0 -421
  446. package/dist/chat-5FDIAQJ4.js +0 -148
  447. package/dist/chunk-22NJUYET.js +0 -281
  448. package/dist/chunk-22NJUYET.js.map +0 -7
  449. package/dist/chunk-2J3566TA.js +0 -215
  450. package/dist/chunk-2OSEZCWZ.js +0 -205
  451. package/dist/chunk-2SRMRC6L.js +0 -421
  452. package/dist/chunk-2SRMRC6L.js.map +0 -7
  453. package/dist/chunk-5OHXYXLD.js +0 -46
  454. package/dist/chunk-5OHXYXLD.js.map +0 -7
  455. package/dist/chunk-6MSCYO7K.js +0 -119
  456. package/dist/chunk-75EBDB7G.js +0 -21
  457. package/dist/chunk-75EBDB7G.js.map +0 -7
  458. package/dist/chunk-7A7NMCQ3.js +0 -534
  459. package/dist/chunk-7FEHI46K.js +0 -20456
  460. package/dist/chunk-7FEHI46K.js.map +0 -7
  461. package/dist/chunk-AETE4F7R.js +0 -252
  462. package/dist/chunk-AZYDW5T7.js +0 -441
  463. package/dist/chunk-B6HCIAM3.js +0 -34
  464. package/dist/chunk-BEWDIM6H.js +0 -42
  465. package/dist/chunk-BEWDIM6H.js.map +0 -7
  466. package/dist/chunk-CCIZJAXB.js +0 -2815
  467. package/dist/chunk-DHZL3FBC.js +0 -107
  468. package/dist/chunk-DONWY7TP.js +0 -39
  469. package/dist/chunk-DVDDXOWT.js +0 -815
  470. package/dist/chunk-E6DRQJJT.js +0 -480
  471. package/dist/chunk-ESKU6LNC.js +0 -36
  472. package/dist/chunk-ESKU6LNC.js.map +0 -7
  473. package/dist/chunk-F6V4AYWP.js +0 -177
  474. package/dist/chunk-FBAJTPBU.js +0 -302
  475. package/dist/chunk-FGMPKWT5.js +0 -371
  476. package/dist/chunk-FK4MYVW2.js +0 -261
  477. package/dist/chunk-FK4MYVW2.js.map +0 -7
  478. package/dist/chunk-FMBJ4SKC.js +0 -98
  479. package/dist/chunk-FMBJ4SKC.js.map +0 -7
  480. package/dist/chunk-FOEZG4VX.js +0 -505
  481. package/dist/chunk-FOEZG4VX.js.map +0 -7
  482. package/dist/chunk-FQRLSKJC.js +0 -226
  483. package/dist/chunk-G6ELKVBG.js +0 -629
  484. package/dist/chunk-GKK3CZ6H.js +0 -4207
  485. package/dist/chunk-GO5SIPFE.js +0 -194
  486. package/dist/chunk-GPOECA3V.js +0 -386
  487. package/dist/chunk-GTOY3JJO.js +0 -288
  488. package/dist/chunk-GTOY3JJO.js.map +0 -7
  489. package/dist/chunk-GW7DHJYH.js +0 -439
  490. package/dist/chunk-GW7DHJYH.js.map +0 -7
  491. package/dist/chunk-H2D7EVUA.js +0 -158
  492. package/dist/chunk-H2K5KZP7.js +0 -95
  493. package/dist/chunk-H5XFH3FV.js +0 -153
  494. package/dist/chunk-H5XFH3FV.js.map +0 -7
  495. package/dist/chunk-HAMDFQIX.js +0 -228
  496. package/dist/chunk-HH4QLSTK.js +0 -4952
  497. package/dist/chunk-HH4QLSTK.js.map +0 -7
  498. package/dist/chunk-IBTPGSYI.js +0 -526
  499. package/dist/chunk-IBTPGSYI.js.map +0 -7
  500. package/dist/chunk-IC7SUXJD.js +0 -82
  501. package/dist/chunk-IC7SUXJD.js.map +0 -7
  502. package/dist/chunk-IGEQI6MR.js +0 -1561
  503. package/dist/chunk-IGEQI6MR.js.map +0 -7
  504. package/dist/chunk-IIRU6VK2.js +0 -2672
  505. package/dist/chunk-ILF2GKBY.js +0 -1205
  506. package/dist/chunk-IP4T477W.js +0 -92
  507. package/dist/chunk-IQIXGTQV.js +0 -84
  508. package/dist/chunk-IQIXGTQV.js.map +0 -7
  509. package/dist/chunk-IXT4U5CE.js +0 -91
  510. package/dist/chunk-IXT4U5CE.js.map +0 -7
  511. package/dist/chunk-JHOGX5VE.js +0 -272
  512. package/dist/chunk-JOXUBWN3.js +0 -381
  513. package/dist/chunk-K57RR3FD.js +0 -142
  514. package/dist/chunk-K6JLCMVL.js +0 -129
  515. package/dist/chunk-KISFQDQE.js +0 -258
  516. package/dist/chunk-KISFQDQE.js.map +0 -7
  517. package/dist/chunk-KSFSM46X.js +0 -100
  518. package/dist/chunk-KVG7FTTK.js +0 -470
  519. package/dist/chunk-LEDPPLQK.js +0 -158
  520. package/dist/chunk-LUTT3MBZ.js +0 -1150
  521. package/dist/chunk-MDL2HG3N.js +0 -257
  522. package/dist/chunk-MDL2HG3N.js.map +0 -7
  523. package/dist/chunk-MNRYCG2S.js +0 -1271
  524. package/dist/chunk-MPJHDHBA.js +0 -2784
  525. package/dist/chunk-MXI3NXRB.js +0 -407
  526. package/dist/chunk-O4PXELXF.js +0 -615
  527. package/dist/chunk-ORPCSG6T.js +0 -14
  528. package/dist/chunk-OUKDZKSZ.js +0 -334
  529. package/dist/chunk-OUKDZKSZ.js.map +0 -7
  530. package/dist/chunk-P5HLYAHP.js +0 -1087
  531. package/dist/chunk-PIACSJPH.js +0 -148
  532. package/dist/chunk-PQABAAEZ.js +0 -31
  533. package/dist/chunk-PSMDCZET.js +0 -46
  534. package/dist/chunk-PSMDCZET.js.map +0 -7
  535. package/dist/chunk-RFIVPTMS.js +0 -217
  536. package/dist/chunk-RSU37SVQ.js +0 -54
  537. package/dist/chunk-RTC4U4PH.js +0 -2327
  538. package/dist/chunk-RTC4U4PH.js.map +0 -7
  539. package/dist/chunk-RZ5JP44H.js +0 -276
  540. package/dist/chunk-RZ5JP44H.js.map +0 -7
  541. package/dist/chunk-SPAIFVM2.js +0 -1155
  542. package/dist/chunk-SPAIFVM2.js.map +0 -7
  543. package/dist/chunk-T2HYA2KL.js +0 -55
  544. package/dist/chunk-TCPU43TU.js +0 -1741
  545. package/dist/chunk-TCPU43TU.js.map +0 -7
  546. package/dist/chunk-TE3DK3A6.js +0 -147
  547. package/dist/chunk-TIQPSXFJ.js +0 -237
  548. package/dist/chunk-TIQPSXFJ.js.map +0 -7
  549. package/dist/chunk-TN5GSG34.js +0 -26
  550. package/dist/chunk-UBGTQMOO.js +0 -52
  551. package/dist/chunk-UBS5UVIY.js +0 -13624
  552. package/dist/chunk-UE5ZYM63.js +0 -48
  553. package/dist/chunk-UE5ZYM63.js.map +0 -7
  554. package/dist/chunk-UQACPOCM.js +0 -102
  555. package/dist/chunk-UR3C4SCH.js +0 -446
  556. package/dist/chunk-UWX7W22M.js +0 -121
  557. package/dist/chunk-VJ37HKM6.js +0 -368
  558. package/dist/chunk-VLTDUJRM.js +0 -293
  559. package/dist/chunk-W6UUEAEP.js +0 -6364
  560. package/dist/chunk-X6UPDFDX.js +0 -229
  561. package/dist/chunk-XD6BFNMR.js +0 -172
  562. package/dist/chunk-XD6BFNMR.js.map +0 -7
  563. package/dist/chunk-XDI4UFCZ.js +0 -467
  564. package/dist/chunk-XDI4UFCZ.js.map +0 -7
  565. package/dist/chunk-XOBD3EAM.js +0 -1425
  566. package/dist/chunk-XOBD3EAM.js.map +0 -7
  567. package/dist/chunk-Y3TDC7NU.js +0 -170
  568. package/dist/chunk-YOTWMCT5.js +0 -824
  569. package/dist/chunk-YUMPQ3CJ.js +0 -203
  570. package/dist/condition-VHP2L4GM.js +0 -330
  571. package/dist/controls-N5Q7U7JR.js +0 -39
  572. package/dist/controls.config-NJMW4SLR.js +0 -37
  573. package/dist/correlation-3LDASF5I.js +0 -96
  574. package/dist/cuminc-UWJ23W6C.js +0 -1147
  575. package/dist/cuminc.integration.spec-OZYYET3W.js +0 -676
  576. package/dist/customdata.inputui-2FVCVSE4.js +0 -285
  577. package/dist/customdata.inputui-2FVCVSE4.js.map +0 -7
  578. package/dist/dataDownload-4S4PE5HX.js +0 -328
  579. package/dist/dataDownload.integration.spec-B57LEKFZ.js +0 -191
  580. package/dist/databrowser.ui-N6GHEQ2P.js +0 -419
  581. package/dist/dictionary-UP46QRYZ.js +0 -98
  582. package/dist/dictionary-UP46QRYZ.js.map +0 -7
  583. package/dist/dnaMethylation-BOGAUAWA.js +0 -36
  584. package/dist/dnaMethylation.integration.spec-UAHBJSSJ.js +0 -179
  585. package/dist/dnaMethylation.integration.spec-UAHBJSSJ.js.map +0 -7
  586. package/dist/e2pca-L5EBQJNP.js +0 -348
  587. package/dist/ep-Z67ORKUX.js +0 -1254
  588. package/dist/expclust.gdc.spec-SP7VOL64.js +0 -305
  589. package/dist/facet-HDB4VDGU.js +0 -519
  590. package/dist/geneExpClustering-6ZPOLTDJ.js +0 -246
  591. package/dist/geneExpression-T6YIG4XQ.js +0 -312
  592. package/dist/geneExpression-T7QUHV5S.js +0 -36
  593. package/dist/geneExpression.unit.spec-DO52L5IB.js +0 -100
  594. package/dist/geneORA-KOUDUWUO.js +0 -276
  595. package/dist/geneVariant-FVR76F6I.js +0 -39
  596. package/dist/geneVariant-I5QUITKG.js +0 -37
  597. package/dist/geneVariant.integration.spec-D4IRM7B5.js +0 -196
  598. package/dist/genefusion.ui-35IYSZD7.js +0 -249
  599. package/dist/geneset-7ZHJ5KWK.js +0 -194
  600. package/dist/genomeBrowser.spec-VXASVLNH.js +0 -279
  601. package/dist/grin2-7NM56COO.js +0 -1554
  602. package/dist/grin2-IY26UUQI.js +0 -1031
  603. package/dist/gsea-TORO46C6.js +0 -45
  604. package/dist/hierCluster-3BKEGW6P.js +0 -58
  605. package/dist/hierCluster-HM3LOM6V.js +0 -62
  606. package/dist/hierCluster.config-LDO5IGQ5.js +0 -38
  607. package/dist/hierCluster.integration.spec-XO5R6CQT.js +0 -374
  608. package/dist/hierCluster.interactivity-NVQ6262K.js +0 -52
  609. package/dist/hierCluster.renderers-SWPPNBLU.js +0 -21
  610. package/dist/imagePlot-V4WLAPV6.js +0 -139
  611. package/dist/importPlot-NZKQEOX4.js +0 -8
  612. package/dist/isoformExpression-TIZBIGNL.js +0 -38
  613. package/dist/isoformExpression.unit.spec-WHH5LPFG.js +0 -124
  614. package/dist/isoformExpression.unit.spec-WHH5LPFG.js.map +0 -7
  615. package/dist/jspdf.es.min-DO4YWL2R.js +0 -40
  616. package/dist/launch.adhoc-JYEN42NM.js +0 -40
  617. package/dist/leftlabel.sample-43DL3J3H.js +0 -257
  618. package/dist/legacyDataset-QRSNRVUA.js +0 -119
  619. package/dist/lollipop-NMWZ4FVF.js +0 -166
  620. package/dist/maf-DS3EOVGV.js +0 -450
  621. package/dist/maftimeline-ZB2753S7.js +0 -591
  622. package/dist/matrix-RCGQWQ3C.js +0 -57
  623. package/dist/matrix-WTTEK4FT.js +0 -62
  624. package/dist/matrix.cells-UO5ASQ35.js +0 -28
  625. package/dist/matrix.config-3UQAT3QR.js +0 -39
  626. package/dist/matrix.controls-PRZ77K5L.js +0 -37
  627. package/dist/matrix.data-4W73RQ3H.js +0 -25
  628. package/dist/matrix.dom-IZFFS4RQ.js +0 -11
  629. package/dist/matrix.groups-5VMPI7SA.js +0 -26
  630. package/dist/matrix.integration.spec-2F5LDLC2.js +0 -3070
  631. package/dist/matrix.interactivity-MIPZ6ELV.js +0 -40
  632. package/dist/matrix.layout-EO5LVYRO.js +0 -42
  633. package/dist/matrix.legend-QBFBFEUG.js +0 -22
  634. package/dist/matrix.renderers-ERJXVCQL.js +0 -36
  635. package/dist/matrix.serieses-E23EPXHA.js +0 -21
  636. package/dist/matrix.sort-I4UGMEXR.js +0 -27
  637. package/dist/matrix.sort.unit.spec-CRGF6CSE.js +0 -470
  638. package/dist/matrix.sorterUi-YLSYTYLE.js +0 -18
  639. package/dist/matrix.sorterUi.unit.spec-ENG3ICOO.js +0 -340
  640. package/dist/mavb-5WR7OJHI.js +0 -730
  641. package/dist/mds.fimo-3ZRH7BBJ.js +0 -516
  642. package/dist/mds.samplescatterplot-RPXR2FVK.js +0 -1548
  643. package/dist/mds.survivalplot-WSSMYUZD.js +0 -481
  644. package/dist/oncomatrix-JKYPUJQR.js +0 -293
  645. package/dist/oncomatrix.spec-OEGU4DYK.js +0 -446
  646. package/dist/plot.2dvaf-ZGARLQNK.js +0 -375
  647. package/dist/plot.app-TKUJH3LK.js +0 -39
  648. package/dist/plot.barplot-FEIPGDZ2.js +0 -100
  649. package/dist/plot.boxplot-6RASUMZB.js +0 -150
  650. package/dist/plot.brainImaging-ZJPFWX2W.js +0 -51
  651. package/dist/plot.disco-2KTKB3XX.js +0 -101
  652. package/dist/plot.disco-2KTKB3XX.js.map +0 -7
  653. package/dist/plot.dzi-PC34YI6Y.js +0 -33
  654. package/dist/plot.ssgq-Z4UNJKWO.js +0 -137
  655. package/dist/plot.vaf2cov-NZ4WULKT.js +0 -257
  656. package/dist/plot.wsi-YYXFAZWY.js +0 -36
  657. package/dist/polar-X2GPIBLB.js +0 -184
  658. package/dist/polar2-TZ553QQH.js +0 -226
  659. package/dist/profile.spec-VB6VMFLY.js +0 -78
  660. package/dist/profileBarchart-SKJSTC7B.js +0 -265
  661. package/dist/profileForms-RLOGSMAQ.js +0 -438
  662. package/dist/profilePlot-267ZS3RG.js +0 -52
  663. package/dist/profileRadar-KGOBHCSF.js +0 -261
  664. package/dist/profileRadarFacility-MCJKSHUM.js +0 -261
  665. package/dist/profileRadarFacility-MCJKSHUM.js.map +0 -7
  666. package/dist/proteomeAbundance-JUYAYO5I.js +0 -63
  667. package/dist/proteomeAbundance-PGHZSVAF.js +0 -19
  668. package/dist/qualitative-3IECKKJM.js +0 -41
  669. package/dist/regression-J6FFRPXN.js +0 -54
  670. package/dist/regression.inputs-T7LWBSYZ.js +0 -46
  671. package/dist/regression.inputs.term-TT7PNX6G.js +0 -46
  672. package/dist/regression.inputs.values.table-SHFUNKCS.js +0 -43
  673. package/dist/regression.integration.spec-QKHMJTHA.js +0 -784
  674. package/dist/regression.integration.spec-QKHMJTHA.js.map +0 -7
  675. package/dist/regression.results-D4WX6VIV.js +0 -38
  676. package/dist/regression.spec-7SW55L7X.js +0 -706
  677. package/dist/report-QYOZ4BRF.js +0 -220
  678. package/dist/sampleScatter.spec-JCHFMGNF.js +0 -200
  679. package/dist/sampleView-7RPKNAZC.js +0 -46
  680. package/dist/samplelst-4WNPHZVG.js +0 -109
  681. package/dist/samplematrix-CG52DSXJ.js +0 -2196
  682. package/dist/sc-OJSWILSA.js +0 -84
  683. package/dist/scatter-LG2RMMEC.js +0 -800
  684. package/dist/scatter.integration.spec-QPANYTKW.js +0 -1194
  685. package/dist/scatter.integration.spec-QPANYTKW.js.map +0 -7
  686. package/dist/selectGenomeWithTklst-QXRVE6N4.js +0 -132
  687. package/dist/singleCellCellType-XBSRL33U.js +0 -36
  688. package/dist/singleCellCellType.unit.spec-YZX4CSXA.js +0 -177
  689. package/dist/singleCellCellType.unit.spec-YZX4CSXA.js.map +0 -7
  690. package/dist/singleCellGeneExpression-64ECP62X.js +0 -36
  691. package/dist/singleCellGeneExpression.unit.spec-CFHFXMA6.js +0 -163
  692. package/dist/singleCellGeneExpression.unit.spec-CFHFXMA6.js.map +0 -7
  693. package/dist/singleCellPlot-E5F62JY6.js +0 -51
  694. package/dist/singlecell-FCY5EOUV.js +0 -84
  695. package/dist/singlecell-S7B5V7NK.js +0 -1570
  696. package/dist/snp-ACKX4GRX.js +0 -36
  697. package/dist/snp.unit.spec-QBGHKKUD.js +0 -174
  698. package/dist/snplocus-7EUOW7J7.js +0 -206
  699. package/dist/spliceevent.a53ss.diagram-ALQZA35Z.js +0 -149
  700. package/dist/spliceevent.exonskip.diagram-UF7WJA5R.js +0 -275
  701. package/dist/spliceevent.noeventdiagram-4HPGRNRR.js +0 -458
  702. package/dist/ssGSEA-FDRBBBLJ.js +0 -36
  703. package/dist/ssGSEA.unit.spec-EZEOWJVV.js +0 -86
  704. package/dist/summarizeCnvGeneexp-FTL2MGAJ.js +0 -158
  705. package/dist/summarizeCnvGeneexp-FTL2MGAJ.js.map +0 -7
  706. package/dist/summarizeGeneexpSurvival-DDIF4UW6.js +0 -105
  707. package/dist/summarizeGeneexpSurvival-DDIF4UW6.js.map +0 -7
  708. package/dist/summarizeMutationCnv-L3GL5YDY.js +0 -159
  709. package/dist/summarizeMutationCnv-L3GL5YDY.js.map +0 -7
  710. package/dist/summarizeMutationDiagnosis-LALOJTHV.js +0 -38
  711. package/dist/summarizeMutationSurvival-TSNTSOBZ.js +0 -97
  712. package/dist/summary-YRHVS64T.js +0 -47
  713. package/dist/summary.integration.spec-766YQLQA.js +0 -412
  714. package/dist/summaryInput-VQ2X6GSX.js +0 -218
  715. package/dist/sunburst-XFOONS6K.js +0 -282
  716. package/dist/sunburst-XFOONS6K.js.map +0 -7
  717. package/dist/survival-FQXZH2MM.js +0 -44
  718. package/dist/survival-TVA3ZWVP.js +0 -56
  719. package/dist/survival.integration.spec-WFIOPD6A.js +0 -787
  720. package/dist/svg2pdf.es.min-EZ4UYRSH.js +0 -3157
  721. package/dist/svgraph-4BFBO7EL.js +0 -1385
  722. package/dist/svmr-ML7GAIIA.js +0 -3840
  723. package/dist/table-SMLMUWPP.js +0 -198
  724. package/dist/termCollection-22CPTISZ.js +0 -36
  725. package/dist/termCollection-EE6AOIVA.js +0 -177
  726. package/dist/termCollection.unit.spec-4DIW3CJ3.js +0 -206
  727. package/dist/tk-ITZCKOQ5.js +0 -44
  728. package/dist/tp.ui-R6HVKCBC.js +0 -1457
  729. package/dist/tvs.density-AQ5GD437.js +0 -18
  730. package/dist/tvs.dt-2263TBEJ.js +0 -37
  731. package/dist/tvs.dtcnv.categorical-TRRHL33N.js +0 -38
  732. package/dist/tvs.dtcnv.continuous-GREYNF52.js +0 -70
  733. package/dist/tvs.dtfusion-XOX46L3M.js +0 -38
  734. package/dist/tvs.dtsnvindel-IDMXT53F.js +0 -38
  735. package/dist/tvs.dtsv-ZDWFYH2C.js +0 -38
  736. package/dist/tvs.numeric-ZN2R7BH3.js +0 -21
  737. package/dist/tvs.samplelst-GAP76HRH.js +0 -102
  738. package/dist/tvs.termCollection-GQ65UKSI.js +0 -151
  739. package/dist/violin-JGDL62YA.js +0 -44
  740. package/dist/violin.integration.spec-W4NN7LBY.js +0 -1417
  741. package/dist/violin.integration.spec-W4NN7LBY.js.map +0 -7
  742. package/dist/violin.interactivity-H4RP4K5U.js +0 -36
  743. package/dist/violin.renderer-QPHLACDC.js +0 -38
  744. package/dist/vocabulary-7JACY4J2.js +0 -39
  745. /package/dist/{2dmaf-SLBAWGPG.js.map → 2dmaf-6ZTETSC5.js.map} +0 -0
  746. /package/dist/{AppHeader-MVYNRMC7.js.map → AppHeader-U7SJPIBS.js.map} +0 -0
  747. /package/dist/{CorrelationVolcano-TZCYC3NI.js.map → CorrelationVolcano-7SE4CTBW.js.map} +0 -0
  748. /package/dist/{DE-2J2SK5UT.js.map → DE-PZ7RHPBS.js.map} +0 -0
  749. /package/dist/{DEinput-QM3GOQHM.js.map → DEinput-UZEQIU2V.js.map} +0 -0
  750. /package/dist/{DifferentialAnalysis-DS7CQOT6.js.map → DifferentialAnalysis-L6BOEYVO.js.map} +0 -0
  751. /package/dist/{Disco.UI-J2B7GGEZ.js.map → Disco.UI-HKOUAD4P.js.map} +0 -0
  752. /package/dist/{DmrPlot-D5W76QPY.js.map → DmrPlot-3R24PTXP.js.map} +0 -0
  753. /package/dist/{GB-LM5SGUG4.js.map → GB-SZVYZASR.js.map} +0 -0
  754. /package/dist/{HicApp-YNBGAGKM.js.map → HicApp-SEEJETVE.js.map} +0 -0
  755. /package/dist/{NumBinaryEditor-4QA5DQJT.js.map → NumBinaryEditor-SDQFJ3FW.js.map} +0 -0
  756. /package/dist/{NumBinaryEditor.unit.spec-YWSIFTOJ.js.map → NumBinaryEditor.unit.spec-76ZZXTYC.js.map} +0 -0
  757. /package/dist/{NumContEditor-ZPLVZFLH.js.map → NumContEditor-G75O4YZE.js.map} +0 -0
  758. /package/dist/{NumContEditor.unit.spec-NBCFOCOX.js.map → NumContEditor.unit.spec-BFUZRBPL.js.map} +0 -0
  759. /package/dist/{NumCustomBinEditor-TXEYRVPL.js.map → NumCustomBinEditor-ILTPHCEF.js.map} +0 -0
  760. /package/dist/{NumCustomBinEditor.unit.spec-SQM63H4B.js.map → NumCustomBinEditor.unit.spec-GFIYV55V.js.map} +0 -0
  761. /package/dist/{NumDiscreteEditor-6C4OWX62.js.map → NumDiscreteEditor-5K3OKUOE.js.map} +0 -0
  762. /package/dist/{NumDiscreteEditor.unit.spec-4HC4AGAM.js.map → NumDiscreteEditor.unit.spec-NZ4KWPFK.js.map} +0 -0
  763. /package/dist/{NumRegularBinEditor-VQAS3OXK.js.map → NumRegularBinEditor-7ZJ2MEMY.js.map} +0 -0
  764. /package/dist/{NumRegularBinEditor.unit.spec-RGVEPB3Z.js.map → NumRegularBinEditor.unit.spec-QGVJET65.js.map} +0 -0
  765. /package/dist/{NumSplineEditor-SXOJICHU.js.map → NumSplineEditor-KE4UPODZ.js.map} +0 -0
  766. /package/dist/{NumSplineEditor.unit.spec-HF5E6ANH.js.map → NumSplineEditor.unit.spec-YQOOZA7S.js.map} +0 -0
  767. /package/dist/{NumericDensity-LMLPMOSE.js.map → NumericDensity-RL42P4QC.js.map} +0 -0
  768. /package/dist/{NumericDensity.unit.spec-3ZI5EVON.js.map → NumericDensity.unit.spec-Y6RMTYC7.js.map} +0 -0
  769. /package/dist/{NumericHandler-Q6F6ANOS.js.map → NumericHandler-4QIX324I.js.map} +0 -0
  770. /package/dist/{NumericHandler.unit.spec-E6Z5HUNZ.js.map → NumericHandler.unit.spec-T6F5QYP6.js.map} +0 -0
  771. /package/dist/{WsiSamplesPlot-KMI5S2EL.js.map → WsiSamplesPlot-CXGWPCDL.js.map} +0 -0
  772. /package/dist/{adSandbox-JTK5XEQL.js.map → adSandbox-DE4VRO4Z.js.map} +0 -0
  773. /package/dist/{alphaGenome-JRAV6WIY.js.map → alphaGenome-FSIGC5ZT.js.map} +0 -0
  774. /package/dist/{app-JKDZL23V.js.map → app-KZGKWQMU.js.map} +0 -0
  775. /package/dist/{app-OEARXM6E.js.map → app-MQRJ7FVL.js.map} +0 -0
  776. /package/dist/{bam-CYEPLBK4.js.map → bam-BDWTA4O3.js.map} +0 -0
  777. /package/dist/{barchart-GG5UFDG4.js.map → barchart-4Q6LVJY4.js.map} +0 -0
  778. /package/dist/{barchart.data-KXA66FAL.js.map → barchart.data-EXENRVMU.js.map} +0 -0
  779. /package/dist/{barchart.events-P2USOIR7.js.map → barchart.events-XRGND6I7.js.map} +0 -0
  780. /package/dist/{barchart.integration.spec-5QSPQQLJ.js.map → barchart.integration.spec-VQITP4YH.js.map} +0 -0
  781. /package/dist/{bars.renderer-T5R3UIBW.js.map → bars.renderer-S7A7I6BQ.js.map} +0 -0
  782. /package/dist/{block.init-ZHX6DFWF.js.map → block.init-NCNSE3HD.js.map} +0 -0
  783. /package/dist/{block.mds.expressionrank-YMGYXXYT.js.map → block.mds.expressionrank-JYZARS7T.js.map} +0 -0
  784. /package/dist/{block.mds.geneboxplot-IAILQYX4.js.map → block.mds.geneboxplot-FD2MCIHV.js.map} +0 -0
  785. /package/dist/{block.mds.junction-BRNFNQMU.js.map → block.mds.junction-LOHVQBIU.js.map} +0 -0
  786. /package/dist/{block.mds.svcnv-OHKC7YPO.js.map → block.mds.svcnv-Z7SAYPQL.js.map} +0 -0
  787. /package/dist/{block.svg-PNGK45HW.js.map → block.svg-LNJOKQNN.js.map} +0 -0
  788. /package/dist/{block.tk.aicheck-SCIOJ4WN.js.map → block.tk.aicheck-IXCMMAGV.js.map} +0 -0
  789. /package/dist/{block.tk.ase-BABJ73GG.js.map → block.tk.ase-WYRYFP6N.js.map} +0 -0
  790. /package/dist/{block.tk.bam-LZWJ5BCQ.js.map → block.tk.bam-EIVBNGAL.js.map} +0 -0
  791. /package/dist/{block.tk.bedgraphdot-7NQLC3XJ.js.map → block.tk.bedgraphdot-3FHLNCU7.js.map} +0 -0
  792. /package/dist/{block.tk.bigwig.ui-VNY4SFD5.js.map → block.tk.bigwig.ui-YDQU5PC4.js.map} +0 -0
  793. /package/dist/{block.tk.hicstraw-36A7VDRM.js.map → block.tk.hicstraw-S3ROL3CV.js.map} +0 -0
  794. /package/dist/{block.tk.junction-D373YEMK.js.map → block.tk.junction-DL7RNWX3.js.map} +0 -0
  795. /package/dist/{block.tk.junction.textmatrixui-FFII7J3X.js.map → block.tk.junction.textmatrixui-Z6I7IEDY.js.map} +0 -0
  796. /package/dist/{block.tk.ld-XGB6KMDO.js.map → block.tk.ld-XHVU6L56.js.map} +0 -0
  797. /package/dist/{block.tk.menu-PEZANZBZ.js.map → block.tk.menu-FPLAEEFY.js.map} +0 -0
  798. /package/dist/{block.tk.pgv-MU5BPTT2.js.map → block.tk.pgv-6ZZ2QGNO.js.map} +0 -0
  799. /package/dist/{brainImaging-LVJON47N.js.map → brainImaging-VSOOMITW.js.map} +0 -0
  800. /package/dist/{chat-5FDIAQJ4.js.map → chat-LW23PIG5.js.map} +0 -0
  801. /package/dist/{chunk-PQABAAEZ.js.map → chunk-2LULD7RN.js.map} +0 -0
  802. /package/dist/{chunk-LEDPPLQK.js.map → chunk-3AGB6HL4.js.map} +0 -0
  803. /package/dist/{chunk-T2HYA2KL.js.map → chunk-3AVDNIDN.js.map} +0 -0
  804. /package/dist/{chunk-JOXUBWN3.js.map → chunk-3DCABJHB.js.map} +0 -0
  805. /package/dist/{chunk-UQACPOCM.js.map → chunk-3JMB3OSC.js.map} +0 -0
  806. /package/dist/{chunk-2J3566TA.js.map → chunk-3UEMY45Y.js.map} +0 -0
  807. /package/dist/{chunk-ILF2GKBY.js.map → chunk-4RR4KPRJ.js.map} +0 -0
  808. /package/dist/{chunk-TE3DK3A6.js.map → chunk-5HCB4HNL.js.map} +0 -0
  809. /package/dist/{chunk-IP4T477W.js.map → chunk-5RFB7TYT.js.map} +0 -0
  810. /package/dist/{chunk-7A7NMCQ3.js.map → chunk-5UMPBVA6.js.map} +0 -0
  811. /package/dist/{chunk-MXI3NXRB.js.map → chunk-6C2SBTLR.js.map} +0 -0
  812. /package/dist/{chunk-UBS5UVIY.js.map → chunk-6LAE5AVA.js.map} +0 -0
  813. /package/dist/{chunk-JHOGX5VE.js.map → chunk-7VV43ICF.js.map} +0 -0
  814. /package/dist/{chunk-O4PXELXF.js.map → chunk-A742TQD2.js.map} +0 -0
  815. /package/dist/{chunk-E6DRQJJT.js.map → chunk-AFLFPYJI.js.map} +0 -0
  816. /package/dist/{chunk-DONWY7TP.js.map → chunk-AQ4OP4GR.js.map} +0 -0
  817. /package/dist/{chunk-FQRLSKJC.js.map → chunk-BAY47D5E.js.map} +0 -0
  818. /package/dist/{chunk-TN5GSG34.js.map → chunk-CFHKYLDY.js.map} +0 -0
  819. /package/dist/{chunk-K6JLCMVL.js.map → chunk-CTAKX5CT.js.map} +0 -0
  820. /package/dist/{chunk-Y3TDC7NU.js.map → chunk-D4QFQQWJ.js.map} +0 -0
  821. /package/dist/{chunk-YUMPQ3CJ.js.map → chunk-DGMK7SXX.js.map} +0 -0
  822. /package/dist/{chunk-UR3C4SCH.js.map → chunk-DNCSPTOQ.js.map} +0 -0
  823. /package/dist/{chunk-IIRU6VK2.js.map → chunk-DTDQKGIQ.js.map} +0 -0
  824. /package/dist/{chunk-K57RR3FD.js.map → chunk-E4NVHKWD.js.map} +0 -0
  825. /package/dist/{chunk-GKK3CZ6H.js.map → chunk-E6KEZENR.js.map} +0 -0
  826. /package/dist/{chunk-X6UPDFDX.js.map → chunk-FRBYOOWT.js.map} +0 -0
  827. /package/dist/{chunk-UWX7W22M.js.map → chunk-FVWCYGJL.js.map} +0 -0
  828. /package/dist/{chunk-CCIZJAXB.js.map → chunk-I4IKRKYJ.js.map} +0 -0
  829. /package/dist/{chunk-W6UUEAEP.js.map → chunk-IEQSUAIO.js.map} +0 -0
  830. /package/dist/{chunk-UBGTQMOO.js.map → chunk-JMPSZMDD.js.map} +0 -0
  831. /package/dist/{chunk-MPJHDHBA.js.map → chunk-JXOL73PT.js.map} +0 -0
  832. /package/dist/{chunk-KSFSM46X.js.map → chunk-K62XUHA4.js.map} +0 -0
  833. /package/dist/{chunk-DVDDXOWT.js.map → chunk-KQMEJUWI.js.map} +0 -0
  834. /package/dist/{chunk-FGMPKWT5.js.map → chunk-LI7FE335.js.map} +0 -0
  835. /package/dist/{chunk-AZYDW5T7.js.map → chunk-MV6O4I2B.js.map} +0 -0
  836. /package/dist/{chunk-PIACSJPH.js.map → chunk-MXNSW55L.js.map} +0 -0
  837. /package/dist/{chunk-HAMDFQIX.js.map → chunk-NB7NLFGZ.js.map} +0 -0
  838. /package/dist/{chunk-FBAJTPBU.js.map → chunk-NGGWK6HX.js.map} +0 -0
  839. /package/dist/{chunk-P5HLYAHP.js.map → chunk-OGGFS66K.js.map} +0 -0
  840. /package/dist/{chunk-DHZL3FBC.js.map → chunk-Q7PYFSNU.js.map} +0 -0
  841. /package/dist/{chunk-GPOECA3V.js.map → chunk-QMI222IJ.js.map} +0 -0
  842. /package/dist/{chunk-AETE4F7R.js.map → chunk-QRIRWDIW.js.map} +0 -0
  843. /package/dist/{chunk-ORPCSG6T.js.map → chunk-R6L6NVEC.js.map} +0 -0
  844. /package/dist/{chunk-B6HCIAM3.js.map → chunk-RLTLYKHO.js.map} +0 -0
  845. /package/dist/{chunk-VLTDUJRM.js.map → chunk-S5ZI6N2I.js.map} +0 -0
  846. /package/dist/{chunk-H2D7EVUA.js.map → chunk-S7T7OZC7.js.map} +0 -0
  847. /package/dist/{chunk-F6V4AYWP.js.map → chunk-SEQLC4AD.js.map} +0 -0
  848. /package/dist/{chunk-RSU37SVQ.js.map → chunk-TEZLFSOV.js.map} +0 -0
  849. /package/dist/{chunk-YOTWMCT5.js.map → chunk-UEMTP6ZC.js.map} +0 -0
  850. /package/dist/{chunk-6MSCYO7K.js.map → chunk-UJU3Q7QJ.js.map} +0 -0
  851. /package/dist/{chunk-RFIVPTMS.js.map → chunk-VIPMLSZP.js.map} +0 -0
  852. /package/dist/{chunk-LUTT3MBZ.js.map → chunk-VUUZJANK.js.map} +0 -0
  853. /package/dist/{chunk-2OSEZCWZ.js.map → chunk-WGHO2NCP.js.map} +0 -0
  854. /package/dist/{chunk-GO5SIPFE.js.map → chunk-WPHOEG56.js.map} +0 -0
  855. /package/dist/{chunk-KVG7FTTK.js.map → chunk-WS5XVKPJ.js.map} +0 -0
  856. /package/dist/{chunk-MNRYCG2S.js.map → chunk-X6URQAFD.js.map} +0 -0
  857. /package/dist/{chunk-VJ37HKM6.js.map → chunk-YALAQWX4.js.map} +0 -0
  858. /package/dist/{chunk-H2K5KZP7.js.map → chunk-YY4CKQJ6.js.map} +0 -0
  859. /package/dist/{chunk-G6ELKVBG.js.map → chunk-Z3KV6SC2.js.map} +0 -0
  860. /package/dist/{condition-VHP2L4GM.js.map → condition-JKQIRMMW.js.map} +0 -0
  861. /package/dist/{controls-N5Q7U7JR.js.map → controls-324AGOZG.js.map} +0 -0
  862. /package/dist/{controls.config-NJMW4SLR.js.map → controls.config-TA4NNARU.js.map} +0 -0
  863. /package/dist/{correlation-3LDASF5I.js.map → correlation-3Z36TKC2.js.map} +0 -0
  864. /package/dist/{cuminc-UWJ23W6C.js.map → cuminc-4DY2CSZF.js.map} +0 -0
  865. /package/dist/{cuminc.integration.spec-OZYYET3W.js.map → cuminc.integration.spec-SFQPLMSF.js.map} +0 -0
  866. /package/dist/{dataDownload-4S4PE5HX.js.map → dataDownload-3AE2N7KI.js.map} +0 -0
  867. /package/dist/{dataDownload.integration.spec-B57LEKFZ.js.map → dataDownload.integration.spec-DKOT6BJP.js.map} +0 -0
  868. /package/dist/{databrowser.ui-N6GHEQ2P.js.map → databrowser.ui-ATODRS5P.js.map} +0 -0
  869. /package/dist/{dnaMethylation-BOGAUAWA.js.map → dnaMethylation-TVA5YMOR.js.map} +0 -0
  870. /package/dist/{e2pca-L5EBQJNP.js.map → e2pca-KHVDNFEZ.js.map} +0 -0
  871. /package/dist/{ep-Z67ORKUX.js.map → ep-B5GAAMNM.js.map} +0 -0
  872. /package/dist/{expclust.gdc.spec-SP7VOL64.js.map → expclust.gdc.spec-EDPX7V6K.js.map} +0 -0
  873. /package/dist/{facet-HDB4VDGU.js.map → facet-ZCSXKXIO.js.map} +0 -0
  874. /package/dist/{geneExpClustering-6ZPOLTDJ.js.map → geneExpClustering-ERNCMAED.js.map} +0 -0
  875. /package/dist/{geneExpression-T7QUHV5S.js.map → geneExpression-HUOXWETT.js.map} +0 -0
  876. /package/dist/{geneExpression-T6YIG4XQ.js.map → geneExpression-X2KXJPND.js.map} +0 -0
  877. /package/dist/{geneExpression.unit.spec-DO52L5IB.js.map → geneExpression.unit.spec-5QQB4ISW.js.map} +0 -0
  878. /package/dist/{geneORA-KOUDUWUO.js.map → geneORA-B5UK77KL.js.map} +0 -0
  879. /package/dist/{geneVariant-FVR76F6I.js.map → geneVariant-7MGUAIZ6.js.map} +0 -0
  880. /package/dist/{geneVariant-I5QUITKG.js.map → geneVariant-FK3KZJ2K.js.map} +0 -0
  881. /package/dist/{geneVariant.integration.spec-D4IRM7B5.js.map → geneVariant.integration.spec-C6TYWKIC.js.map} +0 -0
  882. /package/dist/{genefusion.ui-35IYSZD7.js.map → genefusion.ui-VKAINMY7.js.map} +0 -0
  883. /package/dist/{geneset-7ZHJ5KWK.js.map → geneset-673KAZVX.js.map} +0 -0
  884. /package/dist/{genomeBrowser.spec-VXASVLNH.js.map → genomeBrowser.spec-T6TQCJ3O.js.map} +0 -0
  885. /package/dist/{grin2-7NM56COO.js.map → grin2-376BD4XY.js.map} +0 -0
  886. /package/dist/{grin2-IY26UUQI.js.map → grin2-OALS75LC.js.map} +0 -0
  887. /package/dist/{gsea-TORO46C6.js.map → gsea-25LD2LGP.js.map} +0 -0
  888. /package/dist/{hierCluster-3BKEGW6P.js.map → hierCluster-7KU3K52V.js.map} +0 -0
  889. /package/dist/{hierCluster-HM3LOM6V.js.map → hierCluster-M5VVWKQK.js.map} +0 -0
  890. /package/dist/{hierCluster.config-LDO5IGQ5.js.map → hierCluster.config-EDO3SH2P.js.map} +0 -0
  891. /package/dist/{hierCluster.integration.spec-XO5R6CQT.js.map → hierCluster.integration.spec-UOX7J2XD.js.map} +0 -0
  892. /package/dist/{hierCluster.interactivity-NVQ6262K.js.map → hierCluster.interactivity-FEFZDXML.js.map} +0 -0
  893. /package/dist/{hierCluster.renderers-SWPPNBLU.js.map → hierCluster.renderers-A6MEGO2B.js.map} +0 -0
  894. /package/dist/{imagePlot-V4WLAPV6.js.map → imagePlot-FPXZ2H5Z.js.map} +0 -0
  895. /package/dist/{importPlot-NZKQEOX4.js.map → importPlot-VKWPSFEK.js.map} +0 -0
  896. /package/dist/{isoformExpression-TIZBIGNL.js.map → isoformExpression-2R2TOB6P.js.map} +0 -0
  897. /package/dist/{jspdf.es.min-DO4YWL2R.js.map → jspdf.es.min-FC3BCETM.js.map} +0 -0
  898. /package/dist/{launch.adhoc-JYEN42NM.js.map → launch.adhoc-242RS6DW.js.map} +0 -0
  899. /package/dist/{leftlabel.sample-43DL3J3H.js.map → leftlabel.sample-OJW3AE64.js.map} +0 -0
  900. /package/dist/{legacyDataset-QRSNRVUA.js.map → legacyDataset-PBCPC5I7.js.map} +0 -0
  901. /package/dist/{lollipop-NMWZ4FVF.js.map → lollipop-TRQ3LK7Y.js.map} +0 -0
  902. /package/dist/{maf-DS3EOVGV.js.map → maf-ZBOLN2FE.js.map} +0 -0
  903. /package/dist/{maftimeline-ZB2753S7.js.map → maftimeline-GVX7NJP7.js.map} +0 -0
  904. /package/dist/{matrix-RCGQWQ3C.js.map → matrix-73KRNXLM.js.map} +0 -0
  905. /package/dist/{matrix-WTTEK4FT.js.map → matrix-US3OXYRY.js.map} +0 -0
  906. /package/dist/{matrix.cells-UO5ASQ35.js.map → matrix.cells-U7AQNEBP.js.map} +0 -0
  907. /package/dist/{matrix.config-3UQAT3QR.js.map → matrix.config-Q57D7C3F.js.map} +0 -0
  908. /package/dist/{matrix.controls-PRZ77K5L.js.map → matrix.controls-AWXDRSWP.js.map} +0 -0
  909. /package/dist/{matrix.data-4W73RQ3H.js.map → matrix.data-EEIY6AO4.js.map} +0 -0
  910. /package/dist/{matrix.dom-IZFFS4RQ.js.map → matrix.dom-6QL3AJMW.js.map} +0 -0
  911. /package/dist/{matrix.groups-5VMPI7SA.js.map → matrix.groups-CUB6UWC5.js.map} +0 -0
  912. /package/dist/{matrix.integration.spec-2F5LDLC2.js.map → matrix.integration.spec-PQH67KRM.js.map} +0 -0
  913. /package/dist/{matrix.interactivity-MIPZ6ELV.js.map → matrix.interactivity-JW4AXAWO.js.map} +0 -0
  914. /package/dist/{matrix.layout-EO5LVYRO.js.map → matrix.layout-I56KRVCO.js.map} +0 -0
  915. /package/dist/{matrix.legend-QBFBFEUG.js.map → matrix.legend-42LQGAGX.js.map} +0 -0
  916. /package/dist/{matrix.renderers-ERJXVCQL.js.map → matrix.renderers-IX3FCNBK.js.map} +0 -0
  917. /package/dist/{matrix.serieses-E23EPXHA.js.map → matrix.serieses-4B2WB526.js.map} +0 -0
  918. /package/dist/{matrix.sort-I4UGMEXR.js.map → matrix.sort-BJACNR7G.js.map} +0 -0
  919. /package/dist/{matrix.sort.unit.spec-CRGF6CSE.js.map → matrix.sort.unit.spec-3KKDKIPY.js.map} +0 -0
  920. /package/dist/{matrix.sorterUi-YLSYTYLE.js.map → matrix.sorterUi-W6XFYZY2.js.map} +0 -0
  921. /package/dist/{matrix.sorterUi.unit.spec-ENG3ICOO.js.map → matrix.sorterUi.unit.spec-CMJ7EBIW.js.map} +0 -0
  922. /package/dist/{mavb-5WR7OJHI.js.map → mavb-ROAE6WYA.js.map} +0 -0
  923. /package/dist/{mds.fimo-3ZRH7BBJ.js.map → mds.fimo-UGK5OWCF.js.map} +0 -0
  924. /package/dist/{mds.samplescatterplot-RPXR2FVK.js.map → mds.samplescatterplot-5KFUAYSB.js.map} +0 -0
  925. /package/dist/{mds.survivalplot-WSSMYUZD.js.map → mds.survivalplot-2EVNZUX5.js.map} +0 -0
  926. /package/dist/{oncomatrix-JKYPUJQR.js.map → oncomatrix-UGFXSXQJ.js.map} +0 -0
  927. /package/dist/{oncomatrix.spec-OEGU4DYK.js.map → oncomatrix.spec-FEP7BR7L.js.map} +0 -0
  928. /package/dist/{plot.2dvaf-ZGARLQNK.js.map → plot.2dvaf-WXGLWCOC.js.map} +0 -0
  929. /package/dist/{plot.app-TKUJH3LK.js.map → plot.app-IZAFRTBU.js.map} +0 -0
  930. /package/dist/{plot.barplot-FEIPGDZ2.js.map → plot.barplot-Z4VWOPFJ.js.map} +0 -0
  931. /package/dist/{plot.boxplot-6RASUMZB.js.map → plot.boxplot-QU2KZSB7.js.map} +0 -0
  932. /package/dist/{plot.brainImaging-ZJPFWX2W.js.map → plot.brainImaging-U643YIK7.js.map} +0 -0
  933. /package/dist/{plot.dzi-PC34YI6Y.js.map → plot.dzi-DWXPOOQE.js.map} +0 -0
  934. /package/dist/{plot.ssgq-Z4UNJKWO.js.map → plot.ssgq-GXB2GZO3.js.map} +0 -0
  935. /package/dist/{plot.vaf2cov-NZ4WULKT.js.map → plot.vaf2cov-EKRIADPB.js.map} +0 -0
  936. /package/dist/{plot.wsi-YYXFAZWY.js.map → plot.wsi-E2LLE6HI.js.map} +0 -0
  937. /package/dist/{polar-X2GPIBLB.js.map → polar-MZLIUXHO.js.map} +0 -0
  938. /package/dist/{polar2-TZ553QQH.js.map → polar2-IUVHNQM4.js.map} +0 -0
  939. /package/dist/{profile.spec-VB6VMFLY.js.map → profile.spec-JRW6KYUI.js.map} +0 -0
  940. /package/dist/{profileBarchart-SKJSTC7B.js.map → profileBarchart-N7HJMYZ5.js.map} +0 -0
  941. /package/dist/{profileForms-RLOGSMAQ.js.map → profileForms-Q5TPGPQP.js.map} +0 -0
  942. /package/dist/{profilePlot-267ZS3RG.js.map → profilePlot-TXTUYDVE.js.map} +0 -0
  943. /package/dist/{profileRadar-KGOBHCSF.js.map → profileRadar-ICEASI7W.js.map} +0 -0
  944. /package/dist/{proteomeAbundance-PGHZSVAF.js.map → proteomeAbundance-DE4NVBCN.js.map} +0 -0
  945. /package/dist/{proteomeAbundance-JUYAYO5I.js.map → proteomeAbundance-LTB3QR3G.js.map} +0 -0
  946. /package/dist/{qualitative-3IECKKJM.js.map → qualitative-DFGWQURY.js.map} +0 -0
  947. /package/dist/{regression-J6FFRPXN.js.map → regression-TTQTAEGD.js.map} +0 -0
  948. /package/dist/{regression.inputs-T7LWBSYZ.js.map → regression.inputs-2LU2XRGC.js.map} +0 -0
  949. /package/dist/{regression.inputs.term-TT7PNX6G.js.map → regression.inputs.term-G57GL57T.js.map} +0 -0
  950. /package/dist/{regression.inputs.values.table-SHFUNKCS.js.map → regression.inputs.values.table-JSEM3PXL.js.map} +0 -0
  951. /package/dist/{regression.results-D4WX6VIV.js.map → regression.results-3YNM6LLQ.js.map} +0 -0
  952. /package/dist/{regression.spec-7SW55L7X.js.map → regression.spec-S6WFCPSW.js.map} +0 -0
  953. /package/dist/{report-QYOZ4BRF.js.map → report-YRAV4MY4.js.map} +0 -0
  954. /package/dist/{sampleScatter.spec-JCHFMGNF.js.map → sampleScatter.spec-MBJ4XNTX.js.map} +0 -0
  955. /package/dist/{sampleView-7RPKNAZC.js.map → sampleView-IUR3ZEN7.js.map} +0 -0
  956. /package/dist/{samplelst-4WNPHZVG.js.map → samplelst-C2NBFGH6.js.map} +0 -0
  957. /package/dist/{samplematrix-CG52DSXJ.js.map → samplematrix-AOK2HHSB.js.map} +0 -0
  958. /package/dist/{sc-OJSWILSA.js.map → sc-XT3Z5XJI.js.map} +0 -0
  959. /package/dist/{scatter-LG2RMMEC.js.map → scatter-SAHKZRFL.js.map} +0 -0
  960. /package/dist/{selectGenomeWithTklst-QXRVE6N4.js.map → selectGenomeWithTklst-2YVZ4JWV.js.map} +0 -0
  961. /package/dist/{singleCellCellType-XBSRL33U.js.map → singleCellCellType-NFN5GQJM.js.map} +0 -0
  962. /package/dist/{singleCellGeneExpression-64ECP62X.js.map → singleCellGeneExpression-7AQGLXTR.js.map} +0 -0
  963. /package/dist/{singleCellPlot-E5F62JY6.js.map → singleCellPlot-IWFEG44C.js.map} +0 -0
  964. /package/dist/{singlecell-S7B5V7NK.js.map → singlecell-3QNV4OMZ.js.map} +0 -0
  965. /package/dist/{singlecell-FCY5EOUV.js.map → singlecell-EATPLH66.js.map} +0 -0
  966. /package/dist/{snp-ACKX4GRX.js.map → snp-UP7WL7WG.js.map} +0 -0
  967. /package/dist/{snp.unit.spec-QBGHKKUD.js.map → snp.unit.spec-Y5NWQ442.js.map} +0 -0
  968. /package/dist/{snplocus-7EUOW7J7.js.map → snplocus-WAQK2AZG.js.map} +0 -0
  969. /package/dist/{spliceevent.a53ss.diagram-ALQZA35Z.js.map → spliceevent.a53ss.diagram-FFK27UIB.js.map} +0 -0
  970. /package/dist/{spliceevent.exonskip.diagram-UF7WJA5R.js.map → spliceevent.exonskip.diagram-KWEF2OZJ.js.map} +0 -0
  971. /package/dist/{spliceevent.noeventdiagram-4HPGRNRR.js.map → spliceevent.noeventdiagram-PU4TI7OM.js.map} +0 -0
  972. /package/dist/{ssGSEA-FDRBBBLJ.js.map → ssGSEA-N6QOAVLW.js.map} +0 -0
  973. /package/dist/{ssGSEA.unit.spec-EZEOWJVV.js.map → ssGSEA.unit.spec-KQBNZNNP.js.map} +0 -0
  974. /package/dist/{summarizeMutationDiagnosis-LALOJTHV.js.map → summarizeMutationDiagnosis-5RHSG7L6.js.map} +0 -0
  975. /package/dist/{summarizeMutationSurvival-TSNTSOBZ.js.map → summarizeMutationSurvival-22YYXGS5.js.map} +0 -0
  976. /package/dist/{summary-YRHVS64T.js.map → summary-P3WIKJS7.js.map} +0 -0
  977. /package/dist/{summary.integration.spec-766YQLQA.js.map → summary.integration.spec-ULGRPICW.js.map} +0 -0
  978. /package/dist/{summaryInput-VQ2X6GSX.js.map → summaryInput-IH4EVNF5.js.map} +0 -0
  979. /package/dist/{survival-FQXZH2MM.js.map → survival-2ZE3N62A.js.map} +0 -0
  980. /package/dist/{survival-TVA3ZWVP.js.map → survival-ASCLKIII.js.map} +0 -0
  981. /package/dist/{survival.integration.spec-WFIOPD6A.js.map → survival.integration.spec-C5YXOY77.js.map} +0 -0
  982. /package/dist/{svg2pdf.es.min-EZ4UYRSH.js.map → svg2pdf.es.min-CYTPRWNB.js.map} +0 -0
  983. /package/dist/{svgraph-4BFBO7EL.js.map → svgraph-AYR2UPNK.js.map} +0 -0
  984. /package/dist/{svmr-ML7GAIIA.js.map → svmr-MOMW5DNY.js.map} +0 -0
  985. /package/dist/{table-SMLMUWPP.js.map → table-PQB6KCEY.js.map} +0 -0
  986. /package/dist/{termCollection-22CPTISZ.js.map → termCollection-5AY2AWT4.js.map} +0 -0
  987. /package/dist/{termCollection-EE6AOIVA.js.map → termCollection-OQMUUTW6.js.map} +0 -0
  988. /package/dist/{termCollection.unit.spec-4DIW3CJ3.js.map → termCollection.unit.spec-BUAXYIJK.js.map} +0 -0
  989. /package/dist/{tk-ITZCKOQ5.js.map → tk-EJLFFA5H.js.map} +0 -0
  990. /package/dist/{tp.ui-R6HVKCBC.js.map → tp.ui-WUW6A7KP.js.map} +0 -0
  991. /package/dist/{tvs.density-AQ5GD437.js.map → tvs.density-HSVPDDGA.js.map} +0 -0
  992. /package/dist/{tvs.dt-2263TBEJ.js.map → tvs.dt-MVJXQMNU.js.map} +0 -0
  993. /package/dist/{tvs.dtcnv.categorical-TRRHL33N.js.map → tvs.dtcnv.categorical-FIIDWVK7.js.map} +0 -0
  994. /package/dist/{tvs.dtcnv.continuous-GREYNF52.js.map → tvs.dtcnv.continuous-JPQU3JA2.js.map} +0 -0
  995. /package/dist/{tvs.dtfusion-XOX46L3M.js.map → tvs.dtfusion-BW35GOQM.js.map} +0 -0
  996. /package/dist/{tvs.dtsnvindel-IDMXT53F.js.map → tvs.dtsnvindel-AEMFZ4EH.js.map} +0 -0
  997. /package/dist/{tvs.dtsv-ZDWFYH2C.js.map → tvs.dtsv-JHTU7UFD.js.map} +0 -0
  998. /package/dist/{tvs.numeric-ZN2R7BH3.js.map → tvs.numeric-ICUGA4WY.js.map} +0 -0
  999. /package/dist/{tvs.samplelst-GAP76HRH.js.map → tvs.samplelst-VD2NFFFS.js.map} +0 -0
  1000. /package/dist/{tvs.termCollection-GQ65UKSI.js.map → tvs.termCollection-IKE5Q74D.js.map} +0 -0
  1001. /package/dist/{violin-JGDL62YA.js.map → violin-DPMJLHQG.js.map} +0 -0
  1002. /package/dist/{violin.interactivity-H4RP4K5U.js.map → violin.interactivity-TS4DYUE5.js.map} +0 -0
  1003. /package/dist/{violin.renderer-QPHLACDC.js.map → violin.renderer-53L4PXUT.js.map} +0 -0
  1004. /package/dist/{vocabulary-7JACY4J2.js.map → vocabulary-4MPFHKYC.js.map} +0 -0
@@ -0,0 +1,4207 @@
1
+ import {
2
+ d3lasso
3
+ } from "./chunk-5UG7ZKPU.js";
4
+ import {
5
+ BufferGeometry,
6
+ CanvasTexture,
7
+ Color,
8
+ Float32BufferAttribute,
9
+ Line,
10
+ LineBasicMaterial,
11
+ LinearSRGBColorSpace,
12
+ Mesh,
13
+ MeshBasicMaterial,
14
+ PerspectiveCamera,
15
+ PlaneGeometry,
16
+ Points,
17
+ PointsMaterial,
18
+ Scene,
19
+ TextureLoader,
20
+ Vector2,
21
+ Vector3,
22
+ WebGLRenderer
23
+ } from "./chunk-72PLI3GC.js";
24
+ import {
25
+ getId
26
+ } from "./chunk-VUUZJANK.js";
27
+ import {
28
+ ColorScale,
29
+ Tabs,
30
+ addGeneSearchbox,
31
+ addNewGroup,
32
+ controlsInit,
33
+ digestMessage,
34
+ downloadSingleSVG,
35
+ downloadTable,
36
+ fillTermWrapper,
37
+ getFilter,
38
+ getMaxLabelWidth,
39
+ getSamplelstTW,
40
+ renderTable,
41
+ sayerror,
42
+ shapeSelector,
43
+ shapesArray,
44
+ table2col
45
+ } from "./chunk-OXJ2TWDO.js";
46
+ import {
47
+ dofetch3
48
+ } from "./chunk-7RN3L2BX.js";
49
+ import {
50
+ Menu
51
+ } from "./chunk-A6TQGNDQ.js";
52
+ import {
53
+ icons
54
+ } from "./chunk-5EF5U7MX.js";
55
+ import {
56
+ copyMerge,
57
+ getCompInit
58
+ } from "./chunk-MVTCBVSX.js";
59
+ import {
60
+ roundValueAuto
61
+ } from "./chunk-L4QG7XZE.js";
62
+ import {
63
+ SINGLECELL_CELLTYPE,
64
+ SINGLECELL_GENE_EXPRESSION,
65
+ getDateFromNumber,
66
+ getDateStrFromNumber,
67
+ isNumericTerm
68
+ } from "./chunk-6ITDJ5UR.js";
69
+ import {
70
+ dt2label,
71
+ getColors,
72
+ mclass,
73
+ morigin
74
+ } from "./chunk-XYFDBYOY.js";
75
+ import {
76
+ Greys_default,
77
+ density_default,
78
+ identity,
79
+ line_default,
80
+ path_default,
81
+ zoom_default
82
+ } from "./chunk-IH7ILDJS.js";
83
+ import {
84
+ axisBottom,
85
+ axisLeft
86
+ } from "./chunk-LOZEKOES.js";
87
+ import {
88
+ extent,
89
+ linear,
90
+ max,
91
+ sequential,
92
+ time
93
+ } from "./chunk-OAWQ6LOO.js";
94
+ import {
95
+ create_default,
96
+ select_default
97
+ } from "./chunk-NDWTN4U5.js";
98
+ import {
99
+ rgb
100
+ } from "./chunk-OMR2DT66.js";
101
+ import {
102
+ __commonJS,
103
+ __toESM
104
+ } from "./chunk-HFNDKYVF.js";
105
+
106
+ // ../node_modules/d3-regression/dist/d3-regression.js
107
+ var require_d3_regression = __commonJS({
108
+ "../node_modules/d3-regression/dist/d3-regression.js"(exports, module) {
109
+ (function(global, factory) {
110
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = global || self, factory(global.d3 = {}));
111
+ })(exports, (function(exports2) {
112
+ "use strict";
113
+ function _slicedToArray(arr, i) {
114
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
115
+ }
116
+ function _arrayWithHoles(arr) {
117
+ if (Array.isArray(arr)) return arr;
118
+ }
119
+ function _iterableToArrayLimit(arr, i) {
120
+ var _arr = [];
121
+ var _n = true;
122
+ var _d = false;
123
+ var _e = void 0;
124
+ try {
125
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
126
+ _arr.push(_s.value);
127
+ if (i && _arr.length === i) break;
128
+ }
129
+ } catch (err) {
130
+ _d = true;
131
+ _e = err;
132
+ } finally {
133
+ try {
134
+ if (!_n && _i["return"] != null) _i["return"]();
135
+ } finally {
136
+ if (_d) throw _e;
137
+ }
138
+ }
139
+ return _arr;
140
+ }
141
+ function _nonIterableRest() {
142
+ throw new TypeError("Invalid attempt to destructure non-iterable instance");
143
+ }
144
+ function points(data, x, y, sort) {
145
+ data = data.filter(function(d2, i2) {
146
+ var u = x(d2, i2), v = y(d2, i2);
147
+ return u != null && isFinite(u) && v != null && isFinite(v);
148
+ });
149
+ if (sort) {
150
+ data.sort(function(a, b) {
151
+ return x(a) - x(b);
152
+ });
153
+ }
154
+ var n = data.length, X = new Float64Array(n), Y = new Float64Array(n);
155
+ var ux = 0, uy = 0, xv, yv, d;
156
+ for (var i = 0; i < n; ) {
157
+ d = data[i];
158
+ X[i] = xv = +x(d, i, data);
159
+ Y[i] = yv = +y(d, i, data);
160
+ ++i;
161
+ ux += (xv - ux) / i;
162
+ uy += (yv - uy) / i;
163
+ }
164
+ for (var _i = 0; _i < n; ++_i) {
165
+ X[_i] -= ux;
166
+ Y[_i] -= uy;
167
+ }
168
+ return [X, Y, ux, uy];
169
+ }
170
+ function visitPoints(data, x, y, cb) {
171
+ var iterations = 0;
172
+ for (var i = 0, n = data.length; i < n; i++) {
173
+ var d = data[i], dx = +x(d, i, data), dy = +y(d, i, data);
174
+ if (dx != null && isFinite(dx) && dy != null && isFinite(dy)) {
175
+ cb(dx, dy, iterations++);
176
+ }
177
+ }
178
+ }
179
+ function determination(data, x, y, uY, predict) {
180
+ var SSE = 0, SST = 0;
181
+ visitPoints(data, x, y, function(dx, dy) {
182
+ var sse = dy - predict(dx), sst = dy - uY;
183
+ SSE += sse * sse;
184
+ SST += sst * sst;
185
+ });
186
+ return 1 - SSE / SST;
187
+ }
188
+ function angle(line) {
189
+ return Math.atan2(line[1][1] - line[0][1], line[1][0] - line[0][0]) * 180 / Math.PI;
190
+ }
191
+ function midpoint(line) {
192
+ return [(line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2];
193
+ }
194
+ function interpose(xmin, xmax, predict) {
195
+ var l = Math.log(xmax - xmin) * Math.LOG10E + 1 | 0;
196
+ var precision = 1 * Math.pow(10, -l / 2 - 1), maxIter = 1e4;
197
+ var points2 = [px(xmin), px(xmax)], iter = 0;
198
+ while (find(points2) && iter < maxIter) {
199
+ }
200
+ return points2;
201
+ function px(x) {
202
+ return [x, predict(x)];
203
+ }
204
+ function find(points3) {
205
+ iter++;
206
+ var n = points3.length;
207
+ var found = false;
208
+ for (var i = 0; i < n - 1; i++) {
209
+ var p0 = points3[i], p1 = points3[i + 1], m = midpoint([p0, p1]), mp = px(m[0]), a0 = angle([p0, m]), a1 = angle([p0, mp]), a = Math.abs(a0 - a1);
210
+ if (a > precision) {
211
+ points3.splice(i + 1, 0, mp);
212
+ found = true;
213
+ }
214
+ }
215
+ return found;
216
+ }
217
+ }
218
+ function ols(uX, uY, uXY, uX2) {
219
+ var delta = uX2 - uX * uX, slope = Math.abs(delta) < 1e-24 ? 0 : (uXY - uX * uY) / delta, intercept = uY - slope * uX;
220
+ return [intercept, slope];
221
+ }
222
+ function exponential() {
223
+ var x = function x2(d) {
224
+ return d[0];
225
+ }, y = function y2(d) {
226
+ return d[1];
227
+ }, domain;
228
+ function exponential2(data) {
229
+ var n = 0, Y = 0, YL = 0, XY = 0, XYL = 0, X2Y = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity;
230
+ visitPoints(data, x, y, function(dx, dy) {
231
+ var ly = Math.log(dy), xy = dx * dy;
232
+ ++n;
233
+ Y += (dy - Y) / n;
234
+ XY += (xy - XY) / n;
235
+ X2Y += (dx * xy - X2Y) / n;
236
+ YL += (dy * ly - YL) / n;
237
+ XYL += (xy * ly - XYL) / n;
238
+ if (!domain) {
239
+ if (dx < xmin) xmin = dx;
240
+ if (dx > xmax) xmax = dx;
241
+ }
242
+ });
243
+ var _ols = ols(XY / Y, YL / Y, XYL / Y, X2Y / Y), _ols2 = _slicedToArray(_ols, 2), a = _ols2[0], b = _ols2[1];
244
+ a = Math.exp(a);
245
+ var fn = function fn2(x2) {
246
+ return a * Math.exp(b * x2);
247
+ }, out = interpose(xmin, xmax, fn);
248
+ out.a = a;
249
+ out.b = b;
250
+ out.predict = fn;
251
+ out.rSquared = determination(data, x, y, Y, fn);
252
+ return out;
253
+ }
254
+ exponential2.domain = function(arr) {
255
+ return arguments.length ? (domain = arr, exponential2) : domain;
256
+ };
257
+ exponential2.x = function(fn) {
258
+ return arguments.length ? (x = fn, exponential2) : x;
259
+ };
260
+ exponential2.y = function(fn) {
261
+ return arguments.length ? (y = fn, exponential2) : y;
262
+ };
263
+ return exponential2;
264
+ }
265
+ function linear2() {
266
+ var x = function x2(d) {
267
+ return d[0];
268
+ }, y = function y2(d) {
269
+ return d[1];
270
+ }, domain;
271
+ function linear3(data) {
272
+ var n = 0, X = 0, Y = 0, XY = 0, X2 = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity;
273
+ visitPoints(data, x, y, function(dx, dy) {
274
+ ++n;
275
+ X += (dx - X) / n;
276
+ Y += (dy - Y) / n;
277
+ XY += (dx * dy - XY) / n;
278
+ X2 += (dx * dx - X2) / n;
279
+ if (!domain) {
280
+ if (dx < xmin) xmin = dx;
281
+ if (dx > xmax) xmax = dx;
282
+ }
283
+ });
284
+ var _ols = ols(X, Y, XY, X2), _ols2 = _slicedToArray(_ols, 2), intercept = _ols2[0], slope = _ols2[1], fn = function fn2(x2) {
285
+ return slope * x2 + intercept;
286
+ }, out = [[xmin, fn(xmin)], [xmax, fn(xmax)]];
287
+ out.a = slope;
288
+ out.b = intercept;
289
+ out.predict = fn;
290
+ out.rSquared = determination(data, x, y, Y, fn);
291
+ return out;
292
+ }
293
+ linear3.domain = function(arr) {
294
+ return arguments.length ? (domain = arr, linear3) : domain;
295
+ };
296
+ linear3.x = function(fn) {
297
+ return arguments.length ? (x = fn, linear3) : x;
298
+ };
299
+ linear3.y = function(fn) {
300
+ return arguments.length ? (y = fn, linear3) : y;
301
+ };
302
+ return linear3;
303
+ }
304
+ function median(arr) {
305
+ arr.sort(function(a, b) {
306
+ return a - b;
307
+ });
308
+ var i = arr.length / 2;
309
+ return i % 1 === 0 ? (arr[i - 1] + arr[i]) / 2 : arr[Math.floor(i)];
310
+ }
311
+ var maxiters = 2, epsilon = 1e-12;
312
+ function loess() {
313
+ var x = function x2(d) {
314
+ return d[0];
315
+ }, y = function y2(d) {
316
+ return d[1];
317
+ }, bandwidth = 0.3;
318
+ function loess2(data) {
319
+ var _points = points(data, x, y, true), _points2 = _slicedToArray(_points, 4), xv = _points2[0], yv = _points2[1], ux = _points2[2], uy = _points2[3], n = xv.length, bw = Math.max(2, ~~(bandwidth * n)), yhat = new Float64Array(n), residuals = new Float64Array(n), robustWeights = new Float64Array(n).fill(1);
320
+ for (var iter = -1; ++iter <= maxiters; ) {
321
+ var interval = [0, bw - 1];
322
+ for (var i = 0; i < n; ++i) {
323
+ var dx = xv[i], i0 = interval[0], i1 = interval[1], edge = dx - xv[i0] > xv[i1] - dx ? i0 : i1;
324
+ var W = 0, X = 0, Y = 0, XY = 0, X2 = 0, denom = 1 / Math.abs(xv[edge] - dx || 1);
325
+ for (var k = i0; k <= i1; ++k) {
326
+ var xk = xv[k], yk = yv[k], w = tricube(Math.abs(dx - xk) * denom) * robustWeights[k], xkw = xk * w;
327
+ W += w;
328
+ X += xkw;
329
+ Y += yk * w;
330
+ XY += yk * xkw;
331
+ X2 += xk * xkw;
332
+ }
333
+ var _ols = ols(X / W, Y / W, XY / W, X2 / W), _ols2 = _slicedToArray(_ols, 2), a = _ols2[0], b = _ols2[1];
334
+ yhat[i] = a + b * dx;
335
+ residuals[i] = Math.abs(yv[i] - yhat[i]);
336
+ updateInterval(xv, i + 1, interval);
337
+ }
338
+ if (iter === maxiters) {
339
+ break;
340
+ }
341
+ var medianResidual = median(residuals);
342
+ if (Math.abs(medianResidual) < epsilon) break;
343
+ for (var _i = 0, arg, _w; _i < n; ++_i) {
344
+ arg = residuals[_i] / (6 * medianResidual);
345
+ robustWeights[_i] = arg >= 1 ? epsilon : (_w = 1 - arg * arg) * _w;
346
+ }
347
+ }
348
+ return output(xv, yhat, ux, uy);
349
+ }
350
+ loess2.bandwidth = function(bw) {
351
+ return arguments.length ? (bandwidth = bw, loess2) : bandwidth;
352
+ };
353
+ loess2.x = function(fn) {
354
+ return arguments.length ? (x = fn, loess2) : x;
355
+ };
356
+ loess2.y = function(fn) {
357
+ return arguments.length ? (y = fn, loess2) : y;
358
+ };
359
+ return loess2;
360
+ }
361
+ function tricube(x) {
362
+ return (x = 1 - x * x * x) * x * x;
363
+ }
364
+ function updateInterval(xv, i, interval) {
365
+ var val = xv[i], left = interval[0], right = interval[1] + 1;
366
+ if (right >= xv.length) return;
367
+ while (i > left && xv[right] - val <= val - xv[left]) {
368
+ interval[0] = ++left;
369
+ interval[1] = right;
370
+ ++right;
371
+ }
372
+ }
373
+ function output(xv, yhat, ux, uy) {
374
+ var n = xv.length, out = [];
375
+ var i = 0, cnt = 0, prev = [], v;
376
+ for (; i < n; ++i) {
377
+ v = xv[i] + ux;
378
+ if (prev[0] === v) {
379
+ prev[1] += (yhat[i] - prev[1]) / ++cnt;
380
+ } else {
381
+ cnt = 0;
382
+ prev[1] += uy;
383
+ prev = [v, yhat[i]];
384
+ out.push(prev);
385
+ }
386
+ }
387
+ prev[1] += uy;
388
+ return out;
389
+ }
390
+ function logarithmic() {
391
+ var x = function x2(d) {
392
+ return d[0];
393
+ }, y = function y2(d) {
394
+ return d[1];
395
+ }, base = Math.E, domain;
396
+ function logarithmic2(data) {
397
+ var n = 0, X = 0, Y = 0, XY = 0, X2 = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity, lb = Math.log(base);
398
+ visitPoints(data, x, y, function(dx, dy) {
399
+ var lx = Math.log(dx) / lb;
400
+ ++n;
401
+ X += (lx - X) / n;
402
+ Y += (dy - Y) / n;
403
+ XY += (lx * dy - XY) / n;
404
+ X2 += (lx * lx - X2) / n;
405
+ if (!domain) {
406
+ if (dx < xmin) xmin = dx;
407
+ if (dx > xmax) xmax = dx;
408
+ }
409
+ });
410
+ var _ols = ols(X, Y, XY, X2), _ols2 = _slicedToArray(_ols, 2), intercept = _ols2[0], slope = _ols2[1], fn = function fn2(x2) {
411
+ return slope * Math.log(x2) / lb + intercept;
412
+ }, out = interpose(xmin, xmax, fn);
413
+ out.a = slope;
414
+ out.b = intercept;
415
+ out.predict = fn;
416
+ out.rSquared = determination(data, x, y, Y, fn);
417
+ return out;
418
+ }
419
+ logarithmic2.domain = function(arr) {
420
+ return arguments.length ? (domain = arr, logarithmic2) : domain;
421
+ };
422
+ logarithmic2.x = function(fn) {
423
+ return arguments.length ? (x = fn, logarithmic2) : x;
424
+ };
425
+ logarithmic2.y = function(fn) {
426
+ return arguments.length ? (y = fn, logarithmic2) : y;
427
+ };
428
+ logarithmic2.base = function(n) {
429
+ return arguments.length ? (base = n, logarithmic2) : base;
430
+ };
431
+ return logarithmic2;
432
+ }
433
+ function quad() {
434
+ var x = function x2(d) {
435
+ return d[0];
436
+ }, y = function y2(d) {
437
+ return d[1];
438
+ }, domain;
439
+ function quadratic(data) {
440
+ var _points = points(data, x, y), _points2 = _slicedToArray(_points, 4), xv = _points2[0], yv = _points2[1], ux = _points2[2], uy = _points2[3], n = xv.length;
441
+ var X2 = 0, X3 = 0, X4 = 0, XY = 0, X2Y = 0, i, dx, dy, x2;
442
+ for (i = 0; i < n; ) {
443
+ dx = xv[i];
444
+ dy = yv[i++];
445
+ x2 = dx * dx;
446
+ X2 += (x2 - X2) / i;
447
+ X3 += (x2 * dx - X3) / i;
448
+ X4 += (x2 * x2 - X4) / i;
449
+ XY += (dx * dy - XY) / i;
450
+ X2Y += (x2 * dy - X2Y) / i;
451
+ }
452
+ var Y = 0, n0 = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity;
453
+ visitPoints(data, x, y, function(dx2, dy2) {
454
+ n0++;
455
+ Y += (dy2 - Y) / n0;
456
+ if (!domain) {
457
+ if (dx2 < xmin) xmin = dx2;
458
+ if (dx2 > xmax) xmax = dx2;
459
+ }
460
+ });
461
+ var X2X2 = X4 - X2 * X2, d = X2 * X2X2 - X3 * X3, a = (X2Y * X2 - XY * X3) / d, b = (XY * X2X2 - X2Y * X3) / d, c = -a * X2, fn = function fn2(x3) {
462
+ x3 = x3 - ux;
463
+ return a * x3 * x3 + b * x3 + c + uy;
464
+ };
465
+ var out = interpose(xmin, xmax, fn);
466
+ out.a = a;
467
+ out.b = b - 2 * a * ux;
468
+ out.c = c - b * ux + a * ux * ux + uy;
469
+ out.predict = fn;
470
+ out.rSquared = determination(data, x, y, Y, fn);
471
+ return out;
472
+ }
473
+ quadratic.domain = function(arr) {
474
+ return arguments.length ? (domain = arr, quadratic) : domain;
475
+ };
476
+ quadratic.x = function(fn) {
477
+ return arguments.length ? (x = fn, quadratic) : x;
478
+ };
479
+ quadratic.y = function(fn) {
480
+ return arguments.length ? (y = fn, quadratic) : y;
481
+ };
482
+ return quadratic;
483
+ }
484
+ function polynomial() {
485
+ var x = function x2(d) {
486
+ return d[0];
487
+ }, y = function y2(d) {
488
+ return d[1];
489
+ }, order = 3, domain;
490
+ function polynomial2(data) {
491
+ if (order === 1) {
492
+ var o = linear2().x(x).y(y).domain(domain)(data);
493
+ o.coefficients = [o.b, o.a];
494
+ delete o.a;
495
+ delete o.b;
496
+ return o;
497
+ }
498
+ if (order === 2) {
499
+ var _o = quad().x(x).y(y).domain(domain)(data);
500
+ _o.coefficients = [_o.c, _o.b, _o.a];
501
+ delete _o.a;
502
+ delete _o.b;
503
+ delete _o.c;
504
+ return _o;
505
+ }
506
+ var _points = points(data, x, y), _points2 = _slicedToArray(_points, 4), xv = _points2[0], yv = _points2[1], ux = _points2[2], uy = _points2[3], n = xv.length, lhs = [], rhs = [], k = order + 1;
507
+ var Y = 0, n0 = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity;
508
+ visitPoints(data, x, y, function(dx, dy) {
509
+ ++n0;
510
+ Y += (dy - Y) / n0;
511
+ if (!domain) {
512
+ if (dx < xmin) xmin = dx;
513
+ if (dx > xmax) xmax = dx;
514
+ }
515
+ });
516
+ var i, j, l, v, c;
517
+ for (i = 0; i < k; ++i) {
518
+ for (l = 0, v = 0; l < n; ++l) {
519
+ v += Math.pow(xv[l], i) * yv[l];
520
+ }
521
+ lhs.push(v);
522
+ c = new Float64Array(k);
523
+ for (j = 0; j < k; ++j) {
524
+ for (l = 0, v = 0; l < n; ++l) {
525
+ v += Math.pow(xv[l], i + j);
526
+ }
527
+ c[j] = v;
528
+ }
529
+ rhs.push(c);
530
+ }
531
+ rhs.push(lhs);
532
+ var coef = gaussianElimination(rhs), fn = function fn2(x2) {
533
+ x2 -= ux;
534
+ var y2 = uy + coef[0] + coef[1] * x2 + coef[2] * x2 * x2;
535
+ for (i = 3; i < k; ++i) {
536
+ y2 += coef[i] * Math.pow(x2, i);
537
+ }
538
+ return y2;
539
+ }, out = interpose(xmin, xmax, fn);
540
+ out.coefficients = uncenter(k, coef, -ux, uy);
541
+ out.predict = fn;
542
+ out.rSquared = determination(data, x, y, Y, fn);
543
+ return out;
544
+ }
545
+ polynomial2.domain = function(arr) {
546
+ return arguments.length ? (domain = arr, polynomial2) : domain;
547
+ };
548
+ polynomial2.x = function(fn) {
549
+ return arguments.length ? (x = fn, polynomial2) : x;
550
+ };
551
+ polynomial2.y = function(fn) {
552
+ return arguments.length ? (y = fn, polynomial2) : y;
553
+ };
554
+ polynomial2.order = function(n) {
555
+ return arguments.length ? (order = n, polynomial2) : order;
556
+ };
557
+ return polynomial2;
558
+ }
559
+ function uncenter(k, a, x, y) {
560
+ var z = Array(k);
561
+ var i, j, v, c;
562
+ for (i = 0; i < k; ++i) {
563
+ z[i] = 0;
564
+ }
565
+ for (i = k - 1; i >= 0; --i) {
566
+ v = a[i];
567
+ c = 1;
568
+ z[i] += v;
569
+ for (j = 1; j <= i; ++j) {
570
+ c *= (i + 1 - j) / j;
571
+ z[i - j] += v * Math.pow(x, j) * c;
572
+ }
573
+ }
574
+ z[0] += y;
575
+ return z;
576
+ }
577
+ function gaussianElimination(matrix) {
578
+ var n = matrix.length - 1, coef = [];
579
+ var i, j, k, r, t;
580
+ for (i = 0; i < n; ++i) {
581
+ r = i;
582
+ for (j = i + 1; j < n; ++j) {
583
+ if (Math.abs(matrix[i][j]) > Math.abs(matrix[i][r])) {
584
+ r = j;
585
+ }
586
+ }
587
+ for (k = i; k < n + 1; ++k) {
588
+ t = matrix[k][i];
589
+ matrix[k][i] = matrix[k][r];
590
+ matrix[k][r] = t;
591
+ }
592
+ for (j = i + 1; j < n; ++j) {
593
+ for (k = n; k >= i; k--) {
594
+ matrix[k][j] -= matrix[k][i] * matrix[i][j] / matrix[i][i];
595
+ }
596
+ }
597
+ }
598
+ for (j = n - 1; j >= 0; --j) {
599
+ t = 0;
600
+ for (k = j + 1; k < n; ++k) {
601
+ t += matrix[k][j] * coef[k];
602
+ }
603
+ coef[j] = (matrix[n][j] - t) / matrix[j][j];
604
+ }
605
+ return coef;
606
+ }
607
+ function power() {
608
+ var x = function x2(d) {
609
+ return d[0];
610
+ }, y = function y2(d) {
611
+ return d[1];
612
+ }, domain;
613
+ function power2(data) {
614
+ var n = 0, X = 0, Y = 0, XY = 0, X2 = 0, YS = 0, xmin = domain ? +domain[0] : Infinity, xmax = domain ? +domain[1] : -Infinity;
615
+ visitPoints(data, x, y, function(dx, dy) {
616
+ var lx = Math.log(dx), ly = Math.log(dy);
617
+ ++n;
618
+ X += (lx - X) / n;
619
+ Y += (ly - Y) / n;
620
+ XY += (lx * ly - XY) / n;
621
+ X2 += (lx * lx - X2) / n;
622
+ YS += (dy - YS) / n;
623
+ if (!domain) {
624
+ if (dx < xmin) xmin = dx;
625
+ if (dx > xmax) xmax = dx;
626
+ }
627
+ });
628
+ var _ols = ols(X, Y, XY, X2), _ols2 = _slicedToArray(_ols, 2), a = _ols2[0], b = _ols2[1];
629
+ a = Math.exp(a);
630
+ var fn = function fn2(x2) {
631
+ return a * Math.pow(x2, b);
632
+ }, out = interpose(xmin, xmax, fn);
633
+ out.a = a;
634
+ out.b = b;
635
+ out.predict = fn;
636
+ out.rSquared = determination(data, x, y, YS, fn);
637
+ return out;
638
+ }
639
+ power2.domain = function(arr) {
640
+ return arguments.length ? (domain = arr, power2) : domain;
641
+ };
642
+ power2.x = function(fn) {
643
+ return arguments.length ? (x = fn, power2) : x;
644
+ };
645
+ power2.y = function(fn) {
646
+ return arguments.length ? (y = fn, power2) : y;
647
+ };
648
+ return power2;
649
+ }
650
+ exports2.regressionExp = exponential;
651
+ exports2.regressionLinear = linear2;
652
+ exports2.regressionLoess = loess;
653
+ exports2.regressionLog = logarithmic;
654
+ exports2.regressionPoly = polynomial;
655
+ exports2.regressionPow = power;
656
+ exports2.regressionQuad = quad;
657
+ Object.defineProperty(exports2, "__esModule", { value: true });
658
+ }));
659
+ }
660
+ });
661
+
662
+ // plots/scatter/viewmodel/scatterLasso.ts
663
+ var ScatterLasso = class {
664
+ constructor(scatter) {
665
+ this.scatter = scatter;
666
+ this.model = scatter.model;
667
+ this.view = scatter.view;
668
+ this.interactivity = scatter.interactivity;
669
+ const supportedChartTypes = this.scatter.state.currentCohortChartTypes;
670
+ this.hasSampleView = supportedChartTypes && supportedChartTypes.includes("sampleView");
671
+ }
672
+ start(chart) {
673
+ if (this.scatter.config.lassoOn) {
674
+ chart.lasso.items().attr("transform", (c) => this.model.transform(chart, c, 1 / 2)).style("fill-opacity", (c) => this.model.getOpacity(c) != 0 ? 0.5 : 0).classed("not_possible", true).classed("selected", false);
675
+ }
676
+ }
677
+ draw(chart) {
678
+ if (this.scatter.config.lassoOn) {
679
+ chart.lasso.possibleItems().attr("transform", (c) => this.model.transform(chart, c, 1.2)).style("fill-opacity", (c) => this.model.getOpacity(c)).classed("not_possible", false).classed("possible", true);
680
+ chart.lasso.notPossibleItems().attr("transform", (c) => this.model.transform(chart, c, 1 / 2)).style("fill-opacity", (c) => this.model.getOpacity(c) != 0 ? 0.5 : 0).classed("not_possible", true).classed("possible", false);
681
+ }
682
+ }
683
+ end(dragEnd, chart) {
684
+ if (this.scatter.config.lassoOn) {
685
+ chart.lasso.items().classed("not_possible", false).classed("possible", false);
686
+ chart.lasso.selectedItems().attr("transform", (c) => this.model.transform(chart, c, 1.3));
687
+ chart.lasso.items().style("fill-opacity", (c) => this.model.getOpacity(c));
688
+ this.selectedItems = [];
689
+ for (const item of chart.lasso.selectedItems()) {
690
+ const data = item.__data__;
691
+ if ("sampleId" in data && !(data.hidden["category"] || data.hidden["shape"])) this.selectedItems.push(item);
692
+ }
693
+ chart.lasso.notSelectedItems().attr("transform", (c) => this.model.transform(chart, c));
694
+ const samples = this.selectedItems.map((item) => item.__data__);
695
+ this.showLassoMenu(dragEnd.sourceEvent, samples);
696
+ }
697
+ }
698
+ showLassoMenu(event, samples) {
699
+ this.view.dom.tip.clear().hide();
700
+ if (samples.length == 0) return;
701
+ this.view.dom.tip.show(event.clientX, event.clientY);
702
+ const menuDiv = this.view.dom.tip.d.append("div");
703
+ menuDiv.append("div").attr("class", "sja_menuoption sja_sharp_border").text(`List ${samples.length} samples`).on("click", (event2) => {
704
+ this.view.dom.tip.hide();
705
+ this.showTable(
706
+ {
707
+ name: "Group " + (this.scatter.config.groups.length + 1),
708
+ items: samples
709
+ },
710
+ event2.clientX,
711
+ event2.clientY,
712
+ this.scatter.app.getState().nav.header_mode === "with_tabs"
713
+ );
714
+ });
715
+ if (this.scatter.app.getState().nav.header_mode === "with_tabs")
716
+ menuDiv.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Add to a group").on("click", async () => {
717
+ this.createGroup(samples);
718
+ this.view.dom.tip.hide();
719
+ });
720
+ if (this.scatter.app.getState().nav.header_mode === "with_tabs")
721
+ menuDiv.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Add to a group and filter").on("click", () => {
722
+ const tw = this.createGroup(samples);
723
+ this.interactivity.addToFilter(tw);
724
+ this.view.dom.tip.hide();
725
+ });
726
+ if ("sample" in samples[0] && this.hasSampleView)
727
+ menuDiv.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Open sample view").on("click", async () => {
728
+ const groupSamples = [];
729
+ for (const sample of samples) groupSamples.push({ sampleId: sample.sampleId, sampleName: sample.sample });
730
+ this.scatter.app.dispatch({
731
+ type: "plot_create",
732
+ id: getId(),
733
+ config: {
734
+ chartType: "sampleView",
735
+ samples: groupSamples
736
+ }
737
+ });
738
+ this.view.dom.tip.hide();
739
+ });
740
+ }
741
+ createGroup(samples) {
742
+ const group = {
743
+ name: "Group",
744
+ items: samples
745
+ };
746
+ const tw = getSamplelstTW([group]);
747
+ const filter = getFilter(tw);
748
+ addNewGroup(this.scatter.app, filter, this.scatter.state.groups);
749
+ return tw;
750
+ }
751
+ lassoReset(chart) {
752
+ const mainG = chart.mainG;
753
+ if (this.scatter.config.lassoOn) {
754
+ chart.lasso.items(mainG.select(".sjpcb-scatter-series").selectAll('path[name="serie"]')).targetArea(mainG).on("start", () => this.start(chart)).on("draw", () => this.draw(chart)).on("end", (event) => this.end(event, chart));
755
+ mainG.on(".zoom", null);
756
+ mainG.on("mousedown.drag", null);
757
+ mainG.call(chart.lasso);
758
+ } else {
759
+ chart.mainG.on(".dragstart", null);
760
+ chart.mainG.on(".drag", null);
761
+ chart.mainG.on(".dragend", null);
762
+ }
763
+ }
764
+ getCategoryInfo(d, category) {
765
+ if (!(category in d)) return "";
766
+ return d[category];
767
+ }
768
+ showTable(group, x, y, addGroup) {
769
+ const rows = [];
770
+ const columns = [];
771
+ const first = group.items[0];
772
+ if ("sample" in first) columns.push(formatCell("Sample", "label"));
773
+ if (this.scatter.config.term) columns.push(formatCell(this.scatter.config.term.term.name, "label"));
774
+ if (this.scatter.config.term2) columns.push(formatCell(this.scatter.config.term2.term.name, "label"));
775
+ if (this.scatter.config.colorTW) columns.push(formatCell(this.scatter.config.colorTW.term.name, "label"));
776
+ if (this.scatter.config.shapeTW) columns.push(formatCell(this.scatter.config.shapeTW.term.name, "label"));
777
+ let info = false;
778
+ const hasSampleName = "sample" in group.items[0];
779
+ for (const item of group.items) {
780
+ const row = [];
781
+ if (hasSampleName) row.push(formatCell(item.sample));
782
+ if (this.scatter.config.term) row.push(formatCell(this.getCategoryInfo(item, "x")));
783
+ if (this.scatter.config.term2) row.push(formatCell(this.getCategoryInfo(item, "y")));
784
+ if (this.scatter.config.colorTW) row.push(formatCell(this.getCategoryInfo(item, "category")));
785
+ if (this.scatter.config.shapeTW) row.push(formatCell(this.getCategoryInfo(item, "shape")));
786
+ if ("info" in item) {
787
+ info = true;
788
+ const values = [];
789
+ for (const [k, v] of Object.entries(item.info)) values.push(`${k}: ${v}`);
790
+ row.push(formatCell(values.join(", ")));
791
+ }
792
+ rows.push(row);
793
+ }
794
+ if (info) columns.push(formatCell("Info", "label"));
795
+ this.view.dom.tip.clear();
796
+ const div = this.view.dom.tip.d.append("div").style("padding", "5px");
797
+ const headerDiv = div.append("div").style("margin-top", "5px");
798
+ const groupDiv = headerDiv.append("div").html("&nbsp;" + group.name).style("font-size", "0.9rem").on("click", () => {
799
+ const isEdit = groupDiv.select("input").empty();
800
+ if (!isEdit) return;
801
+ groupDiv.html("");
802
+ const input = groupDiv.append("input").attr("value", group.name).on("change", async () => {
803
+ const name = input.node().value;
804
+ if (name) group.name = name;
805
+ else input.node().value = group.name;
806
+ groupDiv.html("&nbsp;" + group.name);
807
+ });
808
+ input.node().focus();
809
+ input.node().select();
810
+ });
811
+ const tableDiv = div.append("div");
812
+ let buttons;
813
+ if (addGroup) {
814
+ const addGroupCallback = {
815
+ text: "Add to a group",
816
+ callback: (indexes) => {
817
+ const items = [];
818
+ for (const i of indexes) items.push(this.selectedItems[i].__data__);
819
+ const group2 = {
820
+ name: `Group ${this.scatter.config.groups.length + 1}`,
821
+ items,
822
+ index: this.scatter.config.groups.length
823
+ };
824
+ const filter = getFilter(getSamplelstTW([group2]));
825
+ addNewGroup(this.scatter.app, filter, this.scatter.state.groups);
826
+ }
827
+ };
828
+ buttons = [addGroupCallback];
829
+ }
830
+ const columnButton = {
831
+ text: "View",
832
+ callback: async (event, i) => {
833
+ const sample = group.items[i];
834
+ this.interactivity.openSampleView(sample);
835
+ }
836
+ };
837
+ const columnButtons = hasSampleName && this.hasSampleView ? [columnButton] : [];
838
+ renderTable({
839
+ rows,
840
+ columns,
841
+ div: tableDiv,
842
+ showLines: true,
843
+ //maxWidth: columns.length * '15' + 'vw',
844
+ maxHeight: "35vh",
845
+ buttons,
846
+ selectAll: true,
847
+ columnButtons
848
+ });
849
+ this.view.dom.tip.show(x, y, false, false);
850
+ function formatCell(column, name = "value") {
851
+ const dict = {};
852
+ dict[name] = column;
853
+ return dict;
854
+ }
855
+ }
856
+ };
857
+
858
+ // plots/scatter/model/scatterModel.ts
859
+ var import_d3_regression = __toESM(require_d3_regression(), 1);
860
+ var shapes = shapesArray;
861
+ var maxSvgSamplesCutoff = 2e4;
862
+ var noExpColor = "#F5F5F5";
863
+ var expColor = "#ff000d";
864
+ var ScatterModel = class {
865
+ constructor(scatter) {
866
+ this.filterSampleStr = null;
867
+ this.startGradient = {};
868
+ this.stopGradient = {};
869
+ this.scatter = scatter;
870
+ this.axisOffset = { x: 80, y: 30 };
871
+ this.is2DLarge = false;
872
+ this.is3D = false;
873
+ }
874
+ // creates an opts object for the vocabApi.someMethod(),
875
+ // may need to add a new method to client/termdb/vocabulary.js
876
+ // for now, just add methods to TermdbVocab,
877
+ // later on, add methods with same name to FrontendVocab
878
+ getDataRequestOpts() {
879
+ const c = this.scatter.config;
880
+ if (c.singleCellPlot) return c;
881
+ const coordTWs = [];
882
+ if (c.term) coordTWs.push(c.term);
883
+ if (c.term2) coordTWs.push(c.term2);
884
+ const filter = this.scatter.parentId ? this.scatter.state.termfilter.filter : this.scatter.getFilter();
885
+ const opts = {
886
+ name: c.name,
887
+ // the actual identifier of the plot, for retrieving data from server
888
+ colorTW: c.colorTW,
889
+ filter,
890
+ coordTWs,
891
+ chartType: this.scatter.type
892
+ };
893
+ if (this.scatter.state.termfilter.filter0) opts.filter0 = this.scatter.state.termfilter.filter0;
894
+ if (c.colorColumn) opts.colorColumn = c.colorColumn;
895
+ if (c.shapeTW) opts.shapeTW = c.shapeTW;
896
+ if (c.scaleDotTW) {
897
+ if (!c.scaleDotTW.q) c.scaleDotTW.q = {};
898
+ c.scaleDotTW.q.mode = "continuous";
899
+ opts.scaleDotTW = c.scaleDotTW;
900
+ }
901
+ if (c.term0) opts.divideByTW = c.term0;
902
+ opts.excludeOutliers = this.scatter.settings.excludeOutliers;
903
+ return opts;
904
+ }
905
+ async initData() {
906
+ try {
907
+ const reqOpts = this.getDataRequestOpts();
908
+ if (reqOpts.coordTWs?.length == 1 && this.scatter.type == "sampleScatter") return;
909
+ const data = await this.scatter.app.vocabApi.getScatterData(
910
+ reqOpts,
911
+ this.scatter.api?.getAbortSignal()
912
+ );
913
+ if ("error" in data) throw data.error;
914
+ this.charts = [];
915
+ this.range = data.range;
916
+ for (const [key, chartData] of Object.entries(data.result)) {
917
+ if (!Array.isArray(chartData.samples)) throw "data.samples[] not array";
918
+ this.createChart(key, chartData);
919
+ }
920
+ this.is3D = this.scatter.config.term0?.q.mode == "continuous";
921
+ this.initRanges();
922
+ } catch (e) {
923
+ if (this.scatter.app.isAbortError(e)) return;
924
+ console.error(e);
925
+ throw e.message || e;
926
+ }
927
+ }
928
+ createChart(id, data) {
929
+ const cohortSamples = data.samples.filter((sample) => "sampleId" in sample);
930
+ if (cohortSamples.length > maxSvgSamplesCutoff) this.is2DLarge = true;
931
+ const colorLegend = new Map(data.colorLegend);
932
+ const shapeLegend = new Map(data.shapeLegend);
933
+ this.charts.push({ id, data, cohortSamples, colorLegend, shapeLegend });
934
+ }
935
+ async initRanges() {
936
+ let samples = [];
937
+ for (const chart of this.charts) samples = samples.concat(chart.data.samples);
938
+ if (samples.length > maxSvgSamplesCutoff) this.is2DLarge = true;
939
+ if (samples.length == 0) return;
940
+ const s0 = samples[0];
941
+ const [xMin, xMax, yMin, yMax, zMin, zMax, scaleMin, scaleMax, geMin, geMax] = samples.reduce(
942
+ (s, d) => [
943
+ d.x < s[0] ? d.x : s[0],
944
+ d.x > s[1] ? d.x : s[1],
945
+ d.y < s[2] ? d.y : s[2],
946
+ d.y > s[3] ? d.y : s[3],
947
+ d.z < s[4] ? d.z : s[4],
948
+ d.z > s[5] ? d.z : s[5],
949
+ "scale" in d ? d.scale < s[6] ? d.scale : s[6] : Number.POSITIVE_INFINITY,
950
+ "scale" in d ? d.scale > s[7] ? d.scale : s[7] : Number.NEGATIVE_INFINITY,
951
+ "geneExp" in d ? d.geneExp < s[8] ? d.geneExp : s[8] : Number.POSITIVE_INFINITY,
952
+ "geneExp" in d ? d.geneExp > s[9] ? d.geneExp : s[9] : Number.NEGATIVE_INFINITY
953
+ ],
954
+ [s0.x, s0.x, s0.y, s0.y, s0.z, s0.z, s0.scale, s0.scale, s0.geneExp, s0.geneExp]
955
+ );
956
+ const settings = this.scatter.settings;
957
+ for (const chart of this.charts) {
958
+ chart.ranges = {
959
+ xMin: settings.minXScale != null ? settings.minXScale : settings.useGlobalMinMax ? this.range.xMin : xMin,
960
+ xMax: settings.maxXScale != null ? settings.maxXScale : settings.useGlobalMinMax ? this.range.xMax : xMax,
961
+ yMin: settings.minYScale != null ? settings.minYScale : settings.useGlobalMinMax ? this.range.yMin : yMin,
962
+ yMax: settings.maxYScale != null ? settings.maxYScale : settings.useGlobalMinMax ? this.range.yMax : yMax,
963
+ zMin,
964
+ zMax,
965
+ scaleMin,
966
+ scaleMax,
967
+ geMin,
968
+ geMax
969
+ };
970
+ }
971
+ }
972
+ getOpacity(c) {
973
+ if ("sampleId" in c) {
974
+ const hidden = c.hidden?.["category"] || c.hidden?.["shape"];
975
+ if (this.filterSampleStr) {
976
+ if (!c.sample?.toLowerCase().includes(this.filterSampleStr.toLowerCase())) {
977
+ if (hidden) return 0;
978
+ else return 0.1;
979
+ } else return 1.2;
980
+ }
981
+ const opacity = hidden ? 0 : this.scatter.settings.opacity;
982
+ return opacity;
983
+ }
984
+ const refOpacity = this.scatter.settings.showRef ? this.scatter.settings.opacity : 0;
985
+ return refOpacity;
986
+ }
987
+ getShape(chart, c) {
988
+ const index = chart.shapeLegend.get(c.shape).shape % shapes.length;
989
+ return shapes[index];
990
+ }
991
+ /** Returns the calculated coordinate or the min/max axis
992
+ * cap set by the user. */
993
+ getCoordinates(chart, c) {
994
+ const cx = () => {
995
+ return getCoordinate(c.x, this.scatter.settings.minXScale, this.scatter.settings.maxXScale);
996
+ };
997
+ const cy = () => {
998
+ return getCoordinate(c.y, this.scatter.settings.minYScale, this.scatter.settings.maxYScale);
999
+ };
1000
+ const x = chart.xAxisScale(cx());
1001
+ const y = chart.yAxisScale(cy());
1002
+ return { x, y };
1003
+ }
1004
+ getScale(chart, c, factor = 1) {
1005
+ const isRef = !("sampleId" in c);
1006
+ let scale;
1007
+ if (!this.scatter.config.scaleDotTW || isRef) {
1008
+ scale = "sampleId" in c ? this.scatter.settings.size : this.scatter.settings.refSize;
1009
+ } else {
1010
+ const range = this.scatter.settings.maxShapeSize - this.scatter.settings.minShapeSize;
1011
+ if (this.scatter.settings.scaleDotOrder == "Ascending")
1012
+ scale = this.scatter.settings.minShapeSize + (c.scale - chart.ranges.scaleMin) / (chart.ranges.scaleMax - chart.ranges.scaleMin) * range;
1013
+ else
1014
+ scale = this.scatter.settings.maxShapeSize - (c.scale - chart.ranges.scaleMin) / (chart.ranges.scaleMax - chart.ranges.scaleMin) * range;
1015
+ }
1016
+ const zoom = this.is2DLarge ? this.scatter.zoom : 1;
1017
+ scale = zoom * scale * factor / 3;
1018
+ if (this.filterSampleStr) {
1019
+ if (c.sample?.toLowerCase().includes(this.filterSampleStr.toLowerCase())) scale = scale * 2;
1020
+ else scale = scale * 0.8;
1021
+ }
1022
+ return scale;
1023
+ }
1024
+ transform(chart, c, factor = 1) {
1025
+ const scale = this.getScale(chart, c, factor);
1026
+ const particleSize = 16 * scale;
1027
+ const { x, y } = this.getCoordinates(chart, c);
1028
+ const offSetX = x - particleSize / 2;
1029
+ const offSetY = y - particleSize / 2;
1030
+ const transform = `translate(${offSetX},${offSetY}) scale(${scale})`;
1031
+ return transform;
1032
+ }
1033
+ getColor(c, chart) {
1034
+ if (this.scatter.config.colorTW?.term.type == SINGLECELL_GENE_EXPRESSION) {
1035
+ let color;
1036
+ if (!c.geneExp) color = noExpColor;
1037
+ else if (c.geneExp > chart.ranges.geMax) color = expColor;
1038
+ else color = chart.colorGenerator(c.geneExp);
1039
+ return color;
1040
+ }
1041
+ if (this.scatter.config.colorTW?.q.mode == "continuous" && "sampleId" in c) {
1042
+ const [min, max2] = chart.colorGenerator.domain();
1043
+ if (c.category < min) return chart.colorGenerator(min);
1044
+ if (c.category > max2) return chart.colorGenerator(max2);
1045
+ const color = chart.colorGenerator(c.category);
1046
+ return color;
1047
+ }
1048
+ if (c.category == "Default") return this.scatter.settings.defaultColor;
1049
+ const category = chart.colorLegend.get(c.category);
1050
+ return category.color;
1051
+ }
1052
+ async addGroup(group) {
1053
+ group.plotId = this.scatter.id;
1054
+ await this.scatter.app.vocabApi.addGroup(group);
1055
+ }
1056
+ getStrokeWidth(c) {
1057
+ const opacity = this.getOpacity(c);
1058
+ if (opacity <= 0.2)
1059
+ return 0;
1060
+ if (opacity == 1.2)
1061
+ return 2;
1062
+ return 1;
1063
+ }
1064
+ async processData() {
1065
+ const term0Values = this.scatter.config.term0?.term.values;
1066
+ if (term0Values) {
1067
+ const orderedLabels = Object.values(term0Values).sort(
1068
+ (a, b) => "order" in a && "order" in b ? a.order - b.order : 0
1069
+ );
1070
+ this.charts.sort(
1071
+ (a, b) => orderedLabels.findIndex((v) => v.label == a.id) - orderedLabels.findIndex((v) => v.label == b.id)
1072
+ );
1073
+ }
1074
+ for (const chart of this.charts) {
1075
+ this.initAxes(chart);
1076
+ const regressionType = this.scatter.settings.regression;
1077
+ if (!regressionType || regressionType == "None") continue;
1078
+ let regression;
1079
+ const data = [];
1080
+ await chart.cohortSamples.forEach((c) => {
1081
+ data.push(this.getCoordinates(chart, c));
1082
+ });
1083
+ let regressionCurve;
1084
+ if (regressionType == "Polynomial") {
1085
+ regression = (0, import_d3_regression.regressionPoly)().x((c) => c.x).y((c) => c.y).order(3);
1086
+ regressionCurve = regression(data);
1087
+ } else if (regressionType == "Lowess") {
1088
+ const X = [], Y = [];
1089
+ for (const sample of data) {
1090
+ X.push(sample.x);
1091
+ Y.push(sample.y);
1092
+ }
1093
+ regressionCurve = await this.scatter.app.vocabApi.getLowessCurve({ coords: { X, Y } });
1094
+ } else {
1095
+ throw `unsupported regression type='${regressionType}'`;
1096
+ }
1097
+ chart.regressionCurve = regressionCurve;
1098
+ }
1099
+ }
1100
+ initAxes(chart) {
1101
+ const config = this.scatter.config;
1102
+ if (chart.data.samples.length == 0) return;
1103
+ const offsetX = this.axisOffset.x;
1104
+ const offsetY = this.axisOffset.y;
1105
+ const xMin = chart.ranges.xMin;
1106
+ const xMax = chart.ranges.xMax;
1107
+ const yMin = chart.ranges.yMin;
1108
+ const yMax = chart.ranges.yMax;
1109
+ const extraSpaceX = this.scatter.settings.minXScale != null || this.scatter.settings.maxXScale != null ? 0 : (xMax - xMin) * 0.01;
1110
+ const extraSpaceY = this.scatter.settings.minYScale != null || this.scatter.settings.maxYScale != null ? 0 : (yMax - yMin) * 0.01;
1111
+ chart.xAxisScale = linear().domain([xMin - extraSpaceX, xMax + extraSpaceX]).range([offsetX, this.scatter.settings.svgw + offsetX]);
1112
+ if (this.scatter.config.term && this.scatter.config.term.term.type == "date") {
1113
+ const xMinDate = getDateFromNumber(xMin - extraSpaceX);
1114
+ const xMaxDate = getDateFromNumber(xMax + extraSpaceX);
1115
+ chart.xAxisScaleTime = time().domain([xMinDate, xMaxDate]).range([offsetX, this.scatter.settings.svgw + offsetX]);
1116
+ chart.axisBottom = axisBottom(chart.xAxisScaleTime);
1117
+ } else chart.axisBottom = axisBottom(chart.xAxisScale);
1118
+ const svgh = this.scatter.settings.svgh;
1119
+ chart.yAxisScale = linear().domain([yMax + extraSpaceY, yMin - extraSpaceY]).range([offsetY, svgh + offsetY]);
1120
+ if (this.scatter.config.term2 && this.scatter.config.term2.term.type == "date") {
1121
+ const yMinDate = getDateFromNumber(yMin - extraSpaceY);
1122
+ const yMaxDate = getDateFromNumber(yMax + extraSpaceY);
1123
+ chart.yAxisScaleTime = time().domain([yMinDate, yMaxDate]).range([offsetY, this.scatter.settings.svgh + offsetY]);
1124
+ chart.axisLeft = axisLeft(chart.yAxisScaleTime);
1125
+ } else chart.axisLeft = axisLeft(chart.yAxisScale);
1126
+ chart.zAxisScale = linear().domain([chart.ranges.zMin, chart.ranges.zMax]).range([0, this.scatter.settings.svgd]);
1127
+ const gradientColor = rgb(this.scatter.settings.defaultColor);
1128
+ if (!config.startColor) {
1129
+ config.startColor = {};
1130
+ config.stopColor = {};
1131
+ }
1132
+ if (!config.startColor[chart.id]) {
1133
+ config.startColor[chart.id] = config.colorTW?.term.type == SINGLECELL_GENE_EXPRESSION ? noExpColor : config.colorTW?.term.continuousColorScale?.minColor || gradientColor.brighter().brighter().toString();
1134
+ }
1135
+ if (!config.stopColor[chart.id]) {
1136
+ config.stopColor[chart.id] = config.colorTW?.term.type == SINGLECELL_GENE_EXPRESSION ? expColor : config.colorTW?.term.continuousColorScale?.maxColor || gradientColor.darker().toString();
1137
+ }
1138
+ if (config.colorTW?.q.mode === "continuous") {
1139
+ let colorValues;
1140
+ if (config.colorTW.term.type == SINGLECELL_GENE_EXPRESSION) {
1141
+ colorValues = [chart.ranges.geMin, chart.ranges.geMax];
1142
+ } else {
1143
+ colorValues = chart.cohortSamples.filter(
1144
+ (s) => !this.scatter.config.colorTW.term.values || !(s.category in this.scatter.config.colorTW.term.values)
1145
+ ).map((s) => s.category).sort((a, b) => a - b);
1146
+ }
1147
+ chart.colorValues = colorValues;
1148
+ let min, max2, index;
1149
+ const settings = this.scatter.config.settings.sampleScatter;
1150
+ switch (settings.colorScaleMode) {
1151
+ // Fixed mode: Use user-defined min/max values
1152
+ // This is useful when you want consistent scaling across different views
1153
+ case "fixed":
1154
+ min = settings.colorScaleMinFixed;
1155
+ max2 = settings.colorScaleMaxFixed;
1156
+ break;
1157
+ case "percentile":
1158
+ min = colorValues[0];
1159
+ index = Math.floor(colorValues.length * settings.colorScalePercentile / 100);
1160
+ max2 = colorValues[index];
1161
+ break;
1162
+ case "auto":
1163
+ default:
1164
+ min = colorValues[0];
1165
+ max2 = colorValues[colorValues.length - 1];
1166
+ break;
1167
+ }
1168
+ chart.colorGenerator = linear().domain([min, max2]).range([this.scatter.config.startColor[chart.id], this.scatter.config.stopColor[chart.id]]);
1169
+ chart.currentColorRange = { min, max: max2 };
1170
+ }
1171
+ }
1172
+ };
1173
+ function getCoordinate(val, min, max2) {
1174
+ if (min != null && val < min) return min;
1175
+ if (max2 != null && val > max2) return max2;
1176
+ return val;
1177
+ }
1178
+
1179
+ // plots/scatter/viewmodel/scatterLegendInteractivity.ts
1180
+ var ScatterLegendInteractivity = class {
1181
+ constructor(scatter) {
1182
+ this.scatter = scatter;
1183
+ }
1184
+ onLegendClick(chart, name, key, e, category) {
1185
+ const tw = this.scatter.config[name];
1186
+ const isColorTW = name == "colorTW";
1187
+ const hidden = tw.q.hiddenValues ? key in tw.q.hiddenValues : false;
1188
+ const hiddenCount = tw.q.hiddenValues ? Object.keys(tw.q.hiddenValues).length : 0;
1189
+ if (hidden && hiddenCount == 1) {
1190
+ this.hideCategory(tw, key, false);
1191
+ this.dispatchConfig(name, tw);
1192
+ return;
1193
+ }
1194
+ const menu = new Menu({ padding: "0px" });
1195
+ const div = menu.d.append("div");
1196
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text(hidden ? "Show" : "Hide").on("click", () => {
1197
+ this.hideCategory(tw, key, !hidden);
1198
+ menu.hide();
1199
+ this.dispatchConfig(name, tw);
1200
+ });
1201
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Show only").on("click", () => {
1202
+ const map = name == "colorTW" ? chart.colorLegend : chart.shapeLegend;
1203
+ for (const mapKey of map.keys())
1204
+ this.hideCategory(
1205
+ tw,
1206
+ mapKey,
1207
+ tw.term.type == "geneVariant" && tw.q.type == "values" ? !mapKey.startsWith(key) : mapKey != key
1208
+ );
1209
+ menu.hide();
1210
+ this.dispatchConfig(name, tw);
1211
+ });
1212
+ if (hiddenCount > 1)
1213
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Show all").on("click", () => {
1214
+ menu.hide();
1215
+ const map = isColorTW ? chart.colorLegend : chart.shapeLegend;
1216
+ for (const mapKey of map.keys()) this.hideCategory(tw, mapKey, false);
1217
+ this.dispatchConfig(name, tw);
1218
+ });
1219
+ if (isColorTW) {
1220
+ const color = rgb(category.color).formatHex();
1221
+ const input = div.append("div").attr("class", "sja_sharp_border").style("padding", "0px 10px").text("Color:").append("input").attr("type", "color").attr("value", color).on("change", () => {
1222
+ this.changeColor(category.key, input.node().value);
1223
+ menu.hide();
1224
+ });
1225
+ }
1226
+ if (!isColorTW) {
1227
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Change shape").on("click", () => {
1228
+ div.selectAll("*").remove();
1229
+ const callback = (index) => {
1230
+ this.changeShape(category.key, index);
1231
+ menu.hide();
1232
+ };
1233
+ shapeSelector(div, callback);
1234
+ });
1235
+ }
1236
+ menu.showunder(e.target);
1237
+ }
1238
+ async changeShape(key, shape) {
1239
+ const tw = this.scatter.config.shapeTW;
1240
+ if (!tw.term.values) tw.term.values = {};
1241
+ if (!tw.term.values[key]) tw.term.values[key] = {};
1242
+ tw.term.values[key].shape = shape;
1243
+ await this.scatter.app.dispatch({
1244
+ type: "plot_edit",
1245
+ id: this.scatter.id,
1246
+ config: { shapeTW: tw }
1247
+ });
1248
+ }
1249
+ dispatchConfig(name, tw) {
1250
+ this.scatter.app.dispatch({
1251
+ type: "plot_edit",
1252
+ id: this.scatter.id,
1253
+ config: { [name]: tw }
1254
+ });
1255
+ }
1256
+ hideCategory(tw, key, hide) {
1257
+ if (!tw.q) tw.q = {};
1258
+ if (!tw.q.hiddenValues) tw.q.hiddenValues = {};
1259
+ const value = !(tw.term.type == "geneVariant" && tw.q.type == "values") && tw.term.values[key] ? tw.term.values[key] : { key, label: key };
1260
+ if (!hide) delete tw.q.hiddenValues[key];
1261
+ else tw.q.hiddenValues[key] = value;
1262
+ if (key == "Ref") {
1263
+ this.scatter.settings.showRef = !hide;
1264
+ this.scatter.app.dispatch({
1265
+ type: "plot_edit",
1266
+ id: this.scatter.id,
1267
+ config: {
1268
+ settings: { sampleScatter: this.scatter.settings }
1269
+ }
1270
+ });
1271
+ }
1272
+ }
1273
+ changeGradientColor(chart, color, idx) {
1274
+ const hexColor = rgb(color).formatHex();
1275
+ const colorKey = idx == 0 ? "startColor" : "stopColor";
1276
+ this.scatter.config[colorKey][chart.id] = hexColor;
1277
+ const range = chart.currentColorRange || chart.colorGenerator.domain();
1278
+ chart.colorGenerator = linear().domain(range).range([this.scatter.config.startColor[chart.id], this.scatter.config.stopColor[chart.id]]);
1279
+ this.scatter.app.dispatch({
1280
+ type: "plot_edit",
1281
+ id: this.scatter.id,
1282
+ config: this.scatter.config
1283
+ });
1284
+ }
1285
+ async changeColor(key, color) {
1286
+ const tw = this.scatter.config.colorTW;
1287
+ if (!tw.term.values) tw.term.values = {};
1288
+ if (!tw.term.values[key]) tw.term.values[key] = {};
1289
+ tw.term.values[key].color = color;
1290
+ await this.scatter.app.dispatch({
1291
+ type: "plot_edit",
1292
+ id: this.scatter.id,
1293
+ config: { colorTW: tw }
1294
+ });
1295
+ }
1296
+ };
1297
+
1298
+ // plots/scatter/view/scatterView.ts
1299
+ var minShapeSize = 0.2;
1300
+ var maxShapeSize = 6;
1301
+ var ScatterView = class {
1302
+ constructor(scatter) {
1303
+ this.opts = scatter.opts;
1304
+ this.scatter = scatter;
1305
+ const leftDiv = this.opts.holder.insert("div").style("display", "inline-block");
1306
+ const controlsHolder = leftDiv.insert("div").style("display", "inline-block");
1307
+ const rightDiv = this.opts.holder.insert("div").style("display", "inline-block").style("vertical-align", "top");
1308
+ const loadingDiv = rightDiv.append("div").style("display", "inline-block").style("padding", "24px").text("Loading ...");
1309
+ const bannerDiv = rightDiv.append("div").style("display", "none").style("text-align", "center").style("padding", "24px").style("font-size", "16px");
1310
+ const headerDiv = rightDiv.append("div");
1311
+ const mainDiv = rightDiv.append("div").style("display", "flex").style("flex-direction", "row").style("flex-wrap", "wrap").style("max-width", "100vw");
1312
+ this.dom = {
1313
+ loadingDiv,
1314
+ bannerDiv,
1315
+ headerDiv,
1316
+ mainDiv,
1317
+ header: this.opts.header,
1318
+ //holder,
1319
+ tip: new Menu({ padding: "0px" }),
1320
+ tooltip: new Menu({ padding: "2px", offsetX: 10, offsetY: 0 }),
1321
+ controlsHolder,
1322
+ toolsDiv: leftDiv.insert("div")
1323
+ };
1324
+ if (this.dom.header) {
1325
+ const chartName = splitCamelCase(this.scatter.type).toUpperCase();
1326
+ this.dom.header.html(
1327
+ `${this.scatter.config.name || ""} <span style="opacity:.6;font-size:.7em;margin-left:10px;">${chartName}</span>`
1328
+ );
1329
+ }
1330
+ }
1331
+ getControlInputs() {
1332
+ const hasRef = this.scatter.model.charts[0]?.data.samples.find((s) => !("sampleId" in s)) || false;
1333
+ const scaleDotOption = {
1334
+ type: "term",
1335
+ configKey: "scaleDotTW",
1336
+ chartType: "sampleScatter",
1337
+ usecase: { target: "sampleScatter", detail: "numeric" },
1338
+ title: "Scale sample by term value",
1339
+ label: "Scale by",
1340
+ vocabApi: this.scatter.app.vocabApi,
1341
+ numericEditMenuVersion: ["continuous"],
1342
+ //Eventually this will be corrected with usecase.detail
1343
+ //When single cell, only relevant terms will be displayed
1344
+ //in the tree
1345
+ getDisplayStyle: () => {
1346
+ return this.scatter.config?.singleCellPlot ? "none" : "";
1347
+ }
1348
+ };
1349
+ const shapeOption = {
1350
+ type: "term",
1351
+ configKey: "shapeTW",
1352
+ chartType: "sampleScatter",
1353
+ usecase: { target: "sampleScatter", detail: "shapeTW" },
1354
+ title: "Categories to assign a shape",
1355
+ label: "Shape",
1356
+ vocabApi: this.scatter.app.vocabApi,
1357
+ numericEditMenuVersion: ["discrete"],
1358
+ //Eventually this will be corrected with usecase.detail
1359
+ //When single cell, only relevant terms will be displayed
1360
+ //in the tree
1361
+ getDisplayStyle: () => {
1362
+ return this.scatter.config?.singleCellPlot ? "none" : "";
1363
+ },
1364
+ processInput: async (tw) => {
1365
+ if (isNumericTerm(tw?.term)) {
1366
+ tw.q = { mode: "discrete" };
1367
+ await fillTermWrapper(tw, this.scatter.app.vocabApi);
1368
+ }
1369
+ }
1370
+ };
1371
+ const shapeSizeOption = {
1372
+ label: `${this.scatter.settings.itemLabel} size`,
1373
+ type: "number",
1374
+ chartType: "sampleScatter",
1375
+ settingsKey: "size",
1376
+ title: `${this.scatter.settings.itemLabel} size, represents the factor used to scale the ${this.scatter.settings.itemLabel.toLowerCase()}`,
1377
+ min: 0,
1378
+ step: 0.1
1379
+ };
1380
+ const step = (maxShapeSize - minShapeSize) / 10;
1381
+ const minShapeSizeOption = {
1382
+ label: "Min size",
1383
+ type: "number",
1384
+ chartType: "sampleScatter",
1385
+ settingsKey: "minShapeSize",
1386
+ title: "Minimum sample size",
1387
+ min: minShapeSize,
1388
+ max: maxShapeSize,
1389
+ step
1390
+ };
1391
+ const maxShapeSizeOption = {
1392
+ label: "Max size",
1393
+ type: "number",
1394
+ chartType: "sampleScatter",
1395
+ settingsKey: "maxShapeSize",
1396
+ title: "Maximum sample size",
1397
+ min: minShapeSize,
1398
+ max: maxShapeSize,
1399
+ step
1400
+ };
1401
+ const orientation = {
1402
+ label: "Scale order",
1403
+ type: "radio",
1404
+ chartType: "sampleScatter",
1405
+ settingsKey: "scaleDotOrder",
1406
+ options: [
1407
+ { label: "Ascending", value: "Ascending" },
1408
+ { label: "Descending", value: "Descending" }
1409
+ ]
1410
+ };
1411
+ const refSizeOption = {
1412
+ label: "Reference size",
1413
+ type: "number",
1414
+ chartType: "sampleScatter",
1415
+ settingsKey: "refSize",
1416
+ title: "It represents the area of the reference symbol in square pixels",
1417
+ min: 0,
1418
+ step: 0.1
1419
+ };
1420
+ const showAxes = {
1421
+ boxLabel: "",
1422
+ label: "Show axes",
1423
+ type: "checkbox",
1424
+ chartType: "sampleScatter",
1425
+ settingsKey: "showAxes",
1426
+ title: `Option to show/hide plot axes`,
1427
+ testid: "showAxes"
1428
+ };
1429
+ let specialCase = "default";
1430
+ if (this.scatter.config?.singleCellPlot) {
1431
+ specialCase = {
1432
+ type: "singleCell",
1433
+ config: this.scatter.config.singleCellPlot
1434
+ };
1435
+ }
1436
+ const inputs = [
1437
+ {
1438
+ type: "term",
1439
+ configKey: "colorTW",
1440
+ chartType: "sampleScatter",
1441
+ usecase: { target: "sampleScatter", detail: "colorTW", specialCase },
1442
+ title: "Categories to color the samples",
1443
+ label: "Color",
1444
+ vocabApi: this.scatter.app.vocabApi,
1445
+ numericEditMenuVersion: ["continuous", "discrete"]
1446
+ },
1447
+ {
1448
+ label: "Opacity",
1449
+ type: "number",
1450
+ chartType: "sampleScatter",
1451
+ settingsKey: "opacity",
1452
+ title: "It represents the opacity of the elements",
1453
+ min: 0,
1454
+ max: 1,
1455
+ step: 0.1
1456
+ },
1457
+ {
1458
+ label: "Chart width",
1459
+ type: "number",
1460
+ chartType: "sampleScatter",
1461
+ settingsKey: "svgw"
1462
+ },
1463
+ {
1464
+ label: "Chart height",
1465
+ type: "number",
1466
+ chartType: "sampleScatter",
1467
+ settingsKey: "svgh"
1468
+ },
1469
+ {
1470
+ label: "Show contour map",
1471
+ boxLabel: "",
1472
+ type: "checkbox",
1473
+ chartType: "sampleScatter",
1474
+ settingsKey: "showContour",
1475
+ title: "Shows the density of point clouds. If 'Color' is used in continous mode, it uses it to weight the points when calculating the density contours. If 'Z/Divide by' is added in continous mode, it used it instead."
1476
+ },
1477
+ {
1478
+ label: "Save zoom transform",
1479
+ boxLabel: "",
1480
+ type: "checkbox",
1481
+ chartType: "sampleScatter",
1482
+ settingsKey: "saveZoomTransform",
1483
+ title: `Option to save the zoom transformation in the state. Needed if you want to save a session with the actual zoom and pan applied`,
1484
+ processInput: (value) => this.saveZoomTransform(value)
1485
+ }
1486
+ ];
1487
+ if (this.scatter.settings.showContour)
1488
+ inputs.push(
1489
+ {
1490
+ label: "Color contours",
1491
+ boxLabel: "",
1492
+ type: "checkbox",
1493
+ chartType: "sampleScatter",
1494
+ settingsKey: "colorContours"
1495
+ },
1496
+ {
1497
+ label: "Contour bandwidth",
1498
+ type: "number",
1499
+ chartType: "sampleScatter",
1500
+ settingsKey: "contourBandwidth",
1501
+ title: "Reduce to increase resolution.",
1502
+ min: 5,
1503
+ max: 50,
1504
+ step: 5
1505
+ },
1506
+ {
1507
+ label: "Contour thresholds",
1508
+ type: "number",
1509
+ chartType: "sampleScatter",
1510
+ settingsKey: "contourThresholds",
1511
+ title: "Increase to enhance contour detail.",
1512
+ min: 5,
1513
+ max: 30,
1514
+ step: 5
1515
+ }
1516
+ );
1517
+ if (this.scatter.config.sampleCategory) {
1518
+ const options = Object.values(this.scatter.config.sampleCategory.tw.term.values).map((v) => ({
1519
+ label: v.label || v.key,
1520
+ value: v.key
1521
+ }));
1522
+ if (this.scatter.config.sampleCategory.order)
1523
+ options.sort((elem1, elem2) => {
1524
+ const i1 = this.scatter.config.sampleCategory.order.indexOf(elem1.value);
1525
+ const i2 = this.scatter.config.sampleCategory.order.indexOf(elem2.value);
1526
+ if (i1 < i2) return -1;
1527
+ return 1;
1528
+ });
1529
+ if (!this.scatter.settings.sampleCategory)
1530
+ this.scatter.settings.sampleCategory = this.scatter.config.sampleCategory.defaultValue || "";
1531
+ options.push({ label: "All", value: "" });
1532
+ const sampleCategory = {
1533
+ label: "Sample type",
1534
+ type: "dropdown",
1535
+ chartType: "sampleScatter",
1536
+ settingsKey: "sampleCategory",
1537
+ options
1538
+ };
1539
+ inputs.push(sampleCategory);
1540
+ }
1541
+ if (!this.scatter.model.is2DLarge && !this.scatter.config.singleCellPlot) {
1542
+ const isPremade = this.scatter.config.name !== void 0 && !this.scatter.config.term;
1543
+ inputs.unshift({
1544
+ type: "term",
1545
+ configKey: "term0",
1546
+ chartType: "sampleScatter",
1547
+ usecase: { target: "sampleScatter", detail: "term0" },
1548
+ title: "Term to to divide by categories or to use as Z coordinate",
1549
+ label: "Z / Divide by",
1550
+ vocabApi: this.scatter.app.vocabApi,
1551
+ // do not allow 'continuous' mode for now, even if it can be rendered along z-axis,
1552
+ // since clicking to barchart/violin/boxplot tab from the scatter tab does not
1553
+ // automatically convert the divide-by term to discrete; a continuous mode in those
1554
+ // other charts leads to nonsensical chart per unique float/integer value
1555
+ numericEditMenuVersion: ["discrete"],
1556
+ processInput: (tw) => {
1557
+ if (!isPremade && isNumericTerm(tw?.term)) tw.q = { mode: "continuous" };
1558
+ }
1559
+ });
1560
+ } else if (!this.scatter.config.singleCellPlot) {
1561
+ inputs.push(
1562
+ {
1563
+ label: "Sample size",
1564
+ type: "number",
1565
+ chartType: "sampleScatter",
1566
+ settingsKey: "threeSize",
1567
+ title: "Sample size",
1568
+ min: 0,
1569
+ max: 1,
1570
+ step: 1e-3
1571
+ },
1572
+ {
1573
+ label: "Field of Vision",
1574
+ type: "number",
1575
+ chartType: "sampleScatter",
1576
+ settingsKey: "threeFOV",
1577
+ title: "Field of Vision",
1578
+ min: 50,
1579
+ max: 90,
1580
+ step: 1
1581
+ }
1582
+ );
1583
+ }
1584
+ if (this.scatter.config.term) {
1585
+ inputs.unshift(
1586
+ ...[
1587
+ {
1588
+ type: "term",
1589
+ configKey: "term",
1590
+ chartType: "sampleScatter",
1591
+ usecase: { target: "sampleScatter", detail: "numeric" },
1592
+ title: "X coordinate to plot the samples",
1593
+ label: "X",
1594
+ vocabApi: this.scatter.app.vocabApi,
1595
+ menuOptions: "!remove",
1596
+ numericEditMenuVersion: ["continuous"]
1597
+ },
1598
+ {
1599
+ type: "term",
1600
+ configKey: "term2",
1601
+ chartType: "sampleScatter",
1602
+ usecase: { target: "sampleScatter", detail: "numeric" },
1603
+ title: "Y coordinate to plot the samples",
1604
+ label: "Y",
1605
+ vocabApi: this.scatter.app.vocabApi,
1606
+ menuOptions: "!remove",
1607
+ numericEditMenuVersion: ["continuous"]
1608
+ }
1609
+ ]
1610
+ );
1611
+ if (!this.scatter.model.is3D) {
1612
+ inputs.splice(4, 0, shapeOption);
1613
+ inputs.splice(5, 0, scaleDotOption);
1614
+ if (this.scatter.config.scaleDotTW) {
1615
+ inputs.splice(6, 0, minShapeSizeOption);
1616
+ inputs.splice(7, 0, maxShapeSizeOption);
1617
+ inputs.splice(8, 0, orientation);
1618
+ if (hasRef) inputs.splice(9, 0, refSizeOption);
1619
+ } else {
1620
+ inputs.splice(6, 0, shapeSizeOption);
1621
+ if (hasRef) inputs.splice(7, 0, refSizeOption);
1622
+ }
1623
+ inputs.push({
1624
+ label: "Show regression",
1625
+ type: "dropdown",
1626
+ chartType: "sampleScatter",
1627
+ settingsKey: "regression",
1628
+ options: [
1629
+ { label: "None", value: "None" },
1630
+ //{ label: 'Loess', value: 'Loess' },
1631
+ { label: "Lowess", value: "Lowess" },
1632
+ { label: "Polynomial", value: "Polynomial" }
1633
+ ]
1634
+ });
1635
+ } else {
1636
+ inputs.push({
1637
+ label: "Chart depth",
1638
+ type: "number",
1639
+ chartType: "sampleScatter",
1640
+ settingsKey: "svgd"
1641
+ });
1642
+ inputs.push({
1643
+ label: "Field of vision",
1644
+ title: "Camera field of view, in degrees",
1645
+ type: "number",
1646
+ chartType: "sampleScatter",
1647
+ settingsKey: "fov"
1648
+ });
1649
+ }
1650
+ inputs.push(showAxes, ...this.getMinMaxInputs());
1651
+ inputs.push({
1652
+ label: "Default color",
1653
+ type: "color",
1654
+ chartType: "sampleScatter",
1655
+ settingsKey: "defaultColor"
1656
+ });
1657
+ } else if (!this.scatter.model.is2DLarge) {
1658
+ inputs.splice(2, 0, shapeOption);
1659
+ inputs.splice(3, 0, scaleDotOption);
1660
+ if (this.scatter.config.scaleDotTW) {
1661
+ inputs.splice(4, 0, minShapeSizeOption);
1662
+ inputs.splice(5, 0, maxShapeSizeOption);
1663
+ inputs.splice(6, 0, orientation);
1664
+ if (hasRef) inputs.splice(7, 0, refSizeOption);
1665
+ } else {
1666
+ inputs.splice(4, 0, shapeSizeOption);
1667
+ if (hasRef) inputs.splice(5, 0, refSizeOption);
1668
+ }
1669
+ inputs.push(showAxes);
1670
+ }
1671
+ this.mayAddControlLabels(inputs);
1672
+ return inputs;
1673
+ }
1674
+ getMinMaxInputs() {
1675
+ const xMin = roundValueAuto(this.scatter.model.range.xMin);
1676
+ const xMax = roundValueAuto(this.scatter.model.range.xMax);
1677
+ const xStep = (xMax - xMin) / 10;
1678
+ const yMin = roundValueAuto(this.scatter.model.range.yMin);
1679
+ const yMax = roundValueAuto(this.scatter.model.range.yMax);
1680
+ const yStep = (yMax - yMin) / 10;
1681
+ const inputs = [
1682
+ {
1683
+ label: "X axis minimum",
1684
+ type: "number",
1685
+ chartType: this.scatter.type,
1686
+ settingsKey: "minXScale",
1687
+ title: `Set the minimum X axis value between ${xMin} and ${xMax}`,
1688
+ placeholder: `${xMin}`,
1689
+ min: xMin,
1690
+ max: xMax,
1691
+ step: xStep
1692
+ },
1693
+ {
1694
+ label: "X axis maximum",
1695
+ type: "number",
1696
+ chartType: this.scatter.type,
1697
+ settingsKey: "maxXScale",
1698
+ title: `Set the maximum X axis value between ${xMin} and ${xMax}`,
1699
+ placeholder: `${xMax}`,
1700
+ min: xMin,
1701
+ max: xMax,
1702
+ step: xStep,
1703
+ processInput: (value) => {
1704
+ const n = this.dom.controlsHolder.selectAll("input").filter(function() {
1705
+ return this.placeholder == `${xMax}`;
1706
+ });
1707
+ if (!n.node().value) return xMax;
1708
+ else return value;
1709
+ }
1710
+ },
1711
+ {
1712
+ label: "Y axis minimum",
1713
+ type: "number",
1714
+ chartType: this.scatter.type,
1715
+ settingsKey: "minYScale",
1716
+ title: `Set the minimum Y axis value between ${yMin} and ${yMax}`,
1717
+ placeholder: `${yMin}`,
1718
+ min: yMin,
1719
+ max: yMax,
1720
+ step: yStep
1721
+ },
1722
+ {
1723
+ label: "Y axis maximum",
1724
+ type: "number",
1725
+ chartType: this.scatter.type,
1726
+ settingsKey: "maxYScale",
1727
+ title: `Set the maximum Y axis value between ${yMin} and ${yMax}`,
1728
+ placeholder: `${yMax}`,
1729
+ min: yMin,
1730
+ max: yMax,
1731
+ step: yStep,
1732
+ processInput: (value) => {
1733
+ const n = this.dom.controlsHolder.selectAll("input").filter(function() {
1734
+ return this.placeholder == `${yMax}`;
1735
+ });
1736
+ if (!n.node().value) return yMax;
1737
+ else return value;
1738
+ }
1739
+ }
1740
+ ];
1741
+ return inputs;
1742
+ }
1743
+ mayAddControlLabels(inputs) {
1744
+ const controlLabels = structuredClone(this.scatter.config.controlLabels);
1745
+ if (!controlLabels) return;
1746
+ let term1input, term2input, term0input;
1747
+ for (const i of inputs) {
1748
+ if (i.configKey == "term") term1input = i;
1749
+ else if (i.configKey == "term2") term2input = i;
1750
+ else if (i.configKey == "term0") term0input = i;
1751
+ }
1752
+ if (term1input && term2input) {
1753
+ if (controlLabels.term1) term1input.label = controlLabels.term1.label + " (X)";
1754
+ if (controlLabels.term2) term2input.label = controlLabels.term2.label + " (Y)";
1755
+ if (term0input && controlLabels.term0) term0input.label = controlLabels.term0.label + " (Z)";
1756
+ }
1757
+ }
1758
+ saveZoomTransform(value) {
1759
+ if (value) this.scatter.vm.scatterZoom.saveZoomTransform();
1760
+ return value;
1761
+ }
1762
+ };
1763
+ function splitCamelCase(text) {
1764
+ return text.split(/(?=[A-Z])/).join(" ");
1765
+ }
1766
+
1767
+ // plots/scatter/viewmodel/scatterLegend.ts
1768
+ var ScatterLegend = class {
1769
+ constructor(scatter) {
1770
+ this.scatter = scatter;
1771
+ this.vm = scatter.vm;
1772
+ this.model = scatter.model;
1773
+ this.interactivity = scatter.interactivity;
1774
+ this.legendInteractivity = new ScatterLegendInteractivity(scatter);
1775
+ }
1776
+ //Dynamically calculate the length of the legend labels
1777
+ getLegendLabelWidth(chart, key, svg, size) {
1778
+ const legend = chart[`${key}Legend`];
1779
+ if (!legend) return 0;
1780
+ const labels = [];
1781
+ for (const [k, v] of legend.entries()) {
1782
+ if (k != "Ref") labels.push(`${k}, n=(${v.sampleCount})`);
1783
+ }
1784
+ labels.push(this.scatter.config[`${key}TW`]?.term?.name ?? "");
1785
+ const width = getMaxLabelWidth(svg, labels, size) + 70;
1786
+ return width;
1787
+ }
1788
+ getFontSize(chart, legend) {
1789
+ let fontSize = 0.9;
1790
+ if (chart.colorLegend.size < 10 && chart.shapeLegend.size < 10) return fontSize;
1791
+ const top = 20;
1792
+ if (legend.size > top) {
1793
+ fontSize = Math.min(0.9, top / legend.size);
1794
+ if (fontSize < 0.7) fontSize = 0.7;
1795
+ }
1796
+ return fontSize;
1797
+ }
1798
+ renderLegend(chart, step) {
1799
+ const legendG = chart.legendG;
1800
+ legendG.selectAll("*").remove();
1801
+ let offsetX = 0;
1802
+ let offsetY = 15;
1803
+ let legendHeight = 0;
1804
+ if (!this.scatter.config.colorTW && !this.scatter.config.shapeTW && !this.scatter.config.colorColumn) {
1805
+ if (this.scatter.config.scaleDotTW) {
1806
+ chart.scaleG = legendG.append("g").attr("transform", `translate(${offsetX + 45},${this.scatter.vm.legendHeight - 150})`);
1807
+ this.drawScaleDotLegend(chart);
1808
+ }
1809
+ return;
1810
+ }
1811
+ let title;
1812
+ let title0 = this.scatter.config.term0 ? `${this.scatter.config.term0.term.name + " " + chart.id}, n=${chart.cohortSamples.length}` : `${chart.cohortSamples.length} ${this.scatter.config.sampleType ? this.scatter.config.sampleType + "s" : `${this.scatter.settings.itemLabel.toLowerCase()}s`}`;
1813
+ if (this.model.filterSampleStr) title0 += `, search = ${this.model.filterSampleStr}`;
1814
+ legendG.append("text").attr("x", 0).attr("y", offsetY).text(title0).style("font-weight", "bold");
1815
+ const fontSize = this.getFontSize(chart, chart.colorLegend);
1816
+ const scale = chart.colorLegend.size > 20 || chart.shapeLegend.size > 20 ? 0.6 : 0.7;
1817
+ const colorG = legendG.append("g").style("font-size", `${fontSize}em`);
1818
+ offsetY += step + 20;
1819
+ if (this.scatter.config.colorTW || this.scatter.config.colorColumn) {
1820
+ title = `${getTitle(
1821
+ this.scatter.config.colorTW?.term?.name || this.scatter.config.colorColumn.name,
1822
+ 40,
1823
+ this.scatter.config.shapeTW == void 0
1824
+ )}`;
1825
+ const colorRefCategory = chart.colorLegend.get("Ref");
1826
+ if (this.scatter.config.colorTW?.term?.type == "geneVariant" && this.scatter.config.colorTW?.q.type == "values") {
1827
+ offsetY = this.renderGeneVariantLegend(
1828
+ chart,
1829
+ offsetX,
1830
+ offsetY,
1831
+ legendG,
1832
+ this.scatter.config.colorTW,
1833
+ "category",
1834
+ chart.colorLegend,
1835
+ scale
1836
+ );
1837
+ } else {
1838
+ this.addLegendTitle(legendG, title, offsetX, offsetY, this.scatter.config.colorTW, "COLOR");
1839
+ offsetY += step;
1840
+ if (this.scatter.config.colorTW?.q?.mode === "continuous") {
1841
+ let [min, max2] = chart.colorGenerator.domain();
1842
+ const colorValues = chart.colorValues;
1843
+ const scaleG = colorG.append("g");
1844
+ const colorScale = new ColorScale({
1845
+ // Basic visual configuration
1846
+ holder: scaleG,
1847
+ // SVG group to contain our color scale
1848
+ barheight: 20,
1849
+ // Height of the color gradient bar
1850
+ barwidth: 150,
1851
+ // Width of the color gradient bar
1852
+ colors: [
1853
+ // Start and end colors for our gradient
1854
+ this.scatter.config.startColor[chart.id],
1855
+ this.scatter.config.stopColor[chart.id]
1856
+ ],
1857
+ domain: [min, max2],
1858
+ // Current numerical range of our data
1859
+ position: `0, 100`,
1860
+ // Position within the legend
1861
+ ticks: 4,
1862
+ // Number of tick marks to show
1863
+ tickSize: 5,
1864
+ // Size of tick marks
1865
+ topTicks: true,
1866
+ // Display ticks above the gradient bar
1867
+ // Callback for when gradient colors are changed via color picker
1868
+ setColorsCallback: (val, idx) => {
1869
+ this.legendInteractivity.changeGradientColor(chart, val, idx);
1870
+ },
1871
+ // Configuration for our enhanced scaling modes
1872
+ numericInputs: {
1873
+ // Start with either the chart's current mode or default to 'auto'
1874
+ cutoffMode: this.scatter.settings.colorScaleMode,
1875
+ // Default percentile value for percentile mode
1876
+ defaultPercentile: this.scatter.settings.colorScalePercentile,
1877
+ // This callback handles all mode changes and updates
1878
+ callback: (obj) => {
1879
+ if (obj.cutoffMode === "auto") {
1880
+ min = colorValues[0];
1881
+ max2 = colorValues[colorValues.length - 1];
1882
+ } else if (obj.cutoffMode === "fixed") {
1883
+ min = obj.min;
1884
+ max2 = obj.max;
1885
+ } else if (obj.cutoffMode === "percentile") {
1886
+ min = colorValues[0];
1887
+ const index = Math.floor(colorValues.length * obj.percentile / 100);
1888
+ max2 = colorValues[index];
1889
+ }
1890
+ this.scatter.app.dispatch({
1891
+ type: "plot_edit",
1892
+ id: this.scatter.id,
1893
+ config: {
1894
+ settings: {
1895
+ sampleScatter: {
1896
+ colorScaleMode: obj.cutoffMode,
1897
+ colorScaleMinFixed: obj.cutoffMode === "fixed" ? min : null,
1898
+ colorScaleMaxFixed: obj.cutoffMode === "fixed" ? max2 : null,
1899
+ colorScalePercentile: obj.cutoffMode === "percentile" ? obj.percentile : this.scatter.settings.colorScalePercentile
1900
+ }
1901
+ }
1902
+ }
1903
+ });
1904
+ }
1905
+ }
1906
+ });
1907
+ colorScale.updateScale();
1908
+ offsetY += step * 2;
1909
+ } else {
1910
+ for (const [key, category] of chart.colorLegend) {
1911
+ if (key == "Ref") continue;
1912
+ const name = key;
1913
+ const hidden = this.scatter.config.colorTW?.q.hiddenValues ? key in this.scatter.config.colorTW.q.hiddenValues : false;
1914
+ const [circleG, itemG] = this.addLegendItem(
1915
+ chart,
1916
+ colorG,
1917
+ category,
1918
+ name,
1919
+ key,
1920
+ offsetX,
1921
+ offsetY,
1922
+ scale,
1923
+ hidden
1924
+ );
1925
+ if (!this.scatter.config.colorColumn) {
1926
+ circleG.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "colorTW", key, e, category));
1927
+ itemG.on("click", (event) => this.legendInteractivity.onLegendClick(chart, "colorTW", key, event, category));
1928
+ }
1929
+ offsetY += step;
1930
+ }
1931
+ }
1932
+ }
1933
+ if (colorRefCategory?.sampleCount > 0) {
1934
+ offsetY = offsetY + step;
1935
+ const titleG = legendG.append("g");
1936
+ titleG.append("text").attr("x", offsetX).attr("y", offsetY).text("Reference").style("font-weight", "bold");
1937
+ offsetY = offsetY + step;
1938
+ const refColorG = legendG.append("g");
1939
+ refColorG.append("path").attr("transform", () => `translate(${offsetX - 2}, ${offsetY - 4}) scale(${scale})`).style("fill", colorRefCategory.color).attr("d", shapes[0]).style("stroke", rgb(colorRefCategory.color).darker());
1940
+ refColorG.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "colorTW", "Ref", e, colorRefCategory));
1941
+ const refText = legendG.append("g").append("text").attr("x", offsetX + 20).attr("y", offsetY + 4).text(`n=${colorRefCategory.sampleCount}`).style("text-decoration", !this.scatter.settings.showRef ? "line-through" : "none").attr("alignment-baseline", "middle");
1942
+ refText.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "colorTW", "Ref", e, colorRefCategory));
1943
+ }
1944
+ legendHeight = offsetY;
1945
+ }
1946
+ if (this.scatter.config.shapeTW) {
1947
+ offsetX = chart.colorLegendWidth;
1948
+ offsetY = 60;
1949
+ title = `${getTitle(this.scatter.config.shapeTW.term.name, 40)}`;
1950
+ if (this.scatter.config.shapeTW.term.type == "geneVariant" && this.scatter.config.shapeTW.q.type == "values") {
1951
+ this.renderGeneVariantLegend(
1952
+ chart,
1953
+ offsetX,
1954
+ offsetY,
1955
+ legendG,
1956
+ this.scatter.config.shapeTW,
1957
+ "shape",
1958
+ chart.shapeLegend,
1959
+ scale
1960
+ );
1961
+ } else {
1962
+ const shapeG = legendG.append("g").style("font-size", `${this.getFontSize(chart, chart.shapeLegend)}em`);
1963
+ this.addLegendTitle(legendG, title, offsetX, offsetY, this.scatter.config.shapeTW, "SHAPE");
1964
+ offsetY += step;
1965
+ const color = "gray";
1966
+ for (const [key, shape] of chart.shapeLegend) {
1967
+ if (key == "Ref") continue;
1968
+ const index = shape.shape % shapes.length;
1969
+ const symbol = shapes[index];
1970
+ const name = key;
1971
+ const count = shape.sampleCount;
1972
+ const hidden = this.scatter.config.shapeTW.q.hiddenValues ? key in this.scatter.config.shapeTW.q.hiddenValues : false;
1973
+ const itemG = shapeG.append("g");
1974
+ itemG.append("path").attr("transform", () => `translate(${offsetX}, ${offsetY - 4}) scale(${scale + 0.1})`).style("pointer-events", "bounding-box").style("fill", color).attr("d", symbol).style("stroke", rgb(color).darker());
1975
+ itemG.append("text").attr("x", offsetX + 25).attr("y", offsetY + 4).text(`${name}, n=${count}`).style("text-decoration", hidden ? "line-through" : "none").attr("alignment-baseline", "middle");
1976
+ offsetY += step;
1977
+ itemG.on("click", (event) => this.legendInteractivity.onLegendClick(chart, "shapeTW", key, event, shape));
1978
+ }
1979
+ }
1980
+ if (offsetY > legendHeight) legendHeight = offsetY;
1981
+ }
1982
+ if (this.scatter.config.scaleDotTW) {
1983
+ chart.scaleG = legendG.append("g").attr("transform", `translate(${0},${legendHeight + 50})`);
1984
+ this.drawScaleDotLegend(chart);
1985
+ }
1986
+ }
1987
+ addLegendItem(chart, g, category, name, key, x, y, scale, hidden = false) {
1988
+ const circleG = g.append("g");
1989
+ circleG.append("path").attr("d", shapes[0]).attr("transform", `translate(${x - 2}, ${y - 4}) scale(${scale})`).style("fill", category.color).style("stroke", rgb(category.color).darker());
1990
+ if (!this.scatter.config.colorColumn)
1991
+ circleG.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "colorTW", key, e, category));
1992
+ const itemG = g.append("g");
1993
+ itemG.append("text").attr("name", "sjpp-scatter-legend-label").attr("x", x + 20).attr("y", y + 4).text(`${name}, n=${category.sampleCount}`).style("text-decoration", hidden ? "line-through" : "none").attr("alignment-baseline", "middle");
1994
+ return [circleG, itemG];
1995
+ }
1996
+ addLegendTitle(G, title, x, y, tw, extraText) {
1997
+ const _t = G.append("text").attr("data-testid", "legendTitle").attr("x", x).attr("y", y).text(title).style("font-weight", "bold");
1998
+ if (extraText) {
1999
+ _t.append("tspan").text(extraText).attr("dx", 7).style("font-weight", "normal").attr("font-size", ".7em");
2000
+ }
2001
+ }
2002
+ renderGeneVariantLegend(chart, offsetX, offsetY, legendG, tw, cname, map, scale) {
2003
+ const step = 125;
2004
+ const name = tw.term.name.length > 25 ? tw.term.name.slice(0, 25) + "..." : tw.term.name;
2005
+ const title = name;
2006
+ const G = legendG.append("g").style("font-size", "0.9em");
2007
+ this.addLegendTitle(G, title, offsetX, offsetY, tw, cname == "category" ? "COLOR" : "SHAPE");
2008
+ offsetX += step;
2009
+ const mutations = [];
2010
+ for (const value of map.values())
2011
+ if (value.mutation)
2012
+ mutations.push(value.mutation);
2013
+ const mutationsLabels = /* @__PURE__ */ new Set();
2014
+ offsetY += 10;
2015
+ for (const mutation of mutations) {
2016
+ const dt = mutation.dt;
2017
+ const origin = morigin[mutation.origin]?.label;
2018
+ const dtlabel = origin ? `${origin[0]} ${dt2label[dt]}` : dt2label[dt];
2019
+ if (!mutationsLabels.has(dtlabel)) mutationsLabels.add(dtlabel);
2020
+ else continue;
2021
+ offsetY += 15;
2022
+ G.append("text").attr("x", offsetX - step).attr("y", offsetY).text(origin ? `${origin} ${dt2label[dt]}` : dt2label[dt]).style("font-weight", "bold");
2023
+ offsetY += 25;
2024
+ for (const [key, category] of map) {
2025
+ if (key == "Ref") continue;
2026
+ if (!key.includes(dtlabel)) continue;
2027
+ const [mkey, cat_dtlabel] = key.split(", ");
2028
+ if (!cat_dtlabel.includes(dtlabel)) continue;
2029
+ const itemG = G.append("g");
2030
+ if (cname == "shape") {
2031
+ const index = category.shape % shapes.length;
2032
+ itemG.append("path").attr("transform", () => `translate(${offsetX - step - 2}, ${offsetY - 8}) scale(${scale})`).style("fill", "gray").style("pointer-events", "bounding-box").attr("d", shapes[index]).style("stroke", rgb("gray").darker());
2033
+ itemG.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "shapeTW", key, e, category));
2034
+ } else {
2035
+ itemG.append("path").attr("d", shapes[0]).attr("transform", `translate(${-2}, ${offsetY - 8}) scale(${scale})`).style("fill", category.color).style("stroke", rgb(category.color).darker());
2036
+ itemG.on("click", (e) => this.legendInteractivity.onLegendClick(chart, "colorTW", key, e, category));
2037
+ }
2038
+ const hidden = tw.q.hiddenValues ? key in tw.q.hiddenValues : false;
2039
+ const text = mkey.toUpperCase() + (key.includes(dtlabel) ? `, n=${category.sampleCount}` : "");
2040
+ G.append("g").append("text").attr("x", offsetX - step + 24).attr("y", offsetY + 4).attr("name", "sjpp-scatter-legend-label").style("text-decoration", hidden ? "line-through" : "none").text(text).on(
2041
+ "click",
2042
+ (event) => this.legendInteractivity.onLegendClick(
2043
+ chart,
2044
+ cname == "shape" ? "shapeTW" : "colorTW",
2045
+ key,
2046
+ event,
2047
+ category
2048
+ )
2049
+ );
2050
+ offsetY += 25;
2051
+ }
2052
+ }
2053
+ return offsetY;
2054
+ }
2055
+ drawScaleDotLegend(chart) {
2056
+ const scaleG = chart.scaleG;
2057
+ scaleG.selectAll("*").remove();
2058
+ const width = 70;
2059
+ const minScale = this.scatter.settings.minShapeSize / 3;
2060
+ const maxScale = this.scatter.settings.maxShapeSize / 3;
2061
+ const order = this.scatter.settings.scaleDotOrder;
2062
+ const isAscending = order == "Ascending";
2063
+ const titleG = scaleG.append("g");
2064
+ titleG.append("text").text(this.scatter.config.scaleDotTW.term.name).style("font-weight", "bold");
2065
+ const start = roundValueAuto(chart.ranges.scaleMin).toString();
2066
+ const end = roundValueAuto(chart.ranges.scaleMax).toString();
2067
+ const x = 30;
2068
+ const y = 40;
2069
+ const defaultSize = 16;
2070
+ const minSize = defaultSize * minScale;
2071
+ const maxSize = defaultSize * maxScale;
2072
+ const minRadius = minSize / 2;
2073
+ const maxRadius = maxSize / 2;
2074
+ const minG = scaleG.append("g").attr("transform", `translate(${x},${y})`);
2075
+ const shift = 30;
2076
+ minG.append("path").attr("d", shapes[0]).style("fill", "#aaa").style("stroke", "#aaa").attr(
2077
+ "transform",
2078
+ `translate(${isAscending ? -minRadius : -maxRadius}, ${isAscending ? -minRadius : -maxRadius}) scale(${isAscending ? minScale : maxScale})`
2079
+ );
2080
+ const maxG = scaleG.append("g").attr("transform", `translate(${width + x},${y})`);
2081
+ maxG.append("path").attr("d", shapes[0]).style("fill", "#aaa").style("stroke", "#aaa").attr(
2082
+ "transform",
2083
+ `translate(${isAscending ? -maxRadius : -minRadius}, ${isAscending ? -maxRadius : -minRadius}) scale(${isAscending ? maxScale : minScale})`
2084
+ );
2085
+ minG.append("text").attr("x", isAscending ? -minRadius - shift : -maxRadius - shift).attr("y", 5).style("font-size", ".8em").attr("text-anchor", "start").text(start);
2086
+ maxG.append("text").attr("x", isAscending ? maxSize + 5 : minSize + 5).attr("y", 5).style("font-size", ".8em").text(end);
2087
+ minG.append("line").attr("x1", 0).attr("y1", isAscending ? minRadius : maxRadius).attr("x2", width).attr("y2", isAscending ? maxRadius : minRadius).style("stroke", "#aaa");
2088
+ minG.append("line").attr("x1", 0).attr("y1", isAscending ? -minRadius : -maxRadius).attr("x2", width).attr("y2", isAscending ? -maxRadius : -minRadius).style("stroke", "#aaa");
2089
+ scaleG.append("rect").attr("width", 110 * this.scatter.zoom).attr("height", 50).attr("fill", "transparent").on("click", (e) => {
2090
+ const menu = new Menu({ padding: "3px" });
2091
+ const div = menu.d;
2092
+ div.append("label").text("Min:");
2093
+ const minInput = div.append("input").attr("type", "number").attr("min", minShapeSize).attr("step", "0.5").attr("max", maxShapeSize).style("width", "50px").attr("value", this.scatter.settings.minShapeSize).on("change", () => {
2094
+ const value = parseFloat(minInput.node().value);
2095
+ this.scatter.config.settings.sampleScatter.minShapeSize = value;
2096
+ this.scatter.app.dispatch({
2097
+ type: "plot_edit",
2098
+ id: this.scatter.id,
2099
+ config: this.scatter.config
2100
+ });
2101
+ });
2102
+ div.append("label").text("Max:");
2103
+ const maxInput = div.append("input").attr("type", "number").attr("step", "0.5").attr("min", minShapeSize).attr("max", maxShapeSize).style("width", "50px").attr("value", this.scatter.settings.maxShapeSize).on("change", () => {
2104
+ const value = parseFloat(maxInput.node().value);
2105
+ this.scatter.config.settings.sampleScatter.maxShapeSize = value;
2106
+ this.scatter.app.dispatch({
2107
+ type: "plot_edit",
2108
+ id: this.scatter.id,
2109
+ config: this.scatter.config
2110
+ });
2111
+ });
2112
+ const divRadios = menu.d.append("div");
2113
+ divRadios.append("label").text("Order: ");
2114
+ const data = ["Ascending", "Descending"];
2115
+ divRadios.selectAll("input").data(data).enter().append("div").style("display", "inline-block").each((text, i, divs) => {
2116
+ const div2 = select_default(divs[i]);
2117
+ const input = div2.append("input").attr("type", "radio").attr("name", "order").attr("id", text).attr("value", text).property("checked", (text2) => text2 == order);
2118
+ div2.append("label").text(text).attr("for", text);
2119
+ input.on("change", (e2) => {
2120
+ this.changeScaleDotOrder(e2.target.value);
2121
+ });
2122
+ });
2123
+ menu.showunder(e.target);
2124
+ });
2125
+ }
2126
+ changeScaleDotOrder(order) {
2127
+ this.scatter.config.settings.sampleScatter.scaleDotOrder = order;
2128
+ this.scatter.app.dispatch({
2129
+ type: "plot_edit",
2130
+ id: this.scatter.id,
2131
+ config: this.scatter.config
2132
+ });
2133
+ }
2134
+ };
2135
+ function getTitle(name, size = 30, complete = false) {
2136
+ if (name.length > size && !complete) name = name.slice(0, size) + "...";
2137
+ return name;
2138
+ }
2139
+
2140
+ // plots/scatter/viewmodel/scatterTooltip.ts
2141
+ var ScatterTooltip = class {
2142
+ constructor(scatter) {
2143
+ this.scatter = scatter;
2144
+ this.view = scatter.view;
2145
+ this.onClick = false;
2146
+ }
2147
+ showTooltip(event, chart) {
2148
+ if (this.scatter.config.lassoOn) return;
2149
+ this.chart = chart;
2150
+ const onClick = event.type == "click";
2151
+ this.onClick = onClick;
2152
+ if (onClick) this.scatter.interactivity.searchMenu?.hide();
2153
+ if (!(event.target.tagName == "path" && event.target.getAttribute("name") == "serie")) {
2154
+ if (this.onClick && onClick) {
2155
+ this.onClick = false;
2156
+ this.view.dom.tooltip.hide();
2157
+ return;
2158
+ }
2159
+ if (!onClick) {
2160
+ this.view.dom.tooltip.hide();
2161
+ }
2162
+ return;
2163
+ }
2164
+ this.showSampleTooltip(event.target.__data__, event.clientX, event.clientY, chart);
2165
+ }
2166
+ showSampleTooltip(s2, x, y, chart) {
2167
+ this.chart = chart;
2168
+ this.displaySample = "sample" in s2 || "cellId" in s2;
2169
+ const threshold = 5 / this.scatter.zoom;
2170
+ const xMin = chart.xAxisScale.invert(0);
2171
+ const xMax = chart.xAxisScale.invert(chart.width ?? this.scatter.settings.svgw);
2172
+ const yMin = chart.yAxisScale.invert(chart.height ?? this.scatter.settings.svgh);
2173
+ const yMax = chart.yAxisScale.invert(0);
2174
+ const samples = chart.data.samples.filter((s) => {
2175
+ const dist = distance(s.x, s.y, s2.x, s2.y, chart, xMin, xMax, yMin, yMax);
2176
+ if (!("sampleId" in s) && (!this.scatter.settings.showRef || this.scatter.settings.refSize == 0)) return false;
2177
+ return this.scatter.model.getOpacity(s) > 0 && dist < threshold;
2178
+ });
2179
+ this.samples = samples;
2180
+ samples.sort((s1, s22) => {
2181
+ if (!("sampleId" in s1)) return 1;
2182
+ if (this.scatter.config.term) {
2183
+ if (s1.x < s22.x) return -1;
2184
+ if (s1.x > s22.x) return 1;
2185
+ if (s1.y < s22.y) return -1;
2186
+ return 1;
2187
+ }
2188
+ if (this.scatter.config.colorTW) {
2189
+ if (this.scatter.config.colorTW.term.type == "categorical") {
2190
+ if (s1.category.includes(mclass.WT.label) || s1.category.includes(mclass.Blank.label)) return 1;
2191
+ } else {
2192
+ if (s1.category < s22.category) return -1;
2193
+ else if (s1.category > s22.category) return 1;
2194
+ }
2195
+ }
2196
+ if (s1.shape.includes(mclass.WT.label) || s1.shape.includes(mclass.Blank.label)) return 1;
2197
+ return -1;
2198
+ });
2199
+ if (samples.length == 0) return;
2200
+ this.tree = [];
2201
+ const showCoords = this.scatter.config.term ? true : false;
2202
+ for (const sample of samples) {
2203
+ const id = `${roundValueAuto(sample.x)},${roundValueAuto(sample.y)}`;
2204
+ let node = this.tree.find((item) => item.id == id);
2205
+ if (!node) {
2206
+ node = { id, parentId: null, samples: [sample], level: 1, category: null, children: [] };
2207
+ this.tree.push(node);
2208
+ if (showCoords) {
2209
+ const xvalue = this.getCategoryValue("x", sample, this.scatter.config.term);
2210
+ const xnode = {
2211
+ id: xvalue,
2212
+ parentId: id,
2213
+ samples: [sample],
2214
+ level: 2,
2215
+ category: this.scatter.config.term.term.name,
2216
+ children: [],
2217
+ value: xvalue
2218
+ };
2219
+ this.tree.push(xnode);
2220
+ node.children.push(xnode);
2221
+ const yvalue = this.getCategoryValue("y", sample, this.scatter.config.term2);
2222
+ const ynode = {
2223
+ id: `${yvalue}${xvalue}`,
2224
+ parent: xnode,
2225
+ parentId: xvalue,
2226
+ samples: [sample],
2227
+ level: 3,
2228
+ category: this.scatter.config.term2.term.name,
2229
+ children: [],
2230
+ value: yvalue
2231
+ };
2232
+ xnode.children.push(ynode);
2233
+ this.tree.push(ynode);
2234
+ node.xnode = xnode;
2235
+ node.ynode = ynode;
2236
+ }
2237
+ } else {
2238
+ node.samples.push(sample);
2239
+ if (showCoords) {
2240
+ node.xnode.samples.push(sample);
2241
+ node.ynode.samples.push(sample);
2242
+ }
2243
+ }
2244
+ }
2245
+ this.level = showCoords ? 4 : 2;
2246
+ this.parentCategories = showCoords ? ["y", "x", ""] : [""];
2247
+ if (showCoords) this.parentTW = this.scatter.config.term;
2248
+ else this.parentTW = null;
2249
+ if (this.scatter.config.colorTW) this.addNodes("category", this.scatter.config.colorTW);
2250
+ if (this.scatter.config.shapeTW) this.addNodes("shape", this.scatter.config.shapeTW);
2251
+ if (this.scatter.config.scaleDotTW) this.addNodes("scale", this.scatter.config.scaleDotTW);
2252
+ this.view.dom.tooltip.clear();
2253
+ const div = this.view.dom.tooltip.d;
2254
+ if (samples.length > 1)
2255
+ div.append("div").style("color", "#aaa").style("font-weight", "bold").style("margin-left", "1em").text(`${samples.length} ${this.scatter.settings.itemLabel}s`);
2256
+ const tableDiv = div.append("div").style("max-height", "500px").style("overflow-y", "scroll");
2257
+ if (samples.length > 4) tableDiv.attr("class", "sjpp_show_scrollbar");
2258
+ this.tableDiv = tableDiv;
2259
+ const nodes = this.tree.filter((node) => showCoords ? node.level == 1 : node.level == 2);
2260
+ if (showCoords)
2261
+ for (const node of nodes) {
2262
+ if (samples.length > 1) tableDiv.append("div").style("padding", "2px");
2263
+ for (const child of node.children) {
2264
+ this.addCategory(child, null);
2265
+ }
2266
+ }
2267
+ else
2268
+ for (const node of nodes) {
2269
+ if (samples.length > 1) tableDiv.append("div").style("padding", "2px");
2270
+ this.addCategory(node, null);
2271
+ }
2272
+ this.view.dom.tooltip.show(x, y, true, false);
2273
+ }
2274
+ getTW(category) {
2275
+ switch (category) {
2276
+ case "category":
2277
+ return this.scatter.config.colorTW;
2278
+ case "shape":
2279
+ return this.scatter.config.shapeTW;
2280
+ case "scale":
2281
+ return this.scatter.config.scaleDotTW;
2282
+ case "x":
2283
+ return this.scatter.config.term;
2284
+ case "y":
2285
+ return this.scatter.config.term2;
2286
+ default:
2287
+ return null;
2288
+ }
2289
+ }
2290
+ addCategory(node, table) {
2291
+ const samples = this.samples;
2292
+ const chart = this.chart;
2293
+ const tw = this.getTW(node.category);
2294
+ node.added = true;
2295
+ const hasDiscoPlot = this.scatter.state.termdbConfig.queries?.singleSampleMutation;
2296
+ const hasMetArrayPlot = this.scatter.state.termdbConfig.queries?.singleSampleGenomeQuantification;
2297
+ const div = this.tableDiv.append("div");
2298
+ if (!table) table = table2col({ holder: div, disableScroll: true, cellPadding: "5px" });
2299
+ const sample = node.samples[0];
2300
+ if (sample.category != "Ref") {
2301
+ const [tdlabel, td] = table.addRow();
2302
+ const showIcon = tw != null && (tw == this.scatter.config.colorTW || tw == this.scatter.config.shapeTW);
2303
+ let label = tw ? tw.term.name : node.category;
2304
+ if (samples.length > 1 && !this.displaySample) label = label + ` (${node.samples.length})`;
2305
+ tdlabel.text(label);
2306
+ if (showIcon) {
2307
+ const color = tw == this.scatter.config.colorTW ? this.scatter.model.getColor(sample, chart) : this.scatter.config.colorTW ? "gray" : this.scatter.settings.defaultColor;
2308
+ const index = tw == this.scatter.config.colorTW ? chart.shapeLegend.get("Ref").shape % shapesArray.length : chart.shapeLegend.get(sample.shape).shape % shapesArray.length;
2309
+ const shape = shapesArray[index];
2310
+ let fontColor = "black";
2311
+ const whiteColor = rgb("white").toString();
2312
+ if (tw?.term.type == "geneVariant" && tw.q.type == "values") {
2313
+ for (const id in mclass) {
2314
+ const class_info = mclass[id];
2315
+ if (node.value.includes(class_info.label)) {
2316
+ if (rgb(class_info.color).toString() != whiteColor) fontColor = class_info.color;
2317
+ node.value = this.getCategoryValue(node.category, sample, tw, true);
2318
+ break;
2319
+ }
2320
+ }
2321
+ if (this.onClick) {
2322
+ td.append("button").style("float", "right").text("Lollipop").on("click", async () => {
2323
+ await this.scatter.interactivity.openLollipop(label);
2324
+ this.scatter.dom.tip.hide();
2325
+ });
2326
+ }
2327
+ }
2328
+ const chars = node.value.toString().length;
2329
+ const width = chars * 9 + 60;
2330
+ const svg = td.append("svg").attr("width", width).attr("height", "25px");
2331
+ const g = svg.append("g").attr("transform", "translate(0, 14)");
2332
+ g.append("path").attr("d", shape).attr("fill", color).attr("stroke", "#aaa").attr("transform", "translate(0, -4) scale(0.6)");
2333
+ const text = g.append("text").attr("x", 15).attr("y", 6).attr("font-size", "0.9em");
2334
+ text.append("tspan").text(node.value).attr("fill", fontColor);
2335
+ } else td.text(`${node.value}`);
2336
+ }
2337
+ for (const child of node.children) if (!child.added) this.addCategory(child, table);
2338
+ if (node.children.length == 0 && this.displaySample) {
2339
+ for (const sample2 of node.samples) {
2340
+ if ("info" in sample2)
2341
+ for (const [k, v] of Object.entries(sample2.info)) {
2342
+ const [tdlabel2, td2] = table.addRow();
2343
+ tdlabel2.text(k);
2344
+ td2.text(v);
2345
+ }
2346
+ const [tdlabel, td] = table.addRow();
2347
+ tdlabel.text(this.scatter.settings.itemLabel);
2348
+ td.text(sample2.sample || sample2.cellId);
2349
+ if ("sampleId" in sample2 && this.onClick && !this.scatter.config?.singleCellPlot) {
2350
+ if (this.scatter.state.currentCohortChartTypes.includes("sampleView")) {
2351
+ td.append("button").style("float", "right").text("Sample view").on("click", () => this.scatter.interactivity.openSampleView(sample2));
2352
+ }
2353
+ if (hasDiscoPlot)
2354
+ td.append("button").style("float", "right").text("Disco").on("click", async () => this.scatter.interactivity.openDiscoPlot(sample2));
2355
+ if (hasMetArrayPlot)
2356
+ td.append("button").style("float", "right").text("Met Array").on("click", async () => this.scatter.interactivity.openMetArray(sample2));
2357
+ }
2358
+ }
2359
+ }
2360
+ }
2361
+ addNodes(category, tw) {
2362
+ for (const sample of this.samples) {
2363
+ const value = this.getCategoryValue(category, sample, tw);
2364
+ let parentId = "";
2365
+ for (const pc of this.parentCategories) parentId += this.getCategoryValue(pc, sample, this.parentTW);
2366
+ const id = value + parentId;
2367
+ let node = this.tree.find((item) => item.id == id && item.parentId == parentId);
2368
+ const parent = this.tree.find((item) => item.id == parentId);
2369
+ if (!node) {
2370
+ node = { id, parentId, samples: [], level: this.level, category, children: [], value };
2371
+ this.tree.push(node);
2372
+ }
2373
+ node.samples.push(sample);
2374
+ if (parent) parent.children.push(node);
2375
+ }
2376
+ this.parentCategories.unshift(category);
2377
+ this.parentTW = tw;
2378
+ this.level++;
2379
+ }
2380
+ getCategoryValue(category, d, tw, includeMutation = false) {
2381
+ if (category == "") return "";
2382
+ let value = d[category];
2383
+ if (tw?.term.type == "geneVariant" && tw.q?.type == "values") {
2384
+ const mutation = value.split(", ")[0];
2385
+ for (const id in mclass) {
2386
+ const class_info = mclass[id];
2387
+ if (mutation == class_info.label) {
2388
+ const mname = d.cat_info[category].find((m) => m.class == class_info.key).mname;
2389
+ if (mname && includeMutation) value = `${mname} ${value}`;
2390
+ }
2391
+ }
2392
+ }
2393
+ if (tw?.term.type == "date") value = getDateStrFromNumber(value);
2394
+ else if (typeof value == "number" && value % 1 != 0) value = roundValueAuto(value);
2395
+ return value;
2396
+ }
2397
+ };
2398
+ function distance(x1, y1, x2, y2, chart, xMin, xMax, yMin, yMax) {
2399
+ const convertedX1 = getCoordinate(x1, xMin, xMax);
2400
+ const convertedX2 = getCoordinate(x2, xMin, xMax);
2401
+ const convertedY1 = getCoordinate(y1, yMin, yMax);
2402
+ const convertedY2 = getCoordinate(y2, yMin, yMax);
2403
+ const x = chart.xAxisScale(convertedX2) - chart.xAxisScale(convertedX1);
2404
+ const y = chart.yAxisScale(convertedY2) - chart.yAxisScale(convertedY1);
2405
+ const distance2 = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
2406
+ return distance2;
2407
+ }
2408
+
2409
+ // plots/scatter/viewmodel/scatterZoom.ts
2410
+ var ScatterZoom = class {
2411
+ constructor(scatter) {
2412
+ this.zoom = 1;
2413
+ this.scatter = scatter;
2414
+ this.zoomD3 = zoom_default().scaleExtent([0.1, 10]).on("zoom", (event) => this.handleZoom(event.transform)).filter((event) => {
2415
+ if (event.type === "wheel") return event.ctrlKey;
2416
+ return true;
2417
+ }).on("end", async (event) => {
2418
+ this.scatter.transform = event.transform;
2419
+ this.scatter.zoom = event.transform.k;
2420
+ if (this.scatter.settings.saveZoomTransform) this.saveZoomTransform();
2421
+ });
2422
+ }
2423
+ async saveZoomTransform() {
2424
+ const transform = this.scatter.transform?.toString() || null;
2425
+ this.scatter.app.dispatch({ type: "plot_edit", id: this.scatter.id, config: { transform } });
2426
+ }
2427
+ initZoom(toolsDiv) {
2428
+ this.zoomD3.scaleExtent([0.1, this.scatter.config.scaleDotTW ? 4 : 10]);
2429
+ toolsDiv.selectAll("*").remove();
2430
+ const display = "block";
2431
+ const resetDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px").attr("name", "sjpp-reset-btn");
2432
+ icons["restart"](resetDiv, { handler: () => this.resetToIdentity(), title: "Reset plot to defaults" });
2433
+ const zoomInDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px").attr("name", "sjpp-zoom-in-btn");
2434
+ icons["zoomIn"](zoomInDiv, {
2435
+ handler: () => this.zoomIn(),
2436
+ title: "Zoom in. You can also zoom in pressing the Ctrl key and using the mouse wheel"
2437
+ });
2438
+ const zoomOutDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px").attr("name", "sjpp-zoom-out-btn");
2439
+ icons["zoomOut"](zoomOutDiv, {
2440
+ handler: () => this.zoomOut(),
2441
+ title: "Zoom out. You can also zoom out pressing the Ctrl key and using the mouse wheel"
2442
+ });
2443
+ for (const chart of this.scatter.model.charts) {
2444
+ chart.mainG.call(this.zoomD3);
2445
+ }
2446
+ if (this.scatter.config.scaleDotTW && this.zoom > 4) this.resetToIdentity();
2447
+ }
2448
+ handleZoom(transform) {
2449
+ this.zoom = transform.scale(1).k;
2450
+ for (const chart of this.scatter.model.charts) {
2451
+ const new_xScale = transform.rescaleX(chart.xAxisScale);
2452
+ const new_yScale = transform.rescaleY(chart.yAxisScale);
2453
+ chart.serie.attr("transform", transform);
2454
+ chart.regressionG?.attr("transform", transform);
2455
+ chart.xAxis.call(chart.axisBottom.scale(new_xScale));
2456
+ chart.yAxis.call(chart.axisLeft.scale(new_yScale));
2457
+ if (this.scatter.config.lassoOn)
2458
+ chart.lasso.selectedItems().attr("transform", (c) => this.scatter.model.transform(chart, c, 1.2));
2459
+ if (this.scatter.config.scaleDotTW) this.scatter.vm.legendvm.drawScaleDotLegend(chart);
2460
+ }
2461
+ }
2462
+ zoomIn() {
2463
+ this.zoom = this.zoom * 1.2;
2464
+ if (!this.scatter.model.is2DLarge)
2465
+ for (const chart of this.scatter.model.charts) this.zoomD3.scaleBy(chart.mainG.transition().duration(500), 1.2);
2466
+ }
2467
+ zoomOut() {
2468
+ this.zoom = this.zoom * 0.8;
2469
+ if (!this.scatter.model.is2DLarge)
2470
+ for (const chart of this.scatter.model.charts) this.zoomD3.scaleBy(chart.mainG.transition().duration(500), 0.8);
2471
+ }
2472
+ resetToIdentity() {
2473
+ this.zoom = 1;
2474
+ if (!this.scatter.model.is2DLarge)
2475
+ for (const chart of this.scatter.model.charts)
2476
+ chart.mainG.transition().duration(500).call(this.zoomD3.transform, identity);
2477
+ }
2478
+ };
2479
+
2480
+ // plots/scatter/viewmodel/scatterViewModelBase.ts
2481
+ var ScatterViewModelBase = class {
2482
+ constructor(scatter) {
2483
+ this.scatter = scatter;
2484
+ this.view = scatter.view;
2485
+ this.model = scatter.model;
2486
+ this.interactivity = scatter.interactivity;
2487
+ this.legendvm = new ScatterLegend(scatter);
2488
+ this.scatterTooltip = new ScatterTooltip(scatter);
2489
+ this.scatterZoom = new ScatterZoom(scatter);
2490
+ }
2491
+ render() {
2492
+ const chartDivs = this.view.dom.mainDiv.selectAll(":scope > div").data(this.model.charts, (chart) => chart?.id);
2493
+ chartDivs.exit().remove();
2494
+ chartDivs.each((chart, i, divs) => {
2495
+ const div = select_default(divs[i]);
2496
+ this.renderChart(chart, div);
2497
+ });
2498
+ chartDivs.enter().append("div").style("vertical-align", "top").each((chart, i, divs) => {
2499
+ const div = select_default(divs[i]);
2500
+ this.renderChart(chart, div);
2501
+ });
2502
+ if (!this.model.charts?.length) {
2503
+ this.view.dom.bannerDiv.html(`<span>No visible scatter plot data to render</span>`).style("display", "block");
2504
+ return;
2505
+ } else {
2506
+ this.view.dom.bannerDiv.style("display", "none");
2507
+ }
2508
+ }
2509
+ renderChart(chart, div, removePrevious = true) {
2510
+ const s = this.scatter.settings;
2511
+ div.style("opacity", 0).style("display", "inline-block");
2512
+ div.on("mouseover", (event) => {
2513
+ if (!this.scatterTooltip.onClick) this.scatterTooltip.showTooltip(event, chart);
2514
+ });
2515
+ div.on("click", (event) => this.scatterTooltip.showTooltip(event, chart));
2516
+ chart.svg = div.select("svg").empty() ? div.append("svg") : div.select("svg");
2517
+ this.renderSVG(chart, s, removePrevious);
2518
+ div.transition().duration(s.duration).style("opacity", 1);
2519
+ chart.chartDiv = div;
2520
+ }
2521
+ async renderSVG(chart, s, removePrevious) {
2522
+ const svg = chart.svg;
2523
+ let step = Math.min(20 * 40 / chart.colorLegend.size, 25);
2524
+ if (step < 18) step = 18;
2525
+ this.step = step;
2526
+ let colorLegendSize = chart.colorLegend.size * step;
2527
+ if (chart.colorLegend.get("Ref")?.sampleCount > 0) colorLegendSize += 60;
2528
+ const scaleHeight = this.scatter.config.scaleDotTW ? 200 : 100;
2529
+ this.legendHeight = Math.max(colorLegendSize, chart.shapeLegend.size * 25) + scaleHeight;
2530
+ let fontSize = this.legendvm.getFontSize(chart, chart.colorLegend);
2531
+ const labels = [];
2532
+ if (this.scatter.config.colorTW) labels.push(getTitle(this.scatter.config.colorTW.term.name, 40) + " COLOR");
2533
+ if (this.scatter.config.scaleDotTW) labels.push(getTitle(this.scatter.config.scaleDotTW.term.name, 40) + " SHAPE");
2534
+ if (labels.length > 0) {
2535
+ const labelsWidth = getMaxLabelWidth(svg, labels) + 40;
2536
+ chart.colorLegendWidth = this.scatter.config?.colorTW?.q.mode == "continuous" ? Math.max(175, labelsWidth) : Math.max(this.legendvm.getLegendLabelWidth(chart, "color", svg, `${fontSize}em`), labelsWidth);
2537
+ } else chart.colorLegendWidth = 0;
2538
+ fontSize = this.legendvm.getFontSize(chart, chart.shapeLegend);
2539
+ const shapeWidth = this.legendvm.getLegendLabelWidth(chart, "shape", svg, `${fontSize}em`);
2540
+ const width = s.svgw + chart.colorLegendWidth + shapeWidth + 125;
2541
+ svg.attr("width", width).attr("height", Math.max(s.svgh + 200, this.legendHeight)).transition().duration(s.duration);
2542
+ this.fillSvgSubElems(chart);
2543
+ await this.renderSerie(chart, removePrevious);
2544
+ this.legendvm.renderLegend(chart, step);
2545
+ }
2546
+ fillSvgSubElems(chart) {
2547
+ const svg = chart.svg;
2548
+ let axisG, labelsG;
2549
+ if (svg.select(".sjpcb-scatter-mainG").size() == 0) {
2550
+ chart.G = svg.append("g").attr("class", "sjpcb-scatter-G");
2551
+ chart.mainG = chart.G.append("g").attr("class", "sjpcb-scatter-mainG");
2552
+ axisG = svg.append("g").attr("class", "sjpcb-scatter-axis");
2553
+ labelsG = svg.append("g").attr("class", "sjpcb-scatter-labelsG");
2554
+ chart.xAxis = axisG.append("g").attr("class", "sjpcb-scatter-x-axis");
2555
+ chart.yAxis = axisG.append("g").attr("class", "sjpcb-scatter-y-axis").attr("transform", `translate(${this.model.axisOffset.x}, 0)`);
2556
+ chart.mainG.append("rect").attr("class", "zoom").attr("x", this.model.axisOffset.x).attr("y", this.model.axisOffset.y).attr("width", this.scatter.settings.svgw).attr("height", this.scatter.settings.svgh).attr("fill", "white");
2557
+ const id = "clip" + this.scatter.id;
2558
+ chart.clipRect = chart.svg.append("defs").append("clipPath").attr("id", id).append("rect").attr("x", this.model.axisOffset.x).attr("y", this.model.axisOffset.y).attr("width", this.scatter.settings.svgw + 10).attr("height", this.scatter.settings.svgh);
2559
+ chart.serie = chart.mainG.append("g").attr("class", "sjpcb-scatter-series");
2560
+ chart.regressionG = chart.mainG.append("g").attr("class", "sjpcb-scatter-lowess");
2561
+ chart.legendG = svg.append("g").attr("class", "sjpcb-scatter-legend");
2562
+ if (this.scatter.state.config.transform && chart.mainG.attr("transform") != this.scatter.state.config.transform) {
2563
+ chart.mainG.attr("transform", this.scatter.state.config.transform);
2564
+ }
2565
+ chart.G.attr("clip-path", `url(#${id})`);
2566
+ } else {
2567
+ chart.G = svg.select(".sjpcb-scatter-G");
2568
+ chart.mainG = svg.select(".sjpcb-scatter-mainG");
2569
+ chart.serie = chart.mainG.select(".sjpcb-scatter-series");
2570
+ chart.regressionG = chart.mainG.select(".sjpcb-scatter-lowess");
2571
+ axisG = svg.select(".sjpcb-scatter-axis");
2572
+ labelsG = svg.select(".sjpcb-scatter-labelsG");
2573
+ chart.xAxis = axisG.select(".sjpcb-scatter-x-axis");
2574
+ chart.yAxis = axisG.select(".sjpcb-scatter-y-axis");
2575
+ chart.legendG = svg.select(".sjpcb-scatter-legend");
2576
+ chart.clipRect = svg.select("defs").select("clipPath").select("rect");
2577
+ }
2578
+ chart.axisG = axisG;
2579
+ chart.labelsG = labelsG;
2580
+ chart.xAxis.attr("transform", `translate(0, ${this.scatter.settings.svgh + this.model.axisOffset.y})`);
2581
+ chart.legendG.attr("transform", `translate(${this.scatter.settings.svgw + this.model.axisOffset.x + 50}, 20)`);
2582
+ if (chart.axisBottom) {
2583
+ chart.xAxis.call(chart.axisBottom);
2584
+ chart.yAxis.call(chart.axisLeft);
2585
+ }
2586
+ if (this.scatter.config.term) {
2587
+ let termName = getTitle(this.scatter.config.term.term.name, 60);
2588
+ if (!this.scatter.config.colorTW && !this.scatter.config.shapeTW && !this.scatter.config.term0)
2589
+ termName = `${termName}, n=${chart.cohortSamples.length}`;
2590
+ labelsG.selectAll("*").remove();
2591
+ let text = labelsG.append("text").attr(
2592
+ "transform",
2593
+ `translate(${this.model.axisOffset.x + this.scatter.settings.svgw / 2}, ${this.scatter.settings.svgh + this.model.axisOffset.y + 40})`
2594
+ ).attr("text-anchor", "middle").text(termName).style("font-size", "0.9em");
2595
+ if (termName.length > 65) {
2596
+ text.on("mouseenter", (event) => {
2597
+ this.scatter.interactivity.showText(event, this.scatter.config.term.term.name);
2598
+ }).on("mouseleave", () => this.view.dom.tooltip.hide());
2599
+ }
2600
+ if (this.scatter.config.term0 && !this.scatter.config.colorTW && !this.scatter.config.shapeTW) {
2601
+ const term0Name = `${chart.id}, n=${chart.cohortSamples.length}`;
2602
+ labelsG.append("text").attr(
2603
+ "transform",
2604
+ `translate(${this.model.axisOffset.x + this.scatter.settings.svgw / 2}, ${this.scatter.settings.svgh + this.model.axisOffset.y + 65})`
2605
+ ).attr("text-anchor", "middle").text(term0Name);
2606
+ }
2607
+ if (this.scatter.config.term2) {
2608
+ const t2name = this.scatter.config.term2.term.name;
2609
+ const term2Name = getTitle(t2name, 60);
2610
+ text = labelsG.append("text").attr(
2611
+ "transform",
2612
+ `translate(${this.model.axisOffset.x - 50}, ${this.scatter.settings.svgh / 2 + this.model.axisOffset.y}) rotate(-90)`
2613
+ ).attr("text-anchor", "middle").text(term2Name).style("font-size", "0.9em");
2614
+ if (term2Name.length > 60) {
2615
+ text.on("mouseenter", (event) => {
2616
+ this.scatter.interactivity.showText(event, this.scatter.config.term2.term.name);
2617
+ }).on("mouseleave", () => this.view.dom.tooltip.hide());
2618
+ }
2619
+ }
2620
+ }
2621
+ }
2622
+ renderSerie(chart, removePrevious) {
2623
+ const duration = this.scatter.settings.duration;
2624
+ if (this.canvas) this.canvas.remove();
2625
+ const g = chart.serie;
2626
+ const data = chart.data;
2627
+ if (removePrevious) chart.serie.selectAll("*").remove();
2628
+ const symbols = g.selectAll('path[name="serie"]').data(data.samples);
2629
+ symbols.transition().duration(duration).attr("name", "serie").attr("transform", (c) => this.model.transform(chart, c)).attr("d", (c) => this.model.getShape(chart, c)).attr("fill", (c) => this.model.getColor(c, chart)).attr("stroke", (c) => this.model.getColor(c, chart)).attr("stroke-width", (c) => this.model.getStrokeWidth(c)).style("fill-opacity", (c) => this.model.getOpacity(c));
2630
+ symbols.enter().append("path").attr("name", "serie").attr("transform", (c) => this.model.transform(chart, c)).attr("d", (c) => this.model.getShape(chart, c)).attr("fill", (c) => this.model.getColor(c, chart)).attr("stroke", (c) => this.model.getColor(c, chart)).attr("stroke-width", (c) => this.model.getStrokeWidth(c)).style("fill-opacity", (c) => this.model.getOpacity(c)).transition().duration(duration);
2631
+ this.mayRenderRegression();
2632
+ }
2633
+ async mayRenderRegression() {
2634
+ for (const chart of this.model.charts) {
2635
+ chart.regressionG?.selectAll("*").remove();
2636
+ if (chart.regressionCurve) {
2637
+ const l = line_default().x((d) => d[0]).y((d) => d[1]);
2638
+ const regressionPath = chart.regressionG.append("path");
2639
+ regressionPath.attr("d", l(chart.regressionCurve)).attr("stroke", "blue").attr("fill", "none").style("stroke-width", "2");
2640
+ }
2641
+ }
2642
+ }
2643
+ async addGroup(group) {
2644
+ this.model.addGroup(group);
2645
+ this.view.dom.tip.hide();
2646
+ }
2647
+ setTools() {
2648
+ if (!this.model.charts[0]) return;
2649
+ const toolsDiv = this.view.dom.toolsDiv.style("background-color", "white");
2650
+ toolsDiv.selectAll("*").remove();
2651
+ this.scatterZoom.initZoom(toolsDiv);
2652
+ }
2653
+ //2D large and 3D add an svg for the legend
2654
+ addLegendSVG(chart) {
2655
+ chart.chartDiv.style("margin", "20px 20px");
2656
+ chart.legendDiv = this.view.dom.mainDiv.insert("div").style("display", "inline-block").style("vertical-align", "top");
2657
+ chart.legendG = chart.legendDiv.append("svg").attr("width", this.scatter.settings.svgw / 2).attr("height", this.scatter.settings.svgh).append("g").attr("transform", "translate(20, 20)");
2658
+ }
2659
+ };
2660
+
2661
+ // plots/scatter/viewmodel/scatterViewModel.ts
2662
+ var ScatterViewModel = class extends ScatterViewModelBase {
2663
+ constructor(scatter) {
2664
+ super(scatter);
2665
+ this.scatterLasso = new ScatterLasso(scatter);
2666
+ }
2667
+ fillSvgSubElems(chart) {
2668
+ super.fillSvgSubElems(chart);
2669
+ chart.axisG.style("opacity", this.scatter.settings.showAxes ? 1 : 0);
2670
+ chart.labelsG.style("opacity", this.scatter.settings.showAxes ? 1 : 0);
2671
+ }
2672
+ renderSerie(chart, removePrevious) {
2673
+ super.renderSerie(chart, removePrevious);
2674
+ if (this.scatter.settings.showContour) this.renderContours(chart);
2675
+ }
2676
+ renderContours(chart) {
2677
+ const contourG = chart.serie;
2678
+ let zAxisScale;
2679
+ if (this.scatter.config.colorTW?.q.mode == "continuous") {
2680
+ const [zMin, zMax] = extent(chart.data.samples, (d) => d.category);
2681
+ zAxisScale = linear().domain([zMin, zMax]).range([0, 1]);
2682
+ }
2683
+ const data = chart.data.samples.filter((s) => this.model.getOpacity(s) > 0).map((s) => {
2684
+ return { x: chart.xAxisScale(s.x), y: chart.yAxisScale(s.y), z: zAxisScale ? zAxisScale(s.category) : 1 };
2685
+ });
2686
+ renderContours(
2687
+ contourG,
2688
+ data,
2689
+ this.scatter.settings.svgw,
2690
+ this.scatter.settings.svgh,
2691
+ this.scatter.settings.colorContours,
2692
+ this.scatter.settings.contourBandwidth,
2693
+ this.scatter.settings.contourThresholds
2694
+ );
2695
+ }
2696
+ async mayRenderRegression() {
2697
+ for (const chart of this.model.charts) {
2698
+ chart.regressionG?.selectAll("*").remove();
2699
+ if (chart.regressionCurve) {
2700
+ const l = line_default().x((d) => d[0]).y((d) => d[1]);
2701
+ const regressionPath = chart.regressionG.append("path");
2702
+ regressionPath.attr("d", l(chart.regressionCurve)).attr("stroke", "blue").attr("fill", "none").style("stroke-width", "2");
2703
+ }
2704
+ }
2705
+ }
2706
+ async toggleLasso() {
2707
+ this.scatter.config.lassoOn = !this.scatter.config.lassoOn;
2708
+ this.scatter.app.dispatch({ type: "plot_edit", id: this.scatter.id, config: this.scatter.config });
2709
+ }
2710
+ async addGroup(group) {
2711
+ this.model.addGroup(group);
2712
+ this.view.dom.tip.hide();
2713
+ }
2714
+ setTools() {
2715
+ super.setTools();
2716
+ if (this.scatter.config.singleCellPlot) return;
2717
+ const toolsDiv = this.view.dom.toolsDiv;
2718
+ const display = "block";
2719
+ const searchDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px");
2720
+ this.view.dom.lassoDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px");
2721
+ icons["search"](searchDiv, { handler: (e) => this.interactivity.searchSample(e), title: "Search samples" });
2722
+ icons["lasso"](this.view.dom.lassoDiv, {
2723
+ handler: () => this.toggleLasso(),
2724
+ enabled: this.scatter.config.lassoOn,
2725
+ title: "Select a group of samples"
2726
+ });
2727
+ this.view.dom.groupDiv = toolsDiv.insert("div").style("display", display).style("margin", "15px 10px");
2728
+ for (const chart of this.model.charts) {
2729
+ if (!chart.lasso) chart.lasso = d3lasso();
2730
+ this.scatterLasso.lassoReset(chart);
2731
+ }
2732
+ }
2733
+ //2D large and 3D add an svg for the legend
2734
+ addLegendSVG(chart) {
2735
+ chart.chartDiv.style("margin", "20px 20px");
2736
+ chart.legendDiv = this.view.dom.mainDiv.insert("div").style("display", "inline-block").style("vertical-align", "top");
2737
+ chart.legendG = chart.legendDiv.append("svg").attr("width", this.scatter.settings.svgw / 2).attr("height", this.scatter.vm.legendHeight).append("g").attr("transform", "translate(20, 20)");
2738
+ }
2739
+ };
2740
+ function renderContours(contourG, data, width, height, colorContours, bandwidth, thresholds) {
2741
+ const contours = density_default().x((s) => s.x).y((s) => s.y).weight((s) => s.z).size([width, height]).cellSize(2).bandwidth(bandwidth).thresholds(thresholds)(data);
2742
+ const colorScale = sequential().domain([0, max(contours, (d) => d.value)]).interpolator(Greys_default);
2743
+ contourG.attr("fill", "none").attr("stroke", "gray").attr("stroke-linejoin", "round").selectAll().data(contours).join("path").attr("stroke-width", (d, i) => i % 5 ? 0.25 : 1).attr("d", path_default()).attr("fill", colorContours ? (d) => colorScale(d.value) : "none").attr("fill-opacity", 0.05);
2744
+ }
2745
+
2746
+ // plots/scatter/viewmodel/scatterViewModel2DLarge.ts
2747
+ var ScatterViewModel2DLarge = class extends ScatterViewModel {
2748
+ constructor(scatter) {
2749
+ super(scatter);
2750
+ }
2751
+ async renderSerie(chart) {
2752
+ const DragControls = await import("./DragControls-OMQWC4YY.js");
2753
+ this.view.dom.mainDiv.selectAll("*").remove();
2754
+ this.canvas = this.view.dom.mainDiv.insert("div").style("display", "inline-block").append("canvas").node();
2755
+ this.canvas.width = this.scatter.settings.svgw;
2756
+ this.canvas.height = this.scatter.settings.svgh;
2757
+ chart.chartDiv.style("margin", "20px 20px");
2758
+ const fov = this.scatter.settings.threeFOV;
2759
+ const near = 0.1;
2760
+ const far = 1e3;
2761
+ const camera = new PerspectiveCamera(fov, 1, near, far);
2762
+ const scene = new Scene();
2763
+ camera.position.set(0, 0, 1.5);
2764
+ camera.lookAt(scene.position);
2765
+ camera.updateMatrix();
2766
+ const whiteColor = new Color("rgb(255,255,255)");
2767
+ scene.background = whiteColor;
2768
+ const geometry = new BufferGeometry();
2769
+ const { vertices, colors } = this.getVertices(chart);
2770
+ geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
2771
+ geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
2772
+ const tex = getThreeCircle(128);
2773
+ const material = new PointsMaterial({
2774
+ size: this.scatter.settings.threeSize,
2775
+ sizeAttenuation: true,
2776
+ transparent: true,
2777
+ opacity: this.scatter.settings.opacity,
2778
+ map: tex,
2779
+ vertexColors: true
2780
+ });
2781
+ const particles = new Points(geometry, material);
2782
+ scene.add(particles);
2783
+ const renderer = new WebGLRenderer({ antialias: true, canvas: this.canvas, preserveDrawingBuffer: true });
2784
+ renderer.setSize(this.scatter.settings.svgw, this.scatter.settings.svgh);
2785
+ renderer.setPixelRatio(window.devicePixelRatio);
2786
+ new DragControls.DragControls([particles], camera, renderer.domElement);
2787
+ document.addEventListener("mousewheel", (event) => {
2788
+ if (event.ctrlKey) camera.position.z += event.deltaY / 500;
2789
+ });
2790
+ this.addLegendSVG(chart);
2791
+ this.animate(camera, scene, renderer);
2792
+ }
2793
+ animate(camera, scene, renderer) {
2794
+ requestAnimationFrame(() => this.animate(camera, scene, renderer));
2795
+ camera.zoom = this.scatter.vm.scatterZoom.zoom;
2796
+ camera.updateProjectionMatrix();
2797
+ renderer.render(scene, camera);
2798
+ }
2799
+ getVertices(chart) {
2800
+ const xAxisScale = chart.xAxisScale.range([-1, 1]);
2801
+ const yAxisScale = chart.yAxisScale.range([-1, 1]);
2802
+ const vertices = [];
2803
+ const colors = [];
2804
+ for (const sample of chart.data.samples) {
2805
+ const opacity = this.model.getOpacity(sample);
2806
+ if (opacity == 0) continue;
2807
+ const x = xAxisScale(sample.x);
2808
+ const y = yAxisScale(sample.y);
2809
+ const z = 0;
2810
+ vertices.push(x, y, z);
2811
+ const color = new Color(rgb(this.model.getColor(sample, chart)).toString());
2812
+ colors.push(color.r, color.g, color.b);
2813
+ }
2814
+ return { vertices, colors };
2815
+ }
2816
+ };
2817
+ function getThreeCircle(size) {
2818
+ const c = document.createElement("canvas");
2819
+ c.width = size;
2820
+ c.height = size;
2821
+ const ctx = c.getContext("2d");
2822
+ ctx.clearRect(0, 0, size, size);
2823
+ ctx.fillStyle = "white";
2824
+ ctx.beginPath();
2825
+ ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
2826
+ ctx.fill();
2827
+ const tex = new CanvasTexture(c);
2828
+ return tex;
2829
+ }
2830
+
2831
+ // plots/singleCellPlot.js
2832
+ var SAMPLES_TAB = 1;
2833
+ var PLOTS_TAB = 2;
2834
+ var DIFFERENTIAL_EXPRESSION_TAB = 3;
2835
+ var GENE_EXPRESSION_TAB = 4;
2836
+ var IMAGES_TAB = 5;
2837
+ var VIOLIN_TAB = 6;
2838
+ var noExpColor2 = "#F5F5F5";
2839
+ var DE_GENES_TAB = 8;
2840
+ var DE_GSEA_TAB = 7;
2841
+ var singleCellPlot = class _singleCellPlot {
2842
+ static type = "singleCellPlot";
2843
+ constructor() {
2844
+ this.type = _singleCellPlot.type;
2845
+ this.tip = new Menu({ padding: "4px", offsetX: 10, offsetY: 0 });
2846
+ this.tip.d.style("max-height", "300px").style("overflow", "scroll").style("font-size", "0.9em");
2847
+ this.startGradient = {};
2848
+ this.stopGradient = {};
2849
+ }
2850
+ async init(appState) {
2851
+ const state = this.getState(appState);
2852
+ if (this.opts.header) this.opts.header.html(`SINGLE CELL PLOT`).style("font-size", "0.9em");
2853
+ this.tabs = [];
2854
+ const activeTab = state.config.activeTab;
2855
+ const isVisible = () => this.isValidSample;
2856
+ this.tabs.push({
2857
+ label: "Samples",
2858
+ id: SAMPLES_TAB,
2859
+ isVisible,
2860
+ active: activeTab == SAMPLES_TAB,
2861
+ callback: () => this.setActiveTab(SAMPLES_TAB)
2862
+ });
2863
+ this.tabs.push({
2864
+ label: "Plots",
2865
+ id: PLOTS_TAB,
2866
+ active: activeTab == PLOTS_TAB,
2867
+ isVisible,
2868
+ callback: () => this.setActiveTab(PLOTS_TAB)
2869
+ });
2870
+ if (state.termdbConfig.queries.singleCell.DEgenes) {
2871
+ this.tabs.push({
2872
+ label: "Differential Expression",
2873
+ id: DIFFERENTIAL_EXPRESSION_TAB,
2874
+ active: activeTab == DIFFERENTIAL_EXPRESSION_TAB,
2875
+ isVisible,
2876
+ testid: "sjppoldscTabDE",
2877
+ callback: () => this.setActiveTab(DIFFERENTIAL_EXPRESSION_TAB)
2878
+ });
2879
+ }
2880
+ if (state.termdbConfig.queries.singleCell.geneExpression)
2881
+ this.tabs.push({
2882
+ label: "Gene Expression",
2883
+ id: GENE_EXPRESSION_TAB,
2884
+ active: activeTab == GENE_EXPRESSION_TAB,
2885
+ isVisible,
2886
+ testid: "sjppoldscTabGE",
2887
+ callback: () => this.setActiveTab(GENE_EXPRESSION_TAB)
2888
+ });
2889
+ this.tabs.push({
2890
+ label: "Summary",
2891
+ id: VIOLIN_TAB,
2892
+ active: activeTab == VIOLIN_TAB,
2893
+ isVisible,
2894
+ testid: "sjppoldscTabSummary",
2895
+ callback: () => this.setActiveTab(VIOLIN_TAB)
2896
+ });
2897
+ if (state.termdbConfig.queries.singleCell.images)
2898
+ this.tabs.push({
2899
+ label: state.termdbConfig.queries.singleCell.images.label,
2900
+ id: IMAGES_TAB,
2901
+ active: activeTab == IMAGES_TAB,
2902
+ isVisible,
2903
+ callback: () => this.setActiveTab(IMAGES_TAB)
2904
+ });
2905
+ const q = state.termdbConfig.queries;
2906
+ this.opts.holder.style("position", "relative").style("min-height", "200px");
2907
+ this.mainDivId = `${this.id}-sandbox`;
2908
+ const errorDiv = this.opts.holder.append("div");
2909
+ const mainDiv = this.opts.holder.insert("div").style("display", "inline-block").style("vertical-align", "top").style("white-space", "nowrap").attr("id", this.mainDivId);
2910
+ const leftDiv = mainDiv.append("div").style("display", "inline-block").style("vertical-align", "top");
2911
+ const controlsDiv = leftDiv.append("div").attr("class", "pp-termdb-plot-controls");
2912
+ const contentDiv = mainDiv.append("div").style("display", "inline-block").style("vertical-align", "top").style("padding-left", "10px").style("min-height", "300px");
2913
+ this.tabsComp = await new Tabs({
2914
+ holder: contentDiv,
2915
+ tabsPosition: "horizontal",
2916
+ tabs: this.tabs
2917
+ });
2918
+ this.tabsComp.main();
2919
+ const headerDiv = contentDiv.append("div").style("display", "inline-block").style("padding-bottom", "10px");
2920
+ const samplesPromptDiv = headerDiv.append("div").style("display", "none").text("Select a sample below to see its data:").style("padding", "0px 40px 10px 10px");
2921
+ const showDiv = headerDiv.append("div").style("padding-bottom", "10px").style("display", "none");
2922
+ if (state.config.plots.length > 1) this.renderShowPlots(showDiv, state);
2923
+ const geDiv = headerDiv.append("div").style("display", "none");
2924
+ const violinSelectDiv = headerDiv.append("div").style("padding-left", "30px").style("display", "none");
2925
+ const deDiv = headerDiv.append("div").style("display", "none");
2926
+ const sampleDiv = headerDiv.append("div").style("display", "inline-block").html(await this.getSampleDetails(state)).style("padding", "10px 20px");
2927
+ const plotsDivParent = contentDiv.append("div");
2928
+ const samplesTableDiv = plotsDivParent.append("div").style("padding-bottom", "10px");
2929
+ const plotsDiv = plotsDivParent.append("div").style("display", "flex").style("flex-wrap", "wrap").style("justify-content", "flex-start");
2930
+ const loadingDiv = this.opts.holder.append("div").style("position", "absolute").style("top", "0").style("left", "0").style("width", "100%").style("height", "100%").style("background-color", "rgba(255, 255, 255, 0.95)").style("text-align", "center");
2931
+ this.dom = {
2932
+ sampleDiv,
2933
+ samplesPromptDiv,
2934
+ samplesTableDiv,
2935
+ showDiv,
2936
+ mainDiv,
2937
+ loadingDiv,
2938
+ tip: new Menu({ padding: "0px" }),
2939
+ tooltip: new Menu({ padding: "2px", offsetX: 10, offsetY: 0 }),
2940
+ controlsHolder: controlsDiv,
2941
+ geDiv,
2942
+ violinSelectDiv,
2943
+ deDiv,
2944
+ plotsDiv,
2945
+ plotsDivParent,
2946
+ errorDiv
2947
+ };
2948
+ if (q.singleCell?.geneExpression) this.renderGeneExpressionControls(geDiv, state);
2949
+ const offsetX = 80;
2950
+ this.axisOffset = { x: offsetX, y: 30 };
2951
+ if (q.singleCell?.DEgenes) {
2952
+ const label = this.dom.deDiv.append("label").html("View differentially expressed genes for cells of a cluster versus rest of the cells:&nbsp;");
2953
+ this.dom.deselect = label.append("select").attr("data-testid", "sjppoldscDEselect").on("change", (e) => {
2954
+ const display = this.dom.deselect.node().value ? "inline-block" : "none";
2955
+ const cluster = this.dom.deselect.node().value.split(" ")[1];
2956
+ this.genes = null;
2957
+ this.app.dispatch({ type: "plot_edit", id: this.id, config: { cluster, gene: null } });
2958
+ });
2959
+ this.dom.deselect.append("option").text("");
2960
+ }
2961
+ this.settings = {};
2962
+ document.addEventListener("scroll", (event) => this?.tip?.hide());
2963
+ select_default(".sjpp-output-sandbox-content").on("scroll", (event) => this.tip.hide());
2964
+ }
2965
+ getState(appState) {
2966
+ const config = appState.plots.find((p) => p.id === this.id);
2967
+ if (!config) {
2968
+ throw `No plot with id='${this.id}' found. Did you set this.id before this.api = getComponentApi(this)?`;
2969
+ }
2970
+ return {
2971
+ config,
2972
+ dslabel: appState.vocab.dslabel,
2973
+ genome: appState.vocab.genome,
2974
+ termdbConfig: appState.termdbConfig,
2975
+ termfilter: appState.termfilter,
2976
+ vocab: appState.vocab
2977
+ };
2978
+ }
2979
+ // called in relevant dispatch when reactsTo==true
2980
+ // or current.state != replcament.state
2981
+ async main() {
2982
+ this.dom.mainDiv.style("display", "block");
2983
+ this.dom.loadingDiv.selectAll("*").remove();
2984
+ this.dom.loadingDiv.style("display", "").append("div").style("position", "relative").style("top", "50%").text("Loading...");
2985
+ try {
2986
+ const body = {
2987
+ genome: this.state.genome,
2988
+ dslabel: this.state.dslabel,
2989
+ filter0: this.state.termfilter.filter0 || null
2990
+ };
2991
+ const result = await dofetch3("termdb/singlecellSamples", { body });
2992
+ if (result.error) throw result.error;
2993
+ this.samples = result.samples;
2994
+ if (this.samples.length == 0) {
2995
+ this.showNoMatchingDataMessage();
2996
+ return;
2997
+ }
2998
+ this.isValidSample = this.state.config.sample && this.samples.find((i) => i.sample == this.state.config.sample);
2999
+ this.colorByGene = this.state.config.activeTab == GENE_EXPRESSION_TAB || this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB;
3000
+ this.config = structuredClone(this.state.config);
3001
+ copyMerge(this.settings, this.config.settings.singleCellPlot);
3002
+ this.plotColorByDivs = [];
3003
+ this.plots = [];
3004
+ this.legendRendered = false;
3005
+ this.dom.plotsDiv.selectAll("*").remove();
3006
+ await this.getData();
3007
+ await this.setControls();
3008
+ this.dom.sampleDiv.html(await this.getSampleDetails(this.state));
3009
+ this.showActiveTab();
3010
+ this.dom.loadingDiv.style("display", "none");
3011
+ } catch (e) {
3012
+ this.app.tip.hide();
3013
+ this.dom.loadingDiv.style("display", "none");
3014
+ if (e.stack) console.log(e.stack);
3015
+ sayerror(this.dom.errorDiv, e);
3016
+ }
3017
+ }
3018
+ async getData() {
3019
+ if (!this.state.config.sample) return;
3020
+ const plots = [];
3021
+ for (const plot of this.config.plots) {
3022
+ if (plot.selected) plots.push(plot.name);
3023
+ }
3024
+ const body = {
3025
+ genome: this.state.genome,
3026
+ dslabel: this.state.dslabel,
3027
+ plots,
3028
+ filter0: this.state.termfilter.filter0
3029
+ };
3030
+ body.sample = {
3031
+ eID: this.state.config.experimentID,
3032
+ sID: this.state.config.sample
3033
+ };
3034
+ if (this.state.config.gene && (this.state.config.activeTab == GENE_EXPRESSION_TAB || this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB))
3035
+ body.gene = this.state.config.gene;
3036
+ else body.colorBy = this.state.config.colorBy;
3037
+ const result = await dofetch3("termdb/singlecellData", { body });
3038
+ if (result.error) throw result.error;
3039
+ this.refName = result.refName;
3040
+ this.data = result;
3041
+ }
3042
+ async getSampleDetails(state) {
3043
+ if (!this.samples) return "";
3044
+ const sampleIdx = this.samples.findIndex((i) => i.sample == state.config.sample);
3045
+ if (sampleIdx == -1) return "";
3046
+ const extraText = [];
3047
+ if (state.config.experimentID) {
3048
+ extraText.push(
3049
+ '<span style="margin-left:15px;font-size:.7em">SAMPLE</span> ' + this.samples[sampleIdx].experiments?.find((i) => i.experimentID == state.config.experimentID)?.sampleName
3050
+ );
3051
+ } else if (this.samples[sampleIdx].experiments) {
3052
+ extraText.push(
3053
+ '<span style="margin-left:15px;font-size:.7em">SAMPLE</span> ' + this.samples[sampleIdx].experiments[0].sampleName
3054
+ );
3055
+ }
3056
+ if (state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel) {
3057
+ const termname = (await this.app.vocabApi.getterm(state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel)).name;
3058
+ const sampleValue = this.samples[sampleIdx][state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel];
3059
+ extraText.push(`<span style="margin-left:15px;font-size:.7em">${termname.toUpperCase()}</span> ${sampleValue}`);
3060
+ }
3061
+ return `<span style="font-size:.7em">${state.config.settings.singleCellPlot.uiLabels.sample.toUpperCase()}</span>
3062
+ ${this.samples[sampleIdx].sample}
3063
+ ${extraText.join("")}`;
3064
+ }
3065
+ async getSampleFilename(state) {
3066
+ const sampleIdx = this.samples.findIndex((i) => i.sample == state.config.sample);
3067
+ if (sampleIdx == -1) return "";
3068
+ const extraText = [];
3069
+ if (state.config.experimentID) {
3070
+ extraText.push(
3071
+ "SAMPLE_" + this.samples[sampleIdx].experiments?.find((i) => i.experimentID == state.config.experimentID)?.sampleName
3072
+ );
3073
+ } else if (this.samples[sampleIdx].experiments) {
3074
+ extraText.push("SAMPLE_" + this.samples[sampleIdx].experiments[0].sampleName);
3075
+ }
3076
+ if (state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel) {
3077
+ const termname = (await this.app.vocabApi.getterm(state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel)).name;
3078
+ const sampleValue = this.samples[sampleIdx][state.termdbConfig.queries.singleCell.samples.extraSampleTabLabel];
3079
+ extraText.push(`${termname.toUpperCase()}_${sampleValue}`);
3080
+ }
3081
+ if (this.state.config.activeTab == GENE_EXPRESSION_TAB) extraText.push(this.state.config.gene);
3082
+ if (this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB) extraText.push(this.state.config.cluster);
3083
+ if (this.state.config.activeTab == VIOLIN_TAB && this.dom.expressionBySelect)
3084
+ extraText.push(this.dom.expressionBySelect.node().value);
3085
+ const filename = `${state.config.settings.singleCellPlot.uiLabels.sample.toUpperCase()}_
3086
+ ${this.samples[sampleIdx].sample}_
3087
+ ${extraText.join("_")}`;
3088
+ return filename.replace(/[^0-9a-z_]/gi, "");
3089
+ }
3090
+ renderShowPlots(showDiv, state) {
3091
+ showDiv.append("label").text("Plots:").style("font-size", "1.1em");
3092
+ for (const plot of state.config.plots) {
3093
+ const id = plot.name.replace(/\s+/g, "");
3094
+ const key = `show${id}`;
3095
+ showDiv.append("input").attr("type", "checkbox").attr("id", key).property("checked", plot.selected).on("change", (e) => {
3096
+ let plots = structuredClone(this.state.config.plots);
3097
+ plots.find((p) => p.name == plot.name).selected = e.target.checked;
3098
+ const selectedCount = plots.filter((p) => p.selected).length;
3099
+ const defaultSettings = getDefaultSingleCellSettings();
3100
+ let settings = { svgw: defaultSettings.svgw, svgh: defaultSettings.svgh };
3101
+ if (selectedCount > 1) {
3102
+ const width = 800;
3103
+ const height = 800;
3104
+ settings.svgh = width / selectedCount;
3105
+ settings.svgw = height / selectedCount;
3106
+ settings.contourBandwidth = 10;
3107
+ }
3108
+ this.app.dispatch({
3109
+ type: "plot_edit",
3110
+ id: this.id,
3111
+ config: { plots, settings: { singleCellPlot: settings } }
3112
+ });
3113
+ });
3114
+ showDiv.append("label").attr("for", key).text(plot.name);
3115
+ }
3116
+ }
3117
+ renderGeneExpressionControls(geDiv, state) {
3118
+ this.dom.searchboxDiv = geDiv.append("div").style("display", "inline-block");
3119
+ this.dom.geneSearch = addGeneSearchbox({
3120
+ tip: new Menu({ padding: "0px" }),
3121
+ genome: this.app.opts.genome,
3122
+ row: this.dom.searchboxDiv,
3123
+ searchOnly: "gene",
3124
+ placeholder: state.config.gene || "Gene",
3125
+ callback: () => this.colorByGeneExp(),
3126
+ emptyInputCallback: () => this.colorByGeneExp(),
3127
+ hideHelp: true,
3128
+ focusOff: true
3129
+ });
3130
+ this.dom.searchbox = this.dom.geneSearch?.searchbox;
3131
+ }
3132
+ async setActiveTab(tab) {
3133
+ if (!this.state) return;
3134
+ await this.app.dispatch({ type: "plot_edit", id: this.id, config: { activeTab: tab } });
3135
+ }
3136
+ async showActiveTab() {
3137
+ let id = this.state.config.activeTab || this.tabs[0].id;
3138
+ if (!this.isValidSample && id != SAMPLES_TAB) {
3139
+ id = SAMPLES_TAB;
3140
+ this.config.activeTab = SAMPLES_TAB;
3141
+ }
3142
+ const index = this.tabs.findIndex((t) => t.id == id);
3143
+ const tab = this.tabs[index];
3144
+ tab.active = true;
3145
+ this.tabsComp.update(index);
3146
+ this.dom.deDiv.style("display", "none");
3147
+ this.dom.geDiv.style("display", "none");
3148
+ this.dom.showDiv.style("display", "none");
3149
+ this.dom.violinSelectDiv.style("display", "none");
3150
+ this.dom.samplesTableDiv.style("display", "none");
3151
+ this.dom.samplesPromptDiv.style("display", "none");
3152
+ this.dom.controlsHolder.style("display", "none");
3153
+ switch (id) {
3154
+ case SAMPLES_TAB:
3155
+ this.dom.samplesTableDiv.style("display", "block");
3156
+ this.dom.samplesPromptDiv.style("display", "inline-block");
3157
+ this.renderSamplesTable();
3158
+ break;
3159
+ case PLOTS_TAB:
3160
+ await this.renderPlots();
3161
+ this.dom.showDiv.style("display", "inline-block");
3162
+ this.dom.controlsHolder.style("display", "block");
3163
+ break;
3164
+ case GENE_EXPRESSION_TAB:
3165
+ this.dom.controlsHolder.style("display", "block");
3166
+ await this.renderPlots();
3167
+ this.dom.geDiv.style("display", "inline-block");
3168
+ this.dom.searchbox.node().focus();
3169
+ if (this.state.config.gene) this.dom.searchbox.node().value = this.state.config.gene;
3170
+ break;
3171
+ case DIFFERENTIAL_EXPRESSION_TAB:
3172
+ this.dom.deDiv.style("display", "inline-block");
3173
+ this.renderDETable();
3174
+ break;
3175
+ case IMAGES_TAB:
3176
+ this.renderImage();
3177
+ break;
3178
+ case VIOLIN_TAB:
3179
+ this.dom.geDiv.style("display", "inline-block");
3180
+ this.renderViolinTab();
3181
+ this.dom.searchbox.node().focus();
3182
+ break;
3183
+ }
3184
+ }
3185
+ addZoomIcons(iconsDiv, plot) {
3186
+ const zoomInDiv = iconsDiv.append("div").style("margin", "20px 0px");
3187
+ icons["zoomIn"](zoomInDiv, {
3188
+ handler: () => {
3189
+ plot.particles.position.z += 0.1;
3190
+ },
3191
+ title: "Zoom in. You can also zoom in moving the mouse wheel with the Ctrl key pressed."
3192
+ });
3193
+ const zoomOutDiv = iconsDiv.append("div").style("margin", "20px 0px");
3194
+ icons["zoomOut"](zoomOutDiv, {
3195
+ handler: () => {
3196
+ plot.particles.position.z -= 0.1;
3197
+ },
3198
+ title: "Zoom out. You can also zoom out moving the mouse wheel with the Ctrl key pressed."
3199
+ });
3200
+ const identityDiv = iconsDiv.append("div").style("margin", "20px 0px");
3201
+ icons["restart"](identityDiv, {
3202
+ handler: () => {
3203
+ plot.particles.position.z = 0;
3204
+ plot.particles.position.x = 0;
3205
+ plot.particles.position.y = 0;
3206
+ },
3207
+ title: "Reset plot to defaults"
3208
+ });
3209
+ }
3210
+ async renderImage() {
3211
+ const sample = this.state.config.sample || this.samples[0].sample;
3212
+ const i = this.state.termdbConfig.queries.singleCell.images;
3213
+ const result = await dofetch3(`img?file=${i.folder}${i.folder.endsWith("/") ? "" : "/"}${sample}/${i.fileName}`);
3214
+ if (!result.src || result.error) {
3215
+ sayerror(this.dom.plotsDiv, "Cannot load image: " + (result.error || ""));
3216
+ return;
3217
+ }
3218
+ this.dom.plotsDiv.append("img").attr("src", result.src).attr("height", 400);
3219
+ }
3220
+ async renderViolinTab() {
3221
+ if (!this.state.config.gene) return;
3222
+ const selectDiv = this.dom.violinSelectDiv.style("display", "inline-block");
3223
+ selectDiv.selectAll("*").remove();
3224
+ const plotDiv = this.dom.plotsDiv.append("div").style("width", "100%");
3225
+ const options = /* @__PURE__ */ new Set();
3226
+ let selectedOption = "";
3227
+ for (const plot of this.data.plots) {
3228
+ const colorBy = this.state.config.colorBy?.[plot.name] || plot.colorColumns[0];
3229
+ if (!selectedOption) selectedOption = colorBy;
3230
+ for (const c of plot.colorColumns) options.add(c);
3231
+ }
3232
+ if (options.size > 1) {
3233
+ selectDiv.append("label").text("Show expression by: ");
3234
+ const expressionBySelect = selectDiv.append("select").on("change", async (e) => {
3235
+ const expressionBy = e.target.value;
3236
+ violinDiv.selectAll("*").remove();
3237
+ this.renderViolin(expressionBy, violinDiv);
3238
+ });
3239
+ this.dom.expressionBySelect = expressionBySelect;
3240
+ expressionBySelect.selectAll("option").data(Array.from(options)).enter().append("option").attr("value", (d) => d).attr("selected", (d) => d == selectedOption ? d : null).html((d) => d);
3241
+ } else selectDiv.append("label").text(`Expression by ${selectedOption}:`);
3242
+ const violinDiv = this.dom.plotsDiv.append("div");
3243
+ this.renderViolin(selectedOption, violinDiv);
3244
+ }
3245
+ async renderViolin(colorBy, violinDiv) {
3246
+ const gene = this.state.config.gene;
3247
+ const plot = this.data.plots.find((p) => p.colorColumns.find((c) => c == colorBy));
3248
+ this.initPlot(plot);
3249
+ const values = {};
3250
+ for (const cluster of plot.clusters) {
3251
+ values[cluster] = { key: cluster, value: cluster };
3252
+ }
3253
+ const downloadFilename = await this.getSampleFilename(this.state) + "_VIOLIN";
3254
+ const opts = {
3255
+ holder: violinDiv,
3256
+ state: {
3257
+ vocab: this.state.vocab,
3258
+ plots: [
3259
+ {
3260
+ chartType: "violin",
3261
+ term: {
3262
+ $id: await digestMessage(`${gene}-${this.state.config.sample}-${this.state.config.experimentID}`),
3263
+ term: {
3264
+ type: SINGLECELL_GENE_EXPRESSION,
3265
+ id: gene,
3266
+ gene,
3267
+ name: gene,
3268
+ sample: {
3269
+ sID: this.state.config.sample,
3270
+ eID: this.state.config.experimentID
3271
+ }
3272
+ },
3273
+ q: { mode: "continuous" }
3274
+ },
3275
+ term2: {
3276
+ $id: await digestMessage(`${colorBy}-${this.state.config.sample}-${this.state.config.experimentID}`),
3277
+ term: {
3278
+ type: SINGLECELL_CELLTYPE,
3279
+ id: colorBy,
3280
+ name: colorBy,
3281
+ sample: {
3282
+ sID: this.state.config.sample,
3283
+ eID: this.state.config.experimentID
3284
+ },
3285
+ //plot and color by are used to read the sample categories from the plot
3286
+ plot: plot.name,
3287
+ colorBy,
3288
+ values
3289
+ }
3290
+ },
3291
+ downloadFilename
3292
+ }
3293
+ ]
3294
+ }
3295
+ };
3296
+ const plotImport = await import("./plot.app-IZAFRTBU.js");
3297
+ const plotAppApi = await plotImport.appInit(opts);
3298
+ }
3299
+ async renderGSEA(holder) {
3300
+ const gsea_params = {
3301
+ genes: this.genes,
3302
+ fold_change: this.fold_changes,
3303
+ genome: this.app.vocabApi.opts.state.vocab.genome
3304
+ };
3305
+ const downloadFilename = await this.getSampleFilename(this.state) + "_GSEA";
3306
+ const config = {
3307
+ chartType: "gsea",
3308
+ gsea_params,
3309
+ // if getPlotHolder is defined, use this.mainDivId as insertBefore,
3310
+ // so that in GDC frontend framework, plots that are launched from scRNAseq
3311
+ // will be inserted before it. TODO: may insert after the scRNAseq plot instead???
3312
+ insertBefore: this.app.opts?.app?.getPlotHolder ? this.mainDivId : this.id,
3313
+ downloadFilename
3314
+ };
3315
+ const opts = {
3316
+ genome: this.app.opts.genome,
3317
+ holder,
3318
+ state: {
3319
+ vocab: this.state.vocab,
3320
+ plots: [config]
3321
+ }
3322
+ };
3323
+ const plotImport = await import("./plot.app-IZAFRTBU.js");
3324
+ const plotAppApi = await plotImport.appInit(opts);
3325
+ }
3326
+ async renderDETable() {
3327
+ this.dom.deselect.selectAll("*").remove();
3328
+ this.dom.deselect.append("option").text("");
3329
+ const plot = this.data.plots[0];
3330
+ this.initPlot(plot);
3331
+ for (const cluster of plot.clusters) this.dom.deselect.append("option").text(cluster);
3332
+ const categoryName = this.state.config.cluster;
3333
+ this.dom.deselect.node().value = categoryName != void 0 ? `Cluster ${categoryName}` : "";
3334
+ if (!categoryName) return;
3335
+ const columnName = this.state.termdbConfig.queries.singleCell.DEgenes.termId;
3336
+ const sample = this.state.config.experimentID || this.state.config.sample || this.samples?.[0]?.experiments[0]?.experimentID;
3337
+ const DEContentDiv = this.dom.plotsDiv.append("div").style("width", "100%");
3338
+ const tabsDiv = DEContentDiv.append("div");
3339
+ const tableDiv = DEContentDiv.append("div");
3340
+ const GSEADiv = DEContentDiv.append("div").style("display", "none");
3341
+ let result;
3342
+ try {
3343
+ const args = { genome: this.state.genome, dslabel: this.state.dslabel, categoryName, sample, columnName };
3344
+ result = await dofetch3("termdb/singlecellDEgenes", { body: args });
3345
+ if (result.error) {
3346
+ tableDiv.text(result.error);
3347
+ return;
3348
+ }
3349
+ if (!result.data || !result?.data?.length) {
3350
+ tableDiv.text("No differentially expressed genes found.");
3351
+ return;
3352
+ }
3353
+ } catch (e) {
3354
+ if (e.stack) console.error(e.stack);
3355
+ else throw `Error fetching DE genes: ${e.message || e} [singleCellPlot.renderDETable()]`;
3356
+ return;
3357
+ }
3358
+ const tabs = [
3359
+ {
3360
+ label: "Differentially Expressed Genes",
3361
+ id: DE_GENES_TAB,
3362
+ active: true,
3363
+ callback: () => showActiveDETab(DE_GENES_TAB)
3364
+ }
3365
+ ];
3366
+ if (this.app.opts.genome.termdbs) {
3367
+ tabs.push({
3368
+ label: "Gene Set Enrichment Analysis (GSEA)",
3369
+ id: DE_GSEA_TAB,
3370
+ active: false,
3371
+ callback: () => showActiveDETab(DE_GSEA_TAB)
3372
+ });
3373
+ }
3374
+ function showActiveDETab(id) {
3375
+ tableDiv.style("display", "none");
3376
+ GSEADiv.style("display", "none");
3377
+ if (id == DE_GENES_TAB) tableDiv.style("display", "block");
3378
+ if (id == DE_GSEA_TAB) GSEADiv.style("display", "block");
3379
+ }
3380
+ if (tabs.length > 1) {
3381
+ const deTabs = await new Tabs({
3382
+ holder: tabsDiv,
3383
+ tabsPosition: "horizontal",
3384
+ tabs
3385
+ });
3386
+ deTabs.main();
3387
+ }
3388
+ tableDiv.append("div").style("padding-bottom", "10px").text("Select a gene to view its expression:");
3389
+ const tableDivContent = tableDiv.append("div").style("padding-bottom", "10px");
3390
+ const columns = [
3391
+ { label: "Gene", width: "15vw" },
3392
+ { label: "Log2FC", width: "12vw", barplot: {} },
3393
+ { label: "Adjusted P-value", width: "12vw" }
3394
+ ];
3395
+ const rows = [];
3396
+ this.genes = [];
3397
+ this.fold_changes = [];
3398
+ result.data.sort((a, b) => b.fold_change - a.fold_change);
3399
+ const selectedRows = [];
3400
+ let i = 0;
3401
+ for (const gene of result.data) {
3402
+ const row = [
3403
+ { value: gene.gene_name },
3404
+ { value: gene.fold_change },
3405
+ { value: roundValueAuto(gene.adjusted_p_value) }
3406
+ ];
3407
+ rows.push(row);
3408
+ this.genes.push(gene.gene_name);
3409
+ this.fold_changes.push(gene.fold_change);
3410
+ if (gene.gene_name == this.state.config.gene) selectedRows.push(i);
3411
+ i++;
3412
+ }
3413
+ this.DETable = { rows, columns };
3414
+ const downloadFilename = `${await this.getSampleFilename(this.state)}_DE_GENES.tsv`;
3415
+ renderTable({
3416
+ rows,
3417
+ columns,
3418
+ maxHeight: "50vh",
3419
+ div: tableDivContent,
3420
+ singleMode: true,
3421
+ noButtonCallback: (i2, node) => {
3422
+ const gene = result.data[i2].gene_name;
3423
+ this.app.dispatch({
3424
+ type: "plot_edit",
3425
+ id: this.id,
3426
+ config: {
3427
+ gene,
3428
+ sample: this.state.config.sample || this.samples?.[0]?.sample,
3429
+ experimentID: this.state.config.experimentID || this.samples?.[0].experiments?.[0]?.experimentID,
3430
+ activeTab: GENE_EXPRESSION_TAB
3431
+ }
3432
+ });
3433
+ },
3434
+ selectedRows,
3435
+ resize: true,
3436
+ dataTestId: "sjppoldscDEtable",
3437
+ download: { fileName: downloadFilename }
3438
+ });
3439
+ this.renderGSEA(GSEADiv);
3440
+ }
3441
+ colorByGeneExp() {
3442
+ const gene = this.dom.searchbox.node().value;
3443
+ for (const div of this.plotColorByDivs) div.style("display", "none");
3444
+ this.app.dispatch({
3445
+ type: "plot_edit",
3446
+ id: this.id,
3447
+ config: {
3448
+ gene,
3449
+ sample: this.state.config.sample || this.samples?.[0]?.sample,
3450
+ experimentID: this.state.config.experimentID || this.samples?.[0].experiments?.[0]?.experimentID
3451
+ }
3452
+ });
3453
+ }
3454
+ async setControls() {
3455
+ this.dom.controlsHolder.selectAll("*").remove();
3456
+ const inputs = [
3457
+ {
3458
+ label: "Chart width",
3459
+ title: "Chart width",
3460
+ type: "number",
3461
+ chartType: "singleCellPlot",
3462
+ settingsKey: "svgw",
3463
+ min: 300,
3464
+ max: 1e3
3465
+ },
3466
+ {
3467
+ label: "Chart height",
3468
+ title: "Chart height",
3469
+ type: "number",
3470
+ chartType: "singleCellPlot",
3471
+ settingsKey: "svgh",
3472
+ min: 300,
3473
+ max: 1e3
3474
+ },
3475
+ {
3476
+ label: "Dot size",
3477
+ type: "number",
3478
+ chartType: "singleCellPlot",
3479
+ settingsKey: "sampleSizeThree",
3480
+ title: "Dot size",
3481
+ min: 1e-3,
3482
+ max: 0.1,
3483
+ step: 1e-3
3484
+ },
3485
+ {
3486
+ label: "Dot opacity",
3487
+ type: "number",
3488
+ chartType: "singleCellPlot",
3489
+ settingsKey: "opacity",
3490
+ title: "Dot opacity",
3491
+ min: 0.1,
3492
+ max: 1,
3493
+ step: 0.1
3494
+ },
3495
+ {
3496
+ label: "Show grid",
3497
+ boxLabel: "",
3498
+ type: "checkbox",
3499
+ chartType: "singleCellPlot",
3500
+ settingsKey: "showGrid",
3501
+ title: "Show grid"
3502
+ }
3503
+ ];
3504
+ const enableContour = this.state.config.activeTab == GENE_EXPRESSION_TAB && this.state.config.gene;
3505
+ if (enableContour)
3506
+ inputs.push({
3507
+ label: "Show contour map",
3508
+ boxLabel: "",
3509
+ type: "checkbox",
3510
+ chartType: "singleCellPlot",
3511
+ settingsKey: "showContour",
3512
+ title: "Shows the density of point clouds. It uses gene expression to weight the points when calculating the density contours."
3513
+ });
3514
+ if (enableContour && this.settings.showContour)
3515
+ inputs.push(
3516
+ {
3517
+ label: "Color contours",
3518
+ boxLabel: "",
3519
+ type: "checkbox",
3520
+ chartType: "singleCellPlot",
3521
+ settingsKey: "colorContours"
3522
+ },
3523
+ {
3524
+ label: "Contour bandwidth",
3525
+ type: "number",
3526
+ chartType: "singleCellPlot",
3527
+ settingsKey: "contourBandwidth",
3528
+ title: "Reduce to increase resolution. ",
3529
+ min: 5,
3530
+ max: 50,
3531
+ step: 5
3532
+ },
3533
+ {
3534
+ label: "Contour thresholds",
3535
+ type: "number",
3536
+ chartType: "singleCellPlot",
3537
+ settingsKey: "contourThresholds",
3538
+ title: "Dot size",
3539
+ min: 5,
3540
+ max: 30,
3541
+ step: 5
3542
+ }
3543
+ );
3544
+ if ((this.state.config.activeTab == GENE_EXPRESSION_TAB || this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB) && this.state.config.gene)
3545
+ inputs.unshift({
3546
+ label: "Show unexpressed cells",
3547
+ boxLabel: "",
3548
+ type: "checkbox",
3549
+ chartType: "singleCellPlot",
3550
+ settingsKey: "showNoExpCells",
3551
+ title: "Show cells not expressing the selected gene"
3552
+ });
3553
+ this.components = {
3554
+ controls: await controlsInit({
3555
+ app: this.app,
3556
+ id: this.id,
3557
+ holder: this.dom.controlsHolder,
3558
+ inputs
3559
+ })
3560
+ };
3561
+ this.components.controls.on("downloadClick.singleCellPlot", async () => {
3562
+ if (!this.state) return;
3563
+ const filename = await this.getSampleFilename(this.state);
3564
+ if (this.state.config.activeTab == GENE_EXPRESSION_TAB || this.state.config.activeTab == PLOTS_TAB)
3565
+ for (const plot of this.plots) this.downloadPlot(plot, filename);
3566
+ });
3567
+ }
3568
+ downloadSCTable(name, table) {
3569
+ downloadTable(table.rows, table.columns, name);
3570
+ }
3571
+ downloadPlot(plot, filename) {
3572
+ downloadSingleSVG(plot.legendSVG, filename + "_LEGEND.svg", this.opts.holder.node());
3573
+ const downloadImgName = plot.name;
3574
+ const a = document.createElement("a");
3575
+ document.body.appendChild(a);
3576
+ const dataURL = plot.canvas.toDataURL();
3577
+ a.addEventListener(
3578
+ "click",
3579
+ () => {
3580
+ a.download = filename + "_" + downloadImgName + ".png";
3581
+ a.href = dataURL;
3582
+ document.body.removeChild(a);
3583
+ },
3584
+ false
3585
+ );
3586
+ a.click();
3587
+ }
3588
+ showNoMatchingDataMessage() {
3589
+ this.dom.mainDiv.style("display", "none");
3590
+ this.dom.loadingDiv.selectAll("*").remove();
3591
+ this.dom.loadingDiv.style("display", "").append("div").style("font-size", "1.2em").html("No matching cohort data.");
3592
+ }
3593
+ renderPlots() {
3594
+ const result = this.data;
3595
+ if (result.nodata) return;
3596
+ for (const plot of result.plots) {
3597
+ if ((this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB || this.state.config.activeTab == GENE_EXPRESSION_TAB) && this.state.config.gene && !plot.expCells.length)
3598
+ continue;
3599
+ this.renderPlot(plot);
3600
+ }
3601
+ if (this.plots.length == 0) this.dom.plotsDiv.append("div").text("No data to plot");
3602
+ }
3603
+ renderPlot(plot) {
3604
+ if (!plot.plotDiv) {
3605
+ const plotDiv = this.dom.plotsDiv.append("div").style("display", "inline-block").style("vertical-align", "top");
3606
+ const leftDiv = plotDiv.append("div").style("display", "inline-block").style("vertical-align", "top").style("padding-top", "30px");
3607
+ plot.plotDiv = plotDiv.append("div").style("display", "inline-block");
3608
+ this.addZoomIcons(leftDiv, plot);
3609
+ }
3610
+ const colorMap = {};
3611
+ this.initPlot(plot);
3612
+ const cat2Color = getColors(plot.clusters.length + 2);
3613
+ for (const cluster of plot.clusters)
3614
+ colorMap[cluster] = plot.colorMap?.[cluster] ? plot.colorMap[cluster] : cat2Color(cluster);
3615
+ plot.colorMap = colorMap;
3616
+ this.initAxes(plot);
3617
+ plot.headerDiv = plot.plotDiv.append("div");
3618
+ plot.headerDiv.append("label").text(plot.name).style("font-size", "1.2em").style("margin-right", "10px");
3619
+ if (this.colorByGene && this.state.config.gene) {
3620
+ if (!this.config.startColor[plot.name]) this.config.startColor[plot.name] = "#fffee0";
3621
+ if (!this.config.stopColor[plot.name]) this.config.stopColor[plot.name] = "red";
3622
+ const startColor = this.config.startColor[plot.name];
3623
+ const stopColor = this.config.stopColor[plot.name];
3624
+ let min, max2;
3625
+ const expCells = plot.expCells;
3626
+ const values = expCells.map((cell) => cell.geneExp).sort();
3627
+ plot.colorValues = values;
3628
+ if (values.length == 0) {
3629
+ plot.colorGenerator = null;
3630
+ } else {
3631
+ switch (this.settings.colorScaleMode) {
3632
+ // Fixed mode: Use user-defined min/max values
3633
+ // This is useful when you want consistent scaling across different views
3634
+ case "fixed":
3635
+ min = this.settings.colorScaleMinFixed;
3636
+ max2 = this.settings.colorScaleMaxFixed;
3637
+ break;
3638
+ case "percentile":
3639
+ min = values[0];
3640
+ const index = Math.floor(values.length * this.settings.colorScalePercentile / 100);
3641
+ max2 = values[index];
3642
+ break;
3643
+ case "auto":
3644
+ default:
3645
+ min = values[0];
3646
+ max2 = values[values.length - 1];
3647
+ break;
3648
+ }
3649
+ plot.colorGenerator = linear().domain([min, max2]).range([startColor, stopColor]);
3650
+ }
3651
+ }
3652
+ this.renderLargePlotThree(plot);
3653
+ this.renderLegend(plot);
3654
+ }
3655
+ initPlot(plot) {
3656
+ this.plots.push(plot);
3657
+ const expCells = plot.expCells.sort((a, b) => a.geneExp - b.geneExp);
3658
+ plot.cells = [...plot.noExpCells, ...expCells];
3659
+ plot.id = plot.name.replace(/\s+/g, "");
3660
+ let clusters = new Set(plot.cells.map((c) => c.category));
3661
+ plot.clusters = Array.from(clusters).sort((a, b) => {
3662
+ const num1 = parseInt(a.split(" ")[1]);
3663
+ const num2 = parseInt(b.split(" ")[1]);
3664
+ return num1 - num2;
3665
+ });
3666
+ }
3667
+ getOpacity(d) {
3668
+ if (this.config.hiddenClusters[d.category]) return 0;
3669
+ if (this.colorByGene && this.state.config.gene && !d.geneExp)
3670
+ return this.settings.showNoExpCells ? this.settings.opacity : 0;
3671
+ return this.settings.opacity;
3672
+ }
3673
+ getColor(d, plot) {
3674
+ let color = plot.colorMap[d.category];
3675
+ if (this.colorByGene && this.state.config.gene) {
3676
+ if (!d.geneExp) color = noExpColor2;
3677
+ else if (d.geneExp > plot.max) color = plot.colorGenerator(plot.max);
3678
+ else color = plot.colorGenerator(d.geneExp);
3679
+ }
3680
+ return color;
3681
+ }
3682
+ handleZoom(e, plot) {
3683
+ plot.mainG.attr("transform", e.transform);
3684
+ }
3685
+ initAxes(plot) {
3686
+ if (!plot.cells.length) return;
3687
+ const s0 = plot.cells[0];
3688
+ const [xMin, xMax, yMin, yMax] = plot.cells.reduce(
3689
+ (s, d) => [d.x < s[0] ? d.x : s[0], d.x > s[1] ? d.x : s[1], d.y < s[2] ? d.y : s[2], d.y > s[3] ? d.y : s[3]],
3690
+ [s0.x, s0.x, s0.y, s0.y]
3691
+ );
3692
+ plot.xAxisScale = linear().domain([xMin, xMax]).range([-1, 1]);
3693
+ plot.yAxisScale = linear().domain([yMin, yMax]).range([-1, 1]);
3694
+ }
3695
+ renderLegend(plot) {
3696
+ const colorMap = plot.colorMap;
3697
+ let legendSVG = plot.legendSVG;
3698
+ const clustersHeight = 20 * Object.keys(colorMap).length + 50;
3699
+ const height = Math.max(this.settings.svgh, clustersHeight);
3700
+ if (!plot.legendSVG) {
3701
+ const activeTab = this.tabs.find((tab) => tab.active);
3702
+ if (activeTab.id == PLOTS_TAB) {
3703
+ const app = this.app;
3704
+ if (plot.colorColumns.length > 1) {
3705
+ const plotColorByDiv = plot.headerDiv.append("div").style("display", "inline-block").style("padding-bottom", "20px");
3706
+ plotColorByDiv.append("label").text("Color by:").style("margin-right", "5px");
3707
+ const colorBySelect = plotColorByDiv.append("select");
3708
+ this.plotColorByDivs.push(plotColorByDiv);
3709
+ colorBySelect.selectAll("option").data(plot.colorColumns).enter().append("option").attr("value", (d) => d).property("selected", (d) => d == this.state.config.colorBy?.[plot.name]).html((d) => d);
3710
+ colorBySelect.on("change", () => {
3711
+ const colorBy = colorBySelect.node().value;
3712
+ app.dispatch({
3713
+ type: "plot_edit",
3714
+ id: this.id,
3715
+ config: { colorBy: { [plot.name]: colorBy } }
3716
+ });
3717
+ });
3718
+ }
3719
+ }
3720
+ legendSVG = plot.plotDiv.append("svg").attr("width", 250).attr("height", height).style("display", "inline-block").style("vertical-align", "top").style("font-size", "0.9em");
3721
+ plot.legendSVG = legendSVG;
3722
+ }
3723
+ legendSVG.selectAll("*").remove();
3724
+ this.legendRendered = true;
3725
+ if ((this.state.config.activeTab == GENE_EXPRESSION_TAB || this.state.config.activeTab == DIFFERENTIAL_EXPRESSION_TAB) && this.state.config.gene) {
3726
+ this.renderColorGradient(plot);
3727
+ return;
3728
+ }
3729
+ let x = 20;
3730
+ plot.legendSVG.append("text").attr("transform", `translate(${x}, ${25})`).style("font-weight", "bold").text(`${plot.colorBy}`);
3731
+ let step = 25;
3732
+ if (height < 500) {
3733
+ plot.legendSVG.style("font-size", "0.8em");
3734
+ step = 20;
3735
+ }
3736
+ let y = 50;
3737
+ const configPlot = this.state.config.plots.find((p) => p.name == plot.name);
3738
+ const aliases = configPlot.colorColumns.find((c) => c.name == plot.colorBy)?.aliases;
3739
+ for (const cluster in colorMap) {
3740
+ const clusterCells = plot.cells.filter((item) => item.category == cluster);
3741
+ const hidden = this.config.hiddenClusters?.[cluster];
3742
+ const n = clusterCells.length;
3743
+ const color = colorMap[cluster];
3744
+ const itemG = plot.legendSVG.append("g").attr("transform", (c) => `translate(${x}, ${y})`);
3745
+ itemG.append("circle").attr("r", 5).attr("fill", color);
3746
+ itemG.append("g").attr("transform", `translate(15, 5)`).append("text").text(
3747
+ `${cluster == "ref" ? this.state.termdbConfig.queries.singleCell.data.refName : cluster == "query" ? this.state.config.sample || this.samples[0].sample : aliases ? aliases[cluster] : cluster} n=${n}`
3748
+ ).style("text-decoration", hidden ? "line-through" : "none").on("click", (e) => this.showLegendItemMenu(e, cluster, plot));
3749
+ y += step;
3750
+ }
3751
+ }
3752
+ hideCategory(key, hidden) {
3753
+ this.app.dispatch({
3754
+ type: "plot_edit",
3755
+ id: this.id,
3756
+ config: { hiddenClusters: { [key]: hidden } }
3757
+ });
3758
+ }
3759
+ showLegendItemMenu(e, key, plot) {
3760
+ let hiddenCount = 0;
3761
+ for (const cluster in this.state.config.hiddenClusters) if (this.state.config.hiddenClusters[cluster]) hiddenCount++;
3762
+ const hidden = this.state.config.hiddenClusters?.[key];
3763
+ if (hidden && hiddenCount == 1) {
3764
+ this.hideCategory(key, false, plot.legendSVG);
3765
+ return;
3766
+ }
3767
+ const menu = this.tip.clear();
3768
+ const div = menu.d.append("div");
3769
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text(hidden ? "Show" : "Hide").on("click", () => {
3770
+ this.hideCategory(key, !hidden, plot.legendSVG);
3771
+ menu.hide();
3772
+ });
3773
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Show only").on("click", () => {
3774
+ for (const cluster in plot.colorMap) if (key != cluster) this.hideCategory(cluster, true, plot.legendSVG);
3775
+ this.hideCategory(key, false, plot.legendSVG);
3776
+ menu.hide();
3777
+ });
3778
+ if (hiddenCount > 1)
3779
+ div.append("div").attr("class", "sja_menuoption sja_sharp_border").text("Show all").on("click", () => {
3780
+ menu.hide();
3781
+ for (const mapKey in plot.colorMap) this.hideCategory(mapKey, false, plot.legendSVG);
3782
+ });
3783
+ menu.showunder(e.target);
3784
+ }
3785
+ renderColorGradient(plot) {
3786
+ if (plot.cells.length == 0 || !plot.colorGenerator) return;
3787
+ const colors = [this.config.startColor[plot.name], this.config.stopColor[plot.name]];
3788
+ const gene = this.state.config.gene;
3789
+ let offsetY = 20;
3790
+ const barwidth = 100;
3791
+ plot.legendSVG.append("g").attr("transform", `translate(${20}, ${offsetY})`).append("text").text(`${gene} expression`);
3792
+ const legendG = plot.legendSVG.append("g").attr("transform", `translate(20, ${2 * offsetY})`);
3793
+ const colorScale = new ColorScale({
3794
+ holder: legendG,
3795
+ barwidth,
3796
+ barheight: 20,
3797
+ colors,
3798
+ domain: plot.colorGenerator.domain(),
3799
+ position: "0, 20",
3800
+ ticks: 4,
3801
+ tickSize: 5,
3802
+ topTicks: true,
3803
+ setColorsCallback: (val, idx) => {
3804
+ this.changeGradientColor(plot, val, idx);
3805
+ },
3806
+ numericInputs: {
3807
+ cutoffMode: this.settings.colorScaleMode,
3808
+ defaultPercentile: this.settings.colorScalePercentile,
3809
+ callback: (obj) => {
3810
+ let min, max2;
3811
+ const colorValues = plot.colorValues;
3812
+ if (obj.cutoffMode === "auto") {
3813
+ min = colorValues[0];
3814
+ max2 = colorValues[colorValues.length - 1];
3815
+ } else if (obj.cutoffMode === "fixed") {
3816
+ min = obj.min;
3817
+ max2 = obj.max;
3818
+ } else if (obj.cutoffMode === "percentile") {
3819
+ min = colorValues[0];
3820
+ const index = Math.floor(colorValues.length * obj.percentile / 100);
3821
+ max2 = colorValues[index];
3822
+ }
3823
+ this.app.dispatch({
3824
+ type: "plot_edit",
3825
+ id: this.id,
3826
+ config: {
3827
+ settings: {
3828
+ singleCellPlot: {
3829
+ colorScaleMode: obj.cutoffMode,
3830
+ colorScaleMinFixed: obj.cutoffMode === "fixed" ? min : null,
3831
+ colorScaleMaxFixed: obj.cutoffMode === "fixed" ? max2 : null,
3832
+ colorScalePercentile: obj.cutoffMode === "percentile" ? obj.percentile : this.settings.colorScalePercentile
3833
+ }
3834
+ }
3835
+ }
3836
+ });
3837
+ }
3838
+ }
3839
+ });
3840
+ colorScale.updateScale();
3841
+ }
3842
+ changeGradientColor = function(plot, newColor, idx) {
3843
+ const colorKey = idx == 0 ? "startColor" : "stopColor";
3844
+ this.config[colorKey][plot.name] = newColor;
3845
+ this.app.dispatch({
3846
+ type: "plot_edit",
3847
+ id: this.id,
3848
+ config: this.config
3849
+ });
3850
+ };
3851
+ distance(x1, y1, x2, y2, plot) {
3852
+ const x = plot.xAxisScale(x2) - plot.xAxisScale(x1);
3853
+ const y = plot.yAxisScale(y2) - plot.yAxisScale(y1);
3854
+ const distance2 = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
3855
+ return distance2;
3856
+ }
3857
+ showTooltip(event, plot) {
3858
+ if (this.onClick && event.type == "click") {
3859
+ this.onClick = false;
3860
+ this.tip.hide();
3861
+ return;
3862
+ }
3863
+ if (event.target.tagName == "circle") {
3864
+ this.onClick = event.type == "click";
3865
+ const d = event.target.__data__;
3866
+ const menu = this.tip.clear();
3867
+ const table = menu.d.append("table");
3868
+ let tr = table.append("tr");
3869
+ tr.append("td").style("color", "#aaa").text(plot.colorBy);
3870
+ let td = tr.append("td");
3871
+ td.text(d.category);
3872
+ if ("geneExp" in d) {
3873
+ tr = table.append("tr");
3874
+ tr.append("td").style("color", "#aaa").text("Gene expression");
3875
+ td = tr.append("td");
3876
+ const svg = td.append("svg").attr("width", 150).attr("height", 20);
3877
+ const x = 10;
3878
+ const y = 12;
3879
+ const g = svg.append("g").attr("transform", `translate(${x}, ${y})`);
3880
+ g.append("circle").attr("fill", this.getColor(d, plot)).attr("r", 4);
3881
+ svg.append("g").attr("transform", `translate(${x + 15}, ${y + 4})`).append("text").text(roundValueAuto(d.geneExp));
3882
+ }
3883
+ menu.show(event.clientX, event.clientY, true, true);
3884
+ } else this.onMouseOut(event);
3885
+ }
3886
+ onMouseOut(event) {
3887
+ this.tip.hide();
3888
+ }
3889
+ async renderSamplesTable() {
3890
+ const state = this.state;
3891
+ const div = this.dom.samplesTableDiv;
3892
+ div.selectAll("*").remove();
3893
+ const [rows, columns] = await this.getTableData(state);
3894
+ if (columns.length > 5) div.style("font-size", "0.9em");
3895
+ const selectedRows = [];
3896
+ const i = this.samples.findIndex((i2) => i2.sample == state.config.sample);
3897
+ if (i != -1) selectedRows.push(i);
3898
+ renderTable({
3899
+ rows,
3900
+ columns,
3901
+ resize: true,
3902
+ singleMode: true,
3903
+ div,
3904
+ maxWidth: columns.length > 3 ? "98vw" : "40vw",
3905
+ maxHeight: "50vh",
3906
+ dataTestId: "sjppoldscSampleTable",
3907
+ noButtonCallback: (index) => {
3908
+ const sample = rows[index][0].value;
3909
+ const hiddenClusters = {};
3910
+ for (const cluster in this.config.hiddenClusters) hiddenClusters[cluster] = false;
3911
+ const settings = {
3912
+ colorScaleMode: "auto",
3913
+ colorScaleMinFixed: null,
3914
+ colorScaleMaxFixed: null,
3915
+ colorScalePercentile: 95,
3916
+ showNoExpCells: false,
3917
+ showContour: false,
3918
+ colorContours: false,
3919
+ contourBandwidth: 15,
3920
+ contourThresholds: 10
3921
+ };
3922
+ const config = {
3923
+ chartType: "singleCellPlot",
3924
+ sample,
3925
+ // track sample name to identify it in this.samples[]
3926
+ activeTab: PLOTS_TAB,
3927
+ // on selecting a sample from table, auto switch to plots to directly show this sample's plots, to save user a click
3928
+ cluster: null,
3929
+ // reset cluster
3930
+ hiddenClusters,
3931
+ // reset hidden clusters
3932
+ settings: { singleCellPlot: settings }
3933
+ };
3934
+ this.genes = null;
3935
+ if (rows[index][0].__experimentID) {
3936
+ config.experimentID = rows[index][0].__experimentID;
3937
+ }
3938
+ this.app.dispatch({ type: "plot_edit", id: this.id, config });
3939
+ },
3940
+ selectedRows,
3941
+ striped: true,
3942
+ header: { style: { "text-transform": "capitalize" } }
3943
+ // to show header in title case; if it results in a conflict (e.g. a sample name showing in 1st tab has to be lower case), then use sampleColumns[].columnHeader as override of term name
3944
+ });
3945
+ }
3946
+ async getTableData(state) {
3947
+ const { uiLabels } = state.config.settings.singleCellPlot;
3948
+ const s = state.termdbConfig.queries?.singleCell?.samples || {};
3949
+ const samples = this.samples;
3950
+ const rows = [];
3951
+ const hasExperiments = samples.some((i) => i.experiments);
3952
+ const columns = [{ label: uiLabels.Sample }];
3953
+ if (hasExperiments) columns.push({ label: "Sample" });
3954
+ for (const c of s.sampleColumns || []) {
3955
+ let label = c.termid;
3956
+ try {
3957
+ label = (await this.app.vocabApi.getterm(c.termid)).name;
3958
+ } catch (e) {
3959
+ }
3960
+ columns.push({ label, width: "14vw" });
3961
+ }
3962
+ if (hasExperiments) columns.push({ label: "Experiment" });
3963
+ for (const sample of samples) {
3964
+ if (hasExperiments)
3965
+ for (const exp of sample.experiments) {
3966
+ const row = [{ value: sample.sample, __experimentID: exp.experimentID }];
3967
+ row.push({ value: exp.sampleName });
3968
+ for (const c of s.sampleColumns || []) {
3969
+ row.push({ value: sample[c.termid] });
3970
+ }
3971
+ const urlTemp = this.state.termdbConfig?.urlTemplates?.scrnaExperimentId;
3972
+ if (urlTemp) row.push({ value: exp.experimentID, url: `${urlTemp.base}${exp.experimentID}` });
3973
+ else row.push({ value: exp.experimentID });
3974
+ rows.push(row);
3975
+ }
3976
+ else {
3977
+ const row = [{ value: sample.sample }];
3978
+ for (const c of s.sampleColumns || []) {
3979
+ row.push({ value: sample[c.termid] });
3980
+ }
3981
+ rows.push(row);
3982
+ }
3983
+ }
3984
+ return [rows, columns];
3985
+ }
3986
+ renderLargePlotThree = async function(plot) {
3987
+ if (!plot.canvas) {
3988
+ const canvas = plot.plotDiv.append("canvas").attr("data-testid", "sjppoldsccanvas").style("display", "inline-block").style("vertical-align", "top");
3989
+ plot.canvas = canvas.node();
3990
+ plot.canvas.width = this.settings.svgw;
3991
+ plot.canvas.height = this.settings.svgh;
3992
+ plot.renderer = new WebGLRenderer({ antialias: true, canvas: plot.canvas, preserveDrawingBuffer: true });
3993
+ } else plot.renderer.clear();
3994
+ const renderer = plot.renderer;
3995
+ renderer.outputColorSpace = LinearSRGBColorSpace;
3996
+ const DragControls = await import("./DragControls-OMQWC4YY.js");
3997
+ const fov = this.settings.threeFOV;
3998
+ const near = 0.1;
3999
+ const far = 1e3;
4000
+ const camera = new PerspectiveCamera(fov, 1, near, far);
4001
+ const scene = new Scene();
4002
+ camera.position.set(0, 0, 2);
4003
+ camera.lookAt(scene.position);
4004
+ camera.updateMatrix();
4005
+ const whiteColor = new Color("rgb(255,255,255)");
4006
+ scene.background = whiteColor;
4007
+ const geometry = new BufferGeometry();
4008
+ const { vertices, colors } = this.getVertices(plot);
4009
+ geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
4010
+ geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
4011
+ const tex = getThreeCircle(256);
4012
+ const material = new PointsMaterial({
4013
+ size: this.settings.sampleSizeThree,
4014
+ sizeAttenuation: true,
4015
+ transparent: true,
4016
+ opacity: this.settings.opacity,
4017
+ map: tex,
4018
+ vertexColors: true
4019
+ });
4020
+ const particles = new Points(geometry, material);
4021
+ plot.particles = particles;
4022
+ scene.add(particles);
4023
+ renderer.setSize(this.settings.svgw, this.settings.svgh);
4024
+ renderer.setPixelRatio(window.devicePixelRatio);
4025
+ plot.canvas.addEventListener("mousewheel", (event) => {
4026
+ if (!event.ctrlKey) return;
4027
+ event.preventDefault();
4028
+ particles.position.z -= event.deltaY / 500;
4029
+ });
4030
+ if (this.settings.showContour && this.state.config.gene && this.state.config.activeTab == GENE_EXPRESSION_TAB) {
4031
+ const cells = plot.expCells.length > 0 ? plot.expCells : plot.cells;
4032
+ const xAxisScale = plot.xAxisScale.range([0, this.settings.svgw]);
4033
+ const yAxisScale = plot.yAxisScale.range([this.settings.svgh, 0]);
4034
+ let zAxisScale;
4035
+ if (plot.expCells.length > 0) {
4036
+ const [min, max2] = extent(plot.expCells, (d) => d.geneExp);
4037
+ zAxisScale = linear().domain([min, max2]).range([0, 1]);
4038
+ }
4039
+ const xCoords = cells.map((c) => xAxisScale(c.x));
4040
+ const yCoords = cells.map((c) => yAxisScale(c.y));
4041
+ const zCoords = cells.map((c) => zAxisScale ? zAxisScale(c.geneExp) : 1);
4042
+ await this.renderContourMap(scene, xCoords, yCoords, zCoords, plot);
4043
+ }
4044
+ const controls = new DragControls.DragControls([particles], camera, renderer.domElement);
4045
+ function animate() {
4046
+ requestAnimationFrame(animate);
4047
+ renderer.render(scene, camera);
4048
+ }
4049
+ animate();
4050
+ if (this.settings.showGrid) this.renderThreeGrid(scene);
4051
+ };
4052
+ async renderContourMap(scene, xCoords, yCoords, zCoords, plot) {
4053
+ const data = xCoords.map((x, i) => ({ x, y: yCoords[i], z: zCoords[i] }));
4054
+ const imageUrl = getContourImage(
4055
+ data,
4056
+ this.settings.svgw,
4057
+ this.settings.svgh,
4058
+ this.settings.colorContours,
4059
+ this.settings.contourBandwidth,
4060
+ this.settings.contourThresholds
4061
+ );
4062
+ const loader = new TextureLoader();
4063
+ loader.load(imageUrl, (texture) => {
4064
+ const geometry = new PlaneGeometry(2, 2);
4065
+ const material = new MeshBasicMaterial({ map: texture, transparent: true, color: 1315860 });
4066
+ const plane = new Mesh(geometry, material);
4067
+ scene.add(plane);
4068
+ plot.plane = plane;
4069
+ plane.position.z = 1e-5;
4070
+ plot.particles.add(plane);
4071
+ });
4072
+ }
4073
+ renderThreeGrid(scene) {
4074
+ let x = -1;
4075
+ const lineMaterial = new LineBasicMaterial({ color: 4292072403 });
4076
+ const lines = 10;
4077
+ const step = 2 / lines;
4078
+ for (let i = 0; i < lines; i++) {
4079
+ let points = [];
4080
+ points.push(new Vector3(x, 1.5, 0));
4081
+ points.push(new Vector3(x, -1.5, 0));
4082
+ let lineGeometry = new BufferGeometry().setFromPoints(points);
4083
+ let line = new Line(lineGeometry, lineMaterial);
4084
+ line.position.z = 1;
4085
+ scene.add(line);
4086
+ points = [];
4087
+ points.push(new Vector3(-1.5, x, 0));
4088
+ points.push(new Vector3(1.5, x, 0));
4089
+ lineGeometry = new BufferGeometry().setFromPoints(points);
4090
+ line = new Line(lineGeometry, lineMaterial);
4091
+ scene.add(line);
4092
+ x += step;
4093
+ line.position.z = 1;
4094
+ }
4095
+ }
4096
+ getVertices(plot) {
4097
+ const vertices = [];
4098
+ const colors = [];
4099
+ for (const c of plot.cells) {
4100
+ const opacity = this.getOpacity(c);
4101
+ if (opacity == 0) continue;
4102
+ let x = plot.xAxisScale(c.x);
4103
+ let y = plot.yAxisScale(c.y);
4104
+ const rgbColor = rgb(this.getColor(c, plot));
4105
+ vertices.push(x, y, 0);
4106
+ colors.push(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255);
4107
+ }
4108
+ return { vertices, colors };
4109
+ }
4110
+ };
4111
+ function getContourImage(data, width, height, colorContours, bandwidth, thresholds) {
4112
+ const svg = create_default("svg").attr("width", width).attr("height", height);
4113
+ renderContours(svg.append("g"), data, width, height, colorContours, bandwidth, thresholds);
4114
+ const svgString = new XMLSerializer().serializeToString(svg.node());
4115
+ const encodedSvg = encodeURIComponent(svgString);
4116
+ const imageUrl = "data:image/svg+xml;charset=utf-8," + encodedSvg;
4117
+ return imageUrl;
4118
+ }
4119
+ function getMouseNDC(event, rect) {
4120
+ return new Vector2(
4121
+ (event.clientX - rect.left) / rect.width * 2 - 1,
4122
+ -(event.clientY - rect.top) / rect.height * 2 + 1
4123
+ );
4124
+ }
4125
+ var scatterInit = getCompInit(singleCellPlot);
4126
+ var componentInit = scatterInit;
4127
+ async function getPlotConfig(opts, app) {
4128
+ try {
4129
+ const data = app.vocabApi.termdbConfig?.queries?.singleCell?.data;
4130
+ const plots = data?.plots;
4131
+ let settings = getDefaultSingleCellSettings();
4132
+ if (data.settings)
4133
+ for (const key in data.settings) {
4134
+ settings[key] = data.settings[key];
4135
+ }
4136
+ const config = {
4137
+ hiddenClusters: {},
4138
+ settings: {
4139
+ singleCellPlot: settings,
4140
+ controls: { isOpen: false }
4141
+ },
4142
+ startColor: {},
4143
+ stopColor: {},
4144
+ plots,
4145
+ hidePlotFilter: true
4146
+ };
4147
+ const result = copyMerge(config, opts);
4148
+ return result;
4149
+ } catch (e) {
4150
+ console.log(e);
4151
+ throw `${e} [singleCellPlot getPlotConfig()]`;
4152
+ }
4153
+ }
4154
+ function getDefaultSingleCellSettings() {
4155
+ return {
4156
+ svgw: 600,
4157
+ svgh: 600,
4158
+ showGrid: true,
4159
+ sampleSize: 1.5,
4160
+ sampleSizeThree: 0.04,
4161
+ threeFOV: 60,
4162
+ opacity: 0.8,
4163
+ showNoExpCells: false,
4164
+ showContour: false,
4165
+ colorContours: false,
4166
+ contourBandwidth: 15,
4167
+ contourThresholds: 10,
4168
+ uiLabels: {
4169
+ // allow customized user interface labels (buttons, menus, etc) by dataset override,
4170
+ // for example in GDC, use 'Case' instead of 'Sample'
4171
+ // TODO: different plots should use the same uiLabels override,
4172
+ // should not need to define separately for matrix, single cell, etc
4173
+ Samples: "Samples",
4174
+ samples: "samples",
4175
+ Sample: "Sample",
4176
+ sample: "sample"
4177
+ },
4178
+ colorScaleMode: "auto",
4179
+ // Default to automatic scaling based on data range
4180
+ // Other options: 'fixed' (user-defined range) or
4181
+ // 'percentile' (scale based on data distribution)
4182
+ colorScalePercentile: 95,
4183
+ // Default percentile for percentile mode
4184
+ // This means we'll scale colors based on values
4185
+ // up to the 95th percentile by default
4186
+ colorScaleMinFixed: null,
4187
+ // User-defined minimum value for fixed mode
4188
+ // Null indicates this hasn't been set yet
4189
+ colorScaleMaxFixed: null
4190
+ // User-defined maximum value for fixed mode
4191
+ };
4192
+ }
4193
+
4194
+ export {
4195
+ ScatterModel,
4196
+ ScatterView,
4197
+ ScatterViewModel,
4198
+ ScatterViewModel2DLarge,
4199
+ getThreeCircle,
4200
+ getContourImage,
4201
+ getMouseNDC,
4202
+ scatterInit,
4203
+ componentInit,
4204
+ getPlotConfig,
4205
+ getDefaultSingleCellSettings
4206
+ };
4207
+ //# sourceMappingURL=chunk-E6KEZENR.js.map