this
- # TODO: toJSON() must ensure columns in MetricList are ordered by index
- # ...in theory, MetricList.comparator now does this
+ /* * * * TimeSeriesData interface * * * {{{ */
+
+ /**
+ * @returns {Array<Array>} The reified dataset, materialized to a list of rows including timestamps.
+ */
+ getData: ->
+ _.zip ...@getColumns()
- getDates: ->
- dates = @metrics.invoke 'getDates'
+ /**
+ * @returns {Array<Array>} List of all columns (including date column).
+ */
+ getColumns: ->
+ [ @getDateColumn() ].concat @getDataColumns()
+
+ /**
+ * @returns {Array<Date>} The date column.
+ */
+ getDateColumn: ->
+ dates = @metrics.invoke 'getDateColumn'
maxLen = _.max _.pluck dates, 'length'
_.find dates, -> it.length is maxLen
/**
- * @returns {Array} The reified dataset, materialized to an array of data-series arrays.
+ * @returns {Array<Array>} List of all columns except the date column.
*/
- getData: ->
- _.zip ...[ @getDates() ].concat @metrics.invoke 'getData'
+ getDataColumns: ->
+ @metrics.invoke 'getData'
+ /**
+ * @returns {Array<String>} List of column labels.
+ */
getLabels: ->
['Date'].concat @metrics.pluck 'label'
+ # }}}
+
+
newMetric: ->
index = @metrics.length
@metrics.add m = new Metric { index, color:ColorBrewer.Spectral[11][index] }
m
-
onMetricChange: ->
@metrics.reset @get 'metrics'
+ # TODO: toJSON() must ensure columns in MetricList are ordered by index
+ # ...in theory, MetricList.comparator now does this
+
+
# }}}
@rebuildDerived()
+ /* * * * TimeSeriesData interface * * * */
+
+
+ /**
+ * @returns {Array<Array>} List of rows, each of which includes all columns.
+ */
+ getData: ->
+ @data
+
+ /**
+ * @returns {Array<Array>} List of all columns (including date column).
+ */
+ getColumns: ->
+ @columns
+
+ /**
+ * @returns {Array<Date>} The date column.
+ */
+ getDateColumn: ->
+ @dateColumn
+
+ /**
+ * @returns {Array<Array>} List of all columns except the date column.
+ */
+ getDataColumns: ->
+ @dataColumns
+
+ /**
+ * @returns {Array<String>} List of column labels.
+ */
+ getLabels: ->
+ @labels
+
/* * * * Parsing * * * */
/**
- * Stub. Subclass and override to perform preprocessing of the data.
+ * Subclass and override to perform preprocessing of the data.
+ * @private
*/
parse : (rawData) ->
this
/**
* Rebuilds the row-oriented data matrix from the columns.
+ * @private
*/
rebuildData: ->
@rows = _.zip ...@columns
/**
* Rebuilds the column-oriented data matrix from the columns.
+ * @private
*/
rebuildColumns: ->
@columns = _.zip ...@rows
@rebuildDerived()
+ /**
+ * @private
+ */
rebuildDerived: ->
while @transforms.length < @columns.length
@transforms.push []
/* * * * Data Transformation * * * */
+ /**
+ * Applies the stack of transforms to the data.
+ *
+ * TODO: Apply transforms in @getData()?
+ * @private
+ * @returns {this}
+ */
applyTransforms: ->
for fns, idx of @transforms
for fn of fns
@columns[idx] .= map fn, ctx
@rebuildData()
+ /**
+ * Clears all transforms and restores the original data.
+ * @returns {this}
+ */
clearTransforms: ->
@transforms = []
@rows = _.merge [], @untransformedRows
@rebuildColumns()
/**
- * Map a function across the specified columns, one-by-one (in column-major
- * order), replacing the data with the mapped result.
+ * Add a data transform to the specified columns. The function is
+ * applied one-by-one (in column-major order), replacing the data
+ * with the mapped result.
*
* @param {Number|Array} indices List one or more column indices to map. Negative
* numbers are offset from the end of the columns list.
* @param {Function} fn Mapping function of the form:
* `(single_value, row_idx, column) -> new_value`
- * @param {Object} [ctx=this] Execution context.
- * @returns {this}
+ * @param {Object} [ctx=this] Execution context for the function.
+ * @returns {this}
*/
addTransform: (indices, fn, ctx=this) ->
num_cols = @columns.length
@transforms[idx].push fn
@applyTransforms()
+ /**
+ * Add a data transform to all columns except the date column. The function
+ * is applied one-by-one (in column-major order), replacing the data
+ * with the mapped result.
+ *
+ * @param {Function} fn Mapping function of the form:
+ * `(single_value, row_idx, column) -> new_value`
+ * @param {Object} [ctx=this] Execution context for the function.
+ * @returns {this}
+ */
addDataTransform: (fn, ctx=this) ->
@addTransform _.range(1, @columns.length), fn, ctx
/* * * * Misc * * * */
+ /**
+ * @returns {Array<Array>} Deep copy of the data rows (including all columns).
+ */
toJSON: ->
- _.merge [], @rows
+ _.merge [], @getData()
toString: ->
labels = @labels