Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions FCWTAPI/CWTOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
}
}
214 changes: 1 addition & 213 deletions FCWTAPI/FCWTAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}
/// <summary>
/// Moves the 1D array to a 2D jagged array.
/// </summary>
/// <param name="array1D"></param>
/// <param name="size"></param>
/// <param name="noctave"></param>
/// <param name="nvoice"></param>
/// <returns></returns>
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)

/// <summary>
/// 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
/// </summary>
/// <param name="jaggedTwoD">2D jagged array to be converted</param>
/// <returns></returns>
/// <exception cref="IndexOutOfRangeException"></exception>
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;
}

/// <summary>
/// Used to split the imaginary and the real arrays when using a complex wavelet, i.e. the morlet.
/// </summary>
/// <param name="combinedArray"></param>
/// <param name="realArray"></param>
/// <param name="imaginaryArray"></param>
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++;
}
}
/// <summary>
/// Calculates the phase of the continuous wavelet transform output using a morlet wavelet.
/// </summary>
/// <param name="realArray"></param><summary>The real part of the complex morlet CWT.</summary>
/// <param name="imagArray"></param><summary>The imaginary part of the complex morlet CWT. </summary>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
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;
}
/// <summary>
/// Calculates the modulus of the complex morlet continuous wavelet transform.
/// </summary>
/// <param name="realArray"></param>
/// <param name="imagArray"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
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;
}


}

}
}
27 changes: 0 additions & 27 deletions FCWTAPI/GaussianSmoothing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
/// <summary>
/// Performs 2D Gaussian smoothing using an elliptic Gaussian kernel
/// </summary>
Expand Down
77 changes: 0 additions & 77 deletions TestFCWTAPI/FCWTAPITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<IndexOutOfRangeException>(() => 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<IndexOutOfRangeException>(() => 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<IndexOutOfRangeException>(() => 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();
Expand Down
Loading