node-red-contrib-prib-functions 0.18.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -111,8 +111,12 @@ Transformations:
111
111
  * Array to ISO8385
112
112
  * Array to Messages
113
113
  * Array to xlsx / xlsx object (excel uses [xlsx][7])
114
- * AVRO to JSON (uses [avsc][6])
114
+ * AVRO to JSON (uses [avsc][6])
115
+ * Buffer to comprossed
115
116
  * Confluence to JSON
117
+ * Compressed to Buffer
118
+ * Compressed to String
119
+ * COmpressed to JSON
116
120
  * CSV to Array
117
121
  * CSV to HTML
118
122
  * CSV to Messages
@@ -199,7 +203,13 @@ The levenshtein distance between two character strings.
199
203
  Inject messages for a set period of time with varying think time.
200
204
  Primary purpose is testing and useful for load/stress testing.
201
205
 
202
- ![Load Injector](documentation/LoadInjector.JPG "Load Injector")
206
+ Has 3 extra data types
207
+ 1. generated id - Unique id for each message
208
+ 2. generated data - string text generated using [dummy-json][3]
209
+ 3. generated json - json generated using [dummy-json][3]
210
+
211
+
212
+ ![Load Injector](documentation/loadInjector.png "Load Injector")
203
213
 
204
214
  Test example:
205
215
 
@@ -278,27 +288,14 @@ Test/example flow in test/generalTest.json
278
288
 
279
289
  # Version
280
290
 
291
+ 0.19.0 Improve load injector, fix bug in test comparing buffers, add compression tranforms
292
+
281
293
  0.18.0 Add matrix node
282
294
 
283
295
  0.17.0 Add finished wire to load injector
284
296
 
285
- 0.16.10 data analysis add eulcidean distance functions. Add array pairs
286
-
287
297
  0.16.0 fix data analysis variance and stddev, add sample, add tests
288
298
 
289
- 0.14.2 fix general test flows. Add icon for data analysis
290
-
291
- 0.14.1 fix capitalization issue with levenshtein Distance
292
-
293
- 0.14.0 add xlsx transformer
294
-
295
- 0.13.0 Confluence AVRO message converter
296
-
297
- 0.12.0 added xml to json and json to xml. Make snappy installed separately as can cause install issues
298
-
299
- 0.11.1 Fix spelling of AVRO.
300
-
301
- 0.11.0 Transform for AVRO and snappy. Add JSON to CSV
302
299
 
303
300
 
304
301
  # Author
@@ -318,3 +315,5 @@ Test/example flow in test/generalTest.json
318
315
  [6]: https://www.npmjs.com/package/avsc "avsc"
319
316
 
320
317
  [7]: https://www.npmjs.com/package/xlsx "xlsx"
318
+
319
+ [8]: https://www.npmjs.com/package/dummy-json "dummy-json"
@@ -0,0 +1,399 @@
1
+ function PCA() {
2
+ }
3
+ PCA.prototype.computeDeviationMatrix=function(matrix) {
4
+ return this.subtract(matrix, this.scale(this.multiply(this.unitSquareMatrix(matrix.length), matrix), 1 / matrix.length));
5
+ }
6
+ PCA.prototype.computeDeviationScores=function(deviation) {
7
+ return this.multiply(this.transpose(deviation), deviation);
8
+ }
9
+ PCA.prototype.computeVarianceCovariance=function(devSumOfSquares, sample) {
10
+ return this.scale(devSumOfSquares, 1 / (devSumOfSquares.length - sample?1:0));
11
+ }
12
+ PCA.prototype.computeSVD=function((atrix){
13
+ const result = svd(matrix);
14
+ const eigenvectors = result.U;
15
+ const eigenvalues = result.S;
16
+ return eigenvalues.map((value,i)=>{
17
+ return {
18
+ eigenvalue:value,
19
+ vector:eigenvectors.map((vector,j)=>-vector[i]) //HACK prevent completely negative vectors
20
+ }
21
+ });
22
+ }
23
+ // Get reduced dataset after removing some dimensions
24
+ PCA.prototype.computeAdjustedData=function(data, ...vectorObjs){
25
+ const vectors = vectorObjs.map((v)=>v.vector);
26
+ const matrixMinusMean = this.computeDeviationMatrix(data);
27
+ const adjustedData = this.multiply(vectors, this.transpose(matrixMinusMean));
28
+ const unit = this.unitSquareMatrix(data.length);
29
+ const avgData = this.scale(multiply(unit, data), -1 / data.length); //NOTE get the averages to add back
30
+ return {
31
+ adjustedData: adjustedData,
32
+ formattedAdjustedData:formatData(adjustedData, 2),
33
+ avgData: avgData,
34
+ selectedVectors: vectors
35
+ };
36
+ }
37
+ // Get original data set from reduced data set (decompress)
38
+ PCA.prototype.computeOriginalData=function(adjustedData, vectors, avgData) {
39
+ const originalWithoutMean = this.transpose(multiply(transpose(vectors), adjustedData));
40
+ const originalWithMean = this.subtract(originalWithoutMean, avgData);
41
+ return {
42
+ originalData: originalWithMean,
43
+ formattedOriginalData: this.formatData(originalWithMean, 2)
44
+ }
45
+ PCA.prototype.computePercentageExplained=function(vectors, ...selected) {
46
+ const total = vectors.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
47
+ const explained = selected.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
48
+ return (explained / total);
49
+ }
50
+ PCA.prototype.getEigenVectors=function(data) {
51
+ return this.computeSVD(this.computeVarianceCovariance(this.computeDeviationScores(this.computeDeviationMatrix(data)), false));
52
+ }
53
+ PCA.prototype.analyseTopResult=function(data){
54
+ const eigenVectors = this.getEigenVectors(data);
55
+ const sorted = this.eigenVectors.sort((a, b)=>b.eigenvalue-a.eigenvalue);
56
+ const selected = sorted[0].vector;
57
+ return this.computeAdjustedData(data, selected);
58
+ }
59
+ PCA.prototype.formatData=function(data, precision) {
60
+ const factor= Math.pow(10, precision || 2);
61
+ return data.map((d,i)=>d.map((n)=>Math.round(n * factor) / factor))
62
+ }
63
+ PCA.prototype.testMatrix=function(a){
64
+ if(!a[0] || !a.length) throw Error("Not matrix")
65
+ }
66
+ PCA.prototype.multiply=function(a, b){
67
+ this.testMatrix(a);
68
+ this.testMatrix(b);
69
+ if(b.length !== a[0].length) throw new Error('Columns in A should be the same as the number of rows in B');
70
+ const product = [];
71
+ for(let i = 0; i < a.length; i++) {
72
+ product[i] = []; //initialize a new row
73
+ for (var j = 0; j < b[0].length; j++) {
74
+ for (var k = 0; k < a[0].length; k++) {
75
+ (product[i])[j] = !!(product[i])[j] ? (product[i])[j] + (a[i])[k] * (b[k])[j] : (a[i])[k] * (b[k])[j];
76
+ }
77
+ }
78
+ }
79
+ return product;
80
+ }
81
+ PCA.prototype.subtract=function(a,b) {
82
+ if(!(a.length === b.length && a[0].length === b[0].length)) throw Error('Both A and B should have the same dimensions');
83
+ const result=[];
84
+ for(let i=0;i< a.length;i++){
85
+ result[i]=[];
86
+ for (let j = 0; j < b[0].length; j++) {
87
+ (result[i])[j] = (a[i])[j] - (b[i])[j];
88
+ }
89
+ }
90
+ return result;
91
+ }
92
+ PCA.prototype.scale=function(matrix, factor) {
93
+ const result = [];
94
+ for(let i = 0; i < matrix.length; i++) {
95
+ result[i] = [];
96
+ for(let j = 0; j < matrix[0].length; j++) {
97
+ (result[i])[j] = (matrix[i])[j] * factor;
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ PCA.prototype.unitSquareMatrix=function(rows) {
103
+ const result = [];
104
+ for(let i = 0; i < rows; i++) {
105
+ result[i] = [];
106
+ for (var j = 0; j < rows; j++) {
107
+ (result[i])[j] = 1;
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+ PCA.prototype.transpose=function(matrix) {
113
+ const operated = this.clone(matrix);
114
+ return operated[0].map((m,c)=>matrix.map((r)=>r[c]));
115
+ }
116
+ PCA.prototype.clone=function(m) {
117
+ return m.map(r=>r.map(c=>c));
118
+ }
119
+ PCA.prototype.svd=function(A) {
120
+ let temp;
121
+ const prec = Math.pow(2, -52) // double presision
122
+ const tolerance = 1.e-64 // precision;
123
+ const itmax = 50;
124
+ let c = 0;
125
+ let i = 0;
126
+ let j = 0;
127
+ let k = 0;
128
+ let l = 0;
129
+ const u = this.clone(A);
130
+ const m = u.length;
131
+ const n = u[0].length;
132
+ if (m < n) throw "Need more rows than columns"
133
+
134
+ const e = new Array(n); //vector1
135
+ const q = new Array(n); //vector2
136
+ for (i = 0; i < n; i++) e[i] = q[i] = 0.0;
137
+ var v = rep([n, n], 0);
138
+
139
+ function pythag(a, b) {
140
+ a = Math.abs(a)
141
+ b = Math.abs(b)
142
+ if(a > b) return a * Math.sqrt(1.0 + (b * b / a / a))
143
+ if(b == 0.0) return a
144
+ return b * Math.sqrt(1.0 + (a * a / b / b))
145
+ }
146
+ function rep(s, v, k=0) {
147
+ const n=s[k],
148
+ ret=Array(n);
149
+ let i;
150
+ if(k === s.length - 1) {
151
+ for(i=n-2; i >= 0; i-=2) {
152
+ ret[i+1] = v;
153
+ ret[i] = v;
154
+ }
155
+ if(i === -1) ret[0] = v;
156
+ return ret;
157
+ }
158
+ const kPlusOne=k++;
159
+ for (i= n-1; i>=0; i--) {
160
+ ret[i] = rep(s, v, kPlusOne);
161
+ }
162
+ return ret;
163
+ }
164
+ let f = 0.0;
165
+ let g = 0.0;
166
+ let h = 0.0;
167
+ let x = 0.0;
168
+ let y = 0.0;
169
+ let z = 0.0;
170
+ let s = 0.0;
171
+
172
+ for(i=0; i<n; i++) {
173
+ e[i] = g; //vector
174
+ s = 0.0; //sum
175
+ l = i+1; //stays i+1
176
+ for(j=i; j<m; j++)
177
+ s += (u[j][i] * u[j][i]);
178
+ if(s <= tolerance)
179
+ g = 0.0;
180
+ else {
181
+ f = u[i][i];
182
+ g = Math.sqrt(s);
183
+ if(f >= 0.0) g = -g;
184
+ h = f * g - s
185
+ u[i][i] = f - g;
186
+ for(j=l; j<n; j++) {
187
+ s = 0.0
188
+ for(k=i; k < m; k++)
189
+ s += u[k][i] * u[k][j]
190
+ f = s / h
191
+ for(k=i; k<m; k++)
192
+ u[k][j] += f * u[k][i]
193
+ }
194
+ }
195
+ q[i] = g
196
+ s = 0.0
197
+ for(j=l; j<n; j++)
198
+ s = s + u[i][j] * u[i][j]
199
+ if (s <= tolerance)
200
+ g = 0.0
201
+ else {
202
+ f = u[i][i + 1]
203
+ g = Math.sqrt(s)
204
+ if (f >= 0.0) g = -g
205
+ h = f * g - s
206
+ u[i][i + 1] = f - g;
207
+ for(j=l; j < n; j++) e[j] = u[i][j] / h
208
+ for(j=l; j < m; j++) {
209
+ s = 0.0
210
+ for(k=l; k<n; k++)
211
+ s += (u[j][k] * u[i][k])
212
+ for(k=l; k<n; k++)
213
+ u[j][k] += s * e[k]
214
+ }
215
+ }
216
+ y = Math.abs(q[i]) + Math.abs(e[i])
217
+ if(y > x)
218
+ x = y
219
+ }
220
+
221
+ // accumulation of right hand transformations
222
+ for(i = n-1; i!=-1; i--) {
223
+ if (g != 0.0) {
224
+ h = g * u[i][i + 1]
225
+ for (j = l; j < n; j++)
226
+ v[j][i] = u[i][j] / h //u is array, v is square of columns
227
+ for (j = l; j < n; j++) {
228
+ s = 0.0
229
+ for (k = l; k < n; k++)
230
+ s += u[i][k] * v[k][j]
231
+ for (k = l; k < n; k++)
232
+ v[k][j] += (s * v[k][i])
233
+ }
234
+ }
235
+ for (j = l; j < n; j++) {
236
+ v[i][j] = 0;
237
+ v[j][i] = 0;
238
+ }
239
+ v[i][i] = 1;
240
+ g = e[i]
241
+ l = i
242
+ }
243
+
244
+ // accumulation of left hand transformations
245
+ for(i=n-1; i != -1; i += -1) {
246
+ l = i + 1
247
+ g = q[i]
248
+ for (j = l; j < n; j++)
249
+ u[i][j] = 0;
250
+ if (g != 0.0) {
251
+ h = u[i][i] * g
252
+ for (j = l; j < n; j++) {
253
+ s = 0.0
254
+ for (k = l; k < m; k++) s += u[k][i] * u[k][j];
255
+ f = s / h
256
+ for (k = i; k < m; k++) u[k][j] += f * u[k][i];
257
+ }
258
+ for (j = i; j < m; j++) u[j][i] = u[j][i] / g;
259
+ } else
260
+ for (j = i; j < m; j++) u[j][i] = 0;
261
+ u[i][i] += 1;
262
+ }
263
+
264
+ // diagonalization of the bidiagonal form
265
+ prec = prec * x
266
+ for(k=n-1; k != -1; k--) {
267
+ const kPlusOne=k+1;
268
+ const kMinusOne=k-1;
269
+ for(let iteration = 0; iteration < itmax; iteration++) { // test f splitting
270
+ let test_convergence = false
271
+ for(l=k; l != -1; l--) {
272
+ if(Math.abs(e[l]) <= prec) {
273
+ test_convergence = true
274
+ break
275
+ }
276
+ if (Math.abs(q[l - 1]) <= prec)
277
+ break
278
+ }
279
+ if (!test_convergence) { // cancellation of e[l] if l>0
280
+ c = 0.0
281
+ s = 1.0
282
+ const l1 = l - 1
283
+ for(i=l; i<kPlusOne; i++) {
284
+ f = s * e[i]
285
+ e[i] = c * e[i]
286
+ if (Math.abs(f) <= prec)
287
+ break
288
+ g = q[i]
289
+ h = pythag(f, g)
290
+ q[i] = h
291
+ c = g / h
292
+ s = -f / h
293
+ for(j = 0; j<m; j++) {
294
+ y = u[j][l1]
295
+ z = u[j][i]
296
+ u[j][l1] = y * c + (z * s)
297
+ u[j][i] = -y * s + (z * c)
298
+ }
299
+ }
300
+ }
301
+ // test f convergence
302
+ z = q[k]
303
+ if(l == k) { //convergence
304
+ if(z < 0.0) { //q[k] is made non-negative
305
+ q[k] = -z
306
+ for (j=0; j<n; j++)
307
+ v[j][k] = -v[j][k]
308
+ }
309
+ break //break out of iteration loop and move on to next k value
310
+ }
311
+ if (iteration >= itmax - 1)
312
+ throw 'Error: no convergence.'
313
+ // shift from bottom 2x2 minor
314
+ x = q[l]
315
+ y = q[kMinusOne]
316
+ g = e[kMinusOne]
317
+ h = e[k]
318
+ f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
319
+ g = pythag(f, 1.0)
320
+ if(f < 0.0)
321
+ f = ((x - z) * (x + z) + h * (y / (f - g) - h)) / x
322
+ else
323
+ f = ((x - z) * (x + z) + h * (y / (f + g) - h)) / x
324
+ // next QR transformation
325
+ c = 1.0
326
+ s = 1.0
327
+ for(i=l+1; i<kPlusOne; i++) {
328
+ g = e[i]
329
+ y = q[i]
330
+ h = s * g
331
+ g = c * g
332
+ z = pythag(f, h)
333
+ e[i - 1] = z
334
+ c = f / z
335
+ s = h / z
336
+ f = x * c + g * s
337
+ g = -x * s + g * c
338
+ h = y * s
339
+ y = y * c
340
+ for (j = 0; j < n; j++) {
341
+ x = v[j][i - 1]
342
+ z = v[j][i]
343
+ v[j][i - 1] = x * c + z * s
344
+ v[j][i] = -x * s + z * c
345
+ }
346
+ z = pythag(f, h)
347
+ q[i - 1] = z
348
+ c = f / z
349
+ s = h / z
350
+ f = c * g + s * y
351
+ x = -s * g + c * y
352
+ for (j = 0; j < m; j++) {
353
+ y = u[j][i - 1]
354
+ z = u[j][i]
355
+ u[j][i - 1] = y * c + z * s
356
+ u[j][i] = -y * s + z * c
357
+ }
358
+ }
359
+ e[l] = 0.0
360
+ e[k] = f
361
+ q[k] = x
362
+ }
363
+ }
364
+ const ql=q.length;
365
+ for(i=0; i<ql; i++)
366
+ if (q[i] < prec) q[i] = 0
367
+
368
+ //sort eigenvalues
369
+ for(i=0; i<n; i++) {
370
+ for(j=i-1; j>=0; j--) {
371
+ if(q[j] < q[i]) {
372
+ c = q[j]
373
+ q[j] = q[i]
374
+ q[i] = c
375
+ const ul=u.length;
376
+ for(k = 0; k< ul; k++) {
377
+ temp = u[k][i];
378
+ u[k][i] = u[k][j];
379
+ u[k][j] = temp;
380
+ }
381
+ const vl=v.length;
382
+ for(k=0; k<vl; k++) {
383
+ temp = v[k][i];
384
+ v[k][i] = v[k][j];
385
+ v[k][j] = temp;
386
+ }
387
+ i = j
388
+ }
389
+ }
390
+ }
391
+ return {
392
+ U: u,
393
+ S: q,
394
+ V: v
395
+ }
396
+ }
397
+ }
398
+
399
+ module.exports = PCA;
Binary file
package/matrix/matrix.js CHANGED
@@ -30,7 +30,12 @@ Matrix.prototype.addCell=function(row,column,value){
30
30
  this.vector[this.getIndex(row,column)]+=value;
31
31
  return this;
32
32
  }
33
- Matrix.prototype.addRow=function(vector){
33
+ Matrix.prototype.addRow=function(row,vectorIn){
34
+ if(vectorIn & row>=0){
35
+ this.forRowCells(row,(value,column,offset,vector)=>vector[offset]+=vectorIn[column]);
36
+ return this;
37
+ }
38
+ const vector=vectorIn?vectorIn:row;
34
39
  if(this.size==this.sizeMax){
35
40
  this.vector.copyWithin(0,this.columns,this.sizeMax);
36
41
  this.rows--;
@@ -172,7 +177,7 @@ Matrix.prototype.fillArray=function(a){
172
177
  Matrix.prototype.findColumnRow=function(column,call,startRow=0,endRow=this.rows-1){
173
178
  let offset=startRow*this.columns+column;
174
179
  for(let row=startRow;row<=this.rows;row++){
175
- if(call.apply(this,[this.vector[offset],row,offset,this.vector])) {
180
+ if(call.apply(this,[this.vector[offset],row,column,offset,this.vector])) {
176
181
  return row;
177
182
  }
178
183
  offset+=this.columns;
@@ -205,6 +210,17 @@ Matrix.prototype.forEachCell=function(call){
205
210
  }
206
211
  return this;
207
212
  }
213
+ Matrix.prototype.forEachCellLowerTriangle=function(call){
214
+ this.testIsSquare();
215
+ for(let row=0;row<this.rows;row++) {
216
+ let offset=row*this.columns;
217
+ for(let column=0;column<=row;column++) {
218
+ call.apply(this,[this.vector[offset],row,column,this.vector,offset,this]);
219
+ offset++
220
+ }
221
+ }
222
+ return this;
223
+ }
208
224
  Matrix.prototype.forEachCellPairSet=function(matrix,call){
209
225
  if(matrix instanceof Matrix){
210
226
  if(this.rows!=matrix.rows) throw Error("number of rows different");
@@ -223,6 +239,17 @@ Matrix.prototype.forEachCellPairSet=function(matrix,call){
223
239
  }
224
240
  return this;
225
241
  }
242
+ Matrix.prototype.forEachCellUpperTriangle=function(call){
243
+ this.testIsSquare();
244
+ for(let row=0;row<this.rows;row++) {
245
+ let offset=row*this.columns;
246
+ for(let column=row;column<=this.columns;column++) {
247
+ call.apply(this,[this.vector[offset],row,column,this.vector,offset,this]);
248
+ offset++
249
+ }
250
+ }
251
+ return this;
252
+ }
226
253
  Matrix.prototype.forEachRow=function(call){
227
254
  for(let row=0;row<this.rows;row++) {
228
255
  const rowVector=this.getRow(row);
@@ -386,6 +413,11 @@ Matrix.prototype.getRow=function(row){
386
413
  const start=row*this.columns;
387
414
  return this.vector.subarray(start,start+this.columns);
388
415
  }
416
+ Matrix.prototype.getVandermonde=function(vectorIn,columns){
417
+ const matrix = new Matrix(vectorIn.length,columns);
418
+ matrix.forEachCell((cell,row,column,vector,offset,object)=>vector[offset]=vectorIn[row]**column)
419
+ return matrix;
420
+ }
389
421
  Matrix.prototype.getZeroed=function(row, column){
390
422
  const offset=row*this.columns+column;
391
423
  const value=this.vector[offset];
@@ -439,6 +471,16 @@ Matrix.prototype.multiplyRow=function(row,factor){
439
471
  this.forRowCells(row,(cell,column,offset,vector)=>vector[offset]*=factor)
440
472
  return this;
441
473
  }
474
+ Matrix.prototype.norm=function(){
475
+
476
+ return Math.sqrt(this.reduce((aggregate,cell)=>aggregate+cell*cell))
477
+ }
478
+ Matrix.prototype.reduce=function(call,aggregate=0){
479
+ this.forEachCell((cell,row,column,vector,offset,object)=>
480
+ aggregate=call.apply(this,[aggregate,cell,row,column,vector,offset,object])
481
+ );
482
+ return aggregate;
483
+ }
442
484
  Matrix.prototype.reducedRowEchelonForm=function(){
443
485
  const lastColumn=this.columns-1;
444
486
  for(let pivotColumn=0,pivotRow=0;pivotRow<this.rows;pivotRow++){
@@ -526,6 +568,10 @@ Matrix.prototype.setRow=function(vector,row){
526
568
  this.vector.set(vector, row*this.columns);
527
569
  return this;
528
570
  }
571
+ Matrix.prototype.setRunningSum=function(){
572
+ this.forEachCellLowerTriangle((cell,row,column,vector,offset,object)=>vector[offset]=1);
573
+ return this;
574
+ }
529
575
  Matrix.prototype.substract=function(matrix){
530
576
  this.forEachCellPairSet(matrix,(cellA,cellB)=>cellA-cellB)
531
577
  return this;