@lhncbc/ucum-lhc 5.0.0 → 5.0.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.
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.UnitTables = void 0;
7
-
8
7
  /**
9
8
  * This class manages Hashtables that provide references to
10
9
  * defined units.
@@ -12,8 +11,8 @@ exports.UnitTables = void 0;
12
11
  * @author Lee Mericle, based on java version by Gunther Schadow
13
12
  *
14
13
  */
15
- var Ucum = require('./config.js').Ucum;
16
14
 
15
+ var Ucum = require('./config.js').Ucum;
17
16
  class UnitTablesFactory {
18
17
  /**
19
18
  * Constructor. This creates the empty unit tables (hashes) once. After the
@@ -44,6 +43,7 @@ class UnitTablesFactory {
44
43
  * with the code = "s" and the unit with code = "'".
45
44
  */
46
45
  this.unitNames_ = {};
46
+
47
47
  /**
48
48
  * Tracks units by code using case-sensitive version.
49
49
  *
@@ -51,24 +51,24 @@ class UnitTablesFactory {
51
51
  * value is the reference to the Unit object. Codes must
52
52
  * be unique.
53
53
  */
54
-
55
54
  this.unitCodes_ = {};
55
+
56
56
  /**
57
57
  * Keeps track of the order in which units are defined. The order is
58
58
  * important because unit definitions build on previous definitions.
59
59
  *
60
60
  * @type {Array}
61
61
  */
62
-
63
62
  this.codeOrder_ = [];
63
+
64
64
  /**
65
65
  * Tracks units by unit strings, e.g., cm-1
66
66
  *
67
67
  * @type hash - key is the unit string
68
68
  * value is an array of unit objects with that ciUnitString.
69
69
  */
70
-
71
70
  this.unitStrings_ = {};
71
+
72
72
  /**
73
73
  * Tracks units by Dimension vector
74
74
  *
@@ -79,8 +79,8 @@ class UnitTablesFactory {
79
79
  * unit vector, and this can be used to provide a list
80
80
  * of commensurable units.
81
81
  */
82
-
83
82
  this.unitDimensions_ = {};
83
+
84
84
  /**
85
85
  * Maps synonyms to units. Not built until first requested.
86
86
  *
@@ -88,8 +88,8 @@ class UnitTablesFactory {
88
88
  * value is an array of references to Unit objects that
89
89
  * include that synonym.
90
90
  */
91
-
92
91
  this.unitSynonyms_ = {};
92
+
93
93
  /*
94
94
  * Holds onto the index of the index of the dimension vector flag for
95
95
  * the base mass unit (gram). This is set when the base unit (gram) is
@@ -99,25 +99,24 @@ class UnitTablesFactory {
99
99
  *
100
100
  * @type integer
101
101
  */
102
-
103
102
  this.massDimIndex_ = 0;
103
+
104
104
  /**
105
105
  * Map of indices in the dimension vector to base unit symbols.
106
106
  */
107
-
108
107
  this.dimVecIndexToBaseUnit_ = {};
109
108
  }
109
+
110
110
  /**
111
111
  * Provides the number of unit objects written to the tables, using the
112
112
  * codes table since codes must be unique.
113
113
  *
114
114
  * @returns count of the number of unit objects in the unitCodes_ table.
115
115
  */
116
-
117
-
118
116
  unitsCount() {
119
117
  return Object.keys(this.unitCodes_).length;
120
118
  }
119
+
121
120
  /**
122
121
  * Adds a Unit object to the tables.
123
122
  *
@@ -126,32 +125,25 @@ class UnitTablesFactory {
126
125
  * @throws passes on an error if one is thrown by the called functions for
127
126
  * a problem with the unit code or unit name
128
127
  */
129
-
130
-
131
128
  addUnit(theUnit) {
132
129
  let uName = theUnit['name_'];
133
-
134
130
  if (uName) {
135
131
  this.addUnitName(theUnit);
136
132
  }
137
-
138
133
  this.addUnitCode(theUnit);
139
134
  this.addUnitString(theUnit);
140
-
141
135
  try {
142
136
  if (theUnit['dim_'].getProperty('dimVec_')) this.addUnitDimension(theUnit);
143
- } catch (err) {// do nothing - throws error if the property is null
137
+ } catch (err) {
138
+ // do nothing - throws error if the property is null
144
139
  // and that's OK here.
145
140
  }
146
-
147
141
  if (theUnit.isBase_) {
148
142
  const dimVec = theUnit.dim_.dimVec_;
149
143
  let nonZeroIndex;
150
-
151
144
  for (let i = 0, len = dimVec.length; nonZeroIndex == undefined && i < len; ++i) {
152
145
  if (dimVec[i] != 0) nonZeroIndex = i;
153
146
  }
154
-
155
147
  this.dimVecIndexToBaseUnit_[nonZeroIndex] = theUnit.csCode_;
156
148
  }
157
149
  } // end addUnit
@@ -168,11 +160,8 @@ class UnitTablesFactory {
168
160
  * @returns nothing
169
161
  * @throws an error if the unit has no name
170
162
  */
171
-
172
-
173
163
  addUnitName(theUnit) {
174
164
  let uName = theUnit['name_'];
175
-
176
165
  if (uName) {
177
166
  if (this.unitNames_[uName]) this.unitNames_[uName].push(theUnit);else this.unitNames_[uName] = [theUnit];
178
167
  } else throw new Error('UnitTables.addUnitName called for a unit with no name. ' + `Unit code = ${theUnit['csCode_']}.`);
@@ -188,22 +177,16 @@ class UnitTablesFactory {
188
177
  * @throws an error if the unitCodes_ table already contains a unit with
189
178
  * the code
190
179
  */
191
-
192
-
193
180
  addUnitCode(theUnit) {
194
181
  let uCode = theUnit['csCode_'];
195
-
196
182
  if (uCode) {
197
183
  if (this.unitCodes_[uCode]) throw new Error(`UnitTables.addUnitCode called, already contains entry for ` + `unit with code = ${uCode}`);else {
198
184
  this.unitCodes_[uCode] = theUnit;
199
185
  this.codeOrder_.push(uCode);
200
-
201
186
  if (uCode == 'g') {
202
187
  let dimVec = theUnit.dim_.dimVec_;
203
188
  let d = 0;
204
-
205
189
  for (; d < dimVec.length && dimVec[d] < 1; d++);
206
-
207
190
  this.massDimIndex_ = d;
208
191
  }
209
192
  }
@@ -222,12 +205,9 @@ class UnitTablesFactory {
222
205
  * @param theUnit the unit to be added
223
206
  * @returns nothing
224
207
  */
225
-
226
-
227
208
  addUnitString(theUnit) {
228
209
  let uString = null;
229
210
  if (Ucum.caseSensitive_ == true) uString = theUnit['csUnitString_'];else uString = theUnit['ciUnitString_'];
230
-
231
211
  if (uString) {
232
212
  let uEntry = {
233
213
  mag: theUnit['baseFactorStr_'],
@@ -247,11 +227,8 @@ class UnitTablesFactory {
247
227
  * @returns nothing
248
228
  * @throws an error if the unit has no dimension
249
229
  */
250
-
251
-
252
230
  addUnitDimension(theUnit) {
253
231
  let uDim = theUnit['dim_'].getProperty('dimVec_');
254
-
255
232
  if (uDim) {
256
233
  if (this.unitDimensions_[uDim]) this.unitDimensions_[uDim].push(theUnit);else this.unitDimensions_[uDim] = [theUnit];
257
234
  } else throw new Error('UnitTables.addUnitDimension called for a unit with no dimension. ' + `Unit code = ${theUnit['csCode_']}.`);
@@ -267,35 +244,29 @@ class UnitTablesFactory {
267
244
  *
268
245
  * @returns nothing
269
246
  */
270
-
271
-
272
247
  buildUnitSynonyms() {
273
248
  for (let code in this.unitCodes_) {
274
249
  let theUnit = this.unitCodes_[code];
275
- let uSyns = theUnit.synonyms_; // If the current unit has synonyms, process each synonym (often multiples)
250
+ let uSyns = theUnit.synonyms_;
276
251
 
252
+ // If the current unit has synonyms, process each synonym (often multiples)
277
253
  if (uSyns) {
278
254
  let synsAry = uSyns.split(';');
279
-
280
255
  if (synsAry[0] !== '') {
281
256
  let aLen = synsAry.length;
282
-
283
257
  for (let a = 0; a < aLen; a++) {
284
- let theSyn = synsAry[a].trim(); // call addSynonymCodes to process each word in the
285
- // synonym, e.g., "British fluid ounces"
258
+ let theSyn = synsAry[a].trim();
286
259
 
260
+ // call addSynonymCodes to process each word in the
261
+ // synonym, e.g., "British fluid ounces"
287
262
  this.addSynonymCodes(code, theSyn);
288
263
  } // end do for each synonym
289
-
290
264
  } // end if the current unit has a non-null synonym attribute
291
-
292
265
  } // end if the unit has any synonyms
293
- // Now call addSynonymCodes to process each word in the unit's name
294
-
295
266
 
267
+ // Now call addSynonymCodes to process each word in the unit's name
296
268
  this.addSynonymCodes(code, theUnit.name_);
297
269
  } // end do for each unit
298
-
299
270
  } // end buildUnitSynonyms
300
271
 
301
272
  /**
@@ -306,31 +277,28 @@ class UnitTablesFactory {
306
277
  * @param theSynonyms a string containing one or more words to be
307
278
  * considered synonyms (and thus to be added to the unitSynonyms hash).
308
279
  */
309
-
310
-
311
280
  addSynonymCodes(theCode, theSynonyms) {
312
281
  let words = theSynonyms.split(' ');
313
282
  let wLen = words.length;
314
-
315
283
  for (let w = 0; w < wLen; w++) {
316
- let word = words[w]; // if there is already a synonyms entry for the word,
284
+ let word = words[w];
285
+
286
+ // if there is already a synonyms entry for the word,
317
287
  // get the array of unit codes currently assigned to
318
288
  // the word and add the code for the current word to
319
289
  // the synonyms array if it's not already there.
320
-
321
290
  if (this.unitSynonyms_[word]) {
322
291
  let synCodes = this.unitSynonyms_[word];
323
-
324
292
  if (synCodes.indexOf(theCode) === -1) {
325
293
  this.unitSynonyms_[word].push(theCode);
326
294
  }
327
- } // else there are no synonyms entry for the word. Create a
295
+ }
296
+ // else there are no synonyms entry for the word. Create a
328
297
  // synonyms array for the word, setting it to contain the unit code.
329
298
  else {
330
- this.unitSynonyms_[word] = [theCode];
331
- }
299
+ this.unitSynonyms_[word] = [theCode];
300
+ }
332
301
  } // end do for each word in the synonyms being processed
333
-
334
302
  } // end addSynonymCodes
335
303
 
336
304
  /**
@@ -340,17 +308,14 @@ class UnitTablesFactory {
340
308
  * @param uCode the code of the unit to be returned
341
309
  * @returns the unit object or null if it is not found
342
310
  */
343
-
344
-
345
311
  getUnitByCode(uCode) {
346
312
  let retUnit = null;
347
-
348
313
  if (uCode) {
349
314
  retUnit = this.unitCodes_[uCode];
350
315
  }
351
-
352
316
  return retUnit;
353
317
  }
318
+
354
319
  /**
355
320
  * Returns a array of unit objects based on the unit's name. Usually this
356
321
  * will be an array of one, but there may be more, since unit names are
@@ -365,39 +330,27 @@ class UnitTablesFactory {
365
330
  * of one object.
366
331
  * @throws an error if no name is provided to search on
367
332
  */
368
-
369
-
370
333
  getUnitByName(uName) {
371
334
  if (uName === null || uName === undefined) {
372
335
  throw new Error('Unable to find unit by name because no name was provided.');
373
336
  }
374
-
375
337
  let sepPos = uName.indexOf(Ucum.codeSep_);
376
338
  let uCode = null;
377
-
378
339
  if (sepPos >= 1) {
379
340
  uCode = uName.substr(sepPos + Ucum.codeSep_.length);
380
341
  uName = uName.substr(0, sepPos);
381
342
  }
382
-
383
343
  let retUnits = this.unitNames_[uName];
384
-
385
344
  if (retUnits) {
386
345
  let uLen = retUnits.length;
387
-
388
346
  if (uCode && uLen > 1) {
389
347
  let i = 0;
390
-
391
348
  for (; retUnits[i].csCode_ !== uCode && i < uLen; i++);
392
-
393
349
  if (i < uLen) retUnits = [retUnits[i]];else {
394
350
  retUnits = null;
395
351
  }
396
352
  } // end if we need to find both a name and a code
397
-
398
353
  } // end if we got an array of units
399
-
400
-
401
354
  return retUnits;
402
355
  } // end getUnitByName
403
356
 
@@ -410,18 +363,15 @@ class UnitTablesFactory {
410
363
  * @param name the name of the unit to be returned
411
364
  * @returns the array of unit references or null if none were found
412
365
  */
413
-
414
-
415
366
  getUnitByString(uString) {
416
367
  let retAry = null;
417
-
418
368
  if (uString) {
419
369
  retAry = this.unitStrings_[uString];
420
370
  if (retAry === undefined) retAry = null;
421
371
  }
422
-
423
372
  return retAry;
424
373
  }
374
+
425
375
  /**
426
376
  * Returns a array of unit objects based on the unit's dimension vector.
427
377
  *
@@ -432,21 +382,15 @@ class UnitTablesFactory {
432
382
  * @throws an error if no vector is provided to search on
433
383
  * logs an error to the console if no unit is found
434
384
  */
435
-
436
-
437
385
  getUnitsByDimension(uDim) {
438
386
  let unitsArray = null;
439
-
440
387
  if (uDim === null || uDim === undefined) {
441
388
  throw new Error('Unable to find unit by because no dimension ' + 'vector was provided.');
442
389
  }
443
-
444
390
  unitsArray = this.unitDimensions_[uDim];
445
-
446
391
  if (unitsArray === undefined || unitsArray === null) {
447
392
  console.log(`Unable to find unit with dimension = ${uDim}`);
448
393
  }
449
-
450
394
  return unitsArray;
451
395
  } // end getUnitsByDimension
452
396
 
@@ -462,37 +406,28 @@ class UnitTablesFactory {
462
406
  * 'units' any array of unit objects with the specified synonym will be
463
407
  * returned for requests with status = succeeded
464
408
  */
465
-
466
-
467
409
  getUnitBySynonym(uSyn) {
468
410
  let retObj = {};
469
411
  let unitsArray = [];
470
-
471
412
  try {
472
413
  if (uSyn === null || uSyn === undefined) {
473
414
  retObj['status'] = 'error';
474
415
  throw new Error('Unable to find unit by synonym because no synonym ' + 'was provided.');
475
- } // If this is the first request for a unit by synonym, build the hash map
476
-
477
-
416
+ }
417
+ // If this is the first request for a unit by synonym, build the hash map
478
418
  if (Object.keys(this.unitSynonyms_).length === 0) {
479
419
  this.buildUnitSynonyms();
480
420
  }
481
-
482
421
  let foundCodes = [];
483
422
  foundCodes = this.unitSynonyms_[uSyn];
484
-
485
423
  if (foundCodes) {
486
424
  retObj['status'] = 'succeeded';
487
425
  let fLen = foundCodes.length;
488
-
489
426
  for (let f = 0; f < fLen; f++) {
490
427
  unitsArray.push(this.unitCodes_[foundCodes[f]]);
491
428
  }
492
-
493
429
  retObj['units'] = unitsArray;
494
430
  }
495
-
496
431
  if (unitsArray.length === 0) {
497
432
  retObj['status'] = 'failed';
498
433
  retObj['msg'] = `Unable to find any units with synonym = ${uSyn}`;
@@ -500,7 +435,6 @@ class UnitTablesFactory {
500
435
  } catch (err) {
501
436
  retObj['msg'] = err.message;
502
437
  }
503
-
504
438
  return retObj;
505
439
  } // end getUnitBySynonym
506
440
 
@@ -509,8 +443,6 @@ class UnitTablesFactory {
509
443
  *
510
444
  * @returns an array of the unit names
511
445
  */
512
-
513
-
514
446
  getAllUnitNames() {
515
447
  return Object.keys(this.unitNames_);
516
448
  } // end getAllUnitNames
@@ -522,30 +454,25 @@ class UnitTablesFactory {
522
454
  *
523
455
  * @returns {Array}
524
456
  */
525
-
526
-
527
457
  getUnitNamesList() {
528
458
  let nameList = [];
529
459
  let codes = Object.keys(this.unitCodes_);
530
460
  codes.sort(this.compareCodes);
531
461
  let uLen = codes.length;
532
-
533
462
  for (let i = 0; i < uLen; i++) {
534
463
  nameList[i] = codes[i] + Ucum.codeSep_ + this.unitCodes_[codes[i]].name_;
535
464
  } // end do for each code
536
-
537
-
538
465
  return nameList;
539
466
  }
467
+
540
468
  /*
541
469
  * Returns the mass dimension index
542
470
  * @returns this.massDimIndex_
543
471
  */
544
-
545
-
546
472
  getMassDimensionIndex() {
547
473
  return this.massDimIndex_;
548
474
  }
475
+
549
476
  /**
550
477
  * This provides a sort function for unit codes so that sorting ignores
551
478
  * square brackets and case.
@@ -554,8 +481,6 @@ class UnitTablesFactory {
554
481
  * @param b second value
555
482
  * @returns -1 if a is should fall before b; otherwise 1.
556
483
  */
557
-
558
-
559
484
  compareCodes(a, b) {
560
485
  a = a.replace(/[\[\]]/g, '');
561
486
  a = a.toLowerCase();
@@ -563,13 +488,12 @@ class UnitTablesFactory {
563
488
  b = b.toLowerCase();
564
489
  return a < b ? -1 : 1;
565
490
  }
491
+
566
492
  /**
567
493
  * Gets a list of all unit codes in the Unit tables
568
494
  *
569
495
  * @returns an array of the unit names
570
496
  */
571
-
572
-
573
497
  getAllUnitCodes() {
574
498
  return Object.keys(this.unitCodes_);
575
499
  } // end getAllUnitNames
@@ -583,16 +507,12 @@ class UnitTablesFactory {
583
507
  * @returns an array containing all unit objects, ordered by definition
584
508
  * order
585
509
  */
586
-
587
-
588
510
  allUnitsByDef() {
589
511
  let unitsList = [];
590
512
  let uLen = this.codeOrder_.length;
591
-
592
513
  for (let u = 0; u < uLen; u++) {
593
514
  unitsList.push(this.getUnitByCode(this.codeOrder_[u]));
594
515
  }
595
-
596
516
  return unitsList;
597
517
  } // end allUnitsByDef
598
518
 
@@ -606,24 +526,18 @@ class UnitTablesFactory {
606
526
  * @returns a buffer containing all unit objects, ordered by name
607
527
  * order
608
528
  */
609
-
610
-
611
529
  allUnitsByName(cols, sep) {
612
530
  if (sep === undefined || sep === null) sep = '|';
613
531
  let unitBuff = '';
614
532
  let unitsList = this.getAllUnitNames();
615
533
  let uLen = unitsList.length;
616
534
  let cLen = cols.length;
617
-
618
535
  for (let i = 0; i < uLen; i++) {
619
536
  let nameRecs = this.getUnitByName(unitsList[i]);
620
-
621
537
  for (let u = 0; u < nameRecs.length; u++) {
622
538
  let rec = nameRecs[u];
623
-
624
539
  for (let c = 0; c < cLen; c++) {
625
540
  if (c > 0) unitBuff += sep;
626
-
627
541
  if (cols[c] === 'dim_') {
628
542
  if (rec.dim_ !== null && rec.dim_ !== undefined && rec.dim_.dimVec_ instanceof Array) unitBuff += '[' + rec.dim_.dimVec_.join(',') + ']';else unitBuff += '';
629
543
  } else {
@@ -631,13 +545,9 @@ class UnitTablesFactory {
631
545
  if (typeof cbuf === 'string') unitBuff += cbuf.replace(/[\n\r]/g, ' ');else unitBuff += cbuf;
632
546
  }
633
547
  } // end do for each column requested
634
-
635
-
636
548
  unitBuff += '\r\n';
637
549
  } // end do for each unit in the unit names array
638
-
639
550
  }
640
-
641
551
  return unitBuff;
642
552
  } // end allUnitsByName
643
553
 
@@ -654,68 +564,52 @@ class UnitTablesFactory {
654
564
  * (Used to use ; but the synonyms use that extensively).
655
565
  * @returns {string} buffer containing all the listings
656
566
  */
657
-
658
-
659
567
  printUnits(doLong, sep) {
660
568
  if (doLong === undefined) doLong = false;
661
569
  if (sep === undefined) sep = '|';
662
570
  let codeList = '';
663
571
  let uLen = this.codeOrder_.length;
664
572
  let unitString = 'csCode' + sep;
665
-
666
573
  if (doLong) {
667
574
  unitString += 'ciCode' + sep;
668
575
  }
669
-
670
576
  unitString += 'name' + sep;
671
577
  if (doLong) unitString += 'isBase' + sep;
672
578
  unitString += 'magnitude' + sep + 'dimension' + sep + 'from unit(s)' + sep + 'value' + sep + 'function' + sep;
673
579
  if (doLong) unitString += 'property' + sep + 'printSymbol' + sep + 'synonyms' + sep + 'source' + sep + 'class' + sep + 'isMetric' + sep + 'variable' + sep + 'isSpecial' + sep + 'isAbitrary' + sep;
674
580
  unitString += 'comment';
675
581
  codeList = unitString + '\n';
676
-
677
582
  for (let u = 0; u < uLen; u++) {
678
583
  let curUnit = this.getUnitByCode(this.codeOrder_[u]);
679
584
  unitString = this.codeOrder_[u] + sep;
680
-
681
585
  if (doLong) {
682
586
  unitString += curUnit.getProperty('ciCode_') + sep;
683
587
  }
684
-
685
588
  unitString += curUnit.getProperty('name_') + sep;
686
-
687
589
  if (doLong) {
688
590
  if (curUnit.getProperty('isBase_')) unitString += 'true' + sep;else unitString += 'false' + sep;
689
591
  }
690
-
691
592
  unitString += curUnit.getProperty('magnitude_') + sep;
692
593
  let curDim = curUnit.getProperty('dim_');
693
-
694
594
  if (curDim) {
695
595
  unitString += curDim.dimVec_ + sep;
696
596
  } else {
697
597
  unitString += 'null' + sep;
698
598
  }
699
-
700
599
  if (curUnit.csUnitString_) unitString += curUnit.csUnitString_ + sep + curUnit.baseFactor_ + sep;else unitString += 'null' + sep + 'null' + sep;
701
600
  if (curUnit.cnv_) unitString += curUnit.cnv_ + sep;else unitString += 'null' + sep;
702
-
703
601
  if (doLong) {
704
602
  unitString += curUnit.getProperty('property_') + sep + curUnit.getProperty('printSymbol_') + sep + curUnit.getProperty('synonyms_') + sep + curUnit.getProperty('source_') + sep + curUnit.getProperty('class_') + sep + curUnit.getProperty('isMetric_') + sep + curUnit.getProperty('variable_') + sep + curUnit.getProperty('isSpecial_') + sep + curUnit.getProperty('isArbitrary_') + sep;
705
603
  }
706
-
707
604
  if (curUnit.defError_) unitString += 'problem parsing this one, deferred to later.';
708
605
  codeList += unitString + '\n';
709
606
  }
710
-
711
607
  return codeList;
712
608
  }
713
-
714
609
  } // end UnitTablesFactory
610
+
715
611
  // Create a singleton instance and (to preserve the existing API) an object that
716
612
  // provides that instance via getInstance().
717
-
718
-
719
613
  var unitTablesInstance = new UnitTablesFactory();
720
614
  const UnitTables = {
721
615
  getInstance: function () {