Omaha #3600 Implement getAvailableLevels() for radar to increase inventory performance.
Change-Id: I168bd135ae3ddd386761bb87b9160eb97f718642 Former-commit-id: 6f9709b43d307494dfa702030b961964ec8d2170
This commit is contained in:
parent
67818d5e8f
commit
a674630b92
2 changed files with 202 additions and 24 deletions
|
@ -20,6 +20,7 @@
|
||||||
package com.raytheon.uf.common.dataplugin.radar.dataaccess;
|
package com.raytheon.uf.common.dataplugin.radar.dataaccess;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -63,19 +64,19 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
import com.vividsolutions.jts.geom.Envelope;
|
import com.vividsolutions.jts.geom.Envelope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* A data factory for getting radar data from the metadata database. There are
|
* A data factory for getting radar data from the metadata database. There are
|
||||||
* currently not any required identifiers.
|
* currently not any required identifiers.
|
||||||
*
|
*
|
||||||
* Radar does not return subgrids for request envelopes like other gridded
|
* Radar does not return subgrids for request envelopes like other gridded
|
||||||
* types. Instead data for only icaos within the request envelope are returned
|
* types. Instead data for only icaos within the request envelope are returned
|
||||||
* and all data for the product is used. This is done because subgridding radial
|
* and all data for the product is used. This is done because subgridding radial
|
||||||
* products is complex and this is not often what a caller actually wants.
|
* products is complex and this is not often what a caller actually wants.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
* SOFTWARE HISTORY
|
* SOFTWARE HISTORY
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------- -------- ----------- --------------------------
|
* ------------- -------- ----------- --------------------------
|
||||||
* Jan 23, 2013 bsteffen Initial creation
|
* Jan 23, 2013 bsteffen Initial creation
|
||||||
|
@ -86,9 +87,13 @@ import com.vividsolutions.jts.geom.Envelope;
|
||||||
* Oct 28, 2014 3755 nabowle Implement getAvailableParameters, handle
|
* Oct 28, 2014 3755 nabowle Implement getAvailableParameters, handle
|
||||||
* empty parameters, fix error message, and
|
* empty parameters, fix error message, and
|
||||||
* handle dataless radial radars.
|
* handle dataless radial radars.
|
||||||
*
|
* Dec 18, 2014 3600 nabowle Implement getAvailableLevels and add
|
||||||
|
* optional identifiers to indicate what
|
||||||
|
* fields are used for the level one and two
|
||||||
|
* values.
|
||||||
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author bsteffen
|
* @author bsteffen
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +104,10 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
|
|
||||||
private static final String PRIMARY_ANGLE = "primaryElevationAngle";
|
private static final String PRIMARY_ANGLE = "primaryElevationAngle";
|
||||||
|
|
||||||
|
private static final String TRUE_ANGLE = "trueElevationAngle";
|
||||||
|
|
||||||
|
private static final String ELEVATION_NUMBER = "elevationNumber";
|
||||||
|
|
||||||
private static final String ICAO = "icao";
|
private static final String ICAO = "icao";
|
||||||
|
|
||||||
private static final String LONGITUDE = "longitude";
|
private static final String LONGITUDE = "longitude";
|
||||||
|
@ -111,9 +120,19 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
|
|
||||||
private static final String RASTER_FORMAT = "Raster";
|
private static final String RASTER_FORMAT = "Raster";
|
||||||
|
|
||||||
|
private static final String LEVEL_ONE = "level.one.field";
|
||||||
|
|
||||||
|
private static final String LEVEL_TWO = "level.two.field";
|
||||||
|
|
||||||
private static final List<String> SUPPORTED_FORMATS = Arrays.asList(
|
private static final List<String> SUPPORTED_FORMATS = Arrays.asList(
|
||||||
RADIAL_FORMAT, RASTER_FORMAT);
|
RADIAL_FORMAT, RASTER_FORMAT);
|
||||||
|
|
||||||
|
private static final List<String> SUPPORTED_LEVELS = Arrays.asList(
|
||||||
|
PRIMARY_ANGLE, TRUE_ANGLE, ELEVATION_NUMBER);
|
||||||
|
|
||||||
|
private static final String LEVEL_ERROR = " must be " + PRIMARY_ANGLE
|
||||||
|
+ ", " + TRUE_ANGLE + ", or " + ELEVATION_NUMBER;
|
||||||
|
|
||||||
private static RadarInfoDict radarInfo = null;
|
private static RadarInfoDict radarInfo = null;
|
||||||
|
|
||||||
private static MasterLevel tiltLevel = null;
|
private static MasterLevel tiltLevel = null;
|
||||||
|
@ -144,8 +163,7 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
.toString());
|
.toString());
|
||||||
}
|
}
|
||||||
defaultGridData.setUnit(radarRecord.getDataUnit());
|
defaultGridData.setUnit(radarRecord.getDataUnit());
|
||||||
defaultGridData.setLevel(getTiltLevel(radarRecord
|
defaultGridData.setLevel(getLevel(radarRecord, request));
|
||||||
.getPrimaryElevationAngle()));
|
|
||||||
defaultGridData.setLocationName(generateLocationName(radarRecord));
|
defaultGridData.setLocationName(generateLocationName(radarRecord));
|
||||||
|
|
||||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||||
|
@ -157,6 +175,51 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
return defaultGridData;
|
return defaultGridData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the level for the radar record. If the request specifies
|
||||||
|
* {@value #LEVEL_ONE} or {@value #LEVEL_TWO} identifiers, those fields will
|
||||||
|
* be used. If {@value #LEVEL_ONE} is not specified, {@value #PRIMARY_ANGLE}
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param radarRecord
|
||||||
|
* The radar record.
|
||||||
|
* @param request
|
||||||
|
* The request.
|
||||||
|
* @return The created level.
|
||||||
|
*/
|
||||||
|
private Level getLevel(RadarRecord radarRecord, IDataRequest request) {
|
||||||
|
Map<String, Object> identifiers = request.getIdentifiers();
|
||||||
|
String levelOneField = (String) identifiers.get(LEVEL_ONE);
|
||||||
|
String levelTwoField = (String) identifiers.get(LEVEL_TWO);
|
||||||
|
|
||||||
|
if (levelOneField == null) {
|
||||||
|
levelOneField = PRIMARY_ANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Level level;
|
||||||
|
if (PRIMARY_ANGLE.equals(levelOneField)) {
|
||||||
|
level = getTiltLevel(radarRecord.getPrimaryElevationAngle());
|
||||||
|
} else if (TRUE_ANGLE.equals(levelOneField)) {
|
||||||
|
level = getTiltLevel(radarRecord.getTrueElevationAngle());
|
||||||
|
} else { // elevationNumber
|
||||||
|
level = new Level();
|
||||||
|
level.setMasterLevel(new MasterLevel("OSEQD"));
|
||||||
|
level.setLevelonevalue(radarRecord.getElevationNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelTwoField != null) {
|
||||||
|
if (PRIMARY_ANGLE.equals(levelTwoField)) {
|
||||||
|
level.setLeveltwovalue(radarRecord.getPrimaryElevationAngle());
|
||||||
|
} else if (TRUE_ANGLE.equals(levelTwoField)) {
|
||||||
|
level.setLeveltwovalue(radarRecord.getTrueElevationAngle());
|
||||||
|
} else { // elevationNumber
|
||||||
|
level.setLeveltwovalue(radarRecord.getElevationNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a unique name describing the location of the radar data. The name
|
* Get a unique name describing the location of the radar data. The name
|
||||||
* always includes icao, elevation angle, num bins and num radials. For
|
* always includes icao, elevation angle, num bins and num radials. For
|
||||||
|
@ -335,11 +398,29 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
if (levels != null && levels.length > 0) {
|
if (levels != null && levels.length > 0) {
|
||||||
RequestConstraint angleConstraint = new RequestConstraint(null,
|
RequestConstraint angleConstraint = new RequestConstraint(null,
|
||||||
ConstraintType.IN);
|
ConstraintType.IN);
|
||||||
|
RequestConstraint levelTwoConstraint = new RequestConstraint(null,
|
||||||
|
ConstraintType.IN);
|
||||||
|
|
||||||
|
Map<String, Object> identifiers = request.getIdentifiers();
|
||||||
|
String levelOneField = (String) identifiers.get(LEVEL_ONE);
|
||||||
|
String levelTwoField = (String) identifiers.get(LEVEL_TWO);
|
||||||
|
|
||||||
|
if (levelOneField == null) {
|
||||||
|
levelOneField = PRIMARY_ANGLE;
|
||||||
|
}
|
||||||
for (Level level : levels) {
|
for (Level level : levels) {
|
||||||
angleConstraint.addToConstraintValueList(level
|
angleConstraint.addToConstraintValueList(level
|
||||||
.getLevelOneValueAsString());
|
.getLevelOneValueAsString());
|
||||||
|
if (levelTwoField != null
|
||||||
|
&& level.getLeveltwovalue() != Level.INVALID_VALUE) {
|
||||||
|
levelTwoConstraint.addToConstraintValueList(level
|
||||||
|
.getLevelTwoValueAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constraints.put(levelOneField, angleConstraint);
|
||||||
|
if (levelTwoConstraint.getConstraintValue() != null) {
|
||||||
|
constraints.put(levelTwoField, levelTwoConstraint);
|
||||||
}
|
}
|
||||||
constraints.put(PRIMARY_ANGLE, angleConstraint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] locations = request.getLocationNames();
|
String[] locations = request.getLocationNames();
|
||||||
|
@ -456,9 +537,83 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
||||||
return parameters.toArray(new String[0]);
|
return parameters.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the available levels. The optional identifiers, {@value #LEVEL_ONE}
|
||||||
|
* and {@value #LEVEL_TWO} can be supplied to choose which level fields are
|
||||||
|
* returned, otherwise {@value #PRIMARY_ANGLE} will be returned as the level
|
||||||
|
* one value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Level[] getAvailableLevels(IDataRequest request) {
|
||||||
|
DbQueryRequest dbQueryRequest = buildDbQueryRequest(request);
|
||||||
|
dbQueryRequest.setDistinct(Boolean.TRUE);
|
||||||
|
|
||||||
|
Map<String, Object> identifiers = request.getIdentifiers();
|
||||||
|
String levelOneField = (String) identifiers.get(LEVEL_ONE);
|
||||||
|
String levelTwoField = (String) identifiers.get(LEVEL_TWO);
|
||||||
|
|
||||||
|
if (levelOneField == null) {
|
||||||
|
levelOneField = PRIMARY_ANGLE;
|
||||||
|
}
|
||||||
|
dbQueryRequest.addRequestField(levelOneField);
|
||||||
|
if (levelTwoField != null) {
|
||||||
|
dbQueryRequest.addRequestField(levelTwoField);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbQueryResponse dbQueryResponse = this.executeDbQueryRequest(
|
||||||
|
dbQueryRequest, request.toString());
|
||||||
|
Level level;
|
||||||
|
List<Level> levels = new ArrayList<>();
|
||||||
|
for (Map<String, Object> result : dbQueryResponse.getResults()) {
|
||||||
|
if (PRIMARY_ANGLE.equals(levelOneField)
|
||||||
|
|| TRUE_ANGLE.equals(levelTwoField)) {
|
||||||
|
level = getTiltLevel(Double.valueOf(result.get(levelOneField)
|
||||||
|
.toString()));
|
||||||
|
} else {
|
||||||
|
level = new Level();
|
||||||
|
level.setMasterLevel(new MasterLevel("OSEQD"));
|
||||||
|
level.setLevelonevalue(Double.valueOf(result.get(levelOneField)
|
||||||
|
.toString()));
|
||||||
|
}
|
||||||
|
if (levelTwoField != null) {
|
||||||
|
level.setLeveltwovalue(Double.valueOf(result.get(levelTwoField)
|
||||||
|
.toString()));
|
||||||
|
}
|
||||||
|
levels.add(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
return levels.toArray(new Level[0]);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getOptionalIdentifiers() {
|
public String[] getOptionalIdentifiers() {
|
||||||
return new String[] { ICAO };
|
return new String[] { ICAO, LEVEL_ONE, LEVEL_TWO };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DbQueryRequest buildDbQueryRequest(IDataRequest request) {
|
||||||
|
validateLevelIdentifiers(request);
|
||||||
|
return super.buildDbQueryRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that, if specified, the {@value #LEVEL_ONE} and
|
||||||
|
* {@value #LEVEL_TWO} identifier values are supported.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
private void validateLevelIdentifiers(IDataRequest request) {
|
||||||
|
Map<String, Object> identifiers = request.getIdentifiers();
|
||||||
|
String levelOneField = (String) identifiers.get(LEVEL_ONE);
|
||||||
|
String levelTwoField = (String) identifiers.get(LEVEL_TWO);
|
||||||
|
|
||||||
|
if (levelOneField != null && !SUPPORTED_LEVELS.contains(levelOneField)) {
|
||||||
|
throw new DataRetrievalException(LEVEL_ONE + LEVEL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelTwoField != null && !SUPPORTED_LEVELS.contains(levelTwoField)) {
|
||||||
|
throw new DataRetrievalException(LEVEL_TWO + LEVEL_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
# Date Ticket# Engineer Description
|
# Date Ticket# Engineer Description
|
||||||
# ------------ ---------- ----------- --------------------------
|
# ------------ ---------- ----------- --------------------------
|
||||||
# 2014-10-27 3600 nabowle Initial modification. Convert to DAF.
|
# 2014-10-27 3600 nabowle Initial modification. Convert to DAF.
|
||||||
|
# 2014-12-18 3600 nabowle Use new getAvailableLevels() to speed up retrieval.
|
||||||
#
|
#
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
@ -102,20 +103,37 @@ def main():
|
||||||
if timeRange:
|
if timeRange:
|
||||||
tr = timeRange
|
tr = timeRange
|
||||||
else:
|
else:
|
||||||
tr = []
|
tr = None
|
||||||
lines = set()
|
lines = set()
|
||||||
radars = DataAccessLayer.getGridData(req, tr)
|
|
||||||
for radar in radars:
|
if user_args.outputAngle:
|
||||||
line = ""
|
levels = DataAccessLayer.getAvailableLevels(req)
|
||||||
if user_args.outputDate:
|
for level in levels:
|
||||||
line = str(radar.getDataTime()) + ".0"
|
line = ""
|
||||||
if user_args.outputAngle:
|
req.setLevels(level)
|
||||||
line += " "
|
if user_args.outputDate:
|
||||||
if user_args.outputAngle == "true":
|
times = DataAccessLayer.getAvailableTimes(req)
|
||||||
line += "%.1f"%float(radar.getLocationName().split("_")[1])
|
for time in times:
|
||||||
elif user_args.outputAngle == "primary":
|
if not tr or tr.contains(time.getValidPeriod()):
|
||||||
line += radar.getLevel()[0:3] #Trim "TILT"
|
line = str(time) + ".0"
|
||||||
lines.add(line)
|
line += " "
|
||||||
|
if user_args.outputAngle == "true":
|
||||||
|
line += "%.1f"%level.getLeveltwovalue()
|
||||||
|
else:
|
||||||
|
line += "%.1f"%level.getLevelonevalue()
|
||||||
|
lines.add(line)
|
||||||
|
else:
|
||||||
|
if not tr or data_in_time_range(req, tr):
|
||||||
|
if user_args.outputAngle == "true":
|
||||||
|
line = "%.1f"%level.getLeveltwovalue()
|
||||||
|
else:
|
||||||
|
line = "%.1f"%level.getLevelonevalue()
|
||||||
|
lines.add(line)
|
||||||
|
else : # just output time
|
||||||
|
times = DataAccessLayer.getAvailableTimes(req)
|
||||||
|
for time in times:
|
||||||
|
if not tr or tr.contains(time.getValidPeriod()):
|
||||||
|
lines.add(str(time) + ".0")
|
||||||
msg = "\n".join(lines)
|
msg = "\n".join(lines)
|
||||||
else: #retrieve available product codes
|
else: #retrieve available product codes
|
||||||
unfiltered = DataAccessLayer.getAvailableParameters(req)
|
unfiltered = DataAccessLayer.getAvailableParameters(req)
|
||||||
|
@ -158,6 +176,11 @@ def create_request(user_args):
|
||||||
level = Level()
|
level = Level()
|
||||||
level.setLevelonevalue(user_args.angle)
|
level.setLevelonevalue(user_args.angle)
|
||||||
req.setLevels(level)
|
req.setLevels(level)
|
||||||
|
# Indicate that when providing or requesting levels, the Levelonevalue
|
||||||
|
# is the primaryElevationAngle and the Leveltwovalue value is the
|
||||||
|
# trueElevationAngle
|
||||||
|
req.addIdentifier("level.one.field", "primaryElevationAngle")
|
||||||
|
req.addIdentifier("level.two.field", "trueElevationAngle")
|
||||||
|
|
||||||
return req
|
return req
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue