diff --git a/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/ColorMap.java b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/ColorMap.java new file mode 100644 index 0000000..2a5ca31 --- /dev/null +++ b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/ColorMap.java @@ -0,0 +1,110 @@ +package org.gcube.contentmanagement.graphtools.plotting.graphs; + +/* + * Copyright 1999-2004 Carnegie Mellon University. + * Portions Copyright 2002-2004 Sun Microsystems, Inc. + * Portions Copyright 2002-2004 Mitsubishi Electric Research Laboratories. + * All Rights Reserved. Use is subject to license terms. + * + * See the file "README" for information on usage and + * redistribution of this file, and for a DISCLAIMER OF ALL + * WARRANTIES. + * + */ + +import java.util.Arrays; +import java.awt.Color; + +public class ColorMap +{ + public int size; + public byte r[]; + public byte g[]; + public byte b[]; + public Color table[]; + + public static ColorMap getJet() + { + return getJet(64); + } + + public static ColorMap getJet(int n) + { + byte r[] = new byte[n]; + byte g[] = new byte[n]; + byte b[] = new byte[n]; + + int maxval = 255; + //Arrays.fill(g, 0, 8, (byte)0); + Arrays.fill(g, 0, n/8, (byte)0); + //for(int x = 0; x < 16; x++) + // g[x+8] = (byte)(maxval*x/16); + for(int x = 0; x < n/4; x++) + g[x+n/8] = (byte)(maxval*x*4/n); + //Arrays.fill(g, 24, 40, (byte)maxval); + Arrays.fill(g, n*3/8, n*5/8, (byte)maxval); + //for(int x = 0; x < 16; x++) + // g[x+40] = (byte)(maxval-(maxval*x/16)); + for(int x = 0; x < n/4; x++) + g[x+n*5/8] = (byte)(maxval-(maxval*x*4/n)); + //Arrays.fill(g, 56, 64, (byte)0); + Arrays.fill(g, n*7/8, n, (byte)0); + + //for(int x = 0; x < g.length; x++) + // b[x] = g[(x+16) % g.length]; + for(int x = 0; x < g.length; x++) + b[x] = g[(x+n/4) % g.length]; + //Arrays.fill(b, 56, 64, (byte)0); + Arrays.fill(b, n*7/8, n, (byte)0); + //Arrays.fill(g, 0, 8, (byte)0); + Arrays.fill(g, 0, n/8, (byte)0); + //for(int x = 8; x < g.length; x++) + // r[x] = g[(x+48) % g.length]; + for(int x = n/8; x < g.length; x++) + r[x] = g[(x+n*6/8) % g.length]; + + ColorMap cm = new ColorMap(); + cm.size = n; + cm.r = r; + cm.g = g; + cm.b = b; + cm.table = new Color[n]; + for(int x = 0; x < n; x++) + //cm.table[x] = new Color((int)r[x]+maxval/2+1, + //(int)g[x]+maxval/2+1, (int)b[x]+maxval/2+1); + cm.table[x] = new Color(cm.getColor(x)); + return cm; + } + + + public int getColor(int idx) + { + int pixel = ((r[idx] << 16) & 0xff0000) + | ((g[idx] << 8) & 0xff00) + | (b[idx] & 0xff); + + return pixel; + } + + public String toString() + { + StringBuffer s = new StringBuffer(500); + for(int x = 0; x < size; x++) + { + s.append(x+": {"+r[x]+",\t"+g[x]+",\t"+b[x]+"}\t"); + if(x%3 == 2) + s.append("\n"); + } + + return s.toString(); + } + + public static void main(String[] args) + { + ColorMap jet = getJet(); + ColorMap jet128 = getJet(128); + + + System.out.println("Jet:\n"+jet+"\n\nJet128:\n"+jet128); + } +} diff --git a/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/SpectrumPlot2.java b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/SpectrumPlot2.java new file mode 100644 index 0000000..cb8bd84 --- /dev/null +++ b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/SpectrumPlot2.java @@ -0,0 +1,191 @@ +package org.gcube.contentmanagement.graphtools.plotting.graphs; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageFilter; +import java.awt.image.ImageObserver; +import java.awt.image.ReplicateScaleFilter; + +import javax.swing.JPanel; + +public class SpectrumPlot2 extends JPanel { + + private BufferedImage spectrogram = null; + + private Image scaledSpectrogram = null; + + private float zoom = 1.0f; + private float vzoom = 1.0f; + + private double offsetFactor; + + private double[][] data; + + public int width; + public int height; + + private ColorMap cmap = ColorMap.getJet(64); + // private static float minZoom = .1f; + + private double minVal; + private double maxVal; + + public SpectrumPlot2(double[][] dat) { + data = dat; + width = dat.length; + height = dat[0].length; + // audio.addChangeListener(new ChangeListener() { + // public void stateChanged(ChangeEvent event) { + // computeSpectrogram(); + // } + // }); + computeSpectrogram(); + } + + private void computeSpectrogram() { + try { + // prepare the data: + maxVal = 0; + minVal = Integer.MAX_VALUE; + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + if (data[x][y] > maxVal) + maxVal = data[x][y]; + if (data[x][y] < minVal) + minVal = data[x][y]; + } + } + double minIntensity = Math.abs(minVal); + double maxIntensity = maxVal + minIntensity; + + int maxYIndex = height - 1; + Dimension d = new Dimension(width, height); + + setMinimumSize(d); + setMaximumSize(d); + setPreferredSize(d); + + /* + * Create the image for displaying the data. + */ + spectrogram = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + /* + * Set scaleFactor so that the maximum value, after removing the + * offset, will be 0xff. + */ + double scaleFactor = ((0x3f + offsetFactor) / maxIntensity); + + for (int i = 0; i < width; i++) { + for (int j = maxYIndex; j >= 0; j--) { + + /* + * Adjust the grey value to make a value of 0 to mean white + * and a value of 0xff to mean black. + */ + int grey = (int) ((data[i][j] + minIntensity) * scaleFactor - offsetFactor); + // System.out.println(grey); + + // use grey as an index into the colormap; + spectrogram.setRGB(i, maxYIndex - j, cmap.getColor(grey)); + } + } + + ImageFilter scaleFilter = new ReplicateScaleFilter((int) (zoom * width), (int) (vzoom * height)); + scaledSpectrogram = createImage(new FilteredImageSource(spectrogram.getSource(), scaleFilter)); + Dimension sz = getSize(); + repaint(0, 0, 0, sz.width - 1, sz.height - 1); + +// ImageIO.write(ImageTools.toBufferedImage(scaledSpectrogram), "png", new File("saved.png")); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setOffsetFactor(double offsetFactor) { + this.offsetFactor = offsetFactor; + computeSpectrogram(); + } + + public void vzoomSet(float vzoom) { + this.vzoom = vzoom; + zoom(); + } + + public void hzoomSet(float zoom) { + zoomSet(zoom); + } + + protected void zoomSet(float zoom) { + this.zoom = zoom; + zoom(); + } + + public void zoom() { + if (spectrogram != null) { + int width = spectrogram.getWidth(); + int height = spectrogram.getHeight(); + + // do the zooming + width = (int) (zoom * width); + height = (int) (vzoom * height); + + ImageFilter scaleFilter = new ReplicateScaleFilter(width, height); + scaledSpectrogram = createImage(new FilteredImageSource(spectrogram.getSource(), scaleFilter)); + + // so ScrollPane gets notified of the new size: + setPreferredSize(new Dimension(width, height)); + revalidate(); + + repaint(); + } + } + + public float getVZoom() { + return vzoom; + } + + public float getHZoom() { + return zoom; + } + + public SpectrumPlot2 getColorBar() { + int barWidth = 20; + + double[][] cb = new double[barWidth][cmap.size]; + + for (int x = 0; x < cb.length; x++) + for (int y = 0; y < cb[x].length; y++) + cb[x][y] = y; + + return new SpectrumPlot2(cb); + } + + public double getData(int x, int y) { + return data[x][y]; + } + + public int getDataWidth() { + return width; + } + + public int getDataHeight() { + return height; + } + + public void paint(Graphics g) { + Dimension sz = getSize(); + + g.setColor(Color.WHITE); + g.fillRect(0, 0, sz.width - 1, sz.height - 1); + + if (spectrogram != null) { + g.drawImage(scaledSpectrogram, 0, 0, (ImageObserver) null); + } + } +} diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/PeriodicityDetector.java b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/PeriodicityDetector.java index c5b4956..d0b61a3 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/PeriodicityDetector.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/PeriodicityDetector.java @@ -24,6 +24,11 @@ public class PeriodicityDetector { static float defaultSNratio = 0; static float defaultFreqError = 1f; + public int currentSamplingRate; + public int currentWindowShiftSamples; + public int currentWindowAnalysisSamples; + public double[][] currentspectrum; + public double meanF=0; public double lowermeanF=0; public double uppermeanF=0; @@ -38,6 +43,8 @@ public class PeriodicityDetector { public double endPeriodSampleIndex=0; public double periodicityStrength=0; + public double minFrequency; + public double maxFrequency; public String getPeriodicityStregthInterpretation(){ if (periodicityStrength>0.6) @@ -91,6 +98,7 @@ public class PeriodicityDetector { return detectFrequency(signal, false); } + public double detectFrequency(double[] signal, int samplingRate, float minPossibleFreq, float maxPossibleFreq, float wantedFreqError, boolean display) throws Exception { // estimate the best samples based on the error we want @@ -119,12 +127,18 @@ public class PeriodicityDetector { if (minPossibleFreq==0) minPossibleFreq = 0.1f; + minFrequency=minPossibleFreq; + maxFrequency=maxPossibleFreq; // display the signal if (display) SignalProcessing.displaySignalWithGenericTime(signal, 0, 1, "signal"); + this.currentSamplingRate = samplingRate; + this.currentWindowShiftSamples = windowShiftSamples; + this.currentWindowAnalysisSamples = windowAnalysisSamples; + // trace spectrum - double[][] spectrum = SignalConverter.spectrogram("spectogram", signal, samplingRate, windowShiftSamples, windowAnalysisSamples, false); + double[][] spectrum = SignalConverter.spectrogram("spectrogram", signal, samplingRate, windowShiftSamples, windowAnalysisSamples, false); if (display) SignalConverter.displaySpectrogram(spectrum, signal, "complete spectrogram", samplingRate, windowShiftSamples, windowAnalysisSamples); // apply the bandpass filter @@ -136,7 +150,7 @@ public class PeriodicityDetector { SignalConverter signalMaximumAnalyzer = new SignalConverter(); double[] maxfrequencies = signalMaximumAnalyzer.takeMaxFrequenciesInSpectrogram(spectrum, samplingRate, windowAnalysisSamples, minPossibleFreq); double[] powers = signalMaximumAnalyzer.averagepower; - + currentspectrum=spectrum; // display the maximum freqs AnalysisLogger.getLogger().debug("Number of frequency peaks " + maxfrequencies.length); // take the longest stable sequence of frequencies diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalConverter.java b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalConverter.java index a245b82..a0598b2 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalConverter.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalConverter.java @@ -83,10 +83,10 @@ public class SignalConverter { return cepc; } - public static BufferedImage createImage(JPanel panel) { + public static BufferedImage createImage(JPanel panel, int w, int h) { - int w = panel.getWidth(); - int h = panel.getHeight(); +// int w = panel.getWidth(); +// int h = panel.getHeight(); BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); panel.paint(g); @@ -277,6 +277,7 @@ public class SignalConverter { * File(name+".png")); */ // Thread.sleep(2000); +// createImage(spec); } return spectrum; } diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalProcessing.java b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalProcessing.java index 7bd33e0..3876f42 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalProcessing.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/signals/SignalProcessing.java @@ -1,5 +1,7 @@ package org.gcube.dataanalysis.ecoengine.signals; +import java.awt.Image; +import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -8,12 +10,18 @@ import java.util.Arrays; import java.util.Date; import java.util.List; +import marytts.signalproc.display.SpectrogramCustom; +import marytts.signalproc.window.Window; + import org.gcube.contentmanagement.graphtools.data.BigSamplesTable; +import org.gcube.contentmanagement.graphtools.data.conversions.ImageTools; import org.gcube.contentmanagement.graphtools.plotting.graphs.NumericSeriesGraph; +import org.gcube.contentmanagement.graphtools.plotting.graphs.SpectrumPlot2; import org.gcube.contentmanagement.graphtools.plotting.graphs.TimeSeriesGraph; import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger; import org.gcube.contentmanagement.lexicalmatcher.utils.MathFunctions; import org.gcube.dataanalysis.ecoengine.configuration.AlgorithmConfiguration; +import org.jfree.chart.JFreeChart; import org.jfree.data.time.FixedMillisecond; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.XYSeriesCollection; @@ -110,6 +118,58 @@ public class SignalProcessing { nsg.render(collection); } + public static Image renderSignalWithGenericTime(double[] signal, float t0, float timeshift, String name) { + org.jfree.data.xy.XYSeries xyseries = new org.jfree.data.xy.XYSeries(name); + float time = t0; + for (int i = 0; i < signal.length; i++) { + xyseries.add(time, signal[i]); + time = time + timeshift; + } + XYSeriesCollection collection = new XYSeriesCollection(xyseries); + JFreeChart chart = NumericSeriesGraph.createStaticChart(collection); + Image image = ImageTools.toImage(chart.createBufferedImage(680, 420)); + return image; + } + + public static Image renderSignalWithGenericTime(double[] signal, double [] timeline, String name) { + org.jfree.data.xy.XYSeries xyseries = new org.jfree.data.xy.XYSeries(name); + + for (int i = 0; i < signal.length; i++) { + xyseries.add(timeline[i], signal[i]); + } + + XYSeriesCollection collection = new XYSeriesCollection(xyseries); + JFreeChart chart = NumericSeriesGraph.createStaticChart(collection); + Image image = ImageTools.toImage(chart.createBufferedImage(680, 420)); + return image; + } + + public static Image renderSignalSpectrogram(double[] signal, double [] timeline, int samplingRate, int frameslength, int windowshift) { + SpectrogramCustom spec = new SpectrogramCustom(signal, samplingRate, Window.get(Window.HAMMING, frameslength), windowshift, frameslength, 640, 480); + double[][] spectrum = spec.spectra.toArray(new double[spec.spectra.size()][]); + spec.setZoomX(640d/(double)spectrum.length); + BufferedImage image = SignalConverter.createImage(spec,640,480); + return ImageTools.toImage(image); + } + + public static Image renderSignalSpectrogram2(double[][] spectrogram) { + SpectrumPlot2 spectrumPlot = new SpectrumPlot2(spectrogram); + AnalysisLogger.getLogger().debug("Spectrum W:"+spectrumPlot.width); + AnalysisLogger.getLogger().debug("Spectrum H:"+spectrumPlot.height); +// spectrumPlot.hzoomSet(2f); + spectrumPlot.hzoomSet(640f/(float)spectrumPlot.width); + spectrumPlot.vzoomSet(480f/(float)spectrumPlot.height); + /* + ApplicationFrame app = new ApplicationFrame("Spectrogram "); + app.setContentPane(spectrumPlot); + app.pack(); + app.setVisible(true); + */ + BufferedImage image = SignalConverter.createImage(spectrumPlot,640,480); + return ImageTools.toImage(image); + +} + public static void displaySignalWithTime(double[] signal, Date[] dates, String name, String format) { org.jfree.data.time.TimeSeries series = new org.jfree.data.time.TimeSeries(name); for (int i = 0; i < signal.length; i++)