Skip to content

Commit b11a2c9

Browse files
committed
feat: add support for getting and setting individual data elements
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent d1b8126 commit b11a2c9

File tree

5 files changed

+373
-7
lines changed

5 files changed

+373
-7
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var randi = require( '@stdlib/random/base/discrete-uniform' );
22+
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
23+
var filled2dBy = require( '@stdlib/array/base/filled2d-by' );
24+
var ColumnChart = require( '@stdlib/plot/sparklines/unicode/column' );
25+
var TristateChart = require( '@stdlib/plot/sparklines/unicode/tristate' );
26+
var LineChart = require( '@stdlib/plot/sparklines/unicode/line' );
27+
var stdout = require( '@stdlib/streams/node/stdout' );
28+
var UnicodeTable = require( './../lib' );
29+
30+
// Generate some random data sets:
31+
var x0 = discreteUniform( 10, 0, 100, {
32+
'dtype': 'float64'
33+
});
34+
var x1 = discreteUniform( 10, -1, 1, {
35+
'dtype': 'int8'
36+
});
37+
var x2 = discreteUniform( 10, 0, 100, {
38+
'dtype': 'float64'
39+
});
40+
41+
// Create various sparkline charts:
42+
var chart0 = new ColumnChart( x0, {
43+
'yMin': 0,
44+
'yMax': 100,
45+
'bufferSize': 10
46+
});
47+
var chart1 = new TristateChart( x1, {
48+
'bufferSize': 10
49+
});
50+
var chart2 = new LineChart( x2, {
51+
'yMin': 0,
52+
'yMax': 100,
53+
'bufferSize': 10
54+
});
55+
56+
// Add the charts to a hash:
57+
var charts = [
58+
chart0,
59+
chart1,
60+
chart2
61+
];
62+
63+
// Define the number of table rows and columns:
64+
var nrows = 3;
65+
var ncols = 4;
66+
67+
// Define a callback for generating a data set:
68+
function clbk( indices ) {
69+
if ( indices[ 1 ] < ncols-1 ) {
70+
return indices[ 0 ];
71+
}
72+
return charts[ indices[ 0 ] ].render();
73+
}
74+
75+
// Create a data set:
76+
var data = filled2dBy( [ nrows, ncols ], clbk );
77+
78+
// Define column headers:
79+
var headers = [ 'Row', 'Col 1', 'Col 2', 'Sparkline' ];
80+
81+
// Create a table:
82+
var table = new UnicodeTable( data, {
83+
'headers': headers,
84+
'rowSeparator': '-',
85+
'align': 'right',
86+
'marginLeft': 5
87+
});
88+
89+
// Render the table:
90+
var str = table.render();
91+
stdout.write( str+'\n' );
92+
93+
// Compute the number of lines:
94+
var N = str.split( '\n' ).length;
95+
96+
// Created a throttled event listener:
97+
var listener = throttledListener( onUpdate, 250 );
98+
99+
// Listen for change events:
100+
var i;
101+
for ( i = 0; i < charts.length; i++ ) {
102+
charts[ i ].on( 'change', listener );
103+
}
104+
105+
// Periodically update the sparkline charts with new data:
106+
var id = setInterval( update, 1000 );
107+
108+
// After some time, stop updating and close:
109+
setTimeout( onTimeout, 11000 );
110+
111+
function throttledListener( clbk, limit ) {
112+
var flg = false;
113+
return listener;
114+
115+
function listener() {
116+
if ( flg ) {
117+
return;
118+
}
119+
flg = true;
120+
setTimeout( onTimeout, limit );
121+
}
122+
123+
function onTimeout() {
124+
flg = false;
125+
clbk();
126+
}
127+
}
128+
129+
function update() {
130+
// Push data to the individual charts:
131+
chart0.push( randi( 0, 100 ) );
132+
chart1.push( randi( -1, 1 ) );
133+
chart2.push( randi( 0, 100 ) );
134+
}
135+
136+
function onUpdate() {
137+
var i;
138+
139+
// Re-render the sparklines:
140+
for ( i = 0; i < charts.length; i++ ) {
141+
table.set( i, ncols-1, charts[ i ].render() );
142+
}
143+
// Remove the previously rendered table:
144+
clearPreviousLines( N );
145+
146+
// Re-render the table:
147+
stdout.write( table.render()+'\n' );
148+
}
149+
150+
function onTimeout() {
151+
clearInterval( id );
152+
}
153+
154+
function clearPreviousLines( count ) {
155+
var i;
156+
for ( i = 0; i < count; i++ ) {
157+
stdout.write( '\x1b[F' ); // move cursor up one line
158+
stdout.write( '\x1b[2K' ); // clear entire line
159+
}
160+
}

lib/node_modules/@stdlib/plot/table/unicode/examples/streaming.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ var UnicodeTable = require( './../lib' );
2727
var nrows = 10;
2828
var ncols = 5;
2929

30-
// Generate a data set:
30+
// Define initial bounds for generated data:
3131
var start = 0;
3232
var end = 49;
33+
34+
// Generate a data set:
3335
var data = array( linspace( start, end, nrows*ncols ), {
3436
'shape': [ nrows, ncols ]
3537
});
@@ -57,14 +59,23 @@ stdout.write( str+'\n' );
5759
var N = str.split( '\n' ).length;
5860

5961
// Periodically update the table with new data:
60-
var id = setInterval( onInterval, 2000 );
62+
var id = setInterval( update, 2000 );
63+
64+
// After some time, stop updating and close:
6165
setTimeout( onTimeout, 11000 );
6266

63-
function onInterval() {
67+
function update() {
68+
// Update data bounds:
6469
start = end;
6570
end += ncols - 1;
71+
72+
// Push a new row to the table:
6673
table.push( linspace( start, end, ncols ) );
74+
75+
// Remove the previously rendered table:
6776
clearPreviousLines( N );
77+
78+
// Re-render the table:
6879
stdout.write( table.render()+'\n' );
6980
}
7081

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/* eslint-disable no-invalid-this */
20+
21+
'use strict';
22+
23+
// MODULES //
24+
25+
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
26+
var numelDimension = require( '@stdlib/ndarray/base/numel-dimension' );
27+
var format = require( '@stdlib/string/format' );
28+
29+
30+
// MAIN //
31+
32+
/**
33+
* Retrieves a single data element from a table.
34+
*
35+
* @private
36+
* @param {NonNegativeInteger} i - index for the first dimension (i.e., zero-based row number)
37+
* @param {NonNegativeInteger} j - index for the second dimension (i.e., zero-based column number)
38+
* @throws {TypeError} first argument must be a nonnegative integer
39+
* @throws {TypeError} second argument must be a nonnegative integer
40+
* @throws {RangeError} index is out-of-bounds
41+
* @returns {*} data element
42+
*/
43+
function get( i, j ) {
44+
var nrows;
45+
var ncols;
46+
if ( !isNonNegativeInteger( i ) ) {
47+
throw new TypeError( format( 'invalid argument. First argument must be a nonnegative integer. Value: `%s`.', i ) );
48+
}
49+
if ( !isNonNegativeInteger( j ) ) {
50+
throw new TypeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%s`.', j ) );
51+
}
52+
nrows = numelDimension( this._data, 0 );
53+
if ( i >= nrows ) {
54+
throw new RangeError( format( 'invalid argument. First argument must be on the interval: [0,%u]. Value: `%s`.', nrows-1, i ) );
55+
}
56+
ncols = numelDimension( this._data, 1 );
57+
if ( j >= ncols ) {
58+
throw new RangeError( format( 'invalid argument. Second argument must be on the interval: [0,%u]. Value: `%s`.', ncols-1, j ) );
59+
}
60+
return this._data.get( i, j ).raw;
61+
}
62+
63+
64+
// EXPORTS //
65+
66+
module.exports = get;

lib/node_modules/@stdlib/plot/table/unicode/lib/main.js

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
var EventEmitter = require( 'events' ).EventEmitter;
2424
var logger = require( 'debug' );
25-
var setReadWriteAccessor = require( '@stdlib/utils/define-read-write-accessor' );
25+
var setReadWriteAccessor = require( '@stdlib/utils/define-nonenumerable-read-write-accessor' );
26+
var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
2627
var defineProperty = require( '@stdlib/utils/define-property' );
2728
var objectKeys = require( '@stdlib/utils/keys' );
2829
var inherit = require( '@stdlib/utils/inherit' );
@@ -102,6 +103,8 @@ var getVerticalSeparatorMode = require( './props/vertical-separator-mode/get.js'
102103
var defaults = require( './defaults.js' );
103104
var render = require( './render.js' );
104105
var push = require( './push.js' );
106+
var getter = require( './get.js' );
107+
var setter = require( './set.js' );
105108

106109

107110
// VARIABLES //
@@ -1040,6 +1043,32 @@ setReadWriteAccessor( UnicodeTable.prototype, 'rowSeparator', getRowSeparator, s
10401043
*/
10411044
setReadWriteAccessor( UnicodeTable.prototype, 'verticalSeparatorMode', getVerticalSeparatorMode, setVerticalSeparatorMode );
10421045

1046+
/**
1047+
* Retrieves a single data element from a table.
1048+
*
1049+
* @name get
1050+
* @memberof UnicodeTable.prototype
1051+
* @type {Function}
1052+
* @param {NonNegativeInteger} i - index for the first dimension (i.e., zero-based row number)
1053+
* @param {NonNegativeInteger} j - index for the second dimension (i.e., zero-based column number)
1054+
* @throws {TypeError} first argument must be a nonnegative integer
1055+
* @throws {TypeError} second argument must be a nonnegative integer
1056+
* @throws {RangeError} index is out-of-bounds
1057+
* @returns {*} data element
1058+
*
1059+
* @example
1060+
* var table = new UnicodeTable( [ [ 1, 2 ], [ 3, 4 ] ], {
1061+
* 'headers': [ 'A', 'B' ]
1062+
* });
1063+
*
1064+
* var v = table.get( 0, 0 );
1065+
* // returns 1
1066+
*
1067+
* v = table.get( 1, 1 );
1068+
* // returns 4
1069+
*/
1070+
setReadOnly( UnicodeTable.prototype, 'get', getter );
1071+
10431072
/**
10441073
* Appends one or more rows to a table.
10451074
*
@@ -1049,7 +1078,7 @@ setReadWriteAccessor( UnicodeTable.prototype, 'verticalSeparatorMode', getVertic
10491078
* @param {(Object|Collection|VectorLike|MatrixLike)} data - row(s) to add
10501079
* @throws {TypeError} must provide an object, an array-like object, or an ndarray
10511080
* @throws {TypeError} must provide data containing the correct number of columns
1052-
* @returns {UnicodeTable} class instance
1081+
* @returns {UnicodeTable} table instance
10531082
*
10541083
* @example
10551084
* var ndarray2array = require( '@stdlib/ndarray/to-array' );
@@ -1062,7 +1091,7 @@ setReadWriteAccessor( UnicodeTable.prototype, 'verticalSeparatorMode', getVertic
10621091
* data = ndarray2array( table.data );
10631092
* // returns [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]
10641093
*/
1065-
UnicodeTable.prototype.push = push;
1094+
setReadOnly( UnicodeTable.prototype, 'push', push );
10661095

10671096
/**
10681097
* Renders a table.
@@ -1081,7 +1110,36 @@ UnicodeTable.prototype.push = push;
10811110
* var str = table.render();
10821111
* // returns '...'
10831112
*/
1084-
UnicodeTable.prototype.render = render;
1113+
setReadOnly( UnicodeTable.prototype, 'render', render );
1114+
1115+
/**
1116+
* Sets a single data element in a table to a specified value.
1117+
*
1118+
* @name set
1119+
* @memberof UnicodeTable.prototype
1120+
* @type {Function}
1121+
* @param {NonNegativeInteger} i - index for the first dimension (i.e., zero-based row number)
1122+
* @param {NonNegativeInteger} j - index for the second dimension (i.e., zero-based column number)
1123+
* @param {*} value - value to set
1124+
* @throws {TypeError} first argument must be a nonnegative integer
1125+
* @throws {TypeError} second argument must be a nonnegative integer
1126+
* @throws {RangeError} index is out-of-bounds
1127+
* @returns {UnicodeTable} table instance
1128+
*
1129+
* @example
1130+
* var table = new UnicodeTable( [ [ 1, 2 ], [ 3, 4 ] ], {
1131+
* 'headers': [ 'A', 'B' ]
1132+
* });
1133+
*
1134+
* var v = table.get( 1, 0 );
1135+
* // returns 3
1136+
*
1137+
* table.set( 1, 0, 5 );
1138+
*
1139+
* v = table.get( 1, 0 );
1140+
* // returns 5
1141+
*/
1142+
setReadOnly( UnicodeTable.prototype, 'set', setter );
10851143

10861144

10871145
// EXPORTS //

0 commit comments

Comments
 (0)