qesuite 1.0.53 → 1.0.55

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/dist/index.d.mts CHANGED
@@ -175,8 +175,9 @@ declare const Capability: {
175
175
  * @customfunction
176
176
  * @param data The data to evaluate.
177
177
  * @param spec The specification to evaluate the capability against.
178
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
178
179
  */
179
- Analysis(data: number[], spec: Specification): {
180
+ Analysis(data: number[], spec: Specification, subgroupSize?: number): {
180
181
  Cp: number;
181
182
  Cpk: number;
182
183
  Pp: number;
@@ -187,15 +188,49 @@ declare const Capability: {
187
188
  * @customfunction
188
189
  * @param data The data to evaluate.
189
190
  * @param spec The specification to evaluate the capability against.
191
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
190
192
  */
191
- Cp(data: number[], spec: Specification): number;
193
+ Cp(data: number[], spec: Specification, subgroupSize?: number): number;
192
194
  /**
193
195
  * Evaluates the capability index Cpk(overall).
194
196
  * @customfunction
195
197
  * @param data The data to evaluate.
196
198
  * @param spec The specification to evaluate the capability against.
199
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
197
200
  */
198
- Cpk(data: number[], spec: Specification): number;
201
+ Cpk(data: number[], spec: Specification, subgroupSize?: number): number;
202
+ /**
203
+ * Evaluates the capability index Cpk(overall).
204
+ * @customfunction
205
+ * @param data The data to evaluate.
206
+ * @param spec The specification to evaluate the capability against.
207
+ * @param target The target value of the process
208
+ */
209
+ Cpm(data: number[], spec: Specification, target: number): number;
210
+ /**
211
+ * Calculates the defective parts per million.
212
+ * @customfunction
213
+ * @param data The data to evaluate.
214
+ * @param spec The specification to evaluate against.
215
+ * @param confidenceInterval [OPTIONAL] The desired confidence level of the analysis. DEFAULT = 0.95 (95%)
216
+ */
217
+ DPPM(data: number[], spec: Specification, confidenceInterval?: number): {
218
+ LSL: {
219
+ PPM: number;
220
+ LB: number;
221
+ UB: number;
222
+ };
223
+ USL: {
224
+ PPM: number;
225
+ LB: number;
226
+ UB: number;
227
+ };
228
+ Total: {
229
+ PPM: number;
230
+ LB: number;
231
+ UB: number;
232
+ };
233
+ };
199
234
  /**
200
235
  * Evaluates the capability index Pp(within).
201
236
  * @customfunction
@@ -621,7 +656,7 @@ declare const Distributions: {
621
656
  Chebyshev(data: number[], spec: Specification): number;
622
657
  JarqueBera(data: number[]): {
623
658
  JB: number;
624
- p: number;
659
+ p: string | number;
625
660
  };
626
661
  Kurtosis(data: any): number;
627
662
  KolmogorovSmirnov(data: any): {
@@ -647,14 +682,14 @@ declare const Distributions: {
647
682
  ShapiroWilk: {
648
683
  Royston(data: number[]): {
649
684
  W: number;
650
- p: number;
685
+ p: string | number;
651
686
  };
652
687
  Test(data: number[], algorithmic?: boolean): {
653
688
  W: number;
654
- p: number;
689
+ p: string | number;
655
690
  };
656
691
  constants: number[][];
657
- p(W: number, N: number): number;
692
+ p(W: number, N: number): number | "<0.005";
658
693
  pChart: {
659
694
  wValues: number[][];
660
695
  pValues: number[];
package/dist/index.d.ts CHANGED
@@ -175,8 +175,9 @@ declare const Capability: {
175
175
  * @customfunction
176
176
  * @param data The data to evaluate.
177
177
  * @param spec The specification to evaluate the capability against.
178
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
178
179
  */
179
- Analysis(data: number[], spec: Specification): {
180
+ Analysis(data: number[], spec: Specification, subgroupSize?: number): {
180
181
  Cp: number;
181
182
  Cpk: number;
182
183
  Pp: number;
@@ -187,15 +188,49 @@ declare const Capability: {
187
188
  * @customfunction
188
189
  * @param data The data to evaluate.
189
190
  * @param spec The specification to evaluate the capability against.
191
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
190
192
  */
191
- Cp(data: number[], spec: Specification): number;
193
+ Cp(data: number[], spec: Specification, subgroupSize?: number): number;
192
194
  /**
193
195
  * Evaluates the capability index Cpk(overall).
194
196
  * @customfunction
195
197
  * @param data The data to evaluate.
196
198
  * @param spec The specification to evaluate the capability against.
199
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
197
200
  */
198
- Cpk(data: number[], spec: Specification): number;
201
+ Cpk(data: number[], spec: Specification, subgroupSize?: number): number;
202
+ /**
203
+ * Evaluates the capability index Cpk(overall).
204
+ * @customfunction
205
+ * @param data The data to evaluate.
206
+ * @param spec The specification to evaluate the capability against.
207
+ * @param target The target value of the process
208
+ */
209
+ Cpm(data: number[], spec: Specification, target: number): number;
210
+ /**
211
+ * Calculates the defective parts per million.
212
+ * @customfunction
213
+ * @param data The data to evaluate.
214
+ * @param spec The specification to evaluate against.
215
+ * @param confidenceInterval [OPTIONAL] The desired confidence level of the analysis. DEFAULT = 0.95 (95%)
216
+ */
217
+ DPPM(data: number[], spec: Specification, confidenceInterval?: number): {
218
+ LSL: {
219
+ PPM: number;
220
+ LB: number;
221
+ UB: number;
222
+ };
223
+ USL: {
224
+ PPM: number;
225
+ LB: number;
226
+ UB: number;
227
+ };
228
+ Total: {
229
+ PPM: number;
230
+ LB: number;
231
+ UB: number;
232
+ };
233
+ };
199
234
  /**
200
235
  * Evaluates the capability index Pp(within).
201
236
  * @customfunction
@@ -621,7 +656,7 @@ declare const Distributions: {
621
656
  Chebyshev(data: number[], spec: Specification): number;
622
657
  JarqueBera(data: number[]): {
623
658
  JB: number;
624
- p: number;
659
+ p: string | number;
625
660
  };
626
661
  Kurtosis(data: any): number;
627
662
  KolmogorovSmirnov(data: any): {
@@ -647,14 +682,14 @@ declare const Distributions: {
647
682
  ShapiroWilk: {
648
683
  Royston(data: number[]): {
649
684
  W: number;
650
- p: number;
685
+ p: string | number;
651
686
  };
652
687
  Test(data: number[], algorithmic?: boolean): {
653
688
  W: number;
654
- p: number;
689
+ p: string | number;
655
690
  };
656
691
  constants: number[][];
657
- p(W: number, N: number): number;
692
+ p(W: number, N: number): number | "<0.005";
658
693
  pChart: {
659
694
  wValues: number[][];
660
695
  pValues: number[];
package/dist/index.js CHANGED
@@ -134,7 +134,7 @@ var Specification = class {
134
134
  full_tolerance;
135
135
  // methods
136
136
  ParseSpec(spec) {
137
- let string = spec.replace(/\,/g, ".");
137
+ let string = spec.replace(/\,/g, ".").toUpperCase().replace(/MIN/g, ">").replace(/MAX/g, "<").replace(/\-\-/g, "\u2014");
138
138
  let nominal;
139
139
  let USL;
140
140
  let LSL;
@@ -142,6 +142,39 @@ var Specification = class {
142
142
  let tol_minus;
143
143
  let tol;
144
144
  let units;
145
+ if (string.indexOf("\u2014") !== -1) {
146
+ let bookends = string.split("\u2014").map((c) => {
147
+ return Number(c);
148
+ });
149
+ USL = Math.max(...bookends);
150
+ LSL = Math.min(...bookends);
151
+ tol = USL - LSL;
152
+ return {
153
+ nominal: NaN,
154
+ USL,
155
+ LSL,
156
+ units: "",
157
+ tolerance: tol
158
+ };
159
+ }
160
+ if (string.indexOf("<") !== -1) {
161
+ return {
162
+ nominal: NaN,
163
+ USL: Number(string.substring(string.indexOf("<") + 1)),
164
+ LSL: NaN,
165
+ units: "",
166
+ tolerance: NaN
167
+ };
168
+ }
169
+ if (string.indexOf(">") !== -1) {
170
+ return {
171
+ nominal: NaN,
172
+ USL: NaN,
173
+ LSL: Number(string.substring(string.indexOf(">") + 1)),
174
+ units: "",
175
+ tolerance: NaN
176
+ };
177
+ }
145
178
  if (string.indexOf("\xB1") !== -1) {
146
179
  nominal = Number(string.substring(0, string.indexOf("\xB1")).replace("\xD8", ""));
147
180
  let after = this.SplitUnits(string.substring(string.indexOf("\xB1") + 1));
@@ -154,16 +187,18 @@ var Specification = class {
154
187
  tol_plus = Number(this.SplitUnits(string.substring(string.indexOf("+") + 1, string.indexOf("/") > 0 ? string.indexOf("/") : string.indexOf("-") > 0 ? string.indexOf("-") : void 0))[0]);
155
188
  nominal = Number(this.SplitUnits(string)[0].substring(0, string.indexOf("+")));
156
189
  if (string.indexOf("-") === -1) {
157
- tol_minus = 0;
190
+ tol_minus = NaN;
158
191
  }
159
192
  }
160
193
  if (string.indexOf("-") !== -1) {
161
194
  tol_minus = Number(this.SplitUnits(string.substring(string.indexOf("/") > 0 ? Math.max(string.indexOf("/"), string.indexOf("-")) + 1 : string.indexOf("-") + 1))[0]);
162
195
  if (string.indexOf("+") === -1) {
163
- tol_plus = 0;
196
+ tol_plus = NaN;
164
197
  nominal = Number(this.SplitUnits(string.substring(0, string.indexOf("/") > 0 ? Math.min(string.indexOf("/"), string.indexOf("-")) : string.indexOf("-")))[0]);
165
198
  }
166
199
  }
200
+ USL = nominal + tol_plus;
201
+ LSL = nominal - tol_minus;
167
202
  if (string.indexOf("+-") !== -1 || string.indexOf("+/-") !== -1) {
168
203
  nominal = Number(string.substring(0, string.indexOf("+")));
169
204
  let after = this.SplitUnits(string.substring(string.indexOf("-") + 1));
@@ -519,13 +554,35 @@ function RoundTO(number, digits) {
519
554
  }
520
555
  let str = number.toString();
521
556
  let decimalIndex = str.indexOf(".");
557
+ let roundFinalDigit = Number(str.substring(decimalIndex + digits + 2, decimalIndex + digits + 3)) >= 5;
522
558
  let returner = Number(str.substring(0, decimalIndex + digits + 1));
559
+ if (roundFinalDigit) {
560
+ returner = returner + Math.pow(10, -1 * digits);
561
+ }
523
562
  let i = 0;
524
563
  while (returner === 0) {
525
564
  i++;
526
565
  returner = Number(str.substring(0, decimalIndex + digits + 1 + i));
527
566
  }
528
- return returner;
567
+ if (Math.abs(number) < 1e-4) {
568
+ let f_i = 0;
569
+ let l_i = 0;
570
+ let d_i = 0;
571
+ let i2 = 0;
572
+ while (d_i <= digits) {
573
+ if (str[i2] != "0" && str[i2] != ".") {
574
+ d_i += 1;
575
+ if (f_i == 0) {
576
+ f_i = i2;
577
+ }
578
+ ;
579
+ }
580
+ i2 += 1;
581
+ }
582
+ l_i = i2;
583
+ return str[f_i] + "." + str.substring(f_i + 1, f_i + digits) + "e-" + (f_i - decimalIndex);
584
+ }
585
+ return Number(`${returner}`.substring(0, decimalIndex + digits + 1));
529
586
  }
530
587
  var Capability = {
531
588
  /**
@@ -533,11 +590,12 @@ var Capability = {
533
590
  * @customfunction
534
591
  * @param data The data to evaluate.
535
592
  * @param spec The specification to evaluate the capability against.
593
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
536
594
  */
537
- Analysis(data, spec) {
595
+ Analysis(data, spec, subgroupSize = 2) {
538
596
  return {
539
- Cp: Capability.Cp(data, spec),
540
- Cpk: Capability.Cpk(data, spec),
597
+ Cp: Capability.Cp(data, spec, subgroupSize),
598
+ Cpk: Capability.Cpk(data, spec, subgroupSize),
541
599
  Pp: Capability.Pp(data, spec),
542
600
  Ppk: Capability.Ppk(data, spec)
543
601
  };
@@ -547,22 +605,28 @@ var Capability = {
547
605
  * @customfunction
548
606
  * @param data The data to evaluate.
549
607
  * @param spec The specification to evaluate the capability against.
608
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
550
609
  */
551
- Cp(data, spec) {
552
- let standarddeviation = StDev.W(data, 2);
553
- return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
610
+ Cp(data, spec, subgroupSize = 2) {
611
+ let standarddeviation = StDev.W(data, subgroupSize);
612
+ if (!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)) {
613
+ return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
614
+ } else {
615
+ return NaN;
616
+ }
554
617
  },
555
618
  /**
556
619
  * Evaluates the capability index Cpk(overall).
557
620
  * @customfunction
558
621
  * @param data The data to evaluate.
559
622
  * @param spec The specification to evaluate the capability against.
623
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
560
624
  */
561
- Cpk(data, spec) {
625
+ Cpk(data, spec, subgroupSize = 2) {
562
626
  let mean = Mean(data);
563
- let standarddeviation = StDev.W(data, 2);
564
- let AbsUSL = spec.USL - mean;
565
- let AbsLSL = mean - spec.LSL;
627
+ let standarddeviation = StDev.W(data, subgroupSize);
628
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
629
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
566
630
  let min;
567
631
  if (AbsUSL < AbsLSL) {
568
632
  min = AbsUSL;
@@ -572,6 +636,61 @@ var Capability = {
572
636
  return Number(min / (3 * standarddeviation));
573
637
  },
574
638
  /**
639
+ * Evaluates the capability index Cpk(overall).
640
+ * @customfunction
641
+ * @param data The data to evaluate.
642
+ * @param spec The specification to evaluate the capability against.
643
+ * @param target The target value of the process
644
+ */
645
+ Cpm(data, spec, target) {
646
+ return Math.min(spec.USL - target, target - spec.LSL) / (3 * Math.sqrt(SumSquaredDeviation(data, target) / data.length));
647
+ },
648
+ /**
649
+ * Calculates the defective parts per million.
650
+ * @customfunction
651
+ * @param data The data to evaluate.
652
+ * @param spec The specification to evaluate against.
653
+ * @param confidenceInterval [OPTIONAL] The desired confidence level of the analysis. DEFAULT = 0.95 (95%)
654
+ */
655
+ DPPM(data, spec, confidenceInterval = 0.95) {
656
+ let mean = Mean(data);
657
+ let std = StDev.S(data);
658
+ let a = 1 - confidenceInterval;
659
+ let Z_1_a2 = Distributions.Normal.inv(1 - a / 2);
660
+ let Z_lsl = (mean - spec.LSL) / std;
661
+ let Z_usl = (spec.USL - mean) / std;
662
+ let v = data.length - 1;
663
+ let UL = Z_lsl + Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_lsl, 2) / (2 * v));
664
+ let LL = Z_lsl - Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_lsl, 2) / (2 * v));
665
+ let UU = Z_usl + Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_usl, 2) / (2 * v));
666
+ let LU = Z_usl - Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_usl, 2) / (2 * v));
667
+ let PPM_L = (1 - Distributions.Normal.cdf((mean - spec.LSL) / std, 0, 1)) * 1e6;
668
+ let PPM_U = (1 - Distributions.Normal.cdf((spec.USL - mean) / std, 0, 1)) * 1e6;
669
+ let p_hat = 1 - Distributions.Normal.cdf((mean - spec.LSL) / std, 0, 1) + (1 - Distributions.Normal.cdf((mean - spec.USL) / std, 0, 1));
670
+ let ln_p = Math.log(p_hat / (1 - p_hat));
671
+ let part_p_u = 1 / (p_hat * (1 - p_hat)) * (1 / std) * (Distributions.Normal.pdf((spec.USL - mean) / std) - Distributions.Normal.pdf((spec.LSL - mean) / std));
672
+ let part_p_v = 0.5 * (1 / (p_hat * (1 - p_hat))) * ((spec.USL - mean) / Math.pow(std, 3) * Distributions.Normal.pdf((spec.USL - mean) / std) - (spec.LSL - mean) / Math.pow(std, 3) * Distributions.Normal.pdf((spec.LSL - mean) / std));
673
+ let V_hat = Math.pow(part_p_u, 2) * Math.pow(std, 2) / mean + Math.pow(part_p_v, 2) * 2 * Math.pow(std, 4) / v;
674
+ let returner = {
675
+ LSL: {
676
+ PPM: PPM_L,
677
+ LB: 1e6 * (1 - Distributions.Normal.cdf(UL, 0, 1)),
678
+ UB: 1e6 * (1 - Distributions.Normal.cdf(LL, 0, 1))
679
+ },
680
+ USL: {
681
+ PPM: PPM_U,
682
+ LB: 1e6 * (1 - Distributions.Normal.cdf(UU, 0, 1)),
683
+ UB: 1e6 * (1 - Distributions.Normal.cdf(LU, 0, 1))
684
+ },
685
+ Total: {
686
+ PPM: PPM_L + PPM_U,
687
+ LB: Math.exp(ln_p - Z_1_a2 * Math.sqrt(V_hat)) / (1 + Math.exp(ln_p - Z_1_a2 * Math.sqrt(V_hat))) * 1e6,
688
+ UB: Math.exp(ln_p + Z_1_a2 * Math.sqrt(V_hat)) / (1 + Math.exp(ln_p + Z_1_a2 * Math.sqrt(V_hat))) * 1e6
689
+ }
690
+ };
691
+ return returner;
692
+ },
693
+ /**
575
694
  * Evaluates the capability index Pp(within).
576
695
  * @customfunction
577
696
  * @param data The data to evaluate.
@@ -579,7 +698,11 @@ var Capability = {
579
698
  */
580
699
  Pp(data, spec) {
581
700
  let standarddeviation = StDev.S(data);
582
- return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
701
+ if (!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)) {
702
+ return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
703
+ } else {
704
+ return NaN;
705
+ }
583
706
  },
584
707
  /**
585
708
  * Evaluates the capability index Ppk(within).
@@ -590,8 +713,8 @@ var Capability = {
590
713
  Ppk(data, spec) {
591
714
  let mean = Mean(data);
592
715
  let standarddeviation = StDev.S(data);
593
- let AbsUSL = spec.USL - mean;
594
- let AbsLSL = mean - spec.LSL;
716
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
717
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
595
718
  let min;
596
719
  if (AbsUSL < AbsLSL) {
597
720
  min = AbsUSL;
@@ -784,9 +907,11 @@ function CreateCapabilityPlot(data, specification) {
784
907
  ];
785
908
  AddInfoTable(ctx, overallInfo, 3 * chartSettings.width / 4, chartSettings.margins.top, chartSettings.width / 4, chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom, "Overall");
786
909
  const mean = Mean(data);
787
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width / 4, chartSettings.margins.top, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Overall");
788
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width / 4, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Within");
789
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [specification.LSL, specification.USL], chartSettings.width / 4, chartSettings.margins.top + 80 + 2 * (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Specs");
910
+ let plotMin = !isNaN(specification.LSL) ? specification.LSL : Math.max(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
911
+ let plotMax = !isNaN(specification.USL) ? specification.USL : Math.min(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
912
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Overall");
913
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Within");
914
+ AddLinePlot(ctx, plotMin, plotMax, mean, [specification.LSL, specification.USL], chartSettings.width / 4 + 25, chartSettings.margins.top + 80 + 2 * (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Specs");
790
915
  return canvas;
791
916
  }
792
917
  var Beta = {
@@ -1634,9 +1759,10 @@ var Distributions = {
1634
1759
  let S = Distributions.Normal.Skewness(data);
1635
1760
  let K = Distributions.Normal.Kurtosis(data);
1636
1761
  let JB = N / 6 * (Math.pow(S, 2) + 0.25 * Math.pow(K, 2));
1762
+ let p = Distributions.ChiSq.RightTail(JB, 2);
1637
1763
  return {
1638
1764
  JB,
1639
- p: Distributions.ChiSq.RightTail(JB, 2)
1765
+ p: p > 1 || p < 5e-3 ? "<0.005" : p
1640
1766
  };
1641
1767
  },
1642
1768
  Kurtosis(data) {
@@ -1669,7 +1795,7 @@ var Distributions = {
1669
1795
  let p = GoodnessOfFit.AndersonDarling.p(KS, N);
1670
1796
  return {
1671
1797
  KS,
1672
- p
1798
+ p: p > 1 || p < 5e-3 ? "<0.005" : p
1673
1799
  };
1674
1800
  },
1675
1801
  Lilliefors: {
@@ -1686,6 +1812,9 @@ var Distributions = {
1686
1812
  if (p === 1) {
1687
1813
  p = Distributions.Normal.Lilliefors.pApprox(KS, N);
1688
1814
  }
1815
+ if (!Number.isNaN(p)) {
1816
+ p = Number(p) > 1 || Number(p) < 5e-3 ? "<0.005" : p;
1817
+ }
1689
1818
  return p;
1690
1819
  },
1691
1820
  pApprox(KS, N) {
@@ -1827,9 +1956,10 @@ var Distributions = {
1827
1956
  let p_mu = 38915e-7 * Math.pow(Math.log(N), 3) - 0.083751 * Math.pow(Math.log(N), 2) - 0.31082 * Math.log(N) - 1.5861;
1828
1957
  let p_sigma = Math.exp(30302e-7 * Math.pow(Math.log(N), 2) - 0.082676 * Math.log(N) - 0.4803);
1829
1958
  let z = (Math.log(1 - W) - p_mu) / p_sigma;
1959
+ let p = 1 - Distributions.Normal.cdf(z, 0, 1);
1830
1960
  return {
1831
1961
  W,
1832
- p: 1 - Distributions.Normal.cdf(z, 0, 1)
1962
+ p: p < 5e-3 ? "<0.005" : p
1833
1963
  };
1834
1964
  },
1835
1965
  Test(data, algorithmic) {
@@ -1898,7 +2028,8 @@ var Distributions = {
1898
2028
  let w2 = wArray[inflection];
1899
2029
  let p1 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection - 1];
1900
2030
  let p2 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection];
1901
- return p1 + (p2 - p1) / (w2 - w1) * (W - w1);
2031
+ let p = p1 + (p2 - p1) / (w2 - w1) * (W - w1);
2032
+ return p < 5e-3 ? "<0.005" : p;
1902
2033
  },
1903
2034
  pChart: {
1904
2035
  wValues: [
@@ -2300,7 +2431,7 @@ var GoodnessOfFit = {
2300
2431
  if (ADStar <= 0.2) {
2301
2432
  p = 1 - Math.exp(-13.436 + 101.14 * ADStar - 223.73 * Math.pow(ADStar, 2));
2302
2433
  }
2303
- return p;
2434
+ return p > 1 || p < 5e-3 ? "<0.005" : p;
2304
2435
  },
2305
2436
  /**
2306
2437
  * Evaluates the Anderson-Darling goodness-of-fit test for the specified data and cumulative distribution function.
@@ -2523,11 +2654,10 @@ function Median(data) {
2523
2654
  }
2524
2655
  function MovingRange(data, w = 2) {
2525
2656
  let movingRange = [];
2526
- for (let i = 1; i < data.length; i++) {
2527
- let h = i - w + 1;
2657
+ for (let i = 0; i < data.length + 1 - w; i++) {
2528
2658
  let values = [];
2529
2659
  for (let j = 0; j < w; j++) {
2530
- values.push(Number(data[h + j]));
2660
+ values.push(Number(data[i + j]));
2531
2661
  }
2532
2662
  movingRange.push(CalculateRange(values));
2533
2663
  }
@@ -3815,7 +3945,6 @@ var ANOVA = {
3815
3945
  chartSet.width += 1e3;
3816
3946
  chartSet.axis.y.tickOnly = true;
3817
3947
  let graph = CreateSplitGraph(individualCharts, `Main Effects Plot of ${Object.keys(response)[0]}`, chartSet);
3818
- console.log(graph);
3819
3948
  return graph;
3820
3949
  },
3821
3950
  Table(factors, response) {
@@ -3931,7 +4060,6 @@ var ANOVA = {
3931
4060
  });
3932
4061
  }
3933
4062
  });
3934
- console.log(k, SS);
3935
4063
  });
3936
4064
  return anovaTable;
3937
4065
  }
package/dist/index.mjs CHANGED
@@ -42,7 +42,7 @@ var Specification = class {
42
42
  full_tolerance;
43
43
  // methods
44
44
  ParseSpec(spec) {
45
- let string = spec.replace(/\,/g, ".");
45
+ let string = spec.replace(/\,/g, ".").toUpperCase().replace(/MIN/g, ">").replace(/MAX/g, "<").replace(/\-\-/g, "\u2014");
46
46
  let nominal;
47
47
  let USL;
48
48
  let LSL;
@@ -50,6 +50,39 @@ var Specification = class {
50
50
  let tol_minus;
51
51
  let tol;
52
52
  let units;
53
+ if (string.indexOf("\u2014") !== -1) {
54
+ let bookends = string.split("\u2014").map((c) => {
55
+ return Number(c);
56
+ });
57
+ USL = Math.max(...bookends);
58
+ LSL = Math.min(...bookends);
59
+ tol = USL - LSL;
60
+ return {
61
+ nominal: NaN,
62
+ USL,
63
+ LSL,
64
+ units: "",
65
+ tolerance: tol
66
+ };
67
+ }
68
+ if (string.indexOf("<") !== -1) {
69
+ return {
70
+ nominal: NaN,
71
+ USL: Number(string.substring(string.indexOf("<") + 1)),
72
+ LSL: NaN,
73
+ units: "",
74
+ tolerance: NaN
75
+ };
76
+ }
77
+ if (string.indexOf(">") !== -1) {
78
+ return {
79
+ nominal: NaN,
80
+ USL: NaN,
81
+ LSL: Number(string.substring(string.indexOf(">") + 1)),
82
+ units: "",
83
+ tolerance: NaN
84
+ };
85
+ }
53
86
  if (string.indexOf("\xB1") !== -1) {
54
87
  nominal = Number(string.substring(0, string.indexOf("\xB1")).replace("\xD8", ""));
55
88
  let after = this.SplitUnits(string.substring(string.indexOf("\xB1") + 1));
@@ -62,16 +95,18 @@ var Specification = class {
62
95
  tol_plus = Number(this.SplitUnits(string.substring(string.indexOf("+") + 1, string.indexOf("/") > 0 ? string.indexOf("/") : string.indexOf("-") > 0 ? string.indexOf("-") : void 0))[0]);
63
96
  nominal = Number(this.SplitUnits(string)[0].substring(0, string.indexOf("+")));
64
97
  if (string.indexOf("-") === -1) {
65
- tol_minus = 0;
98
+ tol_minus = NaN;
66
99
  }
67
100
  }
68
101
  if (string.indexOf("-") !== -1) {
69
102
  tol_minus = Number(this.SplitUnits(string.substring(string.indexOf("/") > 0 ? Math.max(string.indexOf("/"), string.indexOf("-")) + 1 : string.indexOf("-") + 1))[0]);
70
103
  if (string.indexOf("+") === -1) {
71
- tol_plus = 0;
104
+ tol_plus = NaN;
72
105
  nominal = Number(this.SplitUnits(string.substring(0, string.indexOf("/") > 0 ? Math.min(string.indexOf("/"), string.indexOf("-")) : string.indexOf("-")))[0]);
73
106
  }
74
107
  }
108
+ USL = nominal + tol_plus;
109
+ LSL = nominal - tol_minus;
75
110
  if (string.indexOf("+-") !== -1 || string.indexOf("+/-") !== -1) {
76
111
  nominal = Number(string.substring(0, string.indexOf("+")));
77
112
  let after = this.SplitUnits(string.substring(string.indexOf("-") + 1));
@@ -427,13 +462,35 @@ function RoundTO(number, digits) {
427
462
  }
428
463
  let str = number.toString();
429
464
  let decimalIndex = str.indexOf(".");
465
+ let roundFinalDigit = Number(str.substring(decimalIndex + digits + 2, decimalIndex + digits + 3)) >= 5;
430
466
  let returner = Number(str.substring(0, decimalIndex + digits + 1));
467
+ if (roundFinalDigit) {
468
+ returner = returner + Math.pow(10, -1 * digits);
469
+ }
431
470
  let i = 0;
432
471
  while (returner === 0) {
433
472
  i++;
434
473
  returner = Number(str.substring(0, decimalIndex + digits + 1 + i));
435
474
  }
436
- return returner;
475
+ if (Math.abs(number) < 1e-4) {
476
+ let f_i = 0;
477
+ let l_i = 0;
478
+ let d_i = 0;
479
+ let i2 = 0;
480
+ while (d_i <= digits) {
481
+ if (str[i2] != "0" && str[i2] != ".") {
482
+ d_i += 1;
483
+ if (f_i == 0) {
484
+ f_i = i2;
485
+ }
486
+ ;
487
+ }
488
+ i2 += 1;
489
+ }
490
+ l_i = i2;
491
+ return str[f_i] + "." + str.substring(f_i + 1, f_i + digits) + "e-" + (f_i - decimalIndex);
492
+ }
493
+ return Number(`${returner}`.substring(0, decimalIndex + digits + 1));
437
494
  }
438
495
  var Capability = {
439
496
  /**
@@ -441,11 +498,12 @@ var Capability = {
441
498
  * @customfunction
442
499
  * @param data The data to evaluate.
443
500
  * @param spec The specification to evaluate the capability against.
501
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
444
502
  */
445
- Analysis(data, spec) {
503
+ Analysis(data, spec, subgroupSize = 2) {
446
504
  return {
447
- Cp: Capability.Cp(data, spec),
448
- Cpk: Capability.Cpk(data, spec),
505
+ Cp: Capability.Cp(data, spec, subgroupSize),
506
+ Cpk: Capability.Cpk(data, spec, subgroupSize),
449
507
  Pp: Capability.Pp(data, spec),
450
508
  Ppk: Capability.Ppk(data, spec)
451
509
  };
@@ -455,22 +513,28 @@ var Capability = {
455
513
  * @customfunction
456
514
  * @param data The data to evaluate.
457
515
  * @param spec The specification to evaluate the capability against.
516
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
458
517
  */
459
- Cp(data, spec) {
460
- let standarddeviation = StDev.W(data, 2);
461
- return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
518
+ Cp(data, spec, subgroupSize = 2) {
519
+ let standarddeviation = StDev.W(data, subgroupSize);
520
+ if (!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)) {
521
+ return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
522
+ } else {
523
+ return NaN;
524
+ }
462
525
  },
463
526
  /**
464
527
  * Evaluates the capability index Cpk(overall).
465
528
  * @customfunction
466
529
  * @param data The data to evaluate.
467
530
  * @param spec The specification to evaluate the capability against.
531
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
468
532
  */
469
- Cpk(data, spec) {
533
+ Cpk(data, spec, subgroupSize = 2) {
470
534
  let mean = Mean(data);
471
- let standarddeviation = StDev.W(data, 2);
472
- let AbsUSL = spec.USL - mean;
473
- let AbsLSL = mean - spec.LSL;
535
+ let standarddeviation = StDev.W(data, subgroupSize);
536
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
537
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
474
538
  let min;
475
539
  if (AbsUSL < AbsLSL) {
476
540
  min = AbsUSL;
@@ -480,6 +544,61 @@ var Capability = {
480
544
  return Number(min / (3 * standarddeviation));
481
545
  },
482
546
  /**
547
+ * Evaluates the capability index Cpk(overall).
548
+ * @customfunction
549
+ * @param data The data to evaluate.
550
+ * @param spec The specification to evaluate the capability against.
551
+ * @param target The target value of the process
552
+ */
553
+ Cpm(data, spec, target) {
554
+ return Math.min(spec.USL - target, target - spec.LSL) / (3 * Math.sqrt(SumSquaredDeviation(data, target) / data.length));
555
+ },
556
+ /**
557
+ * Calculates the defective parts per million.
558
+ * @customfunction
559
+ * @param data The data to evaluate.
560
+ * @param spec The specification to evaluate against.
561
+ * @param confidenceInterval [OPTIONAL] The desired confidence level of the analysis. DEFAULT = 0.95 (95%)
562
+ */
563
+ DPPM(data, spec, confidenceInterval = 0.95) {
564
+ let mean = Mean(data);
565
+ let std = StDev.S(data);
566
+ let a = 1 - confidenceInterval;
567
+ let Z_1_a2 = Distributions.Normal.inv(1 - a / 2);
568
+ let Z_lsl = (mean - spec.LSL) / std;
569
+ let Z_usl = (spec.USL - mean) / std;
570
+ let v = data.length - 1;
571
+ let UL = Z_lsl + Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_lsl, 2) / (2 * v));
572
+ let LL = Z_lsl - Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_lsl, 2) / (2 * v));
573
+ let UU = Z_usl + Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_usl, 2) / (2 * v));
574
+ let LU = Z_usl - Z_1_a2 * Math.sqrt(1 / data.length + Math.pow(Z_usl, 2) / (2 * v));
575
+ let PPM_L = (1 - Distributions.Normal.cdf((mean - spec.LSL) / std, 0, 1)) * 1e6;
576
+ let PPM_U = (1 - Distributions.Normal.cdf((spec.USL - mean) / std, 0, 1)) * 1e6;
577
+ let p_hat = 1 - Distributions.Normal.cdf((mean - spec.LSL) / std, 0, 1) + (1 - Distributions.Normal.cdf((mean - spec.USL) / std, 0, 1));
578
+ let ln_p = Math.log(p_hat / (1 - p_hat));
579
+ let part_p_u = 1 / (p_hat * (1 - p_hat)) * (1 / std) * (Distributions.Normal.pdf((spec.USL - mean) / std) - Distributions.Normal.pdf((spec.LSL - mean) / std));
580
+ let part_p_v = 0.5 * (1 / (p_hat * (1 - p_hat))) * ((spec.USL - mean) / Math.pow(std, 3) * Distributions.Normal.pdf((spec.USL - mean) / std) - (spec.LSL - mean) / Math.pow(std, 3) * Distributions.Normal.pdf((spec.LSL - mean) / std));
581
+ let V_hat = Math.pow(part_p_u, 2) * Math.pow(std, 2) / mean + Math.pow(part_p_v, 2) * 2 * Math.pow(std, 4) / v;
582
+ let returner = {
583
+ LSL: {
584
+ PPM: PPM_L,
585
+ LB: 1e6 * (1 - Distributions.Normal.cdf(UL, 0, 1)),
586
+ UB: 1e6 * (1 - Distributions.Normal.cdf(LL, 0, 1))
587
+ },
588
+ USL: {
589
+ PPM: PPM_U,
590
+ LB: 1e6 * (1 - Distributions.Normal.cdf(UU, 0, 1)),
591
+ UB: 1e6 * (1 - Distributions.Normal.cdf(LU, 0, 1))
592
+ },
593
+ Total: {
594
+ PPM: PPM_L + PPM_U,
595
+ LB: Math.exp(ln_p - Z_1_a2 * Math.sqrt(V_hat)) / (1 + Math.exp(ln_p - Z_1_a2 * Math.sqrt(V_hat))) * 1e6,
596
+ UB: Math.exp(ln_p + Z_1_a2 * Math.sqrt(V_hat)) / (1 + Math.exp(ln_p + Z_1_a2 * Math.sqrt(V_hat))) * 1e6
597
+ }
598
+ };
599
+ return returner;
600
+ },
601
+ /**
483
602
  * Evaluates the capability index Pp(within).
484
603
  * @customfunction
485
604
  * @param data The data to evaluate.
@@ -487,7 +606,11 @@ var Capability = {
487
606
  */
488
607
  Pp(data, spec) {
489
608
  let standarddeviation = StDev.S(data);
490
- return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
609
+ if (!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)) {
610
+ return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
611
+ } else {
612
+ return NaN;
613
+ }
491
614
  },
492
615
  /**
493
616
  * Evaluates the capability index Ppk(within).
@@ -498,8 +621,8 @@ var Capability = {
498
621
  Ppk(data, spec) {
499
622
  let mean = Mean(data);
500
623
  let standarddeviation = StDev.S(data);
501
- let AbsUSL = spec.USL - mean;
502
- let AbsLSL = mean - spec.LSL;
624
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
625
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
503
626
  let min;
504
627
  if (AbsUSL < AbsLSL) {
505
628
  min = AbsUSL;
@@ -692,9 +815,11 @@ function CreateCapabilityPlot(data, specification) {
692
815
  ];
693
816
  AddInfoTable(ctx, overallInfo, 3 * chartSettings.width / 4, chartSettings.margins.top, chartSettings.width / 4, chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom, "Overall");
694
817
  const mean = Mean(data);
695
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width / 4, chartSettings.margins.top, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Overall");
696
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width / 4, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Within");
697
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [specification.LSL, specification.USL], chartSettings.width / 4, chartSettings.margins.top + 80 + 2 * (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Specs");
818
+ let plotMin = !isNaN(specification.LSL) ? specification.LSL : Math.max(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
819
+ let plotMax = !isNaN(specification.USL) ? specification.USL : Math.min(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
820
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Overall");
821
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Within");
822
+ AddLinePlot(ctx, plotMin, plotMax, mean, [specification.LSL, specification.USL], chartSettings.width / 4 + 25, chartSettings.margins.top + 80 + 2 * (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Specs");
698
823
  return canvas;
699
824
  }
700
825
  var Beta = {
@@ -1542,9 +1667,10 @@ var Distributions = {
1542
1667
  let S = Distributions.Normal.Skewness(data);
1543
1668
  let K = Distributions.Normal.Kurtosis(data);
1544
1669
  let JB = N / 6 * (Math.pow(S, 2) + 0.25 * Math.pow(K, 2));
1670
+ let p = Distributions.ChiSq.RightTail(JB, 2);
1545
1671
  return {
1546
1672
  JB,
1547
- p: Distributions.ChiSq.RightTail(JB, 2)
1673
+ p: p > 1 || p < 5e-3 ? "<0.005" : p
1548
1674
  };
1549
1675
  },
1550
1676
  Kurtosis(data) {
@@ -1577,7 +1703,7 @@ var Distributions = {
1577
1703
  let p = GoodnessOfFit.AndersonDarling.p(KS, N);
1578
1704
  return {
1579
1705
  KS,
1580
- p
1706
+ p: p > 1 || p < 5e-3 ? "<0.005" : p
1581
1707
  };
1582
1708
  },
1583
1709
  Lilliefors: {
@@ -1594,6 +1720,9 @@ var Distributions = {
1594
1720
  if (p === 1) {
1595
1721
  p = Distributions.Normal.Lilliefors.pApprox(KS, N);
1596
1722
  }
1723
+ if (!Number.isNaN(p)) {
1724
+ p = Number(p) > 1 || Number(p) < 5e-3 ? "<0.005" : p;
1725
+ }
1597
1726
  return p;
1598
1727
  },
1599
1728
  pApprox(KS, N) {
@@ -1735,9 +1864,10 @@ var Distributions = {
1735
1864
  let p_mu = 38915e-7 * Math.pow(Math.log(N), 3) - 0.083751 * Math.pow(Math.log(N), 2) - 0.31082 * Math.log(N) - 1.5861;
1736
1865
  let p_sigma = Math.exp(30302e-7 * Math.pow(Math.log(N), 2) - 0.082676 * Math.log(N) - 0.4803);
1737
1866
  let z = (Math.log(1 - W) - p_mu) / p_sigma;
1867
+ let p = 1 - Distributions.Normal.cdf(z, 0, 1);
1738
1868
  return {
1739
1869
  W,
1740
- p: 1 - Distributions.Normal.cdf(z, 0, 1)
1870
+ p: p < 5e-3 ? "<0.005" : p
1741
1871
  };
1742
1872
  },
1743
1873
  Test(data, algorithmic) {
@@ -1806,7 +1936,8 @@ var Distributions = {
1806
1936
  let w2 = wArray[inflection];
1807
1937
  let p1 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection - 1];
1808
1938
  let p2 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection];
1809
- return p1 + (p2 - p1) / (w2 - w1) * (W - w1);
1939
+ let p = p1 + (p2 - p1) / (w2 - w1) * (W - w1);
1940
+ return p < 5e-3 ? "<0.005" : p;
1810
1941
  },
1811
1942
  pChart: {
1812
1943
  wValues: [
@@ -2208,7 +2339,7 @@ var GoodnessOfFit = {
2208
2339
  if (ADStar <= 0.2) {
2209
2340
  p = 1 - Math.exp(-13.436 + 101.14 * ADStar - 223.73 * Math.pow(ADStar, 2));
2210
2341
  }
2211
- return p;
2342
+ return p > 1 || p < 5e-3 ? "<0.005" : p;
2212
2343
  },
2213
2344
  /**
2214
2345
  * Evaluates the Anderson-Darling goodness-of-fit test for the specified data and cumulative distribution function.
@@ -2431,11 +2562,10 @@ function Median(data) {
2431
2562
  }
2432
2563
  function MovingRange(data, w = 2) {
2433
2564
  let movingRange = [];
2434
- for (let i = 1; i < data.length; i++) {
2435
- let h = i - w + 1;
2565
+ for (let i = 0; i < data.length + 1 - w; i++) {
2436
2566
  let values = [];
2437
2567
  for (let j = 0; j < w; j++) {
2438
- values.push(Number(data[h + j]));
2568
+ values.push(Number(data[i + j]));
2439
2569
  }
2440
2570
  movingRange.push(CalculateRange(values));
2441
2571
  }
@@ -3723,7 +3853,6 @@ var ANOVA = {
3723
3853
  chartSet.width += 1e3;
3724
3854
  chartSet.axis.y.tickOnly = true;
3725
3855
  let graph = CreateSplitGraph(individualCharts, `Main Effects Plot of ${Object.keys(response)[0]}`, chartSet);
3726
- console.log(graph);
3727
3856
  return graph;
3728
3857
  },
3729
3858
  Table(factors, response) {
@@ -3839,7 +3968,6 @@ var ANOVA = {
3839
3968
  });
3840
3969
  }
3841
3970
  });
3842
- console.log(k, SS);
3843
3971
  });
3844
3972
  return anovaTable;
3845
3973
  }
package/index.ts CHANGED
@@ -50,7 +50,7 @@ export class Specification{
50
50
  ParseSpec(spec: string) {
51
51
  // This function parses specs and returns an array of values, in this order:
52
52
  // Nominal, USL, LSL, Units, Tolerance(if UT and LT differ then {UT, LT})
53
- let string = spec.replace(/\,/g, ".");
53
+ let string = spec.replace(/\,/g, ".").toUpperCase().replace(/MIN/g, ">").replace(/MAX/g, "<").replace(/\-\-/g,"—");
54
54
  let nominal;
55
55
  let USL;
56
56
  let LSL;
@@ -58,7 +58,39 @@ export class Specification{
58
58
  let tol_minus;
59
59
  let tol;
60
60
  let units;
61
-
61
+
62
+ if (string.indexOf("—") !== -1){
63
+ let bookends = string.split("—").map(c => {return Number(c)});
64
+ USL = Math.max(...bookends);
65
+ LSL = Math.min(...bookends);
66
+ tol = USL - LSL;
67
+
68
+ return {
69
+ nominal: NaN,
70
+ USL: USL,
71
+ LSL: LSL,
72
+ units: '',
73
+ tolerance: tol
74
+ }
75
+ }
76
+ if (string.indexOf("<") !== -1){
77
+ return {
78
+ nominal: NaN,
79
+ USL: Number(string.substring(string.indexOf("<")+1)),
80
+ LSL: NaN,
81
+ units: '',
82
+ tolerance: NaN
83
+ }
84
+ }
85
+ if (string.indexOf(">") !== -1){
86
+ return {
87
+ nominal: NaN,
88
+ USL: NaN,
89
+ LSL: Number(string.substring(string.indexOf(">")+1)),
90
+ units: '',
91
+ tolerance: NaN
92
+ }
93
+ }
62
94
  if (string.indexOf("±") !== -1) {
63
95
  nominal = Number(string.substring(0, string.indexOf("±")).replace("Ø", ""));
64
96
  let after = this.SplitUnits(string.substring(string.indexOf("±") + 1));
@@ -71,16 +103,18 @@ export class Specification{
71
103
  tol_plus = Number(this.SplitUnits(string.substring(string.indexOf("+") + 1, string.indexOf("/") > 0 ? string.indexOf("/") : string.indexOf("-") > 0 ? string.indexOf("-") : undefined))[0]);
72
104
  nominal = Number(this.SplitUnits(string)[0].substring(0, string.indexOf("+")));
73
105
  if(string.indexOf("-") === -1){
74
- tol_minus = 0;
106
+ tol_minus = NaN;
75
107
  }
76
108
  }
77
109
  if (string.indexOf("-") !== -1) {
78
110
  tol_minus = Number(this.SplitUnits(string.substring(string.indexOf("/") > 0 ? Math.max(string.indexOf("/"), string.indexOf("-")) + 1 : string.indexOf("-") + 1))[0]);
79
111
  if(string.indexOf("+") === -1){
80
- tol_plus = 0;
112
+ tol_plus = NaN;
81
113
  nominal = Number(this.SplitUnits(string.substring(0, string.indexOf("/") > 0 ? Math.min(string.indexOf("/"), string.indexOf("-")) : string.indexOf("-")))[0])
82
114
  }
83
115
  }
116
+ USL = nominal + tol_plus
117
+ LSL = nominal - tol_minus
84
118
  if (string.indexOf("+-") !== -1 || string.indexOf("+/-") !== -1) {
85
119
  nominal = Number(string.substring(0, string.indexOf("+")));
86
120
  let after = this.SplitUnits(string.substring(string.indexOf("-") + 1));
@@ -488,14 +522,35 @@ export function RoundTO(number: number, digits: number){
488
522
  }
489
523
  let str = number.toString();
490
524
  let decimalIndex = str.indexOf('.');
525
+ let roundFinalDigit = Number(str.substring(decimalIndex + digits + 2,decimalIndex + digits + 3)) >= 5
526
+
491
527
  let returner = Number(str.substring(0, decimalIndex + digits + 1));
492
-
528
+ if(roundFinalDigit){
529
+ returner = returner + Math.pow(10,-1*digits)
530
+ }
531
+
493
532
  let i = 0;
494
533
  while(returner === 0){
495
534
  i++;
496
535
  returner = Number(str.substring(0, decimalIndex + digits + 1 + i));
497
536
  }
498
- return returner
537
+ if(Math.abs(number) < .0001){
538
+ let f_i = 0;
539
+ let l_i = 0;
540
+ let d_i = 0;
541
+ let i = 0;
542
+ while(d_i <= digits){
543
+ if(str[i] != "0" && str[i] != "."){
544
+ d_i += 1;
545
+ if(f_i == 0){f_i = i};
546
+ }
547
+ i += 1
548
+ }
549
+ l_i = i;
550
+
551
+ return str[f_i] + "." + str.substring(f_i + 1, f_i + digits) + "e-" + (f_i - decimalIndex);
552
+ }
553
+ return Number(`${returner}`.substring(0, decimalIndex + digits + 1))
499
554
  }
500
555
 
501
556
  // End Classes
@@ -509,11 +564,12 @@ export const Capability = {
509
564
  * @customfunction
510
565
  * @param data The data to evaluate.
511
566
  * @param spec The specification to evaluate the capability against.
567
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
512
568
  */
513
- Analysis(data: number[], spec: Specification){
569
+ Analysis(data: number[], spec: Specification, subgroupSize: number = 2){
514
570
  return {
515
- Cp: Capability.Cp(data, spec),
516
- Cpk: Capability.Cpk(data, spec),
571
+ Cp: Capability.Cp(data, spec, subgroupSize),
572
+ Cpk: Capability.Cpk(data, spec, subgroupSize),
517
573
  Pp: Capability.Pp(data, spec),
518
574
  Ppk: Capability.Ppk(data, spec),
519
575
  }
@@ -523,23 +579,28 @@ export const Capability = {
523
579
  * @customfunction
524
580
  * @param data The data to evaluate.
525
581
  * @param spec The specification to evaluate the capability against.
582
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
526
583
  */
527
- Cp(data: number[], spec: Specification){
528
- let standarddeviation = StDev.W(data, 2);
529
-
530
- return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
584
+ Cp(data: number[], spec: Specification, subgroupSize: number = 2){
585
+ let standarddeviation = StDev.W(data, subgroupSize);
586
+ if(!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)){
587
+ return Number((spec.USL - spec.LSL) / (6 * standarddeviation));
588
+ }else{
589
+ return NaN
590
+ }
531
591
  },
532
592
  /**
533
593
  * Evaluates the capability index Cpk(overall).
534
594
  * @customfunction
535
595
  * @param data The data to evaluate.
536
596
  * @param spec The specification to evaluate the capability against.
597
+ * @param subgroupSize The size of the subgroup to use for calculating within standard deviation
537
598
  */
538
- Cpk(data: number[], spec: Specification){
599
+ Cpk(data: number[], spec: Specification, subgroupSize: number = 2){
539
600
  let mean = Mean(data);
540
- let standarddeviation = StDev.W(data,2);
541
- let AbsUSL = spec.USL - mean;
542
- let AbsLSL = mean - spec.LSL;
601
+ let standarddeviation = StDev.W(data, subgroupSize);
602
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
603
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
543
604
  let min;
544
605
  if (AbsUSL < AbsLSL) {
545
606
  min = AbsUSL;
@@ -551,6 +612,64 @@ export const Capability = {
551
612
 
552
613
  },
553
614
  /**
615
+ * Evaluates the capability index Cpk(overall).
616
+ * @customfunction
617
+ * @param data The data to evaluate.
618
+ * @param spec The specification to evaluate the capability against.
619
+ * @param target The target value of the process
620
+ */
621
+ Cpm(data: number[], spec: Specification, target: number){
622
+ return Math.min(spec.USL - target, target - spec.LSL)/(3*Math.sqrt(SumSquaredDeviation(data, target)/data.length))
623
+ },
624
+ /**
625
+ * Calculates the defective parts per million.
626
+ * @customfunction
627
+ * @param data The data to evaluate.
628
+ * @param spec The specification to evaluate against.
629
+ * @param confidenceInterval [OPTIONAL] The desired confidence level of the analysis. DEFAULT = 0.95 (95%)
630
+ */
631
+ DPPM(data: number[], spec: Specification, confidenceInterval: number = 0.95){
632
+ let mean = Mean(data)
633
+ let std = StDev.S(data)
634
+ let a = 1 - confidenceInterval
635
+ let Z_1_a2 = Distributions.Normal.inv(1 - a/2);
636
+ let Z_lsl = (mean - spec.LSL)/std
637
+ let Z_usl = (spec.USL - mean)/std
638
+ let v = data.length - 1
639
+ let UL = Z_lsl + Z_1_a2 * Math.sqrt(1/data.length + Math.pow(Z_lsl, 2)/(2*v))
640
+ let LL = Z_lsl - Z_1_a2 * Math.sqrt(1/data.length + Math.pow(Z_lsl, 2)/(2*v))
641
+ let UU = Z_usl + Z_1_a2 * Math.sqrt(1/data.length + Math.pow(Z_usl, 2)/(2*v))
642
+ let LU = Z_usl - Z_1_a2 * Math.sqrt(1/data.length + Math.pow(Z_usl, 2)/(2*v))
643
+ let PPM_L = (1 - Distributions.Normal.cdf((mean - spec.LSL)/std, 0, 1)) * 1000000
644
+ let PPM_U = (1 - Distributions.Normal.cdf((spec.USL - mean)/std, 0, 1)) * 1000000
645
+
646
+ let p_hat = (1 - Distributions.Normal.cdf((mean - spec.LSL)/std, 0, 1)) + (1 - Distributions.Normal.cdf((mean - spec.USL)/std, 0, 1))
647
+ let ln_p = Math.log(p_hat/(1 - p_hat));
648
+ let part_p_u = (1/(p_hat * (1 - p_hat))) * (1/std) * (Distributions.Normal.pdf((spec.USL - mean)/std) - Distributions.Normal.pdf((spec.LSL - mean)/std))
649
+ let part_p_v = .5 * (1/(p_hat * (1 - p_hat))) * ( (spec.USL - mean)/Math.pow(std, 3) * Distributions.Normal.pdf((spec.USL - mean)/std) - (spec.LSL - mean)/Math.pow(std, 3) * Distributions.Normal.pdf((spec.LSL - mean)/std))
650
+ let V_hat = Math.pow(part_p_u,2) * Math.pow(std, 2)/mean + Math.pow(part_p_v, 2) * 2 * Math.pow(std, 4)/v
651
+
652
+ let returner = {
653
+ LSL: {
654
+ PPM: PPM_L,
655
+ LB: 1000000 * (1 - Distributions.Normal.cdf(UL, 0, 1)),
656
+ UB: 1000000 * (1 - Distributions.Normal.cdf(LL, 0, 1)),
657
+ },
658
+ USL: {
659
+ PPM: PPM_U,
660
+ LB: 1000000 * (1 - Distributions.Normal.cdf(UU, 0, 1)),
661
+ UB: 1000000 * (1 - Distributions.Normal.cdf(LU, 0, 1)),
662
+ },
663
+ Total: {
664
+ PPM: PPM_L + PPM_U,
665
+ LB: Math.exp(ln_p - Z_1_a2*Math.sqrt(V_hat))/(1 + Math.exp(ln_p - Z_1_a2*Math.sqrt(V_hat))) * 1000000,
666
+ UB: Math.exp(ln_p + Z_1_a2*Math.sqrt(V_hat))/(1 + Math.exp(ln_p + Z_1_a2*Math.sqrt(V_hat))) * 1000000
667
+ }
668
+ }
669
+
670
+ return returner
671
+ },
672
+ /**
554
673
  * Evaluates the capability index Pp(within).
555
674
  * @customfunction
556
675
  * @param data The data to evaluate.
@@ -559,7 +678,12 @@ export const Capability = {
559
678
  Pp(data: number[], spec: Specification) {
560
679
  let standarddeviation = StDev.S(data);
561
680
 
562
- return Number((spec.USL-spec.LSL) / (6 * standarddeviation));
681
+ if(!Number.isNaN(spec.USL) && !Number.isNaN(spec.LSL)){
682
+ return Number((spec.USL-spec.LSL) / (6 * standarddeviation));
683
+ }else{
684
+ return NaN
685
+ }
686
+
563
687
 
564
688
  },
565
689
  /**
@@ -571,8 +695,8 @@ export const Capability = {
571
695
  Ppk(data: number[], spec: Specification) {
572
696
  let mean = Mean(data);
573
697
  let standarddeviation = StDev.S(data);
574
- let AbsUSL = spec.USL - mean;
575
- let AbsLSL = mean - spec.LSL;
698
+ let AbsUSL = !Number.isNaN(spec.USL) ? spec.USL - mean : Infinity;
699
+ let AbsLSL = !Number.isNaN(spec.LSL) ? mean - spec.LSL : Infinity;
576
700
  let min;
577
701
  if (AbsUSL < AbsLSL) {
578
702
  min = AbsUSL;
@@ -809,13 +933,17 @@ export function CreateCapabilityPlot(data: number[], specification: Specificatio
809
933
  AddInfoTable(ctx, overallInfo, 3*chartSettings.width/4, chartSettings.margins.top, chartSettings.width/4, chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom, "Overall");
810
934
 
811
935
  const mean = Mean(data);
936
+ let plotMin = !isNaN(specification.LSL) ? specification.LSL : Math.max(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
937
+ let plotMax = !isNaN(specification.USL) ? specification.USL : Math.min(mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value, mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value);
938
+
812
939
  // Add Overall Line Plot
813
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width/4, chartSettings.margins.top, chartSettings.width/2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom)/3 - 10, "Overall")
814
-
940
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * overallInfo[0].value, mean + 3 * overallInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Overall");
941
+
815
942
  // Add Within Line Plot
816
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width/4, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom)/3, chartSettings.width/2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom)/3 - 10, "Within")
943
+ AddLinePlot(ctx, plotMin, plotMax, mean, [mean - 3 * withinInfo[0].value, mean + 3 * withinInfo[0].value], chartSettings.width / 4 + 25, chartSettings.margins.top + 40 + (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Within");
944
+
817
945
  // Add Specs Line Plot
818
- AddLinePlot(ctx, specification.LSL, specification.USL, mean, [specification.LSL, specification.USL], chartSettings.width/4, chartSettings.margins.top + 80 + 2*(chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom)/3, chartSettings.width/2, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom)/3 - 10, "Specs")
946
+ AddLinePlot(ctx, plotMin, plotMax, mean, [specification.LSL, specification.USL], chartSettings.width / 4 + 25, chartSettings.margins.top + 80 + 2 * (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3, chartSettings.width / 2 - 50, (chartSettings.height - chartSettings.margins.top - chartSettings.margins.bottom) / 3 - 10, "Specs");
819
947
  return canvas;
820
948
  }
821
949
 
@@ -1713,13 +1841,13 @@ export const Distributions = {
1713
1841
  let K = Distributions.Normal.Kurtosis(data);
1714
1842
 
1715
1843
  let JB = (N/6)*(Math.pow(S, 2) + .25 * Math.pow(K, 2));
1844
+ let p = Distributions.ChiSq.RightTail(JB, 2)
1716
1845
  return {
1717
1846
  JB: JB,
1718
- p: Distributions.ChiSq.RightTail(JB, 2)
1847
+ p: p > 1 || p < 0.005 ? "<0.005" : p
1719
1848
  }
1720
1849
  },
1721
1850
  Kurtosis(data){
1722
- // SRC: https://www.omnicalculator.com/statistics/skewness#what-are-skewness-and-kurtosis
1723
1851
  let N = data.length;
1724
1852
  let mean = Mean(data);
1725
1853
  let numsum = 0;
@@ -1748,7 +1876,7 @@ export const Distributions = {
1748
1876
  let p = GoodnessOfFit.AndersonDarling.p(KS, N);
1749
1877
  return {
1750
1878
  KS: KS,
1751
- p: p
1879
+ p: p > 1 || p < 0.005 ? "<0.005" : p
1752
1880
  };
1753
1881
  },
1754
1882
  Lilliefors:{
@@ -1765,6 +1893,9 @@ export const Distributions = {
1765
1893
  if(p === 1){
1766
1894
  p = Distributions.Normal.Lilliefors.pApprox(KS, N)
1767
1895
  }
1896
+ if(!Number.isNaN(p)){
1897
+ p = Number(p) > 1 || Number(p) < 0.005 ? "<0.005" : p
1898
+ }
1768
1899
  return p;
1769
1900
  },
1770
1901
  pApprox(KS: number, N: number){
@@ -1910,10 +2041,10 @@ export const Distributions = {
1910
2041
  let p_mu = 0.0038915*Math.pow(Math.log(N),3)-0.083751*Math.pow(Math.log(N),2)-0.31082*Math.log(N)-1.5861;
1911
2042
  let p_sigma = Math.exp(0.0030302*Math.pow(Math.log(N),2)-0.082676*Math.log(N)-0.4803);
1912
2043
  let z = (Math.log(1 - W) - p_mu)/p_sigma;
1913
-
2044
+ let p = 1 - Distributions.Normal.cdf(z, 0, 1)
1914
2045
  return {
1915
2046
  W: W,
1916
- p: 1 - Distributions.Normal.cdf(z, 0, 1)
2047
+ p: p < .005 ? "<0.005" : p
1917
2048
  }
1918
2049
  },
1919
2050
  Test(data: number[], algorithmic?: boolean){
@@ -1986,7 +2117,8 @@ export const Distributions = {
1986
2117
  let w2 = wArray[inflection];
1987
2118
  let p1 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection - 1]
1988
2119
  let p2 = Distributions.Normal.ShapiroWilk.pChart.pValues[inflection]
1989
- return p1 + ((p2-p1)/(w2-w1))*(W-w1);
2120
+ let p = p1 + ((p2-p1)/(w2-w1))*(W-w1);
2121
+ return p < .005 ? "<0.005" : p
1990
2122
  },
1991
2123
  pChart:{
1992
2124
  wValues: [[0.753,0.756,0.767,0.789,0.959,0.998,0.999,1,1,],
@@ -2377,7 +2509,7 @@ export const GoodnessOfFit = {
2377
2509
  if (ADStar <= .2) {
2378
2510
  p = 1 - Math.exp(-13.436 + 101.14 * ADStar - 223.73 * Math.pow(ADStar, 2))
2379
2511
  }
2380
- return p;
2512
+ return p > 1 || p < 0.005 ? "<0.005" : p;
2381
2513
  },
2382
2514
  /**
2383
2515
  * Evaluates the Anderson-Darling goodness-of-fit test for the specified data and cumulative distribution function.
@@ -2749,12 +2881,10 @@ export function Median(data: any[]){
2749
2881
  export function MovingRange(data: any[], w: number = 2){
2750
2882
  let movingRange: number[] = [];
2751
2883
 
2752
- for(let i = 1; i < data.length; i++){
2753
- let h = i - w + 1;
2754
-
2884
+ for(let i = 0; i < data.length + 1 - w; i++){
2755
2885
  let values: number[] = [];
2756
2886
  for(let j = 0; j < w; j++){
2757
- values.push(Number(data[h + j]));
2887
+ values.push(Number(data[i + j]));
2758
2888
  }
2759
2889
 
2760
2890
  movingRange.push(CalculateRange(values))
@@ -4126,7 +4256,6 @@ export const ANOVA = {
4126
4256
  chartSet.width += 1000
4127
4257
  chartSet.axis.y.tickOnly = true
4128
4258
  let graph = CreateSplitGraph(individualCharts, `Main Effects Plot of ${Object.keys(response)[0]}`, chartSet)
4129
- console.log(graph)
4130
4259
  return graph
4131
4260
  },
4132
4261
  Table(factors: any, response: any){
@@ -4257,7 +4386,6 @@ export const ANOVA = {
4257
4386
  })
4258
4387
  }
4259
4388
  })
4260
- console.log(k, SS);
4261
4389
  })
4262
4390
 
4263
4391
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qesuite",
3
- "version": "1.0.53",
3
+ "version": "1.0.55",
4
4
  "description": "Performs advanced statistical analysis of data. Specifically designed for engineering statistical analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -0,0 +1,19 @@
1
+ ParseSpec() - added support for single-sided and range specifications
2
+ New Specification Types
3
+ - nom-tol_minus : singled-sided spec.; all values are to be greater than nom - tol_minus
4
+ - MIN# : singled-sided spec.; all values are to be greater than the number(#); not case sensitive
5
+ - <# : singled-sided spec.; all values are to be less than the number(#)
6
+ - nom+tol_plus : singled-sided spec.; all values are to be less than nom + tol_plus
7
+ - MAX# : singled-sided spec.; all values are to be less than the number(#); not case sensitive
8
+ - ># : singled-sided spec.; all values are to be greater than the number(#)
9
+ - a--b: range spec.; all values are to be between numbers a & b
10
+ - a—b: range spec.; all values are to be between numbers a & b
11
+ Affected QE.FN()'s
12
+ - QE.CAPABILITYANALYSIS()
13
+ - QE.CP()
14
+ - QE.CPK()
15
+ - QE.PP()
16
+ - QE.PPK()
17
+ - QE.CHEBYSHEV()
18
+
19
+ p-values: fixed bug that allowed p-values > 1
@@ -0,0 +1,2 @@
1
+ Bug Fix: Capability plots did not have missing bounds when using single sided tolerances
2
+ Added rounding on final decimal of RoundTO() and added support for Scientific notation