diff --git a/build/deploy.edex.awips2/esb/etc/ingestGrib.sh b/build/deploy.edex.awips2/esb/etc/ingestGrib.sh index 573827df31..4310c38200 100644 --- a/build/deploy.edex.awips2/esb/etc/ingestGrib.sh +++ b/build/deploy.edex.awips2/esb/etc/ingestGrib.sh @@ -32,6 +32,7 @@ fi let "MAX_MEM = GRIB_DECODE_THREADS * 128" # in Meg let "GRIB_MAX_GRID_POINTS = GRIB_DECODE_THREADS * 25000000" let "GRID_PERSIST_THREADS = GRIB_DECODE_THREADS / 2" +let "GRID_POSTPROCESS_THREADS = 1" let "GRID_MAX_PERSIST_MEMORY_IN_MB = GRID_PERSIST_THREADS * 50" export INIT_MEM=128 # in Meg @@ -39,6 +40,7 @@ export MAX_MEM export GRIB_DECODE_THREADS export GRIB_MAX_GRID_POINTS export GRID_PERSIST_THREADS +export GRID_POSTPROCESS_THREADS export GRID_MAX_PERSIST_MEMORY_IN_MB export METADATA_POOL_MAX=10 diff --git a/crh/gov.noaa.nws.crh.edex.grib.decoderpostprocessor/src/gov/noaa/nws/crh/edex/grib/decoderpostprocessor/OneHrPrecipGridProcessor.java b/crh/gov.noaa.nws.crh.edex.grib.decoderpostprocessor/src/gov/noaa/nws/crh/edex/grib/decoderpostprocessor/OneHrPrecipGridProcessor.java index 4419e04796..a844a0989a 100644 --- a/crh/gov.noaa.nws.crh.edex.grib.decoderpostprocessor/src/gov/noaa/nws/crh/edex/grib/decoderpostprocessor/OneHrPrecipGridProcessor.java +++ b/crh/gov.noaa.nws.crh.edex.grib.decoderpostprocessor/src/gov/noaa/nws/crh/edex/grib/decoderpostprocessor/OneHrPrecipGridProcessor.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Calendar; 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.uf.common.dataplugin.PluginException; 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 - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date          Ticket#  Engineer      Description
  * ------------- -------- ------------- --------------------------
  * Sep 05, 2014           M. Foster     Initial creation
- *
+ * Oct 07, 2015  3756     nabowle       Extends DecoderPostProcessor.
+ * 
  * 
- * + * * @author matthew.foster * @version 1.0 - * + * */ -public abstract class OneHrPrecipGridProcessor implements IDecoderPostProcessor { +public abstract class OneHrPrecipGridProcessor extends DecoderPostProcessor { /** The number of seconds in 1 hour */ protected static final int SECONDS_IN_1_HR = 3600; diff --git a/deltaScripts/16.2.1/DR3756/updatePostProcessorOverrides.sh b/deltaScripts/16.2.1/DR3756/updatePostProcessorOverrides.sh new file mode 100644 index 0000000000..10c7d40114 --- /dev/null +++ b/deltaScripts/16.2.1/DR3756/updatePostProcessorOverrides.sh @@ -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/ECMWFHiResProcessor<\/processorName>/ECMWFHiResProcessor<\/processorName>\n 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 diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/res/spring/grib-decode.xml b/edexOsgi/com.raytheon.edex.plugin.grib/res/spring/grib-decode.xml index 05aef79f60..c5978b6681 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/res/spring/grib-decode.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/res/spring/grib-decode.xml @@ -25,23 +25,20 @@ com.raytheon.edex.plugin.grib.decoderpostprocessors.ARIPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.CPCoutlookGribPostProcessor - com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianNHPostProcessor - com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianRegPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.ECMWFHiResProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor - com.raytheon.edex.plugin.grib.decoderpostprocessors.GFSProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.HPCqpfPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.HWRFPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.LapsPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.MSASPostProcessor - com.raytheon.edex.plugin.grib.decoderpostprocessors.Nam80PostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.RTMAGribPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC130GribPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC236GribPostProcessor com.raytheon.edex.plugin.grib.decoderpostprocessors.TemperatureCorrectionPostProcessor + com.raytheon.edex.plugin.grib.decoderpostprocessors.precipitation.PrecipAccumPostProcessor @@ -75,6 +72,7 @@ + @@ -139,5 +137,25 @@ + + + + + + + + + + + + + java.lang.Throwable + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ARIPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ARIPostProcessor.java index c2b499a257..c6324d0458 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ARIPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ARIPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -34,6 +34,7 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; * Date Ticket# Engineer Description * ------------- -------- ----------- -------------------------- * Sep 21, 2015 4756 dhladky Initial Creation + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * * @@ -41,53 +42,53 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; * @version 1 * */ -public class ARIPostProcessor implements IDecoderPostProcessor { - +public class ARIPostProcessor extends DecoderPostProcessor { + /** name of extraAttribute variable from GribDecoder.py */ private static final String FORECAST_INTERVAL = "forecastInterval"; - + /** name of extraAttribute variable from GribDecoder.py */ private static final String FORECAST_INTERVAL_UNIT = "forecastIntervalUnit"; - + /** 30 minute record identifier **/ private static final String REFZC = "REFZC"; - + /** 1 hr record identifier **/ private static final String REFZI = "REFZI"; - + /** 3 hr record identifier **/ private static final String RETOP = "RETOP"; - + /** 6 hr record identifier **/ private static final String REFD = "REFD"; - + /** 12 hr record identifier **/ private static final String REFC = "REFC"; - + /** Year **/ private static final String YR = "YR"; - + /** ARI (Archival Recurrence Interval **/ private static final String ARI = "ARI"; - + /** 30 min comparison time **/ private static final String MIN30 = "30"; - + /** 1 hour comparison time **/ private static final String HOUR1 = "1"; - + /** 3 hour comparison time **/ private static final String HOUR3 = "3"; - + /** 6 hour comparison time **/ private static final String HOUR6 = "6"; - + /** 12 hour comparison time **/ private static final String HOUR12 = "12"; - + /** ARI is precip in mm **/ private static final String UNIT = "mm"; - + @Override 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 * interval period. - * + * * @param record * @param forecastYear * @return @@ -160,13 +161,12 @@ public class ARIPostProcessor implements IDecoderPostProcessor { throw new IllegalArgumentException("ARI paramName " + paramAbbrev + " is not a valid param for ARI postprocessing"); } - + // Give it a new name/description/unit record.getParameter().setAbbreviation(sb.toString()); record.getParameter().setName(sb2.toString()); record.getParameter().setUnitString(UNIT); - + return record; } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java index 310b83651f..ec7514b673 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -49,13 +49,14 @@ import com.raytheon.uf.common.time.DataTime; * Mar 09, 2011 4243 porricel Initial Creation * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Oct 15, 2013 2473 bsteffen Removed deprecated and unused code. + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * * * @author * @version */ -public class CPCoutlookGribPostProcessor implements IDecoderPostProcessor { +public class CPCoutlookGribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java deleted file mode 100644 index 48cf5ed5ee..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java +++ /dev/null @@ -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 - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Jan 18, 2012           porricel    Initial Creation
- * Oct 15, 2013  2473     bsteffen    Removed unused method argument.
- * 
- * 
- * - * @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 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) dao.queryByCriteria(query); - } catch (DataAccessLayerException e) { - throw new GribException( - "Error getting Precip inventory for Canadian-NH!", e); - } - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - protected List 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) 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 precipInventory = getPrecipInventory(record - .getDataTime().getRefTime()); - - // The current 6-hr precipitation grid inventory in the database - List 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 generatedRecords = new ArrayList(); - 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 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; - } - } - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java deleted file mode 100644 index 0c891fa937..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java +++ /dev/null @@ -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 - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Jan 18, 2012           porricel    Initial Creation
- * Oct 15, 2013  2473     bsteffen    Removed unused method argument.
- * 
- * 
- * 
- * - * @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 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) dao.queryByCriteria(query); - } catch (DataAccessLayerException e) { - throw new GribException( - "Error getting Precip inventory for Canadian-Reg!", e); - } - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - protected List 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) 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 precipInventory = getPrecipInventory(record - .getDataTime().getRefTime()); - - // The current 3-hr precipitation grid inventory in the database - List 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 generatedRecords = new ArrayList(); - 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 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; - } - } - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/DecoderPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/DecoderPostProcessor.java new file mode 100644 index 0000000000..f4139ca58e --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/DecoderPostProcessor.java @@ -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 + * + *
+ * 
+ * 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,
+ * 
+ * 
+ * + * @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 + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ECMWFHiResProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ECMWFHiResProcessor.java index 85083c24a4..ffeeb95853 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ECMWFHiResProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ECMWFHiResProcessor.java @@ -1,187 +1,59 @@ /** * 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 - * + * Grib post processor implementation to scale TP-ECMWF data to the proper unit. + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date          Ticket#  Engineer    Description
  * ------------- -------- ----------- --------------------------
  * Aug 30, 2010  5875     bphillip    Initial Creation
  * Oct 15, 2013  2473     bsteffen    Removed unused method argument.
- * 
- * 
+ * Oct 07, 2015  3756     nabowle     Changed to only do data scaling. Extends
+ *                                    DecoderPostProcessor.
+ *
+ *
  * 
- * + * * @author bphillip * @version 1 */ -public class ECMWFHiResProcessor extends SixHrPrecipGridProcessor { +public class ECMWFHiResProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { // Post process the data if this is a Total Precipitation grid 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 }; } - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - protected List 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) dao.queryByCriteria(query); - } catch (DataAccessLayerException e) { - throw new GribException( - "Error getting Precip inventory for ECMWF!", e); - } - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - protected List 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) 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 precipInventory = getPrecipInventory(record - .getDataTime().getRefTime()); - - // The current 6-hr precipitation grid inventory in the database - List 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 generatedRecords = new ArrayList(); - 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 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; - } - } - } } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java index 030817a673..7da1c6c259 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -51,11 +51,11 @@ import com.raytheon.uf.edex.plugin.grid.PartialGrid; * 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 * into a single grid - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date          Ticket#  Engineer    Description
  * ------------- -------- ----------- --------------------------
  * 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
  * 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.
+ * Oct 07, 2015  3756     nabowle     Extends DecoderPostProcessor.
  * 
- * + * * @author bphillip * @version 1 */ -public class EnsembleGridAssembler implements IDecoderPostProcessor { +public class EnsembleGridAssembler extends DecoderPostProcessor { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(EnsembleGridAssembler.class); @@ -145,7 +146,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { /** * Gets the composite model for the provided model name0 - * + * * @param modelName * The model name to determine the composite model name for * @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 - * + * * @param record * The GridRecord containing the data to add * @param assembledRecord @@ -216,7 +217,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { pGrid.setxOffset((nx * modIndex) - modIndex); pGrid.setyOffset(0); assembledRecord.addExtraAttribute(PartialGrid.KEY, pGrid); - assembledRecord.setMessageData(recordToAssemble.getMessageData()); + assembledRecord.setMessageData(getMessageData(recordToAssemble)); return checkWorldWrap(assembledRecord); } @@ -225,7 +226,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { * Checks if assembledRecord's partial grid has extra columns that wrap * around. This is due to partial grids having 1 column of overlap between * each partial grid. - * + * * @param assembledRecord * @return */ @@ -278,5 +279,4 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { return Util.resizeDataTo1D(rval, ny, nx); } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/FFGGribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/FFGGribPostProcessor.java index 83cb17b975..1848510506 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/FFGGribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/FFGGribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -43,13 +43,14 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * Mar 26, 2013 1821 bsteffen Optimize FFG version query. * Oct 15, 2013 2473 bsteffen Remove deprecated method calls. * Apr 25, 2014 2060 njensen Remove dependency on grid dataURI column + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * * * @author bphillip * @version 1 */ -public class FFGGribPostProcessor implements IDecoderPostProcessor { +public class FFGGribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java deleted file mode 100644 index ccbcfa248c..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java +++ /dev/null @@ -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. - * - *
- * 
- * 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.
- * 
- * 
- * - * @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 generated6hrPrecips = new ArrayList(); - // Get all 6hr records 180Hrs and greater - List precipInventory = getPrecipInventory(record - .getDataTime().getRefTime()); - List generatedRecords = new ArrayList(); - // convert current record to 6hr and add it - GridRecord transformed = transForm12to6(record); - generated6hrPrecips.add(transformed); - precipInventory.add(transformed); - Comparator comparator = new Comparator() { - @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 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) 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); - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java index 8ae072a4c4..b4ad189ae4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java @@ -24,15 +24,22 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; 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.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.message.DataURINotificationMessage; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManagerFactory; 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. * Sep 24, 2015 3731 nabowle Allow pre-registering shortnames and * require fully qualified names otherwise. + * Oct 07, 2015 3756 nabowle Add separate post-processing after the + * decoded record is persisted. * * * @@ -64,6 +73,8 @@ import com.raytheon.uf.common.status.UFStatus; * @version 1 */ public class GribPostProcessor { + private static final GridRecord[] EMPTY_ARR = new GridRecord[] {}; + private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(GribPostProcessor.class); @@ -71,7 +82,7 @@ public class GribPostProcessor { private static GribPostProcessor instance; /** The map containing the currently registered grib post processors */ - private Map> processorMap; + private Map> processorMap; private Map knownProcessors = new HashMap<>(); @@ -110,7 +121,7 @@ public class GribPostProcessor { } } - List processors; + List processors; GridRecord[] results = null; List additionalGrids = null; for (int i = 0; i < records.length; i++) { @@ -118,9 +129,11 @@ public class GribPostProcessor { // which post processing is necessary processors = processorMap.get(records[i].getDatasetId()); if (processors != null) { - for (IDecoderPostProcessor processor : processors) { + for (DecoderPostProcessor processor : processors) { // Post processing is not necessary, so we continue - if (processor == null) { + if (processor == null + || PostProcessorType.POST_PERSIST.equals(processor + .getType())) { continue; } @@ -147,12 +160,83 @@ public class GribPostProcessor { for (int i = 0; i < records.length; 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 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 processors; + GridRecord[] recordResults; + Set 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. * * @param fqClassNames @@ -160,7 +244,7 @@ public class GribPostProcessor { */ public synchronized void register(String... fqClassNames) { String retClass; - IDecoderPostProcessor newProc; + DecoderPostProcessor newProc; Object newObj; for (String className : fqClassNames) { if (className == null || className.trim().isEmpty()) { @@ -177,22 +261,22 @@ public class GribPostProcessor { continue; } - if (!(newObj instanceof IDecoderPostProcessor)) { + if (!(newObj instanceof DecoderPostProcessor)) { statusHandler.warn(className - + " is not an IDecoderPostProcessor"); + + " is not an DecoderPostProcessor"); continue; } - newProc = (IDecoderPostProcessor) newObj; + newProc = (DecoderPostProcessor) newObj; statusHandler.debug("Registering grib post processor for " + className); - retClass = knownProcessors.put(newProc.getClass() - .getSimpleName(), className); + retClass = knownProcessors.put(newProc.getClass().getSimpleName(), + className); /* Warn if two registered classes share the same simple class name. */ if (retClass != null && !retClass.equals(className)) { - statusHandler.warn(retClass - + " has been replaced by " + className); + statusHandler.warn(retClass + " has been replaced by " + + className); } } } @@ -221,7 +305,7 @@ public class GribPostProcessor { statusHandler.info(String.format("Using postProcessorFile [%s]", processorFile)); - Map> newMap = new HashMap<>(); + Map> newMap = new HashMap<>(); /* * Iterate over post processed models. Determine which models apply @@ -232,10 +316,10 @@ public class GribPostProcessor { for (PostProcessedModel ppModel : ppModelSet.getModels()) { for (String modelName : modelNames) { if (modelName.matches(ppModel.getModelName())) { - List processorInstances = newMap + List processorInstances = newMap .get(modelName); if (processorInstances == null) { - processorInstances = new ArrayList(); + processorInstances = new ArrayList(); newMap.put(modelName, processorInstances); } @@ -249,7 +333,7 @@ public class GribPostProcessor { try { processorInstances - .add((IDecoderPostProcessor) Class + .add((DecoderPostProcessor) Class .forName(classToLoad) .newInstance()); } catch (Exception e) { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HPCqpfPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HPCqpfPostProcessor.java index 357edf63c4..b02d171df4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HPCqpfPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HPCqpfPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -28,19 +28,20 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; * This post processor currently looks for precipitation probability grids and * multiplies the data values by 100 to get an actual percentage (values 0-100) * instead of a decimal value (0-1) - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * 6/11/2015    4542       bphillip    Initial creation
- * 
+ * Oct 07, 2015 3756       nabowle     Extends DecoderPostProcessor.
+ *
  * @author bphillip
  * @version 1.0
  */
-public class HPCqpfPostProcessor implements IDecoderPostProcessor {
+public class HPCqpfPostProcessor extends DecoderPostProcessor {
 
     /** Parameter abbreviation patter for perecent probability grids */
     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
         if (parameterAbbreviation.matches(PCT_PROB_PATTERN)) {
             // 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++) {
                 if (data[i] >= 0.0 && data[i] <= 1.0) {
                     data[i] *= 100;
diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HWRFPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HWRFPostProcessor.java
index 5eaea84000..5e9b0a8d49 100644
--- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HWRFPostProcessor.java
+++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/HWRFPostProcessor.java
@@ -1,19 +1,19 @@
 /**
  * This software was developed and / or modified by Raytheon Company,
  * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
- * 
+ *
  * U.S. EXPORT CONTROLLED TECHNICAL DATA
  * This software product contains export-restricted data whose
  * export/transfer/disclosure is restricted by U.S. law. Dissemination
  * to non-U.S. persons whether in the United States or abroad requires
  * an export license or other authorization.
- * 
+ *
  * Contractor Name:        Raytheon Company
  * Contractor Address:     6825 Pine Street, Suite 340
  *                         Mail Stop B8
  *                         Omaha, NE 68106
  *                         402.291.0100
- * 
+ *
  * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
  * further licensing information.
  **/
@@ -46,21 +46,22 @@ import com.vividsolutions.jts.geom.Geometry;
 
 /**
  * HWRF post processor implementation.
- * 
+ *
  * 
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * 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.
+ *
  * 
- * + * * @author rferrel * @version 1 */ -public class HWRFPostProcessor implements IDecoderPostProcessor { +public class HWRFPostProcessor extends DecoderPostProcessor { /** * Format for datasetId prefix --. @@ -131,7 +132,7 @@ public class HWRFPostProcessor implements IDecoderPostProcessor { /** * Add the count in ct's extrainfo to the dataset name prefix. - * + * * @param ct * @param datasetIdPrefix * @return datasetId @@ -156,7 +157,7 @@ public class HWRFPostProcessor implements IDecoderPostProcessor { /** * Find datasetId a result grid that has > 95% intersection with the record. - * + * * @param record * @param result * @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 * info list associated with dsIdPrefix. - * + * * @param record * @param datasetIdPrefix */ diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/IDecoderPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/IDecoderPostProcessor.java deleted file mode 100644 index d1c254b6f6..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/IDecoderPostProcessor.java +++ /dev/null @@ -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 - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#     Engineer    Description
- * ------------ ----------  ----------- --------------------------
- * 8/30/10      5875        bphillip    Initial Creation
- * 
- * 
- * - * @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; -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/LapsPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/LapsPostProcessor.java index 1566aa7e66..458be08bd7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/LapsPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/LapsPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -28,23 +28,24 @@ import com.raytheon.uf.common.parameter.Parameter; /** * Adjusts the LAPS Grib data to have to correct level information - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date          Ticket#  Engineer    Description
  * ------------- -------- ----------- --------------------------
  * Apr 07, 2011  6619     bphillip    Initial creation
  * Oct 15, 2013  2473     bsteffen    Remove deprecated method calls.
  * Sep 09, 2014  3356     njensen     Remove CommunicationException
- * 
+ * Oct 07, 2015  3756     nabowle     Extends DecoderPostProcessor.
+ *
  * 
- * + * * @author bphillip * @version 1.0 */ -public class LapsPostProcessor implements IDecoderPostProcessor { +public class LapsPostProcessor extends DecoderPostProcessor { private static final String FHAG = "FHAG"; diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/MSASPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/MSASPostProcessor.java index b799b8fded..5ba89a6458 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/MSASPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/MSASPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -37,6 +37,7 @@ import com.raytheon.uf.common.parameter.Parameter; * ------------- -------- ----------- -------------------------- * Aug 18, 2011 bphillip Initial creation * Oct 15, 2013 2473 bsteffen Remove deprecated method calls. + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * *
@@ -45,7 +46,7 @@ import com.raytheon.uf.common.parameter.Parameter; * @version 1.0 */ -public class MSASPostProcessor implements IDecoderPostProcessor { +public class MSASPostProcessor extends DecoderPostProcessor { private static final String TSLSA = "TSLSA"; @@ -65,7 +66,7 @@ public class MSASPostProcessor implements IDecoderPostProcessor { /* * (non-Javadoc) - * + * * @see * com.raytheon.edex.plugin.grib.decoderpostprocessors.IDecoderPostProcessor * #process(com.raytheon.uf.common.dataplugin.grib.GridRecord) diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java deleted file mode 100644 index dda454a13b..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java +++ /dev/null @@ -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. - * - *
- * 
- * 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.
- * 
- * 
- * - * @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 results = (List) 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 retVal = new HashSet(); - 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; - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/OverwriteGribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/OverwriteGribPostProcessor.java index ca9c82a6a7..8f097f0d4e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/OverwriteGribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/OverwriteGribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -34,18 +34,18 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 11/12/10 4524 bphillip Initial Creation + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * * * @author bphillip * @version 1 */ -public class OverwriteGribPostProcessor implements IDecoderPostProcessor { +public class OverwriteGribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { record.setOverwriteAllowed(true); return new GridRecord[] { record }; } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RTMAGribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RTMAGribPostProcessor.java index 4424188eb4..dc68c96ee8 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RTMAGribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RTMAGribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -30,23 +30,24 @@ import com.raytheon.uf.common.time.TimeRange; /** * Grib post processor implementation correct the total cloud cover parameter in * the RTMA grib model - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date          Ticket#  Engineer    Description
  * ------------- -------- ----------- --------------------------
  * Feb 01, 2011  6320     bphillip    Initial Creation
  * Oct 15, 2013  2473     bsteffen    Remove deprecated method calls.
- * 
- * 
+ * Oct 07, 2015  3756     nabowle     Extends DecoderPostProcessor.
+ *
+ *
  * 
- * + * * @author bphillip * @version 1 */ -public class RTMAGribPostProcessor implements IDecoderPostProcessor { +public class RTMAGribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC130GribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC130GribPostProcessor.java index b8de53253b..ced7686669 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC130GribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC130GribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -26,21 +26,22 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; /** * Grib post processor implementation to eliminate 2-3hr duration grids from the * RUC130 model - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date         Ticket#     Engineer    Description
  * ------------ ----------  ----------- --------------------------
  * 9/9/10       #4419        bphillip    Initial Creation
- * 
+ * Oct 07, 2015  3756        nabowle     Extends DecoderPostProcessor.
+ *
  * 
- * + * * @author bphillip * @version 1 */ -public class RUC130GribPostProcessor implements IDecoderPostProcessor { +public class RUC130GribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC236GribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC236GribPostProcessor.java index 74c8e65164..722bdb12a5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC236GribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/RUC236GribPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -34,13 +34,13 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 1/24/2012 DR 14263 M. Porricelli Initial Creation - * + * Oct 07, 2015 3756 nabowle Extends DecoderPostProcessor. * * * @author porricel * @version 1 */ -public class RUC236GribPostProcessor implements IDecoderPostProcessor { +public class RUC236GribPostProcessor extends DecoderPostProcessor { @Override public GridRecord[] process(GridRecord record) throws GribException { diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java deleted file mode 100644 index 4ddb30ba4c..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java +++ /dev/null @@ -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 - * - * - *
- * 
- * 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.
- * 
- * 
- * - * @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 generate6hrPrecip(GridRecord record, - List precipInventory) - throws GribException { - List tp6hrRecords = new ArrayList(); - 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); - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/TemperatureCorrectionPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/TemperatureCorrectionPostProcessor.java index e14a1e01be..ae793148db 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/TemperatureCorrectionPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/TemperatureCorrectionPostProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -45,31 +45,32 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; /** - * + * * Adjusts temperature values that are mislabled as Celsius or Kelvin when they * 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 * 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 * if the declared unit is Kelvin - * + * *
- * 
+ *
  * SOFTWARE HISTORY
- * 
+ *
  * Date          Ticket#  Engineer    Description
  * ------------- -------- ----------- --------------------------
  * Mar 28, 2010  2874     bsteffen    Initial creation
  * Apr 25, 2014  2060     njensen     Use JAXB instead of JAXBManager
- * 
- * 
+ * Oct 07, 2015  3756     nabowle     Extends DecoderPostProcessor.
+ *
+ *
  * 
- * + * * @author bsteffen * @version 1.0 */ -public class TemperatureCorrectionPostProcessor implements - IDecoderPostProcessor, ILocalizationFileObserver { +public class TemperatureCorrectionPostProcessor extends DecoderPostProcessor + implements ILocalizationFileObserver { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(TemperatureCorrectionPostProcessor.class); @@ -208,5 +209,4 @@ public class TemperatureCorrectionPostProcessor implements } } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java index abd504a54d..f2ac5511b0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -34,7 +34,11 @@ import com.raytheon.uf.common.time.TimeRange; 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 * * *
@@ -46,14 +50,15 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao;
  * Jan 24, 2012  14299    M. Porricelli Initial creation
  * Aug 30, 2013  2298     rjpeter       Make getPluginName abstract
  * Oct 15, 2013  2473     bsteffen      Removed deprecated and unused code.
+ * Oct 07, 2015  3756     nabowle       Extends DecoderPostProcessor.
  * 
  * 
* * @author porricel * @version 1.0 */ -public abstract class ThreeHrPrecipGridProcessor implements - IDecoderPostProcessor { +public abstract class ThreeHrPrecipGridProcessor extends + DecoderPostProcessor { /** The number of seconds in 3 hours */ protected static final int SECONDS_IN_3_HRS = 10800; @@ -78,7 +83,7 @@ public abstract class ThreeHrPrecipGridProcessor implements /** * Generates the 3hr precipitation grid - * + * * @param record * The current record to clone and modify to produce the new 3hr * grid @@ -113,7 +118,7 @@ public abstract class ThreeHrPrecipGridProcessor implements /** * Generates the 3hr precipitation grid from the current grid and the * previous grid - * + * * @param inventoryRecord * The previous grid from the inventory * @param currentRecord @@ -178,7 +183,7 @@ public abstract class ThreeHrPrecipGridProcessor implements /** * 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 @@ -189,7 +194,7 @@ public abstract class ThreeHrPrecipGridProcessor implements /** * Modifies the DataTime of the provided record to include a 3hr time range - * + * * @param record * The record to modify the datatime for */ diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfig.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfig.java new file mode 100644 index 0000000000..0858e6d94a --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfig.java @@ -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. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 28, 2015 3756       nabowle     Initial creation
+ *
+ * 
+ * + * @author nabowle + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +public class AccumulationConfig { + + @XmlElement(name = "model") + private List models; + + @XmlElement(name = "create") + private List 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 models, + List creations) { + super(); + this.models = models; + this.creations = creations; + } + + /** + * @return the models + */ + public List getModels() { + return models; + } + + /** + * @param models + * the models to set + */ + public void setModels(List 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 getCreations() { + return creations; + } + + /** + * @param creations + * the creations to set + */ + public void setCreations(List 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 getCreations(String parameter, + boolean matchMinuend) { + List 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 GFS215|GFS217} and + * {@code GFS217|GFS215} 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()); + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfigs.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfigs.java new file mode 100644 index 0000000000..f0f338beaa --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationConfigs.java @@ -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. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 28, 2015 3756       nabowle     Initial creation
+ *
+ * 
+ * + * @author nabowle + * @version 1.0 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class AccumulationConfigs { + + @XmlElement(name = "accumulation") + private List accumulations; + + /** + * Constructor. + */ + public AccumulationConfigs() { + super(); + } + + /** + * Constructor. + * + * @param accums + * The list of accumulations. + */ + public AccumulationConfigs(List accums) { + this.accumulations = accums; + } + + /** + * @return the accumulations + */ + public List getAccumulations() { + return accumulations; + } + + /** + * @param accumulations + * the accumulations to set + */ + public void setAccumulations(List 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 getAccumulations(String model) { + List 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); + } + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationCreationConfig.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationCreationConfig.java new file mode 100644 index 0000000000..2d67bcdd48 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/AccumulationCreationConfig.java @@ -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. + * + *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 28, 2015 3756       nabowle     Initial creation
+ *
+ * 
+ * + * @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; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/PrecipAccumPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/PrecipAccumPostProcessor.java new file mode 100644 index 0000000000..790dd5edbd --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/precipitation/PrecipAccumPostProcessor.java @@ -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. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 28, 2015 3756       nabowle     Initial creation
+ *
+ * 
+ * + * @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 retRecords = new ArrayList<>(); + + List 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 generatePrecipGrids(GridRecord record, + AccumulationConfig accumConfig) throws GribException { + List retRecords = new ArrayList<>(); + + List 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 generatePrecipGrids( + GridRecord record, AccumulationCreationConfig creation, + boolean isMinuend) throws GribException { + + List minuendInv = new ArrayList<>(); + List subtrahendInv = new ArrayList<>(); + Set targetForecastInv = new HashSet<>(); + initInventories(record, isMinuend, creation, minuendInv, subtrahendInv, + targetForecastInv); + + List 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 minuendInv, + List subtrahendInv, Set 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 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) 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 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) 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 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; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/notification/grid-postprocessing.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/notification/grid-postprocessing.xml new file mode 100644 index 0000000000..7c0b43d41e --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/notification/grid-postprocessing.xml @@ -0,0 +1,14 @@ + + + Grid.PostProcess + DATAURI + QUEUE + true + 120000 + + + + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml index c9134a8c39..7a387c2845 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml @@ -1,129 +1,131 @@ - - - UKMET[0-9]{2}|ECMF[0-9]|ENSEMBLE[0-9]{2}|AVN[0-9]{2} - - EnsembleGridAssembler - + + + UKMET[0-9]{2}|ECMF[0-9]|ENSEMBLE[0-9]{2}|AVN[0-9]{2} + + EnsembleGridAssembler + - - - HPCqpfNDFD - OverwriteGribPostProcessor - + + + HPCqpfNDFD + OverwriteGribPostProcessor + - - RFCqpf - OverwriteGribPostProcessor - + + RFCqpf + OverwriteGribPostProcessor + - - HPCqpf - OverwriteGribPostProcessor - + + HPCqpf + OverwriteGribPostProcessor + - - MPE-.*|QPE-.* - OverwriteGribPostProcessor - + + MPE-.*|QPE-.* + OverwriteGribPostProcessor + - - URMA25 - OverwriteGribPostProcessor - + + URMA25 + OverwriteGribPostProcessor + - - - FFG-[A-Z]{3} - FFGGribPostProcessor - + + + FFG-[A-Z]{3} + FFGGribPostProcessor + - - - ETA218|GFS212|GFS213|ETA242|RTOFS-.* - TemperatureCorrectionPostProcessor - + + + ETA218|GFS212|GFS213|ETA242|RTOFS-.* + TemperatureCorrectionPostProcessor + - - - RTMA - RTMAGribPostProcessor - + + + RTMA + RTMAGribPostProcessor + - - - ECMWF-HiRes - ECMWFHiResProcessor - + + + ECMWF-HiRes + ECMWFHiResProcessor + PrecipAccumPostProcessor + - - - MSAS - MSASPostProcessor - + + + MSAS + MSASPostProcessor + - - - ETA - Nam80PostProcessor - + + + ETA + PrecipAccumPostProcessor + OverwriteGribPostProcessor + - - - RUC236 - RUC236GribPostProcessor - + + + RUC236 + RUC236GribPostProcessor + - - - CPCoutlook211 - CPCoutlookGribPostProcessor - + + + CPCoutlook211 + CPCoutlookGribPostProcessor + - - - Canadian-NH - CanadianNHPostProcessor - + + + Canadian-NH + PrecipAccumPostProcessor + - - Canadian-Reg - CanadianRegPostProcessor - + + Canadian-Reg + PrecipAccumPostProcessor + - - - LAPS - LapsPostProcessor - + + + LAPS + LapsPostProcessor + - - - RUC130 - RUC130GribPostProcessor - - - - - HPCqpfNDFD + + + RUC130 + RUC130GribPostProcessor + + + + + HPCqpfNDFD HPCqpfPostProcessor - - - - GFS215|GFS217|GFS20-* - gov.noaa.nws.crh.edex.grib.decoderpostprocessor.GFS20PostProcessor - - + + + + GFS215|GFS217|GFS20-.* + PrecipAccumPostProcessor + + - - - ARI - ARIPostProcessor - + + + ARI + ARIPostProcessor + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/precipitationAccumulation.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/precipitationAccumulation.xml new file mode 100644 index 0000000000..3ab1bbf1aa --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/precipitationAccumulation.xml @@ -0,0 +1,37 @@ + + + + Canadian-Reg + + + + + Canadian-NH + + + + + ECMWF-HiRes + + + + + GFS215|GFS217|GFS20-.* + + + + + ETA + + + + + + + \ No newline at end of file