igv 2.11.0 → 2.11.1
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.
- package/README.md +10 -10
- package/dist/igv.esm.js +632 -606
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +641 -588
- package/dist/igv.min.js +6 -6
- package/dist/igv.min.js.map +1 -1
- package/package.json +4 -4
package/dist/igv.esm.js
CHANGED
|
@@ -17624,7 +17624,7 @@ function Node(interval) {
|
|
|
17624
17624
|
* @constructor
|
|
17625
17625
|
*/
|
|
17626
17626
|
|
|
17627
|
-
class FeatureCache {
|
|
17627
|
+
class FeatureCache$1 {
|
|
17628
17628
|
|
|
17629
17629
|
constructor(featureList, genome, range) {
|
|
17630
17630
|
|
|
@@ -19091,7 +19091,7 @@ function createMenuElements$1(itemList, popover) {
|
|
|
19091
19091
|
|
|
19092
19092
|
function embedCSS$2() {
|
|
19093
19093
|
|
|
19094
|
-
var css = '.igv-ui-popover {\n cursor: default;\n position: absolute;\n z-index: 2048;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n background-color: white; }\n .igv-ui-popover > div:first-child {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px; }\n .igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-popover > div:last-child {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white; }\n .igv-ui-popover > div:last-child > div {\n -webkit-user-select: all;\n /* Chrome/Safari */\n -moz-user-select: all;\n /* Firefox */\n margin-left: 4px;\n margin-right: 4px;\n min-width: 220px;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n .igv-ui-popover > div:last-child > div > span {\n font-weight: bolder; }\n .igv-ui-popover > div:last-child hr {\n width: 100%; }\n\n.igv-ui-alert-dialog-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n top: 50%;\n left: 50%;\n width: 400px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n outline: none;\n font-family: \"Open Sans\", sans-serif;\n font-size: 15px;\n font-weight: 400;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:first-child {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body {\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body .igv-ui-alert-dialog-body-copy {\n cursor: pointer;\n margin: 16px;\n width: auto;\n height: auto;\n overflow-wrap: break-word;\n word-break: break-word;\n -webkit-user-select: all;\n -moz-user-select: all;\n -ms-user-select: all;\n user-select: all;\n background-color: white;\n border: unset; }\n .igv-ui-alert-dialog-container > div:last-child {\n width: 100%;\n margin-bottom: 10px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:last-child div {\n margin: unset;\n width: 40px;\n height: 30px;\n line-height: 30px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n border-color: #2B81AF;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-alert-dialog-container > div:last-child div:hover {\n cursor: pointer;\n border-color: #25597f;\n background-color: #25597f; }\n\n.igv-ui-color-swatch {\n position: relative;\n box-sizing: content-box;\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n justify-content: center;\n align-items: center;\n width: 32px;\n height: 32px;\n border-style: solid;\n border-width: 2px;\n border-color: white;\n border-radius: 4px; }\n\n.igv-ui-color-swatch:hover {\n border-color: dimgray; }\n\n.igv-ui-colorpicker-menu-close-button {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 32px;\n margin-top: 4px;\n margin-bottom: 4px;\n padding-right: 8px; }\n .igv-ui-colorpicker-menu-close-button i.fa {\n display: block;\n margin-left: 4px;\n margin-right: 4px;\n color: #5f5f5f; }\n .igv-ui-colorpicker-menu-close-button i.fa:hover,\n .igv-ui-colorpicker-menu-close-button i.fa:focus,\n .igv-ui-colorpicker-menu-close-button i.fa:active {\n cursor: pointer;\n color: #0f0f0f; }\n\n.igv-ui-generic-dialog-container {\n box-sizing: content-box;\n position: fixed;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-generic-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-container div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-ui-generic-container div:first-child div {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-ui-dialog {\n z-index: 2048;\n position: fixed;\n width: fit-content;\n height: fit-content;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n background-color: white;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400; }\n .igv-ui-dialog .igv-ui-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-dialog .igv-ui-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-dialog .igv-ui-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-dialog .igv-ui-dialog-one-liner {\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin: 8px;\n overflow-wrap: break-word;\n background-color: white;\n font-weight: bold; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel {\n width: 100%;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div {\n margin: 16px;\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child {\n background-color: #5ea4e0; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child {\n background-color: #c4c4c4; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-dialog .igv-ui-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-dialog .igv-ui-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-panel, .igv-ui-panel-column, .igv-ui-panel-row {\n z-index: 2048;\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n.igv-ui-panel-column {\n display: flex;\n flex-direction: column; }\n\n.igv-ui-panel-row {\n display: flex;\n flex-direction: row; }\n\n.igv-ui-textbox {\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n/*# sourceMappingURL=igv-ui.css.map */\n';
|
|
19094
|
+
var css = '.igv-ui-popover {\n cursor: default;\n position: absolute;\n z-index: 2048;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: 1px;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n background-color: white; }\n .igv-ui-popover > div:first-child {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-popover > div:first-child > div:first-child {\n margin-left: 4px; }\n .igv-ui-popover > div:first-child > div:last-child {\n margin-right: 4px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-popover > div:first-child > div:last-child:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-popover > div:last-child {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: 400px;\n max-width: 800px;\n background-color: white; }\n .igv-ui-popover > div:last-child > div {\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n margin-left: 4px;\n margin-right: 4px;\n min-width: 220px;\n overflow-x: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n .igv-ui-popover > div:last-child > div > span {\n font-weight: bolder; }\n .igv-ui-popover > div:last-child hr {\n width: 100%; }\n\n.igv-ui-alert-dialog-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n top: 50%;\n left: 50%;\n width: 400px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n outline: none;\n font-family: \"Open Sans\", sans-serif;\n font-size: 15px;\n font-weight: 400;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:first-child {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-alert-dialog-container > div:first-child div:first-child {\n padding-left: 8px; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body {\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n color: #373737;\n width: 100%;\n height: calc(100% - 24px - 64px);\n overflow-y: scroll; }\n .igv-ui-alert-dialog-container .igv-ui-alert-dialog-body .igv-ui-alert-dialog-body-copy {\n margin: 16px;\n width: auto;\n height: auto;\n overflow-wrap: break-word;\n word-break: break-word;\n background-color: white;\n border: unset; }\n .igv-ui-alert-dialog-container > div:last-child {\n width: 100%;\n margin-bottom: 10px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: center;\n align-items: center; }\n .igv-ui-alert-dialog-container > div:last-child div {\n margin: unset;\n width: 40px;\n height: 30px;\n line-height: 30px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: small;\n font-weight: 400;\n border-color: #2B81AF;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-alert-dialog-container > div:last-child div:hover {\n cursor: pointer;\n border-color: #25597f;\n background-color: #25597f; }\n\n.igv-ui-color-swatch {\n position: relative;\n box-sizing: content-box;\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n justify-content: center;\n align-items: center;\n width: 32px;\n height: 32px;\n border-style: solid;\n border-width: 2px;\n border-color: white;\n border-radius: 4px; }\n\n.igv-ui-color-swatch:hover {\n border-color: dimgray; }\n\n.igv-ui-colorpicker-menu-close-button {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 32px;\n margin-top: 4px;\n margin-bottom: 4px;\n padding-right: 8px; }\n .igv-ui-colorpicker-menu-close-button i.fa {\n display: block;\n margin-left: 4px;\n margin-right: 4px;\n color: #5f5f5f; }\n .igv-ui-colorpicker-menu-close-button i.fa:hover,\n .igv-ui-colorpicker-menu-close-button i.fa:focus,\n .igv-ui-colorpicker-menu-close-button i.fa:active {\n cursor: pointer;\n color: #0f0f0f; }\n\n.igv-ui-generic-dialog-container {\n box-sizing: content-box;\n position: fixed;\n top: 0;\n left: 0;\n width: 300px;\n height: 200px;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n z-index: 2048;\n background-color: white;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-one-liner {\n color: #373737;\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin-top: 8px;\n padding-left: 8px;\n overflow-wrap: break-word;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input {\n margin-top: 8px;\n width: 95%;\n height: 24px;\n color: #373737;\n line-height: 24px;\n padding-left: 8px;\n background-color: white;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input div {\n width: 30%;\n height: 100%;\n font-size: 16px;\n text-align: right;\n padding-right: 8px;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-label-input input {\n width: 50%;\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input {\n margin-top: 8px;\n width: calc(100% - 16px);\n height: 24px;\n color: #373737;\n line-height: 24px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n display: block;\n height: 100%;\n width: 100%;\n padding-left: 4px;\n font-family: \"Open Sans\", sans-serif;\n font-weight: 400;\n color: #373737;\n text-align: left;\n outline: none;\n border-style: solid;\n border-width: thin;\n border-color: #7F7F7F;\n background-color: white; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-input input {\n font-size: 16px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel {\n width: 100%;\n height: 28px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div {\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child {\n margin-left: 32px;\n margin-right: 0;\n background-color: #5ea4e0; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child {\n margin-left: 0;\n margin-right: 32px;\n background-color: #c4c4c4; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-generic-dialog-container .igv-ui-generic-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-generic-container {\n box-sizing: content-box;\n position: absolute;\n z-index: 2048;\n background-color: white;\n cursor: pointer;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n align-items: center; }\n .igv-ui-generic-container > div:first-child {\n cursor: move;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n height: 24px;\n width: 100%;\n background-color: #dddddd; }\n .igv-ui-generic-container > div:first-child > div {\n display: block;\n color: #5f5f5f;\n cursor: pointer;\n width: 14px;\n height: 14px;\n margin-right: 8px;\n margin-bottom: 4px; }\n\n.igv-ui-dialog {\n z-index: 2048;\n position: fixed;\n width: fit-content;\n height: fit-content;\n display: flex;\n flex-flow: column;\n flex-wrap: nowrap;\n justify-content: flex-start;\n background-color: white;\n border-color: #7F7F7F;\n border-radius: 4px;\n border-style: solid;\n border-width: thin;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400; }\n .igv-ui-dialog .igv-ui-dialog-header {\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: flex-end;\n align-items: center;\n width: 100%;\n height: 24px;\n cursor: move;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-color: #7F7F7F;\n border-bottom-style: solid;\n border-bottom-width: thin;\n background-color: #eee; }\n .igv-ui-dialog .igv-ui-dialog-header div {\n margin-right: 4px;\n margin-bottom: 2px;\n height: 12px;\n width: 12px;\n color: #7F7F7F; }\n .igv-ui-dialog .igv-ui-dialog-header div:hover {\n cursor: pointer;\n color: #444; }\n .igv-ui-dialog .igv-ui-dialog-one-liner {\n width: 95%;\n height: 24px;\n line-height: 24px;\n text-align: left;\n margin: 8px;\n overflow-wrap: break-word;\n background-color: white;\n font-weight: bold; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel {\n width: 100%;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div {\n margin: 16px;\n margin-top: 32px;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: 14px;\n font-weight: 400;\n width: 75px;\n height: 28px;\n line-height: 28px;\n text-align: center;\n border-color: transparent;\n border-style: solid;\n border-width: thin;\n border-radius: 2px; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child {\n background-color: #5ea4e0; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child {\n background-color: #c4c4c4; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:first-child:hover {\n cursor: pointer;\n background-color: #3b5c7f; }\n .igv-ui-dialog .igv-ui-dialog-ok-cancel div:last-child:hover {\n cursor: pointer;\n background-color: #7f7f7f; }\n .igv-ui-dialog .igv-ui-dialog-ok {\n width: 100%;\n height: 36px;\n margin-top: 32px;\n display: flex;\n flex-flow: row;\n flex-wrap: nowrap;\n justify-content: space-around;\n align-items: center; }\n .igv-ui-dialog .igv-ui-dialog-ok div {\n width: 98px;\n height: 36px;\n line-height: 36px;\n text-align: center;\n color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n border-color: white;\n border-style: solid;\n border-width: thin;\n border-radius: 4px;\n background-color: #2B81AF; }\n .igv-ui-dialog .igv-ui-dialog-ok div:hover {\n cursor: pointer;\n background-color: #25597f; }\n\n.igv-ui-panel, .igv-ui-panel-column, .igv-ui-panel-row {\n z-index: 2048;\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n.igv-ui-panel-column {\n display: flex;\n flex-direction: column; }\n\n.igv-ui-panel-row {\n display: flex;\n flex-direction: row; }\n\n.igv-ui-textbox {\n background-color: white;\n font-family: \"Open Sans\", sans-serif;\n font-size: medium;\n font-weight: 400;\n display: flex;\n justify-content: flex-start;\n align-items: flex-start; }\n\n/*# sourceMappingURL=igv-ui.css.map */\n';
|
|
19095
19095
|
|
|
19096
19096
|
var style = document.createElement('style');
|
|
19097
19097
|
style.setAttribute('type', 'text/css');
|
|
@@ -19711,6 +19711,7 @@ const knownFileExtensions = new Set([
|
|
|
19711
19711
|
"vcf",
|
|
19712
19712
|
"bb",
|
|
19713
19713
|
"bigbed",
|
|
19714
|
+
"biginteract",
|
|
19714
19715
|
"bw",
|
|
19715
19716
|
"bigwig",
|
|
19716
19717
|
"bam",
|
|
@@ -19861,6 +19862,7 @@ function inferTrackType(config) {
|
|
|
19861
19862
|
case "bed":
|
|
19862
19863
|
case "bigbed":
|
|
19863
19864
|
case "bb":
|
|
19865
|
+
case "biginteract":
|
|
19864
19866
|
return "bedtype"
|
|
19865
19867
|
default:
|
|
19866
19868
|
return "annotation"
|
|
@@ -20586,14 +20588,13 @@ class Viewport {
|
|
|
20586
20588
|
console.log('Viewport - draw(drawConfiguration, features, roiFeatures)');
|
|
20587
20589
|
}
|
|
20588
20590
|
|
|
20589
|
-
checkContentHeight() {
|
|
20591
|
+
checkContentHeight(features) {
|
|
20590
20592
|
|
|
20591
20593
|
let track = this.trackView.track;
|
|
20592
|
-
|
|
20594
|
+
features = features || this.cachedFeatures;
|
|
20593
20595
|
if ("FILL" === track.displayMode) {
|
|
20594
20596
|
this.setContentHeight(this.$viewport.height());
|
|
20595
20597
|
} else if (typeof track.computePixelHeight === 'function') {
|
|
20596
|
-
let features = this.cachedFeatures;
|
|
20597
20598
|
if (features && features.length > 0) {
|
|
20598
20599
|
let requiredContentHeight = track.computePixelHeight(features);
|
|
20599
20600
|
let currentContentHeight = this.$content.height();
|
|
@@ -20609,12 +20610,11 @@ class Viewport {
|
|
|
20609
20610
|
}
|
|
20610
20611
|
|
|
20611
20612
|
setContentHeight(contentHeight) {
|
|
20613
|
+
|
|
20612
20614
|
// Maximum height of a canvas is ~32,000 pixels on Chrome, possibly smaller on other platforms
|
|
20613
20615
|
contentHeight = Math.min(contentHeight, 32000);
|
|
20614
|
-
|
|
20615
20616
|
this.$content.height(contentHeight);
|
|
20616
|
-
|
|
20617
|
-
if (this.tile) this.tile.invalidate = true;
|
|
20617
|
+
if (this.canvas._data) this.canvas._data.invalidate = true;
|
|
20618
20618
|
}
|
|
20619
20619
|
|
|
20620
20620
|
isLoading() {
|
|
@@ -20631,8 +20631,6 @@ class Viewport {
|
|
|
20631
20631
|
|
|
20632
20632
|
setWidth(width) {
|
|
20633
20633
|
this.$viewport.width(width);
|
|
20634
|
-
this.canvas.style.width = (`${width}px`);
|
|
20635
|
-
this.canvas.setAttribute('width', width);
|
|
20636
20634
|
}
|
|
20637
20635
|
|
|
20638
20636
|
getWidth() {
|
|
@@ -22759,7 +22757,7 @@ const Cytoband = function (start, end, name, typestain) {
|
|
|
22759
22757
|
}
|
|
22760
22758
|
};
|
|
22761
22759
|
|
|
22762
|
-
const _version = "2.11.
|
|
22760
|
+
const _version = "2.11.1";
|
|
22763
22761
|
function version() {
|
|
22764
22762
|
return _version
|
|
22765
22763
|
}
|
|
@@ -23294,17 +23292,21 @@ class TrackViewport extends Viewport {
|
|
|
23294
23292
|
checkZoomIn() {
|
|
23295
23293
|
|
|
23296
23294
|
const showZoomInNotice = () => {
|
|
23297
|
-
const referenceFrame = this.referenceFrame;
|
|
23298
23295
|
if (this.referenceFrame.chr.toLowerCase() === "all" && !this.trackView.track.supportsWholeGenome()) {
|
|
23299
23296
|
return true
|
|
23300
23297
|
} else {
|
|
23301
23298
|
const visibilityWindow = this.trackView.track.visibilityWindow;
|
|
23302
23299
|
return (
|
|
23303
23300
|
visibilityWindow !== undefined && visibilityWindow > 0 &&
|
|
23304
|
-
(referenceFrame.bpPerPixel * this.$viewport.width() > visibilityWindow))
|
|
23301
|
+
(this.referenceFrame.bpPerPixel * this.$viewport.width() > visibilityWindow))
|
|
23305
23302
|
}
|
|
23306
23303
|
};
|
|
23307
23304
|
|
|
23305
|
+
if (this.trackView.track && "sequence" === this.trackView.track.type && this.referenceFrame.bpPerPixel > 1) {
|
|
23306
|
+
if (this.canvas) ;
|
|
23307
|
+
return false
|
|
23308
|
+
}
|
|
23309
|
+
|
|
23308
23310
|
if (!(this.viewIsReady())) {
|
|
23309
23311
|
return false
|
|
23310
23312
|
}
|
|
@@ -23314,7 +23316,8 @@ class TrackViewport extends Viewport {
|
|
|
23314
23316
|
// Out of visibility window
|
|
23315
23317
|
if (this.canvas) {
|
|
23316
23318
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
23317
|
-
this.
|
|
23319
|
+
this.canvas._data = undefined;
|
|
23320
|
+
this.featureCache = undefined;
|
|
23318
23321
|
}
|
|
23319
23322
|
this.$zoomInNotice.show();
|
|
23320
23323
|
|
|
@@ -23331,21 +23334,19 @@ class TrackViewport extends Viewport {
|
|
|
23331
23334
|
}
|
|
23332
23335
|
|
|
23333
23336
|
return true
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
23337
|
}
|
|
23337
23338
|
|
|
23339
|
+
/**
|
|
23340
|
+
* Adjust the canvas to the current genomic state.
|
|
23341
|
+
*/
|
|
23338
23342
|
shift() {
|
|
23339
|
-
const
|
|
23340
|
-
|
|
23341
|
-
|
|
23342
|
-
|
|
23343
|
-
|
|
23344
|
-
|
|
23345
|
-
|
|
23346
|
-
|
|
23347
|
-
const pixelOffset = Math.round((self.tile.startBP - referenceFrame.start) / referenceFrame.bpPerPixel);
|
|
23348
|
-
self.canvas.style.left = pixelOffset + "px";
|
|
23343
|
+
const referenceFrame = this.referenceFrame;
|
|
23344
|
+
if (this.canvas &&
|
|
23345
|
+
this.canvas._data &&
|
|
23346
|
+
this.canvas._data.chr === this.referenceFrame.chr &&
|
|
23347
|
+
this.canvas._data.bpPerPixel === referenceFrame.bpPerPixel) {
|
|
23348
|
+
const pixelOffset = Math.round((this.canvas._data.startBP - referenceFrame.start) / referenceFrame.bpPerPixel);
|
|
23349
|
+
this.canvas.style.left = pixelOffset + "px";
|
|
23349
23350
|
}
|
|
23350
23351
|
}
|
|
23351
23352
|
|
|
@@ -23368,22 +23369,23 @@ class TrackViewport extends Viewport {
|
|
|
23368
23369
|
this.startSpinner();
|
|
23369
23370
|
|
|
23370
23371
|
try {
|
|
23371
|
-
const
|
|
23372
|
+
const track = this.trackView.track;
|
|
23373
|
+
const features = await this.getFeatures(track, chr, bpStart, bpEnd, referenceFrame.bpPerPixel);
|
|
23372
23374
|
let roiFeatures = [];
|
|
23373
|
-
const roi = mergeArrays(this.browser.roi,
|
|
23375
|
+
const roi = mergeArrays(this.browser.roi, track.roi);
|
|
23374
23376
|
if (roi) {
|
|
23375
23377
|
for (let r of roi) {
|
|
23376
|
-
const f = await
|
|
23377
|
-
r.getFeatures(chr, bpStart, bpEnd, referenceFrame.bpPerPixel);
|
|
23378
|
+
const f = await r.getFeatures(chr, bpStart, bpEnd, referenceFrame.bpPerPixel);
|
|
23378
23379
|
roiFeatures.push({track: r, features: f});
|
|
23379
23380
|
}
|
|
23380
23381
|
}
|
|
23381
23382
|
|
|
23382
|
-
|
|
23383
|
+
const mr = track && ("wig" === track.type || "merged" === track.type); // wig tracks are potentially multiresolution (e.g. bigwig)
|
|
23384
|
+
this.featureCache = new FeatureCache(chr, bpStart, bpEnd, referenceFrame.bpPerPixel, features, roiFeatures, mr);
|
|
23383
23385
|
this.loading = false;
|
|
23384
23386
|
this.hideMessage();
|
|
23385
23387
|
this.stopSpinner();
|
|
23386
|
-
return this.
|
|
23388
|
+
return this.featureCache
|
|
23387
23389
|
} catch (error) {
|
|
23388
23390
|
// Track might have been removed during load
|
|
23389
23391
|
if (this.trackView && this.trackView.disposed !== true) {
|
|
@@ -23397,25 +23399,31 @@ class TrackViewport extends Viewport {
|
|
|
23397
23399
|
}
|
|
23398
23400
|
}
|
|
23399
23401
|
|
|
23400
|
-
|
|
23402
|
+
/**
|
|
23403
|
+
* Repaint the canvas for the current genomic state.
|
|
23404
|
+
*
|
|
23405
|
+
* @returns {Promise<void>}
|
|
23406
|
+
*/
|
|
23407
|
+
repaint() {
|
|
23401
23408
|
|
|
23402
|
-
if (undefined === this.
|
|
23409
|
+
if (undefined === this.featureCache) {
|
|
23403
23410
|
return
|
|
23404
23411
|
}
|
|
23405
23412
|
|
|
23406
|
-
let {features, roiFeatures
|
|
23413
|
+
let {features, roiFeatures} = this.featureCache;
|
|
23414
|
+
//this.tile.bpPerPixel = this.referenceFrame.bpPerPixel
|
|
23407
23415
|
|
|
23408
23416
|
// const isWGV = GenomeUtils.isWholeGenomeView(this.browser.referenceFrameList[0].chr)
|
|
23409
23417
|
const isWGV = GenomeUtils.isWholeGenomeView(this.referenceFrame.chr);
|
|
23410
|
-
let pixelWidth;
|
|
23411
23418
|
|
|
23419
|
+
let pixelWidth;
|
|
23420
|
+
const startBP = this.featureCache.startBP;
|
|
23421
|
+
const endBP = this.featureCache.endBP;
|
|
23422
|
+
let bpPerPixel = this.referenceFrame.bpPerPixel;
|
|
23412
23423
|
if (isWGV) {
|
|
23413
|
-
bpPerPixel = this.referenceFrame.end / this.$viewport.width();
|
|
23414
|
-
startBP = 0;
|
|
23415
|
-
endBP = this.referenceFrame.end;
|
|
23416
23424
|
pixelWidth = this.$viewport.width();
|
|
23417
23425
|
} else {
|
|
23418
|
-
pixelWidth =
|
|
23426
|
+
pixelWidth = 3 * this.$viewport.width();
|
|
23419
23427
|
}
|
|
23420
23428
|
|
|
23421
23429
|
// For deep tracks we paint a canvas == 3*viewportHeight centered on the current vertical scroll position
|
|
@@ -23475,17 +23483,27 @@ class TrackViewport extends Viewport {
|
|
|
23475
23483
|
|
|
23476
23484
|
this.draw(drawConfiguration, features, roiFeatures);
|
|
23477
23485
|
|
|
23478
|
-
|
|
23486
|
+
// Attach metadata to canvas
|
|
23487
|
+
newCanvas._data = {
|
|
23488
|
+
chr: this.referenceFrame.chr, startBP, endBP, bpPerPixel, top: canvasTop, bottom: canvasTop + pixelHeight
|
|
23489
|
+
};
|
|
23479
23490
|
|
|
23480
|
-
if (this
|
|
23481
|
-
this
|
|
23491
|
+
if (this.canvas) {
|
|
23492
|
+
$$1(this.canvas).remove();
|
|
23482
23493
|
}
|
|
23483
|
-
this.$canvas = $$1(newCanvas);
|
|
23484
|
-
this.$content.append(this.$canvas);
|
|
23485
23494
|
this.canvas = newCanvas;
|
|
23486
23495
|
this.ctx = ctx;
|
|
23496
|
+
this.$content.append($$1(newCanvas));
|
|
23497
|
+
|
|
23487
23498
|
}
|
|
23488
23499
|
|
|
23500
|
+
/**
|
|
23501
|
+
* Draw the associated track.
|
|
23502
|
+
*
|
|
23503
|
+
* @param drawConfiguration
|
|
23504
|
+
* @param features
|
|
23505
|
+
* @param roiFeatures
|
|
23506
|
+
*/
|
|
23489
23507
|
draw(drawConfiguration, features, roiFeatures) {
|
|
23490
23508
|
|
|
23491
23509
|
// console.log(`${ Date.now() } viewport draw(). track ${ this.trackView.track.type }. content-css-top ${ this.$content.css('top') }. canvas-top ${ drawConfiguration.pixelTop }.`)
|
|
@@ -23502,60 +23520,6 @@ class TrackViewport extends Viewport {
|
|
|
23502
23520
|
}
|
|
23503
23521
|
}
|
|
23504
23522
|
|
|
23505
|
-
// TODO: Nolonger used. Will discard
|
|
23506
|
-
async toSVG(tile) {
|
|
23507
|
-
|
|
23508
|
-
// Nothing to do if zoomInNotice is active
|
|
23509
|
-
if (this.$zoomInNotice && this.$zoomInNotice.is(":visible")) {
|
|
23510
|
-
return
|
|
23511
|
-
}
|
|
23512
|
-
|
|
23513
|
-
const referenceFrame = this.referenceFrame;
|
|
23514
|
-
const bpPerPixel = tile.bpPerPixel;
|
|
23515
|
-
const features = tile.features;
|
|
23516
|
-
const roiFeatures = tile.roiFeatures;
|
|
23517
|
-
const pixelWidth = this.$viewport.width();
|
|
23518
|
-
const pixelHeight = this.$viewport.height();
|
|
23519
|
-
const bpStart = referenceFrame.start;
|
|
23520
|
-
const bpEnd = referenceFrame.start + pixelWidth * referenceFrame.bpPerPixel;
|
|
23521
|
-
|
|
23522
|
-
const ctx$1 = new ctx(
|
|
23523
|
-
{
|
|
23524
|
-
// svg
|
|
23525
|
-
width: pixelWidth,
|
|
23526
|
-
height: pixelHeight,
|
|
23527
|
-
viewbox:
|
|
23528
|
-
{
|
|
23529
|
-
x: 0,
|
|
23530
|
-
y: -this.$content.position().top,
|
|
23531
|
-
width: pixelWidth,
|
|
23532
|
-
height: pixelHeight
|
|
23533
|
-
}
|
|
23534
|
-
|
|
23535
|
-
});
|
|
23536
|
-
|
|
23537
|
-
const drawConfiguration =
|
|
23538
|
-
{
|
|
23539
|
-
viewport: this,
|
|
23540
|
-
context: ctx$1,
|
|
23541
|
-
top: -this.$content.position().top,
|
|
23542
|
-
pixelTop: 0, // for compatibility with canvas draw
|
|
23543
|
-
pixelWidth,
|
|
23544
|
-
pixelHeight,
|
|
23545
|
-
bpStart,
|
|
23546
|
-
bpEnd,
|
|
23547
|
-
bpPerPixel,
|
|
23548
|
-
referenceFrame: this.referenceFrame,
|
|
23549
|
-
selection: this.selection,
|
|
23550
|
-
viewportWidth: pixelWidth,
|
|
23551
|
-
};
|
|
23552
|
-
|
|
23553
|
-
this.draw(drawConfiguration, features, roiFeatures);
|
|
23554
|
-
|
|
23555
|
-
return ctx$1.getSerializedSvg(true)
|
|
23556
|
-
|
|
23557
|
-
}
|
|
23558
|
-
|
|
23559
23523
|
containsPosition(chr, position) {
|
|
23560
23524
|
if (this.referenceFrame.chr === chr && position >= this.referenceFrame.start) {
|
|
23561
23525
|
return position <= this.referenceFrame.calculateEnd(this.getWidth())
|
|
@@ -23568,11 +23532,12 @@ class TrackViewport extends Viewport {
|
|
|
23568
23532
|
return this.loading
|
|
23569
23533
|
}
|
|
23570
23534
|
|
|
23571
|
-
|
|
23535
|
+
savePNG() {
|
|
23572
23536
|
|
|
23573
23537
|
if (!this.ctx) return
|
|
23574
23538
|
|
|
23575
|
-
const
|
|
23539
|
+
const canvasMetadata = this.canvas._data;
|
|
23540
|
+
const canvasTop = canvasMetadata ? canvasMetadata.top : 0;
|
|
23576
23541
|
const devicePixelRatio = window.devicePixelRatio;
|
|
23577
23542
|
const w = this.$viewport.width() * devicePixelRatio;
|
|
23578
23543
|
const h = this.$viewport.height() * devicePixelRatio;
|
|
@@ -23702,26 +23667,25 @@ class TrackViewport extends Viewport {
|
|
|
23702
23667
|
selection: this.selection
|
|
23703
23668
|
};
|
|
23704
23669
|
|
|
23705
|
-
const features = this.
|
|
23706
|
-
const roiFeatures = this.
|
|
23670
|
+
const features = this.featureCache ? this.featureCache.features : [];
|
|
23671
|
+
const roiFeatures = this.featureCache ? this.featureCache.roiFeatures : undefined;
|
|
23707
23672
|
this.draw(config, features, roiFeatures);
|
|
23708
23673
|
|
|
23709
23674
|
context.restore();
|
|
23710
23675
|
|
|
23711
23676
|
}
|
|
23712
23677
|
|
|
23713
|
-
|
|
23714
|
-
return this.
|
|
23678
|
+
get cachedFeatures() {
|
|
23679
|
+
return this.featureCache ? this.featureCache.features : []
|
|
23715
23680
|
}
|
|
23716
23681
|
|
|
23717
23682
|
async getFeatures(track, chr, start, end, bpPerPixel) {
|
|
23718
23683
|
|
|
23719
|
-
if (this.
|
|
23720
|
-
return this.
|
|
23684
|
+
if (this.featureCache && this.featureCache.containsRange(chr, start, end, bpPerPixel)) {
|
|
23685
|
+
return this.featureCache.features
|
|
23721
23686
|
} else if (typeof track.getFeatures === "function") {
|
|
23722
23687
|
const features = await track.getFeatures(chr, start, end, bpPerPixel, this);
|
|
23723
|
-
this.
|
|
23724
|
-
this.checkContentHeight();
|
|
23688
|
+
this.checkContentHeight(features);
|
|
23725
23689
|
return features
|
|
23726
23690
|
} else {
|
|
23727
23691
|
return undefined
|
|
@@ -23959,9 +23923,7 @@ class TrackViewport extends Viewport {
|
|
|
23959
23923
|
lastClickTime = time;
|
|
23960
23924
|
|
|
23961
23925
|
}
|
|
23962
|
-
|
|
23963
23926
|
}
|
|
23964
|
-
|
|
23965
23927
|
}
|
|
23966
23928
|
|
|
23967
23929
|
removeViewportClickHandler(viewport) {
|
|
@@ -24025,16 +23987,10 @@ function mouseUpHandler(event) {
|
|
|
24025
23987
|
function createClickState(event, viewport) {
|
|
24026
23988
|
|
|
24027
23989
|
const referenceFrame = viewport.referenceFrame;
|
|
24028
|
-
|
|
24029
23990
|
const viewportCoords = translateMouseCoordinates$1(event, viewport.contentDiv);
|
|
24030
23991
|
const canvasCoords = translateMouseCoordinates$1(event, viewport.canvas);
|
|
24031
|
-
|
|
24032
23992
|
const genomicLocation = ((referenceFrame.start) + referenceFrame.toBP(viewportCoords.x));
|
|
24033
23993
|
|
|
24034
|
-
if (undefined === genomicLocation || null === viewport.tile) {
|
|
24035
|
-
return undefined
|
|
24036
|
-
}
|
|
24037
|
-
|
|
24038
23994
|
return {
|
|
24039
23995
|
event,
|
|
24040
23996
|
viewport,
|
|
@@ -24095,22 +24051,30 @@ function formatPopoverText(nameValues) {
|
|
|
24095
24051
|
return rows.join('')
|
|
24096
24052
|
}
|
|
24097
24053
|
|
|
24098
|
-
|
|
24099
|
-
this.chr = chr;
|
|
24100
|
-
this.startBP = tileStart;
|
|
24101
|
-
this.endBP = tileEnd;
|
|
24102
|
-
this.bpPerPixel = bpPerPixel;
|
|
24103
|
-
this.features = features;
|
|
24104
|
-
this.roiFeatures = roiFeatures;
|
|
24105
|
-
};
|
|
24054
|
+
class FeatureCache {
|
|
24106
24055
|
|
|
24107
|
-
|
|
24108
|
-
|
|
24109
|
-
|
|
24056
|
+
constructor(chr, tileStart, tileEnd, bpPerPixel, features, roiFeatures, multiresolution) {
|
|
24057
|
+
this.chr = chr;
|
|
24058
|
+
this.startBP = tileStart;
|
|
24059
|
+
this.endBP = tileEnd;
|
|
24060
|
+
this.bpPerPixel = bpPerPixel;
|
|
24061
|
+
this.features = features;
|
|
24062
|
+
this.roiFeatures = roiFeatures;
|
|
24063
|
+
this.multiresolution = multiresolution;
|
|
24064
|
+
}
|
|
24110
24065
|
|
|
24111
|
-
|
|
24112
|
-
|
|
24113
|
-
|
|
24066
|
+
containsRange(chr, start, end, bpPerPixel) {
|
|
24067
|
+
|
|
24068
|
+
// For multi-resolution tracks allow for a 2X change in bpPerPixel
|
|
24069
|
+
const r = this.multiresolution ? this.bpPerPixel / bpPerPixel : 1;
|
|
24070
|
+
|
|
24071
|
+
return start >= this.startBP && end <= this.endBP && chr === this.chr && r > 0.5 && r < 2
|
|
24072
|
+
}
|
|
24073
|
+
|
|
24074
|
+
overlapsRange(chr, start, end) {
|
|
24075
|
+
return this.chr === chr && end >= this.startBP && start <= this.endBP
|
|
24076
|
+
}
|
|
24077
|
+
}
|
|
24114
24078
|
|
|
24115
24079
|
|
|
24116
24080
|
/**
|
|
@@ -24417,6 +24381,18 @@ class PairedAlignment {
|
|
|
24417
24381
|
return true // By definition
|
|
24418
24382
|
}
|
|
24419
24383
|
|
|
24384
|
+
isMateMapped() {
|
|
24385
|
+
return true // By definition
|
|
24386
|
+
}
|
|
24387
|
+
|
|
24388
|
+
isProperPair() {
|
|
24389
|
+
return this.firstAlignment.isProperPair()
|
|
24390
|
+
}
|
|
24391
|
+
|
|
24392
|
+
get tlen() {
|
|
24393
|
+
return Math.abs(this.firstAlignment.fragmentLength)
|
|
24394
|
+
}
|
|
24395
|
+
|
|
24420
24396
|
firstOfPairStrand() {
|
|
24421
24397
|
|
|
24422
24398
|
if (this.firstAlignment.isFirstOfPair()) {
|
|
@@ -24758,7 +24734,10 @@ function packAlignmentRows(alignments, start, end, showSoftClips) {
|
|
|
24758
24734
|
|
|
24759
24735
|
|
|
24760
24736
|
class AlignmentContainer {
|
|
24761
|
-
|
|
24737
|
+
|
|
24738
|
+
// this.config.samplingWindowSize, this.config.samplingDepth,
|
|
24739
|
+
// this.config.pairsSupported, this.config.alleleFreqThreshold)
|
|
24740
|
+
constructor(chr, start, end, {samplingWindowSize, samplingDepth, pairsSupported, alleleFreqThreshold}) {
|
|
24762
24741
|
|
|
24763
24742
|
this.chr = chr;
|
|
24764
24743
|
this.start = Math.floor(start);
|
|
@@ -24786,17 +24765,12 @@ class AlignmentContainer {
|
|
|
24786
24765
|
return alignment.isMapped() && !alignment.isFailsVendorQualityCheck()
|
|
24787
24766
|
};
|
|
24788
24767
|
|
|
24789
|
-
this.pairedEndStats = new PairedEndStats();
|
|
24790
24768
|
}
|
|
24791
24769
|
|
|
24792
24770
|
push(alignment) {
|
|
24793
24771
|
|
|
24794
24772
|
if (this.filter(alignment) === false) return
|
|
24795
24773
|
|
|
24796
|
-
if (alignment.isPaired()) {
|
|
24797
|
-
this.pairedEndStats.push(alignment);
|
|
24798
|
-
}
|
|
24799
|
-
|
|
24800
24774
|
this.coverageMap.incCounts(alignment); // Count coverage before any downsampling
|
|
24801
24775
|
|
|
24802
24776
|
if (this.pairsSupported && this.downsampledReads.has(alignment.readName)) {
|
|
@@ -24828,8 +24802,6 @@ class AlignmentContainer {
|
|
|
24828
24802
|
|
|
24829
24803
|
this.pairsCache = undefined;
|
|
24830
24804
|
this.downsampledReads = undefined;
|
|
24831
|
-
|
|
24832
|
-
this.pairedEndStats.compute();
|
|
24833
24805
|
}
|
|
24834
24806
|
|
|
24835
24807
|
contains(chr, start, end) {
|
|
@@ -25140,69 +25112,6 @@ class DownsampledInterval {
|
|
|
25140
25112
|
}
|
|
25141
25113
|
}
|
|
25142
25114
|
|
|
25143
|
-
class PairedEndStats {
|
|
25144
|
-
|
|
25145
|
-
constructor(lowerPercentile, upperPercentile) {
|
|
25146
|
-
this.totalCount = 0;
|
|
25147
|
-
this.frCount = 0;
|
|
25148
|
-
this.rfCount = 0;
|
|
25149
|
-
this.ffCount = 0;
|
|
25150
|
-
this.sumF = 0;
|
|
25151
|
-
this.sumF2 = 0;
|
|
25152
|
-
//this.lp = lowerPercentile === undefined ? 0.005 : lowerPercentile;
|
|
25153
|
-
//this.up = upperPercentile === undefined ? 0.995 : upperPercentile;
|
|
25154
|
-
//this.digest = new Digest();
|
|
25155
|
-
}
|
|
25156
|
-
|
|
25157
|
-
push(alignment) {
|
|
25158
|
-
|
|
25159
|
-
if (alignment.isProperPair()) {
|
|
25160
|
-
|
|
25161
|
-
var fragmentLength = Math.abs(alignment.fragmentLength);
|
|
25162
|
-
//this.digest.push(fragmentLength);
|
|
25163
|
-
this.sumF += fragmentLength;
|
|
25164
|
-
this.sumF2 += fragmentLength * fragmentLength;
|
|
25165
|
-
|
|
25166
|
-
var po = alignment.pairOrientation;
|
|
25167
|
-
|
|
25168
|
-
if (typeof po === "string" && po.length === 4) {
|
|
25169
|
-
var tmp = '' + po.charAt(0) + po.charAt(2);
|
|
25170
|
-
switch (tmp) {
|
|
25171
|
-
case 'FF':
|
|
25172
|
-
case 'RR':
|
|
25173
|
-
this.ffCount++;
|
|
25174
|
-
break
|
|
25175
|
-
case "FR":
|
|
25176
|
-
this.frCount++;
|
|
25177
|
-
break
|
|
25178
|
-
case"RF":
|
|
25179
|
-
this.rfCount++;
|
|
25180
|
-
}
|
|
25181
|
-
}
|
|
25182
|
-
this.totalCount++;
|
|
25183
|
-
}
|
|
25184
|
-
}
|
|
25185
|
-
|
|
25186
|
-
compute() {
|
|
25187
|
-
|
|
25188
|
-
if (this.totalCount > 100) {
|
|
25189
|
-
if (this.ffCount / this.totalCount > 0.9) this.orienation = "ff";
|
|
25190
|
-
else if (this.frCount / this.totalCount > 0.9) this.orienation = "fr";
|
|
25191
|
-
else if (this.rfCount / this.totalCount > 0.9) this.orienation = "rf";
|
|
25192
|
-
|
|
25193
|
-
|
|
25194
|
-
var fMean = this.sumF / this.totalCount;
|
|
25195
|
-
var stdDev = Math.sqrt((this.totalCount * this.sumF2 - this.sumF * this.sumF) / (this.totalCount * this.totalCount));
|
|
25196
|
-
this.lowerFragmentLength = fMean - 3 * stdDev;
|
|
25197
|
-
this.upperFragmentLength = fMean + 3 * stdDev;
|
|
25198
|
-
|
|
25199
|
-
//this.lowerFragmentLength = this.digest.percentile(this.lp);
|
|
25200
|
-
//this.upperFragmentLength = this.digest.percentile(this.up);
|
|
25201
|
-
//this.digest = undefined;
|
|
25202
|
-
}
|
|
25203
|
-
}
|
|
25204
|
-
}
|
|
25205
|
-
|
|
25206
25115
|
class SupplementaryAlignment {
|
|
25207
25116
|
|
|
25208
25117
|
constructor(rec) {
|
|
@@ -26392,7 +26301,7 @@ class BamReaderNonIndexed {
|
|
|
26392
26301
|
const header = this.header;
|
|
26393
26302
|
const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr;
|
|
26394
26303
|
const qAlignments = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd);
|
|
26395
|
-
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.
|
|
26304
|
+
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config);
|
|
26396
26305
|
for (let a of qAlignments) {
|
|
26397
26306
|
alignmentContainer.push(a);
|
|
26398
26307
|
}
|
|
@@ -26419,13 +26328,13 @@ class BamReaderNonIndexed {
|
|
|
26419
26328
|
const alignments = [];
|
|
26420
26329
|
this.header = BamUtils.decodeBamHeader(data);
|
|
26421
26330
|
BamUtils.decodeBamRecords(data, this.header.size, alignments, this.header.chrNames);
|
|
26422
|
-
this.alignmentCache = new FeatureCache(alignments, this.genome);
|
|
26331
|
+
this.alignmentCache = new FeatureCache$1(alignments, this.genome);
|
|
26423
26332
|
}
|
|
26424
26333
|
|
|
26425
26334
|
fetchAlignments(chr, bpStart, bpEnd) {
|
|
26426
26335
|
const queryChr = this.header.chrAliasTable.hasOwnProperty(chr) ? this.header.chrAliasTable[chr] : chr;
|
|
26427
26336
|
const features = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd);
|
|
26428
|
-
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.
|
|
26337
|
+
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config);
|
|
26429
26338
|
for (let feature of features) {
|
|
26430
26339
|
alignmentContainer.push(feature);
|
|
26431
26340
|
}
|
|
@@ -27416,9 +27325,7 @@ class BamReader {
|
|
|
27416
27325
|
const chrToIndex = await this.getChrIndex();
|
|
27417
27326
|
const queryChr = this.chrAliasTable.hasOwnProperty(chr) ? this.chrAliasTable[chr] : chr;
|
|
27418
27327
|
const chrId = chrToIndex[queryChr];
|
|
27419
|
-
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd,
|
|
27420
|
-
this.config.samplingWindowSize, this.config.samplingDepth,
|
|
27421
|
-
this.config.pairsSupported, this.config.alleleFreqThreshold);
|
|
27328
|
+
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config);
|
|
27422
27329
|
|
|
27423
27330
|
if (chrId === undefined) {
|
|
27424
27331
|
return alignmentContainer
|
|
@@ -27550,7 +27457,7 @@ class ShardedBamReader {
|
|
|
27550
27457
|
async readAlignments(chr, start, end) {
|
|
27551
27458
|
|
|
27552
27459
|
if (!this.bamReaders.hasOwnProperty(chr)) {
|
|
27553
|
-
return new AlignmentContainer(chr, start, end)
|
|
27460
|
+
return new AlignmentContainer(chr, start, end, this.config)
|
|
27554
27461
|
} else {
|
|
27555
27462
|
|
|
27556
27463
|
let reader = this.bamReaders[chr];
|
|
@@ -27641,7 +27548,7 @@ BamWebserviceReader.prototype.readAlignments = function (chr, bpStart, bpEnd) {
|
|
|
27641
27548
|
|
|
27642
27549
|
header.chrToIndex[queryChr];
|
|
27643
27550
|
|
|
27644
|
-
alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, self.
|
|
27551
|
+
alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, self.config);
|
|
27645
27552
|
|
|
27646
27553
|
BamUtils.decodeSamRecords(sam, alignmentContainer, queryChr, bpStart, bpEnd, self.filter);
|
|
27647
27554
|
|
|
@@ -27895,7 +27802,7 @@ class HtsgetBamReader extends HtsgetReader {
|
|
|
27895
27802
|
const ba = unbgzf(compressedData.buffer);
|
|
27896
27803
|
|
|
27897
27804
|
const chrIdx = this.header.chrToIndex[chr];
|
|
27898
|
-
const alignmentContainer = new AlignmentContainer(chr, start, end, this.
|
|
27805
|
+
const alignmentContainer = new AlignmentContainer(chr, start, end, this.config);
|
|
27899
27806
|
BamUtils.decodeBamRecords(ba, this.header.size, alignmentContainer, this.header.chrNames, chrIdx, start, end);
|
|
27900
27807
|
alignmentContainer.finish();
|
|
27901
27808
|
|
|
@@ -28061,8 +27968,7 @@ class CramReader {
|
|
|
28061
27968
|
const header = await this.getHeader();
|
|
28062
27969
|
const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr;
|
|
28063
27970
|
const chrIdx = header.chrToIndex[queryChr];
|
|
28064
|
-
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd,
|
|
28065
|
-
this.samplingWindowSize, this.samplingDepth, this.pairsSupported, this.alleleFreqThreshold);
|
|
27971
|
+
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config);
|
|
28066
27972
|
|
|
28067
27973
|
if (chrIdx === undefined) {
|
|
28068
27974
|
return alignmentContainer
|
|
@@ -28678,7 +28584,7 @@ Ga4ghAlignmentReader.prototype.readAlignments = function (chr, bpStart, bpEnd) {
|
|
|
28678
28584
|
"pageSize": "10000"
|
|
28679
28585
|
},
|
|
28680
28586
|
decode: decodeGa4ghReads,
|
|
28681
|
-
results: new AlignmentContainer(chr, bpStart, bpEnd, self.
|
|
28587
|
+
results: new AlignmentContainer(chr, bpStart, bpEnd, self.config)
|
|
28682
28588
|
})
|
|
28683
28589
|
})
|
|
28684
28590
|
|
|
@@ -29011,7 +28917,6 @@ class BamSource {
|
|
|
29011
28917
|
|
|
29012
28918
|
this.config = config;
|
|
29013
28919
|
this.genome = genome;
|
|
29014
|
-
this.alignmentContainer = undefined;
|
|
29015
28920
|
|
|
29016
28921
|
if (isDataURL(config.url)) {
|
|
29017
28922
|
if ("cram" === config.format) {
|
|
@@ -29059,19 +28964,11 @@ class BamSource {
|
|
|
29059
28964
|
}
|
|
29060
28965
|
|
|
29061
28966
|
setViewAsPairs(bool) {
|
|
29062
|
-
|
|
29063
|
-
if (this.viewAsPairs !== bool) {
|
|
29064
|
-
this.viewAsPairs = bool;
|
|
29065
|
-
// if (this.alignmentContainer) {
|
|
29066
|
-
// this.alignmentContainer.setViewAsPairs(bool);
|
|
29067
|
-
// }
|
|
29068
|
-
}
|
|
28967
|
+
this.viewAsPairs = bool;
|
|
29069
28968
|
}
|
|
29070
28969
|
|
|
29071
28970
|
setShowSoftClips(bool) {
|
|
29072
|
-
|
|
29073
|
-
this.showSoftClips = bool;
|
|
29074
|
-
}
|
|
28971
|
+
this.showSoftClips = bool;
|
|
29075
28972
|
}
|
|
29076
28973
|
|
|
29077
28974
|
async getAlignments(chr, bpStart, bpEnd) {
|
|
@@ -29079,33 +28976,28 @@ class BamSource {
|
|
|
29079
28976
|
const genome = this.genome;
|
|
29080
28977
|
const showSoftClips = this.showSoftClips;
|
|
29081
28978
|
|
|
29082
|
-
|
|
29083
|
-
|
|
28979
|
+
const alignmentContainer = await this.bamReader.readAlignments(chr, bpStart, bpEnd);
|
|
28980
|
+
let alignments = alignmentContainer.alignments;
|
|
28981
|
+
if (!this.viewAsPairs) {
|
|
28982
|
+
alignments = unpairAlignments([{alignments: alignments}]);
|
|
28983
|
+
}
|
|
28984
|
+
const hasAlignments = alignments.length > 0;
|
|
28985
|
+
alignmentContainer.packedAlignmentRows = packAlignmentRows(alignments, alignmentContainer.start, alignmentContainer.end, showSoftClips);
|
|
29084
28986
|
|
|
29085
|
-
|
|
29086
|
-
|
|
29087
|
-
|
|
29088
|
-
|
|
29089
|
-
|
|
29090
|
-
|
|
29091
|
-
|
|
29092
|
-
|
|
29093
|
-
|
|
29094
|
-
|
|
29095
|
-
this.alignmentContainer = alignmentContainer;
|
|
29096
|
-
|
|
29097
|
-
if (hasAlignments) {
|
|
29098
|
-
const sequence = await genome.sequence.getSequence(chr, alignmentContainer.start, alignmentContainer.end);
|
|
29099
|
-
if (sequence) {
|
|
29100
|
-
alignmentContainer.coverageMap.refSeq = sequence; // TODO -- fix this
|
|
29101
|
-
alignmentContainer.sequence = sequence; // TODO -- fix this
|
|
29102
|
-
return alignmentContainer
|
|
29103
|
-
} else {
|
|
29104
|
-
console.error("No sequence for: " + chr + ":" + alignmentContainer.start + "-" + alignmentContainer.end);
|
|
29105
|
-
}
|
|
28987
|
+
this.alignmentContainer = alignmentContainer;
|
|
28988
|
+
|
|
28989
|
+
if (hasAlignments) {
|
|
28990
|
+
const sequence = await genome.sequence.getSequence(chr, alignmentContainer.start, alignmentContainer.end);
|
|
28991
|
+
if (sequence) {
|
|
28992
|
+
alignmentContainer.coverageMap.refSeq = sequence; // TODO -- fix this
|
|
28993
|
+
alignmentContainer.sequence = sequence; // TODO -- fix this
|
|
28994
|
+
return alignmentContainer
|
|
28995
|
+
} else {
|
|
28996
|
+
console.error("No sequence for: " + chr + ":" + alignmentContainer.start + "-" + alignmentContainer.end);
|
|
29106
28997
|
}
|
|
29107
|
-
return alignmentContainer
|
|
29108
28998
|
}
|
|
28999
|
+
return alignmentContainer
|
|
29000
|
+
|
|
29109
29001
|
}
|
|
29110
29002
|
}
|
|
29111
29003
|
|
|
@@ -29423,7 +29315,7 @@ class TrackBase {
|
|
|
29423
29315
|
|
|
29424
29316
|
// We use the cached features rather than method to avoid async load. If the
|
|
29425
29317
|
// feature is not already loaded this won't work, but the user wouldn't be mousing over it either.
|
|
29426
|
-
if (!features) features = clickState.viewport.
|
|
29318
|
+
if (!features) features = clickState.viewport.cachedFeatures;
|
|
29427
29319
|
|
|
29428
29320
|
if (!features || features.length === 0) {
|
|
29429
29321
|
return []
|
|
@@ -29927,8 +29819,7 @@ class Locus {
|
|
|
29927
29819
|
}
|
|
29928
29820
|
|
|
29929
29821
|
overlaps(locus) {
|
|
29930
|
-
return locus.chr === this.chr
|
|
29931
|
-
&& !(locus.end < this.start || locus.start > this.end)
|
|
29822
|
+
return locus.chr === this.chr && !(locus.end < this.start || locus.start > this.end)
|
|
29932
29823
|
}
|
|
29933
29824
|
|
|
29934
29825
|
extend(l) {
|
|
@@ -31805,6 +31696,19 @@ function makeCircViewChromosomes(genome) {
|
|
|
31805
31696
|
return regions
|
|
31806
31697
|
}
|
|
31807
31698
|
|
|
31699
|
+
function sendChords(chords, track, refFrame, alpha) {
|
|
31700
|
+
|
|
31701
|
+
const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? track.color : getChrColor(refFrame.chr), alpha);
|
|
31702
|
+
const trackColor = IGVColor.addAlpha(track.color || 'rgb(0,0,255)', alpha);
|
|
31703
|
+
|
|
31704
|
+
// name the chord set to include locus and filtering information
|
|
31705
|
+
const encodedName = track.name.replaceAll(' ', '%20');
|
|
31706
|
+
const chordSetName = "all" === refFrame.chr ? encodedName :
|
|
31707
|
+
`${encodedName} ${refFrame.chr}:${refFrame.start}-${refFrame.end}`;
|
|
31708
|
+
track.browser.circularView.addChords(chords, {track: chordSetName, color: chordSetColor, trackColor: trackColor});
|
|
31709
|
+
|
|
31710
|
+
}
|
|
31711
|
+
|
|
31808
31712
|
|
|
31809
31713
|
function createCircularView(el, browser) {
|
|
31810
31714
|
|
|
@@ -31814,42 +31718,102 @@ function createCircularView(el, browser) {
|
|
|
31814
31718
|
|
|
31815
31719
|
const f1 = feature.data;
|
|
31816
31720
|
const f2 = f1.mate;
|
|
31817
|
-
|
|
31721
|
+
addFrameForFeature(f1);
|
|
31722
|
+
addFrameForFeature(f2);
|
|
31723
|
+
|
|
31724
|
+
function addFrameForFeature(feature) {
|
|
31725
|
+
|
|
31726
|
+
feature.chr = browser.genome.getChromosomeName(feature.refName);
|
|
31727
|
+
|
|
31728
|
+
for (let referenceFrame of browser.currentReferenceFrames()) {
|
|
31729
|
+
const l = Locus.fromLocusString(referenceFrame.getLocusString());
|
|
31730
|
+
if (l.contains(feature)) {
|
|
31731
|
+
break
|
|
31732
|
+
} else if (l.overlaps(feature)) {
|
|
31733
|
+
referenceFrame.extend(feature);
|
|
31734
|
+
break
|
|
31735
|
+
} else {
|
|
31736
|
+
const flanking = 2000;
|
|
31737
|
+
const center = (feature.start + feature.end) / 2;
|
|
31738
|
+
browser.addMultiLocusPanel(feature.chr, center - flanking, center + flanking);
|
|
31739
|
+
break
|
|
31740
|
+
}
|
|
31741
|
+
}
|
|
31742
|
+
}
|
|
31743
|
+
}
|
|
31744
|
+
});
|
|
31818
31745
|
|
|
31819
|
-
|
|
31820
|
-
|
|
31746
|
+
return circularView
|
|
31747
|
+
}
|
|
31821
31748
|
|
|
31822
|
-
|
|
31749
|
+
class PairedEndStats {
|
|
31823
31750
|
|
|
31824
|
-
|
|
31751
|
+
constructor(alignments, {minTLENPercentile, maxTLENPercentile}) {
|
|
31752
|
+
this.totalCount = 0;
|
|
31753
|
+
this.frCount = 0;
|
|
31754
|
+
this.rfCount = 0;
|
|
31755
|
+
this.ffCount = 0;
|
|
31756
|
+
this.sumF = 0;
|
|
31757
|
+
this.sumF2 = 0;
|
|
31758
|
+
this.lp = minTLENPercentile === undefined ? 0.1 : minTLENPercentile;
|
|
31759
|
+
this.up = maxTLENPercentile === undefined ? 99.5 : maxTLENPercentile;
|
|
31760
|
+
this.isizes = [];
|
|
31761
|
+
this.compute(alignments);
|
|
31762
|
+
}
|
|
31825
31763
|
|
|
31826
|
-
|
|
31764
|
+
compute(alignments) {
|
|
31827
31765
|
|
|
31828
|
-
|
|
31829
|
-
|
|
31830
|
-
|
|
31831
|
-
|
|
31832
|
-
|
|
31833
|
-
|
|
31834
|
-
|
|
31835
|
-
|
|
31836
|
-
|
|
31766
|
+
for (let alignment of alignments) {
|
|
31767
|
+
if (alignment.isProperPair()) {
|
|
31768
|
+
var tlen = Math.abs(alignment.fragmentLength);
|
|
31769
|
+
this.sumF += tlen;
|
|
31770
|
+
this.sumF2 += tlen * tlen;
|
|
31771
|
+
this.isizes.push(tlen);
|
|
31772
|
+
|
|
31773
|
+
var po = alignment.pairOrientation;
|
|
31774
|
+
|
|
31775
|
+
if (typeof po === "string" && po.length === 4) {
|
|
31776
|
+
var tmp = '' + po.charAt(0) + po.charAt(2);
|
|
31777
|
+
switch (tmp) {
|
|
31778
|
+
case 'FF':
|
|
31779
|
+
case 'RR':
|
|
31780
|
+
this.ffCount++;
|
|
31781
|
+
break
|
|
31782
|
+
case "FR":
|
|
31783
|
+
this.frCount++;
|
|
31784
|
+
break
|
|
31785
|
+
case"RF":
|
|
31786
|
+
this.rfCount++;
|
|
31837
31787
|
}
|
|
31838
31788
|
}
|
|
31839
|
-
|
|
31840
|
-
l1.start = Math.max(0, l1.start - flanking);
|
|
31841
|
-
l1.end += flanking;
|
|
31842
|
-
l2.start = Math.max(0, l2.start - flanking);
|
|
31843
|
-
l2.end += flanking;
|
|
31844
|
-
loci = [l1, l2];
|
|
31789
|
+
this.totalCount++;
|
|
31845
31790
|
}
|
|
31846
|
-
|
|
31847
|
-
const searchString = loci.map(l => l.getLocusString()).join(" ");
|
|
31848
|
-
browser.search(searchString);
|
|
31849
31791
|
}
|
|
31792
|
+
|
|
31793
|
+
if (this.ffCount / this.totalCount > 0.9) this.orienation = "ff";
|
|
31794
|
+
else if (this.frCount / this.totalCount > 0.9) this.orienation = "fr";
|
|
31795
|
+
else if (this.rfCount / this.totalCount > 0.9) this.orienation = "rf";
|
|
31796
|
+
|
|
31797
|
+
this.minTLEN = this.lp === 0 ? 0 : percentile(this.isizes, this.lp);
|
|
31798
|
+
this.maxTLEN = percentile(this.isizes, this.up);
|
|
31799
|
+
|
|
31800
|
+
// var fMean = this.sumF / this.totalCount
|
|
31801
|
+
// var stdDev = Math.sqrt((this.totalCount * this.sumF2 - this.sumF * this.sumF) / (this.totalCount * this.totalCount))
|
|
31802
|
+
// this.minTLEN = fMean - 3 * stdDev
|
|
31803
|
+
// this.maxTLEN = fMean + 3 * stdDev
|
|
31804
|
+
|
|
31805
|
+
}
|
|
31806
|
+
}
|
|
31807
|
+
|
|
31808
|
+
function percentile(array, p) {
|
|
31809
|
+
|
|
31810
|
+
if (array.length === 0) return undefined
|
|
31811
|
+
var k = Math.floor(array.length * (p / 100));
|
|
31812
|
+
array.sort(function (a, b) {
|
|
31813
|
+
return a - b
|
|
31850
31814
|
});
|
|
31815
|
+
return array[k]
|
|
31851
31816
|
|
|
31852
|
-
return circularView
|
|
31853
31817
|
}
|
|
31854
31818
|
|
|
31855
31819
|
/*
|
|
@@ -31916,8 +31880,6 @@ class BAMTrack extends TrackBase {
|
|
|
31916
31880
|
this.showMismatches = false !== config.showMismatches;
|
|
31917
31881
|
this.color = config.color;
|
|
31918
31882
|
this.coverageColor = config.coverageColor;
|
|
31919
|
-
this.minFragmentLength = config.minFragmentLength; // Optional, might be undefined
|
|
31920
|
-
this.maxFragmentLength = config.maxFragmentLength || 1000;
|
|
31921
31883
|
|
|
31922
31884
|
// The sort object can be an array in the case of multi-locus view, however if multiple sort positions
|
|
31923
31885
|
// are present for a given reference frame the last one will take precedence
|
|
@@ -31945,12 +31907,24 @@ class BAMTrack extends TrackBase {
|
|
|
31945
31907
|
return this._height
|
|
31946
31908
|
}
|
|
31947
31909
|
|
|
31910
|
+
get minTemplateLength() {
|
|
31911
|
+
const configMinTLEN = this.config.minTLEN !== undefined ? this.config.minTLEN : this.config.minFragmentLength;
|
|
31912
|
+
return (configMinTLEN !== undefined) ? configMinTLEN :
|
|
31913
|
+
this._pairedEndStats ? this._pairedEndStats.minTLEN : 0
|
|
31914
|
+
}
|
|
31915
|
+
|
|
31916
|
+
get maxTemplateLength() {
|
|
31917
|
+
const configMaxTLEN = this.config.maxTLEN !== undefined ? this.config.maxTLEN : this.config.maxFragmentLength;
|
|
31918
|
+
return (configMaxTLEN !== undefined) ? configMaxTLEN :
|
|
31919
|
+
this._pairedEndStats ? this._pairedEndStats.maxTLEN : 1000
|
|
31920
|
+
}
|
|
31921
|
+
|
|
31948
31922
|
sort(options) {
|
|
31949
31923
|
options = this.assignSort(options);
|
|
31950
31924
|
|
|
31951
31925
|
for (let vp of this.trackView.viewports) {
|
|
31952
31926
|
if (vp.containsPosition(options.chr, options.position)) {
|
|
31953
|
-
const alignmentContainer = vp.
|
|
31927
|
+
const alignmentContainer = vp.cachedFeatures;
|
|
31954
31928
|
if (alignmentContainer) {
|
|
31955
31929
|
sortAlignmentRows(options, alignmentContainer);
|
|
31956
31930
|
vp.repaint();
|
|
@@ -31985,14 +31959,13 @@ class BAMTrack extends TrackBase {
|
|
|
31985
31959
|
|
|
31986
31960
|
const alignmentContainer = await this.featureSource.getAlignments(chr, bpStart, bpEnd);
|
|
31987
31961
|
|
|
31988
|
-
if (alignmentContainer.
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
if (undefined === this.maxFragmentLength) {
|
|
31993
|
-
this.maxFragmentLength = alignmentContainer.pairedEndStats.upperFragmentLength;
|
|
31962
|
+
if (alignmentContainer.paired && !this._pairedEndStats && !this.config.maxFragmentLength) {
|
|
31963
|
+
const pairedEndStats = new PairedEndStats(alignmentContainer.alignments, this.config);
|
|
31964
|
+
if (pairedEndStats.totalCount > 99) {
|
|
31965
|
+
this._pairedEndStats = pairedEndStats;
|
|
31994
31966
|
}
|
|
31995
31967
|
}
|
|
31968
|
+
alignmentContainer.alignments = undefined; // Don't need to hold onto these anymore
|
|
31996
31969
|
|
|
31997
31970
|
const sort = this.sortObject;
|
|
31998
31971
|
if (sort) {
|
|
@@ -32089,7 +32062,7 @@ class BAMTrack extends TrackBase {
|
|
|
32089
32062
|
if (this.alignmentTrack.hasPairs) {
|
|
32090
32063
|
colorByMenuItems.push({key: 'firstOfPairStrand', label: 'first-of-pair strand'});
|
|
32091
32064
|
colorByMenuItems.push({key: 'pairOrientation', label: 'pair orientation'});
|
|
32092
|
-
colorByMenuItems.push({key: '
|
|
32065
|
+
colorByMenuItems.push({key: 'tlen', label: 'insert size (TLEN)'});
|
|
32093
32066
|
colorByMenuItems.push({key: 'unexpectedPair', label: 'pair orientation & insert size (TLEN)'});
|
|
32094
32067
|
}
|
|
32095
32068
|
const tagLabel = 'tag' + (this.alignmentTrack.colorByTag ? ' (' + this.alignmentTrack.colorByTag + ')' : '');
|
|
@@ -32195,7 +32168,7 @@ class BAMTrack extends TrackBase {
|
|
|
32195
32168
|
});
|
|
32196
32169
|
}
|
|
32197
32170
|
|
|
32198
|
-
//
|
|
32171
|
+
// Add chords to JBrowse circular view, if present
|
|
32199
32172
|
if (this.browser.circularView && true === this.browser.circularViewVisible &&
|
|
32200
32173
|
(this.alignmentTrack.hasPairs || this.alignmentTrack.hasSupplemental)) {
|
|
32201
32174
|
menuItems.push('<hr/>');
|
|
@@ -32203,24 +32176,9 @@ class BAMTrack extends TrackBase {
|
|
|
32203
32176
|
menuItems.push({
|
|
32204
32177
|
label: 'Add discordant pairs to circular view',
|
|
32205
32178
|
click: () => {
|
|
32206
|
-
const maxFragmentLength = this.maxFragmentLength;
|
|
32207
|
-
const inView = [];
|
|
32208
32179
|
for (let viewport of this.trackView.viewports) {
|
|
32209
|
-
|
|
32210
|
-
const referenceFrame = viewport.referenceFrame;
|
|
32211
|
-
if (a.end >= referenceFrame.start
|
|
32212
|
-
&& a.start <= referenceFrame.end
|
|
32213
|
-
&& a.mate
|
|
32214
|
-
&& a.mate.chr
|
|
32215
|
-
&& (a.mate.chr !== a.chr || Math.max(a.fragmentLength) > maxFragmentLength)) {
|
|
32216
|
-
inView.push(a);
|
|
32217
|
-
}
|
|
32218
|
-
}
|
|
32180
|
+
this.addPairedChordsForViewport(viewport);
|
|
32219
32181
|
}
|
|
32220
|
-
this.browser.circularViewVisible = true;
|
|
32221
|
-
const chords = makePairedAlignmentChords(inView);
|
|
32222
|
-
const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02);
|
|
32223
|
-
this.browser.circularView.addChords(chords, {track: this.name, color: color});
|
|
32224
32182
|
}
|
|
32225
32183
|
});
|
|
32226
32184
|
}
|
|
@@ -32228,19 +32186,9 @@ class BAMTrack extends TrackBase {
|
|
|
32228
32186
|
menuItems.push({
|
|
32229
32187
|
label: 'Add split reads to circular view',
|
|
32230
32188
|
click: () => {
|
|
32231
|
-
const inView = [];
|
|
32232
32189
|
for (let viewport of this.trackView.viewports) {
|
|
32233
|
-
|
|
32234
|
-
const referenceFrame = viewport.referenceFrame;
|
|
32235
|
-
const sa = a.hasTag('SA');
|
|
32236
|
-
if (a.end >= referenceFrame.start && a.start <= referenceFrame.end && sa) {
|
|
32237
|
-
inView.push(a);
|
|
32238
|
-
}
|
|
32239
|
-
}
|
|
32190
|
+
this.addSplitChordsForViewport(viewport);
|
|
32240
32191
|
}
|
|
32241
|
-
const chords = makeSupplementalAlignmentChords(inView);
|
|
32242
|
-
const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.1);
|
|
32243
|
-
this.browser.circularView.addChords(chords, {track: this.name, color: color});
|
|
32244
32192
|
}
|
|
32245
32193
|
});
|
|
32246
32194
|
}
|
|
@@ -32352,7 +32300,7 @@ class BAMTrack extends TrackBase {
|
|
|
32352
32300
|
}
|
|
32353
32301
|
|
|
32354
32302
|
getCachedAlignmentContainers() {
|
|
32355
|
-
return this.trackView.viewports.map(vp => vp.
|
|
32303
|
+
return this.trackView.viewports.map(vp => vp.cachedFeatures)
|
|
32356
32304
|
}
|
|
32357
32305
|
|
|
32358
32306
|
get dataRange() {
|
|
@@ -32378,6 +32326,62 @@ class BAMTrack extends TrackBase {
|
|
|
32378
32326
|
set autoscale(autoscale) {
|
|
32379
32327
|
this.coverageTrack.autoscale = autoscale;
|
|
32380
32328
|
}
|
|
32329
|
+
|
|
32330
|
+
/**
|
|
32331
|
+
* Add chords to the circular view for the given viewport, represented by its reference frame
|
|
32332
|
+
* @param refFrame
|
|
32333
|
+
*/
|
|
32334
|
+
addPairedChordsForViewport(viewport) {
|
|
32335
|
+
|
|
32336
|
+
const maxTemplateLength = this.maxTemplateLength;
|
|
32337
|
+
const inView = [];
|
|
32338
|
+
const refFrame = viewport.referenceFrame;
|
|
32339
|
+
for (let a of viewport.cachedFeatures.allAlignments()) {
|
|
32340
|
+
if (a.end >= refFrame.start
|
|
32341
|
+
&& a.start <= refFrame.end
|
|
32342
|
+
&& a.mate
|
|
32343
|
+
&& a.mate.chr
|
|
32344
|
+
&& (a.mate.chr !== a.chr || Math.max(a.fragmentLength) > maxTemplateLength)) {
|
|
32345
|
+
inView.push(a);
|
|
32346
|
+
}
|
|
32347
|
+
}
|
|
32348
|
+
const chords = makePairedAlignmentChords(inView);
|
|
32349
|
+
sendChords(chords, this, refFrame, 0.02);
|
|
32350
|
+
|
|
32351
|
+
// const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.02)
|
|
32352
|
+
// const trackColor = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02)
|
|
32353
|
+
//
|
|
32354
|
+
// // name the chord set to include track name and locus
|
|
32355
|
+
// const encodedName = this.name.replaceAll(' ', '%20')
|
|
32356
|
+
// const chordSetName = "all" === refFrame.chr ? encodedName :
|
|
32357
|
+
// `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end}`
|
|
32358
|
+
// this.browser.circularView.addChords(chords, {name: chordSetName, color: chordSetColor, trackColor: trackColor})
|
|
32359
|
+
}
|
|
32360
|
+
|
|
32361
|
+
addSplitChordsForViewport(viewport) {
|
|
32362
|
+
|
|
32363
|
+
const inView = [];
|
|
32364
|
+
const refFrame = viewport.referenceFrame;
|
|
32365
|
+
for (let a of viewport.cachedFeatures.allAlignments()) {
|
|
32366
|
+
|
|
32367
|
+
const sa = a.hasTag('SA');
|
|
32368
|
+
if (a.end >= refFrame.start && a.start <= refFrame.end && sa) {
|
|
32369
|
+
inView.push(a);
|
|
32370
|
+
}
|
|
32371
|
+
}
|
|
32372
|
+
|
|
32373
|
+
const chords = makeSupplementalAlignmentChords(inView);
|
|
32374
|
+
sendChords(chords, this, refFrame, 0.02);
|
|
32375
|
+
|
|
32376
|
+
// const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.02)
|
|
32377
|
+
// const trackColor = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02)
|
|
32378
|
+
//
|
|
32379
|
+
// // name the chord set to include track name and locus
|
|
32380
|
+
// const encodedName = this.name.replaceAll(' ', '%20')
|
|
32381
|
+
// const chordSetName = "all" === refFrame.chr ? encodedName :
|
|
32382
|
+
// `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end}`
|
|
32383
|
+
// this.browser.circularView.addChords(chords, {name: chordSetName, color: chordSetColor, trackColor: trackColor})
|
|
32384
|
+
}
|
|
32381
32385
|
}
|
|
32382
32386
|
|
|
32383
32387
|
|
|
@@ -32498,7 +32502,7 @@ class CoverageTrack {
|
|
|
32498
32502
|
|
|
32499
32503
|
getClickedObject(clickState) {
|
|
32500
32504
|
|
|
32501
|
-
let features = clickState.viewport.
|
|
32505
|
+
let features = clickState.viewport.cachedFeatures;
|
|
32502
32506
|
if (!features || features.length === 0) return
|
|
32503
32507
|
|
|
32504
32508
|
const genomicLocation = Math.floor(clickState.genomicLocation);
|
|
@@ -32574,8 +32578,8 @@ class AlignmentTrack {
|
|
|
32574
32578
|
this.skippedColor = config.skippedColor || "rgb(150, 170, 170)";
|
|
32575
32579
|
this.pairConnectorColor = config.pairConnectorColor;
|
|
32576
32580
|
|
|
32577
|
-
this.
|
|
32578
|
-
this.
|
|
32581
|
+
this.smallTLENColor = config.smallTLENColor || config.smallFragmentLengthColor || "rgb(0, 0, 150)";
|
|
32582
|
+
this.largeTLENColor = config.largeTLENColor || config.largeFragmentLengthColor || "rgb(200, 0, 0)";
|
|
32579
32583
|
|
|
32580
32584
|
this.pairOrientation = config.pairOrienation || 'fr';
|
|
32581
32585
|
this.pairColors = {};
|
|
@@ -32583,7 +32587,7 @@ class AlignmentTrack {
|
|
|
32583
32587
|
this.pairColors["RR"] = config.rrColor || "rgb(20, 50, 200)";
|
|
32584
32588
|
this.pairColors["LL"] = config.llColor || "rgb(0, 150, 150)";
|
|
32585
32589
|
|
|
32586
|
-
this.colorBy = config.colorBy || "
|
|
32590
|
+
this.colorBy = config.colorBy || "unexpectedPair";
|
|
32587
32591
|
this.colorByTag = config.colorByTag ? config.colorByTag.toUpperCase() : undefined;
|
|
32588
32592
|
this.bamColorTag = config.bamColorTag === undefined ? "YC" : config.bamColorTag;
|
|
32589
32593
|
|
|
@@ -32975,7 +32979,7 @@ class AlignmentTrack {
|
|
|
32975
32979
|
direction: direction
|
|
32976
32980
|
};
|
|
32977
32981
|
this.parent.sortObject = newSortObject;
|
|
32978
|
-
sortAlignmentRows(newSortObject, viewport.
|
|
32982
|
+
sortAlignmentRows(newSortObject, viewport.cachedFeatures);
|
|
32979
32983
|
viewport.repaint();
|
|
32980
32984
|
};
|
|
32981
32985
|
list.push('<b>Sort by...</b>');
|
|
@@ -33005,7 +33009,7 @@ class AlignmentTrack {
|
|
|
33005
33009
|
};
|
|
33006
33010
|
this.sortByTag = tag;
|
|
33007
33011
|
this.parent.sortObject = newSortObject;
|
|
33008
|
-
sortAlignmentRows(newSortObject, viewport.
|
|
33012
|
+
sortAlignmentRows(newSortObject, viewport.cachedFeatures);
|
|
33009
33013
|
viewport.repaint();
|
|
33010
33014
|
}
|
|
33011
33015
|
}
|
|
@@ -33032,7 +33036,11 @@ class AlignmentTrack {
|
|
|
33032
33036
|
const referenceFrame = clickState.viewport.referenceFrame;
|
|
33033
33037
|
if (this.browser.genome.getChromosome(clickedAlignment.mate.chr)) {
|
|
33034
33038
|
this.highlightedAlignmentReadNamed = clickedAlignment.readName;
|
|
33035
|
-
this.browser.presentMultiLocusPanel(clickedAlignment, referenceFrame)
|
|
33039
|
+
//this.browser.presentMultiLocusPanel(clickedAlignment, referenceFrame)
|
|
33040
|
+
const bpWidth = referenceFrame.end - referenceFrame.start;
|
|
33041
|
+
const frameStart = clickedAlignment.mate.position - bpWidth / 2;
|
|
33042
|
+
const frameEnd = clickedAlignment.mate.position + bpWidth / 2;
|
|
33043
|
+
this.browser.addMultiLocusPanel(clickedAlignment.mate.chr, frameStart, frameEnd, referenceFrame);
|
|
33036
33044
|
} else {
|
|
33037
33045
|
Alert.presentAlert(`Reference does not contain chromosome: ${clickedAlignment.mate.chr}`);
|
|
33038
33046
|
}
|
|
@@ -33080,19 +33088,7 @@ class AlignmentTrack {
|
|
|
33080
33088
|
list.push({
|
|
33081
33089
|
label: 'Add discordant pairs to circular view',
|
|
33082
33090
|
click: () => {
|
|
33083
|
-
|
|
33084
|
-
const {referenceFrame} = viewport;
|
|
33085
|
-
const inView = viewport.getCachedFeatures().allAlignments().filter(a => {
|
|
33086
|
-
return a.end >= referenceFrame.start
|
|
33087
|
-
&& a.start <= referenceFrame.end
|
|
33088
|
-
&& a.mate
|
|
33089
|
-
&& a.mate.chr
|
|
33090
|
-
&& (a.mate.chr !== a.chr || Math.max(a.fragmentLength) > maxFragmentLength)
|
|
33091
|
-
});
|
|
33092
|
-
this.browser.circularViewVisible = true;
|
|
33093
|
-
const chords = makePairedAlignmentChords(inView);
|
|
33094
|
-
const color = IGVColor.addAlpha(this.parent.color || 'rgb(0,0,255)', 0.02);
|
|
33095
|
-
this.browser.circularView.addChords(chords, {track: this.parent.name, color: color});
|
|
33091
|
+
this.parent.addPairedChordsForViewport(viewport);
|
|
33096
33092
|
}
|
|
33097
33093
|
});
|
|
33098
33094
|
}
|
|
@@ -33100,17 +33096,7 @@ class AlignmentTrack {
|
|
|
33100
33096
|
list.push({
|
|
33101
33097
|
label: 'Add split reads to circular view',
|
|
33102
33098
|
click: () => {
|
|
33103
|
-
|
|
33104
|
-
for (let a of viewport.getCachedFeatures().allAlignments()) {
|
|
33105
|
-
const referenceFrame = viewport.referenceFrame;
|
|
33106
|
-
const sa = a.hasTag('SA');
|
|
33107
|
-
if (a.end >= referenceFrame.start && a.start <= referenceFrame.end && sa) {
|
|
33108
|
-
inView.push(a);
|
|
33109
|
-
}
|
|
33110
|
-
}
|
|
33111
|
-
const chords = makeSupplementalAlignmentChords(inView);
|
|
33112
|
-
const color = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.1);
|
|
33113
|
-
this.browser.circularView.addChords(chords, {track: this.name, color: color});
|
|
33099
|
+
this.parent.addSplitChordsForViewport(viewport);
|
|
33114
33100
|
}
|
|
33115
33101
|
});
|
|
33116
33102
|
}
|
|
@@ -33129,7 +33115,7 @@ class AlignmentTrack {
|
|
|
33129
33115
|
|
|
33130
33116
|
const showSoftClips = this.parent.showSoftClips;
|
|
33131
33117
|
|
|
33132
|
-
let features = viewport.
|
|
33118
|
+
let features = viewport.cachedFeatures;
|
|
33133
33119
|
if (!features || features.length === 0) return
|
|
33134
33120
|
|
|
33135
33121
|
let packedAlignmentRows = features.packedAlignmentRows;
|
|
@@ -33220,14 +33206,17 @@ class AlignmentTrack {
|
|
|
33220
33206
|
break
|
|
33221
33207
|
}
|
|
33222
33208
|
|
|
33209
|
+
case "tlen":
|
|
33223
33210
|
case "fragmentLength":
|
|
33224
33211
|
|
|
33225
|
-
if (alignment.mate && alignment.isMateMapped()
|
|
33226
|
-
|
|
33227
|
-
|
|
33228
|
-
|
|
33229
|
-
|
|
33230
|
-
|
|
33212
|
+
if (alignment.mate && alignment.isMateMapped()) {
|
|
33213
|
+
if (alignment.mate.chr !== alignment.chr) {
|
|
33214
|
+
color = getChrColor(alignment.mate.chr);
|
|
33215
|
+
} else if (this.parent.minTemplateLength && Math.abs(alignment.fragmentLength) < this.parent.minTemplateLength) {
|
|
33216
|
+
color = this.smallTLENColor;
|
|
33217
|
+
} else if (this.parent.maxTemplateLength && Math.abs(alignment.fragmentLength) > this.parent.maxTemplateLength) {
|
|
33218
|
+
color = this.largeTLENColor;
|
|
33219
|
+
}
|
|
33231
33220
|
}
|
|
33232
33221
|
break
|
|
33233
33222
|
|
|
@@ -33269,11 +33258,6 @@ function sortAlignmentRows(options, alignmentContainer) {
|
|
|
33269
33258
|
return true === direction ? i : -i
|
|
33270
33259
|
});
|
|
33271
33260
|
|
|
33272
|
-
// For debugging
|
|
33273
|
-
// for(let r of alignmentContainer.packedAlignmentRows) {
|
|
33274
|
-
// console.log(r.score);
|
|
33275
|
-
// }
|
|
33276
|
-
|
|
33277
33261
|
}
|
|
33278
33262
|
|
|
33279
33263
|
function shadedBaseColor(qual, baseColor) {
|
|
@@ -33433,7 +33417,7 @@ class RulerViewport extends TrackViewport {
|
|
|
33433
33417
|
|
|
33434
33418
|
this.$rulerLabel.click(async () => {
|
|
33435
33419
|
|
|
33436
|
-
await this.browser.
|
|
33420
|
+
await this.browser.gotoMultilocusPanel(this.referenceFrame);
|
|
33437
33421
|
|
|
33438
33422
|
// const removals = this.browser.referenceFrameList.filter(r => this.referenceFrame !== r)
|
|
33439
33423
|
// for (let referenceFrame of removals) {
|
|
@@ -33771,7 +33755,7 @@ class IdeogramViewport extends TrackViewport {
|
|
|
33771
33755
|
referenceFrame.end = ee;
|
|
33772
33756
|
referenceFrame.bpPerPixel = (ee - ss) / width;
|
|
33773
33757
|
|
|
33774
|
-
this.browser.updateViews(
|
|
33758
|
+
this.browser.updateViews(true);
|
|
33775
33759
|
|
|
33776
33760
|
}
|
|
33777
33761
|
|
|
@@ -34369,15 +34353,11 @@ const colorPickerExclusionTypes = new Set(['ruler', 'sequence', 'ideogram']);
|
|
|
34369
34353
|
class TrackView {
|
|
34370
34354
|
|
|
34371
34355
|
constructor(browser, columnContainer, track) {
|
|
34372
|
-
|
|
34373
34356
|
this.namespace = `trackview-${guid$2()}`;
|
|
34374
|
-
|
|
34375
34357
|
this.browser = browser;
|
|
34376
34358
|
this.track = track;
|
|
34377
34359
|
track.trackView = this;
|
|
34378
|
-
|
|
34379
34360
|
this.addDOMToColumnContainer(browser, columnContainer, browser.referenceFrameList);
|
|
34380
|
-
|
|
34381
34361
|
}
|
|
34382
34362
|
|
|
34383
34363
|
/**
|
|
@@ -34540,19 +34520,14 @@ class TrackView {
|
|
|
34540
34520
|
if (false === colorPickerExclusionTypes.has(this.track.type)) {
|
|
34541
34521
|
|
|
34542
34522
|
const trackColors = [];
|
|
34543
|
-
|
|
34544
34523
|
const color = this.track.color || this.track.defaultColor;
|
|
34545
|
-
|
|
34546
34524
|
if (isString$3(color)) {
|
|
34547
34525
|
trackColors.push(color);
|
|
34548
34526
|
}
|
|
34549
|
-
|
|
34550
34527
|
if (this.track.altColor && isString$3(this.track.altColor)) {
|
|
34551
34528
|
trackColors.push(this.track.altColor);
|
|
34552
34529
|
}
|
|
34553
|
-
|
|
34554
34530
|
const defaultColors = trackColors.map(c => c.startsWith("#") ? c : c.startsWith("rgb(") ? IGVColor.rgbToHex(c) : IGVColor.colorNameToHex(c));
|
|
34555
|
-
|
|
34556
34531
|
const colorHandlers =
|
|
34557
34532
|
{
|
|
34558
34533
|
color: color => {
|
|
@@ -34565,7 +34540,6 @@ class TrackView {
|
|
|
34565
34540
|
}
|
|
34566
34541
|
|
|
34567
34542
|
};
|
|
34568
|
-
|
|
34569
34543
|
this.browser.genericColorPicker.configure(defaultColors, colorHandlers);
|
|
34570
34544
|
this.browser.genericColorPicker.setActiveColorHandler(key);
|
|
34571
34545
|
this.browser.genericColorPicker.show();
|
|
@@ -34579,7 +34553,6 @@ class TrackView {
|
|
|
34579
34553
|
if (this.track.minHeight) {
|
|
34580
34554
|
newHeight = Math.max(this.track.minHeight, newHeight);
|
|
34581
34555
|
}
|
|
34582
|
-
|
|
34583
34556
|
if (this.track.maxHeight) {
|
|
34584
34557
|
newHeight = Math.min(this.track.maxHeight, newHeight);
|
|
34585
34558
|
}
|
|
@@ -34674,7 +34647,9 @@ class TrackView {
|
|
|
34674
34647
|
repaintViews() {
|
|
34675
34648
|
|
|
34676
34649
|
for (let viewport of this.viewports) {
|
|
34677
|
-
viewport.
|
|
34650
|
+
if(viewport.isVisible()) {
|
|
34651
|
+
viewport.repaint();
|
|
34652
|
+
}
|
|
34678
34653
|
}
|
|
34679
34654
|
|
|
34680
34655
|
if (typeof this.track.paintAxis === 'function') {
|
|
@@ -34701,6 +34676,9 @@ class TrackView {
|
|
|
34701
34676
|
|
|
34702
34677
|
/**
|
|
34703
34678
|
* Update viewports to reflect current genomic state, possibly loading additional data.
|
|
34679
|
+
*
|
|
34680
|
+
* @param force - if true, force a repaint even if no new data is loaded
|
|
34681
|
+
* @returns {Promise<void>}
|
|
34704
34682
|
*/
|
|
34705
34683
|
async updateViews(force) {
|
|
34706
34684
|
|
|
@@ -34718,24 +34696,24 @@ class TrackView {
|
|
|
34718
34696
|
}
|
|
34719
34697
|
|
|
34720
34698
|
// rpv: viewports whose image (canvas) does not fully cover current genomic range
|
|
34721
|
-
const reloadableViewports = this.viewportsToReload(
|
|
34699
|
+
const reloadableViewports = force ? visibleViewports : this.viewportsToReload();
|
|
34722
34700
|
|
|
34723
34701
|
// Trigger viewport to load features needed to cover current genomic range
|
|
34724
34702
|
// NOTE: these must be loaded synchronously, do not user Promise.all, not all file readers are thread safe
|
|
34725
34703
|
for (let viewport of reloadableViewports) {
|
|
34726
34704
|
await viewport.loadFeatures();
|
|
34727
34705
|
}
|
|
34728
|
-
|
|
34706
|
+
|
|
34729
34707
|
if (this.disposed) return // Track was removed during load
|
|
34730
34708
|
|
|
34731
|
-
//
|
|
34709
|
+
// Special case for variant tracks in multilocus view. The # of rows to allocate to the variant (site)
|
|
34732
34710
|
// section depends on data from all the views. We only need to adjust this however if any data was loaded
|
|
34733
34711
|
// (i.e. reloadableViewports.length > 0)
|
|
34734
34712
|
if (this.track && typeof this.track.variantRowCount === 'function' && reloadableViewports.length > 0) {
|
|
34735
34713
|
let maxRow = 0;
|
|
34736
34714
|
for (let viewport of this.viewports) {
|
|
34737
|
-
if (viewport.
|
|
34738
|
-
maxRow = Math.max(maxRow, viewport.
|
|
34715
|
+
if (viewport.featureCache && viewport.featureCache.features) {
|
|
34716
|
+
maxRow = Math.max(maxRow, viewport.featureCache.features.reduce((a, f) => Math.max(a, f.row || 0), 0));
|
|
34739
34717
|
}
|
|
34740
34718
|
}
|
|
34741
34719
|
const current = this.track.nVariantRows;
|
|
@@ -34747,19 +34725,18 @@ class TrackView {
|
|
|
34747
34725
|
}
|
|
34748
34726
|
}
|
|
34749
34727
|
|
|
34750
|
-
|
|
34751
34728
|
if (this.track.autoscale) {
|
|
34752
34729
|
let allFeatures = [];
|
|
34753
34730
|
for (let visibleViewport of visibleViewports) {
|
|
34754
34731
|
const referenceFrame = visibleViewport.referenceFrame;
|
|
34755
34732
|
const start = referenceFrame.start;
|
|
34756
34733
|
const end = start + referenceFrame.toBP($$1(visibleViewport.contentDiv).width());
|
|
34757
|
-
if (visibleViewport.
|
|
34758
|
-
if (typeof visibleViewport.
|
|
34759
|
-
const max = visibleViewport.
|
|
34734
|
+
if (visibleViewport.featureCache && visibleViewport.featureCache.features) {
|
|
34735
|
+
if (typeof visibleViewport.featureCache.features.getMax === 'function') {
|
|
34736
|
+
const max = visibleViewport.featureCache.features.getMax(start, end);
|
|
34760
34737
|
allFeatures.push({value: max});
|
|
34761
34738
|
} else {
|
|
34762
|
-
allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(visibleViewport.
|
|
34739
|
+
allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(visibleViewport.featureCache.features, start, end));
|
|
34763
34740
|
}
|
|
34764
34741
|
}
|
|
34765
34742
|
}
|
|
@@ -34770,14 +34747,18 @@ class TrackView {
|
|
|
34770
34747
|
}
|
|
34771
34748
|
}
|
|
34772
34749
|
|
|
34773
|
-
// Must repaint all viewports if autoscaling
|
|
34774
|
-
if (
|
|
34775
|
-
for (let
|
|
34776
|
-
|
|
34750
|
+
// Must repaint all viewports if autoscaling. Always repaint ruler.
|
|
34751
|
+
if (this.track.autoscale || this.track.autoscaleGroup || this.track.type === 'ruler' || force) {
|
|
34752
|
+
for (let vp of visibleViewports) {
|
|
34753
|
+
vp.repaint();
|
|
34777
34754
|
}
|
|
34778
34755
|
} else {
|
|
34779
|
-
|
|
34780
|
-
|
|
34756
|
+
const reloadedViewports = new Set(reloadableViewports);
|
|
34757
|
+
for (let vp of visibleViewports) {
|
|
34758
|
+
const invalid = vp.canvas && vp.canvas._data && vp.canvas._data.invalidate;
|
|
34759
|
+
if (invalid || reloadedViewports.has(vp)) {
|
|
34760
|
+
vp.repaint();
|
|
34761
|
+
}
|
|
34781
34762
|
}
|
|
34782
34763
|
}
|
|
34783
34764
|
|
|
@@ -34808,14 +34789,14 @@ class TrackView {
|
|
|
34808
34789
|
/**
|
|
34809
34790
|
* Return a promise to get all in-view features. Used for group autoscaling.
|
|
34810
34791
|
*/
|
|
34811
|
-
async getInViewFeatures(
|
|
34792
|
+
async getInViewFeatures() {
|
|
34812
34793
|
|
|
34813
34794
|
if (!(this.browser && this.browser.referenceFrameList)) {
|
|
34814
34795
|
return []
|
|
34815
34796
|
}
|
|
34816
34797
|
|
|
34817
34798
|
// List of viewports that need reloading
|
|
34818
|
-
const rpV = this.viewportsToReload(
|
|
34799
|
+
const rpV = this.viewportsToReload();
|
|
34819
34800
|
const promises = rpV.map(function (vp) {
|
|
34820
34801
|
return vp.loadFeatures()
|
|
34821
34802
|
});
|
|
@@ -34824,16 +34805,16 @@ class TrackView {
|
|
|
34824
34805
|
|
|
34825
34806
|
let allFeatures = [];
|
|
34826
34807
|
for (let vp of this.viewports) {
|
|
34827
|
-
if (vp.
|
|
34808
|
+
if (vp.featureCache && vp.featureCache.features) {
|
|
34828
34809
|
const referenceFrame = vp.referenceFrame;
|
|
34829
34810
|
const start = referenceFrame.start;
|
|
34830
34811
|
const end = start + referenceFrame.toBP($$1(vp.contentDiv).width());
|
|
34831
34812
|
|
|
34832
|
-
if (typeof vp.
|
|
34833
|
-
const max = vp.
|
|
34813
|
+
if (typeof vp.featureCache.features.getMax === 'function') {
|
|
34814
|
+
const max = vp.featureCache.features.getMax(start, end);
|
|
34834
34815
|
allFeatures.push({value: max});
|
|
34835
34816
|
} else {
|
|
34836
|
-
allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(vp.
|
|
34817
|
+
allFeatures = allFeatures.concat(FeatureUtils.findOverlapping(vp.featureCache.features, start, end));
|
|
34837
34818
|
}
|
|
34838
34819
|
}
|
|
34839
34820
|
}
|
|
@@ -34889,7 +34870,7 @@ class TrackView {
|
|
|
34889
34870
|
const start = referenceFrame.start;
|
|
34890
34871
|
const end = start + referenceFrame.toBP($$1(viewport.contentDiv).width());
|
|
34891
34872
|
const bpPerPixel = referenceFrame.bpPerPixel;
|
|
34892
|
-
return
|
|
34873
|
+
return (!viewport.featureCache || !viewport.featureCache.containsRange(chr, start, end, bpPerPixel))
|
|
34893
34874
|
}
|
|
34894
34875
|
});
|
|
34895
34876
|
return viewports
|
|
@@ -39662,7 +39643,7 @@ class TextFeatureSource {
|
|
|
39662
39643
|
this.sourceType = (config.sourceType === undefined ? "file" : config.sourceType);
|
|
39663
39644
|
this.maxWGCount = config.maxWGCount || DEFAULT_MAX_WG_COUNT;
|
|
39664
39645
|
|
|
39665
|
-
const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "tdf"]);
|
|
39646
|
+
const queryableFormats = new Set(["bigwig", "bw", "bigbed", "bb", "biginteract", "tdf"]);
|
|
39666
39647
|
|
|
39667
39648
|
if (config.features && Array.isArray(config.features)) {
|
|
39668
39649
|
// Explicit array of features
|
|
@@ -39672,7 +39653,7 @@ class TextFeatureSource {
|
|
|
39672
39653
|
mapProperties(features, config.mappings);
|
|
39673
39654
|
}
|
|
39674
39655
|
this.queryable = false;
|
|
39675
|
-
this.featureCache = new FeatureCache(features, genome);
|
|
39656
|
+
this.featureCache = new FeatureCache$1(features, genome);
|
|
39676
39657
|
} else if (config.reader) {
|
|
39677
39658
|
// Explicit reader implementation
|
|
39678
39659
|
this.reader = config.reader;
|
|
@@ -39839,14 +39820,14 @@ class TextFeatureSource {
|
|
|
39839
39820
|
}
|
|
39840
39821
|
|
|
39841
39822
|
// Note - replacing previous cache with new one. genomicInterval is optional (might be undefined => includes all features)
|
|
39842
|
-
this.featureCache = new FeatureCache(features, this.genome, genomicInterval);
|
|
39823
|
+
this.featureCache = new FeatureCache$1(features, this.genome, genomicInterval);
|
|
39843
39824
|
|
|
39844
39825
|
// If track is marked "searchable"< cache features by name -- use this with caution, memory intensive
|
|
39845
39826
|
if (this.config.searchable || this.config.searchableFields) {
|
|
39846
39827
|
this.addFeaturesToDB(features);
|
|
39847
39828
|
}
|
|
39848
39829
|
} else {
|
|
39849
|
-
this.featureCache = new FeatureCache([], genomicInterval); // Empty cache
|
|
39830
|
+
this.featureCache = new FeatureCache$1([], genomicInterval); // Empty cache
|
|
39850
39831
|
}
|
|
39851
39832
|
}
|
|
39852
39833
|
|
|
@@ -40084,9 +40065,9 @@ class BufferedReader {
|
|
|
40084
40065
|
|
|
40085
40066
|
//table chromatinInteract
|
|
40086
40067
|
|
|
40087
|
-
function getDecoder(definedFieldCount, fieldCount, autoSql) {
|
|
40068
|
+
function getDecoder(definedFieldCount, fieldCount, autoSql, format) {
|
|
40088
40069
|
|
|
40089
|
-
if (autoSql && 'chromatinInteract' === autoSql.table) {
|
|
40070
|
+
if (autoSql && 'chromatinInteract' === autoSql.table || "biginteract" === format) {
|
|
40090
40071
|
return decodeInteract
|
|
40091
40072
|
} else {
|
|
40092
40073
|
const standardFieldCount = definedFieldCount - 3;
|
|
@@ -40233,6 +40214,7 @@ class BWReader {
|
|
|
40233
40214
|
|
|
40234
40215
|
constructor(config, genome) {
|
|
40235
40216
|
this.path = config.url;
|
|
40217
|
+
this.format = config.format || "bigwig";
|
|
40236
40218
|
this.genome = genome;
|
|
40237
40219
|
this.rpTreeCache = {};
|
|
40238
40220
|
this.config = config;
|
|
@@ -40833,7 +40815,7 @@ function decodeWigData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chr
|
|
|
40833
40815
|
function getBedDataDecoder() {
|
|
40834
40816
|
|
|
40835
40817
|
const minSize = 3 * 4 + 1; // Minimum # of bytes required for a bed record
|
|
40836
|
-
const decoder = getDecoder(this.header.definedFieldCount, this.header.fieldCount, this.autoSql);
|
|
40818
|
+
const decoder = getDecoder(this.header.definedFieldCount, this.header.fieldCount, this.autoSql, this.format);
|
|
40837
40819
|
return function (data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, chrDict) {
|
|
40838
40820
|
const binaryParser = new BinaryParser(data);
|
|
40839
40821
|
while (binaryParser.remLength() >= minSize) {
|
|
@@ -41701,7 +41683,7 @@ function zoomLevelForScale(chr, bpPerPixel, genome) {
|
|
|
41701
41683
|
function FeatureSource(config, genome) {
|
|
41702
41684
|
|
|
41703
41685
|
const format = config.format ? config.format.toLowerCase() : undefined;
|
|
41704
|
-
if ('bigwig' === format || 'bigbed' === format || 'bb' === format) {
|
|
41686
|
+
if ('bigwig' === format || 'bigbed' === format || 'bb' === format || "biginteract" === format) {
|
|
41705
41687
|
return new BWSource(config, genome)
|
|
41706
41688
|
} else if ("tdf" === format) {
|
|
41707
41689
|
return new TDFSource(config, genome)
|
|
@@ -42648,13 +42630,11 @@ class WigTrack extends TrackBase {
|
|
|
42648
42630
|
this.paintAxis = paintAxis;
|
|
42649
42631
|
|
|
42650
42632
|
const format = config.format ? config.format.toLowerCase() : config.format;
|
|
42633
|
+
this.flipAxis = config.flipAxis ? config.flipAxis : false;
|
|
42634
|
+
this.logScale = config.logScale ? config.logScale : false;
|
|
42651
42635
|
if ("bigwig" === format) {
|
|
42652
|
-
this.flipAxis = config.flipAxis ? config.flipAxis : false;
|
|
42653
|
-
this.logScale = config.logScale ? config.logScale : false;
|
|
42654
42636
|
this.featureSource = new BWSource(config, this.browser.genome);
|
|
42655
42637
|
} else if ("tdf" === format) {
|
|
42656
|
-
this.flipAxis = config.flipAxis ? config.flipAxis : false;
|
|
42657
|
-
this.logScale = config.logScale ? config.logScale : false;
|
|
42658
42638
|
this.featureSource = new TDFSource(config, this.browser.genome);
|
|
42659
42639
|
} else {
|
|
42660
42640
|
this.featureSource = FeatureSource(config, this.browser.genome);
|
|
@@ -42706,7 +42686,7 @@ class WigTrack extends TrackBase {
|
|
|
42706
42686
|
let items = [];
|
|
42707
42687
|
if (this.flipAxis !== undefined) {
|
|
42708
42688
|
items.push({
|
|
42709
|
-
label:"Flip y-axis",
|
|
42689
|
+
label: "Flip y-axis",
|
|
42710
42690
|
click: () => {
|
|
42711
42691
|
this.flipAxis = !this.flipAxis;
|
|
42712
42692
|
this.trackView.repaintViews();
|
|
@@ -43434,7 +43414,7 @@ class SegTrack extends TrackBase {
|
|
|
43434
43414
|
|
|
43435
43415
|
const sortHandler = (sort) => {
|
|
43436
43416
|
const viewport = clickState.viewport;
|
|
43437
|
-
const features = viewport.
|
|
43417
|
+
const features = viewport.cachedFeatures;
|
|
43438
43418
|
this.sortSamples(sort.chr, sort.start, sort.end, sort.direction, features);
|
|
43439
43419
|
};
|
|
43440
43420
|
|
|
@@ -43552,10 +43532,16 @@ const MUT_COLORS = {
|
|
|
43552
43532
|
* THE SOFTWARE.
|
|
43553
43533
|
*/
|
|
43554
43534
|
|
|
43535
|
+
/**
|
|
43536
|
+
* Represents 2 or more wig tracks overlaid on a common viewport.
|
|
43537
|
+
*/
|
|
43555
43538
|
class MergedTrack extends TrackBase {
|
|
43556
43539
|
|
|
43557
43540
|
constructor(config, browser) {
|
|
43558
43541
|
super(config, browser);
|
|
43542
|
+
this.type = "merged";
|
|
43543
|
+
this.featureType = 'numeric';
|
|
43544
|
+
this.paintAxis = paintAxis;
|
|
43559
43545
|
}
|
|
43560
43546
|
|
|
43561
43547
|
init(config) {
|
|
@@ -43566,21 +43552,6 @@ class MergedTrack extends TrackBase {
|
|
|
43566
43552
|
super.init(config);
|
|
43567
43553
|
}
|
|
43568
43554
|
|
|
43569
|
-
get height() {
|
|
43570
|
-
return this._height
|
|
43571
|
-
}
|
|
43572
|
-
|
|
43573
|
-
set height(h) {
|
|
43574
|
-
this._height = h;
|
|
43575
|
-
if (this.tracks) {
|
|
43576
|
-
for (let t of this.tracks) {
|
|
43577
|
-
t.height = h;
|
|
43578
|
-
t.config.height = h;
|
|
43579
|
-
}
|
|
43580
|
-
}
|
|
43581
|
-
}
|
|
43582
|
-
|
|
43583
|
-
|
|
43584
43555
|
async postInit() {
|
|
43585
43556
|
|
|
43586
43557
|
this.tracks = [];
|
|
@@ -43600,11 +43571,55 @@ class MergedTrack extends TrackBase {
|
|
|
43600
43571
|
}
|
|
43601
43572
|
}
|
|
43602
43573
|
|
|
43603
|
-
this.
|
|
43574
|
+
this.flipAxis = this.config.flipAxis ? this.config.flipAxis : false;
|
|
43575
|
+
this.logScale = this.config.logScale ? this.config.logScale : false;
|
|
43576
|
+
this.autoscale = this.config.autoscale || this.config.max === undefined;
|
|
43577
|
+
if (!this.autoscale) {
|
|
43578
|
+
this.dataRange = {
|
|
43579
|
+
min: this.config.min || 0,
|
|
43580
|
+
max: this.config.max
|
|
43581
|
+
};
|
|
43582
|
+
}
|
|
43583
|
+
for (let t of this.tracks) {
|
|
43584
|
+
t.autoscale = false;
|
|
43585
|
+
t.dataRange = this.dataRange;
|
|
43586
|
+
}
|
|
43587
|
+
|
|
43588
|
+
this.height = this.config.height || 50;
|
|
43604
43589
|
|
|
43605
43590
|
return Promise.all(p)
|
|
43606
43591
|
}
|
|
43607
43592
|
|
|
43593
|
+
get height() {
|
|
43594
|
+
return this._height
|
|
43595
|
+
}
|
|
43596
|
+
|
|
43597
|
+
set height(h) {
|
|
43598
|
+
this._height = h;
|
|
43599
|
+
if (this.tracks) {
|
|
43600
|
+
for (let t of this.tracks) {
|
|
43601
|
+
t.height = h;
|
|
43602
|
+
t.config.height = h;
|
|
43603
|
+
}
|
|
43604
|
+
}
|
|
43605
|
+
}
|
|
43606
|
+
|
|
43607
|
+
menuItemList() {
|
|
43608
|
+
let items = [];
|
|
43609
|
+
if (this.flipAxis !== undefined) {
|
|
43610
|
+
items.push({
|
|
43611
|
+
label: "Flip y-axis",
|
|
43612
|
+
click: () => {
|
|
43613
|
+
this.flipAxis = !this.flipAxis;
|
|
43614
|
+
this.trackView.repaintViews();
|
|
43615
|
+
}
|
|
43616
|
+
});
|
|
43617
|
+
}
|
|
43618
|
+
|
|
43619
|
+
items = items.concat(MenuUtils.numericDataMenuItems(this.trackView));
|
|
43620
|
+
|
|
43621
|
+
return items
|
|
43622
|
+
}
|
|
43608
43623
|
|
|
43609
43624
|
async getFeatures(chr, bpStart, bpEnd, bpPerPixel) {
|
|
43610
43625
|
|
|
@@ -43614,44 +43629,26 @@ class MergedTrack extends TrackBase {
|
|
|
43614
43629
|
|
|
43615
43630
|
draw(options) {
|
|
43616
43631
|
|
|
43617
|
-
|
|
43618
|
-
|
|
43619
|
-
mergedFeatures = options.features; // Array of feature arrays, 1 for each track
|
|
43620
|
-
|
|
43621
|
-
dataRange = autoscale(options.referenceFrame.chr, mergedFeatures);
|
|
43632
|
+
const mergedFeatures = options.features; // Array of feature arrays, 1 for each track
|
|
43622
43633
|
|
|
43623
|
-
|
|
43624
|
-
|
|
43625
|
-
|
|
43634
|
+
if (this.autoscale) {
|
|
43635
|
+
this.dataRange = autoscale(options.referenceFrame.chr, mergedFeatures);
|
|
43636
|
+
}
|
|
43626
43637
|
|
|
43627
|
-
|
|
43638
|
+
for (let i = 0, len = this.tracks.length; i < len; i++) {
|
|
43639
|
+
const trackOptions = Object.assign({}, options);
|
|
43628
43640
|
trackOptions.features = mergedFeatures[i];
|
|
43629
|
-
this.tracks[i].dataRange = dataRange;
|
|
43641
|
+
this.tracks[i].dataRange = this.dataRange;
|
|
43642
|
+
this.tracks[i].flipAxis = this.flipAxis;
|
|
43643
|
+
this.tracks[i].logScale = this.logScale;
|
|
43644
|
+
this.tracks[i].graphType = this.graphType;
|
|
43630
43645
|
this.tracks[i].draw(trackOptions);
|
|
43631
43646
|
}
|
|
43632
|
-
|
|
43633
|
-
}
|
|
43634
|
-
|
|
43635
|
-
paintAxis(ctx, pixelWidth, pixelHeight) {
|
|
43636
|
-
|
|
43637
|
-
var i, len, autoscale, track;
|
|
43638
|
-
|
|
43639
|
-
autoscale = true; // Hardcoded for now
|
|
43640
|
-
|
|
43641
|
-
for (i = 0, len = this.tracks.length; i < len; i++) {
|
|
43642
|
-
|
|
43643
|
-
track = this.tracks[i];
|
|
43644
|
-
|
|
43645
|
-
if (typeof track.paintAxis === 'function') {
|
|
43646
|
-
track.paintAxis(ctx, pixelWidth, pixelHeight);
|
|
43647
|
-
if (autoscale) break
|
|
43648
|
-
}
|
|
43649
|
-
}
|
|
43650
43647
|
}
|
|
43651
43648
|
|
|
43652
43649
|
popupData(clickState, features) {
|
|
43653
43650
|
|
|
43654
|
-
const featuresArray = features || clickState.viewport.
|
|
43651
|
+
const featuresArray = features || clickState.viewport.cachedFeatures;
|
|
43655
43652
|
|
|
43656
43653
|
if (featuresArray && featuresArray.length === this.tracks.length) {
|
|
43657
43654
|
// Array of feature arrays, 1 for each track
|
|
@@ -43669,41 +43666,22 @@ class MergedTrack extends TrackBase {
|
|
|
43669
43666
|
|
|
43670
43667
|
|
|
43671
43668
|
supportsWholeGenome() {
|
|
43672
|
-
|
|
43673
|
-
return b
|
|
43669
|
+
return this.tracks.every(track => track.supportsWholeGenome())
|
|
43674
43670
|
}
|
|
43675
43671
|
}
|
|
43676
43672
|
|
|
43677
43673
|
function autoscale(chr, featureArrays) {
|
|
43678
43674
|
|
|
43679
|
-
|
|
43680
|
-
|
|
43681
|
-
|
|
43682
|
-
|
|
43683
|
-
// if (chr === 'all') {
|
|
43684
|
-
// allValues = [];
|
|
43685
|
-
// featureArrays.forEach(function (features) {
|
|
43686
|
-
// features.forEach(function (f) {
|
|
43687
|
-
// if (!Number.isNaN(f.value)) {
|
|
43688
|
-
// allValues.push(f.value);
|
|
43689
|
-
// }
|
|
43690
|
-
// });
|
|
43691
|
-
// });
|
|
43692
|
-
//
|
|
43693
|
-
// min = Math.min(0, IGVMath.percentile(allValues, .1));
|
|
43694
|
-
// max = IGVMath.percentile(allValues, 99.9);
|
|
43695
|
-
//
|
|
43696
|
-
// }
|
|
43697
|
-
// else {
|
|
43698
|
-
featureArrays.forEach(function (features, i) {
|
|
43699
|
-
features.forEach(function (f) {
|
|
43675
|
+
let min = 0;
|
|
43676
|
+
let max = -Number.MAX_VALUE;
|
|
43677
|
+
for(let features of featureArrays) {
|
|
43678
|
+
for(let f of features) {
|
|
43700
43679
|
if (typeof f.value !== 'undefined' && !Number.isNaN(f.value)) {
|
|
43701
43680
|
min = Math.min(min, f.value);
|
|
43702
43681
|
max = Math.max(max, f.value);
|
|
43703
43682
|
}
|
|
43704
|
-
}
|
|
43705
|
-
}
|
|
43706
|
-
// }
|
|
43683
|
+
}
|
|
43684
|
+
}
|
|
43707
43685
|
return {min: min, max: max}
|
|
43708
43686
|
}
|
|
43709
43687
|
|
|
@@ -44245,21 +44223,23 @@ class InteractionTrack extends TrackBase {
|
|
|
44245
44223
|
|
|
44246
44224
|
// inView features are simply features that have been drawn, i.e. have a drawState
|
|
44247
44225
|
const inView = cachedFeatures.filter(f => f.drawState);
|
|
44248
|
-
if(inView.length === 0)
|
|
44226
|
+
if(inView.length === 0) return;
|
|
44249
44227
|
|
|
44250
44228
|
this.browser.circularViewVisible = true;
|
|
44251
44229
|
const chords = makeBedPEChords(inView);
|
|
44252
|
-
|
|
44253
|
-
//
|
|
44254
|
-
|
|
44255
|
-
|
|
44256
|
-
|
|
44257
|
-
//
|
|
44258
|
-
|
|
44259
|
-
|
|
44260
|
-
|
|
44261
|
-
|
|
44262
|
-
|
|
44230
|
+
sendChords(chords, this, refFrame, 0.5);
|
|
44231
|
+
//
|
|
44232
|
+
//
|
|
44233
|
+
// // for filtered set, distinguishing the chromosomes is more critical than tracks
|
|
44234
|
+
// const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.5)
|
|
44235
|
+
// const trackColor = IGVColor.addAlpha(this.color, 0.5)
|
|
44236
|
+
//
|
|
44237
|
+
// // name the chord set to include locus and filtering information
|
|
44238
|
+
// const encodedName = this.name.replaceAll(' ', '%20')
|
|
44239
|
+
// const chordSetName = "all" === refFrame.chr ?
|
|
44240
|
+
// encodedName :
|
|
44241
|
+
// `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end} ; range:${this.dataRange.min}-${this.dataRange.max})`
|
|
44242
|
+
// this.browser.circularView.addChords(chords, {track: chordSetName, color: chordSetColor, trackColor: trackColor})
|
|
44263
44243
|
}
|
|
44264
44244
|
|
|
44265
44245
|
doAutoscale(features) {
|
|
@@ -44324,7 +44304,7 @@ class InteractionTrack extends TrackBase {
|
|
|
44324
44304
|
|
|
44325
44305
|
// We use the cached features rather than method to avoid async load. If the
|
|
44326
44306
|
// feature is not already loaded this won't work, but the user wouldn't be mousing over it either.
|
|
44327
|
-
const featureList = features || clickState.viewport.
|
|
44307
|
+
const featureList = features || clickState.viewport.cachedFeatures;
|
|
44328
44308
|
const candidates = [];
|
|
44329
44309
|
if (featureList) {
|
|
44330
44310
|
const proportional = (this.arcType === "proportional" || this.arcType === "inView" || this.arcType === "partialInView");
|
|
@@ -44850,7 +44830,7 @@ class VariantTrack extends TrackBase {
|
|
|
44850
44830
|
}
|
|
44851
44831
|
|
|
44852
44832
|
} else if (this._color) {
|
|
44853
|
-
variantColor =
|
|
44833
|
+
variantColor = this.color;
|
|
44854
44834
|
} else if ("NONVARIANT" === v.type) {
|
|
44855
44835
|
variantColor = this.nonRefColor;
|
|
44856
44836
|
} else if ("MIXED" === v.type) {
|
|
@@ -44861,6 +44841,10 @@ class VariantTrack extends TrackBase {
|
|
|
44861
44841
|
return variantColor
|
|
44862
44842
|
}
|
|
44863
44843
|
|
|
44844
|
+
get color() {
|
|
44845
|
+
return this._color ? ((typeof this._color === "function") ? this._color(v) : this._color) : this.defaultColor
|
|
44846
|
+
}
|
|
44847
|
+
|
|
44864
44848
|
clickedFeatures(clickState, features) {
|
|
44865
44849
|
|
|
44866
44850
|
let featureList = super.clickedFeatures(clickState, features);
|
|
@@ -45093,19 +45077,9 @@ class VariantTrack extends TrackBase {
|
|
|
45093
45077
|
menuItems.push({
|
|
45094
45078
|
label: 'Add SVs to circular view',
|
|
45095
45079
|
click: () => {
|
|
45096
|
-
const inView = [];
|
|
45097
45080
|
for (let viewport of this.trackView.viewports) {
|
|
45098
|
-
|
|
45099
|
-
for (let f of viewport.getCachedFeatures()) {
|
|
45100
|
-
if (f.end >= refFrame.start && f.start <= refFrame.end) {
|
|
45101
|
-
inView.push(f);
|
|
45102
|
-
}
|
|
45103
|
-
}
|
|
45081
|
+
this.sendChordsForViewport(viewport);
|
|
45104
45082
|
}
|
|
45105
|
-
|
|
45106
|
-
const chords = makeVCFChords(inView);
|
|
45107
|
-
const color = IGVColor.addAlpha(this._color || this.defaultColor, 0.5);
|
|
45108
|
-
this.browser.circularView.addChords(chords, {track: this.name, color: color});
|
|
45109
45083
|
}
|
|
45110
45084
|
});
|
|
45111
45085
|
}
|
|
@@ -45124,13 +45098,7 @@ class VariantTrack extends TrackBase {
|
|
|
45124
45098
|
list.push({
|
|
45125
45099
|
label: 'Add SVs to Circular View',
|
|
45126
45100
|
click: () => {
|
|
45127
|
-
|
|
45128
|
-
const inView = "all" === refFrame.chr ?
|
|
45129
|
-
this.featureSource.getAllFeatures() :
|
|
45130
|
-
this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end);
|
|
45131
|
-
const chords = makeVCFChords(inView);
|
|
45132
|
-
const color = IGVColor.addAlpha(this._color || this.defaultColor, 0.5);
|
|
45133
|
-
this.browser.circularView.addChords(chords, {track: this.name, color: color});
|
|
45101
|
+
this.sendChordsForViewport(viewport);
|
|
45134
45102
|
}
|
|
45135
45103
|
});
|
|
45136
45104
|
|
|
@@ -45140,6 +45108,15 @@ class VariantTrack extends TrackBase {
|
|
|
45140
45108
|
}
|
|
45141
45109
|
|
|
45142
45110
|
|
|
45111
|
+
sendChordsForViewport(viewport) {
|
|
45112
|
+
const refFrame = viewport.referenceFrame;
|
|
45113
|
+
const inView = "all" === refFrame.chr ?
|
|
45114
|
+
this.featureSource.getAllFeatures() :
|
|
45115
|
+
this.featureSource.featureCache.queryFeatures(refFrame.chr, refFrame.start, refFrame.end);
|
|
45116
|
+
const chords = makeVCFChords(inView);
|
|
45117
|
+
sendChords(chords, this, refFrame, 0.5);
|
|
45118
|
+
}
|
|
45119
|
+
|
|
45143
45120
|
/**
|
|
45144
45121
|
* Create a "color by" checkbox menu item, optionally initially checked
|
|
45145
45122
|
* @param menuItem
|
|
@@ -45436,7 +45413,7 @@ class EqtlTrack extends TrackBase {
|
|
|
45436
45413
|
*/
|
|
45437
45414
|
popupData(clickState) {
|
|
45438
45415
|
|
|
45439
|
-
let features = clickState.viewport.
|
|
45416
|
+
let features = clickState.viewport.cachedFeatures;
|
|
45440
45417
|
if (!features || features.length === 0) return []
|
|
45441
45418
|
|
|
45442
45419
|
const tolerance = 3;
|
|
@@ -45766,7 +45743,7 @@ class GWASTrack extends TrackBase {
|
|
|
45766
45743
|
|
|
45767
45744
|
let data = [];
|
|
45768
45745
|
const track = clickState.viewport.trackView.track;
|
|
45769
|
-
const features = clickState.viewport.
|
|
45746
|
+
const features = clickState.viewport.cachedFeatures;
|
|
45770
45747
|
|
|
45771
45748
|
if (features) {
|
|
45772
45749
|
let count = 0;
|
|
@@ -46449,7 +46426,7 @@ class RNAFeatureSource {
|
|
|
46449
46426
|
|
|
46450
46427
|
const data = await igvxhr.loadString(this.config.url, options);
|
|
46451
46428
|
|
|
46452
|
-
this.featureCache = new FeatureCache(parseBP(data), genome);
|
|
46429
|
+
this.featureCache = new FeatureCache$1(parseBP(data), genome);
|
|
46453
46430
|
|
|
46454
46431
|
return this.featureCache.queryFeatures(chr, start, end)
|
|
46455
46432
|
|
|
@@ -47731,6 +47708,15 @@ class ReferenceFrame {
|
|
|
47731
47708
|
this.id = guid$2();
|
|
47732
47709
|
}
|
|
47733
47710
|
|
|
47711
|
+
extend(locus) {
|
|
47712
|
+
const newStart = Math.min(locus.start, this.start);
|
|
47713
|
+
const newEnd = Math.max(locus.end, this.end);
|
|
47714
|
+
const ratio = (newEnd - newStart) / (this.end - this.start);
|
|
47715
|
+
this.start = newStart;
|
|
47716
|
+
this.end = newEnd;
|
|
47717
|
+
this.bpPerPixel *= ratio;
|
|
47718
|
+
}
|
|
47719
|
+
|
|
47734
47720
|
calculateEnd(pixels) {
|
|
47735
47721
|
return this.start + this.bpPerPixel * pixels
|
|
47736
47722
|
}
|
|
@@ -47817,7 +47803,7 @@ class ReferenceFrame {
|
|
|
47817
47803
|
|
|
47818
47804
|
const viewChanged = start !== this.start || bpPerPixel !== this.bpPerPixel;
|
|
47819
47805
|
if (viewChanged) {
|
|
47820
|
-
await browser.updateViews(
|
|
47806
|
+
await browser.updateViews(true);
|
|
47821
47807
|
}
|
|
47822
47808
|
|
|
47823
47809
|
}
|
|
@@ -49619,8 +49605,8 @@ class Browser {
|
|
|
49619
49605
|
this.svgSaveControl = new SVGSaveControl($toggle_button_container.get(0), this);
|
|
49620
49606
|
}
|
|
49621
49607
|
|
|
49622
|
-
if(config.customButtons) {
|
|
49623
|
-
for(let b of config.customButtons) {
|
|
49608
|
+
if (config.customButtons) {
|
|
49609
|
+
for (let b of config.customButtons) {
|
|
49624
49610
|
new CustomButton($toggle_button_container.get(0), this, b);
|
|
49625
49611
|
}
|
|
49626
49612
|
}
|
|
@@ -49781,7 +49767,6 @@ class Browser {
|
|
|
49781
49767
|
return undefined
|
|
49782
49768
|
}
|
|
49783
49769
|
}
|
|
49784
|
-
|
|
49785
49770
|
}
|
|
49786
49771
|
}
|
|
49787
49772
|
|
|
@@ -49871,6 +49856,11 @@ class Browser {
|
|
|
49871
49856
|
|
|
49872
49857
|
await this.loadTrackList(trackConfigurations);
|
|
49873
49858
|
|
|
49859
|
+
// The ruler track is not explicitly loaded, but needs updated nonetheless.
|
|
49860
|
+
for (let rtv of this.trackViews.filter((tv) => tv.track.type === 'ruler')) {
|
|
49861
|
+
rtv.updateViews();
|
|
49862
|
+
}
|
|
49863
|
+
|
|
49874
49864
|
this.updateUIWithReferenceFrameList();
|
|
49875
49865
|
|
|
49876
49866
|
}
|
|
@@ -50049,23 +50039,19 @@ class Browser {
|
|
|
50049
50039
|
|
|
50050
50040
|
async loadTrackList(configList) {
|
|
50051
50041
|
|
|
50052
|
-
|
|
50053
|
-
|
|
50054
|
-
|
|
50055
|
-
|
|
50056
|
-
}
|
|
50042
|
+
const promises = [];
|
|
50043
|
+
for (let config of configList) {
|
|
50044
|
+
promises.push(this.loadTrack(config));
|
|
50045
|
+
}
|
|
50057
50046
|
|
|
50058
|
-
|
|
50059
|
-
|
|
50060
|
-
|
|
50061
|
-
|
|
50062
|
-
|
|
50063
|
-
|
|
50064
|
-
}
|
|
50065
|
-
return loadedTracks
|
|
50066
|
-
} finally {
|
|
50067
|
-
await this.resize();
|
|
50047
|
+
const loadedTracks = await Promise.all(promises);
|
|
50048
|
+
const groupAutoscaleViews = this.trackViews.filter(function (trackView) {
|
|
50049
|
+
return trackView.track.autoscaleGroup
|
|
50050
|
+
});
|
|
50051
|
+
if (groupAutoscaleViews.length > 0) {
|
|
50052
|
+
this.updateViews();
|
|
50068
50053
|
}
|
|
50054
|
+
return loadedTracks
|
|
50069
50055
|
}
|
|
50070
50056
|
|
|
50071
50057
|
async loadROI(config) {
|
|
@@ -50079,6 +50065,8 @@ class Browser {
|
|
|
50079
50065
|
} else {
|
|
50080
50066
|
this.roi.push(new ROI(config, this.genome));
|
|
50081
50067
|
}
|
|
50068
|
+
// Force reload all views (force = true) to insure ROI features are loaded. Wasteful but this function is
|
|
50069
|
+
// rarely called.
|
|
50082
50070
|
await this.updateViews(true);
|
|
50083
50071
|
}
|
|
50084
50072
|
|
|
@@ -50090,14 +50078,14 @@ class Browser {
|
|
|
50090
50078
|
}
|
|
50091
50079
|
}
|
|
50092
50080
|
for (let tv of this.trackViews) {
|
|
50093
|
-
tv.
|
|
50081
|
+
tv.repaintViews();
|
|
50094
50082
|
}
|
|
50095
50083
|
}
|
|
50096
50084
|
|
|
50097
50085
|
clearROIs() {
|
|
50098
50086
|
this.roi = [];
|
|
50099
50087
|
for (let tv of this.trackViews) {
|
|
50100
|
-
tv.
|
|
50088
|
+
tv.repaintViews();
|
|
50101
50089
|
}
|
|
50102
50090
|
}
|
|
50103
50091
|
|
|
@@ -50109,24 +50097,12 @@ class Browser {
|
|
|
50109
50097
|
/**
|
|
50110
50098
|
* Return a promise to load a track.
|
|
50111
50099
|
*
|
|
50112
|
-
* Each track is associated with the following DOM elements
|
|
50113
|
-
*
|
|
50114
|
-
* leftHandGutter - div on the left for track controls and legend
|
|
50115
|
-
* contentDiv - a div element wrapping all the track content. Height can be > viewportDiv height
|
|
50116
|
-
* viewportDiv - a div element through which the track is viewed. This might have a vertical scrollbar
|
|
50117
|
-
* canvas - canvas element upon which the track is drawn. Child of contentDiv
|
|
50118
|
-
*
|
|
50119
|
-
* The width of all elements should be equal. Height of the viewportDiv is controlled by the user, but never
|
|
50120
|
-
* greater than the contentDiv height. Height of contentDiv and canvas are equal, and governed by the data
|
|
50121
|
-
* loaded.
|
|
50122
|
-
*
|
|
50123
|
-
*
|
|
50124
50100
|
* @param config
|
|
50125
50101
|
* @param doResize - undefined by default
|
|
50126
50102
|
* @returns {*}
|
|
50127
50103
|
*/
|
|
50128
50104
|
|
|
50129
|
-
async loadTrack(config
|
|
50105
|
+
async loadTrack(config) {
|
|
50130
50106
|
|
|
50131
50107
|
|
|
50132
50108
|
// config might be json
|
|
@@ -50194,11 +50170,6 @@ class Browser {
|
|
|
50194
50170
|
}
|
|
50195
50171
|
msg += (": " + config.url);
|
|
50196
50172
|
Alert.presentAlert(new Error(msg), undefined);
|
|
50197
|
-
} finally {
|
|
50198
|
-
// TODO: If loadTrack() is called individually - not via loadTrackList() - call this.resize()
|
|
50199
|
-
if (false === doResize) ; else {
|
|
50200
|
-
await this.resize();
|
|
50201
|
-
}
|
|
50202
50173
|
}
|
|
50203
50174
|
}
|
|
50204
50175
|
|
|
@@ -50422,41 +50393,7 @@ class Browser {
|
|
|
50422
50393
|
this.navbarManager.navbarDidResize(this.$navigation.width(), isWGV);
|
|
50423
50394
|
}
|
|
50424
50395
|
|
|
50425
|
-
await
|
|
50426
|
-
}
|
|
50427
|
-
|
|
50428
|
-
async resize() {
|
|
50429
|
-
|
|
50430
|
-
const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length);
|
|
50431
|
-
|
|
50432
|
-
for (let referenceFrame of this.referenceFrameList) {
|
|
50433
|
-
|
|
50434
|
-
const index = this.referenceFrameList.indexOf(referenceFrame);
|
|
50435
|
-
|
|
50436
|
-
const {chr, genome} = referenceFrame;
|
|
50437
|
-
|
|
50438
|
-
const {bpLength} = genome.getChromosome(referenceFrame.chr);
|
|
50439
|
-
|
|
50440
|
-
const viewportWidthBP = referenceFrame.toBP(viewportWidth);
|
|
50441
|
-
|
|
50442
|
-
// viewportWidthBP > bpLength occurs when locus is full chromosome and user widens browser
|
|
50443
|
-
if (GenomeUtils.isWholeGenomeView(chr) || viewportWidthBP > bpLength) {
|
|
50444
|
-
// console.log(`${ Date.now() } Recalc referenceFrame(${ index }) bpp. viewport ${ StringUtils.numberFormatter(viewportWidthBP) } > ${ StringUtils.numberFormatter(bpLength) }.`)
|
|
50445
|
-
referenceFrame.bpPerPixel = bpLength / viewportWidth;
|
|
50446
|
-
} else {
|
|
50447
|
-
// console.log(`${ Date.now() } Recalc referenceFrame(${ index }) end.`)
|
|
50448
|
-
referenceFrame.end = referenceFrame.start + referenceFrame.toBP(viewportWidth);
|
|
50449
|
-
}
|
|
50450
|
-
|
|
50451
|
-
for (let {viewports} of this.trackViews) {
|
|
50452
|
-
viewports[index].setWidth(viewportWidth);
|
|
50453
|
-
}
|
|
50454
|
-
|
|
50455
|
-
}
|
|
50456
|
-
|
|
50457
|
-
await this.updateViews(true);
|
|
50458
|
-
|
|
50459
|
-
this.updateUIWithReferenceFrameList();
|
|
50396
|
+
await resize.call(this);
|
|
50460
50397
|
}
|
|
50461
50398
|
|
|
50462
50399
|
async updateViews(force) {
|
|
@@ -50532,6 +50469,12 @@ class Browser {
|
|
|
50532
50469
|
|
|
50533
50470
|
}
|
|
50534
50471
|
|
|
50472
|
+
repaintViews() {
|
|
50473
|
+
for (let trackView of this.trackViews) {
|
|
50474
|
+
trackView.repaintViews();
|
|
50475
|
+
}
|
|
50476
|
+
}
|
|
50477
|
+
|
|
50535
50478
|
updateLocusSearchWidget() {
|
|
50536
50479
|
|
|
50537
50480
|
const referenceFrameList = this.referenceFrameList;
|
|
@@ -50633,12 +50576,56 @@ class Browser {
|
|
|
50633
50576
|
const viewport = createViewport(trackView, viewportColumn, referenceFrameRight);
|
|
50634
50577
|
trackView.viewports.splice(indexRight, 0, viewport);
|
|
50635
50578
|
}
|
|
50579
|
+
}
|
|
50580
|
+
|
|
50581
|
+
this.centerLineList = this.createCenterLineList(this.columnContainer);
|
|
50582
|
+
|
|
50583
|
+
await resize.call(this);
|
|
50584
|
+
}
|
|
50585
|
+
|
|
50586
|
+
/**
|
|
50587
|
+
* Add a new multi-locus panel for the specified region
|
|
50588
|
+
* @param chr
|
|
50589
|
+
* @param start
|
|
50590
|
+
* @param end
|
|
50591
|
+
* @param referenceFrameLeft - optional, if supplied new panel should be placed to the immediate right
|
|
50592
|
+
*/
|
|
50593
|
+
async addMultiLocusPanel(chr, start, end, referenceFrameLeft) {
|
|
50594
|
+
|
|
50595
|
+
// account for reduced viewport width as a result of adding right mate pair panel
|
|
50596
|
+
const viewportWidth = this.calculateViewportWidth(1 + this.referenceFrameList.length);
|
|
50597
|
+
const scaleFactor = this.calculateViewportWidth(this.referenceFrameList.length) / this.calculateViewportWidth(1 + this.referenceFrameList.length);
|
|
50598
|
+
for (let refFrame of this.referenceFrameList) {
|
|
50599
|
+
refFrame.bpPerPixel *= scaleFactor;
|
|
50600
|
+
}
|
|
50601
|
+
|
|
50602
|
+
const bpp = (end - start) / viewportWidth;
|
|
50603
|
+
const newReferenceFrame = new ReferenceFrame(this.genome, chr, start, end, bpp);
|
|
50604
|
+
const indexLeft = referenceFrameLeft ? this.referenceFrameList.indexOf(referenceFrameLeft) : this.referenceFrameList.length - 1;
|
|
50605
|
+
const indexRight = 1 + indexLeft;
|
|
50636
50606
|
|
|
50607
|
+
// TODO -- this is really ugly
|
|
50608
|
+
const {$viewport} = this.trackViews[0].viewports[indexLeft];
|
|
50609
|
+
const viewportColumn = viewportColumnManager.insertAfter($viewport.get(0).parentElement);
|
|
50610
|
+
|
|
50611
|
+
if (indexRight === this.referenceFrameList.length) {
|
|
50612
|
+
this.referenceFrameList.push(newReferenceFrame);
|
|
50613
|
+
for (let trackView of this.trackViews) {
|
|
50614
|
+
const viewport = createViewport(trackView, viewportColumn, newReferenceFrame);
|
|
50615
|
+
trackView.viewports.push(viewport);
|
|
50616
|
+
}
|
|
50617
|
+
} else {
|
|
50618
|
+
this.referenceFrameList.splice(indexRight, 0, newReferenceFrame);
|
|
50619
|
+
for (let trackView of this.trackViews) {
|
|
50620
|
+
const viewport = createViewport(trackView, viewportColumn, newReferenceFrame);
|
|
50621
|
+
trackView.viewports.splice(indexRight, 0, viewport);
|
|
50622
|
+
}
|
|
50637
50623
|
}
|
|
50638
50624
|
|
|
50625
|
+
|
|
50639
50626
|
this.centerLineList = this.createCenterLineList(this.columnContainer);
|
|
50640
50627
|
|
|
50641
|
-
|
|
50628
|
+
resize.call(this);
|
|
50642
50629
|
}
|
|
50643
50630
|
|
|
50644
50631
|
async removeMultiLocusPanel(referenceFrame) {
|
|
@@ -50667,7 +50654,13 @@ class Browser {
|
|
|
50667
50654
|
|
|
50668
50655
|
}
|
|
50669
50656
|
|
|
50670
|
-
|
|
50657
|
+
/**
|
|
50658
|
+
* Goto the locus represented by the selected referenceFrame, discarding all other panels
|
|
50659
|
+
*
|
|
50660
|
+
* @param referenceFrame
|
|
50661
|
+
* @returns {Promise<void>}
|
|
50662
|
+
*/
|
|
50663
|
+
async gotoMultilocusPanel(referenceFrame) {
|
|
50671
50664
|
|
|
50672
50665
|
const referenceFrameIndex = this.referenceFrameList.indexOf(referenceFrame);
|
|
50673
50666
|
|
|
@@ -50721,7 +50714,7 @@ class Browser {
|
|
|
50721
50714
|
|
|
50722
50715
|
this.updateUIWithReferenceFrameList();
|
|
50723
50716
|
|
|
50724
|
-
await this.updateViews(
|
|
50717
|
+
await this.updateViews();
|
|
50725
50718
|
|
|
50726
50719
|
}
|
|
50727
50720
|
|
|
@@ -50944,7 +50937,6 @@ class Browser {
|
|
|
50944
50937
|
}
|
|
50945
50938
|
|
|
50946
50939
|
|
|
50947
|
-
|
|
50948
50940
|
json["tracks"] = trackJson;
|
|
50949
50941
|
|
|
50950
50942
|
return json // This is an object, not a json string
|
|
@@ -50963,14 +50955,9 @@ class Browser {
|
|
|
50963
50955
|
return surl
|
|
50964
50956
|
}
|
|
50965
50957
|
|
|
50966
|
-
|
|
50967
|
-
const loci = [];
|
|
50958
|
+
currentReferenceFrames() {
|
|
50968
50959
|
const anyTrackView = this.trackViews[0];
|
|
50969
|
-
|
|
50970
|
-
const locusString = referenceFrame.getLocusString();
|
|
50971
|
-
loci.push(locusString);
|
|
50972
|
-
}
|
|
50973
|
-
return loci
|
|
50960
|
+
return anyTrackView.viewports.map(vp => vp.referenceFrame)
|
|
50974
50961
|
}
|
|
50975
50962
|
|
|
50976
50963
|
/**
|
|
@@ -51090,12 +51077,9 @@ class Browser {
|
|
|
51090
51077
|
}
|
|
51091
51078
|
|
|
51092
51079
|
addWindowResizeHandler() {
|
|
51093
|
-
this.
|
|
51080
|
+
// Create a copy of the prototype "resize" function bound to this instance. Neccessary to support removing.
|
|
51081
|
+
this.boundWindowResizeHandler = resize.bind(this);
|
|
51094
51082
|
window.addEventListener('resize', this.boundWindowResizeHandler);
|
|
51095
|
-
|
|
51096
|
-
function windowResizeHandler() {
|
|
51097
|
-
this.resize();
|
|
51098
|
-
}
|
|
51099
51083
|
}
|
|
51100
51084
|
|
|
51101
51085
|
removeWindowResizeHandler() {
|
|
@@ -51194,6 +51178,48 @@ class Browser {
|
|
|
51194
51178
|
}
|
|
51195
51179
|
}
|
|
51196
51180
|
|
|
51181
|
+
/**
|
|
51182
|
+
* Function called win window is resized, or visibility changed (e.g. "show" from a tab). This is a function rather
|
|
51183
|
+
* than class method because it needs to be copied and bound to specific instances of browser to support listener
|
|
51184
|
+
* removal
|
|
51185
|
+
*
|
|
51186
|
+
* @returns {Promise<void>}
|
|
51187
|
+
*/
|
|
51188
|
+
async function resize() {
|
|
51189
|
+
|
|
51190
|
+
const viewportWidth = this.calculateViewportWidth(this.referenceFrameList.length);
|
|
51191
|
+
|
|
51192
|
+
for (let referenceFrame of this.referenceFrameList) {
|
|
51193
|
+
|
|
51194
|
+
const index = this.referenceFrameList.indexOf(referenceFrame);
|
|
51195
|
+
|
|
51196
|
+
const {chr, genome} = referenceFrame;
|
|
51197
|
+
|
|
51198
|
+
const {bpLength} = genome.getChromosome(referenceFrame.chr);
|
|
51199
|
+
|
|
51200
|
+
const viewportWidthBP = referenceFrame.toBP(viewportWidth);
|
|
51201
|
+
|
|
51202
|
+
// viewportWidthBP > bpLength occurs when locus is full chromosome and user widens browser
|
|
51203
|
+
if (GenomeUtils.isWholeGenomeView(chr) || viewportWidthBP > bpLength) {
|
|
51204
|
+
// console.log(`${ Date.now() } Recalc referenceFrame(${ index }) bpp. viewport ${ StringUtils.numberFormatter(viewportWidthBP) } > ${ StringUtils.numberFormatter(bpLength) }.`)
|
|
51205
|
+
referenceFrame.bpPerPixel = bpLength / viewportWidth;
|
|
51206
|
+
} else {
|
|
51207
|
+
// console.log(`${ Date.now() } Recalc referenceFrame(${ index }) end.`)
|
|
51208
|
+
referenceFrame.end = referenceFrame.start + referenceFrame.toBP(viewportWidth);
|
|
51209
|
+
}
|
|
51210
|
+
|
|
51211
|
+
for (let {viewports} of this.trackViews) {
|
|
51212
|
+
viewports[index].setWidth(viewportWidth);
|
|
51213
|
+
}
|
|
51214
|
+
|
|
51215
|
+
}
|
|
51216
|
+
|
|
51217
|
+
this.updateUIWithReferenceFrameList();
|
|
51218
|
+
|
|
51219
|
+
await this.updateViews(true);
|
|
51220
|
+
}
|
|
51221
|
+
|
|
51222
|
+
|
|
51197
51223
|
function handleMouseMove(e) {
|
|
51198
51224
|
|
|
51199
51225
|
e.preventDefault();
|