Compare commits
7 Commits
omm-r5.2.0
...
spectral-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9eb9147055 | ||
|
|
1049ac38ff | ||
|
|
2f435facd4 | ||
|
|
4942e27a89 | ||
|
|
e84a3bfe97 | ||
|
|
48322d46fd | ||
|
|
7616610f2c |
@@ -28,6 +28,15 @@ define([
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
domain: 3
|
||||
}
|
||||
},
|
||||
// Need to enable "LocalTimeSystem" plugin to make use of this
|
||||
// {
|
||||
// key: "local",
|
||||
@@ -109,6 +118,43 @@ define([
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
'example.spectral-generator': {
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "wavelength",
|
||||
name: "Wavelength",
|
||||
unit: "Hz",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
domain: 2,
|
||||
spectralAttribute: true
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 2,
|
||||
spectralAttribute: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
104
example/generator/SpectralGeneratorProvider.js
Normal file
104
example/generator/SpectralGeneratorProvider.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./WorkerInterface'
|
||||
], function (
|
||||
WorkerInterface
|
||||
) {
|
||||
|
||||
var REQUEST_DEFAULTS = {
|
||||
amplitude: 1,
|
||||
wavelength: 1,
|
||||
period: 10,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
randomness: 0,
|
||||
phase: 0
|
||||
};
|
||||
|
||||
function SpectralGeneratorProvider() {
|
||||
this.workerInterface = new WorkerInterface();
|
||||
}
|
||||
|
||||
SpectralGeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||
return domainObject.type === 'example.spectral-generator';
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.supportsRequest =
|
||||
SpectralGeneratorProvider.prototype.supportsSubscribe =
|
||||
SpectralGeneratorProvider.prototype.canProvideTelemetry;
|
||||
|
||||
SpectralGeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request) {
|
||||
var props = [
|
||||
'amplitude',
|
||||
'wavelength',
|
||||
'period',
|
||||
'offset',
|
||||
'dataRateInHz',
|
||||
'phase',
|
||||
'randomness'
|
||||
];
|
||||
|
||||
request = request || {};
|
||||
|
||||
var workerRequest = {};
|
||||
|
||||
props.forEach(function (prop) {
|
||||
if (domainObject.telemetry && Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)) {
|
||||
workerRequest[prop] = domainObject.telemetry[prop];
|
||||
}
|
||||
|
||||
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
||||
workerRequest[prop] = request[prop];
|
||||
}
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
||||
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
||||
}
|
||||
|
||||
workerRequest[prop] = Number(workerRequest[prop]);
|
||||
});
|
||||
|
||||
workerRequest.name = domainObject.name;
|
||||
|
||||
return workerRequest;
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.request = function (domainObject, request) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
||||
workerRequest.start = request.start;
|
||||
workerRequest.end = request.end;
|
||||
workerRequest.spectra = true;
|
||||
|
||||
return this.workerInterface.request(workerRequest);
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
||||
workerRequest.spectra = true;
|
||||
|
||||
return this.workerInterface.subscribe(workerRequest, callback);
|
||||
};
|
||||
|
||||
return SpectralGeneratorProvider;
|
||||
});
|
||||
@@ -54,23 +54,39 @@
|
||||
var start = Date.now();
|
||||
var step = 1000 / data.dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
let work;
|
||||
console.log('dataRate', data);
|
||||
if (data.spectra) {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
const messageCopy = Object.create(message);
|
||||
message.data.start = nextStep - (60 * 1000);
|
||||
message.data.end = nextStep;
|
||||
onRequest(messageCopy);
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
function work(now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness),
|
||||
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness)
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
return nextStep;
|
||||
};
|
||||
} else {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness),
|
||||
wavelength: wavelength(start, nextStep),
|
||||
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness)
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
return nextStep;
|
||||
};
|
||||
}
|
||||
|
||||
subscriptions[message.id] = work;
|
||||
@@ -111,13 +127,21 @@
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness),
|
||||
wavelength: wavelength(start, nextStep),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness)
|
||||
});
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: data
|
||||
data: request.spectra ? {
|
||||
wavelength: data.map((item) => {
|
||||
return item.wavelength;
|
||||
}),
|
||||
cos: data.map((item) => {
|
||||
return item.cos;
|
||||
})
|
||||
} : data
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,6 +155,10 @@
|
||||
* Math.sin(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset;
|
||||
}
|
||||
|
||||
function wavelength(start, nextStep) {
|
||||
return (nextStep - start) / 10;
|
||||
}
|
||||
|
||||
function sendError(error, message) {
|
||||
self.postMessage({
|
||||
error: error.name + ': ' + error.message,
|
||||
|
||||
@@ -24,11 +24,13 @@ define([
|
||||
"./GeneratorProvider",
|
||||
"./SinewaveLimitProvider",
|
||||
"./StateGeneratorProvider",
|
||||
"./SpectralGeneratorProvider",
|
||||
"./GeneratorMetadataProvider"
|
||||
], function (
|
||||
GeneratorProvider,
|
||||
SinewaveLimitProvider,
|
||||
StateGeneratorProvider,
|
||||
SpectralGeneratorProvider,
|
||||
GeneratorMetadataProvider
|
||||
) {
|
||||
|
||||
@@ -61,6 +63,26 @@ define([
|
||||
|
||||
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
||||
|
||||
openmct.types.addType("example.spectral-generator", {
|
||||
name: "Spectral Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||
cssClass: "icon-generator-telemetry",
|
||||
creatable: true,
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
period: 10,
|
||||
amplitude: 1,
|
||||
wavelength: 1,
|
||||
frequency: 1,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
phase: 0,
|
||||
randomness: 0
|
||||
};
|
||||
}
|
||||
});
|
||||
openmct.telemetry.addProvider(new SpectralGeneratorProvider());
|
||||
|
||||
openmct.types.addType("generator", {
|
||||
name: "Sine Wave Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import PlotViewProvider from './PlotViewProvider';
|
||||
import SpectralPlotViewProvider from './spectralPlot/SpectralPlotViewProvider';
|
||||
import SpectralAggregatePlotViewProvider from './spectralAggregatePlot/SpectralAggregatePlotViewProvider';
|
||||
import OverlayPlotViewProvider from './overlayPlot/OverlayPlotViewProvider';
|
||||
import StackedPlotViewProvider from './stackedPlot/StackedPlotViewProvider';
|
||||
import PlotsInspectorViewProvider from './inspector/PlotsInspectorViewProvider';
|
||||
import OverlayPlotCompositionPolicy from './overlayPlot/OverlayPlotCompositionPolicy';
|
||||
import StackedPlotCompositionPolicy from './stackedPlot/StackedPlotCompositionPolicy';
|
||||
import SpectralPlotCompositionPolicy from './spectralPlot/SpectralPlotCompositionPolicy';
|
||||
import SpectralAggregatePlotCompositionPolicy from './spectralAggregatePlot/SpectralAggregatePlotCompositionPolicy';
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
@@ -59,13 +63,46 @@ export default function () {
|
||||
},
|
||||
priority: 890
|
||||
});
|
||||
openmct.types.addType('telemetry.plot.spectral', {
|
||||
key: "telemetry.plot.spectral",
|
||||
name: "Spectral Plot",
|
||||
cssClass: "icon-plot-stacked",
|
||||
description: "View Spectra on Y Axes with non-time domain on the X axis. Can be added to Display Layouts.",
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {};
|
||||
},
|
||||
priority: 890
|
||||
});
|
||||
|
||||
openmct.types.addType('telemetry.plot.spectral-aggregate', {
|
||||
key: "telemetry.plot.spectral-aggregate",
|
||||
name: "Spectral Plot from Aggregate",
|
||||
cssClass: "icon-plot-stacked",
|
||||
description: "View Spectra on Y Axes with non-time domain on the X axis. Can be added to Display Layouts.",
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {
|
||||
plotType: 'bar'
|
||||
};
|
||||
},
|
||||
priority: 891
|
||||
});
|
||||
|
||||
openmct.objectViews.addProvider(new StackedPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new OverlayPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new PlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new SpectralPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new SpectralAggregatePlotViewProvider(openmct));
|
||||
|
||||
openmct.inspectorViews.addProvider(new PlotsInspectorViewProvider(openmct));
|
||||
|
||||
openmct.composition.addPolicy(new OverlayPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new StackedPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new SpectralPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new SpectralAggregatePlotCompositionPolicy(openmct).allow);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import {createMouseEvent, createOpenMct, resetApplicationState, spyOnBuiltins} f
|
||||
import PlotVuePlugin from "./plugin";
|
||||
import Vue from "vue";
|
||||
import StackedPlot from "./stackedPlot/StackedPlot.vue";
|
||||
// import SpectralPlot from "./spectralPlot/SpectralPlot.vue";
|
||||
import configStore from "./configuration/configStore";
|
||||
import EventEmitter from "EventEmitter";
|
||||
import PlotOptions from "./inspector/PlotOptions.vue";
|
||||
@@ -312,6 +313,38 @@ describe("the plugin", function () {
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === "plot-stacked");
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
|
||||
it("provides a spectral plot view for objects with telemetry", () => {
|
||||
const testTelemetryObject = {
|
||||
id: "test-object",
|
||||
type: "telemetry.plot.spectral",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "a-very-fine-key"
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testTelemetryObject, mockObjectPath);
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === "plot-spectral");
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
|
||||
it("provides a spectral aggregate plot view for objects with telemetry", () => {
|
||||
const testTelemetryObject = {
|
||||
id: "test-object",
|
||||
type: "telemetry.plot.spectral.aggregate",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "lots-of-aggregate-telemetry"
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testTelemetryObject, mockObjectPath);
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === "plot-spectral-aggregate");
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("The single plot view", () => {
|
||||
@@ -462,6 +495,146 @@ describe("the plugin", function () {
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* disabling this until we develop the plot view
|
||||
describe("The spectral plot view", () => {
|
||||
let testTelemetryObject;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let testTelemetryObject2;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let config;
|
||||
let spectralPlotObject;
|
||||
let component;
|
||||
let mockComposition;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let plotViewComponentObject;
|
||||
|
||||
beforeEach(() => {
|
||||
const getFunc = openmct.$injector.get;
|
||||
spyOn(openmct.$injector, "get")
|
||||
.withArgs("exportImageService").and.returnValue({
|
||||
exportPNG: () => {},
|
||||
exportJPG: () => {}
|
||||
})
|
||||
.and.callFake(getFunc);
|
||||
|
||||
spectralPlotObject = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-spectral-plot"
|
||||
},
|
||||
type: "telemetry.plot.spectral",
|
||||
name: "Test Spectral Plot"
|
||||
};
|
||||
|
||||
testTelemetryObject = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-object"
|
||||
},
|
||||
type: "test-object",
|
||||
name: "Test Object",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "utc",
|
||||
format: "utc",
|
||||
name: "Time",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-key",
|
||||
name: "Some attribute",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-other-key",
|
||||
name: "Another attribute",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
testTelemetryObject2 = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-object2"
|
||||
},
|
||||
type: "test-object",
|
||||
name: "Test Object2",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "utc",
|
||||
format: "utc",
|
||||
name: "Time",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "wavelength",
|
||||
name: "Wavelength",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-other-key2",
|
||||
name: "Another attribute2",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
mockComposition = new EventEmitter();
|
||||
mockComposition.load = () => {
|
||||
mockComposition.emit('add', testTelemetryObject);
|
||||
|
||||
return [testTelemetryObject];
|
||||
};
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
let viewContainer = document.createElement("div");
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
components: {
|
||||
SpectralPlot
|
||||
},
|
||||
provide: {
|
||||
openmct: openmct,
|
||||
domainObject: spectralPlotObject,
|
||||
composition: openmct.composition.get(spectralPlotObject)
|
||||
},
|
||||
template: "<spectral-plot></spectral-plot>"
|
||||
});
|
||||
|
||||
cleanupFirst.push(() => {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
});
|
||||
|
||||
return telemetryPromise
|
||||
.then(Vue.nextTick())
|
||||
.then(() => {
|
||||
plotViewComponentObject = component.$root.$children[0];
|
||||
const configId = openmct.objects.makeKeyString(testTelemetryObject.identifier);
|
||||
config = configStore.get(configId);
|
||||
});
|
||||
});
|
||||
|
||||
it("Renders a collapsed legend for every telemetry", () => {
|
||||
let legend = element.querySelectorAll(".plot-wrapper-collapsed-legend .plot-series-name");
|
||||
expect(legend.length).toBe(1);
|
||||
expect(legend[0].innerHTML).toEqual("Test Object");
|
||||
});
|
||||
|
||||
}); */
|
||||
|
||||
describe("The stacked plot view", () => {
|
||||
let testTelemetryObject;
|
||||
let testTelemetryObject2;
|
||||
@@ -990,4 +1163,39 @@ describe("the plugin", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the spectral plot", () => {
|
||||
const mockObject = {
|
||||
name: 'A Very Nice Spectral Plot',
|
||||
key: 'telemetry.plot.spectral',
|
||||
creatable: true
|
||||
};
|
||||
|
||||
it('defines a spectral plot object type with the correct key', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral').definition;
|
||||
expect(objectDef.key).toEqual(mockObject.key);
|
||||
});
|
||||
|
||||
it('is creatable', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral').definition;
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the aggregate spectral plot", () => {
|
||||
const mockObject = {
|
||||
name: 'An Even Nicer Aggregate Spectral Plot',
|
||||
key: 'telemetry.plot.spectral-aggregate',
|
||||
creatable: true
|
||||
};
|
||||
|
||||
it('defines a spectral plot object type with the correct key', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral-aggregate').definition;
|
||||
expect(objectDef.key).toEqual(mockObject.key);
|
||||
});
|
||||
|
||||
it('is creatable', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral-aggregate').definition;
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
export default function SpectralAggregatePlotCompositionPolicy(openmct) {
|
||||
function hasAggregateDomainAndRange(metadata) {
|
||||
const rangeValues = metadata.valuesForHints(['spectralAttribute']);
|
||||
const domainValues = metadata.valuesForHints(['spectralAttribute']);
|
||||
|
||||
return rangeValues.length > 0
|
||||
|| domainValues.length > 0;
|
||||
}
|
||||
|
||||
function hasSpectralAggregateTelemetry(domainObject) {
|
||||
if (!Object.prototype.hasOwnProperty.call(domainObject, 'telemetry')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||
|
||||
return metadata.values().length > 0 && hasAggregateDomainAndRange(metadata);
|
||||
}
|
||||
|
||||
return {
|
||||
allow: function (parent, child) {
|
||||
if ((parent.type === 'telemetry.plot.spectral.aggregate')
|
||||
&& ((child.type !== 'telemetry.plot.overlay') && (hasSpectralAggregateTelemetry(child) === false))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import SpectralAggregatePlotCompositionPolicy from "./SpectralAggregatePlotCompositionPolicy";
|
||||
import { createOpenMct } from "utils/testing";
|
||||
|
||||
describe("The spectral aggregation plot composition policy", () => {
|
||||
let openmct;
|
||||
const mockNonSpectralMetaData = {
|
||||
"period": 10,
|
||||
"amplitude": 1,
|
||||
"offset": 0,
|
||||
"dataRateInHz": 1,
|
||||
"phase": 0,
|
||||
"randomness": 0,
|
||||
valuesForHints: () => {
|
||||
return [
|
||||
{
|
||||
"key": "sin",
|
||||
"name": "Sine",
|
||||
"unit": "Hz",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 1,
|
||||
"priority": 4
|
||||
},
|
||||
"source": "sin"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 2,
|
||||
"priority": 5
|
||||
},
|
||||
"source": "cos"
|
||||
}
|
||||
];
|
||||
},
|
||||
values: [
|
||||
{
|
||||
"key": "name",
|
||||
"name": "Name",
|
||||
"format": "string",
|
||||
"source": "name",
|
||||
"hints": {
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "utc",
|
||||
"name": "Time",
|
||||
"format": "utc",
|
||||
"hints": {
|
||||
"domain": 1,
|
||||
"priority": 1
|
||||
},
|
||||
"source": "utc"
|
||||
},
|
||||
{
|
||||
"key": "yesterday",
|
||||
"name": "Yesterday",
|
||||
"format": "utc",
|
||||
"hints": {
|
||||
"domain": 2,
|
||||
"priority": 2
|
||||
},
|
||||
"source": "yesterday"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"domain": 3,
|
||||
"priority": 3
|
||||
},
|
||||
"source": "cos"
|
||||
},
|
||||
{
|
||||
"key": "sin",
|
||||
"name": "Sine",
|
||||
"unit": "Hz",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 1,
|
||||
"priority": 4
|
||||
},
|
||||
"source": "sin"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 2,
|
||||
"priority": 5
|
||||
},
|
||||
"source": "cos"
|
||||
}
|
||||
]
|
||||
};
|
||||
const mockGoodSpectralMetaData = {
|
||||
"period": 10,
|
||||
"amplitude": 1,
|
||||
"offset": 0,
|
||||
"dataRateInHz": 1,
|
||||
"phase": 0,
|
||||
"randomness": 0,
|
||||
"wavelength": 0,
|
||||
valuesForHints: () => {
|
||||
return [
|
||||
{
|
||||
"key": "sin",
|
||||
"name": "Sine",
|
||||
"unit": "Hz",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 1,
|
||||
"priority": 4
|
||||
},
|
||||
"source": "sin"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 2,
|
||||
"priority": 5
|
||||
},
|
||||
"source": "cos"
|
||||
}
|
||||
];
|
||||
},
|
||||
values: [
|
||||
{
|
||||
"key": "name",
|
||||
"name": "Name",
|
||||
"format": "string",
|
||||
"source": "name",
|
||||
"hints": {
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "utc",
|
||||
"name": "Time",
|
||||
"format": "utc",
|
||||
"hints": {
|
||||
"domain": 1,
|
||||
"priority": 1
|
||||
},
|
||||
"source": "utc"
|
||||
},
|
||||
{
|
||||
"key": "yesterday",
|
||||
"name": "Yesterday",
|
||||
"format": "utc",
|
||||
"hints": {
|
||||
"domain": 2,
|
||||
"priority": 2
|
||||
},
|
||||
"source": "yesterday"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"domain": 3,
|
||||
"priority": 3
|
||||
},
|
||||
"source": "cos"
|
||||
},
|
||||
{
|
||||
"key": "sin",
|
||||
"name": "Sine",
|
||||
"unit": "Hz",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 1,
|
||||
"spectralAttribute": true
|
||||
},
|
||||
"source": "sin"
|
||||
},
|
||||
{
|
||||
"key": "cos",
|
||||
"name": "Cosine",
|
||||
"unit": "deg",
|
||||
"formatString": "%0.2f",
|
||||
"hints": {
|
||||
"range": 2,
|
||||
"priority": 5
|
||||
},
|
||||
"source": "cos"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
openmct = createOpenMct();
|
||||
const mockTypeDef = {
|
||||
telemetry: mockGoodSpectralMetaData
|
||||
};
|
||||
const mockTypeService = {
|
||||
getType: () => {
|
||||
return {
|
||||
typeDef: mockTypeDef
|
||||
};
|
||||
}
|
||||
};
|
||||
openmct.$injector = {
|
||||
get: () => {
|
||||
return mockTypeService;
|
||||
}
|
||||
};
|
||||
|
||||
openmct.telemetry.isTelemetryObject = function (domainObject) {
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
it("exists", () => {
|
||||
expect(SpectralAggregatePlotCompositionPolicy(openmct).allow).toBeDefined();
|
||||
});
|
||||
|
||||
it("allow composition only for telemetry that provides/supports spectral data", () => {
|
||||
const parent = {
|
||||
"composition": [],
|
||||
"configuration": {},
|
||||
"name": "Some Spectral Aggregate Plot",
|
||||
"type": "telemetry.plot.spectral.aggregate",
|
||||
"location": "mine",
|
||||
"modified": 1631005183584,
|
||||
"persisted": 1631005183502,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9"
|
||||
}
|
||||
};
|
||||
const child = {
|
||||
"telemetry": {
|
||||
"period": 10,
|
||||
"amplitude": 1,
|
||||
"offset": 0,
|
||||
"dataRateInHz": 1,
|
||||
"phase": 0,
|
||||
"randomness": 0
|
||||
},
|
||||
"name": "Unnamed Sine Wave Generator",
|
||||
"type": "generator",
|
||||
"location": "mine",
|
||||
"modified": 1630399715531,
|
||||
"persisted": 1630399715531,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "21d61f2d-6d2d-4bea-8b0a-7f59fd504c6c"
|
||||
}
|
||||
};
|
||||
expect(SpectralAggregatePlotCompositionPolicy(openmct).allow(parent, child)).toEqual(true);
|
||||
});
|
||||
|
||||
it("disallows composition for telemetry that contain anything else", () => {
|
||||
const mockTypeDef = {
|
||||
telemetry: mockNonSpectralMetaData
|
||||
};
|
||||
const mockTypeService = {
|
||||
getType: () => {
|
||||
return {
|
||||
typeDef: mockTypeDef
|
||||
};
|
||||
}
|
||||
};
|
||||
openmct.$injector = {
|
||||
get: () => {
|
||||
return mockTypeService;
|
||||
}
|
||||
};
|
||||
const parent = {
|
||||
"composition": [],
|
||||
"configuration": {},
|
||||
"name": "Some Spectral Aggregate Plot",
|
||||
"type": "telemetry.plot.spectral.aggregate",
|
||||
"location": "mine",
|
||||
"modified": 1631005183584,
|
||||
"persisted": 1631005183502,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9"
|
||||
}
|
||||
};
|
||||
const child = {
|
||||
"telemetry": {
|
||||
"period": 10,
|
||||
"amplitude": 1,
|
||||
"offset": 0,
|
||||
"dataRateInHz": 1,
|
||||
"phase": 0,
|
||||
"randomness": 0
|
||||
},
|
||||
"name": "Unnamed Sine Wave Generator",
|
||||
"type": "generator",
|
||||
"location": "mine",
|
||||
"modified": 1630399715531,
|
||||
"persisted": 1630399715531,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "21d61f2d-6d2d-4bea-8b0a-7f59fd504c6c"
|
||||
}
|
||||
};
|
||||
expect(SpectralAggregatePlotCompositionPolicy(openmct).allow(parent, child)).toEqual(false);
|
||||
});
|
||||
|
||||
it("passthrough for composition for non spectral aggregate plots", () => {
|
||||
const parent = {
|
||||
"composition": [],
|
||||
"configuration": {},
|
||||
"name": "Some Stacked Plot",
|
||||
"type": "telemetry.plot.stacked",
|
||||
"location": "mine",
|
||||
"modified": 1631005183584,
|
||||
"persisted": 1631005183502,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9"
|
||||
}
|
||||
};
|
||||
const child = {
|
||||
"telemetry": {
|
||||
"period": 10,
|
||||
"amplitude": 1,
|
||||
"offset": 0,
|
||||
"dataRateInHz": 1,
|
||||
"phase": 0,
|
||||
"randomness": 0
|
||||
},
|
||||
"name": "Unnamed Sine Wave Generator",
|
||||
"type": "generator",
|
||||
"location": "mine",
|
||||
"modified": 1630399715531,
|
||||
"persisted": 1630399715531,
|
||||
"identifier": {
|
||||
"namespace": "",
|
||||
"key": "21d61f2d-6d2d-4bea-8b0a-7f59fd504c6c"
|
||||
}
|
||||
};
|
||||
expect(SpectralAggregatePlotCompositionPolicy(openmct).allow(parent, child)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import SpectralAggregateView from './SpectralAggregateView.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default function SpectralAggregatePlotViewProvider(openmct) {
|
||||
function isCompactView(objectPath) {
|
||||
return objectPath.find(object => object.type === 'time-strip');
|
||||
}
|
||||
|
||||
return {
|
||||
key: 'plot-spectral-aggregate',
|
||||
name: 'Spectral Aggregate Plot',
|
||||
cssClass: 'icon-telemetry',
|
||||
canView(domainObject, objectPath) {
|
||||
return domainObject && domainObject.type === 'telemetry.plot.spectral-aggregate';
|
||||
},
|
||||
|
||||
canEdit(domainObject, objectPath) {
|
||||
return domainObject && domainObject.type === 'telemetry.plot.spectral-aggregate';
|
||||
},
|
||||
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
let isCompact = isCompactView(objectPath);
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
SpectralAggregateView
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
compact: isCompact
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<spectral-aggregate-view :options="options"></spectral-aggregate-view>'
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'domainObject']
|
||||
};
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,36 @@
|
||||
export default function SpectralPlotCompositionPolicy(openmct) {
|
||||
function hasSpectralDomainAndRange(metadata) {
|
||||
const rangeValues = metadata.valuesForHints(['range']);
|
||||
const domainValues = metadata.valuesForHints(['domain']);
|
||||
const containsSomeSpectralData = domainValues.some(value => {
|
||||
return ((value.key === 'wavelength') || (value.key === 'frequency'));
|
||||
});
|
||||
|
||||
return rangeValues.length > 0
|
||||
&& domainValues.length > 0
|
||||
&& containsSomeSpectralData;
|
||||
}
|
||||
|
||||
function hasSpectralTelemetry(domainObject) {
|
||||
if (!Object.prototype.hasOwnProperty.call(domainObject, 'telemetry')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||
|
||||
return metadata.values().length > 0 && hasSpectralDomainAndRange(metadata);
|
||||
}
|
||||
|
||||
return {
|
||||
allow: function (parent, child) {
|
||||
|
||||
if ((parent.type === 'telemetry.plot.spectral')
|
||||
&& ((child.type !== 'telemetry.plot.overlay') && (hasSpectralTelemetry(child) === false))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
75
src/plugins/plot/spectralPlot/SpectralPlotViewProvider.js
Normal file
75
src/plugins/plot/spectralPlot/SpectralPlotViewProvider.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import SpectralView from './SpectralView.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default function SpectralPlotViewProvider(openmct) {
|
||||
function isCompactView(objectPath) {
|
||||
return objectPath.find(object => object.type === 'time-strip');
|
||||
}
|
||||
|
||||
return {
|
||||
key: 'plot-spectral',
|
||||
name: 'Spectral Plot',
|
||||
cssClass: 'icon-telemetry',
|
||||
canView(domainObject, objectPath) {
|
||||
return domainObject && domainObject.type === 'telemetry.plot.spectral';
|
||||
},
|
||||
|
||||
canEdit(domainObject, objectPath) {
|
||||
return domainObject && domainObject.type === 'telemetry.plot.spectral';
|
||||
},
|
||||
|
||||
view: function (domainObject, objectPath) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
let isCompact = isCompactView(objectPath);
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
SpectralView
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
compact: isCompact
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<spectral-view :options="options"></spectral-view>'
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
13
src/plugins/plot/spectralPlot/SpectralView.vue
Normal file
13
src/plugins/plot/spectralPlot/SpectralView.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'domainObject']
|
||||
};
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user