Omaha #3756 Add configurable precipitation accumulation grib post processor.

Change-Id: I8cf2a4f3e06f0645fc2348e1a8068f0ef8ce63a8

Former-commit-id: d731f3e21b9c1eac5659ac44de90cfab1013b71b
This commit is contained in:
Nathan Bowler 2015-10-06 13:43:24 -04:00
parent e198c9a4e0
commit d686433642
34 changed files with 1663 additions and 1494 deletions

View file

@ -32,6 +32,7 @@ fi
let "MAX_MEM = GRIB_DECODE_THREADS * 128" # in Meg let "MAX_MEM = GRIB_DECODE_THREADS * 128" # in Meg
let "GRIB_MAX_GRID_POINTS = GRIB_DECODE_THREADS * 25000000" let "GRIB_MAX_GRID_POINTS = GRIB_DECODE_THREADS * 25000000"
let "GRID_PERSIST_THREADS = GRIB_DECODE_THREADS / 2" let "GRID_PERSIST_THREADS = GRIB_DECODE_THREADS / 2"
let "GRID_POSTPROCESS_THREADS = 1"
let "GRID_MAX_PERSIST_MEMORY_IN_MB = GRID_PERSIST_THREADS * 50" let "GRID_MAX_PERSIST_MEMORY_IN_MB = GRID_PERSIST_THREADS * 50"
export INIT_MEM=128 # in Meg export INIT_MEM=128 # in Meg
@ -39,6 +40,7 @@ export MAX_MEM
export GRIB_DECODE_THREADS export GRIB_DECODE_THREADS
export GRIB_MAX_GRID_POINTS export GRIB_MAX_GRID_POINTS
export GRID_PERSIST_THREADS export GRID_PERSIST_THREADS
export GRID_POSTPROCESS_THREADS
export GRID_MAX_PERSIST_MEMORY_IN_MB export GRID_MAX_PERSIST_MEMORY_IN_MB
export METADATA_POOL_MAX=10 export METADATA_POOL_MAX=10

View file

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import com.raytheon.edex.plugin.grib.decoderpostprocessors.IDecoderPostProcessor; import com.raytheon.edex.plugin.grib.decoderpostprocessors.DecoderPostProcessor;
import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.dataplugin.grid.GridRecord;
@ -16,23 +16,24 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/** /**
* Abstract class to generate 1-hour precip grids * Abstract class to generate 1-hour precip grids
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ------------- -------------------------- * ------------- -------- ------------- --------------------------
* Sep 05, 2014 M. Foster Initial creation * Sep 05, 2014 M. Foster Initial creation
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
*
* </pre> * </pre>
* *
* @author matthew.foster * @author matthew.foster
* @version 1.0 * @version 1.0
* *
*/ */
public abstract class OneHrPrecipGridProcessor implements IDecoderPostProcessor { public abstract class OneHrPrecipGridProcessor extends DecoderPostProcessor {
/** The number of seconds in 1 hour */ /** The number of seconds in 1 hour */
protected static final int SECONDS_IN_1_HR = 3600; protected static final int SECONDS_IN_1_HR = 3600;

View file

@ -0,0 +1,38 @@
#!/bin/bash
# AWIPS2 #3756
#
# Updates the non-base postProcessedModels.xml localization files to replace
# precipitation post-processors that have been removed from the baseline with
# the configurable PrecipAccumPostProcessor.
#
#
for file in `find /awips2/edex/data/utility/edex_static/ -name postProcessedModels.xml`
do
level=`echo $file | cut -f 7 -d '/'`
if [ $level != 'base' ] # base is assumed to be correct as deployed.
then
checkForUpdate=`grep PrecipAccumPostProcessor $file`
if [ "${checkForUpdate}" == "" ]
then
echo "Updating $file"
# create a copy of the file with the changes in a temporary file
newFile="${file}_`date +%s`.dr3756"
cat $file | sed 's/com.raytheon.edex.plugin.grib.decoderpostprocessors.//g' | sed -r 's/Nam80PostProcessor|CanadianNHPostProcessor|CanadianRegPostProcessor|gov.noaa.nws.crh.edex.grib.decoderpostprocessor.GFS20PostProcessor/PrecipAccumPostProcessor/g' | sed 's/<processorName>ECMWFHiResProcessor<\/processorName>/<processorName>ECMWFHiResProcessor<\/processorName>\n <processorName>PrecipAccumPostProcessor<\/processorName>/g' > $newFile
if [ -s $newFile ]
then
chmod --reference=$file $newFile
chown --reference=$file $newFile
mv $newFile $file
else
echo "Failed to update $file"
if [ -e $newFile ]
then
rm $newFile
fi
fi
else
echo "$file has already been updated and will be skipped."
fi
fi
done

View file

@ -25,23 +25,20 @@
<list> <list>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.ARIPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.ARIPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.CPCoutlookGribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.CPCoutlookGribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianNHPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianRegPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.ECMWFHiResProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.ECMWFHiResProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.GFSProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.HPCqpfPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.HPCqpfPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.HWRFPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.HWRFPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.LapsPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.LapsPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.MSASPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.MSASPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.Nam80PostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RTMAGribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RTMAGribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC130GribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC130GribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC236GribPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC236GribPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.TemperatureCorrectionPostProcessor</value> <value>com.raytheon.edex.plugin.grib.decoderpostprocessors.TemperatureCorrectionPostProcessor</value>
<value>com.raytheon.edex.plugin.grib.decoderpostprocessors.precipitation.PrecipAccumPostProcessor</value>
</list> </list>
</property> </property>
</bean> </bean>
@ -75,6 +72,7 @@
<endpoint id="gribSplitJmsEndpoint" uri="jms-durable:queue:Ingest.GribSplit?concurrentConsumers=${GRIB_SPLIT_THREADS}"/> <endpoint id="gribSplitJmsEndpoint" uri="jms-durable:queue:Ingest.GribSplit?concurrentConsumers=${GRIB_SPLIT_THREADS}"/>
<endpoint id="gribDecodeJmsEndpoint" uri="jms-durable:queue:Ingest.GribDecode?concurrentConsumers=${GRIB_DECODE_THREADS}"/> <endpoint id="gribDecodeJmsEndpoint" uri="jms-durable:queue:Ingest.GribDecode?concurrentConsumers=${GRIB_DECODE_THREADS}"/>
<endpoint id="gridPostProcessesJmsEndpoint" uri="jms-durable:queue:Grid.PostProcess?concurrentConsumers=${GRID_POSTPROCESS_THREADS}"/>
<!-- Begin Grib Decode Route --> <!-- Begin Grib Decode Route -->
<route id="gribSplitIngestRoute"> <route id="gribSplitIngestRoute">
@ -139,5 +137,25 @@
</split> </split>
</multicast> </multicast>
</route> </route>
<!--
Does a second round of post processing to generate new records
derived from recently persisted records.
-->
<route id="gridPostProcessRoute">
<from ref="gridPostProcessesJmsEndpoint" />
<doTry>
<pipeline>
<bean ref="serializationUtil" method="transformFromThrift" />
<!-- send for processing -->
<bean ref="gribPostProcessor" method="processPersisted" />
<bean ref="gridPersister" method="persist"/>
</pipeline>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:grib?level=ERROR"/>
</doCatch>
</doTry>
</route>
</camelContext> </camelContext>
</beans> </beans>

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -34,6 +34,7 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Sep 21, 2015 4756 dhladky Initial Creation * Sep 21, 2015 4756 dhladky Initial Creation
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* </pre> * </pre>
* *
@ -41,53 +42,53 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
* @version 1 * @version 1
* */ * */
public class ARIPostProcessor implements IDecoderPostProcessor { public class ARIPostProcessor extends DecoderPostProcessor {
/** name of extraAttribute variable from GribDecoder.py */ /** name of extraAttribute variable from GribDecoder.py */
private static final String FORECAST_INTERVAL = "forecastInterval"; private static final String FORECAST_INTERVAL = "forecastInterval";
/** name of extraAttribute variable from GribDecoder.py */ /** name of extraAttribute variable from GribDecoder.py */
private static final String FORECAST_INTERVAL_UNIT = "forecastIntervalUnit"; private static final String FORECAST_INTERVAL_UNIT = "forecastIntervalUnit";
/** 30 minute record identifier **/ /** 30 minute record identifier **/
private static final String REFZC = "REFZC"; private static final String REFZC = "REFZC";
/** 1 hr record identifier **/ /** 1 hr record identifier **/
private static final String REFZI = "REFZI"; private static final String REFZI = "REFZI";
/** 3 hr record identifier **/ /** 3 hr record identifier **/
private static final String RETOP = "RETOP"; private static final String RETOP = "RETOP";
/** 6 hr record identifier **/ /** 6 hr record identifier **/
private static final String REFD = "REFD"; private static final String REFD = "REFD";
/** 12 hr record identifier **/ /** 12 hr record identifier **/
private static final String REFC = "REFC"; private static final String REFC = "REFC";
/** Year **/ /** Year **/
private static final String YR = "YR"; private static final String YR = "YR";
/** ARI (Archival Recurrence Interval **/ /** ARI (Archival Recurrence Interval **/
private static final String ARI = "ARI"; private static final String ARI = "ARI";
/** 30 min comparison time **/ /** 30 min comparison time **/
private static final String MIN30 = "30"; private static final String MIN30 = "30";
/** 1 hour comparison time **/ /** 1 hour comparison time **/
private static final String HOUR1 = "1"; private static final String HOUR1 = "1";
/** 3 hour comparison time **/ /** 3 hour comparison time **/
private static final String HOUR3 = "3"; private static final String HOUR3 = "3";
/** 6 hour comparison time **/ /** 6 hour comparison time **/
private static final String HOUR6 = "6"; private static final String HOUR6 = "6";
/** 12 hour comparison time **/ /** 12 hour comparison time **/
private static final String HOUR12 = "12"; private static final String HOUR12 = "12";
/** ARI is precip in mm **/ /** ARI is precip in mm **/
private static final String UNIT = "mm"; private static final String UNIT = "mm";
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {
@ -123,7 +124,7 @@ public class ARIPostProcessor implements IDecoderPostProcessor {
/** /**
* Create a new parameter abbreviation based on the forecast year and * Create a new parameter abbreviation based on the forecast year and
* interval period. * interval period.
* *
* @param record * @param record
* @param forecastYear * @param forecastYear
* @return * @return
@ -160,13 +161,12 @@ public class ARIPostProcessor implements IDecoderPostProcessor {
throw new IllegalArgumentException("ARI paramName " + paramAbbrev throw new IllegalArgumentException("ARI paramName " + paramAbbrev
+ " is not a valid param for ARI postprocessing"); + " is not a valid param for ARI postprocessing");
} }
// Give it a new name/description/unit // Give it a new name/description/unit
record.getParameter().setAbbreviation(sb.toString()); record.getParameter().setAbbreviation(sb.toString());
record.getParameter().setName(sb2.toString()); record.getParameter().setName(sb2.toString());
record.getParameter().setUnitString(UNIT); record.getParameter().setUnitString(UNIT);
return record; return record;
} }
} }

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -49,13 +49,14 @@ import com.raytheon.uf.common.time.DataTime;
* Mar 09, 2011 4243 porricel Initial Creation * Mar 09, 2011 4243 porricel Initial Creation
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Oct 15, 2013 2473 bsteffen Removed deprecated and unused code. * Oct 15, 2013 2473 bsteffen Removed deprecated and unused code.
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* </pre> * </pre>
* *
* @author * @author
* @version * @version
*/ */
public class CPCoutlookGribPostProcessor implements IDecoderPostProcessor { public class CPCoutlookGribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {

View file

@ -1,183 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Grib post processor implementation to generate 6-hr precipitation grids from
* run accumulated total precipitation
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 18, 2012 porricel Initial Creation
* Oct 15, 2013 2473 bsteffen Removed unused method argument.
*
* </pre>
*
* @author bphillip
* @version 1
*/
public class CanadianNHPostProcessor extends SixHrPrecipGridProcessor {
@Override
public GridRecord[] process(GridRecord record) throws GribException {
// Post process the data if this is a Total Precipitation grid
if (record.getParameter().getAbbreviation().equals("TPrun")) {
return super.process(record);
}
return new GridRecord[] { record };
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<GridRecord> getPrecipInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TPrun");
query.addQueryParam(GridConstants.DATASET_ID, "Canadian-NH");
query.addQueryParam("dataTime.refTime", refTime);
query.addOrder("dataTime.fcstTime", true);
try {
return (List<GridRecord>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for Canadian-NH!", e);
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<Integer> getPrecip6hrInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TP6hr");
query.addQueryParam(GridConstants.DATASET_ID, "Canadian-NH");
query.addQueryParam("dataTime.refTime", refTime);
query.addReturnedField("dataTime.fcstTime");
try {
return (List<Integer>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for Canadian-NH!", e);
}
}
/**
* Generates the 6 hour accumulated grid from the run accumulated
* precipitation grids. This function will look in the inventory and
* generate any 6 hr grids that can be generated.
*
* @param record
* The grib record for which to generate the 6 hour accumulated
* precipitation grid
* @return The generated 6-hr precipitation grids
* @throws GribException
*/
protected synchronized GridRecord[] generate6hrPrecipGrids(GridRecord record)
throws GribException {
// The current run accumulated precipitation grid inventory in the
// database
List<GridRecord> precipInventory = getPrecipInventory(record
.getDataTime().getRefTime());
// The current 6-hr precipitation grid inventory in the database
List<Integer> precip6hrInventory = getPrecip6hrInventory(record
.getDataTime().getRefTime());
// Adds the current record to the precip inventory
float[] currentData = (float[]) record.getMessageData();
record.setMessageData(currentData);
precipInventory.add(record);
// Examine each grid in the inventory and generate the 6hr precipitation
// grid if possible
List<GridRecord> generatedRecords = new ArrayList<GridRecord>();
for (int i = 0; i < precipInventory.size(); i++) {
// Check if the 6hr precipitation grid has already been produced
if (!precip6hrInventory.contains(precipInventory.get(i)
.getDataTime().getFcstTime())) {
// If the precipitation grid has not been produced, generate it
List<GridRecord> generated6hrPrecips = generate6hrPrecip(
precipInventory.get(i), precipInventory);
for (GridRecord newRecord : generated6hrPrecips) {
// Add the generated grid to the current inventory
if (newRecord != null) {
precip6hrInventory.add(newRecord.getDataTime()
.getFcstTime());
generatedRecords.add(newRecord);
}
}
}
}
return generatedRecords.toArray(new GridRecord[] {});
}
/**
* Calculates the new data by subtracting the previous inventory data from
* the current data
*
* @param inventoryData
* The data from the previous precipitation record
* @param newData
* The data from the current precipitation record
*/
protected void calculatePrecipValues(float[] inventoryData, float[] newData) {
for (int i = 0; i < inventoryData.length; i++) {
newData[i] = newData[i] - inventoryData[i];
if (newData[i] < 0) {
newData[i] = 0;
}
}
}
}

View file

@ -1,184 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Grib post processor implementation to generate 3-hr precipitation grids from
* run accumulated total precipitation
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 18, 2012 porricel Initial Creation
* Oct 15, 2013 2473 bsteffen Removed unused method argument.
*
*
* </pre>
*
* @author bphillip
* @version 1
*/
public class CanadianRegPostProcessor extends ThreeHrPrecipGridProcessor {
@Override
public GridRecord[] process(GridRecord record) throws GribException {
// Post process the data if this is a Total Precipitation grid
if (record.getParameter().getAbbreviation().equals("TPrun")) {
return super.process(record);
}
return new GridRecord[] { record };
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<GridRecord> getPrecipInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TPrun");
query.addQueryParam(GridConstants.DATASET_ID, "Canadian-Reg");
query.addQueryParam("dataTime.refTime", refTime);
query.addOrder("dataTime.fcstTime", true);
try {
return (List<GridRecord>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for Canadian-Reg!", e);
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<Integer> getPrecip3hrInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TP3hr");
query.addQueryParam(GridConstants.DATASET_ID, "Canadian-Reg");
query.addQueryParam("dataTime.refTime", refTime);
query.addReturnedField("dataTime.fcstTime");
try {
return (List<Integer>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for Canadian-Reg!", e);
}
}
/**
* Generates the 3 hour accumulated grid from the run accumulated
* precipitation grids. This function will look in the inventory and
* generate any 3 hr grids that can be generated.
*
* @param record
* The grib record for which to generate the 3 hour accumulated
* precipitation grid
* @return The generated 3-hr precipitation grids
* @throws GribException
*/
protected synchronized GridRecord[] generate3hrPrecipGrids(GridRecord record)
throws GribException {
// The current run accumulated precipitation grid inventory in the
// database
List<GridRecord> precipInventory = getPrecipInventory(record
.getDataTime().getRefTime());
// The current 3-hr precipitation grid inventory in the database
List<Integer> precip3hrInventory = getPrecip3hrInventory(record
.getDataTime().getRefTime());
// Adds the current record to the precip inventory
float[] currentData = (float[]) record.getMessageData();
record.setMessageData(currentData);
precipInventory.add(record);
// Examine each grid in the inventory and generate the 3hr precipitation
// grid if possible
List<GridRecord> generatedRecords = new ArrayList<GridRecord>();
for (int i = 0; i < precipInventory.size(); i++) {
// Check if the 3hr precipitation grid has already been produced
if (!precip3hrInventory.contains(precipInventory.get(i)
.getDataTime().getFcstTime())) {
// If the precipitation grid has not been produced, generate it
List<GridRecord> generated3hrPrecips = generate3hrPrecip(
precipInventory.get(i), precipInventory);
for (GridRecord newRecord : generated3hrPrecips) {
// Add the generated grid to the current inventory
if (newRecord != null) {
precip3hrInventory.add(newRecord.getDataTime()
.getFcstTime());
generatedRecords.add(newRecord);
}
}
}
}
return generatedRecords.toArray(new GridRecord[] {});
}
/**
* Calculates the new data by subtracting the previous inventory data from
* the current data
*
* @param inventoryData
* The data from the previous precipitation record
* @param newData
* The data from the current precipitation record
*/
protected void calculatePrecipValues(float[] inventoryData, float[] newData) {
for (int i = 0; i < inventoryData.length; i++) {
newData[i] = newData[i] - inventoryData[i];
if (newData[i] < 0) {
newData[i] = 0;
}
}
}
}

View file

@ -0,0 +1,114 @@
/**
* 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.edex.plugin.grib.decoderpostprocessors;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Grib decoder post processor interface
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 8/30/10 5875 bphillip Initial Creation
* Oct 07, 2015 3756 nabowle Switch interface to abstract class,
* rename from IDecoderPostProcessor, add
* getMessageData(), getType(), and
* relevant enum,
*
* </pre>
*
* @author bphillip
* @version 1
*/
public abstract class DecoderPostProcessor {
/**
* Processes the provided record to see if it needs to be post processed
*
* @param record
* The record to examine to determine if it needs to be post
* processed
* @return The array of grib records including any created during post
* processing
* @throws GribException
*/
public abstract GridRecord[] process(GridRecord record)
throws GribException;
/** Get the type of post processor. Defaults to {@link #PRE_PERSIST}. */
public PostProcessorType getType() {
return PostProcessorType.PRE_PERSIST;
}
/**
* Gets the message data for a record. If the record's messagedata is null,
* the data will be retrieved from the data store, set on the record, and
* returned.
*
* @param record
* The record to get the message data for.
* @return
* @throws GribException
*/
protected float[] getMessageData(GridRecord record) throws GribException {
float[] data = (float[]) record.getMessageData();
if (data == null) {
GridDao dao = null;
try {
dao = new GridDao();
record.setMessageData(((FloatDataRecord) dao.getHDF5Data(
record, -1)[0]).getFloatData());
data = (float[]) record.getMessageData();
} catch (PluginException e) {
throw new GribException("Error populating grib data", e);
}
}
return data;
}
/**
* Defines the types of IDecoderPostProcessors.
*
* It is expected that {@link #POST_PERSIST} processors do not return the
* input record.
*/
public static enum PostProcessorType {
/**
* Processors that process a GridRecord that was just decoded and before
* being persisted.
*/
PRE_PERSIST,
/**
* Processors that process a GridRecord after it was persisted. It is
* expected these processors do not return the input record.
*/
POST_PERSIST
}
}

View file

@ -1,187 +1,59 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
package com.raytheon.edex.plugin.grib.decoderpostprocessors; package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/** /**
* Grib post processor implementation to generate 6-hr precipitation grids from * Grib post processor implementation to scale TP-ECMWF data to the proper unit.
* run accumulated total precipitation *
*
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Aug 30, 2010 5875 bphillip Initial Creation * Aug 30, 2010 5875 bphillip Initial Creation
* Oct 15, 2013 2473 bsteffen Removed unused method argument. * Oct 15, 2013 2473 bsteffen Removed unused method argument.
* * Oct 07, 2015 3756 nabowle Changed to only do data scaling. Extends
* * DecoderPostProcessor.
*
*
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class ECMWFHiResProcessor extends SixHrPrecipGridProcessor { public class ECMWFHiResProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {
// Post process the data if this is a Total Precipitation grid // Post process the data if this is a Total Precipitation grid
if (record.getParameter().getAbbreviation().equals("TP-ECMWF")) { if (record.getParameter().getAbbreviation().equals("TP-ECMWF")) {
return super.process(record); float[] data = getMessageData(record);
for (int i = 0; i < data.length; i++) {
data[i] = data[i] * 1000;
}
} }
return new GridRecord[] { record }; return new GridRecord[] { record };
} }
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<GridRecord> getPrecipInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TP-ECMWF");
query.addQueryParam(GridConstants.DATASET_ID, "ECMWF-HiRes");
query.addQueryParam("dataTime.refTime", refTime);
query.addOrder("dataTime.fcstTime", true);
try {
return (List<GridRecord>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for ECMWF!", e);
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected List<Integer> getPrecip6hrInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TP6hr");
query.addQueryParam(GridConstants.DATASET_ID, "ECMWF-HiRes");
query.addQueryParam("dataTime.refTime", refTime);
query.addReturnedField("dataTime.fcstTime");
try {
return (List<Integer>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for ECMWF!", e);
}
}
/**
* Generates the 6 hour accumulated grid from the run accumulated
* precipitation grids. This function will look in the inventory and
* generate any 6 hr grids that can be generated.
*
* @param record
* The grib record for which to generate the 6 hour accumulated
* precipitation grid
* @return The generated 6-hr precipitation grids
* @throws GribException
*/
protected synchronized GridRecord[] generate6hrPrecipGrids(GridRecord record)
throws GribException {
// The current run accumulated precipitation grid inventory in the
// database
List<GridRecord> precipInventory = getPrecipInventory(record
.getDataTime().getRefTime());
// The current 6-hr precipitation grid inventory in the database
List<Integer> precip6hrInventory = getPrecip6hrInventory(record
.getDataTime().getRefTime());
// Adds the current record to the precip inventory
float[] currentData = (float[]) record.getMessageData();
for (int i = 0; i < currentData.length; i++) {
currentData[i] = currentData[i] * 1000;
}
record.setMessageData(currentData);
precipInventory.add(record);
// Examine each grid in the inventory and generate the 6hr precipitation
// grid if possible
List<GridRecord> generatedRecords = new ArrayList<GridRecord>();
for (int i = 0; i < precipInventory.size(); i++) {
// Check if the 6hr precipitation grid has already been produced
if (!precip6hrInventory.contains(precipInventory.get(i)
.getDataTime().getFcstTime())) {
// If the precipitation grid has not been produced, generate it
List<GridRecord> generated6hrPrecips = generate6hrPrecip(
precipInventory.get(i), precipInventory);
for (GridRecord newRecord : generated6hrPrecips) {
// Add the generated grid to the current inventory
if (newRecord != null) {
precip6hrInventory.add(newRecord.getDataTime()
.getFcstTime());
generatedRecords.add(newRecord);
}
}
}
}
return generatedRecords.toArray(new GridRecord[] {});
}
/**
* Calculates the new data by subtracting the previous inventory data from
* the current data
*
* @param inventoryData
* The data from the previous precipitation record
* @param newData
* The data from the current precipitation record
*/
protected void calculatePrecipValues(float[] inventoryData, float[] newData) {
for (int i = 0; i < inventoryData.length; i++) {
newData[i] = newData[i] - inventoryData[i];
if (newData[i] < 0) {
newData[i] = 0;
}
}
}
} }

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -51,11 +51,11 @@ import com.raytheon.uf.edex.plugin.grid.PartialGrid;
* The EnsembleGridAssembler class is part of the ingest process for grib data. * The EnsembleGridAssembler class is part of the ingest process for grib data.
* Some grib model come in as octants. This class will combine those octants * Some grib model come in as octants. This class will combine those octants
* into a single grid * into a single grid
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Apr 09, 2010 4638 bphillip Initial Creation * Apr 09, 2010 4638 bphillip Initial Creation
@ -70,12 +70,13 @@ import com.raytheon.uf.edex.plugin.grid.PartialGrid;
* Jul 21, 2014 3373 bclement JAXB manager api changes * Jul 21, 2014 3373 bclement JAXB manager api changes
* Aug 18, 2014 4360 rferrel Set secondaryId in {@link #createAssembledRecord(GridRecord, CompositeModel)} * Aug 18, 2014 4360 rferrel Set secondaryId in {@link #createAssembledRecord(GridRecord, CompositeModel)}
* Sep 09, 2015 4868 rjpeter Updated to be stored in partial grids as part of normal route. * Sep 09, 2015 4868 rjpeter Updated to be stored in partial grids as part of normal route.
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class EnsembleGridAssembler implements IDecoderPostProcessor { public class EnsembleGridAssembler extends DecoderPostProcessor {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(EnsembleGridAssembler.class); .getHandler(EnsembleGridAssembler.class);
@ -145,7 +146,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor {
/** /**
* Gets the composite model for the provided model name0 * Gets the composite model for the provided model name0
* *
* @param modelName * @param modelName
* The model name to determine the composite model name for * The model name to determine the composite model name for
* @return The composite model. Null if not found * @return The composite model. Null if not found
@ -175,7 +176,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor {
/** /**
* Merges the data from a GridRecord into the composite GridRecord * Merges the data from a GridRecord into the composite GridRecord
* *
* @param record * @param record
* The GridRecord containing the data to add * The GridRecord containing the data to add
* @param assembledRecord * @param assembledRecord
@ -216,7 +217,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor {
pGrid.setxOffset((nx * modIndex) - modIndex); pGrid.setxOffset((nx * modIndex) - modIndex);
pGrid.setyOffset(0); pGrid.setyOffset(0);
assembledRecord.addExtraAttribute(PartialGrid.KEY, pGrid); assembledRecord.addExtraAttribute(PartialGrid.KEY, pGrid);
assembledRecord.setMessageData(recordToAssemble.getMessageData()); assembledRecord.setMessageData(getMessageData(recordToAssemble));
return checkWorldWrap(assembledRecord); return checkWorldWrap(assembledRecord);
} }
@ -225,7 +226,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor {
* Checks if assembledRecord's partial grid has extra columns that wrap * Checks if assembledRecord's partial grid has extra columns that wrap
* around. This is due to partial grids having 1 column of overlap between * around. This is due to partial grids having 1 column of overlap between
* each partial grid. * each partial grid.
* *
* @param assembledRecord * @param assembledRecord
* @return * @return
*/ */
@ -278,5 +279,4 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor {
return Util.resizeDataTo1D(rval, ny, nx); return Util.resizeDataTo1D(rval, ny, nx);
} }
} }

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -43,13 +43,14 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
* Mar 26, 2013 1821 bsteffen Optimize FFG version query. * Mar 26, 2013 1821 bsteffen Optimize FFG version query.
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls. * Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
* Apr 25, 2014 2060 njensen Remove dependency on grid dataURI column * Apr 25, 2014 2060 njensen Remove dependency on grid dataURI column
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class FFGGribPostProcessor implements IDecoderPostProcessor { public class FFGGribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {

View file

@ -1,226 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataquery.db.QueryParam.QueryOperand;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.parameter.Parameter;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Used to generate 6hr record from 12hr intervals.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 25, 2011 rgeorge Initial creation
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
*
* </pre>
*
* @author rgeorge
* @version 1.0
*/
public class GFSProcessor extends SixHrPrecipGridProcessor {
private static final int SECONDS_IN_12_HRS = 43200;
@Override
public GridRecord[] process(GridRecord record) throws GribException {
// Post process the data if this is a Total Precipitation grid
if (record.getParameter().getAbbreviation().equals("TP12hr")
&& ((record.getDataTime().getFcstTime() / 3600) > 180)) {
return super.process(record);
}
return new GridRecord[] { record };
}
/**
* Generates the 6 hour accumulated grid from the run accumulated
* precipitation grids. This function will look in the inventory and
* generate any 6 hr grids that can be generated.
*
* @param record
* The grib record for which to generate the 6 hour accumulated
* precipitation grid
* @return The generated 6-hr precipitation grids
* @throws GribException
*/
@Override
protected synchronized GridRecord[] generate6hrPrecipGrids(GridRecord record)
throws GribException {
List<GridRecord> generated6hrPrecips = new ArrayList<GridRecord>();
// Get all 6hr records 180Hrs and greater
List<GridRecord> precipInventory = getPrecipInventory(record
.getDataTime().getRefTime());
List<GridRecord> generatedRecords = new ArrayList<GridRecord>();
// convert current record to 6hr and add it
GridRecord transformed = transForm12to6(record);
generated6hrPrecips.add(transformed);
precipInventory.add(transformed);
Comparator<GridRecord> comparator = new Comparator<GridRecord>() {
@Override
public int compare(GridRecord o1, GridRecord o2) {
int retValue = 0;
if (o1 != o2) {
retValue = Double.compare(o1.getDataTime().getFcstTime(),
o2.getDataTime().getFcstTime());
}
return retValue;
}
};
Collections.sort(precipInventory, comparator);
// loop through set, find twelve hour gaps and create new 6hr records.
for (int i = 0; i < (precipInventory.size() - 1); i++) {
GridRecord sequence1Record = precipInventory.get(i);
GridRecord sequence2Record = precipInventory.get(i + 1);
if (sequence1Record.getDataTime().getFcstTime() == (sequence2Record
.getDataTime().getFcstTime() - SECONDS_IN_12_HRS)) {
// we have a 12Hr gap
generated6hrPrecips.add(calculate6hrPrecip(sequence1Record,
sequence2Record));
}
}
for (GridRecord newRecord : generated6hrPrecips) {
// Add the generated grid to the current inventory
if (newRecord != null) {
generatedRecords.add(newRecord);
}
}
return generatedRecords.toArray(new GridRecord[] {});
}
@SuppressWarnings("unchecked")
protected List<GridRecord> getPrecipInventory(Date refTime)
throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "TP6hr",
QueryOperand.IN);
query.addQueryParam(GridConstants.DATASET_ID, "GFS213");
query.addQueryParam("dataTime.refTime", refTime);
query.addQueryParam("dataTime.fcstTime", 648000,
QueryOperand.GREATERTHANEQUALS);
query.addOrder("dataTime.fcstTime", true);
try {
return (List<GridRecord>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException(
"Error getting Precip inventory for ECMWF!", e);
}
}
private GridRecord transForm12to6(GridRecord currentRecord)
throws GribException {
// Clone the current record and set the ID to 0 so Hibernate will
// recognize it as a new record
GridRecord tp6hrRecord = new GridRecord(currentRecord);
tp6hrRecord.setId(0);
if (currentRecord.getMessageData() == null) {
GridDao dao = null;
try {
dao = new GridDao();
currentRecord.setMessageData(((FloatDataRecord) dao
.getHDF5Data(currentRecord, -1)[0]).getFloatData());
} catch (PluginException e) {
throw new GribException("Error populating grib data!", e);
}
}
// Copy the data to the new record so the data from the original record
// does not get modified
float[] currentData = (float[]) currentRecord.getMessageData();
currentRecord.setMessageData(currentData);
float[] newData = new float[currentData.length];
System.arraycopy(currentData, 0, newData, 0, currentData.length);
tp6hrRecord.setMessageData(newData);
// Assign the new parameter abbreviation and cache it if necessary
Parameter param = new Parameter("TP6hr", "Precip Accum 6 hr",
currentRecord.getParameter().getUnit());
tp6hrRecord.setParameter(param);
tp6hrRecord.getInfo().setId(null);
// Change the data time to include the 6-hr time range
super.modifyDataTime(tp6hrRecord);
return tp6hrRecord;
}
/**
* {@inheritDoc}
*/
@Override
protected void calculatePrecipValues(float[] inventoryData, float[] newData) {
for (int i = 0; i < inventoryData.length; i++) {
newData[i] = (newData[i] + inventoryData[i]) / 2;
if (newData[i] < 0) {
newData[i] = 0;
}
}
}
@Override
protected void modifyDataTime(GridRecord record) {
Calendar refTime = record.getDataTime().getRefTimeAsCalendar();
int fcstTime = record.getDataTime().getFcstTime();
// Calculate the start time by subtracting 6 hours from the reference
// time + forecast time
Calendar startTime = (Calendar) refTime.clone();
startTime.add(Calendar.SECOND, fcstTime - SECONDS_IN_6_HRS);
// Calculate the end time by adding the reference time + forecast time
Calendar endTime = (Calendar) refTime.clone();
endTime.add(Calendar.SECOND, fcstTime);
TimeRange validPeriod = new TimeRange(startTime, endTime);
DataTime newDataTime = new DataTime(refTime, fcstTime
- SECONDS_IN_6_HRS, validPeriod);
// Reset the datauri since the datauri contains the DataTime
record.setDataTime(newDataTime);
record.setDataURI(null);
}
}

View file

@ -24,15 +24,22 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
import org.apache.camel.Headers;
import com.raytheon.edex.plugin.grib.decoderpostprocessors.DecoderPostProcessor.PostProcessorType;
import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.edex.plugin.grib.util.GribModelLookup; import com.raytheon.edex.plugin.grib.util.GribModelLookup;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil;
import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.message.DataURINotificationMessage;
import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException; import com.raytheon.uf.common.localization.exception.LocalizationException;
@ -57,6 +64,8 @@ import com.raytheon.uf.common.status.UFStatus;
* Oct 15, 2013 2473 bsteffen Rewrite deprecated and unused code. * Oct 15, 2013 2473 bsteffen Rewrite deprecated and unused code.
* Sep 24, 2015 3731 nabowle Allow pre-registering shortnames and * Sep 24, 2015 3731 nabowle Allow pre-registering shortnames and
* require fully qualified names otherwise. * require fully qualified names otherwise.
* Oct 07, 2015 3756 nabowle Add separate post-processing after the
* decoded record is persisted.
* *
* </pre> * </pre>
* *
@ -64,6 +73,8 @@ import com.raytheon.uf.common.status.UFStatus;
* @version 1 * @version 1
*/ */
public class GribPostProcessor { public class GribPostProcessor {
private static final GridRecord[] EMPTY_ARR = new GridRecord[] {};
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(GribPostProcessor.class); .getHandler(GribPostProcessor.class);
@ -71,7 +82,7 @@ public class GribPostProcessor {
private static GribPostProcessor instance; private static GribPostProcessor instance;
/** The map containing the currently registered grib post processors */ /** The map containing the currently registered grib post processors */
private Map<String, List<IDecoderPostProcessor>> processorMap; private Map<String, List<DecoderPostProcessor>> processorMap;
private Map<String, String> knownProcessors = new HashMap<>(); private Map<String, String> knownProcessors = new HashMap<>();
@ -110,7 +121,7 @@ public class GribPostProcessor {
} }
} }
List<IDecoderPostProcessor> processors; List<DecoderPostProcessor> processors;
GridRecord[] results = null; GridRecord[] results = null;
List<GridRecord> additionalGrids = null; List<GridRecord> additionalGrids = null;
for (int i = 0; i < records.length; i++) { for (int i = 0; i < records.length; i++) {
@ -118,9 +129,11 @@ public class GribPostProcessor {
// which post processing is necessary // which post processing is necessary
processors = processorMap.get(records[i].getDatasetId()); processors = processorMap.get(records[i].getDatasetId());
if (processors != null) { if (processors != null) {
for (IDecoderPostProcessor processor : processors) { for (DecoderPostProcessor processor : processors) {
// Post processing is not necessary, so we continue // Post processing is not necessary, so we continue
if (processor == null) { if (processor == null
|| PostProcessorType.POST_PERSIST.equals(processor
.getType())) {
continue; continue;
} }
@ -147,12 +160,83 @@ public class GribPostProcessor {
for (int i = 0; i < records.length; i++) { for (int i = 0; i < records.length; i++) {
additionalGrids.add(records[i]); additionalGrids.add(records[i]);
} }
return additionalGrids.toArray(new GridRecord[] {}); return additionalGrids.toArray(EMPTY_ARR);
} }
} }
/** /**
* Registers the IDecoderPostProcessor classes for the supplied * Processes the GridRecords to determine if they need post processing
*
* @param notif
* A notification of datauri's that have been persisted.
* @return Only grid records created by the post processors. The records
* matching the uri's will not be returned.
* @throws GribException
*/
public GridRecord[] processPersisted(DataURINotificationMessage notif,
@Headers
Map<String, Object> headers) throws GribException {
headers.put("dequeueTime", System.currentTimeMillis());
String[] dataURIs = notif.getDataURIs();
if (dataURIs == null || dataURIs.length == 0) {
return EMPTY_ARR;
}
synchronized (this) {
if (this.processorMap == null) {
initProcessorMap();
}
}
List<DecoderPostProcessor> processors;
GridRecord[] recordResults;
Set<GridRecord> newGrids = new HashSet<>();
GridRecord record;
for (String uri : dataURIs) {
try {
record = (GridRecord) DataURIUtil.createPluginDataObject(uri);
} catch (PluginException e) {
throw new GribException(
"Could not create plugin data object for " + uri, e);
}
processors = processorMap.get(record.getDatasetId());
if (processors != null) {
for (DecoderPostProcessor processor : processors) {
if (processor == null
|| PostProcessorType.PRE_PERSIST.equals(processor
.getType())) {
continue;
}
recordResults = processor.process(record);
if (recordResults != null) {
for (GridRecord rec : recordResults) {
if (!uri.equals(rec.getDataURI())) {
newGrids.add(rec);
} else {
statusHandler
.warn(uri
+ " will not be re-persisted to prevent an infinite post-processing loop. "
+ processor.getClass()
.getName()
+ " should be of type "
+ PostProcessorType.PRE_PERSIST
.name()
+ " or should not include the post-processed record in the results.");
}
}
}
}
}
}
return newGrids.toArray(EMPTY_ARR);
}
/**
* Registers the DecoderPostProcessor classes for the supplied
* fully-qualified classnames. * fully-qualified classnames.
* *
* @param fqClassNames * @param fqClassNames
@ -160,7 +244,7 @@ public class GribPostProcessor {
*/ */
public synchronized void register(String... fqClassNames) { public synchronized void register(String... fqClassNames) {
String retClass; String retClass;
IDecoderPostProcessor newProc; DecoderPostProcessor newProc;
Object newObj; Object newObj;
for (String className : fqClassNames) { for (String className : fqClassNames) {
if (className == null || className.trim().isEmpty()) { if (className == null || className.trim().isEmpty()) {
@ -177,22 +261,22 @@ public class GribPostProcessor {
continue; continue;
} }
if (!(newObj instanceof IDecoderPostProcessor)) { if (!(newObj instanceof DecoderPostProcessor)) {
statusHandler.warn(className statusHandler.warn(className
+ " is not an IDecoderPostProcessor"); + " is not an DecoderPostProcessor");
continue; continue;
} }
newProc = (IDecoderPostProcessor) newObj; newProc = (DecoderPostProcessor) newObj;
statusHandler.debug("Registering grib post processor for " statusHandler.debug("Registering grib post processor for "
+ className); + className);
retClass = knownProcessors.put(newProc.getClass() retClass = knownProcessors.put(newProc.getClass().getSimpleName(),
.getSimpleName(), className); className);
/* Warn if two registered classes share the same simple class name. */ /* Warn if two registered classes share the same simple class name. */
if (retClass != null && !retClass.equals(className)) { if (retClass != null && !retClass.equals(className)) {
statusHandler.warn(retClass statusHandler.warn(retClass + " has been replaced by "
+ " has been replaced by " + className); + className);
} }
} }
} }
@ -221,7 +305,7 @@ public class GribPostProcessor {
statusHandler.info(String.format("Using postProcessorFile [%s]", statusHandler.info(String.format("Using postProcessorFile [%s]",
processorFile)); processorFile));
Map<String, List<IDecoderPostProcessor>> newMap = new HashMap<>(); Map<String, List<DecoderPostProcessor>> newMap = new HashMap<>();
/* /*
* Iterate over post processed models. Determine which models apply * Iterate over post processed models. Determine which models apply
@ -232,10 +316,10 @@ public class GribPostProcessor {
for (PostProcessedModel ppModel : ppModelSet.getModels()) { for (PostProcessedModel ppModel : ppModelSet.getModels()) {
for (String modelName : modelNames) { for (String modelName : modelNames) {
if (modelName.matches(ppModel.getModelName())) { if (modelName.matches(ppModel.getModelName())) {
List<IDecoderPostProcessor> processorInstances = newMap List<DecoderPostProcessor> processorInstances = newMap
.get(modelName); .get(modelName);
if (processorInstances == null) { if (processorInstances == null) {
processorInstances = new ArrayList<IDecoderPostProcessor>(); processorInstances = new ArrayList<DecoderPostProcessor>();
newMap.put(modelName, processorInstances); newMap.put(modelName, processorInstances);
} }
@ -249,7 +333,7 @@ public class GribPostProcessor {
try { try {
processorInstances processorInstances
.add((IDecoderPostProcessor) Class .add((DecoderPostProcessor) Class
.forName(classToLoad) .forName(classToLoad)
.newInstance()); .newInstance());
} catch (Exception e) { } catch (Exception e) {

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -28,19 +28,20 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
* This post processor currently looks for precipitation probability grids and * This post processor currently looks for precipitation probability grids and
* multiplies the data values by 100 to get an actual percentage (values 0-100) * multiplies the data values by 100 to get an actual percentage (values 0-100)
* instead of a decimal value (0-1) * instead of a decimal value (0-1)
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 6/11/2015 4542 bphillip Initial creation * 6/11/2015 4542 bphillip Initial creation
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
*
* @author bphillip * @author bphillip
* @version 1.0 * @version 1.0
*/ */
public class HPCqpfPostProcessor implements IDecoderPostProcessor { public class HPCqpfPostProcessor extends DecoderPostProcessor {
/** Parameter abbreviation patter for perecent probability grids */ /** Parameter abbreviation patter for perecent probability grids */
private static final String PCT_PROB_PATTERN = "ProbTP\\dp\\d{2}in\\d{1,2}hr"; private static final String PCT_PROB_PATTERN = "ProbTP\\dp\\d{2}in\\d{1,2}hr";
@ -51,7 +52,7 @@ public class HPCqpfPostProcessor implements IDecoderPostProcessor {
// Check to see if this is a grid we are looking for // Check to see if this is a grid we are looking for
if (parameterAbbreviation.matches(PCT_PROB_PATTERN)) { if (parameterAbbreviation.matches(PCT_PROB_PATTERN)) {
// If so, multiply the data by 100 to obtain a percent // If so, multiply the data by 100 to obtain a percent
float[] data = (float[]) record.getMessageData(); float[] data = getMessageData(record);
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
if (data[i] >= 0.0 && data[i] <= 1.0) { if (data[i] >= 0.0 && data[i] <= 1.0) {
data[i] *= 100; data[i] *= 100;

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -46,21 +46,22 @@ import com.vividsolutions.jts.geom.Geometry;
/** /**
* HWRF post processor implementation. * HWRF post processor implementation.
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Sep 10, 2015 4819 rferrel Initial Creation * Sep 10, 2015 4819 rferrel Initial Creation
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
*
* </pre> * </pre>
* *
* @author rferrel * @author rferrel
* @version 1 * @version 1
*/ */
public class HWRFPostProcessor implements IDecoderPostProcessor { public class HWRFPostProcessor extends DecoderPostProcessor {
/** /**
* Format for datasetId prefix <model>-<dx><spacingUnit>-. * Format for datasetId prefix <model>-<dx><spacingUnit>-.
@ -131,7 +132,7 @@ public class HWRFPostProcessor implements IDecoderPostProcessor {
/** /**
* Add the count in ct's extrainfo to the dataset name prefix. * Add the count in ct's extrainfo to the dataset name prefix.
* *
* @param ct * @param ct
* @param datasetIdPrefix * @param datasetIdPrefix
* @return datasetId * @return datasetId
@ -156,7 +157,7 @@ public class HWRFPostProcessor implements IDecoderPostProcessor {
/** /**
* Find datasetId a result grid that has > 95% intersection with the record. * Find datasetId a result grid that has > 95% intersection with the record.
* *
* @param record * @param record
* @param result * @param result
* @return datasetId or null when > 95% intersection not found * @return datasetId or null when > 95% intersection not found
@ -189,7 +190,7 @@ public class HWRFPostProcessor implements IDecoderPostProcessor {
/** /**
* While locked get datasetId for the record's grid info and update the grid * While locked get datasetId for the record's grid info and update the grid
* info list associated with dsIdPrefix. * info list associated with dsIdPrefix.
* *
* @param record * @param record
* @param datasetIdPrefix * @param datasetIdPrefix
*/ */

View file

@ -1,55 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
/**
* Grib decoder post processor interface
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 8/30/10 5875 bphillip Initial Creation
*
* </pre>
*
* @author bphillip
* @version 1
*/
public interface IDecoderPostProcessor {
/**
* Processes the provided record to see if it needs to be post processed
*
* @param record
* The record to examine to determine if it needs to be post
* processed
* @return The array of grib records including any created during post
* processing
* @throws GribException
*/
public GridRecord[] process(GridRecord record) throws GribException;
}

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -28,23 +28,24 @@ import com.raytheon.uf.common.parameter.Parameter;
/** /**
* Adjusts the LAPS Grib data to have to correct level information * Adjusts the LAPS Grib data to have to correct level information
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Apr 07, 2011 6619 bphillip Initial creation * Apr 07, 2011 6619 bphillip Initial creation
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls. * Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
* Sep 09, 2014 3356 njensen Remove CommunicationException * Sep 09, 2014 3356 njensen Remove CommunicationException
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
*
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1.0 * @version 1.0
*/ */
public class LapsPostProcessor implements IDecoderPostProcessor { public class LapsPostProcessor extends DecoderPostProcessor {
private static final String FHAG = "FHAG"; private static final String FHAG = "FHAG";

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -37,6 +37,7 @@ import com.raytheon.uf.common.parameter.Parameter;
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Aug 18, 2011 bphillip Initial creation * Aug 18, 2011 bphillip Initial creation
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls. * Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* *
* </pre> * </pre>
@ -45,7 +46,7 @@ import com.raytheon.uf.common.parameter.Parameter;
* @version 1.0 * @version 1.0
*/ */
public class MSASPostProcessor implements IDecoderPostProcessor { public class MSASPostProcessor extends DecoderPostProcessor {
private static final String TSLSA = "TSLSA"; private static final String TSLSA = "TSLSA";
@ -65,7 +66,7 @@ public class MSASPostProcessor implements IDecoderPostProcessor {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see * @see
* com.raytheon.edex.plugin.grib.decoderpostprocessors.IDecoderPostProcessor * com.raytheon.edex.plugin.grib.decoderpostprocessors.IDecoderPostProcessor
* #process(com.raytheon.uf.common.dataplugin.grib.GridRecord) * #process(com.raytheon.uf.common.dataplugin.grib.GridRecord)

View file

@ -1,215 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.parameter.Parameter;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Post processor for the NAM80 (ETA) model. This post processor generates the
* missing 6 hour total and convective precipitation grids.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Nov 17, 2011 bphillip Initial creation
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
*
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class Nam80PostProcessor implements IDecoderPostProcessor {
/** The number of seconds in 6 hours */
private static final int SECONDS_IN_6_HRS = 21600;
/** Parameter abbreviation for 12 hr total precipitation accumulation */
private static final String TP_12HR = "TP12hr";
/** Parameter abbreviation for 6 hr total precipitation accumulation */
private static final String TP_6HR = "TP6hr";
/** Parameter abbreviation for 12 hr convective precipitation accumulation */
private static final String CP_12HR = "CP12hr";
/** Parameter abbreviation for 6 hr convective precipitation accumulation */
private static final String CP_6HR = "CP6hr";
/*
* (non-Javadoc)
*
* @see
* com.raytheon.edex.plugin.grib.decoderpostprocessors.IDecoderPostProcessor
* #process(com.raytheon.uf.common.dataplugin.grib.GridRecord)
*/
@Override
public GridRecord[] process(GridRecord record) throws GribException {
/*
* Determine if this record is a 6 or 12 hour total precipitation
* accumulation grid
*/
if (record.getParameter().getAbbreviation().equals(TP_12HR)) {
return generate6HrGrids(record, false, TP_6HR, TP_12HR);
} else if (record.getParameter().getAbbreviation().equals(TP_6HR)) {
return generate6HrGrids(record, true, TP_6HR, TP_12HR);
} else if (record.getParameter().getAbbreviation().equals(CP_12HR)) {
return generate6HrGrids(record, false, CP_6HR, CP_12HR);
} else if (record.getParameter().getAbbreviation().equals(CP_6HR)) {
return generate6HrGrids(record, true, CP_6HR, CP_12HR);
}
return new GridRecord[] { record };
}
@SuppressWarnings("unchecked")
private GridRecord[] generate6HrGrids(GridRecord currentRecord,
boolean sixHr, String parameter6hr, String parameter12hr)
throws GribException {
// The 12 hr accumulation grid to use in the calculations
GridRecord tp12record = null;
// The 6 hr accumulation grid to use in the calculations
GridRecord tp6record = null;
Date refTime = currentRecord.getDataTime().getRefTime();
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating Grib Dao!", e);
}
/*
* If the current record is a 6 hr accumulation grid, get the 12 hr grid
* and vice versa
*/
DatabaseQuery dbQuery = new DatabaseQuery(GridRecord.class);
dbQuery.addQueryParam(GridConstants.DATASET_ID, "ETA");
dbQuery.addQueryParam("dataTime.refTime", refTime);
if (sixHr) {
tp6record = currentRecord;
dbQuery.addQueryParam(GridConstants.PARAMETER_ABBREVIATION,
parameter12hr);
dbQuery.addQueryParam("dataTime.fcstTime", currentRecord
.getDataTime().getFcstTime() + SECONDS_IN_6_HRS);
} else {
tp12record = currentRecord;
dbQuery.addQueryParam(GridConstants.PARAMETER_ABBREVIATION,
parameter6hr);
dbQuery.addQueryParam("dataTime.fcstTime", currentRecord
.getDataTime().getFcstTime() - SECONDS_IN_6_HRS);
}
try {
List<GridRecord> results = (List<GridRecord>) dao
.queryByCriteria(dbQuery);
if (results.isEmpty()) {
return new GridRecord[] { currentRecord };
}
if (sixHr) {
tp12record = results.get(0);
} else {
tp6record = results.get(0);
}
} catch (DataAccessLayerException e) {
throw new GribException("Error querying for 12 hr precip records!",
e);
}
Set<GridRecord> retVal = new HashSet<GridRecord>();
retVal.add(currentRecord);
retVal.add(generateGrid(tp12record, tp6record, dao, parameter6hr));
return retVal.toArray(new GridRecord[] {});
}
private GridRecord generateGrid(GridRecord tp12HrRecord,
GridRecord tp6HrRecord, GridDao dao, String parameter)
throws GribException {
GridRecord newRecord = new GridRecord();
try {
float[] newData = null;
float[] tp6Data = null;
if (tp12HrRecord.getMessageData() == null) {
newData = ((FloatDataRecord) dao.getHDF5Data(tp12HrRecord, -1)[0])
.getFloatData();
} else {
newData = (float[]) tp12HrRecord.getMessageData();
}
if (tp6HrRecord.getMessageData() == null) {
tp6Data = ((FloatDataRecord) dao.getHDF5Data(tp6HrRecord, -1)[0])
.getFloatData();
} else {
tp6Data = (float[]) tp6HrRecord.getMessageData();
}
for (int i = 0; i < newData.length; i++) {
newData[i] -= tp6Data[i];
}
newRecord.setMessageData(newData);
} catch (PluginException e) {
throw new GribException("Error retrieving precipitation data", e);
}
newRecord.setLocation(tp6HrRecord.getLocation());
newRecord.setDatasetId(tp6HrRecord.getDatasetId());
newRecord.setLevel(tp6HrRecord.getLevel());
Parameter param = new Parameter(parameter, tp6HrRecord.getParameter()
.getUnit());
newRecord.setParameter(param);
Calendar refTime = tp12HrRecord.getDataTime().getRefTimeAsCalendar();
Date start = new Date(tp12HrRecord.getDataTime().getValidPeriod()
.getEnd().getTime()
- (SECONDS_IN_6_HRS * 1000));
DataTime newDataTime = new DataTime(refTime, tp12HrRecord.getDataTime()
.getFcstTime(), new TimeRange(start, tp12HrRecord.getDataTime()
.getValidPeriod().getEnd()));
// Reset the datauri since the datauri contains the DataTime
newRecord.setDataTime(newDataTime);
newRecord.getInfo().setId(null);
newRecord.setDataURI(null);
newRecord.setOverwriteAllowed(true);
return newRecord;
}
}

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -34,18 +34,18 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 11/12/10 4524 bphillip Initial Creation * 11/12/10 4524 bphillip Initial Creation
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class OverwriteGribPostProcessor implements IDecoderPostProcessor { public class OverwriteGribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {
record.setOverwriteAllowed(true); record.setOverwriteAllowed(true);
return new GridRecord[] { record }; return new GridRecord[] { record };
} }
} }

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -30,23 +30,24 @@ import com.raytheon.uf.common.time.TimeRange;
/** /**
* Grib post processor implementation correct the total cloud cover parameter in * Grib post processor implementation correct the total cloud cover parameter in
* the RTMA grib model * the RTMA grib model
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Feb 01, 2011 6320 bphillip Initial Creation * Feb 01, 2011 6320 bphillip Initial Creation
* Oct 15, 2013 2473 bsteffen Remove deprecated method calls. * Oct 15, 2013 2473 bsteffen Remove deprecated method calls.
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
*
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class RTMAGribPostProcessor implements IDecoderPostProcessor { public class RTMAGribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -26,21 +26,22 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
/** /**
* Grib post processor implementation to eliminate 2-3hr duration grids from the * Grib post processor implementation to eliminate 2-3hr duration grids from the
* RUC130 model * RUC130 model
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 9/9/10 #4419 bphillip Initial Creation * 9/9/10 #4419 bphillip Initial Creation
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
*
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
* @version 1 * @version 1
*/ */
public class RUC130GribPostProcessor implements IDecoderPostProcessor { public class RUC130GribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -34,13 +34,13 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 1/24/2012 DR 14263 M. Porricelli Initial Creation * 1/24/2012 DR 14263 M. Porricelli Initial Creation
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* </pre> * </pre>
* *
* @author porricel * @author porricel
* @version 1 * @version 1
*/ */
public class RUC236GribPostProcessor implements IDecoderPostProcessor { public class RUC236GribPostProcessor extends DecoderPostProcessor {
@Override @Override
public GridRecord[] process(GridRecord record) throws GribException { public GridRecord[] process(GridRecord record) throws GribException {

View file

@ -1,214 +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.
**/
package com.raytheon.edex.plugin.grib.decoderpostprocessors;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.parameter.Parameter;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Abstract class to generate 6hr records
*
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 25, 2011 rgeorge Initial creation
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Oct 15, 2013 2473 bsteffen Removed deprecated and unused code.
*
* </pre>
*
* @author rgeorge
* @version 1.0
*/
public abstract class SixHrPrecipGridProcessor implements IDecoderPostProcessor {
/** The number of seconds in 6 hours */
protected static final int SECONDS_IN_6_HRS = 21600;
@Override
public GridRecord[] process(GridRecord record) throws GribException {
// Post process the data if this is a Total Precipitation grid
GridRecord[] newRecords = generate6hrPrecipGrids(record);
GridRecord[] retVal = new GridRecord[newRecords.length + 1];
retVal[0] = record;
for (int i = 1; i < retVal.length; i++) {
retVal[i] = newRecords[i - 1];
}
return retVal;
}
protected abstract GridRecord[] generate6hrPrecipGrids(GridRecord record)
throws GribException;
/**
* Generates the 6hr precipitation grid
*
* @param record
* The current record to clone and modify to produce the new 6hr
* grid
* @param precipInventory
* The current run accumulated grid inventory
* @return The generated 6hr precipitation grid
* @throws GribException
*/
protected List<GridRecord> generate6hrPrecip(GridRecord record,
List<GridRecord> precipInventory)
throws GribException {
List<GridRecord> tp6hrRecords = new ArrayList<GridRecord>();
int currentFcstTime = record.getDataTime().getFcstTime();
// If this is the first grid (the 6 hr grid), the 6hr precip
// accumulation is the same as the 6hr run accumulated grid
if (currentFcstTime == SECONDS_IN_6_HRS) {
tp6hrRecords.add(calculate6hrPrecip(null, record));
}
// If this is not the first grid, generate the new grid using the
// previous grid
else {
for (GridRecord rec : precipInventory) {
if (rec.getDataTime().getFcstTime() == (currentFcstTime - SECONDS_IN_6_HRS)) {
tp6hrRecords.add(calculate6hrPrecip(rec, record));
}
}
}
return tp6hrRecords;
}
/**
* Generates the 6hr precipitation grid from the current grid and the
* previous grid
*
* @param inventoryRecord
* The previous grid from the inventory
* @param currentRecord
* The current grid
* @return The generated 6hr precipitation grid
* @throws GribException
*/
protected GridRecord calculate6hrPrecip(GridRecord inventoryRecord,
GridRecord currentRecord) throws GribException {
// Clone the current record and set the ID to 0 so Hibernate will
// recognize it as a new record
GridRecord tp6hrRecord = new GridRecord(currentRecord);
tp6hrRecord.setId(0);
if (currentRecord.getMessageData() == null) {
GridDao dao = null;
try {
dao = new GridDao();
currentRecord.setMessageData(((FloatDataRecord) dao
.getHDF5Data(currentRecord, -1)[0]).getFloatData());
} catch (PluginException e) {
throw new GribException("Error populating grib data!", e);
}
}
// Copy the data to the new record so the data from the original record
// does not get modified
float[] currentData = (float[]) currentRecord.getMessageData();
currentRecord.setMessageData(currentData);
float[] newData = new float[currentData.length];
System.arraycopy(currentData, 0, newData, 0, currentData.length);
tp6hrRecord.setMessageData(newData);
// Assign the new parameter abbreviation and cache it if necessary
Parameter param = new Parameter("TP6hr", "Precip Accum 6 hr",
currentRecord.getParameter().getUnit());
tp6hrRecord.setParameter(param);
tp6hrRecord.getInfo().setId(null);
// Change the data time to include the 6-hr time range
modifyDataTime(tp6hrRecord);
// Calculate the new data values
if (inventoryRecord != null) {
if (inventoryRecord.getMessageData() == null) {
GridDao dao = null;
try {
dao = new GridDao();
inventoryRecord
.setMessageData(((FloatDataRecord) dao.getHDF5Data(
inventoryRecord, 0)[0]).getFloatData());
} catch (PluginException e) {
throw new GribException("Error populating grib data!", e);
}
}
calculatePrecipValues((float[]) inventoryRecord.getMessageData(),
(float[]) tp6hrRecord.getMessageData());
}
return tp6hrRecord;
}
/**
* Calculates the new data by subtracting the previous inventory data from
* the current data
*
* @param inventoryData
* The data from the previous precipitation record
* @param newData
* The data from the current precipitation record
*/
protected abstract void calculatePrecipValues(float[] messageData,
float[] messageData2);
/**
* Modifies the DataTime of the provided record to include a 6hr time range
*
* @param record
* The record to modify the datatime for
*/
protected void modifyDataTime(GridRecord record) {
Calendar refTime = record.getDataTime().getRefTimeAsCalendar();
int fcstTime = record.getDataTime().getFcstTime();
// Calculate the start time by subtracting 6 hours from the reference
// time + forecast time
Calendar startTime = (Calendar) refTime.clone();
startTime.add(Calendar.SECOND, fcstTime - SECONDS_IN_6_HRS);
// Calculate the end time by adding the reference time + forecast time
Calendar endTime = (Calendar) refTime.clone();
endTime.add(Calendar.SECOND, fcstTime);
TimeRange validPeriod = new TimeRange(startTime, endTime);
DataTime newDataTime = new DataTime(refTime, fcstTime, validPeriod);
// Reset the datauri since the datauri contains the DataTime
record.setDataTime(newDataTime);
record.setDataURI(null);
}
}

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -45,31 +45,32 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
/** /**
* *
* Adjusts temperature values that are mislabled as Celsius or Kelvin when they * Adjusts temperature values that are mislabled as Celsius or Kelvin when they
* actually represent the other one. Loads a list of parameters and thresholds * actually represent the other one. Loads a list of parameters and thresholds
* from a localization file. Assumes that all values above the threshold for a * from a localization file. Assumes that all values above the threshold for a
* parameter are in Kelvin and will convert if the declared unit is Celsius. * parameter are in Kelvin and will convert if the declared unit is Celsius.
* Values below the threshold are assumed to be in Celsius and will be converted * Values below the threshold are assumed to be in Celsius and will be converted
* if the declared unit is Kelvin * if the declared unit is Kelvin
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Mar 28, 2010 2874 bsteffen Initial creation * Mar 28, 2010 2874 bsteffen Initial creation
* Apr 25, 2014 2060 njensen Use JAXB instead of JAXBManager * Apr 25, 2014 2060 njensen Use JAXB instead of JAXBManager
* * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
*
* </pre> * </pre>
* *
* @author bsteffen * @author bsteffen
* @version 1.0 * @version 1.0
*/ */
public class TemperatureCorrectionPostProcessor implements public class TemperatureCorrectionPostProcessor extends DecoderPostProcessor
IDecoderPostProcessor, ILocalizationFileObserver { implements ILocalizationFileObserver {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(TemperatureCorrectionPostProcessor.class); .getHandler(TemperatureCorrectionPostProcessor.class);
@ -208,5 +209,4 @@ public class TemperatureCorrectionPostProcessor implements
} }
} }
} }

View file

@ -1,19 +1,19 @@
/** /**
* This software was developed and / or modified by Raytheon Company, * This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government. * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
* *
* U.S. EXPORT CONTROLLED TECHNICAL DATA * U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose * This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination * export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires * to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization. * an export license or other authorization.
* *
* Contractor Name: Raytheon Company * Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340 * Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8 * Mail Stop B8
* Omaha, NE 68106 * Omaha, NE 68106
* 402.291.0100 * 402.291.0100
* *
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * further licensing information.
**/ **/
@ -34,7 +34,11 @@ import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao; import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/** /**
* Abstract class to generate 3hr records * Abstract class to generate 3hr records.
*
* Note: This class has been replaced by PrecipAccumPostProcessor and only
* remains for
* gov.noaa.nws.crh.edex.grib.decoderpostprocessor.GFS20PostProcessor
* *
* *
* <pre> * <pre>
@ -46,14 +50,15 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
* Jan 24, 2012 14299 M. Porricelli Initial creation * Jan 24, 2012 14299 M. Porricelli Initial creation
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Oct 15, 2013 2473 bsteffen Removed deprecated and unused code. * Oct 15, 2013 2473 bsteffen Removed deprecated and unused code.
* Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor.
* *
* </pre> * </pre>
* *
* @author porricel * @author porricel
* @version 1.0 * @version 1.0
*/ */
public abstract class ThreeHrPrecipGridProcessor implements public abstract class ThreeHrPrecipGridProcessor extends
IDecoderPostProcessor { DecoderPostProcessor {
/** The number of seconds in 3 hours */ /** The number of seconds in 3 hours */
protected static final int SECONDS_IN_3_HRS = 10800; protected static final int SECONDS_IN_3_HRS = 10800;
@ -78,7 +83,7 @@ public abstract class ThreeHrPrecipGridProcessor implements
/** /**
* Generates the 3hr precipitation grid * Generates the 3hr precipitation grid
* *
* @param record * @param record
* The current record to clone and modify to produce the new 3hr * The current record to clone and modify to produce the new 3hr
* grid * grid
@ -113,7 +118,7 @@ public abstract class ThreeHrPrecipGridProcessor implements
/** /**
* Generates the 3hr precipitation grid from the current grid and the * Generates the 3hr precipitation grid from the current grid and the
* previous grid * previous grid
* *
* @param inventoryRecord * @param inventoryRecord
* The previous grid from the inventory * The previous grid from the inventory
* @param currentRecord * @param currentRecord
@ -178,7 +183,7 @@ public abstract class ThreeHrPrecipGridProcessor implements
/** /**
* Calculates the new data by subtracting the previous inventory data from * Calculates the new data by subtracting the previous inventory data from
* the current data * the current data
* *
* @param inventoryData * @param inventoryData
* The data from the previous precipitation record * The data from the previous precipitation record
* @param newData * @param newData
@ -189,7 +194,7 @@ public abstract class ThreeHrPrecipGridProcessor implements
/** /**
* Modifies the DataTime of the provided record to include a 3hr time range * Modifies the DataTime of the provided record to include a 3hr time range
* *
* @param record * @param record
* The record to modify the datatime for * The record to modify the datatime for
*/ */

View file

@ -0,0 +1,228 @@
/**
* 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.edex.plugin.grib.decoderpostprocessors.precipitation;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
/**
* Stores a list of models and a list of AccumulationCreationConfigs to apply
* for those models.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 28, 2015 3756 nabowle Initial creation
*
* </pre>
*
* @author nabowle
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class AccumulationConfig {
@XmlElement(name = "model")
private List<String> models;
@XmlElement(name = "create")
private List<AccumulationCreationConfig> creations;
/**
* Constructor
*/
public AccumulationConfig() {
super();
}
/**
* Constructor.
*
* @param models
* The list of models to match.
* @param creations
* The list of accumulations to create.
*/
public AccumulationConfig(List<String> models,
List<AccumulationCreationConfig> creations) {
super();
this.models = models;
this.creations = creations;
}
/**
* @return the models
*/
public List<String> getModels() {
return models;
}
/**
* @param models
* the models to set
*/
public void setModels(List<String> models) {
this.models = models;
}
public boolean addModel(String model) {
if (this.models == null) {
this.models = new ArrayList<>();
}
return this.models.add(model);
}
/**
* @return the creations
*/
public List<AccumulationCreationConfig> getCreations() {
return creations;
}
/**
* @param creations
* the creations to set
*/
public void setCreations(List<AccumulationCreationConfig> creations) {
this.creations = creations;
}
/**
* Convenience method to determine if this configuration matches a given
* model.
*
* @param model
* The model to check for.
* @return True if the model matches one of the configured models, false
* otherwise.
*/
public boolean modelMatches(String model) {
if (this.models == null) {
return false;
}
for (String mod : this.models) {
if (model.matches(mod)) {
return true;
}
}
return false;
}
/**
* Gets the subset of creation configs whose minuend's or subtrahend's
* parameter matches the given parameter, if any.
*
* @param parameter
* The parameter to match.
* @param matchMinuend
* If true, parameter will be matched to the minuends'
* parameters. If false, it will be match to the subtrahends'
* parameters.
* @return the subset of creation configs whose minuend's or subtrahend's
* parameter matches the given parameter, if any. An empty list is
* returned if no matches are found.
*/
public List<AccumulationCreationConfig> getCreations(String parameter,
boolean matchMinuend) {
List<AccumulationCreationConfig> matchedCreations = new ArrayList<>();
if (this.creations != null) {
String param;
for (AccumulationCreationConfig creation : this.creations) {
param = matchMinuend ? creation.getMinuendParam() : creation
.getSubtrahendParam();
if (param.equals(parameter)) {
matchedCreations.add(creation);
}
}
}
return matchedCreations;
}
/**
* Merges the list of creations of this config with the creations of the
* other config. If this config already contains a creation, the duplicate
* will not be added into this config.
*
* @param otherConfig
* The accumulation config that's creations will be merged into
* this config's creations.
*/
public void mergeCreations(AccumulationConfig otherConfig) {
if (otherConfig == null) {
return;
}
if (this.creations == null) {
this.creations = otherConfig.getCreations();
} else if (otherConfig.getCreations() != null) {
boolean dupe;
for (AccumulationCreationConfig toMerge : otherConfig
.getCreations()) {
if (toMerge == null) {
continue;
}
dupe = false;
for (AccumulationCreationConfig local : this.creations) {
if (local.equals(toMerge)) {
dupe = true;
break;
}
}
if (!dupe) {
this.creations.add(toMerge);
}
}
}
}
/**
* Determines if this AccumulationConfig has an equivalent collection of
* models to the other AccumulationConfig. This collections are considered
* equivalent if both are null or empty, or both contain the same models,
* even if in different orders.
*
* This will not handle cases where a model-regex lists models in different
* orders, e.g. {@code <model>GFS215|GFS217</model>} and
* {@code <model>GFS217|GFS215</model>} are not considered equivalent,
* though in practice they are.
*/
public boolean modelsEqual(AccumulationConfig other) {
if (other == null) {
return false;
}
if (other.getModels() == null || other.getModels().isEmpty()) {
return this.models == null || this.getModels().isEmpty();
}
return other.getModels().containsAll(this.getModels())
&& this.getModels().containsAll(other.getModels());
}
}

View file

@ -0,0 +1,134 @@
/**
* 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.edex.plugin.grib.decoderpostprocessors.precipitation;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Container for multiple AccumulationConfig instances.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 28, 2015 3756 nabowle Initial creation
*
* </pre>
*
* @author nabowle
* @version 1.0
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class AccumulationConfigs {
@XmlElement(name = "accumulation")
private List<AccumulationConfig> accumulations;
/**
* Constructor.
*/
public AccumulationConfigs() {
super();
}
/**
* Constructor.
*
* @param accums
* The list of accumulations.
*/
public AccumulationConfigs(List<AccumulationConfig> accums) {
this.accumulations = accums;
}
/**
* @return the accumulations
*/
public List<AccumulationConfig> getAccumulations() {
return accumulations;
}
/**
* @param accumulations
* the accumulations to set
*/
public void setAccumulations(List<AccumulationConfig> accumulations) {
this.accumulations = accumulations;
}
/**
* Gets a list of {@link AccumulationConfig}s that match the given model, if
* any. If no matches are found, an empty list is returned.
*
* @param model
* The model to match.
* @return A list containing all matching accumulation configs. If no
* matches are found, and empty list is returned.
*/
public List<AccumulationConfig> getAccumulations(String model) {
List<AccumulationConfig> accums = new ArrayList<>();
for (AccumulationConfig accum : this.accumulations) {
if (accum.modelMatches(model)) {
accums.add(accum);
}
}
return accums;
}
/**
* Merges the AccumulationConfigs with this one. Any configs with equivalent
* model lists will be merged, otherwise the config will be added into the
* list of configs.
*
* @param configs
* The configs to merge. If null, nothing is done.
*/
public void merge(AccumulationConfigs configs) {
if (configs == null) {
return;
}
boolean merged;
for (AccumulationConfig toMerge : configs.getAccumulations()) {
if (toMerge == null) {
continue;
}
merged = false;
for (AccumulationConfig local : this.accumulations) {
if (local.modelsEqual(toMerge)) {
local.mergeCreations(toMerge);
merged = true;
}
}
if (!merged) {
this.accumulations.add(toMerge);
}
}
}
}

View file

@ -0,0 +1,210 @@
/**
* 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.edex.plugin.grib.decoderpostprocessors.precipitation;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.common.time.util.TimeUtil;
/**
* Describes the parameters used in an accumulation calculation.
*
* <pre>
*
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 28, 2015 3756 nabowle Initial creation
*
* </pre>
*
* @author nabowle
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class AccumulationCreationConfig {
@XmlAttribute(required = true)
private int forecastPeriodHours;
@XmlAttribute(required = true)
private String accumulationParam;
@XmlAttribute(required = true)
private String minuendParam;
@XmlAttribute(required = true)
private String subtrahendParam;
/**
* Constructor.
*/
public AccumulationCreationConfig() {
super();
}
/**
* Constructor.
*
*
* @param forecastPeriod
* The forecast period in hours.
* @param accumulation
* The parameter to use for the calculated accumulation.
* @param minuend
* The parameter subtracted from in calculating accumulation.
* @param subtrahend
* The parameter being subtracted.
*/
public AccumulationCreationConfig(int forecastPeriod, String accumulation,
String minuend, String subtrahend) {
super();
this.forecastPeriodHours = forecastPeriod;
this.accumulationParam = accumulation;
this.minuendParam = minuend;
this.subtrahendParam = subtrahend;
}
/**
* @return the forecastPeriod
*/
public int getForecastPeriodHours() {
return forecastPeriodHours;
}
/**
* @param forecastPeriod
* the forecastPeriod to set
*/
public void setForecastPeriodHours(int forecastPeriod) {
this.forecastPeriodHours = forecastPeriod;
}
/**
* @return the forecastPeriod in seconds.
*/
public int getForecastPeriodSeconds() {
return forecastPeriodHours * TimeUtil.SECONDS_PER_HOUR;
}
/**
* @return the accumulation
*/
public String getAccumulationParam() {
return accumulationParam;
}
/**
* @param accumulation
* the accumulation to set
*/
public void setAccumulationParam(String accumulation) {
this.accumulationParam = accumulation;
}
/**
* @return the minuend
*/
public String getMinuendParam() {
return minuendParam;
}
/**
* @param minuend
* the minuend to set
*/
public void setMinuendParam(String minuend) {
this.minuendParam = minuend;
}
/**
* @return the subtrahend
*/
public String getSubtrahendParam() {
return subtrahendParam;
}
/**
* @param subtrahend
* the subtrahend to set
*/
public void setSubtrahendParam(String subtrahend) {
this.subtrahendParam = subtrahend;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((accumulationParam == null) ? 0 : accumulationParam
.hashCode());
result = prime * result + forecastPeriodHours;
result = prime * result
+ ((minuendParam == null) ? 0 : minuendParam.hashCode());
result = prime * result
+ ((subtrahendParam == null) ? 0 : subtrahendParam.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
AccumulationCreationConfig other = (AccumulationCreationConfig) obj;
if (accumulationParam == null) {
if (other.accumulationParam != null) {
return false;
}
} else if (!accumulationParam.equals(other.accumulationParam)) {
return false;
}
if (forecastPeriodHours != other.forecastPeriodHours) {
return false;
}
if (minuendParam == null) {
if (other.minuendParam != null) {
return false;
}
} else if (!minuendParam.equals(other.minuendParam)) {
return false;
}
if (subtrahendParam == null) {
if (other.subtrahendParam != null) {
return false;
}
} else if (!subtrahendParam.equals(other.subtrahendParam)) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,479 @@
/**
* 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.edex.plugin.grib.decoderpostprocessors.precipitation;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBException;
import com.raytheon.edex.plugin.grib.decoderpostprocessors.DecoderPostProcessor;
import com.raytheon.edex.plugin.grib.decoderpostprocessors.GribPostProcessor;
import com.raytheon.edex.plugin.grib.exception.GribException;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.parameter.Parameter;
import com.raytheon.uf.common.parameter.lookup.ParameterLookup;
import com.raytheon.uf.common.serialization.JAXBManager;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
/**
* Configurable grib post processor for accumulating precipitation.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 28, 2015 3756 nabowle Initial creation
*
* </pre>
*
* @author nabowle
* @version 1.0
*/
public class PrecipAccumPostProcessor extends DecoderPostProcessor {
private static final GridRecord[] EMPTY_ARR = new GridRecord[0];
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(GribPostProcessor.class);
/**
* The configured set of Accumulation Configurations. Note: This is not
* thread safe if modified.
*/
private static final AccumulationConfigs configs = initConfigs();
/**
* Constructor.
*
* @throws JAXBException
*/
public PrecipAccumPostProcessor() {
super();
}
@Override
public GridRecord[] process(GridRecord record) throws GribException {
if (configs == null) {
return EMPTY_ARR;
}
return generatePrecipGrids(record);
}
/**
* Generates precipitation grids for a record. If no records can be
* generated, an empty array is returned.
*
* @param record
* The record.
* @return The generated precipitation grids, if any.
* @throws GribException
*/
private GridRecord[] generatePrecipGrids(GridRecord record)
throws GribException {
List<GridRecord> retRecords = new ArrayList<>();
List<AccumulationConfig> accumConfigs = configs.getAccumulations(record
.getDatasetId());
for (AccumulationConfig accumConfig : accumConfigs) {
retRecords.addAll(generatePrecipGrids(record, accumConfig));
}
return retRecords.toArray(EMPTY_ARR);
}
/**
* Generates precipitation grids for a record and an accumulation config. An
* empty collection is returned if no grids were created.
*
* @param record
* The record.
* @param accumConfig
* An accumulation config who's model matches the record's
* dataset id.
* @return The created records, if any.
* @throws GribException
*/
private Collection<GridRecord> generatePrecipGrids(GridRecord record,
AccumulationConfig accumConfig) throws GribException {
List<GridRecord> retRecords = new ArrayList<>();
List<AccumulationCreationConfig> creations = accumConfig.getCreations(
record.getParameter().getAbbreviation(), true);
for (AccumulationCreationConfig creation : creations) {
retRecords.addAll(generatePrecipGrids(record, creation, true));
}
// look for out-of-order creations where this is the subtrahend
creations = accumConfig.getCreations(record.getParameter()
.getAbbreviation(), false);
for (AccumulationCreationConfig creation : creations) {
retRecords.addAll(generatePrecipGrids(record, creation, false));
}
return retRecords;
}
/**
* Generates precipitation grids for a record and accumulation creation
* config. An empty collection is returned if no grids were created.
*
* @param record
* The record.
* @param creation
* The accumulation creation config.
* @param isMinuend
* If true, the record will is used as the minuend. If false, the
* record is used as the subtrahend.
* @return The created records, if any.
* @throws GribException
*/
private Collection<? extends GridRecord> generatePrecipGrids(
GridRecord record, AccumulationCreationConfig creation,
boolean isMinuend) throws GribException {
List<GridRecord> minuendInv = new ArrayList<>();
List<GridRecord> subtrahendInv = new ArrayList<>();
Set<Integer> targetForecastInv = new HashSet<>();
initInventories(record, isMinuend, creation, minuendInv, subtrahendInv,
targetForecastInv);
List<GridRecord> retRecords = new ArrayList<>();
int targetForecast = creation.getForecastPeriodSeconds();
int minFcst;
for (GridRecord minRec : minuendInv) {
minFcst = minRec.getDataTime().getFcstTime();
if (!targetForecastInv.contains(minFcst)) {
targetForecastInv.add(minFcst);
if (isMinuend && minFcst == targetForecast) {
/*
* this record matches the target forecast period. create a
* copy of it with the desired parameter.
*/
retRecords.add(createRecord(creation, minRec, null));
} else {
for (GridRecord subRec : subtrahendInv) {
if (minFcst - subRec.getDataTime().getFcstTime() == targetForecast) {
retRecords.add(createRecord(creation, minRec,
subRec));
}
}
}
}
}
return retRecords;
}
/**
* Initializes minuendInv, subtrahendInv, and targetForecastInv.
*
* @throws GribException
*/
private void initInventories(GridRecord record, boolean isMinuend,
AccumulationCreationConfig create, List<GridRecord> minuendInv,
List<GridRecord> subtrahendInv, Set<Integer> targetForecastInv)
throws GribException {
String datasetId = record.getDatasetId();
Date refTime = record.getDataTime().getRefTime();
if (isMinuend) {
minuendInv.add(record);
subtrahendInv.addAll(getPrecipInventory(refTime,
create.getSubtrahendParam(), datasetId));
} else {
minuendInv.addAll(getPrecipInventory(refTime,
create.getMinuendParam(), datasetId));
subtrahendInv.add(record);
}
targetForecastInv.addAll(getPrecipForecastTimes(refTime,
create.getAccumulationParam(), datasetId));
}
/**
* @param creation
* The accumulation creation config.
* @param minRec
* The minuend record.
* @param subRec
* The subtrahend record. Can be null if the minRec's forecast
* time matches the desired forecast period, skipping the need
* to calculate the precipitation values.
* @return
* @throws GribException
*/
protected GridRecord createRecord(AccumulationCreationConfig creation,
GridRecord minRec, GridRecord subRec) throws GribException {
GridRecord created = createAccumRecord(creation, minRec);
if (subRec != null) {
calculatePrecipValues(subRec, created);
}
return created;
}
/**
* Calculates the accumulation values. In general, this is the difference
* between the created record's value (which is currently a copy from the
* minuend record's value) and the subtrahend record's value, i.e.
* createdValue[i] = minuendValue[i] - subtrahendValue[i], capped to 0 on
* the low end.
*
* @param subRec
* The subtrahend record.
* @param created
* The record that was created. It's expected that it's current
* data is a copy of the minuend record's data.
* @throws GribException
*/
protected void calculatePrecipValues(GridRecord subRec, GridRecord created)
throws GribException {
float[] subData = getMessageData(subRec);
float[] accumData = (float[]) created.getMessageData();
float newVal;
for (int i = 0; i < accumData.length; i++) {
newVal = accumData[i] - subData[i];
accumData[i] = newVal < 0F ? 0F : newVal;
}
}
/**
* Creates the record for the accumulation based on the accumulation
* creation config and base record.
*
* @param creation
* The accumulation creation config.
* @param baseRec
* The record to base the accumulation off of.
* @return
* @throws GribException
*/
protected GridRecord createAccumRecord(AccumulationCreationConfig creation,
GridRecord baseRec) throws GribException {
GridRecord createdRec = new GridRecord(baseRec);
createdRec.setId(0);
createdRec.getInfo().setId(null);
createdRec.setDataURI(null);
float[] data = getMessageData(baseRec);
float[] dataCopy = Arrays.copyOf(data, data.length);
createdRec.setMessageData(dataCopy);
updateParameter(creation, baseRec, createdRec);
updateRefTime(creation, createdRec);
return createdRec;
}
/**
* Updates the created record's datatime.
*
* @param creation
* @param createdRec
*/
private void updateRefTime(AccumulationCreationConfig creation,
GridRecord createdRec) {
Calendar refTime = createdRec.getDataTime().getRefTimeAsCalendar();
int fcstTime = createdRec.getDataTime().getFcstTime();
// Calculate the end time by adding the reference time + forecast time
Calendar endTime = (Calendar) refTime.clone();
endTime.add(Calendar.SECOND, fcstTime);
// Start time is endTime - forecast period
Calendar startTime = (Calendar) refTime.clone();
startTime.add(Calendar.SECOND,
fcstTime - creation.getForecastPeriodSeconds());
TimeRange validPeriod = new TimeRange(startTime, endTime);
DataTime newDataTime = new DataTime(refTime, fcstTime, validPeriod);
createdRec.setDataTime(newDataTime);
}
/**
* Updates the created record's parameter.
*
* @param creation
* @param base
* @param createdRec
*/
private void updateParameter(AccumulationCreationConfig creation,
GridRecord base, GridRecord createdRec) {
Parameter param = ParameterLookup.getInstance().getParameter(
creation.getAccumulationParam());
Parameter createdParam;
if (param == null) {
createdParam = new Parameter(creation.getAccumulationParam(),
"Precipitation Accumulation", base.getParameter().getUnit());
} else {
createdParam = new Parameter(param.getAbbreviation(),
param.getName(), base.getParameter().getUnit());
}
createdRec.setParameter(createdParam);
}
/**
* Retrieves an inventory of GridRecords for the reftime, parameter
* abbreviation, and datasetId
*
* @param refTime
* The reftime.
* @param param
* The parameter abbreviation.
* @param datasetId
* The datasetId.
* @return
* @throws GribException
*/
@SuppressWarnings("unchecked")
private List<GridRecord> getPrecipInventory(Date refTime, String param,
String datasetId) throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao.", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, param);
query.addQueryParam(GridConstants.DATASET_ID, datasetId);
query.addQueryParam("dataTime.refTime", refTime);
query.addOrder("dataTime.fcstTime", true);
try {
return (List<GridRecord>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException("Error getting " + param
+ " inventory for " + datasetId, e);
}
}
/**
* Retrieves an inventory of forecast times for the refTime, parameter
* abbreviation, and datasetId.
*
* @param refTime
* The reftime.
* @param param
* The parameter abbreviation.
* @param datasetId
* The datasetId.
* @return
* @throws GribException
*/
@SuppressWarnings("unchecked")
private List<Integer> getPrecipForecastTimes(Date refTime, String param,
String datasetId) throws GribException {
GridDao dao = null;
try {
dao = new GridDao();
} catch (PluginException e) {
throw new GribException("Error instantiating grib dao!", e);
}
DatabaseQuery query = new DatabaseQuery(GridRecord.class);
query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, param);
query.addQueryParam(GridConstants.DATASET_ID, datasetId);
query.addQueryParam("dataTime.refTime", refTime);
query.addReturnedField("dataTime.fcstTime");
try {
return (List<Integer>) dao.queryByCriteria(query);
} catch (DataAccessLayerException e) {
throw new GribException("Error getting " + param
+ " forecast inventory for " + datasetId, e);
}
}
/**
* Initializes the configuration.
*/
private static AccumulationConfigs initConfigs() {
AccumulationConfigs retConfigs = null;
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationLevel[] levels = new LocalizationLevel[] {
LocalizationLevel.BASE, LocalizationLevel.REGION,
LocalizationLevel.CONFIGURED, LocalizationLevel.SITE };
LocalizationFile locFile;
Map<LocalizationLevel, LocalizationFile> files = pathMgr
.getTieredLocalizationFile(LocalizationType.EDEX_STATIC,
"/grib/postProcessModels/precipitationAccumulation.xml");
AccumulationConfigs configs = null;
for (LocalizationLevel level : levels) {
locFile = files.get(level);
if (locFile == null) {
continue;
}
try (InputStream is = locFile.openInputStream()) {
JAXBManager manager = new JAXBManager(AccumulationConfigs.class);
configs = (AccumulationConfigs) manager
.unmarshalFromInputStream(is);
} catch (IOException | LocalizationException | JAXBException
| SerializationException e) {
statusHandler
.fatal("Could not initialize the precipitation accumulation config.",
e);
}
if (retConfigs == null) {
retConfigs = configs;
} else {
retConfigs.merge(configs);
}
}
return retConfigs;
}
@Override
public PostProcessorType getType() {
return PostProcessorType.POST_PERSIST;
}
}

View file

@ -0,0 +1,14 @@
<pluginNotificationList>
<pluginNotification>
<endpointName>Grid.PostProcess</endpointName>
<format>DATAURI</format>
<endpointType>QUEUE</endpointType>
<durable>true</durable>
<timeToLive>120000</timeToLive>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="grid" constraintType="EQUALS"/>
</mapping>
</metadataMap>
</pluginNotification>
</pluginNotificationList>

View file

@ -1,129 +1,131 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<postProcessedModels> <postProcessedModels>
<!-- Post Processor definitions for models containing grids needing to be <!-- Post Processor definitions for models containing grids needing to be
stitched together --> stitched together -->
<postProcessedModel> <postProcessedModel>
<modelName>UKMET[0-9]{2}|ECMF[0-9]|ENSEMBLE[0-9]{2}|AVN[0-9]{2} <modelName>UKMET[0-9]{2}|ECMF[0-9]|ENSEMBLE[0-9]{2}|AVN[0-9]{2}
</modelName> </modelName>
<processorName>EnsembleGridAssembler</processorName> <processorName>EnsembleGridAssembler</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definitions for models which disseminate updated grids <!-- Post processor definitions for models which disseminate updated grids
containing identical metadata. This data is primarily from RFCs. The overwrite containing identical metadata. This data is primarily from RFCs. The overwrite
post processor is used to prevent updated data from being discarded as duplicates. --> post processor is used to prevent updated data from being discarded as duplicates. -->
<postProcessedModel> <postProcessedModel>
<modelName>HPCqpfNDFD</modelName> <modelName>HPCqpfNDFD</modelName>
<processorName>OverwriteGribPostProcessor</processorName> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<postProcessedModel> <postProcessedModel>
<modelName>RFCqpf</modelName> <modelName>RFCqpf</modelName>
<processorName>OverwriteGribPostProcessor</processorName> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<postProcessedModel> <postProcessedModel>
<modelName>HPCqpf</modelName> <modelName>HPCqpf</modelName>
<processorName>OverwriteGribPostProcessor</processorName> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<postProcessedModel> <postProcessedModel>
<modelName>MPE-.*|QPE-.*</modelName> <modelName>MPE-.*|QPE-.*</modelName>
<processorName>OverwriteGribPostProcessor</processorName> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<postProcessedModel> <postProcessedModel>
<modelName>URMA25</modelName> <modelName>URMA25</modelName>
<processorName>OverwriteGribPostProcessor</processorName> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for FFG grids. Similar to the models using <!-- Post processor definition for FFG grids. Similar to the models using
the overwrite post processor, FFG gridded data is also updated without changing the overwrite post processor, FFG gridded data is also updated without changing
the associated metadata. In this case, the previous updates need to be retained. --> the associated metadata. In this case, the previous updates need to be retained. -->
<postProcessedModel> <postProcessedModel>
<modelName>FFG-[A-Z]{3}</modelName> <modelName>FFG-[A-Z]{3}</modelName>
<processorName>FFGGribPostProcessor</processorName> <processorName>FFGGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definitions for models using the temperature correction <!-- Post processor definitions for models using the temperature correction
post processor. These models may have some parameters which are incorrectly post processor. These models may have some parameters which are incorrectly
labeled Celsius vs. Kelvin. The list of parameters to correct is in temperatureCorrectionParameters.xml --> labeled Celsius vs. Kelvin. The list of parameters to correct is in temperatureCorrectionParameters.xml -->
<postProcessedModel> <postProcessedModel>
<modelName>ETA218|GFS212|GFS213|ETA242|RTOFS-.*</modelName> <modelName>ETA218|GFS212|GFS213|ETA242|RTOFS-.*</modelName>
<processorName>TemperatureCorrectionPostProcessor</processorName> <processorName>TemperatureCorrectionPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the RTMA model --> <!-- Post processor definition for the RTMA model -->
<postProcessedModel> <postProcessedModel>
<modelName>RTMA</modelName> <modelName>RTMA</modelName>
<processorName>RTMAGribPostProcessor</processorName> <processorName>RTMAGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the ECMWF-HiRes model --> <!-- Post processor definition for the ECMWF-HiRes model -->
<postProcessedModel> <postProcessedModel>
<modelName>ECMWF-HiRes</modelName> <modelName>ECMWF-HiRes</modelName>
<processorName>ECMWFHiResProcessor</processorName> <processorName>ECMWFHiResProcessor</processorName>
</postProcessedModel> <processorName>PrecipAccumPostProcessor</processorName>
</postProcessedModel>
<!-- Post processor definition for the MSAS model --> <!-- Post processor definition for the MSAS model -->
<postProcessedModel> <postProcessedModel>
<modelName>MSAS</modelName> <modelName>MSAS</modelName>
<processorName>MSASPostProcessor</processorName> <processorName>MSASPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the ETA (NAM80) model --> <!-- Post processor definition for the ETA (NAM80) model -->
<postProcessedModel> <postProcessedModel>
<modelName>ETA</modelName> <modelName>ETA</modelName>
<processorName>Nam80PostProcessor</processorName> <processorName>PrecipAccumPostProcessor</processorName>
</postProcessedModel> <processorName>OverwriteGribPostProcessor</processorName>
</postProcessedModel>
<!-- Post processor definition for the RUC236 model --> <!-- Post processor definition for the RUC236 model -->
<postProcessedModel> <postProcessedModel>
<modelName>RUC236</modelName> <modelName>RUC236</modelName>
<processorName>RUC236GribPostProcessor</processorName> <processorName>RUC236GribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the CPCoutlook211 model --> <!-- Post processor definition for the CPCoutlook211 model -->
<postProcessedModel> <postProcessedModel>
<modelName>CPCoutlook211</modelName> <modelName>CPCoutlook211</modelName>
<processorName>CPCoutlookGribPostProcessor</processorName> <processorName>CPCoutlookGribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definitions for the Canadian models --> <!-- Post processor definitions for the Canadian models -->
<postProcessedModel> <postProcessedModel>
<modelName>Canadian-NH</modelName> <modelName>Canadian-NH</modelName>
<processorName>CanadianNHPostProcessor</processorName> <processorName>PrecipAccumPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<postProcessedModel> <postProcessedModel>
<modelName>Canadian-Reg</modelName> <modelName>Canadian-Reg</modelName>
<processorName>CanadianRegPostProcessor</processorName> <processorName>PrecipAccumPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the LAPS model --> <!-- Post processor definition for the LAPS model -->
<postProcessedModel> <postProcessedModel>
<modelName>LAPS</modelName> <modelName>LAPS</modelName>
<processorName>LapsPostProcessor</processorName> <processorName>LapsPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the RUC130 model --> <!-- Post processor definition for the RUC130 model -->
<postProcessedModel> <postProcessedModel>
<modelName>RUC130</modelName> <modelName>RUC130</modelName>
<processorName>RUC130GribPostProcessor</processorName> <processorName>RUC130GribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for HPCqpfNDFD --> <!-- Post processor definition for HPCqpfNDFD -->
<postProcessedModel> <postProcessedModel>
<modelName>HPCqpfNDFD</modelName> <modelName>HPCqpfNDFD</modelName>
<processorName>HPCqpfPostProcessor</processorName> <processorName>HPCqpfPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the GFS20 model --> <!-- Post processor definition for the GFS20 model -->
<postProcessedModel> <postProcessedModel>
<modelName>GFS215|GFS217|GFS20-*</modelName> <modelName>GFS215|GFS217|GFS20-.*</modelName>
<processorName>gov.noaa.nws.crh.edex.grib.decoderpostprocessor.GFS20PostProcessor</processorName> <processorName>PrecipAccumPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the HWRF model --> <!-- Post processor definition for the HWRF model -->
<!-- This breaks GFE and volume browser. The post processing <!-- This breaks GFE and volume browser. The post processing
creates models based on a storm's moving grid. Currently creates models based on a storm's moving grid. Currently
@ -137,11 +139,11 @@
</postProcessedModel> </postProcessedModel>
--> -->
<!-- Post Processor for ARI grids (FFG source for FFMP) --> <!-- Post Processor for ARI grids (FFG source for FFMP) -->
<postProcessedModel> <postProcessedModel>
<modelName>ARI</modelName> <modelName>ARI</modelName>
<processorName>ARIPostProcessor</processorName> <processorName>ARIPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
</postProcessedModels> </postProcessedModels>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<accumulationConfigs>
<accumulation>
<model>Canadian-Reg</model>
<create forecastPeriodHours="3" accumulationParam="TP3hr" minuendParam="TPrun" subtrahendParam="TPrun" />
</accumulation>
<accumulation>
<model>Canadian-NH</model>
<create forecastPeriodHours="6" accumulationParam="TP6hr" minuendParam="TPrun" subtrahendParam="TPrun" />
</accumulation>
<accumulation>
<model>ECMWF-HiRes</model>
<create forecastPeriodHours="6" accumulationParam="TP6hr" minuendParam="TP-ECMWF" subtrahendParam="TP-ECMWF" />
</accumulation>
<accumulation>
<model>GFS215|GFS217|GFS20-.*</model>
<create forecastPeriodHours="3" accumulationParam="TP3hr" minuendParam="TP6hr" subtrahendParam="TP3hr" />
</accumulation>
<accumulation>
<model>ETA</model>
<create forecastPeriodHours="6" accumulationParam="TP6hr" minuendParam="TP12hr" subtrahendParam="TP6hr" />
<create forecastPeriodHours="6" accumulationParam="CP6hr" minuendParam="CP12hr" subtrahendParam="CP6hr" />
</accumulation>
<!-- NamNestPostProcessor equivalent. -->
<!--
<accumulation>
<model></model>
<create forecastPeriodHours="1" accumulationParam="TP1hr" minuendParam="TP3hr" subtrahendParam="TP2hr" />
<create forecastPeriodHours="1" accumulationParam="TP1hr" minuendParam="TP2hr" subtrahendParam="TP1hr" />
</accumulation>
-->
</accumulationConfigs>