Issue #798 - Code review changes

Issue #798 - Code review updates
Change-Id: I5447574392a42c79fa4295ce4f9bb5ac295d06bb

Former-commit-id: cb05a9f95384806537106dc804833331d6c7db48
This commit is contained in:
James Korman 2012-07-13 10:04:26 -05:00
parent 97a1d083cd
commit 38a2e426d9
22 changed files with 1769 additions and 727 deletions

View file

@ -28,6 +28,7 @@ import org.apache.commons.collections.keyvalue.MultiKey;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.datum.PixelInCell;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.StorageException; import com.raytheon.uf.common.datastorage.StorageException;
import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.data.IDataPreparer; import com.raytheon.uf.viz.core.data.IDataPreparer;
@ -53,7 +54,8 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Feb 15, 2007 chammack Initial Creation. * Feb 15, 2007 chammack Initial Creation.
* * - AWIPS2 Baseline Repository --------
* Jul 18, 2012 798 jkorman Modified {@link #createTile} to remove hard-coded interpolation groups.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -97,7 +99,7 @@ public class FileBasedTileSet extends AbstractTileSet {
this.dataset = dataset; this.dataset = dataset;
} }
/* /**
* (non-Javadoc) * (non-Javadoc)
* *
* @see * @see
@ -109,10 +111,10 @@ public class FileBasedTileSet extends AbstractTileSet {
throws VizException { throws VizException {
IImage raster = target.getExtension(IColormappedImageExtension.class) IImage raster = target.getExtension(IColormappedImageExtension.class)
.initializeRaster( .initializeRaster(
new HDF5DataRetriever(new File(this.hdf5File), "/" new HDF5DataRetriever(new File(this.hdf5File),
+ this.group + "/" + this.dataset DataStoreFactory.createDataSetName(group,
+ "-interpolated/" + level, this.tileSet dataset, level), this.tileSet.getTile(
.getTile(level, i, j).getRectangle()), level, i, j).getRectangle()),
rsc.getCapability(ColorMapCapability.class) rsc.getCapability(ColorMapCapability.class)
.getColorMapParameters()); .getColorMapParameters());
return raster; return raster;

View file

@ -23,6 +23,7 @@ import java.awt.Rectangle;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
@ -44,7 +45,8 @@ import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Oct 28, 2009 mschenke Initial creation * Oct 28, 2009 mschenke Initial creation
* * - AWIPS2 Baseline Repository --------
* Jul 18, 2012 798 jkorman Modified constructor to remove hard-coded dataset name.
* </pre> * </pre>
* *
* @author mschenke * @author mschenke
@ -69,7 +71,9 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
Rectangle dataSetBounds, boolean signed, ByteBuffer retreivedBuffer) { Rectangle dataSetBounds, boolean signed, ByteBuffer retreivedBuffer) {
this.pdo = pdo; this.pdo = pdo;
this.datasetBounds = dataSetBounds; this.datasetBounds = dataSetBounds;
this.dataset = "Data" + "-interpolated/" + level;
dataset = DataStoreFactory.createDataSetName(null, DataStoreFactory.DEF_DATASET_NAME, level);
this.signed = signed; this.signed = signed;
this.retreivedBuffer = retreivedBuffer; this.retreivedBuffer = retreivedBuffer;
} }
@ -88,12 +92,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
retreivedBuffer = null; retreivedBuffer = null;
} else { } else {
try { try {
byte[] data = getRawData(); satBuffer = ByteBuffer.wrap(getRawData());
if (data != null) {
satBuffer = ByteBuffer.wrap(data);
} else {
System.out.println("Problem!");
}
} catch (Exception e) { } catch (Exception e) {
statusHandler.handle(Priority.SIGNIFICANT, statusHandler.handle(Priority.SIGNIFICANT,
"Error retrieving satellite data", e); "Error retrieving satellite data", e);
@ -108,6 +107,8 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
} }
public byte[] getRawData() { public byte[] getRawData() {
byte [] retData = null;
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[] {
this.datasetBounds.x + this.datasetBounds.width, this.datasetBounds.x + this.datasetBounds.width,
@ -116,14 +117,14 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
try { try {
dataRecord = DataCubeContainer dataRecord = DataCubeContainer
.getDataRecord(pdo, req, this.dataset); .getDataRecord(pdo, req, this.dataset);
if (dataRecord != null && dataRecord.length == 1) {
retData = ((ByteDataRecord) dataRecord[0]).getByteData();
}
} catch (VizDataCubeException e) { } catch (VizDataCubeException e) {
statusHandler.handle(Priority.SIGNIFICANT, statusHandler.handle(Priority.SIGNIFICANT,
"Error retrieving satellite data", e); "Error retrieving satellite data", e);
} }
if (dataRecord != null && dataRecord.length == 1) { return retData;
return ((ByteDataRecord) dataRecord[0]).getByteData();
}
return null;
} }
/* /*

View file

@ -45,6 +45,7 @@ import com.raytheon.uf.common.dataplugin.satellite.units.counts.DerivedWVPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel; import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.goes.PolarPrecipWaterPixel; import com.raytheon.uf.common.dataplugin.satellite.units.goes.PolarPrecipWaterPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel; import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
@ -94,7 +95,9 @@ import com.raytheon.viz.satellite.SatelliteConstants;
* 03/25/2009 2086 jsanchez Mapped correct converter to parameter type. * 03/25/2009 2086 jsanchez Mapped correct converter to parameter type.
* Updated the call to ColormapParametersFactory.build * Updated the call to ColormapParametersFactory.build
* 03/30/2009 2169 jsanchez Updated numLevels handling. * 03/30/2009 2169 jsanchez Updated numLevels handling.
* * - AWIPS2 Baseline Repository --------
* 07/17/2012 798 jkorman Use decimationLevels from SatelliteRecord. Removed hard-coded
* data set names.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -266,15 +269,8 @@ public class SatResource extends
getCapability(ColorMapCapability.class).setColorMapParameters( getCapability(ColorMapCapability.class).setColorMapParameters(
colorMapParameters); colorMapParameters);
numLevels = 1; // number of interpolation levels plus the base level!
int newSzX = record.getSpatialObject().getNx(); numLevels = record.getInterpolationLevels() + 1;
int newSzY = record.getSpatialObject().getNy();
while ((newSzX > 512 && newSzY > 512)) {
newSzX /= 2;
newSzY /= 2;
numLevels++;
}
} }
@Override @Override
@ -490,13 +486,13 @@ public class SatResource extends
} }
if (baseTile == null) { if (baseTile == null) {
tile = baseTile = new SatFileBasedTileSet(record, "Data", tile = baseTile = new SatFileBasedTileSet(record, DataStoreFactory.DEF_DATASET_NAME,
numLevels, 256, numLevels, 256,
MapUtil.getGridGeometry(((SatelliteRecord) record) MapUtil.getGridGeometry(((SatelliteRecord) record)
.getSpatialObject()), this, .getSpatialObject()), this,
PixelInCell.CELL_CORNER, viewType); PixelInCell.CELL_CORNER, viewType);
} else { } else {
tile = new SatFileBasedTileSet(record, "Data", baseTile); tile = new SatFileBasedTileSet(record, DataStoreFactory.DEF_DATASET_NAME, baseTile);
} }
tile.addMeshCallback(this); tile.addMeshCallback(this);
tile.setMapDescriptor(this.descriptor); tile.setMapDescriptor(this.descriptor);

View file

@ -0,0 +1,143 @@
#!/usr/bin/python
#
"""
Convert to append the coverageid to the satellite datauris, and
modify the associated satellite hdf5 group names to append the
coverageid. The new groups are added as an alias to the existing
datasets.
Date Ticket# Engineer Description
------------ ---------- ----------- --------------------------
20120711 798 jkorman Initial Development
"""
from subprocess import Popen, PIPE
import sys
from time import time
import h5py
POSTGRES_CMD = "psql -U awips -d metadata -t -q -A -c "
HDF5_LOC = "/awips2/edex/data/hdf5"
DATAURI_IDX = 1
COVERAGE_IDX = 2
def update_satellite_table():
"""
Add the interpolationLevels column to the satellite table.
"""
result = queryPostgres("select count(*) from information_schema.columns where table_name='satellite' and column_name='interpolationlevels';")
if(result[0][0] == '0'):
result = result = queryPostgres("alter table satellite add column interpolationlevels integer;")
print "Adding interpolationlevels column to satellite table"
def formatFileTime(refTime):
"""
Extract and format the year (YYYY), month (MM), day (DD), and hour (HH)
from the reference time. The output is formatted as YYYY-MM-DD-HH
"""
return refTime[0:4] + "-" + refTime[5:7] + "-" + refTime[8:10] + "-" + refTime[11:13]
def getFilename(refTime):
"""
Create the satellite data hdf filename corresponding to the given reference time.
"""
return "satellite-" + formatFileTime(refTime) + ".h5"
def queryPostgres(sql):
"""
Extract and format the year (YYYY), month (MM), day (DD), and hour (HH)
from the reference time. The output is formatted as YYYY-MM-DD-HH
"""
result = Popen(POSTGRES_CMD + "\"" + sql + "\"", stdout=PIPE, shell=True)
retVal = []
for line in result.stdout:
retVal.append(line.strip().split("|"))
return retVal
def get_sectorids():
"""
Get a list of unique sector identifiers from the satellite table.
"""
return queryPostgres("select distinct sectorid from satellite;")
def get_satellite_rows(sectorid):
"""
Extract and format the year (YYYY), month (MM), day (DD), and hour (HH)
from the reference time. The output is formatted as YYYY-MM-DD-HH
"""
keys = {}
rows = queryPostgres("select id, dataURI, coverage_gid, sectorid, physicalelement, reftime from satellite where sectorid=" + repr(sectorid) + ";")
for row in rows:
# updateSql = "update satellite set datauri='" + row[DATAURI_IDX] + "/" + row[COVERAGE_IDX] + "' where id=" + row[0] + ";"
# queryPostgres(updateSql)
# create the key for this entry.
key = "/satellite/" + row[3] + "/" + row[4] + "/" + getFilename(row[5])
# have we found this key already?
if(key in keys):
# if so, get the row list for this key
rowList = keys[key]
else:
# otherwise create an empty list to put the row in
rowList = []
# add it to the collection
keys[key] = rowList
# and add the row to the list
rowList.append(row)
return keys
def process_all_satellite():
"""
Process all entries in the satellite table.
Do one sector id at a time.
"""
sectorids = get_sectorids()
if(sectorids):
for sectorid in sectorids:
print "Processing sector " + sectorid[0]
keys = get_satellite_rows(sectorid[0])
if(keys):
for key in keys:
print "=========================================================="
print " Processing key = " + key
fname = HDF5_LOC + key
try:
f = h5py.File(fname,'r+')
for row in keys[key]:
newGroupName = row[DATAURI_IDX] + "/" + row[COVERAGE_IDX]
group = f.create_group(newGroupName)
group = f.create_group(newGroupName + "/Data-interpolated")
oldds = row[DATAURI_IDX] + "/Data"
newds = newGroupName + "/Data"
# Link to the old data set
f[newds] = h5py.SoftLink(oldds)
group = f[row[DATAURI_IDX] + "/Data-interpolated"]
numLevels = 1
for n in group.keys():
numLevels += 1
newds = newGroupName + "/Data-interpolated/" + n
if (n == '0'):
# special case for this link.
# dataset /Data-interpolated/0 points to /Data
oldds = row[DATAURI_IDX] + "/Data"
else:
oldds = row[DATAURI_IDX] + "/Data-interpolated/" + n
f[newds] = h5py.SoftLink(oldds)
# now back up one for the Data,Data-interpolated/0 link
numLevels -= 1
updateSql = "update satellite set datauri='" + row[DATAURI_IDX] + "/" + row[COVERAGE_IDX] + "'"
updateSql += ", interpolationlevels=" + repr(numLevels)
updateSql += " where id=" + row[0] + ";"
queryPostgres(updateSql)
f.close()
except:
print "Error occurred processing file " + fname
else:
print "No keys found for the sector id " + sectorid[0]
else:
print "No sector identifiers found in the satellite table"
if __name__ == '__main__':
t = time()
update_satellite_table()
process_all_satellite()
print "Total Conversion time %ds" % (time() - t)

View file

@ -23,3 +23,4 @@
# Java Library Path (location of Wrapper.DLL or libwrapper.so) # Java Library Path (location of Wrapper.DLL or libwrapper.so)
wrapper.java.library.path.1=%EDEX_HOME%/bin/linux-x86-32/ wrapper.java.library.path.1=%EDEX_HOME%/bin/linux-x86-32/

View file

@ -32,6 +32,9 @@ export RADAR_SERVER=tcp://localhost:8813
# set the AWIPS II shared directory # set the AWIPS II shared directory
export SHARE_DIR=/awips2/edex/data/share export SHARE_DIR=/awips2/edex/data/share
# set the AWIPS II temporary directory
export TEMP_DIR=/awips2/edex/data/tmp
# set hydroapps directory path # set hydroapps directory path
export apps_dir=${SHARE_DIR}/hydroapps export apps_dir=${SHARE_DIR}/hydroapps
# site identifier for hydroapps # site identifier for hydroapps

View file

@ -123,6 +123,7 @@ wrapper.java.additional.42=-Dweb.port=8080
wrapper.java.additional.43=-Dconfidential.port=8443 wrapper.java.additional.43=-Dconfidential.port=8443
wrapper.java.additional.44=-Dhttp.port=%HTTP_PORT% wrapper.java.additional.44=-Dhttp.port=%HTTP_PORT%
wrapper.java.additional.45=-Dedex.arch=%EDEX_ARCH% wrapper.java.additional.45=-Dedex.arch=%EDEX_ARCH%
wrapper.java.additional.46=-Dedex.tmp=%TEMP_DIR%
# Initial Java Heap Size (in MB) # Initial Java Heap Size (in MB)
wrapper.java.initmemory=%INIT_MEM% wrapper.java.initmemory=%INIT_MEM%

View file

@ -38,7 +38,9 @@ import com.raytheon.edex.util.satellite.SatellitePosition;
import com.raytheon.edex.util.satellite.SatelliteUnit; import com.raytheon.edex.util.satellite.SatelliteUnit;
import com.raytheon.uf.common.dataplugin.PluginDataObject; 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.SatelliteMessageData;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.edex.decodertools.time.TimeTools; import com.raytheon.uf.edex.decodertools.time.TimeTools;
import com.raytheon.uf.edex.wmo.message.WMOHeader; import com.raytheon.uf.edex.wmo.message.WMOHeader;
@ -50,7 +52,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
* *
* OFTWARE HISTORY * OFTWARE HISTORY
* *
* ate Ticket# Engineer Description * Date Ticket# Engineer Description
* ----------- ---------- ----------- -------------------------- * ----------- ---------- ----------- --------------------------
* 006 garmenda Initial Creation * 006 garmenda Initial Creation
* /14/2007 139 Phillippe Modified to follow refactored plugin pattern * /14/2007 139 Phillippe Modified to follow refactored plugin pattern
@ -65,7 +67,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
* 02/05/2010 4120 jkorman Modified removeWmoHeader to handle WMOHeader in * 02/05/2010 4120 jkorman Modified removeWmoHeader to handle WMOHeader in
* various start locations. * various start locations.
* 04/17/2012 14724 kshresth This is a temporary workaround - Projection off CONUS * 04/17/2012 14724 kshresth This is a temporary workaround - Projection off CONUS
* * - AWIPS2 Baseline Repository --------
* 06/27/2012 798 jkorman Using SatelliteMessageData to "carry" the decoded image.
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
@ -242,10 +245,9 @@ public class SatelliteDecoder extends AbstractDecoder {
SatellitePosition position = dao SatellitePosition position = dao
.getSatellitePosition(record.getCreatingEntity()); .getSatellitePosition(record.getCreatingEntity());
if (position == null) { if (position == null) {
logger logger.info("Unable to determine geostationary location of ["
.info("Unable to determine geostationary location of [" + record.getCreatingEntity()
+ record.getCreatingEntity() + "]. Zeroing out fields.");
+ "]. Zeroing out fields.");
} else { } else {
record.setSatSubPointLat(position.getLatitude()); record.setSatSubPointLat(position.getLatitude());
record.setSatSubPointLon(position.getLongitude()); record.setSatSubPointLon(position.getLongitude());
@ -265,7 +267,7 @@ public class SatelliteDecoder extends AbstractDecoder {
/* /*
* Rotate image if necessary * Rotate image if necessary
*/ */
// TODO: Can these numbers be an enum or constants?
switch (scanMode) { switch (scanMode) {
case 1: case 1:
Util.flipHoriz(tempBytes, ny, nx); Util.flipHoriz(tempBytes, ny, nx);
@ -280,8 +282,8 @@ public class SatelliteDecoder extends AbstractDecoder {
default: default:
break; break;
} }
SatelliteMessageData messageData = new SatelliteMessageData(
record.setMessageData(tempBytes); tempBytes, nx, ny);
// get the latitude of the first point // get the latitude of the first point
byteBuffer.position(20); byteBuffer.position(20);
@ -315,7 +317,8 @@ public class SatelliteDecoder extends AbstractDecoder {
float dx = 0.0f, dy = 0.0f, lov = 0.0f, lo2 = 0.0f, la2 = 0.0f; float dx = 0.0f, dy = 0.0f, lov = 0.0f, lo2 = 0.0f, la2 = 0.0f;
// Do specialized decoding and retrieve spatial data for Lambert // Do specialized decoding and retrieve spatial data for Lambert
// Conformal and Polar Stereographic projections // Conformal and Polar Stereographic projections
if ((mapProjection == 3) || (mapProjection == 5)) { if ((mapProjection == SatMapCoverage.PROJ_LAMBERT)
|| (mapProjection == SatMapCoverage.PROJ_POLAR_STEREO)) {
byteBuffer.position(30); byteBuffer.position(30);
byteBuffer.get(threeBytesArray, 0, 3); byteBuffer.get(threeBytesArray, 0, 3);
dx = byteArrayToFloat(threeBytesArray) / 10; dx = byteArrayToFloat(threeBytesArray) / 10;
@ -332,7 +335,7 @@ public class SatelliteDecoder extends AbstractDecoder {
// Do specialized decoding and retrieve spatial data for // Do specialized decoding and retrieve spatial data for
// Mercator // Mercator
// projection // projection
else if (mapProjection == 1) { else if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
dx = byteBuffer.getShort(33); dx = byteBuffer.getShort(33);
dy = byteBuffer.getShort(35); dy = byteBuffer.getShort(35);
@ -352,31 +355,32 @@ public class SatelliteDecoder extends AbstractDecoder {
SatMapCoverage mapCoverage = null; SatMapCoverage mapCoverage = null;
try { try {
/** /**
* This is a temporary workaround for DR14724, hopefully to be removed after NESDIS changes * This is a temporary workaround for DR14724, hopefully to
* the product header * be removed after NESDIS changes the product header
*/ */
if ((mapProjection == 3) if ((mapProjection == SatMapCoverage.PROJ_LAMBERT)
&& (record.getPhysicalElement().equalsIgnoreCase("Imager 13 micron (IR)") ) && (record.getPhysicalElement()
&& (record.getSectorID().equalsIgnoreCase("West CONUS"))){ .equalsIgnoreCase("Imager 13 micron (IR)"))
nx = 1100; && (record.getSectorID()
ny = 1280; .equalsIgnoreCase("West CONUS"))) {
dx = 4063.5f; nx = 1100;
dy = 4063.5f; ny = 1280;
la1 = 12.19f; dx = 4063.5f;
lo1 = -133.4588f; dy = 4063.5f;
} la1 = 12.19f;
/** lo1 = -133.4588f;
* End of DR14724 }
*/ /**
* End of DR14724
*/
mapCoverage = SatSpatialFactory.getInstance() mapCoverage = SatSpatialFactory.getInstance()
.getMapCoverage(mapProjection, nx, ny, dx, dy, lov, .getMapCoverage(mapProjection, nx, ny, dx, dy, lov,
latin, la1, lo1, la2, lo2); latin, la1, lo1, la2, lo2);
} catch (Exception e) { } catch (Exception e) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
buf buf.append(
.append( "Error getting or constructing SatMapCoverage for values: ")
"Error getting or constructing SatMapCoverage for values: ")
.append("\n\t"); .append("\n\t");
buf.append("mapProjection=" + mapProjection).append("\n\t"); buf.append("mapProjection=" + mapProjection).append("\n\t");
buf.append("nx=" + nx).append("\n\t"); buf.append("nx=" + nx).append("\n\t");
@ -399,8 +403,11 @@ public class SatelliteDecoder extends AbstractDecoder {
.getTime()); .getTime());
record.setPluginName("satellite"); record.setPluginName("satellite");
record.constructDataURI(); record.constructDataURI();
// Create the data record.
IDataRecord dataRec = messageData.getStorageRecord(record,
SatelliteRecord.SAT_DATASET_NAME);
record.setMessageData(dataRec);
} }
} }
} }
if (record == null) { if (record == null) {
@ -435,26 +442,21 @@ public class SatelliteDecoder extends AbstractDecoder {
} }
String msgStr = new String(message); String msgStr = new String(message);
Matcher matcher = null; Matcher matcher = null;
if (msgStr != null) { matcher = Pattern.compile(WMOHeader.WMO_HEADER).matcher(msgStr);
matcher = Pattern.compile(WMOHeader.WMO_HEADER).matcher(msgStr); if (matcher.find()) {
if (matcher.find()) { int headerStart = matcher.start();
int headerStart = matcher.start(); if (SAT_HDR_TT.equals(msgStr
if (SAT_HDR_TT.equals(msgStr.substring(headerStart, .substring(headerStart, headerStart + 2))) {
headerStart + 2))) { int startOfSatellite = matcher.end();
int startOfSatellite = matcher.end(); retMessage = new byte[messageData.length - startOfSatellite];
retMessage = new byte[messageData.length - startOfSatellite]; System.arraycopy(messageData, startOfSatellite, retMessage, 0,
System.arraycopy(messageData, startOfSatellite, retMessage, retMessage.length);
0, retMessage.length);
} else {
throw new DecoderException(
"First character of the WMO header must be 'T'");
}
} else { } else {
throw new DecoderException("Cannot decode an empty WMO header"); throw new DecoderException(
"First character of the WMO header must be 'T'");
} }
} else { } else {
throw new DecoderException( throw new DecoderException("Cannot decode an empty WMO header");
"Could not create data for WMO header search");
} }
return retMessage; return retMessage;

View file

@ -40,6 +40,8 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 7/24/07 353 bphillip Initial Check in * 7/24/07 353 bphillip Initial Check in
* - AWIPS2 Baseline Repository --------
* 06/27/2012 798 jkorman Corrected id query type.
* *
* </pre> * </pre>
* *
@ -64,7 +66,7 @@ public class SatMapCoverageDao extends CoreDao {
* @return A SatelliteMapCoverage object with the corresponding ID. Null if * @return A SatelliteMapCoverage object with the corresponding ID. Null if
* not found. * not found.
*/ */
public SatMapCoverage queryByMapId(String mapId) { public SatMapCoverage queryByMapId(Integer mapId) {
return (SatMapCoverage) this.queryById(mapId); return (SatMapCoverage) this.queryById(mapId);
} }
@ -152,7 +154,7 @@ public class SatMapCoverageDao extends CoreDao {
query.addQueryParam("la1",la1); query.addQueryParam("la1",la1);
query.addQueryParam("lo1",lo1); query.addQueryParam("lo1",lo1);
if (mapProjection == 1) { if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
query.addQueryParam("la2",la2); query.addQueryParam("la2",la2);
query.addQueryParam("lo2",lo2); query.addQueryParam("lo2",lo2);
} }

View file

@ -19,9 +19,13 @@
**/ **/
package com.raytheon.edex.plugin.satellite.dao; package com.raytheon.edex.plugin.satellite.dao;
import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.edex.util.satellite.SatelliteCreatingEntity; import com.raytheon.edex.util.satellite.SatelliteCreatingEntity;
import com.raytheon.edex.util.satellite.SatellitePhysicalElement; import com.raytheon.edex.util.satellite.SatellitePhysicalElement;
@ -32,14 +36,23 @@ import com.raytheon.edex.util.satellite.SatelliteUnit;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.IPersistable;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataquery.db.QueryResult; import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.StorageException; import com.raytheon.uf.common.datastorage.StorageException;
import com.raytheon.uf.common.datastorage.StorageProperties; import com.raytheon.uf.common.datastorage.StorageProperties;
import com.raytheon.uf.common.datastorage.records.AbstractStorageRecord;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.interpolation.GridDownscaler;
import com.raytheon.uf.common.geospatial.interpolation.data.AbstractDataWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.ByteArrayWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.DataDestination;
import com.raytheon.uf.common.geospatial.interpolation.data.ShortArrayWrapper;
import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.plugin.PluginDao; import com.raytheon.uf.edex.database.plugin.PluginDao;
@ -55,7 +68,8 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Feb 11, 2009 bphillip Initial creation * Feb 11, 2009 bphillip Initial creation
* * - AWIPS2 Baseline Repository --------
* 07/09/2012 798 jkorman Modified datastore population.
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
@ -99,31 +113,77 @@ public class SatelliteDao extends PluginDao {
super(pluginName); super(pluginName);
} }
/**
* Populated a given IDataStore object with the data record to be persisted.
*
* @param dataStore
* Storage object to be populated.
* @param record
* The persistable record containing the data to be persisted.
* @return The populated data storage object.
*/
@Override @Override
protected IDataStore populateDataStore(IDataStore dataStore, protected IDataStore populateDataStore(IDataStore dataStore,
IPersistable record) throws StorageException { IPersistable record) throws StorageException {
SatelliteRecord satRecord = (SatelliteRecord) record; SatelliteRecord satRecord = (SatelliteRecord) record;
AbstractStorageRecord storageRecord = null;
long nx = satRecord.getCoverage().getNx(); IDataRecord storageRecord = (IDataRecord) satRecord.getMessageData();
long ny = satRecord.getCoverage().getNy(); if (storageRecord != null) {
StorageProperties props = new StorageProperties();
String compression = PluginRegistry.getInstance()
.getRegisteredObject(pluginName).getCompression();
if (compression != null) {
props.setCompression(StorageProperties.Compression
.valueOf(compression));
}
props.setDownscaled(false);
storageRecord.setProperties(props);
storageRecord.setCorrelationObject(satRecord);
// Store the base record.
dataStore.addDataRecord(storageRecord);
long[] sizes = new long[] { nx, ny }; Map<String, Object> attributes = storageRecord.getDataAttributes();
storageRecord = new ByteDataRecord("Data", satRecord.getDataURI(),
(byte[]) satRecord.getMessageData(), 2, sizes); Float fillValue = getAttribute(attributes,
SatelliteRecord.SAT_FILL_VALUE, 0.0f);
SatMapCoverage coverage = satRecord.getCoverage();
GridDownscaler downScaler = createDownscaler(coverage,
storageRecord, fillValue);
// How many interpolation levels do we need for this data?
// Subtract one for the base level data.
int levels = downScaler.getNumberOfDownscaleLevels() - 1;
// set the number of levels in the 'parent' satellite data.
satRecord.setInterpolationLevels(levels);
if (DataStoreFactory.isInterpolated(levels)) {
for (int downscaleLevel = 1; downscaleLevel <= levels; downscaleLevel++) {
Rectangle size = downScaler
.getDownscaleSize(downscaleLevel);
AbstractDataWrapper dest = getDestination(storageRecord,
size);
dest.setFillValue(fillValue);
try {
downScaler.downscale(downscaleLevel, dest);
IDataRecord dr = createDataRecord(satRecord, dest,
downscaleLevel, size);
// Set the attributes and properties from the parent
// data.
dr.setDataAttributes(attributes);
dr.setProperties(props);
dataStore.addDataRecord(dr);
} catch (TransformException e) {
throw new StorageException(
"Error creating downscaled data",
storageRecord, e);
}
}
}
StorageProperties props = new StorageProperties();
String compression = PluginRegistry.getInstance()
.getRegisteredObject(pluginName).getCompression();
if (compression != null) {
props.setCompression(StorageProperties.Compression
.valueOf(compression));
} }
props.setDownscaled(true);
storageRecord.setProperties(props);
storageRecord.setCorrelationObject(satRecord);
dataStore.addDataRecord(storageRecord);
return dataStore; return dataStore;
} }
@ -166,12 +226,13 @@ public class SatelliteDao extends PluginDao {
query.addQueryParam("dataTime.refTime", theDate); query.addQueryParam("dataTime.refTime", theDate);
query.addOrder("dataTime.refTime", true); query.addOrder("dataTime.refTime", true);
try { try {
PluginDataObject[] pdos = this.getFullRecord(query, -1); PluginDataObject[] pdos = this.getFullRecord(query, 0);
for (int i = 0; i < pdos.length; i++) { for (int i = 0; i < pdos.length; i++) {
satRecords.add((SatelliteRecord) pdos[i]); satRecords.add((SatelliteRecord) pdos[i]);
satRecords.get(i).setMessageData( satRecords.get(i)
(ByteDataRecord) ((IDataRecord[]) satRecords.get(i) .setMessageData(
.getMessageData())[0]); ((IDataRecord[]) satRecords.get(i)
.getMessageData())[0]);
} }
} catch (Exception e) { } catch (Exception e) {
throw new DataAccessLayerException( throw new DataAccessLayerException(
@ -328,4 +389,130 @@ public class SatelliteDao extends PluginDao {
this.positionDao = positionDao; this.positionDao = positionDao;
} }
/**
* Create an {@link AbstractDataWrapper} destination from the supplied
* {@link IDataRecord} with given dimensions.
*
* @param rec
* The record containing data to be wrapped.
* @param size
* A {@link Rectangle} containing the size of the input data.
* @return The wrapped data.
*/
private AbstractDataWrapper getDestination(IDataRecord rec, Rectangle size) {
AbstractDataWrapper dest = null;
if (rec instanceof ByteDataRecord) {
dest = new ByteArrayWrapper(size.width, size.height);
} else if (rec instanceof ShortDataRecord) {
dest = new ShortArrayWrapper(size.width, size.height);
}
return dest;
}
/**
* Create an {@link AbstractDataWrapper} source from the supplied
* {@link IDataRecord} with given dimensions.
*
* @param rec
* The record containing data to be wrapped.
* @param nx
* Number of items on the x axis.
* @param ny
* Number of items on the y axis.
* @return The wrapped data.
*/
private AbstractDataWrapper getSource(IDataRecord rec, int nx, int ny) {
AbstractDataWrapper source = null;
if (rec instanceof ByteDataRecord) {
byte[] b = ((ByteDataRecord) rec).getByteData();
source = new ByteArrayWrapper(b, nx, ny);
} else if (rec instanceof ShortDataRecord) {
short[] s = ((ShortDataRecord) rec).getShortData();
source = new ShortArrayWrapper(s, nx, ny);
}
return source;
}
/**
* Create the {@link IDataRecord} from the {@link DataDestination} using the
* original satellite data, size and
*
* @param satRec
* The original satellite data record.
* @param data
* The down-scaled data.
* @param downscaledLevel
* The level identifier for this data.
* @param size
* Size of the down-scaled data.
* @return The created data record to be stored.
*/
private IDataRecord createDataRecord(SatelliteRecord satRec,
DataDestination data, int downscaleLevel, Rectangle size) {
SatelliteMessageData msgData = null;
Object o = null;
if (data instanceof ByteArrayWrapper) {
o = ((ByteArrayWrapper) data).getArray();
} else if (data instanceof ShortArrayWrapper) {
o = ((ShortArrayWrapper) data).getArray();
}
if (o != null) {
msgData = new SatelliteMessageData(o, size.width, size.height);
}
IDataRecord rec = msgData.getStorageRecord(satRec,
String.valueOf(downscaleLevel));
rec.setCorrelationObject(satRec);
rec.setGroup(DataStoreFactory.createGroupName(satRec.getDataURI(),
SatelliteRecord.SAT_DATASET_NAME, true));
return rec;
}
/**
* Create a down scaler for the given data.
*
* @param coverage
* Satellite Map Coverage for the source data.
* @param rec
* The original data that will be down-scaled.
* @param fillValue
* The declared fill value for the data.
* @return
*/
private GridDownscaler createDownscaler(SatMapCoverage coverage,
IDataRecord rec, double fillValue) {
GridDownscaler downScaler = null;
AbstractDataWrapper dataSource = getSource(rec, coverage.getNx(),
coverage.getNy());
dataSource.setFillValue(fillValue);
downScaler = new GridDownscaler(MapUtil.getGridGeometry(coverage),
dataSource);
return downScaler;
}
/**
* Get the value of an named attribute.
*
* @param attrs
* Attributes that contain the value.
* @param attrName
* Name of the attribute.
* @param defValue
* A default value.
* @return
*/
public static Float getAttribute(Map<String, Object> attrs,
String attrName, Float defValue) {
Float retValue = defValue;
if ((attrs != null) && (attrName != null)) {
retValue = (Float) attrs.get(attrName);
}
return retValue;
}
} }

View file

@ -42,7 +42,8 @@ import com.vividsolutions.jts.io.WKTReader;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 12/19/07 439 bphillip Initial creation * 12/19/07 439 bphillip Initial creation
* * - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* *
* </pre> * </pre>
*/ */
@ -172,7 +173,7 @@ public class SatSpatialFactory {
ProjectedCRS crs = null; ProjectedCRS crs = null;
// Get the correct CRS // Get the correct CRS
if (mapProjection == 1) { if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
double cm = 0.0; double cm = 0.0;
if ((lo1 > 0.0) && (lo2 < 0.0)) { if ((lo1 > 0.0) && (lo2 < 0.0)) {
cm = 180.0; cm = 180.0;
@ -200,7 +201,7 @@ public class SatSpatialFactory {
* Projection is Mercator. Determine corner points from la1,lo1,la2,lo2 * Projection is Mercator. Determine corner points from la1,lo1,la2,lo2
* provided in the satellite file * provided in the satellite file
*/ */
if (mapProjection == 1) { if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
logger.debug("Determining corner points for Mercator projection"); logger.debug("Determining corner points for Mercator projection");
corner1.x = lo1; corner1.x = lo1;
corner1.y = la1; corner1.y = la1;

View file

@ -21,6 +21,7 @@
package com.raytheon.uf.common.dataplugin.satellite; package com.raytheon.uf.common.dataplugin.satellite;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
@ -35,6 +36,7 @@ import org.hibernate.annotations.Type;
import org.opengis.referencing.FactoryException; import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.geospatial.CRSCache; import com.raytheon.uf.common.geospatial.CRSCache;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.ISpatialObject;
@ -57,7 +59,8 @@ import com.vividsolutions.jts.geom.Polygon;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 7/24/07 353 bphillip Initial Checkin * 7/24/07 353 bphillip Initial Checkin
* * - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* *
* </pre> * </pre>
*/ */
@ -65,13 +68,23 @@ import com.vividsolutions.jts.geom.Polygon;
@Table(name = "satellite_spatial") @Table(name = "satellite_spatial")
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize @DynamicSerialize
@Embeddable
public class SatMapCoverage extends PersistableDataObject implements public class SatMapCoverage extends PersistableDataObject implements
ISpatialObject { ISpatialObject {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final int PROJ_MERCATOR = 1;
public static final int PROJ_LAMBERT = 3;
public static final int PROJ_POLAR_STEREO = 5;
public static final int PROJ_CYLIN_EQUIDISTANT = 7;
@Id @Id
@DynamicSerializeElement @DynamicSerializeElement
@DataURI(position = 0)
private int gid; private int gid;
/** /**

View file

@ -26,9 +26,13 @@ import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord; import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/** /**
* TODO Add Description * Encapsulate satellite image data as well as the dimensions of
* the image grid. Attributes about the data may also be added. As an
* example these attributes could include "scale factor" and/or "fill_value".
* *
* <pre> * <pre>
* *
@ -36,31 +40,39 @@ import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jun 27, 2012 jkorman Initial creation * Jun 27, 2012 798 jkorman Initial creation
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
@DynamicSerialize
public class SatelliteMessageData { public class SatelliteMessageData {
private static final int DATA_DIMS = 2; private static final int DATA_DIMS = 2;
// Number of columns in the image data
@DynamicSerializeElement
private int nx; private int nx;
// Number of rows in the image data
@DynamicSerializeElement
private int ny; private int ny;
// The image grid data - Usually some type (T [])
@DynamicSerializeElement
private Object messageData; private Object messageData;
@DynamicSerializeElement
private Map<String, Object> dataAttributes; private Map<String, Object> dataAttributes;
/** /**
* * Create a message object containing the gridded image data as well as
* @param messageData * its dimensions.
* @param numCols * @param messageData The image grid data - Usually some type (T [])
* @param numRows * @param numCols Number of columns in the image grid.
* @param numRows Number of rows in the image grid.
*/ */
public SatelliteMessageData(Object messageData, int numCols, int numRows) { public SatelliteMessageData(Object messageData, int numCols, int numRows) {
this.messageData = messageData; this.messageData = messageData;
@ -69,7 +81,8 @@ public class SatelliteMessageData {
} }
/** /**
* * Set the gridded image data.
* @param data The image grid data - Usually some type (T [])
* @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#setMessageData(java.lang.Object) * @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#setMessageData(java.lang.Object)
*/ */
public void setMessageData(Object data) { public void setMessageData(Object data) {
@ -77,7 +90,9 @@ public class SatelliteMessageData {
} }
/** /**
* * Set an attribute associated with the image data.
* @param key Name to store the information against.
* @param value The value to store against the given key.
*/ */
public void setDataAttribute(String key, Object value) { public void setDataAttribute(String key, Object value) {
if (dataAttributes == null) { if (dataAttributes == null) {
@ -87,7 +102,9 @@ public class SatelliteMessageData {
} }
/** /**
* * Set the dimensions of the data.
* @param nx Number of columns in the image grid.
* @param ny Number of rows in the image grid.
* @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#setDimensions(int, * @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#setDimensions(int,
* int) * int)
*/ */
@ -97,7 +114,11 @@ public class SatelliteMessageData {
} }
/** /**
* * Create a data record that encapsulates the data in this class.
* @param dataRec A satellite record that will supply the information needed to
* populate the data record being built.
* @param dataSetName The name that will be used to identify the data set.
* @return The created data record.
* @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#getStorageRecord() * @see com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData#getStorageRecord()
*/ */
public IDataRecord getStorageRecord(SatelliteRecord dataRec, String dataSetName) { public IDataRecord getStorageRecord(SatelliteRecord dataRec, String dataSetName) {
@ -120,4 +141,59 @@ public class SatelliteMessageData {
return storageRecord; return storageRecord;
} }
/**
* Get the number of columns in the image grid.
* @return The number of columns in the image grid.
*/
public int getNx() {
return nx;
}
/**
* Set the number of columns in the image grid.
* @param nx Number of columns in the image grid.
*/
public void setNx(int nx) {
this.nx = nx;
}
/**
* Get the number of rows in the image grid.
* @return The number of rows in the image grid.
*/
public int getNy() {
return ny;
}
/**
* Set the number of rows in the image grid.
* @param ny Number of rows in the image grid.
*/
public void setNy(int ny) {
this.ny = ny;
}
/**
* Get the data attributes.
* @return The data attributes.
*/
public Map<String, Object> getDataAttributes() {
return dataAttributes;
}
/**
* Set the data attributes.
* @param dataAttributes The data attributes.
*/
public void setDataAttributes(Map<String, Object> dataAttributes) {
this.dataAttributes = dataAttributes;
}
/**
* Get the underlying message data object.
* @return The underlying message data object.
*/
public Object getMessageData() {
return messageData;
}
} }

View file

@ -35,6 +35,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.dataplugin.IDecoderGettable; import com.raytheon.uf.common.dataplugin.IDecoderGettable;
import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.ServerSpecificPersistablePluginDataObject; import com.raytheon.uf.common.dataplugin.persist.ServerSpecificPersistablePluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.geospatial.ISpatialEnabled; import com.raytheon.uf.common.geospatial.ISpatialEnabled;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
@ -65,239 +66,276 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize @DynamicSerialize
public class SatelliteRecord extends ServerSpecificPersistablePluginDataObject public class SatelliteRecord extends ServerSpecificPersistablePluginDataObject
implements ISpatialEnabled { implements ISpatialEnabled {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** public static final String SAT_DATASET_NAME = DataStoreFactory.DEF_DATASET_NAME;
* The source of the data - NESDIS
*/ public static final String SAT_FILL_VALUE = "FILL_VALUE";
@Column(length = 31)
@DataURI(position = 1)
@XmlAttribute
@DynamicSerializeElement
private String source;
/** The creating entity. See table 4.5 of GINI satellite ICD */ public static final String SAT_ADD_OFFSET = "ADD_OFFSET";
@Column(length = 63)
@DataURI(position = 2)
@XmlAttribute
@DynamicSerializeElement
private String creatingEntity;
/** The sector ID. See table 4.6 of the GINI satellite ICD */ public static final String SAT_SCALE_FACTOR = "SCALE_FACTOR";
@Column(length = 63)
@DataURI(position = 3)
@XmlAttribute
@DynamicSerializeElement
private String sectorID;
/** The physical Element. See table 4.7 of the GINI satellite ICD */ /**
@Column(length = 63) * The source of the data - NESDIS
@DataURI(position = 4) */
@XmlAttribute @Column(length = 31)
@DynamicSerializeElement @DataURI(position = 1)
private String physicalElement; @XmlAttribute
@DynamicSerializeElement
private String source;
/** /** The creating entity. See table 4.5 of GINI satellite ICD */
* Number of logical records in the product. See tables 4.9, 4.11, 4.12, @Column(length = 63)
* 4.13, 4.14, 4.16 of the GINI satellite ICD @DataURI(position = 2)
*/ @XmlAttribute
@Column @DynamicSerializeElement
@XmlAttribute private String creatingEntity;
@DynamicSerializeElement
private Integer numRecords;
/** /** The sector ID. See table 4.6 of the GINI satellite ICD */
* Size of logical records in bytes for product. See tables 4.9, 4.11, 4.12, @Column(length = 63)
* 4.13, 4.14, 4.16 of the GINI satellite ICD @DataURI(position = 3)
*/ @XmlAttribute
@Column @DynamicSerializeElement
@XmlAttribute private String sectorID;
@DynamicSerializeElement
private Integer sizeRecords;
/** The latitude directly beneath the satellite */ /** The physical Element. See table 4.7 of the GINI satellite ICD */
@Column @Column(length = 63)
@DynamicSerializeElement @DataURI(position = 4)
private Float satSubPointLat; @XmlAttribute
@DynamicSerializeElement
private String physicalElement;
/** The longitude directly beneath the satellite */ /**
@Column * Number of logical records in the product. See tables 4.9, 4.11, 4.12,
@DynamicSerializeElement * 4.13, 4.14, 4.16 of the GINI satellite ICD
private Float satSubPointLon; */
@Column
@XmlAttribute
@DynamicSerializeElement
private Integer numRecords;
/** The upper right hand latitude */ /**
@Column * Size of logical records in bytes for product. See tables 4.9, 4.11, 4.12,
@DynamicSerializeElement * 4.13, 4.14, 4.16 of the GINI satellite ICD
private Float upperRightLat; */
@Column
@XmlAttribute
@DynamicSerializeElement
private Integer sizeRecords;
/** The upper right hand longitude */ /** The latitude directly beneath the satellite */
@Column @Column
@DynamicSerializeElement @DynamicSerializeElement
private Float upperRightLon; private Float satSubPointLat;
/** Height of the satellite in km */ /** The longitude directly beneath the satellite */
@Column @Column
@DynamicSerializeElement @DynamicSerializeElement
private Integer satHeight; private Float satSubPointLon;
/** Units of the satellite data * */ /** The upper right hand latitude */
@Column(length = 26) @Column
@XmlAttribute @DynamicSerializeElement
@DynamicSerializeElement private Float upperRightLat;
private String units;
@ManyToOne /** The upper right hand longitude */
@PrimaryKeyJoinColumn @Column
@XmlElement @DynamicSerializeElement
@DynamicSerializeElement private Float upperRightLon;
private SatMapCoverage coverage;
@Override /** Height of the satellite in km */
public SatMapCoverage getSpatialObject() { @Column
return coverage; @DynamicSerializeElement
} private Integer satHeight;
public SatMapCoverage getCoverage() { /** Units of the satellite data * */
return coverage; @Column(length = 26)
} @XmlAttribute
@DynamicSerializeElement
private String units;
public void setCoverage(SatMapCoverage coverage) { /** Number of interpolation levels in the data store */
this.coverage = coverage; @Column
} @XmlAttribute
@DynamicSerializeElement
private Integer interpolationLevels;
@DataURI(position = 5, embedded=true)
@ManyToOne
@PrimaryKeyJoinColumn
@XmlElement
@DynamicSerializeElement
private SatMapCoverage coverage;
public Float getSatSubPointLat() { @Override
return satSubPointLat; public SatMapCoverage getSpatialObject() {
} return coverage;
}
public void setSatSubPointLat(Float satSubPointLat) { public SatMapCoverage getCoverage() {
this.satSubPointLat = satSubPointLat; return coverage;
} }
public Float getSatSubPointLon() { public void setCoverage(SatMapCoverage coverage) {
return satSubPointLon; this.coverage = coverage;
} }
public void setSatSubPointLon(Float satSubPointLon) { public Float getSatSubPointLat() {
this.satSubPointLon = satSubPointLon; return satSubPointLat;
} }
public Float getUpperRightLat() { public void setSatSubPointLat(Float satSubPointLat) {
return upperRightLat; this.satSubPointLat = satSubPointLat;
} }
public void setUpperRightLat(Float upperRightLat) { public Float getSatSubPointLon() {
this.upperRightLat = upperRightLat; return satSubPointLon;
} }
public Float getUpperRightLon() { public void setSatSubPointLon(Float satSubPointLon) {
return upperRightLon; this.satSubPointLon = satSubPointLon;
} }
public void setUpperRightLon(Float upperRightLon) { public Float getUpperRightLat() {
this.upperRightLon = upperRightLon; return upperRightLat;
} }
/** public void setUpperRightLat(Float upperRightLat) {
* No-arg constructor. this.upperRightLat = upperRightLat;
*/ }
public SatelliteRecord() {
} public Float getUpperRightLon() {
return upperRightLon;
}
/** public void setUpperRightLon(Float upperRightLon) {
* Constructs a satellite record from a dataURI this.upperRightLon = upperRightLon;
* }
* @param uri
* The dataURI
* @param tableDef
* The table definition associated with this class
*/
public SatelliteRecord(String uri) {
super(uri);
}
public Integer getNumRecords() { /**
return numRecords; * No-arg constructor.
} */
public SatelliteRecord() {
public void setNumRecords(Integer numRecords) { }
this.numRecords = numRecords;
}
public Integer getSizeRecords() { /**
return sizeRecords; * Constructs a satellite record from a dataURI
} *
* @param uri
* The dataURI
* @param tableDef
* The table definition associated with this class
*/
public SatelliteRecord(String uri) {
super(uri);
}
public void setSizeRecords(Integer sizeRecords) { public Integer getNumRecords() {
this.sizeRecords = sizeRecords; return numRecords;
} }
public Integer getSatHeight() { public void setNumRecords(Integer numRecords) {
return satHeight; this.numRecords = numRecords;
} }
public void setSatHeight(Integer satHeight) { public Integer getSizeRecords() {
this.satHeight = satHeight; return sizeRecords;
} }
/** public void setSizeRecords(Integer sizeRecords) {
* @return the units this.sizeRecords = sizeRecords;
*/ }
public String getUnits() {
return units;
}
/** public Integer getSatHeight() {
* @param units return satHeight;
* the units to set }
*/
public void setUnits(String units) {
this.units = units;
}
/** public void setSatHeight(Integer satHeight) {
* Get the IDecoderGettable reference for this record. this.satHeight = satHeight;
* }
* @return The IDecoderGettable reference for this record. Null for this
* class.
*/
@Override
public IDecoderGettable getDecoderGettable() {
return null;
}
public String getSource() { /**
return source; * @return the units
} */
public String getUnits() {
return units;
}
public void setSource(String source) { /**
this.source = source; * @param units
} * the units to set
*/
public void setUnits(String units) {
this.units = units;
}
public String getCreatingEntity() { /**
return creatingEntity; * Get the IDecoderGettable reference for this record.
} *
* @return The IDecoderGettable reference for this record. Null for this
* class.
*/
@Override
public IDecoderGettable getDecoderGettable() {
return null;
}
public void setCreatingEntity(String creatingEntity) { public String getSource() {
this.creatingEntity = creatingEntity; return source;
} }
public String getSectorID() { public void setSource(String source) {
return sectorID; this.source = source;
} }
public void setSectorID(String sectorID) { public String getCreatingEntity() {
this.sectorID = sectorID; return creatingEntity;
} }
public String getPhysicalElement() { public void setCreatingEntity(String creatingEntity) {
return physicalElement; this.creatingEntity = creatingEntity;
} }
public void setPhysicalElement(String physicalElement) { public String getSectorID() {
this.physicalElement = physicalElement; return sectorID;
} }
public void setSectorID(String sectorID) {
this.sectorID = sectorID;
}
public String getPhysicalElement() {
return physicalElement;
}
public void setPhysicalElement(String physicalElement) {
this.physicalElement = physicalElement;
}
/**
* Get the number of interpolation levels in the data store.
* @return The number of interpolation levels. Data that is not interpolated
* should return a value of 0.
*/
public Integer getInterpolationLevels() {
return interpolationLevels;
}
/**
* Set the number of interpolation levels in the data store. If the data
* are not interpolated a value of 0 should be used.
* @param levels The number of interpolation levels in the data. Any value less than
* zero is set to zero.
*/
public void setInterpolationLevels(Integer levels) {
if(!DataStoreFactory.isInterpolated(levels)) {
levels = 0;
}
interpolationLevels = levels;
}
} }

View file

@ -58,6 +58,7 @@ import ncsa.hdf.hdf5lib.exceptions.HDF5Exception;
import ncsa.hdf.hdf5lib.exceptions.HDF5LibraryException; import ncsa.hdf.hdf5lib.exceptions.HDF5LibraryException;
import ncsa.hdf.hdf5lib.exceptions.HDF5SymbolTableException; import ncsa.hdf.hdf5lib.exceptions.HDF5SymbolTableException;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.DuplicateRecordStorageException; import com.raytheon.uf.common.datastorage.DuplicateRecordStorageException;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
@ -90,6 +91,8 @@ import com.raytheon.uf.common.util.FileUtil;
* Sep 25, 2007 chammack Added replace record functionality * Sep 25, 2007 chammack Added replace record functionality
* Apr 01, 2008 1041 chammack Added delete functionality * Apr 01, 2008 1041 chammack Added delete functionality
* Jun 30, 2008 2538 jsanchez Update readProperties for Strings. * Jun 30, 2008 2538 jsanchez Update readProperties for Strings.
* - AWIPS2 Baseline Repository --------
* Jul 18, 2012 798 jkorman Removed some hard-coded interpolation code/constants.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -438,7 +441,7 @@ public class HDF5DataStore implements IDataStore {
String[] datasets = getDatasets(group); String[] datasets = getDatasets(group);
for (String ds : datasets) { for (String ds : datasets) {
if (includeInterpolated && ds.endsWith("-interpolated")) { if (includeInterpolated && ds.endsWith(DataStoreFactory.DEF_INTERPOLATED_GROUP)) {
IDataRecord[] subresults; IDataRecord[] subresults;
subresults = this.retrieve(group + "/" + ds, false); subresults = this.retrieve(group + "/" + ds, false);
@ -447,7 +450,7 @@ public class HDF5DataStore implements IDataStore {
records.add(result); records.add(result);
} }
} }
} else if (!ds.endsWith("-interpolated")) { } else if (!ds.endsWith(DataStoreFactory.DEF_INTERPOLATED_GROUP)) {
IDataRecord record = this.retrieve(group, ds, Request.ALL); IDataRecord record = this.retrieve(group, ds, Request.ALL);
records.add(record); records.add(record);
} }
@ -1626,9 +1629,8 @@ public class HDF5DataStore implements IDataStore {
.getData()); .getData());
} }
rec.setName("" + level); rec.setName(String.valueOf(level));
rec.setGroup(originalGroup + "/" + originalDatasetName rec.setGroup(DataStoreFactory.createGroupName(originalGroup, originalDatasetName, true));
+ "-interpolated");
rec.setSizes(new long[] { w / 2, h / 2 }); rec.setSizes(new long[] { w / 2, h / 2 });

View file

@ -43,6 +43,9 @@ import com.raytheon.uf.common.datastorage.records.StringDataRecord;
* Feb 12, 2007 chammack Initial Creation. * Feb 12, 2007 chammack Initial Creation.
* 20070914 379 jkorman Added createStorageRecord factory methods. * 20070914 379 jkorman Added createStorageRecord factory methods.
* Refactored from HDFDataStore. * Refactored from HDFDataStore.
* - AWIPS2 Baseline Repository --------
* Jul 18, 2012 798 jkorman Extracted methods {@link #createDataSetName}, {@link #createGroupName}, and
* {@link #isInterpolated} from various classes.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -50,6 +53,28 @@ import com.raytheon.uf.common.datastorage.records.StringDataRecord;
*/ */
public class DataStoreFactory { public class DataStoreFactory {
/**
* Default data set name; {@value #DEF_DATASET_NAME}.
*/
public static final String DEF_DATASET_NAME = "Data";
/**
* Default interpolation suffix ({@value #DEF_INTERPOLATED_GROUP}) for
* interpolated groups.
*/
public static final String DEF_INTERPOLATED_GROUP = "-interpolated";
/**
* Default group element separator; {@value #DEF_SEPARATOR}.
*/
public static final String DEF_SEPARATOR = "/";
/**
* Base interpolation level. Any interpolation level greater than this value
* ({@value #BASE_LEVEL}) is considered to be a valid interpolation level.
*/
public static final int BASE_LEVEL = 0;
private static final DataStoreFactory instance = new DataStoreFactory(); private static final DataStoreFactory instance = new DataStoreFactory();
private IDataStoreFactory underlyingFactory; private IDataStoreFactory underlyingFactory;
@ -160,4 +185,190 @@ public class DataStoreFactory {
return record; return record;
} }
/**
* Create a storage dataset name using the group and data set name and an
* interpolation level. Any interpolation level less than or equal to zero
* generates the base dataset name with no interpolation. Any interpolation
* levels greater than zero are considered to be decimated levels of the
* original data.
* <table>
* <tr>
* <th>base group</th>
* <th>dataset</th>
* <th>interpolation</th>
* <th>result</th>
* </tr>
* <tr>
* <td>null</td>
* <td>null</td>
* <td>-1</td>
* <td>/Data</td>
* </tr>
* </tr>
* <tr>
* <td>null</td>
* <td>null</td>
* <td>0</td>
* <td>/Data</td>
* </tr>
* <tr>
* <td>null</td>
* <td>null</td>
* <td>4</td>
* <td>/Data-interpolated/4</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>null</td>
* <td>0</td>
* <td>/data/group/Data</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>null</td>
* <td>3</td>
* <td>/data/group/Data-interpolated/3</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>dsname</td>
* <td>-1</td>
* <td>/data/group/dsname</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>dsname</td>
* <td>2</td>
* <td>/data/group/dsname-interpolated/2</td>
* </tr>
* </table>
*
* @param groupName
* The group name this data set belongs to. If null, an empty
* group name is generated.
* @param baseDataSet
* Data set name The dataset name. This name and the
* {@link DEF_INTERPOLATED_GROUP} are used to create the
* interpolated suffix for the group name. If null and
* interpolation is requested, a default value
* {@link DEF_DATASET_NAME} will be used.
* @param interpolatedLevel
* The interpolation level data set numeric identifier.
* @return The generated fully qualified dataset name.
*/
public static String createDataSetName(String groupName,
String baseDataSet, int interpolatedLevel) {
boolean interpolated = isInterpolated(interpolatedLevel);
StringBuilder interpolatedGroup = new StringBuilder(createGroupName(
groupName, baseDataSet, interpolated));
interpolatedGroup.append(DEF_SEPARATOR);
if (interpolated) {
interpolatedGroup.append(String.valueOf(interpolatedLevel));
} else {
if (baseDataSet != null) {
interpolatedGroup.append(baseDataSet);
} else {
interpolatedGroup.append(DEF_DATASET_NAME);
}
}
return interpolatedGroup.toString();
}
/**
* Create a hierarchical group name, given a base group name, a dataset name
* and if interpolated levels are being created. If interpolation is not
* requested then the base group name is returned unchanged or if null an
* empty string is returned. When interpolation is requested, the dataset
* name is appended with an interpolation identifer to create an
* interpolation level group name.
* <table>
* <tr>
* <th>base group</th>
* <th>dataset</th>
* <th>interpolation</th>
* <th>result</th>
* </tr>
* <tr>
* <td>null</td>
* <td>null</td>
* <td>false</td>
* <td>zero length string</td>
* </tr>
* <tr>
* <td>null</td>
* <td>null</td>
* <td>true</td>
* <td>/Data-interpolated</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>null</td>
* <td>false</td>
* <td>/data/group</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>null</td>
* <td>true</td>
* <td>/data/group/Data-interpolated</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>dsname</td>
* <td>false</td>
* <td>/data/group</td>
* </tr>
* <tr>
* <td>/data/group</td>
* <td>dsname</td>
* <td>true</td>
* <td>/data/group/dsname-interpolated</td>
* </tr>
* </table>
*
* @param groupName
* The base group name.
* @param baseDataSet
* Data set name The dataset name. This name and the
* {@link #DEF_INTERPOLATED_GROUP} are used to create the
* interpolated suffix for the group name. If null and
* interpolation is requested, a default value
* {@link #DEF_DATASET_NAME} will be used.
* @param interpolatedLevel
* Create an interpolated group name.
* @return The generated group name.
*/
public static String createGroupName(String groupName, String baseDataSet,
boolean interpolated) {
StringBuilder interpolatedGroup = new StringBuilder();
if (groupName != null) {
interpolatedGroup.append(groupName);
}
if (interpolated) {
interpolatedGroup.append(DEF_SEPARATOR);
if (baseDataSet != null) {
if (baseDataSet.length() > BASE_LEVEL) {
interpolatedGroup.append(baseDataSet);
} else {
interpolatedGroup.append(DEF_DATASET_NAME);
}
} else {
interpolatedGroup.append(DEF_DATASET_NAME);
}
interpolatedGroup.append(DEF_INTERPOLATED_GROUP);
}
return interpolatedGroup.toString();
}
/**
* Is the specified interpolation greater than the {@link BASE_LEVEL}?
*
* @param interpolatedLevel
* An interpolation level.
* @return
*/
public static boolean isInterpolated(int interpolatedLevel) {
return (interpolatedLevel > BASE_LEVEL);
}
} }

View file

@ -0,0 +1,116 @@
/**
* 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.geospatial.interpolation.data;
import org.geotools.coverage.grid.GeneralGridGeometry;
/**
* {@link AbstractDataWrapper} implementation for byte array data.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 13, 2012 jkorman Initial creation
*
* </pre>
*
* @author jkorman
* @version 1.0
*/
public class ByteArrayWrapper extends DataWrapper1D {
// The wrapped byte array data.
protected final byte[] array;
/**
* Wrap a byte array using a specified geometry.
* @param array Byte array data to be wrapped.
* @param geometry A {@link GeneralGridGeometry} that will be used to discover
* the shape of the input data.
*/
public ByteArrayWrapper(byte[] array, GeneralGridGeometry geometry) {
super(geometry);
this.array = array;
}
/**
* Wrap a byte array using given x and y axis dimensions.
* @param array Byte array data to be wrapped.
* @param nx Number of elements on the x axis.
* @param ny Number of elements on the y axis.
*/
public ByteArrayWrapper(byte[] array, int nx, int ny) {
super(nx, ny);
this.array = array;
}
/**
* Create an instance with a byte array using given x and y axis dimensions.
* @param nx Number of elements on the x axis.
* @param ny Number of elements on the y axis.
*/
public ByteArrayWrapper(int nx, int ny) {
this(new byte[nx * ny], nx, ny);
}
/**
* Create an instance with a byte array using a specified geometry.
* @param geometry A {@link GeneralGridGeometry} that will be used to discover
* the shape of the input data.
*/
public ByteArrayWrapper(GeneralGridGeometry geometry) {
// assume this is going to be a destination and avoid passing
// geometry to super to save time on checking for wrapping.
this(geometry.getGridRange().getSpan(0), geometry.getGridRange()
.getSpan(1));
}
/**
* Get a reference to the internal wrapped data.
* @return The internal byte array data.
*/
public byte[] getArray() {
return array;
}
/**
* Get the value of the internal data at a specified position.
* @param index Position within the internal data to get.
* @return The value of the internal data.
*/
@Override
protected double getDataValueInternal(int index) {
return array[index];
}
/**
* Set the value of the internal data at a specified position.
* @param dataValue A value to set at the given index.
* @param index Position within the internal data to set.
*/
@Override
public void setDataValueInternal(double dataValue, int index) {
array[index] = (byte) dataValue;
}
}

View file

@ -21,6 +21,7 @@
package com.raytheon.uf.common.util; package com.raytheon.uf.common.util;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -28,6 +29,7 @@ import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -47,6 +49,9 @@ import java.util.zip.GZIPOutputStream;
* return false when unable to * return false when unable to
* obtain directory listing. * obtain directory listing.
* Sep 16, 2008 1250 jelkins Added join function * Sep 16, 2008 1250 jelkins Added join function
* - AWIPS2 Baseline Repository --------
* Jul 06, 2012 798 jkorman Added more robust {@link #copyFile}. Added methods
* to create temporary directories and files.
* *
* </pre> * </pre>
* *
@ -311,29 +316,23 @@ public class FileUtil {
return unmangled.toString(); return unmangled.toString();
} }
/**
* Copy a file to a another file.
*
* @param fileToCopy
* The source file. This file reference must exist.
* @param outputFile
* The destination file. This file may exist, if so it will be
* overwritten.
* @throws IOException
* An error occurred while copying the data.
* @throws NullPointerException
* Either the source or target file references are null.
*/
public static void copyFile(File fileToCopy, File outputFile) public static void copyFile(File fileToCopy, File outputFile)
throws IOException { throws IOException {
// Copy the entire file.
FileInputStream fis = null; copyFile(fileToCopy, outputFile, 0);
FileOutputStream fos = null;
try {
fis = new FileInputStream(fileToCopy);
outputFile.getParentFile().mkdirs();
fos = new FileOutputStream(outputFile);
byte[] bytes = new byte[2048];
int len = fis.read(bytes);
while (len > -1) {
fos.write(bytes, 0, len);
len = fis.read(bytes);
}
} finally {
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
} }
public static String file2String(File file) throws IOException { public static String file2String(File file) throws IOException {
@ -621,4 +620,215 @@ public class FileUtil {
return VALID_FILENAME.matcher(fileName).matches(); return VALID_FILENAME.matcher(fileName).matches();
} }
/**
* Copy a file from one location to another. The file copy may begin at some
* specified position within the source file.
*
* @param source
* The source file. This file reference must exist.
* @param target
* The destination file. This file may exist, if so it will be
* overwritten.
* @param position
* The start position within the source file where the copy
* operation will begin. The position must be greater than or
* equal to zero, and less than the file length of the source.
* @return Was the required data copied to the target file.
* @throws IOException
* An error occurred while copying the data.
* @throws IllegalArgumentException
* The position is less than zero or greater than the length of
* the source file or either of the source, target files are null.
*/
public static boolean copyFile(File source, File target, int position)
throws IOException {
boolean status = false;
if (source != null) {
if (target != null) {
if ((position >= 0) && (position < source.length())) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(source);
FileChannel fci = fis.getChannel();
fos = new FileOutputStream(target);
FileChannel fco = fos.getChannel();
long count = source.length() - position;
long transfered = fci.transferTo(position, count, fco);
// ensure we copied all of the data.
status = (transfered == count);
} finally {
String cause = null;
try {
close(fis);
} catch (IOException e) {
cause = String.format(
"copyFile.source.close[%s][%s]", e
.getClass().getName(), e
.getMessage());
}
try {
close(fos);
} catch (IOException e) {
if (cause == null) {
cause = String.format(
"copyFile.target.close[%s][%s]", e
.getClass().getName(), e
.getMessage());
} else {
cause = String.format(
"%s copyFile.target.close[%s][%s]",
cause, e.getClass().getName(),
e.getMessage());
}
}
// One or more closes failed. Construct and throw an
// exception.
if (cause != null) {
throw new IOException(cause);
}
}
} else {
String msg = String.format(
"position [%d] is out of range. Max is [%d]",
position, source.length());
throw new IllegalArgumentException(msg);
}
} else {
throw new IllegalArgumentException("target file reference is null");
}
} else {
throw new IllegalArgumentException("source file reference is null");
}
return status;
}
/**
* Attempt to create a temporary directory under a given base directory for
* temporary directories. If the directory already exists it is returned,
* otherwise it is created.
*
* @param tempPath
* The base path for temporary directories.
* @param componentName
* The component requesting a temporary directory. If this is
* null the tempPath will be used.
* @return The file reference to the created or existing temporary
* directory.
* @throws IOException
* The attempt to create the temporary directory failed.
* @throws IllegalArgumentException
* The temporary directory path is null.
*/
public static File createTempDir(String tempPath, String componentName)
throws IOException {
File tempDir = null;
if (tempPath != null) {
if (componentName == null) {
tempDir = new File(tempPath);
} else {
tempDir = new File(tempPath, componentName);
}
try {
// Check if the directory already exists...
if (!tempDir.exists()) {
// it doesn't, so create it.
if (!tempDir.mkdirs()) {
throw new IOException(
"Could not create temporary directory "
+ tempDir.getAbsolutePath());
}
} else {
if (!tempDir.isDirectory()) {
String msg = String
.format("Path [%s] is not a directory, cannot create temporary directory",
tempDir.getAbsolutePath());
throw new IOException(msg);
}
}
} catch (SecurityException se) {
throw new IOException("Could not create temporary directory "
+ tempDir.getAbsolutePath(), se);
}
} else {
throw new IllegalArgumentException("Temporary path is null");
}
return tempDir;
}
/**
* Create an empty temporary file. The file is created in the directory
* referenced by tempPath. The file created will be named
*
* <pre>
* tempPath / namePrefix_tempFileUniquePart.nameSuffix
* </pre>
*
* @param tempPath
* Base path to the temporary directory.
* @param namePrefix
* The temporary filename prefix. If this is null a default
* prefix of "<strong>tempFile</strong>" will be used.
* @param nameSuffix
* The temporary filename suffix. If this is null the default
* suffix "<strong>.tmp</strong>" will be used.
* @return The File reference to the created temporary file.
* @throws IOException
* The tempPath does not exist and could not be created or an
* error occurred while creating the temporary file.
* @throws IllegalArgumentException
* The temporary path was null.
*/
public static File createTempFile(File tempPath, String namePrefix,
String nameSuffix) throws IOException {
String defaultPrefix = "tempFile";
String prefixFiller = "xxx";
File tempFile = null;
if (tempPath != null) {
if (!tempPath.exists()) {
if (!tempPath.mkdirs()) {
throw new IOException(
"Could not create temporary directory "
+ tempPath.getAbsolutePath());
}
}
// isDirectory will not work until we actually have a path that
// exists!
if (!tempPath.isDirectory()) {
String msg = String
.format("Path [%s] is not a directory, cannot create temporary file",
tempPath.getAbsolutePath());
throw new IOException(msg);
}
if (namePrefix == null) {
namePrefix = defaultPrefix;
} else if (namePrefix.length() < 3) {
namePrefix += prefixFiller;
}
namePrefix += "_";
tempFile = File.createTempFile(namePrefix, nameSuffix, tempPath);
} else {
throw new IllegalArgumentException("Temporary path is null");
}
return tempFile;
}
/**
* Attempt to close a {@link Closeable} object.
*
* @param c
* An object that needs to be closed.
* @throws IOException
* An error occurred attempting to close the object.
*/
public static void close(Closeable c) throws IOException {
if (c != null) {
c.close();
}
}
} }

View file

@ -344,7 +344,8 @@ public abstract class PluginDao extends CoreDao {
* @param objects * @param objects
* The objects to retrieve the HDF5 component for * The objects to retrieve the HDF5 component for
* @param tileSet * @param tileSet
* The tile set to retrieve. Currently unimplemented * The tile set to retrieve. Any value less than or equal
* to zero returns the "base" data only.
* @return The HDF5 data records * @return The HDF5 data records
* @throws StorageException * @throws StorageException
* If problems occur while interacting with HDF5 data stores * If problems occur while interacting with HDF5 data stores
@ -355,32 +356,29 @@ public abstract class PluginDao extends CoreDao {
List<IDataRecord[]> retVal = new ArrayList<IDataRecord[]>(); List<IDataRecord[]> retVal = new ArrayList<IDataRecord[]>();
for (PluginDataObject obj : objects) { for (PluginDataObject obj : objects) {
IDataRecord[] record = null;
if (obj instanceof IPersistable) { if (obj instanceof IPersistable) {
/* connect to the data store and retrieve the data */ /* connect to the data store and retrieve the data */
IDataStore dataStore = getDataStore((IPersistable) obj); IDataStore dataStore = getDataStore((IPersistable) obj);
if (tileSet != -1) { boolean interpolated = DataStoreFactory.isInterpolated(tileSet);
record = new IDataRecord[tileSet + 1]; if(!interpolated) {
for (int i = 0; i <= tileSet; i++) { tileSet = 0;
try { }
record[i] = dataStore.retrieve(obj.getDataURI() IDataRecord[] record = new IDataRecord[tileSet + 1];
+ File.separator + "Data-interpolated" try {
+ File.separator, String.valueOf(tileSet), String group = DataStoreFactory.createGroupName(
Request.ALL); obj.getDataURI(),
} catch (Exception e) { DataStoreFactory.DEF_DATASET_NAME, interpolated);
throw new PluginException( // Retrieve the base record.
"Error getting HDF5 data", e); record[0] = dataStore.retrieve(obj.getDataURI(),
} DataStoreFactory.DEF_DATASET_NAME, Request.ALL);
} // Now get the interpolated data, if any!
} else { for (int tile = 1; tile < record.length; tile++) {
record = new IDataRecord[1]; record[tile] = dataStore.retrieve(group,
try { String.valueOf(tile), Request.ALL);
record[0] = dataStore.retrieve(obj.getDataURI(),
"Data", Request.ALL);
} catch (Exception e) {
throw new PluginException("Error getting HDF5 data", e);
} }
} catch (Exception e) {
throw new PluginException("Error getting HDF5 data", e);
} }
retVal.add(record); retVal.add(record);
} }

View file

@ -40,9 +40,11 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
import com.raytheon.uf.edex.plugin.satellite.mcidas.util.McidasSatelliteLookups; import com.raytheon.uf.edex.plugin.satellite.mcidas.util.McidasSatelliteLookups;
import com.raytheon.uf.edex.plugin.satellite.mcidas.util.McidasSatelliteLookups.PhysicalElementValue; import com.raytheon.uf.edex.plugin.satellite.mcidas.util.McidasSatelliteLookups.PhysicalElementValue;
/** McIDAS AREA Decoder /**
* McIDAS AREA Decoder
* *
* <p>Implemented: * <p>
* Implemented:
* <ul> * <ul>
* <li>Mercator projection</li> * <li>Mercator projection</li>
* <li>Multiple bands</li> * <li>Multiple bands</li>
@ -55,32 +57,53 @@ import com.raytheon.uf.edex.plugin.satellite.mcidas.util.McidasSatelliteLookups.
* <li>Calibration block</li> * <li>Calibration block</li>
* <li>Non-byte data types</li> * <li>Non-byte data types</li>
* </ul> * </ul>
* <pre>
*
* OFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ----------- ---------- ----------- --------------------------
* No previous history
* - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* </pre>
*
* @author
* @version
*/ */
public class McidasSatelliteDecoder { public class McidasSatelliteDecoder {
private static final IUFStatusHandler theHandler = UFStatus private static final IUFStatusHandler theHandler = UFStatus
.getHandler(McidasSatelliteDecoder.class); .getHandler(McidasSatelliteDecoder.class);
private static final String UNEXPECTED_HEADER_VALUE = "Unexpected value in format"; private static final String UNEXPECTED_HEADER_VALUE = "Unexpected value in format";
private static final int EXPECTED_IMAGE_TYPE_LE = 4; private static final int EXPECTED_IMAGE_TYPE_LE = 4;
private static final int EXPECTED_IMAGE_TYPE_BE = 0x04000000; private static final int EXPECTED_IMAGE_TYPE_BE = 0x04000000;
private static final double HALFPI = Math.PI/2.; private static final double HALFPI = Math.PI / 2.;
private static final double RTD = 180./Math.PI;
private static final double DTR = Math.PI/180.; private static final double RTD = 180. / Math.PI;
private static final double DTR = Math.PI / 180.;
private SatelliteDao dao; private SatelliteDao dao;
private String traceId; private String traceId;
public McidasSatelliteDecoder() { public McidasSatelliteDecoder() {
} }
public PluginDataObject[] decode(byte[] data, Headers headers) throws Exception { public PluginDataObject[] decode(byte[] data, Headers headers)
throws Exception {
traceId = (String) headers.get("traceId"); traceId = (String) headers.get("traceId");
try { try {
return decodeMcidasArea(data); return decodeMcidasArea(data);
} catch (DecoderException e) { } catch (DecoderException e) {
// Any DecoderExceptions throw by this decoder do not need a stack trace // Any DecoderExceptions throw by this decoder do not need a stack
// trace
theHandler.error(e.getMessage(), e); theHandler.error(e.getMessage(), e);
return new PluginDataObject[0]; return new PluginDataObject[0];
} }
@ -89,8 +112,8 @@ public class McidasSatelliteDecoder {
/** /**
* References:<br/> * References:<br/>
* <ul> * <ul>
* <li> http://www.ssec.wisc.edu/mcidas/doc/prog_man/2006/formats-1.html </li> * <li>http://www.ssec.wisc.edu/mcidas/doc/prog_man/2006/formats-1.html</li>
* <li> http://www.ssec.wisc.edu/mcidas/doc/misc_doc/area2.html </li> * <li>http://www.ssec.wisc.edu/mcidas/doc/misc_doc/area2.html</li>
* </ul> * </ul>
* *
* @param data * @param data
@ -100,7 +123,7 @@ public class McidasSatelliteDecoder {
private PluginDataObject[] decodeMcidasArea(byte[] data) throws Exception { private PluginDataObject[] decodeMcidasArea(byte[] data) throws Exception {
ByteBuffer buf = ByteBuffer.wrap(data); ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
// Decode the directory block // Decode the directory block
if (buf.getInt() != 0) if (buf.getInt() != 0)
formatError(UNEXPECTED_HEADER_VALUE); formatError(UNEXPECTED_HEADER_VALUE);
@ -152,37 +175,36 @@ public class McidasSatelliteDecoder {
buf.getInt(); // reserved buf.getInt(); // reserved
/* int calibrationOffset = */buf.getInt(); /* int calibrationOffset = */buf.getInt();
buf.getInt(); // comment cards buf.getInt(); // comment cards
long bandBits = ((long) bandMap33to64 << 32) | bandMap1to32; long bandBits = ((long) bandMap33to64 << 32) | bandMap1to32;
if (nBands != Long.bitCount(bandBits)) if (nBands != Long.bitCount(bandBits))
formatError("Specified number of bands does not match number of bits in band map"); formatError("Specified number of bands does not match number of bits in band map");
// Decode the navigation block // Decode the navigation block
buf.position(navBlockOffset); buf.position(navBlockOffset);
SatMapCoverage coverage = decodeNavigation(elementResolution, lineResolution, SatMapCoverage coverage = decodeNavigation(elementResolution,
ulImageElement, ulImageLine, lineResolution, ulImageElement, ulImageLine, nElementsPerLine,
nElementsPerLine, nLines, buf); nLines, buf);
// Decode the data block, creating a SatelliteRecord for each band. // Decode the data block, creating a SatelliteRecord for each band.
PluginDataObject[] result = new PluginDataObject[nBands]; PluginDataObject[] result = new PluginDataObject[nBands];
int bitIndex = 0; int bitIndex = 0;
RECORD: RECORD: for (int ri = 0; ri < nBands; ++ri) {
for (int ri = 0; ri < nBands; ++ri) {
while ((bandBits & (1L << bitIndex)) == 0) while ((bandBits & (1L << bitIndex)) == 0)
if (++bitIndex >= 64) if (++bitIndex >= 64)
break RECORD; // shouldn't happen break RECORD; // shouldn't happen
SatelliteRecord rec = new SatelliteRecord(); SatelliteRecord rec = new SatelliteRecord();
rec.setDataTime(new DataTime(unpackTime(yyyddd, hhmmss))); rec.setDataTime(new DataTime(unpackTime(yyyddd, hhmmss)));
rec.setSource("McIDAS"); rec.setSource("McIDAS");
rec.setCreatingEntity(getCreatingEntity(sensorSourceNumber)); rec.setCreatingEntity(getCreatingEntity(sensorSourceNumber));
PhysicalElementValue pev = getPhysicalElement(sensorSourceNumber, PhysicalElementValue pev = getPhysicalElement(sensorSourceNumber,
bitIndex + 1); bitIndex + 1);
rec.setPhysicalElement(pev.name); rec.setPhysicalElement(pev.name);
rec.setUnits(pev.units); rec.setUnits(pev.units);
rec.setSectorID(getAreaName(areaNumber)); rec.setSectorID(getAreaName(areaNumber));
rec.setCoverage(coverage); rec.setCoverage(coverage);
// TODO: Line pad if not a multiple of four bytes // TODO: Line pad if not a multiple of four bytes
if (linePrefixLength == 0 && nBytesPerElement == 1 && nBands == 1) { if (linePrefixLength == 0 && nBytesPerElement == 1 && nBands == 1) {
byte[] imageBytes = new byte[nLines * nElementsPerLine]; byte[] imageBytes = new byte[nLines * nElementsPerLine];
@ -202,8 +224,8 @@ public class McidasSatelliteDecoder {
} }
} }
} else } else
unimplemented("non-byte elements"); unimplemented("non-byte elements");
rec.setTraceId(traceId); rec.setTraceId(traceId);
rec.setPersistenceTime(TimeTools.getSystemCalendar().getTime()); rec.setPersistenceTime(TimeTools.getSystemCalendar().getTime());
rec.setPluginName("satellite"); rec.setPluginName("satellite");
@ -214,14 +236,14 @@ public class McidasSatelliteDecoder {
return result; return result;
} }
/** /**
* Reference: http://www.ssec.wisc.edu/mcidas/doc/prog_man/2006/formats-13a.html * Reference:
* http://www.ssec.wisc.edu/mcidas/doc/prog_man/2006/formats-13a.html
* *
*/ */
private SatMapCoverage decodeNavigation(int xImgRes, int yImgRes, private SatMapCoverage decodeNavigation(int xImgRes, int yImgRes, int ulX,
int ulX, int ulY, int ulY, int nx, int ny, ByteBuffer buf) throws Exception {
int nx, int ny, ByteBuffer buf) throws Exception {
SatMapCoverage result = new SatMapCoverage(); SatMapCoverage result = new SatMapCoverage();
String navType = get4cc(buf); String navType = get4cc(buf);
if (navType.equals("MERC")) { if (navType.equals("MERC")) {
@ -231,121 +253,127 @@ public class McidasSatelliteDecoder {
int spacingAtStdLatInMeters = buf.getInt(); int spacingAtStdLatInMeters = buf.getInt();
int nrmlLonDDMMSS = buf.getInt(); int nrmlLonDDMMSS = buf.getInt();
// NOTE: We do not check the following for compatibility with WGS84. // NOTE: We do not check the following for compatibility with WGS84.
int radiusInMeters = buf.getInt(); int radiusInMeters = buf.getInt();
/*int eccentricity = */buf.getInt(); /* int eccentricity = */buf.getInt();
/*boolean geodetic = */buf.getInt()/* >= 0*/; /* boolean geodetic = */buf.getInt()/* >= 0 */;
boolean westPositive = buf.getInt() >= 0; boolean westPositive = buf.getInt() >= 0;
float la1, lo1, la2, lo2; float la1, lo1, la2, lo2;
/* The following is based on /*
* gov.noaa.nws.ncep.edex.plugin.mcidas/src/gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java * The following is based on
* gov.noaa.nws.ncep.edex.plugin.mcidas/src
* /gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java
*/ */
double clon = flipLon(unpackDdmmss(nrmlLonDDMMSS), westPositive); double clon = flipLon(unpackDdmmss(nrmlLonDDMMSS), westPositive);
double clat = unpackDdmmss(stdLatDDMMSS); double clat = unpackDdmmss(stdLatDDMMSS);
double dx = spacingAtStdLatInMeters * xImgRes; double dx = spacingAtStdLatInMeters * xImgRes;
double dy = spacingAtStdLatInMeters * yImgRes; double dy = spacingAtStdLatInMeters * yImgRes;
{ {
double phi0r = clat * DTR; double phi0r = clat * DTR;
double rxp = ((double) (elementOfEquator - ulX) / xImgRes + 1.); double rxp = ((double) (elementOfEquator - ulX) / xImgRes + 1.);
double ryp = (ny - (double) (lineOfEquator - ulY) / yImgRes); double ryp = (ny - (double) (lineOfEquator - ulY) / yImgRes);
double dxp = 1. - rxp; double dxp = 1. - rxp;
double dyp = 1. - ryp; double dyp = 1. - ryp;
double rm = dx * dyp; double rm = dx * dyp;
double rcos = radiusInMeters * Math.cos(phi0r); double rcos = radiusInMeters * Math.cos(phi0r);
double arg = Math.exp(rm/rcos); double arg = Math.exp(rm / rcos);
la1 = (float) ((2. * Math.atan(arg) - HALFPI ) * RTD); la1 = (float) ((2. * Math.atan(arg) - HALFPI) * RTD);
lo1 = (float) prnlon ((clon + ((dx * dxp) / rcos) * RTD)); lo1 = (float) prnlon((clon + ((dx * dxp) / rcos) * RTD));
dxp = nx -rxp; dxp = nx - rxp;
dyp = ny -ryp; dyp = ny - ryp;
rm = dx * dyp; rm = dx * dyp;
arg = Math.exp(rm / rcos); arg = Math.exp(rm / rcos);
la2 = (float) ((2. * Math.atan(arg) - HALFPI ) * RTD); la2 = (float) ((2. * Math.atan(arg) - HALFPI) * RTD);
lo2 = (float) prnlon ((clon + ((dx * dxp) / rcos) * RTD)); lo2 = (float) prnlon((clon + ((dx * dxp) / rcos) * RTD));
lo2 = (float) prnlon (lo2); lo2 = (float) prnlon(lo2);
} }
result = SatSpatialFactory.getInstance().getMapCoverage(1, nx, ny, result = SatSpatialFactory.getInstance().getMapCoverage(
(float) dx, (float) dy, (float) clon, (float) clat, SatMapCoverage.PROJ_MERCATOR, nx, ny, (float) dx,
la1, lo1, la2, lo2); (float) dy, (float) clon, (float) clat, la1, lo1, la2, lo2);
} else } else
unimplemented(String.format("navigation type \"%s\"", navType)); unimplemented(String.format("navigation type \"%s\"", navType));
return result; return result;
} }
private static double prnlon (double lon) { private static double prnlon(double lon) {
double dlon = lon - (int)(lon / 360.f) * 360.f; double dlon = lon - (int) (lon / 360.f) * 360.f;
if (lon < -180.) { if (lon < -180.) {
dlon = lon + 360.f; dlon = lon + 360.f;
} } else if (lon > 180.) {
else if (lon > 180.) {
dlon = (double) (lon - 360.); dlon = (double) (lon - 360.);
} }
return dlon; return dlon;
} }
private static Calendar unpackTime(int yyyddd, int hhmmss) { private static Calendar unpackTime(int yyyddd, int hhmmss) {
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(0); cal.setTimeInMillis(0);
cal.set(Calendar.YEAR, + 1900 + yyyddd / 1000); cal.set(Calendar.YEAR, +1900 + yyyddd / 1000);
cal.set(Calendar.DAY_OF_YEAR, yyyddd % 1000); cal.set(Calendar.DAY_OF_YEAR, yyyddd % 1000);
int hh = hhmmss / 10000; int hh = hhmmss / 10000;
cal.set(Calendar.HOUR_OF_DAY, hh); cal.set(Calendar.HOUR_OF_DAY, hh);
cal.set(Calendar.MINUTE, (hhmmss - hh * 10000) / 100); cal.set(Calendar.MINUTE, (hhmmss - hh * 10000) / 100);
cal.set(Calendar.SECOND, hhmmss % 100); cal.set(Calendar.SECOND, hhmmss % 100);
return cal; return cal;
} }
private static double unpackDdmmss(int ddmmss) { private static double unpackDdmmss(int ddmmss) {
int dd = ddmmss / 10000; int dd = ddmmss / 10000;
int mm = (ddmmss - dd * 10000) / 100; int mm = (ddmmss - dd * 10000) / 100;
int ss = ddmmss % 100; int ss = ddmmss % 100;
return dd + mm/60.0 + ss/3600.0; return dd + mm / 60.0 + ss / 3600.0;
} }
private static double flipLon(double lon, boolean flip) { private static double flipLon(double lon, boolean flip) {
return flip ? - lon : lon; return flip ? -lon : lon;
} }
private static String get4cc(ByteBuffer buf) { private static String get4cc(ByteBuffer buf) {
byte[] bytes = new byte[4]; byte[] bytes = new byte[4];
buf.get(bytes); buf.get(bytes);
return new String(bytes, Charset.forName("ISO-8859-1")); return new String(bytes, Charset.forName("ISO-8859-1"));
} }
private String getCreatingEntity(int sensorSourceNumber) { private String getCreatingEntity(int sensorSourceNumber) {
String value = McidasSatelliteLookups.getInstance().getCreatingEntity(sensorSourceNumber); String value = McidasSatelliteLookups.getInstance().getCreatingEntity(
return value != null ? value : String.format("Unknown-%d", sensorSourceNumber); sensorSourceNumber);
return value != null ? value : String.format("Unknown-%d",
sensorSourceNumber);
} }
private PhysicalElementValue getPhysicalElement(int ssn, int bandIndex) { private PhysicalElementValue getPhysicalElement(int ssn, int bandIndex) {
PhysicalElementValue value = McidasSatelliteLookups.getInstance().getPhysicalElement(ssn, bandIndex); PhysicalElementValue value = McidasSatelliteLookups.getInstance()
return value != null ? value : .getPhysicalElement(ssn, bandIndex);
new PhysicalElementValue(String.format("Unknown-%d", bandIndex), null); return value != null ? value : new PhysicalElementValue(String.format(
"Unknown-%d", bandIndex), null);
} }
private String getAreaName(int areaNumber) { private String getAreaName(int areaNumber) {
String value = McidasSatelliteLookups.getInstance().getAreaName(areaNumber); String value = McidasSatelliteLookups.getInstance().getAreaName(
areaNumber);
return value != null ? value : String.format("AREA%04d", areaNumber); return value != null ? value : String.format("AREA%04d", areaNumber);
} }
private void formatError(String message) throws DecoderException { private void formatError(String message) throws DecoderException {
throw new DecoderException(String.format("%s: %s", traceId, message)); throw new DecoderException(String.format("%s: %s", traceId, message));
} }
protected void unimplemented(String feature) throws DecoderException { protected void unimplemented(String feature) throws DecoderException {
throw new DecoderException(String.format("%s: unimplemented: %s", traceId, feature)); throw new DecoderException(String.format("%s: unimplemented: %s",
traceId, feature));
} }
/** /**
* @return the dao * @return the dao
*/ */
public SatelliteDao getDao() { public SatelliteDao getDao() {
@ -353,7 +381,8 @@ public class McidasSatelliteDecoder {
} }
/** /**
* @param dao the dao to set * @param dao
* the dao to set
*/ */
public void setDao(SatelliteDao dao) { public void setDao(SatelliteDao dao) {
this.dao = dao; this.dao = dao;

View file

@ -29,38 +29,23 @@ import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import ucar.nc2.Attribute; import ucar.nc2.Attribute;
import ucar.nc2.NetcdfFile; import ucar.nc2.NetcdfFile;
/** /**
* Decoder implementation for alaska and regional satellite plugin. * Decoder implementation for alaska and regional satellite plugin. This decoder
* This decoder ingests netcdf3 files generated by the Alaska Region and GOES-R Proving Ground * ingests netcdf3 files generated by the Alaska Region and GOES-R Proving
* for their satellite data. * Ground for their satellite data.
* *
* The following are the relevant elements in the netcdf3 files being used by the decoder * The following are the relevant elements in the netcdf3 files being used by
* dimensions: * the decoder dimensions: y = 1024 ; x = 1280 ;
* y = 1024 ;
* x = 1280 ;
*
* variables:
* byte image(y, x) ;
* double validTime ;
* validTime:units = "seconds since 1970-1-1 00:00:00.00 0:00" ;
* validTime:long_name = "Valid Time" ;
* *
* global attributes: * variables: byte image(y, x) ; double validTime ; validTime:units =
* :channel = "0.58 - 0.68 micron VISL" ; * "seconds since 1970-1-1 00:00:00.00 0:00" ; validTime:long_name =
* :depictorName = "AkSec1a1" ; * "Valid Time" ;
* :satelliteName = "HRPT" ; *
* :projName = "STEREOGRAPHIC" ; * global attributes: :channel = "0.58 - 0.68 micron VISL" ; :depictorName =
* :centralLat = 90.f ; * "AkSec1a1" ; :satelliteName = "HRPT" ; :projName = "STEREOGRAPHIC" ;
* :centralLon = -156.f ; * :centralLat = 90.f ; :centralLon = -156.f ; :lat00 = 62.057667f ; :lon00 =
* :lat00 = 62.057667f ; * -168.81633f ; :latNxNy = 52.910168f ; :lonNxNy = -146.53101f ; :dxKm =
* :lon00 = -168.81633f ; * 1.0164f ; :dyKm = 1.0164f ; :latDxDy = 58.f ; :lonDxDy = -156.f ;
* :latNxNy = 52.910168f ;
* :lonNxNy = -146.53101f ;
* :dxKm = 1.0164f ;
* :dyKm = 1.0164f ;
* :latDxDy = 58.f ;
* :lonDxDy = -156.f ;
* *
* <pre> * <pre>
* *
@ -68,8 +53,9 @@ import ucar.nc2.NetcdfFile;
* *
* date Ticket# Engineer Description * date Ticket# Engineer Description
* ----------- ---------- ----------- -------------------------- * ----------- ---------- ----------- --------------------------
* 7/15/11 tk Initial Creation * 7/15/11 tk Initial Creation
* * - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* </pre> * </pre>
* *
* @author tk * @author tk
@ -78,309 +64,332 @@ import ucar.nc2.NetcdfFile;
public class RegionalSatDecoder extends AbstractDecoder { public class RegionalSatDecoder extends AbstractDecoder {
private String traceId = ""; private String traceId = "";
private SatelliteDao dao; private SatelliteDao dao;
private String source;
private String filename;
/**
* The decoder method uses the NetcdfFile API to retrieve the attributes and satellite image data
* from the Alaska Region and GOES-R Proving Ground netcdf3 files. These netcdf3 files are generated
* for use in Alaska and the metadata and data are specified by the requirements for the Alaska Region.
* Once the netcdf3 file is decoded, the metadata is stored in the Satellite table in Postgres and
* the image data is stored in the HDF5 repository as Satellite records. The GIS map metadata is stored
* in the satellite_spatial table by creating a SatMapCoverage object.
*
* The following parameters are set in the spring configuraiton file alaskasat-ingest.xml and the
* dao and source members are set when the RegionalSatDecoder instance is initialized:
*
* * @param dao the data access object for satellite records
* * @param source the source of the satellite images (Alaska Region)
*/
public PluginDataObject[] decode(byte[] data) throws Exception {
PluginDataObject[] retData = null; private String source;
SatelliteRecord record = null; private String filename;
NetcdfFile netCdfFile = null; /**
* The decoder method uses the NetcdfFile API to retrieve the attributes and
* satellite image data from the Alaska Region and GOES-R Proving Ground
* netcdf3 files. These netcdf3 files are generated for use in Alaska and
* the metadata and data are specified by the requirements for the Alaska
* Region. Once the netcdf3 file is decoded, the metadata is stored in the
* Satellite table in Postgres and the image data is stored in the HDF5
* repository as Satellite records. The GIS map metadata is stored in the
* satellite_spatial table by creating a SatMapCoverage object.
*
* The following parameters are set in the spring configuraiton file
* alaskasat-ingest.xml and the dao and source members are set when the
* RegionalSatDecoder instance is initialized:
*
* * @param dao the data access object for satellite records * @param source
* the source of the satellite images (Alaska Region)
*/
public PluginDataObject[] decode(byte[] data) throws Exception {
if ((data != null) && (data.length > 0)) { PluginDataObject[] retData = null;
Calendar calendar = Calendar.getInstance(TimeZone SatelliteRecord record = null;
.getTimeZone("GMT"));
record = new SatelliteRecord(); NetcdfFile netCdfFile = null;
//String filename = "alaska_netcdf3"; // dummy filename; TODO: get filename from camel context? if ((data != null) && (data.length > 0)) {
netCdfFile = NetcdfFile.openInMemory(filename,data);
Calendar calendar = Calendar.getInstance(TimeZone
// set the source; Alaska Region .getTimeZone("GMT"));
if (source == null) {
source = "Source"; // use to look up source value; default of Source record = new SatelliteRecord();
}
record.setSource(getSource(source)); // lookup source value // String filename = "alaska_netcdf3"; // dummy filename; TODO: get
// filename from camel context?
// set the creating entity netCdfFile = NetcdfFile.openInMemory(filename, data);
// set the source; Alaska Region
if (source == null) {
source = "Source"; // use to look up source value; default of
// Source
}
record.setSource(getSource(source)); // lookup source value
// set the creating entity
Attribute satName = netCdfFile.findGlobalAttribute("satelliteName"); Attribute satName = netCdfFile.findGlobalAttribute("satelliteName");
String entity = null; //"HRPT"; "GOESR-PG"; "Blended2"; String entity = null; // "HRPT"; "GOESR-PG"; "Blended2";
if (satName != null) { if (satName != null) {
entity = satName.getStringValue(); entity = satName.getStringValue();
} }
if (entity != null) { if (entity != null) {
String parsed = getCreatingEntity(entity); String parsed = getCreatingEntity(entity);
if (parsed != null && parsed.length() > 0) { if (parsed != null && parsed.length() > 0) {
record.setCreatingEntity(parsed); record.setCreatingEntity(parsed);
} } else {
else { record.setCreatingEntity(entity);
record.setCreatingEntity(entity); }
} } else {
} record.setCreatingEntity("Unknown");
else {
record.setCreatingEntity("Unknown");
} // end of error block } // end of error block
// read the sector ID, may need to change to use satelliteSector attribute? // read the sector ID, may need to change to use satelliteSector
String sector = netCdfFile.findGlobalAttribute("depictorName").getStringValue().trim(); // attribute?
record.setSectorID(sector); String sector = netCdfFile.findGlobalAttribute("depictorName")
.getStringValue().trim();
record.setSectorID(sector);
// read and set the physical element // read and set the physical element
PhysicalElementValue pev = null; PhysicalElementValue pev = null;
Attribute chan = netCdfFile.findGlobalAttribute("channel"); Attribute chan = netCdfFile.findGlobalAttribute("channel");
if(chan != null) { if (chan != null) {
String channel = chan.getStringValue().trim(); String channel = chan.getStringValue().trim();
pev = getPhysicalElement(entity, channel); pev = getPhysicalElement(entity, channel);
String element = pev.name; String element = pev.name;
if (pev.name != null) { if (pev.name != null) {
record.setPhysicalElement(element); record.setPhysicalElement(element);
} else { } else {
record.setPhysicalElement(channel); record.setPhysicalElement(channel);
} }
} else { } else {
record.setPhysicalElement("Imager Visible"); record.setPhysicalElement("Imager Visible");
} }
// read and set the units (IRPixel, GenericPixel, ...)
// defined in physicalElements.xml lookup file
if(pev != null)
{
String units = pev.units;
if (pev.units != null) {
record.setUnits(units);
}
}
// read the number of records
int numRecords = netCdfFile.findDimension("y").getLength();
record.setNumRecords(numRecords); // read and set the units (IRPixel, GenericPixel, ...)
// defined in physicalElements.xml lookup file
if (pev != null) {
String units = pev.units;
if (pev.units != null) {
record.setUnits(units);
}
}
// read the size of each record // read the number of records
int recordSize = netCdfFile.findDimension("x").getLength(); int numRecords = netCdfFile.findDimension("y").getLength();
record.setSizeRecords(recordSize);
// read the valid time in seconds and store the time in milliseconds record.setNumRecords(numRecords);
long time = netCdfFile.findVariable("validTime").readScalarLong(); // time in seconds
calendar.setTimeInMillis(time * 1000); // need to convert seconds to milliseconds
/*
Date date = new Date(); // used for setting the test data time
long time = date.getTime();
calendar.setTimeInMillis(time); // need to convert seconds to millisconds
*/
record.setDataTime(new DataTime(calendar));
// set lov to central lon // read the size of each record
float lov = netCdfFile.findGlobalAttribute("centralLon").getNumericValue().floatValue(); int recordSize = netCdfFile.findDimension("x").getLength();
record.setSizeRecords(recordSize);
int mapProjection = 5; // STEREOGRAPHIC projection default // read the valid time in seconds and store the time in milliseconds
float latin = 0.0f; // set to zero for Stereographic projections long time = netCdfFile.findVariable("validTime").readScalarLong(); // time
float rotation = 0.0f; // in
// seconds
// read the projection calendar.setTimeInMillis(time * 1000); // need to convert seconds to
String projection = netCdfFile.findGlobalAttribute("projName").getStringValue().trim(); // milliseconds
if(!projection.equalsIgnoreCase("STEREOGRAPHIC"))
{
// get latin for projection from data
latin = netCdfFile.findGlobalAttribute("centralLat").getNumericValue().floatValue();
if(projection.equalsIgnoreCase("LAMBERT") || projection.equalsIgnoreCase("LAMBERT_CONFORMAL"))
{
mapProjection = 3;
}
else if(projection.equalsIgnoreCase("MERCATOR"))
{
mapProjection = 1;
}
else if(projection.equalsIgnoreCase("CYLINDRICAL_EQUIDISTANT"))
{
mapProjection = 7;
}
} else {
Attribute rot = netCdfFile.findGlobalAttribute("rotation");
if (rot != null) {
rotation = rot.getNumericValue().floatValue();
// STEREOGRAPHIC projection add rotation to lov
lov += rotation;
}
} // end of if projection block
// declare and initialize /*
float dx = 0.0f, dy = 0.0f, lo1 = 0.0f, la1 = 0.0f, lo2 = 0.0f, la2 = 0.0f; * Date date = new Date(); // used for setting the test data time
int nx = 0, ny = 0; * long time = date.getTime(); calendar.setTimeInMillis(time); //
* need to convert seconds to millisconds
// Do specialized decoding and retrieve spatial data for projections */
if ((mapProjection == 3) || (mapProjection == 5) || (mapProjection == 1) || (mapProjection == 7)) {
// set number of points along x-axis record.setDataTime(new DataTime(calendar));
nx = recordSize;
// set number of points along y-axis
ny = numRecords;
// read the image as byte data and store as byte array // set lov to central lon
record.setMessageData((byte []) netCdfFile.readSection("image").get1DJavaArray(Class.forName("java.lang.Byte"))); float lov = netCdfFile.findGlobalAttribute("centralLon")
.getNumericValue().floatValue();
// get the latitude of the first point, upper left corner int mapProjection = SatMapCoverage.PROJ_POLAR_STEREO; // STEREOGRAPHIC
la1 = netCdfFile.findGlobalAttribute("lat00").getNumericValue().floatValue(); // projection
// default
float latin = 0.0f; // set to zero for Stereographic projections
float rotation = 0.0f;
// get longitude of the first point, upper left corner // read the projection
lo1 = (netCdfFile.findGlobalAttribute("lon00").getNumericValue().floatValue()); String projection = netCdfFile.findGlobalAttribute("projName")
.getStringValue().trim();
if (!projection.equalsIgnoreCase("STEREOGRAPHIC")) {
// get latin for projection from data
latin = netCdfFile.findGlobalAttribute("centralLat")
.getNumericValue().floatValue();
if (projection.equalsIgnoreCase("LAMBERT")
|| projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) {
mapProjection = SatMapCoverage.PROJ_LAMBERT;
} else if (projection.equalsIgnoreCase("MERCATOR")) {
mapProjection = SatMapCoverage.PROJ_MERCATOR;
} else if (projection
.equalsIgnoreCase("CYLINDRICAL_EQUIDISTANT")) {
mapProjection = SatMapCoverage.PROJ_CYLIN_EQUIDISTANT;
}
// get the pixel spacing } else {
dx = netCdfFile.findGlobalAttribute("dxKm").getNumericValue().floatValue(); Attribute rot = netCdfFile.findGlobalAttribute("rotation");
dx *= 1000f; // convert to meters from km if (rot != null) {
dy = netCdfFile.findGlobalAttribute("dyKm").getNumericValue().floatValue(); rotation = rot.getNumericValue().floatValue();
dy *= 1000f; // convert to meters from km // STEREOGRAPHIC projection add rotation to lov
lov += rotation;
}
} // end of if projection block
la2 = netCdfFile.findGlobalAttribute("latNxNy").getNumericValue().floatValue(); // declare and initialize
lo2 = netCdfFile.findGlobalAttribute("lonNxNy").getNumericValue().floatValue(); float dx = 0.0f, dy = 0.0f, lo1 = 0.0f, la1 = 0.0f, lo2 = 0.0f, la2 = 0.0f;
} else { int nx = 0, ny = 0;
throw new DecoderException(
"Unable to decode Satellite: Encountered Unknown projection");
} // end of if map projection block
// Get latitude of upper right hand corner // Do specialized decoding and retrieve spatial data for projections
float urLat = 0; // not used so set to zero, if required get and set value if ((mapProjection == SatMapCoverage.PROJ_MERCATOR)
record.setUpperRightLat(urLat); || (mapProjection == SatMapCoverage.PROJ_LAMBERT)
|| (mapProjection == SatMapCoverage.PROJ_POLAR_STEREO)
|| (mapProjection == SatMapCoverage.PROJ_CYLIN_EQUIDISTANT)) {
// Get longitude of upper right hand corner // set number of points along x-axis
float urLon = 0; // not used so set to zero, if required get and set value nx = recordSize;
record.setUpperRightLon(urLon); // set number of points along y-axis
ny = numRecords;
SatMapCoverage mapCoverage = null; // read the image as byte data and store as byte array
record.setMessageData((byte[]) netCdfFile.readSection("image")
.get1DJavaArray(Class.forName("java.lang.Byte")));
try { // get the latitude of the first point, upper left corner
mapCoverage = RegionalSatSpatialFactory.getInstance() la1 = netCdfFile.findGlobalAttribute("lat00").getNumericValue()
.getMapCoverage(mapProjection, nx, ny, dx, dy, lov, .floatValue();
latin, la1, lo1, la2, lo2);
} catch (Exception e) {
StringBuffer buf = new StringBuffer();
buf
.append(
"Error getting or constructing SatMapCoverage for values: ")
.append("\n\t");
buf.append("mapProjection=" + mapProjection).append("\n\t");
buf.append("nx=" + nx).append("\n\t");
buf.append("ny=" + ny).append("\n\t");
buf.append("dx=" + dx).append("\n\t");
buf.append("dy=" + dy).append("\n\t");
buf.append("lov=" + lov).append("\n\t");
buf.append("latin=" + latin).append("\n\t");
buf.append("la1=" + la1).append("\n\t");
buf.append("lo1=" + lo1).append("\n\t");
buf.append("la2=" + la2).append("\n\t");
buf.append("lo2=" + lo2).append("\n");
throw new DecoderException(buf.toString(), e);
} // end of catch block
if (record != null) {
record.setTraceId(traceId);
record.setCoverage(mapCoverage);
record.setPersistenceTime(TimeTools.getSystemCalendar()
.getTime());
record.setPluginName("satellite");
record.constructDataURI();
} // end of if statement
} // end of if data not empty statement // get longitude of the first point, upper left corner
lo1 = (netCdfFile.findGlobalAttribute("lon00")
.getNumericValue().floatValue());
if (record == null) { // get the pixel spacing
retData = new PluginDataObject[0]; dx = netCdfFile.findGlobalAttribute("dxKm").getNumericValue()
} else { .floatValue();
retData = new PluginDataObject[] { record }; dx *= 1000f; // convert to meters from km
} dy = netCdfFile.findGlobalAttribute("dyKm").getNumericValue()
return retData; .floatValue();
} dy *= 1000f; // convert to meters from km
// uses lookup map instead of database to store creating entity parameter configuration la2 = netCdfFile.findGlobalAttribute("latNxNy")
private String getCreatingEntity(String name) { .getNumericValue().floatValue();
String value = RegionalSatLookups.getInstance().getCreatingEntity(name); lo2 = netCdfFile.findGlobalAttribute("lonNxNy")
return value != null ? value : String.format("Unknown-%s", name); .getNumericValue().floatValue();
} } else {
throw new DecoderException(
"Unable to decode Satellite: Encountered Unknown projection");
} // end of if map projection block
// uses lookup map instead of database to store physical element parameter configuration // Get latitude of upper right hand corner
private PhysicalElementValue getPhysicalElement(String satName, String channel) { float urLat = 0; // not used so set to zero, if required get and set
PhysicalElementValue value = RegionalSatLookups.getInstance().getPhysicalElement(satName, channel); // value
return value != null ? value : record.setUpperRightLat(urLat);
new PhysicalElementValue(String.format("Unknown-%s", channel), null);
}
// uses lookup map instead of database to store source parameter configuration // Get longitude of upper right hand corner
private String getSource(String name) { float urLon = 0; // not used so set to zero, if required get and set
String value = RegionalSatLookups.getInstance().getSource(name); // value
return value != null ? value : String.format("Unknown-%s", name); record.setUpperRightLon(urLon);
}
/** SatMapCoverage mapCoverage = null;
try {
mapCoverage = RegionalSatSpatialFactory.getInstance()
.getMapCoverage(mapProjection, nx, ny, dx, dy, lov,
latin, la1, lo1, la2, lo2);
} catch (Exception e) {
StringBuffer buf = new StringBuffer();
buf.append(
"Error getting or constructing SatMapCoverage for values: ")
.append("\n\t");
buf.append("mapProjection=" + mapProjection).append("\n\t");
buf.append("nx=" + nx).append("\n\t");
buf.append("ny=" + ny).append("\n\t");
buf.append("dx=" + dx).append("\n\t");
buf.append("dy=" + dy).append("\n\t");
buf.append("lov=" + lov).append("\n\t");
buf.append("latin=" + latin).append("\n\t");
buf.append("la1=" + la1).append("\n\t");
buf.append("lo1=" + lo1).append("\n\t");
buf.append("la2=" + la2).append("\n\t");
buf.append("lo2=" + lo2).append("\n");
throw new DecoderException(buf.toString(), e);
} // end of catch block
if (record != null) {
record.setTraceId(traceId);
record.setCoverage(mapCoverage);
record.setPersistenceTime(TimeTools.getSystemCalendar()
.getTime());
record.setPluginName("satellite");
record.constructDataURI();
} // end of if statement
} // end of if data not empty statement
if (record == null) {
retData = new PluginDataObject[0];
} else {
retData = new PluginDataObject[] { record };
}
return retData;
}
// uses lookup map instead of database to store creating entity parameter
// configuration
private String getCreatingEntity(String name) {
String value = RegionalSatLookups.getInstance().getCreatingEntity(name);
return value != null ? value : String.format("Unknown-%s", name);
}
// uses lookup map instead of database to store physical element parameter
// configuration
private PhysicalElementValue getPhysicalElement(String satName,
String channel) {
PhysicalElementValue value = RegionalSatLookups.getInstance()
.getPhysicalElement(satName, channel);
return value != null ? value : new PhysicalElementValue(String.format(
"Unknown-%s", channel), null);
}
// uses lookup map instead of database to store source parameter
// configuration
private String getSource(String name) {
String value = RegionalSatLookups.getInstance().getSource(name);
return value != null ? value : String.format("Unknown-%s", name);
}
/**
* @return dao the data access object for satellite records * @return dao the data access object for satellite records
*/ */
public SatelliteDao getDao() { public SatelliteDao getDao() {
return dao; return dao;
} }
/** /**
* @param dao * @param dao
* the data access object for satellite records * the data access object for satellite records
*/ */
public void setDao(SatelliteDao dao) { public void setDao(SatelliteDao dao) {
this.dao = dao; this.dao = dao;
} }
/** /**
* @return the source * @return the source
*/ */
public String getSource() { public String getSource() {
return source; return source;
} }
/** /**
* @param source * @param source
* the source of the satellite images (Alaska Region) * the source of the satellite images (Alaska Region)
*/ */
public void setSource(String source) { public void setSource(String source) {
this.source = source; this.source = source;
} }
/** /**
* @return the filename * @return the filename
*/ */
public String getFilename() { public String getFilename() {
return filename; return filename;
} }
/** /**
* @param filename * @param filename
* the filename of the netcdf3 file * the filename of the netcdf3 file
*/ */
public void setFilename(String file) { public void setFilename(String file) {
this.filename = file; this.filename = file;
} }
} }

View file

@ -37,7 +37,8 @@ import com.vividsolutions.jts.io.WKTReader;
* date Ticket# Engineer Description * date Ticket# Engineer Description
* ----------- ---------- ----------- -------------------------- * ----------- ---------- ----------- --------------------------
* 7/15/11 tk Initial Creation * 7/15/11 tk Initial Creation
* * - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* </pre> * </pre>
* *
* @author tk * @author tk
@ -179,13 +180,13 @@ public class RegionalSatSpatialFactory {
ProjectedCRS crs = null; ProjectedCRS crs = null;
// Get the correct CRS // Get the correct CRS
if (mapProjection == 1) { if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, lov); MapUtil.AWIPS_EARTH_RADIUS, latin, lov);
} else if (mapProjection == 3) { } else if (mapProjection == SatMapCoverage.PROJ_LAMBERT) {
crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov); MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov);
} else if (mapProjection == 7) { } else if (mapProjection == SatMapCoverage.PROJ_CYLIN_EQUIDISTANT) {
crs = MapUtil.constructEquidistantCylindrical(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructEquidistantCylindrical(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, lov, latin); MapUtil.AWIPS_EARTH_RADIUS, lov, latin);
} else { } else {