From 5056938522014c300115f4c6bb2271b68ca3094d Mon Sep 17 00:00:00 2001 From: zdanaceau Date: Fri, 19 Aug 2022 10:59:54 -0500 Subject: [PATCH] Cleaned up code, removing outdated methods and fixing minor issues. --- FCWTAPI/CWTOutput.cs | 34 +++- FCWTAPI/FCWTAPI.cs | 214 +------------------------- FCWTAPI/GaussianSmoothing.cs | 27 ---- TestFCWTAPI/FCWTAPITests.cs | 77 --------- TestFCWTAPI/GaussianSmoothingTests.cs | 78 ---------- 5 files changed, 33 insertions(+), 397 deletions(-) diff --git a/FCWTAPI/CWTOutput.cs b/FCWTAPI/CWTOutput.cs index fe1e52e..f57ebb9 100644 --- a/FCWTAPI/CWTOutput.cs +++ b/FCWTAPI/CWTOutput.cs @@ -15,8 +15,8 @@ public class CWTOutput public CWTOutput(double[][] real, double[][] imag) { - RealArray = FCWTAPI.ToTwoDArray(real); - ImagArray = FCWTAPI.ToTwoDArray(imag); + RealArray = ToTwoDArray(real); + ImagArray = ToTwoDArray(imag); Columns = RealArray.GetLength(1); Rows = RealArray.GetLength(0); } @@ -54,5 +54,35 @@ public CWTOutput(double[][] real, double[][] imag) } return output; } + public static double[,] ToTwoDArray(double[][] jaggedTwoD) + { + int arrayCount = jaggedTwoD.Length; + int arrayLength = jaggedTwoD[0].Length; + double[,] twodOutput = new double[arrayCount, arrayLength]; + for (int i = 0; i < arrayCount; i++) + { + if (i > 0) + { + if (jaggedTwoD[i].Length != jaggedTwoD[i - 1].Length) + { + arrayLength = jaggedTwoD[i].Length + 1; + } + } + try + { + for (int j = 0; j < arrayLength; j++) + { + twodOutput[i, j] = jaggedTwoD[i][j]; + } + } + catch (IndexOutOfRangeException) + { + string rowError = String.Format("Invalid array length in row {0}", i); + throw new IndexOutOfRangeException(rowError); + } + + } + return twodOutput; + } } } diff --git a/FCWTAPI/FCWTAPI.cs b/FCWTAPI/FCWTAPI.cs index 3057628..1d9d769 100644 --- a/FCWTAPI/FCWTAPI.cs +++ b/FCWTAPI/FCWTAPI.cs @@ -107,219 +107,7 @@ private static float ToFloat(double value) private static float[] GenerateOutputArray(int size, int noctave, int nvoice) { return new float[size * noctave * nvoice * 2]; - } - /// - /// Moves the 1D array to a 2D jagged array. - /// - /// - /// - /// - /// - /// - public static float[][] FixOutputArray(float[] array1D, int size, int noctave, int nvoice) - { - // From the original fCWT library code - int numberCols = noctave * nvoice * 2; - int numberRows = size; - // Creates the final with freq as higher dim - float[][] fixedResults = new float[numberCols][]; - for(int i = 0; i < numberCols; i += 2) - { - float[] imagtemp = new float[size]; - float[] realtemp = new float[size]; - for (int j = 0; j < numberRows; j++) - { - if(j % 2 == 0) - { - realtemp[j] = array1D[j]; - } - else - { - imagtemp[j] = array1D[j]; - } - } - fixedResults[i] = realtemp; - fixedResults[i + 1] = imagtemp; - } - return fixedResults; - } - - //First element corresponds to the first jagged array dimension (voices), second element corresponds to the second dim (timepoints) - - /// - /// Converts jagged 2D arrays to formal 2D arrays - /// The first dimension of the resulting 2D array corresponds to the voices - /// The second dimension corresponds to the time points of the input signal - /// - /// 2D jagged array to be converted - /// - /// - public static float[,] ToTwoDArray(float[][] jaggedTwoD) - { - - int arrayCount = jaggedTwoD.Length; - int arrayLength = jaggedTwoD[0].Length; - float[,] twodOutput = new float[arrayCount, arrayLength]; - for (int i = 0; i < arrayCount; i++) - { - if(i > 0) - { - if (jaggedTwoD[i].Length != jaggedTwoD[i - 1].Length) - { - arrayLength = jaggedTwoD[i].Length + 1; - } - } - try - { - for (int j = 0; j < arrayLength; j++) - { - twodOutput[i, j] = jaggedTwoD[i][j]; - } - } - catch(IndexOutOfRangeException) - { - string rowError = String.Format("Invalid array length in row {0}", i); - throw new IndexOutOfRangeException(rowError); - } - - } - return twodOutput; - } - public static double[,] ToTwoDArray(double[][] jaggedTwoD) - { - int arrayCount = jaggedTwoD.Length; - int arrayLength = jaggedTwoD[0].Length; - double[,] twodOutput = new double[arrayCount, arrayLength]; - for (int i = 0; i < arrayCount; i++) - { - if (i > 0) - { - if (jaggedTwoD[i].Length != jaggedTwoD[i - 1].Length) - { - arrayLength = jaggedTwoD[i].Length + 1; - } - } - try - { - for (int j = 0; j < arrayLength; j++) - { - twodOutput[i, j] = jaggedTwoD[i][j]; - } - } - catch (IndexOutOfRangeException) - { - string rowError = String.Format("Invalid array length in row {0}", i); - throw new IndexOutOfRangeException(rowError); - } - - } - return twodOutput; - } - - /// - /// Used to split the imaginary and the real arrays when using a complex wavelet, i.e. the morlet. - /// - /// - /// - /// - public static void SplitIntoRealAndImaginary(float[][] combinedArray, out float[][] realArray, out float[][] imaginaryArray) - { - // every other row is the opposite - int rowNumber = combinedArray.GetLength(0); - int colNumber = combinedArray[0].Length; - // row number will always be even when using a complex wavelet - - realArray = new float[colNumber / 2][]; - imaginaryArray = new float[colNumber / 2][]; - - int realIndexer = 0; - int imagIndexer = 0; - int combinedIndexer = 0; - while (combinedIndexer < colNumber) - { - int colLength = combinedArray[combinedIndexer].Length; - if (combinedIndexer % 2 == 0) - { - realArray[realIndexer] = new float[colLength]; - realArray[realIndexer] = combinedArray[combinedIndexer]; - realIndexer++; - } - else - { - imaginaryArray[imagIndexer] = new float[colLength]; - imaginaryArray[imagIndexer] = combinedArray[combinedIndexer]; - imagIndexer++; - } - combinedIndexer++; - } - } - /// - /// Calculates the phase of the continuous wavelet transform output using a morlet wavelet. - /// - /// The real part of the complex morlet CWT. - /// The imaginary part of the complex morlet CWT. - /// - /// - public static float[][] CalculatePhase(float[][] realArray, float[][] imagArray) - { - int realRows = realArray.GetLength(0); - int imagRows = imagArray.GetLength(0); - - int realCols = realArray[0].Length; - if(realRows != imagRows) - { - throw new ArgumentException("Real and imaginary arrays have unequal lengths"); - } - - float[][] phaseArray = new float[realRows][]; - - for(int i = 0; i < realRows; i++) - { - float[] temp = new float[realCols]; - for(int j =0; j < realCols; j++) - { - float val = imagArray[i][j] / realArray[i][j]; - double v = (Math.Atan((double)val)); - temp[j] = 1F / (float)v; - } - phaseArray[i] = temp; - } - return phaseArray; - } - /// - /// Calculates the modulus of the complex morlet continuous wavelet transform. - /// - /// - /// - /// - /// - public static float[][] CalculateModulus(float[][] realArray, float[][] imagArray) - { - int realRows = realArray.GetLength(0); - int imagRows = imagArray.GetLength(0); - - int realCols = realArray[0].Length; - if (realRows != imagRows) - { - throw new ArgumentException("Real and imaginary arrays have unequal lengths"); - } - - float[][] modArray = new float[realRows][]; - - for (int i = 0; i < realRows; i++) - { - float[] temp = new float[realCols]; - for (int j = 0; j < realCols; j++) - { - float val = realArray[i][j]*realArray[i][j] + imagArray[i][j]*imagArray[i][j]; - temp[j] = (float)Math.Sqrt((double)val); - } - modArray[i] = temp; - } - return modArray; - } - - + } } } \ No newline at end of file diff --git a/FCWTAPI/GaussianSmoothing.cs b/FCWTAPI/GaussianSmoothing.cs index b9bd6a7..8f7c1b1 100644 --- a/FCWTAPI/GaussianSmoothing.cs +++ b/FCWTAPI/GaussianSmoothing.cs @@ -105,33 +105,6 @@ public class GaussianSmoothing } return dim2Smoothing; } - public static double[,] EllipticGaussianConvolution(double[,] inputData, double frequencyDeviation, double timeDeviation) - { - if (inputData.GetLength(0) < (frequencyDeviation * 6 + 1) || inputData.GetLength(1) < (timeDeviation * 6 + 1)) - { - throw new ArgumentException("Matrix may not be smaller than the convoluting Gaussian kernel"); - } - double[,] frequencyKernel = CalculateNormalized1DSampleKernel(frequencyDeviation); - double[,] timeKernel = CalculateNormalized1DSampleKernel(timeDeviation); - // Calculates the 1D kernel to be used for smoothing - double[,] frequencySmoothing = new double[inputData.GetLength(0), inputData.GetLength(1)]; - double[,] timeSmoothing = new double[inputData.GetLength(0), inputData.GetLength(1)]; - // x-direction smoothing - for (int i = 0; i < inputData.GetLength(0); i++) - { - // Calculates each point in the x direction - for (int j = 0; j < inputData.GetLength(1); j++) - frequencySmoothing[i, j] = ProcessPoint(inputData, i, j, frequencyKernel, 0); - } - //y-direction smoothing - for (int i = 0; i < inputData.GetLength(0); i++) - { - //Calculates each point in the y direction from the x smoothed array res 1 - for (int j = 0; j < inputData.GetLength(1); j++) - timeSmoothing[i, j] = ProcessPoint(frequencySmoothing, i, j, timeKernel, 1); - } - return timeSmoothing; - } /// /// Performs 2D Gaussian smoothing using an elliptic Gaussian kernel /// diff --git a/TestFCWTAPI/FCWTAPITests.cs b/TestFCWTAPI/FCWTAPITests.cs index 3a89098..ef51d0a 100644 --- a/TestFCWTAPI/FCWTAPITests.cs +++ b/TestFCWTAPI/FCWTAPITests.cs @@ -38,83 +38,6 @@ public static void TestConvertDoubleToFloat() Assert.AreEqual((float)testArray[1], fArray[1]); } [Test] - public static void TestFixOutputArray() - { - float[] testArray = new float[] - {1F, 2F, 3F, - 4F, 5F, 6F, - 7F, 8F, 9F, - 10F, 11F, 12F}; - - float[][] outputArray = FCWTAPI.FixOutputArray(testArray, 3, 1, 2); - Assert.AreEqual(4, outputArray.GetLength(0)); - } - - - [Test] - public static void TestToTwoDArray() - { - float[][] testJagged2d = new float[][] - { - new float[] {1, 2, 3, 4, 5, 6}, - new float[] {7, 8, 9, 10, 11, 12 }, - new float[] {11, 12, 13, 14, 15, 16} - }; - float[,] test2DArray = FCWTAPI.ToTwoDArray(testJagged2d); - Assert.AreEqual(3, test2DArray.GetLength(0)); - Assert.AreEqual(6, test2DArray.GetLength(1)); - Assert.AreEqual(testJagged2d[0][4], test2DArray[0, 4]); - Assert.AreEqual(testJagged2d[2][2], test2DArray[2, 2]); - float[][] badJaggedArray1 = new float[][] - { - new float[] {1, 2, 3, 4, 5, 6, 22}, - new float[] {7, 8, 9, 10, 11, 12 }, - new float[] {11, 12, 13, 14, 15, 16} - }; - Assert.Throws(() => FCWTAPI.ToTwoDArray(badJaggedArray1)); - float[][] badJaggedArray2 = new float[][] - { - new float[] {1, 2, 3, 4, 5, 6}, - new float[] {7, 8, 9, 10, 11, 12, 22 }, - new float[] {11, 12, 13, 14, 15, 16} - }; - Assert.Throws(() => FCWTAPI.ToTwoDArray(badJaggedArray2)); - float[][] badJaggedArray3 = new float[][] - { - new float[] {1, 2, 3, 4, 5, 6}, - new float[] {7, 8, 9, 10, 11, 12 }, - new float[] {11, 12, 13, 14, 15, 16, 22} - }; - Assert.Throws(() => FCWTAPI.ToTwoDArray(badJaggedArray3)); - } - [Test] - public static void TestCalculatePhase() - { - float[][] testArray = new float[][] - { - new float[] {1F, 1.2F, 1.3F, 1.4F }, - new float[] {1.5F, 1.6F, 1.7F, 1.8F } - }; - - float[][] phaseArray = FCWTAPI.CalculatePhase(testArray, testArray); - - Assert.AreEqual(1.273, phaseArray[0][0], 0.001); - } - [Test] - public static void TestCalculateModulus() - { - float[][] testArray = new float[][] - { - new float[] {1F, 2F, 3F, 4F }, - new float[] {5F, 6F, 7F, 8F } - }; - - float[][] modArray = FCWTAPI.CalculateModulus(testArray, testArray); - Console.WriteLine(string.Join("; ", modArray[0].AsEnumerable())); - Assert.AreEqual(1.41421, modArray[0][0], 0.001); - - } - [Test] public void TestAPIResults() { float[] input = Enumerable.Range(0, 1000).Select(i => (float)Math.Cos(0.5 * Math.PI * (double)i)).ToArray(); diff --git a/TestFCWTAPI/GaussianSmoothingTests.cs b/TestFCWTAPI/GaussianSmoothingTests.cs index 9f22b9a..fb36aa7 100644 --- a/TestFCWTAPI/GaussianSmoothingTests.cs +++ b/TestFCWTAPI/GaussianSmoothingTests.cs @@ -342,84 +342,6 @@ public static void TestSliceEllipticGaussianConvolution() } [Test] - public static void TestEllipticGaussianConvolution() - { - double[,] invalid2DArray = new double[,] - { - {1, 2, 3, 4, 5 }, - {4, 5, 6, 7, 8 }, - {9, 10, 11, 12, 13 }, - }; - Assert.Throws(() => GaussianSmoothing.EllipticGaussianConvolution(invalid2DArray, 1, 2)); - double testDim1Deviation = 1; - double testDim2Deviation = 2; - double[,] test2DArray = new double[51, 51]; - // List of points to add to a test array - var pointArray = new (int, int, double)[] - { - (13, 13, 1), // Generic point - (27, 13, -1), // Sample point with a negative value - (2, 43, 1), // Sample point next to an edge - (50, 50, 1) // Sample point in a corner - }; - double centerPoint = 1 / (2 * Math.PI * testDim1Deviation * testDim2Deviation); - // Generates a 2D array containing all points from pointArray - for (int i = 0; i < 51; i++) - { - for (int j = 0; j < 51; j++) - { - for (int t = 0; t < 4; t++) - if (i == pointArray[t].Item1 && j == pointArray[t].Item2) - { - test2DArray[i, j] = pointArray[t].Item3; - } - } - } - - // Generates a list of coordinates to points adjacent to the points in pointArray off by 1 unit in the higher dimension - var adjacentDim1Array = new (int, int, double)[] - { - (12, 13, 1), - (28, 13, -1), - (3, 43, 1), - (49, 50, 1) - }; - double dim1AdjacentPoint = 1 / (2 * Math.PI * testDim1Deviation * testDim2Deviation) * Math.Exp(-1 / (2 * Math.Pow(testDim1Deviation, 2))); - - // Generates a list of coordinates to points adjacent to the points in pointArray off by 1 unit in the lower dimension - var adjacentDim2Array = new (int, int, double)[] - { - (13, 14, 1), - (27, 12, -1), - (2, 42, 1), - (50, 49, 1) - - }; - double dim2AdjacentPoint = 1 / (2 * Math.PI * testDim1Deviation * testDim2Deviation) * Math.Exp(-1 / (2 * Math.Pow(testDim2Deviation, 2))); - - // Generates a list of coordinates to points diagonal to the points in pointArray - var diagonalArray = new (int, int, double)[] - { - (14, 14, 1), - (26, 14, -1), - (1, 42, 1), - (49, 49, 1) - }; - double diagonalPoint = 1 / (2 * Math.PI * testDim1Deviation * testDim2Deviation) * Math.Exp(-1 * ((1 / (2 * Math.Pow(testDim1Deviation, 2))) + (1 / (2* Math.Pow(testDim2Deviation, 2))))); - double[,] testAsymmetricalBlurArray = GaussianSmoothing.EllipticGaussianConvolution(test2DArray, testDim1Deviation, testDim2Deviation); - for(int p = 0; p < 4; p++) - { - // Checks all the center point values for correctness - Assert.AreEqual(centerPoint * pointArray[p].Item3, testAsymmetricalBlurArray[pointArray[p].Item1, pointArray[p].Item2], 0.001); - // Checks all the adjacent dim1 point values for correctness - Assert.AreEqual(dim1AdjacentPoint * pointArray[p].Item3, testAsymmetricalBlurArray[adjacentDim1Array[p].Item1, adjacentDim1Array[p].Item2], 0.001); - // Checks all the adjacent dim2 point values for correctness - Assert.AreEqual(dim2AdjacentPoint * pointArray[p].Item3, testAsymmetricalBlurArray[adjacentDim2Array[p].Item1, adjacentDim2Array[p].Item2], 0.001); - // Checks all the diagonal point values for correctness - Assert.AreEqual(diagonalPoint * pointArray[p].Item3, testAsymmetricalBlurArray[diagonalArray[p].Item1, diagonalArray[p].Item2], 0.001); - } - } - [Test] public static void TestGaussianSmoothing1D() { double[] invalidArray = { 1, 2, 3, 4, 5 };