Merge branch 'unidata_18.2.1' of github.com:Unidata/awips2 into docChanges

This commit is contained in:
Tiffany Meyer 2021-08-16 13:42:45 -04:00
commit a9c71e58f6
4 changed files with 106 additions and 139 deletions

View file

@ -1,3 +1,2 @@
bin.includes = META-INF/,\
.,\
utility/

View file

@ -2,5 +2,4 @@ source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/,\
utility/
res/

View file

@ -1,24 +1,25 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.plugin.modelsounding.decoder;
import java.io.File;
import java.util.Calendar;
import java.util.List;
@ -26,12 +27,11 @@ import com.raytheon.uf.common.dataplugin.modelsounding.SoundingLevel;
import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite;
import com.raytheon.uf.common.geospatial.spi.SPIContainer;
import com.raytheon.uf.common.geospatial.spi.SPIEntry;
import com.raytheon.uf.common.localization.ILocalizationFile;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationUtil;
import com.raytheon.uf.common.localization.PathManager;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.pointdata.PointDataContainer;
import com.raytheon.uf.common.pointdata.PointDataDescription;
@ -43,6 +43,7 @@ import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.wmo.WMOHeader;
import com.raytheon.uf.edex.bufrtools.BUFRDataDocument;
import com.raytheon.uf.edex.bufrtools.descriptors.BUFRDescriptor;
import com.raytheon.uf.edex.bufrtools.packets.BUFRStringPacket;
import com.raytheon.uf.edex.bufrtools.packets.BUFRSublistPacket;
import com.raytheon.uf.edex.bufrtools.packets.DataPacketTypes;
import com.raytheon.uf.edex.bufrtools.packets.IBUFRDataPacket;
@ -53,7 +54,7 @@ import com.raytheon.uf.edex.plugin.modelsounding.common.SoundingModels;
/**
* This class contains several utility methods that construct a ProfilerObs
* instance from the BUFR decoded data.
*
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
@ -68,11 +69,13 @@ import com.raytheon.uf.edex.plugin.modelsounding.common.SoundingModels;
* Sep 16, 2014 3628 mapeters Replaced static imports.
* Jul 12, 2016 5744 mapeters SoundingStations constructor no longer takes
* path parameter
* Jan 04, 2018 7100 dgilling Code cleanup, read SPI file from
* CONFIGURED level.
*
* Sep 05, 2018 mjames@ucar Remove modelBufr filter.
*
* May 19, 2021 22629 mgamazaychikov Fixed the header issue for GFS v16 update
*
* </pre>
*
*
* @author jkorman
*/
public class ModelSoundingDataAdapter {
@ -82,48 +85,13 @@ public class ModelSoundingDataAdapter {
private static final Object LOCK = new Object();
public static final String SPI_FILE = LocalizationUtil.join("basemaps",
"modelBufr.spi");
public static final String MODEL_STATION_LIST_FILENAME = "modelBufrStationList.txt";
public static final String MODEL_STATION_LIST_PATH = LocalizationUtil
.join("modelsounding", MODEL_STATION_LIST_FILENAME);
public static final String MODEL_STATION_LIST = "modelBufrStationList.txt";
private static SoundingStations stationsList = new SoundingStations();
private static SPIContainer SPI_DATA = populateSPIData();
public static void updateSPIData() {
SPIContainer spi = populateSPIData();
synchronized (LOCK) {
if ((spi != null) && (spi.isLoaded())) {
SPI_DATA = spi;
}
}
}
public static void updateStationList() {
SoundingStations ss = new SoundingStations();
synchronized (LOCK) {
stationsList = ss;
}
}
public static void update() {
SoundingStations ss = new SoundingStations();
SPIContainer spi = populateSPIData();
synchronized (LOCK) {
stationsList = ss;
if ((spi != null) && (spi.isLoaded())) {
SPI_DATA = spi;
}
}
}
/**
* Get the temporal and model information.
*
*
* @param dataDoc
* @param wmoHeader
* @return
@ -169,7 +137,7 @@ public class ModelSoundingDataAdapter {
/**
* Construct a ProfilerObs instance from the BUFR decoded data contained in
* the specified separator.
*
*
* @param iterator
* A iterator containing decoded BUFR data.
* @param wmoHeader
@ -223,7 +191,7 @@ public class ModelSoundingDataAdapter {
/**
* Extract all header data from the "main" observation list.
*
*
* @param dataList
* List of data packets to get data from.
* @return The ProfilerObs with primary data populated.
@ -241,57 +209,57 @@ public class ModelSoundingDataAdapter {
obsData = new SoundingSite();
SurfaceObsLocation location = new SurfaceObsLocation();
IBUFRDataPacket dp = dataList.get(index);
index++;
IBUFRDataPacket dp = dataList.get(index++);
/*
* dp is forecastHr packet, already handled in
* SoundingModelTemporalData
*/
int wmoStaNum = getInt(dataList.get(index), -9999);
index++;
int wmoStaNum = getInt(dataList.get(index++), -9999);
view.setInt("wmoStaNum", wmoStaNum);
// Map the WMO station number to a station Id
String stationId = stationsList.mapId(String.format("%010d",
wmoStaNum));
// Now determine if the station Id is in this localization list.
SPIEntry s = SPI_DATA.getEntryById(stationId);
if (s != null) {
if (stationId != null) {
location.setStationId(stationId);
obsData.setSiteId(String.format("%06d", wmoStaNum));
}
if (model.equals(SoundingModels.MODEL_ETA)) {
if (stationId != null) {
location.setStationId(stationId);
obsData.setSiteId(String.format("%06d", wmoStaNum));
}
if (model.equals(SoundingModels.MODEL_ETA)) {
index++;
} else if (model.equals(SoundingModels.MODEL_GFS)) {
// GFS v16 data headers have station ID just like MODEL_ETA headers
// For that type of data index needs to be incremented so the
// reading of station ID is skipped.
dp = dataList.get(index);
if (dp instanceof BUFRStringPacket) {
index++;
}
Double lat = null;
dp = dataList.get(index);
index++;
int d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 5, 2)) {
lat = (Double) dp.getValue();
}
Double lon = null;
dp = dataList.get(index);
index++;
d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 6, 2)) {
lon = (Double) dp.getValue();
}
location.assignLocation(lat.floatValue(), lon.floatValue());
dp = dataList.get(index);
d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 10, 194)) {
stationHeight = (dp.getValue() != null) ? ((Double) dp
.getValue()).intValue() : null;
location.setElevation(stationHeight);
}
obsData.setLocation(location);
obsData.setPointDataView(view);
} else {
obsData = null;
}
Double lat = null;
dp = dataList.get(index++);
int d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 5, 2)) {
lat = (Double) dp.getValue();
}
Double lon = null;
dp = dataList.get(index++);
d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 6, 2)) {
lon = (Double) dp.getValue();
}
location.assignLocation(lat.floatValue(), lon.floatValue());
dp = dataList.get(index);
d = dp.getReferencingDescriptor().getDescriptor();
if (d == BUFRDescriptor.createDescriptor(0, 10, 194)) {
stationHeight = (dp.getValue() != null) ? ((Double) dp
.getValue()).intValue() : null;
location.setElevation(stationHeight);
}
obsData.setLocation(location);
obsData.setPointDataView(view);
}
return obsData;
@ -299,7 +267,7 @@ public class ModelSoundingDataAdapter {
/**
* Extract all header data from the "main" observation list.
*
*
* @param siteData
* List of data packets to get data from.
* @return The ProfilerObs with primary data populated.
@ -310,7 +278,16 @@ public class ModelSoundingDataAdapter {
if ((dataList != null) && (siteData != null)) {
// get the replication sublist for the sounding data
IBUFRDataPacket p = dataList.get(5);
// istart is the number of header fields in the packet
// in the pre v16 GFS the header has 5 fields
// in the v16 upgrade the header has 6 fields
// use 3rd IBUFRDataPacket to determine the version
IBUFRDataPacket dp = dataList.get(2);
int istart = 6;
if (!(dp instanceof BUFRStringPacket)) {
istart = 5;
}
IBUFRDataPacket p = dataList.get(istart);
if ((p instanceof BUFRSublistPacket)
&& (DataPacketTypes.RepSubList.getPacketType().equals(p
.getUnits()))) {
@ -359,7 +336,7 @@ public class ModelSoundingDataAdapter {
/**
* Creates individual level data from level "sublists" that were decoded.
*
*
* @param levelList
* A sublist containing level data.
* @param level
@ -387,7 +364,7 @@ public class ModelSoundingDataAdapter {
/**
* Extract all header data from the "main" observation list.
*
*
* @param siteData
* List of data packets to get data from.
* @return The ProfilerObs with primary data populated.
@ -526,26 +503,4 @@ public class ModelSoundingDataAdapter {
return retValue;
}
private static SPIContainer populateSPIData() {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.CONFIGURED);
String site = ctx.getContextName();
logger.info("Loading " + SPI_FILE + " for site [" + site + "]");
ILocalizationFile srcFile = pathMgr.getLocalizationFile(ctx, SPI_FILE);
SPIContainer container = new SPIContainer(srcFile);
if (container.isLoaded()) {
logger.info("Loading " + SPI_FILE + " for site [" + site
+ "] Successful");
} else {
logger.error("Loading " + SPI_FILE + " for site [" + site
+ "] failed");
}
return container;
}
}

View file

@ -1,19 +1,19 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
@ -27,57 +27,70 @@ import java.util.Map;
import com.raytheon.uf.common.localization.ILocalizationFile;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Loads a map from a file (modelBufrStationList.txt) for mapping wmo numbers to
* icaos.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------------------------
* Aug 10, 2009 jkorman Initial creation
* Dec 02, 2013 2537 bsteffen Switch logger to ufstatus.
* Jul 08, 2016 5744 mapeters Config file moved from edex_static to
* common_static, cleanup
* Jan 04, 2018 7100 dgilling Code cleanup, read from CONFIGURED level.
*
*
* </pre>
*
*
* @author jkorman
*/
public class SoundingStations {
private static final String STATION_LIST = ModelSoundingDataAdapter.MODEL_STATION_LIST;
private static final IUFStatusHandler logger = UFStatus
.getHandler(SoundingStations.class);
private static final String STATION_LIST = ModelSoundingDataAdapter.MODEL_STATION_LIST_FILENAME;
private static final String STATION_LIST_PATH = ModelSoundingDataAdapter.MODEL_STATION_LIST_PATH;
private final Map<String, String> stationMap;
private static Map<String, String> stationMap;
public SoundingStations() {
this.stationMap = new HashMap<>();
stationMap = new HashMap<>();
populateMap();
}
private void populateMap() {
try {
IPathManager pm = PathManagerFactory.getPathManager();
ILocalizationFile locFile = pm.getStaticLocalizationFile(
LocalizationType.COMMON_STATIC, STATION_LIST_PATH);
String fullLocPath = "modelsounding" + IPathManager.SEPARATOR
+ STATION_LIST;
if (locFile != null) {
/*
* Check SITE first, as the updated config file is stored there when
* NDM files are ingested. If not found, use default BASE file.
*/
LocalizationContext context = pm.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
ILocalizationFile srcFile = pm.getLocalizationFile(context,
fullLocPath);
if (srcFile == null || !srcFile.exists()) {
context = pm.getContext(LocalizationType.COMMON_STATIC,
LocalizationLevel.BASE);
srcFile = pm.getLocalizationFile(context, fullLocPath);
}
if (srcFile != null && srcFile.exists()) {
try (BufferedReader bf = new BufferedReader(
new InputStreamReader(locFile.openInputStream()))) {
new InputStreamReader(srcFile.openInputStream()))) {
int count = 0;
String line = null;
while ((line = bf.readLine()) != null) {
@ -92,13 +105,14 @@ public class SoundingStations {
logger.debug(String.format("Read %d stationIds from %s.",
count, STATION_LIST));
} catch (IOException ioe) {
logger.error("Unable to read sounding stations from ["
+ locFile + "].", ioe);
logger.handle(Priority.PROBLEM, ioe.getLocalizedMessage(),
ioe);
}
} else {
logger.error("Localization file " + STATION_LIST_PATH
logger.error("Localization file " + fullLocPath
+ " does not exist");
}
} catch (Exception e) {
logger.error("Error reading model sounding station list", e);
}
@ -106,7 +120,7 @@ public class SoundingStations {
/**
* Map a modelsounding wmoId to a pseudoICAO identifier.
*
*
* @param stationId
* @return
*/