/* AbstractWignerMapProvider.java created 2008-03-11 * */ package org.signalml.domain.book; import org.signalml.exception.SanityCheckException; import pl.edu.fuw.MP.WignerMap.WignerMap; /** AbstractWignerMapProvider * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. * (based on code sent by Dobieslaw Ircha) */ public abstract class AbstractWignerMapProvider { protected WignerMapScaleType scaleType = WignerMapScaleType.NORMAL; protected int width; protected int height; protected double minFrequency; protected double maxFrequency; protected double minPosition; protected double maxPosition; protected double[][] map; protected double[][] normalMap; protected boolean mapDirty = true; protected boolean normalMapDirty = true; protected float samplingFrequency; public AbstractWignerMapProvider(float samplingFrequency) { this.samplingFrequency = samplingFrequency; } public WignerMapScaleType getScaleType() { return scaleType; } public void setScaleType(WignerMapScaleType scaleType) { if (this.scaleType != scaleType) { this.scaleType = scaleType; mapDirty = true; } } public int getWidth() { return width; } public void setWidth(int width) { if (this.width != width) { this.width = width; map = null; normalMap = null; } } public int getHeight() { return height; } public void setHeight(int height) { if (this.height != height) { this.height = height; map = null; normalMap = null; } } public void setSize(int width, int height) { if (this.width != width || this.height != height) { this.width = width; this.height = height; map = null; normalMap = null; } } public double getMinFrequency() { return minFrequency; } public void setMinFrequency(double minFrequency) { if (this.minFrequency != minFrequency) { this.minFrequency = minFrequency; mapDirty = true; normalMapDirty = true; } } public double getMaxFrequency() { return maxFrequency; } public void setMaxFrequency(double maxFrequency) { if (this.maxFrequency != maxFrequency) { this.maxFrequency = maxFrequency; mapDirty = true; normalMapDirty = true; } } public double getMinPosition() { return minPosition; } public void setMinPosition(double minPosition) { if (this.minPosition != minPosition) { this.minPosition = minPosition; mapDirty = true; normalMapDirty = true; } } public double getMaxPosition() { return maxPosition; } public void setMaxPosition(double maxPosition) { if (this.maxPosition != maxPosition) { this.maxPosition = maxPosition; mapDirty = true; normalMapDirty = true; } } public void setRange(double minFrequency, double maxFrequency, double minPosition, double maxPosition) { if ( this.minFrequency != minFrequency || this.maxFrequency != maxFrequency || this.minPosition != minPosition || this.maxPosition != maxPosition ) { this.minFrequency = minFrequency; this.maxFrequency = maxFrequency; this.minPosition = minPosition; this.maxPosition = maxPosition; mapDirty = true; normalMapDirty = true; } } public void setRangeAndSize(double minFrequency, double maxFrequency, double minPosition, double maxPosition, int width, int height) { if (this.width != width || this.height != height) { map = null; normalMap = null; } else if ( this.minFrequency != minFrequency || this.maxFrequency != maxFrequency || this.minPosition != minPosition || this.maxPosition != maxPosition ) { mapDirty = true; normalMapDirty = true; } else { // all equal return; } this.minFrequency = minFrequency; this.maxFrequency = maxFrequency; this.minPosition = minPosition; this.maxPosition = maxPosition; this.width = width; this.height = height; } public double[][] getMap() { if (scaleType == WignerMapScaleType.NORMAL) { return getNormalMap(); } if (map == null) { map = new double[width][height]; mapDirty = true; } if (mapDirty) { map = scaleMap(map, getNormalMap(), width, height, scaleType); } return map; } public abstract double[][] getNormalMap(); public void calculateNormalMap(StandardBookSegment segment, double[][] map) { if (segment == null || segment.getAtomCount() == 0) { for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { map[x][y] = 0; } } return; } // XXX test Wigner map calculation below, remove when not needed /* StandardBookAtom atom = segment.getAtomAt(0); double stretchX = (maxPosition-minPosition) / segment.getSegmentTimeLength(); double stretchY = (maxFrequency-minFrequency) / (samplingFrequency/2); double pixelPerSecond = (width / segment.getSegmentTimeLength()) / stretchX; double pixelPerHz = (height / (samplingFrequency/2) ) / stretchY; int cenX = (int) Math.round( (atom.getTimePosition()-minPosition)*pixelPerSecond ); int cenY = (int) Math.round( (atom.getHzFrequency()-minFrequency)*pixelPerHz ); for( int x=0; x<width; x++ ) { for( int y=0; y<height; y++ ) { map[x][y] = (1.0 + Math.sin( (2*Math.PI/300) * Math.sqrt(Util.sqr(stretchX*((double)(x-cenX))) + Util.sqr(stretchY*((double)(y-cenY))) ) ) ) / 2; } } */ int naturalMinFrequency = (int) Math.round((minFrequency / samplingFrequency) * segment.getSegmentLength()); int naturalMaxFrequency = (int) Math.round((maxFrequency / samplingFrequency) * segment.getSegmentLength()); int pointMinPosition = (int) Math.round(minPosition * samplingFrequency); int pointMaxPosition = (int) Math.round(maxPosition * samplingFrequency); WignerMap wignerMap = new WignerMap(width, height, pointMinPosition, pointMaxPosition, naturalMinFrequency, naturalMaxFrequency); wignerMap.setBook(segment); double[][] normMap = wignerMap.getWignerMap(); double scaleFactor = 1.0 / (wignerMap.getMaxVal()-wignerMap.getMinVal()); for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { map[x][y] = normMap[x][y] * scaleFactor; } } } public double[][] scaleMap(double[][] target, double[][] normalMap, int width, int height, WignerMapScaleType scaleType) { if (scaleType == WignerMapScaleType.NORMAL) { // doesn't copy to target in this case!!! return normalMap; } double[][] map; if (target != null) { map = target; } else { map = new double[width][height]; } double min = Double.MAX_VALUE; double max = 0; if (scaleType == WignerMapScaleType.LOG) { for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { map[x][y] = Math.log(1.0+normalMap[x][y]); if (map[x][y] > max) { max = map[x][y]; } if (map[x][y] < min) { min = map[x][y]; } } } } else if (scaleType == WignerMapScaleType.SQRT) { for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { map[x][y] = Math.sqrt(normalMap[x][y]); if (map[x][y] > max) { max = map[x][y]; } if (map[x][y] < min) { min = map[x][y]; } } } } else { throw new SanityCheckException("Unsupported scale type [" + scaleType.name() + "]"); } // normalize map double factor = 1.0 / (max-min); for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { map[x][y] = (map[x][y] - min) * factor; } } return map; } public boolean isDirty() { if (map == null || normalMap == null || mapDirty || normalMapDirty) { return true; } return false; } }