diff --git a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/GenerateFSSObReport.java b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/GenerateFSSObReport.java index 186cdafd5d..efd8ec6e23 100644 --- a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/GenerateFSSObReport.java +++ b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/GenerateFSSObReport.java @@ -7,103 +7,116 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.fssobs.FSSObsRecord; import com.raytheon.uf.common.monitor.data.ObConst; import com.raytheon.uf.common.monitor.data.ObConst.ReportType; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.viz.monitor.data.ObReport; /** - * @author skorolev (initial creation) + * Generates FSSObs Report for tables. * - * Change history: - * Date Ticket # Engineer Description - * --------------------------------------------------- - * May 15, 2012 14510 zhao Modified generateObReport() - * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ *                         skorolev     Initial creation
+ * May 15, 2012 14510      zhao         Modified generateObReport()
+ * Jan 06, 2014  2653      skorolev     Included SNOW data into ObReport.
+ * 
+ * 
+ * 
+ * + * @author skorolev + * @version 1.0 */ public class GenerateFSSObReport { + private static IUFStatusHandler statusHandler = UFStatus + .getHandler(GenerateFSSObReport.class); - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.viz.monitor.IObReportable#generateObReport(com.raytheon - * .uf.common.dataplugin.PluginDataObject, - * com.raytheon.uf.viz.monitor.data.ObReport, - * com.raytheon.uf.common.monitor.data.ObConst.ChosenAppKey) - */ + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.viz.monitor.IObReportable#generateObReport(com.raytheon + * .uf.common.dataplugin.PluginDataObject, + * com.raytheon.uf.viz.monitor.data.ObReport, + * com.raytheon.uf.common.monitor.data.ObConst.ChosenAppKey) + */ public static ObReport generateObReport(PluginDataObject report) { - // Generate the observation report. - ObReport obReport = new ObReport(); - FSSObsRecord metar = (FSSObsRecord) report; - try { - obReport.setObservationTime(metar.getTimeObs().getTime()); - obReport.setRefHour(metar.getRefHour().getTime()); - } catch (Exception e) { - System.out.println("Warning: missing obsTime or refHour at getTimeObs() when processing obs data; " + e + "; trying to set obsTime and refHour from dataURI"); - obReport.setTimesFromFssobDataURI(report.getDataURI()); - } - obReport.setPlatformId(metar.getPlatformId()); - obReport.setStationary(true); - obReport.setLatitude((float) metar.getLatitude()); - obReport.setLongitude((float) metar.getLongitude()); - // Table data: - obReport.setCeiling(metar.getCeiling()); - obReport.setWindDir(metar.getWindDir()); - obReport.setWindSpeed(metar.getWindSpeed()); - obReport.setMaxWindSpeed(metar.getMaxWindSpeed()); - obReport.setWindGust(metar.getWindGust()); - obReport.setRelativeHumidity(metar.getRelativeHumidity()); - try { - obReport.setVisibility(metar.getVisibility()); - } catch (Exception e) { - obReport.setVisibility(0); - } - obReport.setDewpoint(metar.getDewpoint()); - obReport.setTemperature(metar.getTemperature()); - obReport.setDewpointDepr(metar.getDewpointDepr()); + // Generate the observation report. + ObReport obReport = new ObReport(); + FSSObsRecord metar = (FSSObsRecord) report; + try { + obReport.setObservationTime(metar.getTimeObs().getTime()); + obReport.setRefHour(metar.getRefHour().getTime()); + } catch (Exception e) { + statusHandler + .error("Warning: missing obsTime or refHour at getTimeObs() when processing obs data; " + + e + + "; trying to set obsTime and refHour from dataURI"); + obReport.setTimesFromFssobDataURI(report.getDataURI()); + } + obReport.setPlatformId(metar.getPlatformId()); + obReport.setStationary(true); + obReport.setLatitude((float) metar.getLatitude()); + obReport.setLongitude((float) metar.getLongitude()); + // Table data: + obReport.setCeiling(metar.getCeiling()); + obReport.setWindDir(metar.getWindDir()); + obReport.setWindSpeed(metar.getWindSpeed()); + obReport.setMaxWindSpeed(metar.getMaxWindSpeed()); + obReport.setWindGust(metar.getWindGust()); + obReport.setRelativeHumidity(metar.getRelativeHumidity()); + try { + obReport.setVisibility(metar.getVisibility()); + } catch (Exception e) { + obReport.setVisibility(0); + } + obReport.setDewpoint(metar.getDewpoint()); + obReport.setTemperature(metar.getTemperature()); + obReport.setDewpointDepr(metar.getDewpointDepr()); - obReport.setPresentWx(getPrWX(metar.getPresWeather())); + obReport.setPresentWx(getPrWX(metar.getPresWeather())); - obReport.setHighResWaveHeight(ObConst.MISSING); - obReport.setWaveSteepness(metar.getWaveSteepness()); + obReport.setHighResWaveHeight(ObConst.MISSING); + obReport.setWaveSteepness(metar.getWaveSteepness()); - obReport.setSeaLevelPress(metar.getSeaLevelPress()); - obReport.setWavePeriod(metar.getWavePeriod()); - obReport.setWindGust(metar.getWindGust()); - obReport.setPSwellHeight(metar.getPrimarySwellWaveHeight() - .floatValue()); - obReport.setPSwellPeriod(metar.getPrimarySwellWavePeriod()); - obReport.setPSwellDir(metar.getPrimarySwellWaveDir().floatValue()); - obReport.setSSwellHeight(metar.getSecondarySwellWaveHeight() - .floatValue()); - obReport.setSSwellPeriod(metar.getSecondarySwellWavePeriod()); - obReport.setSSwellDir(metar.getSecondarySwellWaveDir().floatValue()); - obReport.setPressure(metar.getPressureAltimeter()); - obReport.setPressureChange(metar.getPressChange3Hour()); - try { - obReport.setPressChangeChar(Short.parseShort(metar - .getPressChangeChar())); - } catch (NumberFormatException e) { - obReport.setPressChangeChar((short) 0); - } + obReport.setSeaLevelPress(metar.getSeaLevelPress()); + obReport.setWavePeriod(metar.getWavePeriod()); + obReport.setWindGust(metar.getWindGust()); + obReport.setPSwellHeight(metar.getPrimarySwellWaveHeight().floatValue()); + obReport.setPSwellPeriod(metar.getPrimarySwellWavePeriod()); + obReport.setPSwellDir(metar.getPrimarySwellWaveDir().floatValue()); + obReport.setSSwellHeight(metar.getSecondarySwellWaveHeight() + .floatValue()); + obReport.setSSwellPeriod(metar.getSecondarySwellWavePeriod()); + obReport.setSSwellDir(metar.getSecondarySwellWaveDir().floatValue()); + obReport.setPressure(metar.getPressureAltimeter()); + obReport.setPressureChange(metar.getPressChange3Hour()); + try { + obReport.setPressChangeChar(Short.parseShort(metar + .getPressChangeChar())); + } catch (NumberFormatException e) { + obReport.setPressChangeChar((short) 0); + } - obReport.setHourlyPrecip(metar.getHourlyPrecip()); - // obReport.setPresentWx(WeatherCondition.toCanonicalForm(metar.getWeatherCondition())); - obReport.setRawMessage(metar.getRawMessage()); - // TODO: report type ??? - obReport.setReportType(ReportType.METAR); + obReport.setHourlyPrecip(metar.getHourlyPrecip()); - // if (chosenAppKey == ChosenAppKey.SNOW) { - // obReport = ObUtil.generateObReportSnow(obReport, - // metar.getMessageData()); - // } else if (chosenAppKey == ChosenAppKey.FOG) { - // obReport = ObUtil.generateObReportFog(obReport, - // metar.getSkyCoverage(), - // metar.getVertVisibility()); - // } - obReport.setSeaSurfaceTemp(metar.getSeaSurfaceTemp()); - return obReport; - } + obReport.setRawMessage(metar.getRawMessage()); + obReport.setReportType(ReportType.METAR); + obReport.setSnincrHourly(metar.getSnincrHourly()); + obReport.setSnincrTotal(metar.getSnincrTotal()); + obReport.setFrostbiteTime(metar.getFrostbiteTime()); + obReport.setWindChill(metar.getWindChill()); + obReport.setSnowDepth(metar.getSnowDepth()); + obReport.setSeaSurfaceTemp(metar.getSeaSurfaceTemp()); + return obReport; + } /** + * Construct Present Weather string. + * * @param presWeather * @return */ diff --git a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/util/ObUtil.java b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/util/ObUtil.java index 14d4601636..faeaf52b43 100644 --- a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/util/ObUtil.java +++ b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/util/ObUtil.java @@ -22,7 +22,6 @@ package com.raytheon.uf.viz.monitor.util; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.Scanner; import java.util.Set; import java.util.TimeZone; @@ -46,6 +45,7 @@ import com.raytheon.uf.viz.monitor.data.ObReport; * Jan 19, 2010 4240 zhao Modified generateObReportSnow method * Aug 14, 2013 2262 dgilling Use new wxmath method for calcrh. * Oct 23, 2013 2361 njensen Removed two unused methods + * Jan 06, 2014 2653 skorolev Removed not used methods. * * * @@ -177,80 +177,6 @@ public final class ObUtil { return ThreatLevel.GRAY; } - /** - * This method supplements generation of an observation report for SNOW - * - * @param obReport - * -- the observation report - * @return -- the generated observation report - */ - public static ObReport generateObReportSnow(ObReport obReport, - String remarks) { - // Check parameters for wind chill/frostbite - // time calculation (upper limit for wind chill - // is set at 40F) : - if ((obReport.getTemperature() == ObConst.MISSING) - || (obReport.getTemperature() > 277.6) // 40 F - || (obReport.getWindSpeed() == ObConst.MISSING) - || (obReport.getWindSpeed() > 1e36f)) { - obReport.setWindChill(ObConst.MISSING); - obReport.setFrostbiteTime(ObConst.MISSING); - } else { - // Kelvin to Celsius - // float tempC = obReport.getTemperature() - 273.15f; - - // obReport.getTemperature() in Celsius already - // [Jan 19, 2010, zhao] - float tempC = obReport.getTemperature(); - - // mps to kph - // float speedKPH = obReport.getWindSpeed() * 3.6f; - - // mph to kph - // [Jan 19, 2010, zhao] - float speedKPH = obReport.getWindSpeed() * 1.6f; - - // Call AWIPS wind chill routine. Return units - // are in Celsius. - float windChillC = calcWindChill(tempC, speedKPH); - float windChillK = 273.15f; - // Check for too-warm default (default should come back - // as 1e37 if conditions are too warm, so we'll check one - // order of magnitude lower, for > 1e36.) Actual limit - // is 16C or ~61F. If the wind chill is valid, carry - // it through the active program as Fahrenheit, but store - // it in the NetCDF files as Kelvin (to match the other - // temperature parameters). - - if (windChillC > 1e36f) { - obReport.setWindChill(ObConst.MISSING); - windChillK = ObConst.MISSING; - } else { - // Carry through the program in Fahrenheit... - obReport.setWindChill(1.8f * windChillC + 32.0f); - windChillK += windChillC; - } - - // Calculate frostbite time. - - float fbMinutes = calcFrostbiteTime(speedKPH, tempC); - obReport.setFrostbiteTime(fbMinutes); - - } - - // Check for Snow Increasing Rapidly (SNINCR) in the remarks. - // First, retrieve the current raw report (don't want to have - // to store it in the Report class). - - // Call routine to get the hourly and total values, if present. - getSNINCR(remarks, obReport); - - // Call routine to get snow depth, if present. - getSnowDepth(remarks, obReport); - - return obReport; - } - /** * This method supplements generation of an observation report for FOG * @@ -306,140 +232,6 @@ public final class ObUtil { return ceiling >= 1e20f ? ObConst.MISSING : ceiling; } - /** - * This method calculates the windChill from temperature and windSpeed. - * - * @param temp - * -- temperature in degrees Celsius - * @param windSpd - * -- wind speed in kilometers per hour - * @return -- wind chill in degrees Celsius - */ - public static float calcWindChill(float temp, float windSpd) { - float spd; - - /* arbitrarily do the calculation only for temps at or below 60F */ - if (temp > 16.) { - return 1e37f; - } - - /* no chilling if speed < 4 mph = 6.44km/h */ - if (windSpd < 6.4) { - return temp; - } - /* peg speed at 80 mph (= 128.75 km/h) */ - if (windSpd > 128.75) { - spd = 128.75f; - } else { - spd = windSpd; - } - - spd = (float) Math.pow(spd, 0.16); - float windChillTemp = 13.12f + 0.6215f * temp - 11.37f * spd + 0.3965f - * temp * spd; - return windChillTemp; - } - - /** - * This method calculates the amount of time needed for frostbite to occur - * on exposed skin. - * - * @param windspeedKPH - * -- wind speed in kilometers per hour - * @param temperatureC - * -- temperature in degrees Celsius - * @return -- time in minutes - */ - public static float calcFrostbiteTime(float windspeedKPH, float temperatureC) { - float fbMinutes = ObConst.MISSING; - - // Temperature must be lower than -4.8C (23F) to avoid a calculation - // error (a negative number to -1.668 power is NAN) - - if (temperatureC < -4.8) { - fbMinutes = ((-24.5f * ((0.667f * windspeedKPH) + 4.8f)) + 2111f) - * (float) Math.pow((-4.8 - temperatureC), -1.668); - } else { - return ObConst.MISSING; - } - - // Check for frostbite boundaries - - if (!(fbMinutes <= 30 && windspeedKPH > 25.0 && windspeedKPH <= 80.5)) { - fbMinutes = ObConst.MISSING; - } - - return fbMinutes; - } - - /** - * This method retrieves "snow increasing rapidly" parameters -- hourly and - * total snowfall in inches -- from a METAR's remarks section. This method - * update the observation report with the "snow increasing rapidly" - * parameters. - * - * @param remarks - * -- the METAR remarks - * @param obReport - * -- the observation report - * @return success - */ - public static boolean getSNINCR(String remarks, ObReport obReport) { - - // New up a Scanner to use to parse the raw data for desired pattern. - Scanner sc = new Scanner(remarks); - String whatMatched; - whatMatched = sc.findWithinHorizon("REMARK_EXPR", 0); - if (whatMatched != null) { - whatMatched = sc.findWithinHorizon("SNINCR", 0); - if (whatMatched != null) { - sc.useDelimiter("/"); - obReport.setSnincrHourly(sc.nextInt()); - sc.reset(); - obReport.setSnincrTotal(sc.nextInt()); - } else { - obReport.setSnincrHourly(ObConst.MISSING); - obReport.setSnincrTotal(ObConst.MISSING); - } - } else { - obReport.setSnincrHourly(ObConst.MISSING); - obReport.setSnincrTotal(ObConst.MISSING); - } - - return true; - } - - /** - * This method retrieves "snow depth" parameters -- total snow depth in - * inches -- from a METAR's remarks section. This method update the - * observation report with the "snow depth" parameters. - * - * @param remarks - * -- the METAR remarks - * @param obReport - * -- the observation report - * @return success - */ - public static boolean getSnowDepth(String remarks, ObReport obReport) { - - // New up a Scanner to use to parse the raw data for desired pattern. - Scanner sc = new Scanner(remarks); - String whatMatched; - whatMatched = sc.findWithinHorizon("REMARK_EXPR", 0); - if (whatMatched != null) { - whatMatched = sc.findWithinHorizon("4/", 0); - if (whatMatched != null) { - obReport.setSnowDepth(sc.nextInt()); - } else { - obReport.setSnowDepth(ObConst.MISSING); - } - } else { - obReport.setSnowDepth(ObConst.MISSING); - } - - return true; - } - /** * This method determines the RH from temperature and dew point in degrees * celsius. diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java index 93113bf8ed..448f7b0826 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java @@ -54,6 +54,8 @@ import com.raytheon.uf.edex.pointdata.PointDataQuery; * Nov 26, 2012 1297 skorolev Changed ArrayList to List.Clean code * May 15, 2013 1869 bsteffen Remove DataURI column from ldadmesonet. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * Jan 02, 2014 2580 skorolev Fixed FSSObs error. + * Jan 06, 2014 2653 skorolev Corrected decoding of snincrHourly and snincrTotal. * * * @@ -65,6 +67,9 @@ public class FSSObsUtils { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(FSSObsUtils.class); + /** Centigrade -> Kelvin */ + public static final float TMCK = 273.15f; + /** * Value of missed data. */ @@ -348,14 +353,18 @@ public class FSSObsUtils { * @return -- Snow data from METAR */ public static float[] getSnowData(FSSObsRecord tableRow) { - // Check parameters for wind chill in K/frostbite in minutes/snow - // increase and depth in inches + // Check parameters for wind chill in K + // frost bite in minutes + // snow increase and depth in inches // time calculation (upper limit for wind chill // is set at 40F and wind speed between 14 and 43 knts) : float[] retVal = new float[5]; for (int i = 0; i < 5; i++) { retVal[i] = MISSING; } + float temp = tableRow.getTemperature(); + float windspd = tableRow.getWindSpeed(); + Scanner sc = new Scanner(tableRow.getRawMessage()); String whatMatched; whatMatched = sc.findWithinHorizon("RMK", 0); @@ -363,31 +372,33 @@ public class FSSObsUtils { whatMatched = sc.findWithinHorizon("SNINCR", 0); if (whatMatched != null) { sc.useDelimiter("/"); - // last hour snow in inches - retVal[0] = sc.nextInt(); + if (sc.hasNext()) { + // last hour snow in inches + retVal[0] = Float.parseFloat(sc.next()); + } sc.reset(); - // total snow in inches - retVal[1] = sc.nextInt(); + sc.findWithinHorizon("/", 0); + if (sc.hasNextInt()) { + // total snow in inches + retVal[1] = sc.nextInt(); + } } whatMatched = sc.findWithinHorizon("4/", 0); if (whatMatched != null) { // snow depth on ground in inches - if (retVal.length >= 5) { - retVal[5] = sc.nextInt(); - } + retVal[2] = sc.nextInt(); } } - if ((tableRow.getTemperature() != MISSING) - && (tableRow.getTemperature() < 4.4f) - // 277.6 K = 40 F = 4.44444 Celsium - && (tableRow.getWindSpeed() != MISSING) - && (tableRow.getWindSpeed() <= 43.0f && tableRow.getWindSpeed() >= 14.0f)) { - float speedKPH = tableRow.getWindSpeed() * 1.6f; - float t = tableRow.getTemperature(); + sc.close(); + if ((temp != MISSING) && (temp < 4.4f) + // 277.6 K = 40 F = 4.44444 C + && (windspd != MISSING) + && (windspd <= 43.0f && windspd >= 14.0f)) { + float speedKPH = windspd * 1.6f; // in Kelvin - retVal[3] = calcWindChill(t, speedKPH) + 273.15f; + retVal[3] = calcWindChill(temp, speedKPH) + TMCK; // in minutes - retVal[4] = calcFrostbiteTime(speedKPH, t); + retVal[4] = calcFrostbiteTime(speedKPH, temp); } return retVal; }