/// <summary> /// Returns a matrix whose columns consist of the bottom row of the WPD tree for each WPD window of length 2^L where L= levelNumber. /// The WPD windows do not overlap. /// </summary> /// <param name="signal"></param> /// <param name="levelNumber"></param> /// <returns></returns> public static double[,] GetWPDSpectralSequence(double[] signal, int levelNumber) { int windowWidth = (int)Math.Pow(2, levelNumber); int halfWindow = windowWidth / 2; int sampleCount = signal.Length / windowWidth; //int minLag, //int maxLag double[,] wpdByTime = new double[halfWindow, sampleCount]; for (int s = 0; s < sampleCount; s++) { int start = s * windowWidth; double[] subArray = DataTools.Subarray(signal, start, windowWidth); //double[] autocor = AutoCorrelation.MyAutoCorrelation(subArray); //autocor = DataTools.filterMovingAverage(autocor, 5); //autocor = DataTools.Subarray(autocor, autocor.Length / 4, windowWidth); //DataTools.writeBarGraph(autocor); // only interested in autocorrelation peaks > half max. An oscillation spreads autocor energy. //double threshold = autocor.Max() / 2; //int[] histo = DataTools.GetHistogramOfDistancesBetweenEveryPairOfPeaks(autocor, threshold); var wpd = new WaveletPacketDecomposition(subArray); double[] energySpectrumWithoutDC = wpd.GetWPDEnergySpectrumWithoutDC(); // there should only be one dominant oscilation in any one freq band at one time. // keep only the maximum value but divide by the total energy in the spectrum. // Energy dispersed through the spectrum is indicative of a single impulse, not an oscilation. int index = DataTools.GetMaxIndex(energySpectrumWithoutDC); double[] spectrum = new double[halfWindow]; spectrum[index] = energySpectrumWithoutDC[index] / energySpectrumWithoutDC.Sum(); MatrixTools.SetColumn(wpdByTime, s, spectrum); } // calculate statistics for values in matrix //string imagePath = @"C:\SensorNetworks\Output\Sonograms\wpdHistogram.png"; //Histogram.DrawDistributionsAndSaveImage(wpdByTime, imagePath); string path = @"C:\SensorNetworks\Output\Sonograms\testwavelet.png"; ImageTools.DrawReversedMatrix(wpdByTime, path); // MatrixTools.writeMatrix(wpdByTime); return(wpdByTime); }
/// <summary> /// /// </summary> /// <param name="signal"></param> /// <param name="fftWindowWidth"></param> /// <param name="wpdLevelNumber"></param> /// <returns></returns> public static double[,] GetFrequencyByOscillationsMatrix(double[] signal, int fftWindowWidth, int wpdLevelNumber) { // produce spectrogram int wpdWindowWidth = (int)Math.Pow(2, wpdLevelNumber); int sampleCount = signal.Length / wpdWindowWidth; double[,] wpdByTime = new double[wpdWindowWidth, sampleCount]; double[,] freqByOscillationsMatrix = new double[fftWindowWidth, wpdWindowWidth]; // do a WPD over each frequency bin // accumulate the WPD spectra into a frequency bin by oscillations per second matrix. //double[,] matrix = Wavelets.GetWPDSpectralSequence(signal, wpdLevelNumber); double[,] matrix = WaveletPacketDecomposition.GetWPDEnergySequence(signal, wpdLevelNumber); double[] V = MatrixTools.GetRowAverages(matrix); return(freqByOscillationsMatrix); }
/// <summary> /// Returns a matrix whose columns consist of the energy vector derived from the WPD tree for each WPD window of length 2^L where L= levelNumber. /// The WPD windows do not overlap. /// </summary> /// <param name="signal"></param> /// <param name="levelNumber"></param> /// <returns></returns> public static double[,] GetWPDEnergySequence(double[] signal, int levelNumber) { int windowWidth = (int)Math.Pow(2, levelNumber); int sampleCount = signal.Length / windowWidth; int lengthOfEnergyVector = (int)Math.Pow(2, levelNumber + 1) - 1; double[,] wpdByTime = new double[lengthOfEnergyVector, sampleCount]; for (int s = 0; s < sampleCount; s++) { int start = s * windowWidth; double[] subArray = DataTools.Subarray(signal, start, windowWidth); var wpd = new WaveletPacketDecomposition(subArray); double[] energyVector = wpd.GetWPDEnergyVector(); // reverse the energy vector so that low resolution coefficients are at the bottom. energyVector = DataTools.reverseArray(energyVector); MatrixTools.SetColumn(wpdByTime, s, energyVector); } return(wpdByTime); }
/// <summary> /// These examples are used to do Wavelet Packet Decomposition on test signals to which noise can be added. /// </summary> public static void ExampleOfWavelets_1() { //this signal contains one block impulse in centre //double[] signal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, // 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //double[] signal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; double[] signal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, }; //double[] signal = {1,0,0,0,0,0,0,0}; //double[] signal = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; //double[] signal = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; //this signal contains four cycles //double[] signal = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 }; //this signal contains eight cycles //double[] signal = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, // 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 }; //this signal contains 16 cycles //double[] signal = { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, // 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 }; //this signal contains four step cycles //double[] signal = { 1, 1, 0.5, 0, -0.5, -1.0, -1.0, -0.5, 0, 0.5, 1.0, 1.0, 0.5, 0.0, -0.5, -1, -1, -0.5, 0, 0.5, 1.0, 1.0, 0.5, 0.0, -0.5, -1.0, -1.0, -0.5, 0, 0.5, 1.0, 1.0, // 1, 1, 0.5, 0, -0.5, -1.0, -1.0, -0.5, 0, 0.5, 1.0, 1.0, 0.5, 0.0, -0.5, -1, -1, -0.5, 0, 0.5, 1.0, 1.0, 0.5, 0.0, -0.5, -1.0, -1.0, -0.5, 0, 0.5, 1.0, 1.0 }; //this 128 sample signal contains 32 cycles //double[] signal = { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, // 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, // 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, // 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 }; //this 128 sample signal contains 64 cycles //The output bin vector tree and image will show strong energy at level level 8, bin zero and bin 64. //i.e. bin 64 implies 64 cycles within the length of the WPD window of 128. //double[] signal = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, // 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, // 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, // 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; // add noise to signal //RandomNumber rn = new RandomNumber(); //double[] rv = RandomNumber.GetRandomVector(128, rn); // note that even when noise is twice amplitude of signal the first column of UMatrix is excellent reproduction of // first column when signal has no added noise. // relative noise amplitude //double noiseAmplitude = 2.0; //DataTools.Normalise(rv, 0.0, noiseAmplitude); //// signal plus noise //signal = DataTools.AddVectors(signal, rv); //// normalising seems to make little difference to the result //signal = DataTools.NormaliseMatrixValues(signal); //int levelNumber = 7; WaveletPacketDecomposition wpd = new WaveletPacketDecomposition(signal); double[,] M = wpd.GetWPDSignalTree(); string path = @"C:\SensorNetworks\Output\Test\testwavelet.png"; ImageTools.DrawReversedMatrix(M, path); //MatrixTools.writeMatrix(M); MatrixTools.WriteLocationOfMaximumValues(M); double[] energySpectrumWithoutDC = wpd.GetWPDEnergySpectrumWithoutDC(); }