Issue #189 migrate d2d graph adapters to grid.

Former-commit-id: c2c32dd382 [formerly 6ffd19010837d81bf548863144f4c525ed332a7c]
Former-commit-id: 25d99f66f9
This commit is contained in:
Ben Steffensmeier 2012-09-25 13:19:17 -05:00
parent 8e5b20236d
commit 68877e66b2
5 changed files with 370 additions and 261 deletions

View file

@ -9,71 +9,33 @@ Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
Eclipse-BuddyPolicy: ext, global
Require-Bundle: org.eclipse.core.runtime,
com.raytheon.uf.viz.xy.crosssection;bundle-version="1.0.0",
com.raytheon.uf.viz.xy.timeheight;bundle-version="1.0.0",
com.raytheon.uf.viz.xy.varheight;bundle-version="1.12.1174"
com.raytheon.uf.viz.xy.varheight;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.xy;bundle-version="1.12.1174",
com.raytheon.viz.core;bundle-version="1.12.1174",
com.raytheon.viz.core.graphing;bundle-version="1.12.1174",
com.raytheon.uf.viz.xy.timeseries;bundle-version="1.12.1174",
javax.measure;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.raytheon.edex.plugin.bufrmos.common,
com.raytheon.edex.plugin.modelsounding.common,
com.raytheon.edex.util,
com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.dataplugin.acarssounding,
com.raytheon.uf.common.dataplugin.bufrua,
com.raytheon.uf.common.dataplugin.goessounding,
com.raytheon.uf.common.dataplugin.grib,
Import-Package: com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.dataplugin.grid,
com.raytheon.uf.common.dataplugin.level,
com.raytheon.uf.common.dataplugin.obs.metar,
com.raytheon.uf.common.dataplugin.profiler,
com.raytheon.uf.common.dataplugin.radar,
com.raytheon.uf.common.dataplugin.radar.util,
com.raytheon.uf.common.dataquery.requests,
com.raytheon.uf.common.datastorage,
com.raytheon.uf.common.datastorage.records,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.gridcoverage,
com.raytheon.uf.common.parameter,
com.raytheon.uf.common.pointdata,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.status,
com.raytheon.uf.common.time,
com.raytheon.uf.viz.core,
com.raytheon.uf.viz.core.catalog,
com.raytheon.uf.viz.core.datastructure,
com.raytheon.uf.viz.core.exception,
com.raytheon.uf.viz.core.interp,
com.raytheon.uf.viz.core.level,
com.raytheon.uf.viz.core.map,
com.raytheon.uf.viz.core.rsc,
com.raytheon.uf.viz.core.rsc.capabilities,
com.raytheon.uf.viz.core.style.level,
com.raytheon.uf.viz.d2d.xy.adapters,
com.raytheon.uf.viz.objectiveanalysis.rsc,
com.raytheon.uf.viz.xy,
com.raytheon.uf.viz.xy.crosssection.adapter,
com.raytheon.uf.viz.xy.crosssection.rsc,
com.raytheon.uf.viz.xy.graph,
com.raytheon.uf.viz.xy.timeseries.adapter,
com.raytheon.uf.viz.xy.timeseries.rsc,
com.raytheon.uf.viz.xy.varheight.adapter,
com.raytheon.uf.viz.xy.varheight.rsc,
com.raytheon.viz.core.graphing.util,
com.raytheon.viz.core.graphing.xy,
com.raytheon.viz.core.map,
com.raytheon.viz.core.slice.request,
com.raytheon.viz.grid,
com.raytheon.viz.grid.inv,
com.raytheon.viz.radar.util,
com.vividsolutions.jts.geom,
javax.measure.converter,
javax.measure.unit,
org.eclipse.swt.graphics,
org.geotools.coverage.grid,
org.geotools.geometry,
org.geotools.referencing,
org.geotools.referencing.operation.matrix,
org.geotools.referencing.operation.transform,
org.opengis.metadata.spatial,
org.opengis.referencing,
org.opengis.referencing.crs,
org.opengis.referencing.datum,
org.opengis.referencing.operation
org.eclipse.swt.graphics
Export-Package: com.raytheon.uf.viz.d2d.xy.adapters,
com.raytheon.uf.viz.d2d.xy.adapters.crosssection,
com.raytheon.uf.viz.d2d.xy.adapters.timeseries,

View file

@ -4,9 +4,9 @@
<extension
point="com.raytheon.uf.viz.xy.crosssection.crosssectionadapter">
<crossSectionAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.crosssection.GribCSAdapter"
class="com.raytheon.uf.common.dataplugin.grib.GribRecord"
name="Grib Cross Section Adapter">
adapter="com.raytheon.uf.viz.d2d.xy.adapters.crosssection.GridCSAdapter"
class="com.raytheon.uf.common.dataplugin.grid.GridRecord"
name="Grid Cross Section Adapter">
</crossSectionAdapter>
<crossSectionAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.crosssection.PointCSAdapter"
@ -60,9 +60,9 @@
<extension
point="com.raytheon.uf.viz.xy.timeseries.timeseriesadapter">
<timeSeriesAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.timeseries.GribTimeSeriesAdapter"
class="com.raytheon.uf.common.dataplugin.grib.GribRecord"
name="Grib Time Series Adapter">
adapter="com.raytheon.uf.viz.d2d.xy.adapters.timeseries.GridTimeSeriesAdapter"
class="com.raytheon.uf.common.dataplugin.grid.GridRecord"
name="Grid Time Series Adapter">
</timeSeriesAdapter>
<timeSeriesAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.timeseries.DmdTimeSeriesAdapter"
@ -126,9 +126,9 @@
<extension
point="com.raytheon.uf.viz.xy.varheight.varheightadapter">
<varHeightAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.varheight.GribVarHeightAdapter"
class="com.raytheon.uf.common.dataplugin.grib.GribRecord"
name="Grib Var Height Adapter">
adapter="com.raytheon.uf.viz.d2d.xy.adapters.varheight.GridVarHeightAdapter"
class="com.raytheon.uf.common.dataplugin.grid.GridRecord"
name="Grid Var Height Adapter">
</varHeightAdapter>
<varHeightAdapter
adapter="com.raytheon.uf.viz.d2d.xy.adapters.varheight.PointDataVarHeightAdapter"

View file

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.measure.unit.Unit;
@ -35,16 +36,15 @@ import org.geotools.geometry.DirectPosition2D;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grib.GribModel;
import com.raytheon.uf.common.dataplugin.grib.GribRecord;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.PointUtil;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
@ -60,7 +60,7 @@ import com.raytheon.viz.grid.inv.GridInventory;
import com.vividsolutions.jts.geom.Coordinate;
/**
* TODO Add Description
* Adapter providing CrossSections of grid data.
*
* <pre>
*
@ -78,18 +78,21 @@ import com.vividsolutions.jts.geom.Coordinate;
* @version 1.0
*/
public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
public class GridCSAdapter extends AbstractCrossSectionAdapter<GridRecord> {
private static final long serialVersionUID = 1L;
protected String yParameter = null;
protected Map<DataTime, Set<GribRecord>> yRecords = new HashMap<DataTime, Set<GribRecord>>();
protected Map<DataTime, Set<GridRecord>> yRecords = new HashMap<DataTime, Set<GridRecord>>();
private Unit<?> unit;
private CoordinateReferenceSystem crs;
private Map<GridCoverage, Map<DataTime, Rectangle>> rectangleCache = new HashMap<GridCoverage, Map<DataTime, Rectangle>>(
4);
/*
* (non-Javadoc)
*
@ -101,10 +104,9 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
public String getParameterName() {
String name = null;
if (records != null && !records.isEmpty()) {
GribModel modelInfo = records.get(0).getModelInfo();
name = modelInfo.getParameterName();
name = records.get(0).getParameter().getName();
if (name == null || name.isEmpty()) {
name = modelInfo.getParameterAbbreviation();
name = records.get(0).getParameter().getAbbreviation();
}
}
return name;
@ -134,13 +136,13 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
throws VizException {
DataTime recordTime = currentTime.clone();
recordTime.setLevelValue(null);
Set<GribRecord> yRecords = getYRecords(recordTime);
Map<Level, GribRecord> xMap = new HashMap<Level, GribRecord>();
Set<GridRecord> yRecords = getYRecords(recordTime);
Map<Level, GridRecord> xMap = new HashMap<Level, GridRecord>();
synchronized (records) {
for (GribRecord rec : records) {
for (GridRecord rec : records) {
if (rec.getDataTime().equals(recordTime)) {
xMap.put(rec.getModelInfo().getLevel(), rec);
xMap.put(rec.getLevel(), rec);
}
}
}
@ -149,10 +151,10 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
return null;
}
Map<Level, GribRecord> yMap = new HashMap<Level, GribRecord>();
for (GribRecord rec : yRecords) {
Map<Level, GridRecord> yMap = new HashMap<Level, GridRecord>();
for (GridRecord rec : yRecords) {
if (rec.getDataTime().equals(recordTime)) {
yMap.put(rec.getModelInfo().getLevel(), rec);
yMap.put(rec.getLevel(), rec);
}
}
@ -165,76 +167,66 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
int nx = (int) geometry.getGridRange2D().getWidth();
int ny = (int) geometry.getGridRange2D().getHeight();
ISpatialObject area = records.get(0).getSpatialObject();
Rectangle requestArea = null;
Coordinate[] coordinates = GeoUtil.splitLine(nx,
descriptor.getLine(currentTime).getCoordinates());
for (Coordinate c : coordinates) {
DirectPosition2D point = null;
try {
point = PointUtil.determineExactIndex(c, area.getCrs(),
MapUtil.getGridGeometry(area));
} catch (Exception e) {
throw new VizException(e);
}
if (requestArea == null) {
requestArea = new Rectangle((int) Math.floor(point.x),
(int) Math.floor(point.y), 1, 1);
} else {
requestArea.add(point);
Map<GridCoverage, List<PluginDataObject>> recordsByLocation = new HashMap<GridCoverage, List<PluginDataObject>>();
for (GridRecord record : xMap.values()) {
List<PluginDataObject> list = recordsByLocation.get(record
.getLocation());
if (list == null) {
list = new ArrayList<PluginDataObject>();
recordsByLocation.put(record.getLocation(), list);
}
list.add(record);
}
requestArea.height += 1;
requestArea.width += 1;
requestArea = requestArea.intersection(new Rectangle(0, 0,
area.getNx(), area.getNy()));
if (requestArea.isEmpty()) {
throw new VizException(
"Invalid line position. Check that the line is within the grib boundaries.");
}
Request request = Request.buildSlab(
new int[] { (int) requestArea.getMinX(),
(int) requestArea.getMinY() },
new int[] { (int) requestArea.getMaxX(),
(int) requestArea.getMaxY() });
List<PluginDataObject> pdos = new ArrayList<PluginDataObject>(
xMap.size() * 2);
pdos.addAll(xMap.values());
pdos.addAll(yMap.values());
DataCubeContainer.getDataRecords(pdos, request, null);
List<float[]> result = new ArrayList<float[]>();
for (int i = 0; i < nx; i++) {
DirectPosition2D point = null;
try {
point = PointUtil.determineExactIndex(coordinates[i],
area.getCrs(), MapUtil.getGridGeometry(area));
} catch (Exception e) {
throw new VizException(e);
for (GridRecord record : yMap.values()) {
List<PluginDataObject> list = recordsByLocation.get(record
.getLocation());
if (list == null) {
list = new ArrayList<PluginDataObject>();
recordsByLocation.put(record.getLocation(), list);
}
if (!requestArea.contains(point)) {
list.add(record);
}
for (Entry<GridCoverage, List<PluginDataObject>> entry : recordsByLocation
.entrySet()) {
Request request = getRequest(entry.getKey(), currentTime, geometry);
if (request == null) {
continue;
}
DataCubeContainer.getDataRecords(entry.getValue(), request, null);
}
Coordinate[] coordinates = GeoUtil.splitLine(nx,
descriptor.getLine(currentTime).getCoordinates());
List<float[]> result = new ArrayList<float[]>();
for (int i = 0; i < nx; i++) {
List<List<XYData>> dataLists = new ArrayList<List<XYData>>(
result.size());
for (Level level : xMap.keySet()) {
GribRecord yRecord = yMap.get(level);
GridRecord yRecord = yMap.get(level);
FloatDataRecord yRec = (FloatDataRecord) (((IDataRecord[]) yRecord
.getMessageData())[0]);
GribRecord xRecord = xMap.get(level);
GridRecord xRecord = xMap.get(level);
IDataRecord[] results = (IDataRecord[]) xRecord
.getMessageData();
float yVal = InterpUtils.getInterpolatedData(requestArea,
point.x, point.y, yRec.getFloatData());
DirectPosition2D yPoint = null;
try {
yPoint = PointUtil.determineExactIndex(coordinates[i],
yRecord.getLocation().getCrs(),
MapUtil.getGridGeometry(yRecord.getLocation()));
} catch (Exception e) {
throw new VizException(e);
}
Rectangle yRect = getRectangle(yRecord.getLocation(),
currentTime, geometry);
if (!yRect.contains(yPoint)) {
continue;
}
float yVal = InterpUtils.getInterpolatedData(yRect, yPoint.x,
yPoint.y, yRec.getFloatData());
yVal = (float) yRecord
.getModelInfo()
.getParameterUnitObject()
.getParameter()
.getUnit()
.getConverterTo(
descriptor.getHeightScale().getParameterUnit())
.convert(yVal);
@ -244,12 +236,23 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
while (dataLists.size() < results.length) {
dataLists.add(new ArrayList<XYData>());
}
double speed = Float.NaN;
double direction = Double.NaN;
DirectPosition2D xPoint = null;
try {
xPoint = PointUtil.determineExactIndex(coordinates[i],
xRecord.getLocation().getCrs(),
MapUtil.getGridGeometry(xRecord.getLocation()));
} catch (Exception e) {
throw new VizException(e);
}
Rectangle xRect = getRectangle(xRecord.getLocation(),
currentTime, geometry);
if (!xRect.contains(xPoint)) {
continue;
}
for (int c = 0; c < results.length; c++) {
FloatDataRecord xRec = (FloatDataRecord) results[c];
float xVal = InterpUtils.getInterpolatedData(requestArea,
point.x, point.y, xRec.getFloatData());
float xVal = InterpUtils.getInterpolatedData(xRect,
xPoint.x, xPoint.y, xRec.getFloatData());
if (xVal <= -9999) {
continue;
}
@ -267,20 +270,72 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
float[] column = InterpUtils.makeColumn(dataList, ny, graph,
descriptor.getHeightScale().getMinVal() < descriptor
.getHeightScale().getMaxVal(), -999999f);
for (int j = 0; j < column.length; j++) {
floatData[j * nx + i] = column[j];
}
}
}
return result;
}
private Rectangle getRectangle(GridCoverage location, DataTime time,
GridGeometry2D geometry) throws VizException {
Map<DataTime, Rectangle> timeCache = rectangleCache.get(location);
if (timeCache == null) {
timeCache = new HashMap<DataTime, Rectangle>();
rectangleCache.put(location, timeCache);
}
Rectangle rectangle = timeCache.get(time);
if (rectangle == null) {
Coordinate[] coordinates = GeoUtil.splitLine(geometry
.getGridRange2D().width, descriptor.getLine(time)
.getCoordinates());
for (Coordinate c : coordinates) {
DirectPosition2D point = null;
try {
point = PointUtil.determineExactIndex(c, location.getCrs(),
MapUtil.getGridGeometry(location));
} catch (Exception e) {
throw new VizException(e);
}
if (rectangle == null) {
rectangle = new Rectangle((int) Math.floor(point.x),
(int) Math.floor(point.y), 1, 1);
} else {
rectangle.add(point);
}
}
rectangle.height += 1;
rectangle.width += 1;
rectangle = rectangle.intersection(new Rectangle(0, 0, location
.getNx(), location.getNy()));
timeCache.put(time, rectangle);
}
return rectangle;
}
private Request getRequest(GridCoverage location, DataTime time,
GridGeometry2D geometry) throws VizException {
Rectangle rectangle = getRectangle(location, time, geometry);
if (rectangle.isEmpty()) {
return null;
}
return Request.buildSlab(
new int[] { (int) rectangle.getMinX(),
(int) rectangle.getMinY() },
new int[] { (int) rectangle.getMaxX(),
(int) rectangle.getMaxY() });
}
public void addRecord(PluginDataObject pdo) {
super.addRecord(pdo);
if (pdo != null && pdo instanceof GribRecord) {
unit = ((GribRecord) pdo).getModelInfo().getParameterUnitObject();
crs = ((GribRecord) pdo).getSpatialObject().getCrs();
if (pdo != null && pdo instanceof GridRecord) {
unit = ((GridRecord) pdo).getParameter().getUnit();
crs = ((GridRecord) pdo).getSpatialObject().getCrs();
}
yRecords.remove(pdo.getDataTime());
}
@ -290,9 +345,9 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
super.remove(time);
}
private Set<GribRecord> getYRecords(DataTime time) throws VizException {
private Set<GridRecord> getYRecords(DataTime time) throws VizException {
synchronized (yRecords) {
Set<GribRecord> yRecords = this.yRecords.get(time);
Set<GridRecord> yRecords = this.yRecords.get(time);
if (yRecords != null) {
return yRecords;
}
@ -313,9 +368,9 @@ public class GribCSAdapter extends AbstractCrossSectionAdapter<GribRecord> {
property.setSelectedEntryTimes(new DataTime[] { time });
List<Object> recs = DataCubeContainer.getData(property, 60000);
yRecords = new HashSet<GribRecord>(recs.size());
yRecords = new HashSet<GridRecord>(recs.size());
for (Object obj : recs) {
yRecords.add((GribRecord) obj);
yRecords.add((GridRecord) obj);
}
this.yRecords.put(time, yRecords);
if (yRecords.isEmpty()) {

View file

@ -23,6 +23,7 @@ import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
@ -31,13 +32,14 @@ import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grib.GribRecord;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.PointUtil;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
@ -54,7 +56,7 @@ import com.raytheon.viz.core.graphing.xy.XYWindImageData;
import com.raytheon.viz.grid.GridLevelTranslator;
/**
* TODO Add Description
* Adapter providing a TimeSeries view of GridData.
*
* <pre>
*
@ -69,14 +71,14 @@ import com.raytheon.viz.grid.GridLevelTranslator;
* @version 1.0
*/
public class GribTimeSeriesAdapter extends
AbstractTimeSeriesAdapter<GribRecord> {
public class GridTimeSeriesAdapter extends
AbstractTimeSeriesAdapter<GridRecord> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(GribTimeSeriesAdapter.class);
.getHandler(GridTimeSeriesAdapter.class);
private Map<GribRecord, IDataRecord[]> cache = new WeakHashMap<GribRecord, IDataRecord[]>();
private Map<GridRecord, IDataRecord[]> cache = new WeakHashMap<GridRecord, IDataRecord[]>();
protected Map<DataTime, Set<GribRecord>> recordsByTime = new HashMap<DataTime, Set<GribRecord>>();
protected Map<DataTime, Set<GridRecord>> recordsByTime = new HashMap<DataTime, Set<GridRecord>>();
/** the level I would prefer to use **/
protected Level preferredLevel = null;
@ -127,30 +129,29 @@ public class GribTimeSeriesAdapter extends
*/
@Override
public XYDataList loadData() throws VizException {
ArrayList<GribRecord> gribs = null;
ArrayList<GridRecord> gribs = null;
synchronized (recordsByTime) {
// get available times
Set<DataTime> times = recordsByTime.keySet();
// set initial size of gribs
gribs = new ArrayList<GribRecord>(times.size());
gribs = new ArrayList<GridRecord>(times.size());
// get the best record from each time ( use only one record for a
// point in time )
for (DataTime key : times) {
Set<GribRecord> records = recordsByTime.get(key);
GribRecord[] allRecords = records
.toArray(new GribRecord[records.size()]);
GribRecord bestRecord = null;
Set<GridRecord> records = recordsByTime.get(key);
GridRecord[] allRecords = records
.toArray(new GridRecord[records.size()]);
GridRecord bestRecord = null;
// if only one record, use it
if (allRecords.length == 1) {
bestRecord = allRecords[0];
} else if (records.size() > 1) {
// get the first record, or the one that matches the
// preferredLevel
for (GribRecord rec : allRecords) {
for (GridRecord rec : allRecords) {
if (bestRecord == null) {
bestRecord = rec;
} else if (rec.getModelInfo().getLevel()
.equals(preferredLevel)) {
} else if (rec.getLevel().equals(preferredLevel)) {
bestRecord = rec;
break;
}
@ -162,7 +163,26 @@ public class GribTimeSeriesAdapter extends
}
}
}
return loadInternal(gribs.toArray(new GribRecord[gribs.size()]));
HashMap<GridCoverage, List<GridRecord>> gridsByLocation = new HashMap<GridCoverage, List<GridRecord>>();
for (GridRecord grid : gribs) {
List<GridRecord> list = gridsByLocation.get(grid.getLocation());
if (list == null) {
list = new ArrayList<GridRecord>();
gridsByLocation.put(grid.getLocation(), list);
}
list.add(grid);
}
XYDataList result = null;
for (List<GridRecord> list : gridsByLocation.values()) {
XYDataList newResult = loadInternal(list
.toArray(new GridRecord[list.size()]));
if (result == null) {
result = newResult;
} else {
result.getData().addAll(newResult.getData());
}
}
return result;
}
@Override
@ -175,26 +195,25 @@ public class GribTimeSeriesAdapter extends
*/
@Override
public XYDataList loadRecord(PluginDataObject pdo) throws VizException {
GribRecord[] gribs = new GribRecord[1];
gribs[0] = (GribRecord) pdo;
GridRecord[] gribs = new GridRecord[1];
gribs[0] = (GridRecord) pdo;
return loadInternal(gribs);
}
@Override
public void addRecord(PluginDataObject pdo) {
// store off records by level
if (pdo instanceof GribRecord) {
if (pdo instanceof GridRecord) {
synchronized (recordsByTime) {
GribRecord record = (GribRecord) pdo;
GridRecord record = (GridRecord) pdo;
// set preferredLevel to first level
if (preferredLevel == null) {
preferredLevel = record.getModelInfo().getLevel();
preferredUnit = record.getModelInfo()
.getParameterUnitObject();
parameterName = record.getModelInfo().getParameterName();
parameterAbbreviation = record.getModelInfo()
.getParameterAbbreviation();
preferredLevel = record.getLevel();
preferredUnit = record.getParameter().getUnit();
parameterName = record.getParameter().getName();
parameterAbbreviation = record.getParameter()
.getAbbreviation();
if (parameterName == null || parameterName.isEmpty()) {
if (parameterAbbreviation == null) {
parameterAbbreviation = "";
@ -204,27 +223,27 @@ public class GribTimeSeriesAdapter extends
}
// add Unit to levelUnitMap if needed ( quick look-ups )
Level lvl = record.getModelInfo().getLevel();
Level lvl = record.getLevel();
Unit<?> unit = levelUnitMap.get(lvl);
if (unit == null) {
unit = record.getModelInfo().getParameterUnitObject();
unit = record.getParameter().getUnit();
levelUnitMap.put(lvl, unit);
}
// add record to records by time
Set<GribRecord> recordsAtTime = recordsByTime.get(record
Set<GridRecord> recordsAtTime = recordsByTime.get(record
.getDataTime());
if (recordsAtTime == null) {
recordsAtTime = new HashSet<GribRecord>();
recordsAtTime = new HashSet<GridRecord>();
recordsByTime.put(record.getDataTime(), recordsAtTime);
}
recordsAtTime.add(record);
}
} else {
// this shouldn't happen, code expects all pdo's for
// GribTimeSeriesAdapter to be GribRecords
// GribTimeSeriesAdapter to be GridRecords
String message = "Unexpected PluginDataObject type; got "
+ pdo.getClass().getName() + " expected GribRecord";
+ pdo.getClass().getName() + " expected GridRecord";
statusHandler.handle(Priority.PROBLEM, message, new Exception(
message));
}
@ -233,7 +252,7 @@ public class GribTimeSeriesAdapter extends
@Override
public boolean hasRecord(PluginDataObject pdo) {
synchronized (recordsByTime) {
Set<GribRecord> possibleRecords = recordsByTime.get(pdo
Set<GridRecord> possibleRecords = recordsByTime.get(pdo
.getDataTime());
if (possibleRecords != null && possibleRecords.contains(pdo)) {
return true;
@ -242,7 +261,7 @@ public class GribTimeSeriesAdapter extends
}
}
private XYDataList loadInternal(GribRecord[] gribs) throws VizException {
private XYDataList loadInternal(GridRecord[] gribs) throws VizException {
ArrayList<XYData> data = new ArrayList<XYData>();
ISpatialObject area = gribs[0].getSpatialObject();
@ -266,7 +285,7 @@ public class GribTimeSeriesAdapter extends
boolean isIcon = displayType == DisplayType.ICON;
for (GribRecord rec : gribs) {
for (GridRecord rec : gribs) {
IDataRecord[] records = cache.get(rec);
if (records == null) {
@ -278,15 +297,8 @@ public class GribTimeSeriesAdapter extends
// received a (wind) vector result
if (records.length > 1) {
double rotation = 0;
if ((rec.getResCompFlags() == null)
|| (rec.getResCompFlags() & 8) != 0) {
rotation = 180 - MapUtil.rotation(
resourceData.getCoordinate(),
rec.getSpatialObject());
}
float[] vectorDirections = (float[]) records[1].getDataObject();
vectorDirection = vectorDirections[0] + rotation;
vectorDirection = vectorDirections[0];
isVectorData = true;
}
@ -298,9 +310,8 @@ public class GribTimeSeriesAdapter extends
XYData dataPoint = null;
// do I need to convert?
if (!rec.getModelInfo().getLevel().equals(preferredLevel)) {
Unit<?> dataUnit = levelUnitMap.get(rec.getModelInfo()
.getLevel());
if (!rec.getLevel().equals(preferredLevel)) {
Unit<?> dataUnit = levelUnitMap.get(rec.getLevel());
if (!dataUnit.equals(preferredUnit)) {
// convert
UnitConverter conv = dataUnit.getConverterTo(preferredUnit);

View file

@ -21,10 +21,12 @@ package com.raytheon.uf.viz.d2d.xy.adapters.varheight;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.measure.unit.Unit;
@ -32,15 +34,17 @@ import javax.measure.unit.Unit;
import org.geotools.geometry.DirectPosition2D;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grib.GribRecord;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.PointUtil;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
@ -54,7 +58,8 @@ import com.raytheon.viz.core.slice.request.HeightScale;
import com.raytheon.viz.grid.inv.GridInventory;
/**
* TODO Add Description
* Adapter for Grid data that returns the value of a variable at multiple
* heights.
*
* <pre>
*
@ -69,9 +74,11 @@ import com.raytheon.viz.grid.inv.GridInventory;
* @version 1.0
*/
public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
public class GridVarHeightAdapter extends AbstractVarHeightAdapter<GridRecord> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(GridVarHeightAdapter.class);
protected HashMap<DataTime, Set<GribRecord>> yRecordMap = new HashMap<DataTime, Set<GribRecord>>();
protected HashMap<DataTime, Set<GridRecord>> yRecordMap = new HashMap<DataTime, Set<GridRecord>>();
/*
* (non-Javadoc)
@ -83,11 +90,11 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
@Override
public String getParameterName() {
synchronized (records) {
String name = ((GribRecord) records.iterator().next())
.getModelInfo().getParameterName();
String name = ((GridRecord) records.iterator().next())
.getParameter().getName();
if (name == null || name.isEmpty()) {
name = ((GribRecord) records.iterator().next()).getModelInfo()
.getParameterAbbreviation();
name = ((GridRecord) records.iterator().next()).getParameter()
.getAbbreviation();
}
return name;
@ -106,8 +113,8 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
if (records == null || records.size() == 0) {
return null;
}
return ((GribRecord) records.iterator().next()).getModelInfo()
.getParameterUnitObject();
return ((GridRecord) records.iterator().next()).getParameter()
.getUnit();
}
}
@ -126,10 +133,10 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
Set<DataTime> keys = yRecordMap.keySet();
for (DataTime key : keys) {
Set<GribRecord> aRecord = yRecordMap.get(key);
Set<GridRecord> aRecord = yRecordMap.get(key);
if (!aRecord.isEmpty()) {
return ((GribRecord) aRecord.iterator().next()).getModelInfo()
.getParameterUnitObject();
return ((GridRecord) aRecord.iterator().next()).getParameter()
.getUnit();
}
}
return null;
@ -146,33 +153,31 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
public List<XYData> loadData(DataTime currentTime) throws VizException {
populateYRecords();
ArrayList<GribRecord> needsRequested = new ArrayList<GribRecord>();
ArrayList<GridRecord> hasData = new ArrayList<GridRecord>(
records.size());
Map<Level, GribRecord> xMap = new HashMap<Level, GribRecord>();
ISpatialObject area = null;
Map<Level, GridRecord> xMap = new HashMap<Level, GridRecord>();
synchronized (records) {
for (GribRecord rec : records) {
area = rec.getSpatialObject();
for (GridRecord rec : records) {
if (rec.getDataTime().equals(currentTime)) {
xMap.put(rec.getModelInfo().getLevel(), rec);
if (rec.getMessageData() == null) {
needsRequested.add(rec);
xMap.put(rec.getLevel(), rec);
if (rec.getMessageData() != null) {
hasData.add(rec);
}
}
}
}
Map<Level, GribRecord> yMap = new HashMap<Level, GribRecord>();
Map<Level, GridRecord> yMap = new HashMap<Level, GridRecord>();
synchronized (yRecordMap) {
Set<GribRecord> yRecords = yRecordMap.get(currentTime);
Set<GridRecord> yRecords = yRecordMap.get(currentTime);
if (yRecords != null) {
for (GribRecord rec : yRecords) {
yMap.put(rec.getModelInfo().getLevel(), rec);
if (rec.getMessageData() == null) {
needsRequested.add(rec);
for (GridRecord rec : yRecords) {
yMap.put(rec.getLevel(), rec);
if (rec.getMessageData() != null) {
hasData.add(rec);
}
}
}
@ -188,62 +193,74 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
return dataList;
}
DirectPosition2D point = null;
try {
point = PointUtil.determineExactIndex(resourceData.getPoint(),
area.getCrs(), MapUtil.getGridGeometry(area));
} catch (Exception e) {
throw new VizException(e);
Map<GridCoverage, List<PluginDataObject>> recordsByLocation = new HashMap<GridCoverage, List<PluginDataObject>>(
4);
for (GridRecord record : xMap.values()) {
if (hasData.contains(record)) {
continue;
}
List<PluginDataObject> list = recordsByLocation.get(record
.getLocation());
if (list == null) {
list = new ArrayList<PluginDataObject>(xMap.size() * 2);
recordsByLocation.put(record.getLocation(), list);
}
list.add(record);
}
Rectangle requestArea = new Rectangle((int) Math.floor(point.x),
(int) Math.floor(point.y), 2, 2);
requestArea = requestArea.intersection(new Rectangle(0, 0,
area.getNx(), area.getNy()));
if (requestArea.isEmpty()) {
throw new VizException("Invalid point position("
+ resourceData.getPoint()
+ "). Check that the point is within the grib boundaries.");
for (GridRecord record : yMap.values()) {
if (hasData.contains(record)) {
continue;
}
List<PluginDataObject> list = recordsByLocation.get(record
.getLocation());
if (list == null) {
list = new ArrayList<PluginDataObject>(yMap.size());
recordsByLocation.put(record.getLocation(), list);
}
list.add(record);
}
Request request = Request.buildSlab(
new int[] { (int) requestArea.getMinX(),
(int) requestArea.getMinY() },
new int[] { (int) requestArea.getMaxX(),
(int) requestArea.getMaxY() });
List<PluginDataObject> pdos = new ArrayList<PluginDataObject>(
xMap.size() * 2);
pdos.addAll(xMap.values());
pdos.addAll(yMap.values());
for (Entry<GridCoverage, List<PluginDataObject>> entry : recordsByLocation
.entrySet()) {
Request request = getRequest(entry.getKey());
if (request == null) {
continue;
}
DataCubeContainer.getDataRecords(entry.getValue(), request, null);
// only request pdos without data
pdos.retainAll(needsRequested);
DataCubeContainer.getDataRecords(pdos, request, null);
}
for (Level level : xMap.keySet()) {
GribRecord yRecord = yMap.get(level);
GridRecord yRecord = yMap.get(level);
FloatDataRecord yRec = (FloatDataRecord) ((IDataRecord[]) yRecord
.getMessageData())[0];
float yVal = InterpUtils.getInterpolatedData(requestArea, point.x,
point.y, yRec.getFloatData());
DirectPosition2D yPoint = getPoint(yRecord.getLocation());
Rectangle yRect = getRectangle(yRecord.getLocation());
float yVal = InterpUtils.getInterpolatedData(yRect, yPoint.x,
yPoint.y, yRec.getFloatData());
if (yVal <= -9999) {
continue;
}
GribRecord xRecord = xMap.get(level);
GridRecord xRecord = xMap.get(level);
DirectPosition2D xPoint = getPoint(xRecord.getLocation());
Rectangle xRect = getRectangle(xRecord.getLocation());
IDataRecord[] results = ((IDataRecord[]) xRecord.getMessageData());
if (results.length == 4) {
if (results == null) {
continue;
} else if (results.length == 4) {
FloatDataRecord speedRec = (FloatDataRecord) results[0];
FloatDataRecord dirRec = (FloatDataRecord) results[1];
float speed = InterpUtils.getInterpolatedData(requestArea,
point.x, point.y, speedRec.getFloatData());
float dir = InterpUtils.getInterpolatedData(requestArea,
point.x, point.y, dirRec.getFloatData());
float speed = InterpUtils.getInterpolatedData(xRect, xPoint.x,
xPoint.y, speedRec.getFloatData());
float dir = InterpUtils.getInterpolatedData(xRect, xPoint.x,
xPoint.y, dirRec.getFloatData());
dataList.add(new XYWindImageData(speed, yVal, speed, dir));
} else {
FloatDataRecord xRec = (FloatDataRecord) results[0];
float xVal = InterpUtils.getInterpolatedData(requestArea,
point.x, point.y, xRec.getFloatData());
float xVal = InterpUtils.getInterpolatedData(xRect, xPoint.x,
xPoint.y, xRec.getFloatData());
if (xVal <= -9999) {
continue;
}
@ -251,9 +268,73 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
}
}
if (dataList.isEmpty()) {
statusHandler.handle(Priority.INFO, "No data found for point "
+ resourceData.getPoint() + ", at time " + currentTime
+ ", please verify point is within bounds of the data.");
return Collections.emptyList();
}
return dataList;
}
/**
* Retrive the coordinate in grid space(defined by location) where this
* adapter is expected to load data.
*
* @param location
* @return
* @throws VizException
*/
private DirectPosition2D getPoint(GridCoverage location)
throws VizException {
try {
return PointUtil.determineExactIndex(resourceData.getPoint(),
location.getCrs(), location.getGridGeometry());
} catch (Exception e) {
throw new VizException(e);
}
}
/**
* find the rectangle in grid space(defined by location) where this adapter
* should request data, the rectangle is formed by adding enough space
* around the point to perform bilinear interpolation.
*
* @param location
* @return
* @throws VizException
*/
private Rectangle getRectangle(GridCoverage location) throws VizException {
DirectPosition2D point = getPoint(location);
Rectangle rectangle = new Rectangle((int) Math.floor(point.x),
(int) Math.floor(point.y), 2, 2);
rectangle = rectangle.intersection(new Rectangle(0, 0,
location.getNx(), location.getNy()));
return rectangle;
}
/**
* Find the datastore request needed to get data for GridRecords with the
* provided location.
*
* @param location
* @return
* @throws VizException
*/
private Request getRequest(GridCoverage location) throws VizException {
Rectangle rectangle = getRectangle(location);
if (rectangle.isEmpty()) {
return null;
}
return Request.buildSlab(
new int[] { (int) rectangle.getMinX(),
(int) rectangle.getMinY() },
new int[] { (int) rectangle.getMaxX(),
(int) rectangle.getMaxY() });
}
public void addRecord(PluginDataObject pdo) {
DataTime key = pdo.getDataTime().clone();
key.setLevelValue(null);
@ -309,13 +390,13 @@ public class GribVarHeightAdapter extends AbstractVarHeightAdapter<GribRecord> {
List<Object> recs = DataCubeContainer.getData(property, 60000);
for (Object obj : recs) {
GribRecord gRecord = (GribRecord) obj;
Set<GribRecord> recordSet = yRecordMap.get(gRecord
GridRecord gRecord = (GridRecord) obj;
Set<GridRecord> recordSet = yRecordMap.get(gRecord
.getDataTime());
if (recordSet != null) {
recordSet.add(gRecord);
} else {
recordSet = new HashSet<GribRecord>();
recordSet = new HashSet<GridRecord>();
recordSet.add(gRecord);
yRecordMap.put(gRecord.getDataTime(), recordSet);
}