Omaha #3600 Implement getAvailableLevels() for radar to increase inventory performance.
Change-Id: I168bd135ae3ddd386761bb87b9160eb97f718642 Former-commit-id:863ac95fef
[formerly863ac95fef
[formerly 6f9709b43d307494dfa702030b961964ec8d2170]] Former-commit-id:a674630b92
Former-commit-id:c7805340b5
This commit is contained in:
parent
503e45d730
commit
7f68dff20a
2 changed files with 202 additions and 24 deletions
|
@ -20,6 +20,7 @@
|
|||
package com.raytheon.uf.common.dataplugin.radar.dataaccess;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -63,19 +64,19 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
import com.vividsolutions.jts.geom.Envelope;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A data factory for getting radar data from the metadata database. There are
|
||||
* currently not any required identifiers.
|
||||
*
|
||||
*
|
||||
* Radar does not return subgrids for request envelopes like other gridded
|
||||
* 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
|
||||
* products is complex and this is not often what a caller actually wants.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Jan 23, 2013 bsteffen Initial creation
|
||||
|
@ -86,9 +87,13 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
* Oct 28, 2014 3755 nabowle Implement getAvailableParameters, handle
|
||||
* empty parameters, fix error message, and
|
||||
* 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>
|
||||
*
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
@ -99,6 +104,10 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
|||
|
||||
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 LONGITUDE = "longitude";
|
||||
|
@ -111,9 +120,19 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
|||
|
||||
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(
|
||||
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 MasterLevel tiltLevel = null;
|
||||
|
@ -144,8 +163,7 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
|||
.toString());
|
||||
}
|
||||
defaultGridData.setUnit(radarRecord.getDataUnit());
|
||||
defaultGridData.setLevel(getTiltLevel(radarRecord
|
||||
.getPrimaryElevationAngle()));
|
||||
defaultGridData.setLevel(getLevel(radarRecord, request));
|
||||
defaultGridData.setLocationName(generateLocationName(radarRecord));
|
||||
|
||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||
|
@ -157,6 +175,51 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
|||
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
|
||||
* 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) {
|
||||
RequestConstraint angleConstraint = new RequestConstraint(null,
|
||||
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) {
|
||||
angleConstraint.addToConstraintValueList(level
|
||||
.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();
|
||||
|
@ -456,9 +537,83 @@ public class RadarGridFactory extends AbstractGridDataPluginFactory implements
|
|||
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
|
||||
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
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 2014-10-27 3600 nabowle Initial modification. Convert to DAF.
|
||||
# 2014-12-18 3600 nabowle Use new getAvailableLevels() to speed up retrieval.
|
||||
#
|
||||
|
||||
import argparse
|
||||
|
@ -102,20 +103,37 @@ def main():
|
|||
if timeRange:
|
||||
tr = timeRange
|
||||
else:
|
||||
tr = []
|
||||
tr = None
|
||||
lines = set()
|
||||
radars = DataAccessLayer.getGridData(req, tr)
|
||||
for radar in radars:
|
||||
line = ""
|
||||
if user_args.outputDate:
|
||||
line = str(radar.getDataTime()) + ".0"
|
||||
if user_args.outputAngle:
|
||||
line += " "
|
||||
if user_args.outputAngle == "true":
|
||||
line += "%.1f"%float(radar.getLocationName().split("_")[1])
|
||||
elif user_args.outputAngle == "primary":
|
||||
line += radar.getLevel()[0:3] #Trim "TILT"
|
||||
lines.add(line)
|
||||
|
||||
if user_args.outputAngle:
|
||||
levels = DataAccessLayer.getAvailableLevels(req)
|
||||
for level in levels:
|
||||
line = ""
|
||||
req.setLevels(level)
|
||||
if user_args.outputDate:
|
||||
times = DataAccessLayer.getAvailableTimes(req)
|
||||
for time in times:
|
||||
if not tr or tr.contains(time.getValidPeriod()):
|
||||
line = str(time) + ".0"
|
||||
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)
|
||||
else: #retrieve available product codes
|
||||
unfiltered = DataAccessLayer.getAvailableParameters(req)
|
||||
|
@ -158,6 +176,11 @@ def create_request(user_args):
|
|||
level = Level()
|
||||
level.setLevelonevalue(user_args.angle)
|
||||
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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue