Issue #2788 Fix topo for large areas.

Change-Id: Idb4a19ffea527ad40efb5e586913aab9d37602df

Former-commit-id: fcf45916f4 [formerly 882576fcf6f41b9a41ea8f4a31a40c8c31d51aad]
Former-commit-id: 2f067699f2
This commit is contained in:
Ron Anderson 2014-02-11 17:38:22 -06:00
parent 361881dfda
commit 2d7c87ac84
16 changed files with 433 additions and 139 deletions

View file

@ -36,6 +36,8 @@ import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters.PersistedParameters;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.style.LabelingPreferences;
import com.raytheon.uf.common.style.ParamLevelMatchCriteria;
@ -91,6 +93,8 @@ public class TopoResource extends
protected TileSetRenderable topoTileSet;
private double noDataValue;
protected TopoResource(TopoResourceData topoData,
LoadProperties loadProperties, File dataFile) throws VizException {
super(topoData, loadProperties);
@ -189,12 +193,13 @@ public class TopoResource extends
}
SamplePreferences samplePrefs = prefs.getSamplePrefs();
if (samplePrefs != null && samplePrefs.getFormatString() != null) {
if ((samplePrefs != null)
&& (samplePrefs.getFormatString() != null)) {
params.setFormatString(samplePrefs.getFormatString());
}
LabelingPreferences labelPrefs = prefs.getColorbarLabeling();
if (labelPrefs != null && labelPrefs.getValues() != null) {
if ((labelPrefs != null) && (labelPrefs.getValues() != null)) {
params.setColorBarIntervals(labelPrefs.getValues());
}
}
@ -213,6 +218,16 @@ public class TopoResource extends
getCapability(ColorMapCapability.class).setColorMapParameters(params);
IDataStore dataStore = DataStoreFactory.getDataStore(this.dataFile);
try {
IDataRecord rec = dataStore.retrieve("/", "full",
Request.buildPointRequest(new java.awt.Point(0, 0)));
noDataValue = rec.getFillValue().doubleValue();
} catch (Exception e) {
statusHandler.error(e.getLocalizedMessage(), e);
noDataValue = Double.NaN;
}
topoTileSet = new TileSetRenderable(
getCapability(ImagingCapability.class), getTopoGeometry(),
getTopoTileImageCreator(), getNumberOfTopoLevels(), 512);
@ -284,7 +299,7 @@ public class TopoResource extends
double height;
try {
// height = TopoQuery.getInstance().getHeight(coord.asLatLon());
height = topoTileSet.interrogate(coord.asLatLon());
height = topoTileSet.interrogate(coord.asLatLon(), noDataValue);
} catch (Exception e) {
throw new VizException("Error transforming", e);
}

View file

@ -59,6 +59,8 @@ import com.raytheon.viz.gfe.rsc.GFEResource;
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
* parameters, disable colormap interpolation
* by default.
* 02/11/2014 #2788 randerso Fixed infinite loop in computeIntervalAndPrecision
* when pmax < pmin
*
* </pre>
*
@ -186,10 +188,10 @@ public class ContinuousColorbar implements IColorBarDisplay {
dstring.font = colorbarResource.getColorbarScaleFont();
dstring.textStyle = TextStyle.NORMAL;
for (int i = 0; (minParm + i * interval) <= maxParm; i++) {
for (int i = 0; (minParm + (i * interval)) <= maxParm; i++) {
// check to see whether this colorTable item needs to be
// rendered
float labelValue = minParm + i * interval;
float labelValue = minParm + (i * interval);
// Check to see if value is same as previous unless float....
if ((tmpValue != (int) labelValue) || (precision > 0)) {
@ -197,7 +199,7 @@ public class ContinuousColorbar implements IColorBarDisplay {
labelValue, precision);
labelLoc = llx
+ ((labelValue - minParm) / (maxParm - minParm) * xExtent);
+ (((labelValue - minParm) / (maxParm - minParm)) * xExtent);
if (GFEColorbarResource.isLabelWithin(pe.getMinX(),
pe.getMaxX(), labelLoc, 0)) {
@ -219,10 +221,10 @@ public class ContinuousColorbar implements IColorBarDisplay {
labelValue = labelValueObj.floatValue();
if (precision == 0) {
labelLoc = llx
+ ((labelValue - minParm) / (maxParm - minParm) * xExtent);
+ (((labelValue - minParm) / (maxParm - minParm)) * xExtent);
} else {
labelLoc = llx
+ ((labelValue - minParm) / (maxParm - minParm) * xExtent);
+ (((labelValue - minParm) / (maxParm - minParm)) * xExtent);
}
if (GFEColorbarResource.isLabelWithin(pe.getMinX(),
pe.getMaxX(), labelLoc, 0)) {
@ -246,7 +248,7 @@ public class ContinuousColorbar implements IColorBarDisplay {
float floatValue = ((ScalarWxValue) wxv).getValue();
if ((floatValue >= minParm) && (floatValue <= maxParm)) {
labelLoc = llx
+ ((floatValue - minParm) / (maxParm - minParm) * xExtent);
+ (((floatValue - minParm) / (maxParm - minParm)) * xExtent);
String s = wxv.toString();
dstring.font = colorbarResource.getPickupValueFont();
@ -261,12 +263,11 @@ public class ContinuousColorbar implements IColorBarDisplay {
dstring.shadowColor = new RGB(0, 0, 0);
}
double halfWidth = target.getStringsBounds(dstring).getWidth()
* ratio / 2;
double halfWidth = (target.getStringsBounds(dstring).getWidth() * ratio) / 2;
if (labelLoc - halfWidth < pe.getMinX()) {
if ((labelLoc - halfWidth) < pe.getMinX()) {
labelLoc = pe.getMinX() + halfWidth;
} else if (labelLoc + halfWidth > pe.getMaxX()) {
} else if ((labelLoc + halfWidth) > pe.getMaxX()) {
labelLoc = pe.getMaxX() - halfWidth;
}
dstring.setCoordinates(labelLoc,
@ -298,7 +299,8 @@ public class ContinuousColorbar implements IColorBarDisplay {
// initial values are good if decade < parmExtent
// loop is infinite if parmExtent is NaN or 0, so avoid it
if (decade < parmExtent || Float.isNaN(parmExtent) || parmExtent == 0.0) {
if (Float.isNaN(parmExtent) || (parmExtent <= 0.0)
|| (decade < parmExtent)) {
return new float[] { finterval, precision, labelLength };
}
@ -438,7 +440,7 @@ public class ContinuousColorbar implements IColorBarDisplay {
switch (parm.getGridInfo().getGridType()) {
case SCALAR:
return new ScalarWxValue(min + (max - min) * fractionX, parm);
return new ScalarWxValue(min + ((max - min) * fractionX), parm);
case VECTOR:
WxValue previous = parm.getParmState().getPickUpValue();
float mag = 0.0f;
@ -448,7 +450,7 @@ public class ContinuousColorbar implements IColorBarDisplay {
dir = ((VectorWxValue) previous).getDir();
}
if (mouseButton == 1) {
mag = min + (max - min) * fractionX;
mag = min + ((max - min) * fractionX);
} else if (mouseButton == 2) {
dir = 360 * fractionX;
}

View file

@ -74,6 +74,7 @@ import com.raytheon.uf.common.topo.TopoQuery;
* Jun 13, 2013 #2044 randerso Refactored to use non-singleton GridParmManager,
* code cleanup
* Nov 20, 2013 #2331 randerso Changed return type of getTopoData
* Feb 11, 2014 #2788 randerso Set missing data points to 0 to match A1
*
* </pre>
*
@ -236,6 +237,8 @@ public class TopoDatabaseManager {
if (!allowValuesBelowZero && (heights[i] < 0)) {
heights[i] = 0.0f;
}
} else {
heights[i] = 0.0f;
}
}

View file

@ -88,6 +88,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Feb 15, 2013 1638 mschenke Moved from edex.topo project (not edex
* specific)
* Aug 06, 2013 2235 bsteffen Added Caching version of TopoQuery.
* Feb 10, 2014 2788 randerso Removed override of CRS from Topo file.
* Fixed handling of fill values (missing data)
*
* </pre>
*
@ -198,10 +200,6 @@ public class TopoQuery {
CoordinateReferenceSystem crs = CRSCache.getInstance()
.getCoordinateReferenceSystem(crsString);
crs = MapUtil.constructEquidistantCylindrical(
MapUtil.AWIPS_EARTH_RADIUS, MapUtil.AWIPS_EARTH_RADIUS, 0,
0);
double[] input = new double[] { ulLon, ulLat, lrLon, lrLat };
double[] output = new double[4];
@ -288,6 +286,7 @@ public class TopoQuery {
public double[] getHeight(Coordinate[] coords) {
final int size = coords.length;
double[] topo = new double[size];
Arrays.fill(topo, Double.NaN);
double[] input = new double[size * 2];
double[] output = new double[input.length];
@ -310,15 +309,18 @@ public class TopoQuery {
Request request = Request.buildPointRequest(points);
ShortDataRecord record = (ShortDataRecord) dataStore.retrieve("/",
"full", request);
short fillValue = record.getFillValue().shortValue();
short[] data = record.getShortData();
// bounds checking?
for (int i = 0; i < size; i++) {
topo[i] = data[i];
short value = data[i];
if (value != fillValue) {
topo[i] = value;
}
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error retriving topo value for lat/lons", e);
Arrays.fill(topo, Double.NaN);
}
return topo;
@ -367,8 +369,9 @@ public class TopoQuery {
if (first) {
first = false;
} else if (Math.abs(p1.getOrdinate(0) - prev) > 180.0
|| (Math.abs(p1.getOrdinate(0)) > 180 && Math.abs(prev) < 180)) {
} else if ((Math.abs(p1.getOrdinate(0) - prev) > 180.0)
|| ((Math.abs(p1.getOrdinate(0)) > 180) && (Math
.abs(prev) < 180))) {
crossedDLHoriz = true;
}
prev = p1.getOrdinate(0);
@ -424,8 +427,9 @@ public class TopoQuery {
if (first) {
first = false;
} else if (Math.abs(p1.getOrdinate(0) - prev) > 180.0
|| (Math.abs(p1.getOrdinate(0)) > 180 && Math.abs(prev) < 180)) {
} else if ((Math.abs(p1.getOrdinate(0) - prev) > 180.0)
|| ((Math.abs(p1.getOrdinate(0)) > 180) && (Math
.abs(prev) < 180))) {
crossedDLVert = true;
}
prev = p1.getOrdinate(0);
@ -541,7 +545,7 @@ public class TopoQuery {
worldRect.getMaxY() };
double[] crsCorners = new double[worldCorners.length];
GeneralEnvelope env = new GeneralEnvelope(2);
if (worldCorners[2] > worldGeomPM.getGridRange().getHigh(0) + 1) {
if (worldCorners[2] > (worldGeomPM.getGridRange().getHigh(0) + 1)) {
worldGeomDL.getGridToCRS(PixelInCell.CELL_CORNER)
.transform(worldCorners, 0, crsCorners, 0,
worldCorners.length / 2);
@ -643,7 +647,7 @@ public class TopoQuery {
}
// if grid is too big to load into memory
if (width * height > TOPO_LIMIT) {
if ((width * height) > TOPO_LIMIT) {
// try the next interpolation level if it exists
int level = topoLevel + 1;
if (level < numLevels) {
@ -675,15 +679,18 @@ public class TopoQuery {
y + intersection.height });
rec = (ShortDataRecord) dataStore.retrieve("", dataset,
request);
short fillValue = rec.getFillValue().shortValue();
int xOffset = intersection.x - worldRect.x + rectOffset;
int xOffset = (intersection.x - worldRect.x) + rectOffset;
int yOffset = intersection.y - worldRect.y;
int recOffset = 0;
for (int j = 0; j < intersection.height; j++) {
for (int i = 0; i < intersection.width; i++) {
topoValues[j + yOffset][i + xOffset] = rec
.getShortData()[i + recOffset];
short value = rec.getShortData()[i + recOffset];
if (value != fillValue) {
topoValues[j + yOffset][i + xOffset] = value;
}
}
recOffset += intersection.width;
// someData = true;
@ -697,10 +704,6 @@ public class TopoQuery {
rectOffset += worldRect.width;
}
// if (!someData) {
// throw new EdexException("No topo data available");
// }
Envelope env = computeEnv(new Rectangle(rectangles[0].x,
rectangles[0].y, width, height));
@ -789,8 +792,10 @@ public class TopoQuery {
int sx = (int) Math.round(coord[0]);
int sy = (int) Math.round(coord[1]);
if (sx >= 0 && sx < sourceWidth && sy >= 0 && sy < sourceHeight)
output[y * targetWidth + x] = sourceData[sy][sx];
if ((sx >= 0) && (sx < sourceWidth) && (sy >= 0)
&& (sy < sourceHeight)) {
output[(y * targetWidth) + x] = sourceData[sy][sx];
}
}
}
@ -812,9 +817,9 @@ public class TopoQuery {
MathTransform mt = null;
for (MathTransform mti : transforms) {
if (mt == null)
if (mt == null) {
mt = mti;
else {
} else {
mt = mtFactory.createConcatenatedTransform(mt, mti);
}
}

View file

@ -50,7 +50,8 @@ import com.raytheon.uf.common.geospatial.CRSCache;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 2, 2013 bsteffen Initial creation
* Aug 2, 2013 bsteffen Initial creation
* Feb 10, 2014 #2788 randerso Changed default topo file name
*
* </pre>
*
@ -60,7 +61,9 @@ import com.raytheon.uf.common.geospatial.CRSCache;
public class TopoUtils {
private static final String DEFAULT_TOPO_PATH = "/topo/srtm30.hdf";
// NOTE: this file is actually a symbolic link to the desired topo data file
// allowing the topo data set to be changed without updating Java code
private static final String DEFAULT_TOPO_PATH = "/topo/defaultTopo.h5";
private static final String FULL_TOPO_DATASET = "/full";

View file

@ -21,7 +21,7 @@
<styleRuleset>
<styleRule>
<paramLevelMatches>
<parameter>srtm30.hdf</parameter>
<parameter>defaultTopo.h5</parameter>
</paramLevelMatches>
<imageStyle>
<displayUnits>kft</displayUnits>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.topo.utilities</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View file

@ -0,0 +1,11 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Utilities
Bundle-SymbolicName: com.raytheon.uf.topo.utilities
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.pypies;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174"

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
logback.xml

View file

@ -0,0 +1,68 @@
<configuration debug="false" scan="false">
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5p %d [%t] %c{0}: %m%n</pattern>
</encoder>
<filter class="com.raytheon.uf.common.status.logback.InvertedThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<appender name="errConsole" class="ch.qos.logback.core.ConsoleAppender">
<target>System.err</target>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<encoder>
<pattern>%-5p %d [%t] %c{0}: %m%n</pattern>
</encoder>
</appender>
<logger name="CaveLogger">
<level value="ALL"/>
</logger>
<logger name="PerformanceLogger">
<level value="ALL"/>
</logger>
<logger name="com.raytheon">
<level value="INFO"/>
</logger>
<logger name="com.tc">
<level value="WARN"/>
</logger>
<logger name="mx4j">
<level value="ERROR"/>
</logger>
<logger name="org.apache">
<level value="INFO"/>
</logger>
<logger name="org.apache.activemq.spring">
<level value="WARN"/>
</logger>
<logger name="org.apache.commons.beanutils">
<level value="WARN"/>
</logger>
<logger name="org.apache.qpid">
<level value="WARN"/>
</logger>
<logger name="org.geotools">
<level value="WARN"/>
</logger>
<logger name="org.apache.xbean.spring">
<level value="WARN"/>
</logger>
<logger name="org.springframework">
<level value="ERROR"/>
</logger>
<logger name="uk.ltd.getahead">
<level value="WARN"/>
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="console"/>
<appender-ref ref="errConsole"/>
</root>
</configuration>

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.topo.util;
package com.raytheon.uf.topo.utilities;
import java.io.BufferedReader;
import java.io.DataInputStream;
@ -34,7 +34,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import org.opengis.referencing.crs.ProjectedCRS;
import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.StorageProperties;
import com.raytheon.uf.common.datastorage.StorageProperties.Compression;
@ -44,6 +45,8 @@ import com.raytheon.uf.common.datastorage.records.IntegerDataRecord;
import com.raytheon.uf.common.datastorage.records.LongDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.pypies.PyPiesDataStore;
import com.raytheon.uf.common.pypies.PypiesProperties;
/**
* Import topo data into HDF5
@ -53,7 +56,8 @@ import com.raytheon.uf.common.geospatial.MapUtil;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 22, 2009 #3280 randerso Initial creation
* Oct 22, 2009 #3280 randerso Initial creation
* Feb 11, 2014 #2788 randerso Changed to use PyPiesDataStore
*
* </pre>
*
@ -68,22 +72,14 @@ public class TopoImporter {
String byteOrder;
String layout;
int nRows;
int nCols;
int nBands;
int nBits;
int bandRowBytes;
int totalRowBytes;
int bandGapBytes;
long noData;
double ulXmap;
@ -95,6 +91,18 @@ public class TopoImporter {
double yDim;
public TopoHdr(File file) {
if (file.getName().endsWith(".HDR")) {
readHdrFile(file);
} else if (file.getName().endsWith(".ers")) {
readErsFile(file);
} else {
throw new IllegalArgumentException(
"Unrecognized header file format: "
+ file.getAbsolutePath());
}
}
private void readHdrFile(File file) {
BufferedReader in = null;
try {
this.file = file;
@ -105,22 +113,14 @@ public class TopoImporter {
if ("BYTEORDER".equals(s[0])) {
byteOrder = s[1];
} else if ("LAYOUT".equals(s[0])) {
layout = s[1];
} else if ("NROWS".equals(s[0])) {
nRows = Integer.parseInt(s[1]);
} else if ("NCOLS".equals(s[0])) {
nCols = Integer.parseInt(s[1]);
} else if ("NBANDS".equals(s[0])) {
nBands = Integer.parseInt(s[1]);
} else if ("NBITS".equals(s[0])) {
nBits = Integer.parseInt(s[1]);
} else if ("BANDROWBYTES".equals(s[0])) {
bandRowBytes = Integer.parseInt(s[1]);
} else if ("TOTALROWBYTES".equals(s[0])) {
totalRowBytes = Integer.parseInt(s[1]);
} else if ("BANDGAPBYTES".equals(s[0])) {
bandGapBytes = Integer.parseInt(s[1]);
} else if ("NODATA".equals(s[0])) {
noData = Long.parseLong(s[1]);
} else if ("ULXMAP".equals(s[0])) {
@ -149,6 +149,91 @@ public class TopoImporter {
}
}
private void readErsFile(File file) {
BufferedReader in = null;
try {
this.file = file;
in = new BufferedReader(new FileReader(file));
String line;
while ((line = in.readLine()) != null) {
line = line.replace(" = ", " ");
String[] s = line.split("\\s+");
if ("ByteOrder".equals(s[0])) {
byteOrder = s[1];
} else if ("NrOfLines".equals(s[0])) {
nRows = Integer.parseInt(s[1]);
} else if ("NrOfCellsPerLine".equals(s[0])) {
nCols = Integer.parseInt(s[1]);
} else if ("CellType".equals(s[0])) {
if (s[1].equals("Signed16BitInteger")) {
nBits = 16;
} else if (s[1].equals("Signed32BitInteger")) {
nBits = 32;
} else if (s[1].equals("Signed64BitInteger")) {
nBits = 64;
} else {
throw new IllegalArgumentException(
"Unrecognized data type: " + s[1]);
}
} else if ("NullCellValue".equals(s[0])) {
noData = Long.parseLong(s[1]);
} else if ("Longitude".equals(s[0])) {
ulXmap = parseDMS(s[1]);
} else if ("Latitude".equals(s[0])) {
ulYmap = parseDMS(s[1]);
} else if ("Xdimension".equals(s[0])) {
xDim = Double.parseDouble(s[1]);
} else if ("Ydimension".equals(s[0])) {
yDim = Double.parseDouble(s[1]);
} else {
// TODO: fully recognize the ers header file
System.out.println("Unrecognized line in file "
+ file.getAbsolutePath() + "\n" + line);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// convert upper left coordinate from corner to
// center of cell
ulXmap += xDim / 2;
ulYmap -= yDim / 2;
totalRowBytes = (nCols * nBits) / 8;
}
}
}
private double parseDMS(String dms) {
// parse a string in degrees:minutes:seconds format into decimal
// degrees
double degrees = Double.NaN;
String[] s = dms.split(":");
if (s.length == 3) {
try {
int deg = Integer.parseInt(s[0]);
int min = Integer.parseInt(s[1]);
double sec = Double.parseDouble(s[2]);
degrees = deg + (min - ((sec / 60.0) / 60.0));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Unable to parse DMS: "
+ dms, e);
}
} else {
throw new IllegalArgumentException("Unable to parse DMS: "
+ dms);
}
return degrees;
}
/*
* (non-Javadoc)
*
@ -176,7 +261,7 @@ public class TopoImporter {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".HDR");
return name.endsWith(".HDR") || name.endsWith(".ers");
}
};
@ -195,6 +280,11 @@ public class TopoImporter {
hdrList.add(new TopoHdr(file));
}
if (hdrList.isEmpty()) {
throw new IllegalArgumentException(
"No recognized header files found");
}
// sort the hdr files by descending lat/ascending lon
Collections.sort(hdrList);
@ -202,12 +292,14 @@ public class TopoImporter {
// determine the total dataset dimensions
double startLat = hdrList.get(0).ulYmap;
double startLon = hdrList.get(0).ulXmap;
double xDim = hdrList.get(0).xDim;
double yDim = hdrList.get(0).yDim;
int last = hdrList.size() - 1;
double endLat = hdrList.get(last).ulYmap
- (hdrList.get(last).nRows - 1) * hdrList.get(last).yDim;
- ((hdrList.get(last).nRows - 1) * hdrList.get(last).yDim);
double endLon = hdrList.get(last).ulXmap
+ (hdrList.get(last).nCols - 1) * hdrList.get(last).xDim;
+ ((hdrList.get(last).nCols - 1) * hdrList.get(last).xDim);
int bits = hdrList.get(0).nBits;
double expectedLat = startLat;
@ -233,7 +325,7 @@ public class TopoImporter {
maxCols = Math.max(cols, maxCols);
expectedLat = hdr.ulYmap;
expectedLon = hdr.ulXmap + hdr.nCols * hdr.xDim;
expectedLon = hdr.ulXmap + (hdr.nCols * hdr.xDim);
if ((expectedLon - startLon) > (360.0 - TOL)) {
expectedLon = startLon;
expectedLat -= hdr.nRows * hdr.yDim;
@ -244,8 +336,8 @@ public class TopoImporter {
}
// create the hdf5 file
File hdf = new File(dir.getParent() + File.separatorChar
+ dir.getName().toLowerCase() + "_unpacked.hdf");
File hdf = new File("topo" + File.separatorChar
+ dir.getName().toLowerCase() + "_unpacked.h5");
if (hdf.exists()) {
System.out
.println(hdf.getAbsolutePath()
@ -253,7 +345,9 @@ public class TopoImporter {
System.exit(-1);
}
IDataStore store = DataStoreFactory.getDataStore(hdf);
PypiesProperties pypiesProps = new PypiesProperties();
pypiesProps.setAddress("http://localhost:9582");
IDataStore store = new PyPiesDataStore(hdf, true, pypiesProps);
String dataset = "full";
long[] sizes = new long[] { maxCols, maxRows };
@ -263,31 +357,47 @@ public class TopoImporter {
properties.setChunked(true);
IDataRecord record = null;
if (bits <= 8) {
record = new ByteDataRecord(dataset, "/", null, 2, sizes);
if (bits <= Byte.SIZE) {
record = new ByteDataRecord(dataset, null, null, 2, sizes);
record.setFillValue(Byte.MIN_VALUE);
} else if (bits <= 16) {
record = new ShortDataRecord(dataset, "/", null, 2, sizes);
} else if (bits <= Short.SIZE) {
record = new ShortDataRecord(dataset, null, null, 2, sizes);
record.setFillValue(Short.MIN_VALUE);
} else if (bits <= 32) {
record = new IntegerDataRecord(dataset, "/", null, 2, sizes);
} else if (bits <= Integer.SIZE) {
record = new IntegerDataRecord(dataset, null, null, 2, sizes);
record.setFillValue(Integer.MIN_VALUE);
} else if (bits <= 64) {
record = new LongDataRecord(dataset, "/", null, 2, sizes);
} else if (bits <= Long.SIZE) {
record = new LongDataRecord(dataset, null, null, 2, sizes);
record.setFillValue(Long.MIN_VALUE);
} else {
System.out.println("NBITS > 64");
System.exit(-1);
}
double centralMeridian = 0.0;
double latOfOrigin = 0.0;
double cm = (startLon + endLon) / 2;
centralMeridian = Math.round(cm);
ProjectedCRS crs = MapUtil.constructEquidistantCylindrical(
MapUtil.AWIPS_EARTH_RADIUS, MapUtil.AWIPS_EARTH_RADIUS,
centralMeridian, latOfOrigin);
Map<String, Object> attributes = new LinkedHashMap<String, Object>();
attributes.put("Width", maxCols);
attributes.put("Height", maxRows);
attributes.put("ulLat", startLat);
attributes.put("ulLon", startLon);
attributes.put("lrLat", endLat);
attributes.put("lrLon", endLon);
attributes.put("CRS", MapUtil.LATLON_PROJECTION.toWKT());
// Using arrays to work around serialization "feature" that returns
// floats when doubles are stored
// H5DataStore created these arrays automatically, Pypies does not
attributes.put("xDim", new double[] { xDim });
attributes.put("yDim", new double[] { yDim });
attributes.put("ulLat", new double[] { startLat });
attributes.put("ulLon", new double[] { startLon });
attributes.put("lrLat", new double[] { endLat });
attributes.put("lrLon", new double[] { endLon });
attributes.put("CRS", crs.toWKT());
record.setProperties(properties);
record.setDataAttributes(attributes);
@ -301,8 +411,14 @@ public class TopoImporter {
rows = 0;
cols = 0;
for (TopoHdr hdr : hdrList) {
File dem = new File(hdr.file.getAbsolutePath().replace(".HDR",
".DEM"));
String demPath = hdr.file.getAbsolutePath();
if (demPath.endsWith(".HDR")) {
demPath = demPath.replace(".HDR", ".DEM");
} else if (demPath.endsWith(".ers")) {
demPath = demPath.replace(".ers", "");
}
File dem = new File(demPath);
System.out.println(cols + ", " + rows + " " + dem.getName());
@ -311,76 +427,75 @@ public class TopoImporter {
in = new DataInputStream(new FileInputStream(dem));
ByteBuffer buffer = ByteBuffer.allocate(hdr.totalRowBytes);
if ("M".equals(hdr.byteOrder)) {
if (hdr.byteOrder.startsWith("M")) {
buffer.order(ByteOrder.BIG_ENDIAN);
} else {
buffer.order(ByteOrder.LITTLE_ENDIAN);
System.out.println("WARNING: unrecognize BYTEORDER \""
+ hdr.byteOrder + "\" assuming LITTLE_ENDIAN");
}
sizes[0] = hdr.nCols;
sizes[1] = 1;
record = null;
long writeSize = 0;
for (int i = 0; i < hdr.nRows; i++) {
in.read(buffer.array());
buffer.rewind();
if (bits <= 8) {
if (bits <= Byte.SIZE) {
byte[] byteData = new byte[hdr.nCols];
for (int j = 0; j < byteData.length; j++) {
byteData[j] = buffer.get();
// replace no data flag with 0
if (byteData[j] == (byte) hdr.noData) {
byteData[j] = 0;
byteData[j] = Byte.MIN_VALUE;
}
}
record = new ByteDataRecord(dataset, "/", null, 2,
record = new ByteDataRecord(dataset, null, null, 2,
sizes);
record.setMinIndex(new long[] { cols, rows + i });
record.setFillValue(Byte.MIN_VALUE);
((ByteDataRecord) record).setByteData(buffer.array());
} else if (bits <= 16) {
} else if (bits <= Short.SIZE) {
short[] shortData = new short[hdr.nCols];
for (int j = 0; j < shortData.length; j++) {
shortData[j] = buffer.getShort();
// replace no data flag with 0
if (shortData[j] == (short) hdr.noData) {
shortData[j] = 0;
shortData[j] = Short.MIN_VALUE;
}
}
record = new ShortDataRecord(dataset, "/", null, 2,
record = new ShortDataRecord(dataset, null, null, 2,
sizes);
record.setMinIndex(new long[] { cols, rows + i });
record.setFillValue(Short.MIN_VALUE);
((ShortDataRecord) record).setShortData(shortData);
} else if (bits <= 32) {
} else if (bits <= Integer.SIZE) {
int[] intData = new int[hdr.nCols];
for (int j = 0; j < intData.length; j++) {
intData[j] = buffer.getInt();
// replace no data flag with 0
if (intData[j] == (int) hdr.noData) {
intData[j] = 0;
intData[j] = Integer.MIN_VALUE;
}
}
record = new IntegerDataRecord(dataset, "/", null, 2,
record = new IntegerDataRecord(dataset, null, null, 2,
sizes);
record.setMinIndex(new long[] { cols, rows + i });
record.setFillValue(Integer.MIN_VALUE);
((IntegerDataRecord) record).setIntData(intData);
} else if (bits <= 64) {
} else if (bits <= Long.SIZE) {
long[] longData = new long[hdr.nCols];
for (int j = 0; j < longData.length; j++) {
longData[j] = buffer.getLong();
// replace no data flag with 0
if (longData[j] == hdr.noData) {
longData[j] = 0;
longData[j] = Long.MIN_VALUE;
}
}
record = new LongDataRecord(dataset, "/", null, 2,
record = new LongDataRecord(dataset, null, null, 2,
sizes);
record.setMinIndex(new long[] { cols, rows + i });
record.setFillValue(Long.MIN_VALUE);
@ -388,6 +503,11 @@ public class TopoImporter {
}
store.addDataRecord(record, properties);
writeSize += hdr.totalRowBytes;
if (writeSize > (64 * 1024 * 1024)) {
store.store();
writeSize = 0;
}
}
store.store();
} catch (Throwable e) {
@ -410,7 +530,7 @@ public class TopoImporter {
cols = 0;
}
}
System.out.println("took " + (System.currentTimeMillis() - t0) / 1000
System.out.println("took " + ((System.currentTimeMillis() - t0) / 1000)
+ " seconds");
}
}

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.topo.util;
package com.raytheon.uf.topo.utilities;
import java.awt.Point;
import java.awt.RenderingHints;
@ -40,7 +40,6 @@ import javax.media.jai.PlanarImage;
import javax.media.jai.RasterFactory;
import javax.media.jai.TiledImage;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.StorageProperties;
@ -50,9 +49,11 @@ import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.IntegerDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.pypies.PyPiesDataStore;
import com.raytheon.uf.common.pypies.PypiesProperties;
/**
* TODO Add Description
* Interpolator for topo data files
*
* <pre>
*
@ -62,6 +63,8 @@ import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
* Oct 26, 2009 randerso Initial creation
* Feb 12, 2013 #1608 randerso Remove exlicit references to HDF5DataStore
* Added explicit calls to deleteGroups
* Feb 11, 2014 #2788 randerso Changed to use PyPiesDataStore
* Fixed corner points for interpolated levels
*
* </pre>
*
@ -72,22 +75,17 @@ import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
public class TopoInterpolator {
private static final int BLOCK_SIZE = 2400;
private static final String DEFAULT_TOPO_FILE = "/topo/srtm30.hdf";
private IDataStore dataStore;
public TopoInterpolator() {
this(new File(DEFAULT_TOPO_FILE));
}
/**
* Create a TopoInterpolator instance for the specified hdf file
*
* @param file
*/
public TopoInterpolator(File hdf) {
dataStore = DataStoreFactory.getDataStore(hdf);
PypiesProperties pypiesProps = new PypiesProperties();
pypiesProps.setAddress("http://localhost:9582");
dataStore = new PyPiesDataStore(hdf, true, pypiesProps);
}
public void interpolate(String group, String dataSet) {
@ -97,8 +95,18 @@ public class TopoInterpolator {
try {
IDataRecord record = dataStore.retrieve(group, dataSet, request);
Map<String, Object> attributes = record.getDataAttributes();
int srcWidth = (Integer) attributes.get("Width");
int srcHeight = (Integer) attributes.get("Height");
int width = (Integer) attributes.get("Width");
int height = (Integer) attributes.get("Height");
// These attributes are stored as 1x1 arrays in the file to match
// what H5DataStore did
// Pypies automatically returns them as scalars
double xDim = (Double) attributes.get("xDim");
double yDim = (Double) attributes.get("yDim");
double startLat = (Double) attributes.get("ulLat");
double startLon = (Double) attributes.get("ulLon");
double endLat = (Double) attributes.get("lrLat");
double endLon = (Double) attributes.get("lrLon");
int level = 1;
String srcGroup = group;
@ -120,14 +128,33 @@ public class TopoInterpolator {
long t1 = t0;
while (level < 6) {
System.out.print("\nInterpolating " + srcGroup + srcDataSet
+ " (" + srcWidth + ", " + srcHeight + ")");
+ " (" + width + ", " + height + ")");
int srcWidth = width;
int srcHeight = height;
// compute attributes for new level
width /= 2;
height /= 2;
startLon += xDim / 2;
startLat -= yDim / 2;
endLon -= xDim / 2;
endLat += yDim / 2;
xDim *= 2;
yDim *= 2;
String dstDataSet = "" + level;
record.setName(dstDataSet);
record.setGroup(dstGroup);
record.setSizes(new long[] { srcWidth / 2, srcHeight / 2 });
record.setSizes(new long[] { width, height });
record.setProperties(properties);
attributes.put("Width", srcWidth / 2);
attributes.put("Height", srcHeight / 2);
attributes.put("Width", width);
attributes.put("Height", height);
attributes.put("xDim", new double[] { xDim });
attributes.put("yDim", new double[] { yDim });
attributes.put("ulLat", new double[] { startLat });
attributes.put("ulLon", new double[] { startLon });
attributes.put("lrLat", new double[] { endLat });
attributes.put("lrLon", new double[] { endLon });
record.setDataAttributes(attributes);
dataStore.createDataset(record);
@ -159,17 +186,15 @@ public class TopoInterpolator {
}
long t2 = System.currentTimeMillis();
System.out.print(" took " + (t2 - t1) / 1000 + " s");
System.out.print(" took " + ((t2 - t1) / 1000) + " s");
t1 = t2;
srcGroup = dstGroup;
srcDataSet = dstDataSet;
level++;
srcWidth /= 2;
srcHeight /= 2;
}
System.out.print("\nTotal " + (System.currentTimeMillis() - t0)
/ 1000 + " s");
System.out.print("\nTotal "
+ ((System.currentTimeMillis() - t0) / 1000) + " s");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -230,7 +255,7 @@ public class TopoInterpolator {
param.setParameter("xScale", 1.0f / scale);
param.setParameter("yScale", 1.0f / scale);
Interpolation interpol = Interpolation
.getInstance(Interpolation.INTERP_BICUBIC);
.getInstance(Interpolation.INTERP_NEAREST);
param.setParameter("interpolation", interpol);
RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
BorderExtender.createInstance(BorderExtender.BORDER_COPY));
@ -263,14 +288,14 @@ public class TopoInterpolator {
public static void main(String[] args) {
TopoInterpolator ti;
if (args.length < 1) {
ti = new TopoInterpolator();
System.out.println("usage: TopoInterpolator topofile");
} else {
ti = new TopoInterpolator(new File(args[0]));
}
String fileName = args[0];
System.out.println("Interpolating " + fileName);
ti = new TopoInterpolator(new File(fileName));
System.out.println("Interpolating "
+ (args.length < 1 ? DEFAULT_TOPO_FILE : args[0]));
ti.interpolate("/", "full");
ti.interpolate("/", "full");
}
}
}

View file

@ -78,7 +78,10 @@ fi
TOPO_TO_COPY=\
(\
'srtm30.hdf'\
'gtopo30.h5'\
'srtm30.h5'\
'srtm30_plus.h5'\
'defaultTopo.h5' \
'akTopo.dat.gz' \
'caribTopo.dat.gz' \
'modelStaticTopo.h5' \
@ -91,21 +94,13 @@ TOPO_TO_COPY=\
for topoFile in ${TOPO_TO_COPY[*]};
do
cp -r %{_awipscm_share}/${TOPO_SRC_DIR}/${topoFile} \
cp -Pp %{_awipscm_share}/${TOPO_SRC_DIR}/${topoFile} \
${RPM_BUILD_ROOT}/awips2/edex/data/hdf5/topo
if [ $? -ne 0 ]; then
exit 1
fi
done
# Copy our hlsTopo
mkdir -p ${RPM_BUILD_ROOT}/awips2/edex/data/hdf5/topo/hlsTopo
cp -r %{_awipscm_share}/${TOPO_SRC_DIR}/hlsTopo/* \
${RPM_BUILD_ROOT}/awips2/edex/data/hdf5/topo/hlsTopo
if [ $? -ne 0 ]; then
exit 1
fi
copyLegal "awips2/edex/data/hdf5/topo"
%pre

View file

@ -1 +1 @@
20110824
20140211