Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cypress/e2e/figures.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe("Figure", function() {
data["type_"] = "parallelplot";
const parallelPlot = Figure.fromMultiplot(data, canvas.width, canvas.height, canvasID);

scatter.sendRubberBandsMultiplot([scatter2, parallelPlot]);
// scatter.sendRubberBandsMultiplot([scatter2, parallelPlot]);

expect(scatter2.axes[0].rubberBand, "scatter2.axes[0].rubberBand").to.not.deep.equal(scatter.axes[1].rubberBand);
expect(scatter2.axes[1].rubberBand, "scatter2.axes[1].rubberBand").to.not.deep.equal(scatter.axes[0].rubberBand);
Expand Down Expand Up @@ -121,7 +121,7 @@ describe("Figure", function() {
[scatter.axes[0].name, scatter.axes[0].rubberBand],
[scatter.axes[1].name, scatter.axes[1].rubberBand]
]);
scatter.initRubberBandMultiplot(multiplotRubberBands);
// scatter.initRubberBandMultiplot(multiplotRubberBands);

scatter.axes.forEach(axis => {
expect(multiplotRubberBands.get(axis.name).minValue, `empty rubberband ${axis.name}.minValue`).to.deep.equal(referenceRubberBands.get(axis.name).minValue);
Expand All @@ -132,7 +132,7 @@ describe("Figure", function() {
scatter.axes[0].rubberBand.maxValue = 4;
scatter.axes[1].rubberBand.minValue = 2;
scatter.axes[1].rubberBand.maxValue = 5;
scatter.updateRubberBandMultiplot(multiplotRubberBands);
// scatter.updateRubberBandMultiplot(multiplotRubberBands);
scatter.axes.forEach(axis => {
expect(multiplotRubberBands.get(axis.name).minValue, `edited rubberband ${axis.name}.minValue`).to.deep.equal(referenceRubberBands.get(axis.name).minValue);
expect(multiplotRubberBands.get(axis.name).maxValue, `edited rubberband ${axis.name}.minValue`).to.deep.equal(referenceRubberBands.get(axis.name).maxValue);
Expand Down
28 changes: 21 additions & 7 deletions src/axes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Vertex, Shape } from "./baseShape"
import { Rect, Point } from "./primitives"
import { TextParams, Text, RubberBand } from "./shapes"
import { EventEmitter } from "events"
import { onAxisSelection, rubberbandsChange } from "./interactions"
import { filter, withLatestFrom } from "rxjs"

export class TitleSettings {
constructor(
Expand Down Expand Up @@ -76,6 +78,22 @@ export class Axis extends Shape {
this.updateOffsetTicks();
this.offsetTitle = 0;
this.title = new Text(this.titleText, new Vertex(0, 0), {});

onAxisSelection.pipe(
filter((axis) => this.name !== "number" && this.name === axis.name),
withLatestFrom(rubberbandsChange)
).subscribe(([axis, rubberbands]) => {
let rubberband = rubberbands.get(this.name);
if (!rubberband) {
rubberband = new RubberBand(axis.name, axis.rubberBand.minValue, axis.rubberBand.maxValue, this.isVertical)
} else {
rubberband.minValue = axis.rubberBand.minValue;
rubberband.maxValue = axis.rubberBand.maxValue;
}
rubberbands.set(axis.name, rubberband)
this.rubberBand.minValue = rubberband.minValue;
this.rubberBand.maxValue = rubberband.maxValue;
})
};

public get drawLength(): number {
Expand Down Expand Up @@ -233,10 +251,6 @@ export class Axis extends Shape {
this.rubberBand.defaultStyle();
}

public sendRubberBand(rubberBands: Map<string, RubberBand>) { this.rubberBand.selfSend(rubberBands) }

public sendRubberBandRange(rubberBands: Map<string, RubberBand>) { this.rubberBand.selfSendRange(rubberBands) }

private static nearestFive(value: number): number {
const tenPower = Math.floor(Math.log10(Math.abs(value)));
const normedValue = Math.floor(value / Math.pow(10, tenPower - 2));
Expand Down Expand Up @@ -621,7 +635,7 @@ export class Axis extends Shape {
this.updateRubberBand();
context.setTransform(canvasMatrix);
this.rubberBand.draw(context);
if (this.rubberBand.isClicked) this.emitter.emit("rubberBandChange", this.rubberBand);
if (this.rubberBand.isClicked) onAxisSelection.next(this);
}

protected mouseTranslate(mouseDown: Vertex, mouseCoords: Vertex): void { }
Expand All @@ -639,7 +653,7 @@ export class Axis extends Shape {
private clickOnArrow(mouseDown: Vertex): void {
this.is_drawing_rubberband = true; // OLD
this.rubberBand.isHovered ? this.rubberBand.mouseDown(mouseDown) : this.rubberBand.reset();
this.emitter.emit("rubberBandChange", this.rubberBand);
onAxisSelection.next(this);
}

private clickOnDrawnPath(mouseDown: Vertex): void {
Expand Down Expand Up @@ -676,7 +690,7 @@ export class Axis extends Shape {
this.title.mouseUp(false);
this.title.isClicked = false;
this.rubberBand.mouseUp(keepState);
if (this.is_drawing_rubberband) this.emitter.emit("rubberBandChange", this.rubberBand);
if (this.is_drawing_rubberband) onAxisSelection.next(this);
this.is_drawing_rubberband = false;
}

Expand Down
72 changes: 7 additions & 65 deletions src/figures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { colorHsl } from "./colors"
import { PointStyle } from "./styles"
import { Vertex, Shape } from "./baseShape"
import { Rect, Point, LineSequence } from "./primitives"
import { ScatterPoint, Bar, RubberBand, SelectionBox } from "./shapes"
import { ScatterPoint, Bar, SelectionBox } from "./shapes"
import { Axis, ParallelAxis } from "./axes"
import { ShapeCollection, GroupCollection, PointSet } from "./collections"
import { RemoteFigure } from "./remoteFigure"
import { DataInterface } from "./dataInterfaces"
import { HighlightData } from "./interactions"
import { HighlightData, onAxisSelection } from "./interactions"

export class Figure extends RemoteFigure {
constructor(
Expand Down Expand Up @@ -67,32 +67,6 @@ export class Figure extends RemoteFigure {
}

public receivePointSets(pointSets: PointSet[]): void { this.pointSets = pointSets }

public initRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {
this.axes.forEach(axis => axis.sendRubberBand(multiplotRubberBands));
}

public updateRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {
this.axes.forEach(axis => axis.sendRubberBandRange(multiplotRubberBands));
}

public sendRubberBandsMultiplot(figures: Figure[]): void {
figures.forEach(figure => figure.receiveRubberBandFromFigure(this));
}

protected sendRubberBandsInFigure(figure: Figure): void {
figure.axes.forEach(otherAxis => {
this.axes.forEach(thisAxis => {
if (thisAxis.name == otherAxis.name && thisAxis.name != "number") {
otherAxis.rubberBand.minValue = thisAxis.rubberBand.minValue;
otherAxis.rubberBand.maxValue = thisAxis.rubberBand.maxValue;
otherAxis.emitter.emit("rubberBandChange", otherAxis.rubberBand);
}
})
})
}

protected receiveRubberBandFromFigure(figure: Figure): void { figure.sendRubberBandsInFigure(this) }
}

export class Frame extends Figure {
Expand Down Expand Up @@ -222,6 +196,8 @@ export class Frame extends Figure {
this.axes[1].rubberBand.minValue = Math.min(frameDown.y, frameMouse.y);
this.axes[0].rubberBand.maxValue = Math.max(frameDown.x, frameMouse.x);
this.axes[1].rubberBand.maxValue = Math.max(frameDown.y, frameMouse.y);
onAxisSelection.next(this.axes[0]);
onAxisSelection.next(this.axes[1]);
super.updateSelectionBox(...this.rubberBandsCorners);
}

Expand All @@ -235,9 +211,9 @@ export class Frame extends Figure {
return [new Vertex(this.axes[0].rubberBand.minValue, this.axes[1].rubberBand.minValue), new Vertex(this.axes[0].rubberBand.maxValue, this.axes[1].rubberBand.maxValue)]
}

public activateSelection(emittedRubberBand: RubberBand, index: number): void {
super.activateSelection(emittedRubberBand, index)
this.selectionBox.rubberBandUpdate(emittedRubberBand, ["x", "y"][index]);
public activateSelection(axis: Axis): void {
super.activateSelection(axis)
this.selectionBox.rubberBandUpdate(axis.rubberBand, ["x", "y"][this.getAxisIndex(axis)]);
}
}

Expand Down Expand Up @@ -403,24 +379,6 @@ export class Histogram extends Frame {
this.scaleY = 1;
super.regulateScale();
}

public initRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {
this.axes[0].sendRubberBand(multiplotRubberBands);
}

public updateRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {
this.axes[0].sendRubberBandRange(multiplotRubberBands);
}

protected sendRubberBandsInFigure(figure: Figure): void {
figure.axes.forEach(otherAxis => {
if (this.axes[0].name == otherAxis.name) {
otherAxis.rubberBand.minValue = this.axes[0].rubberBand.minValue;
otherAxis.rubberBand.maxValue = this.axes[0].rubberBand.maxValue;
otherAxis.emitter.emit("rubberBandChange", otherAxis.rubberBand);
}
})
}
}

export class Scatter extends Frame {
Expand Down Expand Up @@ -815,14 +773,6 @@ export class Graph2D extends Scatter {
public multiplotSelectedIntersection(multiplotSelected: number[], isSelecting: boolean): [number[], boolean] { return [multiplotSelected, isSelecting] }

public receivePointSets(pointSets: PointSet[]): void {}

public initRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {}

public updateRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {}

public sendRubberBandsMultiplot(figures: Figure[]): void {}

protected receiveRubberBandFromFigure(figure: Figure): void {}
}

export class ParallelPlot extends Figure {
Expand Down Expand Up @@ -1177,14 +1127,6 @@ export class Draw extends Frame {

public receivePointSets(pointSets: PointSet[]): void {}

public initRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {}

public updateRubberBandMultiplot(multiplotRubberBands: Map<string, RubberBand>): void {}

public sendRubberBandsMultiplot(figures: Figure[]): void {}

protected receiveRubberBandFromFigure(figure: Figure): void {}

public highlightFromReferencePath(highlightData: HighlightData) {
const highlight = highlightData.highlight;
const shapes = this.getShapesFromPath(highlightData.referencePath);
Expand Down
7 changes: 6 additions & 1 deletion src/interactions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Subject } from "rxjs"
import { BehaviorSubject, ReplaySubject, Subject } from "rxjs"
import { Axis } from "./axes";
import { RubberBand } from "./shapes";

export interface HighlightData {
referencePath: string,
Expand All @@ -7,3 +9,6 @@ export interface HighlightData {
}

export const highlightShape: Subject<HighlightData> = new Subject();

export const onAxisSelection: Subject<Axis> = new Subject();
export const rubberbandsChange: Subject<Map<String, RubberBand>> = new Subject();
42 changes: 6 additions & 36 deletions src/multiplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RubberBand, SelectionBox } from "./shapes"
import { SelectionBoxCollection, PointSet } from "./collections"
import { Figure, Scatter, Graph2D, ParallelPlot, Draw } from './figures'
import { DataInterface, MultiplotDataInterface } from "./dataInterfaces"
import { rubberbandsChange } from "./interactions"

/*
TODO: Does this inherit from RemoteFigure or the opposite or does this
Expand All @@ -18,7 +19,7 @@ export class Multiplot {
public featureNames: string[];
public nSamples: number;
public figures: Figure[];
public rubberBands: Map<string, RubberBand>;
public rubberBands: Map<string, RubberBand> = new Map<string, RubberBand>();
public figureZones = new SelectionBoxCollection([]);

public isSelecting: boolean = false;
Expand Down Expand Up @@ -46,7 +47,6 @@ export class Multiplot {
this.nSamples = this.features.entries().next().value[1].length;
this.computeTable();
this.draw();
this.initRubberBands();
this.mouseListener();
}

Expand Down Expand Up @@ -176,15 +176,10 @@ export class Multiplot {

private activateAxisEvents(figure: Figure): void {
figure.axes.forEach(axis => axis.emitter.on('axisStateChange', e => figure.axisChangeUpdate(e)));
figure.axes.forEach((axis, index) => {
axis.emitter.on('rubberBandChange', e => {
figure.activateSelection(e, index);
this.isSelecting = true;
})
})
}

public selectionOn(): void {
// Never called. Is this useful ?
this.isSelecting = true;
this.figures.forEach(figure => figure.isSelecting = true);
this.canvas.style.cursor = 'crosshair';
Expand All @@ -200,6 +195,7 @@ export class Multiplot {
}

public switchSelection(): void {
// Never called. Is this useful ?
this.isSelecting ? this.selectionOff() : this.selectionOn();
}

Expand Down Expand Up @@ -310,19 +306,6 @@ export class Multiplot {

public updateHoveredIndices(figure: Figure): void { this.hoveredIndices = figure.sendHoveredIndicesMultiplot() }

public initRubberBands(): void {
this.rubberBands = new Map<string, RubberBand>();
this.figures.forEach(figure => figure.initRubberBandMultiplot(this.rubberBands));
}

public updateRubberBands(currentFigure: Figure): void {
if (this.isSelecting) {
if (!this.rubberBands) this.initRubberBands();
currentFigure.sendRubberBandsMultiplot(this.figures);
this.figures.forEach(figure => figure.updateRubberBandMultiplot(this.rubberBands));
}
}

public resetRubberBands(): void {
this.rubberBands.forEach(rubberBand => rubberBand.reset());
this.figures.forEach(figure => figure.resetRubberBands());
Expand All @@ -332,17 +315,6 @@ export class Multiplot {
this.figures.forEach(figure => figure.axes.forEach(axis => axis.emitter.on('axisStateChange', e => figure.axisChangeUpdate(e))));
}

private listenRubberBandChange(): void {
this.figures.forEach(figure => {
figure.axes.forEach((axis, index) => {
axis.emitter.on('rubberBandChange', e => {
figure.activateSelection(e, index);
this.isSelecting = true;
})
})
})
}

private keyDownDrawer(e: KeyboardEvent, ctrlKey: boolean, shiftKey: boolean, spaceKey: boolean): [boolean, boolean, boolean] {
if (e.key == "Control") {
ctrlKey = true;
Expand Down Expand Up @@ -423,7 +395,7 @@ export class Multiplot {
} else this.resizeWithMouse(absoluteMouse, clickedObject);

this.updateHoveredIndices(this.figures[this.hoveredFigureIndex]);
this.updateRubberBands(this.figures[this.hoveredFigureIndex]);
rubberbandsChange.next(this.rubberBands);
this.updateSelectedIndices();
return [canvasMouse, frameMouse, absoluteMouse, canvasDown, hasLeftFigure]
}
Expand All @@ -440,7 +412,7 @@ export class Multiplot {
if (!(this.figures[this.hoveredFigureIndex] instanceof Graph2D || this.figures[this.hoveredFigureIndex] instanceof Draw)) {
this.clickedIndices = this.figures[this.hoveredFigureIndex].clickedIndices;
}
this.updateRubberBands(this.figures[this.hoveredFigureIndex]);
rubberbandsChange.next(this.rubberBands);
hasLeftFigure = this.resetStateAttributes(shiftKey, ctrlKey);
clickedObject = null;
this.updateSelectedIndices();
Expand Down Expand Up @@ -474,8 +446,6 @@ export class Multiplot {

this.listenAxisStateChange();

this.listenRubberBandChange();

window.addEventListener('keydown', e => [ctrlKey, shiftKey, spaceKey] = this.keyDownDrawer(e, ctrlKey, shiftKey, spaceKey));

window.addEventListener('keyup', e => [ctrlKey, shiftKey, spaceKey] = this.keyUpDrawer(e, ctrlKey, shiftKey, spaceKey));
Expand Down
Loading