Skip to content

Commit

Permalink
Remove large series models from reactive data in plots (#6961)
Browse files Browse the repository at this point in the history
* remove series object from highlights

* remove series models from legend reactive data

* drawing all annotations at once is way faster

* fix multi annotations

* lots of reactive things depending on config

* make annotation lookup faster

* lint

* readd perf test

* address PR comments

* fix highlight typo

---------

Co-authored-by: Jesse Mazzella <[email protected]>
Co-authored-by: Shefali Joshi <[email protected]>
  • Loading branch information
3 people authored Sep 6, 2023
1 parent 0be106f commit 8e917b2
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 174 deletions.
2 changes: 1 addition & 1 deletion e2e/tests/performance/tagging.perf.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const {
waitForPlotsToRender
} = require('../../appActions');

test.describe.fixme('Plot Tagging Performance', () => {
test.describe('Plot Tagging Performance', () => {
/**
* Given a canvas and a set of points, tags the points on the canvas.
* @param {import('@playwright/test').Page} page
Expand Down
95 changes: 54 additions & 41 deletions src/plugins/plot/MctPlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@
:rectangles="rectangles"
:highlights="highlights"
:show-limit-line-labels="limitLineLabels"
:annotated-points="annotatedPoints"
:annotation-selections="annotationSelections"
:annotated-points-by-series="annotatedPointsBySeries"
:annotation-selections-by-series="annotationSelectionsBySeries"
:hidden-y-axis-ids="hiddenYAxisIds"
:annotation-viewing-and-editing-allowed="annotationViewingAndEditingAllowed"
@plotReinitializeCanvas="initCanvas"
Expand Down Expand Up @@ -245,9 +245,9 @@ export default {
data() {
return {
altPressed: false,
annotatedPointsBySeries: {},
highlights: [],
annotatedPoints: [],
annotationSelections: [],
annotationSelectionsBySeries: {},
annotationsEverLoaded: false,
lockHighlightPoint: false,
yKeyOptions: [],
Expand All @@ -256,8 +256,6 @@ export default {
plotHistory: [],
selectedXKeyOption: {},
xKeyOptions: [],
seriesModels: [],
legend: {},
pending: 0,
isRealTime: this.openmct.time.isRealTime(),
loaded: false,
Expand Down Expand Up @@ -346,6 +344,8 @@ export default {
this.abortController = new AbortController();
},
mounted() {
this.seriesModels = [];
this.config = {};
this.yAxisIdVisibility = {};
this.offsetWidth = 0;

Expand All @@ -357,7 +357,6 @@ export default {
this.setTimeContext = this.setTimeContext.bind(this);

this.config = this.getConfig();
this.legend = this.config.legend;
this.yAxes = [
{
id: this.config.yAxis.id,
Expand Down Expand Up @@ -455,7 +454,7 @@ export default {
const clickedOption = event.target.closest('.js-autocomplete-options') !== null;
if (!clickedInsidePlot && !clickedInsideInspector && !clickedOption) {
this.rectangles = [];
this.annotationSelections = [];
this.annotationSelectionsBySeries = {};
this.selectPlot();
document.body.removeEventListener('click', this.cancelSelection);
}
Expand Down Expand Up @@ -639,7 +638,7 @@ export default {
})
);
if (rawAnnotationsForPlot) {
this.annotatedPoints = this.findAnnotationPoints(rawAnnotationsForPlot);
this.annotatedPointsBySeries = this.findAnnotationPoints(rawAnnotationsForPlot);
}
this.annotationsEverLoaded = true;
},
Expand Down Expand Up @@ -795,7 +794,7 @@ export default {
};
this.config.xAxis.set('range', newRange);
if (!isTick) {
this.annotatedPoints = [];
this.annotatedPointsBySeries = {};
this.clearPanZoomHistory();
this.synchronizeIfBoundsMatch();
this.loadMoreData(newRange, true);
Expand Down Expand Up @@ -1157,7 +1156,7 @@ export default {
series.closest = series.nearestPoint(point);

return {
series: series,
seriesKeyString: series.keyString,
point: series.closest
};
});
Expand Down Expand Up @@ -1245,7 +1244,7 @@ export default {

startMarquee(event, annotationEvent) {
this.rectangles = [];
this.annotationSelections = [];
this.annotationSelectionsBySeries = {};
this.canvas.classList.remove('plot-drag');
this.canvas.classList.add('plot-marquee');

Expand Down Expand Up @@ -1273,7 +1272,10 @@ export default {

const nearbyAnnotations = this.gatherNearbyAnnotations();

if (this.annotationViewingAndEditingAllowed && this.annotationSelections.length) {
if (
this.annotationViewingAndEditingAllowed &&
Object.keys(this.annotationSelectionsBySeries).length
) {
//no annotations were found, but we are adding some now
return;
}
Expand Down Expand Up @@ -1353,20 +1355,18 @@ export default {

document.body.addEventListener('click', this.cancelSelection);
},
selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBox, event) {
selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBoxBySeries, event) {
let targetDomainObjects = {};
let targetDetails = {};
let annotations = [];
pointsInBox.forEach((pointInBox) => {
if (pointInBox.length) {
const seriesID = pointInBox[0].series.keyString;
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === pointInBox[0].series.get('yAxisId')
);
targetDetails[seriesID] = boundingBoxWithId?.boundingBox;
Object.keys(pointsInBoxBySeries).forEach((seriesKey) => {
const seriesModel = this.getSeries(seriesKey);
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === seriesModel.get('yAxisId')
);
targetDetails[seriesKey] = boundingBoxWithId?.boundingBox;

targetDomainObjects[seriesID] = pointInBox[0].series.domainObject;
}
targetDomainObjects[seriesKey] = seriesModel.domainObject;
});
this.selectPlotAnnotations({
targetDetails,
Expand All @@ -1375,7 +1375,7 @@ export default {
});
},
findAnnotationPoints(rawAnnotations) {
const annotationsByPoints = [];
const annotationsBySeries = {};
rawAnnotations.forEach((rawAnnotation) => {
if (rawAnnotation.targets) {
const targetValues = Object.values(rawAnnotation.targets);
Expand All @@ -1390,22 +1390,33 @@ export default {
if (!series) {
return;
}
if (!annotationsBySeries[seriesId]) {
annotationsBySeries[seriesId] = [];
}

boundingBoxPerYAxis.push({
id: series.get('yAxisId'),
boundingBox
});
});

const pointsInBox = this.getPointsInBox(boundingBoxPerYAxis, rawAnnotation);
if (pointsInBox && pointsInBox.length) {
annotationsByPoints.push(pointsInBox.flat());
const pointsInBoxBySeries = this.getPointsInBoxBySeries(
boundingBoxPerYAxis,
rawAnnotation
);
if (pointsInBoxBySeries && Object.values(pointsInBoxBySeries).length) {
Object.keys(pointsInBoxBySeries).forEach((seriesKeyString) => {
const pointsInBox = pointsInBoxBySeries[seriesKeyString];
if (pointsInBox && pointsInBox.length) {
annotationsBySeries[seriesKeyString].push(...pointsInBox);
}
});
}
}
}
});

return annotationsByPoints.flat();
return annotationsBySeries;
},
searchWithFlatbush(seriesData, seriesModel, boundingBox) {
const flatbush = new Flatbush(seriesData.length);
Expand All @@ -1425,9 +1436,15 @@ export default {

return rangeResults;
},
getPointsInBox(boundingBoxPerYAxis, rawAnnotation) {
getSeries(keyStringToFind) {
const foundSeries = this.seriesModels.find((series) => {
return series.keyString === keyStringToFind;
});
return foundSeries;
},
getPointsInBoxBySeries(boundingBoxPerYAxis, rawAnnotation) {
// load series models in KD-Trees
const seriesKDTrees = [];
const searchResultsBySeries = {};
this.seriesModels.forEach((seriesModel) => {
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === seriesModel.get('yAxisId')
Expand All @@ -1440,16 +1457,15 @@ export default {

const seriesData = seriesModel.getSeriesData();
if (seriesData && seriesData.length) {
const searchResults = [];
searchResultsBySeries[seriesModel.keyString] = [];
const rangeResults = this.searchWithFlatbush(seriesData, seriesModel, boundingBox);
rangeResults.forEach((id) => {
const seriesDatum = seriesData[id];
if (seriesDatum) {
const result = {
series: seriesModel,
point: seriesDatum
};
searchResults.push(result);
searchResultsBySeries[seriesModel.keyString].push(result);
}

if (rawAnnotation) {
Expand All @@ -1463,13 +1479,10 @@ export default {
seriesDatum.annotationsById[annotationKeyString] = rawAnnotation;
}
});
if (searchResults.length) {
seriesKDTrees.push(searchResults);
}
}
});

return seriesKDTrees;
return searchResultsBySeries;
},
endAnnotationMarquee(event) {
const boundingBoxPerYAxis = [];
Expand All @@ -1490,13 +1503,13 @@ export default {
});
});

const pointsInBox = this.getPointsInBox(boundingBoxPerYAxis);
if (!pointsInBox) {
const pointsInBoxBySeries = this.getPointsInBoxBySeries(boundingBoxPerYAxis);
if (!pointsInBoxBySeries || Object.values(pointsInBoxBySeries).length === 0) {
return;
}

this.annotationSelections = pointsInBox.flat();
this.selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBox, event);
this.annotationSelectionsBySeries = pointsInBoxBySeries;
this.selectNewPlotAnnotations(boundingBoxPerYAxis, this.annotationSelectionsBySeries, event);
},
endZoomMarquee() {
const startPixels = this.marquee.startPixels;
Expand Down
Loading

0 comments on commit 8e917b2

Please sign in to comment.