Issue #2492 Got mosaicing to happen in mosaic image units, satellite provides data units for images

Change-Id: I5a244397aa6172e406df1d0f4619dd53373584e0

Former-commit-id: 8a7d3ceab1 [formerly 927801985a] [formerly 8a7d3ceab1 [formerly 927801985a] [formerly 3696896b49 [formerly 029c03379ffa8317fa0afe8b2f69cbe1ac3c3fd1]]]
Former-commit-id: 3696896b49
Former-commit-id: ca5e771451 [formerly 70ca78c7b5]
Former-commit-id: a3f5fcabf6
This commit is contained in:
Ben Steffensmeier 2013-11-15 17:51:05 -06:00
parent 67b724a541
commit d307af23eb
25 changed files with 768 additions and 649 deletions

View file

@ -77,9 +77,11 @@ import com.vividsolutions.jts.geom.Coordinate;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jul 18, 2011 2190 mschenke Initial creation * Jul 18, 2011 2190 mschenke Initial creation
* Oct 2, 2013 2333 mschenke Converted to use IGridGeometryProvider * Oct 2, 2013 2333 mschenke Converted to use IGridGeometryProvider
* Nov 20, 2013 2492 bsteffen Refactor deprecated references to
* ColorMapParameters.getDataUnit
* *
* </pre> * </pre>
* *
@ -389,8 +391,8 @@ public class CloudHeightResource extends
if (rsc != null && rsc.hasCapability(ColorMapCapability.class)) { if (rsc != null && rsc.hasCapability(ColorMapCapability.class)) {
ColorMapParameters params = rsc.getCapability( ColorMapParameters params = rsc.getCapability(
ColorMapCapability.class).getColorMapParameters(); ColorMapCapability.class).getColorMapParameters();
if (params != null && params.getDataUnit() != null if (params != null && params.getColorMapUnit() != null
&& TEMP_UNIT.isCompatible(params.getDataUnit())) { && TEMP_UNIT.isCompatible(params.getColorMapUnit())) {
return true; return true;
} }
} }

View file

@ -39,6 +39,7 @@ import com.raytheon.uf.viz.core.maps.scales.MapScales.MapScale;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale; import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale;
import com.raytheon.uf.viz.core.procedures.Bundle; import com.raytheon.uf.viz.core.procedures.Bundle;
import com.raytheon.uf.viz.core.rsc.ResourceList; import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
/** /**
* MapRenderableDisplay associated with a {@link MapScale} * MapRenderableDisplay associated with a {@link MapScale}
@ -48,9 +49,10 @@ import com.raytheon.uf.viz.core.rsc.ResourceList;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Mar 22, 2013 mschenke Initial creation * Mar 22, 2013 mschenke Initial creation
* Oct 10, 2013 2104 mschenke Switched to use MapScalesManager * Oct 10, 2013 2104 mschenke Switched to use MapScalesManager
* Nov 20, 2013 2492 bsteffen Recycle resources in clear.
* *
* </pre> * </pre>
* *
@ -133,9 +135,13 @@ public class MapScaleRenderableDisplay extends PlainMapRenderableDisplay
// non-map/system layers and reset display // non-map/system layers and reset display
ResourceList list = descriptor.getResourceList(); ResourceList list = descriptor.getResourceList();
for (ResourcePair rp : list) { for (ResourcePair rp : list) {
if (rp.getProperties().isMapLayer() == false ResourceProperties props = rp.getProperties();
&& rp.getProperties().isSystemResource() == false) { if (props.isMapLayer() == false
&& props.isSystemResource() == false) {
list.remove(rp); list.remove(rp);
} else {
props.setVisible(true);
rp.getResource().recycle();
} }
} }

View file

@ -28,7 +28,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import org.geotools.coverage.grid.GridEnvelope2D; import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
@ -72,10 +71,12 @@ import com.vividsolutions.jts.geom.Coordinate;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Jun 19, 2013 2122 mschenke Initial creation. * Jun 19, 2013 2122 mschenke Initial creation.
* Oct 16, 2013 2333 mschenke Added method for auto-unit conversion * Oct 16, 2013 2333 mschenke Added method for auto-unit conversion
* interrogating * interrogating
* Nov 20, 2013 2492 bsteffen Move unit converting interrogate into
* TileSetRenderable.
* *
* </pre> * </pre>
* *
@ -369,61 +370,12 @@ public class RecordTileSetRenderable extends TileSetRenderable {
return interrogate(coordinate, parameters.getNoDataValue()); return interrogate(coordinate, parameters.getNoDataValue());
} }
/** @Override
* Returns the raw image value from tile image that contains the lat/lon public double interrogate(Coordinate coordinate, Unit<?> resultUnit)
* coordinate in units of desiredUnit
*
* @param coordinate
* in lat/lon space
* @param desiredUnit
* unit to convert data value to if not nanValue
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, Unit<?> desiredUnit)
throws VizException { throws VizException {
ColorMapParameters parameters = colormapping.getColorMapParameters(); ColorMapParameters parameters = colormapping.getColorMapParameters();
return interrogate(coordinate, parameters.getNoDataValue(), desiredUnit); return super.interrogate(coordinate, resultUnit,
} parameters.getNoDataValue());
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate in units of desiredUnit
*
* @param coordinate
* in lat/lon space
* @param nanValue
* if interrogated value is equal to nanValue, {@link Double#NaN}
* will be returned
* @param desiredUnit
* unit to convert data value to if not nanValue
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, double nanValue,
Unit<?> desiredUnit) throws VizException {
double dataValue = super.interrogate(coordinate, nanValue);
if (Double.isNaN(dataValue) == false) {
ColorMapParameters params = colormapping.getColorMapParameters();
Unit<?> dataUnit = params.getDataUnit();
if (dataUnit != null && desiredUnit != null
&& dataUnit != desiredUnit) {
if (dataUnit.isCompatible(desiredUnit)) {
dataValue = dataUnit.getConverterTo(desiredUnit).convert(
dataValue);
} else {
throw new IllegalArgumentException(
"Unable to interrogate tile set. "
+ String.format(
"Desired unit (%s) is not compatible with data unit (%s).",
UnitFormat.getUCUMInstance()
.format(desiredUnit),
UnitFormat.getUCUMInstance()
.format(dataUnit)));
}
}
}
return dataValue;
} }
/** /**

View file

@ -27,6 +27,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import org.geotools.coverage.grid.GeneralGridGeometry; import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.referencing.crs.DefaultGeographicCRS;
@ -67,6 +70,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made * Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made
* canceling jobs safer * canceling jobs safer
* Oct 16, 2013 2333 mschenke Added auto NaN checking for interrogation * Oct 16, 2013 2333 mschenke Added auto NaN checking for interrogation
* Nov 14, 2013 2492 mschenke Added more interrogate methods that take units
* *
* </pre> * </pre>
* *
@ -475,12 +479,33 @@ public class TileSetRenderable implements IRenderable {
* @throws VizException * @throws VizException
*/ */
public double interrogate(Coordinate coordinate) throws VizException { public double interrogate(Coordinate coordinate) throws VizException {
return interrogate(coordinate, Double.NaN); return interrogate(coordinate, null);
} }
/** /**
* Returns the raw image value from tile image that contains the lat/lon * Returns the raw image value from tile image that contains the lat/lon
* coordinate. Any values matching nanValue will return {@link Double#NaN} * coordinate
*
* @param coordinate
* in lat/lon space
* @param resultUnit
* unit result from interrogate will be returned is. If unit is
* not compatible with data unit, {@link Double#NaN} will be
* returned. Null indicates data will not be converted
* @param nanValue
* if interrogated value is equal to nanValue, {@link Double#NaN}
* will be returned
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, Unit<?> resultUnit)
throws VizException {
return interrogate(coordinate, resultUnit, Double.NaN);
}
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate
* *
* @param coordinate * @param coordinate
* in lat/lon space * in lat/lon space
@ -492,6 +517,27 @@ public class TileSetRenderable implements IRenderable {
*/ */
public double interrogate(Coordinate coordinate, double nanValue) public double interrogate(Coordinate coordinate, double nanValue)
throws VizException { throws VizException {
return interrogate(coordinate, null, nanValue);
}
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate. Any values matching nanValue will return {@link Double#NaN}
*
* @param coordinate
* in lat/lon space
* @param resultUnit
* unit result from interrogate will be returned is. If unit is
* not compatible with data unit, {@link Double#NaN} will be
* returned. Null indicates data will not be converted
* @param nanValue
* if interrogated value is equal to nanValue, {@link Double#NaN}
* will be returned
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, Unit<?> resultUnit,
double nanValue) throws VizException {
double dataValue = Double.NaN; double dataValue = Double.NaN;
try { try {
double[] local = new double[2]; double[] local = new double[2];
@ -515,8 +561,27 @@ public class TileSetRenderable implements IRenderable {
% tileSize); % tileSize);
if (dataValue == nanValue) { if (dataValue == nanValue) {
dataValue = Double.NaN; dataValue = Double.NaN;
} else {
Unit<?> dataUnit = cmapImage.getDataUnit();
if (resultUnit != null && dataUnit != null
&& dataUnit.equals(resultUnit) == false) {
if (resultUnit.isCompatible(dataUnit)) {
dataValue = dataUnit.getConverterTo(
resultUnit).convert(dataValue);
} else {
throw new IllegalArgumentException(
"Unable to interrogate tile set. "
+ String.format(
"Desired unit (%s) is not compatible with data unit (%s).",
UnitFormat
.getUCUMInstance()
.format(resultUnit),
UnitFormat
.getUCUMInstance()
.format(dataUnit)));
}
}
} }
} }
} }
} }

View file

@ -49,7 +49,7 @@ vec4 applyColorBand(int colorband) {
vec2((xy.x / width), (xy.y / height))); vec2((xy.x / width), (xy.y / height)));
// Lookup raw data value // Lookup raw data value
float dataValue = getDataValue(rawData, gl_TexCoord[0].st); float dataValue = textureToDataValue(rawData, gl_TexCoord[0].st);
float r = curVal.r; float r = curVal.r;
float g = curVal.g; float g = curVal.g;

View file

@ -232,8 +232,7 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
parameters.put(colorMapParameters, null); parameters.put(colorMapParameters, null);
GLSLStructFactory.createDataTexture(program, "rawData", 0, GLSLStructFactory.createDataTexture(program, "rawData", 0,
cmapImage.getDataFormat(), cmapImage);
colorMapParameters.getNoDataValue());
int numMappingValues = 0; int numMappingValues = 0;
GLDataMapping mapping = cmapImage.getDataMapping(); GLDataMapping mapping = cmapImage.getDataMapping();

View file

@ -7,7 +7,7 @@ uniform ColorMapping colorMapping;
uniform ColorModifiers modifiers; uniform ColorModifiers modifiers;
void main(void) { void main(void) {
float dataValue = getDataValue(rawData, gl_TexCoord[0].st); float dataValue = textureToDataValue(rawData, gl_TexCoord[0].st);
// No data check/special NaN check // No data check/special NaN check
if (dataValue == rawData.noDataValue || dataValue != dataValue) { if (dataValue == rawData.noDataValue || dataValue != dataValue) {

View file

@ -14,6 +14,8 @@ struct DataTexture {
int isScaled; int isScaled;
float scaleMin; float scaleMin;
float scaleMax; float scaleMax;
float width;
float height;
}; };
/** /**
@ -51,7 +53,7 @@ struct ColorMapping {
/** /**
* Returns the data value for the DataTexture at location. * Returns the data value for the DataTexture at location.
*/ */
float getDataValue(DataTexture texture, vec2 location) { float textureToDataValue(DataTexture texture, vec2 location) {
vec4 textureValue = texture2D(texture.rawTex, location); vec4 textureValue = texture2D(texture.rawTex, location);
float dataValue = textureValue.r; float dataValue = textureValue.r;
@ -63,6 +65,18 @@ float getDataValue(DataTexture texture, vec2 location) {
return dataValue; return dataValue;
} }
/**
* Returns the data value for the DataTexture at location.
*/
float dataToTextureValue(DataTexture texture, float dataValue) {
float textureValue = dataValue;
if (texture.isScaled == 1) {
textureValue = (dataValue - texture.scaleMin)
/ (texture.scaleMax - texture.scaleMin);
}
return textureValue;
}
/** /**
* Looks up a value in a mapping texture given an index [0-numMappingValues). * Looks up a value in a mapping texture given an index [0-numMappingValues).
*/ */
@ -103,8 +117,8 @@ float dataToColorMapValue(float dataValue, DataMapping mapping) {
int nextIndex = lowIndex + ((highIndex - lowIndex) / 2); int nextIndex = lowIndex + ((highIndex - lowIndex) / 2);
if (nextIndex > lowIndex && nextIndex < highIndex) { if (nextIndex > lowIndex && nextIndex < highIndex) {
// Look up next value and determine if it is a high or low // Look up next value and determine if it is a high or low
float nextValue = lookupMappingValue(mapping.dataMappingValues, nextIndex, float nextValue = lookupMappingValue(mapping.dataMappingValues,
numMappingValues); nextIndex, numMappingValues);
if (nextValue < dataValue) { if (nextValue < dataValue) {
if (reversed == 0) { if (reversed == 0) {
lowIndex = nextIndex; lowIndex = nextIndex;
@ -132,10 +146,10 @@ float dataToColorMapValue(float dataValue, DataMapping mapping) {
factor = 1.0 - factor; factor = 1.0 - factor;
} }
float lowCmapValue = lookupMappingValue(mapping.colorMappingValues, lowIndex, float lowCmapValue = lookupMappingValue(mapping.colorMappingValues,
numMappingValues); lowIndex, numMappingValues);
float highCmapValue = lookupMappingValue(mapping.colorMappingValues, highIndex, float highCmapValue = lookupMappingValue(mapping.colorMappingValues,
numMappingValues); highIndex, numMappingValues);
return lowCmapValue + (highCmapValue - lowCmapValue) * factor; return lowCmapValue + (highCmapValue - lowCmapValue) * factor;
} }

View file

@ -1,19 +1,27 @@
// this shader program sets values into a mosaic texture // this shader program sets values into a mosaic texture
// which is the same size as the screen (frame buffer) // which is the same size as the screen (frame buffer)
uniform sampler2D imageData; #include <mapping>
uniform sampler2D mosaicTexture;
uniform int height;
uniform int width;
void main(void) uniform DataTexture imageData;
{ uniform DataMapping imageToMosaic;
vec2 xy = gl_FragCoord.xy; uniform DataTexture mosaicData;
vec4 imageVal = texture2D(imageData,gl_TexCoord[0].st);
vec4 curVal = texture2D(mosaicTexture, vec2((xy.x / float(width)), (xy.y / float(height)))); void main(void) {
if ( imageVal.r > curVal.r ) { float imageValue = textureToDataValue(imageData, gl_TexCoord[0].st);
gl_FragColor = vec4(imageVal.r,0.0,0.0,1.0); vec2 frag_xy = gl_FragCoord.xy;
} else { float mosaicValue = textureToDataValue(mosaicData,
gl_FragColor = vec4(curVal.r,0.0,0.0,1.0); vec2(frag_xy.x / mosaicData.width, frag_xy.y / mosaicData.height));
float newValue = mosaicValue;
// No data check/special NaN check
if (imageValue != imageData.noDataValue && imageValue == imageValue) {
// Convert image value to mosaic value
imageValue = dataToColorMapValue(imageValue, imageToMosaic);
if (imageValue > mosaicValue) {
newValue = imageValue;
} }
} }
gl_FragColor = vec4(dataToTextureValue(mosaicData, newValue), 0.0, 0.0,
1.0);
}

View file

@ -1,20 +1,26 @@
// this shader program sets values into a mosaic texture // this shader program sets values into a mosaic texture
// which is the same size as the screen (frame buffer) // which is the same size as the screen (frame buffer)
uniform sampler2D imageData; #include <mapping>
uniform sampler2D mosaicTexture;
uniform int height;
uniform int width;
void main(void) uniform DataTexture imageData;
{ uniform DataMapping imageToMosaic;
vec2 xy = gl_FragCoord.xy; uniform DataTexture mosaicData;
vec4 imageVal = texture2D(imageData,gl_TexCoord[0].st);
vec4 curVal = texture2D(mosaicTexture, vec2((xy.x / float(width)), (xy.y / float(height)))); void main(void) {
// assume 0 or NaN is No Data and should be replaced if another image has better values. float imageValue = textureToDataValue(imageData, gl_TexCoord[0].st);
if ( imageVal.r != 0.0 && imageVal.r == imageVal.r) { vec2 frag_xy = gl_FragCoord.xy;
gl_FragColor = vec4(imageVal.r,0.0,0.0,1.0); float mosaicValue = textureToDataValue(mosaicData,
vec2(frag_xy.x / mosaicData.width, frag_xy.y / mosaicData.height));
float newValue;
// No data check/special NaN check
if (imageValue == imageData.noDataValue || imageValue != imageValue) {
// Use existing value
newValue = mosaicValue;
} else { } else {
gl_FragColor = vec4(curVal.r,0.0,0.0,1.0); newValue = dataToColorMapValue(imageValue, imageToMosaic);
} }
gl_FragColor = vec4(dataToTextureValue(mosaicData, newValue), 0.0, 0.0,
1.0);
} }

View file

@ -53,9 +53,6 @@
<graphicsExtension <graphicsExtension
class="com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension"> class="com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension">
</graphicsExtension> </graphicsExtension>
<graphicsExtension
class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicImageExtension">
</graphicsExtension>
<graphicsExtension <graphicsExtension
class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicMaxValImageExtension"> class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicMaxValImageExtension">
</graphicsExtension> </graphicsExtension>

View file

@ -55,13 +55,15 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Nov 18, 2011 mschenke Initial creation * Nov 18, 2011 mschenke Initial creation
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap * Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
* parameters, disable colormap interpolation * parameters, disable colormap interpolation
* by default. * by default.
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled. * Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled.
* Added support for colormapping in non-data unit. * Added support for colormapping in non-data unit.
* Nov 20, 2013 2492 bsteffen Mosaic in image units.
*
* *
* </pre> * </pre>
* *
@ -174,7 +176,8 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
} }
/** /**
* Sets up a {@link GLDataMapping} for use in image rendering * Sets up a {@link GLDataMapping} for use in image rendering. Data will be
* mapped to the image's {@link ColorMapParameters#getColorMapUnit()}
* *
* @param gl * @param gl
* @param glImage * @param glImage
@ -185,14 +188,32 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
public static void setupDataMapping(GL gl, public static void setupDataMapping(GL gl,
AbstractGLColormappedImage glImage, int dataMappedTexBinding, AbstractGLColormappedImage glImage, int dataMappedTexBinding,
int colorMappedTexBinding) throws VizException { int colorMappedTexBinding) throws VizException {
setupDataMapping(gl, glImage, glImage.getColorMapParameters()
.getColorMapUnit(), dataMappedTexBinding, colorMappedTexBinding);
}
/**
* Sets up a {@link GLDataMapping} for use in image renderingData will be
* mapped to the unit provided
*
* @param gl
* @param glImage
* @param colorMapUnit
* @param dataMappedTexBinding
* @param colorMappedTexBinding
* @throws VizException
*/
public static void setupDataMapping(GL gl,
AbstractGLColormappedImage glImage, Unit<?> colorMapUnit,
int dataMappedTexBinding, int colorMappedTexBinding)
throws VizException {
ColorMapParameters colorMapParameters = glImage.getColorMapParameters(); ColorMapParameters colorMapParameters = glImage.getColorMapParameters();
// Get GLDataMapping and generate if datamapping is not set. If // Get GLDataMapping and generate if datamapping is not set. If
// datamapping is not set, the data has already been mapped to // datamapping is not set, the data has already been mapped to
// colorMapUnits and we need not do anything // colorMapUnits and we need not do anything
GLDataMapping dataMapping = glImage.getDataMapping(); GLDataMapping dataMapping = glImage.getDataMapping();
if (dataMapping == null && colorMapParameters.getDataMapping() == null) { if (dataMapping == null && colorMapParameters.getDataMapping() == null) {
Unit<?> colorMapUnit = colorMapParameters.getColorMapUnit(); Unit<?> dataUnit = glImage.getDataUnit();
Unit<?> dataUnit = colorMapParameters.getDataUnit();
int colorMapSize = colorMapParameters.getColorMap().getSize(); int colorMapSize = colorMapParameters.getColorMap().getSize();
float colorMapMin = colorMapParameters.getColorMapMin(); float colorMapMin = colorMapParameters.getColorMapMin();
float colorMapMax = colorMapParameters.getColorMapMax(); float colorMapMax = colorMapParameters.getColorMapMax();
@ -290,8 +311,7 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
ColorMapParameters colorMapParameters = image.getColorMapParameters(); ColorMapParameters colorMapParameters = image.getColorMapParameters();
GLSLStructFactory.createDataTexture(program, "rawData", 0, GLSLStructFactory.createDataTexture(program, "rawData", 0, image);
image.getDataFormat(), colorMapParameters.getNoDataValue());
int numMappingValues = 0; int numMappingValues = 0;
GLDataMapping mapping = image.getDataMapping(); GLDataMapping mapping = image.getDataMapping();

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.core.gl.glsl;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat; import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
/** /**
* Factory for creating API defined GLSL structs in a {@link GLShaderProgram}. * Factory for creating API defined GLSL structs in a {@link GLShaderProgram}.
@ -49,14 +50,15 @@ public class GLSLStructFactory {
* @param program * @param program
* @param name * @param name
* @param texBinding * @param texBinding
* @param dataFormat * @param image
* @param noDataValue
*/ */
public static void createDataTexture(GLShaderProgram program, String name, public static void createDataTexture(GLShaderProgram program, String name,
int texBinding, AbstractGLColorMapDataFormat dataFormat, int texBinding, AbstractGLColormappedImage image) {
double noDataValue) { ColorMapParameters parameters = image.getColorMapParameters();
AbstractGLColorMapDataFormat dataFormat = image.getDataFormat();
setFieldUniform(program, name, "rawTex", texBinding); setFieldUniform(program, name, "rawTex", texBinding);
setFieldUniform(program, name, "noDataValue", noDataValue); setFieldUniform(program, name, "noDataValue",
parameters.getNoDataValue());
setFieldUniform(program, name, "isScaled", dataFormat.isScaled()); setFieldUniform(program, name, "isScaled", dataFormat.isScaled());
if (dataFormat.isScaled()) { if (dataFormat.isScaled()) {
setFieldUniform(program, name, "scaleMin", setFieldUniform(program, name, "scaleMin",
@ -64,6 +66,8 @@ public class GLSLStructFactory {
setFieldUniform(program, name, "scaleMax", setFieldUniform(program, name, "scaleMax",
dataFormat.getDataFormatMax()); dataFormat.getDataFormatMax());
} }
setFieldUniform(program, name, "width", (float) image.getWidth());
setFieldUniform(program, name, "height", (float) image.getHeight());
} }
/** /**

View file

@ -33,8 +33,12 @@ import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension; import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension; import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
import com.raytheon.viz.core.gl.ext.imaging.GLColormappedImageExtension;
import com.raytheon.viz.core.gl.ext.imaging.GLDataMappingFactory.GLDataMapping;
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension; import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
import com.raytheon.viz.core.gl.glsl.GLShaderProgram; import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
import com.raytheon.viz.core.gl.images.AbstractGLImage; import com.raytheon.viz.core.gl.images.AbstractGLImage;
import com.raytheon.viz.core.gl.images.GLColormappedImage; import com.raytheon.viz.core.gl.images.GLColormappedImage;
import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage; import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
@ -47,12 +51,13 @@ import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Dec 16, 2011 mschenke Initial creation * Dec 16, 2011 mschenke Initial creation
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data * Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
* format for offscreen textures. * format for offscreen textures.
* Oct 16, 2013 2333 mschenke Cleaned up render logic, switched to * Oct 16, 2013 2333 mschenke Cleaned up render logic, switched to use
* use GLOffscreenColormappedImage * GLOffscreenColormappedImage
* Nov 20, 2013 2492 bsteffen Mosaic in image units.
* *
* </pre> * </pre>
* *
@ -60,8 +65,8 @@ import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
* @version 1.0 * @version 1.0
*/ */
public class GLMosaicImageExtension extends AbstractGLSLImagingExtension public abstract class GLMosaicImageExtension extends
implements IMosaicImageExtension { AbstractGLSLImagingExtension implements IMosaicImageExtension {
private GLOffscreenColormappedImage writeToImage; private GLOffscreenColormappedImage writeToImage;
@ -75,19 +80,6 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
imageExtent, this.getClass()); imageExtent, this.getClass());
} }
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#getShaderProgramName
* ()
*/
@Override
public String getShaderProgramName() {
// Default mosaicing algorithm glsl program
return "mosaicOrdered";
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -142,16 +134,20 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
new DrawableImage(mosaicImage.getWrappedImage(), new DrawableImage(mosaicImage.getWrappedImage(),
coverage)); coverage));
} }
// Don't actually render this image now since we just did it } else if (image instanceof AbstractGLColormappedImage) {
return null;
} else {
GL gl = target.getGl(); GL gl = target.getGl();
// activate on texture2 as 0 is radar image and 1 is colormap // activate on texture2 as 0 is radar image and 1 is colormap
gl.glActiveTexture(GL.GL_TEXTURE1); gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(writeToImage.getTextureStorageType(), gl.glBindTexture(writeToImage.getTextureStorageType(),
writeToImage.getTextureid()); writeToImage.getTextureid());
GLColormappedImageExtension.setupDataMapping(gl,
(AbstractGLColormappedImage) image,
writeToImage.getDataUnit(), 2, 3);
return image; return image;
} }
// Fall through here, no actual rendering will occur
return null;
} }
private GLOffscreenColormappedImage getWriteToImage( private GLOffscreenColormappedImage getWriteToImage(
@ -208,6 +204,12 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
// activate on texture2 as 0 is radar image // activate on texture2 as 0 is radar image
gl.glActiveTexture(GL.GL_TEXTURE1); gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(writeToImage.getTextureStorageType(), 0); gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
gl.glActiveTexture(GL.GL_TEXTURE2);
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
gl.glActiveTexture(GL.GL_TEXTURE3);
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
} }
/* /*
@ -220,14 +222,27 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
* com.raytheon.uf.viz.core.drawables.PaintProperties) * com.raytheon.uf.viz.core.drawables.PaintProperties)
*/ */
@Override @Override
public void loadShaderData(GLShaderProgram program, IImage image, public void loadShaderData(GLShaderProgram program, IImage iimage,
PaintProperties paintProps) throws VizException { PaintProperties paintProps) throws VizException {
program.setUniform("imageData", 0); AbstractGLColormappedImage image = null;
program.setUniform("mosaicTexture", 1); if (iimage instanceof AbstractGLColormappedImage == false) {
throw new VizException(
"Cannot apply glsl mosaicing shader to non gl colormap image");
}
image = (AbstractGLColormappedImage) iimage;
// pass in width and height GLSLStructFactory.createDataTexture(program, "imageData", 0, image);
program.setUniform("height", writeToImage.getHeight());
program.setUniform("width", writeToImage.getWidth()); int numMappingValues = 0;
GLDataMapping mapping = image.getDataMapping();
if (mapping != null && mapping.isValid()) {
numMappingValues = mapping.getNumMappingValues();
}
GLSLStructFactory.createDataMapping(program, "imageToMosaic", 2, 3,
numMappingValues);
GLSLStructFactory.createDataTexture(program, "mosaicData", 1,
writeToImage);
} }
} }

View file

@ -24,6 +24,8 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.measure.Measure;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
@ -63,6 +65,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Jul 31, 2013 2190 mschenke Removed arbitrary check for 0.0 and instead * Jul 31, 2013 2190 mschenke Removed arbitrary check for 0.0 and instead
* only check for NaN. SatResource handles fill * only check for NaN. SatResource handles fill
* values and returns NaN now * values and returns NaN now
* Nov 20, 2013 2492 bsteffen Update inspect to use Measure objects
* *
* </pre> * </pre>
* *
@ -282,10 +285,12 @@ public class SatBlendedResource extends
for (int i = list.size() - 1; i >= 0; --i) { for (int i = list.size() - 1; i >= 0; --i) {
AbstractVizResource<?, ?> rsc = list.get(i).getResource(); AbstractVizResource<?, ?> rsc = list.get(i).getResource();
Map<String, Object> dataMap = rsc.interrogate(coord); Map<String, Object> dataMap = rsc.interrogate(coord);
if (dataMap.get(SatResource.RAW_VALUE) instanceof Number) { Measure<?, ?> value = (Measure<?, ?>) dataMap
double value = ((Number) dataMap.get(SatResource.RAW_VALUE)) .get(SatResource.SATELLITE_DATA_INTERROGATE_ID);
if (value != null && value.getValue() instanceof Number) {
double measuredValue = ((Number) value.getValue())
.doubleValue(); .doubleValue();
if (Double.isNaN(value) == false) { if (Double.isNaN(measuredValue) == false) {
// use this resource // use this resource
inspectString = rsc.inspect(coord); inspectString = rsc.inspect(coord);
break; break;

View file

@ -29,6 +29,7 @@ import java.util.Map;
import javax.measure.Measure; import javax.measure.Measure;
import javax.measure.converter.UnitConverter; import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -41,18 +42,14 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage; import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits; import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits;
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.style.ParamLevelMatchCriteria; import com.raytheon.uf.common.style.ParamLevelMatchCriteria;
import com.raytheon.uf.common.style.StyleException; import com.raytheon.uf.common.style.StyleException;
import com.raytheon.uf.common.style.StyleManager; import com.raytheon.uf.common.style.StyleManager;
import com.raytheon.uf.common.style.StyleRule; import com.raytheon.uf.common.style.StyleRule;
import com.raytheon.uf.common.style.image.ColorMapParameterFactory; import com.raytheon.uf.common.style.image.ColorMapParameterFactory;
import com.raytheon.uf.common.style.image.DataScale;
import com.raytheon.uf.common.style.image.ImagePreferences; import com.raytheon.uf.common.style.image.ImagePreferences;
import com.raytheon.uf.common.style.image.SamplePreferences; import com.raytheon.uf.common.style.image.SamplePreferences;
import com.raytheon.uf.common.style.level.Level; import com.raytheon.uf.common.style.level.Level;
@ -83,18 +80,24 @@ import com.vividsolutions.jts.geom.Coordinate;
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Mar 1, 2007 chammack Initial Creation. * Mar 01, 2007 chammack Initial Creation.
* 02/17/2009 njensen Refactored to new rsc architecture. * Feb 17, 2009 njensen Refactored to new rsc architecture.
* 03/02/2009 2032 jsanchez Added check for displayedDate if no data. * Mar 02, 2009 2032 jsanchez Added check for displayedDate if no
* 03/25/2009 2086 jsanchez Mapped correct converter to parameter type. * data.
* Updated the call to ColormapParametersFactory.build * Mar 25, 2009 2086 jsanchez Mapped correct converter to parameter
* 03/30/2009 2169 jsanchez Updated numLevels handling. * type. Updated the call to
* - AWIPS2 Baseline Repository -------- * ColormapParametersFactory.build
* 07/17/2012 798 jkorman Use decimationLevels from SatelliteRecord. Removed hard-coded * Mar 30, 2009 2169 jsanchez Updated numLevels handling.
* Jul 17, 2012 798 jkorman Use decimationLevels from
* SatelliteRecord. Removed hard-coded
* data set names. * data set names.
* 06/20/2013 2122 mschenke Modified to use SatTileSetRenderable * Jun 20, 2013 2122 mschenke Modified to use SatTileSetRenderable
* 07/31/2013 2190 mschenke Switched to use Measure objects for interrogation * Jul 31, 2013 2190 mschenke Switched to use Measure objects for
* interrogation
* Nov 20, 2013 2492 bsteffen Always get min/max values from style
* rules.
*
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -103,11 +106,6 @@ import com.vividsolutions.jts.geom.Coordinate;
public class SatResource extends public class SatResource extends
AbstractPluginDataObjectResource<SatResourceData, IMapDescriptor> { AbstractPluginDataObjectResource<SatResourceData, IMapDescriptor> {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SatResource.class);
public static String RAW_VALUE = "rawValue";
/** String id to look for satellite-provided data values */ /** String id to look for satellite-provided data values */
public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue"; public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue";
@ -215,12 +213,12 @@ public class SatResource extends
} }
} }
public InterrogationResult interrogate(Coordinate latLon) public InterrogationResult interrogate(Coordinate latLon,
throws VizException { Unit<?> requestUnit) throws VizException {
InterrogationResult result = null; InterrogationResult result = null;
synchronized (tileMap) { synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) { for (SatTileSetRenderable renderable : tileMap.values()) {
double rValue = renderable.interrogate(latLon, fillValue); double rValue = renderable.interrogate(latLon, requestUnit);
if (Double.isNaN(rValue) == false) { if (Double.isNaN(rValue) == false) {
result = new InterrogationResult( result = new InterrogationResult(
renderable.getSatelliteRecord(), rValue); renderable.getSatelliteRecord(), rValue);
@ -235,7 +233,8 @@ public class SatResource extends
protected SamplePreferences sampleRange; protected SamplePreferences sampleRange;
protected double fillValue = 0; /** Flag to avoid reinitializing ColorMapParameters from style rules */
private boolean initialized = false;
/** /**
* Constructor * Constructor
@ -249,21 +248,19 @@ public class SatResource extends
@Override @Override
protected DataTime getDataObjectTime(PluginDataObject pdo) { protected DataTime getDataObjectTime(PluginDataObject pdo) {
SatelliteRecord record = (SatelliteRecord) pdo; if (initialized == false) {
if (dataTimes.isEmpty()) {
try { try {
initializeFirstFrame(record); initializeFirstFrame((SatelliteRecord) pdo);
} catch (VizException e) { } catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), throw new IllegalStateException(
e); "Unable to initialize the satellite resource");
} }
initialized = true;
} }
DataTime pdoTime = pdo.getDataTime(); DataTime pdoTime = pdo.getDataTime();
if (resourceData.getBinOffset() != null) { if (resourceData.getBinOffset() != null) {
pdoTime = resourceData.getBinOffset().getNormalizedTime(pdoTime); pdoTime = resourceData.getBinOffset().getNormalizedTime(pdoTime);
} }
return pdoTime; return pdoTime;
} }
@ -286,7 +283,6 @@ public class SatResource extends
} }
SingleLevel level = new SingleLevel(Level.LevelType.SURFACE); SingleLevel level = new SingleLevel(Level.LevelType.SURFACE);
Unit<?> unit = SatDataRetriever.getRecordUnit(record);
String physicalElement = null; String physicalElement = null;
DerivedParameterRequest request = (DerivedParameterRequest) record DerivedParameterRequest request = (DerivedParameterRequest) record
.getMessageData(); .getMessageData();
@ -301,25 +297,42 @@ public class SatResource extends
match.setParameterName(Arrays.asList(physicalElement)); match.setParameterName(Arrays.asList(physicalElement));
match.setLevels(Arrays.asList((Level) level)); match.setLevels(Arrays.asList((Level) level));
match.setCreatingEntityNames(Arrays.asList(record.getCreatingEntity())); match.setCreatingEntityNames(Arrays.asList(record.getCreatingEntity()));
StyleRule sr; Unit<?> unit = SatDataRetriever.getRecordUnit(record);
try { try {
sr = StyleManager.getInstance().getStyleRule( StyleRule sr = StyleManager.getInstance().getStyleRule(
StyleManager.StyleType.IMAGERY, match); StyleManager.StyleType.IMAGERY, match);
} catch (StyleException e) {
throw new VizException(e.getLocalizedMessage(), e); ImagePreferences preferences = null;
if (sr == null
|| sr.getPreferences() instanceof ImagePreferences == false) {
// No style rule, this is a best guess at what might look good.
preferences = new ImagePreferences();
if (unit != null && unit.isCompatible(Temperature.UNIT)) {
preferences.setDefaultColormap("Sat/IR/CIRA (IR Default)");
} else {
preferences.setDefaultColormap("Sat/VIS/ZA (Vis Default)");
} }
if (sr != null && sr.getPreferences() instanceof ImagePreferences) { DataScale range = new DataScale();
sampleRange = ((ImagePreferences) sr.getPreferences()) range.setScaleType(DataScale.Type.LINEAR);
.getSamplePrefs(); range.setMinValue(0.0);
String lg = ((ImagePreferences) sr.getPreferences()).getLegend(); range.setMaxValue(255.0);
preferences.setDataScale(range);
} else {
preferences = (ImagePreferences) sr.getPreferences();
}
colorMapParameters = ColorMapParameterFactory.build(preferences,
unit);
sampleRange = preferences.getSamplePrefs();
String lg = preferences.getLegend();
// test, so legend is not over written with empty string // test, so legend is not over written with empty string
if (lg != null && !lg.trim().isEmpty()) { if (lg != null && !lg.trim().isEmpty()) {
legend = lg; legend = lg;
} }
} catch (StyleException e) {
throw new VizException(e.getLocalizedMessage(), e);
} }
colorMapParameters = ColorMapParameterFactory.build(sr, null, level,
unit);
// If null, set from style rules // If null, set from style rules
if (cmName == null) { if (cmName == null) {
cmName = colorMapParameters.getColorMapName(); cmName = colorMapParameters.getColorMapName();
@ -343,26 +356,7 @@ public class SatResource extends
if (persisted != null) { if (persisted != null) {
colorMapParameters.applyPersistedParameters(persisted); colorMapParameters.applyPersistedParameters(persisted);
} }
colorMapParameters.setNoDataValue(0);
// TODO: Figure out data/color map min/max values better
if (unit == null) {
colorMapParameters.setColorMapMin(0.0f);
colorMapParameters.setColorMapMax(255.0f);
}
if (unit instanceof GenericPixel) {
// Derived parameter data will be signed
colorMapParameters.setDataMin(-128.0f);
colorMapParameters.setDataMax(127.0f);
} else if (unit instanceof BlendedTPWPixel) {
colorMapParameters.setDataMin(0.0f);
colorMapParameters.setDataMax(252.0f);
colorMapParameters.setColorMapMin(0.0f);
colorMapParameters.setColorMapMax(252.0f);
} else {
colorMapParameters.setDataMin(0.0f);
colorMapParameters.setDataMax(255.0f);
}
getCapability(ColorMapCapability.class).setColorMapParameters( getCapability(ColorMapCapability.class).setColorMapParameters(
colorMapParameters); colorMapParameters);
@ -389,10 +383,11 @@ public class SatResource extends
ColorMapParameters parameters = getCapability(ColorMapCapability.class) ColorMapParameters parameters = getCapability(ColorMapCapability.class)
.getColorMapParameters(); .getColorMapParameters();
double dataValue = Double.NaN; double dataValue = Double.NaN;
Unit<?> dataUnit = parameters.getColorMapUnit();
if (renderable != null) { if (renderable != null) {
try { try {
InterrogationResult result = renderable.interrogate(coord InterrogationResult result = renderable.interrogate(
.asLatLon()); coord.asLatLon(), dataUnit);
if (result != null) { if (result != null) {
dataValue = result.getValue(); dataValue = result.getValue();
dataMap.put(IGridGeometryProvider.class.toString(), result dataMap.put(IGridGeometryProvider.class.toString(), result
@ -403,9 +398,8 @@ public class SatResource extends
} }
} }
dataMap.put(RAW_VALUE, dataValue);
dataMap.put(SATELLITE_DATA_INTERROGATE_ID, dataMap.put(SATELLITE_DATA_INTERROGATE_ID,
Measure.valueOf(dataValue, parameters.getDataUnit())); Measure.valueOf(dataValue, dataUnit));
return dataMap; return dataMap;
} }
@ -413,8 +407,14 @@ public class SatResource extends
@Override @Override
public String inspect(ReferencedCoordinate coord) throws VizException { public String inspect(ReferencedCoordinate coord) throws VizException {
Map<String, Object> dataMap = interrogate(coord); Map<String, Object> dataMap = interrogate(coord);
Double value = (Double) dataMap.get(RAW_VALUE);
if (value == null || value.isNaN()) { Measure<?, ?> value = (Measure<?, ?>) dataMap
.get(SATELLITE_DATA_INTERROGATE_ID);
double measuredValue = Double.NaN;
if (value != null && value.getValue() instanceof Double) {
measuredValue = (Double) value.getValue();
}
if (Double.isNaN(measuredValue)) {
return "NO DATA"; return "NO DATA";
} }
ColorMapParameters cmp = getCapability(ColorMapCapability.class) ColorMapParameters cmp = getCapability(ColorMapCapability.class)
@ -425,18 +425,21 @@ public class SatResource extends
if (dataMapping != null) { if (dataMapping != null) {
// if the pixel value matches the data mapping entry use that // if the pixel value matches the data mapping entry use that
// label instead // label instead
String label = dataMapping.getLabelValueForDataValue(value); String label = dataMapping.getLabelValueForDataValue(measuredValue);
if (label != null) { if (label != null) {
return label; return label;
} }
} }
UnitConverter dataToDisplay = cmp.getDataToDisplayConverter(); Unit<?> unit = cmp.getDisplayUnit();
Unit<?> measuredUnit = value.getUnit();
if (unit != null && measuredUnit != null) {
UnitConverter dataToDisplay = measuredUnit.getConverterTo(unit);
if (dataToDisplay != null) { if (dataToDisplay != null) {
value = dataToDisplay.convert(value); measuredValue = dataToDisplay.convert(measuredValue);
}
} }
Unit<?> unit = cmp.getDisplayUnit();
// Had to use 'bit' as the display unit because // Had to use 'bit' as the display unit because
// counts was not an acceptable unit. // counts was not an acceptable unit.
String unitString = unit == null ? "" String unitString = unit == null ? ""
@ -447,13 +450,13 @@ public class SatResource extends
f1 = sampleRange.getMaxValue(); f1 = sampleRange.getMaxValue();
f2 = sampleRange.getMinValue(); f2 = sampleRange.getMinValue();
} }
if (value > f1 && value > f2) { if (measuredValue > f1 && measuredValue > f2) {
return String.format(">%.1f%s", Math.max(f1, f2), unitString); return String.format(">%.1f%s", Math.max(f1, f2), unitString);
} }
if (value < f1 && value < f2) { if (measuredValue < f1 && measuredValue < f2) {
return String.format("<%.1f%s", Math.min(f1, f2), unitString); return String.format("<%.1f%s", Math.min(f1, f2), unitString);
} }
return String.format("%.1f%s", value, unitString); return String.format("%.1f%s", measuredValue, unitString);
} }
private String getLegend(PluginDataObject record) { private String getLegend(PluginDataObject record) {

View file

@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.text.ParseException; import java.text.ParseException;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.util.Map;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat; import javax.measure.unit.UnitFormat;
@ -61,6 +62,8 @@ import com.raytheon.viz.satellite.SatelliteConstants;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jun 20, 2013 2122 mschenke Initial creation * Jun 20, 2013 2122 mschenke Initial creation
* Nov 13, 2013 2492 mschenke Added extraction of scale/offset from
* data record attributes for unit
* *
* </pre> * </pre>
* *
@ -92,8 +95,8 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
*/ */
@Override @Override
public ColorMapData getColorMapData() { public ColorMapData getColorMapData() {
// TODO: Read scale/offset out of attributes?
Buffer data = null; Buffer data = null;
Unit<?> dataUnit = Unit.ONE;
boolean signed = false; boolean signed = false;
Request req = Request.buildSlab(new int[] { this.datasetBounds.x, Request req = Request.buildSlab(new int[] { this.datasetBounds.x,
this.datasetBounds.y }, new int[] { this.datasetBounds.y }, new int[] {
@ -112,6 +115,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
} }
Unit<?> recordUnit = getRecordUnit(this.record); Unit<?> recordUnit = getRecordUnit(this.record);
signed = recordUnit instanceof GenericPixel; signed = recordUnit instanceof GenericPixel;
dataUnit = getDataUnit(recordUnit, record);
} }
} catch (VizDataCubeException e) { } catch (VizDataCubeException e) {
statusHandler.handle(Priority.SIGNIFICANT, statusHandler.handle(Priority.SIGNIFICANT,
@ -134,7 +138,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
} }
return new ColorMapData(data, new int[] { datasetBounds.width, return new ColorMapData(data, new int[] { datasetBounds.width,
datasetBounds.height }, dataType); datasetBounds.height }, dataType, dataUnit);
} }
/** /**
@ -150,7 +154,8 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
physicalElement = request.getParameterAbbreviation(); physicalElement = request.getParameterAbbreviation();
} }
if (record.getUnits() != null && record.getUnits().isEmpty() == false && request == null) { if (record.getUnits() != null && record.getUnits().isEmpty() == false
&& request == null) {
try { try {
recordUnit = UnitFormat.getUCUMInstance().parseProductUnit( recordUnit = UnitFormat.getUCUMInstance().parseProductUnit(
record.getUnits(), new ParsePosition(0)); record.getUnits(), new ParsePosition(0));
@ -181,6 +186,37 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
return recordUnit; return recordUnit;
} }
/**
* Extracts the data units for the data record given the PDO's base unit
*
* @param recordUnit
* @param dataRecord
* @return
*/
private static Unit<?> getDataUnit(Unit<?> recordUnit,
IDataRecord dataRecord) {
Unit<?> units = recordUnit != null ? recordUnit : Unit.ONE;
Map<String, Object> attrs = dataRecord.getDataAttributes();
if (attrs != null) {
Number offset = (Number) attrs.get(SatelliteRecord.SAT_ADD_OFFSET);
Number scale = (Number) attrs.get(SatelliteRecord.SAT_SCALE_FACTOR);
if (offset != null) {
double offsetVal = offset.doubleValue();
if (offsetVal != 0.0) {
units = units.plus(offsetVal);
}
}
if (scale != null) {
double scaleVal = scale.doubleValue();
if (scaleVal != 0.0) {
units = units.times(scaleVal);
}
}
}
return units;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *

View file

@ -65,7 +65,7 @@ public class ColorMapSliderComp extends Composite {
private static final int SLIDER_MIN = 0; private static final int SLIDER_MIN = 0;
private static final int SLIDER_MAX = 255; private static final int SLIDER_MAX = 250;
private static final int SLIDER_INC = 1; private static final int SLIDER_INC = 1;
@ -79,9 +79,9 @@ public class ColorMapSliderComp extends Composite {
private Text maxValueText; private Text maxValueText;
private final float cmapAbsoluteMin; private float cmapAbsoluteMin;
private final float cmapAbsoluteMax; private float cmapAbsoluteMax;
private final float origCmapMin; private final float origCmapMin;
@ -93,8 +93,6 @@ public class ColorMapSliderComp extends Composite {
private final DecimalFormat format; private final DecimalFormat format;
private final boolean dataInverted;
private UnitConverter displayToColorMap; private UnitConverter displayToColorMap;
private UnitConverter colorMapToDisplay; private UnitConverter colorMapToDisplay;
@ -106,8 +104,10 @@ public class ColorMapSliderComp extends Composite {
public ColorMapSliderComp(Composite parent, ColorMapParameters cmap) { public ColorMapSliderComp(Composite parent, ColorMapParameters cmap) {
super(parent, SWT.NONE); super(parent, SWT.NONE);
this.cmap = cmap; this.cmap = cmap;
this.currentCmapMin = this.origCmapMin = cmap.getColorMapMin(); this.cmapAbsoluteMin = this.currentCmapMin = this.origCmapMin = cmap
this.currentCmapMax = this.origCmapMax = cmap.getColorMapMax(); .getColorMapMin();
this.cmapAbsoluteMax = this.currentCmapMax = this.origCmapMax = cmap
.getColorMapMax();
this.displayToColorMap = cmap.getDisplayToColorMapConverter(); this.displayToColorMap = cmap.getDisplayToColorMapConverter();
this.colorMapToDisplay = cmap.getColorMapToDisplayConverter(); this.colorMapToDisplay = cmap.getColorMapToDisplayConverter();
if (displayToColorMap == null) { if (displayToColorMap == null) {
@ -116,34 +116,9 @@ public class ColorMapSliderComp extends Composite {
if (colorMapToDisplay == null) { if (colorMapToDisplay == null) {
colorMapToDisplay = Unit.ONE.getConverterTo(Unit.ONE); colorMapToDisplay = Unit.ONE.getConverterTo(Unit.ONE);
} }
float cmapAbsoluteMin, cmapAbsoluteMax;
if (cmap.getDataMapping() != null) {
cmapAbsoluteMin = cmap.getColorMapMin();
cmapAbsoluteMax = cmap.getColorMapMax();
} else {
UnitConverter dataToColorMap = cmap.getDataToColorMapConverter();
cmapAbsoluteMin = cmap.getDataMin();
cmapAbsoluteMax = cmap.getDataMax();
if (dataToColorMap != null) {
cmapAbsoluteMin = (float) dataToColorMap.convert(cmap
.getDataMin());
cmapAbsoluteMax = (float) dataToColorMap.convert(cmap
.getDataMax());
}
}
this.cmapAbsoluteMin = cmapAbsoluteMin; updateAbsolutes(cmapAbsoluteMin, cmapAbsoluteMax);
this.cmapAbsoluteMax = cmapAbsoluteMax;
boolean dataInverted = false;
if ((cmapAbsoluteMin > cmapAbsoluteMax && cmap.getDataMin() < cmap
.getDataMax())
|| (cmapAbsoluteMin < cmapAbsoluteMax && cmap.getDataMin() > cmap
.getDataMax())) {
dataInverted = true;
}
this.dataInverted = dataInverted;
this.format = getTextFormat(); this.format = getTextFormat();
initializeComponents(); initializeComponents();
@ -205,6 +180,7 @@ public class ColorMapSliderComp extends Composite {
} }
}); });
minSlider.addSelectionListener(new SelectionAdapter() { minSlider.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
@ -217,8 +193,7 @@ public class ColorMapSliderComp extends Composite {
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (e.character == SWT.CR) { if (e.character == SWT.CR) {
setColorMapMax(textToColorMapValue(maxValueText.getText() updateMinMaxFromText(maxValueText);
.trim()));
} }
} }
}); });
@ -227,8 +202,7 @@ public class ColorMapSliderComp extends Composite {
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (e.character == SWT.CR) { if (e.character == SWT.CR) {
setColorMapMin(textToColorMapValue(minValueText.getText() updateMinMaxFromText(minValueText);
.trim()));
} }
} }
}); });
@ -237,6 +211,48 @@ public class ColorMapSliderComp extends Composite {
setColorMapMax(currentCmapMax); setColorMapMax(currentCmapMax);
} }
private void updateMinMaxFromText(Text text) {
float newCmapValue = textToColorMapValue(text);
if (Float.isNaN(newCmapValue)) {
// Change nothing
if (text == minValueText) {
newCmapValue = currentCmapMin;
} else {
newCmapValue = currentCmapMax;
}
} else {
// Update colormap range
if (text == minValueText) {
currentCmapMin = newCmapValue;
} else {
currentCmapMax = newCmapValue;
}
}
updateAbsolutes(currentCmapMin, currentCmapMax);
setColorMapMin(currentCmapMin);
setColorMapMax(currentCmapMax);
}
/**
*
*/
private void updateAbsolutes(float cmapAbsoluteMin, float cmapAbsoluteMax) {
double displayAbsMax = colorMapToDisplay.convert(cmapAbsoluteMax);
double displayAbsMin = colorMapToDisplay.convert(cmapAbsoluteMin);
if (displayAbsMax < displayAbsMin) {
float tmp = cmapAbsoluteMax;
cmapAbsoluteMax = cmapAbsoluteMin;
cmapAbsoluteMin = tmp;
}
// Add a 1/16 buffer on either side for fine tuning
float buffer = (cmapAbsoluteMax - cmapAbsoluteMin) * .0625f;
this.cmapAbsoluteMin = cmapAbsoluteMin - buffer;
this.cmapAbsoluteMax = cmapAbsoluteMax + buffer;
}
/** /**
* Converts a slider selection index to a colormap value * Converts a slider selection index to a colormap value
* *
@ -246,9 +262,6 @@ public class ColorMapSliderComp extends Composite {
private float selectionToColorMapValue(int selection) { private float selectionToColorMapValue(int selection) {
double indexValue = Colormapper.getLinearIndex(selection, SLIDER_MIN, double indexValue = Colormapper.getLinearIndex(selection, SLIDER_MIN,
SLIDER_MAX); SLIDER_MAX);
if (dataInverted) {
indexValue = 1 - indexValue;
}
double colorMapValue = cmapAbsoluteMin double colorMapValue = cmapAbsoluteMin
+ (cmapAbsoluteMax - cmapAbsoluteMin) * indexValue; + (cmapAbsoluteMax - cmapAbsoluteMin) * indexValue;
return (float) colorMapValue; return (float) colorMapValue;
@ -263,9 +276,6 @@ public class ColorMapSliderComp extends Composite {
private int colorMapValueToSelection(float colorMapValue) { private int colorMapValueToSelection(float colorMapValue) {
double indexValue = Colormapper.getLinearIndex(colorMapValue, double indexValue = Colormapper.getLinearIndex(colorMapValue,
cmapAbsoluteMin, cmapAbsoluteMax); cmapAbsoluteMin, cmapAbsoluteMax);
if (dataInverted) {
indexValue = 1 - indexValue;
}
return (int) (SLIDER_MIN + (SLIDER_MAX - SLIDER_MIN) * indexValue); return (int) (SLIDER_MIN + (SLIDER_MAX - SLIDER_MIN) * indexValue);
} }
@ -275,7 +285,8 @@ public class ColorMapSliderComp extends Composite {
* @param text * @param text
* @return * @return
*/ */
private float textToColorMapValue(String text) { private float textToColorMapValue(Text textControl) {
String text = textControl.getText().trim();
if (cmap.getDataMapping() != null && text.isEmpty() == false) { if (cmap.getDataMapping() != null && text.isEmpty() == false) {
// First check for data mapping entries // First check for data mapping entries
for (DataMappingEntry entry : cmap.getDataMapping().getEntries()) { for (DataMappingEntry entry : cmap.getDataMapping().getEntries()) {
@ -285,13 +296,28 @@ public class ColorMapSliderComp extends Composite {
} }
} }
if (NaN_STRING.equals(text)) { if (NaN_STRING.equals(text)) {
// If special NaN String, try to find first NaN value // If special NaN String, try to find closest NaN value
float currentColorMapValue = textControl == maxValueText ? currentCmapMax
: currentCmapMin;
int currentSliderValue = colorMapValueToSelection(currentColorMapValue);
int minDist = Integer.MAX_VALUE;
float bestNanValue = currentColorMapValue;
for (int i = SLIDER_MIN; i < SLIDER_MAX; i += SLIDER_INC) { for (int i = SLIDER_MIN; i < SLIDER_MAX; i += SLIDER_INC) {
float colorMapValue = selectionToColorMapValue(i); float colorMapValue = selectionToColorMapValue(i);
if (Double.isNaN(colorMapToDisplay.convert(colorMapValue))) { if (Double.isNaN(colorMapToDisplay.convert(colorMapValue))) {
return colorMapValue; int dist = Math.abs(i - currentSliderValue);
if (dist < minDist) {
minDist = dist;
bestNanValue = colorMapValue;
} else if (i > currentSliderValue) {
break;
}
} else {
// For now, assume NaN will live on low end of slider
break;
} }
} }
return bestNanValue;
} else { } else {
// Attempt to parse and convert // Attempt to parse and convert
try { try {

View file

@ -26,13 +26,14 @@ import javax.measure.converter.UnitConverter;
import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.HashCodeBuilder;
/** /**
* Converts a temperature value in Kelvin to a pixel value from 0 to 255 * Converts a temperature value in Kelvin to a pixel value.
* *
* <pre> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Aug 29, 2007 njensen Initial creation * Aug 29, 2007 njensen Initial creation
* Nov 20, 2013 2492 bsteffen Make conversion unbounded.
* *
* </pre> * </pre>
* *
@ -52,12 +53,6 @@ public class IRTempToPixelConverter extends UnitConverter {
result = 656.3 - (2.0 * aTemperature); result = 656.3 - (2.0 * aTemperature);
} }
if (result < 0) {
result = 0.0;
} else if (result > 255) {
result = 255.0;
}
return result; return result;
} }

View file

@ -1,118 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.satellite.units.water;
import javax.measure.converter.ConversionException;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.SI;
import org.apache.commons.lang.builder.HashCodeBuilder;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 18, 2010 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class BlendedTPWLengthToPixelConverter extends UnitConverter {
private static final long serialVersionUID = 1L;
private static UnitConverter meterToMillimeter = SI.METRE.getConverterTo(SI
.MILLI(SI.METRE));
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#convert( double)
*/
@Override
public double convert(double aLength) throws ConversionException {
double result = 0.0;
aLength = meterToMillimeter.convert(aLength);
if (aLength < 1) {
result = 176;
} else {
result = aLength + 176;
}
if (result < 0) {
result = 0;
} else if (result > 255) {
result = 255;
}
return result;
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#equals(java.lang.Object)
*/
@Override
public boolean equals(Object aConverter) {
return (aConverter instanceof BlendedTPWLengthToPixelConverter);
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#hashCode()
*/
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#inverse()
*/
@Override
public UnitConverter inverse() {
return new BlendedTPWPixelToLengthConverter();
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#isLinear()
*/
@Override
public boolean isLinear() {
return false;
}
}

View file

@ -19,6 +19,7 @@
**/ **/
package com.raytheon.uf.common.dataplugin.satellite.units.water; package com.raytheon.uf.common.dataplugin.satellite.units.water;
import javax.measure.converter.AddConverter;
import javax.measure.converter.UnitConverter; import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Length; import javax.measure.quantity.Length;
import javax.measure.unit.DerivedUnit; import javax.measure.unit.DerivedUnit;
@ -28,15 +29,17 @@ import javax.measure.unit.Unit;
import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.HashCodeBuilder;
/** /**
* TODO Add Description * Represents a pixel value on a satellite blended total precipitable water(TPW)
* image.
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Mar 18, 2010 jsanchez Initial creation * Mar 18, 2010 jsanchez Initial creation
* Nov 20, 2013 2492 bsteffen Make conversion unbounded.
* *
* </pre> * </pre>
* *
@ -66,6 +69,7 @@ public class BlendedTPWPixel extends DerivedUnit<Length> {
@Override @Override
public UnitConverter toStandardUnit() { public UnitConverter toStandardUnit() {
return new BlendedTPWPixelToLengthConverter(); return SI.MILLI(SI.METRE).getConverterTo(SI.METRE)
.concatenate(new AddConverter(-176));
} }
} }

View file

@ -1,111 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.satellite.units.water;
import javax.measure.converter.ConversionException;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.SI;
import org.apache.commons.lang.builder.HashCodeBuilder;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 18, 2010 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class BlendedTPWPixelToLengthConverter extends UnitConverter {
private static final long serialVersionUID = 1L;
private static UnitConverter millimeterToMeter = (SI.MILLI(SI.METRE))
.getConverterTo(SI.METRE);
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#convert(double)
*/
@Override
public double convert(double aPixel) throws ConversionException {
double result = 0.0;
if (aPixel <= 176) {
result = 0.0;
} else {
result = aPixel - 176;
}
result = millimeterToMeter.convert(result);
return result;
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#equals(java.lang.Object)
*/
@Override
public boolean equals(Object aConverter) {
return (aConverter instanceof BlendedTPWPixelToLengthConverter);
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#hashCode()
*/
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#inverse()
*/
@Override
public UnitConverter inverse() {
return new BlendedTPWLengthToPixelConverter();
}
/*
* (non-Javadoc)
*
* @see javax.measure.converter.UnitConverter#isLinear()
*/
@Override
public boolean isLinear() {
return false;
}
}

View file

@ -43,8 +43,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap> <defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
</imageStyle> </imageStyle>
@ -75,8 +75,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap> <defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
</imageStyle> </imageStyle>
@ -199,8 +199,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap> <defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
</imageStyle> </imageStyle>
@ -211,8 +211,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap> <defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
</imageStyle> </imageStyle>
@ -223,8 +223,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap> <defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
</imageStyle> </imageStyle>
@ -235,8 +235,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap> <defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
</imageStyle> </imageStyle>
@ -248,8 +248,8 @@
<imageStyle> <imageStyle>
<displayUnits>C</displayUnits> <displayUnits>C</displayUnits>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap> <defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap>
<colorbarLabeling> <colorbarLabeling>
@ -264,8 +264,8 @@
<imageStyle> <imageStyle>
<displayUnits>C</displayUnits> <displayUnits>C</displayUnits>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap> <defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap>
<colorbarLabeling> <colorbarLabeling>
@ -436,7 +436,7 @@
<imageStyle> <imageStyle>
<displayUnits>mm</displayUnits> <displayUnits>mm</displayUnits>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>0</minValue> <minValue>-176</minValue>
<maxValue>76</maxValue> <maxValue>76</maxValue>
</range> </range>
<defaultColormap>Sat/Precip Water/Blended Total Precip Water</defaultColormap> <defaultColormap>Sat/Precip Water/Blended Total Precip Water</defaultColormap>
@ -492,8 +492,8 @@
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<range scale="LINEAR"> <range scale="LINEAR">
<minValue>1</minValue> <minValue>0</minValue>
<maxValue>254</maxValue> <maxValue>255</maxValue>
</range> </range>
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap> <defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
</imageStyle> </imageStyle>
@ -530,5 +530,4 @@
</colorbarLabeling> </colorbarLabeling>
</imageStyle> </imageStyle>
</styleRule> </styleRule>
</styleRuleset> </styleRuleset>

View file

@ -28,6 +28,8 @@ import javax.measure.unit.Unit;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences;
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences.DataMappingEntry;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
@ -42,7 +44,6 @@ import com.raytheon.uf.common.style.level.RangeLevel;
import com.raytheon.uf.common.style.level.SingleLevel; import com.raytheon.uf.common.style.level.SingleLevel;
import com.raytheon.uf.common.util.GridUtil; import com.raytheon.uf.common.util.GridUtil;
/** /**
* ColorMapParameterFactory * ColorMapParameterFactory
* *
@ -57,6 +58,7 @@ import com.raytheon.uf.common.util.GridUtil;
* Feb 15, 2013 1638 mschenke Moved GRID_FILL_VALUE from edex.common Util into GridUtil * Feb 15, 2013 1638 mschenke Moved GRID_FILL_VALUE from edex.common Util into GridUtil
* Jun 24, 2013 2122 mschenke Added method for constructing {@link ColorMapParameters} from {@link StyleRule} * Jun 24, 2013 2122 mschenke Added method for constructing {@link ColorMapParameters} from {@link StyleRule}
* Sep 24, 2013 2404 bclement moved to common.style from viz.core, added build method that takes ParamLevelMatchCriteria, removed unused methods * Sep 24, 2013 2404 bclement moved to common.style from viz.core, added build method that takes ParamLevelMatchCriteria, removed unused methods
* Nov 13, 2013 2492 mschenke Create build that does not take data for adaptive building
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -129,7 +131,17 @@ public class ColorMapParameterFactory {
} }
// If a record to convert units exists, use it // If a record to convert units exists, use it
params.setDataUnit(parameterUnits); Unit<?> colorMapUnit = null;
try {
colorMapUnit = preferences.getColorMapUnitsObject();
} catch (StyleException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
}
if (colorMapUnit == null) {
params.setColorMapUnit(parameterUnits);
} else {
params.setColorMapUnit(colorMapUnit);
}
params.setDisplayUnit(preferences.getDisplayUnits()); params.setDisplayUnit(preferences.getDisplayUnits());
params.setDataMapping(preferences.getDataMapping()); params.setDataMapping(preferences.getDataMapping());
@ -237,9 +249,10 @@ public class ColorMapParameterFactory {
.convert(colormapMax) : colormapMax; .convert(colormapMax) : colormapMax;
if (preferences.getColorbarLabeling() != null) { if (preferences.getColorbarLabeling() != null) {
extractLabelValues(sr, displayMax, displayMin, params); extractLabelValues(preferences, displayMax, displayMin, params);
} else if (preferences.getDataMapping() == null) { } else if (preferences.getDataMapping() == null) {
calculateLabelValues(sr, displayMax, displayMin, params); calculateLabelValues(preferences, displayMax, displayMin,
params);
if (scale != null) { if (scale != null) {
params.setMirror(scale.isMirror()); params.setMirror(scale.isMirror());
} }
@ -325,8 +338,8 @@ public class ColorMapParameterFactory {
params.setColorMapMin((float) dataMin); params.setColorMapMin((float) dataMin);
params.setDataMin((float) dataMin); params.setDataMin((float) dataMin);
extractLabelValues(sr, (float) displayMax, (float) displayMin, extractLabelValues(preferences, (float) displayMax,
params); (float) displayMin, params);
params.setColorMapName(preferences.getDefaultColormap()); params.setColorMapName(preferences.getDefaultColormap());
} }
if (preferences.getDataScale() != null) { if (preferences.getDataScale() != null) {
@ -338,6 +351,154 @@ public class ColorMapParameterFactory {
} }
/**
* Does the same thing as {@link #build(ImagePreferences, Unit)} but first
* unpacks the ImagePreference from a {@link StyleRule}.
*
* @param sr
* @param defaultColorMapUnit
* @return
* @throws StyleException
*/
public static ColorMapParameters build(StyleRule sr,
Unit<?> defaultColorMapUnit) throws StyleException {
if (sr == null) {
throw new IllegalArgumentException(
"StyleRule must not be null when building ColorMapParameters");
}
if (sr.getPreferences() instanceof ImagePreferences == false) {
throw new IllegalArgumentException(
"ImagePreferences are only supported for building ColorMapParameters");
}
return build((ImagePreferences) sr.getPreferences(),
defaultColorMapUnit);
}
/**
* Builds a {@link ColorMapParameters} given {@link ImagePreferences} and a
* unit to colormap in. This method provides for the simplest color mapping
* case. No data or level information is input so the
* {@link ImagePreferences} must specify an exact range or data mapping and
* also no lableing is added unless the colorbar labeling is specifically
* set in the style rule.
*
* @param preferences
* @param defaultColorMapUnit
* @return
* @throws StyleException
*/
public static ColorMapParameters build(ImagePreferences preferences,
Unit<?> defaultColorMapUnit) throws StyleException {
ColorMapParameters params = new ColorMapParameters();
Unit<?> colorMapUnit = preferences.getColorMapUnitsObject();
if (colorMapUnit == null) {
colorMapUnit = defaultColorMapUnit;
}
Unit<?> displayUnit = preferences.getDisplayUnits();
if (displayUnit == null) {
displayUnit = colorMapUnit;
} else if (colorMapUnit == null) {
colorMapUnit = displayUnit;
}
params.setColorMapUnit(colorMapUnit);
params.setDisplayUnit(displayUnit);
params.setDataMapping(preferences.getDataMapping());
params.setColorMapName(preferences.getDefaultColormap());
Float displayMin = null, displayMax = null;
DataScale scale = preferences.getDataScale();
boolean mirrored = false;
Type scaleType = Type.LINEAR;
if (scale != null) {
if (scale.getMinValue() != null) {
displayMin = scale.getMinValue().floatValue();
}
if (scale.getMaxValue() != null) {
displayMax = scale.getMaxValue().floatValue();
}
mirrored = scale.isMirror();
scaleType = scale.getScaleType();
}
if (displayMin == null || displayMax == null) {
// Could not find min/max in DataScale, attempt to get from
// DataMappingPreferences if set
if (params.getDataMapping() != null) {
DataMappingPreferences mapping = params.getDataMapping();
List<DataMappingEntry> entries = mapping.getEntries();
if (entries != null && entries.isEmpty() == false) {
if (displayMin == null) {
DataMappingEntry min = entries.get(0);
if (min.getPixelValue() != null
&& min.getDisplayValue() != null) {
displayMin = min.getDisplayValue().floatValue();
}
}
if (displayMax == null) {
DataMappingEntry max = entries.get(entries.size() - 1);
if (max.getPixelValue() != null
&& max.getDisplayValue() != null) {
displayMax = max.getDisplayValue().floatValue();
}
}
}
} else if (mirrored && (displayMin != null || displayMax != null)) {
// Mirror value set
if (displayMin == null) {
displayMin = -displayMax;
} else {
displayMax = -displayMin;
}
}
}
if (displayMin == null || displayMax == null) {
throw new StyleException("Unable to determine colormap min/max.");
}
params.setMirror(mirrored);
params.setLogarithmic(scaleType == Type.LOG);
// Convert to colormap min/max
float colorMapMin = displayMin;
float colorMapMax = displayMax;
UnitConverter displayToColorMap = params
.getDisplayToColorMapConverter();
if (displayToColorMap != null) {
colorMapMin = (float) displayToColorMap.convert(displayMin);
colorMapMax = (float) displayToColorMap.convert(displayMax);
}
params.setColorMapMin(colorMapMin);
params.setColorMapMax(colorMapMax);
LabelingPreferences labeling = preferences.getColorbarLabeling();
if (labeling != null) {
if (labeling.getValues() != null) {
params.setColorBarIntervals(labeling.getValues());
} else if (labeling.getIncrement() != 0) {
float increment = labeling.getIncrement();
float initialPoint = (float) (Math
.ceil(colorMapMin / increment) * increment);
float finalPoint = (float) (Math.floor(colorMapMin / increment) * increment);
int count = (int) ((finalPoint - initialPoint) / increment) + 1;
float[] vals = new float[count];
for (int i = 0; i < count; i += 1) {
vals[i] = initialPoint + increment * i;
}
}
}
return params;
}
private static Number[] repackData(Object data) { private static Number[] repackData(Object data) {
Number[] numArray = null; Number[] numArray = null;
if (data instanceof byte[]) { if (data instanceof byte[]) {
@ -375,15 +536,11 @@ public class ColorMapParameterFactory {
return build(data, parameter, parameterUnits, level, null); return build(data, parameter, parameterUnits, level, null);
} }
private static void extractLabelValues(StyleRule sr, float max, float min, private static void extractLabelValues(ImagePreferences preferences,
ColorMapParameters parameters) { float max, float min, ColorMapParameters parameters) {
if (sr != null) {
ImagePreferences preferences = (ImagePreferences) sr
.getPreferences();
if (preferences.getColorbarLabeling() != null) { if (preferences.getColorbarLabeling() != null) {
DataScale dataScale = preferences.getDataScale(); DataScale dataScale = preferences.getDataScale();
if (dataScale != null if (dataScale != null && dataScale.isMirror()
&& dataScale.isMirror()
&& !dataScale.isAdaptive() && !dataScale.isAdaptive()
&& preferences.getColorbarLabeling().getValues() != null) { && preferences.getColorbarLabeling().getValues() != null) {
// if its mirror and not adaptive and the upper half labels // if its mirror and not adaptive and the upper half labels
@ -392,20 +549,18 @@ public class ColorMapParameterFactory {
parameters.setMirror(dataScale.isMirror()); parameters.setMirror(dataScale.isMirror());
} else if (preferences.getColorbarLabeling().getValues() != null) { } else if (preferences.getColorbarLabeling().getValues() != null) {
// If a list is provided, use it // If a list is provided, use it
float[] vals = preferences.getColorbarLabeling() float[] vals = preferences.getColorbarLabeling().getValues();
.getValues();
parameters.setColorBarIntervals(vals); parameters.setColorBarIntervals(vals);
} else { } else {
// Populate the list using min and max // Populate the list using min and max
calculateLabelValues(sr, max, min, parameters); calculateLabelValues(preferences, max, min, parameters);
if (dataScale != null) { if (dataScale != null) {
parameters.setMirror(dataScale.isMirror()); parameters.setMirror(dataScale.isMirror());
} }
} }
} }
} }
}
/** /**
* Copy positive values to negative side. * Copy positive values to negative side.
@ -432,17 +587,13 @@ public class ColorMapParameterFactory {
/** /**
* Derived from ImageDepictable.C::adaptGridImageStyle * Derived from ImageDepictable.C::adaptGridImageStyle
*/ */
private static void calculateLabelValues(StyleRule sr, float max, private static void calculateLabelValues(ImagePreferences preferences,
float min, ColorMapParameters parameters) { float max, float min, ColorMapParameters parameters) {
boolean haveIncrement = false; boolean haveIncrement = false;
float increment = 0.1f; float increment = 0.1f;
Type dataScaleType = Type.LINEAR; Type dataScaleType = Type.LINEAR;
boolean isMirror = false; boolean isMirror = false;
if (sr != null) {
ImagePreferences preferences = (ImagePreferences) sr
.getPreferences();
if (preferences != null) {
LabelingPreferences prefs = preferences.getColorbarLabeling(); LabelingPreferences prefs = preferences.getColorbarLabeling();
if (prefs != null) { if (prefs != null) {
increment = prefs.getIncrement(); increment = prefs.getIncrement();
@ -454,8 +605,6 @@ public class ColorMapParameterFactory {
dataScaleType = dataScale.getScaleType(); dataScaleType = dataScale.getScaleType();
isMirror = dataScale.isMirror(); isMirror = dataScale.isMirror();
} }
}
}
if (Math.abs(max - min) / increment > 16) { if (Math.abs(max - min) / increment > 16) {
increment *= 2; increment *= 2;
} }

View file

@ -20,6 +20,11 @@
package com.raytheon.uf.common.style.image; package com.raytheon.uf.common.style.image;
import java.text.ParseException;
import java.text.ParsePosition;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
@ -28,6 +33,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences; import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences;
import com.raytheon.uf.common.style.AbstractStylePreferences; import com.raytheon.uf.common.style.AbstractStylePreferences;
import com.raytheon.uf.common.style.LabelingPreferences; import com.raytheon.uf.common.style.LabelingPreferences;
import com.raytheon.uf.common.style.StyleException;
/** /**
* *
@ -40,6 +46,7 @@ import com.raytheon.uf.common.style.LabelingPreferences;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 27, 2007 chammack Initial Creation. * Jul 27, 2007 chammack Initial Creation.
* Nov 25, 2013 2492 bsteffen Add colorMapUnits
* *
* </pre> * </pre>
* *
@ -62,15 +69,18 @@ public class ImagePreferences extends AbstractStylePreferences {
@XmlElement @XmlElement
private SamplePreferences samplePrefs; private SamplePreferences samplePrefs;
@XmlElement(name = "dataMapping") @XmlElement
private DataMappingPreferences dataMapping; private DataMappingPreferences dataMapping;
@XmlElement(name = "colorbarLabeling") @XmlElement
private LabelingPreferences colorbarLabeling; private LabelingPreferences colorbarLabeling;
@XmlElement(name = "interpolate") @XmlElement
private boolean interpolate = true; private boolean interpolate = true;
@XmlElement
private String colorMapUnits;
public boolean isInterpolate() { public boolean isInterpolate() {
return interpolate; return interpolate;
} }
@ -154,4 +164,37 @@ public class ImagePreferences extends AbstractStylePreferences {
return legend; return legend;
} }
/**
*
* @return String representation of colorMapUnits for serialization.
* @see ImagePreferences#getColorMapUnitsObject()
*/
public String getColorMapUnits() {
return colorMapUnits;
}
/**
* @param colorMapUnits
* String representation of colorMapUnits for serialization.
* @see ImagePreferences#getColorMapUnitsObject()
*/
public void setColorMapUnits(String colorMapUnits) {
this.colorMapUnits = colorMapUnits;
}
/**
* Units that should be used when color mapping. Mostly useful for cases
* where the colormap should be applied non linearly.
*/
public Unit<?> getColorMapUnitsObject() throws StyleException {
if (colorMapUnits != null && !colorMapUnits.isEmpty()) {
try {
return UnitFormat.getUCUMInstance().parseProductUnit(
colorMapUnits, new ParsePosition(0));
} catch (ParseException e) {
throw new StyleException("Unable to parse colorMap Units.");
}
}
return null;
}
} }