Skip to content

Commit

Permalink
Merge pull request #286 from JalenEvans/TrailingDigitsTest
Browse files Browse the repository at this point in the history
countOfTrailingDigits() Bug Fix
  • Loading branch information
bowring authored Jan 17, 2025
2 parents d62204f + 5b2a16a commit 819c839
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,43 @@ public class FormatterForSigFigN {
*/
public static int countOfTrailingDigitsForSigFig(double standardError, int sigFig) {
int countOfTrailingDigitsForSigFig = 0;
if (Math.abs(standardError) < 10.0) {
if (Math.abs(standardError) < 10.0 && Math.abs(standardError) > 0.0) {
double rounded = MathUtilities.roundedToSize(standardError, sigFig);
DecimalFormat df = new DecimalFormat("#");
String pattern = generatePattern(rounded, sigFig);
DecimalFormat df = new DecimalFormat(pattern);
df.setMaximumFractionDigits(8);
String roundedString = df.format(rounded);
int dotIndex = roundedString.indexOf(".");
countOfTrailingDigitsForSigFig = Math.max(roundedString.length() - dotIndex - 1, sigFig);
int scale = roundedString.split("\\.")[1].length();
countOfTrailingDigitsForSigFig = scale;
}
return countOfTrailingDigitsForSigFig;
}

/**
* Generates a DecimalFormat pattern that allows for a certain amount of trailing zeros specified by
* the amount of significant figures
* @param rounded
* @return String pattern to be used in DecimalFormat
*/
public static String generatePattern(double rounded, int sigFig) {
String pattern = "#.";
if (Double.isFinite(rounded)) {
// Converts the decimal value to a BigDecimal to find the scale
BigDecimal valueBD = new BigDecimal(String.valueOf(rounded));
int scale = sigFig - (valueBD.precision() - valueBD.scale());

// Allows for a trailing zero in each decimal place within the scale
for (int i = 0; i < scale; i++) {
pattern += "0";
}

return pattern;
}

// Returns default pattern if rounded number is infinite
return "#";
}

/**
* see https://docs.google.com/document/d/14PPEDEJPylNMavpJDpYSuemNb0gF5dz_To3Ek1Y_Agw/edit#bookmark=id.bf8wjg6paqcw
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static int nChooseR(int n, int r) {

/**
* see https://docs.google.com/document/d/14PPEDEJPylNMavpJDpYSuemNb0gF5dz_To3Ek1Y_Agw/edit#bookmark=id.k016qg1ghequ
* seehttps://www.lexjansen.com/wuss/2007/DatabaseMgtWarehousing/DMW_Lin_CleaningData.pdf
* see https://www.lexjansen.com/wuss/2007/DatabaseMgtWarehousing/DMW_Lin_CleaningData.pdf
*
* @param dataIn
* @return
Expand All @@ -76,12 +76,14 @@ public static boolean[] applyChauvenetsCriterion(double[] dataIn, boolean[] incl
For now, assume a default value of ChauvenetRejectionProbability = 0.5. In the future, we can ask the user to input
this constant (must be on [0,1]), but I’ve never heard of anyone using a different value than 0.5.
***
Assemble the data to evaluate into a vector called data. Do not include cycles and blocks previously rejected by the user in the data vector.
The number of elements in data is n
Calculate the mean and standard deviation of data, xbar and stddev.
For each element of data, calculate absZ_i = abs(data_i - xbar) / stddev where abs() is the absolute value
Calculate Chauvenet’s criterion, C_i = n * erfc(absZ_i) for each absZ_i
Identify all data with C_i > ChauvenetRejectionProbability as an outlier by Chauvenet’s Criterion
***
Plot Chauvenet-identified outliers in red and recalculate all statistics after rejecting the identified outliers.
Gray out the Chauvenet button so that it can’t be re-applied.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
package org.cirdles.tripoli.utilities.mathUtilities;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import static org.apache.commons.math3.special.Erf.erfc;
import com.google.common.math.Stats;

class MathUtilitiesTest {

double[] arr;
boolean[] indices;

boolean[] solvedIndices;

@BeforeEach
/**
* Created a data set of double values
*
* Document the process of using the python script and mention the imports used
*/
void setUp() {
//Create an array of doubles
arr = new double[] {47.3, 50.5, 53.7, 55.8, 55.0, 56.0001, 57.0012345678, 57.004999, 58.153, 58.852, 58.123, 58.543, 60.415, 60.794, 60.351,
61.751, 61.652, 61.325, 61.587, 61.126, 61.897, 62.543, 62.258, 62.689, 63.5473, 63.789, 64.369, 67.115, 68.142, 72.368};
indices = new boolean[] {true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true};


solvedIndices = new boolean[] {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false};
}

@AfterEach
void tearDown() {
}

@Test
void roundedToSize() {

Expand All @@ -30,4 +62,64 @@ void nChooseR() {
assertEquals(20, MathUtilities.nChooseR(6, 3)); // n=6, r=3
assertEquals(252, MathUtilities.nChooseR(10, 5)); // n=10, r=5
}

@Test
void applyChauvenetsCriterion() {
assertArrayEquals(solvedIndices, MathUtilities.applyChauvenetsCriterion(arr, indices));
}

@Test
void testDescriptiveStatistics() {
//Add all data points to Descriptive Statistics (descStats)
DescriptiveStatistics descStats = new DescriptiveStatistics();
for (int i = 0; i < arr.length; i++) {
descStats.addValue(arr[i]);
}

//Add all data points to Stats (stats)
Stats stats = Stats.of(arr);

//Compare their respective methods
assertEquals(descStats.getMean(), stats.mean(), 0.000000000001);
assertEquals(descStats.getStandardDeviation(), stats.sampleStandardDeviation(), 0.00000000001);
}

@Test
void testRoundedToSize() {
int sigFigs = 4;

double[] nums = {6.1542565, 2.36489, 8.9125, 0.025483, 10.5475, 103.2578, 0.00012563, 0.2000, 0.0000, 2.0, 3};

double[] actual = new double[nums.length];

double[] expected = {6.154,2.365,8.913,0.02548,10.55,103.3,0.0001256,0.2000,0.0000,2.000,3.000}; // Iff sigFigs is equal to 4

for (int i = 0; i < nums.length; i++) {
actual[i] = MathUtilities.roundedToSize(nums[i], sigFigs);
}

assertArrayEquals(expected, actual);
}


@Test
void testCountOfTrailingDigits() {
int sigFigs = 4;

/*
Conditions for a Good Set of Numbers: Include Whole Integers, Numbers with Trailing Zeros, Numbers with Leading Zeros,
Numbers greater than 10, Numbers less than 10, Numbers with Spurious Digits, Numbers with 0s in between Non-Zero digits,
*/
double[] nums = {6.1542565, 2.30089, 8.9125, 0.025483, 10.5475, 103.2578, 0.00012563, 0.2000, 0.0000, 2.0, 3};
double[] actual = new double[nums.length];

double[] expected = {3,3,3,5,0,0,7,4,0,3,3}; // Iff sigFigs is equal to 4

for (int i = 0; i < nums.length; i++) {
actual[i] = FormatterForSigFigN.countOfTrailingDigitsForSigFig(nums[i], sigFigs);
}

assertArrayEquals(expected, actual);
}
}

0 comments on commit 819c839

Please sign in to comment.