diff --git a/src/App.js b/src/App.js index bef720aa..226900cb 100644 --- a/src/App.js +++ b/src/App.js @@ -41,7 +41,6 @@ const stringToColourSave = function (colorKey) { }; class App extends Component { - layerRef = React.createRef(); layerRef2 = React.createRef(null); constructor(props) { @@ -66,6 +65,17 @@ class App extends Component { "useVerticalCompression", this.recalcY.bind(this) ); + observe( + this.props.store, + "useWidthCompression", + this.recalcXLayout.bind(this) + ); + observe(this.props.store, "useConnector", this.recalcXLayout.bind(this)); + observe( + this.props.store, + "binScalingFactor", + this.recalcXLayout.bind(this) + ); observe(this.props.store, "pixelsPerColumn", this.recalcXLayout.bind(this)); observe(this.props.store.chunkURLs, this.nextChunk.bind(this)); // this.nextChunk(); @@ -122,7 +132,9 @@ class App extends Component { (component) => component.arrivals.length + (component.departures.length - 1) + - (component.lastBin - component.firstBin) + + (this.props.store.useWidthCompression + ? this.props.store.binScalingFactor + : component.lastBin - component.firstBin) + 1 ) .reduce(sum, 0); @@ -138,6 +150,8 @@ class App extends Component { this.schematic.components, this.props.store.pixelsPerColumn, this.props.store.topOffset, + this.props.store.useWidthCompression, + this.props.store.binScalingFactor, this.leftXStart.bind(this) ); this.distanceSortedLinks = links; @@ -218,10 +232,13 @@ class App extends Component { leftXStart(schematizeComponent, i, firstDepartureColumn, j) { /* Return the x coordinate pixel that starts the LinkColumn at i, j*/ - let previousColumns = - schematizeComponent.firstBin - - this.props.store.getBeginBin() + - schematizeComponent.offset; + let previousColumns = !this.props.store.useWidthCompression + ? schematizeComponent.firstBin - + this.props.store.getBeginBin() + + schematizeComponent.offset + : schematizeComponent.offset + + (schematizeComponent.index - this.schematic.components[0].index) * + this.props.store.binScalingFactor; let pixelsFromColumns = (previousColumns + firstDepartureColumn + j) * this.props.store.pixelsPerColumn; @@ -237,7 +254,10 @@ class App extends Component { key={i} height={this.visibleHeight()} width={ - schematizeComponent.firstDepartureColumn() + + schematizeComponent.arrivals.length + + (this.props.store.useWidthCompression + ? this.props.store.binScalingFactor + : schematizeComponent.num_bin) + (schematizeComponent.departures.length - 1) } compressed_row_mapping={this.compressed_row_mapping} @@ -254,7 +274,11 @@ class App extends Component { ); })} {schematizeComponent.departures.slice(0, -1).map((linkColumn, j) => { - let leftPad = schematizeComponent.firstDepartureColumn(); + let leftPad = + schematizeComponent.arrivals.length + + (this.props.store.useWidthCompression + ? this.props.store.binScalingFactor + : schematizeComponent.num_bin); return this.renderLinkColumn( schematizeComponent, i, diff --git a/src/ComponentRect.js b/src/ComponentRect.js index fa3ce897..67663d14 100644 --- a/src/ComponentRect.js +++ b/src/ComponentRect.js @@ -140,7 +140,12 @@ class ComponentRect extends React.Component { // x is the (num_bins + num_arrivals + num_departures)*pixelsPerColumn const x_val = component.x + - (component.firstDepartureColumn() + component.departures.length - 1) * + (component.arrivals.length + + (this.props.store.useWidthCompression + ? this.props.store.binScalingFactor + : component.num_bin) + + component.departures.length - + 1) * this.props.store.pixelsPerColumn; let this_y = count; if (!this.props.store.useVerticalCompression) { @@ -169,8 +174,8 @@ class ComponentRect extends React.Component { fill={this.state.color} onClick={this.handleClick} > - {this.renderMatrix()} - {this.renderAllConnectors()} + {!this.props.store.useWidthCompression ? this.renderMatrix() : null} + {this.props.store.useConnector ? this.renderAllConnectors() : null} ); } diff --git a/src/ControlHeader.js b/src/ControlHeader.js index 77e8ba46..37b6a31c 100644 --- a/src/ControlHeader.js +++ b/src/ControlHeader.js @@ -156,8 +156,39 @@ class ControlHeader extends React.Component { {" "} Use Vertical Compression: - + + + {" "} + Use Width Compression: + + + {this.props.store.useWidthCompression ? ( + + + {" "} + Render Connectors: + + + + {" "} + Component Width Scaling Factor: + + {() => ( + + )} + + + + ) : ( + <> + )} {" "} Row Height: @@ -190,21 +221,64 @@ ControlHeader.propTypes = { store: PropTypes.object, }; -class CompressedViewSwitch extends React.Component { +class VerticalCompressedViewSwitch extends React.Component { + render() { + return ( + + {() => ( + + )} + + ); + } +} + +VerticalCompressedViewSwitch.propTypes = { + store: PropTypes.object, +}; + +class RenderConnectorSwitch extends React.Component { render() { return ( - {() => this.props.store.useVerticalCompression} - } - onChange={this.props.store.toggleUseVerticalCompression} - /> + + {() => ( + + )} + + ); + } +} + +RenderConnectorSwitch.propTypes = { + store: PropTypes.object, +}; + +class WidthCompressedViewSwitch extends React.Component { + render() { + return ( + + {() => ( + + )} + ); } } -CompressedViewSwitch.propTypes = { +WidthCompressedViewSwitch.propTypes = { store: PropTypes.object, }; + export default ControlHeader; diff --git a/src/LinkRecord.js b/src/LinkRecord.js index 6d65ab24..ee18ea52 100644 --- a/src/LinkRecord.js +++ b/src/LinkRecord.js @@ -18,6 +18,8 @@ export function calculateLinkCoordinates( schematic, pixelsPerColumn, topOffset, + useWidthCompression, + binScalingFactor, leftXStart ) { //leftXStart is necessary as a method at the moment @@ -57,7 +59,10 @@ export function calculateLinkCoordinates( let xCoordDeparture = leftXStart( schematizeComponent, i, - schematizeComponent.firstDepartureColumn(), + schematizeComponent.arrivals.length + + (useWidthCompression + ? binScalingFactor + : schematizeComponent.num_bin), k ); let paddedKey = departure.key; diff --git a/src/PangenomeSchematic.js b/src/PangenomeSchematic.js index 7ceaf2da..04c76a8e 100644 --- a/src/PangenomeSchematic.js +++ b/src/PangenomeSchematic.js @@ -69,10 +69,10 @@ class PangenomeSchematic extends React.Component { return fetch(indexPath) .then((res) => res.json()) .then((json) => { - if (!this.props.store.getChunkURLs()[0]) { + if (!this.props.store.getChunkURLs()[0]) { // Initial state this.props.store.switchChunkURLs( - `${process.env.PUBLIC_URL}test_data/${this.props.store.jsonName}/${json["files"][0]["file"]}`, + `${process.env.PUBLIC_URL}test_data/${this.props.store.jsonName}/${json["files"][0]["file"]}`, `${process.env.PUBLIC_URL}test_data/${this.props.store.jsonName}/${json["files"][1]["file"]}` ); } @@ -94,7 +94,10 @@ class PangenomeSchematic extends React.Component { this.pathNames = this.jsonData.path_names; this.jsonData.mid_bin = data.last_bin; //placeholder let lastChunkURLIndex = this.props.store.chunkURLs.length - 1; - if (this.props.store.getChunkURLs()[0] === this.props.store.getChunkURLs()[lastChunkURLIndex]) { + if ( + this.props.store.getChunkURLs()[0] === + this.props.store.getChunkURLs()[lastChunkURLIndex] + ) { this.processArray(); } else { this.jsonFetch(this.props.store.getChunkURLs()[lastChunkURLIndex]).then( @@ -146,9 +149,9 @@ class PangenomeSchematic extends React.Component { } else { var componentArray = []; var offsetLength = 0; - for (var component of this.jsonData.components) { + for (let [index, component] of this.jsonData.components.entries()) { if (component.last_bin >= beginBin) { - var componentItem = new Component(component, offsetLength); + var componentItem = new Component(component, offsetLength, index); offsetLength += componentItem.arrivals.length + componentItem.departures.length - 1; componentArray.push(componentItem); @@ -169,8 +172,9 @@ class PangenomeSchematic extends React.Component { } class Component { - constructor(component, offsetLength) { + constructor(component, offsetLength, index) { this.offset = offsetLength; + this.index = index; this.firstBin = component.first_bin; this.lastBin = component.last_bin; this.arrivals = []; @@ -189,9 +193,6 @@ class Component { this.matrix = Array.from(component.matrix); this.num_bin = this.lastBin - this.firstBin + 1; } - firstDepartureColumn() { - return this.num_bin + this.arrivals.length; - } } class LinkColumn { diff --git a/src/ViewportInputsStore.js b/src/ViewportInputsStore.js index e64a0c67..ec6b369a 100644 --- a/src/ViewportInputsStore.js +++ b/src/ViewportInputsStore.js @@ -1,9 +1,8 @@ import { types } from "mobx-state-tree"; import { urlExists } from "./URL"; - const BeginEndBin = types.optional(types.array(types.integer), [1, 40]); -const ChunkURLs = types.optional(types.array(types.string), ['', '']); +const ChunkURLs = types.optional(types.array(types.string), ["", ""]); const PathNucPos = types.model("PathNucPos", { path: types.string, @@ -14,6 +13,9 @@ export let RootStore; RootStore = types .model({ useVerticalCompression: false, + useWidthCompression: false, + binScalingFactor: 3, + useConnector: true, beginEndBin: BeginEndBin, pixelsPerColumn: 7, pixelsPerRow: 7, @@ -55,6 +57,10 @@ RootStore = types self.topOffset = newTopOffset; } } + function updateBinScalingFactor(event) { + let newFactor = event.target.value; + self.binScalingFactor = Math.max(1, Number(newFactor)); + } function updateHighlightedLink(linkRect) { self.highlightedLink = linkRect; } @@ -73,6 +79,12 @@ RootStore = types function toggleUseVerticalCompression() { self.useVerticalCompression = !self.useVerticalCompression; } + function toggleUseWidthCompression() { + self.useWidthCompression = !self.useWidthCompression; + } + function toggleUseConnector() { + self.useConnector = !self.useConnector; + } function updateHeight(event) { self.pixelsPerRow = Math.max(1, Number(event.target.value)); } @@ -89,7 +101,7 @@ RootStore = types self.jsonName = event.target.value; } } - function switchChunkURLs(startFile, endFile){ + function switchChunkURLs(startFile, endFile) { self.chunkURLs = [startFile, endFile]; } function getChunkURLs() { @@ -134,7 +146,10 @@ RootStore = types updateMaxHeight, resetRenderStats, updateCellTooltipContent, + updateBinScalingFactor, toggleUseVerticalCompression, + toggleUseWidthCompression, + toggleUseConnector, updateHeight, updateWidth, tryJSONpath,