UNPKG

@rcsb/rcsb-saguaro

Version:
245 lines (244 loc) 10.1 kB
import { RcsbBoard } from '../../RcsbBoard/RcsbBoard'; import { RcsbFvDefaultConfigValues } from '../RcsbFvConfig/RcsbFvDefaultConfigValues'; import { RcsbFvDisplay } from "./RcsbFvDisplay"; import { RcsbFvConfig } from "../RcsbFvConfig/RcsbFvConfig"; import { RcsbFvTrackData, RcsbDataManager, RcsbFvTrackDataMap } from "../../RcsbDataManager/RcsbDataManager"; import { EventType } from "../RcsbFvContextManager/RcsbFvContextManager"; /**This className provides an abstraction layer to build and manage a particular board annotation cell*/ export class RcsbFvTrack { constructor(args, xScale, selection, contextManager) { /**Board annotation cells may contain different tracks to avoid visual overlapping*/ this.rcsbTrackArray = new Array(); this.contextManager = contextManager; this.xScale = xScale; this.selection = selection; if (typeof args.elementId === "string" && document.getElementById(args.elementId) != null) { this.rcsbBoard = new RcsbBoard(args.elementId, xScale, this.selection, this.contextManager); } this.buildTrack(args); this.subscription = this.subscribe(); this.rcsbBoard.highlightRegion(null, "set", "select", true); } /**Builds the board annotation cell * @param args Board track configuration object * */ buildTrack(args) { this.setConfig(args); if (typeof this.rcsbFvConfig.elementId === "string") { this.init(this.rcsbFvConfig.elementId); } if (typeof this.rcsbFvConfig.trackData != "undefined" && this.rcsbFvConfig.displayType != "composite" /* RcsbFvDisplayTypes.COMPOSITE */) { this.load(this.rcsbFvConfig.trackData); } else if (this.rcsbFvConfig.displayType === "composite" /* RcsbFvDisplayTypes.COMPOSITE */) { const data = this.collectCompositeData(); if (data != null) { this.load(data); } } else { this.buildRcsbTrack(); } this.start(); } /**Start rendering the board track annotation cell * @param elementId DOM element Id * */ init(elementId) { if (document.getElementById(elementId) != null) { this.elementId = elementId; if (this.rcsbBoard === null) { this.rcsbBoard = new RcsbBoard(this.elementId, this.xScale, this.selection, this.contextManager); } if (this.rcsbFvConfig.configCheck()) { this.initRcsbBoard(); } else { throw "Board length is not defined"; } } else { throw "HTML element " + elementId + " not found"; } } /**Replaces the track configuration * @param args Board row configuration object * */ setConfig(args) { if (this.rcsbFvConfig == null) { this.rcsbFvConfig = new RcsbFvConfig(args); } else { this.rcsbFvConfig.updateConfig(args); } } /**Sets parameters for the SVG/HTML level object manager*/ initRcsbBoard() { if (typeof this.rcsbFvConfig.elementClickCallback === "function") this.rcsbBoard.setElementClickCallback(this.rcsbFvConfig.elementClickCallback); if (this.rcsbFvConfig.highlightHoverPosition === true) { this.rcsbBoard.setHighlightHoverPosition(); } if (this.rcsbFvConfig.highlightHoverElement === true) { this.rcsbBoard.setHighlightHoverElement(true); } if (typeof this.rcsbFvConfig.highlightHoverCallback === "function") { this.rcsbBoard.addHoverCallback(this.rcsbFvConfig.highlightHoverCallback); } if (typeof this.rcsbFvConfig.trackWidth === "number") this.rcsbBoard.setBoardWidth(this.rcsbFvConfig.trackWidth); if (typeof this.rcsbFvConfig.range === "object") this.rcsbBoard.setRange(this.rcsbFvConfig.range.min - RcsbFvDefaultConfigValues.increasedView, this.rcsbFvConfig.range.max + RcsbFvDefaultConfigValues.increasedView); else if (typeof this.rcsbFvConfig.length === "number") this.rcsbBoard.setRange(1 - RcsbFvDefaultConfigValues.increasedView, this.rcsbFvConfig.length + RcsbFvDefaultConfigValues.increasedView); } /**Build an inner track within a board track annotation cell * @return Inner track display object * */ buildRcsbTrack() { this.rcsbFvDisplay = new RcsbFvDisplay(this.rcsbFvConfig); const rcsbTrack = this.rcsbFvDisplay.initDisplay(); rcsbTrack.height(this.rcsbFvConfig.trackHeight); rcsbTrack.trackColor(this.rcsbFvConfig.trackColor); this.rcsbTrackArray.push(rcsbTrack); return rcsbTrack; } /**Transforms data of composite displays * @return Array of annotation objects * */ collectCompositeData() { var _a; const data = new Array(); if (((_a = this.rcsbFvConfig) === null || _a === void 0 ? void 0 : _a.displayConfig) != undefined) { for (let displayItem of this.rcsbFvConfig.displayConfig) { if (typeof displayItem.displayData != "undefined") { data.push(displayItem.displayData); } } if (data.length == this.rcsbFvConfig.displayConfig.length) { return data; } } return null; } /**Class inner function that transform annotation data for composite or single displays * @param trackData array of annotation objects * */ load(trackData) { var _a; if (this.rcsbFvConfig.displayType === "composite" /* RcsbFvDisplayTypes.COMPOSITE */ && Array.isArray(trackData)) { const trackNonOverlappingMap = new Array(); let maxTracks = 1; trackData.forEach((f, i) => { if (!this.rcsbFvConfig.overlap) { const nonOverlapping = RcsbDataManager.getNonOverlappingData(f); trackNonOverlappingMap.push(nonOverlapping); if (nonOverlapping.length > maxTracks) maxTracks = nonOverlapping.length; } else { trackNonOverlappingMap.push([f]); } }); for (let i = 0; i < maxTracks; i++) { const rcsbCompositeTrack = this.buildRcsbTrack(); if (((_a = this.rcsbFvConfig) === null || _a === void 0 ? void 0 : _a.trackHeight) != undefined) rcsbCompositeTrack.setCompositeHeight(i * this.rcsbFvConfig.trackHeight); const displayIds = this.rcsbFvDisplay.getDisplayIds(); const trackDataMap = new RcsbFvTrackDataMap(); trackNonOverlappingMap.forEach((v, j) => { const id = displayIds[j]; if (i < v.length) trackDataMap.set(id, v[i]); else trackDataMap.set(id, []); }); rcsbCompositeTrack.data(trackDataMap); } } else if (trackData instanceof RcsbFvTrackData) { let nonOverlapping; if (!this.rcsbFvConfig.overlap) { nonOverlapping = RcsbDataManager.getNonOverlappingData(trackData); } else { nonOverlapping = [trackData]; } nonOverlapping.forEach(trackData => { this.buildRcsbTrack().data(trackData); }); } else { throw new Error("Data loader error. Data type not supported."); } } /**Add all inner track to the SVG/HTML level manager and start rendering*/ start() { this.rcsbTrackArray.forEach(track => { this.rcsbBoard.addTrack(track); }); this.rcsbBoard.startBoard(); } /**Subscribe function to handle events and communicate all board track annotations cell panels * @return Subscription object * */ subscribe() { return this.contextManager.subscribe((obj) => { if (obj.eventType === EventType.SCALE) { this.setScale(obj.eventData); } else if (obj.eventType === EventType.SELECTION) { this.setSelection(obj.eventData); } else if (obj.eventType === EventType.RESET) { this.reset(obj.eventData); } }); } /**Unsubscribe all functions * */ unsubscribe() { this.subscription.unsubscribe(); this.rcsbBoard.removeScrollEvent(); } /**Modify d3 x-scale * @param boardId Id of the SVG/HTML manager that triggered the event * */ setScale(boardId) { this.rcsbBoard.setScale(boardId); } /**Highlights the region(s) defined by the attribute selection * @param selection object describing sequence regions * */ setSelection(selection) { this.rcsbBoard.setSelection(selection.trackId, selection.mode); } /**Reset the cell content * @param trackId Event reset object interface * */ reset(trackId) { if (this.rcsbFvConfig.trackId === trackId) { this._reset(); } } /**Reset all inner tracks*/ _reset() { this.rcsbTrackArray = new Array(); this.rcsbBoard.reset(); } /**Calculate height as function of the number of inner tracks * @return Board track annotation cell height * */ getTrackHeight() { var _a, _b; if (this.rcsbTrackArray.length > 0 && ((_a = this.rcsbFvConfig) === null || _a === void 0 ? void 0 : _a.trackHeight) != undefined) { return this.rcsbTrackArray.length * this.rcsbFvConfig.trackHeight; } else if (((_b = this.rcsbFvConfig) === null || _b === void 0 ? void 0 : _b.trackHeight) != undefined) { return this.rcsbFvConfig.trackHeight; } else { return null; } } }