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.dataplugin.PluginDataObject;
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.FFMPGap;
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceBasin;
@ -209,9 +208,8 @@ import com.vividsolutions.jts.geom.Point;
* Sep 14, 2016 3241 bsteffen Update deprecated JTSCompiler method calls
* Jan 23, 2017 6032 njensen Implement IExtraTextGeneratingResource
* 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
* opening basin trend graphs
* opening basin trend graphs
*
* </pre>
*
@ -1930,24 +1928,16 @@ public class FFMPResource
List<Long> pfafs) {
float qpe = 0.0f;
float guid = 0.0f;
Float qpf = null;
float guid = 0.0f;
float diff = Float.NaN;
String ffgType = getFFGName();
FFMPRecord qpfRecord = this.getQpfRecord(getPaintTime().getRefTime());
FFMPBasinData qpfBasin = null;
if (qpfRecord != null) {
qpfBasin = qpfRecord.getBasinData();
}
try {
if (aggregate) {
if (isWorstCase()) {
List<Float> qpes = null;
List<Float> guids = null;
List<Float> qpfs = null;
if ((getQpeRecord() != null)
&& (getGuidanceRecord() != null)) {
qpes = getQpeRecord().getBasinData().getAccumValues(
@ -1959,12 +1949,9 @@ public class FFMPResource
getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType));
}
if (qpfBasin != null) {
qpfs = qpfBasin.getAccumValues(pfafs, getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
if ((qpes != null) && (guids != null)) {
diff = FFMPUtils.getMaxDiffValue(qpes, qpfs, guids);
diff = FFMPUtils.getMaxDiffValue(qpes, guids);
}
} else {
if ((getQpeRecord() != null)
@ -1979,15 +1966,8 @@ public class FFMPResource
.getAverageGuidanceValue(pfafs,
getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType));
if (qpfBasin != null) {
qpf = qpfBasin.getAccumAverageValue(pfafs,
getTableTime(), recentTime,
getQpfSourceExpiration(), getResourceData()
.getPrimarySourceXML().isRate());
}
diff = FFMPUtils.getDiffValue(qpe, qpf, guid);
diff = FFMPUtils.getDiffValue(qpe, guid);
}
}
} else {
@ -2003,12 +1983,8 @@ public class FFMPResource
guid = forceValue(pfafs,
getBasin(key, getField(), recentTime, aggregate),
guid);
if (qpfBasin != null) {
qpf = qpfBasin.get(key).getAccumValue(getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
diff = FFMPUtils.getDiffValue(qpe, qpf, guid);
diff = FFMPUtils.getDiffValue(qpe, guid);
}
}
} catch (Exception e) {
@ -2029,22 +2005,15 @@ public class FFMPResource
float qpe = 0.0f;
float guid = 0.0f;
Float qpf = null;
float ratio = Float.NaN;
String ffgType = getFFGName();
FFMPRecord qpfRecord = this.getQpfRecord(getPaintTime().getRefTime());
FFMPBasinData qpfBasin = null;
if (qpfRecord != null) {
qpfBasin = qpfRecord.getBasinData();
}
try {
if (aggregate) {
if (isWorstCase()) {
List<Float> qpes = null;
List<Float> guids = null;
List<Float> qpfs = null;
List<Float> guids = null;
if (getQpeRecord() != null) {
qpes = getQpeRecord().getBasinData().getAccumValues(
pfafs, getTableTime(), recentTime,
@ -2056,13 +2025,9 @@ public class FFMPResource
getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType));
}
if (qpfBasin != null) {
qpfs = qpfBasin.getAccumValues(pfafs, getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
if ((qpes != null) && (guids != null)) {
ratio = FFMPUtils.getMaxRatioValue(qpes, qpfs, guids);
ratio = FFMPUtils.getMaxRatioValue(qpes, guids);
}
} else {
if ((getQpeRecord() != null)
@ -2077,15 +2042,7 @@ public class FFMPResource
.getAverageGuidanceValue(pfafs,
getGuidanceInterpolation(ffgType),
getGuidSourceExpiration(ffgType));
if (qpfBasin != null) {
qpf = qpfBasin.getAccumAverageValue(pfafs,
getTableTime(), recentTime,
getQpfSourceExpiration(), getResourceData()
.getPrimarySourceXML().isRate());
}
ratio = FFMPUtils.getRatioValue(qpe, qpf, guid);
}
}
} else {
@ -2097,14 +2054,8 @@ public class FFMPResource
(FFMPGuidanceBasin) getGuidanceRecord()
.getBasinData().get(key),
recentTime, ffgType);
qpf = null;
if (qpfBasin != null) {
qpf = qpfBasin.get(key).getAccumValue(getTableTime(),
recentTime, getQpfSourceExpiration(), isRate());
}
ratio = FFMPUtils.getRatioValue(qpe, qpf, guid);
ratio = FFMPUtils.getRatioValue(qpe, guid);
}
}
} catch (Exception e) {
@ -3404,8 +3355,7 @@ public class FFMPResource
Float guidancev = 0.0f;
Float qpev = fgd.getQpe(fgdQpeTime).floatValue();
Float qpfv = Float.NaN;
// Initialize to NaN. If there is no guidance then we want
// NaN as the default value as it will be "missing".
double diff = Double.NaN;
@ -3432,9 +3382,8 @@ public class FFMPResource
Double qpf = fgd.getQpf(fgdQpeTime);
if (qpf != null){
qpfv = qpf.floatValue();
diff = FFMPUtils.getDiffValue(qpev, qpfv, guidancev);
ratio = FFMPUtils.getRatioValue(qpev, qpfv, guidancev);
diff = FFMPUtils.getDiffValue(qpev, guidancev);
ratio = FFMPUtils.getRatioValue(qpev, guidancev);
}
}
@ -4366,4 +4315,4 @@ public class FFMPResource
}
return new String[] { sb.toString() };
}
}
}

View file

@ -63,8 +63,7 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
* Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL
* Apr 30, 2014 2060 njensen Safety checks for null guidance
* 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>
*
@ -179,7 +178,7 @@ public class FFMPRowGenerator implements Runnable {
Float guidance = Float.NaN;
Float qpe = Float.NaN;
Float rate = Float.NaN;
Float qpf = null;
Float qpf = Float.NaN;
FIELDS rowField = FIELDS.NAME;
if (isVGB) {
@ -272,8 +271,8 @@ public class FFMPRowGenerator implements Runnable {
// If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance);
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
}
trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue));
@ -339,8 +338,8 @@ public class FFMPRowGenerator implements Runnable {
// If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance);
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
}
trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue));
@ -457,8 +456,8 @@ public class FFMPRowGenerator implements Runnable {
float diffValue = Float.NaN;
// If guidance is NaN then it cannot be > 0
if (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpf, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpf, guidance);
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
}
trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue));
@ -535,7 +534,7 @@ public class FFMPRowGenerator implements Runnable {
Float qpe = Float.NaN;
Float guidance = Float.NaN;
Float rate = Float.NaN;
Float qpf = null;
Float qpf = Float.NaN;
Float ratioValue = Float.NaN;
Float diffValue = Float.NaN;
@ -700,16 +699,12 @@ public class FFMPRowGenerator implements Runnable {
ft, huc);
}
List<Float> qpfs = null;
if (qpfBasin != null ){
qpfs = qpfBasin.getAccumValues(pfafs, monitor.getQpfWindow().getAfterTime(), monitor.getQpfWindow().getBeforeTime(), expirationTime, isRate);
}
if ((!qpes.isEmpty())
&& ((guids != null) && (!guids.isEmpty()))) {
ratioValue = FFMPUtils
.getMaxRatioValue(qpes, qpfs, guids);
diffValue = FFMPUtils.getMaxDiffValue(qpes, qpfs, guids);
.getMaxRatioValue(qpes, guids);
diffValue = FFMPUtils.getMaxDiffValue(qpes, guids);
}
trd.setTableCellData(i + 5, new FFMPTableCellData(
FIELDS.RATIO, ratioValue));
@ -770,14 +765,12 @@ public class FFMPRowGenerator implements Runnable {
ArrayList<Long> pfafs, Float qpe) {
Float guidance;
Float ratioValue;
Float diffValue;
Float qpfValue;
Float diffValue;
int i = 0;
for (String guidType : guidBasins.keySet()) {
guidance = Float.NaN;
diffValue = Float.NaN;
ratioValue = Float.NaN;
qpfValue = null;
ratioValue = Float.NaN;
FFFGForceUtil forceUtil = forceUtils.get(guidType);
forceUtil.setSliderTime(sliderTime);
@ -813,19 +806,10 @@ public class FFMPRowGenerator implements Runnable {
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 (!qpe.isNaN() && (guidance > 0.0f)) {
ratioValue = FFMPUtils.getRatioValue(qpe, qpfValue, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, qpfValue, guidance);
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
}
trd.setTableCellData(i + 5, new FFMPTableCellData(FIELDS.RATIO,
ratioValue));
@ -956,4 +940,4 @@ public class FFMPRowGenerator implements Runnable {
return new FFMPTableCellData(FIELDS.GUIDANCE, guidance, forced);
}
}
}

View file

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

View file

@ -24,6 +24,8 @@
-->
<fieldDisplayTypesFile>
<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="ageoW" displayTypes="BARB,ARROW" />
<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
* 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
* Aug. 1 2018 DR20030 jdeng Fix problems of importing rating curve, rework on all white
* spaces.
* </pre>
*
* @author lvenable
@ -1192,7 +1194,7 @@ public class RatingCurveDlg extends CaveSWTDialog {
// Read File Line By Line
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
if (line.length == 2) {
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()
* Oct 06, 2017 6407 bkowal Cleanup. Updates to support GOES-R SATPRE.
* 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>
*
@ -1137,6 +1139,7 @@ public class MPEDisplayManager {
ColorMapParameters params = new ColorMapParameters();
params.setFormatString("0.00");
params.setDisplayUnit(displayUnit);
params.setDataUnit(dataUnit);
UnitConverter displayToData = MPEConversionUtils
.constructConverter(displayUnit, dataUnit);
@ -1199,6 +1202,10 @@ public class MPEDisplayManager {
params.setColorMap(new ColorMap(cvUse, red, green, blue));
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
// 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.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.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
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
* ------------ ---------- ----------- --------------------------
* Oct 30, 2017 17911 wkwock Initial creation
* Jul 31, 2018 20677 wkwock Use FileLocator to open input stream.
*
* </pre>
*
@ -40,13 +46,12 @@ public class RfcMask {
public static XmrgFile getRFCMask(String rfcSite) throws IOException {
String rfcName = RFCSiteLookup.RFCMAP.get(rfcSite).toLowerCase();
XmrgFile xmrgFile = new XmrgFile();
try (InputStream is = MPEFieldResource.class
.getResourceAsStream("/res/RFCmask/xmrg_" + rfcName + "mask")) {
Bundle bundle = Activator.getDefault().getBundle();
IPath path = new Path("/res/RFCmask/xmrg_" + rfcName + "mask");
try (InputStream is = FileLocator.openStream(bundle, path, false)) {
xmrgFile.load(is);
} catch (Exception e) {
logger.error("Failed to read " + rfcName + "RFC mask file.", e);
logger.error("Failed to read " + rfcName + " RFC mask file.", e);
}
return xmrgFile;

View file

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

View file

@ -14,7 +14,7 @@
</configIni>
<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>
<programArgsLin>-consoleLog
</programArgsLin>
@ -63,11 +63,13 @@
</win>
</launcher>
<vm>
<linux include="true">jdk1.7.0</linux>
<windows include="true">jdk1.7.0</windows>
</vm>
<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.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.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.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.viz.avnfps.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.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.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.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>
<configurations>
@ -122,4 +128,11 @@
<plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" />
</configurations>
<preferencesInfo>
<targetfile overwrite="false"/>
</preferencesInfo>
<cssInfo>
</cssInfo>
</product>

View file

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -24,18 +24,13 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
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.UnitFormat;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
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.dataplugin.satellite.units.SatelliteUnitsUtil;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
@ -48,16 +43,15 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.datacube.DataCubeContainer;
import com.raytheon.viz.satellite.SatelliteConstants;
/**
* {@link IColorMapDataRetrievalCallback} for satellite imagery data. Supports
* signed and unsigned byte and short data
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jun 20, 2013 2122 mschenke Initial creation
@ -66,11 +60,11 @@ import com.raytheon.viz.satellite.SatelliteConstants;
* Apr 09, 2014 2947 bsteffen Improve flexibility of sat derived
* parameters.
* 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>
*
*
* @author mschenke
* @version 1.0
*/
public class SatDataRetriever implements IColorMapDataRetrievalCallback {
private static final transient IUFStatusHandler statusHandler = UFStatus
@ -92,7 +86,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
/*
* (non-Javadoc)
*
*
* @see com.raytheon.uf.viz.core.data.IDataRetrievalCallback#getData()
*/
@Override
@ -100,10 +94,10 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
Buffer data = null;
Unit<?> dataUnit = Unit.ONE;
boolean signed = false;
Request req = Request.buildSlab(new int[] { this.datasetBounds.x,
this.datasetBounds.y }, new int[] {
this.datasetBounds.x + this.datasetBounds.width,
this.datasetBounds.y + this.datasetBounds.height });
Request req = Request.buildSlab(
new int[] { this.datasetBounds.x, this.datasetBounds.y },
new int[] { this.datasetBounds.x + this.datasetBounds.width,
this.datasetBounds.y + this.datasetBounds.height });
IDataRecord[] dataRecord = null;
try {
dataRecord = DataCubeContainer.getDataRecord(record, req,
@ -141,89 +135,39 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
dataType = ColorMapData.getDataType(data);
}
return new ColorMapData(data, new int[] { datasetBounds.width,
datasetBounds.height }, dataType, dataUnit);
return new ColorMapData(data,
new int[] { datasetBounds.width, datasetBounds.height },
dataType, dataUnit);
}
/**
* @param record2
* @return
* @deprecated use {@link SatelliteUnitsUtil#getRecordUnit(SatelliteRecord)}
*/
@Deprecated
public static Unit<?> getRecordUnit(SatelliteRecord record) {
Unit<?> recordUnit = null;
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;
return SatelliteUnitsUtil.getRecordUnit(record);
}
/**
* Extracts the data units for the data record given the PDO's base unit
*
* @param recordUnit
* @param dataRecord
* @return
* @deprecated use {@link SatelliteUnitsUtil#getDataUnit(Unit, IDataRecord)}
*/
@Deprecated
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;
return SatelliteUnitsUtil.getDataUnit(recordUnit, dataRecord);
}
/**
* @deprecated use {@link SatelliteUnitsUtil#isSigned(IDataRecord)}
*/
@Deprecated
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;
return SatelliteUnitsUtil.isSigned(record);
}
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#hashCode()
*/
@Override
@ -239,33 +183,42 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (obj == null)
}
if (obj == null) {
return false;
if (getClass() != obj.getClass())
}
if (getClass() != obj.getClass()) {
return false;
}
SatDataRetriever other = (SatDataRetriever) obj;
if (dataset == null) {
if (other.dataset != null)
if (other.dataset != null) {
return false;
} else if (!dataset.equals(other.dataset))
}
} else if (!dataset.equals(other.dataset)) {
return false;
}
if (datasetBounds == null) {
if (other.datasetBounds != null)
if (other.datasetBounds != null) {
return false;
} else if (!datasetBounds.equals(other.datasetBounds))
}
} else if (!datasetBounds.equals(other.datasetBounds)) {
return false;
}
if (record == null) {
if (other.record != null)
if (other.record != null) {
return false;
} else if (!record.equals(other.record))
}
} else if (!record.equals(other.record)) {
return false;
}
return true;
}

View file

@ -24,26 +24,72 @@
of the file.
-->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="menuItem" menuText="Max Temp" key="MxT12hr" />
<contribute xsi:type="menuItem" menuText="Min Temp" key="MnT12hr" />
<contribute xsi:type="menuItem" menuText="Min Rel Humidity" key="MINRH12hr" />
<contribute xsi:type="toolbarSubMenu" menuText="Aviation">
<contribute xsi:type="menuItem" menuText="Cloud Base" key="CC" />
<contribute xsi:type="menuItem" menuText="Echo Tops" key="RETOP" />
<contribute xsi:type="menuItem" menuText="LLWS Height" key="LLWSHgt" />
<contribute xsi:type="menuItem" menuText="LLWS Wind" key="LLWSWind" />
<contribute xsi:type="menuItem" menuText="Simulated Maximum Reflectivity" key="MAXREFmax1hr" />
<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 Level" key="SNOWLVL" />
</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>
<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 Wet Bulb Temp" key="MaxTW" />
<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 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="Snow-Liquid Ratio" key="SNOWRATIO" />
<contribute xsi:type="menuItem" menuText="Snow Level" key="SNOWLVL" />
<contribute xsi:type="menuItem" menuText="Visibility" key="Vis" />
<contribute xsi:type="menuItem" menuText="Tstorm Prob 3hr" key="ThP3hr" />
<contribute xsi:type="menuItem" menuText="Tstorm Prob 6hr" key="ThP6hr" />
</menuTemplate>
<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>

View file

@ -81,6 +81,7 @@
<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="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="El" indentText="false" />
<contribute xsi:type="menuItem" textLookup="LevelMapping" key="SIG0.8-0.5"
@ -160,4 +161,9 @@
indentText="false" />
</contribute>
<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>

View file

@ -29,14 +29,12 @@
id="com.raytheon.viz.volumebrowser.volumeBrowser"
name="Volume Browser">
</command>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="com.raytheon.viz.volumebrowser.volumeBrowserRef"
name="Volume Browser">
<commandParameter
id="viewType"
name="viewType"
optional="false">
</commandParameter>
</command>
</extension>
<extension
@ -57,14 +55,14 @@
<path
application="D2D"
localizationType="CAVE_STATIC,COMMON_STATIC"
name="Volume Browser Sources"
value="volumebrowser"
name="Volume Browser"
value="level/mappings"
recursive="true">
</path>
<path
application="D2D"
localizationType="CAVE_STATIC"
name="Volume Browser Height Scales"
name="Height Scales"
value="scales"
recursive="true">
</path>
@ -75,7 +73,7 @@
locationURI="menu:volume?after=top">
<command
commandId="com.raytheon.viz.volumebrowser.volumeBrowserRef"
label="Volume Browser">
label="Browser...">
</command>
<separator name="afterVB" visible="false"/>
<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):
# validates the xml is syntactically correct based on the provided schema
# there is no validation of the content, just the format

View file

@ -6,12 +6,13 @@
# overrides of these files.
##
import copy
import logging
import glob
import imp
import os
import os.path
import pprint
import re
import shutil
@ -141,48 +142,86 @@ from DefaultCityLocation import CityLocation
def create_incremental_area_dictionary():
for file in glob.iglob(AREA_DICT_GLOB_PATH):
log.info("Generating incremental override file [%s]...", file)
for site_file in glob.iglob(AREA_DICT_GLOB_PATH):
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):
log.error("Could not find CONFIGURED level file [%s].", base_file)
log.error("Skipping to next file.")
continue
with open(site_file, 'r') as f:
contents = f.read()
if "from DefaultAreaDictionary import AreaDictionary" in contents:
log.info("Site AreaDictionary file [%s] has already been upgraded.", site_file)
continue
log.debug("Using configured file [%s]...", base_file)
log.debug("Using site file [%s]...", file)
log.info("Using configured file [%s]...", base_file)
log.info("Using site file [%s]...", site_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
site_dict = site_module.AreaDictionary
diffs = diff_dicts(configured_dict, site_dict)
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():
for file in glob.iglob(CITY_LOC_GLOB_PATH):
log.info("Generating incremental override file [%s]...", file)
for site_file in glob.iglob(CITY_LOC_GLOB_PATH):
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):
log.error("Could not find CONFIGURED level file [%s].", base_file)
log.error("Skipping to next file..")
log.error("Skipping to next file.")
continue
with open(site_file, 'r') as f:
contents = f.read()
if "from DefaultCityLocation import CityLocation" in contents:
log.info("Site CityLocation file [%s] has already been upgraded.", site_file)
continue
log.debug("Using configured file [%s]...", base_file)
log.debug("Using site file [%s]...", file)
log.info("Using configured file [%s]...", base_file)
log.info("Using site file [%s]...", site_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
site_dict = site_module.CityLocation
diffs = diff_dicts(configured_dict, site_dict)
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 = {}
keys = set().union(base.keys(), override.keys())
@ -191,45 +230,50 @@ def diff_dicts(base, override, level=0):
for key in sorted(keys):
if key not in base:
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:
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:
if base[key] != override[key]:
if base[key] != override[key]:
differences[key] = override[key]
return differences
def write_override_file(file, object_name, object_value, header):
backup_file = file + ".bak.dr_6346"
def write_override_file(file_name, object_name, object_value, header):
backup_file = file_name + ".bak.dr_6346"
log.info("Writing backup file [%s]", backup_file)
try:
shutil.copy(file, backup_file)
shutil.copy(file_name, backup_file)
except:
log.exception("Unable to write backup file [%s]", backup_file)
log.error("Skipping file [%s]", file)
log.error("Skipping file [%s]", file_name)
return
log.info("Writing override file [%s]", file)
log.info("Writing override file [%s]", file_name)
try:
with open(file, 'w') as out_file:
with open(file_name, 'w') as out_file:
printer = pprint.PrettyPrinter()
out_file.write(header)
for key in sorted(object_value.keys()):
for sub_key in sorted(object_value[key].keys()):
out_file.write("{}[{}][{}] = {}".format(object_name, key, sub_key, printer.pformat(object_value[key][sub_key])))
for (key, value, added) in sorted(object_value, key=lambda i: i[0]):
if added:
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')
except:
log.exception("Unable to write incremental override file [%s]", file)
log.critical("Restore backup file [%s] to [%s] before restarting EDEX.", backup_file, 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_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():
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 |
| 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]. |
| 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) |
| 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. |

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
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
-------------------

View file

@ -1,5 +1,5 @@
#!/bin/bash
#
##
# This software was developed and / or modified by Raytheon Company,
# 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
# 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 ###############################################################
@ -37,7 +54,7 @@ ssl_dir=/awips2/database/ssl
tablespace_dir=/awips2/database/tablespaces
# pg_hba.conf backup location
hba_backup="$(mktemp pg_hba.backup.XXXXXX)"
hba_backup="$(mktemp /tmp/pg_hba.backup.XXXXXX)"
rm -f "${hba_backup}"
# 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
psql=/awips2/psql/bin/psql
${as_awips}='sudo -u awips -i '
as_awips='sudo -u awips -i '
log() {
echo $* | ${as_awips} tee -a "${log_file}"
@ -73,22 +90,26 @@ stop_server() {
do_pg_ctl -m fast stop && sleep 1
do_pg_ctl -s status
# 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() {
for dir in ("${data_dir}" "${tablespace_dir}"); do
rm -rf "${dir}"
${as_awips} mkdir -p "${dir}"
${as_awips} chmod 700 "${dir}"
done
rm -rf "${data_dir}"
${as_awips} mkdir -p "${data_dir}"
${as_awips} chmod 700 "${data_dir}"
rm -rf "${tablespace_dir}"
${as_awips} mkdir -p "${tablespace_dir}"
${as_awips} chmod 700 "${tablespace_dir}"
}
restore_pg_hba() {
if [[ -f "${hba_backup}" ]]; then
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
else
log "WARN: No backed up pg_hba.conf to restore"
fi
}
@ -171,6 +192,7 @@ trap 'cleanup_exit' SIGINT SIGTERM
# Get certificates from master
master_ssl_dir="${ssl_dir}/replication/${master_hostname}"
echo ${as_awips} mkdir -p "${master_ssl_dir}"
${as_awips} mkdir -p "${master_ssl_dir}"
log "INFO: Downloading SSL certs and keyfile from ${master_hostname}"
# 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
if [[ -f "${data_dir}/pg_hba.conf" ]]; then
${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
# Delete all database files
@ -206,7 +231,11 @@ ${as_awips} "${pg_basebackup}" \
--username="${db_rep_user}" \
--port=${master_port} \
--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
@ -248,4 +277,6 @@ if [[ "${is_recovery}" != "t" ]]; then
cleanup_exit
fi
rm -f "${hba_backup}"
log "INFO: Setup is complete. No errors reported."

View file

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

View file

@ -52,7 +52,7 @@
# 01/19/2015 #4014 dgilling Added ETSS.
# 02/11/2015 #4053 rferrel Added GLWN and moved GLERL to display only for Great Lakes sites..
# 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/30/2015 #17288 bhunder Added Guam-RTMA to D2D models
# 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
# 12/06/2017 DCS20267 psantos Add NWPS Rip Current Guidance
# 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']
# 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
break
groups['powt']=list(siteRegion['CR'])
groups['powt']=list(groups['OCONUS_SITES']+ siteRegion['CR'] + siteRegion['ER'] + siteRegion['SR'] + siteRegion['WR'])
groups['marineSites']=[
# CONUS WFOs
"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)
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)
PoTIP=('PotSleet', SCALAR, '%', 'Prob of Sleet', 100.0, 0.0, 0, NO)
PoTR=('PotRain', SCALAR, '%', 'Prob of Rain', 100.0, 0.0, 0, NO)
PoTS=('PotSnow', SCALAR, '%', 'Prob of Snow', 100.0, 0.0, 0, NO)
PoTZR=('PotFreezingRain', SCALAR, '%', 'Prob of Freezing Rain', 100.0, 0.0, 0, NO)
MaxTwAloft=("MaxTwAloft", SCALAR, 'C', 'Max Wet-Bulb Temp in Warm Nose', 40.0, -20.0, 1, NO)
ProbIcePresent=("ProbIcePresent", SCALAR, "%", "Prob of Ice Present", 100.0, 0.0, 0, NO)
ProbRefreezeSleet=("ProbRefreezeSleet", SCALAR, "%", "Prob of Refreeze into Sleet", 100.0, 0.0, 0, NO)
SnowAmt01 = ("SnowAmt01", SCALAR, "in", "1-h Snow Accumulation", 20.0, 0.0, 1, YES)
IceAccum01 = ("IceAccum01", SCALAR, "inch", "1-h Ice Accumulation", maxIceVal, 0.0, 3, NO)
IceAccum = ("IceAccum", SCALAR, "inch", "6-h Ice Accumulation", 13.0, 0.0, 3, NO)
TstmPrb1 = ("TstmPrb1", SCALAR, "%", "1-h SREF-based Prob. of a Thunderstorm", 100.0, 0.0, 0, NO)
DryTstmPrb = ("DryTstmPrb", SCALAR, "%", "3-h SREF-based Prob. of a Dry Thunderstorm", 100.0, 0.0, 0, NO)
WGS50pct =("WGS50pct", SCALAR, "kts", "10-m Wind Gust",125.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
ISC_ROUTING_TABLE_ADDRESS = {
"ANCF" : "http://localhost:8080/irt",
"BNCF" : "http://localhost:8080/irt"
"ANCF" : "http://svcbu-ancf.er.awips.noaa.gov: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['GFS20'] = {
'D2DMODELS': 'GFS215',
'D2DMODELS': 'GFS20',
'D2DAccumulativeElements': ['tp3hr','tp6hr', 'tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'],
'DB': ('GFS20', 'GRID', '', NO, NO, 2, 0),
'Parms': [([Wetflag], FireWx1300TC),
@ -2723,8 +2732,8 @@ modelDict['GWW'] = {
],
}
modelDict['GWW233'] = {
'D2DMODELS': 'GWW233',}
modelDict['WaveWatch'] = {
'D2DMODELS': 'WaveWatch',}
modelDict['GlobalWave'] = {
'D2DMODELS': 'GlobalWave',
@ -2838,7 +2847,7 @@ modelDict['NAHwave4'] = {
modelDict['NAM12'] = {
'D2DAccumulativeElements': ['tp', 'cp', 'crain', 'csnow', 'cfrzr', 'cicep'],
'D2DMODELS': 'ETA218',
'D2DMODELS': 'NAM12',
'DB': ('NAM12', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'NAM12',
'Parms': STD3_MODEL,
@ -2846,11 +2855,11 @@ modelDict['NAM12'] = {
modelDict['NAM20'] = {
'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'mesoEta215',}
'D2DMODELS': 'NAM20',}
modelDict['NAM40'] = {
'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'mesoEta212',
'D2DMODELS': 'NAM40',
'DB': ('NAM40', 'GRID', '', NO, NO, 2, 0),
'Parms': STD3_MODEL,
}
@ -2882,7 +2891,9 @@ modelDict['NamDNG'] = {
}
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',
'DB': ('NationalBlend', 'GRID', '', NO, NO, 7, 0),
'INITMODULES': 'NationalBlend',
@ -2890,11 +2901,24 @@ modelDict['NationalBlend'] = {
([QPF1,PPI01,CloudBasePrimary,Ceiling,Visibility],TC1),
([PoTIP, PoTR, PoTRW, PoTS, PoTSW, PoTZR,],TC1),
([SnowLevel,MaxTwAloft,ProbIcePresent, ProbRefreezeSleet,SnowRatio],TC1),
([PositiveEnergyAloft,NegativeEnergyLowLevel],TC1),
([TstmPrb3],TC3NG),
([TstmPrb6,QPF,PoP6,PPI06],TC6NG),
([PositiveEnergyAloft, NegativeEnergyLowLevel],TC1),
([MixHgt, TransWind, LLWS, VentRate, LLWSHgt, Radar,
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),
([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',}
modelDict['RFCQPF'] = {
'D2DAccumulativeElements': ['tpHPC'],
'D2DMODELS': 'RFCqpf',
'DB': ('RFCQPF', 'GRID', '', NO, NO, 4, 0),
'INITMODULES': 'RFCQPF',
'Parms': [([QPF], TC6NG),
],
}
@ -2924,11 +2946,11 @@ modelDict['RTMA'] = {
'Parms': RTMAPARMS,
}
modelDict['RUC13'] = {
modelDict['RAP13'] = {
'D2DAccumulativeElements': ['tp', 'cp'],
'D2DMODELS': 'RUC130',
'DB': ('RUC13', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'RUC13',
'D2DMODELS': 'RAP13',
'DB': ('RAP13', 'GRID', '', NO, NO, 2, 0),
'INITMODULES': 'RAP13',
'INITSKIPS': [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23],
'Parms': STD1_MODEL,
}
@ -3178,11 +3200,11 @@ if SID in groups['ALASKA_SITES']:
updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsAK')
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,'HIRESWnmm','D2DMODELS', 'HiResW-NMM-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,'NationalBlend','D2DMODELS', 'NationalBlendAK')
updateModelDict(modelDict,'RTMA','D2DMODELS', 'AK-RTMA3')
@ -3213,7 +3235,7 @@ elif SID == "HFO":
'Parms': STD6_MODEL,
}
updateModelDict(modelDict,'GWW233','D2DMODELS', 'GWW233')
updateModelDict(modelDict,'WaveWatch','D2DMODELS', 'WaveWatch')
updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave')
updateModelDict(modelDict,'RTMA','D2DMODELS', 'HI-RTMA')
updateModelDict(modelDict,'NamDNG','D2DMODELS', 'HI-NamDNG5')
@ -3228,7 +3250,7 @@ elif SID == "HFO":
updateModelDict(modelDict,'MOSGuide','D2DMODELS', 'MOSGuide-HI')
updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendHI')
# Model databases for HFO
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS75', 'GWW233', 'GlobalWave',
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS75', 'WaveWatch', 'GlobalWave',
'HIRESWarw', 'HIRESWnmm', 'MOSGuide', 'NamDNG', 'NationalBlend',
'RTMA', 'RTOFS-Honolulu', 'SPC', 'TPCProb', 'TPCProbPrelim', 'nwpsCG1GUM',
'nwpsCG1HFO', 'nwpsTrkngCG0GUM', 'nwpsTrkngCG0HFO',
@ -3259,7 +3281,7 @@ elif SID == "GUM":
elif SID == "SJU":
updateModelDict(modelDict,'GFS80','D2DMODELS', 'AVN211')
updateModelDict(modelDict,'NAM80','D2DMODELS', 'ETA')
updateModelDict(modelDict,'GWW233','D2DMODELS', 'GWW233')
updateModelDict(modelDict,'WaveWatch','D2DMODELS', 'WaveWatch')
updateModelDict(modelDict,'GlobalWave','D2DMODELS', 'GlobalWave')
updateModelDict(modelDict,'WNAwave10','D2DMODELS', 'WNAwave10')
updateModelDict(modelDict,'WNAwave4','D2DMODELS', 'WNAwave4')
@ -3273,10 +3295,10 @@ elif SID == "SJU":
updateModelDict(modelDict,'RTOFS-Atlantic','D2DMODELS', 'RTOFS-Atlantic')
updateModelDict(modelDict,'ESTOFS','D2DMODELS', 'estofsPR')
updateModelDict(modelDict,'NAHwave4','D2DMODELS', 'NAHwave4')
updateModelDict(modelDict,'GFS20','D2DMODELS', 'GFS20-PRICO')
updateModelDict(modelDict,'GFS20','D2DMODELS', 'PR-GFS')
updateModelDict(modelDict,'NationalBlend','D2DMODELS', 'NationalBlendPR')
# Model databases for SJU
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS20', 'GFS80', 'GWW233',
includeOnly = ['ECMWFHiRes', 'ESTOFS', 'GFS20', 'GFS80', 'WaveWatch',
'GlobalWave', 'HIRESWarw', 'HIRESWnmm', 'NAHwave4', 'NAM80',
'NationalBlend', 'RTMA', 'RTOFS-Atlantic', 'SPC', 'TPCProb',
'TPCProbPrelim', 'WNAwave10', 'WNAwave4',

View file

@ -25,6 +25,13 @@
# 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 numpy import *
@ -276,7 +283,7 @@ class NationalBlendForecaster(Forecaster):
# values.
CloudBasePrimary = where(less(CloudBasePrimary, 0), 250, CloudBasePrimary)
return self.smoothpm(CloudBasePrimary, 3)
return CloudBasePrimary
def calcMaxRH(self, MAXRH12hr_FHAG2):
return MAXRH12hr_FHAG2
@ -287,8 +294,8 @@ class NationalBlendForecaster(Forecaster):
#===========================================================================
# Calc MaxTwAloft - Convert K to C
#===========================================================================
def calcMaxTwAloft(self, MaxTW_EA):
return (MaxTW_EA - 273.15)
def calcMaxTwAloft(self, maxtw_FHAG61040000):
return (maxtw_FHAG61040000 - 273.15)
def calcMinRH(self, MINRH12hr_FHAG2):
return MINRH12hr_FHAG2
@ -299,14 +306,14 @@ class NationalBlendForecaster(Forecaster):
#===========================================================================
# NegativeEnergyLowLevel
#===========================================================================
def calcNegativeEnergyLowLevel(self, nbe_EA):
return nbe_EA
def calcNegativeEnergyLowLevel(self, nbe_SFC):
return nbe_SFC
#===========================================================================
# Positive Energy Aloft
#===========================================================================
def calcPositiveEnergyAloft(self, pbe_EA):
return pbe_EA
def calcPositiveEnergyAloft(self, pbe_FHAG61040000):
return pbe_FHAG61040000
def calcPoP(self, pop_SFC):
return pop_SFC
@ -421,6 +428,395 @@ class NationalBlendForecaster(Forecaster):
def calcPotFreezingRain(self, 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():
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
# 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 *
##--------------------------------------------------------------------------

View file

@ -28,13 +28,13 @@
from Init import *
##--------------------------------------------------------------------------
## Module that calculates surface weather elements from RUC80 model
## Module that calculates surface weather elements from RAP40 model
## output.
##
##--------------------------------------------------------------------------
class RUC80Forecaster(Forecaster):
class RAP40Forecaster(Forecaster):
def __init__(self):
Forecaster.__init__(self, "RUC80")
Forecaster.__init__(self, "RAP40")
##--------------------------------------------------------------------------
## These levels will be used to create vertical soundings. These are
@ -531,4 +531,4 @@ class RUC80Forecaster(Forecaster):
return lal
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 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)
for key in advisory["ZoneData"][zone]:
if "Threat" not in key or "highestHunkerDown" in key:
break
continue
if key not in seenValidThreatLevel:
seenValidThreatLevel[key] = False

View file

@ -22,7 +22,7 @@
# 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 JsonSupport
@ -1457,7 +1457,7 @@ class SectionCommon():
self._sectionHeaderName = sectionHeaderName
self._segment = segment
self._tr = None
self.isThreatNoneForEntireStorm = True
self.isThreatNoneForEntireStorm = False
def _isThreatNoneForEntireStorm(self, threatName):
previousAdvisories = self._textProduct._getPreviousAdvisories()
@ -1471,7 +1471,7 @@ class SectionCommon():
if advisory["ZoneData"][self._segment][threatName] != "None":
return False
return True
return False
def _setProductPartValue(self, dictionary, productPartName, value):
dictionary[self._sectionName + '._' + productPartName] = value

View file

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

View file

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

View file

@ -291,6 +291,17 @@
<fcst>943200</fcst>
<fcst>946800</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>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>mnt</short_name>
@ -466,27 +477,12 @@
<level>SFC</level>
</levels>
</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">
<short_name>ppi6hr</short_name>
<long_name>6HR PPI</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>6hrPcpProbIndex</uiname>
<units>1ndex</units>
<udunits>index</udunits>
<uiname>PPI6hr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
@ -546,14 +542,15 @@
<long_name>Wind Direction</long_name>
<units>degreeTrue</units>
<udunits>degree_True</udunits>
<uiname>windDir</uiname>
<uiname>WD</uiname>
<valid_range>0.0</valid_range>
<valid_range>360.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc>
<levelsDesc>FHAG 10, FHAG 0-610</levelsDesc>
<levels>
<level>FHAG10</level>
<level>FHAG0610</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -628,14 +625,15 @@
<long_name>Wind Speed</long_name>
<units>m/s</units>
<udunits>meter/sec</udunits>
<uiname>windSpeed</uiname>
<uiname>WS</uiname>
<valid_range>-150.0</valid_range>
<valid_range>150.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc>
<levelsDesc>FHAG 10, FHAG 0-610</levelsDesc>
<levels>
<level>FHAG10</level>
<level>FHAG0610</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -708,26 +706,11 @@
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>2 FHAG</levelsDesc>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</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">
<short_name>snowlvl</short_name>
<long_name>Snow Level</long_name>
@ -753,7 +736,7 @@
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>2 FHAG</levelsDesc>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
@ -768,13 +751,13 @@
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>2 FHAG</levelsDesc>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</gridParameterInfo>
<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>
<units>K</units>
<udunits>degree_Kelvin</udunits>
@ -783,16 +766,16 @@
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>EA</levelsDesc>
<levelsDesc>FHAG 610-40000</levelsDesc>
<levels>
<level>EA</level>
<level>FHAG61040000</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>ptyp</short_name>
<long_name>Precipitation type</long_name>
<units/>
<udunits/>
<units>1</units>
<udunits>1</udunits>
<uiname>pTyp</uiname>
<valid_range>1.0</valid_range>
<valid_range>5.0</valid_range>
@ -903,9 +886,9 @@
<valid_range>6000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levelsDesc>FHAG 610-40000</levelsDesc>
<levels>
<level>EA</level>
<level>FHAG61040000</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -918,9 +901,9 @@
<valid_range>6000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>EA</levelsDesc>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>EA</level>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
@ -938,4 +921,440 @@
<level>SFC</level>
</levels>
</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>

View file

@ -85,21 +85,6 @@
<level>SFC</level>
</levels>
</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">
<short_name>tpALR</short_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
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
-->

View file

@ -28,7 +28,7 @@
Mar 31, 2014 #2934 dgilling Updated params for pSurge2.0/PHISH data.
Jul 03, 2014 DR 14068 mfoster Added parameters for 3km AK-RTMA
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
Jun 29, 2015 #4537 rferrel Added parameters for HRRR.
Oct 08, 2015 #4958 dgilling Added parameters for NationalBlend.
@ -593,9 +593,34 @@
<alias base="PTypIcePellets">ptypicepellets</alias>
<alias base="SNOWLVL">snowlvl</alias>
<alias base="SNOWRATIO">snowratio</alias>
<alias base="PBE">pbe</alias>
<alias base="NBE">nbe</alias>
<alias base="RIPCOP">ripcop</alias>
<alias base="EROSNP">erosnp</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>

View file

@ -52,6 +52,7 @@
# Jul 17, 2017 DR19976 MPorricelli Add labeling of Probability Matched Mean fields#
# Nov 29, 2017 6536 bsteffen Handle redundant statistical specifiers better.
# Feb 07, 2018 7213 nabowle Only allow P-ETSS to create Statistical parameters.
# Mar 19, 2018 20395 wkwock Added PDS template 15
#
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
# Exception cases are handled accordingly
if pdsTemplateNumber <= 12:
if pdsTemplateNumber <= 12 or pdsTemplateNumber == 15:
# Get the basic level and parameter information
if (pdsTemplate[0] == 255):
@ -477,7 +478,13 @@ class GribDecoder():
levelName = 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:
levelName = gribLevel.getAbbreviation();
@ -519,10 +526,7 @@ class GribDecoder():
else:
levelTwoValue = float(pdsTemplate[14] * pow(10, pdsTemplate[13] * -1))
if levelName == 'SFC' and levelOneValue != float(0):
levelOneValue = float(0)
if levelName == 'EATM':
if levelName == 'EATM' or levelName == 'SFC':
levelOneValue = float(0)
levelTwoValue = float(Level.getInvalidLevelValue())

View file

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -89,11 +89,11 @@ import ucar.unidata.io.RandomAccessFile;
/**
* Grib decoder implementation for decoding grib version 1 files.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------------------------
* Mar 11, 2010 4758 bphillip Initial Creation
@ -111,10 +111,12 @@ import ucar.unidata.io.RandomAccessFile;
* Apr 11, 2016 5564 bsteffen Move localization files to common_static
* Apr 19, 2016 5572 bsteffen Move GribModelLookup to common
* Sep 11, 2017 6406 bsteffen Upgrade ucar
*
*
* Aug 02, 2018 7397 mapeters Fix parameter table lookups so standard
* ucar lookups are used
*
*
* </pre>
*
*
* @author bphillip
*/
public class Grib1Decoder {
@ -123,7 +125,7 @@ public class Grib1Decoder {
/**
* http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html#FOS
*
*
* Grib files using these coverages have an entire row of data that is
* located at the pole. Rather than sending the same value multiple times,
* they only send a single point. Since we must have a data value for each
@ -159,25 +161,21 @@ public class Grib1Decoder {
LocalizationLevel.BASE),
"/grib/ucar/userTables.lst")
.getPath();
Grib1ParamTables tables;
try {
Grib1ParamTables.Lookup lookup = new Grib1ParamTables.Lookup();
lookup.readLookupTable(ucarUserFile);
tables = new Grib1ParamTables(lookup, null);
Grib1ParamTables.addParameterTableLookup(ucarUserFile);
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
"Error reading user parameter tables for ucar grib decoder",
e);
tables = new Grib1ParamTables(null, null);
}
paramTables = tables;
paramTables = new Grib1ParamTables();
}
/**
* Decodes the grib file provided.
*
* @param gribFileName
* The name of the file to be decoded
*
* @param message
* message describing the grib file to decode
* @return The decoded GridRecords
* @throws GribException
* If decoding the file fails or encounters problems
@ -227,7 +225,7 @@ public class Grib1Decoder {
/**
* Decodes a single record from the grib file
*
*
* @param rec
* The record to decode
* @param raf
@ -443,12 +441,12 @@ public class Grib1Decoder {
* https://github.com/Unidata/thredds/issues/82. That bug only
* identifies the problem with cubicSpline interpolation, but
* linear interpolation is making the same assumptions.
*
*
* The problem is that the ucar interpolation method assumes the
* data is cylindrical and it spaces the points evenly along the
* cylinder, while fillThinedGrids only interpolates in the 2D
* space of the grid.
*
*
* For example if you have a row with only 2 data points then
* fillThinnedGrid would place one point on the left and the
* other on the right and the grid is filled by interpolating
@ -462,7 +460,7 @@ public class Grib1Decoder {
* those points to fill the right half. If you have a worldwide
* grid Lat/Lon then this treatment makes sense because the
* projection is a cylinder.
*
*
* We get thinned grids in "quadrant" form, using grids 37-44.
* These grids are definitely not a cylinder so the ucar method
* is wrong.
@ -586,7 +584,7 @@ public class Grib1Decoder {
/**
* Resizes a 1-D data array into a 2-D array based on the provided row and
* column count
*
*
* @param data
* The 1-D array of data
* @param columnCount
@ -660,7 +658,7 @@ public class Grib1Decoder {
/**
* Resizes a 2-D array of data to a 1-D array
*
*
* @param data
* The 2-D array of data
* @param rowCount
@ -683,7 +681,7 @@ public class Grib1Decoder {
/**
* Extracts a sub-grid of data from a 2-D array of data
*
*
* @param data
* The 2-D array of data
* @param startColumn
@ -746,7 +744,7 @@ public class Grib1Decoder {
/**
* Flips the grid according to the scan mode in the GDS
*
*
* @param data
* The data
* @param nx
@ -782,7 +780,7 @@ public class Grib1Decoder {
/**
* Gets the time ranges for the data
*
*
* @param refTime
* The reference time
* @param timeRange
@ -829,7 +827,7 @@ public class Grib1Decoder {
/**
* Gets the spatial information from the grib record
*
*
* @param gdsVars
* The gds values
* @param gridNumber
@ -963,7 +961,7 @@ public class Grib1Decoder {
/**
* Checks the cache for the GridCoverage object.
*
*
* @param coverage
* The coverage to check the cache for
* @param gridNumber
@ -995,7 +993,7 @@ public class Grib1Decoder {
/**
* Look up a model name based off the grib numbers
*
*
* @param centerId
* @param subcenterId
* @param process
@ -1011,7 +1009,7 @@ public class Grib1Decoder {
/**
* Check if the forecast flag should be removed
*
*
* @param time
* The datatime to remove forecast flag if needed
* @param centerId
@ -1033,7 +1031,7 @@ public class Grib1Decoder {
/**
* Constructs a data time object from the time information extracted from
* the grib record
*
*
* @param refTime
* The reference time
* @param forecastTime
@ -1060,7 +1058,7 @@ public class Grib1Decoder {
/**
* Converts a time value to seconds
*
*
* @param value
* The value to convert
* @param fromUnit
@ -1114,7 +1112,7 @@ public class Grib1Decoder {
/**
* Converts a grib 1 level to the equivalent grib 2 representation
*
*
* @param ltype1
* The type of level
* @param lval1
@ -1284,7 +1282,7 @@ public class Grib1Decoder {
/**
* Gets the level information
*
*
* @param centerID
* The center
* @param subcenterID
@ -1369,7 +1367,7 @@ public class Grib1Decoder {
/**
* Bounds a longitude to between -180 and 180
*
*
* @param lon
* The longitude to correct
* @return The corrected longitude
@ -1393,7 +1391,7 @@ public class Grib1Decoder {
/**
* Bounds a latitude to between -90 and 90
*
*
* @param lat
* The latitude to correct
* @return The corrected latitude

View file

@ -71,6 +71,36 @@
</process>
</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-->
<model>
<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
2:2:Haines Index:Numeric:HINDEX
3:3:Haines Index:Numeric:HINDEX
4:4:Fosberg Index:Numeric:FOSINDX
#192-254 Reserved for local use
255:255:Missing

View file

@ -1,6 +1,10 @@
# Product Discipline 0: Meteorological products, Parameter Category 1: Moisture
#192-254 Reserved for local use
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
243:243:Precipitation Potential Index (PPI):%:PPI
255:255:Missing

View file

@ -1,4 +1,5 @@
# 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:192:Maximum Snow Albedo:%:MXSALB
193:193:Snow-Free Albedo:%:SNFALB
@ -44,5 +45,6 @@
233:233:Icing probability:non-dim:ICPRB
234:234:Icing severity:non-dim:ICSEV
235:235:Snow Level:m:SNOWLVL
236:236:Snow Level:m:SNOWLVL
255:255:Missing

View file

@ -1,6 +1,6 @@
# Product Discipline 0: Meteorological products, Parameter Category 2: Momentum
# 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
194:194:U-Component Storm Motion:m/s:USTM
195:195:V-Component Storm Motion:m/s:VSTM
@ -10,8 +10,8 @@
199:199:Longitude of U Wind Component of Velocity:degrees:LOUV
200:200:Latitude of V Wind Component of Velocity:degrees:LAVV
201:201:Longitude of V Wind Component of Velocity:degrees:LOVV
202:202:Latitude of Pressure Point:degrees:LAPP
203:203:Longitude of Pressure Point:degrees:LOPP
202:202:Latitude of Presure Point:degrees:LAPP
203:203:Longitude of Presure Point:degrees:LOPP
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
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
223:223:V Component of Hourly Maximum 10m Wind Speed:m/s:MAXVW
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

View file

@ -10,5 +10,8 @@
197:197:Updraft Helicity:m^2/s^2:UPHL
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
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

View file

@ -2,7 +2,7 @@
#192-254 Reserved for local use
192:192:Level at Specified Pressure Difference from Ground to Level:Pa:PDLY:LYRBL
193:193:Eta Level:Eta value:ELYR:ETA
200:200:Entire Atmosphere::NONE:EA
200:200:Entire Atmosphere::EA
201:201:Entire Ocean::NONE
204:204:Highest Tropospheric Freezing Level::HTFL
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
233:233:Icing probability:non-dim:ICPRB
234:234:Icing severity:non-dim:ICSEV
237:237:Dry Thunderstorm Probability:%:DRYTPROB
255:255:Missing

View file

@ -652,6 +652,9 @@ TW_NBM-NCEP-MDL MaxTW
CAPE_NBM-NCEP-MDL PBE
CIn_NBM-NCEP-MDL NBE
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.
ThP0.0%_SREF-NCEP-MDL_2345x1597_10800-0 ThP3hr
//END NationalBLend

View file

@ -102,8 +102,7 @@ import com.vividsolutions.jts.io.WKTWriter;
* Aug 08, 2015 4722 dhladky Added Grid coverage and parsing methods.
* Sep 17, 2015 4756 dhladky Multiple guidance source bugs.
* Feb 12, 2016 5370 dhladky Camel case for insertTime.
* Apr 07, 2016 5491 tjensen Fix NullPointerException from getRawGeometries
* Mar 07, 2017 DR 11861 lshi FFMP use of QPF in Basin Table
* Apr 07, 2016 5491 tjensen Fix NullPointerException from getRawGeometries
* May 11, 2017 6266 nabowle Use GetRadarSpatialRequest in getRadarCenter().
* </pre>
*
@ -1302,18 +1301,13 @@ public class FFMPUtils {
* Gets the ratio value
*
* @param qpe
* @param qpf
* @param guid
* @return
*/
public static float getRatioValue(float qpe, float qpf, float guid) {
public static float getRatioValue(float qpe, float guid) {
float value = Float.NaN;
if ((qpe >= 0.0f) && (guid >= 0.0f)) {
value = qpe;
if ( !Float.isNaN(qpf)){
value += qpf;
}
value = (float) ((value / guid) * 100.0);
value = (float) ((qpe / guid) * 100.0);
}
@ -1322,22 +1316,19 @@ public class FFMPUtils {
/**
* find max ratio in list
*
* @param qpes
* @param qpfs
* @param qpes
* @param guids
* @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;
boolean hasQpfs = qpfs != null && qpfs.size() == qpes.size();
if ((qpes.size() == guids.size()) && (!qpes.isEmpty())
&& (!guids.isEmpty())) {
for (int i = 0; i < qpes.size(); i++) {
if (guids.get(i) > 0.0f) {
float qpf = hasQpfs ? qpfs.get(i): Float.NaN;
float nratio = getRatioValue(qpes.get(i), qpf, guids.get(i));
if ((!Float.isNaN(nratio) &&(nratio > ratio))
float nratio = getRatioValue(qpes.get(i), guids.get(i));
if (((nratio > ratio) && !Float.isNaN(nratio))
|| Float.isNaN(ratio)) {
if (!Float.isInfinite(nratio)) {
ratio = nratio;
@ -1354,20 +1345,18 @@ public class FFMPUtils {
/**
* Gets the diff value
*
* @param qpe
* @param qpf
* @param qpe
* @param guid
* @return
*/
public static float getDiffValue(float qpe, float qpf, float guid) {
public static float getDiffValue(float qpe, float guid) {
float value = Float.NaN;
if ((qpe >= 0.0f) && (guid >= 0.0f)) {
value = qpe;
if ( !Float.isNaN(qpf)){
value += qpf;
}
value -= guid;
float qpeRnd = Float.parseFloat(formatter.format(qpe));
float guidRnd = Float.parseFloat(formatter.format(guid));
value = new Float(qpeRnd - guidRnd);
}
@ -1378,23 +1367,20 @@ public class FFMPUtils {
/**
* find max diff in the list
*
* @param qpes
* @param qpfs
* @param qpes
* @param guids
* @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;
boolean hasQpfs = qpfs != null && qpfs.size() == qpes.size();
if ((qpes.size() == guids.size()) && (!qpes.isEmpty())
&& (!guids.isEmpty())) {
for (int i = 0; i < qpes.size(); i++) {
if (guids.get(i) > 0.0f) {
float qpf = hasQpfs ? qpfs.get(i): Float.NaN;
float ndiff = getDiffValue(qpes.get(i), qpf, guids.get(i));
if ((!Float.isNaN(ndiff) && (ndiff > diff))
float ndiff = getDiffValue(qpes.get(i), guids.get(i));
if ((((ndiff) > diff) && !Float.isNaN(ndiff))
|| Float.isNaN(diff)) {
diff = ndiff;
}
@ -1501,4 +1487,4 @@ public class FFMPUtils {
return dataPath.split(DataURI.SEPARATOR);
}
}
}

View file

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

View file

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -30,6 +30,8 @@ import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.NullUtil;
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.annotations.NullString;
@ -46,11 +48,11 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* space in the db since across time most grid data has the same
* level/parameter/etc so having all other information in a separate table saves
* space and improves theoretical performance.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* May 21, 2012 bsteffen Initial creation
@ -60,16 +62,18 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
* Aug 03, 2016 4360 rferrel Add name to unique constraint.
* Made datasetId, secondaryId, ensembleId, non-nullable.
* Now use EMPTY_STRING for null values and created static nullValue_ methods
*
* Aug 03, 2018 7424 tjensen Add index to GridCoverage location
*
* </pre>
*
*
* @author bsteffen
* @version 1.0
*/
@Entity
@Table(name = "grid_info", uniqueConstraints = { @UniqueConstraint(name = "uk_grid_info_datauri_fields", columnNames = {
"datasetid", "parameter_abbreviation", "level_id", "secondaryid",
"ensembleid", "location_id" }) })
@Table(name = "grid_info", uniqueConstraints = {
@UniqueConstraint(name = "uk_grid_info_datauri_fields", columnNames = {
"datasetid", "parameter_abbreviation", "level_id",
"secondaryid", "ensembleid", "location_id" }) })
@SequenceGenerator(name = "GRIDINFO_GENERATOR", sequenceName = "gridinfo_seq", allocationSize = 1)
@DynamicSerialize
public class GridInfoRecord extends PersistableDataObject<Integer> {
@ -109,6 +113,7 @@ public class GridInfoRecord extends PersistableDataObject<Integer> {
@ManyToOne(optional = false)
@PrimaryKeyJoinColumn
@DataURI(position = 3, converter = GridCoverageConverter.class)
@Index(name = "grid_info_location_id_index")
@DynamicSerializeElement
private GridCoverage location;

View file

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

View file

@ -4978,4 +4978,61 @@ in | .03937 | 0 | 4 | | |..|8000F0FF| | 16 | \
</contourLabeling>
</contourStyle>
</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>

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.ir,
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.Entry;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
@ -38,20 +39,25 @@ import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataaccess.exception.InvalidIdentifiersException;
import com.raytheon.uf.common.dataaccess.impl.AbstractGridDataPluginFactory;
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.satellite.SatelliteRecord;
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.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;
/**
* A data factory for getting satellite data from the metadata database. There
* are currently not any required identifiers.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 02, 2012 bkowal Initial creation
@ -70,9 +76,11 @@ import com.raytheon.uf.common.numeric.source.DataSource;
* Aug 01, 2016 2416 tgurney Add dataURI as optional identifier
* Mar 06, 2017 6142 bsteffen Remove dataURI as optional identifier
* 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>
*
*
* @author bkowal
*/
public class SatelliteGridFactory extends AbstractGridDataPluginFactory {
@ -149,7 +157,7 @@ public class SatelliteGridFactory extends AbstractGridDataPluginFactory {
/**
* Builds the base constraint map based on the supplied grid request
*
*
* @param request
* the original grid request
* @return the base constraint map
@ -223,6 +231,32 @@ public class SatelliteGridFactory extends AbstractGridDataPluginFactory {
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(
SatelliteRecord satelliteRecord) {
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

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -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
import java.io.Serializable;
import java.util.Date;
import javax.persistence.AttributeOverride;
@ -32,6 +31,8 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
@ -41,27 +42,30 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Dhrradar generated by hbm2java
*
*
*
*
* <pre>
*
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 17, 2008 Initial generation by hbm2java
* Aug 19, 2011 10672 jkorman Move refactor to new project
* Oct 07, 2013 2361 njensen Removed XML annotations
* Sep 26, 2016 5631 bkowal Cleanup.
*
* Aug 19, 2011 10672 jkorman Move refactor to new project
* Oct 07, 2013 2361 njensen Removed XML annotations
* Sep 26, 2016 5631 bkowal Cleanup.
* Jul 25, 2018 5588 mapeters Added NamedQueries annotation
*
* </pre>
*
*
* @author jkorman
*/
@NamedQueries({
@NamedQuery(name = Dhrradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME, query = Dhrradar.SELECT_BY_RAD_ID_BETWEEN_OBS_TIME_HQL) })
@Entity
@Table(name = "dhrradar")
@DynamicSerialize
public class Dhrradar extends PersistableDataObject<DhrradarId>
implements Serializable, IGriddedRadarRecord {
implements IGriddedRadarRecord {
private static final long serialVersionUID = 1L;
@ -139,8 +143,8 @@ public class Dhrradar extends PersistableDataObject<DhrradarId>
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "radid", column = @Column(name = "radid", nullable = false, length = 3) ),
@AttributeOverride(name = "obstime", column = @Column(name = "obstime", nullable = false, length = 29) ) })
@AttributeOverride(name = "radid", column = @Column(name = "radid", nullable = false, length = 3)),
@AttributeOverride(name = "obstime", column = @Column(name = "obstime", nullable = false, length = 29)) })
public DhrradarId getId() {
return this.id;
}

View file

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

View file

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -30,25 +30,26 @@ import com.raytheon.uf.common.ohd.AppsDefaults;
/**
* Apps_Defaults utility to convert String-based Apps_Defaults properties to
* usable Java objects.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 2, 2016 5614 bkowal Initial creation
* May 13, 2016 5576 bkowal Updated to be more of a general utility for
* Apps_Defaults property conversions.
* 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.
* Aug 10, 2016 4619 bkowal The parallel write flag is now a constant to
* ensure it is not accidentally overwritten.
* 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>
*
*
* @author bkowal
*/
@ -66,7 +67,7 @@ public final class AppsDefaultsConversionWrapper {
* currently enabled. TODO: completely remove this method when the decision
* is made to transition to the new MPE framework. Expect several errors
* that will need to be resolved after removing this method.
*
*
* @return {@code true}, if parallel execution is enabled; {@code false},
* otherwise
*/
@ -76,16 +77,18 @@ public final class AppsDefaultsConversionWrapper {
/**
* Retrieves a {@link Path} associated with an Apps_Defaults token. Will
* also verify that that Path exists and make any required standard
* modifications to the Path before returning it.
*
* also make any required standard modifications to the Path before
* 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
* the specified Apps_Defaults token.
* @return the {@link Path} associated with the specified token.
* @throws AppsDefaultsPathException
* @return the {@link Path} associated with the specified token, which may
* not exist.
*/
public static Path getPathForToken(final String token)
throws AppsDefaultsPathException {
public static Path getPathForTokenWithoutCreating(final String token) {
final String directory = AppsDefaults.getInstance().getToken(token);
if (directory == null) {
throw new IllegalArgumentException("No " + AppsDefaults.NAME
@ -99,6 +102,29 @@ public final class AppsDefaultsConversionWrapper {
+ PARALLEL_DIRECTORY;
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)) {
try {
com.raytheon.uf.common.util.file.Files.createDirectories(
@ -114,7 +140,7 @@ public final class AppsDefaultsConversionWrapper {
/**
* Retrieves a {@link Boolean} for Apps_Defaults properties.
*
*
* @param token
* the specified token identifying the property to retrieve.
* @return {@code null} if the property is not found. True if the retrieved

View file

@ -9,6 +9,7 @@
<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="dspGather" class="com.raytheon.uf.edex.plugin.mpe.gather.dsp.DSPGather" />
<bean id="dhrDecoder"
class="com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRDecoder" />
@ -21,10 +22,19 @@
<constructor-arg value="jms-durable:queue:Ingest.dhr" />
</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">
<!-- Begin non-clustered dhr Routes -->
<route id="dhrIngestFilter">
<!-- Begin non-clustered DHR/DSP Routes -->
<route id="dhrDspIngestFilter">
<from uri="jms-durable:queue:Ingest.dhr" />
<setHeader headerName="pluginName">
<constant>dhr</constant>
@ -44,23 +54,39 @@
</route>
</camelContext>
<camelContext id="clusteredDHRroutes"
<camelContext id="clusteredDhrDspRoutes"
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 -->
<route id="dhrIngestRoute">
<from uri="jms-durable:queue:dhrProcess" />
<doTry>
<pipeline>
<bean ref="serializationUtil" method="transformFromThrift" />
<bean ref="dhrDecodeSrv" method="process" />
<filter>
<method ref="dhrGather" method="executeAllowed" />
<bean ref="serializationUtil" method="transformFromThrift" />
<filter>
<method ref="dhrGather" method="precipExists" />
<bean ref="dhrDecoder" method="execute" />
<bean ref="dspDecoder" method="execute" />
<!-- TODO: this will eventually continue the route to HPE Field
Gen -->
<method ref="dhrDecodeSrv" method="prepareForGather" />
<filter>
<method ref="dhrGather" method="precipExists" />
<bean ref="dhrDecoder" method="execute" />
<!-- TODO: this will eventually continue the route to HPE Field
Gen -->
</filter>
</filter>
</filter>
</pipeline>
@ -70,10 +96,35 @@
</doCatch>
</doTry>
</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>
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredDHRroutes" />
<constructor-arg ref="clusteredDhrDspRoutes" />
</bean>
</beans>
</beans>

View file

@ -1,19 +1,19 @@
/**
* 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.
**/
@ -25,6 +25,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -44,10 +45,11 @@ import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.ohd.MainMethod;
import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGather;
/**
* Service implementation for decoding DHR radar files.
*
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
@ -67,9 +69,12 @@ import com.raytheon.uf.edex.ohd.MainMethod;
* 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 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>
*
*
* @author snaples
*/
public class HPEDhrSrv {
@ -104,7 +109,11 @@ public class HPEDhrSrv {
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();
@ -127,27 +136,32 @@ public class HPEDhrSrv {
public static final String KSH = "ksh";
/**
* Route endpoint for "dhrIngestRoute". Takes a message, writes the file to
* disk, and then runs the DHR data processing scripts so the file is
* ingested.
*
* Route endpoint for "legacyDhrDspIngestRoute". Takes a message, writes the
* file to disk, and then runs the DHR data processing scripts so the file
* is ingested. This is everything necessary for legacy processing of the
* given message.
*
* @param message
* A <code>HPEDhrMessage</code> describing the DHR radar file to
* be ingested.
*/
public void process(HPEDhrMessage message) {
try {
writeFile(message);
} 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;
public void legacyProcess(HPEDhrMessage message) {
if (writeFile(message, true)) {
runLegacyGatherScripts();
}
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);
}
/**
@ -156,49 +170,60 @@ public class HPEDhrSrv {
* <p>
* This method removes the leading bytes to ensure proper decoding of DHR
* files.
*
*
* @param message
* A <code>HPEDhrMessage</code> describing the DHR radar file to
* be ingested.
* @throws FileNotFoundException
* If the output file cannot be created or opened for any
* reason.
* @throws IOException
* If an I/O error occurs while writing the file.
* @param legacy
* whether to write the file to the legacy product dir or the
* Java-based product dir
* @return true if the file was successfully written, false otherwise
*/
private void writeFile(HPEDhrMessage message)
throws FileNotFoundException, IOException {
private boolean writeFile(HPEDhrMessage message, boolean legacy) {
String dtype = message.getDtype();
String outname = dtype + message.getRadarId() + "." + message.getDt();
String dirToken = DHR.equals(dtype) ? DHR_PROD_DIR : DSP_PROD_DIR;
String outPath;
if (dtype.equals(DHR)) {
outPath = appsDefaults.getToken(DHR_PROD_DIR);
if (legacy) {
outPath = appsDefaults.getToken(dirToken);
} else {
outPath = appsDefaults.getToken(DSP_PROD_DIR);
}
File oP = new File(outPath);
if (!oP.exists()) {
com.raytheon.uf.common.util.file.Files.createDirectories(
oP.toPath(),
FilePermissionConstants.POSIX_DIRECTORY_ATTRIBUTES);
Path path = AppsDefaultsConversionWrapper
.getPathForTokenWithoutCreating(dirToken);
outPath = path.toAbsolutePath().toString();
}
byte[] fileContents = message.getData();
int offset = findStartRadarData(new String(fileContents, 0, 80));
String outFile = FileUtil.join(outPath, outname);
try (OutputStream os = IOPermissionsHelper.getOutputStream(
new File(outFile).toPath(),
FilePermissionConstants.POSIX_FILE_SET);
BufferedOutputStream bos = new BufferedOutputStream(os)) {
bos.write(fileContents, offset, fileContents.length - offset);
try {
File oP = new File(outPath);
if (!oP.exists()) {
com.raytheon.uf.common.util.file.Files.createDirectories(
oP.toPath(),
FilePermissionConstants.POSIX_DIRECTORY_ATTRIBUTES);
}
byte[] fileContents = message.getData();
int offset = findStartRadarData(new String(fileContents, 0, 80));
String outFile = FileUtil.join(outPath, outname);
try (OutputStream os = IOPermissionsHelper.getOutputStream(
new File(outFile).toPath(),
FilePermissionConstants.POSIX_FILE_SET);
BufferedOutputStream bos = new BufferedOutputStream(os)) {
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
* determines whether or not this file is a DHR radar file. If it is, a
* message is sent to a JMS queue so it is later ingested.
*
* Route endpoint for "dhrDspIngestFilter". Reads the given file to memory
* and determines whether or not this file is a DHR/DSP radar file. If it
* is, a message is sent to a JMS queue so it is later ingested.
*
* @param fileContents
* The radar file content
* @param headers
@ -239,9 +264,12 @@ public class HPEDhrSrv {
/**
* Takes the given parameters and constructs a <code>HPEDhrMessage</code> to
* be placed onto the queue used by <code>HPEDhrSrv</code> for actual data
* processing.
*
* be placed onto the appropriate queues used by <code>HPEDhrSrv</code> for
* 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
* The contents of the radar file.
* @param radid
@ -261,13 +289,20 @@ public class HPEDhrSrv {
String dt) throws SerializationException, EdexException {
HPEDhrMessage message = new HPEDhrMessage(data, radid, dtype, dt);
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.
*/
private void runGatherScripts() {
private void runLegacyGatherScripts() {
int exitValue = MainMethod.runProgram(KSH,
appsDefaults.getToken(PPROC_BIN) + File.separatorChar
+ DSP_GATHER);
@ -295,7 +330,7 @@ public class HPEDhrSrv {
/**
* Given a radar file name and file header, this function determines whether
* or not this file is a DHR radar file.
*
*
* @param fileName
* The name of the radar file
* @param fileHeader
@ -355,7 +390,7 @@ public class HPEDhrSrv {
/**
* Given the header data from a radar file, this function determines the
* ending offset of the WMO header.
*
*
* @param headerInfo
* The header data from a radar file.
* @return Returns the offset after the last character in the WMO header.

View file

@ -54,9 +54,8 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator;
* Apr 01, 2011 dhladky Initial creation
* July 13, 2012 dhladky Revamped to help memory
* 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
* 03/07/17 DR 11861 lshi FFMP use of QPF in Basin Table
*
* </pre>
*
@ -344,7 +343,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null
&& values.getQpes() != null) {
tempVal = FFMPUtils.getMaxRatioValue(
values.getQpes(), null, values.getGuids());
values.getQpes(), values.getGuids());
}
} else if (attribute.getAttributeName().equals(
FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) {
@ -352,7 +351,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null
&& values.getQpes() != null) {
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
&& values.getQpes() != null) {
val = FFMPUtils.getMaxRatioValue(values.getQpes(), null,
val = FFMPUtils.getMaxRatioValue(values.getQpes(),
values.getGuids());
}
@ -411,7 +410,7 @@ public class FFTI implements Runnable {
if (values.getGuids() != null
&& values.getQpes() != null) {
val = FFMPUtils.getMaxDiffValue(values.getQpes(), null,
val = FFMPUtils.getMaxDiffValue(values.getQpes(),
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;
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.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;
import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGather;
import com.raytheon.uf.edex.plugin.mpe.gather.MpeRadarGatherConstants;
/**
* Replacement for the DHRgather script. The DHRgather script does not perform
* 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.
* Replacement for the DHRgather script.
*
* <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.
* Jan 10, 2016 6058 bkowal Silently ignore invalid DHR input files. Do not fully
* 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>
*
* @author bkowal
*/
public class DHRGather extends MpeRadarGather {
public class DHRGather {
private final Logger logger = LoggerFactory.getLogger(getClass());
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);
}
public DHRGather() {
super(MpeRadarGatherConstants.DHR_PRODUCT_TYPE,
MpeRadarGatherConstants.AppsDefaults.DHR_PROD_DIR);
}
}

View file

@ -48,6 +48,8 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarInputException;
* Nov 22, 2016 5588 nabowle Initial creation
* Dec 14, 2016 5588 nabowle Fix negative values. Round to 3 decimals
* to match legacy.
* Jul 19, 2018 5588 mapeters Change rounding to truncating to match
* legacy
*
* </pre>
*
@ -56,7 +58,11 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarInputException;
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();
@ -120,14 +126,14 @@ public class DSPDecoder extends MpeRadarDecoder<DSPRadarFile> {
for (int j = 0; j < MpeRadarDecodeConstants.MAX_JHRAP; j++) {
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) {
return Math.round(f * ROUND_FACTOR) / ROUND_FACTOR;
private float truncateFloat(float f) {
return (int) (f * TRUNCATE_FACTOR) / TRUNCATE_FACTOR;
}
@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
* ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation
* Jul 19, 2018 5588 mapeters Fix parsing of maxPrecipValue
*
* </pre>
*
@ -44,8 +45,6 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarProductDescription;
public class DSPProductDescription extends MpeRadarProductDescription {
private static final float PRECIP_DIVIDEND = 10.0f;
private static final class DSPDescriptionIndices {
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 MAX_PRECIP_INDEX = 21;
public static final int MAX_PRECIP_INDEX = 37;
}
private Calendar startDateTime;
@ -71,7 +70,8 @@ public class DSPProductDescription extends MpeRadarProductDescription {
private short julianBeginTime;
public DSPProductDescription(ByteBuffer buf) throws InvalidMpeRadarException {
public DSPProductDescription(ByteBuffer buf)
throws InvalidMpeRadarException {
super(buf);
}
@ -84,8 +84,7 @@ public class DSPProductDescription extends MpeRadarProductDescription {
(short) (julianBeginTime / TimeUtil.SECONDS_PER_MINUTE));
minDataLevel = data[DSPDescriptionIndices.MIN_DATA_LVL_INDEX];
dataLevelScaleFactor = data[DSPDescriptionIndices.DATA_LVL_SCALE_INDEX];
maxPrecipValue = data[DSPDescriptionIndices.MAX_PRECIP_INDEX]
/ PRECIP_DIVIDEND;
maxPrecipValue = data[DSPDescriptionIndices.MAX_PRECIP_INDEX];
}
/**

View file

@ -41,6 +41,7 @@ import com.raytheon.uf.edex.plugin.mpe.gather.radar.MpeRadarSymbologyData;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation
* Jul 24, 2018 5588 mapeters Use MpeRadarFile.BUILD_VERSION_5 constant
*
* </pre>
*
@ -122,7 +123,7 @@ public class DSPRadarFile extends MpeRadarFile<DSPProductDescription> {
adapt.setMaxZrefl(params[i++]);
adapt.setMinBirng(params[i++]);
if (getVersion() == 5) {
if (getVersion() == MpeRadarFile.BUILD_VERSION_5) {
adapt.setMaxStmspd(params[i++]);
adapt.setMaxTimdif(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 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
@ -35,6 +35,7 @@ import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 22, 2016 5588 nabowle Initial creation
* Jul 18, 2018 5588 mapeters Fix DSP dir constants
*
* </pre>
*
@ -44,13 +45,13 @@ import com.raytheon.uf.edex.plugin.mpe.gather.dhr.DHRGatherConstants;
public class MpeRadarDecodeConstants {
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_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
@ -129,7 +130,7 @@ public class MpeRadarDecodeConstants {
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() {
}

View file

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

View file

@ -25,8 +25,6 @@ import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.xml.bind.JAXBException;
import org.slf4j.Logger;
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.mpe.util.AppsDefaultsConversionWrapper;
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.SingleTypeJAXBManager;
@ -56,6 +53,8 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
* ------------ ---------- ----------- --------------------------
* Dec 01, 2016 5588 nabowle Initial creation
* 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>
*
@ -63,7 +62,9 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
*/
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;
@ -127,14 +128,14 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
"Unable to retrieve the grid dir.", e);
}
String prodDir = AppsDefaults.getInstance()
.getToken(this.appsDefaultProductDir, null);
File productDir = new File(prodDir);
if (!Files.exists(productDir.toPath())) {
Path prodDir = AppsDefaultsConversionWrapper
.getPathForTokenWithoutCreating(this.appsDefaultProductDir);
if (!Files.exists(prodDir)) {
throw new MpeRadarDecodeException(
"Unable to retrieve the product dir.");
}
File productDir = prodDir.toFile();
File[] files = productDir.listFiles();
for (File file : files) {
if (!file.isFile()) {
@ -148,17 +149,10 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
radarFile = loadRadarFile(path,
MpeRadarDecodeConstants.DEFAULT_BUILD_VERSION);
} catch (MpeRadarInputException e) {
if (AppsDefaultsConversionWrapper.parallelExecEnabled()) {
logger.info(
"{} would be deleted because it is not a valid radar file.",
path, e);
} else {
logger.info(
"{} will be deleted because it is not a valid radar file.",
path, e);
file.delete();
}
logger.info(
"{} will be deleted because it is not a valid radar file.",
path, e);
file.delete();
continue;
}
@ -175,6 +169,9 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
if (this.writeToDb) {
writeRadarRecords(radarFile);
}
// Successfully processed, delete the temp file
file.delete();
}
}
@ -206,17 +203,8 @@ public abstract class MpeRadarDecoder<T extends MpeRadarFile<?>> {
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()) {
MpeRadarDecoderConfig config = jaxb.unmarshalFromInputStream(is);
MpeRadarDecoderConfig config = JAXB.unmarshalFromInputStream(is);
this.writeToDb = config.getWriteToDB();
logger.debug("Configuration from {} has been read.",
this.configFile);

View file

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