VLab Issue #3864 - NCuair plugin improvements

Decoded mandatory level even if stations not reporting all mandatory
levels; fixed interpolated level winds; used reftime instead of synoptic
time in data retrieval for Nsharp. Thus some sounding profile may
display as 11Z

Change-Id: Id5c0fcb296f71eaa0d020d2dd4bfac1b512b552f

Former-commit-id: 54a730a11f [formerly 0f5f541687] [formerly 006e7e7a6c [formerly 0ba40f87cc2398fd4a63ec3bc03d9814ff692c5f]]
Former-commit-id: 006e7e7a6c
Former-commit-id: 3e871ed397
This commit is contained in:
Stephen Gilbert 2014-06-16 16:03:12 -04:00
parent 4359758262
commit 33b4d4bd5c
4 changed files with 2827 additions and 2561 deletions

View file

@ -15,6 +15,8 @@
* 03/2010 210 L. Lin Initial coding
* 09/2011 457 S. Gurung Renamed H5 to Nc and h5 to nc
* 10/2011 S. Gurung Use updated getElevation() method
* 6/2014 T. Lee Decoded mandatory levels even if stations
* do not report all man levels
*
* </pre>
*
@ -29,181 +31,206 @@ import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairRecord;
import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN;
public class NcUairPressureHeightGroup {
private static float pressure;
private static float height;
public static float getPressure() {
return pressure;
}
public static void setPressure(float pressure) {
NcUairPressureHeightGroup.pressure = pressure;
}
private static float pressure;
public static float getHeight() {
return height;
}
private static float height;
public static void setHeight(float height) {
NcUairPressureHeightGroup.height = height;
}
public static float getPressure() {
return pressure;
}
/**
* Decodes pressure and height data
*
* @param presGroup The input pressure code group
* @param above The input above is flag
* @param level the input pressure level
* @param stationNumber The input station number
* @param dataType The input data type
* @return
*/
public static void PressureHeightField(String presGroup, Boolean above,
int level, String stationNumber, String dataType, NcUairRecord record) {
pressure = IDecoderConstantsN.UAIR_FLOAT_MISSING;
height = IDecoderConstantsN.UAIR_FLOAT_MISSING;
int iabove = 0;
int ipres = IDecoderConstantsN.UAIR_INTEGER_MISSING;
int ihhh = IDecoderConstantsN.UAIR_INTEGER_MISSING;
Boolean drop = false;
Boolean ship = false;
public static void setPressure(float pressure) {
NcUairPressureHeightGroup.pressure = pressure;
}
String pressValue[][] = { { "99", "00", "92", "85", "70", "50",
"40", "30", "25", "20", "15", "10" },
{ "70", "50", "30", "20", "10", "07",
"05", "03", "02", "01", "xx" , "//"}
};
if ( dataType.substring(0,2).equals("XX") ) {
// dropsonde data
drop = true;
} else if ( dataType.substring(0,2).equals("UU") ) {
// ship data
ship = true;
}
if (above) {
iabove =1;
}
public static float getHeight() {
return height;
}
if ( presGroup.length() == 5 && ( level < 12 )) {
String pp = presGroup.substring(0,2);
String hhh = presGroup.substring(2,5);
if (pp.equals(pressValue[iabove][level])) {
if ( ! pp.equals("//") ) {
ipres = Integer.parseInt(pp);
}
if ( ! hhh.equals("///") ) {
ihhh = Integer.parseInt(hhh);
}
if (! above) {
/*
* Encoded pressure was pressure / 10. 00 is 1000.
* Above 100mb, encoded pressure is whole number.
*/
if ( ipres != IDecoderConstantsN.UAIR_INTEGER_MISSING ) {
ipres = ipres * 10;
if ( ipres == 0 ) {
ipres = 1000;
}
//Take care of the 925 mb level, which comes in as 920.
if ( ipres == 920 ) {
ipres = 925;
}
pressure = ipres;
}
public static void setHeight(float height) {
NcUairPressureHeightGroup.height = height;
}
/*
* For data below 100 mb, use the pressure to decode the
* height. This algorithm is from the U. of Wisconsin and
* differs slightly from the PROFS algorithm.
*/
if ( ihhh != IDecoderConstantsN.UAIR_INTEGER_MISSING ) {
height = ihhh;
if ( (ipres == 1000) && (height > 500)) {
height = 500 - height;
} else if ( (ipres == 925) && (height < 200) && (! drop) ) {
height = height + 1000;
} else if ( (ipres == 850) && (height < 900) ) {
height = height + 1000;
} else if ( (ipres == 700) && (height < 500) ) {
height = height + 3000;
} else if ( ipres == 700 ) {
height = height + 2000;
} else if ( ipres <= 500 ) {
ihhh = ihhh * 10;
height = height * 10;
if ( (ipres == 300) && (ihhh < 3000) ) {
height = height + 10000;
} else if ( (ipres == 250) && (ihhh < 5000) ) {
height = height + 10000;
} else if ( (ipres == 200) && (ihhh < 7000) ) {
height = height + 10000;
} else if (ipres <= 150) {
height = height + 10000;
}
}
}
} else {
pressure = ipres;
/*
* Compute the height above 100 mb. The ten thousands digit
* is added here. The value may need to be changed in the
* future if it proves incorrect.
*/
if ( ihhh != IDecoderConstantsN.UAIR_INTEGER_MISSING ) {
ihhh = ihhh * 10;
height = ihhh;
if ( ipres == 70 ) {
height = height + 10000;
} else if ( (ipres == 50) && (ihhh >= 8000)) {
height = height + 10000;
} else if ( (ipres == 50) && (height < 8000) ) {
height = height + 20000;
} else if ( ipres >= 20 ) {
height = height + 20000;
} else if ( (ipres == 10) && (height > 8000) ) {
height = height + 20000;
} else if ( (ipres == 10) && (height < 8000) ) {
height = height + 30000;
} else if ( ipres >= 3 ) {
height = height + 30000;
} else if ( (ipres == 2) && (height > 8000) ) {
height = height + 30000;
} else if ( (ipres == 2) && (height < 8000) ) {
height = height + 40000;
} else {
height = height + 40000;
}
}
}
/*
* This subroutine decodes the surface data from a TTAA
*/
if ( pp.equals("99") && ! above ) {
int ihhhSurface = Integer.parseInt(hhh);
pressure = ihhhSurface;
if ( ihhhSurface < 100 ) {
pressure = pressure + 1000;
}
if ( ! drop && stationNumber != null ) {
height = IDecoderConstantsN.UAIR_INTEGER_MISSING;
height = (float) record.getElevation();
} else if ( drop ){
// dropsonde data
height = IDecoderConstantsN.UAIR_INTEGER_MISSING;
} else {
// ship data
height = NcUairShipMobile.getSurfaceHeight();
}
}
}
}
}
/**
* Decodes pressure and height data
*
* @param presGroup
* The input pressure code group
* @param above
* The input above is flag
* @param level
* the input pressure level
* @param stationNumber
* The input station number
* @param dataType
* The input data type
* @return
*/
public static void PressureHeightField(String presGroup, Boolean above,
int level, String stationNumber, String dataType,
NcUairRecord record) {
pressure = IDecoderConstantsN.UAIR_FLOAT_MISSING;
height = IDecoderConstantsN.UAIR_FLOAT_MISSING;
int iabove = 0;
int ipres = IDecoderConstantsN.UAIR_INTEGER_MISSING;
int ihhh = IDecoderConstantsN.UAIR_INTEGER_MISSING;
Boolean drop = false;
Boolean ship = false;
Boolean cont;
String pressValue[][] = {
{ "99", "00", "92", "85", "70", "50", "40", "30", "25", "20",
"15", "10" },
{ "70", "50", "30", "20", "10", "07", "05", "03", "02", "01",
"xx", "//" } };
// System.out.println(" line 80 of NcUairPressureHeight!!!!!!! "
// + presGroup);
if (dataType.substring(0, 2).equals("XX")) {
// dropsonde data
drop = true;
} else if (dataType.substring(0, 2).equals("UU")) {
// ship data
ship = true;
}
if (above) {
iabove = 1;
}
if (presGroup.length() == 5 && (level < 12)) {
String pp = presGroup.substring(0, 2);
String hhh = presGroup.substring(2, 5);
cont = true;
while (cont) {
// System.out.println(" line 108 of NcUairPressureHeight!!!!!!! "
// + pp + " " + hhh + " pressValue: "
// + pressValue[iabove][level]);
if (pp.equals(pressValue[iabove][level])) {
// System.out
// .println(" Line 111 of NcUairPressureHeight/Man Pressure level !!!!!!!!!!! "
// + pp);
cont = false;
if (!pp.equals("//")) {
ipres = Integer.parseInt(pp);
}
if (!hhh.equals("///")) {
ihhh = Integer.parseInt(hhh);
}
if (!above) {
/*
* Encoded pressure was pressure / 10. 00 is 1000. Above
* 100mb, encoded pressure is whole number.
*/
if (ipres != IDecoderConstantsN.UAIR_INTEGER_MISSING) {
ipres = ipres * 10;
if (ipres == 0) {
ipres = 1000;
}
// Take care of the 925 mb level, which comes in as
// 920.
if (ipres == 920) {
ipres = 925;
}
pressure = ipres;
}
/*
* For data below 100 mb, use the pressure to decode the
* height. This algorithm is from the U. of Wisconsin
* and differs slightly from the PROFS algorithm.
*/
if (ihhh != IDecoderConstantsN.UAIR_INTEGER_MISSING) {
height = ihhh;
if ((ipres == 1000) && (height > 500)) {
height = 500 - height;
} else if ((ipres == 925) && (height < 200)
&& (!drop)) {
height = height + 1000;
} else if ((ipres == 850) && (height < 900)) {
height = height + 1000;
} else if ((ipres == 700) && (height < 500)) {
height = height + 3000;
} else if (ipres == 700) {
height = height + 2000;
} else if (ipres <= 500) {
ihhh = ihhh * 10;
height = height * 10;
if ((ipres == 300) && (ihhh < 3000)) {
height = height + 10000;
} else if ((ipres == 250) && (ihhh < 5000)) {
height = height + 10000;
} else if ((ipres == 200) && (ihhh < 7000)) {
height = height + 10000;
} else if (ipres <= 150) {
height = height + 10000;
}
}
}
} else {
pressure = ipres;
/*
* Compute the height above 100 mb. The ten thousands
* digit is added here. The value may need to be changed
* in the future if it proves incorrect.
*/
if (ihhh != IDecoderConstantsN.UAIR_INTEGER_MISSING) {
ihhh = ihhh * 10;
height = ihhh;
if (ipres == 70) {
height = height + 10000;
} else if ((ipres == 50) && (ihhh >= 8000)) {
height = height + 10000;
} else if ((ipres == 50) && (height < 8000)) {
height = height + 20000;
} else if (ipres >= 20) {
height = height + 20000;
} else if ((ipres == 10) && (height > 8000)) {
height = height + 20000;
} else if ((ipres == 10) && (height < 8000)) {
height = height + 30000;
} else if (ipres >= 3) {
height = height + 30000;
} else if ((ipres == 2) && (height > 8000)) {
height = height + 30000;
} else if ((ipres == 2) && (height < 8000)) {
height = height + 40000;
} else {
height = height + 40000;
}
}
}
/*
* This subroutine decodes the surface data from a TTAA
*/
if (pp.equals("99") && !above) {
int ihhhSurface = Integer.parseInt(hhh);
pressure = ihhhSurface;
if (ihhhSurface < 100) {
pressure = pressure + 1000;
}
if (!drop && stationNumber != null) {
height = IDecoderConstantsN.UAIR_INTEGER_MISSING;
height = (float) record.getElevation();
} else if (drop) {
// dropsonde data
height = IDecoderConstantsN.UAIR_INTEGER_MISSING;
} else {
// ship data
height = NcUairShipMobile.getSurfaceHeight();
}
}
} else {
level++;
}
}
}
}
}

View file

@ -9,6 +9,7 @@
* ------------ ---------- ----------- --------------------------
* 03/2010 210 L. Lin Initial coding
* 09/2011 457 S. Gurung Renamed H5 to Nc and h5 to nc
* 6/2014 T. Lee Wind sets to missing if > 400kts
*
* </pre>
*
@ -22,87 +23,96 @@ package gov.noaa.nws.ncep.edex.plugin.ncuair.util;
import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN;
public class NcUairWindGroup {
private static float sped;
private static float drct;
public static float getSped() {
return sped;
}
public void setSped (float sped) {
this.sped = sped;
}
private static float sped;
public static float getDrct() {
return drct;
}
private static float drct;
public void setDrct(float drct) {
this.drct = drct;
}
public static float getSped() {
return sped;
}
/**
* This subroutine decodes a wind field in the form dddff where ddd
* is the direction in degrees and ff is the wind speed.
* If last digit of ddd is not equal to 0, then it becomes ddfff.
* In other words, wind speed should be "dff" not "ff".
*
* @param report The input report
* @param windKnot The input windKnot is flag to indicate wind in knot or not.
* @return
*/
public static void WindField(String windGroup, Boolean windKnot) {
sped = IDecoderConstantsN.UAIR_FLOAT_MISSING;
drct = IDecoderConstantsN.UAIR_FLOAT_MISSING;
if ( windGroup != null ) {
if ( windGroup.length() == 5 ) {
String ddd = windGroup.substring(0,3);
String ff = windGroup.substring(3,5);
String wDir = windGroup.substring(0,2);
String wSpeed = windGroup.substring(2,5);
if ( ! ddd.substring(0,2).equals("//") && ! ff.equals("//")) {
/*
* The tens and hundreds of the wind direction is encoded in the
* first two digits.
*/
int idir = Integer.parseInt(wDir);
idir = idir * 10;
public void setSped(float sped) {
this.sped = sped;
}
//The wind speed is encoded in the last three digits.
int ispeed = Integer.parseInt(wSpeed);
if ( ispeed >= 500 ) {
/*
* The units value of the direction rounded to 0 or 5 is
* multiplied by 100 and added to the wind speed.
*/
ispeed = ispeed - 500;
idir = idir + 5;
}
public static float getDrct() {
return drct;
}
/*
* Set the output values. Return missing data if direction is
* greater than 360 or field is '31313'.
*/
if ( idir == 360 ) {
idir = 0;
}
sped = ispeed;
if ( windKnot ) {
sped = (float) (sped / 1.9425);
}
drct = idir;
} else if ( ! ddd.equals("///") && ff.equals("//")) {
// wind speed missing
int idir = Integer.parseInt(ddd);
drct = idir;
}
}
}
}
public void setDrct(float drct) {
this.drct = drct;
}
/**
* This subroutine decodes a wind field in the form dddff where ddd is the
* direction in degrees and ff is the wind speed. If last digit of ddd is
* not equal to 0, then it becomes ddfff. In other words, wind speed should
* be "dff" not "ff".
*
* @param report
* The input report
* @param windKnot
* The input windKnot is flag to indicate wind in knot or not.
* @return
*/
public static void WindField(String windGroup, Boolean windKnot) {
sped = IDecoderConstantsN.UAIR_FLOAT_MISSING;
drct = IDecoderConstantsN.UAIR_FLOAT_MISSING;
if (windGroup != null) {
if (windGroup.length() == 5) {
String ddd = windGroup.substring(0, 3);
String ff = windGroup.substring(3, 5);
String wDir = windGroup.substring(0, 2);
String wSpeed = windGroup.substring(2, 5);
if (!ddd.substring(0, 2).equals("//") && !ff.equals("//")) {
/*
* The tens and hundreds of the wind direction is encoded in
* the first two digits.
*/
int idir = Integer.parseInt(wDir);
idir = idir * 10;
// The wind speed is encoded in the last three digits.
int ispeed = Integer.parseInt(wSpeed);
if (ispeed >= 500) {
/*
* The units value of the direction rounded to 0 or 5 is
* multiplied by 100 and added to the wind speed.
*/
ispeed = ispeed - 500;
idir = idir + 5;
}
/*
* Set the output values. Return missing data if direction
* is greater than 360 or field is '31313'.
*/
if (idir == 360) {
idir = 0;
}
sped = ispeed;
if (windKnot) {
sped = (float) (sped / 1.9425);
}
drct = idir;
if (sped > 400.) {
sped = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING;
idir = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING;
}
} else if (!ddd.equals("///") && ff.equals("//")) {
// wind speed missing
int idir = Integer.parseInt(ddd);
drct = idir;
}
}
}
}
}

View file

@ -41,8 +41,8 @@ import com.vividsolutions.jts.geom.Coordinate;
*
* gov.noaa.nws.ncep.edex.uengine.tasks.profile.ObservedSoundingQuery
*
* This java class performs the observed sounding data query functions.
* This code has been developed by the SIB for use in the AWIPS2 system.
* This java class performs the observed sounding data query functions. This
* code has been developed by the SIB for use in the AWIPS2 system.
*
* <pre>
* SOFTWARE HISTORY
@ -66,6 +66,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* better performance
* Jul 19, 2013 1992 bsteffen Remove redundant time columns from bufrua.
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* June, 2014 Chin Chen Retrieved observed sounding with reftime
* </pre>
*
* @author Chin Chen
@ -211,15 +212,15 @@ public class ObservedSoundingQuery {
} else if (obType.equals(ObsSndType.NCUAIR.toString())) {
currentDBTblName = NCUAIR_TBL_NAME;
queryStr = new String(
"Select Distinct latitude, longitude, id, stationId, elevation, synoptictime FROM "
"Select Distinct latitude, longitude, id, stationId, elevation, reftime FROM "
+ currentDBTblName
+ " where nil='FALSE' AND synoptictime='"
+ " where nil='FALSE' AND reftime='"
+ selectedSndTime
+ "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9");
queryStr1 = new String(
"Select Distinct latitude, longitude FROM "
+ currentDBTblName
+ " where nil='FALSE' AND synoptictime='"
+ " where nil='FALSE' AND reftime='"
+ selectedSndTime
+ "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9");
dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class));
@ -320,9 +321,9 @@ public class ObservedSoundingQuery {
} else if (obType.equals(ObsSndType.NCUAIR.toString())) {
currentDBTblName = NCUAIR_TBL_NAME;
queryStr = new String("Select Distinct synoptictime FROM "
queryStr = new String("Select Distinct reftime FROM "
+ currentDBTblName
+ " where nil='FALSE' ORDER BY synoptictime DESC");
+ " where nil='FALSE' ORDER BY reftime DESC");
dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class));
} else {
return tl;
@ -356,10 +357,9 @@ public class ObservedSoundingQuery {
} else if (obType.equals(ObsSndType.NCUAIR.toString())) {
currentDBTblName = NCUAIR_TBL_NAME;
queryStr = new String("Select Distinct synoptictime FROM "
+ currentDBTblName
+ " where nil='FALSE' AND synoptictime >= '" + startTimeStr
+ "' AND synoptictime <= '" + endTimeStr
queryStr = new String("Select Distinct reftime FROM "
+ currentDBTblName + " where nil='FALSE' AND reftime >= '"
+ startTimeStr + "' AND reftime <= '" + endTimeStr
+ "' ORDER BY synoptictime DESC");
dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class));
} else {