[Plot] Add JSDoc

Add inline comments to Plot scripts. WTD-533.
This commit is contained in:
Victor Woeltjen
2014-12-02 14:38:03 -08:00
parent 870172ec6f
commit 622f1f8be7
10 changed files with 494 additions and 27 deletions

View File

@ -5,10 +5,30 @@ define(
function () {
"use strict";
/**
* A PlotAxis provides a template-ready set of options
* for the domain or range axis, sufficient to populate
* selectors.
*
* @constructor
* @param {string} axisType the field in metadatas to
* look at for axis options; usually one of
* "domains" or "ranges"
* @param {object[]} metadatas metadata objects, as
* returned by the `getMetadata()` method of
* a `telemetry` capability.
* @param {object} defaultValue the value to use for the
* active state in the event that no options are
* found; should contain "name" and "key" at
* minimum.
*
*/
function PlotAxis(axisType, metadatas, defaultValue) {
var keys = {},
options = [];
// Look through all metadata objects and assemble a list
// of all possible domain or range options
function buildOptionsForMetadata(m) {
(m[axisType] || []).forEach(function (option) {
if (!keys[option.key]) {
@ -24,7 +44,18 @@ define(
// template, so expose properties directly to facilitate
// two-way data binding (for drop-down menus)
return {
/**
* The set of options applicable for this axis;
* an array of objects, where each object contains a
* "key" field and a "name" field (for machine- and
* human-readable names respectively)
*/
options: options,
/**
* The currently chosen option for this axis. An
* initial value is provided; this will be updated
* directly form the plot template.
*/
active: options[0] || defaultValue
};
}

View File

@ -5,8 +5,15 @@ define(
function () {
"use strict";
// Date format to use for domain values; in particular,
// use day-of-year instead of month/day
var DATE_FORMAT = "YYYY-DDD HH:mm:ss";
/**
* The PlotFormatter is responsible for formatting (as text
* for display) values along either the domain or range of a
* plot.
*/
function PlotFormatter() {
function formatDomainValue(v) {
return moment.utc(v).format(DATE_FORMAT);
@ -17,7 +24,20 @@ define(
}
return {
/**
* Format a domain value.
* @param {number} v the domain value; a timestamp
* in milliseconds since start of 1970
* @returns {string} a textual representation of the
* data and time, suitable for display.
*/
formatDomainValue: formatDomainValue,
/**
* Format a range value.
* @param {number} v the range value; a numeric value
* @returns {string} a textual representation of the
* value, suitable for display.
*/
formatRangeValue: formatRangeValue
};
}

View File

@ -52,18 +52,57 @@ define(
}).concat([1]); // RGBA
});
/**
* PlotPalette allows a consistent set of colors to be retrieved
* by index, in various color formats. All PlotPalette methods are
* static, so there is no need for a constructor call; using
* this will simply return PlotPalette itself.
* @constructor
*/
function PlotPalette() {
return PlotPalette;
}
/**
* Look up a color in the plot's palette, by index.
* This will be returned as a three element array of RGB
* values, as integers in the range of 0-255.
* @param {number} i the index of the color to look up
* @return {number[]} the color, as integer RGB values
*/
PlotPalette.getIntegerColor = function (i) {
return integerPalette[Math.floor(i) % integerPalette.length];
};
/**
* Look up a color in the plot's palette, by index.
* This will be returned as a three element array of RGB
* values, in the range of 0.0-1.0.
*
* This format is present specifically to support use with
* WebGL, which expects colors of that form.
*
* @param {number} i the index of the color to look up
* @return {number[]} the color, as floating-point RGB values
*/
PlotPalette.getFloatColor = function (i) {
return floatPalette[Math.floor(i) % floatPalette.length];
};
/**
* Look up a color in the plot's palette, by index.
* This will be returned as a string using #-prefixed
* six-digit RGB hex notation (e.g. #FF0000)
* See http://www.w3.org/TR/css3-color/#rgb-color.
*
* This format is useful for representing colors in in-line
* styles.
*
* @param {number} i the index of the color to look up
* @return {string} the color, as a style-friendly string
*/
PlotPalette.getStringColor = function (i) {
return stringPalette[Math.floor(i) % stringPalette.length];
};

View File

@ -5,9 +5,30 @@ define(
function () {
"use strict";
/**
* The PlotPanZoomStack is responsible for maintaining the
* pan-zoom state of a plot (expressed as a boundary starting
* at an origin and extending to certain dimensions) in a
* stack, to support the back and unzoom buttons in plot controls.
*
* Dimensions and origins are here described each by two-element
* arrays, where the first element describes a value or quantity
* along the domain axis, and the second element describes the same
* along the range axis.
*
* @constructor
* @param {number[]} origin the plot's origin, initially
* @param {number[]} dimensions the plot's dimensions, initially
*/
function PlotPanZoomStack(origin, dimensions) {
// Use constructor parameters as the stack's initial state
var stack = [{ origin: origin, dimensions: dimensions }];
// Various functions which follow are simply wrappers for
// normal stack-like array methods, with the exception that
// they prevent undesired modification and enforce that this
// stack must remain non-empty.
// See JSDoc for specific methods below for more detail.
function getDepth() {
return stack.length;
}
@ -43,13 +64,70 @@ define(
}
return {
/**
* Get the current stack depth; that is, the number
* of items on the stack. A depth of one means that no
* panning or zooming relative to the base value has
* been applied.
* @returns {number} the depth of the stack
*/
getDepth: getDepth,
/**
* Push a new pan-zoom state onto the stack; this will
* become the active pan-zoom state.
* @param {number[]} origin the new origin
* @param {number[]} dimensions the new dimensions
*/
pushPanZoom: pushPanZoom,
/**
* Pop a pan-zoom state from the stack. Whatever pan-zoom
* state was previously present will become current.
* If called when there is only one pan-zoom state on the
* stack, this acts as a no-op (that is, the lowest
* pan-zoom state on the stack cannot be popped, to ensure
* that some pan-zoom state is always available.)
*/
popPanZoom: popPanZoom,
/**
* Set the base pan-zoom state; that is, the state at the
* bottom of the stack. This allows the "unzoomed" state of
* a plot to be updated (e.g. as new data comes in) without
* interfering with the user's chosen zoom level.
* @param {number[]} origin the base origin
* @param {number[]} dimensions the base dimensions
*/
setBasePanZoom: setBasePanZoom,
/**
* Clear the pan-zoom stack down to its bottom element;
* in effect, pop all elements but the last, e.g. to remove
* any temporary user modifications to pan-zoom state.
*/
clearPanZoom: clearPanZoom,
/**
* Get the current pan-zoom state (the state at the top
* of the stack), expressed as an object with "origin" and
* "dimensions" fields.
* @returns {object} the current pan-zoom state
*/
getPanZoom: getPanZoom,
/**
* Get the current origin, as represented on the top of the
* stack.
* @returns {number[]} the current plot origin
*/
getOrigin: getOrigin,
/**
* Get the current dimensions, as represented on the top of
* the stack.
* @returns {number[]} the current plot dimensions
*/
getDimensions: getDimensions
};
}

View File

@ -5,27 +5,65 @@ define(
function () {
"use strict";
/**
* A PlotPosition converts from pixel coordinates to domain-range
* coordinates, based on the current plot boundary as described on
* the pan-zoom stack.
*
* These coordinates are not updated after construction; that is,
* they represent the result of the conversion at the time the
* PlotPosition was instantiated. Care should be taken when retaining
* PlotPosition objects across changes to the pan-zoom stack.
*
* @constructor
* @param {number} x the horizontal pixel position in the plot area
* @param {number} y the vertical pixel position in the plot area
* @param {number} width the width of the plot area
* @param {number} height the height of the plot area
* @param {PanZoomStack} panZoomStack the applicable pan-zoom stack,
* used to determine the plot's domain-range boundaries.
*/
function PlotPosition(x, y, width, height, panZoomStack) {
var panZoom = panZoomStack.getPanZoom(),
origin = panZoom.origin,
dimensions = panZoom.dimensions,
position;
function convert(v, i) {
return v * dimensions[i] + origin[i];
}
if (!dimensions || !origin) {
// We need both dimensions and origin to compute a position
position = [];
} else {
position = [ x / width, (height - y) / height ].map(function (v, i) {
return v * dimensions[i] + origin[i];
});
// Convert from pixel to domain-range space.
// Note that range is reversed from the y-axis in pixel space
//(positive range points up, positive pixel-y points down)
position = [ x / width, (height - y) / height ].map(convert);
}
return {
/**
* Get the domain value corresponding to this pixel position.
* @returns {number} the domain value
*/
getDomain: function () {
return position[0];
},
/**
* Get the range value corresponding to this pixel position.
* @returns {number} the range value
*/
getRange: function () {
return position[1];
},
/**
* Get the domain and values corresponding to this
* pixel position.
* @returns {number[]} an array containing the domain and
* the range value, in that order
*/
getPosition: function () {
return position;
}

View File

@ -10,6 +10,16 @@ define(
function identity(x) { return x; }
/**
* The PlotPreparer is responsible for handling data sets and
* preparing them to be rendered. It creates a WebGL-plottable
* Float32Array for each trace, and tracks the boundaries of the
* data sets (since this is convenient to do during the same pass).
* @constructor
* @param {Telemetry[]} datas telemetry data objects
* @param {string} domain the key to use when looking up domain values
* @param {string} range the key to use when looking up range values
*/
function PlotPreparer(datas, domain, range) {
var index,
vertices = [],
@ -23,14 +33,18 @@ define(
// Remove any undefined data sets
datas = (datas || []).filter(identity);
// Filter out un
// Do a first pass to determine the domain offset.
// This will be use to reduce the magnitude of domain values
// in the buffer, to minimize loss-of-precision when
// converting to a 32-bit float.
datas.forEach(function (data) {
domainOffset = Math.min(data.getDomainValue(0, domain), domainOffset);
});
// Assemble buffers, and track bounds of the data present
datas.forEach(function (data, i) {
vertices.push([]);
for (index = 0; index < data.getPointCount(); index = index + 1) {
for (index = 0; index < data.getPointCount(); index += 1) {
x = data.getDomainValue(index, domain);
y = data.getRangeValue(index, range);
vertices[i].push(x - domainOffset);
@ -42,23 +56,62 @@ define(
}
});
// If range is empty, add some padding
if (max[1] === min[1]) {
max[1] = max[1] + 1.0;
min[1] = min[1] - 1.0;
}
// Convert to Float32Array
buffers = vertices.map(function (v) { return new Float32Array(v); });
return {
/**
* Get the dimensions which bound all data in the provided
* data sets. This is given as a two-element array where the
* first element is domain, and second is range.
* @returns {number[]} the dimensions which bound this data set
*/
getDimensions: function () {
return [max[0] - min[0], max[1] - min[1]];
},
/**
* Get the origin of this data set's boundary.
* This is given as a two-element array where the
* first element is domain, and second is range.
* The domain value here is not adjusted by the domain offset.
* @returns {number[]} the origin of this data set's boundary
*/
getOrigin: function () {
return min;
},
/**
* Get the domain offset; this offset will have been subtracted
* from all domain values in all buffers returned by this
* preparer, in order to minimize loss-of-precision due to
* conversion to the 32-bit float format needed by WebGL.
* @returns {number} the domain offset
*/
getDomainOffset: function () {
return domainOffset;
},
/**
* Get all renderable buffers for this data set. This will
* be returned as an array which can be correlated back to
* the provided telemetry data objects (from the constructor
* call) by index.
*
* Internally, these are flattened; each buffer contains a
* sequence of alternating domain and range values.
*
* All domain values in all buffers will have been adjusted
* from their original values by subtraction of the domain
* offset; this minimizes loss-of-precision resulting from
* the conversion to 32-bit floats, which may otherwise
* cause aliasing artifacts (particularly for timestamps)
*
* @returns {Float32Array[]} the buffers for these traces
*/
getBuffers: function () {
return buffers;
}

View File

@ -5,8 +5,22 @@ define(
function () {
"use strict";
/**
* The PlotTickGenerator provides labels for ticks along the
* domain and range axes of the plot, to support the plot
* template.
*
* @constructor
* @param {PlotPanZoomStack} panZoomStack the pan-zoom stack for
* this plot, used to determine plot boundaries
* @param {PlotFormatter} formatter used to format (for display)
* domain and range values.
*/
function PlotTickGenerator(panZoomStack, formatter) {
// Generate ticks; interpolate from start up to
// start + span in count steps, using the provided
// formatter to represent each value.
function generateTicks(start, span, count, format) {
var step = span / (count - 1),
result = [],
@ -23,6 +37,11 @@ define(
return {
/**
* Generate tick marks for the domain axis.
* @param {number} count the number of ticks
* @returns {string[]} labels for those ticks
*/
generateDomainTicks: function (count) {
var panZoom = panZoomStack.getPanZoom();
return generateTicks(
@ -32,6 +51,12 @@ define(
formatter.formatDomainValue
);
},
/**
* Generate tick marks for the range axis.
* @param {number} count the number of ticks
* @returns {string[]} labels for those ticks
*/
generateRangeTicks: function (count) {
var panZoom = panZoomStack.getPanZoom();
return generateTicks(