hydro plugin updates from origin/master_18.1.1

This commit is contained in:
mjames-upc 2018-08-27 15:05:23 -06:00
parent e97d66b924
commit eacb3727d0
72 changed files with 8923 additions and 6899 deletions

View file

@ -55,7 +55,6 @@ import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasin; import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasin;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinData;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinMetaData; import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinMetaData;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGap; import com.raytheon.uf.common.dataplugin.ffmp.FFMPGap;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceBasin; import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceBasin;
@ -209,7 +208,6 @@ import com.vividsolutions.jts.geom.Point;
* Sep 14, 2016 3241 bsteffen Update deprecated JTSCompiler method calls * Sep 14, 2016 3241 bsteffen Update deprecated JTSCompiler method calls
* Jan 23, 2017 6032 njensen Implement IExtraTextGeneratingResource * Jan 23, 2017 6032 njensen Implement IExtraTextGeneratingResource
* May 05 2017 DR 14336 lshi FFMP VGB value differences between A1 and A2 * May 05 2017 DR 14336 lshi FFMP VGB value differences between A1 and A2
* May 15, 2017 DR 11861 lshi FFMP use of QPF in calculating QPE in Basin Table
* Sep 15, 2017 DR 20297 lshi FFMP AlertViz errors when changing layers and * Sep 15, 2017 DR 20297 lshi FFMP AlertViz errors when changing layers and
* opening basin trend graphs * opening basin trend graphs
* *
@ -1931,22 +1929,14 @@ public class FFMPResource
float qpe = 0.0f; float qpe = 0.0f;
float guid = 0.0f; float guid = 0.0f;
Float qpf = null;
float diff = Float.NaN; float diff = Float.NaN;
String ffgType = getFFGName(); String ffgType = getFFGName();
FFMPRecord qpfRecord = this.getQpfRecord(getPaintTime().getRefTime());
FFMPBasinData qpfBasin = null;
if (qpfRecord != null) {
qpfBasin = qpfRecord.getBasinData();
}
try { try {
if (aggregate) { if (aggregate) {
if (isWorstCase()) { if (isWorstCase()) {
List<Float> qpes = null; List<Float> qpes = null;
List<Float> guids = null; List<Float> guids = null;
List<Float> qpfs = null;
if ((getQpeRecord() != null) if ((getQpeRecord() != null)
&& (getGuidanceRecord() != null)) { && (getGuidanceRecord() != null)) {
@ -1959,12 +1949,9 @@ public class FFMPResource
getGuidanceInterpolation(ffgType), getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType)); getGuidSourceExpiration(ffgType));
} }
if (qpfBasin != null) {
qpfs = qpfBasin.getAccumValues(pfafs, getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
if ((qpes != null) && (guids != null)) { if ((qpes != null) && (guids != null)) {
diff = FFMPUtils.getMaxDiffValue(qpes, qpfs, guids); diff = FFMPUtils.getMaxDiffValue(qpes, guids);
} }
} else { } else {
if ((getQpeRecord() != null) if ((getQpeRecord() != null)
@ -1980,14 +1967,7 @@ public class FFMPResource
getGuidanceInterpolation(ffgType), getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType)); getGuidSourceExpiration(ffgType));
if (qpfBasin != null) { diff = FFMPUtils.getDiffValue(qpe, guid);
qpf = qpfBasin.getAccumAverageValue(pfafs,
getTableTime(), recentTime,
getQpfSourceExpiration(), getResourceData()
.getPrimarySourceXML().isRate());
}
diff = FFMPUtils.getDiffValue(qpe, qpf, guid);
} }
} }
} else { } else {
@ -2004,11 +1984,7 @@ public class FFMPResource
getBasin(key, getField(), recentTime, aggregate), getBasin(key, getField(), recentTime, aggregate),
guid); guid);
if (qpfBasin != null) { diff = FFMPUtils.getDiffValue(qpe, guid);
qpf = qpfBasin.get(key).getAccumValue(getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
diff = FFMPUtils.getDiffValue(qpe, qpf, guid);
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -2029,22 +2005,15 @@ public class FFMPResource
float qpe = 0.0f; float qpe = 0.0f;
float guid = 0.0f; float guid = 0.0f;
Float qpf = null;
float ratio = Float.NaN; float ratio = Float.NaN;
String ffgType = getFFGName(); String ffgType = getFFGName();
FFMPRecord qpfRecord = this.getQpfRecord(getPaintTime().getRefTime());
FFMPBasinData qpfBasin = null;
if (qpfRecord != null) {
qpfBasin = qpfRecord.getBasinData();
}
try { try {
if (aggregate) { if (aggregate) {
if (isWorstCase()) { if (isWorstCase()) {
List<Float> qpes = null; List<Float> qpes = null;
List<Float> guids = null; List<Float> guids = null;
List<Float> qpfs = null;
if (getQpeRecord() != null) { if (getQpeRecord() != null) {
qpes = getQpeRecord().getBasinData().getAccumValues( qpes = getQpeRecord().getBasinData().getAccumValues(
pfafs, getTableTime(), recentTime, pfafs, getTableTime(), recentTime,
@ -2056,13 +2025,9 @@ public class FFMPResource
getGuidanceInterpolation(ffgType), getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType)); getGuidSourceExpiration(ffgType));
} }
if (qpfBasin != null) {
qpfs = qpfBasin.getAccumValues(pfafs, getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
if ((qpes != null) && (guids != null)) { if ((qpes != null) && (guids != null)) {
ratio = FFMPUtils.getMaxRatioValue(qpes, qpfs, guids); ratio = FFMPUtils.getMaxRatioValue(qpes, guids);
} }
} else { } else {
if ((getQpeRecord() != null) if ((getQpeRecord() != null)
@ -2078,14 +2043,6 @@ public class FFMPResource
getGuidanceInterpolation(ffgType), getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType)); getGuidSourceExpiration(ffgType));
if (qpfBasin != null) {
qpf = qpfBasin.getAccumAverageValue(pfafs,
getTableTime(), recentTime,
getQpfSourceExpiration(), getResourceData()
.getPrimarySourceXML().isRate());
}
ratio = FFMPUtils.getRatioValue(qpe, qpf, guid);
} }
} }
} else { } else {
@ -2097,14 +2054,8 @@ public class FFMPResource
(FFMPGuidanceBasin) getGuidanceRecord() (FFMPGuidanceBasin) getGuidanceRecord()
.getBasinData().get(key), .getBasinData().get(key),
recentTime, ffgType); recentTime, ffgType);
qpf = null;
if (qpfBasin != null) { ratio = FFMPUtils.getRatioValue(qpe, guid);
qpf = qpfBasin.get(key).getAccumValue(getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
ratio = FFMPUtils.getRatioValue(qpe, qpf, guid);
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -3404,7 +3355,6 @@ public class FFMPResource
Float guidancev = 0.0f; Float guidancev = 0.0f;
Float qpev = fgd.getQpe(fgdQpeTime).floatValue(); Float qpev = fgd.getQpe(fgdQpeTime).floatValue();
Float qpfv = Float.NaN;
// Initialize to NaN. If there is no guidance then we want // Initialize to NaN. If there is no guidance then we want
// NaN as the default value as it will be "missing". // NaN as the default value as it will be "missing".
@ -3432,9 +3382,8 @@ public class FFMPResource
Double qpf = fgd.getQpf(fgdQpeTime); Double qpf = fgd.getQpf(fgdQpeTime);
if (qpf != null){ if (qpf != null){
qpfv = qpf.floatValue(); diff = FFMPUtils.getDiffValue(qpev, guidancev);
diff = FFMPUtils.getDiffValue(qpev, qpfv, guidancev); ratio = FFMPUtils.getRatioValue(qpev, guidancev);
ratio = FFMPUtils.getRatioValue(qpev, qpfv, guidancev);
} }
} }

View file

@ -63,7 +63,6 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
* Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL * Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL
* Apr 30, 2014 2060 njensen Safety checks for null guidance * Apr 30, 2014 2060 njensen Safety checks for null guidance
* Oct 12, 2015 4948 dhladky Improved forced FFG handling. * Oct 12, 2015 4948 dhladky Improved forced FFG handling.
* Mar 07 2017 DR 11861 lshi FFMP use of QPF in Basin Table
* Apr 12, 2017 DR 11250 lshi VGBs inclusion for localization was incorrect * Apr 12, 2017 DR 11250 lshi VGBs inclusion for localization was incorrect
* *
* </pre> * </pre>
@ -179,7 +178,7 @@ public class FFMPRowGenerator implements Runnable {
Float guidance = Float.NaN; Float guidance = Float.NaN;
Float qpe = Float.NaN; Float qpe = Float.NaN;
Float rate = Float.NaN; Float rate = Float.NaN;
Float qpf = null; Float qpf = Float.NaN;
FIELDS rowField = FIELDS.NAME; FIELDS rowField = FIELDS.NAME;
if (isVGB) { if (isVGB) {
@ -272,8 +271,8 @@ public class FFMPRowGenerator implements Runnable {
// If guidance is NaN then it cannot be > 0 // If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) { if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance); ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance); diffValue = FFMPUtils.getDiffValue(qpe, guidance);
} }
trd.setTableCellData(i + 5, new FFMPTableCellData( trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue)); FIELDS.RATIO, ratioValue));
@ -339,8 +338,8 @@ public class FFMPRowGenerator implements Runnable {
// If guidance is NaN then it cannot be > 0 // If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) { if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance); ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance); diffValue = FFMPUtils.getDiffValue(qpe, guidance);
} }
trd.setTableCellData(i + 5, new FFMPTableCellData( trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue)); FIELDS.RATIO, ratioValue));
@ -457,8 +456,8 @@ public class FFMPRowGenerator implements Runnable {
float diffValue = Float.NaN; float diffValue = Float.NaN;
// If guidance is NaN then it cannot be > 0 // If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) { if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance); ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance); diffValue = FFMPUtils.getDiffValue(qpe, guidance);
} }
trd.setTableCellData(i + 5, new FFMPTableCellData( trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue)); FIELDS.RATIO, ratioValue));
@ -535,7 +534,7 @@ public class FFMPRowGenerator implements Runnable {
Float qpe = Float.NaN; Float qpe = Float.NaN;
Float guidance = Float.NaN; Float guidance = Float.NaN;
Float rate = Float.NaN; Float rate = Float.NaN;
Float qpf = null; Float qpf = Float.NaN;
Float ratioValue = Float.NaN; Float ratioValue = Float.NaN;
Float diffValue = Float.NaN; Float diffValue = Float.NaN;
@ -700,16 +699,12 @@ public class FFMPRowGenerator implements Runnable {
ft, huc); ft, huc);
} }
List<Float> qpfs = null;
if (qpfBasin != null ){
qpfs = qpfBasin.getAccumValues(pfafs, monitor.getQpfWindow().getAfterTime(), monitor.getQpfWindow().getBeforeTime(), expirationTime, isRate);
}
if ((!qpes.isEmpty()) if ((!qpes.isEmpty())
&& ((guids != null) && (!guids.isEmpty()))) { && ((guids != null) && (!guids.isEmpty()))) {
ratioValue = FFMPUtils ratioValue = FFMPUtils
.getMaxRatioValue(qpes, qpfs, guids); .getMaxRatioValue(qpes, guids);
diffValue = FFMPUtils.getMaxDiffValue(qpes, qpfs, guids); diffValue = FFMPUtils.getMaxDiffValue(qpes, guids);
} }
trd.setTableCellData(i + 5, new FFMPTableCellData( trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue)); FIELDS.RATIO, ratioValue));
@ -771,13 +766,11 @@ public class FFMPRowGenerator implements Runnable {
Float guidance; Float guidance;
Float ratioValue; Float ratioValue;
Float diffValue; Float diffValue;
Float qpfValue;
int i = 0; int i = 0;
for (String guidType : guidBasins.keySet()) { for (String guidType : guidBasins.keySet()) {
guidance = Float.NaN; guidance = Float.NaN;
diffValue = Float.NaN; diffValue = Float.NaN;
ratioValue = Float.NaN; ratioValue = Float.NaN;
qpfValue = null;
FFFGForceUtil forceUtil = forceUtils.get(guidType); FFFGForceUtil forceUtil = forceUtils.get(guidType);
forceUtil.setSliderTime(sliderTime); forceUtil.setSliderTime(sliderTime);
@ -813,19 +806,10 @@ public class FFMPRowGenerator implements Runnable {
FIELDS.GUIDANCE, Float.NaN)); FIELDS.GUIDANCE, Float.NaN));
} }
if (qpfBasin != null) {
FFMPBasin basin = qpfBasin.get(cBasin.getPfaf());
if (basin != null) {
FFMPTimeWindow window = monitor.getQpfWindow();
qpfValue = basin.getAverageValue(window.getAfterTime(),
window.getBeforeTime());
}
}
// If guidance is NaN then it cannot be > 0 // If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) { if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpfValue, guidance); ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpfValue, guidance); diffValue = FFMPUtils.getDiffValue(qpe, guidance);
} }
trd.setTableCellData(i + 5, new FFMPTableCellData(FIELDS.RATIO, trd.setTableCellData(i + 5, new FFMPTableCellData(FIELDS.RATIO,
ratioValue)); ratioValue));

View file

@ -55,7 +55,7 @@ class Procedure (SmartScript.SmartScript):
tr = self.createTimeRange(0, 60, "Database", dbID) tr = self.createTimeRange(0, 60, "Database", dbID)
self.copyCmd(elements, dbID, tr) self.copyCmd(elements, dbID, tr)
#Copy #Copy
dbID = self.findDatabase("RUC80") dbID = self.findDatabase("RAP40")
tr = self.createTimeRange(0, 12, "Database", dbID) tr = self.createTimeRange(0, 12, "Database", dbID)
self.copyCmd(elements, dbID, tr) self.copyCmd(elements, dbID, tr)

View file

@ -24,6 +24,8 @@
--> -->
<fieldDisplayTypesFile> <fieldDisplayTypesFile>
<field key="Wind" displayTypes="BARB,ARROW,STREAMLINE" /> <field key="Wind" displayTypes="BARB,ARROW,STREAMLINE" />
<field key="TransWind" displayTypes="BARB,ARROW,STREAMLINE" />
<field key="LLWSWind" displayTypes="BARB,ARROW,STREAMLINE" />
<field key="geoW" displayTypes="BARB,ARROW" /> <field key="geoW" displayTypes="BARB,ARROW" />
<field key="ageoW" displayTypes="BARB,ARROW" /> <field key="ageoW" displayTypes="BARB,ARROW" />
<field key="ageoVC" displayTypes="STREAMLINE" /> <field key="ageoVC" displayTypes="STREAMLINE" />

View file

@ -84,6 +84,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* 27 Apr 2016 5483 randerso Fix GUI sizing issues * 27 Apr 2016 5483 randerso Fix GUI sizing issues
* 10/02/2017 DR20030 qzhu Fix problems of importing rating curve * 10/02/2017 DR20030 qzhu Fix problems of importing rating curve
* 11/07/2017 DR19987 jdeng Can't Insert a Point in the Middle of Rating Curve Table * 11/07/2017 DR19987 jdeng Can't Insert a Point in the Middle of Rating Curve Table
* Aug. 1 2018 DR20030 jdeng Fix problems of importing rating curve, rework on all white
* spaces.
* </pre> * </pre>
* *
* @author lvenable * @author lvenable
@ -1192,7 +1194,7 @@ public class RatingCurveDlg extends CaveSWTDialog {
// Read File Line By Line // Read File Line By Line
while ((strLine = br.readLine()) != null) { while ((strLine = br.readLine()) != null) {
String[] line = strLine.trim().split("\t"); String[] line = strLine.trim().split("\\s+");
// should be ordered stage, flow separated by a space // should be ordered stage, flow separated by a space
if (line.length == 2) { if (line.length == 2) {
rci.add(new Double(line[0]), new Double(line[1])); rci.add(new Double(line[0]), new Double(line[1]));

View file

@ -130,6 +130,8 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor;
* Mar 06, 2017 6161 mduff Added getFieldData() * Mar 06, 2017 6161 mduff Added getFieldData()
* Oct 06, 2017 6407 bkowal Cleanup. Updates to support GOES-R SATPRE. * Oct 06, 2017 6407 bkowal Cleanup. Updates to support GOES-R SATPRE.
* Apr 10, 2017 17911 mgamazaychikov/wkwock Add loadRFCQPEXmrg. * Apr 10, 2017 17911 mgamazaychikov/wkwock Add loadRFCQPEXmrg.
* Jun 22, 2018 7321 smanoj fixed issue with hourly grid cells not displaying according to color scale
* and color scale on the lower left corner not displaying numeric values.
* *
* </pre> * </pre>
* *
@ -1137,6 +1139,7 @@ public class MPEDisplayManager {
ColorMapParameters params = new ColorMapParameters(); ColorMapParameters params = new ColorMapParameters();
params.setFormatString("0.00"); params.setFormatString("0.00");
params.setDisplayUnit(displayUnit); params.setDisplayUnit(displayUnit);
params.setDataUnit(dataUnit);
UnitConverter displayToData = MPEConversionUtils UnitConverter displayToData = MPEConversionUtils
.constructConverter(displayUnit, dataUnit); .constructConverter(displayUnit, dataUnit);
@ -1199,6 +1202,10 @@ public class MPEDisplayManager {
params.setColorMap(new ColorMap(cvUse, red, green, blue)); params.setColorMap(new ColorMap(cvUse, red, green, blue));
params.setDataMapping(dm); params.setDataMapping(dm);
params.setDataMin(0);
params.setDataMax(numColors - 1);
params.setColorMapMin(params.getDataMin());
params.setColorMapMax(params.getDataMax());
// Check for Index parameter and set labels to radar sites // Check for Index parameter and set labels to radar sites
// Determine and store radar type (S/D/M) for display in legend // Determine and store radar type (S/D/M) for display in legend

View file

@ -6,11 +6,16 @@ package com.raytheon.viz.mpe.ui.rfcmask;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.osgi.framework.Bundle;
import com.raytheon.uf.common.mpe.util.RFCSiteLookup; import com.raytheon.uf.common.mpe.util.RFCSiteLookup;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.xmrg.XmrgFile; import com.raytheon.uf.common.xmrg.XmrgFile;
import com.raytheon.viz.mpe.ui.rsc.MPEFieldResource; import com.raytheon.viz.mpe.ui.Activator;
/** /**
* *
@ -23,6 +28,7 @@ import com.raytheon.viz.mpe.ui.rsc.MPEFieldResource;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Oct 30, 2017 17911 wkwock Initial creation * Oct 30, 2017 17911 wkwock Initial creation
* Jul 31, 2018 20677 wkwock Use FileLocator to open input stream.
* *
* </pre> * </pre>
* *
@ -40,10 +46,9 @@ public class RfcMask {
public static XmrgFile getRFCMask(String rfcSite) throws IOException { public static XmrgFile getRFCMask(String rfcSite) throws IOException {
String rfcName = RFCSiteLookup.RFCMAP.get(rfcSite).toLowerCase(); String rfcName = RFCSiteLookup.RFCMAP.get(rfcSite).toLowerCase();
XmrgFile xmrgFile = new XmrgFile(); XmrgFile xmrgFile = new XmrgFile();
Bundle bundle = Activator.getDefault().getBundle();
try (InputStream is = MPEFieldResource.class IPath path = new Path("/res/RFCmask/xmrg_" + rfcName + "mask");
.getResourceAsStream("/res/RFCmask/xmrg_" + rfcName + "mask")) { try (InputStream is = FileLocator.openStream(bundle, path, false)) {
xmrgFile.load(is); xmrgFile.load(is);
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to read " + rfcName + " RFC mask file.", e); logger.error("Failed to read " + rfcName + " RFC mask file.", e);

View file

@ -60,6 +60,7 @@ import com.raytheon.viz.mpe.ui.rfcmask.RfcMask;
* Mar 01, 2017 6160 bkowal Implemented {@link #getDisplayString()}. * Mar 01, 2017 6160 bkowal Implemented {@link #getDisplayString()}.
* Oct 30, 2017 17911 wkwock Display RFC QPE * Oct 30, 2017 17911 wkwock Display RFC QPE
* May 04, 2018 20677 wkwock Fix display WFO QPE data issue. * May 04, 2018 20677 wkwock Fix display WFO QPE data issue.
* Jul 31, 2018 20677 wkwock Add check for null pointer.
* *
* </pre> * </pre>
* *
@ -310,7 +311,11 @@ public class MPEFieldResourceData extends AbstractMPEGriddedResourceData {
public void maskData(MPEFieldFrame frame) { public void maskData(MPEFieldFrame frame) {
if (frame.origData == null) { if (frame.origData == null) {
frame.origData = frame.data.clone(); frame.origData = frame.data.clone();
if (frame.editedData != null) {
frame.origEditedData = frame.editedData.clone(); frame.origEditedData = frame.editedData.clone();
} else {
frame.origEditedData = null;
}
if (maskXmrg == null) { if (maskXmrg == null) {
AppsDefaults appsDefaults = AppsDefaults.getInstance(); AppsDefaults appsDefaults = AppsDefaults.getInstance();
@ -336,9 +341,11 @@ public class MPEFieldResourceData extends AbstractMPEGriddedResourceData {
for (int i = 0; i < maskData.length; i++) { for (int i = 0; i < maskData.length; i++) {
if (maskData[i] == 0) { if (maskData[i] == 0) {
frame.data[i] = CommonHydroConstants.MISSING_VALUE; frame.data[i] = CommonHydroConstants.MISSING_VALUE;
if (frame.editedData != null) {
frame.editedData[i] = CommonHydroConstants.MISSING_VALUE; frame.editedData[i] = CommonHydroConstants.MISSING_VALUE;
} }
} }
}
} else { } else {
logger.warn( logger.warn(
"QPE data size does not match with RFC mask file size. Check file ascii/coord_*.dat."); "QPE data size does not match with RFC mask file size. Check file ascii/coord_*.dat.");

View file

@ -14,7 +14,7 @@
</configIni> </configIni>
<launcherArgs> <launcherArgs>
<programArgs>-data @user.home/caveData -user @user.home/caveData <programArgs>-data @user.home/caveData -user @user.home/caveData -alertviz -vm "C:/Program Files/Raytheon/AWIPS II/Java/jre/bin/javaw.exe"
</programArgs> </programArgs>
<programArgsLin>-consoleLog <programArgsLin>-consoleLog
</programArgsLin> </programArgsLin>
@ -63,11 +63,13 @@
</win> </win>
</launcher> </launcher>
<vm> <vm>
<linux include="true">jdk1.7.0</linux> <linux include="true">jdk1.7.0</linux>
<windows include="true">jdk1.7.0</windows> <windows include="true">jdk1.7.0</windows>
</vm> </vm>
<plugins> <plugins>
</plugins> </plugins>
@ -104,15 +106,19 @@
<feature id="com.raytheon.uf.viz.ncep.perspective.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.ncep.perspective.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.thinclient.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.thinclient.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.npp.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.npp.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.skewt.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.npp.sounding.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.npp.sounding.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.skewt.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.acarssounding.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.acarssounding.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.viz.avnfps.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.viz.hydro.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.viz.hydro.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.dat.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.gfe.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.d2d.gfe.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.damagepath.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.gisdatastore.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.gisdatastore.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.ui.awips.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.d2d.ui.awips.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.alertview.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.alertview.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.d2d.damagepath.feature" version="1.0.0.qualifier"/> <feature id="com.raytheon.uf.viz.ffmp.feature" version="1.0.0.qualifier"/>
<feature id="com.raytheon.uf.viz.scan.feature" version="1.0.0.qualifier"/>
</features> </features>
<configurations> <configurations>
@ -122,4 +128,11 @@
<plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" /> <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" />
</configurations> </configurations>
<preferencesInfo>
<targetfile overwrite="false"/>
</preferencesInfo>
<cssInfo>
</cssInfo>
</product> </product>

View file

@ -24,18 +24,13 @@ import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Map;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import com.raytheon.uf.common.colormap.image.ColorMapData; import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType; import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.goes.PolarPrecipWaterPixel; import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnitsUtil;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
@ -48,7 +43,6 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback; import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.datacube.DataCubeContainer; import com.raytheon.uf.viz.datacube.DataCubeContainer;
import com.raytheon.viz.satellite.SatelliteConstants;
/** /**
* {@link IColorMapDataRetrievalCallback} for satellite imagery data. Supports * {@link IColorMapDataRetrievalCallback} for satellite imagery data. Supports
@ -66,11 +60,11 @@ import com.raytheon.viz.satellite.SatelliteConstants;
* Apr 09, 2014 2947 bsteffen Improve flexibility of sat derived * Apr 09, 2014 2947 bsteffen Improve flexibility of sat derived
* parameters. * parameters.
* Apr 15, 2014 4388 bsteffen Add method to get signed vs. unsigned from data record. * Apr 15, 2014 4388 bsteffen Add method to get signed vs. unsigned from data record.
* Jul 31, 2018 6389 mapeters Units methods extracted to SatelliteUnitsUtil
* *
* </pre> * </pre>
* *
* @author mschenke * @author mschenke
* @version 1.0
*/ */
public class SatDataRetriever implements IColorMapDataRetrievalCallback { public class SatDataRetriever implements IColorMapDataRetrievalCallback {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
@ -100,9 +94,9 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
Buffer data = null; Buffer data = null;
Unit<?> dataUnit = Unit.ONE; Unit<?> dataUnit = Unit.ONE;
boolean signed = false; boolean signed = false;
Request req = Request.buildSlab(new int[] { this.datasetBounds.x, Request req = Request.buildSlab(
this.datasetBounds.y }, new int[] { new int[] { this.datasetBounds.x, this.datasetBounds.y },
this.datasetBounds.x + this.datasetBounds.width, new int[] { this.datasetBounds.x + this.datasetBounds.width,
this.datasetBounds.y + this.datasetBounds.height }); this.datasetBounds.y + this.datasetBounds.height });
IDataRecord[] dataRecord = null; IDataRecord[] dataRecord = null;
try { try {
@ -141,84 +135,34 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
dataType = ColorMapData.getDataType(data); dataType = ColorMapData.getDataType(data);
} }
return new ColorMapData(data, new int[] { datasetBounds.width, return new ColorMapData(data,
datasetBounds.height }, dataType, dataUnit); new int[] { datasetBounds.width, datasetBounds.height },
dataType, dataUnit);
} }
/** /**
* @param record2 * @deprecated use {@link SatelliteUnitsUtil#getRecordUnit(SatelliteRecord)}
* @return
*/ */
@Deprecated
public static Unit<?> getRecordUnit(SatelliteRecord record) { public static Unit<?> getRecordUnit(SatelliteRecord record) {
Unit<?> recordUnit = null; return SatelliteUnitsUtil.getRecordUnit(record);
String physicalElement = record.getPhysicalElement();
if (record.getUnits() != null && record.getUnits().isEmpty() == false) {
try {
recordUnit = UnitFormat.getUCUMInstance().parseProductUnit(
record.getUnits(), new ParsePosition(0));
} catch (ParseException e) {
statusHandler
.handle(Priority.PROBLEM,
"Unable to parse satellite units: "
+ record.getUnits(), e);
}
}
if (physicalElement.equals(SatelliteConstants.PRECIP)) {
String creatingEntity = record.getCreatingEntity();
if (creatingEntity.equals(SatelliteConstants.DMSP)
|| creatingEntity.equals(SatelliteConstants.POES)) {
recordUnit = new PolarPrecipWaterPixel();
} else if (creatingEntity.equals(SatelliteConstants.MISC)) {
recordUnit = new BlendedTPWPixel();
}
}
return recordUnit;
} }
/** /**
* Extracts the data units for the data record given the PDO's base unit * @deprecated use {@link SatelliteUnitsUtil#getDataUnit(Unit, IDataRecord)}
*
* @param recordUnit
* @param dataRecord
* @return
*/ */
@Deprecated
public static Unit<?> getDataUnit(Unit<?> recordUnit, public static Unit<?> getDataUnit(Unit<?> recordUnit,
IDataRecord dataRecord) { IDataRecord dataRecord) {
Unit<?> units = recordUnit != null ? recordUnit : Unit.ONE; return SatelliteUnitsUtil.getDataUnit(recordUnit, dataRecord);
Map<String, Object> attrs = dataRecord.getDataAttributes();
if (attrs != null) {
Number offset = (Number) attrs.get(SatelliteRecord.SAT_ADD_OFFSET);
Number scale = (Number) attrs.get(SatelliteRecord.SAT_SCALE_FACTOR);
if (offset != null) {
double offsetVal = offset.doubleValue();
if (offsetVal != 0.0) {
units = units.plus(offsetVal);
}
}
if (scale != null) {
double scaleVal = scale.doubleValue();
if (scaleVal != 0.0) {
units = units.times(scaleVal);
}
}
}
return units;
} }
/**
* @deprecated use {@link SatelliteUnitsUtil#isSigned(IDataRecord)}
*/
@Deprecated
public static boolean isSigned(IDataRecord record) { public static boolean isSigned(IDataRecord record) {
Map<String, Object> attrs = record.getDataAttributes(); return SatelliteUnitsUtil.isSigned(record);
if (attrs != null) {
Boolean signed = (Boolean) attrs
.get(SatelliteRecord.SAT_SIGNED_FLAG);
if (signed != null && signed) {
return true;
}
}
return false;
} }
/* /*
@ -244,28 +188,37 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
*/ */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj) {
return true; return true;
if (obj == null) }
if (obj == null) {
return false; return false;
if (getClass() != obj.getClass()) }
if (getClass() != obj.getClass()) {
return false; return false;
}
SatDataRetriever other = (SatDataRetriever) obj; SatDataRetriever other = (SatDataRetriever) obj;
if (dataset == null) { if (dataset == null) {
if (other.dataset != null) if (other.dataset != null) {
return false; return false;
} else if (!dataset.equals(other.dataset)) }
} else if (!dataset.equals(other.dataset)) {
return false; return false;
}
if (datasetBounds == null) { if (datasetBounds == null) {
if (other.datasetBounds != null) if (other.datasetBounds != null) {
return false; return false;
} else if (!datasetBounds.equals(other.datasetBounds)) }
} else if (!datasetBounds.equals(other.datasetBounds)) {
return false; return false;
}
if (record == null) { if (record == null) {
if (other.record != null) if (other.record != null) {
return false; return false;
} else if (!record.equals(other.record)) }
} else if (!record.equals(other.record)) {
return false; return false;
}
return true; return true;
} }

View file

@ -24,26 +24,72 @@
of the file. of the file.
--> -->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="menuItem" menuText="Max Temp" key="MxT12hr" /> <contribute xsi:type="toolbarSubMenu" menuText="Aviation">
<contribute xsi:type="menuItem" menuText="Min Temp" key="MnT12hr" /> <contribute xsi:type="menuItem" menuText="Cloud Base" key="CC" />
<contribute xsi:type="menuItem" menuText="Min Rel Humidity" key="MINRH12hr" /> <contribute xsi:type="menuItem" menuText="Echo Tops" key="RETOP" />
<contribute xsi:type="menuItem" menuText="Max Rel Humidity" key="MAXRH12hr" /> <contribute xsi:type="menuItem" menuText="LLWS Height" key="LLWSHgt" />
<contribute xsi:type="menuItem" menuText="Max Wet Bulb Temp" key="MaxTW" /> <contribute xsi:type="menuItem" menuText="LLWS Wind" key="LLWSWind" />
<contribute xsi:type="menuItem" menuText="POP 12hr" key="POP12hr" /> <contribute xsi:type="menuItem" menuText="Simulated Maximum Reflectivity" key="MAXREFmax1hr" />
<contribute xsi:type="menuItem" menuText="1hr Precip Pot Idx" key="PPI1hr" />
<contribute xsi:type="menuItem" menuText="6hr Precip Pot Idx" key="PPI6hr" />
<contribute xsi:type="menuItem" menuText="1hr Precip Accum" key="TP1hr" />
<contribute xsi:type="menuItem" menuText="6hr Precip Accum" key="TP6hr" />
<contribute xsi:type="menuItem" menuText="Prob Cloud Ice" key="PrbCldIce" />
<contribute xsi:type="menuItem" menuText="Prob Rain" key="PTypRain" />
<contribute xsi:type="menuItem" menuText="Prob Freezing Rain" key="PTypFreezingRain" />
<contribute xsi:type="menuItem" menuText="Prob Snow" key="PTypSnow" />
<contribute xsi:type="menuItem" menuText="Prob Ice Pellets" key="PTypIcePellets" />
<contribute xsi:type="menuItem" menuText="Prob Refreeze Ice Plts" key="PTypeRefIP" />
<contribute xsi:type="menuItem" menuText="Total Cloud Cover" key="TCC" /> <contribute xsi:type="menuItem" menuText="Total Cloud Cover" key="TCC" />
<contribute xsi:type="menuItem" menuText="Vertically Integrated Liquid" key="VILIQ" />
<contribute xsi:type="menuItem" menuText="Visibility" key="Vis" />
</contribute>
<contribute xsi:type="toolbarSubMenu" menuText="FireWx">
<contribute xsi:type="menuItem" menuText="Fosberg Fire Weather index" key="FOSINDX6hr" />
<contribute xsi:type="menuItem" menuText="Haines Index" key="HINDEX6hr" />
<contribute xsi:type="menuItem" menuText="Mixing Height" key="MIXHT" />
<contribute xsi:type="menuItem" menuText="Transport Wind" key="TransWind" />
<contribute xsi:type="menuItem" menuText="Ventilation Rate" key="VRATE" />
</contribute>
<contribute xsi:type="toolbarSubMenu" menuText="Winter Wx">
<contribute xsi:type="menuItem" menuText="1-h Ice Accumulation" key="FICEAC1hr" />
<contribute xsi:type="menuItem" menuText="6-h Ice Accumulation" key="FICEAC6hr" />
<contribute xsi:type="menuItem" menuText="Max Wet Bulb Temp" key="MaxTW" />
<contribute xsi:type="menuItem" menuText="Negative Energy Low-level" key="NBE" />
<contribute xsi:type="menuItem" menuText="Positive Energy Aloft" key="PBE" />
<contribute xsi:type="menuItem" menuText="Predominant Weather" key="PWTHER" />
<contribute xsi:type="menuItem" menuText="Prob Cloud Ice" key="PrbCldIce" />
<contribute xsi:type="menuItem" menuText="Prob Freezing Rain" key="PTypFreezingRain" />
<contribute xsi:type="menuItem" menuText="Prob Ice Pellets" key="PTypIcePellets" />
<contribute xsi:type="menuItem" menuText="Prob Rain" key="PTypRain" />
<contribute xsi:type="menuItem" menuText="Prob Refreeze Ice Plts" key="PTypeRefIP" />
<contribute xsi:type="menuItem" menuText="Prob Snow" key="PTypSnow" />
<contribute xsi:type="menuItem" menuText="1-h Snow Accumulation" key="TOTSN1hr" />
<contribute xsi:type="menuItem" menuText="6-h Snow Accumulation" key="TOTSN6hr" />
<contribute xsi:type="menuItem" menuText="Snow-Liquid Ratio" key="SNOWRATIO" /> <contribute xsi:type="menuItem" menuText="Snow-Liquid Ratio" key="SNOWRATIO" />
<contribute xsi:type="menuItem" menuText="Snow Level" key="SNOWLVL" /> <contribute xsi:type="menuItem" menuText="Snow Level" key="SNOWLVL" />
<contribute xsi:type="menuItem" menuText="Visibility" key="Vis" /> </contribute>
<contribute xsi:type="toolbarSubMenu" menuText="Tstorm">
<contribute xsi:type="menuItem" menuText="12-h Prob. of a Thunderstorm" key="ThP12hr" />
<contribute xsi:type="menuItem" menuText="3-h SREF-based Prob. of a Dry Thunderstorm" key="DRYTPPROB3hr" />
<contribute xsi:type="menuItem" menuText="1-h SREF-based Prob. of a Thunderstorm" key="ThP1hr" />
<contribute xsi:type="menuItem" menuText="Tstorm Prob 3hr" key="ThP3hr" /> <contribute xsi:type="menuItem" menuText="Tstorm Prob 3hr" key="ThP3hr" />
<contribute xsi:type="menuItem" menuText="Tstorm Prob 6hr" key="ThP6hr" /> </contribute>
<contribute xsi:type="toolbarSubMenu" menuText="Oceanic">
<contribute xsi:type="menuItem" menuText="50th Percentile Air temperature" key="T50pct" />
<contribute xsi:type="menuItem" menuText="10th Percentile Mean Sea Level Pressure" key="PMSL10pct" />
<contribute xsi:type="menuItem" menuText="50th Percentile Mean Sea Level Pressure" key="PMSL50pct" />
<contribute xsi:type="menuItem" menuText="90th Percentile Mean Sea Level Pressure" key="PMSL90pct" />
<contribute xsi:type="menuItem" menuText="10-m Wind Gust" key="WGS50pct" />
<contribute xsi:type="menuItem" menuText="30-m/80-m Wind Speed" key="WS50pct" />
</contribute>
<contribute xsi:type="menuItem" menuText="Max Rel Humidity" key="MAXRH12hr" />
<contribute xsi:type="menuItem" menuText="Max Temp" key="MxT12hr" />
<contribute xsi:type="menuItem" menuText="Min Rel Humidity" key="MINRH12hr" />
<contribute xsi:type="menuItem" menuText="Min Temp" key="MnT12hr" />
<contribute xsi:type="menuItem" menuText="10th percentile 6-h Quant" key="TP10pct6hr" />
<contribute xsi:type="menuItem" menuText="50th percentile 6-h Quant" key="TP50pct6hr" />
<contribute xsi:type="menuItem" menuText="90th percentile 6-h Quant" key="TP90pct6hr" />
<contribute xsi:type="menuItem" menuText="POP 12hr" key="POP12hr" />
<contribute xsi:type="menuItem" menuText="1hr Precip Accum" key="TP1hr" />
<contribute xsi:type="menuItem" menuText="6hr Precip Accum" key="TP6hr" />
<contribute xsi:type="menuItem" menuText="1hr Precip Potential Index" key="PPI1hr" />
<contribute xsi:type="menuItem" menuText="6hr Precip Potential Index" key="PPI6hr" />
<contribute xsi:type="menuItem" menuText="6-h Prob. of Precipitation" key="POP6hr" />
<contribute xsi:type="menuItem" menuText="Significant Wave Height" key="HTSGW" />
</menuTemplate> </menuTemplate>

View file

@ -81,6 +81,7 @@
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="120agl" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="120agl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="150agl" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="150agl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="400agl" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="400agl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="0.61-40kmAgl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="EchoTop" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="EchoTop" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="El" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="El" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="SIG0.8-0.5" <contribute xsi:type="menuItem" textLookup="LevelMapping" key="SIG0.8-0.5"
@ -160,4 +161,9 @@
indentText="false" /> indentText="false" />
</contribute> </contribute>
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="NTAT" indentText="false" /> <contribute xsi:type="menuItem" textLookup="LevelMapping" key="NTAT" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="2FHAG" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="10FHAG" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="0-0.61kmAgl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="30mAgl" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="80mAgl" indentText="false" />
</menuTemplate> </menuTemplate>

View file

@ -29,14 +29,12 @@
id="com.raytheon.viz.volumebrowser.volumeBrowser" id="com.raytheon.viz.volumebrowser.volumeBrowser"
name="Volume Browser"> name="Volume Browser">
</command> </command>
</extension>
<extension
point="org.eclipse.ui.commands">
<command <command
id="com.raytheon.viz.volumebrowser.volumeBrowserRef" id="com.raytheon.viz.volumebrowser.volumeBrowserRef"
name="Volume Browser"> name="Volume Browser">
<commandParameter
id="viewType"
name="viewType"
optional="false">
</commandParameter>
</command> </command>
</extension> </extension>
<extension <extension
@ -57,14 +55,14 @@
<path <path
application="D2D" application="D2D"
localizationType="CAVE_STATIC,COMMON_STATIC" localizationType="CAVE_STATIC,COMMON_STATIC"
name="Volume Browser Sources" name="Volume Browser"
value="volumebrowser" value="level/mappings"
recursive="true"> recursive="true">
</path> </path>
<path <path
application="D2D" application="D2D"
localizationType="CAVE_STATIC" localizationType="CAVE_STATIC"
name="Volume Browser Height Scales" name="Height Scales"
value="scales" value="scales"
recursive="true"> recursive="true">
</path> </path>
@ -75,7 +73,7 @@
locationURI="menu:volume?after=top"> locationURI="menu:volume?after=top">
<command <command
commandId="com.raytheon.viz.volumebrowser.volumeBrowserRef" commandId="com.raytheon.viz.volumebrowser.volumeBrowserRef"
label="Volume Browser"> label="Browser...">
</command> </command>
<separator name="afterVB" visible="false"/> <separator name="afterVB" visible="false"/>
<separator name="VolumeBundles" visible="true"/> <separator name="VolumeBundles" visible="true"/>

View file

@ -126,6 +126,14 @@ NWS_ROLE_DATA = {
] ]
} }
def formatElement(element):
s = "<" + element.tag
if element.attrib:
for id, value in element.items():
s += ' %s="%s"' % (id, value)
s += ">"
return s
def validateSchema(element, schema): def validateSchema(element, schema):
# validates the xml is syntactically correct based on the provided schema # validates the xml is syntactically correct based on the provided schema
# there is no validation of the content, just the format # there is no validation of the content, just the format

View file

@ -6,12 +6,13 @@
# overrides of these files. # overrides of these files.
## ##
import copy
import logging import logging
import glob import glob
import imp import imp
import os
import os.path import os.path
import pprint import pprint
import re
import shutil import shutil
@ -141,48 +142,86 @@ from DefaultCityLocation import CityLocation
def create_incremental_area_dictionary(): def create_incremental_area_dictionary():
for file in glob.iglob(AREA_DICT_GLOB_PATH): for site_file in glob.iglob(AREA_DICT_GLOB_PATH):
log.info("Generating incremental override file [%s]...", file) log.info("Generating incremental override file [%s]...", site_file)
base_file = file.replace("site", "configured", 1) base_file = site_file.replace("site", "configured", 1)
if not os.path.isfile(base_file): if not os.path.isfile(base_file):
log.error("Could not find CONFIGURED level file [%s].", base_file) log.error("Could not find CONFIGURED level file [%s].", base_file)
log.error("Skipping to next file.") log.error("Skipping to next file.")
continue
log.debug("Using configured file [%s]...", base_file) with open(site_file, 'r') as f:
log.debug("Using site file [%s]...", file) contents = f.read()
if "from DefaultAreaDictionary import AreaDictionary" in contents:
log.info("Site AreaDictionary file [%s] has already been upgraded.", site_file)
continue
log.info("Using configured file [%s]...", base_file)
log.info("Using site file [%s]...", site_file)
configured_module = imp.load_source('base', base_file) configured_module = imp.load_source('base', base_file)
site_module = imp.load_source('override', file) site_module = imp.load_source('override', site_file)
configured_dict = configured_module.AreaDictionary configured_dict = configured_module.AreaDictionary
site_dict = site_module.AreaDictionary site_dict = site_module.AreaDictionary
diffs = diff_dicts(configured_dict, site_dict) diffs = diff_dicts(configured_dict, site_dict)
log.debug("AreaDictionary Differences: %r", diffs) log.debug("AreaDictionary Differences: %r", diffs)
write_override_file(file, 'AreaDictionary', diffs, AREA_DICT_HEADER) write_override_file(site_file, 'AreaDictionary', diffs, AREA_DICT_HEADER)
delete_files(base_file + '*')
def create_incremental_city_location(): def create_incremental_city_location():
for file in glob.iglob(CITY_LOC_GLOB_PATH): for site_file in glob.iglob(CITY_LOC_GLOB_PATH):
log.info("Generating incremental override file [%s]...", file) log.info("Generating incremental override file [%s]...", site_file)
base_file = file.replace("site", "configured", 1) base_file = site_file.replace("site", "configured", 1)
if not os.path.isfile(base_file): if not os.path.isfile(base_file):
log.error("Could not find CONFIGURED level file [%s].", base_file) log.error("Could not find CONFIGURED level file [%s].", base_file)
log.error("Skipping to next file..") log.error("Skipping to next file.")
continue
log.debug("Using configured file [%s]...", base_file) with open(site_file, 'r') as f:
log.debug("Using site file [%s]...", file) contents = f.read()
if "from DefaultCityLocation import CityLocation" in contents:
log.info("Site CityLocation file [%s] has already been upgraded.", site_file)
continue
log.info("Using configured file [%s]...", base_file)
log.info("Using site file [%s]...", site_file)
configured_module = imp.load_source('base', base_file) configured_module = imp.load_source('base', base_file)
site_module = imp.load_source('override', file) site_module = imp.load_source('override', site_file)
configured_dict = configured_module.CityLocation configured_dict = configured_module.CityLocation
site_dict = site_module.CityLocation site_dict = site_module.CityLocation
diffs = diff_dicts(configured_dict, site_dict) diffs = diff_dicts(configured_dict, site_dict)
log.debug("CityLocation Differences: %r", diffs) log.debug("CityLocation Differences: %r", diffs)
write_override_file(file, 'CityLocation', diffs, CITY_LOCATION_HEADER) write_override_file(site_file, 'CityLocation', diffs, CITY_LOCATION_HEADER)
def diff_dicts(base, override, level=0): delete_files(base_file + '*')
def diff_dicts(base, override):
differences = []
keys = set().union(base.keys(), override.keys())
# log.debug("Combined keys: %s", keys)
for key in sorted(keys):
if key not in base:
log.debug("Key [%s] in override, but not base.", key)
differences.append((key, copy.copy(override[key]), True))
elif key not in override:
log.debug("Key [%s] in base, but not override.", key)
else:
sub_diffs = sub_diff_dicts(base[key], override[key])
if sub_diffs:
log.debug("Differences for key [%s]: %r", key, sub_diffs)
differences.append((key, sub_diffs, False))
return differences
def sub_diff_dicts(base, override, level=0):
differences = {} differences = {}
keys = set().union(base.keys(), override.keys()) keys = set().union(base.keys(), override.keys())
@ -191,45 +230,50 @@ def diff_dicts(base, override, level=0):
for key in sorted(keys): for key in sorted(keys):
if key not in base: if key not in base:
log.debug("Key [%s] in override, but not base.", key) log.debug("Key [%s] in override, but not base.", key)
differences[key] = override[key].copy() differences[key] = copy.copy(override[key])
elif key not in override: elif key not in override:
log.debug("Key [%s] in base, but not override.", key) log.debug("Key [%s] in base, but not override.", key)
else:
if level != 1:
sub_diffs = diff_dicts(base[key], override[key], level+1)
if sub_diffs:
log.debug("Differences for key [%s]: %r", key, sub_diffs)
differences[key] = sub_diffs
else: else:
if base[key] != override[key]: if base[key] != override[key]:
differences[key] = override[key] differences[key] = override[key]
return differences return differences
def write_override_file(file, object_name, object_value, header): def write_override_file(file_name, object_name, object_value, header):
backup_file = file + ".bak.dr_6346" backup_file = file_name + ".bak.dr_6346"
log.info("Writing backup file [%s]", backup_file) log.info("Writing backup file [%s]", backup_file)
try: try:
shutil.copy(file, backup_file) shutil.copy(file_name, backup_file)
except: except:
log.exception("Unable to write backup file [%s]", backup_file) log.exception("Unable to write backup file [%s]", backup_file)
log.error("Skipping file [%s]", file) log.error("Skipping file [%s]", file_name)
return return
log.info("Writing override file [%s]", file) log.info("Writing override file [%s]", file_name)
try: try:
with open(file, 'w') as out_file: with open(file_name, 'w') as out_file:
printer = pprint.PrettyPrinter() printer = pprint.PrettyPrinter()
out_file.write(header) out_file.write(header)
for key in sorted(object_value.keys()): for (key, value, added) in sorted(object_value, key=lambda i: i[0]):
for sub_key in sorted(object_value[key].keys()): if added:
out_file.write("{}[{}][{}] = {}".format(object_name, key, sub_key, printer.pformat(object_value[key][sub_key]))) out_file.write("{}[{!r}] = {}".format(object_name, key, printer.pformat(value)))
out_file.write('\n')
else:
for sub_key in sorted(value.keys()):
out_file.write("{}[{!r}][{!r}] = {}".format(object_name, key, sub_key, printer.pformat(value[sub_key])))
out_file.write('\n') out_file.write('\n')
out_file.write('\n') out_file.write('\n')
except: except:
log.exception("Unable to write incremental override file [%s]", file) log.exception("Unable to write incremental override file [%s]", file_name)
log.critical("Restore backup file [%s] to [%s] before restarting EDEX.", backup_file, file) log.critical("Restore backup file [%s] to [%s] before restarting EDEX.", backup_file, file_name)
def delete_files(file_pattern):
for f in glob.iglob(file_pattern):
try:
os.remove(f)
except:
log.exception("Unable to delete file [%s].", f)
def main(): def main():
log.info("Starting delta script for DR #6346: creating incremental overrides for AreaDictionary.py and CityLocation.py...") log.info("Starting delta script for DR #6346: creating incremental overrides for AreaDictionary.py and CityLocation.py...")

View file

@ -0,0 +1,11 @@
#!/bin/bash
# #7424 - This script adds an index to the grid_info table's location column to
# allow for faster lookup and deletion of large numbers of grid_coverage.
#
# NOTE: This script will error if the index already exists, but this will not
# negatively impact the system.
# run the update
echo "DR #7427 - Adding index to grid_info.location..."
/awips2/psql/bin/psql -U awipsadmin -d metadata -c "CREATE INDEX grid_info_location_id_index ON grid_info USING btree (location_id);"

View file

@ -82,7 +82,7 @@ td:first-child { font-weight: bold }
| lsr | Local Storm Reports | | lsr | Local Storm Reports |
| mpe | Multi-sensor Precipitation Estimation | | mpe | Multi-sensor Precipitation Estimation |
| preciprate | Precipitation Rate from SCAN. Raw data input: radar data [with WSR-88D product mnemonic and number] needed for preciprate are Digital Hybrid Reflectivity [DHR, 32]. | | preciprate | Precipitation Rate from SCAN. Raw data input: radar data [with WSR-88D product mnemonic and number] needed for preciprate are Digital Hybrid Reflectivity [DHR, 32]. |
| qpf | Quantitative Precipitation Forecast from SCAN. (raw data inputs: radar and some RUC130 fields. Radar data [with WSR-88D product mnemonics and numbers] needed for SCANs QPF are 0.5 degree Base Reflectivity [Z, 19], 4 km Vertically Integrated Liquid [VIL, 57], and Storm Track [STI, 58]. The RUC130 field needed is 700 mb Wind, as defined in the SCANRunSiteConfig.xml file.) | | qpf | Quantitative Precipitation Forecast from SCAN. (raw data inputs: radar and some RAP13 fields. Radar data [with WSR-88D product mnemonics and numbers] needed for SCANs QPF are 0.5 degree Base Reflectivity [Z, 19], 4 km Vertically Integrated Liquid [VIL, 57], and Storm Track [STI, 58]. The RAP13 field needed is 700 mb Wind, as defined in the SCANRunSiteConfig.xml file.) |
| satpre | Satellite-estimated Pecipiration (hydroApps) | | satpre | Satellite-estimated Pecipiration (hydroApps) |
| scan | SCAN (System for Convection Analysis and Nowcasting). (Inputs for the SCAN Table include radar, cloud-to-ground lightning from the NLDN, fields from RAP13, and CWAT. Specific radar products [with WSR-88D product mnemonics and numbers] are: 1 km Composite Reflectivity [CZ, 37]; 0.5 degree Base Reflectivity [Z, 19]; 4 km Vertically Integrated Liquid [VIL, 57]; Storm Track [STI, 58]; Mesocyclone Detections [MD, 141]; and Tornadic Vortex Signature [TVS, 61]. | | scan | SCAN (System for Convection Analysis and Nowcasting). (Inputs for the SCAN Table include radar, cloud-to-ground lightning from the NLDN, fields from RAP13, and CWAT. Specific radar products [with WSR-88D product mnemonics and numbers] are: 1 km Composite Reflectivity [CZ, 37]; 0.5 degree Base Reflectivity [Z, 19]; 4 km Vertically Integrated Liquid [VIL, 57]; Storm Track [STI, 58]; Mesocyclone Detections [MD, 141]; and Tornadic Vortex Signature [TVS, 61]. |
| shef | Standard Hydrometeorological Exchange Format data. | | shef | Standard Hydrometeorological Exchange Format data. |

View file

@ -18,6 +18,15 @@ Every server should have one line for every server in the replication setup,
including itself--thus all servers should have the same lines. This enables including itself--thus all servers should have the same lines. This enables
quickly changing which server is the master without extra configuration. quickly changing which server is the master without extra configuration.
Also you need to add a SSL certificate and key for the "replication" DB role.
You have to create these files yourself, except for root.crt which is the
root certificate for the database--you can copy that one straight from
/awips2/database/ssl. Put them here:
/awips2/database/ssl/replication/${hostname -s}/replication.crt
/awips2/database/ssl/replication/${hostname -s}/replication.key
/awips2/database/ssl/replication/${hostname -s}/root.crt
SETTING UP STANDBYS SETTING UP STANDBYS
------------------- -------------------

View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# ##
# This software was developed and / or modified by Raytheon Company, # This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government. # pursuant to Contract DG133W-05-CQ-1067 with the US Government.
# #
@ -18,6 +18,23 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for # See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information. # further licensing information.
# #
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# Sep 22, 2016 5885 tgurney Initial creation
# Jan 4, 2017 6056 tgurney Fix tmp dir cleanup
# Mar 16, 2017 6184 tgurney Update to fetch and use SSL certificates
# Mar 29, 2017 6184 tgurney Fix SSL certificate sync from master
# Apr 4, 2017 6184 tgurney Set correct permissions on cert directory
# Apr 4, 2017 6122 tgurney Move database to /awips2/database
# + cleanup and fixes for postgres 9.5.x
# Aug 6, 2018 7431 tgurney Bug fixes. Allow starting without a
# pg_hba.conf on standby server
#
##
# Configuration ############################################################### # Configuration ###############################################################
@ -37,7 +54,7 @@ ssl_dir=/awips2/database/ssl
tablespace_dir=/awips2/database/tablespaces tablespace_dir=/awips2/database/tablespaces
# pg_hba.conf backup location # pg_hba.conf backup location
hba_backup="$(mktemp pg_hba.backup.XXXXXX)" hba_backup="$(mktemp /tmp/pg_hba.backup.XXXXXX)"
rm -f "${hba_backup}" rm -f "${hba_backup}"
# For logging the output of this script # For logging the output of this script
@ -54,7 +71,7 @@ pg_basebackup=${pg_dir}/bin/pg_basebackup
pg_ctl=${pg_dir}/bin/pg_ctl pg_ctl=${pg_dir}/bin/pg_ctl
psql=/awips2/psql/bin/psql psql=/awips2/psql/bin/psql
${as_awips}='sudo -u awips -i ' as_awips='sudo -u awips -i '
log() { log() {
echo $* | ${as_awips} tee -a "${log_file}" echo $* | ${as_awips} tee -a "${log_file}"
@ -73,22 +90,26 @@ stop_server() {
do_pg_ctl -m fast stop && sleep 1 do_pg_ctl -m fast stop && sleep 1
do_pg_ctl -s status do_pg_ctl -s status
# error code 3 from pg_ctl means server is not running # error code 3 from pg_ctl means server is not running
[[ "$?" -eq 3 ]]; return $? # 4 means there is no database in the data dir, this is okay
[[ "$?" -eq 3 || "$?" -eq 4 ]]; return $?
} }
make_clean_db_dirs() { make_clean_db_dirs() {
for dir in ("${data_dir}" "${tablespace_dir}"); do rm -rf "${data_dir}"
rm -rf "${dir}" ${as_awips} mkdir -p "${data_dir}"
${as_awips} mkdir -p "${dir}" ${as_awips} chmod 700 "${data_dir}"
${as_awips} chmod 700 "${dir}" rm -rf "${tablespace_dir}"
done ${as_awips} mkdir -p "${tablespace_dir}"
${as_awips} chmod 700 "${tablespace_dir}"
} }
restore_pg_hba() { restore_pg_hba() {
if [[ -f "${hba_backup}" ]]; then if [[ -f "${hba_backup}" ]]; then
log "INFO: Restoring backed up pg_hba.conf" log "INFO: Restoring backed up pg_hba.conf"
${as_awips} mv "${hba_backup}" "${data_dir}"/pg_hba.conf ${as_awips} cp -a "${hba_backup}" "${data_dir}"/pg_hba.conf
${as_awips} chmod 600 "${data_dir}"/pg_hba.conf ${as_awips} chmod 600 "${data_dir}"/pg_hba.conf
else
log "WARN: No backed up pg_hba.conf to restore"
fi fi
} }
@ -171,6 +192,7 @@ trap 'cleanup_exit' SIGINT SIGTERM
# Get certificates from master # Get certificates from master
master_ssl_dir="${ssl_dir}/replication/${master_hostname}" master_ssl_dir="${ssl_dir}/replication/${master_hostname}"
echo ${as_awips} mkdir -p "${master_ssl_dir}"
${as_awips} mkdir -p "${master_ssl_dir}" ${as_awips} mkdir -p "${master_ssl_dir}"
log "INFO: Downloading SSL certs and keyfile from ${master_hostname}" log "INFO: Downloading SSL certs and keyfile from ${master_hostname}"
# must ssh as root to skip password prompt # must ssh as root to skip password prompt
@ -184,6 +206,9 @@ find "${ssl_dir}"/replication -xdev -type d -exec chmod 700 {} \;
# Backup pg_hba.conf # Backup pg_hba.conf
if [[ -f "${data_dir}/pg_hba.conf" ]]; then if [[ -f "${data_dir}/pg_hba.conf" ]]; then
${as_awips} cp -a "${data_dir}/pg_hba.conf" "${hba_backup}" || cleanup_exit ${as_awips} cp -a "${data_dir}/pg_hba.conf" "${hba_backup}" || cleanup_exit
log "INFO: Backup of pg_hba.conf is at ${hba_backup}"
else
log "WARN: Cannot backup local ${data_dir}/pg_hba.conf because it does not exist. Continuing anyway."
fi fi
# Delete all database files # Delete all database files
@ -206,7 +231,11 @@ ${as_awips} "${pg_basebackup}" \
--username="${db_rep_user}" \ --username="${db_rep_user}" \
--port=${master_port} \ --port=${master_port} \
--db="${ssl_part}" \ --db="${ssl_part}" \
-D "${data_tmpdir}" || cleanup_exit -D "${data_dir}" 2>&1 | tee -a ${log_file}
if [[ "${PIPESTATUS[0]}" != "0" ]]; then
cleanup_exit
fi
# Write recovery.conf # Write recovery.conf
@ -248,4 +277,6 @@ if [[ "${is_recovery}" != "t" ]]; then
cleanup_exit cleanup_exit
fi fi
rm -f "${hba_backup}"
log "INFO: Setup is complete. No errors reported." log "INFO: Setup is complete. No errors reported."

View file

@ -177,9 +177,9 @@ public class SmartInitQueue {
* *
* <pre> * <pre>
* Examples: * Examples:
* OAX_GRID_D2D_RUC13_20100923_0900 or * OAX_GRID_D2D_RAP13_20100923_0900 or
* OAX_GRID_D2D_RUC13_20100923_0900:1 or * OAX_GRID_D2D_RAP13_20100923_0900:1 or
* OAX_GRID_D2D_RUC13_20100923_0900:1:myRUC13 * OAX_GRID_D2D_RAP13_20100923_0900:1:myRAP13
* </pre> * </pre>
*/ */
public void addManualInit(String init) { public void addManualInit(String init) {
@ -290,9 +290,9 @@ public class SmartInitQueue {
return rval; return rval;
} }
// OAX_GRID_D2D_RUC13_20100923_0900 or // OAX_GRID_D2D_RAP13_20100923_0900 or
// OAX_GRID_D2D_RUC13_20100923_0900:1 or // OAX_GRID_D2D_RAP13_20100923_0900:1 or
// OAX_GRID_D2D_RUC13_20100923_0900:1:myRUC13 // OAX_GRID_D2D_RAP13_20100923_0900:1:myRAP13
String[] tokens = initName.split("[:]"); String[] tokens = initName.split("[:]");
int index = tokens[0].indexOf("_GRID_D2D_"); int index = tokens[0].indexOf("_GRID_D2D_");

View file

@ -52,7 +52,7 @@
# 01/19/2015 #4014 dgilling Added ETSS. # 01/19/2015 #4014 dgilling Added ETSS.
# 02/11/2015 #4053 rferrel Added GLWN and moved GLERL to display only for Great Lakes sites.. # 02/11/2015 #4053 rferrel Added GLWN and moved GLERL to display only for Great Lakes sites..
# 01/19/2015 #4014 dgilling Added ETSS. # 01/19/2015 #4014 dgilling Added ETSS.
# 02/24/2015 #16692 byin Added RTMA. Removed gfsLR and GWW233 # 02/24/2015 #16692 byin Added RTMA. Removed gfsLR and WaveWatch
# 03/19/2015 #4300 randerso Remove GUMa as it is obsolete (per Shannon White) # 03/19/2015 #4300 randerso Remove GUMa as it is obsolete (per Shannon White)
# 03/30/2015 #17288 bhunder Added Guam-RTMA to D2D models # 03/30/2015 #17288 bhunder Added Guam-RTMA to D2D models
# 03/30/2015 #17206 yteng Changed some parameters that are not rate parameters # 03/30/2015 #17206 yteng Changed some parameters that are not rate parameters
@ -102,8 +102,10 @@
# 11/28/2017 6539 randerso Made P-ETSS and TPCSurgeProb elements D2DAccumulativeElements # 11/28/2017 6539 randerso Made P-ETSS and TPCSurgeProb elements D2DAccumulativeElements
# 12/06/2017 DCS20267 psantos Add NWPS Rip Current Guidance # 12/06/2017 DCS20267 psantos Add NWPS Rip Current Guidance
# 12/20/2017 20510 ryu changes to StormTotalSnow parameter # 12/20/2017 20510 ryu changes to StormTotalSnow parameter
# 02/23/2018 #20395 wkwock Added NBM3.1 elements.
# 04/03/2018 DR20656 arivera Missing comma: "Dune Erosion Probability" in optionalParmsDict['marine'] # 04/03/2018 DR20656 arivera Missing comma: "Dune Erosion Probability" in optionalParmsDict['marine']
# 05/09/2018 DR20715 arivera Missing comma: groups['marineSites'] after 'AVAK' # 05/09/2018 DR20715 arivera Missing comma: groups['marineSites'] after 'AVAK'
# 06/18/2018 16729 ryu Remove tpHPC element from RFCQPF model and the smart init for the model.
# #
#################################################################################################### ####################################################################################################
@ -865,7 +867,7 @@ for r in siteRegion:
myRegion=r myRegion=r
break break
groups['powt']=list(siteRegion['CR']) groups['powt']=list(groups['OCONUS_SITES']+ siteRegion['CR'] + siteRegion['ER'] + siteRegion['SR'] + siteRegion['WR'])
groups['marineSites']=[ groups['marineSites']=[
# CONUS WFOs # CONUS WFOs
"CAR","GYX","BOX","OKX","PHI","LWX","AKQ","MHX","ILM","CHS", "CAR","GYX","BOX","OKX","PHI","LWX","AKQ","MHX","ILM","CHS",
@ -1128,13 +1130,20 @@ PPI01=('PPI01', SCALAR, '%', '1-H Precip Potential Index', 100.0, 0.0, 0, NO)
PPI06=('PPI06', SCALAR, '%', '6-H Precip Potential Index', 100.0, 0.0, 0, NO) PPI06=('PPI06', SCALAR, '%', '6-H Precip Potential Index', 100.0, 0.0, 0, NO)
PositiveEnergyAloft=("PositiveEnergyAloft" , SCALAR, "j/kg", "Positive energy aloft" , 500.0, 0.0, 1, NO) PositiveEnergyAloft=("PositiveEnergyAloft" , SCALAR, "j/kg", "Positive energy aloft" , 500.0, 0.0, 1, NO)
NegativeEnergyLowLevel=("NegativeEnergyLowLevel" , SCALAR, "j/kg", "Negative energy in the low levels" , 0.0, -500.0, 1, NO) NegativeEnergyLowLevel=("NegativeEnergyLowLevel" , SCALAR, "j/kg", "Negative energy in the low levels" , 0.0, -500.0, 1, NO)
PoTIP=('PotSleet', SCALAR, '%', 'Prob of Sleet', 100.0, 0.0, 0, NO) SnowAmt01 = ("SnowAmt01", SCALAR, "in", "1-h Snow Accumulation", 20.0, 0.0, 1, YES)
PoTR=('PotRain', SCALAR, '%', 'Prob of Rain', 100.0, 0.0, 0, NO) IceAccum01 = ("IceAccum01", SCALAR, "inch", "1-h Ice Accumulation", maxIceVal, 0.0, 3, NO)
PoTS=('PotSnow', SCALAR, '%', 'Prob of Snow', 100.0, 0.0, 0, NO) IceAccum = ("IceAccum", SCALAR, "inch", "6-h Ice Accumulation", 13.0, 0.0, 3, NO)
PoTZR=('PotFreezingRain', SCALAR, '%', 'Prob of Freezing Rain', 100.0, 0.0, 0, NO) TstmPrb1 = ("TstmPrb1", SCALAR, "%", "1-h SREF-based Prob. of a Thunderstorm", 100.0, 0.0, 0, NO)
MaxTwAloft=("MaxTwAloft", SCALAR, 'C', 'Max Wet-Bulb Temp in Warm Nose', 40.0, -20.0, 1, NO) DryTstmPrb = ("DryTstmPrb", SCALAR, "%", "3-h SREF-based Prob. of a Dry Thunderstorm", 100.0, 0.0, 0, NO)
ProbIcePresent=("ProbIcePresent", SCALAR, "%", "Prob of Ice Present", 100.0, 0.0, 0, NO) WGS50pct =("WGS50pct", SCALAR, "kts", "10-m Wind Gust",125.0 , 0.0, 0, NO)
ProbRefreezeSleet=("ProbRefreezeSleet", SCALAR, "%", "Prob of Refreeze into Sleet", 100.0, 0.0, 0, NO) WS50Prcntl30m =("WS50Prcntl30m", SCALAR, "kts", "30-m Wind Speed", 125.0, 0.0, 0, NO)
WS50Prcntl80m =("WS50Prcntl80m", SCALAR, "kts", "80-m Wind Speed", 125.0, 0.0, 0, NO)
Vis50pct =("Vis50pct", SCALAR, "SM", "Visibility",10.0 , 0.0, 3, NO)
T50pct =("T50pct", SCALAR, "F", "Air Temperature", maxTempVal, minTempVal, 1, NO)
PMSL10pct =("PMSL10pct", SCALAR, "mb", "10th percentile Mean Sea Level Pressure", 1100.0, 900.0, 1, NO)
PMSL50pct =("PMSL50pct", SCALAR, "mb", "50th percentile Mean Sea Level Pressure", 1100.0, 900.0, 1, NO)
PMSL90pct =("PMSL90pct", SCALAR, "mb", "90th percentile Mean Sea Level Pressure", 1100.0, 900.0, 1, NO)
FosBerg = ("FosBerg", SCALAR, "none", "Fosberg Fire Weather Index", 100.0, 0.0, 0, NO)
@ -2368,8 +2377,8 @@ else:
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# base urls for the ISC Routing Table # base urls for the ISC Routing Table
ISC_ROUTING_TABLE_ADDRESS = { ISC_ROUTING_TABLE_ADDRESS = {
"ANCF" : "http://localhost:8080/irt", "ANCF" : "http://svcbu-ancf.er.awips.noaa.gov:8080/irt",
"BNCF" : "http://localhost:8080/irt" "BNCF" : "http://svcbu-bncf.er.awips.noaa.gov:8080/irt"
} }
@ -2685,7 +2694,7 @@ for s in ['ALR', 'FWR', 'KRF', 'MSR', 'ORN', 'PTR', 'RHA', 'RSA', 'STR', 'TAR',
modelDict['FFG'+s] = {'D2DMODELS': 'FFG-'+s} modelDict['FFG'+s] = {'D2DMODELS': 'FFG-'+s}
modelDict['GFS20'] = { modelDict['GFS20'] = {
'D2DMODELS': 'GFS215', 'D2DMODELS': 'GFS20',
'D2DAccumulativeElements': ['tp3hr','tp6hr', 'tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'], 'D2DAccumulativeElements': ['tp3hr','tp6hr', 'tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'],
'DB': ('GFS20', 'GRID', '', NO, NO, 2, 0), 'DB': ('GFS20', 'GRID', '', NO, NO, 2, 0),
'Parms': [([Wetflag], FireWx1300TC), 'Parms': [([Wetflag], FireWx1300TC),
@ -2723,8 +2732,8 @@ modelDict['GWW'] = {
], ],
} }
modelDict['GWW233'] = { modelDict['WaveWatch'] = {
'D2DMODELS': 'GWW233',} 'D2DMODELS': 'WaveWatch',}
modelDict['GlobalWave'] = { modelDict['GlobalWave'] = {
'D2DMODELS': 'GlobalWave', 'D2DMODELS': 'GlobalWave',
@ -2838,7 +2847,7 @@ modelDict['NAHwave4'] = {
modelDict['NAM12'] = { modelDict['NAM12'] = {
'D2DAccumulativeElements': ['tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'], 'D2DAccumulativeElements': ['tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'],
'D2DMODELS': 'ETA218', 'D2DMODELS': 'NAM12',
'DB': ('NAM12', 'GRID', '', NO, NO, 2, 0), 'DB': ('NAM12', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'NAM12', 'INITMODULES': 'NAM12',
'Parms': STD3_MODEL, 'Parms': STD3_MODEL,
@ -2846,11 +2855,11 @@ modelDict['NAM12'] = {
modelDict['NAM20'] = { modelDict['NAM20'] = {
'D2DAccumulativeElements': ['tp', 'cp'], 'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'mesoEta215',} 'D2DMODELS': 'NAM20',}
modelDict['NAM40'] = { modelDict['NAM40'] = {
'D2DAccumulativeElements': ['tp', 'cp'], 'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'mesoEta212', 'D2DMODELS': 'NAM40',
'DB': ('NAM40', 'GRID', '', NO, NO, 2, 0), 'DB': ('NAM40', 'GRID', '', NO, NO, 2, 0),
'Parms': STD3_MODEL, 'Parms': STD3_MODEL,
} }
@ -2882,7 +2891,9 @@ modelDict['NamDNG'] = {
} }
modelDict['NationalBlend'] = { modelDict['NationalBlend'] = {
'D2DAccumulativeElements': ["pop12hr", "pop", "pop6hr", "tp", "ppi1hr", "ppi6hr", "tp1hr", "tp6hr", "thp3hr", "thp6hr"], 'D2DAccumulativeElements': ["pop12hr", "pop", "pop6hr", "tp", "ppi1hr", "ppi6hr",
"tp1hr", "tp6hr", "thp3hr", "thp6hr",
"totsn1hr", "totsn6hr", "ficeac1hr", "ficeac6hr"],
'D2DMODELS': 'NationalBlend', 'D2DMODELS': 'NationalBlend',
'DB': ('NationalBlend', 'GRID', '', NO, NO, 7, 0), 'DB': ('NationalBlend', 'GRID', '', NO, NO, 7, 0),
'INITMODULES': 'NationalBlend', 'INITMODULES': 'NationalBlend',
@ -2891,10 +2902,23 @@ modelDict['NationalBlend'] = {
([PoTIP, PoTR, PoTRW, PoTS, PoTSW, PoTZR,],TC1), ([PoTIP, PoTR, PoTRW, PoTS, PoTSW, PoTZR,],TC1),
([SnowLevel,MaxTwAloft,ProbIcePresent, ProbRefreezeSleet,SnowRatio],TC1), ([SnowLevel,MaxTwAloft,ProbIcePresent, ProbRefreezeSleet,SnowRatio],TC1),
([PositiveEnergyAloft, NegativeEnergyLowLevel],TC1), ([PositiveEnergyAloft, NegativeEnergyLowLevel],TC1),
([TstmPrb3],TC3NG), ([MixHgt, TransWind, LLWS, VentRate, LLWSHgt, Radar,
([TstmPrb6,QPF,PoP6,PPI06],TC6NG), SigWaveHgt, Weather, Haines, FosBerg,
SnowAmt01, IceAccum01, TstmPrb1],TC1),
([TstmPrb3, DryTstmPrb],TC3NG),
([TstmPrb6, QPF, PoP6, PPI06, SnowAmt, IceAccum,
QPF10Prcntl, QPF50Prcntl, QPF90Prcntl],TC6NG),
([MaxT], MaxTTC), ([MinT], MinTTC), ([MaxT], MaxTTC), ([MinT], MinTTC),
([MaxRH], MaxRHTC), ([MinRH], MinRHTC),([PoP],TC12NG), ([MaxRH], MaxRHTC), ([MinRH], MinRHTC),([PoP, TstmPrb12],TC12NG),
],
}
modelDict['NationalBlendOC'] = {
'D2DMODELS': 'NationalBlendOC',
'DB': ('NationalBlend', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'NationalBlendOC',
'Parms': [([WGS50pct, WS50Prcntl30m, WS50Prcntl80m, Vis50pct, T50pct,
PMSL10pct, PMSL50pct, PMSL90pct], TC1),
], ],
} }
@ -2908,10 +2932,8 @@ modelDict['PWPF'] = {
'D2DMODELS': 'PWPF',} 'D2DMODELS': 'PWPF',}
modelDict['RFCQPF'] = { modelDict['RFCQPF'] = {
'D2DAccumulativeElements': ['tpHPC'],
'D2DMODELS': 'RFCqpf', 'D2DMODELS': 'RFCqpf',
'DB': ('RFCQPF', 'GRID', '', NO, NO, 4, 0), 'DB': ('RFCQPF', 'GRID', '', NO, NO, 4, 0),
'INITMODULES': 'RFCQPF',
'Parms': [([QPF], TC6NG), 'Parms': [([QPF], TC6NG),
], ],
} }
@ -2924,11 +2946,11 @@ modelDict['RTMA'] = {
'Parms': RTMAPARMS, 'Parms': RTMAPARMS,
} }
modelDict['RUC13'] = { modelDict['RAP13'] = {
'D2DAccumulativeElements': ['tp', 'cp'], 'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'RUC130', 'D2DMODELS': 'RAP13',
'DB': ('RUC13', 'GRID', '', NO, NO, 2, 0), 'DB': ('RAP13', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'RUC13', 'INITMODULES': 'RAP13',
'INITSKIPS': [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23], 'INITSKIPS': [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23],
'Parms': STD1_MODEL, 'Parms': STD1_MODEL,
} }
@ -3178,11 +3200,11 @@ if SID in groups['ALASKA_SITES']:
updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsAK') updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsAK')
updateModelDict(modelDict,'ETSS','D2DMODELS', 'ETSS-AK') updateModelDict(modelDict,'ETSS','D2DMODELS', 'ETSS-AK')
updateModelDict(modelDict,'GFS20','D2DMODELS', 'GFS217') updateModelDict(modelDict,'GFS20','D2DMODELS', 'AK-GFS22')
updateModelDict(modelDict,'HIRESWarw','D2DMODELS', 'HiResW-ARW-AK') updateModelDict(modelDict,'HIRESWarw','D2DMODELS', 'HiResW-ARW-AK')
updateModelDict(modelDict,'HIRESWnmm','D2DMODELS', 'HiResW-NMM-AK') updateModelDict(modelDict,'HIRESWnmm','D2DMODELS', 'HiResW-NMM-AK')
updateModelDict(modelDict,'MOSGuide','D2DMODELS', 'MOSGuide-AK') updateModelDict(modelDict,'MOSGuide','D2DMODELS', 'MOSGuide-AK')
updateModelDict(modelDict,'NAM12','D2DMODELS', 'ETA242') updateModelDict(modelDict,'NAM12','D2DMODELS', 'AK-NAM11')
updateModelDict(modelDict,'NamDNG','D2DMODELS', 'AK-NamDNG3') updateModelDict(modelDict,'NamDNG','D2DMODELS', 'AK-NamDNG3')
updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendAK') updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendAK')
updateModelDict(modelDict,'RTMA','D2DMODELS', 'AK-RTMA3') updateModelDict(modelDict,'RTMA','D2DMODELS', 'AK-RTMA3')
@ -3213,7 +3235,7 @@ elif SID == "HFO":
'Parms': STD6_MODEL, 'Parms': STD6_MODEL,
} }
updateModelDict(modelDict,'GWW233','D2DMODELS', 'GWW233') updateModelDict(modelDict,'WaveWatch','D2DMODELS', 'WaveWatch')
updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave') updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave')
updateModelDict(modelDict,'RTMA','D2DMODELS', 'HI-RTMA') updateModelDict(modelDict,'RTMA','D2DMODELS', 'HI-RTMA')
updateModelDict(modelDict,'NamDNG','D2DMODELS', 'HI-NamDNG5') updateModelDict(modelDict,'NamDNG','D2DMODELS', 'HI-NamDNG5')
@ -3228,7 +3250,7 @@ elif SID == "HFO":
updateModelDict(modelDict,'MOSGuide','D2DMODELS', 'MOSGuide-HI') updateModelDict(modelDict,'MOSGuide','D2DMODELS', 'MOSGuide-HI')
updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendHI') updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendHI')
# Model databases for HFO # Model databases for HFO
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS75', 'GWW233', 'GlobalWave', includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS75', 'WaveWatch', 'GlobalWave',
'HIRESWarw', 'HIRESWnmm', 'MOSGuide', 'NamDNG', 'NationalBlend', 'HIRESWarw', 'HIRESWnmm', 'MOSGuide', 'NamDNG', 'NationalBlend',
'RTMA', 'RTOFS-Honolulu', 'SPC', 'TPCProb', 'TPCProbPrelim', 'nwpsCG1GUM', 'RTMA', 'RTOFS-Honolulu', 'SPC', 'TPCProb', 'TPCProbPrelim', 'nwpsCG1GUM',
'nwpsCG1HFO', 'nwpsTrkngCG0GUM', 'nwpsTrkngCG0HFO', 'nwpsCG1HFO', 'nwpsTrkngCG0GUM', 'nwpsTrkngCG0HFO',
@ -3259,7 +3281,7 @@ elif SID == "GUM":
elif SID == "SJU": elif SID == "SJU":
updateModelDict(modelDict,'GFS80','D2DMODELS', 'AVN211') updateModelDict(modelDict,'GFS80','D2DMODELS', 'AVN211')
updateModelDict(modelDict,'NAM80','D2DMODELS', 'ETA') updateModelDict(modelDict,'NAM80','D2DMODELS', 'ETA')
updateModelDict(modelDict,'GWW233','D2DMODELS', 'GWW233') updateModelDict(modelDict,'WaveWatch','D2DMODELS', 'WaveWatch')
updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave') updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave')
updateModelDict(modelDict,'WNAwave10','D2DMODELS', 'WNAwave10') updateModelDict(modelDict,'WNAwave10','D2DMODELS', 'WNAwave10')
updateModelDict(modelDict,'WNAwave4','D2DMODELS', 'WNAwave4') updateModelDict(modelDict,'WNAwave4','D2DMODELS', 'WNAwave4')
@ -3273,10 +3295,10 @@ elif SID == "SJU":
updateModelDict(modelDict,'RTOFS-Atlantic','D2DMODELS', 'RTOFS-Atlantic') updateModelDict(modelDict,'RTOFS-Atlantic','D2DMODELS', 'RTOFS-Atlantic')
updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsPR') updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsPR')
updateModelDict(modelDict,'NAHwave4','D2DMODELS', 'NAHwave4') updateModelDict(modelDict,'NAHwave4','D2DMODELS', 'NAHwave4')
updateModelDict(modelDict,'GFS20','D2DMODELS', 'GFS20-PRICO') updateModelDict(modelDict,'GFS20','D2DMODELS', 'PR-GFS')
updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendPR') updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendPR')
# Model databases for SJU # Model databases for SJU
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS20', 'GFS80', 'GWW233', includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS20', 'GFS80', 'WaveWatch',
'GlobalWave', 'HIRESWarw', 'HIRESWnmm', 'NAHwave4', 'NAM80', 'GlobalWave', 'HIRESWarw', 'HIRESWnmm', 'NAHwave4', 'NAM80',
'NationalBlend', 'RTMA', 'RTOFS-Atlantic', 'SPC', 'TPCProb', 'NationalBlend', 'RTMA', 'RTOFS-Atlantic', 'SPC', 'TPCProb',
'TPCProbPrelim', 'WNAwave10', 'WNAwave4', 'TPCProbPrelim', 'WNAwave10', 'WNAwave4',

View file

@ -25,6 +25,13 @@
# Configuration Guides->Smart Initialization Configuration section of the GFE # Configuration Guides->Smart Initialization Configuration section of the GFE
# Online Help for guidance on creating a new smart init # Online Help for guidance on creating a new smart init
## ##
# ----------------------------------------------------------------------------
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 02/23/2018 #20395 wkwock Added NBM3.1 elements.
from numpy import * from numpy import *
@ -276,7 +283,7 @@ class NationalBlendForecaster(Forecaster):
# values. # values.
CloudBasePrimary = where(less(CloudBasePrimary, 0), 250, CloudBasePrimary) CloudBasePrimary = where(less(CloudBasePrimary, 0), 250, CloudBasePrimary)
return self.smoothpm(CloudBasePrimary, 3) return CloudBasePrimary
def calcMaxRH(self, MAXRH12hr_FHAG2): def calcMaxRH(self, MAXRH12hr_FHAG2):
return MAXRH12hr_FHAG2 return MAXRH12hr_FHAG2
@ -287,8 +294,8 @@ class NationalBlendForecaster(Forecaster):
#=========================================================================== #===========================================================================
# Calc MaxTwAloft - Convert K to C # Calc MaxTwAloft - Convert K to C
#=========================================================================== #===========================================================================
def calcMaxTwAloft(self, MaxTW_EA): def calcMaxTwAloft(self, maxtw_FHAG61040000):
return (MaxTW_EA - 273.15) return (maxtw_FHAG61040000 - 273.15)
def calcMinRH(self, MINRH12hr_FHAG2): def calcMinRH(self, MINRH12hr_FHAG2):
return MINRH12hr_FHAG2 return MINRH12hr_FHAG2
@ -299,14 +306,14 @@ class NationalBlendForecaster(Forecaster):
#=========================================================================== #===========================================================================
# NegativeEnergyLowLevel # NegativeEnergyLowLevel
#=========================================================================== #===========================================================================
def calcNegativeEnergyLowLevel(self, nbe_EA): def calcNegativeEnergyLowLevel(self, nbe_SFC):
return nbe_EA return nbe_SFC
#=========================================================================== #===========================================================================
# Positive Energy Aloft # Positive Energy Aloft
#=========================================================================== #===========================================================================
def calcPositiveEnergyAloft(self, pbe_EA): def calcPositiveEnergyAloft(self, pbe_FHAG61040000):
return pbe_EA return pbe_FHAG61040000
def calcPoP(self, pop_SFC): def calcPoP(self, pop_SFC):
return pop_SFC return pop_SFC
@ -421,6 +428,395 @@ class NationalBlendForecaster(Forecaster):
def calcPotFreezingRain(self, ptypfreezingrain_SFC): def calcPotFreezingRain(self, ptypfreezingrain_SFC):
return(ptypfreezingrain_SFC) return(ptypfreezingrain_SFC)
def calcTransWind(self, trwspd_EA, trwdir_EA):
newmag=self.convertMsecToKts(trwspd_EA)
return (newmag, trwdir_EA)
def calcLLWS(self, wind_FHAG0610):
mag, dir = wind_FHAG0610
Mask = mag >= 150
mag = self.convertMsecToKts(mag) # convert to knots from m/s
mag[Mask] = 0
dir[Mask] = 0
return (mag, dir)
def calcSnowAmt(self, totsn6hr_SFC):
return (totsn6hr_SFC * 1000) / 25.4
def calcMixHgt(self, mixht_EA):
return mixht_EA / 0.3048
def calcVentRate(self, vrate_EA):
return vrate_EA
def calcHaines(self, hindex6hr_EA):
return hindex6hr_EA
def calcFosBerg(self, fosindx6hr_SFC):
return fosindx6hr_SFC
def calcLLWSHgt(self, llwshgt_FHAG0610):
return llwshgt_FHAG0610 * 32.808398951
def calcRadar(self, maxref1hr_FHAG1000):
return maxref1hr_FHAG1000
def calcSigWaveHgt(self, htsgw_SFC):
return htsgw_SFC / 0.3048
def calcWx(self, pwther_SFC):
#https://graphical.weather.gov/definitions/defineWx.html
wx = pwther_SFC.astype(int8)
outOfAreaMask = logical_or(greater(wx, 7),less(wx, 0))
wx[outOfAreaMask] = 0
wxtypes = ["<NoCov>:<NoWx>:<NoInten>:<NoVis>:",
"Chc:R:-:<NoVis>:",
"SChc:R:-:<NoVis>:",
"Lkly:R:-:<NoVis>:",
"Def:R:-:<NoVis>:",
"Def:R:m:<NoVis>:",
"Lkly:R:m:<NoVis>:",
"Chc:R:m:<NoVis>:",
"SChc:R:m:<NoVis>:",
"Def:R:+:<NoVis>:",
"Lkly:R:+:<NoVis>:",
"Chc:R:+:<NoVis>:",
"Iso:T:<NoInten>:<NoVis>:^SChc:RW:-:<NoVis>:",
"Chc:RW:-:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Chc:RW:-:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"SChc:S:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Chc:S:-:<NoVis>:^Chc:R:-:<NoVis>:",
"SChc:S:-:<NoVis>:",
"SChc:R:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Chc:S:-:<NoVis>:",
"Chc:R:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Lkly:S:-:<NoVis>:^Lkly:R:-:<NoVis>:",
"Lkly:S:-:<NoVis>:",
"Lkly:S:m:<NoVis>:",
"Lkly:S:m:<NoVis>:^Lkly:R:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^Def:R:-:<NoVis>:",
"Def:S:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Def:S:m:<NoVis>:",
"Def:R:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Def:S:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Chc:S:m:<NoVis>:",
"SChc:S:m:<NoVis>:",
"Def:S:+:<NoVis>:",
"Lkly:S:+:<NoVis>:",
"Chc:R:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:S:+:<NoVis>:^Def:R:+:<NoVis>:",
"Def:S:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Lkly:S:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Def:S:m:<NoVis>:^Def:R:m:<NoVis>:",
"Def:S:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:S:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:S:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Def:S:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:S:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Chc:S:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Lkly:RW:-:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Chc:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:S:+:<NoVis>:^Lkly:R:+:<NoVis>:",
"Lkly:RW:-:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"Lkly:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:S:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Chc:S:+:<NoVis>:",
"Chc:S:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Lkly:S:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Chc:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"SChc:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:",
"SChc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"SChc:ZR:-:<NoVis>:",
"Def:RW:-:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"SChc:S:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Chc:RW:m:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Lkly:RW:m:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Chc:RW:m:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"Lkly:RW:m:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"Def:RW:-:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"Def:RW:m:<NoVis>:^Sct:T:<NoInten>:<NoVis>:",
"Def:RW:m:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Def:S:-:<NoVis>:^Lkly:R:-:<NoVis>:",
"Chc:S:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:S:+:<NoVis>:^Chc:ZR:+:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Lkly:S:-:<NoVis>:^Lkly:ZR:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^Lkly:ZR:-:<NoVis>:",
"Def:R:-:<NoVis>:^Def:S:-:<NoVis>:",
"Lkly:S:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:S:m:<NoVis>:",
"SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Chc:IP:-:<NoVis>:^Chc:S:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Def:S:+:<NoVis>:^Chc:R:+:<NoVis>:",
"Def:R:m:<NoVis>:^Lkly:S:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Lkly:S:m:<NoVis>:",
"Def:RW:+:<NoVis>:^Iso:T:<NoInten>:<NoVis>:",
"Chc:R:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Chc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Chc:R:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Chc:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Chc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Def:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Def:R:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Lkly:R:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^Chc:ZR:+:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:R:+:<NoVis>:^Chc:IP:+:<NoVis>:",
"Lkly:R:+:<NoVis>:^Chc:IP:+:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^Chc:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:+:<NoVis>:^Chc:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:R:+:<NoVis>:^SChc:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^SChc:ZR:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Def:R:+:<NoVis>:^SChc:ZR:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Def:R:+:<NoVis>:^Chc:ZR:+:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Lkly:IP:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^SChc:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Lkly:R:+:<NoVis>:^Chc:ZR:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Def:R:+:<NoVis>:^Chc:ZR:+:<NoVis>:^SChc:IP:+:<NoVis>:",
"Def:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^Chc:IP:+:<NoVis>:^Chc:ZR:+:<NoVis>:",
"Def:R:+:<NoVis>:^Chc:IP:+:<NoVis>:^Chc:ZR:+:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Def:R:+:<NoVis>:^Lkly:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^Lkly:IP:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"Def:R:+:<NoVis>:^Lkly:IP:+:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Lkly:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:R:+:<NoVis>:^Lkly:IP:+:<NoVis>:",
"Def:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Lkly:R:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:R:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Lkly:ZR:-:<NoVis>:",
"Chc:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:ZR:+:<NoVis>:^Chc:R:+:<NoVis>:",
"Chc:S:+:<NoVis>:^Chc:R:+:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Chc:IP:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Chc:S:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Chc:ZR:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Chc:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Chc:R:m:<NoVis>:^SChc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:",
"Chc:R:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Chc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^SChc:ZR:m:<NoVis>:",
"Def:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:S:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Chc:ZR:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^SChc:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Lkly:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:^Chc:ZR:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:R:m:<NoVis>:^SChc:IP:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Lkly:S:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^SChc:S:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Lkly:S:m:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Chc:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Lkly:IP:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:^Chc:IP:m:<NoVis>:",
"Def:IP:-:<NoVis>:^Lkly:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:ZR:m:<NoVis>:^Def:IP:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Def:ZR:m:<NoVis>:^Lkly:IP:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Lkly:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^SChc:R:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:R:m:<NoVis>:^Chc:ZR:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Lkly:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Chc:R:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:S:-:<NoVis>:^Lkly:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Lkly:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:ZR:-:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:R:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:ZR:m:<NoVis>:^Chc:R:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Chc:ZR:m:<NoVis>:^Chc:IP:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:R:m:<NoVis>:^SChc:S:m:<NoVis>:",
"Chc:ZR:m:<NoVis>:^Chc:S:m:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Chc:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Lkly:IP:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Def:R:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Def:IP:-:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:^Lkly:S:m:<NoVis>:",
"Def:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Lkly:R:m:<NoVis>:^Lkly:IP:m:<NoVis>:^Lkly:S:m:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:S:-:<NoVis>:^Def:R:-:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:^Lkly:R:-:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Def:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Def:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^SChc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Def:ZR:m:<NoVis>:^Def:IP:m:<NoVis>:^Def:S:m:<NoVis>:",
"Def:S:m:<NoVis>:^SChc:IP:m:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Def:S:-:<NoVis>:^Def:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Def:S:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:S:-:<NoVis>:",
"Def:S:-:<NoVis>:^Lkly:IP:-:<NoVis>:",
"Lkly:ZR:m:<NoVis>:",
"Def:IP:-:<NoVis>:^Def:S:-:<NoVis>:^Lkly:ZR:-:<NoVis>:",
"Def:S:-:<NoVis>:^Lkly:ZR:-:<NoVis>:^Lkly:IP:-:<NoVis>:",
"Chc:R:-:<NoVis>:^SChc:ZR:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Def:ZR:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Lkly:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:R:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^SChc:R:-:<NoVis>:",
"Chc:R:-:<NoVis>:^Chc:IP:-:<NoVis>:^Chc:S:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Chc:R:-:<NoVis>:^Chc:ZR:-:<NoVis>:",
"Lkly:R:-:<NoVis>:^Lkly:IP:-:<NoVis>:^Lkly:S:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Chc:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Chc:S:-:<NoVis>:^Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^Chc:S:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:^SChc:S:-:<NoVis>:^SChc:IP:-:<NoVis>:",
"Def:S:+:<NoVis>:^SChc:ZR:+:<NoVis>:",
"SChc:R:-:<NoVis>:^SChc:IP:-:<NoVis>:^SChc:S:-:<NoVis>:",
]
return (wx, wxtypes)
def calcSnowAmt01(self, totsn1hr_SFC):
return (totsn1hr_SFC * 1000) / 25.4
def calcIceAccum01(self, ficeac1hr_SFC):
return (ficeac1hr_SFC * 1000) / 25.4
def calcIceAccum(self, ficeac6hr_SFC):
return (ficeac6hr_SFC * 1000) / 25.4
def calcQPF10Prcntl(self, tp10pct6hr_SFC):
return tp10pct6hr_SFC / 25.4
def calcQPF50Prcntl(self, tp50pct6hr_SFC):
return tp50pct6hr_SFC / 25.4
def calcQPF90Prcntl(self, tp90pct6hr_SFC):
return tp90pct6hr_SFC / 25.4
def calcTstmPrb1(self, thp1hr_SFC):
return thp1hr_SFC
def calcDryTstmPrb(self, drytpprob3hr_SFC):
return drytpprob3hr_SFC
def calcTstmPrb12(self, thp12hr_SFC):
return thp12hr_SFC
def main(): def main():
NationalBlendForecaster().run() NationalBlendForecaster().run()

View file

@ -0,0 +1,71 @@
##
#This software was developed and / or modified by NOAA/NWS/OCP/ASDT##
##
# This is a base file that is not intended to be overridden.
#
# This file can be subclassed to override behavior. Please see the
# Configuration Guides->Smart Initialization Configuration section of the GFE
# Online Help for guidance on creating a new smart init
##
# ----------------------------------------------------------------------------
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 02/23/2018 #20395 wkwock Added NBM3.1 elements.
from Init import *
##--------------------------------------------------------------------------
## Module that calculates surface weather elements from SPC model
## output.
##
##--------------------------------------------------------------------------
class NationalBlendOCForecaster(Forecaster):
def __init__(self):
Forecaster.__init__(self, "NationalBlendOC", "NationalBlend")
def calcWGS50pct(self, wgs50pct_FHAG10):
return wgs50pct_FHAG10
def calcWS50Prcntl30m(self, ws50pct_FHAG30):
return ws50pct_FHAG30
def calcWS50Prcntl80m(self, ws50pct_FHAG80):
return ws50pct_FHAG80
def calcVis50pct(self, vis50pct_SFC):
return self.convertMtoSM(vis50pct_SFC)
def calcT50pct(self, t50pct_FHAG2):
return self.convertKtoF(t50pct_FHAG2)
def calcPMSL10pct(self, pmsl10pct_MSL):
return pmsl10pct_MSL / 100.0
def calcPMSL50pct(self, pmsl50pct_MSL):
return pmsl50pct_MSL / 100.0
def calcPMSL90pct(self, pmsl90pct_MSL):
return pmsl90pct_MSL / 100.0
def windChillCalc(self, T, Wind):
mag = Wind[0] * 1.15077945
WindChill = where(less_equal(mag, 1), T, 35.74 + (0.6215 * T) - (35.75 * (mag ** 0.16)) + (0.4275 * T * (mag ** 0.16)))
# clip values where WindChill > T
WindChill = where(greater(WindChill, T), T, WindChill)
# substitute the temperature if WindChill >= 51 degrees
WindChill = where(greater_equal(T, 51), T, WindChill)
return WindChill
def main():
NationalBlendOCForecaster().run()
if __name__ == "__main__":
main()

View file

@ -17,6 +17,15 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for # See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information. # further licensing information.
## ##
##
# This is a base file that is not intended to be overridden.
#
# This file can be subclassed to override behavior. Please see the
# Configuration Guides->Smart Initialization Configuration section of the GFE
# Online Help for guidance on creating a new smart init
##
from Init import * from Init import *
##-------------------------------------------------------------------------- ##--------------------------------------------------------------------------

View file

@ -28,13 +28,13 @@
from Init import * from Init import *
##-------------------------------------------------------------------------- ##--------------------------------------------------------------------------
## Module that calculates surface weather elements from RUC80 model ## Module that calculates surface weather elements from RAP40 model
## output. ## output.
## ##
##-------------------------------------------------------------------------- ##--------------------------------------------------------------------------
class RUC80Forecaster(Forecaster): class RAP40Forecaster(Forecaster):
def __init__(self): def __init__(self):
Forecaster.__init__(self, "RUC80") Forecaster.__init__(self, "RAP40")
##-------------------------------------------------------------------------- ##--------------------------------------------------------------------------
## These levels will be used to create vertical soundings. These are ## These levels will be used to create vertical soundings. These are
@ -531,4 +531,4 @@ class RUC80Forecaster(Forecaster):
return lal return lal
def main(): def main():
RUC80Forecaster().run() RAP40Forecaster().run()

View file

@ -1,559 +0,0 @@
##
# This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
#
# U.S. EXPORT CONTROLLED TECHNICAL DATA
# This software product contains export-restricted data whose
# export/transfer/disclosure is restricted by U.S. law. Dissemination
# to non-U.S. persons whether in the United States or abroad requires
# an export license or other authorization.
#
# Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8
# Omaha, NE 68106
# 402.291.0100
#
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
##
# This is a base file that is not intended to be overridden.
#
# This file can be subclassed to override behavior. Please see the
# Configuration Guides->Smart Initialization Configuration section of the GFE
# Online Help for guidance on creating a new smart init
##
from Init import *
##--------------------------------------------------------------------------
## Module that calculates surface weather elements from RUC13 model
## output.
##
##--------------------------------------------------------------------------
class RUC13Forecaster(Forecaster):
def __init__(self):
Forecaster.__init__(self, "RUC13")
##--------------------------------------------------------------------------
## These levels will be used to create vertical soundings. These are
## defined here since they are model dependent.
##--------------------------------------------------------------------------
def levels(self):
return ["MB1000", "MB950", "MB900", "MB850", "MB800", "MB750", "MB700",
"MB650", "MB600", "MB550", "MB500", "MB450", "MB400",
"MB350", "MB300"]
##-------------------------------------------------------------------------
## Returns the maximum of the specified MaxT and the T grids
##--------------------------------------------------------------------------
def calcMaxT(self, T, MaxT):
if MaxT is None:
return T
return maximum(MaxT, T)
##-------------------------------------------------------------------------
## Returns the minimum of the specified MinT and T grids
##--------------------------------------------------------------------------
def calcMinT(self, T, MinT):
if MinT is None:
return T
return minimum(MinT, T)
##-------------------------------------------------------------------------
## Calculates the temperature at the elevation indicated in the topo
## grid. This tool simply interpolates the temperature value from
## model's isobaric temperature cube.
##-------------------------------------------------------------------------
def calcT(self, t_FHAG2, t_BL030, t_BL6090, t_BL150180,
p_SFC, topo, stopo, gh_c, t_c):
p = self.newGrid(-1)
tmb = self.newGrid(-1)
tms = self.newGrid(-1)
# go up the column to figure out the surface pressure
for i in xrange(1, gh_c.shape[0]):
higher = greater(gh_c[i], topo)
# interpolate the pressure at topo height
val = self.linear(gh_c[i], gh_c[i - 1],
log(self.pres[i]), log(self.pres[i - 1]), topo)
val.clip(-.00001, 10, val)
m = logical_and(equal(p, -1), higher)
p[m] = exp(val)[m]
# interpolate the temperature at true elevation
tval1 = self.linear(gh_c[i], gh_c[i - 1], t_c[i], t_c[i - 1], topo)
m = logical_and(equal(tmb, -1), higher)
tmb[m] = tval1[m]
# interpolate the temperature at model elevation
tval2 = self.linear(gh_c[i], gh_c[i - 1], t_c[i], t_c[i - 1], stopo)
m = logical_and(equal(tms, -1), greater(gh_c[i], stopo))
tms[m] = tval2[m]
p_SFC /= 100
# define the pres. of each of the boundary layers
pres = [p_SFC, p_SFC - 15, p_SFC - 75, p_SFC - 168]
# list of temperature grids
temps = [t_FHAG2, t_BL030, t_BL6090, t_BL150180]
st = self.newGrid(-1)
# Calculate the lapse rate in units of pressure
for i in xrange(1, len(pres)):
val = self.linear(pres[i], pres[i - 1], temps[i], temps[i - 1], p)
gm = greater(pres[i - 1], p)
lm = less_equal(pres[i], p)
mask = logical_and(gm, lm)
m = logical_and(equal(st, -1), mask)
st[m] = val[m]
# where topo level is above highest level in BL fields...use tmb
m = logical_and(equal(st,-1),less(p,p_SFC-135))
st[m] = tmb[m]
# where topo level is below model surface...use difference
# of t at pressure of surface and tFHAG2 and subtract from tmb
m = equal(st, -1)
st[m] = (tmb - tms + t_FHAG2)[m]
return self.KtoF(st)
##-------------------------------------------------------------------------
## Calculates dew point from the specified pressure, temp and rh
## fields.
##-------------------------------------------------------------------------
def calcTd(self, p_SFC, T, t_FHAG2, stopo, topo, rh_FHAG2):
# at the model surface
sfce = rh_FHAG2 / 100 * self.esat(t_FHAG2)
w = (0.622 * sfce) / ((p_SFC + 0.0001) / 100 - sfce)
# at the true surface
tsfce = self.esat(self.FtoK(T))
dpdz = 287.04 * t_FHAG2 / (p_SFC / 100 * 9.8) # meters / millibar
newp = p_SFC / 100 + (stopo - topo) / dpdz
ws = (0.622 * tsfce) / (newp - tsfce)
rh = w / ws
# Finally, calculate the dew point
tsfcesat = rh * tsfce
tsfcesat.clip(0.00001, tsfcesat, tsfcesat)
b = 26.66082 - log(tsfcesat)
td = (b - sqrt(b * b - 223.1986)) / 0.0182758048
td = self.KtoF(td)
m = w > ws
td[m] = T[m]
return td
##-------------------------------------------------------------------------
## Calculates RH from the T and Td grids
##-------------------------------------------------------------------------
def calcRH(self, T, Td):
Tc = .556 * (T - 32.0)
Tdc = .556 * (Td - 32.0)
Vt = 6.11 * pow(10, (Tc * 7.5 / (Tc + 237.3)))
Vd = 6.11 * pow(10, (Tdc * 7.5 / (Tdc + 237.3)))
RH = (Vd / Vt) * 100.0
# Return the new value
return RH
##-------------------------------------------------------------------------
## Returns the maximum of the specified MaxRH and the RH grids
##--------------------------------------------------------------------------
def calcMaxRH(self, RH, MaxRH):
if MaxRH is None:
return RH
return maximum(MaxRH, RH)
##-------------------------------------------------------------------------
## Returns the minimum of the specified MinRH and RH grids
##--------------------------------------------------------------------------
def calcMinRH(self, RH, MinRH):
if MinRH is None:
return RH
return minimum(MinRH, RH)
##-------------------------------------------------------------------------
## Calculates QPF from the total precip field out of the model
##-------------------------------------------------------------------------
def calcQPF(self, cp_SFC, lgsp_SFC):
tp_SFC = cp_SFC + lgsp_SFC
qpf = tp_SFC / 25.4 # convert from millimeters to inches
return qpf
def calcSky(self, rh_c, gh_c, topo, p_SFC):
return self.skyFromRH(rh_c, gh_c, topo, p_SFC)
##-------------------------------------------------------------------------
## Calculates Prob. of Precip. based on QPF and RH cube. Where there
## is QPF > 0 ramp the PoP from (0.01, 35%) to 100%. Then in areas
## of QPF < 0.2 raise the PoP if it's very humid.
##-------------------------------------------------------------------------
def calcPoP(self, gh_c, rh_c, QPF, topo):
rhavg = where(less(gh_c, topo), float32(-1), rh_c)
rhavg[greater(gh_c, topo + 5000 * 0.3048)] = -1
count = not_equal(rhavg, -1)
rhavg[equal(rhavg, -1)] = 0
count = add.reduce(count, 0, dtype=float32)
rhavg = add.reduce(rhavg, 0)
## add this much based on humidity only
dpop = where(count, rhavg / (count + .001), 0) - 70.0
dpop[less(dpop, -30)] = -30
## calculate the base PoP
pop = where(less(QPF, 0.02), QPF * 1000, QPF * 350 + 13)
pop += dpop # add the adjustment based on humidity
pop.clip(0, 100, pop) # clip to 100%
return pop
##-------------------------------------------------------------------------
## Calculates the Freezing level based on height and temperature
## cubes. Finds the height at which freezing occurs.
##-------------------------------------------------------------------------
def calcFzLevel(self, gh_FRZ):
return gh_FRZ / 0.3048
##-------------------------------------------------------------------------
## Calculates the Snow level based on wet-bulb zero height.
##-------------------------------------------------------------------------
def calcSnowLevel(self, gh_c, t_c, rh_c):
# Only use the levels that are >= freezind (plus one level)
# This is a performance and memory optimization
clipindex = 2
for i in xrange(t_c.shape[0] - 1, -1, -1):
if maximum.reduce(maximum.reduce(t_c[i])) >= 273.15:
clipindex = i + 1
break
gh_c = gh_c[:clipindex, :, :]
t_c = t_c[:clipindex, :, :]
rh_c = rh_c[:clipindex, :, :]
snow = self.newGrid(-1)
#
# make pressure cube
#
pmb = ones_like(gh_c)
for i in xrange(gh_c.shape[0]):
pmb[i] = self.pres[i]
pmb.clip(1, 1050, pmb)
#
# convert temps to C and limit to reasonable values
#
tc = t_c - 273.15
tc.clip(-120, 60, tc)
#
# limit RH to reasonable values
#
rh = clip(rh_c, 0.5, 99.5)
#
# calculate the wetbulb temperatures
# (this is expensive - even in numeric python - and somewhat
# wasteful, since you do not need to calculate the wetbulb
# temp for all levels when it may cross zero way down toward
# the bottom. Nevertheless - all the gridpoints will cross
# zero at different levels - so you cannot know ahead of time
# how high up to calculate them. In the end - this was the
# most expedient way to code it - and it works - so I stuck
# with it.
#
wetb = self.Wetbulb(tc, rh, pmb)
tc = rh = pmb = None
#
# find the zero level
#
for i in xrange(1, gh_c.shape[0]):
try:
val = gh_c[i - 1] + (gh_c[i] - gh_c[i - 1]) / (wetb[i] - wetb[i - 1])\
* (-wetb[i - 1])
except:
val = gh_c[i]
m = logical_and(equal(snow, -1), less_equal(wetb[i], 0))
snow[m] = val[m]
#
# convert to feet
#
snow /= 0.3048
return snow
##-------------------------------------------------------------------------
## Calculates Snow amount based on the Temp, Freezing level, QPF,
## topo and Weather grid
##-------------------------------------------------------------------------
def calcSnowAmt(self, T, FzLevel, QPF, topo, Wx):
# figure out the snow to liquid ratio
snowr = T * -0.5 + 22.5
snowr[less(T, 9)] = 20
snowr[greater_equal(T, 30)] = 0
# calc. snow amount based on the QPF and the ratio
snowamt = where(less_equal(FzLevel - 1000, topo / 0.3048),
snowr * QPF, float32(0))
# Only make snow at points where the weather is snow
snowmask = logical_or(equal(Wx[0], 1), equal(Wx[0], 3))
snowmask = logical_or(snowmask, logical_or(equal(Wx[0], 7),
equal(Wx[0], 9)))
snowamt[logical_not(snowmask)] = 0
return snowamt
##--------------------------------------------------------------------------
## Calculate the Haines index based on the temp and RH cubes
## Define self.whichHainesIndex to be "HIGH", "MEDIUM", or "LOW".
## Default is "HIGH".
##--------------------------------------------------------------------------
def calcHaines(self, t_c, rh_c):
return self.hainesIndex(self.whichHainesIndex, t_c, rh_c)
##-------------------------------------------------------------------------
## Calculates the mixing height for the given sfc temperature,
## temperature cube, height cube and topo
##-------------------------------------------------------------------------
def calcMixHgt(self, T, topo, t_c, gh_c):
mask = greater_equal(gh_c, topo)
pt = []
for i in xrange(len(self.pres)): # for each pres. level
p = self.newGrid(self.pres[i]) # get the pres. value in mb
tmp = self.ptemp(t_c[i], p) # calculate the pot. temp
pt = pt + [tmp] # add to the list
pt = array(pt)
pt[logical_not(mask)] = 0
avg = add.accumulate(pt, 0)
count = add.accumulate(mask, 0)
mh = self.newGrid(-1)
# for each pres. level, calculate a running avg. of pot temp.
# As soon as the next point deviates from the running avg by
# more than 3 deg. C, interpolate to get the mixing height.
for i in xrange(1, avg.shape[0]):
runavg = avg[i] / (count[i] + .0001)
diffpt = pt[i] - runavg
# calc. the interpolated mixing height
tmh = self.linear(pt[i], pt[i - 1], gh_c[i], gh_c[i - 1], runavg)
# assign new values if the difference is greater than 3
m = logical_and(logical_and(mask[i], equal(mh, -1)), greater(diffpt, 3))
mh[m] = tmh[m]
mh -= topo
mh /= 0.3048 # convert to feet
return mh
##-------------------------------------------------------------------------
## Converts the lowest available wind level from m/s to knots
##-------------------------------------------------------------------------
def calcWind(self, wind_FHAG10):
mag = wind_FHAG10[0] # get the wind grids
dir = wind_FHAG10[1]
mag += 1.94 # convert m/s to knots
dir.clip(0, 359.5, dir)
return (mag, dir)
##-------------------------------------------------------------------------
## Calculates the wind at 3000 feet AGL.
##-------------------------------------------------------------------------
def calcFreeWind(self, gh_c, wind_c, topo):
wm = wind_c[0]
wd = wind_c[1]
# Make a grid that's topo + 3000 feet (914 meters)
fatopo = topo + 914.4
# find the points that are above the 3000 foot level
mask = greater_equal(gh_c, fatopo)
# initialize the grids into which the value are stored
famag = self.newGrid(-1)
fadir = self.newGrid(-1)
# start at the bottom and store the first point we find that's
# above the topo + 3000 feet level.
for i in xrange(wind_c[0].shape[0]):
m = logical_and(equal(famag, -1), mask[i])
famag[m] = wm[i][m]
m = logical_and(equal(fadir, -1), mask[i])
fadir[m] = wd[i][m]
fadir.clip(0, 359.5, fadir) # clip the value to 0, 360
famag *= 1.94 # convert to knots
return (famag, fadir) # return the tuple of grids
##-------------------------------------------------------------------------
## Calculates the average wind vector in the mixed layer as defined
## by the mixing height. This function creates a mask that identifies
## all grid points between the ground and the mixing height and calculates
## a vector average of the wind field in that layer.
##-------------------------------------------------------------------------
def calcTransWind(self, MixHgt, wind_c, gh_c, topo):
nmh = MixHgt * 0.3048 # convert MixHt from feet -> meters
u, v = self._getUV(wind_c[0], wind_c[1]) # get the wind grids
# set a mask at points between the topo and topo + MixHt
mask = logical_and(greater_equal(gh_c, topo),
less_equal(gh_c, nmh + topo))
# set the points outside the layer to zero
u[logical_not(mask)] = 0
v[logical_not(mask)] = 0
mask = add.reduce(mask).astype(float32)
mmask = mask + 0.0001
# calculate the average value in the mixed layerlayer
u = where(mask, add.reduce(u) / mmask, float32(0))
v = where(mask, add.reduce(v) / mmask, float32(0))
# convert u, v to mag, dir
tmag, tdir = self._getMD(u, v)
tdir.clip(0, 359.5, tdir)
tmag *= 1.94 # convert to knots
tmag.clip(0, 125, tmag) # clip speed to 125 knots
return (tmag, tdir)
##-------------------------------------------------------------------------
## Uses a derivation of the Bourgouin allgorithm to calculate precipitation
## type, and other algorithms to determine the coverage and intensity.
## The Bourgoin technique figures out precip type from calculating how
## long a hydrometer is exposed to alternating layers of above zero (C) and
## below zero temperature layers. This tool calculates at each grid point
## which of the four Bourgouin cases apply. Then the appropriate algorithm
## is applied to that case that further refines the precip. type. Once the
## type is determined, other algorithms are used to determine the coverage
## and intensity. See the Weather and Forecasting Journal article Oct. 2000,
## "A Method to Determine Precipitation Types", by Pierre Bourgouin
##-------------------------------------------------------------------------
def calcWx(self, QPF, T, p_SFC, t_c, gh_c, topo, lgsp_SFC, cp_SFC):
tp_SFC = cp_SFC + lgsp_SFC
gh_c = gh_c[:13, :, :]
t_c = t_c[:13, :, :]
T = self.FtoK(T)
p_SFC = p_SFC / 100 # sfc pres. in mb
pres = self.pres
a1 = self.empty()
a2 = self.empty()
a3 = self.empty()
aindex = self.empty()
# Go through the levels to identify each case type 0-3
for i in xrange(1, gh_c.shape[0] - 1):
# get the sfc pres. and temp.
pbot = where(greater(gh_c[i - 1], topo), pres[i - 1], p_SFC)
tbot = where(greater(gh_c[i - 1], topo), t_c[i - 1], T)
# Calculate the area of this layer in Temp/pres coordinates
a11, a22, cross = self.getAreas(pbot, tbot, pres[i], t_c[i])
topomask = greater(gh_c[i], topo)
m = logical_and(equal(aindex, 0), topomask)
a1[m] += a11[m]
m = logical_and(equal(aindex, 1), topomask)
a2[m] += a11[m]
m = logical_and(equal(aindex, 2), topomask)
a3[m] += a11[m]
topomask = logical_and(topomask, cross)
aindex = where(topomask, aindex + 1, aindex)
m = logical_and(equal(aindex, 0), topomask)
a1[m] += a22[m]
m = logical_and(equal(aindex, 1), topomask)
a2[m] += a22[m]
m = logical_and(equal(aindex, 2), topomask)
a3[m] += a22[m]
# Now apply a different algorithm for each type
key = ['<NoCov>:<NoWx>:<NoInten>:<NoVis>:',
"Wide:S:-:<NoVis>:", "Wide:R:-:<NoVis>:",
"Wide:S:-:<NoVis>:^Wide:R:-:<NoVis>:",
'Wide:ZR:-:<NoVis>:', 'Wide:IP:-:<NoVis>:',
'Wide:ZR:-:<NoVis>:^Wide:IP:-:<NoVis>:',
"Sct:SW:-:<NoVis>:", "Sct:RW:-:<NoVis>:",
"Sct:SW:-:<NoVis>:^Sct:RW:-:<NoVis>:",
"Chc:ZR:-:<NoVis>:", 'Chc:IP:-:<NoVis>:',
'Chc:ZR:-:<NoVis>:^Chc:IP:-:<NoVis>:']
wx = self.empty(int8)
# Case d (snow)
snowmask = equal(aindex, 0)
wx[logical_and(snowmask, greater(a1, 0))] = 2
wx[logical_and(snowmask, less_equal(a1, 0))] = 1
# Case c (rain / snow / rainSnowMix)
srmask = equal(aindex, 1)
wx[logical_and(srmask, less(a1, 5.6))] = 1
wx[logical_and(srmask, greater(a1, 13.2))] = 2
wx[logical_and(srmask,
logical_and(greater_equal(a1, 5.6),
less(a1, 13.2)))] = 3
# Case a (Freezing Rain / Ice Pellets)
ipmask = equal(aindex, 2)
ipm = greater(a1, a2 * 0.66 + 66)
wx[logical_and(ipmask, ipm)] = 5
zrm = less(a1, a2 * 0.66 + 46)
wx[logical_and(ipmask, zrm)] = 4
zrm = logical_not(zrm)
ipm = logical_not(ipm)
wx[logical_and(ipmask, logical_and(zrm, ipm))] = 6
# Case b (Ice pellets / rain)
cmask = greater_equal(aindex, 3)
ipmask = logical_and(less(a3, 2), cmask)
wx[logical_and(ipmask, less(a1, 5.6))] = 1
wx[logical_and(ipmask, greater(a1, 13.2))] = 2
wx[logical_and(ipmask, logical_and(greater_equal(a1, 5.6),
less_equal(a1, 13.2)))] = 3
ipmask = logical_and(greater_equal(a3, 2), cmask)
wx[logical_and(ipmask, greater(a1, 66 + 0.66 * a2))] = 5
wx[logical_and(ipmask, less(a1, 46 + 0.66 * a2))] = 4
wx[logical_and(ipmask, logical_and(greater_equal(a1, 46 + 0.66 * a2),
less_equal(a1, 66 + 0.66 * a2)))] = 6
# Make showers (scattered/Chc)
convecMask = greater(cp_SFC / (tp_SFC + .001), 0.5)
wx[logical_and(not_equal(wx, 0), convecMask)] += 6
# This section commented out since bli is no longer available for RUC.
# Thunder
#for i in xrange(len(key)):
#tcov = string.split(key[i], ":")[0]
#if tcov == "Chc" or tcov == "<NoCov>":
#tcov = "Sct"
#key.append(key[i] + "^" + tcov
#+ ":T:<NoInten>:<NoVis>:")
#wx = where(less_equal(bli_SFC, -3), wx + 13, wx)
# No wx where no qpf
wx[less(QPF, 0.01)] = 0
return(wx, key)
##-------------------------------------------------------------------------
## Calculates chance of wetting rain based on QPF.
##-------------------------------------------------------------------------
def calcCWR(self, QPF):
m1 = less(QPF, 0.01) # all the places that are dry
m2 = greater_equal(QPF, 0.3) # all the places that are wet
# all the places that are 0.01 to 0.10
m3 = logical_and(greater_equal(QPF, 0.01), less_equal(QPF, 0.1))
# all the places that are 0.1 to 0.3
m4 = logical_and(greater(QPF, 0.1), less(QPF, 0.3))
# assign 0 to the dry grid point, 100 to the wet grid points,
# and a ramping function to all point in between
cwr = where(m1, float32(0), where(m2, float32(100),
where(m3, 444.4 * (QPF - 0.01) + 10,
where(m4, 250 * (QPF - 0.1) + 50,
QPF))))
return cwr
##-------------------------------------------------------------------------
## Calculates Lightning Activity Level based on total precip., lifted index
## and 3-D relative humidity.
##-------------------------------------------------------------------------
def calcLAL(self, bli_SFC, lgsp_SFC, cp_SFC, rh_c, rh_FHAG2):
tp_SFC = cp_SFC + lgsp_SFC
lal = self.newGrid(1)
# Add one to lal if we have 0.5 mm of precip.
lal[logical_and(greater(cp_SFC, 0), greater(tp_SFC / cp_SFC, 0.5))] += 1
# make an average rh field
midrh = add.reduce(rh_c[6:9], 0) / 3
# Add one to lal if mid-level rh high and low level rh low
lal[logical_and(greater(midrh, 70), less(rh_FHAG2, 30))] += 1
# Add on to lal if lifted index is <-3 and another if <-5
lal[less(bli_SFC, -3)] += 1
lal[less(bli_SFC, -5)] += 1
return lal
def main():
RUC13Forecaster().run()

View file

@ -1,4 +1,4 @@
# Version 2018.02.26-2 # Version 2018.06.05
import GenericHazards import GenericHazards
import string, time, os, re, types, copy, LogStream, collections import string, time, os, re, types, copy, LogStream, collections
@ -1253,7 +1253,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
self.debug_print("Looking at zone %s" % (zone), 1) self.debug_print("Looking at zone %s" % (zone), 1)
for key in advisory["ZoneData"][zone]: for key in advisory["ZoneData"][zone]:
if "Threat" not in key or "highestHunkerDown" in key: if "Threat" not in key or "highestHunkerDown" in key:
break continue
if key not in seenValidThreatLevel: if key not in seenValidThreatLevel:
seenValidThreatLevel[key] = False seenValidThreatLevel[key] = False

View file

@ -22,7 +22,7 @@
# This is a base file that is not intended to be overridden. # This is a base file that is not intended to be overridden.
## ##
# Version 2017.12.13-0 # Version 2018.6.5-0
import GenericHazards import GenericHazards
import JsonSupport import JsonSupport
@ -1457,7 +1457,7 @@ class SectionCommon():
self._sectionHeaderName = sectionHeaderName self._sectionHeaderName = sectionHeaderName
self._segment = segment self._segment = segment
self._tr = None self._tr = None
self.isThreatNoneForEntireStorm = True self.isThreatNoneForEntireStorm = False
def _isThreatNoneForEntireStorm(self, threatName): def _isThreatNoneForEntireStorm(self, threatName):
previousAdvisories = self._textProduct._getPreviousAdvisories() previousAdvisories = self._textProduct._getPreviousAdvisories()
@ -1471,7 +1471,7 @@ class SectionCommon():
if advisory["ZoneData"][self._segment][threatName] != "None": if advisory["ZoneData"][self._segment][threatName] != "None":
return False return False
return True return False
def _setProductPartValue(self, dictionary, productPartName, value): def _setProductPartValue(self, dictionary, productPartName, value):
dictionary[self._sectionName + '._' + productPartName] = value dictionary[self._sectionName + '._' + productPartName] = value

View file

@ -27,10 +27,10 @@
--> -->
<aliasList caseSensitive="true" namespace="gfeParamInfo"> <aliasList caseSensitive="true" namespace="gfeParamInfo">
<alias base="MOSGuide-HI">mosGuideNDFD</alias> <alias base="MOSGuide-HI">mosGuideNDFD</alias>
<alias base="GFS217">gfs20km</alias> <alias base="AK-GFS22">gfs20km</alias>
<alias base="GFS215">gfs20km</alias> <alias base="GFS20">gfs20km</alias>
<alias base="GFS20-PAC">gfs20km</alias> <alias base="GFS20-PAC">gfs20km</alias>
<alias base="GFS20-PRICO">gfs20km</alias> <alias base="PR-GFS">gfs20km</alias>
<alias base="estofsAK">ESTOFS</alias> <alias base="estofsAK">ESTOFS</alias>
<alias base="estofsEP">ESTOFS</alias> <alias base="estofsEP">ESTOFS</alias>
<alias base="estofsHI">ESTOFS</alias> <alias base="estofsHI">ESTOFS</alias>
@ -73,16 +73,16 @@
<alias base="MRF26">mrf202</alias> <alias base="MRF26">mrf202</alias>
<alias base="GFS201">gfs201</alias> <alias base="GFS201">gfs201</alias>
<alias base="mrfNH">mrf201</alias> <alias base="mrfNH">mrf201</alias>
<alias base="GFS213">gfs213</alias> <alias base="GFS95">gfs95</alias>
<alias base="AVN211">avn211</alias> <alias base="AVN211">avn211</alias>
<alias base="mesoEta212">mesoEta212</alias> <alias base="NAM40">NAM40</alias>
<alias base="mesoEta215">mesoEta215</alias> <alias base="NAM20">NAM20</alias>
<alias base="ETA212">eta212</alias> <alias base="NAM40">eta212</alias>
<alias base="AVN203">avn203</alias> <alias base="AVN203">avn203</alias>
<alias base="MRF203">mrf203</alias> <alias base="MRF203">mrf203</alias>
<alias base="MRF204">mrf204</alias> <alias base="MRF204">mrf204</alias>
<alias base="MRF205">mrf205</alias> <alias base="MRF205">mrf205</alias>
<alias base="ETA207">eta207</alias> <alias base="AK-NAM95">eta207</alias>
<alias base="AVN-NorthernHemisphere">avnNH</alias> <alias base="AVN-NorthernHemisphere">avnNH</alias>
<alias base="AVN37">avnNH</alias> <alias base="AVN37">avnNH</alias>
<alias base="AVN38">avnNH</alias> <alias base="AVN38">avnNH</alias>
@ -92,7 +92,7 @@
<alias base="AVN42">avnNH</alias> <alias base="AVN42">avnNH</alias>
<alias base="AVN43">avnNH</alias> <alias base="AVN43">avnNH</alias>
<alias base="AVN44">avnNH</alias> <alias base="AVN44">avnNH</alias>
<alias base="GWW233">gww233</alias> <alias base="WaveWatch">gww233</alias>
<alias base="GWW21">gww233</alias> <alias base="GWW21">gww233</alias>
<alias base="GWW22">gww233</alias> <alias base="GWW22">gww233</alias>
<alias base="GWW23">gww233</alias> <alias base="GWW23">gww233</alias>
@ -101,26 +101,28 @@
<alias base="SeaIce220">seaIce219</alias> <alias base="SeaIce220">seaIce219</alias>
<alias base="SeaIce173">seaIce219</alias> <alias base="SeaIce173">seaIce219</alias>
<alias base="SeaIce235">seaIce219</alias> <alias base="SeaIce235">seaIce219</alias>
<alias base="RUC236">ruc236</alias> <alias base="RAP40">rap40</alias>
<alias base="AVN225">avn225</alias> <alias base="AVN225">avn225</alias>
<alias base="AKWAVE239">akWave239</alias> <alias base="AKWAVE239">akWave239</alias>
<alias base="WNAWAVE238">wnaWave238</alias> <alias base="WNAWAVE238">wnaWave238</alias>
<alias base="mesoEta216">mesoEta216</alias> <alias base="AK-NAM45">AK-NAM45</alias>
<alias base="mesoEta217">mesoEta217</alias> <alias base="AK-NAM22">AK-NAM22</alias>
<alias base="ETA218">eta218</alias> <alias base="NAM12">NAM12</alias>
<alias base="ETA242">eta242</alias> <alias base="AK-NAM11">eta242</alias>
<alias base="ENPWAVE253">enpWave253</alias> <alias base="ENPWAVE253">enpWave253</alias>
<alias base="HurWind226">TPCtcm226</alias> <alias base="HurWind226">TPCtcm226</alias>
<alias base="HurWind175">TCPtcm175</alias> <alias base="HurWind175">TCPtcm175</alias>
<alias base="HurWind250">TPCtpm250</alias> <alias base="HurWind250">TPCtpm250</alias>
<alias base="NICICE">nic218</alias> <alias base="NICICE">nic218</alias>
<alias base="AK-NICICE">nic242</alias> <alias base="AK-NICICE">nic242</alias>
<alias base="GFS212">gfs212</alias> <alias base="DGEX">dgex185</alias>
<alias base="AK-DGEX">dgex186</alias>
<alias base="GFS40">gfs212</alias>
<alias base="GFS160">gfs160</alias> <alias base="GFS160">gfs160</alias>
<alias base="GFS254">gfs254</alias> <alias base="GFS254">gfs254</alias>
<alias base="GFS161">gfs161</alias> <alias base="GFS161">gfs161</alias>
<alias base="GFS199">gfs161</alias> <alias base="GFS199">gfs161</alias>
<alias base="RUC130">ruc130</alias> <alias base="RAP13">RAP13</alias>
<alias base="RTMA25">rtmaNDFD</alias> <alias base="RTMA25">rtmaNDFD</alias>
<alias base="URMA25">urmaNDFD</alias> <alias base="URMA25">urmaNDFD</alias>
<alias base="namdng25">NamDNG</alias> <alias base="namdng25">NamDNG</alias>
@ -150,7 +152,7 @@
<alias base="GRLKwave">GRLKwave</alias> <alias base="GRLKwave">GRLKwave</alias>
<alias base="MSAS">msas</alias> <alias base="MSAS">msas</alias>
<alias base="GFSSouthernHemisphere">gfs201</alias> <alias base="GFSSouthernHemisphere">gfs201</alias>
<alias base="mesoEta237">eta218</alias> <alias base="PR-NAM">NAM12</alias>
<alias base="ENSEMBLE">ensembleNH</alias> <alias base="ENSEMBLE">ensembleNH</alias>
<alias base="ENSEMBLE37">ensembleNH</alias> <alias base="ENSEMBLE37">ensembleNH</alias>
<alias base="ENSEMBLE38">ensembleNH</alias> <alias base="ENSEMBLE38">ensembleNH</alias>
@ -330,6 +332,7 @@
<alias base="NationalBlendPR">NationalBlend</alias> <alias base="NationalBlendPR">NationalBlend</alias>
<alias base="NationalBlendHI">NationalBlend</alias> <alias base="NationalBlendHI">NationalBlend</alias>
<alias base="NationalBlendAK">NationalBlend</alias> <alias base="NationalBlendAK">NationalBlend</alias>
<alias base="NationalBlendOC">NationalBlend</alias>
<alias base="PGBlended">PGBlended</alias> <alias base="PGBlended">PGBlended</alias>
<alias base="PGBlended-Night">PGBlended</alias> <alias base="PGBlended-Night">PGBlended</alias>
<alias base="NCOM-USEAST">ncom</alias> <alias base="NCOM-USEAST">ncom</alias>

View file

@ -284,6 +284,9 @@
<Level key="FHAG10"> <Level key="FHAG10">
<DatabaseLevel levelName="FHAG" levelOneValue="10.0" unit="m"/> <DatabaseLevel levelName="FHAG" levelOneValue="10.0" unit="m"/>
</Level> </Level>
<Level key="FHAG30">
<DatabaseLevel levelName="FHAG" levelOneValue="30.0" unit="m"/>
</Level>
<Level key="FHAG80"> <Level key="FHAG80">
<DatabaseLevel levelName="FHAG" levelOneValue="80.0" unit="m"/> <DatabaseLevel levelName="FHAG" levelOneValue="80.0" unit="m"/>
</Level> </Level>
@ -293,6 +296,9 @@
<Level key="FHAG4000"> <Level key="FHAG4000">
<DatabaseLevel levelName="FHAG" levelOneValue="4000.0" unit="m"/> <DatabaseLevel levelName="FHAG" levelOneValue="4000.0" unit="m"/>
</Level> </Level>
<Level key="FHAG0610">
<DatabaseLevel levelName="FHAG" levelOneValue="0.0" levelTwoValue="610.0" unit="m"/>
</Level>
<Level key="FHAG01000"> <Level key="FHAG01000">
<DatabaseLevel levelName="FHAG" levelOneValue="0.0" levelTwoValue="1000.0" unit="m"/> <DatabaseLevel levelName="FHAG" levelOneValue="0.0" levelTwoValue="1000.0" unit="m"/>
</Level> </Level>
@ -302,6 +308,9 @@
<Level key="FHAG06000"> <Level key="FHAG06000">
<DatabaseLevel levelName="FHAG" levelOneValue="0.0" levelTwoValue="6000.0" unit="m"/> <DatabaseLevel levelName="FHAG" levelOneValue="0.0" levelTwoValue="6000.0" unit="m"/>
</Level> </Level>
<Level key="FHAG61040000">
<DatabaseLevel levelName="FHAG" levelOneValue="610.0" levelTwoValue="40000.0" unit="m"/>
</Level>
<Level key="FRZ"> <Level key="FRZ">
<DatabaseLevel levelName="FRZ" levelOneValue="0.0"/> <DatabaseLevel levelName="FRZ" levelOneValue="0.0"/>
</Level> </Level>
@ -671,4 +680,7 @@
<Level key="NTAT"> <Level key="NTAT">
<DatabaseLevel levelName="NTAT" levelOneValue="0.0"/> <DatabaseLevel levelName="NTAT" levelOneValue="0.0"/>
</Level> </Level>
<Level key="MWSL">
<DatabaseLevel levelName="MWSL" levelOneValue="0.0"/>
</Level>
</LevelMappings> </LevelMappings>

View file

@ -291,6 +291,17 @@
<fcst>943200</fcst> <fcst>943200</fcst>
<fcst>946800</fcst> <fcst>946800</fcst>
<fcst>950400</fcst> <fcst>950400</fcst>
<fcst>957600</fcst>
<fcst>961200</fcst>
<fcst>964800</fcst>
<fcst>968400</fcst>
<fcst>972000</fcst>
<fcst>975600</fcst>
<fcst>979200</fcst>
<fcst>982800</fcst>
<fcst>986400</fcst>
<fcst>990000</fcst>
<fcst>993600</fcst>
</valtimeMINUSreftime> </valtimeMINUSreftime>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>mnt</short_name> <short_name>mnt</short_name>
@ -466,27 +477,12 @@
<level>SFC</level> <level>SFC</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>ppi1hr</short_name>
<long_name>1HR PPI</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>1hrPcpProbIndex</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>ppi6hr</short_name> <short_name>ppi6hr</short_name>
<long_name>6HR PPI</long_name> <long_name>6HR PPI</long_name>
<units>%</units> <units>1ndex</units>
<udunits>percent</udunits> <udunits>index</udunits>
<uiname>6hrPcpProbIndex</uiname> <uiname>PPI6hr</uiname>
<valid_range>0.0</valid_range> <valid_range>0.0</valid_range>
<valid_range>100.0</valid_range> <valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
@ -546,14 +542,15 @@
<long_name>Wind Direction</long_name> <long_name>Wind Direction</long_name>
<units>degreeTrue</units> <units>degreeTrue</units>
<udunits>degree_True</udunits> <udunits>degree_True</udunits>
<uiname>windDir</uiname> <uiname>WD</uiname>
<valid_range>0.0</valid_range> <valid_range>0.0</valid_range>
<valid_range>360.0</valid_range> <valid_range>360.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>1</n3D> <n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc> <levelsDesc>FHAG 10, FHAG 0-610</levelsDesc>
<levels> <levels>
<level>FHAG10</level> <level>FHAG10</level>
<level>FHAG0610</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -628,14 +625,15 @@
<long_name>Wind Speed</long_name> <long_name>Wind Speed</long_name>
<units>m/s</units> <units>m/s</units>
<udunits>meter/sec</udunits> <udunits>meter/sec</udunits>
<uiname>windSpeed</uiname> <uiname>WS</uiname>
<valid_range>-150.0</valid_range> <valid_range>-150.0</valid_range>
<valid_range>150.0</valid_range> <valid_range>150.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>1</n3D> <n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc> <levelsDesc>FHAG 10, FHAG 0-610</levelsDesc>
<levels> <levels>
<level>FHAG10</level> <level>FHAG10</level>
<level>FHAG0610</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -708,26 +706,11 @@
<valid_range>330.0</valid_range> <valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>1</n3D> <n3D>1</n3D>
<levelsDesc>2 FHAG</levelsDesc> <levelsDesc>FHAG 2</levelsDesc>
<levels> <levels>
<level>FHAG2</level> <level>FHAG2</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>totsn</short_name>
<long_name>Total Snowfall</long_name>
<units>m</units>
<udunits>meters</udunits>
<uiname>SnowAmt</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>snowlvl</short_name> <short_name>snowlvl</short_name>
<long_name>Snow Level</long_name> <long_name>Snow Level</long_name>
@ -753,7 +736,7 @@
<valid_range>330.0</valid_range> <valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>0</n3D> <n3D>0</n3D>
<levelsDesc>2 FHAG</levelsDesc> <levelsDesc>FHAG 2</levelsDesc>
<levels> <levels>
<level>FHAG2</level> <level>FHAG2</level>
</levels> </levels>
@ -768,13 +751,13 @@
<valid_range>330.0</valid_range> <valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>0</n3D> <n3D>0</n3D>
<levelsDesc>2 FHAG</levelsDesc> <levelsDesc>FHAG 2</levelsDesc>
<levels> <levels>
<level>FHAG2</level> <level>FHAG2</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>MaxTW</short_name> <short_name>maxtw</short_name>
<long_name>Max Wetbulb Aloft</long_name> <long_name>Max Wetbulb Aloft</long_name>
<units>K</units> <units>K</units>
<udunits>degree_Kelvin</udunits> <udunits>degree_Kelvin</udunits>
@ -783,16 +766,16 @@
<valid_range>330.0</valid_range> <valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>0</n3D> <n3D>0</n3D>
<levelsDesc>EA</levelsDesc> <levelsDesc>FHAG 610-40000</levelsDesc>
<levels> <levels>
<level>EA</level> <level>FHAG61040000</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>ptyp</short_name> <short_name>ptyp</short_name>
<long_name>Precipitation type</long_name> <long_name>Precipitation type</long_name>
<units/> <units>1</units>
<udunits/> <udunits>1</udunits>
<uiname>pTyp</uiname> <uiname>pTyp</uiname>
<valid_range>1.0</valid_range> <valid_range>1.0</valid_range>
<valid_range>5.0</valid_range> <valid_range>5.0</valid_range>
@ -903,9 +886,9 @@
<valid_range>6000.0</valid_range> <valid_range>6000.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>1</n3D> <n3D>1</n3D>
<levelsDesc>EA</levelsDesc> <levelsDesc>FHAG 610-40000</levelsDesc>
<levels> <levels>
<level>EA</level> <level>FHAG61040000</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -918,9 +901,9 @@
<valid_range>6000.0</valid_range> <valid_range>6000.0</valid_range>
<fillValue>-99999.0</fillValue> <fillValue>-99999.0</fillValue>
<n3D>1</n3D> <n3D>1</n3D>
<levelsDesc>EA</levelsDesc> <levelsDesc>SFC</levelsDesc>
<levels> <levels>
<level>EA</level> <level>SFC</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -938,4 +921,440 @@
<level>SFC</level> <level>SFC</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>mixht</short_name>
<long_name>Mixing Height</long_name>
<units>m</units>
<udunits>meters</udunits>
<uiname>MIXHT</uiname>
<valid_range>0.0</valid_range>
<valid_range>3689.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>trwdir</short_name>
<long_name>Transport Wind direction</long_name>
<units>deg</units>
<udunits>degrees</udunits>
<uiname>TRWDIR</uiname>
<valid_range>0.0</valid_range>
<valid_range>360.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>trwspd</short_name>
<long_name>Transport Wind Speed</long_name>
<units>m/s</units>
<udunits>meter/sec</udunits>
<uiname>TRWSPD</uiname>
<valid_range>0.0</valid_range>
<valid_range>65.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>vrate</short_name>
<long_name>Ventilation Rate</long_name>
<units>m^2/s</units>
<udunits>meter2/sec</udunits>
<uiname>VRATE</uiname>
<valid_range>0.0</valid_range>
<valid_range>49958.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>hindex6hr</short_name>
<long_name>Haines Index</long_name>
<units>index</units>
<udunits>index</udunits>>
<uiname>HINDEX6hr</uiname>
<valid_range>2.0</valid_range>
<valid_range>6.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>fosindx6hr</short_name>
<long_name>Fosberg Fire Weather Index</long_name>
<units>index</units>
<udunits>index</udunits>>
<uiname>FOSINDX6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>llwshgt</short_name>
<long_name>LLWS Height</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>LLWSHgt</uiname>
<valid_range>0.0</valid_range>
<valid_range>609.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 0-610</levelsDesc>
<levels>
<level>FHAG0610</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>maxref1hr</short_name>
<long_name>Simulated Maximum Reflectivity</long_name>
<units>dBZ</units>
<udunits>dBZ</udunits>
<uiname>MAXREF1hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 1000</levelsDesc>
<levels>
<level>FHAG1000</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>viliq</short_name>
<long_name>Vertically Integrated Liquid</long_name>
<units>kg/m^2</units>
<udunits>kilogram/meters2</udunits>
<uiname>VILIQ</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>retop</short_name>
<long_name>Echo Tops</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>RETOP</uiname>
<valid_range>1.0</valid_range>
<valid_range>88888.203</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>CTL</levelsDesc>
<levels>
<level>CTL</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>wgs50pct</short_name>
<long_name>10-m Wind Gust</long_name>
<units>knots</units>
<udunits>knots</udunits>
<uiname>WGS50pct</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc>
<levels>
<level>FHAG10</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>ws50pct</short_name>
<long_name>30-m/80-m Wind Speed</long_name>
<units>m/s</units>
<udunits>meter/sec</udunits>
<uiname>WS50pct</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 30, 80</levelsDesc>
<levels>
<level>FHAG30</level>
<level>FHAG80</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>vis50pct</short_name>
<long_name>Visibility</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>Vis50pct</uiname>
<valid_range>0.0</valid_range>
<valid_range>100000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>t50pct</short_name>
<long_name>Air Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>T50pct</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>pmsl10pct</short_name>
<long_name>10th percentile Mean Sea Level Pressure</long_name>
<units>Pa</units>
<udunits>pascal</udunits>
<uiname>PMSL10pct</uiname>
<valid_range>80000.0</valid_range>
<valid_range>110000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>MSL</levelsDesc>
<levels>
<level>MSL</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>pmsl50pct</short_name>
<long_name>50th percentile Mean Sea Level Pressure</long_name>
<units>Pa</units>
<udunits>pascal</udunits>
<uiname>PMSL50pct</uiname>
<valid_range>80000.0</valid_range>
<valid_range>110000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>MSL</levelsDesc>
<levels>
<level>MSL</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>pmsl90pct</short_name>
<long_name>90th percentile Mean Sea Level Pressure</long_name>
<units>Pa</units>
<udunits>pascal</udunits>
<uiname>PMSL90pct</uiname>
<valid_range>80000.0</valid_range>
<valid_range>110000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>MSL</levelsDesc>
<levels>
<level>MSL</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>htsgw</short_name>
<long_name>Significant Wave Height</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>HTSGW</uiname>
<valid_range>0.0</valid_range>
<valid_range>50.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>pwther</short_name>
<long_name>Predominant Weather</long_name>
<units>Numeric</units>
<udunits>Numeric</udunits>
<uiname>PWTHER</uiname>
<valid_range>0.0</valid_range>
<valid_range>138.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>totsn1hr</short_name>
<long_name>1-h Snow Accumulation</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>TOTSN1hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>3.78</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>ficeac1hr</short_name>
<long_name>1-h Ice Accumulation</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>FICEAC1hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>15</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>totsn6hr</short_name>
<long_name>6-h Snow Accumulation</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>TOTSN6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>ficeac6hr</short_name>
<long_name>6-h Ice Accumulation</long_name>
<units>m</units>
<udunits>meter</udunits>
<uiname>FICEAC6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>15.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>ppi1hr</short_name>
<long_name>1-h Precipitation Potential Index</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>PPI1hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>thp1hr</short_name>
<long_name>1-h SREF-based Prob. of a Thunderstorm</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>ThP1hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>drytpprob3hr</short_name>
<long_name>3-h SREF-based Prob. of a Dry Thunderstorm</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>DRYTPPROB3hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>tp10pct6hr</short_name>
<long_name>10th percentile 6hr Quant</long_name>
<units>millimeter</units>
<udunits>mm</udunits>
<uiname>TP10pct6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>tp50pct6hr</short_name>
<long_name>50th percentile 6hr Quant</long_name>
<units>millimeter</units>
<udunits>mm</udunits>
<uiname>TP50pct6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>tp90pct6hr</short_name>
<long_name>90th percentile 6hr Quant</long_name>
<units>millimeter</units>
<udunits>mm</udunits>
<uiname>TP90pct6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-999999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
</gridParamInfo> </gridParamInfo>

View file

@ -85,21 +85,6 @@
<level>SFC</level> <level>SFC</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>tpHPC</short_name>
<long_name>6 hr Total Precip</long_name>
<units>mm</units>
<udunits>millimeter</udunits>
<uiname>totPrecip</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>tpALR</short_name> <short_name>tpALR</short_name>
<long_name>6 hr Total Precip for RFC-&gt; ALR</long_name> <long_name>6 hr Total Precip for RFC-&gt; ALR</long_name>

View file

@ -22,7 +22,7 @@
<!-- <!--
Mar 20, 2013 #1774 randerso Added forecast hours out to 18 Mar 20, 2013 #1774 randerso Added forecast hours out to 18
Jun 19, 2013 #2044 randerso Updated to match model Jun 19, 2013 #2044 randerso Updated to match model
Feb 24 20153 DCS14537 byin Added HPBL for RUC13 Feb 24 20153 DCS14537 byin Added HPBL for RAP13
Jun 13, 2016 #17308 bhunderm Corrected LI units Jun 13, 2016 #17308 bhunderm Corrected LI units
--> -->

View file

@ -28,7 +28,7 @@
Mar 31, 2014 #2934 dgilling Updated params for pSurge2.0/PHISH data. Mar 31, 2014 #2934 dgilling Updated params for pSurge2.0/PHISH data.
Jul 03, 2014 DR 14068 mfoster Added parameters for 3km AK-RTMA Jul 03, 2014 DR 14068 mfoster Added parameters for 3km AK-RTMA
Dec 15, 2014 DR 14024 jwatson Added parameters for 2.5km GFSLAMPGrid Dec 15, 2014 DR 14024 jwatson Added parameters for 2.5km GFSLAMPGrid
Feb 24, 2015 DR 16671 byin Added HPBL for RUC13 Feb 24, 2015 DR 16671 byin Added HPBL for RAP13
May 21, 2015 DR 17515 bhunder Added parameters for URMA25 May 21, 2015 DR 17515 bhunder Added parameters for URMA25
Jun 29, 2015 #4537 rferrel Added parameters for HRRR. Jun 29, 2015 #4537 rferrel Added parameters for HRRR.
Oct 08, 2015 #4958 dgilling Added parameters for NationalBlend. Oct 08, 2015 #4958 dgilling Added parameters for NationalBlend.
@ -593,9 +593,34 @@
<alias base="PTypIcePellets">ptypicepellets</alias> <alias base="PTypIcePellets">ptypicepellets</alias>
<alias base="SNOWLVL">snowlvl</alias> <alias base="SNOWLVL">snowlvl</alias>
<alias base="SNOWRATIO">snowratio</alias> <alias base="SNOWRATIO">snowratio</alias>
<alias base="PBE">pbe</alias>
<alias base="NBE">nbe</alias>
<alias base="RIPCOP">ripcop</alias> <alias base="RIPCOP">ripcop</alias>
<alias base="EROSNP">erosnp</alias> <alias base="EROSNP">erosnp</alias>
<alias base="OWASHP">owashp</alias> <alias base="OWASHP">owashp</alias>
<alias base="MIXHT">mixht</alias>
<alias base="TRWSPD">trwspd</alias>
<alias base="TRWDIR">trwdir</alias>
<alias base="VRATE">vrate</alias>
<alias base="HINDEX6hr">hindex6hr</alias>
<alias base="FOSINDX6hr">fosindx6hr</alias>
<alias base="MAXREF1hr">maxref1hr</alias>
<alias base="PWTHER">pwther</alias>
<alias base="TOTSN1hr">totsn1hr</alias>
<alias base="FICEAC1hr">ficeac1hr</alias>
<alias base="TOTSN6hr">totsn6hr</alias>
<alias base="FICEAC6hr">ficeac6hr</alias>
<alias base="TP10pct6hr">tp10pct6hr</alias>
<alias base="TP50pct6hr">tp50pct6hr</alias>
<alias base="TP90pct6hr">tp90pct6hr</alias>
<alias base="ThP1hr">thp1hr</alias>
<alias base="DRYTPPROB3hr">drytpprob3hr</alias>
<alias base="WGS50pct">wgs50pct</alias>
<alias base="WS50pct">ws50pct</alias>
<alias base="Vis50pct">vis50pct</alias>
<alias base="T50pct">t50pct</alias>
<alias base="PMSL10pct">pmsl10pct</alias>
<alias base="PMSL50pct">pmsl50pct</alias>
<alias base="PMSL90pct">pmsl90pct</alias>
<alias base="CC">cc</alias>
<alias base="MaxTW">maxtw</alias>
<alias base="LLWSHgt">llwshgt</alias>
</aliasList> </aliasList>

View file

@ -52,6 +52,7 @@
# Jul 17, 2017 DR19976 MPorricelli Add labeling of Probability Matched Mean fields# # Jul 17, 2017 DR19976 MPorricelli Add labeling of Probability Matched Mean fields#
# Nov 29, 2017 6536 bsteffen Handle redundant statistical specifiers better. # Nov 29, 2017 6536 bsteffen Handle redundant statistical specifiers better.
# Feb 07, 2018 7213 nabowle Only allow P-ETSS to create Statistical parameters. # Feb 07, 2018 7213 nabowle Only allow P-ETSS to create Statistical parameters.
# Mar 19, 2018 20395 wkwock Added PDS template 15
# #
import grib2 import grib2
@ -444,7 +445,7 @@ class GribDecoder():
# Templates 0-11 are ordered the same for the most part and can therefore be processed the same # Templates 0-11 are ordered the same for the most part and can therefore be processed the same
# Exception cases are handled accordingly # Exception cases are handled accordingly
if pdsTemplateNumber <= 12: if pdsTemplateNumber <= 12 or pdsTemplateNumber == 15:
# Get the basic level and parameter information # Get the basic level and parameter information
if (pdsTemplate[0] == 255): if (pdsTemplate[0] == 255):
@ -477,7 +478,13 @@ class GribDecoder():
levelName = None; levelName = None;
levelUnit = None; levelUnit = None;
gribLevel = GribTableLookup.getInstance().getTableValue(centerID, subcenterID, LEVELS_TABLE, int(pdsTemplate[9]))
#In case the 1st level is 'SFC' and the 2nd level is 'FHAG', use FHAG as the level number
levelNumber = int(pdsTemplate[9])
levelNumber2 = int(pdsTemplate[12])
if levelNumber == 1 and levelNumber2 == 103:
levelNumber = levelNumber2
gribLevel = GribTableLookup.getInstance().getTableValue(centerID, subcenterID, LEVELS_TABLE, levelNumber)
if gribLevel is not None: if gribLevel is not None:
levelName = gribLevel.getAbbreviation(); levelName = gribLevel.getAbbreviation();
@ -519,10 +526,7 @@ class GribDecoder():
else: else:
levelTwoValue = float(pdsTemplate[14] * pow(10, pdsTemplate[13] * -1)) levelTwoValue = float(pdsTemplate[14] * pow(10, pdsTemplate[13] * -1))
if levelName == 'SFC' and levelOneValue != float(0): if levelName == 'EATM' or levelName == 'SFC':
levelOneValue = float(0)
if levelName == 'EATM':
levelOneValue = float(0) levelOneValue = float(0)
levelTwoValue = float(Level.getInvalidLevelValue()) levelTwoValue = float(Level.getInvalidLevelValue())

View file

@ -111,6 +111,8 @@ import ucar.unidata.io.RandomAccessFile;
* Apr 11, 2016 5564 bsteffen Move localization files to common_static * Apr 11, 2016 5564 bsteffen Move localization files to common_static
* Apr 19, 2016 5572 bsteffen Move GribModelLookup to common * Apr 19, 2016 5572 bsteffen Move GribModelLookup to common
* Sep 11, 2017 6406 bsteffen Upgrade ucar * Sep 11, 2017 6406 bsteffen Upgrade ucar
* Aug 02, 2018 7397 mapeters Fix parameter table lookups so standard
* ucar lookups are used
* *
* *
* </pre> * </pre>
@ -159,25 +161,21 @@ public class Grib1Decoder {
LocalizationLevel.BASE), LocalizationLevel.BASE),
"/grib/ucar/userTables.lst") "/grib/ucar/userTables.lst")
.getPath(); .getPath();
Grib1ParamTables tables;
try { try {
Grib1ParamTables.Lookup lookup = new Grib1ParamTables.Lookup(); Grib1ParamTables.addParameterTableLookup(ucarUserFile);
lookup.readLookupTable(ucarUserFile);
tables = new Grib1ParamTables(lookup, null);
} catch (IOException e) { } catch (IOException e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error reading user parameter tables for ucar grib decoder", "Error reading user parameter tables for ucar grib decoder",
e); e);
tables = new Grib1ParamTables(null, null);
} }
paramTables = tables; paramTables = new Grib1ParamTables();
} }
/** /**
* Decodes the grib file provided. * Decodes the grib file provided.
* *
* @param gribFileName * @param message
* The name of the file to be decoded * message describing the grib file to decode
* @return The decoded GridRecords * @return The decoded GridRecords
* @throws GribException * @throws GribException
* If decoding the file fails or encounters problems * If decoding the file fails or encounters problems

View file

@ -71,6 +71,36 @@
</process> </process>
</model> </model>
<!--
DThP3hr is repackaged from SPC.
-->
<model>
<name>NationalBlend</name>
<center>7</center>
<subcenter>9</subcenter>
<grids>
<id>NBMv3</id>
</grids>
<process>
<id>113</id>
</process>
</model>
<!--
Fosberg Fire Weather Index (mxffwi) is repackaged from SPC.
-->
<model>
<name>NationalBlend</name>
<center>7</center>
<subcenter>14</subcenter>
<grids>
<id>NBMv3</id>
</grids>
<process>
<id>104</id>
</process>
</model>
<!--Alaska--> <!--Alaska-->
<model> <model>
<name>NationalBlendAK</name> <name>NationalBlendAK</name>

View file

@ -3,6 +3,7 @@
1:1:Fire Outlook Due to Dry Thunderstorm:index(see GRIB 2 code table 4.224):FIREODT 1:1:Fire Outlook Due to Dry Thunderstorm:index(see GRIB 2 code table 4.224):FIREODT
2:2:Haines Index:Numeric:HINDEX 2:2:Haines Index:Numeric:HINDEX
3:3:Haines Index:Numeric:HINDEX 3:3:Haines Index:Numeric:HINDEX
4:4:Fosberg Index:Numeric:FOSINDX
#192-254 Reserved for local use #192-254 Reserved for local use
255:255:Missing 255:255:Missing

View file

@ -1,6 +1,10 @@
# Product Discipline 0: Meteorological products, Parameter Category 1: Moisture # Product Discipline 0: Meteorological products, Parameter Category 1: Moisture
#192-254 Reserved for local use #192-254 Reserved for local use
220:220:SnowRatio::SNOWRATIO 220:220:SnowRatio::SNOWRATIO
228:228:Flat Ice Accumulation (FRAM):kg m-2:FICEAC
231:231:Precipitation Potential Index (PPI):%:PPI
232:232:Probability Cloud Ice Present:%:PRBCLDICE
233:233:Snow Liquid ratio:kg kg-1:SNOWRATIO
242:242:Probability of Cloud Ice Present:%:PRBCLDICE 242:242:Probability of Cloud Ice Present:%:PRBCLDICE
243:243:Precipitation Potential Index (PPI):%:PPI 243:243:Precipitation Potential Index (PPI):%:PPI
255:255:Missing 255:255:Missing

View file

@ -1,4 +1,5 @@
# Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties # Product Discipline 0: Meteorological products, Parameter Category 19: Physical atmospheric properties
3:3:Mixed Layer Depth:m:MIXHT
#192-254 Reserved for local use #192-254 Reserved for local use
192:192:Maximum Snow Albedo:%:MXSALB 192:192:Maximum Snow Albedo:%:MXSALB
193:193:Snow-Free Albedo:%:SNFALB 193:193:Snow-Free Albedo:%:SNFALB
@ -44,5 +45,6 @@
233:233:Icing probability:non-dim:ICPRB 233:233:Icing probability:non-dim:ICPRB
234:234:Icing severity:non-dim:ICSEV 234:234:Icing severity:non-dim:ICSEV
235:235:Snow Level:m:SNOWLVL 235:235:Snow Level:m:SNOWLVL
236:236:Snow Level:m:SNOWLVL
255:255:Missing 255:255:Missing

View file

@ -1,6 +1,6 @@
# Product Discipline 0: Meteorological products, Parameter Category 2: Momentum # Product Discipline 0: Meteorological products, Parameter Category 2: Momentum
# 192-254 Reserved for local use # 192-254 Reserved for local use
192:192:Vertical speed shear:s^-1:VWSH:VSS 192:192:Vertical speed sheer:s^-1:VWSH:VSS
193:193:Horizontal Momentum Flux:N/m^2:MFLX 193:193:Horizontal Momentum Flux:N/m^2:MFLX
194:194:U-Component Storm Motion:m/s:USTM 194:194:U-Component Storm Motion:m/s:USTM
195:195:V-Component Storm Motion:m/s:VSTM 195:195:V-Component Storm Motion:m/s:VSTM
@ -10,8 +10,8 @@
199:199:Longitude of U Wind Component of Velocity:degrees:LOUV 199:199:Longitude of U Wind Component of Velocity:degrees:LOUV
200:200:Latitude of V Wind Component of Velocity:degrees:LAVV 200:200:Latitude of V Wind Component of Velocity:degrees:LAVV
201:201:Longitude of V Wind Component of Velocity:degrees:LOVV 201:201:Longitude of V Wind Component of Velocity:degrees:LOVV
202:202:Latitude of Pressure Point:degrees:LAPP 202:202:Latitude of Presure Point:degrees:LAPP
203:203:Longitude of Pressure Point:degrees:LOPP 203:203:Longitude of Presure Point:degrees:LOPP
204:204:Vertical Eddy Diffusivity Heat exchange:m^2/s:VEDH 204:204:Vertical Eddy Diffusivity Heat exchange:m^2/s:VEDH
205:205:Covariance between Meridional and Zonal Components of the wind.:m^2/s^2:COVMZ 205:205:Covariance between Meridional and Zonal Components of the wind.:m^2/s^2:COVMZ
206:206:Covariance between Temperature and Zonal Components of the wind.:K*m/s:COVTZ 206:206:Covariance between Temperature and Zonal Components of the wind.:K*m/s:COVTZ
@ -33,4 +33,6 @@
222:222:U Component of Hourly Maximum 10m Wind Speed:m/s:MAXUW 222:222:U Component of Hourly Maximum 10m Wind Speed:m/s:MAXUW
223:223:V Component of Hourly Maximum 10m Wind Speed:m/s:MAXVW 223:223:V Component of Hourly Maximum 10m Wind Speed:m/s:MAXVW
224:224:Ventilation Rate:m^2/s:VRATE 224:224:Ventilation Rate:m^2/s:VRATE
225:225:Transport Wind Speed:m/s:TRWSPD
226:226:Transport Wind Direction:Deg:TRWDIR
255:255:Missing 255:255:Missing

View file

@ -10,5 +10,8 @@
197:197:Updraft Helicity:m^2/s^2:UPHL 197:197:Updraft Helicity:m^2/s^2:UPHL
198:198:Leaf Area Index::LAI 198:198:Leaf Area Index::LAI
199:199:Hourly Maximum of Updraft Helicity over Layer 2km to 5 km AGL:m^2/s^2:MXUPHL 199:199:Hourly Maximum of Updraft Helicity over Layer 2km to 5 km AGL:m^2/s^2:MXUPHL
201:201:Bourgoiun Negative Energy Layer (surface to freezing level):J/kg:NBE
202:202:Bourgoiun Positive Energy Layer (2k ft AGL to 400 hPa):J/kg:PBE
255:255:Missing 255:255:Missing

View file

@ -2,7 +2,7 @@
#192-254 Reserved for local use #192-254 Reserved for local use
192:192:Level at Specified Pressure Difference from Ground to Level:Pa:PDLY:LYRBL 192:192:Level at Specified Pressure Difference from Ground to Level:Pa:PDLY:LYRBL
193:193:Eta Level:Eta value:ELYR:ETA 193:193:Eta Level:Eta value:ELYR:ETA
200:200:Entire Atmosphere::NONE:EA 200:200:Entire Atmosphere::EA
201:201:Entire Ocean::NONE 201:201:Entire Ocean::NONE
204:204:Highest Tropospheric Freezing Level::HTFL 204:204:Highest Tropospheric Freezing Level::HTFL
206:206:Grid Scale Cloud Bottom Level::GSCBL 206:206:Grid Scale Cloud Bottom Level::GSCBL

View file

@ -43,5 +43,6 @@
232:232:Volcanic Ash Forecast Transport and Dispersion:log10(kg/m^3):VAFTD 232:232:Volcanic Ash Forecast Transport and Dispersion:log10(kg/m^3):VAFTD
233:233:Icing probability:non-dim:ICPRB 233:233:Icing probability:non-dim:ICPRB
234:234:Icing severity:non-dim:ICSEV 234:234:Icing severity:non-dim:ICSEV
237:237:Dry Thunderstorm Probability:%:DRYTPROB
255:255:Missing 255:255:Missing

View file

@ -652,6 +652,9 @@ TW_NBM-NCEP-MDL MaxTW
CAPE_NBM-NCEP-MDL PBE CAPE_NBM-NCEP-MDL PBE
CIn_NBM-NCEP-MDL NBE CIn_NBM-NCEP-MDL NBE
PRBCLDICE-9.999e+18%_NBM-NCEP-MDL PrbCldIce PRBCLDICE-9.999e+18%_NBM-NCEP-MDL PrbCldIce
PRBCLDICE0.0%_NBM-NCEP-MDL PrbCldIce
GeH_NBM-NCEP-MDL LLWSHgt
DRYTPROB0.0%_NBM-NCEP-MDL DRYTPPROB
// NBM publishes this, it is marked SREF because NBM doesn't change it. // NBM publishes this, it is marked SREF because NBM doesn't change it.
ThP0.0%_SREF-NCEP-MDL_2345x1597_10800-0 ThP3hr ThP0.0%_SREF-NCEP-MDL_2345x1597_10800-0 ThP3hr
//END NationalBLend //END NationalBLend

View file

@ -103,7 +103,6 @@ import com.vividsolutions.jts.io.WKTWriter;
* Sep 17, 2015 4756 dhladky Multiple guidance source bugs. * Sep 17, 2015 4756 dhladky Multiple guidance source bugs.
* Feb 12, 2016 5370 dhladky Camel case for insertTime. * Feb 12, 2016 5370 dhladky Camel case for insertTime.
* Apr 07, 2016 5491 tjensen Fix NullPointerException from getRawGeometries * Apr 07, 2016 5491 tjensen Fix NullPointerException from getRawGeometries
* Mar 07, 2017 DR 11861 lshi FFMP use of QPF in Basin Table
* May 11, 2017 6266 nabowle Use GetRadarSpatialRequest in getRadarCenter(). * May 11, 2017 6266 nabowle Use GetRadarSpatialRequest in getRadarCenter().
* </pre> * </pre>
* *
@ -1302,18 +1301,13 @@ public class FFMPUtils {
* Gets the ratio value * Gets the ratio value
* *
* @param qpe * @param qpe
* @param qpf
* @param guid * @param guid
* @return * @return
*/ */
public static float getRatioValue(float qpe, float qpf, float guid) { public static float getRatioValue(float qpe, float guid) {
float value = Float.NaN; float value = Float.NaN;
if ((qpe >= 0.0f) && (guid >= 0.0f)) { if ((qpe >= 0.0f) && (guid >= 0.0f)) {
value = qpe; value = (float) ((qpe / guid) * 100.0);
if ( !Float.isNaN(qpf)){
value += qpf;
}
value = (float) ((value / guid) * 100.0);
} }
@ -1323,21 +1317,18 @@ public class FFMPUtils {
* find max ratio in list * find max ratio in list
* *
* @param qpes * @param qpes
* @param qpfs
* @param guids * @param guids
* @return * @return
*/ */
public static float getMaxRatioValue(List<Float> qpes, List<Float> qpfs, List<Float> guids) { public static float getMaxRatioValue(List<Float> qpes, List<Float> guids) {
float ratio = Float.NaN; float ratio = Float.NaN;
boolean hasQpfs = qpfs != null && qpfs.size() == qpes.size();
if ((qpes.size() == guids.size()) && (!qpes.isEmpty()) if ((qpes.size() == guids.size()) && (!qpes.isEmpty())
&& (!guids.isEmpty())) { && (!guids.isEmpty())) {
for (int i = 0; i < qpes.size(); i++) { for (int i = 0; i < qpes.size(); i++) {
if (guids.get(i) > 0.0f) { if (guids.get(i) > 0.0f) {
float qpf = hasQpfs ? qpfs.get(i): Float.NaN; float nratio = getRatioValue(qpes.get(i), guids.get(i));
float nratio = getRatioValue(qpes.get(i), qpf, guids.get(i)); if (((nratio > ratio) && !Float.isNaN(nratio))
if ((!Float.isNaN(nratio) &&(nratio > ratio))
|| Float.isNaN(ratio)) { || Float.isNaN(ratio)) {
if (!Float.isInfinite(nratio)) { if (!Float.isInfinite(nratio)) {
ratio = nratio; ratio = nratio;
@ -1355,19 +1346,17 @@ public class FFMPUtils {
* Gets the diff value * Gets the diff value
* *
* @param qpe * @param qpe
* @param qpf
* @param guid * @param guid
* @return * @return
*/ */
public static float getDiffValue(float qpe, float qpf, float guid) { public static float getDiffValue(float qpe, float guid) {
float value = Float.NaN; float value = Float.NaN;
if ((qpe >= 0.0f) && (guid >= 0.0f)) { if ((qpe >= 0.0f) && (guid >= 0.0f)) {
value = qpe; float qpeRnd = Float.parseFloat(formatter.format(qpe));
if ( !Float.isNaN(qpf)){ float guidRnd = Float.parseFloat(formatter.format(guid));
value += qpf; value = new Float(qpeRnd - guidRnd);
}
value -= guid;
} }
@ -1379,22 +1368,19 @@ public class FFMPUtils {
* find max diff in the list * find max diff in the list
* *
* @param qpes * @param qpes
* @param qpfs
* @param guids * @param guids
* @return * @return
*/ */
public static float getMaxDiffValue(List<Float> qpes, List<Float> qpfs, List<Float> guids) { public static float getMaxDiffValue(List<Float> qpes, List<Float> guids) {
float diff = Float.NaN; float diff = Float.NaN;
boolean hasQpfs = qpfs != null && qpfs.size() == qpes.size();
if ((qpes.size() == guids.size()) && (!qpes.isEmpty()) if ((qpes.size() == guids.size()) && (!qpes.isEmpty())
&& (!guids.isEmpty())) { && (!guids.isEmpty())) {
for (int i = 0; i < qpes.size(); i++) { for (int i = 0; i < qpes.size(); i++) {
if (guids.get(i) > 0.0f) { if (guids.get(i) > 0.0f) {
float qpf = hasQpfs ? qpfs.get(i): Float.NaN; float ndiff = getDiffValue(qpes.get(i), guids.get(i));
float ndiff = getDiffValue(qpes.get(i), qpf, guids.get(i)); if ((((ndiff) > diff) && !Float.isNaN(ndiff))
if ((!Float.isNaN(ndiff) && (ndiff > diff))
|| Float.isNaN(diff)) { || Float.isNaN(diff)) {
diff = ndiff; diff = ndiff;
} }

View file

@ -108,7 +108,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='50.0' pixelValue='0'/> <entry displayValue='50.0' pixelValue='0'/>
<entry displayValue='55.0' pixelValue='17'/> <entry displayValue='55.0' pixelValue='17'/>
@ -313,7 +313,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='1.0' pixelValue='17'/> <entry displayValue='1.0' pixelValue='17'/>
@ -341,7 +341,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='1.0' pixelValue='17'/> <entry displayValue='1.0' pixelValue='17'/>
@ -368,7 +368,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -395,7 +395,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -423,7 +423,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -450,7 +450,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -477,7 +477,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -505,7 +505,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -532,7 +532,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -559,7 +559,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -586,7 +586,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>
@ -613,7 +613,7 @@ ARIFFG100, then the style rule parameter tag will look like this example....
</paramLevelMatches> </paramLevelMatches>
<imageStyle> <imageStyle>
<displayUnits>in</displayUnits> <displayUnits>in</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap> <defaultColormap>Grid/Gridded Data</defaultColormap>
<dataMapping> <dataMapping>
<entry displayValue='0.0' pixelValue='0'/> <entry displayValue='0.0' pixelValue='0'/>
<entry displayValue='2.0' pixelValue='17'/> <entry displayValue='2.0' pixelValue='17'/>

View file

@ -30,6 +30,8 @@ import javax.persistence.SequenceGenerator;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.NullUtil; import com.raytheon.uf.common.dataplugin.NullUtil;
import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.annotations.NullString; import com.raytheon.uf.common.dataplugin.annotations.NullString;
@ -60,6 +62,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* Aug 03, 2016 4360 rferrel Add name to unique constraint. * Aug 03, 2016 4360 rferrel Add name to unique constraint.
* Made datasetId, secondaryId, ensembleId, non-nullable. * Made datasetId, secondaryId, ensembleId, non-nullable.
* Now use EMPTY_STRING for null values and created static nullValue_ methods * Now use EMPTY_STRING for null values and created static nullValue_ methods
* Aug 03, 2018 7424 tjensen Add index to GridCoverage location
* *
* </pre> * </pre>
* *
@ -67,9 +70,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* @version 1.0 * @version 1.0
*/ */
@Entity @Entity
@Table(name = "grid_info", uniqueConstraints = { @UniqueConstraint(name = "uk_grid_info_datauri_fields", columnNames = { @Table(name = "grid_info", uniqueConstraints = {
"datasetid", "parameter_abbreviation", "level_id", "secondaryid", @UniqueConstraint(name = "uk_grid_info_datauri_fields", columnNames = {
"ensembleid", "location_id" }) }) "datasetid", "parameter_abbreviation", "level_id",
"secondaryid", "ensembleid", "location_id" }) })
@SequenceGenerator(name = "GRIDINFO_GENERATOR", sequenceName = "gridinfo_seq", allocationSize = 1) @SequenceGenerator(name = "GRIDINFO_GENERATOR", sequenceName = "gridinfo_seq", allocationSize = 1)
@DynamicSerialize @DynamicSerialize
public class GridInfoRecord extends PersistableDataObject<Integer> { public class GridInfoRecord extends PersistableDataObject<Integer> {
@ -109,6 +113,7 @@ public class GridInfoRecord extends PersistableDataObject<Integer> {
@ManyToOne(optional = false) @ManyToOne(optional = false)
@PrimaryKeyJoinColumn @PrimaryKeyJoinColumn
@DataURI(position = 3, converter = GridCoverageConverter.class) @DataURI(position = 3, converter = GridCoverageConverter.class)
@Index(name = "grid_info_location_id_index")
@DynamicSerializeElement @DynamicSerializeElement
private GridCoverage location; private GridCoverage location;

View file

@ -42,6 +42,7 @@ import com.raytheon.uf.common.style.level.SingleLevel;
* Jul 30, 2007 chammack Initial Creation. * Jul 30, 2007 chammack Initial Creation.
* May 01, 2014 DCS 027 MPorricelli Add WBZ level * May 01, 2014 DCS 027 MPorricelli Add WBZ level
* Aug 15, 2016 5821 bsteffen Add TROP level * Aug 15, 2016 5821 bsteffen Add TROP level
* May 18, 2018 20395 wkwock Add CBL and CLG level
* *
* </pre> * </pre>
* *
@ -86,6 +87,10 @@ public class GridLevelTranslator {
level = new SingleLevel(Level.LevelType.FRZ); level = new SingleLevel(Level.LevelType.FRZ);
} else if (levelType.equalsIgnoreCase("WBZ")) { } else if (levelType.equalsIgnoreCase("WBZ")) {
level = new SingleLevel(Level.LevelType.WBZ); level = new SingleLevel(Level.LevelType.WBZ);
} else if (levelType.equalsIgnoreCase("CBL")) {
level = new SingleLevel(Level.LevelType.CBL);
} else if (levelType.equalsIgnoreCase("CLG")) {
level = new SingleLevel(Level.LevelType.CLG);
} else { } else {
return new SingleLevel(Level.LevelType.DEFAULT); return new SingleLevel(Level.LevelType.DEFAULT);
} }

View file

@ -4978,4 +4978,61 @@ in | .03937 | 0 | 4 | | |..|8000F0FF| | 16 | \
</contourLabeling> </contourLabeling>
</contourStyle> </contourStyle>
</styleRule> </styleRule>
<styleRule>
<paramLevelMatches>
<parameter>LLWSHgt</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits label="hft">ft*100.0</displayUnits>
<contourLabeling labelSpacing="4" maxLabel="." minMaxLabelFormat="#0">
<values>5 10 15 20</values>
</contourLabeling>
</contourStyle>
</styleRule>
<styleRule>
<paramLevelMatches>
<singleLevel units="CBL" />
<parameter>CC</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits label="hft">ft*100.0</displayUnits>
<contourLabeling labelSpacing="4">
<values>0 1 2 6 10 20 31 100 200</values>
</contourLabeling>
</contourStyle>
</styleRule>
<styleRule>
<paramLevelMatches>
<singleLevel units="CLG" />
<parameter>CC</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits label="ft">ft</displayUnits>
<contourLabeling labelSpacing="6">
<values>0 100 200 600 1000 2000 3100 10000 20000</values>
</contourLabeling>
</contourStyle>
</styleRule>
<styleRule>
<paramLevelMatches>
<parameter>MIXHT</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits>m</displayUnits>
<contourLabeling labelSpacing="4">
<increment>1</increment>
</contourLabeling>
</contourStyle>
</styleRule>
<styleRule>
<paramLevelMatches>
<parameter>HTSGW</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits>ft</displayUnits>
<contourLabeling labelSpacing="4">
<increment>1</increment>
</contourLabeling>
</contourStyle>
</styleRule>
</styleRuleset> </styleRuleset>

View file

@ -24,3 +24,4 @@ Export-Package: com.raytheon.uf.common.dataplugin.satellite,
com.raytheon.uf.common.dataplugin.satellite.units.goes.convert, com.raytheon.uf.common.dataplugin.satellite.units.goes.convert,
com.raytheon.uf.common.dataplugin.satellite.units.ir, com.raytheon.uf.common.dataplugin.satellite.units.ir,
com.raytheon.uf.common.dataplugin.satellite.units.water com.raytheon.uf.common.dataplugin.satellite.units.water
Import-Package: com.raytheon.uf.common.status

View file

@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat; import javax.measure.unit.UnitFormat;
@ -38,10 +39,15 @@ import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataaccess.exception.InvalidIdentifiersException; import com.raytheon.uf.common.dataaccess.exception.InvalidIdentifiersException;
import com.raytheon.uf.common.dataaccess.impl.AbstractGridDataPluginFactory; import com.raytheon.uf.common.dataaccess.impl.AbstractGridDataPluginFactory;
import com.raytheon.uf.common.dataaccess.impl.DefaultGridData; import com.raytheon.uf.common.dataaccess.impl.DefaultGridData;
import com.raytheon.uf.common.dataaccess.util.DataWrapperUtil;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits; import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits;
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnitsUtil;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.data.UnitConvertingDataFilter;
import com.raytheon.uf.common.geospatial.util.SubGridGeometryCalculator;
import com.raytheon.uf.common.numeric.source.DataSource; import com.raytheon.uf.common.numeric.source.DataSource;
/** /**
@ -70,6 +76,8 @@ import com.raytheon.uf.common.numeric.source.DataSource;
* Aug 01, 2016 2416 tgurney Add dataURI as optional identifier * Aug 01, 2016 2416 tgurney Add dataURI as optional identifier
* Mar 06, 2017 6142 bsteffen Remove dataURI as optional identifier * Mar 06, 2017 6142 bsteffen Remove dataURI as optional identifier
* Aug 29, 2017 6389 bsteffen Ensure location names are unique. * Aug 29, 2017 6389 bsteffen Ensure location names are unique.
* Jul 31, 2018 6389 mapeters Override getDataSource() to handle unit
* conversion for GOES-R
* *
* </pre> * </pre>
* *
@ -223,6 +231,32 @@ public class SatelliteGridFactory extends AbstractGridDataPluginFactory {
return idValStrings.toArray(new String[idValues.length]); return idValStrings.toArray(new String[idValues.length]);
} }
@Override
protected DataSource getDataSource(PluginDataObject pdo,
SubGridGeometryCalculator subGrid) {
IDataRecord dataRecord = getDataRecord(pdo, subGrid);
if (dataRecord == null) {
return null;
}
// Get converter from data unit to record unit
Unit<?> recordUnit = SatelliteUnitsUtil
.getRecordUnit((SatelliteRecord) pdo);
if (recordUnit == null) {
recordUnit = Unit.ONE;
}
Unit<?> dataUnit = SatelliteUnitsUtil.getDataUnit(recordUnit,
dataRecord);
UnitConverter converter = dataUnit.getConverterTo(recordUnit);
// Construct unit-converting data source
DataSource dataSource = DataWrapperUtil
.constructArrayWrapper(dataRecord, false);
dataSource = UnitConvertingDataFilter.apply(dataSource, converter);
return dataSource;
}
protected static String generateLocationName( protected static String generateLocationName(
SatelliteRecord satelliteRecord) { SatelliteRecord satelliteRecord) {
StringBuilder locationName = new StringBuilder(32); StringBuilder locationName = new StringBuilder(32);

View file

@ -0,0 +1,146 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.satellite.units;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Map;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.goes.PolarPrecipWaterPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Utility class for dealing with satellite record units.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ------- ----------- -------------------------------------------
* Jul 31, 2018 6389 mapeters Initial creation (extracted from
* SatDataRetriever)
*
* </pre>
*
* @author mapeters
*/
public class SatelliteUnitsUtil {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(SatelliteUnitsUtil.class);
private static final String DMSP = "DMSP";
private static final String POES = "POES-NPOESS";
private static final String MISC = "Miscellaneous";
private static final String PRECIP = "Sounder Based Derived Precipitable Water (PW)";
/**
* Extracts the record units from the given satellite record
*
* @param record
* @return the record units
*/
public static Unit<?> getRecordUnit(SatelliteRecord record) {
Unit<?> recordUnit = null;
String physicalElement = record.getPhysicalElement();
if (record.getUnits() != null && !record.getUnits().isEmpty()) {
try {
recordUnit = UnitFormat.getUCUMInstance().parseProductUnit(
record.getUnits(), new ParsePosition(0));
} catch (ParseException e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to parse satellite units: " + record.getUnits(),
e);
}
}
if (physicalElement.equals(PRECIP)) {
String creatingEntity = record.getCreatingEntity();
if (creatingEntity.equals(DMSP) || creatingEntity.equals(POES)) {
recordUnit = new PolarPrecipWaterPixel();
} else if (creatingEntity.equals(MISC)) {
recordUnit = new BlendedTPWPixel();
}
}
return recordUnit;
}
/**
* Extracts the data units for the data record given the PDO's base unit
*
* @param recordUnit
* @param dataRecord
* @return
*/
public static Unit<?> getDataUnit(Unit<?> recordUnit,
IDataRecord dataRecord) {
Unit<?> units = recordUnit != null ? recordUnit : Unit.ONE;
Map<String, Object> attrs = dataRecord.getDataAttributes();
if (attrs != null) {
Number offset = (Number) attrs.get(SatelliteRecord.SAT_ADD_OFFSET);
Number scale = (Number) attrs.get(SatelliteRecord.SAT_SCALE_FACTOR);
if (offset != null) {
double offsetVal = offset.doubleValue();
if (offsetVal != 0.0) {
units = units.plus(offsetVal);
}
}
if (scale != null) {
double scaleVal = scale.doubleValue();
if (scaleVal != 0.0) {
units = units.times(scaleVal);
}
}
}
return units;
}
/**
* Determines whether or not the data within the given record is signed
*
* @param record
* @return whether or not record's data is signed
*/
public static boolean isSigned(IDataRecord record) {
Map<String, Object> attrs = record.getDataAttributes();
if (attrs != null) {
Boolean signed = (Boolean) attrs
.get(SatelliteRecord.SAT_SIGNED_FLAG);
if (signed != null && signed) {
return true;
}
}
return false;
}
}

View file

@ -21,7 +21,6 @@ package com.raytheon.uf.common.dataplugin.shef.tables;
// Generated Oct 17, 2008 2:22:17 PM by Hibernate Tools 3.2.2.GA // Generated Oct 17, 2008 2:22:17 PM by Hibernate Tools 3.2.2.GA
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverride;
@ -32,6 +31,8 @@ import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; import javax.persistence.Transient;
@ -52,16 +53,19 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* Aug 19, 2011 10672 jkorman Move refactor to new project * Aug 19, 2011 10672 jkorman Move refactor to new project
* Oct 07, 2013 2361 njensen Removed XML annotations * Oct 07, 2013 2361 njensen Removed XML annotations
* Sep 26, 2016 5631 bkowal Cleanup. * Sep 26, 2016 5631 bkowal Cleanup.
* Jul 25, 2018 5588 mapeters Added NamedQueries annotation
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
*/ */
@NamedQueries({
@NamedQuery(name = Dhrradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME, query = Dhrradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME_HQL) })
@Entity @Entity
@Table(name = "dhrradar") @Table(name = "dhrradar")
@DynamicSerialize @DynamicSerialize
public class Dhrradar extends PersistableDataObject<DhrradarId> public class Dhrradar extends PersistableDataObject<DhrradarId>
implements Serializable, IGriddedRadarRecord { implements IGriddedRadarRecord {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View file

@ -18,9 +18,6 @@
* further licensing information. * further licensing information.
**/ **/
package com.raytheon.uf.common.dataplugin.shef.tables; package com.raytheon.uf.common.dataplugin.shef.tables;
// default package
import java.io.Serializable;
// Generated Oct 17, 2008 2:22:17 PM by Hibernate Tools 3.2.2.GA // Generated Oct 17, 2008 2:22:17 PM by Hibernate Tools 3.2.2.GA
@ -34,12 +31,15 @@ import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.Transient; import javax.persistence.Transient;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/** /**
@ -55,16 +55,19 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* Aug 19, 2011 10672 jkorman Move refactor to new project * Aug 19, 2011 10672 jkorman Move refactor to new project
* Oct 07, 2013 2361 njensen Removed XML annotations * Oct 07, 2013 2361 njensen Removed XML annotations
* Nov 21, 2016 5588 nabowle Cleanup. * Nov 21, 2016 5588 nabowle Cleanup.
* Jul 25, 2018 5588 mapeters Added NamedQueries annotation
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
*/ */
@NamedQueries({
@NamedQuery(name = Dspradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME, query = Dspradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME_HQL) })
@Entity @Entity
@Table(name = "dspradar") @Table(name = "dspradar")
@com.raytheon.uf.common.serialization.annotations.DynamicSerialize @DynamicSerialize
public class Dspradar extends PersistableDataObject<DspradarId> public class Dspradar extends PersistableDataObject<DspradarId>
implements Serializable, IGriddedRadarRecord { implements IGriddedRadarRecord {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -287,6 +290,7 @@ public class Dspradar extends PersistableDataObject<DspradarId>
this.JEndTime = JEndTime; this.JEndTime = JEndTime;
} }
@Override
@Column(name = "mean_field_bias") @Column(name = "mean_field_bias")
public Short getMeanFieldBias() { public Short getMeanFieldBias() {
return this.meanFieldBias; return this.meanFieldBias;
@ -305,6 +309,7 @@ public class Dspradar extends PersistableDataObject<DspradarId>
this.sampleSize = sampleSize; this.sampleSize = sampleSize;
} }
@Override
@Column(name = "grid_filename", length = 20) @Column(name = "grid_filename", length = 20)
public String getGridFilename() { public String getGridFilename() {
return this.gridFilename; return this.gridFilename;

View file

@ -41,11 +41,12 @@ import com.raytheon.uf.common.ohd.AppsDefaults;
* May 13, 2016 5576 bkowal Updated to be more of a general utility for * May 13, 2016 5576 bkowal Updated to be more of a general utility for
* Apps_Defaults property conversions. * Apps_Defaults property conversions.
* Jun 13, 2016 5576 bkowal Added {@link #parallelExecEnabled()}. * Jun 13, 2016 5576 bkowal Added {@link #parallelExecEnabled()}.
* Jun 29, 2016 5576 bkowal Added a TODO explaning future steps. * Jun 29, 2016 5576 bkowal Added a todo explaining future steps.
* Jul 12, 2016 4619 bkowal Relocated to common. * Jul 12, 2016 4619 bkowal Relocated to common.
* Aug 10, 2016 4619 bkowal The parallel write flag is now a constant to * Aug 10, 2016 4619 bkowal The parallel write flag is now a constant to
* ensure it is not accidentally overwritten. * ensure it is not accidentally overwritten.
* Aug 07, 2017 6334 bkowal Directories are now created with 770 permissions and files 660. * Aug 07, 2017 6334 bkowal Directories are now created with 770 permissions and files 660.
* Jul 19, 2018 5588 mapeters Added {@link #getPathForTokenWithoutCreating(String)}
* *
* </pre> * </pre>
* *
@ -76,16 +77,18 @@ public final class AppsDefaultsConversionWrapper {
/** /**
* Retrieves a {@link Path} associated with an Apps_Defaults token. Will * Retrieves a {@link Path} associated with an Apps_Defaults token. Will
* also verify that that Path exists and make any required standard * also make any required standard modifications to the Path before
* modifications to the Path before returning it. * returning it.
*
* Note that the path will NOT be created if it doesn't exist. See
* {@link #getPathForToken(String)} if it should be created in this case.
* *
* @param token * @param token
* the specified Apps_Defaults token. * the specified Apps_Defaults token.
* @return the {@link Path} associated with the specified token. * @return the {@link Path} associated with the specified token, which may
* @throws AppsDefaultsPathException * not exist.
*/ */
public static Path getPathForToken(final String token) public static Path getPathForTokenWithoutCreating(final String token) {
throws AppsDefaultsPathException {
final String directory = AppsDefaults.getInstance().getToken(token); final String directory = AppsDefaults.getInstance().getToken(token);
if (directory == null) { if (directory == null) {
throw new IllegalArgumentException("No " + AppsDefaults.NAME throw new IllegalArgumentException("No " + AppsDefaults.NAME
@ -99,6 +102,29 @@ public final class AppsDefaultsConversionWrapper {
+ PARALLEL_DIRECTORY; + PARALLEL_DIRECTORY;
directoryPath = Paths.get(destinationRoot, destinationDirectory); directoryPath = Paths.get(destinationRoot, destinationDirectory);
} }
return directoryPath;
}
/**
* Retrieves a {@link Path} associated with an Apps_Defaults token. Will
* also make any required standard modifications to the Path before
* returning it.
*
* Note that the path will be created if it doesn't exist. See
* {@link #getPathForTokenWithoutCreating(String)} if it doesn't need to be
* created.
*
* @param token
* the specified Apps_Defaults token.
* @return the {@link Path} associated with the specified token, which is
* guaranteed to exist.
* @throws AppsDefaultsPathException
* if an I/O error occurs when trying to create the path
*/
public static Path getPathForToken(final String token)
throws AppsDefaultsPathException {
Path directoryPath = getPathForTokenWithoutCreating(token);
if (!Files.exists(directoryPath)) { if (!Files.exists(directoryPath)) {
try { try {
com.raytheon.uf.common.util.file.Files.createDirectories( com.raytheon.uf.common.util.file.Files.createDirectories(

View file

@ -9,6 +9,7 @@
<bean id="dhrDecodeSrv" class="com.raytheon.uf.edex.ohd.pproc.HPEDhrSrv" /> <bean id="dhrDecodeSrv" class="com.raytheon.uf.edex.ohd.pproc.HPEDhrSrv" />
<bean id="dhrGather" class="com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGather" /> <bean id="dhrGather" class="com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGather" />
<bean id="dspGather" class="com.raytheon.uf.edex.plugin.mpe.gather.dsp.DSPGather" />
<bean id="dhrDecoder" <bean id="dhrDecoder"
class="com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRDecoder" /> class="com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRDecoder" />
@ -21,10 +22,19 @@
<constructor-arg value="jms-durable:queue:Ingest.dhr" /> <constructor-arg value="jms-durable:queue:Ingest.dhr" />
</bean> </bean>
<camelContext id="nonClusteredDHRroutes" <bean id="dhrRadarServerDistRegistry" factory-bean="radarserverDistributionSrv"
factory-method="register">
<constructor-arg value="dhr" />
<constructor-arg value="jms-durable:queue:Ingest.dhr" />
</bean>
<!-- DHR and DSP files both come in from Ingest.dhr URI, and are then sent
to a single legacyDhrDspIngestRoute URI for legacy processing and
separate dxxIngestRoute URIs for Java processing (all handled below) -->
<camelContext id="nonClusteredDhrDspRoutes"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<!-- Begin non-clustered dhr Routes --> <!-- Begin non-clustered DHR/DSP Routes -->
<route id="dhrIngestFilter"> <route id="dhrDspIngestFilter">
<from uri="jms-durable:queue:Ingest.dhr" /> <from uri="jms-durable:queue:Ingest.dhr" />
<setHeader headerName="pluginName"> <setHeader headerName="pluginName">
<constant>dhr</constant> <constant>dhr</constant>
@ -44,25 +54,41 @@
</route> </route>
</camelContext> </camelContext>
<camelContext id="clusteredDHRroutes" <camelContext id="clusteredDhrDspRoutes"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<!-- Begin legacy dhr/dsp Routes -->
<route id="legacyDhrDspIngestRoute">
<from uri="jms-durable:queue:legacyDhrDspProcess" />
<doTry>
<pipeline>
<bean ref="serializationUtil" method="transformFromThrift" />
<bean ref="dhrDecodeSrv" method="legacyProcess" />
</pipeline>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:dhr?level=INFO" />
</doCatch>
</doTry>
</route>
<!-- Begin dhr Routes --> <!-- Begin dhr Routes -->
<route id="dhrIngestRoute"> <route id="dhrIngestRoute">
<from uri="jms-durable:queue:dhrProcess" /> <from uri="jms-durable:queue:dhrProcess" />
<doTry> <doTry>
<pipeline> <pipeline>
<bean ref="serializationUtil" method="transformFromThrift" />
<bean ref="dhrDecodeSrv" method="process" />
<filter> <filter>
<method ref="dhrGather" method="executeAllowed" /> <method ref="dhrGather" method="executeAllowed" />
<bean ref="serializationUtil" method="transformFromThrift" />
<filter>
<method ref="dhrDecodeSrv" method="prepareForGather" />
<filter> <filter>
<method ref="dhrGather" method="precipExists" /> <method ref="dhrGather" method="precipExists" />
<bean ref="dhrDecoder" method="execute" /> <bean ref="dhrDecoder" method="execute" />
<bean ref="dspDecoder" method="execute" />
<!-- TODO: this will eventually continue the route to HPE Field <!-- TODO: this will eventually continue the route to HPE Field
Gen --> Gen -->
</filter> </filter>
</filter> </filter>
</filter>
</pipeline> </pipeline>
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
@ -70,10 +96,35 @@
</doCatch> </doCatch>
</doTry> </doTry>
</route> </route>
<!-- Begin dsp Routes -->
<route id="dspIngestRoute">
<from uri="jms-durable:queue:dspProcess" />
<doTry>
<pipeline>
<filter>
<method ref="dspGather" method="executeAllowed" />
<bean ref="serializationUtil" method="transformFromThrift" />
<filter>
<method ref="dhrDecodeSrv" method="prepareForGather" />
<filter>
<method ref="dspGather" method="precipExists" />
<bean ref="dspDecoder" method="execute" />
<!-- TODO: this will eventually continue the route to HPE Field
Gen -->
</filter>
</filter>
</filter>
</pipeline>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:dsp?level=INFO" />
</doCatch>
</doTry>
</route>
</camelContext> </camelContext>
<bean factory-bean="contextManager" factory-method="registerClusteredContext"> <bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredDHRroutes" /> <constructor-arg ref="clusteredDhrDspRoutes" />
</bean> </bean>
</beans> </beans>

View file

@ -25,6 +25,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Path;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -44,6 +45,7 @@ import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig; import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.ohd.MainMethod; import com.raytheon.uf.edex.ohd.MainMethod;
import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGather;
/** /**
* Service implementation for decoding DHR radar files. * Service implementation for decoding DHR radar files.
@ -67,6 +69,9 @@ import com.raytheon.uf.edex.ohd.MainMethod;
* Jan 10, 2016 6058 bkowal Removed direct usage of the Java-based DHRGather. * Jan 10, 2016 6058 bkowal Removed direct usage of the Java-based DHRGather.
* Aug 02, 2017 6334 bkowal Write DHR/DSP gather files with the correct permissions. * Aug 02, 2017 6334 bkowal Write DHR/DSP gather files with the correct permissions.
* Aug 07, 2017 6334 bkowal Directories are now created with 770 permissions and files 660. * Aug 07, 2017 6334 bkowal Directories are now created with 770 permissions and files 660.
* Jul 19, 2018 5588 mapeters More fully separate legacy/java decode paths (e.g. use separate
* gather dirs), use separate JMS uris for DHR/DSP in java path
*
* *
* </pre> * </pre>
* *
@ -104,7 +109,11 @@ public class HPEDhrSrv {
private static final int DT_IDX = 2; private static final int DT_IDX = 2;
private static final String JMS_QUEUE_URI = "jms-durable:queue:dhrProcess"; private static final String DHR_JMS_QUEUE_URI = "jms-durable:queue:dhrProcess";
private static final String DSP_JMS_QUEUE_URI = "jms-durable:queue:dspProcess";
private static final String LEGACY_DHR_DSP_JMS_QUEUE_URI = "jms-durable:queue:legacyDhrDspProcess";
private final AppsDefaults appsDefaults = AppsDefaults.getInstance(); private final AppsDefaults appsDefaults = AppsDefaults.getInstance();
@ -127,27 +136,32 @@ public class HPEDhrSrv {
public static final String KSH = "ksh"; public static final String KSH = "ksh";
/** /**
* Route endpoint for "dhrIngestRoute". Takes a message, writes the file to * Route endpoint for "legacyDhrDspIngestRoute". Takes a message, writes the
* disk, and then runs the DHR data processing scripts so the file is * file to disk, and then runs the DHR data processing scripts so the file
* ingested. * is ingested. This is everything necessary for legacy processing of the
* given message.
* *
* @param message * @param message
* A <code>HPEDhrMessage</code> describing the DHR radar file to * A <code>HPEDhrMessage</code> describing the DHR radar file to
* be ingested. * be ingested.
*/ */
public void process(HPEDhrMessage message) { public void legacyProcess(HPEDhrMessage message) {
try { if (writeFile(message, true)) {
writeFile(message); runLegacyGatherScripts();
} catch (FileNotFoundException e) {
logger.handle(Priority.PROBLEM, "HPE cannot create output file.",
e);
return;
} catch (IOException e) {
logger.handle(Priority.PROBLEM,
"HPE Error writing updated contents of HPE file", e);
return;
} }
runGatherScripts(); }
/**
* Route endpoint for "dhrIngestRoute" and "dspIngestRoute". Takes a message
* and writes the file to disk so that it can be used by DHR/DSP Gather.
*
* @param message
* A <code>HPEDhrMessage</code> describing the DHR radar file to
* be ingested.
* @return true if the file was successfully written, false otherwise
*/
public boolean prepareForGather(HPEDhrMessage message) {
return writeFile(message, false);
} }
/** /**
@ -160,22 +174,26 @@ public class HPEDhrSrv {
* @param message * @param message
* A <code>HPEDhrMessage</code> describing the DHR radar file to * A <code>HPEDhrMessage</code> describing the DHR radar file to
* be ingested. * be ingested.
* @throws FileNotFoundException * @param legacy
* If the output file cannot be created or opened for any * whether to write the file to the legacy product dir or the
* reason. * Java-based product dir
* @throws IOException * @return true if the file was successfully written, false otherwise
* If an I/O error occurs while writing the file.
*/ */
private void writeFile(HPEDhrMessage message) private boolean writeFile(HPEDhrMessage message, boolean legacy) {
throws FileNotFoundException, IOException {
String dtype = message.getDtype(); String dtype = message.getDtype();
String outname = dtype + message.getRadarId() + "." + message.getDt(); String outname = dtype + message.getRadarId() + "." + message.getDt();
String dirToken = DHR.equals(dtype) ? DHR_PROD_DIR : DSP_PROD_DIR;
String outPath; String outPath;
if (dtype.equals(DHR)) { if (legacy) {
outPath = appsDefaults.getToken(DHR_PROD_DIR); outPath = appsDefaults.getToken(dirToken);
} else { } else {
outPath = appsDefaults.getToken(DSP_PROD_DIR); Path path = AppsDefaultsConversionWrapper
.getPathForTokenWithoutCreating(dirToken);
outPath = path.toAbsolutePath().toString();
} }
try {
File oP = new File(outPath); File oP = new File(outPath);
if (!oP.exists()) { if (!oP.exists()) {
com.raytheon.uf.common.util.file.Files.createDirectories( com.raytheon.uf.common.util.file.Files.createDirectories(
@ -192,12 +210,19 @@ public class HPEDhrSrv {
BufferedOutputStream bos = new BufferedOutputStream(os)) { BufferedOutputStream bos = new BufferedOutputStream(os)) {
bos.write(fileContents, offset, fileContents.length - offset); bos.write(fileContents, offset, fileContents.length - offset);
} }
return true;
} catch (FileNotFoundException e) {
logger.warn("HPE cannot create output file.", e);
} catch (IOException e) {
logger.warn("HPE Error writing updated contents of HPE file", e);
}
return false;
} }
/** /**
* Route endpoint for "dhrIngestFilter". Reads the given file to memory and * Route endpoint for "dhrDspIngestFilter". Reads the given file to memory
* determines whether or not this file is a DHR radar file. If it is, a * and determines whether or not this file is a DHR/DSP radar file. If it
* message is sent to a JMS queue so it is later ingested. * is, a message is sent to a JMS queue so it is later ingested.
* *
* @param fileContents * @param fileContents
* The radar file content * The radar file content
@ -239,8 +264,11 @@ public class HPEDhrSrv {
/** /**
* Takes the given parameters and constructs a <code>HPEDhrMessage</code> to * Takes the given parameters and constructs a <code>HPEDhrMessage</code> to
* be placed onto the queue used by <code>HPEDhrSrv</code> for actual data * be placed onto the appropriate queues used by <code>HPEDhrSrv</code> for
* processing. * actual data processing. If parallel exec is enabled, the file will be
* placed both on the legacy DHR/DSP queue, and the product-type-specific
* queue for Java processing. Otherwise, it will just be placed on the
* legacy queue.
* *
* @param data * @param data
* The contents of the radar file. * The contents of the radar file.
@ -261,13 +289,20 @@ public class HPEDhrSrv {
String dt) throws SerializationException, EdexException { String dt) throws SerializationException, EdexException {
HPEDhrMessage message = new HPEDhrMessage(data, radid, dtype, dt); HPEDhrMessage message = new HPEDhrMessage(data, radid, dtype, dt);
byte[] messageData = SerializationUtil.transformToThrift(message); byte[] messageData = SerializationUtil.transformToThrift(message);
EDEXUtil.getMessageProducer().sendAsyncUri(JMS_QUEUE_URI, messageData); EDEXUtil.getMessageProducer().sendAsyncUri(LEGACY_DHR_DSP_JMS_QUEUE_URI,
messageData);
if (AppsDefaultsConversionWrapper.parallelExecEnabled()) {
String jmsQueueUri = DHR.equals(dtype) ? DHR_JMS_QUEUE_URI
: DSP_JMS_QUEUE_URI;
EDEXUtil.getMessageProducer().sendAsyncUri(jmsQueueUri,
messageData);
}
} }
/** /**
* Runs the DSPgather and DHRgather data processing scripts. * Runs the DSPgather and DHRgather data processing scripts.
*/ */
private void runGatherScripts() { private void runLegacyGatherScripts() {
int exitValue = MainMethod.runProgram(KSH, int exitValue = MainMethod.runProgram(KSH,
appsDefaults.getToken(PPROC_BIN) + File.separatorChar appsDefaults.getToken(PPROC_BIN) + File.separatorChar
+ DSP_GATHER); + DSP_GATHER);

View file

@ -56,7 +56,6 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator;
* 02/01/13 1569 D. Hladky Added constants * 02/01/13 1569 D. Hladky Added constants
* 02/25/13 1660 D. Hladky Moved FFTI processing to help with mosaic memory usage * 02/25/13 1660 D. Hladky Moved FFTI processing to help with mosaic memory usage
* 01/10/14 2359 njensen Fix exception logging * 01/10/14 2359 njensen Fix exception logging
* 03/07/17 DR 11861 lshi FFMP use of QPF in Basin Table
* *
* </pre> * </pre>
* *
@ -344,7 +343,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null if (values.getGuids() != null
&& values.getQpes() != null) { && values.getQpes() != null) {
tempVal = FFMPUtils.getMaxRatioValue( tempVal = FFMPUtils.getMaxRatioValue(
values.getQpes(), null, values.getGuids()); values.getQpes(), values.getGuids());
} }
} else if (attribute.getAttributeName().equals( } else if (attribute.getAttributeName().equals(
FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) {
@ -352,7 +351,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null if (values.getGuids() != null
&& values.getQpes() != null) { && values.getQpes() != null) {
tempVal = FFMPUtils.getMaxDiffValue( tempVal = FFMPUtils.getMaxDiffValue(
values.getQpes(), null, values.getGuids()); values.getQpes(), values.getGuids());
} }
} }
@ -402,7 +401,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null if (values.getGuids() != null
&& values.getQpes() != null) { && values.getQpes() != null) {
val = FFMPUtils.getMaxRatioValue(values.getQpes(), null, val = FFMPUtils.getMaxRatioValue(values.getQpes(),
values.getGuids()); values.getGuids());
} }
@ -411,7 +410,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null if (values.getGuids() != null
&& values.getQpes() != null) { && values.getQpes() != null) {
val = FFMPUtils.getMaxDiffValue(values.getQpes(), null, val = FFMPUtils.getMaxDiffValue(values.getQpes(),
values.getGuids()); values.getGuids());
} }
} }

View file

@ -0,0 +1,65 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.plugin.mpe.gather;
import java.nio.ByteBuffer;
import com.raytheon.uf.edex.plugin.mpe.gather.radar.InvalidMpeRadarException;
import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarSymbologyData;
/**
* Extension of {@link MpeRadarSymbologyData} designed to only read the Radar
* Symbology data from an input file. Also handles the case when the Radar
* Symbology data cannot be found in the specified file.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 10, 2017 6058 bkowal Initial creation
* Jul 24, 2018 5588 mapeters Moved from com.raytheon.uf.edex.plugin.mpe.gather.dhr
*
* </pre>
*
* @author bkowal
*/
public final class MpePrecipCheckRadarSymbologyData
extends MpeRadarSymbologyData {
public boolean readPrecipIndicationParams(final ByteBuffer buf) {
try {
readPsmParams(buf);
} catch (InvalidMpeRadarException e) {
/*
* Apparently, there is a mixture of files with the proper structure
* and files without the proper structure in the DHR/DSP Gather file
* directories. So, if a file with the wrong structure is
* encountered, it will just be ignored to match the legacy
* implementation.
*/
return false;
}
return (getPsmParams() != null
&& getPsmParams().length > MpeRadarGatherConstants.DHR_PARAM_PRECIP);
}
}

View file

@ -0,0 +1,346 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.plugin.mpe.gather;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.common.dataplugin.shef.tables.Radarloc;
import com.raytheon.uf.common.mpe.util.AppsDefaultsConversionWrapper;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
import com.raytheon.uf.edex.plugin.mpe.dao.impl.RadarlocDao;
/**
* Replacement for the DHRgather and DSPgather scripts. Those scripts do not
* perform any file copying or moving (all commands that originally handled it
* have previously been commented out in the scripts). HPEDhrSrv already handles
* writing and/or moving the radar products it supports.
*
* This script has been setup to scan the DHR or DSP product directory for new
* files that have been added since its last run. The parameters will be checked
* in each file that is scanned to determine if the file includes precipitation
* data.
*
* Any time a DHR product that included precipitation was found by the legacy
* script, it would start and manage and monitor an external process for
* decoding of both DHR and DSP files. This external process would be allowed to
* run for a maximum of 20 minutes unless additional precipitation data was
* discovered. This caused DHR/DSP products to be decoded within that 20-minute
* window regardless of whether or not they had precipitation. However, this was
* done only for stability reasons (so that the decoding process wasn't
* starting/stopping continuously), as radar products without precipitation
* don't actually need to be decoded. Thus, this is not needed now that the
* process is on a camel route, so the 20-minute window and decoding products
* without precipitation have been removed in this implementation.
*
* Also, in the legacy implementation, only DHR products were checked for
* precipitation in order to determine when decoding of both DHR and DSP files
* should occur. With this new implementation, they are each checked separately
* to avoid timing issues and ensure that radar products with precipitation are
* correctly decoded.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 24, 2018 5588 mapeters Initial creation
*
* </pre>
*
* @author mapeters
*/
public abstract class MpeRadarGather {
protected final Logger logger = LoggerFactory.getLogger(getClass());
protected final String productType;
protected final String gatherDirToken;
protected final String clusterLockName;
protected final String clusterLockDetails;
protected MpeRadarGather(String productType, String gatherDir) {
this.productType = productType;
this.gatherDirToken = gatherDir;
this.clusterLockName = productType
+ MpeRadarGatherConstants.CLUSTER_LOCK_NAME_SUFFIX;
this.clusterLockDetails = productType
+ MpeRadarGatherConstants.CLUSTER_LOCK_DETAILS_SUFFIX;
}
public boolean precipExists() {
final Date currentRunDate = TimeUtil.newDate();
ITimer timer = TimeUtil.getTimer();
timer.start();
boolean precipFound = false;
logger.info("{} Gather has started ...", productType);
if (shouldExecute()) {
try {
precipFound = gather(currentRunDate);
} catch (Exception e) {
logger.warn(productType + " Gather failed.", e);
}
}
timer.stop();
logger.info("{} Gather has successfully finished in {}.", productType,
TimeUtil.prettyDuration(timer.getElapsedTime()));
return precipFound;
}
/**
* Determines if the Java version of MPE Radar Gather should be allowed to
* run/execute; dependent on whether or not parallel execution mode has been
* enabled.
*
* @return
*/
public boolean executeAllowed() {
return AppsDefaultsConversionWrapper.parallelExecEnabled();
}
/**
* MPE Radar Gather should only be executed when there is one or more radar
* in use. This method will determine if there is a sufficient number of
* radars in use.
*
* @return {@code true}, if there are a sufficient number of radars in use.
* {@code false}, otherwise.
*/
private boolean shouldExecute() {
final List<Radarloc> radarsInUse = new RadarlocDao()
.getInUseRadarlocs();
if (radarsInUse.isEmpty()) {
logger.info("No radars are in use. Halting {} Gather.",
productType);
return false;
}
logger.info("Found {} radars in use. {} Gather continuing ...",
radarsInUse.size(), productType);
return true;
}
private boolean gather(final Date currentRunDate) throws Exception {
/*
* Get the location of the Product Directory from Apps_Defaults.
*/
Path productDir = AppsDefaultsConversionWrapper
.getPathForTokenWithoutCreating(gatherDirToken);
if (!Files.exists(productDir)) {
/*
* If the directory does not exist, there are no products to
* process.
*/
logger.info(
"The {} Product directory: {} does not exist. Halting {} Gather.",
productType, productDir, productType);
return false;
}
/*
* The legacy DHRgather script used to place an empty file on the
* filesystem to determine when it last ran. The new version will use
* cluster locks.
*/
final ClusterTask clusterTask = ClusterLockUtils
.lookupLock(clusterLockName, clusterLockDetails);
Date lastRunDate = null;
if (clusterTask != null && clusterTask.getExtraInfo() != null) {
try {
lastRunDate = MpeRadarGatherConstants.lockDF.get()
.parse(clusterTask.getExtraInfo());
} catch (ParseException e) {
logger.error(
"Failed to parse the date: " + lastRunDate
+ "associated with the Cluster Lock. Resetting last run date.",
e);
}
}
if (lastRunDate == null) {
/*
* No previous record of when this Gather was last ran or this is
* the first time that Gather is running.
*/
storeCurrentRunDate(currentRunDate, false);
logger.info(
"First run of {} Gather. Successfully prepared for subsequent runs. Halting {} Gather.",
productType, productType);
return false;
}
/*
* Identify all product files that are newer than the last run date.
*/
final long lastRunDateMillis = lastRunDate.getTime();
final Set<Path> gatherFilesSet = new HashSet<>();
Files.walkFileTree(productDir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path,
BasicFileAttributes attrs) throws IOException {
final long modifiedTime = Files.getLastModifiedTime(path)
.toMillis();
if (modifiedTime >= lastRunDateMillis
&& modifiedTime < currentRunDate.getTime()) {
gatherFilesSet.add(path);
}
return FileVisitResult.CONTINUE;
}
});
if (gatherFilesSet.isEmpty()) {
logger.info(
"No {} products created on or after {} were found in the {} Product directory: {}. Halting {} Gather.",
productType, lastRunDate.toString(), productType,
productDir.toString(), productType);
storeCurrentRunDate(currentRunDate, true);
return false;
}
/*
* Determine if the start_hpe script should be started. TODO: this
* version of DHR/DSP Gather will not actually interact with the
* successor of start_hpe until it has been implemented in Java.
*/
boolean precipFound = false;
for (Path gatherFilePath : gatherFilesSet) {
try {
logger.info("Evaluating {} product: {} ...", productType,
gatherFilePath.toString());
MpePrecipCheckRadarSymbologyData radarSymData = new MpePrecipCheckRadarSymbologyData();
File f = gatherFilePath.toFile();
boolean hasPrecipParams;
try (FileInputStream fis = new FileInputStream(f);
FileChannel fc = fis.getChannel()) {
ByteBuffer byteBuffer = fc.map(MapMode.READ_ONLY, 0,
f.length());
hasPrecipParams = radarSymData
.readPrecipIndicationParams(byteBuffer);
}
if (!hasPrecipParams) {
/*
* The precipitation information was not present in the file
* that was checked. Remove this file.
*/
logger.info(
"Precipitation information not included in {} product: {}.",
productType, gatherFilePath);
deletePath(gatherFilePath);
continue;
}
final float param = radarSymData
.getPsmParams()[MpeRadarGatherConstants.DHR_PARAM_PRECIP];
/*
* This if/else statement used to be reversed based on the if
* statement in: get_dhrpsm/TEXT/main_DHRPsm.c starting on line
* 115, which made it appear that a param value > 0 indicated no
* precipitation and a value <= 0 indicated precipitation.
*
* However, DHRgather actually uses the PSM value printed in
* that C function (line 113) and not its return value, so a
* param value > 0 actually indicates precipitation.
*/
if (param > 0.0) {
logger.info("Precipitation was detected in {} product: {}.",
productType, gatherFilePath);
precipFound = true;
} else {
logger.info(
"Precipitation was NOT detected in {} product: {}.",
productType, gatherFilePath);
deletePath(gatherFilePath);
}
logger.info("{} product: {} evaluation complete.", productType,
gatherFilePath.toString());
} catch (Exception e) {
logger.error("Failed to load " + productType
+ " Radar product: " + gatherFilePath.toString()
+ ". Skipping file.", e);
}
}
// Clear the gather directory if no precipitation was found
if (!precipFound) {
logger.info(
"Removing all {} products in {} due to no precipitation.",
productType, productDir);
for (File file : productDir.toFile().listFiles()) {
if (!file.isFile()) {
// Skip non-files
continue;
}
deletePath(file.toPath());
}
}
storeCurrentRunDate(currentRunDate, true);
return precipFound;
}
private void deletePath(Path path) {
try {
Files.delete(path);
} catch (IOException e) {
logger.warn("Failed to delete " + productType + " product: " + path,
e);
}
}
private void storeCurrentRunDate(final Date currentRunDate,
final boolean update) {
final String extraInfo = MpeRadarGatherConstants.lockDF.get()
.format(currentRunDate);
if (update) {
ClusterLockUtils.updateExtraInfo(clusterLockName,
clusterLockDetails, extraInfo);
} else {
ClusterLockUtils.lock(clusterLockName, clusterLockDetails,
extraInfo, 30, true);
}
}
}

View file

@ -0,0 +1,76 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.plugin.mpe.gather;
import java.text.SimpleDateFormat;
/**
* Common, centralized declaration of constants that will be utilized by
* {@link MpeRadarGather}s.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 30, 2016 4625 bkowal Initial creation
* Jul 24, 2018 5588 mapeters Added some constants for addition of DSPGather, refactored from
* com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants
*
* </pre>
*
* @author bkowal
*/
public class MpeRadarGatherConstants {
private static final String LOCK_DATE_FORMAT = "MM-dd-yyy HH:mm";
public static final ThreadLocal<SimpleDateFormat> lockDF = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
SimpleDateFormat sdf = new SimpleDateFormat(LOCK_DATE_FORMAT);
return sdf;
}
};
public static final String CLUSTER_LOCK_NAME_SUFFIX = "GatherLock";
public static final String CLUSTER_LOCK_DETAILS_SUFFIX = "Gather";
public static final String DHR_PRODUCT_TYPE = "DHR";
public static final String DSP_PRODUCT_TYPE = "DSP";
public static final int DHR_DEFAULT_VERSION = 8;
public static final int DHR_PARAM_PRECIP = 4;
public static class AppsDefaults {
public static final String DHR_PROD_DIR = "dhr_prod_dir";
public static final String DSP_PROD_DIR = "dsp_prod_dir";
}
private MpeRadarGatherConstants() {
}
}

View file

@ -19,52 +19,11 @@
**/ **/
package com.raytheon.uf.edex.plugin.mpe.gather.dhr; package com.raytheon.uf.edex.plugin.mpe.gather.dhr;
import java.io.File; import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGather;
import java.io.FileInputStream; import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGatherConstants;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.common.dataplugin.shef.tables.Radarloc;
import com.raytheon.uf.common.mpe.util.AppsDefaultsConversionWrapper;
import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
import com.raytheon.uf.edex.plugin.mpe.dao.impl.RadarlocDao;
/** /**
* Replacement for the DHRgather script. The DHRgather script does not perform * Replacement for the DHRgather script.
* any file copying or moving (all commands that originally handled it have
* previously been commented out in the script). {@link HPEDhrSrv} already
* handles writing and/or moving the radar products it supports.
*
* This script has been setup to scan the DHR product directory for new files
* that have been added since its last run. The parameters will be checked in
* each file that is scanned to determine if the file includes precipitation
* data.
*
* Any time a radar product that included precipitation was found by the legacy
* script, it would start and manage and monitor an external process. This
* external process would be allowed to run for a maximum of 20 minutes unless
* additional precipitation data was discovered. That implementation will remain
* as part of the legacy implementation.
* *
* <pre> * <pre>
* *
@ -76,220 +35,18 @@ import com.raytheon.uf.edex.plugin.mpe.dao.impl.RadarlocDao;
* Nov 22, 2016 5588 nabowle Check PSM param for precipitation. * Nov 22, 2016 5588 nabowle Check PSM param for precipitation.
* Jan 10, 2016 6058 bkowal Silently ignore invalid DHR input files. Do not fully * Jan 10, 2016 6058 bkowal Silently ignore invalid DHR input files. Do not fully
* read an entire file just to check for precip. * read an entire file just to check for precip.
* Jul 24, 2018 5588 mapeters Fix determination of whether DHR product has precip,
* account for legacy/java decode paths using separate
* gather dirs, abstracted out to {@link MpeRadarGather}
* *
* </pre> * </pre>
* *
* @author bkowal * @author bkowal
*/ */
public class DHRGather extends MpeRadarGather {
public class DHRGather { public DHRGather() {
super(MpeRadarGatherConstants.DHR_PRODUCT_TYPE,
private final Logger logger = LoggerFactory.getLogger(getClass()); MpeRadarGatherConstants.AppsDefaults.DHR_PROD_DIR);
public boolean precipExists() {
final Date currentRunDate = TimeUtil.newDate();
ITimer timer = TimeUtil.getTimer();
timer.start();
boolean precipFound = false;
logger.info("DHRGather has started ...");
if (shouldExecute()) {
try {
precipFound = gather(currentRunDate);
} catch (Exception e) {
logger.warn("Gather failed. ", e);
}
}
timer.stop();
logger.info("DHRGather has successfully finished in {}.",
TimeUtil.prettyDuration(timer.getElapsedTime()));
return precipFound;
}
/**
* Determines if the Java version of DHR Gather should be allowed to
* run/execute; dependent on whether or not parallel execution mode has been
* enabled.
*
* @return
*/
public boolean executeAllowed() {
return AppsDefaultsConversionWrapper.parallelExecEnabled();
}
/**
* {@link DHRGather} should only be executed when there is one or more radar
* in use. This method will determine if there is a sufficient number of
* radars in use.
*
* @return {@code true}, if there are a sufficient number of radars in use.
* {@code false}, otherwise.
*/
private boolean shouldExecute() {
final List<Radarloc> radarsInUse = new RadarlocDao()
.getInUseRadarlocs();
if (radarsInUse.isEmpty()) {
logger.info("No radars are in use. Halting DHR Gather.");
return false;
}
logger.info("Found {} radars in use. DHR Gather continuing ...",
radarsInUse.size());
return true;
}
private boolean gather(final Date currentRunDate) throws Exception {
/*
* Get the location of the DHR Product Directory from Apps_Defaults.
*/
final String dhrProdDir = AppsDefaults.getInstance()
.getToken(DHRGatherConstants.AppsDefaults.DHR_PROD_DIR, null);
if (dhrProdDir == null) {
throw new DHRGatherFailedException(
"Failed to retrieve the DHR Product directory from "
+ AppsDefaults.NAME + ". Please verify that the '"
+ DHRGatherConstants.AppsDefaults.DHR_PROD_DIR
+ "' property has been defined.");
}
Path dhrProductPath = Paths.get(dhrProdDir);
if (!Files.exists(dhrProductPath)) {
/*
* If the directory does not exist, there are not any dhr products
* to process.
*/
logger.info(
"The DHR Product directory: {} does not exist. Halting DHR Gather.",
dhrProductPath.toString());
return false;
}
/*
* The legacy DHRgather script used to place an empty file on the
* filesystem to determine when it last ran. The new version will use
* cluster locks.
*/
final ClusterTask clusterTask = ClusterLockUtils.lookupLock(
DHRGatherConstants.CLUSTER_LOCK_NAME,
DHRGatherConstants.CLUSTER_LOCK_DETAILS);
Date lastRunDate = null;
if (clusterTask != null && clusterTask.getExtraInfo() != null) {
try {
lastRunDate = DHRGatherConstants.lockDF.get()
.parse(clusterTask.getExtraInfo());
} catch (ParseException e) {
logger.error(
"Failed to parse the date: " + lastRunDate
+ "associated with the Cluster Lock. Resetting last run date.",
e);
}
}
if (lastRunDate == null) {
/*
* No previous record of when DHRGather was last ran or this is the
* first time that DHRGather is running.
*/
storeCurrentRunDate(currentRunDate, false);
logger.info(
"First run of DHR Gather. Successfully prepared for subsequent runs. Halting DHR Gather.");
return false;
}
/*
* Identify all DHR product files that are newer than the last run date.
*/
final long lastRunDateMillis = lastRunDate.getTime();
final Set<Path> gatherFilesSet = new HashSet<>();
Files.walkFileTree(dhrProductPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path,
BasicFileAttributes attrs) throws IOException {
final long modifiedTime = Files.getLastModifiedTime(path)
.toMillis();
if (modifiedTime >= lastRunDateMillis
&& modifiedTime < currentRunDate.getTime()) {
gatherFilesSet.add(path);
}
return FileVisitResult.CONTINUE;
}
});
if (gatherFilesSet.isEmpty()) {
logger.info(
"No DHR products created on or after {} were found in the DHR Product directory: {}. Halting DHR Gather.",
lastRunDate.toString(), dhrProductPath.toString());
storeCurrentRunDate(currentRunDate, true);
return false;
}
/*
* Determine if the start_hpe script should be started. TODO: this
* version of DHR Gather will not actually interact with the successor
* of start_hpe until it has been implemented in Java.
*/
boolean precipFound = false;
for (Path gatherFilePath : gatherFilesSet) {
try {
logger.info("Evaluating DHR product: {} ...",
gatherFilePath.toString());
MpePrecipCheckRadarSymbologyData radarSymData = new MpePrecipCheckRadarSymbologyData();
File f = gatherFilePath.toFile();
try (FileInputStream fis = new FileInputStream(f);
FileChannel fc = fis.getChannel()) {
ByteBuffer byteBuffer = fc.map(MapMode.READ_ONLY, 0,
f.length());
if (!radarSymData.readPrecipIndicationParams(byteBuffer)) {
/*
* The precipitation information was not present in the
* file that was checked. Silently skip this file.
*/
continue;
}
}
final float param = radarSymData
.getPsmParams()[DHRGatherConstants.DHR_PARAM_PRECIP];
/*
* This if statement is based on the if statement in:
* get_dhrpsm/TEXT/main_DHRPsm.c starting on line 115. A param
* value > 0 indicated no precipitation and a value <= 0
* indicated precipitation.
*/
if (param > 0.0) {
logger.info(
"Precipitation was NOT detected in DHR product: {}.",
gatherFilePath.toString());
} else {
logger.info(
"Precipitation was detected in DHR product: {}.",
gatherFilePath.toString());
precipFound = true;
break;
}
logger.info("DHR product: {} evaluation complete.",
gatherFilePath.toString());
} catch (Exception e) {
logger.error("Failed to load DHR Radar product: "
+ gatherFilePath.toString() + ". Skipping file.", e);
}
}
storeCurrentRunDate(currentRunDate, true);
return precipFound;
}
private void storeCurrentRunDate(final Date currentRunDate,
final boolean update) {
final String extraInfo = DHRGatherConstants.lockDF.get()
.format(currentRunDate);
if (update) {
ClusterLockUtils.updateExtraInfo(
DHRGatherConstants.CLUSTER_LOCK_NAME,
DHRGatherConstants.CLUSTER_LOCK_DETAILS, extraInfo);
} else {
ClusterLockUtils.lock(DHRGatherConstants.CLUSTER_LOCK_NAME,
DHRGatherConstants.CLUSTER_LOCK_DETAILS, extraInfo, 30,
true);
}
} }
} }

View file

@ -48,6 +48,8 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarInputException;
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Dec 14, 2016 5588 nabowle Fix negative values. Round to 3 decimals * Dec 14, 2016 5588 nabowle Fix negative values. Round to 3 decimals
* to match legacy. * to match legacy.
* Jul 19, 2018 5588 mapeters Change rounding to truncating to match
* legacy
* *
* </pre> * </pre>
* *
@ -56,7 +58,11 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarInputException;
public class DSPDecoder extends MpeRadarDecoder<DSPRadarFile> { public class DSPDecoder extends MpeRadarDecoder<DSPRadarFile> {
private static final float ROUND_FACTOR = 1000F; /**
* The factor that determines the number of decimal places to truncate the
* data values to (1000 = 3 decimal places).
*/
private static final float TRUNCATE_FACTOR = 1000F;
private DspradarDao radarDao = new DspradarDao(); private DspradarDao radarDao = new DspradarDao();
@ -120,14 +126,14 @@ public class DSPDecoder extends MpeRadarDecoder<DSPRadarFile> {
for (int j = 0; j < MpeRadarDecodeConstants.MAX_JHRAP; j++) { for (int j = 0; j < MpeRadarDecodeConstants.MAX_JHRAP; j++) {
for (int i = 0; i < MpeRadarDecodeConstants.MAX_IHRAP; i++) { for (int i = 0; i < MpeRadarDecodeConstants.MAX_IHRAP; i++) {
ledos.writeFloat(roundFloat(data[j][i])); ledos.writeFloat(truncateFloat(data[j][i]));
} }
} }
} }
} }
private float roundFloat(float f) { private float truncateFloat(float f) {
return Math.round(f * ROUND_FACTOR) / ROUND_FACTOR; return (int) (f * TRUNCATE_FACTOR) / TRUNCATE_FACTOR;
} }
@Override @Override

View file

@ -0,0 +1,46 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.plugin.mpe.gather.dsp;
import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGather;
import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGatherConstants;
/**
* Replacement for the DSPgather script.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 24, 2018 5588 mapeters Initial creation
*
* </pre>
*
* @author mapeters
*/
public class DSPGather extends MpeRadarGather {
protected DSPGather() {
super(MpeRadarGatherConstants.DSP_PRODUCT_TYPE,
MpeRadarGatherConstants.AppsDefaults.DSP_PROD_DIR);
}
}

View file

@ -36,6 +36,7 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarProductDescription;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Jul 19, 2018 5588 mapeters Fix parsing of maxPrecipValue
* *
* </pre> * </pre>
* *
@ -44,8 +45,6 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarProductDescription;
public class DSPProductDescription extends MpeRadarProductDescription { public class DSPProductDescription extends MpeRadarProductDescription {
private static final float PRECIP_DIVIDEND = 10.0f;
private static final class DSPDescriptionIndices { private static final class DSPDescriptionIndices {
public static final int START_DATE_INDEX = 17; public static final int START_DATE_INDEX = 17;
@ -56,7 +55,7 @@ public class DSPProductDescription extends MpeRadarProductDescription {
public static final int DATA_LVL_SCALE_INDEX = 22; public static final int DATA_LVL_SCALE_INDEX = 22;
public static final int MAX_PRECIP_INDEX = 21; public static final int MAX_PRECIP_INDEX = 37;
} }
private Calendar startDateTime; private Calendar startDateTime;
@ -71,7 +70,8 @@ public class DSPProductDescription extends MpeRadarProductDescription {
private short julianBeginTime; private short julianBeginTime;
public DSPProductDescription(ByteBuffer buf) throws InvalidMpeRadarException { public DSPProductDescription(ByteBuffer buf)
throws InvalidMpeRadarException {
super(buf); super(buf);
} }
@ -84,8 +84,7 @@ public class DSPProductDescription extends MpeRadarProductDescription {
(short) (julianBeginTime / TimeUtil.SECONDS_PER_MINUTE)); (short) (julianBeginTime / TimeUtil.SECONDS_PER_MINUTE));
minDataLevel = data[DSPDescriptionIndices.MIN_DATA_LVL_INDEX]; minDataLevel = data[DSPDescriptionIndices.MIN_DATA_LVL_INDEX];
dataLevelScaleFactor = data[DSPDescriptionIndices.DATA_LVL_SCALE_INDEX]; dataLevelScaleFactor = data[DSPDescriptionIndices.DATA_LVL_SCALE_INDEX];
maxPrecipValue = data[DSPDescriptionIndices.MAX_PRECIP_INDEX] maxPrecipValue = data[DSPDescriptionIndices.MAX_PRECIP_INDEX];
/ PRECIP_DIVIDEND;
} }
/** /**

View file

@ -41,6 +41,7 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarSymbologyData;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Jul 24, 2018 5588 mapeters Use MpeRadarFile.BUILD_VERSION_5 constant
* *
* </pre> * </pre>
* *
@ -122,7 +123,7 @@ public class DSPRadarFile extends MpeRadarFile<DSPProductDescription> {
adapt.setMaxZrefl(params[i++]); adapt.setMaxZrefl(params[i++]);
adapt.setMinBirng(params[i++]); adapt.setMinBirng(params[i++]);
if (getVersion() == 5) { if (getVersion() == MpeRadarFile.BUILD_VERSION_5) {
adapt.setMaxStmspd(params[i++]); adapt.setMaxStmspd(params[i++]);
adapt.setMaxTimdif(params[i++]); adapt.setMaxTimdif(params[i++]);
adapt.setMinArtcon(params[i++]); adapt.setMinArtcon(params[i++]);

View file

@ -22,7 +22,7 @@ package com.raytheon.uf.edex.plugin.mpe.gather.radar;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants; import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGatherConstants;
/** /**
* Constants for decoding DHR and DSP files. Based on * Constants for decoding DHR and DSP files. Based on
@ -35,6 +35,7 @@ import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Jul 18, 2018 5588 mapeters Fix DSP dir constants
* *
* </pre> * </pre>
* *
@ -44,13 +45,13 @@ import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants;
public class MpeRadarDecodeConstants { public class MpeRadarDecodeConstants {
public static class AppsDefaults { public static class AppsDefaults {
public static final String DSP_GRID_DIR = "dhr_grid_dir"; public static final String DSP_GRID_DIR = "dsp_grid_dir";
public static final String DSP_PROD_DIR = "dhr_prod_dir"; public static final String DSP_PROD_DIR = "dsp_prod_dir";
public static final String DHR_GRID_DIR = "dhr_grid_dir"; public static final String DHR_GRID_DIR = "dhr_grid_dir";
public static final String DHR_PROD_DIR = DHRGatherConstants.AppsDefaults.DHR_PROD_DIR; public static final String DHR_PROD_DIR = MpeRadarGatherConstants.AppsDefaults.DHR_PROD_DIR;
} }
public static final ThreadLocal<SimpleDateFormat> filenameDateFormat = TimeUtil public static final ThreadLocal<SimpleDateFormat> filenameDateFormat = TimeUtil
@ -129,7 +130,7 @@ public class MpeRadarDecodeConstants {
public static final int SHORT_BYTES = 2; public static final int SHORT_BYTES = 2;
public static final int DEFAULT_BUILD_VERSION = DHRGatherConstants.DHR_DEFAULT_VERSION; public static final int DEFAULT_BUILD_VERSION = MpeRadarGatherConstants.DHR_DEFAULT_VERSION;
private MpeRadarDecodeConstants() { private MpeRadarDecodeConstants() {
} }

View file

@ -42,6 +42,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Dec 14, 2015 5588 nabowle Fix caching. * Dec 14, 2015 5588 nabowle Fix caching.
* Jul 19, 2018 5588 mapeters Reverse lat/lon in Coordinates so
* lon=x and lat=y
* *
* </pre> * </pre>
* *
@ -81,7 +83,7 @@ public class MpeRadarDecodeUtils {
public static void buildLookupTable(int radLat, int radLon, public static void buildLookupTable(int radLat, int radLon,
int[][] quarterHrapToRadarAzimuth, int[][] quarterHrapToRadarAzimuth,
int[][] quarterHrapToRadarRange) { int[][] quarterHrapToRadarRange) {
Coordinate coord = new Coordinate(radLat, radLon); Coordinate coord = new Coordinate(radLon, radLat);
SoftReference<int[][][]> cachedRef = lookupCache.get(coord); SoftReference<int[][][]> cachedRef = lookupCache.get(coord);
if (cachedRef != null) { if (cachedRef != null) {
int[][][] cachedTable = cachedRef.get(); int[][][] cachedTable = cachedRef.get();

View file

@ -25,8 +25,6 @@ import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import javax.xml.bind.JAXBException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -36,7 +34,6 @@ import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException; import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.mpe.util.AppsDefaultsConversionWrapper; import com.raytheon.uf.common.mpe.util.AppsDefaultsConversionWrapper;
import com.raytheon.uf.common.mpe.util.AppsDefaultsPathException; import com.raytheon.uf.common.mpe.util.AppsDefaultsPathException;
import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.serialization.SingleTypeJAXBManager; import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
@ -56,6 +53,8 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Dec 01, 2016 5588 nabowle Initial creation * Dec 01, 2016 5588 nabowle Initial creation
* Dec 16, 2016 5588 nabowle Throw exceptions for invalid azimuth and range. * Dec 16, 2016 5588 nabowle Throw exceptions for invalid azimuth and range.
* Jul 19, 2018 5588 mapeters Account for legacy/java decode paths using separate
* gather dirs
* *
* </pre> * </pre>
* *
@ -63,7 +62,9 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
*/ */
public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> { public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
private static SingleTypeJAXBManager<MpeRadarDecoderConfig> jaxb;
private static final SingleTypeJAXBManager<MpeRadarDecoderConfig> JAXB = SingleTypeJAXBManager
.createWithoutException(MpeRadarDecoderConfig.class);
private volatile boolean initialized; private volatile boolean initialized;
@ -127,14 +128,14 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
"Unable to retrieve the grid dir.", e); "Unable to retrieve the grid dir.", e);
} }
String prodDir = AppsDefaults.getInstance() Path prodDir = AppsDefaultsConversionWrapper
.getToken(this.appsDefaultProductDir, null); .getPathForTokenWithoutCreating(this.appsDefaultProductDir);
File productDir = new File(prodDir); if (!Files.exists(prodDir)) {
if (!Files.exists(productDir.toPath())) {
throw new MpeRadarDecodeException( throw new MpeRadarDecodeException(
"Unable to retrieve the product dir."); "Unable to retrieve the product dir.");
} }
File productDir = prodDir.toFile();
File[] files = productDir.listFiles(); File[] files = productDir.listFiles();
for (File file : files) { for (File file : files) {
if (!file.isFile()) { if (!file.isFile()) {
@ -148,17 +149,10 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
radarFile = loadRadarFile(path, radarFile = loadRadarFile(path,
MpeRadarDecodeConstants.DEFAULT_BUILD_VERSION); MpeRadarDecodeConstants.DEFAULT_BUILD_VERSION);
} catch (MpeRadarInputException e) { } catch (MpeRadarInputException e) {
if (AppsDefaultsConversionWrapper.parallelExecEnabled()) {
logger.info(
"{} would be deleted because it is not a valid radar file.",
path, e);
} else {
logger.info( logger.info(
"{} will be deleted because it is not a valid radar file.", "{} will be deleted because it is not a valid radar file.",
path, e); path, e);
file.delete(); file.delete();
}
continue; continue;
} }
@ -175,6 +169,9 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
if (this.writeToDb) { if (this.writeToDb) {
writeRadarRecords(radarFile); writeRadarRecords(radarFile);
} }
// Successfully processed, delete the temp file
file.delete();
} }
} }
@ -206,17 +203,8 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
return; return;
} }
if (jaxb == null) {
try {
jaxb = new SingleTypeJAXBManager<>(MpeRadarDecoderConfig.class);
} catch (JAXBException e) {
logger.error("Unable to initialize the JAXB Manager.", e);
return;
}
}
try (InputStream is = localizationFile.openInputStream()) { try (InputStream is = localizationFile.openInputStream()) {
MpeRadarDecoderConfig config = jaxb.unmarshalFromInputStream(is); MpeRadarDecoderConfig config = JAXB.unmarshalFromInputStream(is);
this.writeToDb = config.getWriteToDB(); this.writeToDb = config.getWriteToDB();
logger.debug("Configuration from {} has been read.", logger.debug("Configuration from {} has been read.",
this.configFile); this.configFile);

View file

@ -39,6 +39,7 @@ import java.util.regex.Pattern;
* Nov 22, 2016 5588 nabowle Initial creation * Nov 22, 2016 5588 nabowle Initial creation
* Jan 10, 2016 6058 bkowal Updated to allow extracting only the symbology * Jan 10, 2016 6058 bkowal Updated to allow extracting only the symbology
* from a radar data file. * from a radar data file.
* Jul 19, 2018 5588 mapeters Fix readParams() ignoring the last param
* *
* </pre> * </pre>
* *
@ -153,7 +154,7 @@ public class MpeRadarSymbologyData {
private void readParams(final ByteBuffer buf, float[] paramArray, private void readParams(final ByteBuffer buf, float[] paramArray,
String parameterType) throws InvalidMpeRadarException { String parameterType) throws InvalidMpeRadarException {
String paramStr; String paramStr;
for (int i = 0; i < paramArray.length - 1; i++) { for (int i = 0; i < paramArray.length; i++) {
paramStr = readNextParamString(buf); paramStr = readNextParamString(buf);
if (paramStr.isEmpty()) { if (paramStr.isEmpty()) {
paramArray[i] = EMPTY_PARAM; paramArray[i] = EMPTY_PARAM;