diff --git a/cave/build/cave/memorySettings.xml b/cave/build/cave/memorySettings.xml index fa2998cf5c..7e1d2bbfa4 100644 --- a/cave/build/cave/memorySettings.xml +++ b/cave/build/cave/memorySettings.xml @@ -175,11 +175,11 @@ - 256M + 384M - 64M + 96M diff --git a/cave/build/static/win32.x86/cave/lib/zlib1.dll b/cave/build/static/win32.x86/cave/lib/zlib1.dll new file mode 100644 index 0000000000..076f50336d Binary files /dev/null and b/cave/build/static/win32.x86/cave/lib/zlib1.dll differ diff --git a/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/rsc/HpeLabelResource.java b/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/rsc/HpeLabelResource.java index 1d89badae1..97793709d6 100644 --- a/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/rsc/HpeLabelResource.java +++ b/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/rsc/HpeLabelResource.java @@ -65,6 +65,7 @@ import com.raytheon.viz.grid.rsc.general.D2DGridResource; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 5, 2014 3026 mpduff Initial creation + * Dec 16, 2014 3026 mpduff Change location of text * * * @@ -121,7 +122,7 @@ public class HpeLabelResource extends .getResourcesByTypeAsType(D2DGridResource.class); if (!list.isEmpty()) { double[] pixel = paintProps.getView().getDisplayCoords( - new double[] { 125, 50 }, target); + new double[] { 125, 100 }, target); RGB color = getCapability(ColorableCapability.class).getColor(); for (D2DGridResource rsc : list) { GridRecord currentGridRec = rsc.getCurrentGridRecord(); diff --git a/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/util/HpeUtils.java b/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/util/HpeUtils.java index 7d38180a93..17f528b367 100644 --- a/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/util/HpeUtils.java +++ b/cave/com.raytheon.uf.viz.hpe/src/com/raytheon/uf/viz/hpe/util/HpeUtils.java @@ -32,7 +32,8 @@ import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * May 6, 2014 3026 mpduff Initial creation + * May 6, 2014 3026 mpduff Initial creation. + * Jan 6, 2015 3026 mpduff Added Bias HPE. * * * @@ -43,6 +44,8 @@ import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup; public class HpeUtils { private static final String HPE = "HPE"; + private static final String BIAS_HPE = "BiasHPE"; + /** * Determine if this title represents an HPE model. * @@ -64,6 +67,7 @@ public class HpeUtils { if (title == null) { return false; } - return HPE.equals(title); + + return HPE.equals(title) || BIAS_HPE.equals(title); } } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java index 452a15e522..70e3c8620e 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java @@ -198,6 +198,7 @@ import com.vividsolutions.jts.geom.Point; * assignments. * Sep 23, 2014 3009 njensen Overrode recycleInternal() * Nov 10, 2014 3026 dhladky HPE BIAS displays. + * Dec 16, 2014 3026 mpduff Change location of text * * * @author dhladky @@ -1495,7 +1496,7 @@ public class FFMPResource extends private void paintProductString(IGraphicsTarget target, PaintProperties paintProps) throws VizException { double[] pixel = paintProps.getView().getDisplayCoords( - new double[] { 110, 50 }, target); + new double[] { 110, 100 }, target); StringBuilder sb = new StringBuilder(); if (isAutoRefresh || isQuery) { sb.append("FFMP ").append(df.format(getTime())).append(" hour ") @@ -4171,8 +4172,9 @@ public class FFMPResource extends } /** - * This method creates the upper left legend text for HPE derived QPE sources. - * It is only used for HPE QPE sources. + * This method creates the upper left legend text for HPE derived QPE + * sources. It is only used for HPE QPE sources. + * * @param date * @return */ @@ -4190,18 +4192,18 @@ public class FFMPResource extends } /** - * HPE source lookup job + * HPE source lookup job * *
-     *
+     * 
      * SOFTWARE HISTORY
-     *
+     * 
      * Date         Ticket#    Engineer    Description
      * ------------ ---------- ----------- --------------------------
      * Nov 11, 2014  3026       dhladky     Initial creation
-     *
+     * 
      * 
- * + * * @author dhladky * @version 1.0 */ diff --git a/cave/com.raytheon.uf.viz.thinclient.cave/src/com/raytheon/uf/viz/thinclient/cave/refresh/ThinClientDataUpdateTree.java b/cave/com.raytheon.uf.viz.thinclient.cave/src/com/raytheon/uf/viz/thinclient/cave/refresh/ThinClientDataUpdateTree.java index 302610d774..f4763e6a2e 100644 --- a/cave/com.raytheon.uf.viz.thinclient.cave/src/com/raytheon/uf/viz/thinclient/cave/refresh/ThinClientDataUpdateTree.java +++ b/cave/com.raytheon.uf.viz.thinclient.cave/src/com/raytheon/uf/viz/thinclient/cave/refresh/ThinClientDataUpdateTree.java @@ -28,12 +28,12 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; -import com.raytheon.uf.common.inventory.exception.DataCubeException; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataquery.requests.DbQueryRequest; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; import com.raytheon.uf.common.dataquery.responses.DbQueryResponse; +import com.raytheon.uf.common.inventory.exception.DataCubeException; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; @@ -62,6 +62,7 @@ import com.raytheon.viz.grid.util.RadarAdapter; * Dec 13, 2011 bsteffen Initial creation * Feb 21, 2014 DR 16744 D. Friedman Add radar/grid updates * Apr 1, 2014 DR 17220 D. Friedman Handle uninitialized grid inventory + * Dec 15, 2014 3923 bsteffen Retrieve pdo for grid instead of dataURI. * * * @@ -179,14 +180,14 @@ public class ThinClientDataUpdateTree extends DataUpdateTree { newQuery.put("insertTime", new RequestConstraint(time, ConstraintType.GREATER_THAN)); dbRequest.setConstraints(newQuery); - dbRequest.addRequestField("dataURI"); DbQueryResponse response = null; try { response = (DbQueryResponse) ThriftClient.sendRequest(dbRequest); - for (String dataURI : response.getFieldObjects("dataURI", - String.class)) { + + for (PluginDataObject pdo : response + .getEntityObjects(PluginDataObject.class)) { AlertMessage am = new AlertMessage(); - am.dataURI = dataURI; + am.dataURI = pdo.getDataURI(); am.decodedAlert = RecordFactory.getInstance().loadMapFromUri( am.dataURI); messages.add(am); diff --git a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textProducts/HLSTCV_Common.py b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textProducts/HLSTCV_Common.py index 495b5f317e..8433cc49a9 100644 --- a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textProducts/HLSTCV_Common.py +++ b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textProducts/HLSTCV_Common.py @@ -1,35 +1,170 @@ -# Version 2014.11.21-0 +# Version 2014.12.17-0 + import GenericHazards import JsonSupport +import LocalizationSupport import string, time, os, errno, re, types, copy, collections import LogStream, ModuleAccessor, SampleAnalysis, EditAreaUtils import math +import pprint -try: # See if this is the AWIPS I environment - import AFPS - from AFPS import AbsTime - from IFPDialog import Dialog - AWIPS_ENVIRON = "AWIPS1" -except: # Must be the AWIPS II environment - from AbsTime import * - from StartupDialog import IFPDialog as Dialog - from LockingFile import File - from com.raytheon.uf.common.localization import PathManagerFactory - from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType - AWIPS_ENVIRON = "AWIPS2" +from AbsTime import * +from StartupDialog import IFPDialog as Dialog +from LockingFile import File +AWIPS_ENVIRON = "AWIPS2" class TextProduct(GenericHazards.TextProduct): Definition = copy.deepcopy(GenericHazards.TextProduct.Definition) def __init__(self): GenericHazards.TextProduct.__init__(self) + self._pp = pprint.PrettyPrinter() - ###################################################### - # Populate Product Parts for HLS and TCV - ###################################################### + + ############################################################### + ### Hazards and Additional Hazards + ### allowedHazards is used for VTEC records and summary + ### headlines + ### allowedHeadlines are additional hazards reported in + ### certain sections + ############################################################### + + ############################################################### + ### Initialization + ############################################################### + + ############################################################### + ### Analysis Lists, SampleAnalysis Overrides and other + ### analysis related methods + ############################################################### + + ############################################################### + ### Product Parts Implementation + ############################################################### + + ############################################################### + ### Product Dictionary methods for creating, populating and + ### formatting the product dictionary + ############################################################### + + ############################################################### + ### Sampling and Statistics related methods + ############################################################### + + ############################################################### + ### Area, Zone and Segment related methods + ############################################################### + + ############################################################### + ### Hazards related methods + ############################################################### + + ############################################################### + ### Time related methods + ############################################################### + + ############################################################### + ### Storm Information and TCP related methods + ############################################################### + + ############################################################### + ### Advisory related methods + ############################################################### + + ############################################################### + ### GUI related methods + ############################################################### + + + ############################################################### + ### Hazards and Additional Hazards + + def allowedHazards(self): + tropicalActions = ["NEW", "EXA", "CAN", "CON"] + return [ + ('HU.A',tropicalActions,'Hurricane'), + ('HU.W',tropicalActions,'Hurricane'), + ('SS.A',tropicalActions,'Surge'), + ('SS.W',tropicalActions,'Surge'), + ('TR.A',tropicalActions,'Tropical'), + ('TR.W',tropicalActions,'Tropical'), + ] + def allowedHeadlines(self): + allActions = ["NEW", "EXA", "EXB", "EXT", "CAN", "CON", "EXP"] + return [ + ('FF.A', allActions, 'Flood'), # FLASH FLOOD WATCH + ('FA.A', allActions, 'Flood'), # FLOOD WATCH + ('TO.A', allActions, 'Convective'), # TORNADO WATCH + ] + + ############################################################### + ### Initialization + + def _initializeVariables(self, argDict): + # Get variables + error = self._getVariables(argDict) + if error is not None: + return error + + self._backupFullStationID = self._fullStationID + self._argDict = argDict + + argDict["definition"] = self._definition + + self._initializeTimeVariables(argDict) + + self._initializeHazardsTable(argDict) + + error = self._initializeStormInformation() + if error is not None: + return error + + # Set up the areaDictionary for all to use + accessor = ModuleAccessor.ModuleAccessor() + self._areaDict = accessor.variable(self._areaDictionary, "AreaDictionary") + self._tpc = TextProductCommon() + self._tpc.setUp(self._areaDict) + + return None + + ############################################################### + ### Analysis Lists, SampleAnalysis Overrides and other + ### analysis related methods + + def moderated_dict(self, parmHisto, timeRange, componentName): + """ + Specifies the lower percentages and upper percentages of + data to be thrown out for moderated stats. + """ + # COMMENT: This dictionary defines the low and high limit at which + # outliers will be removed when calculating moderated stats. + # By convention the first value listed is the percentage + # allowed for low values and second the percentage allowed + # for high values. + + # Get Baseline thresholds + dict = SampleAnalysis.SampleAnalysis.moderated_dict( + self, parmHisto, timeRange, componentName) + + # Change thresholds + dict["Wind"] = (0, 15) + dict["WindGust"] = (0, 15) + dict["pws34int"] = (0, 5) + dict["pws64int"] = (0, 5) + dict["pwsD34"] = (0, 5) + dict["pwsN34"] = (0, 5) + dict["pwsD64"] = (0, 5) + dict["pwsN64"] = (0, 5) + dict["InundationMax"] = (0, 5) + dict["InundationTiming"] = (0, 5) + return dict + + ############################################################### + ### Product Parts Implementation + ################# Product Level - + def _wmoHeader(self, productDict, productSegmentGroup, arguments=None): headerDict = collections.OrderedDict() headerDict['TTAAii'] = self._wmoID @@ -55,7 +190,193 @@ class TextProduct(GenericHazards.TextProduct): headerDict['issuedByString'] = self.getIssuedByString() headerDict['issuanceTimeDate'] = self._timeLabel productDict['productHeader'] = headerDict + + ################# Mixed Level + + def _ugcHeader(self, productDict, productSegmentGroup, productSegment): + productDict['ugcCodes'] = self._formatUGC_entries() + self._ugcHeader_value = self._tpc.formatUGCs(self._ugcs, self._expireTime) + productDict['ugcHeader'] = self._ugcHeader_value + + ################# Product Parts Processing + + def _processProductParts(self, productGenerator, productDict, productSegmentGroup, productParts): + ''' + @param productDict + @param productSegmentGroup + @param productParts + @return product dictionary created from the product parts + + Note that this method is called recursively such that a product part is allowed to be + a set of subParts specified as follows: + (subPartLabel, list of productParts for each subPart) + For example, we have + ('segments', [list of [segment product parts]]) + # Product Dictionary + # Contains information for all formats e.g. + # partner XML, CAP, and Legacy text + ''' + + + if type(productParts) is types.DictType: + arguments = productParts.get('arguments') + partsList = productParts.get('partsList') + else: + partsList = productParts + + removedParts = [] + for part in partsList: + if type(part) is types.TupleType: + # e.g. subPart == 'segments', subPartsLists == list of parts for each segment + subPart, subPartsLists = part + subParts = [] + for subPartsList in subPartsLists: + subDict = collections.OrderedDict() + self._processProductParts(productGenerator, subDict, productSegmentGroup, subPartsList) + subParts.append(subDict) + # e.g. productDict['segments'] = segment dictionaries + productDict[subPart] = subParts + else: + if part not in self._noOpParts(): + execString = 'productGenerator._'+part+'(productDict, productSegmentGroup, arguments)' + exec execString + if part not in productDict: + removedParts.append(part) + + for part in removedParts: + self.debug_print("in _processProductParts - " + + "Removing product part = %s" % (part), 1) + partsList.remove(part) + + ################# Product Parts Helper Methods + + def _formatUGC_entries(self): + ugcCodeList = [] + for ugc in self._ugcs: + areaDictEntry = self._areaDict.get(ugc) + if areaDictEntry is None: + # We are not localized correctly for the hazard + # So get the first dictionary entry + self.logger.info('Not Localized for the hazard area -- ugc' + ugc) + keys = self._areaDict.keys() + areaDictEntry = self._areaDict.get(keys[0]) + ugcEntry = collections.OrderedDict() + ugcEntry['state'] = areaDictEntry.get('stateAbbr') + ugcEntry['type'] = self._getUgcInfo(ugc, 'type') + ugcEntry['number'] = self._getUgcInfo(ugc, 'number') + ugcEntry['text'] = ugc + ugcEntry['subArea'] = '' + ugcCodeList.append(ugcEntry) + return ugcCodeList + + def _getUgcInfo(self, ugc, part='type'): + if part == 'type': + if ugc[2] == 'C': + return 'County' + else: + return 'Zone' + if part == 'number': + return ugc[3:] + + ############################################################### + ### Product Dictionary methods for creating, populating and + ### formatting the product dictionary + + def _createProductDictionary(self, segmentList): + # Create the product dictionary + productSegmentGroup = self._groupSegments(segmentList) + + productDict = self._initializeProductDictionary(productSegmentGroup) + productParts = productSegmentGroup.get('productParts') + productDict['productParts'] = productParts + self._processProductParts(self, productDict, productSegmentGroup, productParts) + + return productDict + + def _initializeProductDictionary(self, productSegmentGroup): + ''' + Set up the Product Dictionary for the given Product consisting of a + group of segments. + + Fill in the dictionary information for the product header. + + @param productSegmentGroup: holds meta information about the product + @return initialized product dictionary + + *********** + Example segmented product: + + WGUS63 KBOU 080400 + FFABOU + + URGENT - IMMEDIATE BROADCAST REQUESTED + FLOOD WATCH + NATIONAL WEATHER SERVICE DENVER CO + 400 AM GMT TUE FEB 8 2011 + + Overview Headline + Overview + + *********** + Example non-segmented product: + WGUS63 KBOU 080400 + FFWBOU + + ''' + self._productID = productSegmentGroup.get('productID', 'NNN') + if self._areaName != '': + self._areaName = ' FOR ' + self._areaName + '\n' + self._geoType = productSegmentGroup.get('geoType') + self._mapType = productSegmentGroup.get('mapType') + self._productTimeZones = [] + + # Fill in product dictionary information + productDict = collections.OrderedDict() + productDict['productID'] = self._productID + return productDict + + def _formatProductDictionary(self, formatterClass, productDict): + formatter = formatterClass(self) + product = formatter.execute(productDict) + + return product + + ############################################################### + ### Sampling and Statistics related methods + + def _getStatValue(self, statDict, element, method=None, dataType=None): + stats = statDict.get(element, None) + if stats is None: return None + if type(stats) is types.ListType: + stats = stats[0] + stats, tr = stats + if dataType==self.VECTOR(): + stats, dir = stats + return self.getValue(stats, method) + + ############################################################### + ### Area, Zone and Segment related methods + + def _allAreas(self): + return self._inlandAreas() + self._coastalAreas() + + def _computeIntersectAreas(self, editAreas, argDict): + editAreaUtils = EditAreaUtils.EditAreaUtils() + editAreaUtils.setUp(None, argDict) + surgeEditArea = editAreaUtils.getEditArea("StormSurgeWW_EditArea", argDict) + intersectAreas =[] + for (_, editAreaLabel) in editAreas: + editArea = editAreaUtils.getEditArea(editAreaLabel, argDict) + intersectAreaLabel = "intersect_"+editAreaLabel + intersectArea = editAreaUtils.intersectAreas(intersectAreaLabel, editArea, surgeEditArea) + grid = intersectArea.getGrid() + if grid.isAnyBitsSet(): + editAreaUtils.saveEditAreas([intersectArea]) + intersectAreas.append((intersectAreaLabel, intersectAreaLabel)) + + return intersectAreas + ############################################################### ### Hazards related methods @@ -72,31 +393,60 @@ class TextProduct(GenericHazards.TextProduct): self._hazardsTable = self._getHazardsTable(argDict, self.filterMethod) argDict["hazards"] = self._hazardsTable - - def _setVTECActiveTable(self, argDict): - dataMgr = argDict["dataMgr"] - gfeMode = dataMgr.getOpMode().name() - - if gfeMode == "PRACTICE": - argDict["vtecActiveTable"] = "PRACTICE" - else: - argDict["vtecActiveTable"] = "active" - - def _getAllVTECRecords(self): - allRecords = [] - for segment in self._segmentList: - vtecRecords = self._hazardsTable.getHazardList(segment) - allRecords += vtecRecords - - return allRecords - + + def _getHazardsTable(self, argDict, filterMethod, editAreas=None): + # Set up edit areas as list of lists + # Need to check hazards against all edit areas in the CWA MAOR + argDict["combinations"]= [(self._allAreas(),"Region1")] + dfEditAreas = argDict["combinations"] + editAreas = [] + for area, label in dfEditAreas: + if type(area) is types.ListType: + editAreas.append(area) + elif type(area) is types.TupleType: #LatLon + editAreas.append([self.__getLatLonAreaName(area)]) + else: + editAreas.append([area]) + # Get Product ID and other info for HazardsTable + pil = self._pil.upper() # Ensure PIL is in UPPERCASE + stationID4 = self._fullStationID + productCategory = pil[0:3] #part of the pil + definition = argDict['definition'] + sampleThreshold = definition.get("hazardSamplingThreshold", (10, None)) + # Process the hazards + accurateCities = definition.get('accurateCities', 0) + cityRefData = [] + import HazardsTable + hazards = HazardsTable.HazardsTable( + argDict["ifpClient"], editAreas, productCategory, filterMethod, + argDict["databaseID"], + stationID4, argDict["vtecActiveTable"], argDict["vtecMode"], sampleThreshold, + creationTime=argDict["creationTime"], accurateCities=accurateCities, + cityEditAreas=cityRefData, dataMgr=argDict['dataMgr']) + return hazards + def _ignoreActions(self): # Ignore hazards with these action codes in the overview headlines # NOTE: the VTEC and segments will still include them correctly. return ['CAN', 'UPG'] - # In order to have the HazardsTable use the allowedHeadlines list, - # we need to supply a filterMethod that uses allowedHeadlines instead of allowedHazards + def _setVTECActiveTable(self, argDict): + dataMgr = argDict["dataMgr"] + gfeMode = dataMgr.getOpMode().name() + + self.debug_print("*" *100, 1) + self.debug_print("gfeMode = '%s'" % (gfeMode), 1) + self.debug_print("*" *100, 1) + + if gfeMode == "PRACTICE": + argDict["vtecActiveTable"] = "PRACTICE" + else: + argDict["vtecActiveTable"] = "active" + + def _getVtecRecords(self, segment, vtecEngine=None): + vtecRecords = self._hazardsTable.getHazardList(segment) + return vtecRecords + def _getAllowedHazardList(self, allowedHazardList=None): if allowedHazardList is None: allowedHazardList = self.allowedHazards() @@ -107,7 +457,7 @@ class TextProduct(GenericHazards.TextProduct): else: hazardList.append(h) return hazardList - + def _altFilterMethod(self, hazardTable, allowedHazardsOnly=False): # Remove hazards not in allowedHeadlines list allowedHazardList = self._getAllowedHazardList(self.allowedHeadlines()) @@ -156,15 +506,16 @@ class TextProduct(GenericHazards.TextProduct): for area in hazard['id']: hazDict.setdefault((hdln, phen, sig), []).append(area) - #self.debug_print("hazDict", hazDict + self.debug_print("hazDict = %s" % (self._pp.pformat(hazDict)), 1) hazardHdlns=[] huAreas = [] -# self.debug_print("\nAdditional Hazard Headlines" + self.debug_print("Additional Hazard Headlines", 1) for key in hazDict.keys(): hdln, phen, sig = key huAreas = huAreas + hazDict[key] hazardHdln = ((hdln, "NEW", phen,sig), hazDict[key], [],[],[]) - #self.debug_print(" ", hazardHdln, hazDict[key] + self.debug_print(" %s" % (self._pp.pformat(hazardHdln)), 1) + self.debug_print(" %s" % (self._pp.pformat(hazDict[key])), 1) hazardHdlns.append(hazardHdln) return hazardHdlns, huAreas @@ -187,14 +538,12 @@ class TextProduct(GenericHazards.TextProduct): # Otherwise, they are ignored. # # E.g. hdlnList = self._checkHazard(hazardHdlns, [("FA","W")], returnList=True) - self.debug_print("_checkHazard hazardHdlns is %s" % (hazardHdlns), 1) - self.debug_print("_checkHazard phenSigList is %s" % (phenSigList), 1) + self.debug_print("_checkHazard hazardHdlns is %s" % (self._pp.pformat(hazardHdlns)), 1) + self.debug_print("_checkHazard phenSigList is %s" % (self._pp.pformat(phenSigList)), 1) chosen = [] for key, landList, marineList, coastalList, inlandList in hazardHdlns: -# self.debug_print("what is mode?", mode - # SARAH - we do not want to consider marine hazards in this product -# hazAreas = landList+marineList + # We do not want to consider marine hazards in this product hazAreas = landList hazValue = (key, hazAreas) self.debug_print("hazValue is %s" % (repr(hazValue)), 1) @@ -209,10 +558,9 @@ class TextProduct(GenericHazards.TextProduct): # Check for land, marine, etc. for checkAreaType in checkAreaTypes: exec "testList = " + checkAreaType + "List" -# self.debug_print("testList is", testList + self.debug_print("testList is %s" % (testList), 1) if testList != []: chosen.append(hazValue) -# self.debug_print("chosen is ", chosen elif checkAreas is not None: acceptedAreas=[] for hazArea in hazAreas: @@ -224,46 +572,12 @@ class TextProduct(GenericHazards.TextProduct): chosen.append(hazValue) if not returnList and chosen!=[]: break - self.debug_print("MATT _checkHazard chosen = %s" % (repr(chosen)), 1) + self.debug_print("In _checkHazard chosen = %s" % + (self._pp.pformat(chosen)), 1) if not returnList: return chosen!=[] return chosen - def getVtecRecords(self, segment, vtecEngine=None): - vtecRecords = self._hazardsTable.getHazardList(segment) - return vtecRecords - - def _getHazardsTable(self, argDict, filterMethod, editAreas=None): - # Set up edit areas as list of lists - # Need to check hazards against all edit areas in the CWA MAOR - argDict["combinations"]= [(self._allAreas(),"Region1")] - dfEditAreas = argDict["combinations"] - editAreas = [] - for area, label in dfEditAreas: - if type(area) is types.ListType: - editAreas.append(area) - elif type(area) is types.TupleType: #LatLon - editAreas.append([self.__getLatLonAreaName(area)]) - else: - editAreas.append([area]) - # Get Product ID and other info for HazardsTable - pil = self._pil.upper() # Ensure PIL is in UPPERCASE - stationID4 = self._fullStationID - productCategory = pil[0:3] #part of the pil - definition = argDict['definition'] - sampleThreshold = definition.get("hazardSamplingThreshold", (10, None)) - # Process the hazards - accurateCities = definition.get('accurateCities', 0) - cityRefData = [] - import HazardsTable - hazards = HazardsTable.HazardsTable( - argDict["ifpClient"], editAreas, productCategory, filterMethod, - argDict["databaseID"], - stationID4, argDict["vtecActiveTable"], argDict["vtecMode"], sampleThreshold, - creationTime=argDict["creationTime"], accurateCities=accurateCities, - cityEditAreas=cityRefData, dataMgr=argDict['dataMgr']) - return hazards - ############################################################### ### Time related methods @@ -278,7 +592,7 @@ class TextProduct(GenericHazards.TextProduct): self._expireTime = self._issueTime_secs + self._purgeTime*3600 self._timeLabel = self.getCurrentTime( argDict, "%l%M %p %Z %a %b %e %Y", stripLeading=1) - + def _determineTimeRanges(self, argDict): # Set up the time range for 0-120 hours @@ -298,12 +612,15 @@ class TextProduct(GenericHazards.TextProduct): trList = [] self._periodList = [] for index, tr in enumerate(subRanges): - # self.debug_print(tr) + self.debug_print("In _determineTimeRanges -> tr = %s" % + (self._pp.pformat(tr)), 1) trList.append((tr, "Label")) if index == 0: startTime = tr.startTime() localtime = time.localtime(startTime.unixTime()) + + # Determine the number of hours to the next 6AM or 6PM period if localtime.tm_hour < 6: periodLength = 6 - localtime.tm_hour elif localtime.tm_hour >= 6 and localtime.tm_hour < 18: @@ -311,6 +628,8 @@ class TextProduct(GenericHazards.TextProduct): else: periodLength = 30 - localtime.tm_hour + # Don't allow the first period to be less than 3 hours long; + # instead just start with the next period if periodLength < 3: periodStart = startTime + periodLength*3600 period = self.makeTimeRange(periodStart, periodStart+12*3600) @@ -318,10 +637,13 @@ class TextProduct(GenericHazards.TextProduct): period = self.makeTimeRange(startTime, startTime+periodLength*3600) self._periodList.append(period) + for i in range(1,10): startTime = period.endTime() # Start where the last period leaves off period = self.makeTimeRange(startTime, startTime+12*3600) self._periodList.append(period) + self.debug_print("final periodList =\n\n%s\n" % + (self._pp.pformat(self._periodList)), 1) self._timeRangeList = trList def _calculateStartTime(self, localCreationTime): @@ -330,21 +652,21 @@ class TextProduct(GenericHazards.TextProduct): day = localCreationTime[2] hour = localCreationTime[3] - # If we are more than halfway though a 3 hr period - if hour % 3 > 1: - adjust = 3 # move on to the next 3 hr block + # Define a variable to control which resolution we want + resolution = self._resolution() # 6 is also a valid option + + # If we are more than halfway though a block we would want + if hour % resolution > resolution / 2: + adjust = resolution # move on to the next block else: adjust = 0 -# if hour % 6 > 3: -# adjust = 6 # move on to the next 6 hr block -# else: -# adjust = 0 -# self.debug_print("MATT: _calculateStartTime %d adjust = %d" % (hour % 6, adjust) + self.debug_print("In _calculateStartTime %d adjust = %d" % + (hour % resolution, adjust), 1) - # Now "truncate" to a 6-hourly boundary and compute startTime in local Time. -# hour = int( (hour/6) * 6) + adjust - hour = int( (hour/3) * 3) + adjust + # Now "truncate" to a block boundary and compute startTime in local time. +# hour = int( (hour/3) * 3) + adjust + hour = int( (hour/resolution) * resolution) + adjust if hour > 23: hour -= 24 elif hour < 0: @@ -363,7 +685,7 @@ class TextProduct(GenericHazards.TextProduct): # DAY + MORNING / AFTERNOON / EVENING / OVERNIGHT. # If wholePeriod, format FROM ... TO... - self.debug_print("MATT Format period wholePeriod = %s, period = %s, useEndTime =%s" % + self.debug_print("Format period wholePeriod = %s, period = %s, useEndTime =%s" % (str(wholePeriod), str(period), str(useEndTime)), 1) if period is None: return "" @@ -372,10 +694,10 @@ class TextProduct(GenericHazards.TextProduct): else: startTime = period.startTime() result = self._getTimeDesc(startTime, resolution, shiftToLocal) - self.debug_print("MATT result = '%s'" % (result), 1) + self.debug_print("_getTimeDesc result = '%s'" % (result), 1) if wholePeriod: endResult = self._getTimeDesc(period.endTime(), resolution, shiftToLocal) - self.debug_print("MATT endResult = '%s'" % (endResult), 1) + self.debug_print("_getTimeDesc endResult = '%s'" % (endResult), 1) if result != endResult: result=result + " TO "+ endResult return result @@ -445,69 +767,6 @@ class TextProduct(GenericHazards.TextProduct): else: partOfDay = "evening" return prevDay, partOfDay - ############################################################### - ### Sampling and Statistics related methods - - def moderated_dict(self, parmHisto, timeRange, componentName): - """ - Specifies the lower percentages and upper percentages of - data to be thrown out for moderated stats. - """ - # COMMENT: This dictionary defines the low and high limit at which - # outliers will be removed when calculating moderated stats. - # By convention the first value listed is the percentage - # allowed for low values and second the percentage allowed - # for high values. - - # Get Baseline thresholds - dict = SampleAnalysis.SampleAnalysis.moderated_dict( - self, parmHisto, timeRange, componentName) - - # Change thresholds - dict["Wind"] = (0, 15) - dict["WindGust"] = (0, 15) - dict["pws34int"] = (0, 5) - dict["pws64int"] = (0, 5) - dict["pwsD34"] = (0, 5) - dict["pwsN34"] = (0, 5) - dict["pwsD64"] = (0, 5) - dict["pwsN64"] = (0, 5) - dict["InundationMax"] = (0, 5) - dict["InundationTiming"] = (0, 5) - return dict - - def _getStatValue(self, statDict, element, method=None, dataType=None): - stats = statDict.get(element, None) - if stats is None: return None - if type(stats) is types.ListType: - stats = stats[0] - stats, tr = stats - if dataType==self.VECTOR(): - stats, dir = stats - return self.getValue(stats, method) - - ############################################################### - ### Area, Zone and Segment related methods - - def _allAreas(self): - return self._inlandAreas() + self._coastalAreas() - - def _computeIntersectAreas(self, editAreas, argDict): - editAreaUtils = EditAreaUtils.EditAreaUtils() - editAreaUtils.setUp(None, argDict) - surgeEditArea = editAreaUtils.getEditArea("StormSurgeWW_EditArea", argDict) - intersectAreas =[] - for (_, editAreaLabel) in editAreas: - editArea = editAreaUtils.getEditArea(editAreaLabel, argDict) - intersectAreaLabel = "intersect_"+editAreaLabel - intersectArea = editAreaUtils.intersectAreas(intersectAreaLabel, editArea, surgeEditArea) - grid = intersectArea.getGrid() - if grid.isAnyBitsSet(): - editAreaUtils.saveEditAreas([intersectArea]) - intersectAreas.append((intersectAreaLabel, intersectAreaLabel)) - - return intersectAreas - ############################################################### ### Storm Information and TCP related methods @@ -758,16 +1017,21 @@ NEXT COMPLETE ADVISORY...500 AM EDT. $$ FORECASTER STEWART""" - + ############################################################### ### Advisory related methods - + + def _initializeAdvisories(self): + self._currentAdvisory = dict() + self._currentAdvisory['ZoneData'] = dict() + self._loadLastTwoAdvisories() + def _synchronizeAdvisories(self): - pathManager = PathManagerFactory.getPathManager() - context = pathManager.getContextForSite(LocalizationType.CAVE_STATIC, self._site) - + # Retrieving a directory causes synching to occur - file = pathManager.getLocalizationFile(context, self._getAdvisoryPath()).getFile() + file = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, self._site, + self._getAdvisoryPath()).getFile() return file @@ -783,17 +1047,22 @@ FORECASTER STEWART""" return path - def _loadLastTwoAdvisories(self): + def _getStormAdvisoryNames(self): advisoryDirectoryPath = self._getLocalAdvisoryDirectoryPath() filenames = os.listdir(advisoryDirectoryPath) allAdvisories = filter(lambda filename: filename[-5:] == ".json", filenames) - self.debug_print("allAdvisories = %s" % (repr(allAdvisories))) + self.debug_print("allAdvisories = %s" % (self._pp.pformat(allAdvisories))) stormAdvisories = filter(lambda filename: self._getStormNameFromTCP() in filename, allAdvisories) stormAdvisories = map(lambda filename: filename[:-5], stormAdvisories) - self.debug_print("stormAdvisories = %s" % (repr(stormAdvisories))) + self.debug_print("stormAdvisories = %s" % (self._pp.pformat(stormAdvisories))) + + return stormAdvisories + + def _loadLastTwoAdvisories(self): + stormAdvisories = self._getStormAdvisoryNames() # We need to reverse the order of the advisories so the latest # advisories come first in this list @@ -813,8 +1082,8 @@ FORECASTER STEWART""" else: # Must be the HLS lastTwoAdvisories = stormAdvisories[:2] - self.debug_print("MATT DEBUG: last two advisories = %s" % - (repr(lastTwoAdvisories)), 1) + self.debug_print("DEBUG: last two advisories = %s" % + (self._pp.pformat(lastTwoAdvisories)), 1) self._previousAdvisory = None if len(lastTwoAdvisories) >= 1: self._previousAdvisory = self._loadAdvisory(lastTwoAdvisories[0]) @@ -828,12 +1097,12 @@ FORECASTER STEWART""" fileName = self._getAdvisoryFilename(advisoryName) try: - pythonDict = JsonSupport.loadFromJson(LocalizationType.CAVE_STATIC, + pythonDict = JsonSupport.loadFromJson(LocalizationSupport.CAVE_STATIC, self._site, fileName) - self.debug_print("SARAH: File contents for %s:" % (fileName), 1) - self.debug_print(repr(pythonDict), 1) + self.debug_print("File contents for %s:" % (fileName), 1) + self.debug_print(self._pp.pformat(pythonDict), 1) # Only use transmitted advisories if pythonDict["Transmitted"] == False and advisoryName != "pending": @@ -841,8 +1110,7 @@ FORECASTER STEWART""" else: return pythonDict except Exception, e: - self.debug_print("SARAH Load Exception for %s : %s" % - (fileName, e), 1) + self.debug_print("Load Exception for %s : %s" % (fileName, e), 1) return None def _getAdvisoryPath(self): @@ -857,7 +1125,7 @@ FORECASTER STEWART""" advisoryFilename = os.path.join(self._getAdvisoryPath(), advisoryName+".json") return advisoryFilename - + ############################################################### ### GUI related methods @@ -899,48 +1167,7 @@ FORECASTER STEWART""" "headers": ("blue", ("Helvetica", 14, "bold")), "instructions": (None, ("Helvetica", 12, "italic")), } - - ############################################################### - ### TCV Statistics - - def threatKeyOrder(self): - return [None, "None", "Elevated", "Mod", "High", "Extreme"] - - def allowedHazards(self): - tropicalActions = ["NEW", "EXA", "CAN", "CON"] - return [ - ('HU.A',tropicalActions,'Hurricane'), - ('HU.W',tropicalActions,'Hurricane'), - ('SS.A',tropicalActions,'Surge'), - ('SS.W',tropicalActions,'Surge'), - ('TR.A',tropicalActions,'Tropical'), - ('TR.W',tropicalActions,'Tropical'), - ] - - def allowedHeadlines(self): - allActions = ["NEW", "EXA", "EXB", "EXT", "CAN", "CON", "EXP"] - return [ - ('FF.A', allActions, 'Flood'), # FLASH FLOOD WATCH - ('FA.A', allActions, 'Flood'), # FLOOD WATCH - ('TO.A', allActions, 'Convective'), # TORNADO WATCH - ] - - def _initializeAdvisories(self): - self._currentAdvisory = dict() - self._currentAdvisory['ZoneData'] = dict() - self._loadLastTwoAdvisories() - - def _initializeSegmentZoneData(self, segment): - # The current advisory will be populated when setting a section's stats - self._currentAdvisory['ZoneData'][segment] = { - "WindThreat": None, - "WindForecast": None, - "StormSurgeThreat": None, - "StormSurgeForecast": None, - "FloodingRainThreat": None, - "FloodingRainForecast": None, - "TornadoThreat": None, - } + import Tkinter class Common_Dialog(Dialog): @@ -950,6 +1177,7 @@ class Common_Dialog(Dialog): self._varDict = {} # all end results must be saved here self._infoDict = infoDict self._parent = parent + self._pp = pprint.PrettyPrinter() Dialog.__init__(self, parent=None, title=title) def getVarDict(self): diff --git a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/utilities/TCVDictionary.py b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/utilities/TCVDictionary.py index 6bbe5711f2..4af55bc76c 100644 --- a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/utilities/TCVDictionary.py +++ b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/utilities/TCVDictionary.py @@ -630,7 +630,7 @@ PotentialImpactStatements = { }, } -EvacuationStatements = ["For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take essential materiasl from your Emergency Supplies Kit. Let others know where you are going and when you intend to arrive.", +EvacuationStatements = ["For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take essential materials from your Emergency Supplies Kit. Let others know where you are going and when you intend to arrive.", "If evacuating the area, stick to prescribed evacuation routes. Look for additional traffic information on roadway smart signs and listen to select radio channels for further travel instructions. Do not use your cell phone while driving." "For those not under evacuation orders, understand that there are inherent risks to evacuation (such as traffic congestion, accidents, and driving in bad weather), so evacuate only if necessary. Help keep roadways open for those that are under evacuation orders."] @@ -678,7 +678,6 @@ OtherPreparednessActions = { "Problems with sewer backups can contaminate standing flood waters. Keep children away. Also, listen for boil water alerts relative to communities whose tap water may have become temporarily non-potable."], } -AdditionalSources = ["- For information on appropriate preparations see ready.gov/louisiana", - "- For information on local evacuation shelters see www.emergency.louisana.gov/disaster_evaluation_guide.html", +AdditionalSources = ["- For information on appropriate preparations see ready.gov", "- For information on creating an emergency plan see getagameplan.org", "- For additional disaster preparedness information see redcross.org"] diff --git a/cave/com.raytheon.viz.grid/localization/menus/mrms/index.xml b/cave/com.raytheon.viz.grid/localization/menus/mrms/index.xml index 028671a071..5dc174e36c 100644 --- a/cave/com.raytheon.viz.grid/localization/menus/mrms/index.xml +++ b/cave/com.raytheon.viz.grid/localization/menus/mrms/index.xml @@ -4,7 +4,7 @@ Darrel Kingfield NOAA/NSSL/CIMMS 09-02-2014 Initial File Creation --> - \ No newline at end of file diff --git a/cave/com.raytheon.viz.grid/localization/menus/mrms/mrms.xml b/cave/com.raytheon.viz.grid/localization/menus/mrms/mrms.xml index d0f34c3b70..6fec96a168 100644 --- a/cave/com.raytheon.viz.grid/localization/menus/mrms/mrms.xml +++ b/cave/com.raytheon.viz.grid/localization/menus/mrms/mrms.xml @@ -5,8 +5,6 @@ --> - - - - - \ No newline at end of file + + + diff --git a/cave/com.raytheon.viz.grid/plugin.xml b/cave/com.raytheon.viz.grid/plugin.xml index 6cc5628c92..a680a122ca 100644 --- a/cave/com.raytheon.viz.grid/plugin.xml +++ b/cave/com.raytheon.viz.grid/plugin.xml @@ -53,4 +53,21 @@ name="Grid" category="com.raytheon.uf.viz.productbrowser.productbrowserpreferencespage"/> + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/DisplayFieldData.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/DisplayFieldData.java index ecb7e731d7..6f1072b9fe 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/DisplayFieldData.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/DisplayFieldData.java @@ -11,7 +11,7 @@ package com.raytheon.viz.mpe.ui; * ------------ ---------- ----------- -------------------------- * Jun 9, 2011 rgeorge Initial creation * Jun 30, 2014 17457 snaples Updated getCv_use to return name - * + * Jan 7, 2015 16954 cgobs Fix for cv_use issue - using getFieldName() in certain parts. * * * @author rgeorge @@ -56,7 +56,7 @@ public enum DisplayFieldData { mlqmosaic("mpe_mlqmosaic_dir", "Q2 MultiSensor Mosaic", 3600, "PRECIP_ACCUM"), //best estimate QPE - Xmrg("rfcwide_xmrg_dir", "Best Estimate QPE (in)"), // + Xmrg("rfcwide_xmrg_dir", "Best Estimate QPE (in)", 3600, "PRECIP_ACCUM" ), // p3lMosaic("rfcwide_p3lmosaic_dir", "P3 Local Bias Corrected Radar-Derived Precip (in)", 3600, "PRECIP_ACCUM"), // @@ -146,11 +146,18 @@ public enum DisplayFieldData { } } + public String getFieldName() { + return name().toUpperCase(); + } + + /** * @return the cv_use */ public String getCv_use() { - cv_use = name().toUpperCase(); + if (cv_use == null) { + cv_use = getFieldName(); + } return cv_use; } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/DrawDQCStations.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/DrawDQCStations.java index 8e829a6cfc..7b9f897daa 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/DrawDQCStations.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/DrawDQCStations.java @@ -84,8 +84,6 @@ import com.raytheon.viz.mpe.util.DailyQcUtils; public class DrawDQCStations { private static DrawDQCStations instance = null; - - private DailyQcUtils dqc = DailyQcUtils.getInstance(); private static final List pColorSetGroup = MPEColors .build_mpe_colors(); @@ -101,13 +99,13 @@ public class DrawDQCStations { int points_flag; - boolean qpf_on = MPEDisplayManager.getCurrent().isQpf(); + boolean qpf_on = false; boolean flf_on = false; boolean maxmin_on = false; - int isom = dqc.isom; + int isom = DailyQcUtils.isom; int pcpn_time_step = 0; @@ -119,7 +117,7 @@ public class DrawDQCStations { public static int grids_flag = 0; - int dflag[] = dqc.dflag; + int dflag[] = DailyQcUtils.dflag; int pcpn_time = 0; @@ -298,25 +296,25 @@ public class DrawDQCStations { time_pos = 0; display_flag = 0; hed = 0; - plot_view = dqc.plot_view; - contour_flag = dqc.contour_flag; - points_flag = dqc.points_flag; + plot_view = DailyQcUtils.plot_view; + contour_flag = DailyQcUtils.contour_flag; + points_flag = DailyQcUtils.points_flag; qpf_on = MPEDisplayManager.getCurrent().isQpf(); flf_on = MPEDisplayManager.getCurrent().isZflag(); maxmin_on = MPEDisplayManager.getCurrent().isMaxmin(); tbuf = new StringBuilder(); - isom = dqc.isom; + isom = DailyQcUtils.isom; pcpn_time_step = MPEDisplayManager.pcpn_time_step; - map_flag = dqc.map_flag; - pcp_flag = dqc.pcp_flag; - pcpn_day = dqc.pcpn_day; - grids_flag = dqc.grids_flag; - dflag = dqc.dflag; - pcpn_time = dqc.pcpn_time; -// pdata = DailyQcUtils.pdata; - old_isom = dqc.old_isom; -// tdata = DailyQcUtils.tdata; -// zdata = DailyQcUtils.zdata; + map_flag = DailyQcUtils.map_flag; + pcp_flag = DailyQcUtils.pcp_flag; + pcpn_day = DailyQcUtils.pcpn_day; + grids_flag = DailyQcUtils.grids_flag; + dflag = DailyQcUtils.dflag; + pcpn_time = DailyQcUtils.pcpn_time; +// pdata = DailyQcUtils.pdata; + old_isom = DailyQcUtils.old_isom; +// tdata = DailyQcUtils.tdata; +// zdata = DailyQcUtils.zdata; /* * get the token dqc_preprocessor_basetime, the default value is 12Z @@ -431,14 +429,17 @@ public class DrawDQCStations { if (contour_flag == 1) { Set mode = mpd.getDisplayMode(); - if (md.getResourceList().containsRsc(pgp)) { - md.getResourceList().removeRsc(pgp); + if (display.getDescriptor().getResourceList() + .containsRsc(pgp)) { + display.getDescriptor().getResourceList() + .removeRsc(pgp); pgp.dispose(); } if (mode.contains(DisplayMode.Contour)) { // we are ok } else { mpd.toggleDisplayMode(DisplayMode.Contour); + mode = mpd.getDisplayMode(); if (mode.contains(DisplayMode.Image)) { mpd.toggleDisplayMode(DisplayMode.Image); } @@ -717,7 +718,7 @@ public class DrawDQCStations { Calendar ltime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); StringBuilder mbuf = new StringBuilder(); - int dqcEndingObsTime = dqc.getEnding6HourObsTime(); + int dqcEndingObsTime = DailyQcUtils.getEnding6HourObsTime(); tbuf = new StringBuilder(); if (qpf_on == true) { @@ -731,10 +732,10 @@ public class DrawDQCStations { /* Precipitation period is always 12z-12z. */ if ((pcpn_time < 2) && (pcpn_time_step == 0)) { - ltime.setTime(dqc.pdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.pdata[pcpn_day].data_time); ltime.add(Calendar.SECOND, -86400); } else { - ltime.setTime(dqc.pdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.pdata[pcpn_day].data_time); } tbuf.append("Precipitation "); @@ -784,18 +785,18 @@ public class DrawDQCStations { tbuf.append(" ending at 12z"); } - if (dqc.pdata[pcpn_day].level == 1) { + if (DailyQcUtils.pdata[pcpn_day].level == 1) { tbuf.append(" - Level 1"); - } else if (dqc.pdata[pcpn_day].level == 2) { + } else if (DailyQcUtils.pdata[pcpn_day].level == 2) { tbuf.append(" - Level 2"); } - if (dqc.pdata[pcpn_day].used[ptime_pos] == 4) { + if (DailyQcUtils.pdata[pcpn_day].used[ptime_pos] == 4) { tbuf.append(" Saved"); - } else if ((dqc.pdata[pcpn_day].used[ptime_pos] == 3) - || (dqc.pdata[pcpn_day].used[ptime_pos] == 2)) { + } else if ((DailyQcUtils.pdata[pcpn_day].used[ptime_pos] == 3) + || (DailyQcUtils.pdata[pcpn_day].used[ptime_pos] == 2)) { tbuf.append(" Modified"); - } else if (dqc.pdata[pcpn_day].used[ptime_pos] == 1) { + } else if (DailyQcUtils.pdata[pcpn_day].used[ptime_pos] == 1) { tbuf.append(" Not Modified"); } else { tbuf.append(" - No Data"); @@ -810,19 +811,19 @@ public class DrawDQCStations { if (dqcEndingObsTime == 12) { /* Times: 18, 00, 06, 12 */ if (pcpn_time < 1) { - ltime.setTime(dqc.zdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.zdata[pcpn_day].data_time); ltime.add(Calendar.SECOND, -86400); } else { - ltime.setTime(dqc.zdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.zdata[pcpn_day].data_time); } } else { /* Times 12, 18, 00, 06 */ if (pcpn_time < 2) { - ltime.setTime(dqc.zdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.zdata[pcpn_day].data_time); ltime.add(Calendar.SECOND, -86400); } else { - ltime.setTime(dqc.zdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.zdata[pcpn_day].data_time); } } @@ -882,20 +883,20 @@ public class DrawDQCStations { } - if (dqc.zdata[pcpn_day].level[ptime_pos] == 1) { + if (DailyQcUtils.zdata[pcpn_day].level[ptime_pos] == 1) { tbuf.append(" - Level 1"); - } else if (dqc.zdata[pcpn_day].level[ptime_pos] == 2) { + } else if (DailyQcUtils.zdata[pcpn_day].level[ptime_pos] == 2) { tbuf.append(" - Level 2"); } - if (dqc.zdata[pcpn_day].used[ptime_pos] == 6) { + if (DailyQcUtils.zdata[pcpn_day].used[ptime_pos] == 6) { tbuf.append(" Calculated"); - } else if (dqc.zdata[pcpn_day].used[ptime_pos] == 4) { + } else if (DailyQcUtils.zdata[pcpn_day].used[ptime_pos] == 4) { tbuf.append(" Saved"); - } else if ((dqc.zdata[pcpn_day].used[ptime_pos] == 3) - || (dqc.zdata[pcpn_day].used[ptime_pos] == 2)) { + } else if ((DailyQcUtils.zdata[pcpn_day].used[ptime_pos] == 3) + || (DailyQcUtils.zdata[pcpn_day].used[ptime_pos] == 2)) { tbuf.append(" Modified"); - } else if (dqc.zdata[pcpn_day].used[ptime_pos] == 1) { + } else if (DailyQcUtils.zdata[pcpn_day].used[ptime_pos] == 1) { tbuf.append(" Not Modified"); } else { tbuf.append(" - No Data"); @@ -915,18 +916,18 @@ public class DrawDQCStations { if (dqcEndingObsTime == 12) { if ((pcpn_time < 1) && (pcpn_time_step == 0)) { - ltime.setTime(dqc.tdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.tdata[pcpn_day].data_time); ltime.add(Calendar.SECOND, -86400); } else { - ltime.setTime(dqc.tdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.tdata[pcpn_day].data_time); } } else { if ((pcpn_time < 2) && (pcpn_time_step == 0)) { - ltime.setTime(dqc.tdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.tdata[pcpn_day].data_time); ltime.add(Calendar.SECOND, -86400); } else { - ltime.setTime(dqc.tdata[pcpn_day].data_time); + ltime.setTime(DailyQcUtils.tdata[pcpn_day].data_time); } } @@ -994,18 +995,18 @@ public class DrawDQCStations { tbuf.append(" ending at 12z"); } - if (dqc.tdata[pcpn_day].level[ptime_pos] == 1) { + if (DailyQcUtils.tdata[pcpn_day].level[ptime_pos] == 1) { tbuf.append(" - Level 1"); - } else if (dqc.tdata[pcpn_day].level[ptime_pos] == 2) { + } else if (DailyQcUtils.tdata[pcpn_day].level[ptime_pos] == 2) { tbuf.append(" - Level 2"); } - if (dqc.tdata[pcpn_day].used[ptime_pos] == 4) { + if (DailyQcUtils.tdata[pcpn_day].used[ptime_pos] == 4) { tbuf.append(" Saved"); - } else if ((dqc.tdata[pcpn_day].used[ptime_pos] == 3) - || (dqc.tdata[pcpn_day].used[ptime_pos] == 2)) { + } else if ((DailyQcUtils.tdata[pcpn_day].used[ptime_pos] == 3) + || (DailyQcUtils.tdata[pcpn_day].used[ptime_pos] == 2)) { tbuf.append(" Modified"); - } else if (dqc.tdata[pcpn_day].used[ptime_pos] == 1) { + } else if (DailyQcUtils.tdata[pcpn_day].used[ptime_pos] == 1) { tbuf.append(" Not Modified"); } else { tbuf.append(" - No Data"); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/GroupEditPrecipStns.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/GroupEditPrecipStns.java index e32d951ae6..98b0bc8d00 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/GroupEditPrecipStns.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/GroupEditPrecipStns.java @@ -36,7 +36,7 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Jun 17, 2009 snaples Initial creation * May 06, 2011 #8994 jpiatt Added set precipitation value as zero - * + * Sep 04, 2014 283 cgobs Fixed possible selection of filtered-out gages * * * @author snaples @@ -45,15 +45,13 @@ import com.vividsolutions.jts.geom.Coordinate; public class GroupEditPrecipStns { - private DailyQcUtils dqc = DailyQcUtils.getInstance(); - public void group_edit_precip_stations(ReferencedCoordinate rcoord) { int time_pos; int i, m, k; float lat, lon; double testdist, maxdist; int isave; - int max_stations = dqc.precip_stations.size(); + int max_stations = DailyQcUtils.precip_stations.size(); Coordinate coord = new Coordinate(); try { @@ -64,7 +62,7 @@ public class GroupEditPrecipStns { } if (MPEDisplayManager.pcpn_time_step == 0) { - time_pos = dqc.pcpn_time; + time_pos = DailyQcUtils.pcpn_time; } else { time_pos = 4; @@ -78,47 +76,61 @@ public class GroupEditPrecipStns { * mouse click point. */ for (i = 0; i < max_stations; i++) { - if (dqc.pdata[dqc.pcpn_day].stn[i].frain[time_pos].data < 0) { + if (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i].frain[time_pos].data < 0) { continue; } - if (dqc.pdata[dqc.pcpn_day].stn[i].frain[time_pos].data < QcPrecipOptionsDialog + //precip filter + if (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i].frain[time_pos].data < QcPrecipOptionsDialog .getPointFilterValue()) { continue; } + //reverse precip filter + if (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i].frain[time_pos].data > QcPrecipOptionsDialog + .getPointFilterReverseValue()) { + continue; + } + + //elevation filter + if (DailyQcUtils.precip_stations.get(i).elev < DailyQcUtils.elevation_filter_value) + { + continue; + } + + /* Retrieve the latitude and longitude of this station. */ - lat = dqc.precip_stations.get(i).lat; - lon = dqc.precip_stations.get(i).lon; + lat = DailyQcUtils.precip_stations.get(i).lat; + lon = DailyQcUtils.precip_stations.get(i).lon; - if (dqc.precip_stations.get(i).tip == 0 - && dqc.gage_char[0] == -1) { + if (DailyQcUtils.precip_stations.get(i).tip == 0 + && DailyQcUtils.gage_char[0] == -1) { continue; } - if (dqc.precip_stations.get(i).tip == 1 - && dqc.gage_char[1] == -1) { + if (DailyQcUtils.precip_stations.get(i).tip == 1 + && DailyQcUtils.gage_char[1] == -1) { continue; } - for (m = 0; m < dqc.tsmax; m++) { + for (m = 0; m < DailyQcUtils.tsmax; m++) { - if ((dqc.precip_stations.get(i).parm.substring(3, 5) - .equalsIgnoreCase(dqc.ts[m].abr)) - && dqc.dflag[m + 1] == 1) { + if ((DailyQcUtils.precip_stations.get(i).parm.substring(3, 5) + .equalsIgnoreCase(DailyQcUtils.ts[m].abr)) + && DailyQcUtils.dflag[m + 1] == 1) { break; } } - if (m == dqc.tsmax) { + if (m == DailyQcUtils.tsmax) { continue; } for (m = 0; m < 9; m++) { - if (m == dqc.pdata[dqc.pcpn_day].stn[i].frain[time_pos].qual - && dqc.qflag[m] == 1) { + if (m == DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i].frain[time_pos].qual + && DailyQcUtils.qflag[m] == 1) { break; } @@ -143,19 +155,19 @@ public class GroupEditPrecipStns { return; } - if (dqc.pdata[dqc.pcpn_day].stn[isave].frain[time_pos].qual != GroupEditStationsDialog.group_qual) { + if (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[time_pos].qual != GroupEditStationsDialog.group_qual) { QcPrecipOptionsDialog.renderGridsBtn.setEnabled(true); } - dqc.pdata[dqc.pcpn_day].stn[isave].frain[time_pos].qual = (short) GroupEditStationsDialog.group_qual; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[time_pos].qual = (short) GroupEditStationsDialog.group_qual; if (GroupEditStationsDialog.group_qual == 1 && time_pos == 4 - && dqc.pdata[dqc.pcpn_day].stn[isave].sflag[time_pos] == 1) { + && DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].sflag[time_pos] == 1) { - dqc.pdata[dqc.pcpn_day].stn[isave].frain[time_pos].data = dqc.pdata[dqc.pcpn_day].stn[isave].rrain[time_pos].data; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[time_pos].data = DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].rrain[time_pos].data; - dqc.pdata[dqc.pcpn_day].stn[isave].sflag[time_pos] = -1; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].sflag[time_pos] = -1; } @@ -164,7 +176,7 @@ public class GroupEditPrecipStns { || GroupEditStationsDialog.group_qual == 0 || GroupEditStationsDialog.group_qual == 8)) { for (k = 0; k < 4; k++) { - dqc.pdata[dqc.pcpn_day].stn[isave].frain[k].qual = (short) GroupEditStationsDialog.group_qual; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[k].qual = (short) GroupEditStationsDialog.group_qual; } } @@ -176,12 +188,12 @@ public class GroupEditPrecipStns { * and QC codes to "Manual" */ if (GroupEditStationsDialog.group_qual == 2) { - dqc.pdata[dqc.pcpn_day].stn[isave].frain[time_pos].data = 0.0f; - dqc.pdata[dqc.pcpn_day].stn[isave].frain[time_pos].qual = 2; - if ((dqc.pdata[dqc.pcpn_day].stn[isave].frain[4].data - 0.0) < 0.0001) { + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[time_pos].data = 0.0f; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[time_pos].qual = 2; + if ((DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[4].data - 0.0) < 0.0001) { for (k = 0; k < 4; k++) { - dqc.pdata[dqc.pcpn_day].stn[isave].frain[k].data = 0.0f; - dqc.pdata[dqc.pcpn_day].stn[isave].frain[k].qual = 2; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[k].data = 0.0f; + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[k].qual = 2; } } } @@ -190,23 +202,23 @@ public class GroupEditPrecipStns { if (time_pos != 4 && GroupEditStationsDialog.group_qual == 1 - && dqc.pdata[dqc.pcpn_day].stn[isave].frain[4].qual != 5 - && dqc.pdata[dqc.pcpn_day].stn[isave].frain[4].qual != 4) { - dqc.pdata[dqc.pcpn_day].stn[isave].frain[4].qual = (short) GroupEditStationsDialog.group_qual; + && DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[4].qual != 5 + && DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[4].qual != 4) { + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[isave].frain[4].qual = (short) GroupEditStationsDialog.group_qual; } for (k = 0; k < 5; k++) { if (k < 4) { - time_pos = dqc.pcpn_day * 4 + k; + time_pos = DailyQcUtils.pcpn_day * 4 + k; } else { - time_pos = 40 + dqc.pcpn_day; + time_pos = 40 + DailyQcUtils.pcpn_day; } - dqc.pcp_in_use[time_pos] = -1; + DailyQcUtils.pcp_in_use[time_pos] = -1; - if (dqc.pdata[dqc.pcpn_day].used[k] != 0) { - dqc.pdata[dqc.pcpn_day].used[k] = 2; + if (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].used[k] != 0) { + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].used[k] = 2; } } return; diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/OtherPrecipOptions.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/OtherPrecipOptions.java index 2660a8a54f..10d03622d9 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/OtherPrecipOptions.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/OtherPrecipOptions.java @@ -45,7 +45,6 @@ import com.raytheon.viz.mpe.util.MakeRsel; import com.raytheon.viz.mpe.util.QCStations; import com.raytheon.viz.mpe.util.QCTStations; import com.raytheon.viz.mpe.util.ReadFreezingStationList; -import com.raytheon.viz.mpe.util.ReadPrecipStationList; import com.raytheon.viz.mpe.util.ReadTemperatureStationList; import com.raytheon.viz.mpe.util.RenderPcp; import com.raytheon.viz.mpe.util.RenderT; @@ -442,8 +441,8 @@ public class OtherPrecipOptions { MakeRsel mr = new MakeRsel(); // Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); Calendar tmtime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - ReadPrecipStationList rp = new ReadPrecipStationList(); - int num_stations = rp.getNumPstations(); +// ReadPrecipStationList rp = new ReadPrecipStationList(); + int num_stations = dqc.precip_stations.size(); String s = appsDefaults.getToken(dqc_ending_6hour_obstime_tok); int dqc_ending_6hour_obstime = ((!(null == s)) ? Integer.parseInt(s) : -1); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveBestEstimate.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveBestEstimate.java index 342cf0281c..4b94128770 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveBestEstimate.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveBestEstimate.java @@ -16,6 +16,14 @@ * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 7, 2015  16954      cgobs      Fix for cv_use issue - using getFieldName() in certain parts.
+ * 
**/ package com.raytheon.viz.mpe.ui.actions; @@ -116,7 +124,7 @@ public class SaveBestEstimate { String rfc = MPEDataManager.getInstance().getRFC(); - update_rwr_save(rfc, editDate, bestEstField.getCv_use()); + update_rwr_save(rfc, editDate, bestEstField.getFieldName()); XmrgFile xmrgFile = MPEDisplayManager.getXmrgFile(bestEstField, editDate); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveLevel2Data.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveLevel2Data.java index e7cd5bc289..17bc4fb92c 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveLevel2Data.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/actions/SaveLevel2Data.java @@ -1032,7 +1032,7 @@ public class SaveLevel2Data { /* build map file */ System.out.println("Building MAP ."); - found: for (m = 0; mean_areal_precip_global[m].hb5 != ""; m++) { + found: for (m = 0; mean_areal_precip_global[m] != null; m++) { for (k = 0; k < 4; k++) { num = j * 4 + 3 - k; @@ -1047,9 +1047,11 @@ public class SaveLevel2Data { } - if (mean_areal_precip_global[m].hb5 == "") { + if (mean_areal_precip_global[m] != null) { + if (mean_areal_precip_global[m].hb5 == "") { System.out.println("MAP.hb5 is empty, continuing. "); continue; + } } gm.setTime(dqc.pdata[j].data_time); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java index 54d532a304..575d32c179 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java @@ -167,7 +167,6 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { cal.setTime(prevDate); if( prevHydDate == null ){ - // prevHydDate = prevDate; prevHydDate = displayMgr.getCurrentEditDate(); hydroCal.setTime(prevHydDate); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/EditPrecipStationsDialog.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/EditPrecipStationsDialog.java index 6203fece5a..d085318e9e 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/EditPrecipStationsDialog.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/EditPrecipStationsDialog.java @@ -387,6 +387,7 @@ public class EditPrecipStationsDialog extends AbstractMPEDialog implements if (srain.data > -98) { if (time_pos == HOURS_24 && srain.data >= 0) { snow = true; + System.out.println("Snow data is true for station."); } } @@ -476,6 +477,7 @@ public class EditPrecipStationsDialog extends AbstractMPEDialog implements "Snow water change is %5.2f in.", srain.data)); if (time_pos == HOURS_24 && srain.data >= 0) { snow = true; + System.out.println("Snow water change is available for " + selectedStation.hb5); } } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/QcPrecipOptionsDialog.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/QcPrecipOptionsDialog.java index 4e2b430a46..952b0f8a80 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/QcPrecipOptionsDialog.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/QcPrecipOptionsDialog.java @@ -210,8 +210,8 @@ public class QcPrecipOptionsDialog extends AbstractMPEDialog { Shell parent = this.getParent(); Display display = parent.getDisplay(); MPEDisplayManager displayMgr = MPEDisplayManager.getCurrent(); - Date prevDate = displayMgr.getCurrentEditDate(); - Date currDate = ChooseDataPeriodDialog.prevDate; + Date prevDate = ChooseDataPeriodDialog.getCurrentHydroEditDate(); + Date currDate = ChooseDataPeriodDialog.prevHydDate; String QcArea = ChooseDataPeriodDialog.prevArea; AppsDefaults appDefaults = AppsDefaults.getInstance(); DisplayFieldData df = displayMgr.getDisplayFieldType(); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DeletePolygonDlg.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DeletePolygonDlg.java index 34a1209d0f..7df54c8c8b 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DeletePolygonDlg.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DeletePolygonDlg.java @@ -56,7 +56,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Polygon values will now be * displayed for polygons with * the "sub" action. - * + * Jan 7, 2015 16954 cgobs Fix for cv_use issue - using getFieldName() in certain parts. * * * @author mpduff @@ -286,8 +286,8 @@ public class DeletePolygonDlg extends CaveSWTDialog { polygonListBox.removeAll(); - String type = displayManager.getDisplayFieldType().getCv_use() - .toUpperCase(); + String type = displayManager.getDisplayFieldType().getFieldName(); + productTF.setText(type); polygonList = PolygonEditManager.getPolygonEdits(fieldData, editDate); recreatePolygonListBox(); @@ -314,7 +314,7 @@ public class DeletePolygonDlg extends CaveSWTDialog { PolygonEditAction action = data.getEditAction(); if (action == PolygonEditAction.SUB) { - String value = data.getSubDrawSource().getCv_use(); + String value = data.getSubDrawSource().getFieldName(); polygonListBox.add(String.format(format2, number, displayed, persist, action.toPrettyName(), value)); } else { diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DrawPolygonDlg.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DrawPolygonDlg.java index e011b4dc25..485d42cc88 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DrawPolygonDlg.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/DrawPolygonDlg.java @@ -33,6 +33,7 @@ import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; @@ -63,6 +64,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Jan 29, 2014 16561 snaples Updated processDrawPrecipValue to remove polygon wireframe after setting value. * Feb 2, 2014 16201 snaples Added saved data flag support * Apr 28, 2014 16707 snaples Added code to save and set location of dialog box when moved. + * Jan 12, 2015 16993 snaples Restored code for Substitute Field Combo box. * * * @@ -78,6 +80,9 @@ public class DrawPolygonDlg extends CaveSWTDialog { private static final String MAKE_PERSISTENT = "Make Persistent"; + private DisplayFieldData[] displayFieldDataArray; + private String[] displayTypeNameArray; + /** * Bold Font. */ @@ -88,6 +93,11 @@ public class DrawPolygonDlg extends CaveSWTDialog { */ private Font font = null; + /** + * The field type selection Combo control. + */ + private Combo fieldTypeCombo = null; + /** * The precip value spinner control. */ @@ -227,7 +237,7 @@ public class DrawPolygonDlg extends CaveSWTDialog { GridData gd = new GridData(345, SWT.DEFAULT); subGroup.setLayoutData(gd); - getSubChecks(subGroup); + createFieldCombo(subGroup); // Create Substitute button final Button subBtn = new Button(subGroup, SWT.PUSH); @@ -349,398 +359,80 @@ public class DrawPolygonDlg extends CaveSWTDialog { * @param groupComp * The group composite */ - private void getSubChecks(Group groupComp) { + private void createFieldCombo(Group groupComp) { // Spacer - Label spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); + + // Create a container to hold the label and the combo box. + GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + Composite prodListComp = new Composite(shell, SWT.NONE); + GridLayout prodListCompLayout = new GridLayout(2, false); + prodListComp.setLayout(prodListCompLayout); + prodListComp.setLayoutData(gd); - Button radarMosaicChk = new Button(groupComp, SWT.RADIO); - GridData gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - radarMosaicChk.setLayoutData(gd); - radarMosaicChk.setText("Radar Mosaic"); - radarMosaicChk.setFont(font); - radarMosaicChk.setLayoutData(gd); - // Default to radar mosaic on dialog creation - radarMosaicChk.setSelection(true); - subType = DisplayFieldData.rMosaic; - radarMosaicChk.addSelectionListener(new SelectionAdapter() { + gd = new GridData(SWT.FILL, SWT.CENTER, true, false); + Label fieldTypeLabel = new Label(prodListComp, SWT.CENTER); + fieldTypeLabel.setText(SUBSTITUTE_VALUE_TEXT); + fieldTypeLabel.setLayoutData(gd); + + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + fieldTypeCombo = new Combo(groupComp, SWT.LEFT | SWT.DROP_DOWN + | SWT.READ_ONLY); + + if (displayFieldDataArray == null) + { + displayFieldDataArray = MPEDisplayManager.mpe_qpe_fields; + } + + // Label spaceLabel = new Label(groupComp, SWT.NONE); + // spaceLabel.setText("***** "); + + int selectedFieldIndex = 0; + + //find the index of the selected field + for (selectedFieldIndex = 0; selectedFieldIndex < displayFieldDataArray.length; selectedFieldIndex++) + { + if (displayFieldDataArray[selectedFieldIndex] == subType) + { + break; + } + } + + //create and initialize the display field type name array + displayTypeNameArray = new String[displayFieldDataArray.length]; + + for (int i = 0; i < displayFieldDataArray.length; i++) { + + String fieldName = displayFieldDataArray[i].toString(); + // System.out.println("DrawPolygon.createFieldCombo(): FieldName = :" + fieldName + ":"); + displayTypeNameArray[i] = fieldName; + } + + //select the field + fieldTypeCombo.setTextLimit(35); + fieldTypeCombo.setLayoutData(gd); + fieldTypeCombo.setItems(displayTypeNameArray); + fieldTypeCombo.select(selectedFieldIndex); + + fieldTypeCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.rMosaic; - } + String selectedFieldString = fieldTypeCombo.getText(); + // System.out.println("DrawPolygon.createFieldCombo(): selectedFieldString = " + + // selectedFieldString); + + subType = DisplayFieldData.fromDisplayNameString(selectedFieldString); + + // if (subType != null) +// { + // System.out.println("DrawPolygon.createFieldCombo(): subType = " + + // subType.toString()); + // } + } }); - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button avgRadarMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - avgRadarMosaicChk.setLayoutData(gd); - avgRadarMosaicChk.setText("Average Radar Mosaic"); - avgRadarMosaicChk.setFont(font); - avgRadarMosaicChk.setLayoutData(gd); - avgRadarMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.avgrMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button maxRadarMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - maxRadarMosaicChk.setLayoutData(gd); - maxRadarMosaicChk.setText("Max Radar Mosaic"); - maxRadarMosaicChk.setFont(font); - maxRadarMosaicChk.setLayoutData(gd); - maxRadarMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.maxrMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button fieldBiasRadarMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - fieldBiasRadarMosaicChk.setLayoutData(gd); - fieldBiasRadarMosaicChk.setText("Field Bias Radar Mosaic"); - fieldBiasRadarMosaicChk.setFont(font); - fieldBiasRadarMosaicChk.setLayoutData(gd); - fieldBiasRadarMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.bMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button localBiasRadarMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - localBiasRadarMosaicChk.setLayoutData(gd); - localBiasRadarMosaicChk.setText("Local Bias Radar Mosaic"); - localBiasRadarMosaicChk.setFont(font); - localBiasRadarMosaicChk.setLayoutData(gd); - localBiasRadarMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.lMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button gageOnlyChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - gageOnlyChk.setLayoutData(gd); - gageOnlyChk.setText("Gage Only Analysis"); - gageOnlyChk.setFont(font); - gageOnlyChk.setLayoutData(gd); - gageOnlyChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.gageOnly; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button multiSensorMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - multiSensorMosaicChk.setLayoutData(gd); - multiSensorMosaicChk.setText("Multisensor Mosaic"); - multiSensorMosaicChk.setFont(font); - multiSensorMosaicChk.setLayoutData(gd); - multiSensorMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.mMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button localBiasMultiSensorMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - localBiasMultiSensorMosaicChk.setLayoutData(gd); - localBiasMultiSensorMosaicChk.setText("Local Bias Multisensor Mosaic"); - localBiasMultiSensorMosaicChk.setFont(font); - localBiasMultiSensorMosaicChk.setLayoutData(gd); - localBiasMultiSensorMosaicChk - .addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.mlMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button satPrecipChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - satPrecipChk.setLayoutData(gd); - satPrecipChk.setText("Satellite Precip"); - satPrecipChk.setFont(font); - satPrecipChk.setLayoutData(gd); - satPrecipChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.satPre; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button localBiasSatPrecipChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - localBiasSatPrecipChk.setLayoutData(gd); - localBiasSatPrecipChk.setText("Local Bias Satellite Precip"); - localBiasSatPrecipChk.setFont(font); - localBiasSatPrecipChk.setLayoutData(gd); - localBiasSatPrecipChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.lsatPre; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button satRadarMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - satRadarMosaicChk.setLayoutData(gd); - satRadarMosaicChk.setText("Satellite Radar Mosaic"); - satRadarMosaicChk.setFont(font); - satRadarMosaicChk.setLayoutData(gd); - satRadarMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.srMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button satGageMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - satGageMosaicChk.setLayoutData(gd); - satGageMosaicChk.setText("Satellite Gage Mosaic"); - satGageMosaicChk.setFont(font); - satGageMosaicChk.setLayoutData(gd); - satGageMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.sgMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button satRadarGageMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - satRadarGageMosaicChk.setLayoutData(gd); - satRadarGageMosaicChk.setText("Satellite Radar Gage Mosaic"); - satRadarGageMosaicChk.setFont(font); - satRadarGageMosaicChk.setLayoutData(gd); - satRadarGageMosaicChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.srgMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button triangulatedLocalBiasMosaicChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - triangulatedLocalBiasMosaicChk.setLayoutData(gd); - triangulatedLocalBiasMosaicChk - .setText("Triangulated Local Bias Mosaic"); - triangulatedLocalBiasMosaicChk.setFont(font); - triangulatedLocalBiasMosaicChk.setLayoutData(gd); - triangulatedLocalBiasMosaicChk - .addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.p3lMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button bestEstQPEChk = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - bestEstQPEChk.setLayoutData(gd); - bestEstQPEChk.setText("Best Estimate QPE"); - bestEstQPEChk.setFont(font); - bestEstQPEChk.setLayoutData(gd); - bestEstQPEChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.Xmrg; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button rfcFieldBiasMosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - rfcFieldBiasMosaic.setLayoutData(gd); - rfcFieldBiasMosaic.setText("RFC Field Bias Mosaic"); - rfcFieldBiasMosaic.setFont(font); - rfcFieldBiasMosaic.setLayoutData(gd); - rfcFieldBiasMosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.rfcbMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button rfcMultiSensorMosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - rfcMultiSensorMosaic.setLayoutData(gd); - rfcMultiSensorMosaic.setText("RFC Multisensor Mosaic"); - rfcMultiSensorMosaic.setFont(font); - rfcMultiSensorMosaic.setLayoutData(gd); - rfcMultiSensorMosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.rfcmMosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button rawQ2Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - rawQ2Mosaic.setLayoutData(gd); - rawQ2Mosaic.setText("Raw Q2 Mosaic"); - rawQ2Mosaic.setFont(font); - rawQ2Mosaic.setLayoutData(gd); - rawQ2Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.qmosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button localBQ2Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - localBQ2Mosaic.setLayoutData(gd); - localBQ2Mosaic.setText("Local Bias Q2 Mosaic"); - localBQ2Mosaic.setFont(font); - localBQ2Mosaic.setLayoutData(gd); - localBQ2Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.lqmosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button mQ2Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - mQ2Mosaic.setLayoutData(gd); - mQ2Mosaic.setText("Multisensor Q2 Mosaic"); - mQ2Mosaic.setFont(font); - mQ2Mosaic.setLayoutData(gd); - mQ2Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.mlqmosaic; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button local1Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - local1Mosaic.setLayoutData(gd); - local1Mosaic.setText("Local Field #1"); - local1Mosaic.setFont(font); - local1Mosaic.setLayoutData(gd); - local1Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.localField1; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button local2Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - local2Mosaic.setLayoutData(gd); - local2Mosaic.setText("Local Field #2"); - local2Mosaic.setFont(font); - local2Mosaic.setLayoutData(gd); - local2Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.localField2; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button local3Mosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - local3Mosaic.setLayoutData(gd); - local3Mosaic.setText("Local Field #3"); - local3Mosaic.setFont(font); - local3Mosaic.setLayoutData(gd); - local3Mosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.localField3; - } - }); - - spaceLabel = new Label(groupComp, SWT.NONE); - spaceLabel.setText(" "); - - Button rfcQpeMosaic = new Button(groupComp, SWT.RADIO); - gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false); - rfcQpeMosaic.setLayoutData(gd); - rfcQpeMosaic.setText("RFC QPE Mosaic"); - rfcQpeMosaic.setFont(font); - rfcQpeMosaic.setLayoutData(gd); - rfcQpeMosaic.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - subType = DisplayFieldData.rfcMosaic; - } - }); } + + /** * Process the selection. diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/PolygonEditManager.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/PolygonEditManager.java index 0156455054..b4c7e7d78b 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/PolygonEditManager.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/polygon/PolygonEditManager.java @@ -16,6 +16,14 @@ * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 7, 2015  16954      cgobs      Fix for cv_use issue - using getFieldName() in certain parts.
+ * 
**/ package com.raytheon.viz.mpe.ui.dialogs.polygon; @@ -233,7 +241,7 @@ public class PolygonEditManager { String polyEditStr = editAction.toPrettyName() + " " - + (subDrawSource != null ? subDrawSource.getCv_use() + + (subDrawSource != null ? subDrawSource.getFieldName() : String.format("%6.2f", precipValue)) + " " + editPoints.length + " " + (visible ? "1" : "0"); toUse.append(idx + " " + polyEditStr + "\n"); @@ -288,7 +296,7 @@ public class PolygonEditManager { } private static File getHourlyEditFile(DisplayFieldData fieldData, Date date) { - String fieldname = fieldData.getCv_use(); + String fieldname = fieldData.getFieldName(); String polygonDir = MPEDisplayManager.getPolygonEditDir(); /* Build the polygon filename. */ @@ -299,7 +307,7 @@ public class PolygonEditManager { private static File getPersistentEditFile(DisplayFieldData fieldData, Date date) { - String fieldname = fieldData.getCv_use(); + String fieldname = fieldData.getFieldName(); String polygonDir = MPEDisplayManager.getPolygonEditDir(); /* Build the persistent polygon filename. */ String persistentFilename = String.format("%s/DrawPoly%s", polygonDir, @@ -345,7 +353,7 @@ public class PolygonEditManager { DisplayFieldData subData = null; for (DisplayFieldData fieldData : DisplayFieldData .values()) { - if (fieldData.getCv_use() + if (fieldData.getFieldName() .equalsIgnoreCase(subCvUse)) { subData = fieldData; break; diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/PostAnalysisManager.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/PostAnalysisManager.java index 9cb80cc03d..5226197a40 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/PostAnalysisManager.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/PostAnalysisManager.java @@ -58,8 +58,6 @@ public class PostAnalysisManager private XmrgFile.XmrgHeader xmrgHeader = null; private boolean misbin[][] = getMisBin(); - private DailyQcUtils dqc = DailyQcUtils.getInstance(); - private static final double MISSING_VALUE = -9999.0; private static final double MM_PER_INCH = 25.4; @@ -88,14 +86,14 @@ public class PostAnalysisManager } - public Date getSelectedDate() + public static Date getSelectedDate() { - Date date = dqc.pdata[dqc.pcpn_day].data_time; + Date date = DailyQcUtils.pdata[DailyQcUtils.pcpn_day].data_time; return date; } - public String getSelectedDateString() + public static String getSelectedDateString() { String header = "postAnalysisManager.getSelectedDateString(): "; @@ -116,7 +114,7 @@ public class PostAnalysisManager } - public String get24HourGageOnlyFilePath() + public static String get24HourGageOnlyFilePath() { String filePath = null; final String mpe_grid_precip_dir_tok = "mpe_grid_precip_dir"; @@ -124,9 +122,9 @@ public class PostAnalysisManager String mpe_grid_precip_dir = ad.getToken(mpe_grid_precip_dir_tok); - String currentQcArea = dqc.currentQcArea; + String currentQcArea = DailyQcUtils.currentQcArea; - String dateString = getSelectedDateString(); + String dateString = PostAnalysisManager.getSelectedDateString(); // String dateString = "20140112"; @@ -232,7 +230,7 @@ public class PostAnalysisManager String[] fileNameArray = fileDirectory.list(); - int precipDay = dqc.pcpn_day; + int precipDay = DailyQcUtils.pcpn_day; List filteredFileNameList = filterFileNames(precipDay, fileNameArray); @@ -270,9 +268,9 @@ public class PostAnalysisManager return endTime; } - public double[][] get24HourTotalPrecip(int height, int width, double scaleFactor) + public static double[][] get24HourTotalPrecip(int height, int width, double scaleFactor) { - Date endDate = getSelectedDate(); + Date endDate = PostAnalysisManager.getSelectedDate(); // System.out.println("PostAnalysisManager.getEndTime() = " + endDate); double missingValue = -999.0; @@ -352,8 +350,8 @@ public class PostAnalysisManager double distanceSquared; double nearestDistanceSquared = 9999999.0; - int XOR = dqc.getHrap_grid().hrap_minx; - int YOR = dqc.getHrap_grid().hrap_miny; + int XOR = DailyQcUtils.getHrap_grid().hrap_minx; + int YOR = DailyQcUtils.getHrap_grid().hrap_miny; // Find the distance to the nearest precip station from this HRAP // bin at [i][j] @@ -389,7 +387,7 @@ public class PostAnalysisManager { String header = "PostAnalysisManager.create3DGridArray(): "; - Hrap_Grid hrap_grid = dqc.getHrap_grid(); + Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); int maxI = hrap_grid.maxi; int maxJ = hrap_grid.maxj; @@ -408,7 +406,7 @@ public class PostAnalysisManager { //String header = "PostAnalysisManager.create2DGridArray(): "; - Hrap_Grid hrap_grid = dqc.getHrap_grid(); + Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); int maxCols = hrap_grid.maxi; int maxRows = hrap_grid.maxj; @@ -992,7 +990,7 @@ public class PostAnalysisManager } */ - Hrap_Grid grid = dqc.getHrap_grid(); + Hrap_Grid grid = DailyQcUtils.getHrap_grid(); int maxJ = grid.maxj; int maxI = grid.maxi; @@ -1249,8 +1247,8 @@ public class PostAnalysisManager { String header = "PostAnalysisManager.mergeData(): "; - int MAXX = dqc.getHrap_grid().maxi; - int MAXY = dqc.getHrap_grid().maxj; + int MAXX = DailyQcUtils.getHrap_grid().maxi; + int MAXY = DailyQcUtils.getHrap_grid().maxj; double logRHat; int i, j; @@ -1258,10 +1256,10 @@ public class PostAnalysisManager double weightingFactor; int precipStationCount; -// List precipStationList = dqc.precip_stations; + List precipStationList = DailyQcUtils.precip_stations; - precipStationCount = dqc.precip_stations.size(); + precipStationCount = precipStationList.size(); logRHat = Math.log((double) rhat); @@ -1316,7 +1314,7 @@ public class PostAnalysisManager //System.out.println(header + "merge section"); weightingFactor = computeObservedWeight (i, j, logRHat, - dqc.precip_stations, precipStationCount, estimatedScale); + precipStationList, precipStationCount, estimatedScale); double mergedValueInInches = weightingFactor * gageOnlyGridValueInInches + (1.0 - weightingFactor) * qpeInches; diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/SummedHourlyMpeDlg.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/SummedHourlyMpeDlg.java index ed6d482140..dea16fd548 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/SummedHourlyMpeDlg.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/postanalysis/SummedHourlyMpeDlg.java @@ -63,7 +63,6 @@ public class SummedHourlyMpeDlg extends BasePostAnalysisDlg private static final int SECONDS_PER_HOUR = 3600; private static final int SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR; - private DailyQcUtils dqc = DailyQcUtils.getInstance(); /** Bundle file location */ //private static final String BUNDLE_LOC = "bundles/MPE/postAnalysisBundle.xml"; @@ -80,11 +79,10 @@ public class SummedHourlyMpeDlg extends BasePostAnalysisDlg setResourceType1(PAResourceType.XMRG); setResourceType2(PAResourceType.ASCII_XMRG); - PostAnalysisManager paMgr = new PostAnalysisManager(); // 24 accumulated 1-hour precip grids - Hrap_Grid grid = dqc.getHrap_grid(); + Hrap_Grid grid = DailyQcUtils.getHrap_grid(); int wfoMinX = grid.hrap_minx; int wfoMinY = grid.hrap_miny; int width = grid.maxi; @@ -97,7 +95,7 @@ public class SummedHourlyMpeDlg extends BasePostAnalysisDlg float scaleFactor = 25.4f * 100.0f; - double[][] totalPrecipGrid = paMgr.get24HourTotalPrecip(height, width, scaleFactor); + double[][] totalPrecipGrid = PostAnalysisManager.get24HourTotalPrecip(height, width, scaleFactor); //floatArray units are hundredths of MM @@ -106,7 +104,7 @@ public class SummedHourlyMpeDlg extends BasePostAnalysisDlg setDataArray1(floatArray); //24 hour gage only - String dataFilePath2 = paMgr.get24HourGageOnlyFilePath(); + String dataFilePath2 = PostAnalysisManager.get24HourGageOnlyFilePath(); setDataFileName2(dataFilePath2); return; @@ -116,12 +114,12 @@ public class SummedHourlyMpeDlg extends BasePostAnalysisDlg private float[] convertToFloatArray(double[][] totalPrecipGrid, float unitConversionFactor) { String header = "SummedHourlyMpeDlg.convertToFloatArray(qpeAccum24hr): "; - Hrap_Grid hrap_grid = dqc.getHrap_grid(); + Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); int maxCols = hrap_grid.maxi; int maxRows = hrap_grid.maxj; - int precipDay = dqc.pcpn_day; + int precipDay = DailyQcUtils.pcpn_day; - System.out.println(header + "DailyQcUtils.pcpn_day = " + dqc.pcpn_day); + System.out.println(header + "DailyQcUtils.pcpn_day = " + DailyQcUtils.pcpn_day); System.out.println(header + "precipDay = " + precipDay); float[] valueArray = new float[maxRows*maxCols]; diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/DisplayMeanArealPrecipResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/DisplayMeanArealPrecipResource.java index 3c518200b7..79cb501d74 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/DisplayMeanArealPrecipResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/DisplayMeanArealPrecipResource.java @@ -16,6 +16,14 @@ * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 7, 2015  16954      cgobs      Fix for cv_use issue - using getFieldName() in certain parts.
+ * 
**/ package com.raytheon.viz.mpe.ui.rsc; @@ -580,7 +588,7 @@ public class DisplayMeanArealPrecipResource extends // this will accumulate all hours requested and display it // this holds current xmrg values short[] tempdata = null; - String cv_use = displayMgr.getDisplayFieldType().getCv_use(); + String cv_use = displayMgr.getDisplayFieldType().getFieldName(); String dirname = appsDefaults.getToken(displayMgr.getDisplayFieldType() .getDirToken()); String fname = ""; diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PlotGriddedPrecipResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PlotGriddedPrecipResource.java index ce8e6d2158..63c093fea5 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PlotGriddedPrecipResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PlotGriddedPrecipResource.java @@ -73,6 +73,8 @@ import com.raytheon.viz.mpe.ui.actions.DrawDQCStations; import com.raytheon.viz.mpe.ui.actions.OtherPrecipOptions; import com.raytheon.viz.mpe.util.CreateMap; import com.raytheon.viz.mpe.util.DailyQcUtils; +import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid; +import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; @@ -97,10 +99,6 @@ public class PlotGriddedPrecipResource extends IMpeResource { MPEDisplayManager displayMgr = null; - - private DailyQcUtils dqc = DailyQcUtils.getInstance(); - - private DrawDQCStations ddq = DrawDQCStations.getInstance(); private GriddedImageDisplay2 gridDisplay; @@ -124,11 +122,11 @@ public class PlotGriddedPrecipResource extends int display_flag; -// Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); + Hrap_Grid hrap_grid = DailyQcUtils.getHrap_grid(); -// Pcp pcp = DailyQcUtils.pcp; + Pcp pcp = DailyQcUtils.pcp; -// Pcp spf = DailyQcUtils.spf; + Pcp spf = DailyQcUtils.spf; private ColorMapParameters parameters = new ColorMapParameters(); @@ -143,7 +141,7 @@ public class PlotGriddedPrecipResource extends this.colorSet = colorSet; } - ColorMap precip_colormap = ddq.colorMap; + ColorMap precip_colormap = DrawDQCStations.colorMap; RGB color = null; @@ -154,8 +152,8 @@ public class PlotGriddedPrecipResource extends public void plot_gridded_precip(String prefix, int num, int mnum) { int pcpn_time_step = MPEDisplayManager.pcpn_time_step; int rsmode = OtherPrecipOptions.rsmode; - boolean wfo_all = dqc.wfo_all; - int[] wfo_in_use = dqc.wfo_in_use; + boolean wfo_all = DailyQcUtils.wfo_all; + int[] wfo_in_use = DailyQcUtils.wfo_in_use; CreateMap cm = new CreateMap(); float value = 0; @@ -225,37 +223,37 @@ public class PlotGriddedPrecipResource extends if (num == 0) { i1 = 0; } - if (dqc.pcp_in_use[num + mnum] != -1 - && dqc.pcp_in_use[num + mnum - i1] != -1) { - cm.read_file(file, num + mnum, dqc.spf); - cm.read_file(file, num + mnum - i1, dqc.pcp); + if (DailyQcUtils.pcp_in_use[num + mnum] != -1 + && DailyQcUtils.pcp_in_use[num + mnum - i1] != -1) { + cm.read_file(file, num + mnum, spf); + cm.read_file(file, num + mnum - i1, pcp); - for (i = 0; i < (dqc.getHrap_grid().maxi - dqc.getHrap_grid().hrap_minx) - 1; i++) { - for (j = 0; j < dqc.getHrap_grid().maxj - dqc.getHrap_grid().hrap_miny - 1; j++) { - dqc.spf.value[i][j] = (dqc.spf.value[i][j] + dqc.pcp.value[i][j]) / 2; + for (i = 0; i < (hrap_grid.maxi - hrap_grid.hrap_minx) - 1; i++) { + for (j = 0; j < hrap_grid.maxj - hrap_grid.hrap_miny - 1; j++) { + spf.value[i][j] = (spf.value[i][j] + pcp.value[i][j]) / 2; } } - } else if (dqc.pcp_in_use[num + mnum] == 1) { - cm.read_file(file, num + mnum, dqc.spf); - } else if (dqc.pcp_in_use[num + mnum - i1] == 1) { - cm.read_file(file, num + mnum - i1, dqc.spf); + } else if (DailyQcUtils.pcp_in_use[num + mnum] == 1) { + cm.read_file(file, num + mnum, spf); + } else if (DailyQcUtils.pcp_in_use[num + mnum - i1] == 1) { + cm.read_file(file, num + mnum - i1, spf); } } - if (dqc.pcp_in_use[num] == -1) { + if (DailyQcUtils.pcp_in_use[num] == -1) { return; } - cm.read_file(file, num, dqc.pcp); + cm.read_file(file, num, pcp); - buf = FloatBuffer.allocate(dqc.getHrap_grid().maxi * dqc.getHrap_grid().maxj); + buf = FloatBuffer.allocate(hrap_grid.maxi * hrap_grid.maxj); /* Get value in the HRAP grid bins. */ // for (i = 0; i < (hrap_grid.maxi); i++) { // for (j = 0; j < hrap_grid.maxj; j++) { - for (j = dqc.getHrap_grid().maxj - 1; j >= 0; j--) { - for (i = 0; i < dqc.getHrap_grid().maxi; i++) { - if (dqc.getHrap_grid().owner[i][j] == -1) { + for (j = hrap_grid.maxj - 1; j >= 0; j--) { + for (i = 0; i < hrap_grid.maxi; i++) { + if (hrap_grid.owner[i][j] == -1) { continue; } @@ -266,14 +264,14 @@ public class PlotGriddedPrecipResource extends break; } - if (dqc.getHrap_grid().owner[i][j] == wfo_in_use[m]) { + if (hrap_grid.owner[i][j] == wfo_in_use[m]) { break; } } } Float fg = 0f; - value = dqc.pcp.value[i][j]; + value = pcp.value[i][j]; // fg = (float) (value / 100.0); if (fg.isNaN() || value < 0) { fg = -9999f; @@ -302,8 +300,8 @@ public class PlotGriddedPrecipResource extends } buf.rewind(); - Rectangle extent = new Rectangle(dqc.getHrap_grid().hrap_minx, - dqc.getHrap_grid().hrap_miny, dqc.getHrap_grid().maxi, dqc.getHrap_grid().maxj); + Rectangle extent = new Rectangle(hrap_grid.hrap_minx, + hrap_grid.hrap_miny, hrap_grid.maxi, hrap_grid.maxj); if (extent.x == 0 && extent.y == 0) { Rectangle coord = null; @@ -388,7 +386,7 @@ public class PlotGriddedPrecipResource extends int x = p.x - extent.x; int y = p.y - extent.y; - short s = (short) dqc.pcp.value[x][y]; + short s = (short) pcp.value[x][y]; double d = parameters.getDataToDisplayConverter().convert(s); @@ -464,20 +462,21 @@ public class PlotGriddedPrecipResource extends @Override protected void initInternal(IGraphicsTarget target) throws VizException { this.target = target; - time_pos = ddq.time_pos; - plot_gridded_precip(ddq.prefix, time_pos, 100); + time_pos = DrawDQCStations.time_pos; + plot_gridded_precip(DrawDQCStations.prefix, time_pos, 100); } @Override protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { - if (buf == null || dqc.grids_flag != 1 + if (buf == null || (DailyQcUtils.grids_flag != 1 && DailyQcUtils.contour_flag != 1) || displayMgr.isQpf() != true) { return; } Set mode = displayMgr.getDisplayMode(); + System.out.println("Mode is: "+mode.toString()); if (mode.contains(DisplayMode.Image)) { if (gridDisplay == null) { @@ -514,11 +513,11 @@ public class PlotGriddedPrecipResource extends */ @Override public String getName() { - if (ddq.qcmode == "") { + if (DrawDQCStations.qcmode == "") { return "No Data Available"; } - return ddq.qcmode; + return DrawDQCStations.qcmode; } @Override diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java index 5bc199ab69..0ed2a06334 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointFreezePlotResource.java @@ -57,6 +57,7 @@ import com.raytheon.uf.viz.core.PixelCoverage; import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.RGBColors; import com.raytheon.uf.viz.core.data.IRenderedImageCallback; +import com.raytheon.uf.viz.core.data.prep.IODataPreparer; import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IImage; import com.raytheon.uf.viz.core.drawables.PaintProperties; @@ -74,6 +75,8 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Ztn; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.index.strtree.STRtree; +import com.raytheon.viz.mpe.ui.dialogs.EditFreezeStationsDialog; +import com.raytheon.viz.mpe.util.DailyQcUtils.Zdata; /** * MPEMultiple point resource. @@ -113,6 +116,8 @@ public class PointFreezePlotResource extends private double scaleHeightValue = 0.0; + private Station gageData = null; + private static final String[] color_map_a = { "Cyan1", "Salmon", "Orange1", "Yellow1", "Magenta1", "Green1", "Green4", "Gray74", "White", "Cyan1" }; @@ -124,6 +129,10 @@ public class PointFreezePlotResource extends private Hashtable zdataMap; + int pcpn_day = 0; + + static int prevPcpnDay; + private final DailyQcUtils dqc = DailyQcUtils.getInstance(); /** @@ -162,12 +171,13 @@ public class PointFreezePlotResource extends dataMap = new Hashtable(); zdataMap = new Hashtable(); strTree = new STRtree(); - Station gageData = new Station(); - ArrayList station = dqc.freezing_stations; + gageData = dqc.new Station(); + prevPcpnDay = 0; +// ArrayList station = dqc.freezing_stations; - if (!station.isEmpty()) { + if (!dqc.freezing_stations.isEmpty()) { int i = 0; - for (ListIterator it = station.listIterator(); it + for (ListIterator it = dqc.freezing_stations.listIterator(); it .hasNext();) { gageData = it.next(); Coordinate xy = new Coordinate(); @@ -195,6 +205,7 @@ public class PointFreezePlotResource extends strTree.insert(env, data); i++; } + prevPcpnDay = dqc.pcpn_day; } } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java index 7d2227cadd..9feff2848b 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointPrecipPlotResource.java @@ -37,6 +37,8 @@ import javax.measure.unit.NonSI; import javax.measure.unit.Unit; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; import org.opengis.referencing.FactoryException; import org.opengis.referencing.operation.TransformException; @@ -70,10 +72,8 @@ import com.raytheon.viz.mpe.ui.actions.DrawDQCStations; import com.raytheon.viz.mpe.ui.actions.OtherPrecipOptions; import com.raytheon.viz.mpe.ui.dialogs.QcPrecipOptionsDialog; import com.raytheon.viz.mpe.util.DailyQcUtils; -import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata; import com.raytheon.viz.mpe.util.DailyQcUtils.Station; import com.raytheon.viz.mpe.util.DailyQcUtils.Stn; -import com.raytheon.viz.mpe.util.DailyQcUtils.Ts; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.index.strtree.STRtree; @@ -132,6 +132,8 @@ public class PointPrecipPlotResource extends private Hashtable pdataMap; private final DailyQcUtils dqc = DailyQcUtils.getInstance(); + + static int prevPcpnDay; /** * Constructor. @@ -148,6 +150,7 @@ public class PointPrecipPlotResource extends public PointPrecipPlotResource(PointPrecipResourceData resourceData, LoadProperties props) { super(resourceData, props); + prevPcpnDay = 0; df.setMaximumFractionDigits(2); df.setMaximumIntegerDigits(4); } @@ -169,12 +172,13 @@ public class PointPrecipPlotResource extends dataMap = new Hashtable(); pdataMap = new Hashtable(); strTree = new STRtree(); - gageData = new Station(); - ArrayList station = dqc.precip_stations; - if (!station.isEmpty()) { + gageData = dqc.new Station(); + + if (!station.isEmpty()) { + + if (!dqc.precip_stations.isEmpty()) { int i = 0; - Pdata[] pdata = dqc.pdata; - for (ListIterator it = station.listIterator(); it + for (ListIterator it = dqc.precip_stations.listIterator(); it .hasNext();) { gageData = it.next(); Coordinate xy = new Coordinate(); @@ -187,7 +191,7 @@ public class PointPrecipPlotResource extends kv.append(":"); kv.append(pm); dataMap.put(kv.toString(), gageData); - pdataMap.put(kv.toString(), pdata[dqc.pcpn_day].stn[i]); + pdataMap.put(kv.toString(), DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i]); /* Create a small envelope around the point */ Coordinate p1 = new Coordinate(xy.x + .02, xy.y + .02); @@ -195,11 +199,14 @@ public class PointPrecipPlotResource extends Envelope env = new Envelope(p1, p2); ArrayList data = new ArrayList(); data.add(xy); - data.add("STATION: " + gageData.hb5 + " VALUE: " - + pdata[dqc.pcpn_day].stn[i].frain[time_pos].data); + data.add("STATION: " + + gageData.hb5 + + " VALUE: " + + DailyQcUtils.pdata[DailyQcUtils.pcpn_day].stn[i].frain[time_pos].data); strTree.insert(env, data); i++; } + prevPcpnDay = DailyQcUtils.pcpn_day; } // target.setNeedsRefresh(true); } @@ -265,26 +272,23 @@ public class PointPrecipPlotResource extends IFont font) throws VizException { if ((MPEDisplayManager.getCurrent().isQpf() == true) - && (dqc.points_flag == 1)) { - int type = dqc.plot_view; + && (DailyQcUtils.points_flag == 1)) { + int type = DailyQcUtils.plot_view; int i = 0; int m = 0; int dcmode = OtherPrecipOptions.dcmode; int tcmode = OtherPrecipOptions.tcmode; int dmvalue = dqc.dmvalue; - Ts ts[] = dqc.ts; int tsmax = dqc.tsmax; boolean frzlvl_flag = dqc.frzlvl_flag; int gage_char[] = dqc.gage_char; int find_station_flag = dqc.find_station_flag; - int dflag[] = dqc.dflag; - int qflag[] = dqc.qflag; String mbuf = ""; String tbuf = ""; String val = ""; if (MPEDisplayManager.pcpn_time_step == 0) { - time_pos = dqc.pcpn_time; + time_pos = DailyQcUtils.pcpn_time; } else { time_pos = 4; } @@ -296,7 +300,7 @@ public class PointPrecipPlotResource extends double[] centerpixels = descriptor.worldToPixel(new double[] { c.x, c.y }); color = RGBColors.getRGBColor(color_map_n[15]); - if ((dqc.points_flag == 1) + if ((DailyQcUtils.points_flag == 1) && (QcPrecipOptionsDialog.isOpen == true) && (MPEDisplayManager.getCurrent().isQpf() == true)) { } else { @@ -333,7 +337,7 @@ public class PointPrecipPlotResource extends for (m = 0; m < tsmax; m++) { if (station.parm.substring(3, 5).equalsIgnoreCase(ts[m].abr) - && (dflag[m + 1] == 1)) { + && (DailyQcUtils.dflag[m + 1] == 1)) { break; } } @@ -361,8 +365,8 @@ public class PointPrecipPlotResource extends /* locate station in data stream */ if (((type == 4) || (type == 5)) - && (dqc.pdata[dqc.pcpn_day].used[time_pos] == 0) - && (dqc.pdata[dqc.pcpn_day].level == 0)) { + && (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].used[time_pos] == 0) + && (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].level == 0)) { return; } if (((type == 4) || (type == 5)) @@ -408,8 +412,8 @@ public class PointPrecipPlotResource extends tbuf = station.name; } else if (type == 4) { - if ((dqc.pdata[dqc.pcpn_day].used[time_pos] == 0) - && (dqc.pdata[dqc.pcpn_day].level == 0)) { + if ((DailyQcUtils.pdata[DailyQcUtils.pcpn_day].used[time_pos] == 0) + && (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].level == 0)) { return; } @@ -433,8 +437,8 @@ public class PointPrecipPlotResource extends tbuf = mbuf; } else if (type == 5) { - if ((dqc.pdata[dqc.pcpn_day].used[time_pos] == 0) - && (dqc.pdata[dqc.pcpn_day].level == 0)) { + if ((DailyQcUtils.pdata[DailyQcUtils.pcpn_day].used[time_pos] == 0) + && (DailyQcUtils.pdata[DailyQcUtils.pcpn_day].level == 0)) { return; } @@ -699,7 +703,7 @@ public class PointPrecipPlotResource extends // Fonts are shared and cached, no need to init or dispose IFont font = fontFactory.getMPEFont(MPEDisplayManager.getFontId()); - if ((dqc.points_flag == 1) && (displayMgr.isQpf() == true)) { + if ((DailyQcUtils.points_flag == 1) && (displayMgr.isQpf() == true)) { Iterator iter = dataMap.keySet().iterator(); while (iter.hasNext()) { diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java index b45a1ea096..39a720ac55 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/PointTempPlotResource.java @@ -118,6 +118,8 @@ public class PointTempPlotResource extends private double scaleHeightValue = 0.0; + private Station gageData = null; + private static final String[] color_map_a = { "Cyan1", "Salmon", "Orange1", "Yellow1", "Magenta1", "Green1", "Green4", "Gray74", "White", "Cyan1" }; @@ -131,6 +133,10 @@ public class PointTempPlotResource extends private Hashtable tdataMap; + int pcpn_day = 0; + + static int prevPcpnDay; + private final DailyQcUtils dqc = DailyQcUtils.getInstance(); /** @@ -169,13 +175,14 @@ public class PointTempPlotResource extends dataMap = new Hashtable(); tdataMap = new Hashtable(); strTree = new STRtree(); - Station gageData = new Station(); + gageData = dqc.new Station(); ArrayList station = dqc.temperature_stations; Tdata[] tdata = dqc.tdata; + prevPcpnDay = 0; - if (!station.isEmpty()) { + if (!dqc.temperature_stations.isEmpty()) { int i = 0; - for (ListIterator it = station.listIterator(); it + for (ListIterator it = dqc.temperature_stations.listIterator(); it .hasNext();) { gageData = it.next(); Coordinate xy = new Coordinate(); @@ -188,7 +195,7 @@ public class PointTempPlotResource extends kv.append(":"); kv.append(pm); dataMap.put(kv.toString(), gageData); - tdataMap.put(kv.toString(), tdata[dqc.pcpn_day].tstn[i]); + tdataMap.put(kv.toString(), dqc.tdata[dqc.pcpn_day].tstn[i]); /* Create a small envelope around the point */ Coordinate p1 = new Coordinate(xy.x + .02, xy.y + .02); @@ -197,10 +204,11 @@ public class PointTempPlotResource extends ArrayList data = new ArrayList(); data.add(xy); data.add("STATION: " + gageData.hb5 + " VALUE: " - + tdata[dqc.pcpn_day].tstn[i].tlevel2[time_pos].data); + + dqc.tdata[dqc.pcpn_day].tstn[i].tlevel2[time_pos].data); strTree.insert(env, data); i++; } + prevPcpnDay = dqc.pcpn_day; } } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/DailyQcUtils.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/DailyQcUtils.java index 50eff783fa..01360606f9 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/DailyQcUtils.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/DailyQcUtils.java @@ -85,7 +85,7 @@ public class DailyQcUtils { private String lastQcArea = ""; - public String currentQcArea; + public static String currentQcArea; private Date currDate; @@ -101,7 +101,7 @@ public class DailyQcUtils { public int init_maxmin = -1; - public int pcp_in_use[] = new int[500]; + public static int pcp_in_use[] = new int[500]; boolean newarea = false; @@ -171,13 +171,13 @@ public class DailyQcUtils { public int method = 2; - public boolean wfo_all = false; + public static boolean wfo_all = false; public boolean render_all = true; public int wfo_orig; - public int[] wfo_in_use = new int[20]; + public static int[] wfo_in_use = new int[20]; public String[] tag = new String[20]; @@ -261,39 +261,39 @@ public class DailyQcUtils { public String mpe_show_missing_gage; - public int isom = -1; + public static int isom = -1; - public int old_isom = -1; + public static int old_isom = -1; - public ArrayList precip_stations = new ArrayList(); + public static ArrayList precip_stations = new ArrayList(); - public ArrayList temperature_stations = new ArrayList(); + public static ArrayList temperature_stations = new ArrayList(); - public ArrayList freezing_stations = new ArrayList(); + public static ArrayList freezing_stations = new ArrayList(); - public Pdata pdata[]; + public static Pdata pdata[]; - public Tdata tdata[]; + public static Tdata tdata[]; - public Zdata zdata[]; + public static Zdata zdata[]; - private Hrap_Grid hrap_grid = new Hrap_Grid(); + private static Hrap_Grid hrap_grid = new Hrap_Grid(); // public static Hrap_Grid hrap_tgrid = new Hrap_Grid(); public static String type = "QME "; - public Ts[] ts; + public static Ts[] ts; - public int tsmax = 0; + public static int tsmax = 0; public Maps mean_areal_precip_global[]; - public Pcp pcp = new Pcp(); + public static Pcp pcp = new Pcp(); - public Pcp spf = new Pcp(); + public static Pcp spf = new Pcp(); - public Pcp tpf = new Pcp(); + public static Pcp tpf = new Pcp(); public Bad_Daily_Values bad_values[]; @@ -441,15 +441,15 @@ public class DailyQcUtils { public static int hrgt12z = -1; - public int[] dflag = new int[10]; + public static int[] dflag = new int[10]; - public int[] qflag = new int[10]; + public static int[] qflag = new int[10]; public float pxtemp = 1.0f; public int dmvalue = (int) ((1.0 * 100 * 3.28) / .55); - public int elevation_filter_value = 0; + public static int elevation_filter_value = 0; public int temperature_filter_value = -50; @@ -472,27 +472,27 @@ public class DailyQcUtils { /* Function which associates the Gage QC edit levels with a value. */ public int funct[] = { 8, 0, 6, 2, 3, 4, 5, 1, 7, 9 }; - public int gage_char[] = new int[2]; + public static int gage_char[] = new int[2]; - public int plot_view = 0; + public static int plot_view = 0; public boolean frzlvl_flag = true; public int find_station_flag = -1; - public int pcpn_time = 0; + public static int pcpn_time = 0; - public int pcp_flag = -1; + public static int pcp_flag = -1; - public int pcpn_day = 0; + public static int pcpn_day = 0; - public int contour_flag = -1; + public static int contour_flag = -1; - public int points_flag = 1; + public static int points_flag = 1; - public int grids_flag = -1; + public static int grids_flag = -1; - public int map_flag = -1; + public static int map_flag = -1; static int curHrMinSec = -1; @@ -815,7 +815,7 @@ public class DailyQcUtils { float fvalue; } - public static class Station { + public class Station { public float isoh[]; public float max[]; @@ -901,7 +901,7 @@ public class DailyQcUtils { return retval; } - public int getEnding6HourObsTime() { + public static int getEnding6HourObsTime() { String s = appsDefaults.getToken(dqc_ending_6hour_obstime_tok); int value = ((!(null == s)) ? Integer.parseInt(s) : -1); @@ -915,6 +915,9 @@ public class DailyQcUtils { String currntQcArea, int days, boolean autoqc) { currentQcArea = currntQcArea; currDate = currentDate; + if (prevDate == null){ + prevDate = currDate; + } selDate = prevDate; auto_dailyqc_flag = autoqc; qcDays = MPEDataManager.getInstance().getDQCDays(); @@ -1044,7 +1047,6 @@ public class DailyQcUtils { */ Calendar currentTime = Calendar .getInstance(TimeZone.getTimeZone("GMT")); - emonth = btime.get(Calendar.MONTH); Calendar otime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); otime.setTime(btime.getTime()); @@ -2129,7 +2131,7 @@ public class DailyQcUtils { /** * @return the hrap_grid */ - public Hrap_Grid getHrap_grid() { + public static Hrap_Grid getHrap_grid() { return hrap_grid; } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/Disagg6Hr.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/Disagg6Hr.java index 1eeaa62aa1..f7c337a984 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/Disagg6Hr.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/Disagg6Hr.java @@ -368,7 +368,7 @@ public class Disagg6Hr { values6hr = new Values_6hr[(dqc.qcDays * num_disagg_stations)]; for (int z = 0; z < (dqc.qcDays * num_disagg_stations); z++) { - disagg_station_6hr[z] = new Station(); + disagg_station_6hr[z] = dqc.new Station(); disaggValues[z] = new Values_1hr(); values6hr[z] = new Values_6hr(); } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitPrecipClimo.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitPrecipClimo.java index f4e572f3d7..7bf9b41fcf 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitPrecipClimo.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitPrecipClimo.java @@ -100,7 +100,7 @@ public class InitPrecipClimo { // if (precip_stations.get(index).parm.charAt(4) == // tokens[1] // .charAt(4)) { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = precip_stations.get(index); for (int m = 0; m < 12; m++) { nstation.isoh[m] = Float.parseFloat(tokens[m + 2]); @@ -145,7 +145,7 @@ public class InitPrecipClimo { if ((precip_stations.get(index).isoh[0] < 0) || (precip_stations.get(index).cparm .equalsIgnoreCase("PPMPBCM"))) { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = precip_stations.get(index); for (int m = 0; m < 12; m++) { @@ -174,7 +174,7 @@ public class InitPrecipClimo { if ((precip_stations.get(index).isoh[0] < 0) || (precip_stations.get(index).cparm .equalsIgnoreCase("PPMPBCM"))) { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = precip_stations.get(index); for (int m = 0; m < 12; m++) { @@ -195,7 +195,7 @@ public class InitPrecipClimo { int oldk = -1; int k; - Station astation = new Station(); + Station astation = dc.new Station(); for (int kk = 0; kk < 12; kk++) { if (kk < 3) { diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitTempClimo.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitTempClimo.java index e45d125c0e..6ede1762dd 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitTempClimo.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/InitTempClimo.java @@ -114,7 +114,7 @@ public class InitTempClimo { /* Increment the station array index. */ ++index; } else { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = temperature_stations.get(index); if ((tokens[1].charAt(5) == 'X') @@ -161,7 +161,7 @@ public class InitTempClimo { /* Increment the station array index. */ ++index; } else { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = temperature_stations.get(index); /* * Is the extremum code 'Maximum'? Of temperature, @@ -246,7 +246,7 @@ public class InitTempClimo { /* Increment the station array index. */ ++index; } else { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = temperature_stations.get(index); if ((tokens[1].charAt(5) == 'X') @@ -309,7 +309,7 @@ public class InitTempClimo { .get(index).min[0] < 0)) || temperature_stations.get(index).cparm.substring( 0, 5).equalsIgnoreCase("TAIPB")) { - Station nstation = new Station(); + Station nstation = dc.new Station(); nstation = temperature_stations.get(index); /* * Is the extremum code 'Maximum'? Of temperature, diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MapFreezingGagesGrid.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MapFreezingGagesGrid.java index 60476846fc..524cbaee41 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MapFreezingGagesGrid.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MapFreezingGagesGrid.java @@ -262,7 +262,7 @@ public class MapFreezingGagesGrid { * Update the precip station list to contain the nearest freezing level * stations. */ - Station station = new Station(); + Station station = dqc.new Station(); for (i = 0; i < numPstations; i++) { station = precip_stations.get(i); diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MeanMonthlyPrecip.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MeanMonthlyPrecip.java index 9be81678db..e204132de6 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MeanMonthlyPrecip.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/MeanMonthlyPrecip.java @@ -90,8 +90,9 @@ public class MeanMonthlyPrecip { displayUnit = NonSI.INCH; dataUnit = SI.MILLIMETER; cmc.setDisplayUnit(displayUnit); + cmc.setColorMapUnit(SI.MILLIMETER); cmc.setDataUnit(dataUnit); - UnitConverter dataToImage = cmc.getDataToImageConverter(); + UnitConverter dataToImage = cmc.getColorMapToDisplayConverter();//cmc.getDataToImageConverter(); /* * Loop over the months. Determine for which months PRISM data are diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadFreezingStationList.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadFreezingStationList.java index 7607be589e..45a4fee219 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadFreezingStationList.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadFreezingStationList.java @@ -144,7 +144,7 @@ public class ReadFreezingStationList { tokens = null; } if ((tokens != null) && (tokens.length == 7)) { - Station astation = new Station(); + Station astation = dqc.new Station(); astation.hb5 = tokens[0].toString().trim(); astation.parm = tokens[1].toString().trim(); double lat = Double.parseDouble(tokens[2].trim()); @@ -233,7 +233,7 @@ public class ReadFreezingStationList { .substring(0, 2))) && (record[1] .equalsIgnoreCase(stations.get(i).parm))) { - Station statn = new Station(); + Station statn = dqc.new Station(); statn = stations.get(i); statn.xadd = Integer.parseInt(record[2].trim()); statn.yadd = Integer.parseInt(record[3].trim()); diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadPrecipStationList.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadPrecipStationList.java index 837684c639..f4e29b4aef 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadPrecipStationList.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadPrecipStationList.java @@ -74,7 +74,7 @@ public class ReadPrecipStationList { e.printStackTrace(); } - ReadPrecipStationList.max_pstations = dqc.precip_stations.size(); + max_pstations = dqc.precip_stations.size(); return dqc.precip_stations; @@ -123,7 +123,7 @@ public class ReadPrecipStationList { tokens = null; } if ((tokens != null) && (tokens.length == 7)) { - Station astation = new Station(); + Station astation = dqc.new Station(); astation.hb5 = tokens[0].toString().trim(); astation.parm = tokens[1].toString().trim(); double lat = Double.parseDouble(tokens[2]); @@ -204,7 +204,7 @@ public class ReadPrecipStationList { if ((record[1].substring(0, 2).compareTo( stations.get(i).parm.substring(0, 2)) == 0) && (record[1].equals(stations.get(i).parm))) { - Station statn = new Station(); + Station statn = dqc.new Station(); statn = stations.get(i); statn.xadd = Integer.parseInt(record[2]); statn.yadd = Integer.parseInt(record[3]); @@ -237,8 +237,8 @@ public class ReadPrecipStationList { int qcn = dqc.mpe_dqc_max_precip_neighbors; double sorted[] = new double[qcn]; double dist; - Station stati = new Station(); - Station statm = new Station(); + Station stati = dqc.new Station(); + Station statm = dqc.new Station(); stati.index = new short[qcn]; statm.index = new short[qcn]; diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadQPFGrids.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadQPFGrids.java index 19cb9f6b91..5b7186e61f 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadQPFGrids.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadQPFGrids.java @@ -112,7 +112,7 @@ public class ReadQPFGrids { } else { iflag = 0; } - for (i = 0; i < gmaxi; i++) { + for (i = 0; i < (dqc.getHrap_grid().maxi); i++) { if (iflag == 0) { kbuf = in.readLine().trim(); @@ -130,7 +130,7 @@ public class ReadQPFGrids { // if (ghrapi > minhrapi && ghrapi <= maxhrapi) { - for (j = 0; j < gmaxj; j++) { + for (j = 0; j < (dqc.getHrap_grid().maxj); j++) { // ghrapj = gminj + j; // diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadSnowData.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadSnowData.java index f4fc440fb8..1383233d35 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadSnowData.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadSnowData.java @@ -86,6 +86,7 @@ public class ReadSnowData { } } in = new BufferedReader(new FileReader(prece)); + System.out.println("Reading Snow data from : " + prece); // int p = 1; // String sn = cbuf; @@ -168,6 +169,7 @@ public class ReadSnowData { dqc.pdata[i].stn[j].srain[kk].data = Float.parseFloat(qbuf); dqc.pdata[i].stn[j].srain[kk].qual = 8; + System.out.println("Loading Snow Data for Station "+ hb5 +" with value: "+ dqc.pdata[i].stn[j].srain[kk].data); break; diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadTemperatureStationList.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadTemperatureStationList.java index 3b5d686812..659f5cfd70 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadTemperatureStationList.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/ReadTemperatureStationList.java @@ -83,7 +83,7 @@ public class ReadTemperatureStationList { e.printStackTrace(); } - ReadTemperatureStationList.max_tstations = dqc.temperature_stations + max_tstations = dqc.temperature_stations .size(); return dqc.temperature_stations; @@ -136,7 +136,7 @@ public class ReadTemperatureStationList { tokens = null; } if ((tokens != null) && (tokens.length == 7)) { - Station astation = new Station(); + Station astation = dqc.new Station(); astation.hb5 = tokens[0].toString().trim(); astation.parm = tokens[1].toString().trim(); double lat = Double.parseDouble(tokens[2].trim()); @@ -231,7 +231,7 @@ public class ReadTemperatureStationList { .substring(0, 2))) && (record[1] .equalsIgnoreCase(stations.get(i).parm))) { - Station statn = new Station(); + Station statn = dqc.new Station(); statn = stations.get(i); statn.xadd = Integer.parseInt(record[2].trim()); statn.yadd = Integer.parseInt(record[3].trim()); @@ -268,8 +268,8 @@ public class ReadTemperatureStationList { int qcn = dqc.mpe_dqc_max_temp_neighbors; double sorted[] = new double[qcn]; double dist; - Station stati = new Station(); - Station statm = new Station(); + Station stati = dqc.new Station(); + Station statm = dqc.new Station(); for (i = 0; i < max_tstations; i++) { stati = stations.get(i); diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/StationListManager.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/StationListManager.java index 5958ee8a48..3e3d7e6814 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/StationListManager.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/StationListManager.java @@ -197,7 +197,7 @@ public class StationListManager { (stationTokens.length == 7) && // input is valid and (inputLine.charAt(0) != '#')) // not a comment { - Station aStation = new Station(); + Station aStation = dqc.new Station(); aStation.hb5 = stationTokens[0].toString().trim(); // Location // ID aStation.parm = stationTokens[1].toString().trim(); diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java index 414cdd4a57..4748900bbf 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java @@ -30,6 +30,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; +import jep.JepException; + import com.google.common.util.concurrent.MoreExecutors; import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.exception.GfeMissingConfigurationException; @@ -38,12 +40,21 @@ import com.raytheon.edex.plugin.gfe.server.IFPServer; import com.raytheon.edex.site.SiteUtil; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException; +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.python.PyUtil; +import com.raytheon.uf.common.python.PythonScript; import com.raytheon.uf.common.site.notify.SiteActivationNotification; import com.raytheon.uf.common.site.notify.SiteActivationNotification.ACTIVATIONSTATUS; import com.raytheon.uf.common.site.notify.SiteActivationNotification.ACTIVATIONTYPE; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil; import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.database.DataAccessLayerException; @@ -79,7 +90,9 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications; * May 15, 2014 #3157 dgilling Mark getActiveSites() as deprecated. * Jul 09, 2014 #3146 randerso Eliminated redundant evaluation of serverConfig * Sent activation failure message to alertViz - * Oct 07, 2014 #3684 randerso Restructured IFPServer start up + * Oct 07, 2014 #3684 randerso Restructured IFPServer start up + * Dec 10, 2014 #4953 randerso Added requestTCVFiles call at site activation + * * * * @author njensen @@ -325,6 +338,21 @@ public class GFESiteActivation implements ISiteActivationListener { try { IRTManager.getInstance().enableISC(siteID, config); isIscActivated = true; + + // wait until EDEX is up and running to request TCV files + final IFPServerConfig configRef = config; + Runnable requestTCV = new Runnable() { + + @Override + public void run() { + EDEXUtil.waitForRunning(); + + requestTCVFiles(siteID, configRef); + } + }; + + postActivationTaskExecutor.submit(requestTCV); + } catch (Exception e) { statusHandler .error("Error starting GFE ISC. ISC functionality will be unavailable!!", @@ -478,4 +506,45 @@ public class GFESiteActivation implements ISiteActivationListener { return retVal; } + private void requestTCVFiles(String siteId, IFPServerConfig config) { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonBaseCx = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr.getFile(commonBaseCx, + FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "requestTCV.py")) + .getPath(); + + String pythonIncludePath = PyUtil.buildJepIncludePath( + ActiveTablePyIncludeUtil.getCommonPythonIncludePath(), + ActiveTablePyIncludeUtil.getCommonGfeIncludePath(), + ActiveTablePyIncludeUtil.getVtecIncludePath(siteId), + ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId), + ActiveTablePyIncludeUtil.getIscScriptsIncludePath()); + + PythonScript script = null; + try { + script = new PythonScript(scriptPath, pythonIncludePath, this + .getClass().getClassLoader()); + + try { + Map argMap = new HashMap(); + argMap.put("siteID", siteId); + argMap.put("config", config); + script.execute("runFromJava", argMap); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error executing requestTCV.", e); + } + } catch (JepException e) { + statusHandler + .handle(Priority.PROBLEM, + "Unable to instantiate requestTCV python script object.", + e); + } finally { + if (script != null) { + script.dispose(); + } + } + } + } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscReceiveSrv.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscReceiveSrv.java index 0176cb6fa4..9e60345b95 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscReceiveSrv.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscReceiveSrv.java @@ -56,9 +56,10 @@ import com.raytheon.uf.edex.site.SiteAwareRegistry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 05, 2012 #361 dgilling Initial creation - * Mar 12, 2013 #1759 dgilling Re-implement using IscScript. - * Mar 14, 2013 1794 djohnson Consolidate common FilenameFilter implementations. + * Mar 05, 2012 #361 dgilling Initial creation + * Mar 12, 2013 #1759 dgilling Re-implement using IscScript. + * Mar 14, 2013 #1794 djohnson Consolidate common FilenameFilter implementations. + * Dec 10, 2014 #4953 randerso Properly handle single file reception * * * @@ -144,6 +145,7 @@ public class IscReceiveSrv { xmlFileName = incomingFiles[1]; } + // TODO properly decode the xml final File incomingXMLFile = new File(xmlFileName); String fileContents = FileUtil.file2String(incomingXMLFile); Pattern siteTagRegEx = Pattern.compile("(.*?)"); @@ -186,18 +188,40 @@ public class IscReceiveSrv { if (activeSites.contains(site) && IFPServerConfigManager.getServerConfig(site) .requestISC()) { - String newFileName = dataFileName + "." + site; - String newXmlFileName = xmlFileName + "." + site; - try { - FileUtil.copyFile(new File(dataFileName), new File( - newFileName)); - } catch (IOException e) { - statusHandler.error("Failed to copy: [" - + dataFileName + "] to " + newFileName - + ". Unable to execute iscDataRec for " - + site, e); - continue; + String[] modifiedArgs = new String[args.length]; + System.arraycopy(args, 0, modifiedArgs, 0, args.length); + + if (dataFileName != null) { + String newFileName = dataFileName + "." + site; + try { + FileUtil.copyFile(new File(dataFileName), + new File(newFileName)); + } catch (IOException e) { + statusHandler + .error("Failed to copy: [" + + dataFileName + + "] to " + + newFileName + + ". Unable to execute iscDataRec for " + + site, e); + continue; + } + + if (!new File(newFileName).exists()) { + statusHandler + .error("Failed to copy: [" + + dataFileName + + "] to " + + newFileName + + ". Unable to execute iscDataRec for " + + site); + continue; + } + modifiedArgs[2] = modifiedArgs[2].replace( + dataFileName, newFileName); } + + String newXmlFileName = xmlFileName + "." + site; try { FileUtil.copyFile(new File(xmlFileName), new File( newXmlFileName)); @@ -208,14 +232,6 @@ public class IscReceiveSrv { + site, e); continue; } - if (!new File(newFileName).exists()) { - statusHandler.error("Failed to copy: [" - + dataFileName + "] to " + newFileName - + ". Unable to execute iscDataRec for " - + site); - continue; - } - if (!new File(newXmlFileName).exists()) { statusHandler.error("Failed to copy: [" + xmlFileName + "] to " + newXmlFileName @@ -224,24 +240,23 @@ public class IscReceiveSrv { continue; } - String[] modifiedArgs = new String[args.length]; - System.arraycopy(args, 0, modifiedArgs, 0, args.length); - modifiedArgs[2] = modifiedArgs[2].replace(dataFileName, - newFileName); modifiedArgs[2] = modifiedArgs[2].replace(xmlFileName, newXmlFileName); siteMap.put(site, modifiedArgs); } } } finally { - File dataFile = new File(dataFileName); - File xmlFile = incomingXMLFile; - - if (dataFile.exists()) { - if (!dataFile.delete()) { - statusHandler.error("Unable to delete " + dataFileName); + if (dataFileName != null) { + File dataFile = new File(dataFileName); + if (dataFile.exists()) { + if (!dataFile.delete()) { + statusHandler.error("Unable to delete " + + dataFileName); + } } } + + File xmlFile = incomingXMLFile; if (xmlFile.exists()) { if (!xmlFile.delete()) { statusHandler.error("Unable to delete " + xmlFileName); diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscScript.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscScript.java index 8867c442be..bd7cbf2400 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscScript.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/IscScript.java @@ -45,11 +45,13 @@ import com.raytheon.uf.common.util.FileUtil; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 11, 2013 dgilling Initial creation - * May 22, 2013 #1759 dgilling Ensure addSitePath() also adds base - * path. - * May 31, 2013 #1759 dgilling Ensure any site-specific paths are - * always removed post-execution. + * Mar 11, 2013 dgilling Initial creation + * May 22, 2013 #1759 dgilling Ensure addSitePath() also adds base + * path. + * May 31, 2013 #1759 dgilling Ensure any site-specific paths are + * always removed post-execution. + * Dec 08, 2014 #4953 randerso Updated Jep include path to allow use of + * LocalizationSupport and TCVUtil * * * @@ -82,6 +84,8 @@ public class IscScript extends PythonScript { private static String buildIncludePath() { return PyUtil.buildJepIncludePath( GfePyIncludeUtil.getCommonPythonIncludePath(), + GfePyIncludeUtil.getCommonGfeIncludePath(), + GfePyIncludeUtil.getVtecIncludePath(), GfePyIncludeUtil.getIscScriptsIncludePath()); } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/AreaDictionaryMaker.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/AreaDictionaryMaker.java index cc0f62f1ec..1f4a524139 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/AreaDictionaryMaker.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/AreaDictionaryMaker.java @@ -61,6 +61,8 @@ import com.raytheon.uf.edex.database.tasks.SqlQueryTask; * Oct 8, 2014 #4953 randerso Added hooks for TCVAreaDictionary creation * Oct 10, 2014 #3685 randerso Add code to generate the fips2cities and zones2cites * python modules from the GIS database tables + * Dec 08, 2014 #4953 randerso Updated Jep include path to allow use of + * LocalizationSupport * * * @@ -243,7 +245,9 @@ public class AreaDictionaryMaker { String includePath = PyUtil.buildJepIncludePath(true, GfePyIncludeUtil.getCommonPythonIncludePath(), + GfePyIncludeUtil.getCommonGfeIncludePath(), configDir.getPath(), scriptFile.getParent()); + Map argMap = new HashMap(); LocalizationContext caveStaticConfig = pathMgr.getContext( diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/AbstractWatchNotifierSrv.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/AbstractWatchNotifierSrv.java index 0daf7b50ad..d857a749ec 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/AbstractWatchNotifierSrv.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/AbstractWatchNotifierSrv.java @@ -58,8 +58,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; public abstract class AbstractWatchNotifierSrv { - protected final IUFStatusHandler statusHandler = UFStatus - .getHandler(getClass()); + protected static final IUFStatusHandler statusHandler = UFStatus + .getHandler(AbstractWatchNotifierSrv.class); protected final String watchType; diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/TPCWatchSrv.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/TPCWatchSrv.java index 91500fea89..874ff840a0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/TPCWatchSrv.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/watch/TPCWatchSrv.java @@ -20,6 +20,11 @@ package com.raytheon.edex.plugin.gfe.watch; import java.io.File; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -27,9 +32,13 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jep.JepException; +import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; +import com.raytheon.edex.plugin.gfe.server.IFPServer; import com.raytheon.uf.common.activetable.VTECPartners; import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; @@ -44,8 +53,10 @@ import com.raytheon.uf.common.localization.exception.LocalizationOpFailedExcepti import com.raytheon.uf.common.python.PyUtil; import com.raytheon.uf.common.python.PythonScript; import com.raytheon.uf.common.site.SiteMap; +import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.util.FileUtil; -import com.raytheon.uf.common.util.file.FilenameFilters; +import com.raytheon.uf.common.util.RunProcess; +import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil; /** * Watches ingested warnings for WOU products from the SPC (Storm Prediction @@ -66,7 +77,9 @@ import com.raytheon.uf.common.util.file.FilenameFilters; * Changed to use Python to store TCVAdvisory files * Added code to keep practice and operational * advisory files separated - * + * Added call to nwrwavestcv.csh + * Added support for sending TCVAdvisory files to + * VTEC partners * * * @author njensen @@ -74,6 +87,8 @@ import com.raytheon.uf.common.util.file.FilenameFilters; */ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { + private static final String NWRWAVES_SCRIPT = "/awips/adapt/NWRWAVES/nwrwavestcv.csh "; + private static final String TCV_ADVISORY_PATH = FileUtil.join("gfe", "tcvAdvisories"); @@ -109,7 +124,7 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { actMap = Collections.unmodifiableMap(actMapTemp); } - private ThreadLocal pythonScript = new ThreadLocal() { + private static final ThreadLocal pythonScript = new ThreadLocal() { /* * (non-Javadoc) @@ -140,6 +155,13 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { }; + // regex to parse storm name and advisory number from HLS MND header + private static final Pattern mndPattern = Pattern.compile( + "^.*\\s(?\\w+)\\sLOCAL STATEMENT " + + "(?SPECIAL |INTERMEDIATE )?" + + "(ADVISORY NUMBER\\s(?\\w+))?.*$", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + /** * Constructor */ @@ -156,29 +178,86 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { */ @Override public void handleWatch(List warningRecs) { - super.handleWatch(warningRecs); - /* * Since all records originate from a single TCV product the issuing * office and record type will be the same we only need to look at the * first record. */ AbstractWarningRecord record = warningRecs.get(0); + String pil = record.getPil(); boolean practiceMode = (record instanceof PracticeWarningRecord); String issuingOffice = record.getOfficeid(); + // if it's a TCV + if ("TCV".equals(pil)) { + super.handleWatch(warningRecs); + } + + // if we are not in practice mode + if (!practiceMode) { + + // if xxxId ends with a digit (i.e. its a national TCV) + String xxxId = record.getXxxid(); + if (Character.isDigit(xxxId.charAt(xxxId.length() - 1))) { + + // build the full 9-letter PIL + String fullPil = SiteMap.getInstance().mapICAOToCCC( + issuingOffice) + + pil + xxxId; + + // build the command line for the NWRWAVES script + final String command = NWRWAVES_SCRIPT + fullPil; + + // Create a separate thread to run the script + Thread thread = new Thread(new Runnable() { + + @Override + public void run() { + RunProcess proc; + try { + proc = RunProcess.getRunProcess().exec(command); + } catch (IOException e) { + statusHandler + .error("Error executing " + command, e); + return; + } + + int exitCode = proc.waitFor(); + if (exitCode != 0) { + statusHandler.error(command + + " terminated abnormally with exit code: " + + exitCode); + } + } + }); + + thread.start(); + } + } + + // update TCV Advisories for (String siteId : getActiveSites()) { String site4 = SiteMap.getInstance().getSite4LetterId(siteId); if (issuingOffice.equals(site4)) { - this.saveTCVAdvisories(siteId, practiceMode); + // if TCV save the pending.json files + if ("TCV".equals(pil)) { + this.saveTCVAdvisories(siteId, pil, practiceMode); + + } + // if HLS then delete the advisory files if the watch is + // canceled + else if ("HLS".equals(pil)) { + this.deleteTCVAdvisoriesIfCanceled(siteId, pil, + practiceMode, record.getRawmessage()); + } break; // found matching officeId so we're done } } } - private void saveTCVAdvisories(String siteId, boolean practiceMode) { - File advisoriesDirectory = this.synchronizeTCVAdvisories(siteId, - practiceMode); + private void saveTCVAdvisories(String siteId, String pil, + boolean practiceMode) { + this.synchronizeTCVAdvisories(siteId, practiceMode); String pendingFilename = "pending.json"; LocalizationFile pendingFile = this.getLocalizationFile(siteId, @@ -209,12 +288,64 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { } if (transmittedFileSaved) { - boolean allCAN = (Boolean) pendingDict.get("AllCAN"); - if (allCAN) { - for (File advisory : advisoriesDirectory - .listFiles(FilenameFilters.byFileExtension(".json"))) { - String advisoryName = advisory.getName(); - if (advisoryName.startsWith(stormName)) { + try { + pendingFile.delete(); + } catch (LocalizationOpFailedException e) { + statusHandler.error("Unable to delete " + pendingFile, e); + } + + // if not practice mode + if (!practiceMode) { + // send TCV files to VTEC partner sites + sendTCVFiles(siteId); + } + } + } + + private void deleteTCVAdvisoriesIfCanceled(String siteId, String pil, + boolean practiceMode, String productText) { + File advisoriesDirectory = this.synchronizeTCVAdvisories(siteId, + practiceMode); + + Matcher matcher = mndPattern.matcher(productText); + if (matcher.find()) { + String stormName = matcher.group("stormName"); + + // get the list of json files for this storm + List jsonFiles = new ArrayList(); + try (DirectoryStream stream = Files.newDirectoryStream( + advisoriesDirectory.toPath(), stormName + "*.json")) { + for (Path path : stream) { + jsonFiles.add(path.getFileName().toString()); + } + } catch (IOException e) { + statusHandler.error( + "Unable to get list of json files for storm: " + + stormName, e); + } + + if (!jsonFiles.isEmpty()) { + // load the highest numbered file for this storm + Collections.sort(jsonFiles, Collections.reverseOrder()); + LocalizationFile advFile = this.getLocalizationFile(siteId, + jsonFiles.get(0), practiceMode); + + Map advDict = loadJSONDictionary(advFile); + + boolean allCAN = (Boolean) advDict.get("AllCAN"); + if (allCAN) { + // create a flag file to indicate AllCAN has occurred + File tcvDir = advFile.getFile().getParentFile(); + File allCanFile = new File(FileUtil.join( + tcvDir.getAbsolutePath(), stormName + ".allCAN")); + try { + allCanFile.createNewFile(); + } catch (IOException e) { + statusHandler.error("Unable to create file: " + + allCanFile.getAbsolutePath(), e); + } + + for (String advisoryName : jsonFiles) { LocalizationFile advisoryFile = this .getLocalizationFile(siteId, advisoryName, practiceMode); @@ -225,13 +356,54 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv { + advisoryFile, e); } } + + sendTCVFiles(siteId); } } + } + } + + private void sendTCVFiles(String siteId) { + IFPServer ifpServer = IFPServer.getActiveServer(siteId); + if (ifpServer == null) { + return; + } + IFPServerConfig config = ifpServer.getConfig(); + + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonBaseCx = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr.getFile(commonBaseCx, + FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "sendTCV.py")) + .getPath(); + + String pythonIncludePath = PyUtil.buildJepIncludePath( + ActiveTablePyIncludeUtil.getCommonPythonIncludePath(), + ActiveTablePyIncludeUtil.getCommonGfeIncludePath(), + ActiveTablePyIncludeUtil.getVtecIncludePath(siteId), + ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId), + ActiveTablePyIncludeUtil.getIscScriptsIncludePath()); + + PythonScript script = null; + try { + script = new PythonScript(scriptPath, pythonIncludePath, this + .getClass().getClassLoader()); try { - pendingFile.delete(); - } catch (LocalizationOpFailedException e) { + Map argMap = new HashMap(); + argMap.put("siteID", siteId); + argMap.put("config", config); + script.execute("runFromJava", argMap); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error executing sendTCV.", e); } + + script.dispose(); + + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Unable to instantiate sendTCV python script object.", e); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/notification/gfe-watch.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/notification/gfe-watch.xml index de7071949d..086cbadb25 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/notification/gfe-watch.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/notification/gfe-watch.xml @@ -21,7 +21,7 @@ - + diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/JsonSupport.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/JsonSupport.py index f6ba5bf5c7..35dee4fd6c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/JsonSupport.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/JsonSupport.py @@ -25,22 +25,22 @@ # # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- -# 11/10/14 randerso Initial Creation. +# 11/10/2014 randerso Initial Creation. +# 12/08/2014 #4953 randerso Updated for changes to LocalizationSupport ## import json import LocalizationSupport - import JUtil def loadFromJson(localizationType, siteID, fileName): - jsonString = LocalizationSupport.readFile(localizationType, siteID, fileName) + jsonString = LocalizationSupport.readFile(localizationType, LocalizationSupport.SITE, siteID, fileName) object = json.loads(jsonString) return object def saveToJson(localizationType, siteID, fileName, object): jsonString = json.dumps(object, sort_keys=True, indent=4, separators=(',', ': ')) - LocalizationSupport.writeFile(localizationType, siteID, fileName, jsonString) + LocalizationSupport.writeFile(localizationType, LocalizationSupport.SITE, siteID, fileName, jsonString) def loadJsonFromJava(localizationType, siteID, fileName): object = loadFromJson(localizationType, siteID, fileName) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/LocalizationSupport.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/LocalizationSupport.py index a714adc48a..5bca27558b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/LocalizationSupport.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/python/gfe/LocalizationSupport.py @@ -24,33 +24,50 @@ # # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- -# 11/10/14 randerso Initial Creation. +# 11/10/2014 randerso Initial Creation. +# 12/08/2014 #4953 randerso Made for generic allowing specification of LocalizationLevel +# Re-exported Java enums for easier use. ## from LockingFile import File from com.raytheon.uf.common.localization import PathManagerFactory +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationLevel as LocalizationLevel -def __getLocalizationFile(loctype, site, filename): +EDEX_STATIC = LocalizationType.EDEX_STATIC +CAVE_STATIC = LocalizationType.CAVE_STATIC +CAVE_CONFIG = LocalizationType.CAVE_CONFIG +COMMON_STATIC = LocalizationType.COMMON_STATIC + +BASE = LocalizationLevel.BASE +REGION = LocalizationLevel.REGION +CONFIGURED = LocalizationLevel.CONFIGURED +SITE = LocalizationLevel.SITE +WORKSTATION = LocalizationLevel.WORKSTATION +USER = LocalizationLevel.USER + +def getLocalizationFile(loctype, loclevel, contextname, filename): pathManager = PathManagerFactory.getPathManager() - context = pathManager.getContextForSite(loctype, site) + context = pathManager.getContext(loctype, loclevel) + context.setContextName(contextname) localizationFile = pathManager.getLocalizationFile(context, filename) return localizationFile -def readFile(loctype, site, filename): - localizationFile = __getLocalizationFile(loctype, site, filename) +def readFile(loctype, loclevel, contextname, filename): + localizationFile = getLocalizationFile(loctype, loclevel, contextname, filename) with File(localizationFile.getFile(), filename, 'r') as pythonFile: fileContents = pythonFile.read() return fileContents -def writeFile(loctype, site, filename, contents): - localizationFile = __getLocalizationFile(loctype, site, filename) +def writeFile(loctype, loclevel, contextname, filename, contents): + localizationFile = getLocalizationFile(loctype, loclevel, contextname, filename) with File(localizationFile.getFile(), filename, 'w') as pythonFile: pythonFile.write(contents) localizationFile.save() -def deleteFile(loctype, site, filename): - localizationFile = __getLocalizationFile(loctype, site, filename) +def deleteFile(loctype, loclevel, contextname, filename): + localizationFile = getLocalizationFile(loctype, loclevel, contextname, filename) localizationFile.delete() \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/doConfig.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/doConfig.py index 34a46ad251..8031d7800f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/doConfig.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/doConfig.py @@ -1,26 +1,26 @@ ## # 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 +# 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 -# +# 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. ## # doConfig - validate and convert serverConfig into simple Java objects # -# this file was originally config.py -# it was renamed to avoid a conflict with jep's built-in config module +# this file was originally config.py +# it was renamed to avoid a conflict with jep's built-in config module # # ---------------------------------------------------------------------------- # @@ -35,37 +35,37 @@ # 11/18/2014 #4953 randerso Added check for empty unit string # ######################################################################## -import types - -from java.util import ArrayList,LinkedHashMap -from java.lang import Integer,Float -from com.vividsolutions.jts.geom import Coordinate -from java.awt import Point - -Databases = {} -Projections = {} -DiscreteDef = LinkedHashMap() #from parseKeys() - -# Check a python sequence to see that -# it matches the format. -# data: is a sequence of objects -# fmt : is a parallel sequence of type objects -# message : optional message to print on exception -# -# Returns data. -# If len(data) != len(fmt) -# or the type of each element in data does not -# match the coresponding type in fmt, then -# a TypeError is raised. -# Example: a, b = check(([1, 3], "foo"), (list, str)) -def check(data, fmt, message, allData = None): - if len(data) != len(fmt): - m = message + ": Wrong number of items found, " + \ - "Expected " + `len(fmt)` + ", got " + `len(data)` + \ - " Input: " + `data` - if allData is not None: - m = m + ' All: ' + `allData` - raise AssertionError, m +import types + +from java.util import ArrayList,LinkedHashMap +from java.lang import Integer,Float +from com.vividsolutions.jts.geom import Coordinate +from java.awt import Point + +Databases = {} +Projections = {} +DiscreteDef = LinkedHashMap() #from parseKeys() + +# Check a python sequence to see that +# it matches the format. +# data: is a sequence of objects +# fmt : is a parallel sequence of type objects +# message : optional message to print on exception +# +# Returns data. +# If len(data) != len(fmt) +# or the type of each element in data does not +# match the coresponding type in fmt, then +# a TypeError is raised. +# Example: a, b = check(([1, 3], "foo"), (list, str)) +def check(data, fmt, message, allData = None): + if len(data) != len(fmt): + m = message + ": Wrong number of items found, " + \ + "Expected " + `len(fmt)` + ", got " + `len(data)` + \ + " Input: " + `data` + if allData is not None: + m = m + ' All: ' + `allData` + raise AssertionError, m for i in xrange(len(data)): obj = data[i] if hasattr(obj, "jclassname"): @@ -73,328 +73,328 @@ def check(data, fmt, message, allData = None): else: t = type(obj) - if t != fmt[i]: - m = message + ": Wrong data type found, " + \ - "Expected " + `fmt[i]` + ", got " + `t` + \ - " for position #" + `i+1` + " Input: " + `data` - if allData is not None: - m = m + ' All: ' + `allData` - raise AssertionError, m - return data - -# dictionary check, keys are strings, values/subvalues as specified -def dictCheck(dictionary, value, subvalue, configName): - map = LinkedHashMap() - if type(dictionary) == dict: - for k in dictionary.keys(): - if type(k) != str: - raise TypeError, configName + " key [" + `k` + "] not a str" - l = dictionary[k] - if type(l) != value: - raise TypeError, configName + " value [" + `l` + "] not a " \ - + `value` - if value == list or value == tuple: - n = ArrayList() - for m in l: - if type(m) != subvalue: - raise TypeError, configName + " value [" + `l` \ - + "] isn't a " + `subvalue` + ": " + `m` - elif subvalue == int: - n.add(Integer(m)) - elif subvalue == float: - n.add(Float(m)) - else: - n.add(m) - map.put(k, n) - else: - if value == int: - map.put(k,Integer(l)) - elif value == float: - map.put(k,Float(l)) - else: - map.put(k, l) - else: - raise TypeError, configName + " not a dict:" + `dictionary` - return map - -def getWx(wxtypes, wxvisibilities): - from com.raytheon.uf.common.dataplugin.gfe.weather import WeatherCoverage, WeatherIntensity, WeatherAttribute - from com.raytheon.edex.plugin.gfe.config import SimpleWeatherTypeConfig - types = ArrayList() - for t in wxtypes: - symbol, description, cov, inten, attr = \ - check(t, (str, str, list, list, list), "Error in WeatherType") - coverages = ArrayList() - intensities = ArrayList() - attributes = ArrayList() - for c in cov: - csym, cdes = check(c, (str, str), "Error in Weather Coverage", t) - coverages.add(WeatherCoverage(csym, cdes)) - for i in inten: - isym, ides = check(i, (str, str), "Error in Weather Intensity", t) - intensities.add(WeatherIntensity(isym, ides)) - for a in attr: - asym, ades = check(a, (str, str), "Error in Weather Attributes", t) - attributes.add(WeatherAttribute(asym, ades)) - - types.add(SimpleWeatherTypeConfig(symbol, description, coverages, - intensities, attributes)) - vis = ArrayList() - for v in wxvisibilities: - vis.add(v) - return (vis, types) - -#note that DiscreteDef is a dictionary that contains the following -#coded strings: ['OVERLAPS', 'AuxLength', sym1, des1, sym2, des2, ....] -#We do this to pass to C++ as a InitDict, which -#is a Dict. -def parseKeys(name, overlaps, auxLength, keys): - if not DiscreteDef.containsKey(name): - ts = ArrayList() - if overlaps: - ts.add("OVERLAPS") - else: - ts.add("MUTEXC") - ts.add(`auxLength`) - for symdes in keys: - sym, des = check(symdes, (str, str), - "Error in DiscreteKey Definition", keys) - ts.add(sym) - ts.add(des) - if overlaps and len(keys) > 0 and keys[0][0] != "": - s = "1st discrete key must be for OVERLAP-defined " +\ - "weather element. [" + name + "]" + `keys` - raise Exception, s - DiscreteDef.put(name, ts); - -def createParm(parminfo, domain, tc): - from com.raytheon.edex.plugin.gfe.config import SimpleGridParmConfig - - m = "Format Error in Weather Element Definition" - if len(parminfo) < 2: - raise TypeError, m + ': ' + `parminfo` - - dim, origin, extent, timezone, projection,officeType = domain - - if parminfo[1] == 'Scalar' or parminfo[1] == 'Vector': - parmInfoFmt = (str, str, str, str, float, float, int, int) - name, type, units, description, max, min, precision, \ - rateParm = check(parminfo, parmInfoFmt, m) - - elif parminfo[1] == 'Weather': - name, type, units, description = \ - check(parminfo, (str, str, str, str), m) - max = 0 - min = 0 - precision = 0 - rateParm = False - - elif parminfo[1] == 'Discrete': - if len(parminfo) == 6: - parmInfoFmt = (str, str, str, str, int, list) - name, type, units, description, overlaps, keys = \ - check(parminfo, parmInfoFmt, m) - auxSize = 0 - else: - parmInfoFmt = (str, str, str, str, int, list, int) - name, type, units, description, overlaps, keys, auxSize = \ - check(parminfo, parmInfoFmt, m) - max = 0.0 - min = 0.0 - precision = 0 - rateParm = False - parseKeys(name, overlaps, auxSize, keys) - - else: - raise Exception, "Illegal WE type specified for " + `parminfo[0]` - - #don't add parms with your own office type in the name. - if name.find(officeType) != -1: + if t != fmt[i]: + m = message + ": Wrong data type found, " + \ + "Expected " + `fmt[i]` + ", got " + `t` + \ + " for position #" + `i+1` + " Input: " + `data` + if allData is not None: + m = m + ' All: ' + `allData` + raise AssertionError, m + return data + +# dictionary check, keys are strings, values/subvalues as specified +def dictCheck(dictionary, value, subvalue, configName): + map = LinkedHashMap() + if type(dictionary) == dict: + for k in dictionary.keys(): + if type(k) != str: + raise TypeError, configName + " key [" + `k` + "] not a str" + l = dictionary[k] + if type(l) != value: + raise TypeError, configName + " value [" + `l` + "] not a " \ + + `value` + if value == list or value == tuple: + n = ArrayList() + for m in l: + if type(m) != subvalue: + raise TypeError, configName + " value [" + `l` \ + + "] isn't a " + `subvalue` + ": " + `m` + elif subvalue == int: + n.add(Integer(m)) + elif subvalue == float: + n.add(Float(m)) + else: + n.add(m) + map.put(k, n) + else: + if value == int: + map.put(k,Integer(l)) + elif value == float: + map.put(k,Float(l)) + else: + map.put(k, l) + else: + raise TypeError, configName + " not a dict:" + `dictionary` + return map + +def getWx(wxtypes, wxvisibilities): + from com.raytheon.uf.common.dataplugin.gfe.weather import WeatherCoverage, WeatherIntensity, WeatherAttribute + from com.raytheon.edex.plugin.gfe.config import SimpleWeatherTypeConfig + types = ArrayList() + for t in wxtypes: + symbol, description, cov, inten, attr = \ + check(t, (str, str, list, list, list), "Error in WeatherType") + coverages = ArrayList() + intensities = ArrayList() + attributes = ArrayList() + for c in cov: + csym, cdes = check(c, (str, str), "Error in Weather Coverage", t) + coverages.add(WeatherCoverage(csym, cdes)) + for i in inten: + isym, ides = check(i, (str, str), "Error in Weather Intensity", t) + intensities.add(WeatherIntensity(isym, ides)) + for a in attr: + asym, ades = check(a, (str, str), "Error in Weather Attributes", t) + attributes.add(WeatherAttribute(asym, ades)) + + types.add(SimpleWeatherTypeConfig(symbol, description, coverages, + intensities, attributes)) + vis = ArrayList() + for v in wxvisibilities: + vis.add(v) + return (vis, types) + +#note that DiscreteDef is a dictionary that contains the following +#coded strings: ['OVERLAPS', 'AuxLength', sym1, des1, sym2, des2, ....] +#We do this to pass to C++ as a InitDict, which +#is a Dict. +def parseKeys(name, overlaps, auxLength, keys): + if not DiscreteDef.containsKey(name): + ts = ArrayList() + if overlaps: + ts.add("OVERLAPS") + else: + ts.add("MUTEXC") + ts.add(`auxLength`) + for symdes in keys: + sym, des = check(symdes, (str, str), + "Error in DiscreteKey Definition", keys) + ts.add(sym) + ts.add(des) + if overlaps and len(keys) > 0 and keys[0][0] != "": + s = "1st discrete key must be for OVERLAP-defined " +\ + "weather element. [" + name + "]" + `keys` + raise Exception, s + DiscreteDef.put(name, ts); + +def createParm(parminfo, domain, tc): + from com.raytheon.edex.plugin.gfe.config import SimpleGridParmConfig + + m = "Format Error in Weather Element Definition" + if len(parminfo) < 2: + raise TypeError, m + ': ' + `parminfo` + + dim, origin, extent, timezone, projection,officeType = domain + + if parminfo[1] == 'Scalar' or parminfo[1] == 'Vector': + parmInfoFmt = (str, str, str, str, float, float, int, int) + name, type, units, description, max, min, precision, \ + rateParm = check(parminfo, parmInfoFmt, m) + + elif parminfo[1] == 'Weather': + name, type, units, description = \ + check(parminfo, (str, str, str, str), m) + max = 0 + min = 0 + precision = 0 + rateParm = False + + elif parminfo[1] == 'Discrete': + if len(parminfo) == 6: + parmInfoFmt = (str, str, str, str, int, list) + name, type, units, description, overlaps, keys = \ + check(parminfo, parmInfoFmt, m) + auxSize = 0 + else: + parmInfoFmt = (str, str, str, str, int, list, int) + name, type, units, description, overlaps, keys, auxSize = \ + check(parminfo, parmInfoFmt, m) + max = 0.0 + min = 0.0 + precision = 0 + rateParm = False + parseKeys(name, overlaps, auxSize, keys) + + else: + raise Exception, "Illegal WE type specified for " + `parminfo[0]` + + #don't add parms with your own office type in the name. + if name.find(officeType) != -1: return None #skip this one if len(units) == 0: - raise Exception, 'Unit string must not be empty. For unitless quantities enter "1"' - - updateProjections(projection) - start, repeat, duration = tc - timeIndependentParm = (repeat == 0 and duration == 0) - -# return WeatherElement(name, type, units, description, max, min, -# precision, timeIndependentParm, dim, origin, -# extent, start, repeat, duration, rateParm) - return SimpleGridParmConfig(name, type, units, description, 1.0*max, 1.0*min, - precision, timeIndependentParm, Point(dim[0], dim[1]), Coordinate(origin[0], origin[1]), - Coordinate(extent[0], extent[1]), start, repeat, duration, rateParm) - -def getDB(site, projID, dbinfo): - from com.raytheon.edex.plugin.gfe.config import SimpleModelConfig - - dbinfoFmt = (str, str, str, int, int, int, int) - name, format, type, single, official, numVer, purgeAge = \ - check(dbinfo, dbinfoFmt, "Error in Database Attribute Definition") - - if not Databases.has_key(name+type): - Databases[name+type] = SimpleModelConfig(site, format, type, name, projID, - single, official, numVer, purgeAge) - - return Databases[name+type] - -def parseDBItm(site, domain, item): -# import serverConfig -# domain = serverConfig.SITES[site] - - dbinfo, parminfo = check(item, (tuple, list), - "Database Definition or Parm Group Format Error") - projID = domain[4][0] - - db = getDB(site, projID, dbinfo) - grids = db.grids - for ptc in parminfo: - parms, tc = check(ptc, (list, tuple), - "Parm Group/Time Constraint Tuple Error") - check(tc, (int, int, int), "Time Constraint Format Error", ptc) - for parm in parms: - grids.add(createParm(parm, domain, tc)) - db.grids = grids - -def updateProjections(projection): - from com.raytheon.uf.common.dataplugin.gfe.config import ProjectionData - # extract projection data + raise Exception, 'Unit string must not be empty. For unitless quantities enter "1"' + + updateProjections(projection) + start, repeat, duration = tc + timeIndependentParm = (repeat == 0 and duration == 0) + +# return WeatherElement(name, type, units, description, max, min, +# precision, timeIndependentParm, dim, origin, +# extent, start, repeat, duration, rateParm) + return SimpleGridParmConfig(name, type, units, description, 1.0*max, 1.0*min, + precision, timeIndependentParm, Point(dim[0], dim[1]), Coordinate(origin[0], origin[1]), + Coordinate(extent[0], extent[1]), start, repeat, duration, rateParm) + +def getDB(site, projID, dbinfo): + from com.raytheon.edex.plugin.gfe.config import SimpleModelConfig + + dbinfoFmt = (str, str, str, int, int, int, int) + name, format, type, single, official, numVer, purgeAge = \ + check(dbinfo, dbinfoFmt, "Error in Database Attribute Definition") + + if not Databases.has_key(name+type): + Databases[name+type] = SimpleModelConfig(site, format, type, name, projID, + single, official, numVer, purgeAge) + + return Databases[name+type] + +def parseDBItm(site, domain, item): +# import serverConfig +# domain = serverConfig.SITES[site] + + dbinfo, parminfo = check(item, (tuple, list), + "Database Definition or Parm Group Format Error") + projID = domain[4][0] + + db = getDB(site, projID, dbinfo) + grids = db.grids + for ptc in parminfo: + parms, tc = check(ptc, (list, tuple), + "Parm Group/Time Constraint Tuple Error") + check(tc, (int, int, int), "Time Constraint Format Error", ptc) + for parm in parms: + grids.add(createParm(parm, domain, tc)) + db.grids = grids + +def updateProjections(projection): + from com.raytheon.uf.common.dataplugin.gfe.config import ProjectionData + # extract projection data projFmt = (str, "com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData$ProjectionType", - tuple, tuple, tuple, float, float, tuple, tuple, float, float, float) - projID, ptype, pllll, pllur, pllo, pspo, pspt, pgpll, pgpur, pli, \ - plc, plo = check(projection, projFmt, "Format error in Projection") - check(pllll, (float, float), - "Format error lower left long/lat in Projection", projection) - check(pllur, (float, float), - "Format error upper right long/lat in Projection", projection) - check(pllo, (float, float), - "Format error long/lat origin in Projection", projection) - check(pgpll, (int, int), - "Format error lower left grid point in Projection", projection) - check(pgpur, (int, int), - "Format error upper right grid point in Projection", projection) - - if not Projections.has_key(projID): - Projections[projID] = ProjectionData(projID, ptype, - Coordinate(pllll[0],pllll[1]), - Coordinate(pllur[0],pllur[1]), - Coordinate(pllo[0],pllo[1]), - pspo, pspt, - Point(pgpll[0], pgpll[1]), - Point(pgpur[0], pgpur[1]), - pli, plc, plo) - -def parseGridLocation(domain): - from com.raytheon.edex.plugin.gfe.config import SimpleGridLocation - - #if office type is present: - if len(domain) == 6: - domainFmt = (list,tuple,tuple,str,tuple,str) - gridSize, origin, extent, tz, proj, officeType = check(domain, domainFmt, "Format error in SITES line") - #if office type is not present: - else: - domainFmt = (list, tuple, tuple, str, tuple) - gridSize, origin, extent, tz, proj = check(domain, domainFmt, - "Format error in SITES line") - check(gridSize, (int, int), "GridSize format error from SITES", domain) - check(origin, (float, float), "Origin format error from SITES", domain) - check(extent, (float, float), "Extent format error from SITES", domain) - + tuple, tuple, tuple, float, float, tuple, tuple, float, float, float) + projID, ptype, pllll, pllur, pllo, pspo, pspt, pgpll, pgpur, pli, \ + plc, plo = check(projection, projFmt, "Format error in Projection") + check(pllll, (float, float), + "Format error lower left long/lat in Projection", projection) + check(pllur, (float, float), + "Format error upper right long/lat in Projection", projection) + check(pllo, (float, float), + "Format error long/lat origin in Projection", projection) + check(pgpll, (int, int), + "Format error lower left grid point in Projection", projection) + check(pgpur, (int, int), + "Format error upper right grid point in Projection", projection) + + if not Projections.has_key(projID): + Projections[projID] = ProjectionData(projID, ptype, + Coordinate(pllll[0],pllll[1]), + Coordinate(pllur[0],pllur[1]), + Coordinate(pllo[0],pllo[1]), + pspo, pspt, + Point(pgpll[0], pgpll[1]), + Point(pgpur[0], pgpur[1]), + pli, plc, plo) + +def parseGridLocation(domain): + from com.raytheon.edex.plugin.gfe.config import SimpleGridLocation + + #if office type is present: + if len(domain) == 6: + domainFmt = (list,tuple,tuple,str,tuple,str) + gridSize, origin, extent, tz, proj, officeType = check(domain, domainFmt, "Format error in SITES line") + #if office type is not present: + else: + domainFmt = (list, tuple, tuple, str, tuple) + gridSize, origin, extent, tz, proj = check(domain, domainFmt, + "Format error in SITES line") + check(gridSize, (int, int), "GridSize format error from SITES", domain) + check(origin, (float, float), "Origin format error from SITES", domain) + check(extent, (float, float), "Extent format error from SITES", domain) + projFmt = (str, "com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData$ProjectionType", - tuple, tuple, tuple, float, float, tuple, tuple, float, float, float) - projID, projType, llll, llur, llo, sp1, sp2, gpll, gpur, li, lc, lo = \ - check(proj, projFmt, "Format error in Projection") - check(llll, (float, float), - "Format error lower left long/lat in Projection", proj) - check(llur, (float, float), - "Format error upper right long/lat in Projection", proj) - check(llo, (float, float), - "Format error long/lat origin in Projection", proj) - check(gpll, (int, int), - "Format error lower left grid point in Projection", proj) - check(gpur, (int, int), - "Format error upper right grid point in Projection", proj) - - gloc = SimpleGridLocation(Point(gridSize[0], gridSize[1]), - Coordinate(origin[0], origin[1]), - Coordinate(extent[0], extent[1]), - projID, projType, - Coordinate(llll[0], llll[1]), - Coordinate(llur[0], llur[1]), - Coordinate(llo[0], llo[1]), - sp1, sp2, - Point(gpll[0], gpll[1]), - Point(gpur[0], gpur[1]), - li, lc, lo) - return gloc - -def parse(site, databases, wxtypes, wxvisibilities, allSites, inProjections): - from com.raytheon.edex.plugin.gfe.config import SimpleGridLocation - domain = parseGridLocation(allSites[site]) - for itm in databases: - parseDBItm(site, allSites[site], itm) - - if type(wxtypes) != list: - raise TypeError, "Format Error in WeatherTypes, not a list: " \ - + `wxtypes` - if type(wxvisibilities) != list: - raise TypeError, "Format Error in visibilities, not a list: " \ - + `wxvisibilities` - vis, types = getWx(wxtypes, wxvisibilities) - - models = ArrayList() - for key in Databases.keys(): - models.add(Databases[key]) - - projections = ArrayList() - if type(inProjections) != list: - raise TypeError, "Format Error in Projections, not a list: " \ - + `inProjections` - for p in inProjections: - updateProjections(p) - for key in Projections.keys(): - projections.add(Projections[key]) - - allSiteIDs = ArrayList() - allOfficeTypes = ArrayList() - for key in allSites.keys(): - allSiteIDs.add(key) - try: - ot = allSites[key][5] - if type(ot) != str: - raise TypeError, "Format Error in office type, not a str:",allSites[key] - except: - ot = "wfo" #assumes wfo if not present - allOfficeTypes.add(ot) - - siteId = ArrayList() - siteId.add(site) - - timeZone = ArrayList() - timeZone.add(allSites[site][3]) - - return models, projections, vis, types, DiscreteDef, allSiteIDs, domain, siteId, timeZone, allOfficeTypes - -def d2dParse(d2dmodels): - dict = LinkedHashMap() - for entry in d2dmodels: - if type(entry) is types.TupleType: - d2dModelName, gfeModelName = check(entry, (str, str), - "Format error in D2DMODELS entry", d2dmodels) - - dict.put(d2dModelName, gfeModelName) - - elif type(entry) is types.StringType: - d2dModelName = entry - dict.put(d2dModelName, d2dModelName) - - else: - raise SyntaxError, "Invalid syntax for D2DMODELS" + `d2dmodels` - - return dict + tuple, tuple, tuple, float, float, tuple, tuple, float, float, float) + projID, projType, llll, llur, llo, sp1, sp2, gpll, gpur, li, lc, lo = \ + check(proj, projFmt, "Format error in Projection") + check(llll, (float, float), + "Format error lower left long/lat in Projection", proj) + check(llur, (float, float), + "Format error upper right long/lat in Projection", proj) + check(llo, (float, float), + "Format error long/lat origin in Projection", proj) + check(gpll, (int, int), + "Format error lower left grid point in Projection", proj) + check(gpur, (int, int), + "Format error upper right grid point in Projection", proj) + + gloc = SimpleGridLocation(Point(gridSize[0], gridSize[1]), + Coordinate(origin[0], origin[1]), + Coordinate(extent[0], extent[1]), + projID, projType, + Coordinate(llll[0], llll[1]), + Coordinate(llur[0], llur[1]), + Coordinate(llo[0], llo[1]), + sp1, sp2, + Point(gpll[0], gpll[1]), + Point(gpur[0], gpur[1]), + li, lc, lo) + return gloc + +def parse(site, databases, wxtypes, wxvisibilities, allSites, inProjections): + from com.raytheon.edex.plugin.gfe.config import SimpleGridLocation + domain = parseGridLocation(allSites[site]) + for itm in databases: + parseDBItm(site, allSites[site], itm) + + if type(wxtypes) != list: + raise TypeError, "Format Error in WeatherTypes, not a list: " \ + + `wxtypes` + if type(wxvisibilities) != list: + raise TypeError, "Format Error in visibilities, not a list: " \ + + `wxvisibilities` + vis, types = getWx(wxtypes, wxvisibilities) + + models = ArrayList() + for key in Databases.keys(): + models.add(Databases[key]) + + projections = ArrayList() + if type(inProjections) != list: + raise TypeError, "Format Error in Projections, not a list: " \ + + `inProjections` + for p in inProjections: + updateProjections(p) + for key in Projections.keys(): + projections.add(Projections[key]) + + allSiteIDs = ArrayList() + allOfficeTypes = ArrayList() + for key in allSites.keys(): + allSiteIDs.add(key) + try: + ot = allSites[key][5] + if type(ot) != str: + raise TypeError, "Format Error in office type, not a str:",allSites[key] + except: + ot = "wfo" #assumes wfo if not present + allOfficeTypes.add(ot) + + siteId = ArrayList() + siteId.add(site) + + timeZone = ArrayList() + timeZone.add(allSites[site][3]) + + return models, projections, vis, types, DiscreteDef, allSiteIDs, domain, siteId, timeZone, allOfficeTypes + +def d2dParse(d2dmodels): + dict = LinkedHashMap() + for entry in d2dmodels: + if type(entry) is types.TupleType: + d2dModelName, gfeModelName = check(entry, (str, str), + "Format error in D2DMODELS entry", d2dmodels) + + dict.put(d2dModelName, gfeModelName) + + elif type(entry) is types.StringType: + d2dModelName = entry + dict.put(d2dModelName, d2dModelName) + + else: + raise SyntaxError, "Invalid syntax for D2DMODELS" + `d2dmodels` + + return dict def netcdfParse(netcdfDirs): dict = LinkedHashMap() @@ -417,139 +417,107 @@ def netcdfParse(netcdfDirs): raise SyntaxError, "Invalid syntax for NETCDFDIRS" + `netcdfDirs` return dict - -def parseSat(satdata): - rval = LinkedHashMap() - for e in satdata: - if type(e) is types.TupleType: - direct, name = check(e, (str, str), - "Format error in SATDATA entry", satdata) - rval.put(direct, name) - else: - raise SyntaxError, "Invalid syntax for SATDATA" + `satdata` - return rval - -def otherParse(serverhost, mhsid, port, - initmodules, accumElem, - initskips, d2ddbver, logfilepurge, prddir, home, - extraWEPrec, vtecRequestTime, autoConfigureNotifyTextProd, - iscRoutingTableAddress, requestedISCsites, requestISC, sendiscOnSave, - sendiscOnPublish, requestedISCparms, transmitScript): - if type(serverhost) != str: - raise TypeError, "GFESUITE_HOST not an str: " + `serverhost` - if type(mhsid) != str: - raise TypeError, "GFESUITE_MHSID not an str: " + `mhsid` + +def parseSat(satdata): + rval = LinkedHashMap() + for e in satdata: + if type(e) is types.TupleType: + direct, name = check(e, (str, str), + "Format error in SATDATA entry", satdata) + rval.put(direct, name) + else: + raise SyntaxError, "Invalid syntax for SATDATA" + `satdata` + return rval + +def otherParse(serverhost, mhsid, port, + initmodules, accumElem, + initskips, d2ddbver, logfilepurge, prddir, home, + extraWEPrec, vtecRequestTime, autoConfigureNotifyTextProd, + iscRoutingTableAddress, requestedISCsites, requestISC, sendiscOnSave, + sendiscOnPublish, requestedISCparms, transmitScript): + if type(serverhost) != str: + raise TypeError, "GFESUITE_HOST not an str: " + `serverhost` + if type(mhsid) != str: + raise TypeError, "GFESUITE_MHSID not an str: " + `mhsid` if type(vtecRequestTime) != int: raise TypeError, "VTECPartners: VTEC_REMOTE_TABLE_FETCH_TIME " + \ - "not an int: " + `vtecRequestTime` - if type(port) != int: - raise TypeError, "GFESUITE_PORT not an int: " + `port` - javainitmodules = dictCheck(initmodules, list, str, "INITMODULES") - accumElem = dictCheck(accumElem, list, str, "D2DAccumulativeElements") - initskips = dictCheck(initskips, list, int, "INITSKIPS") - d2ddbver = dictCheck(d2ddbver, int, None, "D2DDBVERSIONS") - if type(logfilepurge) != int: - raise TypeError, "LOG_FILE_PURGE_AFTER not an int: " + `logfilepurge` - if type(autoConfigureNotifyTextProd) != int: - raise TypeError, "AUTO_CONFIGURE_NOTIFYTEXTPROD not an int: " + \ - `logfilepurge` - if type(prddir) != str: - raise TypeError, "GFESUITE_PRDDIR not an str: " + `prddir` - if type(home) != str: - raise TypeError, "GFESUITE_HOME not an str: " + `home` - if type(extraWEPrec) != list: - raise TypeError, "ExtraWEPrec not an list: " + `extraWEPrec` - else: - extraWEPrecision = LinkedHashMap() - for e in extraWEPrec: - if type(e) == str: - extraWEPrecision.put(e, Integer(1)) - elif type(e) == tuple and len(e) == 2 and type(e[0]) == str and \ - type(e[1]) == int: - extraWEPrecision.put(e[0], Integer(e[1])) - else: - raise TypeError, \ - "Entry in ExtraWEPrec not str or (str, int): " + `e` - - iscRoutingTableAddress = dictCheck(iscRoutingTableAddress,str,str,"ISC_ROUTING_TABLE_ADDRESS") - #if type(iscRoutingTableAddress) not in [str, types.NoneType]: - # raise TypeError, "ISC_ROUTING_TABLE_ADDRESS not None or a str: " + \ - # `iscRoutingTableAddress` - #elif iscRoutingTableAddress is None: - # iscRoutingTableAddress = "" - - reqISCsites = ArrayList() - if type(requestedISCsites) not in [list, types.NoneType]: - raise TypeError, "REQUESTED_ISC_SITES not None or a list: " + \ - `requestedISCsites` - elif type(requestedISCsites) is list: - for r in requestedISCsites: - if type(r) != str: - raise TypeError, "REQUESTED_ISC_SITES not list of strings: " + \ - `requestedISCsites` - else: - reqISCsites.add(r); - - reqISCparms = ArrayList() - if type(requestedISCparms) not in [list, types.NoneType]: - raise TypeError, "REQUESTED_ISC_PARMS not None or a list: " + \ - `requestedISCparms` - elif type(requestedISCparms) is list: - for r in requestedISCparms: - if type(r) != str: - raise TypeError, "REQUESTED_ISC_PARMS not list of strings: " + \ - `requestedISCparms` - else: - reqISCparms.add(r) - - if type(requestISC) != int: - raise TypeError, "REQUEST_ISC not an int: " + `requestISC` - if type(sendiscOnSave) != int: - raise TypeError, "SEND_ISC_ON_SAVE not an int: " + `sendiscOnSave` - if type(sendiscOnPublish) != int: - raise TypeError, "SEND_ISC_ON_PUBLISH not an int: " + `sendiscOnPublish` - - if type(transmitScript) not in [str, types.NoneType]: - raise TypeError, "TRANSMIT_SCRIPT not None or str: " + `transmitScript` - elif transmitScript is None: - transmitScript = "" - - # build model to init mapping - modelToInit = {} - for module in initmodules: - for model in initmodules[module]: - if modelToInit.has_key(model): - modelToInit[model].append(module) + "not an int: " + `vtecRequestTime` + if type(port) != int: + raise TypeError, "GFESUITE_PORT not an int: " + `port` + initmodules = dictCheck(initmodules, list, str, "INITMODULES") + accumElem = dictCheck(accumElem, list, str, "D2DAccumulativeElements") + initskips = dictCheck(initskips, list, int, "INITSKIPS") + d2ddbver = dictCheck(d2ddbver, int, None, "D2DDBVERSIONS") + if type(logfilepurge) != int: + raise TypeError, "LOG_FILE_PURGE_AFTER not an int: " + `logfilepurge` + if type(autoConfigureNotifyTextProd) != int: + raise TypeError, "AUTO_CONFIGURE_NOTIFYTEXTPROD not an int: " + \ + `logfilepurge` + if type(prddir) != str: + raise TypeError, "GFESUITE_PRDDIR not an str: " + `prddir` + if type(home) != str: + raise TypeError, "GFESUITE_HOME not an str: " + `home` + if type(extraWEPrec) != list: + raise TypeError, "ExtraWEPrec not an list: " + `extraWEPrec` + else: + extraWEPrecision = LinkedHashMap() + for e in extraWEPrec: + if type(e) == str: + extraWEPrecision.put(e, Integer(1)) + elif type(e) == tuple and len(e) == 2 and type(e[0]) == str and \ + type(e[1]) == int: + extraWEPrecision.put(e[0], Integer(e[1])) else: - modelToInit[model] = [module] - - # check for duplicate init modules - for model in modelToInit: - modules = modelToInit[model] - if len(modules) > 1: - message = "Multiple smartInit modules " + str(modules) + \ - " are enabled for D2D model: " + model + ". " + str(modules[1:]) + \ - " will be disabled. Please edit your localConfig.py file and disable all but one." + raise TypeError, \ + "Entry in ExtraWEPrec not str or (str, int): " + `e` - # log error message to edex log - import LogStream - LogStream.logProblem(message); - - # log error to alertViz - from com.raytheon.uf.edex.core import EDEXUtil - from com.raytheon.uf.common.status import UFStatus_Priority as Priority - EDEXUtil.sendMessageAlertViz(Priority.ERROR, - "com.raytheon.edex.plugin.gfe", "GFE", "GFE", message, - message, None) + iscRoutingTableAddress = dictCheck(iscRoutingTableAddress,str,str,"ISC_ROUTING_TABLE_ADDRESS") + #if type(iscRoutingTableAddress) not in [str, types.NoneType]: + # raise TypeError, "ISC_ROUTING_TABLE_ADDRESS not None or a str: " + \ + # `iscRoutingTableAddress` + #elif iscRoutingTableAddress is None: + # iscRoutingTableAddress = "" - # remove duplicate - for module in modules[1:]: - javainitmodules.remove(module) - - return serverhost, mhsid, \ - port, javainitmodules, accumElem, \ - initskips, d2ddbver, logfilepurge, prddir, home,\ - extraWEPrecision, vtecRequestTime, \ - autoConfigureNotifyTextProd, \ - iscRoutingTableAddress, reqISCsites, requestISC, sendiscOnSave, \ - sendiscOnPublish, reqISCparms, transmitScript + reqISCsites = ArrayList() + if type(requestedISCsites) not in [list, types.NoneType]: + raise TypeError, "REQUESTED_ISC_SITES not None or a list: " + \ + `requestedISCsites` + elif type(requestedISCsites) is list: + for r in requestedISCsites: + if type(r) != str: + raise TypeError, "REQUESTED_ISC_SITES not list of strings: " + \ + `requestedISCsites` + else: + reqISCsites.add(r); + + reqISCparms = ArrayList() + if type(requestedISCparms) not in [list, types.NoneType]: + raise TypeError, "REQUESTED_ISC_PARMS not None or a list: " + \ + `requestedISCparms` + elif type(requestedISCparms) is list: + for r in requestedISCparms: + if type(r) != str: + raise TypeError, "REQUESTED_ISC_PARMS not list of strings: " + \ + `requestedISCparms` + else: + reqISCparms.add(r) + + if type(requestISC) != int: + raise TypeError, "REQUEST_ISC not an int: " + `requestISC` + if type(sendiscOnSave) != int: + raise TypeError, "SEND_ISC_ON_SAVE not an int: " + `sendiscOnSave` + if type(sendiscOnPublish) != int: + raise TypeError, "SEND_ISC_ON_PUBLISH not an int: " + `sendiscOnPublish` + + if type(transmitScript) not in [str, types.NoneType]: + raise TypeError, "TRANSMIT_SCRIPT not None or str: " + `transmitScript` + elif transmitScript is None: + transmitScript = "" + + return serverhost, mhsid, \ + port, initmodules, accumElem, \ + initskips, d2ddbver, logfilepurge, prddir, home,\ + extraWEPrecision, vtecRequestTime, \ + autoConfigureNotifyTextProd, \ + iscRoutingTableAddress, reqISCsites, requestISC, sendiscOnSave, \ + sendiscOnPublish, reqISCparms, transmitScript diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/createAreaDictionary.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/createAreaDictionary.py index b4772eb55f..5e2ac44812 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/createAreaDictionary.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/createAreaDictionary.py @@ -17,6 +17,17 @@ # See the AWIPS II Master Rights File ("Master Rights File.pdf") for # further licensing information. ## +# +# Create Area Dictionary +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 12/05/14 4953 randerso Changed to use LocalizationSupport +# +## import os, string, copy import tempfile, stat @@ -26,8 +37,7 @@ from fips2cities import * from zones2cities import * from LockingFile import File -from com.raytheon.uf.common.localization import PathManagerFactory -from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType, LocalizationContext_LocalizationLevel as LocalizationLevel +import LocalizationSupport # # Creates area dictionary specific to a site. Somewhat ported from AWIPS-I. @@ -447,25 +457,17 @@ def _getZones(siteID): siteID + ".py" zonesKey = "Zones_" + siteID - editAreasFileContents = _getFileContents(LocalizationType.CAVE_STATIC, - LocalizationLevel.CONFIGURED, - siteID, - editAreasFilename) + editAreasFileContents = LocalizationSupport.readFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.CONFIGURED, + siteID, + editAreasFilename) + + exec(editAreasFileContents) # EASourceMap comes from the EditAreas file return EASourceMap[zonesKey] -def _getFileContents(loctype, loclevel, locname, filename): - pathManager = PathManagerFactory.getPathManager() - context = pathManager.getContext(loctype, loclevel) - context.setContextName(locname) - localizationFile = pathManager.getLocalizationFile(context, filename) - with File(localizationFile.getFile(), filename, 'r') as pythonFile: - fileContents = pythonFile.read() - - return fileContents - def _formatDictionary(dictionary, tabLevel, output=""): TAB = " " * 4 diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtAccess.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtAccess.py index 31f6af9c6b..f4bd7d39e3 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtAccess.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtAccess.py @@ -24,20 +24,27 @@ # # Author: mathewson # ---------------------------------------------------------------------------- - +## # # This class provides interfaces to the ISC Routing Table Web Service. # +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 12/10/14 #4953 randerso Cleaned up imports, +# improved spawning of shell cmd +# +## -import xml from xml.etree import ElementTree from xml.etree.ElementTree import Element, SubElement import socket import urllib, urllib2, time, os, copy, string -import LogStream,JUtil - -import JUtil, iscUtil -from java.util import ArrayList +import LogStream +import JUtil +import iscUtil class IrtAccess(): diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py index da97fae738..9da24db683 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py @@ -20,13 +20,12 @@ import cPickle -import LogStream, tempfile, os, sys, JUtil, subprocess, traceback +import LogStream, tempfile, os, sys, JUtil, subprocess, traceback, errno import time, copy, string, iscUtil from com.raytheon.edex.plugin.gfe.isc import IRTManager - # # Port of IRT functionality from legacy ifpServer # @@ -46,28 +45,31 @@ from com.raytheon.edex.plugin.gfe.isc import IRTManager # makeISCrequest(). # 10/16/13 2475 dgilling Remove unneeded code to handle # registration with IRT. -# -# +# 12/08/2014 4953 randerso Added support for sending/receiving TCV files +# Additional code clean up # +## +PURGE_AGE = 30 * 24 * 60 * 60 # 30 days in seconds +def getLogger(): + import logging + return iscUtil.getLogger("irtServer", logLevel=logging.DEBUG) + def logEvent(*msg): - iscUtil.getLogger("irtServer").info(iscUtil.tupleToString(*msg)) + getLogger().info(iscUtil.tupleToString(*msg)) def logProblem(*msg): - iscUtil.getLogger("irtServer").error(iscUtil.tupleToString(*msg)) + getLogger().error(iscUtil.tupleToString(*msg)) def logException(*msg): - iscUtil.getLogger("irtServer").exception(iscUtil.tupleToString(*msg)) + getLogger().exception(iscUtil.tupleToString(*msg)) -def logVerbose(*msg): - iscUtil.getLogger("irtServer").debug(iscUtil.tupleToString(*msg)) - def logDebug(*msg): - logVerbose(iscUtil.tupleToString(*msg)) + getLogger().debug(iscUtil.tupleToString(*msg)) # called by iscDataRec when another site has requested the active table # returns the active table, filtered, pickled. -def getVTECActiveTable(siteAndFilterInfo, xmlPacket): +def getVTECActiveTable(dataFile, xmlPacket): import siteConfig import VTECPartners @@ -75,7 +77,9 @@ def getVTECActiveTable(siteAndFilterInfo, xmlPacket): return #respond is disabled #decode the data (pickled) - info = cPickle.loads(siteAndFilterInfo) + with open(dataFile, "rb") as fp: + info = cPickle.load(fp) + (mhsSite, reqsite, filterSites, countDict, issueTime) = info #get the active table, and write it to a temporary file @@ -159,8 +163,11 @@ def getVTECActiveTable(siteAndFilterInfo, xmlPacket): #when we receive a requested active table from another site, this function #is called from iscDataRec -def putVTECActiveTable(strTable, xmlPacket): +def putVTECActiveTable(dataFile, xmlPacket): import siteConfig + + with open(dataFile, "rb") as fp: + strTable = fp.read() #write the xmlpacket to a temporary file, if one was passed inDir = os.path.join(siteConfig.GFESUITE_PRDDIR, "ATBL") @@ -188,6 +195,142 @@ def putVTECActiveTable(strTable, xmlPacket): logProblem("Error executing ingestAT: ", traceback.format_exc()) logEvent("ingesAT command output: ", output) +def putTCVFiles(siteID, tarFile): + import LocalizationSupport + import glob + import TCVUtil + + logEvent("Receiving TCV files from " + siteID) + + siteDir = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, + siteID, "gfe").getFile() + siteDir = siteDir.getParentFile().getParentFile().getAbsolutePath() + logDebug("siteDir: "+siteDir) + + try: + tmpDir = tempfile.mkdtemp(dir="/tmp") + logDebug("tmpDir: "+tmpDir) + subprocess.check_call(["cd " + tmpDir + "; tar xvzf " + tarFile], shell=True) + except: + logException('Error untarring TCV files from site: ' + siteID) + raise + + TCVUtil.purgeAllCanFiles(getLogger()) + + # create the new allCAN files + for tmpFile in glob.iglob(os.path.join(tmpDir, "*/gfe/tcvAdvisories/*.allCAN")): + # create tcvDir if necessary + tcvDir = os.path.dirname(tmpFile).replace(tmpDir, siteDir) + logDebug("tcvDir: "+tcvDir) + try: + os.makedirs(tcvDir, 0755) + except OSError, e: + if e.errno != errno.EEXIST: + logProblem("%s: '%s'" % (e.strerror,e.filename)) + + basename = os.path.basename(tmpFile) + stormName = basename.replace(".allCAN", "") + allCanPath = os.path.join(tcvDir, basename) + logDebug("copying "+tmpFile+" to "+allCanPath) + try: + # just create the empty allCan file + with open(allCanPath, 'w'): + pass + except: + logException("Error creating: "+ allCanPath) + + try: + # delete all JSON files starting with stormName + for fn in glob.iglob(os.path.join(tcvDir, stormName + "*.json")): + try: + site = fn.replace(siteDir,"").split("/")[1] + basename = os.path.basename(fn) + logDebug("removing canceled file: ", os.path.join(site, "gfe/tcvAdvisories", basename)) + LocalizationSupport.deleteFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, site, + "gfe/tcvAdvisories/" + basename) + except: + logException("Error removing " + fn) + + + os.remove(tmpFile) + except: + logException("Error removing JSON files for " + stormName) + + # copy in the json files + for tmpFile in glob.iglob(os.path.join(tmpDir, "*/gfe/tcvAdvisories/*.json")): + site = tmpFile.replace(tmpDir,"").split("/")[1] + jsonFile = "gfe/tcvAdvisories/" + os.path.basename(tmpFile) + logDebug("copying "+tmpFile+" to "+jsonFile) + try: + with open(tmpFile, 'r') as tf: + jsonData = tf.read() + LocalizationSupport.writeFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, + site, jsonFile, jsonData) + os.remove(tmpFile) + except: + logException("Error copying JSON file: "+jsonFile) + + # delete tmpDir + try: + for dirpath, dirs, files in os.walk(tmpDir, topdown=False): + os.rmdir(dirpath) + except: + logException("Unable to remove "+ tmpDir) + + +def getTCVFiles(ourMhsID, srcServer, destE): + import IrtAccess + import TCVUtil + import siteConfig + + irt = IrtAccess.IrtAccess("") + localSites = [srcServer['site']] + for addressE in destE: + if addressE.tag != "address": + continue + + destServer = irt.decodeXMLAddress(addressE) + if destServer['mhsid'] == ourMhsID: + localSites.append(destServer['site']) + + + logEvent("Sending TCV files for " + str(localSites) + " to " + srcServer['mhsid']) + + tcvProductsDir = os.path.join(siteConfig.GFESUITE_HOME, "products", "TCV") + + # create tcvProductsDir if necessary + try: + os.makedirs(tcvProductsDir, 0755) + except OSError, e: + if e.errno != errno.EEXIST: + logger.warn("%s: '%s'" % (e.strerror,e.filename)) + + # get temporary file name for packaged TCV files + with tempfile.NamedTemporaryFile(suffix='.sendtcv', dir=tcvProductsDir, delete=False) as fp: + fname = fp.name + + try: + TCVUtil.packageTCVFiles(localSites, fname, getLogger()) + + from xml.etree import ElementTree + from xml.etree.ElementTree import Element, SubElement + iscE = ElementTree.Element('isc') + irt.addSourceXML(iscE, destServer) + irt.addDestinationXML(iscE, [srcServer]) + + # create the XML file + with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd: + fnameXML = fd.name + fd.write(ElementTree.tostring(iscE)) + + # send the files to srcServer + sendMHSMessage("PUT_TCV_FILES", srcServer['mhsid'], [fname, fnameXML]) + except: + logException('Error sending TCV files for ' + str(localSites)) + # get servers direct call for IRT def irtGetServers(ancfURL, bncfURL, iscWfosWanted): import IrtAccess @@ -227,15 +370,22 @@ def makeISCrequest(xmlRequest, gridDims, gridProj, gridBoundBox, mhs, host, port # we need to modify the incoming xmlRequest and add the # and move the into the
- requestTree = ElementTree.ElementTree(ElementTree.XML(xmlRequest)) - requestE = requestTree.getroot() - ElementTree.tostring(requestE) - ourServer = {'mhsid': ServerMHS, 'host': ServerHost, 'port': ServerPort, - 'protocol': ServerProtocol, 'site': ServerSite, - 'area': {'xdim': gridDims[0], 'ydim': gridDims[1]}, - 'domain': {'proj': gridProj, - 'origx': gridBoundBox[0][0], 'origy': gridBoundBox[0][1], - 'extx': gridBoundBox[1][0], 'exty': gridBoundBox[1][1]}} + requestE = ElementTree.fromstring(xmlRequest) + ourServer = {'mhsid': ServerMHS, + 'host': ServerHost, + 'port': ServerPort, + 'protocol': ServerProtocol, + 'site': ServerSite, + 'area': {'xdim': gridDims[0], + 'ydim': gridDims[1] + }, + 'domain': {'proj': gridProj, + 'origx': gridBoundBox[0][0], + 'origy': gridBoundBox[0][1], + 'extx': gridBoundBox[1][0], + 'exty': gridBoundBox[1][1] + } + } sourcesE, addressE = irt.addSourceXML(requestE, ourServer) #find the and move it @@ -310,7 +460,7 @@ def makeISCrequest(xmlRequest, gridDims, gridProj, gridBoundBox, mhs, host, port os._exit(0) -def serviceISCRequest(xmlRequest): +def serviceISCRequest(dataFile): # function called by iscDataRec with an isc request to be serviced. # We take this information, convert it into a different format, # and queue the request via the IFPServer to the SendISCMgr @@ -324,7 +474,7 @@ def serviceISCRequest(xmlRequest): logEvent("serviceISCRequest.....") # validate xml - inTree = ElementTree.ElementTree(ElementTree.XML(xmlRequest)) + inTree = ElementTree.parse(dataFile) inE = inTree.getroot() if inE.tag != "iscrequest": raise Exception, "iscrequest packet missing from request" @@ -360,3 +510,49 @@ def irtGetServers(ancfURL, bncfURL, iscWfosWanted): status, xml = irt.getServers(iscWfosWanted) return xml +def sendMHSMessage(subject, adressees, attachments, xmtScript=None): + # Transmit the request -- do string substitution + import siteConfig + from com.raytheon.edex.plugin.gfe.config import IFPServerConfigManager + config = IFPServerConfigManager.getServerConfig(siteConfig.GFESUITE_SITEID) + ourMHS = siteConfig.GFESUITE_MHSID + + if xmtScript is None: + xmtScript = config.transmitScript() + + # create the required wmoid + wmoid = "TTAA00 " + if ourMHS in ['SJU']: + wmoid += "TJSJ" + elif ourMHS in ['AFG', 'AJK', 'HFO', 'GUM']: + wmoid += "P" + ourMHS + elif ourMHS in ['AER', 'ALU']: + wmoid += "PAFC" + elif len(ourMHS) == 3: + wmoid += "K" + ourMHS + elif len(ourMHS) == 4: + wmoid += ourMHS + else: + wmoid = "XXXX" + wmoid += " " + time.strftime("%d%H%M", time.gmtime(time.time())) + + if type(adressees) in [list, tuple]: + adressees = ",".join(addresses) + + if type(attachments) in [list, tuple]: + attachments = ",".join(attachments) + + cmd = copy.deepcopy(xmtScript) + for s1, s2 in [("%SUBJECT", subject), + ("%ADDRESSES", adressees), + ("%WMOID", wmoid), + ("%ATTACHMENTS", attachments)]: + cmd = cmd.replace(s1, s2) + + logDebug("cmd: "+ cmd) + + # start subprocess to actually make the call + try: + subprocess.check_call([cmd], shell=True) + except: + logException("Error running cmd: " + cmd) \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscDataRec.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscDataRec.py index 8da06958a4..46bc01e306 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscDataRec.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscDataRec.py @@ -43,9 +43,10 @@ from java.util import ArrayList # for iscMosaic, support changes # to IscReceiveSrv. # 01/24/14 2504 randerso removed obsolete A1 comments -# -# +# 12/08/2014 4953 randerso Added support for sending/receiving TCV files +# Additional code cleanup # +## iscDataRecLogger=None @@ -92,9 +93,9 @@ def execIscDataRec(MSGID,SUBJECT,FILES): ourMhsID = siteConfig.GFESUITE_MHSID # for most transactions, first attachment is the data file, 2nd file is the - # XML destinations. The ISCREQUEST is unique with only 1 file being the + # XML destinations. ISCREQUEST and GET_TCV_FILES have only 1 file being the # XML destinations. We simulate two files naming them the same. - if SUBJECT == "ISCREQUEST": + if SUBJECT in ["ISCREQUEST", "GET_TCV_FILES"]: FILES.append(FILES[0]) dataFile = FILES[0] #first attachment is always the data file @@ -157,78 +158,83 @@ def execIscDataRec(MSGID,SUBJECT,FILES): logProblem("destinations packet missing from xml") return - # decode and print the source server (if present) - for addressE in destE: - if addressE.tag != "address": - continue + # Handle GET_TCV_FILES out side the loop as it needs to do it's own loop + if SUBJECT == 'GET_TCV_FILES': + IrtServer.getTCVFiles(ourMhsID, srcServer, destE) + else: + # decode and print the source server (if present) + for addressE in destE: + if addressE.tag != "address": + continue + + destServer = irt.decodeXMLAddress(addressE) + + # find destination server information + mhsidDest=serverDest=portDest=protocolDest=None + for attrE in addressE.getchildren(): + if attrE.tag == "mhsid": + mhsidDest = attrE.text + elif attrE.tag == "server": + serverDest = attrE.text + elif attrE.tag == "port": + portDest = attrE.text + elif attrE.tag == "protocol": + protocolDest = attrE.text + + if destServer['mhsid'].upper() != ourMhsID.upper(): + logDebug(SUBJECT, 'Not our mhs of ' + ourMhsID + \ + ', so skipped:', irt.printServerInfo(destServer)) + continue #this destination is for someone else. + + # transmit the data to the ifpServer + time2 = time.clock() - destServer = irt.decodeXMLAddress(addressE) + if SUBJECT == 'PUT_ACTIVE_TABLE': + IrtServer.putVTECActiveTable(dataFile, None) + elif SUBJECT == 'PUT_ACTIVE_TABLE2': + IrtServer.putVTECActiveTable(dataFile, xmlFileBuf) + elif SUBJECT == 'GET_ACTIVE_TABLE': + IrtServer.getVTECActiveTable(dataFile, None) + elif SUBJECT == 'GET_ACTIVE_TABLE2': + IrtServer.getVTECActiveTable(dateFile, xmlFileBuf) + elif SUBJECT in ['ISCGRIDS', 'ISCGRIDS2']: + args = {"siteID": siteConfig.GFESUITE_SITEID, + "userID": 'SITE', + "databaseID": siteConfig.GFESUITE_SITEID+"_GRID__ISC_00000000_0000", + "parmsToProcess": [], + "blankOtherPeriods": True, + "startTime": None, + "endTime": None, + "altMask": None, + "replaceOnly": False, + "eraseFirst": False, + "announce": "ISC: ", + "renameWE": True, + "iscSends": False, + "inFiles": [dataFile], + "ignoreMask": False, + "adjustTranslate": True, + "deleteInput": True, + "parmsToIgnore": [], + "gridDelay": 0.0, + "logFileName": None} + mosaic = iscMosaic.IscMosaic(args) + mosaic.execute() - # find destination server information - mhsidDest=serverDest=portDest=protocolDest=None - for attrE in addressE.getchildren(): - if attrE.tag == "mhsid": - mhsidDest = attrE.text - elif attrE.tag == "server": - serverDest = attrE.text - elif attrE.tag == "port": - portDest = attrE.text - elif attrE.tag == "protocol": - protocolDest = attrE.text - - if destServer['mhsid'].upper() != ourMhsID.upper(): - logDebug(SUBJECT, 'Not our mhs of ' + ourMhsID + \ - ', so skipped:', irt.printServerInfo(destServer)) - continue #this destination is for someone else. - - # transmit the data to the ifpServer - with open(dataFile, "rb") as fp: - fpData = fp.read() - time2 = time.clock() - - if SUBJECT == 'PUT_ACTIVE_TABLE': - IrtServer.putVTECActiveTable(fpData, None) - elif SUBJECT == 'PUT_ACTIVE_TABLE2': - IrtServer.putVTECActiveTable(fpData, xmlFileBuf) - elif SUBJECT == 'GET_ACTIVE_TABLE': - IrtServer.getVTECActiveTable(fpData, None) - elif SUBJECT == 'GET_ACTIVE_TABLE2': - IrtServer.getVTECActiveTable(fpData, xmlFileBuf) - elif SUBJECT in ['ISCGRIDS', 'ISCGRIDS2']: - args = {"siteID": siteConfig.GFESUITE_SITEID, - "userID": 'SITE', - "databaseID": siteConfig.GFESUITE_SITEID+"_GRID__ISC_00000000_0000", - "parmsToProcess": [], - "blankOtherPeriods": True, - "startTime": None, - "endTime": None, - "altMask": None, - "replaceOnly": False, - "eraseFirst": False, - "announce": "ISC: ", - "renameWE": True, - "iscSends": False, - "inFiles": [dataFile], - "ignoreMask": False, - "adjustTranslate": True, - "deleteInput": True, - "parmsToIgnore": [], - "gridDelay": 0.0, - "logFileName": None} - mosaic = iscMosaic.IscMosaic(args) - mosaic.execute() - - elif SUBJECT == 'ISCREQUEST': - IrtServer.serviceISCRequest(fpData) - else: - nosend = True - logProblem("unknown subject: ", SUBJECT) - continue - time3 = time.clock() - delta1 = time2-time1 - delta2 = time3-time2 - logEvent('Sent to:', - irt.printServerInfo(destServer), "connectT=", delta1, "xmtT=", delta2) + elif SUBJECT == 'ISCREQUEST': + IrtServer.serviceISCRequest(dataFile) + elif SUBJECT == 'PUT_TCV_FILES': + IrtServer.putTCVFiles(srcServer.get('site'), dataFile) + pass + else: + nosend = True + logProblem("unknown subject: ", SUBJECT) + continue + time3 = time.clock() + delta1 = time2-time1 + delta2 = time3-time2 + logEvent('Sent to:', + irt.printServerInfo(destServer), "connectT=", delta1, "xmtT=", delta2) except: logProblem("iscDataRec failed!",traceback.format_exc()) finally: diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/GenericHazards.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/GenericHazards.py index e09bffa4b8..61b6ecdac7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/GenericHazards.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/GenericHazards.py @@ -516,24 +516,39 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis, nwsIntroUsed = 1 if phraseCount == 0: phraseCount = 1 - hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \ - hazNameA + forPhrase + \ - "...WHICH IS IN EFFECT" + endTimePhrase + ". " + if eachHazard['phen'] in ['HU', 'TR', 'TY']: + hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \ + hazNameA + ". " + else: + hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \ + hazNameA + forPhrase + \ + "...WHICH IS IN EFFECT" + endTimePhrase + ". " elif phraseCount == 1: phraseCount = 2 if hdln != lastHdln: - hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ - " HAS ALSO BEEN ISSUED. THIS " + hazName + forPhrase + \ - " IS IN EFFECT" + endTimePhrase + ". " + if eachHazard['phen'] in ['HU', 'TR', 'TY']: + hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ + " HAS ALSO BEEN ISSUED." + else: + hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ + " HAS ALSO BEEN ISSUED. THIS " + hazName + forPhrase + \ + " IS IN EFFECT" + endTimePhrase + ". " else: - hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ - " HAS ALSO BEEN ISSUED" + endTimePhrase + ". " + if eachHazard['phen'] in ['HU', 'TR', 'TY']: + hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ + " HAS ALSO BEEN ISSUED." + else: + hazardBodyPhrase = hazardBodyPhrase + hazNameA + forPhrase + \ + " HAS ALSO BEEN ISSUED" + endTimePhrase + ". " else: - hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \ - hazNameA + forPhrase + " HAS BEEN ISSUED. THIS " + hazName + \ - " IS IN EFFECT" + endTimePhrase + ". " - lastHdln = hdln - + if eachHazard['phen'] in ['HU', 'TR', 'TY']: + hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \ + hazNameA + " HAS BEEN ISSUED." + else: + hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \ + hazNameA + forPhrase + " HAS BEEN ISSUED. THIS " + hazName + \ + " IS IN EFFECT" + endTimePhrase + ". " + lastHdln = hdln # # This is for the can hazards # diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/HLS.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/HLS.py index 0d406c4967..875e1de0a9 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/HLS.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/HLS.py @@ -1,4 +1,4 @@ -# Version 2014.11.24-0 +# Version 2015.1.6-0 import GenericHazards import string, time, os, re, types, copy, LogStream, collections @@ -6,6 +6,7 @@ import ModuleAccessor, SampleAnalysis, EditAreaUtils import math import Tkinter import numpy +import LocalizationSupport from AbsTime import * from StartupDialog import IFPDialog as Dialog @@ -52,6 +53,7 @@ class TextProduct(HLSTCV_Common.TextProduct): # Add options for debugging Definition["debug"] = { + #TextProduct "__init__": 0, "_inlandAreas": 0, "_coastalAreas": 0, @@ -60,15 +62,16 @@ class TextProduct(HLSTCV_Common.TextProduct): "_localReferencePoints": 0, "_localReferencePoints_defaults": 0, "_referencePointLimit": 0, + "_productParts_HLS": 0, "_analysisList_HLS": 0, "_analysisList_HLS_WholeDomain": 0, "_intersectAnalysisList_HLS": 0, - "_productParts_HLS": 0, - "_impactsKeyFunction": 0, - "_ugcHeader": 0, + "generateForecast": 0, + "_initializeVariables": 0, + "_initializeHeadlines": 0, + "_initializeSamplingDict": 0, + "_noOpParts": 0, "_areaList": 0, - "_formatUGC_entries": 0, - "_getUgcInfo": 0, "_summaryHeadlines": 0, "_changesHazards": 0, "_currentHazards": 0, @@ -84,81 +87,66 @@ class TextProduct(HLSTCV_Common.TextProduct): "_otherPreparednessActions": 0, "_additionalSourcesInfo": 0, "_nextUpdate": 0, + "_impactsKeyFunction": 0, "_getPotentialImpactsStatements": 0, "_impactCategoryToThreatLevel": 0, - "generateForecast": 0, "_determineHazardStates": 0, "_sampleHLSData": 0, - "_createWholeDomainEditArea": 0, - "_sampleMostSignificantDiscreteValue": 0, + "_sampleTCVAdvisory": 0, "_sampleRankedDiscreteValue": 0, + "_sampleMostSignificantDiscreteValue": 0, "_getDominantThreatLevel": 0, "_getHighestThreat": 0, "_getLowestThreat": 0, - "_initializeVariables": 0, - "_initializeHeadlines": 0, - "_initializeSamplingDict": 0, - "_sampleTCVAdvisory": 0, "_setHazardImpactCategories": 0, - "_grabHeadline": 0, + "_createWholeDomainEditArea": 0, + "_groupSegments": 0, "_determineHazards": 0, - "SituationOverview": 0, + "_formatLocalTime": 0, + "_getTimeZoneList": 0, + "_grabHeadline": 0, "_getStormInfo": 0, "_grabStormInfo": 0, "_decodeStormInfo": 0, "_expandBearings": 0, "_removeKM": 0, "_cleanText": 0, - "_formatLocalTime": 0, - "_getTimeZoneList": 0, "_calcLocalReferences": 0, "_calcReference": 0, "_distanceFromLatLon": 0, "_bearing": 0, "_dirInEnglish": 0, - "_processProductParts": 0, - "_noOpParts": 0, - "_createProductDictionary": 0, - "_formatProductDictionary": 0, - "_groupSegments": 0, - "_findNEWAssociatedWithUPG": 0, - "_initializeProductDict": 0, - "_initializeHazardsTable": 0, - "_setVTECActiveTable": 0, - "_allAreas": 0, "_overview_list": 0, "_displayGUI": 0, "_frame": 0, - # Legacy formatter class - "execute": 0, - "_processProductParts": 0, - "_noOpParts": 0, - "processWmoHeader": 0, - "processProductHeader": 0, - "formatIssueTime": 0, - "processSummaryHeadlines": 0, - "processHazards": 0, - "_areaWords": 0, - "processStormInformation": 0, - "processSituationOverview": 0, - "processHazardsSection": 0, - "processSubParts": 0, - - # HLSTCV_Common methods + #HLSTCV_Common + "allowedHazards": 0, + "allowedHeadlines": 0, + "_initializeVariables": 0, + "moderated_dict": 0, "_wmoHeader": 0, "_productHeader": 0, + "_ugcHeader": 0, + "_processProductParts": 0, + "_formatUGC_entries": 0, + "_getUgcInfo": 0, + "_createProductDictionary": 0, + "_initializeProductDictionary": 0, + "_formatProductDictionary": 0, + "_getStatValue": 0, + "_allAreas": 0, + "_computeIntersectAreas": 0, "_initializeHazardsTable": 0, - "_setVTECActiveTable": 0, - "_getAllVTECRecords": 0, + "_getHazardsTable": 0, "_ignoreActions": 0, + "_setVTECActiveTable": 0, + "_getVtecRecords": 0, "_getAllowedHazardList": 0, "_altFilterMethod": 0, "_filterHazards": 0, "_getAdditionalHazards": 0, "_checkHazard": 0, - "getVtecRecords": 0, - "_getHazardsTable": 0, "_initializeTimeVariables": 0, "_determineTimeRanges": 0, "_calculateStartTime": 0, @@ -166,10 +154,6 @@ class TextProduct(HLSTCV_Common.TextProduct): "_formatPeriod": 0, "_getTimeDesc": 0, "_getPartOfDay": 0, - "moderated_dict": 0, - "_getStatValue": 0, - "_allAreas": 0, - "_computeIntersectAreas": 0, "_initializeStormInformation": 0, "_parseTCP": 0, "_getStormTypeFromTCP": 0, @@ -179,22 +163,26 @@ class TextProduct(HLSTCV_Common.TextProduct): "_getStormNumberStringFromTCP": 0, "_useTestTCP": 0, "_testTCP": 0, + "_initializeAdvisories": 0, "_synchronizeAdvisories": 0, "_getLocalAdvisoryDirectoryPath": 0, + "_getStormAdvisoryNames": 0, "_loadLastTwoAdvisories": 0, "_loadAdvisory": 0, "_getAdvisoryPath": 0, - "_getLocalizationFile": 0, "_getAdvisoryFilename": 0, "_processVariableList": 0, "_GUI_sizing_dict": 0, "_GUI1_configDict": 0, "_font_GUI_dict": 0, - "threatKeyOrder": 0, - "allowedHazards": 0, - "allowedHeadlines": 0, - "_initializeAdvisories": 0, - "_initializeSegmentZoneData": 0, + + #Overview_Dialog + "body": 0, + "_makeStep3": 0, + "_makeButtons": 0, + "okCB": 0, + + #Common_Dialog "getVarDict": 0, "_makeRadioOrCheckList": 0, "_makeEntry": 0, @@ -204,6 +192,21 @@ class TextProduct(HLSTCV_Common.TextProduct): "_setVarDict": 0, "status": 0, "buttonbox": 0, + + #LegacyFormatter + "execute": 0, + "_processProductParts": 0, + "processWmoHeader": 0, + "processProductHeader": 0, + "processSummaryHeadlines": 0, + "processHazards": 0, + "_areaWords": 0, + "processStormInformation": 0, + "processSituationOverview": 0, + "processHazardsSection": 0, + "processSubParts": 0, + + #TextProductCommon "setUp": 0, "hazardTimeZones": 0, "getExpireTime": 0, @@ -228,10 +231,20 @@ class TextProduct(HLSTCV_Common.TextProduct): ##################################################################### ##################################################################### ### Organization of Formatter Code - + ############################################################### ### MUST OVERRIDE DEFINITIONS !!! - ### _inlandAreas, _coastalAreas, _cwa + ### _inlandAreas, _coastalAreas, _cwa, _cwa_descriptor, + ### _localReferencePoints, _localReferencePoints_defaults + ############################################################### + + ############################################################### + ### Optional Overrides + ### _referencePointLimit + ############################################################### + + ############################################################### + ### HLS Product and Segment Parts Definition ############################################################### ############################################################### @@ -239,30 +252,24 @@ class TextProduct(HLSTCV_Common.TextProduct): ### analysis related methods ############################################################### - ############################################################### - ### Hazards and Additional Hazards - ### allowedHazards is used for VTEC records and summary - ### headlines - ### allowedHeadlines are additional hazards reported in - ### certain sections - ############################################################### - - ############################################################### - ### HLS Product and Segment Parts Definition - ############################################################### - ############################################################### # CODE ############################################################### ### High level flow of formatter - ### generateForecast, initializeVariables, - ### determineSegments, determineTimeRanges, sampleData, - ### createProductDictionary, formatProductDictionary, - ### archiveCurrentAdvisory... + ### generateForecast, _initializeVariables, + ### _loadLastTwoAdvisories, _determineTimeRanges, + ### _initializeSamplingDict, _sampleTCVAdvisory, + ### _sampleHLSData, _determineHazardStates, + ### _setHazardImpactCategories, _createProductDictionary, + ### _formatProductDictionary ############################################################### ############################################################### - ### Product Dictionary methods + ### Product Parts Implementation + ############################################################### + + ############################################################### + ### Sampling and Statistics related methods ############################################################### ############################################################### @@ -273,10 +280,6 @@ class TextProduct(HLSTCV_Common.TextProduct): ### Hazards related methods ############################################################### - ############################################################### - ### Sampling and Statistics related methods - ############################################################### - ############################################################### ### Time related methods ############################################################### @@ -285,27 +288,23 @@ class TextProduct(HLSTCV_Common.TextProduct): ### Storm Information and TCP related methods ############################################################### - ############################################################### - ### Advisory related methods - ############################################################### - ############################################################### ### GUI related methods ############################################################### - - + + ############################################################### ### MUST OVERRIDE DEFINITIONS !!! def _inlandAreas(self): return [ -# "FLZ063", "FLZ066", "FLZ067", "FLZ068", "FLZ070", -# "FLZ071", "FLZ072", "FLZ073", "FLZ074", + #"FLZ063", "FLZ066", "FLZ067", "FLZ068", "FLZ070", + #"FLZ071", "FLZ072", "FLZ073", "FLZ074", ] def _coastalAreas(self): return [ -# "FLZ069", "FLZ075", "FLZ168", "FLZ172", "FLZ173", "FLZ174", + #"FLZ069", "FLZ075", "FLZ168", "FLZ172", "FLZ173", "FLZ174", ] def _cwa(self): @@ -338,6 +337,46 @@ class TextProduct(HLSTCV_Common.TextProduct): # Also give a label (e.g. "two") for the GUI return (2, "two") + ############################################################### + ### HLS Product and Segment Parts Definition + + def _productParts_HLS(self, segment_vtecRecords_tuples): + partsList = [ + 'wmoHeader', + 'ugcHeader', + 'productHeader', + 'areaList', + 'summaryHeadlines', + 'newInformationHeader', + 'changesHazards', + 'currentHazards', + 'stormInformation', + 'situationOverview', + 'sigPotentialImpacts', + ] + + if self._ImpactsAnticipated: + includedImpacts = sorted(self._IncludedImpacts, key=self._impactsKeyFunction) + for ((_, sectionName), _) in includedImpacts: + self.debug_print("adding section = '%s'" % (sectionName), 1) + partsList.append(sectionName) + + partsList.append('preparednessSection') + + if self._ImpactsAnticipated: + partsList.append('evacuationStatements') + partsList.append('otherPreparednessActions') + partsList.append('additionalSourcesInfo') + + partsList.append('nextUpdate') + partsList.append('endProduct') + + self.debug_print("Product Parts partsList =\n\n%s\n" % (self._pp.pformat(partsList)), 1) + + return { + 'partsList': partsList + } + ############################################################### ### Analysis Lists, SampleAnalysis Overrides and other ### analysis related methods @@ -379,101 +418,119 @@ class TextProduct(HLSTCV_Common.TextProduct): ] return analysisList - + ############################################################### - ### TCV Product and Segment Parts Definition + ### High level flow of formatter - def _productParts_HLS(self, segment_vtecRecords_tuples): - partsList = [ - 'wmoHeader', - 'ugcHeader', - 'productHeader', - 'areaList', - 'summaryHeadlines', - 'newInformationHeader', - 'changesHazards', - 'currentHazards', - 'stormInformation', - 'situationOverview', - 'sigPotentialImpacts', - ] + def generateForecast(self, argDict): + # Generate Text Phrases for a list of edit areas + + error = self._initializeVariables(argDict) + if error is not None: + return error + + if self._stormName is None or self._stormName.strip() == "": + return "Could not determine the storm name" + + self._loadLastTwoAdvisories() + if self._previousAdvisory is None and self._ImpactsAnticipated: + return "A TCV must be transmitted before an HLS can be run" + + # Determine time ranges + self._determineTimeRanges(argDict) if self._ImpactsAnticipated: - includedImpacts = sorted(self._IncludedImpacts, key=self._impactsKeyFunction) - for ((_, sectionName), _) in includedImpacts: - self.debug_print("SARAH: adding section = '%s'" % (sectionName), 1) - partsList.append(sectionName) - - partsList.append('preparednessSection') - - if self._ImpactsAnticipated: - partsList.append('evacuationStatements') - partsList.append('otherPreparednessActions') - partsList.append('additionalSourcesInfo') - - partsList.append('nextUpdate') - partsList.append('endProduct') - - return { - 'partsList': partsList - } + + # Sample the data + self._initializeSamplingDict() + self._sampleTCVAdvisory(self._previousAdvisory) + self._sampleHLSData(argDict) + + self._determineHazardStates() - def _impactsKeyFunction(self, optionIndexTuple): - ((_, _), indexStr) = optionIndexTuple - indexStr = indexStr.strip() - if len(indexStr) == 0: - return 9999 - else: - return int(indexStr) + for threatName in ['WindThreat', 'StormSurgeThreat', 'FloodingRainThreat', 'TornadoThreat']: + self._setHazardImpactCategories(threatName) - def _ugcHeader(self, productDict, productSegmentGroup, productSegment): - self._ugcs = self._allAreas() - productDict['ugcCodes'] = self._formatUGC_entries() - self._ugcHeader_value = self._tpc.formatUGCs(self._ugcs, self._expireTime) - productDict['ugcHeader'] = self._ugcHeader_value + # Create the product dictionary and format it to create the output + productDict = self._createProductDictionary(self._allAreas()) + productOutput = self._formatProductDictionary(LegacyFormatter, productDict) + + return productOutput + + def _initializeVariables(self, argDict): + error = HLSTCV_Common.TextProduct._initializeVariables(self, argDict) + if error is not None: + return error + + self._getStormInfo(argDict) + + self._initializeHeadlines() + + self._ugcs = sorted(self._allAreas()) + + return None + + def _initializeHeadlines(self): + if self._MainHeadline == "Enter": + self._headlines = [self._MainHeadline_entry] + elif self._MainHeadline == "UsePrev": + self._prevHLS = self.getPreviousProduct(self._textdbPil) + self._headlines = [self._grabHeadline(self._prevHLS)] + elif self._MainHeadline == "UseTCP": + try: + self._headlines = [self._grabHeadline(self._TCP)] + except: + self._headlines = [] + + def _initializeSamplingDict(self): + self._samplingDict = dict() + statsDict = dict() + statsDict['catastrophicThreshold'] = None + statsDict['decidingField'] = None + statsDict['inputThreatLow'] = None + statsDict['inputThreatHigh'] = None + statsDict['inputThreatDominant'] = None + statsDict['impactMin'] = None + statsDict['impactMax'] = None + statsDict['impactRange'] = None + + self._samplingDict['WindThreat'] = copy.copy(statsDict) + self._samplingDict['StormSurgeThreat'] = copy.copy(statsDict) + self._samplingDict['FloodingRainThreat'] = copy.copy(statsDict) + self._samplingDict['TornadoThreat'] = copy.copy(statsDict) + + self._samplingDict['WindThreat']['catastrophicThreshold'] = 137 # knots + self._samplingDict['StormSurgeThreat']['catastrophicThreshold'] = 14 # feet + self._samplingDict['FloodingRainThreat']['catastrophicThreshold'] = 3 # percent + + ############################################################### + ### Product Parts Implementation + + def _noOpParts(self): + ''' + These represent product parts that should be skipped when calling product part methods. + They will be handled automatically by the formatters. + ''' + return ['CR', 'endProduct', 'endSegment', 'doubleAmpersand', 'newInformationHeader', 'sigPotentialImpacts'] + + ################# Product Level def _areaList(self, productDict, productSegmentGroup, productSegment): productDict['areaList'] = "This product covers " + self._cwa_descriptor() - def _formatUGC_entries(self): - ugcCodeList = [] - for ugc in self._ugcs: - areaDictEntry = self._areaDict.get(ugc) - if areaDictEntry is None: - # We are not localized correctly for the hazard - # So get the first dictionary entry - self.logger.info('Not Localized for the hazard area -- ugc' + ugc) - keys = self._areaDict.keys() - areaDictEntry = self._areaDict.get(keys[0]) - ugcEntry = collections.OrderedDict() - ugcEntry['state'] = areaDictEntry.get('stateAbbr') - ugcEntry['type'] = self._getUgcInfo(ugc, 'type') - ugcEntry['number'] = self._getUgcInfo(ugc, 'number') - ugcEntry['text'] = ugc - ugcEntry['subArea'] = '' - ugcCodeList.append(ugcEntry) - return ugcCodeList - - def _getUgcInfo(self, ugc, part='type'): - if part == 'type': - if ugc[2] == 'C': - return 'County' - else: - return 'Zone' - if part == 'number': - return ugc[3:] - def _summaryHeadlines(self, productDict, productSegmentGroup, productSegment): productDict['summaryHeadlines'] = self._headlines def _changesHazards(self, productDict, productSegmentGroup, productSegment): - if not self._ImpactsAnticipated: + if (not self._ImpactsAnticipated) or \ + (self._ImpactsAnticipated and self._GeneralOnsetTime == "recovery"): productDict['changesHazards'] = [] else: productDict['changesHazards'] = self._changesHazardsList def _currentHazards(self, productDict, productSegmentGroup, productSegment): - if not self._ImpactsAnticipated: + if (not self._ImpactsAnticipated) or \ + (self._ImpactsAnticipated and self._GeneralOnsetTime == "recovery"): productDict['currentHazards'] = [] else: productDict['currentHazards'] = self._currentHazardsList @@ -603,15 +660,17 @@ class TextProduct(HLSTCV_Common.TextProduct): elif len(impactParts) == 1: impactRangeRest = impactParts[0] - self.debug_print("MATT DEBUG: impactRange = '%s' impactMax = '%s' impactMin = '%s'" % (impactRange, impactMax, impactMin), 1) + self.debug_print("DEBUG: impactRange = '%s' impactMax = '%s' impactMin = '%s'" % + (impactRange, impactMax, impactMin), 1) # If there are additional life-threatening surge areas if impactRange != impactMax and impactRange != impactMin: curPhrase = "Brace for %s%s damage across %s." % \ (lifeThreatening, impactRange, self._frame("ENTER AREA DESCRIPTION")) - self.debug_print("MATT DEBUG: curPhrase = '%s'" % (curPhrase), 1) - self.debug_print("MATT DEBUG: sectionDict['additionalImpactRange'] = '%s'" % (repr(sectionDict['additionalImpactRange'])), 1) + self.debug_print("DEBUG: curPhrase = '%s'" % (curPhrase), 1) + self.debug_print("DEBUG: sectionDict['additionalImpactRange'] = \n'%s'" % + (sectionDict['additionalImpactRange']), 1) # If this phrase is not already part of the additional impacts if curPhrase not in sectionDict['additionalImpactRange']: @@ -642,7 +701,8 @@ class TextProduct(HLSTCV_Common.TextProduct): # Add it now sectionDict['additionalImpactRange'].append(curPhrase) - self.debug_print("Final Surge sectionDict['additionalImpactRange'] = '%s'" % (sectionDict['additionalImpactRange']), 1) + self.debug_print("Final Surge sectionDict['additionalImpactRange'] = '%s'" % + (sectionDict['additionalImpactRange']), 1) productDict['surgeSection'] = sectionDict def _floodingRainSection(self, productDict, productSegmentGroup, productSegment): @@ -659,7 +719,7 @@ class TextProduct(HLSTCV_Common.TextProduct): inputThreatDominant = self._samplingDict['FloodingRainThreat']['inputThreatDominant'] self.debug_print("In _floodingRainSection", 1) - self.debug_print("_samplingDict = %s" % (repr(self._samplingDict['FloodingRainThreat'])), 1) + self.debug_print("_samplingDict = \n\n%s\n" % (self._pp.pformat(self._samplingDict['FloodingRainThreat'])), 1) # Test the simplest case first if impactMin == "none" and impactMax == "none": @@ -839,13 +899,23 @@ class TextProduct(HLSTCV_Common.TextProduct): self._wfoCityState + \ " around " + self._NextUpdate_entry.strip() + ", or sooner if conditions warrant." + ################# Product Parts Helper Methods + + def _impactsKeyFunction(self, optionIndexTuple): + ((_, _), indexStr) = optionIndexTuple + indexStr = indexStr.strip() + if len(indexStr) == 0: + return 9999 + else: + return int(indexStr) + def _getPotentialImpactsStatements(self, elementName, maxThreat): import TCVDictionary potentialImpactStatements = TCVDictionary.PotentialImpactStatements statements = potentialImpactStatements[elementName][maxThreat] return statements - + def _impactCategoryToThreatLevel(self, impactCategory): if impactCategory == "catastrophic" or impactCategory == "devastating": return "Extreme" @@ -857,57 +927,6 @@ class TextProduct(HLSTCV_Common.TextProduct): return "Elevated" else: return "None" - - ############################################################### - ### High level flow of formatter - - def generateForecast(self, argDict): - # Generate Text Phrases for a list of edit areas - - error = self._initializeVariables(argDict) - if error is not None: - return error - - # Determine time ranges - self._initializeTimeVariables(argDict) - self._determineTimeRanges(argDict) - - error = self._initializeStormInformation() - if error is not None: - return error - - self._getStormInfo(argDict) - if self._stormName is None or self._stormName.strip() == "": - return "Could not determine the storm name" - - self._loadLastTwoAdvisories() - if self._previousAdvisory is None and self._ImpactsAnticipated: - return "A TCV must be transmitted before an HLS can be run" - - self._initializeHeadlines() - - self._initializeHazardsTable(argDict) - - if self._ImpactsAnticipated: - - self._determineHazardStates() - - # Sample the data - self._initializeSamplingDict() - - self._sampleTCVAdvisory(self._previousAdvisory) - - self._sampleHLSData(argDict) - - for threatName in ['WindThreat', 'StormSurgeThreat', 'FloodingRainThreat', 'TornadoThreat']: - self._setHazardImpactCategories(threatName) - - # Create the product dictionary and format it to create the output - productDict = self._createProductDictionary() - productOutput = self._formatProductDictionary(productDict) - - return productOutput - def _determineHazardStates(self): self._currentHazardsList = [] @@ -919,16 +938,15 @@ class TextProduct(HLSTCV_Common.TextProduct): for key in keys: self.debug_print("%s : %s" % (key, self._previousAdvisory[key]), 1) for hazard in self._previousAdvisory["HazardsForHLS"]: - self.debug_print("SARAH DEBUG Hazard: %s" % (repr(hazard)), 1) + self.debug_print("DEBUG Hazard: %s" % (self._pp.pformat(hazard)), 1) if hazard['act'] != 'CON': self._changesHazardsList.append(hazard) - if hazard['act'] != 'CAN': + if hazard['act'] not in ['CAN', "UPG"]: self._currentHazardsList.append(hazard) self.debug_print("-"*80, 1) self.debug_print("self._changesHazardsList = %s" % (self._changesHazardsList), 1) self.debug_print("self._currentHazardsList = %s" % (self._currentHazardsList), 1) - ############################################################### ### Sampling and Statistics related methods @@ -948,7 +966,7 @@ class TextProduct(HLSTCV_Common.TextProduct): self.debug_print("=" * 100, 1) self.debug_print("In _sampleHLSData for period %s (%s)" % \ - (period, repr(self._timeRangeList[period][0])), 1) + (period, self._timeRangeList[period][0]), 1) statDict = statList[period] for threatName in ['WindThreat', 'FloodingRainThreat', 'TornadoThreat']: @@ -960,9 +978,9 @@ class TextProduct(HLSTCV_Common.TextProduct): if decidingField is None or qpfToFfgRatio > decidingField: self._samplingDict['FloodingRainThreat']['decidingField'] = qpfToFfgRatio - self.debug_print("SARAH: WindThreat = %s" % (self._samplingDict['WindThreat']['inputThreatDominant']), 1) - self.debug_print("SARAH: FloodingRainThreat = %s" % (self._samplingDict['FloodingRainThreat']['inputThreatDominant']), 1) - self.debug_print("SARAH: TornadoThreat = %s" % (self._samplingDict['TornadoThreat']['inputThreatDominant']), 1) + self.debug_print("WindThreat = %s" % (self._samplingDict['WindThreat']['inputThreatDominant']), 1) + self.debug_print("FloodingRainThreat = %s" % (self._samplingDict['FloodingRainThreat']['inputThreatDominant']), 1) + self.debug_print("TornadoThreat = %s" % (self._samplingDict['TornadoThreat']['inputThreatDominant']), 1) @@ -1005,58 +1023,81 @@ class TextProduct(HLSTCV_Common.TextProduct): if decidingField is None or inundationMax > decidingField: self._samplingDict['StormSurgeThreat']['decidingField'] = inundationMax - self.debug_print("SARAH: StormSurgeThreat = %s" % (self._samplingDict['StormSurgeThreat']['inputThreatDominant']), 1) + self.debug_print("StormSurgeThreat = %s" % (self._samplingDict['StormSurgeThreat']['inputThreatDominant']), 1) - def _createWholeDomainEditArea(self, argDict): - editAreaUtils = EditAreaUtils.EditAreaUtils() - editAreaUtils.setUp(None, argDict) + def _sampleTCVAdvisory(self, advisory): + self.debug_print("sampling TCV advisory!", 1) + for zone in advisory["ZoneData"]: + self.debug_print("-" * 60, 1) + self.debug_print("Looking at zone %s" % (zone), 1) + for key in advisory["ZoneData"][zone]: + if "Threat" not in key: + continue + + self.debug_print("Looking at key '%s'" % (key), 1) + + threatLevel = advisory["ZoneData"][zone][key] + self.debug_print(" Threat level = %s" % (threatLevel), 1) + if self._samplingDict[key]['inputThreatLow'] is None: + self._samplingDict[key]['inputThreatLow'] = threatLevel + if self._samplingDict[key]['inputThreatHigh'] is None: + self._samplingDict[key]['inputThreatHigh'] = threatLevel + + lowThreat = self._samplingDict[key]['inputThreatLow'] + highThreat = self._samplingDict[key]['inputThreatHigh'] + threatOrder = self.mostSignificantDiscrete_keyOrder_dict(None, None, None)[key] + + if threatOrder.index(threatLevel) < threatOrder.index(lowThreat): + lowThreat = threatLevel + if threatOrder.index(threatLevel) > threatOrder.index(highThreat): + highThreat = threatLevel + + self.debug_print(" low threat = %s" % (lowThreat), 1) + self.debug_print(" high threat = %s" % (highThreat), 1) + + self._samplingDict[key]['inputThreatLow'] = lowThreat + self._samplingDict[key]['inputThreatHigh'] = highThreat - gridLoc = editAreaUtils.getGridLoc() - grid2Dbit = JavaGrid2DBit( gridLoc.gridSize().x, gridLoc.gridSize().y) - grid2Dbit.setAllValues(1) - - refID = ReferenceID("WholeDomain") - refData = ReferenceData(gridLoc, refID, grid2Dbit) - editAreaUtils.saveEditAreas([refData]) + self.debug_print("Sampling dict =\n\n%s\n" % (self._pp.pformat(self._samplingDict)), 1) + + def _sampleRankedDiscreteValue(self, threatName, statDict): + self.debug_print("-" * 60, 1) + self.debug_print("_sampleRankedDiscreteValue statDict =\n\n%s\n" % (self._pp.pformat(statDict)), 1) + rankedThreatLevels = self.getStats(statDict, threatName + "__rankedDiscreteValue") + self.debug_print("sampling %s" % (threatName), 1) + self.debug_print("sampleData: rankedThreatLevels =\n\n%s\n" % (self._pp.pformat(rankedThreatLevels)), 1) + if rankedThreatLevels is not None: + dominantThreatLevel = self._getDominantThreatLevel(threatName, rankedThreatLevels) + self.debug_print("dominantThreatLevel = %s" % (dominantThreatLevel), 1) + + currentDominantThreatLevel = self._samplingDict[threatName]['inputThreatDominant'] + self.debug_print("currentDominantThreatLevel = %s" % (currentDominantThreatLevel), 1) + self._samplingDict[threatName]['inputThreatDominant'] = self._getHighestThreat(threatName, + dominantThreatLevel, + currentDominantThreatLevel) + self.debug_print("new dominant = %s" % (self._samplingDict[threatName]['inputThreatDominant']), 1) def _sampleMostSignificantDiscreteValue(self, threatName, statDict): - self.debug_print("SARAH: _sampleMostSignificantDiscreteValue for %s" % (threatName), 1) + self.debug_print("_sampleMostSignificantDiscreteValue for %s" % (threatName), 1) threatLevel = self.getStats(statDict, threatName + "__mostSignificantDiscreteValue") - self.debug_print("SARAH: threatLevel = %s" % (threatLevel), 1) + self.debug_print("threatLevel = %s" % (threatLevel), 1) if threatLevel is not None: inputThreatLow = self._samplingDict[threatName]['inputThreatLow'] - self.debug_print("SARAH: current inputThreatLow = %s" % (inputThreatLow), 1) + self.debug_print("current inputThreatLow = %s" % (inputThreatLow), 1) if inputThreatLow is None: self._samplingDict[threatName]['inputThreatLow'] = threatLevel else: self._samplingDict[threatName]['inputThreatLow'] = self._getLowestThreat(threatName, threatLevel, inputThreatLow) - self.debug_print("SARAH: new inputThreatLow = %s" % (self._samplingDict[threatName]['inputThreatLow']), 1) + self.debug_print("new inputThreatLow = %s" % (self._samplingDict[threatName]['inputThreatLow']), 1) inputThreatHigh = self._samplingDict[threatName]['inputThreatHigh'] - self.debug_print("SARAH: current inputThreatHigh = %s" % (inputThreatHigh), 1) + self.debug_print("current inputThreatHigh = %s" % (inputThreatHigh), 1) self._samplingDict[threatName]['inputThreatHigh'] = self._getHighestThreat(threatName, threatLevel, inputThreatHigh) - self.debug_print("SARAH: new inputThreatHigh = %s" % (self._samplingDict[threatName]['inputThreatHigh']), 1) - - def _sampleRankedDiscreteValue(self, threatName, statDict): - self.debug_print("-" * 60, 1) - self.debug_print("_sampleRankedDiscreteValue statDict = %s" % (repr(statDict)), 1) - rankedThreatLevels = self.getStats(statDict, threatName + "__rankedDiscreteValue") - self.debug_print("SARAH: sampling %s" % (threatName), 1) - self.debug_print("SARAH: sampleData: rankedThreatLevels = %s" % (repr(rankedThreatLevels)), 1) - if rankedThreatLevels is not None: - dominantThreatLevel = self._getDominantThreatLevel(threatName, rankedThreatLevels) - self.debug_print("SARAH: dominantThreatLevel = %s" % (dominantThreatLevel), 1) - - currentDominantThreatLevel = self._samplingDict[threatName]['inputThreatDominant'] - self.debug_print("SARAH: currentDominantThreatLevel = %s" % (currentDominantThreatLevel), 1) - self._samplingDict[threatName]['inputThreatDominant'] = self._getHighestThreat(threatName, - dominantThreatLevel, - currentDominantThreatLevel) - self.debug_print("SARAH: new dominant = %s" % (self._samplingDict[threatName]['inputThreatDominant']), 1) + self.debug_print("new inputThreatHigh = %s" % (self._samplingDict[threatName]['inputThreatHigh']), 1) def _getDominantThreatLevel(self, threatName, rankedThreatLevels): dominantLevelWithHighestRank = None @@ -1101,93 +1142,6 @@ class TextProduct(HLSTCV_Common.TextProduct): else: return threatLevel2 - def _initializeVariables(self, argDict): - # Get variables - error = self._getVariables(argDict) - if error is not None: - return error - - self._backupFullStationID = self._fullStationID - self._argDict = argDict - - argDict["definition"] = self._definition - - # Set up the areaDictionary for all to use - accessor = ModuleAccessor.ModuleAccessor() - self._areaDict = accessor.variable(self._areaDictionary, "AreaDictionary") - self._tpc = HLSTCV_Common.TextProductCommon() - self._tpc.setUp(self._areaDict) - - return None - - def _initializeHeadlines(self): - if self._MainHeadline == "Enter": - self._headlines = [self._MainHeadline_entry] - elif self._MainHeadline == "UsePrev": - self._prevHLS = self.getPreviousProduct(self._textdbPil) - self._headlines = [self._grabHeadline(self._prevHLS)] - elif self._MainHeadline == "UseTCP": - try: - self._headlines = [self._grabHeadline(self._TCP)] - except: - self._headlines = [] - - def _initializeSamplingDict(self): - self._samplingDict = dict() - statsDict = dict() - statsDict['catastrophicThreshold'] = None - statsDict['decidingField'] = None - statsDict['inputThreatLow'] = None - statsDict['inputThreatHigh'] = None - statsDict['inputThreatDominant'] = None - statsDict['impactMin'] = None - statsDict['impactMax'] = None - statsDict['impactRange'] = None - - self._samplingDict['WindThreat'] = copy.copy(statsDict) - self._samplingDict['StormSurgeThreat'] = copy.copy(statsDict) - self._samplingDict['FloodingRainThreat'] = copy.copy(statsDict) - self._samplingDict['TornadoThreat'] = copy.copy(statsDict) - - self._samplingDict['WindThreat']['catastrophicThreshold'] = 137 # knots - self._samplingDict['StormSurgeThreat']['catastrophicThreshold'] = 14 # feet - self._samplingDict['FloodingRainThreat']['catastrophicThreshold'] = 3 # percent - - def _sampleTCVAdvisory(self, advisory): - self.debug_print("SARAH: sampling TCV advisory!", 1) - for zone in advisory["ZoneData"]: - self.debug_print("-" * 60, 1) - self.debug_print("Looking at zone %s" % (zone), 1) - for key in advisory["ZoneData"][zone]: - if "Threat" not in key: - continue - - self.debug_print("Looking at key '%s'" % (key), 1) - - threatLevel = advisory["ZoneData"][zone][key] - self.debug_print(" Threat level = %s" % (threatLevel), 1) - if self._samplingDict[key]['inputThreatLow'] is None: - self._samplingDict[key]['inputThreatLow'] = threatLevel - if self._samplingDict[key]['inputThreatHigh'] is None: - self._samplingDict[key]['inputThreatHigh'] = threatLevel - - lowThreat = self._samplingDict[key]['inputThreatLow'] - highThreat = self._samplingDict[key]['inputThreatHigh'] - threatOrder = self.mostSignificantDiscrete_keyOrder_dict(None, None, None)[key] - - if threatOrder.index(threatLevel) < threatOrder.index(lowThreat): - lowThreat = threatLevel - if threatOrder.index(threatLevel) > threatOrder.index(highThreat): - highThreat = threatLevel - - self.debug_print(" low threat = %s" % (lowThreat), 1) - self.debug_print(" high threat = %s" % (highThreat), 1) - - self._samplingDict[key]['inputThreatLow'] = lowThreat - self._samplingDict[key]['inputThreatHigh'] = highThreat - - self.debug_print("Sampling dict = %s" % (repr(self._samplingDict)), 1) - def _setHazardImpactCategories(self, threatName): inputThreatLow = self._samplingDict[threatName]['inputThreatLow'] inputThreatHigh = self._samplingDict[threatName]['inputThreatHigh'] @@ -1196,7 +1150,7 @@ class TextProduct(HLSTCV_Common.TextProduct): catastrophicThreshold = self._samplingDict[threatName]['catastrophicThreshold'] self.debug_print("-" * 60, 1) - self.debug_print("MATT DEBUG: _setHazardImpactCategories for %s" % (threatName), 1) + self.debug_print("DEBUG: _setHazardImpactCategories for %s" % (threatName), 1) impactMin = None impactMax = None @@ -1240,7 +1194,7 @@ class TextProduct(HLSTCV_Common.TextProduct): impactRangeMax = "none" self.debug_print( - "MATT DEBUG: impactMin = '%s' impactMax = '%s' impactRangeMax = '%s'" % \ + "DEBUG: impactMin = '%s' impactMax = '%s' impactRangeMax = '%s'" % \ (impactMin, impactMax, impactRangeMax), 1) # Determine dominant impact category for rest of CWA - No impact @@ -1265,6 +1219,155 @@ class TextProduct(HLSTCV_Common.TextProduct): self._samplingDict[threatName]['impactMax'] = impactMax self._samplingDict[threatName]['impactRange'] = impactRange + ############################################################### + ### Area, Zone and Segment related methods + + def _createWholeDomainEditArea(self, argDict): + editAreaUtils = EditAreaUtils.EditAreaUtils() + editAreaUtils.setUp(None, argDict) + + gridLoc = editAreaUtils.getGridLoc() + grid2Dbit = JavaGrid2DBit( gridLoc.gridSize().x, gridLoc.gridSize().y ) + grid2Dbit.setAllValues(1) + + refID = ReferenceID("WholeDomain") + refData = ReferenceData(gridLoc, refID, grid2Dbit) + editAreaUtils.saveEditAreas([refData]) + + def _groupSegments(self, segments): + ''' + Group the segments into the products + return a list of productSegmentGroup dictionaries + ''' + + segment_vtecRecords_tuples = [] + for segment in segments: + vtecRecords = self._getVtecRecords(segment) + self.debug_print("vtecRecords =\n\n%s\n" % (self._pp.pformat(vtecRecords))) + segment_vtecRecords_tuples.append((segment, vtecRecords)) + + productSegmentGroup = { + 'productID' : 'HLS', + 'productName': self._productName, + 'geoType': 'area', + 'vtecEngine': self._hazardsTable, + 'mapType': 'publicZones', + 'segmented': True, + 'productParts': self._productParts_HLS(segment_vtecRecords_tuples), + } + + return productSegmentGroup + + ############################################################### + ### Hazards related methods + + def _determineHazards(self, segments): + # Return a list of hazards from the given segments in the form: + # (key, landList, marineList, coastalList, inlandList) + # where key is (hdln, act, phen, sig) and the lists show which areas + # contain the hazard separated by category + hazAreaList = [] + for segment in segments: + hazardTable = self._argDict["hazards"] + hazards = hazardTable.getHazardList(segment) + for hazard in hazards: + action = hazard['act'] + hazAreaList.append((hazard, segment)) + # Consolidate hazards (there could be multiple segments with the same phen/sig/act) + hazardDict = {} + hazardList = [] + for hazard, segment in hazAreaList: + key = (hazard['hdln'], hazard['act'], hazard['phen'], hazard['sig']) + if key not in hazardDict.keys(): + hazardDict[key] = segment + hazardList.append(key) + else: + hazardDict[key] = hazardDict[key]+segment + + self.debug_print("hazardList =\n\n%s\n" % (self._pp.pformat(hazardList)), 1) + + return hazardList + + ############################################################### + ### Time related methods + + def _formatLocalTime(self, para, areas): + # Create a time string in local time + # e.g. 2 AM EDT + # Get the Z time hour + timeSearch = re.compile("...([0-9]+) *(Z|UTC)...") + timeStr = timeSearch.search(para) + +## gmtStr = para[timeStr.start():timeStr.end()] +## gmt = gmtStr.strip("...").replace("Z","") +## gmtHour = int(gmt)/100 + + # This code could bomb in the unlikely event we don't find a UTC + # time. We should probably add some kind of default hour here, + # keyed off the current hour, to prevent this. (MHB) + try: + # Convert the hour portion of the time string to an integer + gmtHour = int(timeStr.group(1)[:2]) + except: + gmtHour = time.gmtime().tm_hour + + gmtTR = self.createTimeRange(gmtHour, gmtHour+1, "Zulu") + gmtTime = gmtTR.startTime().unixTime() + + # Now make a string for each time zone + zoneList = self._getTimeZoneList(areas) + timeStrs = [] + timeDesc = "" + for timeZone in zoneList: + timeStr = self.formatTimeString(gmtTime, "%I %p %Z ", timeZone) + timeStr = string.replace(timeStr, " ", " ") + timeStr = string.strip(timeStr) + timeStr = timeStr.lstrip("0") + if timeStr not in timeStrs: + if len(timeStrs) > 0: + timeDesc += "...OR " + timeStrs.append(timeStr) + timeDesc += timeStr + return timeDesc + + def _getTimeZoneList(self, areaList): + # NOTE -- this code was taken from the middle of getAreaHeader + # in Header.py -- it really should be put back in and used + # in Header.py, but to avoid confusion, I'm repeating it here + # get this time zone + thisTimeZone = os.environ["TZ"] + zoneList = [] + # check to see if we have any areas outside our time zone + for areaName in areaList: + if areaName in self._areaDict.keys(): + entry = self._areaDict[areaName] + if not entry.has_key("ugcTimeZone"): #add your site tz + if thisTimeZone not in zoneList: + zoneList.append(thisTimeZone) + continue # skip this entry + timeZoneList = entry["ugcTimeZone"] + if type(timeZoneList) is types.StringType: # a single value + timeZoneList = [timeZoneList] # make it into a list + for timeZone in timeZoneList: + if timeZone not in zoneList: + zoneList.append(timeZone) + # if the resulting zoneList is empty, put in our time zone + if len(zoneList) == 0: + zoneList.append(thisTimeZone) + # if the resulting zoneList has our time zone in it, be sure it + # is the first one in the list + try: + index = zoneList.index(thisTimeZone) + if index != 0: + del zoneList[index] + zoneList.insert(0, thisTimeZone) + except: + pass + return zoneList + + ############################################################### + ### Storm Information and TCP related methods + def _grabHeadline(self, text=''): # Get first headline found in text and return it as a string @@ -1300,79 +1403,6 @@ class TextProduct(HLSTCV_Common.TextProduct): return "" # Changed to an null string instead of None # (MHB 04/08/2009) - def _determineHazards(self, segments): - # Return a list of hazards from the given segments in the form: - # (key, landList, marineList, coastalList, inlandList) - # where key is (hdln, act, phen, sig) and the lists show which areas - # contain the hazard separated by category - hazAreaList = [] - for segment in segments: - hazardTable = self._argDict["hazards"] - hazards = hazardTable.getHazardList(segment) - for hazard in hazards: - action = hazard['act'] - hazAreaList.append((hazard, segment)) - # Consolidate hazards (there could be multiple segments with the same phen/sig/act) - hazardDict = {} - hazardList = [] - for hazard, segment in hazAreaList: - key = (hazard['hdln'], hazard['act'], hazard['phen'], hazard['sig']) - if key not in hazardDict.keys(): - hazardDict[key] = segment - hazardList.append(key) - else: - hazardDict[key] = hazardDict[key]+segment - - #self.debug_print("hazardList = %s" % (repr(hazardList)), 1) - - return hazardList - - def SituationOverview(self, title, info): - t = title - un = self._Uncertainty - ec = self._EventContext - if ec == "Abbreviated": - hdlns = info.hazardHdlns - #self.debug_print("*** Headlines ***") - reported = 0 - for hazardHdln in hdlns: - key = hazardHdln - #self.debug_print("hazard = '%s'" % (hazardHdln), 1) - hdln, act, phen, sig = key - if phen == "HU" and sig == "S": - continue - if act in self._ignoreActions(): - continue - if hdlns.index(hazardHdln) > 0: - t+= " AND " - t+= "A " + hdln - reported += 1 - if reported > 0: - if reported > 1: t+= " HAVE " - else: t+= " HAS " - t+="NOW BEEN ISSUED. " - t+="A MORE DETAILED STATEMENT WILL FOLLOW SHORTLY.\n" - - if ec in ["PreEvent","Watch","Warning"]: - if un=="High": - t+="IT IS VITAL THAT YOU DO NOT FOCUS ON THE EXACT FORECAST TRACK. " - t+="TO DO SO COULD RESULT IN BAD DECISIONS AND PLACE YOU OR THOSE YOU ARE " - t+="RESPONSIBLE FOR AT GREATER RISK. " - elif un == "Average": - t+="WHEN MAKING DECISIONS...DO NOT FOCUS ON THE EXACT FORECAST TRACK. " - - if ec != "Abbreviated": t+=self._frame("Succinctly describe the expected evolution of the event for the CWA & MAOR; which hazards are of greater (or lesser) concern, forecast focus, etc.")+ "\n" - - if ec in ["PreEvent", "Watch"]: - if info.anyLand: - t+="IT IS TOO EARLY TO PROVIDE EXACT WIND AND SURGE FORECAST VALUES FOR SPECIFIC LOCATIONS. " - damage = self._getCategoryDamage(info.maxWind_CWA_MAOR) - if damage.strip() != "": - t+="A GENERAL CONCERN SHOULD BE FOR THE POSSIBILITY OF "+damage+" SOMEWHERE WITHIN "\ - + self._cwa_descriptor() + ". " - - return t - def _getStormInfo(self, argDict): # Get the Storm information self._stormType = "TROPICAL" @@ -1390,7 +1420,7 @@ class TextProduct(HLSTCV_Common.TextProduct): # Storm intensity in mph and the stated intensity trend. self._stormIntensityTrend = "Storm Intensity " + stormDict.get("StormIntensity","") - self.debug_print("SARAH: BEGIN STORM INFORMATION", 1) + self.debug_print("BEGIN STORM INFORMATION", 1) self.debug_print("storm dict = %s" % (stormDict), 1) self.debug_print("storm name = %s" % (self._stormName), 1) self.debug_print("type = %s" % (self._stormType), 1) @@ -1403,7 +1433,7 @@ class TextProduct(HLSTCV_Common.TextProduct): self.debug_print("references = %s" % (self._stormLocalReferences), 1) self.debug_print("movement trend = %s" % (self._stormMovementTrend), 1) self.debug_print("intensity trend = %s" % (self._stormIntensityTrend), 1) - self.debug_print("SARAH: END STORM INFORMATION", 1) + self.debug_print("END STORM INFORMATION", 1) def _grabStormInfo(self, tcp): # Get the storm information from the selected TCP @@ -1528,7 +1558,7 @@ class TextProduct(HLSTCV_Common.TextProduct): # Assume we only have one NHC reference point by default nhcReference = dict["StormReference"] -## self.debug_print("referenceIndex = %s" % (referenceIndex), 1) + self.debug_print("referenceIndex = %s" % (referenceIndex), 1) # If we have more than one NHC reference point if referenceIndex != -1: @@ -1576,13 +1606,15 @@ class TextProduct(HLSTCV_Common.TextProduct): # Display some debug info - if flag is set self.debug_print("storminfoSearch = '%s'" % (stormInfoSearch)) -## self.debug_print(repr(stormInfoSearch.groups()), 1) + if stormInfoSearch is not None: + self.debug_print("\n\n%s\n" % + (self._pp.pformat(stormInfoSearch.groups())), 1) # If we found the storm info section of the product if stormInfoSearch is not None: -# for group in stormInfoSearch.groups(): -# self.debug_print('-'*50, 1) -# self.debug_print("%s\n" % (group), 1) + for group in stormInfoSearch.groups(): + self.debug_print('-'*50, 1) + self.debug_print("%s\n" % (group), 1) # Clean this section up a bit. Keep each paragraph separate # by a single , but remove all others as well as extra @@ -1614,7 +1646,7 @@ class TextProduct(HLSTCV_Common.TextProduct): # If we cannot find the summary, try to find a "repeating" section if repeatInfo is None: repeatInfo = re.search("(?is)(REPEATING.+?\.)\n *\n", tcp) -## self.debug_print(repr(repeatInfo), 1) + self.debug_print(self._pp.pformat(repeatInfo), 1) # If we found the repeated storm information summary if repeatInfo is not None: @@ -1634,7 +1666,8 @@ class TextProduct(HLSTCV_Common.TextProduct): # Display some debug info - if flag is set self.debug_print("locationSearch = '%s'" % (locationSearch), 1) -## self.debug_print(repr(locationSearch.groups()), 1) + if locationSearch is not None: + self.debug_print("\n\n%s\n" % (self._pp.pformat(locationSearch.groups())), 1) # If we found the storm location section of the product if locationSearch is not None: @@ -1693,18 +1726,18 @@ class TextProduct(HLSTCV_Common.TextProduct): #======================================================================== # Display final decoded information from TCP -## self.debug_print("*" *80, 1) -## self.debug_print("Final TCP Info...\n", 1) -## self.debug_print('dict["StormType"] = %s' % (dict["StormType"]), 1) -## self.debug_print('dict["StormName"] = %s' % (dict["StormName"]), 1) -## self.debug_print('dict["StormTime"] = %s' % (dict["StormTime"]), 1) -## self.debug_print('dict["StormLat"] = %s' % (dict["StormLat"]), 1) -## self.debug_print('dict["StormLon"] = %s' % (dict["StormLon"]), 1) -## self.debug_print('dict["StormReference"] = %s' % (dict["StormReference"]), 1) -## self.debug_print('dict["StormIntensity"] = %s' % (dict["StormIntensity"]), 1) -## self.debug_print('dict["StormMotion"] = %s' % (dict["StormMotion"]), 1) -## self.debug_print('dict["StormInfo"] = %s' % (dict["StormInfo"]), 1) -## self.debug_print('dict["StormCenter"] = %s' % (dict["StormCenter"]), 1) + self.debug_print("*" *80, 1) + self.debug_print("Final TCP Info...\n", 1) + self.debug_print('dict["StormType"] = %s' % (dict["StormType"]), 1) + self.debug_print('dict["StormName"] = %s' % (dict["StormName"]), 1) + self.debug_print('dict["StormTime"] = %s' % (dict["StormTime"]), 1) + self.debug_print('dict["StormLat"] = %s' % (dict["StormLat"]), 1) + self.debug_print('dict["StormLon"] = %s' % (dict["StormLon"]), 1) + self.debug_print('dict["StormReference"] = %s' % (dict["StormReference"]), 1) + self.debug_print('dict["StormIntensity"] = %s' % (dict["StormIntensity"]), 1) + self.debug_print('dict["StormMotion"] = %s' % (dict["StormMotion"]), 1) + self.debug_print('dict["StormInfo"] = %s' % (dict["StormInfo"]), 1) + self.debug_print('dict["StormCenter"] = %s' % (dict["StormCenter"]), 1) # Return the dictionary will all the information we found in the TCP return dict @@ -1717,7 +1750,7 @@ class TextProduct(HLSTCV_Common.TextProduct): self._stormReference = "" self._stormLocalReferences = "" para = stormDict.get("StormCenter", "") - # self.debug_print("para %d %s" % (len(para), para), 1) + self.debug_print("para %d %s" % (len(para), para), 1) if len(para)<= 0: return @@ -1741,13 +1774,15 @@ class TextProduct(HLSTCV_Common.TextProduct): # Try to find these patterns in the text coordPtnMatch = coordPtn.search(para) -## self.debug_print("+" * 90, 1) -## self.debug_print("coordinate search...", 1) -## self.debug_print(coordPtnMatch.groups(), 1) + self.debug_print("+" * 90, 1) + self.debug_print("coordinate search...", 1) + if coordPtnMatch is not None: + self.debug_print("\n\n%s|n" % (self._pp.pformat(coordPtnMatch.groups())), 1) refPtnMatch = refPtn.search(para) -## self.debug_print("reference search...", 1) -## self.debug_print(refPtnMatch.groups(), 1) + self.debug_print("reference search...", 1) + if refPtnMatch is not None: + self.debug_print("\n\n%s|n" % (self._pp.pformat(refPtnMatch.groups())), 1) # If we found the coordinates we were after if coordPtnMatch is not None: @@ -1791,12 +1826,12 @@ class TextProduct(HLSTCV_Common.TextProduct): self._stormLocalReferences = self._calcLocalReferences( self._stormLat, self._stormLon) -## self.debug_print("stormLocalRefs = %s" % (self._stormLocalReferences), 1) + self.debug_print("stormLocalRefs = %s" % (self._stormLocalReferences), 1) # Compare the NHC reference to the local references for localRef in self._stormLocalReferences: -## self.debug_print("self._stormReference = '%s', localRef = '%s'" % (self._stormReference, localRef), 1) + self.debug_print("self._stormReference = '%s', localRef = '%s'" % (self._stormReference, localRef), 1) # Get the locations from these statements nhcRef = re.search('(?i)(north|south|east|west) of (.+)', @@ -1804,7 +1839,11 @@ class TextProduct(HLSTCV_Common.TextProduct): testRef = re.search('(?i)(north|south|east|west) of (.+)', localRef) -## self.debug_print("nhcRef = '%s'\ttestRef = '%s'" % (nhcRef.group(2), testRef.group(2)), 1) + if nhcRef is not None: + self.debug_print("nhcRef = '%s'" % (nhcRef.group(2)), 1) + + if testRef is not None: + self.debug_print("testRef = '%s'" % (testRef.group(2)), 1) # If we have a local reference that matches the national # center reference @@ -1835,7 +1874,7 @@ class TextProduct(HLSTCV_Common.TextProduct): text = text.replace(' NNW ', ' NORTH-NORTHWEST ') return text - + # Modified 12/15/2010 (MHB) - modified to recognize the new way NHC will # present metric speeds. Will continue to recognize the "old" way for # testing purposes as well. @@ -1843,7 +1882,7 @@ class TextProduct(HLSTCV_Common.TextProduct): # Remove references to KM e.g. # 420 KM... 100 KM/HR... -# self.debug_print("words = '%s'" % (words), 1) + self.debug_print("words = '%s'" % (words), 1) kmSearch = re.compile("\.\.\. *[0-9]+ +(KM|KM/HR?) *\.?\.?\.?") @@ -1856,7 +1895,7 @@ class TextProduct(HLSTCV_Common.TextProduct): for doubleSpace in doubleSpaces: words = re.sub(doubleSpace, ' ', words) -# self.debug_print("\tfinal words = '%s'" % (words), 1) + self.debug_print("\tfinal words = '%s'" % (words), 1) return words def _cleanText(self, text=''): @@ -1880,80 +1919,6 @@ class TextProduct(HLSTCV_Common.TextProduct): # Return the cleaned-up text return text - def _formatLocalTime(self, para, areas): - # Create a time string in local time - # e.g. 2 AM EDT - # Get the Z time hour - timeSearch = re.compile("...([0-9]+) *(Z|UTC)...") - timeStr = timeSearch.search(para) - -## gmtStr = para[timeStr.start():timeStr.end()] -## gmt = gmtStr.strip("...").replace("Z","") -## gmtHour = int(gmt)/100 - - # This code could bomb in the unlikely event we don't find a UTC - # time. We should probably add some kind of default hour here, - # keyed off the current hour, to prevent this. (MHB) - try: - # Convert the hour portion of the time string to an integer - gmtHour = int(timeStr.group(1)[:2]) - except: - gmtHour = time.gmtime().tm_hour - - gmtTR = self.createTimeRange(gmtHour, gmtHour+1, "Zulu") - gmtTime = gmtTR.startTime().unixTime() - - # Now make a string for each time zone - zoneList = self._getTimeZoneList(areas) - timeStrs = [] - timeDesc = "" - for timeZone in zoneList: - timeStr = self.formatTimeString(gmtTime, "%I %p %Z ", timeZone) - timeStr = string.replace(timeStr, " ", " ") - timeStr = string.strip(timeStr) - timeStr = timeStr.lstrip("0") - if timeStr not in timeStrs: - if len(timeStrs) > 0: - timeDesc += "...OR " - timeStrs.append(timeStr) - timeDesc += timeStr - return timeDesc - - def _getTimeZoneList(self, areaList): - # NOTE -- this code was taken from the middle of getAreaHeader - # in Header.py -- it really should be put back in and used - # in Header.py, but to avoid confusion, I'm repeating it here - # get this time zone - thisTimeZone = os.environ["TZ"] - zoneList = [] - # check to see if we have any areas outside our time zone - for areaName in areaList: - if areaName in self._areaDict.keys(): - entry = self._areaDict[areaName] - if not entry.has_key("ugcTimeZone"): #add your site tz - if thisTimeZone not in zoneList: - zoneList.append(thisTimeZone) - continue # skip this entry - timeZoneList = entry["ugcTimeZone"] - if type(timeZoneList) is types.StringType: # a single value - timeZoneList = [timeZoneList] # make it into a list - for timeZone in timeZoneList: - if timeZone not in zoneList: - zoneList.append(timeZone) - # if the resulting zoneList is empty, put in our time zone - if len(zoneList) == 0: - zoneList.append(thisTimeZone) - # if the resulting zoneList has our time zone in it, be sure it - # is the first one in the list - try: - index = zoneList.index(thisTimeZone) - if index != 0: - del zoneList[index] - zoneList.insert(0, thisTimeZone) - except: - pass - return zoneList - def _calcLocalReferences(self, lat0, lon0): localRefs = [] refList = self._LocalReferencePoints @@ -1981,9 +1946,9 @@ class TextProduct(HLSTCV_Common.TextProduct): direction = self._bearing(lat1, lon1, lat0, lon0) direction = self._dirInEnglish(direction) localRef ="ABOUT "+distMph_str+" MILES "+direction -# self.debug_print("localRef = %s" % (localRef), 1) + self.debug_print("localRef = %s" % (localRef), 1) return localRef - + # Returns the distance from lat0, lon0 to lat1, lon1 in kilometers def _distanceFromLatLon(self, lat0, lon0, lat1, lon1): R = 6371.0 @@ -1993,7 +1958,7 @@ class TextProduct(HLSTCV_Common.TextProduct): lon1 = numpy.deg2rad(lon1) dist = math.acos(math.sin(lat0) * math.sin(lat1) + math.cos(lat0) * math.cos(lat1) * math.cos(lon1 - lon0)) * R return dist - + def _bearing(self, lat0, lon0, lat1, lon1): dlat = numpy.deg2rad((lat0 - lat1)) @@ -2009,8 +1974,7 @@ class TextProduct(HLSTCV_Common.TextProduct): direction = direction % 360 return direction - - + def _dirInEnglish(self, direction): dirList = ["North", "North-Northeast", "Northeast", "East-Northeast", "East", "East-Southeast", "Southeast", "South-Southeast", @@ -2021,213 +1985,6 @@ class TextProduct(HLSTCV_Common.TextProduct): dirIndex = dirIndex - 16 return dirList[dirIndex] - ###################################################### - # Product Part processing - ###################################################### - - def _processProductParts(self, productGenerator, productDict, productSegmentGroup, productParts): - ''' - @param productDict - @param productSegmentGroup - @param productParts - @return product dictionary created from the product parts - - Note that this method is called recursively such that a product part is allowed to be - a set of subParts specified as follows: - (subPartLabel, list of productParts for each subPart) - For example, we have - ('segments', [list of [segment product parts]]) - - # Product Dictionary - # Contains information for all formats e.g. - # partner XML, CAP, and Legacy text - ''' - - - if type(productParts) is types.DictType: - arguments = productParts.get('arguments') - partsList = productParts.get('partsList') - else: - partsList = productParts - - removedParts = [] - for part in partsList: - if type(part) is types.TupleType: - # e.g. subPart == 'segments', subPartsLists == list of parts for each segment - subPart, subPartsLists = part - subParts = [] - for subPartsList in subPartsLists: - subDict = collections.OrderedDict() - self._processProductParts(productGenerator, subDict, productSegmentGroup, subPartsList) - subParts.append(subDict) - # e.g. productDict['segments'] = segment dictionaries - productDict[subPart] = subParts - else: - if part not in self._noOpParts(): - execString = 'productGenerator._'+part+'(productDict, productSegmentGroup, arguments)' - exec execString - if part not in productDict: - removedParts.append(part) - - for part in removedParts: - self.debug_print("SARAH: Removing part = %s" % (part), 1) - partsList.remove(part) - - def _noOpParts(self): - ''' - These represent product parts that should be skipped when calling product part methods. - They will be handled automatically by the formatters. - ''' - return ['CR', 'endProduct', 'endSegment', 'doubleAmpersand', 'newInformationHeader', 'sigPotentialImpacts'] - - ############################################################### - ### Product Dictionary methods - - def _createProductDictionary(self): - # Create the product dictionary - productSegmentGroup = self._groupSegments(self._allAreas()) - - productDict = self._initializeProductDict(productSegmentGroup) - productParts = productSegmentGroup.get('productParts') - productDict['productParts'] = productParts - self._processProductParts(self, productDict, productSegmentGroup, productParts) -# self._wrapUpProductDict(productDict) - - return productDict - - def _formatProductDictionary(self, productDict): - legacyFormatter = LegacyFormatter(self) - product = legacyFormatter.execute(productDict) -# xmlFormatter = XMLFormatter(self) -# product = xmlFormatter.execute(productDict) - - return product - - def _groupSegments(self, segments): - ''' - Group the segments into the products - return a list of productSegmentGroup dictionaries - ''' - - segment_vtecRecords_tuples = [] - for segment in segments: - vtecRecords = self.getVtecRecords(segment) - for record in vtecRecords: - if record['act'] == "UPG": - upgPhenSig = record['phen'] + "." + record['sig'] - newRecord = self._findNEWAssociatedWithUPG(upgPhenSig, vtecRecords) - record['new_record'] = newRecord - self.debug_print("SARAH: vtecRecord = %s" % (repr(record))) - segment_vtecRecords_tuples.append((segment, vtecRecords)) - - productSegmentGroup = { - 'productID' : 'HLS', - 'productName': self._productName, - 'geoType': 'area', - 'vtecEngine': self._hazardsTable, - 'mapType': 'publicZones', - 'segmented': True, - 'productParts': self._productParts_HLS(segment_vtecRecords_tuples), - } - - return productSegmentGroup - - def _findNEWAssociatedWithUPG(self, upgPhenSig, vtecRecords): - import VTECTable - - possibleUpgrades = [] - for upgradedTo, upgradedFrom in VTECTable.upgradeHazardsDict: - if upgPhenSig in upgradedFrom: - possibleUpgrades.append(upgradedTo) - - for record in vtecRecords: - if record['act'] == "NEW": - newPhenSig = record['phen'] + "." + record['sig'] - if newPhenSig in possibleUpgrades: - return record - - return None - - ###################################################### - # Product Dictionary -- General product information - ###################################################### - - def _initializeProductDict(self, productSegmentGroup): - ''' - Set up the Product Dictionary for the given Product consisting of a - group of segments. - - Fill in the dictionary information for the product header. - - @param productSegmentGroup: holds meta information about the product - @return initialized product dictionary - - *********** - Example segmented product: - - WGUS63 KBOU 080400 - FFABOU - - URGENT - IMMEDIATE BROADCAST REQUESTED - FLOOD WATCH - NATIONAL WEATHER SERVICE DENVER CO - 400 AM GMT TUE FEB 8 2011 - - Overview Headline - Overview - - *********** - Example non-segmented product: - WGUS63 KBOU 080400 - FFWBOU - - ''' - self._productID = productSegmentGroup.get('productID', 'NNN') - if self._areaName != '': - self._areaName = ' FOR ' + self._areaName + '\n' - self._geoType = productSegmentGroup.get('geoType') - self._mapType = productSegmentGroup.get('mapType') - self._productTimeZones = [] - - # Fill in product dictionary information - productDict = collections.OrderedDict() - productDict['productID'] = self._productID - return productDict - - ############################################################### - ### Hazards related methods - - def _initializeHazardsTable(self, argDict): - import VTECMessageType - productID = self._pil[0:3] - vtecMode = VTECMessageType.getVTECMessageType(productID.upper()) - argDict["vtecMode"] = vtecMode - - self._setVTECActiveTable(argDict) - - # Need to check hazards against all edit areas in the CWA MAOR - argDict["combinations"]= [(self._allAreas(),"Region1")] - - self._hazardsTable = self._getHazardsTable(argDict, self.filterMethod) - argDict["hazards"] = self._hazardsTable - - def _setVTECActiveTable(self, argDict): - dataMgr = argDict["dataMgr"] - gfeMode = dataMgr.getOpMode().name() - - self.debug_print("*" *100, 1) - self.debug_print("gfeMode = '%s'" % (gfeMode), 1) - self.debug_print("*" *100, 1) - - - if gfeMode == "PRACTICE": - argDict["vtecActiveTable"] = "PRACTICE" - else: - argDict["vtecActiveTable"] = "active" - - def _allAreas(self): - return self._inlandAreas() + self._coastalAreas() - ############################################################### ### GUI related methods @@ -2237,10 +1994,12 @@ class TextProduct(HLSTCV_Common.TextProduct): "name": "ImpactsAnticipated", "label": "Step 1. Potential Impacts Anticipated?", "options": [ - ("Yes", True), + ("Yes (NOTE: Any case other than dispel rumors must\n" + "have current TCP for storm in question)", True), ("No (Dispel Rumors)", False), ], - "default": "Yes", + "default": "Yes (NOTE: Any case other than dispel rumors must\n" + "have current TCP for storm in question)", }, { "name": "StormInfo", @@ -2279,7 +2038,7 @@ class TextProduct(HLSTCV_Common.TextProduct): ("Watch", 'check plans'), ("Warning", 'complete preparations'), ("Conditions/Ongoing", 'hunker down'), - ("Recovery", 'recovery'), + ("Recovery (After last TCV)", 'recovery'), ], }, { @@ -2452,7 +2211,7 @@ class Overview_Dialog(HLSTCV_Common.Common_Dialog): # pull the data from the tkObject_dict before they get toasted tkObject_dict = self._tkObject_dict overviewList = self._parent._overview_list() - print("SARAH: in okCB!") + print("in okCB!") for infoDict in overviewList: name = infoDict["name"] label = infoDict["label"] @@ -2471,7 +2230,7 @@ class Overview_Dialog(HLSTCV_Common.Common_Dialog): checkList.append((options[i], svar.get())) else: if ivarList[i].get(): - print("SARAH: adding option = %s" % (repr(options[i]))) + print("adding option = %s" % (self._pp.pformat(options[i]))) checkList.append(options[i]) value = checkList self._setVarDict(name, value) @@ -2508,8 +2267,8 @@ class LegacyFormatter(): @param productParts -- list of instances of the ProductPart class with information about how to format each product part @return text -- product string ''' - text = '' - print("SARAH: productParts = %s" % (productParts)) + text = "" + self._textProduct.debug_print("productParts = %s" % (productParts)) for part in productParts: valtype = type(part) if valtype is str: @@ -2517,15 +2276,15 @@ class LegacyFormatter(): elif valtype is tuple: name = part[0] infoDicts = part[1] - self.debug_print("SARAH: name = %s" % (str(name)), 1) - self.debug_print("SARAH: infoDicts = %s" % (repr(infoDicts)), 1) + self._textProduct.debug_print("name = %s" % (name), 1) + self._textProduct.debug_print("infoDicts =\n\n%s\n" % (self._pp.pformat(infoDicts)), 1) newtext = self.processSubParts(productDict.get(name), infoDicts) - self.debug_print("SARAH: newtext type = %s" % (type(newtext)), 1) - self.debug_print("SARAH: newtext = %s" % (repr(newtext)), 1) + self._textProduct.debug_print("newtext type = %s" % (type(newtext)), 1) + self._textProduct.debug_print("newtext =\n\n%s\b" % (self._pp.pformat(newtext)), 1) text += newtext continue elif valtype is list: - self.debug_print('GOT HERE -- found list', 1) + self._textProduct.debug_print('GOT HERE -- found list', 1) self._tpc.flush() # TODO THIS SHOULD BE REMOVED AFTER THE REFACTOR OF HazardServicesProductGenerationHandler.JAVA tup = (part[0], part[1]) @@ -2552,9 +2311,11 @@ class LegacyFormatter(): header = "New Information" text += header + "\n" + "-"*len(header) + "\n\n" elif name == "changesHazards": - text += "* Changes to Watches and Warnings:\n" + self.processHazards(productDict['changesHazards']) + text += "* Changes to Watches and Warnings:\n" + \ + self.processHazards(productDict['changesHazards'], isChangesHazards=True) elif name == "currentHazards": - text += "* Current Watches and Warnings:\n" + self.processHazards(productDict['currentHazards']) + text += "* Current Watches and Warnings:\n" + \ + self.processHazards(productDict['currentHazards'], isChangesHazards=False) elif name == "stormInformation": text += self.processStormInformation(productDict['stormInformation']) elif name == "situationOverview": @@ -2607,8 +2368,8 @@ class LegacyFormatter(): text += '&&\n' elif name not in self._noOpParts(): textStr = productDict.get(name) - self.debug_print("SARAH: name = %s" % (name), 1) - self.debug_print("SARAH: textStr = '%s'" % (textStr), 1) + self._textProduct.debug_print("name = %s" % (name), 1) + self._textProduct.debug_print("textStr = '%s'" % (textStr), 1) if textStr: text += textStr + '\n' return text @@ -2654,14 +2415,6 @@ class LegacyFormatter(): return text - def formatIssueTime(self): - text = '' - sentTimeZ = self._tpc.getVal(self.productDict, 'sentTimeZ_datetime') - timeZones = self._tpc.getVal(self.productDict, 'timeZones') - for timeZone in timeZones: - text += self._tpc.formatDatetime(sentTimeZ, '%I%M %p %Z %a %e %b %Y', timeZone) + '\n' - return text - def processSummaryHeadlines(self, headlinesList): if headlinesList in [[], [""]]: text = "**" + self._textProduct._frame("Enter headline here") + "**\n\n" @@ -2675,26 +2428,36 @@ class LegacyFormatter(): return text - def processHazards(self, hazardsList): + def processHazards(self, hazardsList, isChangesHazards): text = "" if len(hazardsList) == 0: - text = self.TAB + "- None\n" + if isChangesHazards and \ + self._textProduct._ImpactsAnticipated and \ + self._textProduct._GeneralOnsetTime == "recovery": + text = self.TAB + "- All watches and warnings have been canceled\n" + else: + text = self.TAB + "- None\n" for hazard in hazardsList: hazardText = "" if hazard['act'] == "CON": hazardText = "A " + hazard['hdln'] + " remains in effect for " + self._areaWords(hazard['id']) elif hazard['act'] in ["NEW", "EXA"]: - hazardText = "A " + hazard['hdln'] + " has been issued for " + self._areaWords(hazard['id']) - elif hazard['act'] == "UPG": - if hazard['new_record'] is not None: - hazardText = "A " + hazard['hdln'] + \ - " has been upgraded to a " + hazard['new_record']['hdln'] + \ + if isChangesHazards and hazard.has_key('upgradeFrom') and hazard['upgradeFrom'] is not None: + import VTECTable + upgradeRecord = hazard['upgradeFrom'] + hazardText = "A " + VTECTable.VTECTable[upgradeRecord['phensig']]['hdln'] + \ + " has been upgraded to a " + hazard['hdln'] + \ " for " + self._areaWords(hazard['id']) else: - hazardText = "A " + hazard['hdln'] + " has been upgraded for " + self._areaWords(hazard['id']) + if isChangesHazards: + hazardText = "A " + hazard['hdln'] + " has been issued for " + self._areaWords(hazard['id']) + else: + hazardText = "A " + hazard['hdln'] + " is in effect for " + self._areaWords(hazard['id']) elif hazard['act'] == "CAN": hazardText = "The " + hazard['hdln'] + " for " + self._areaWords(hazard['id']) + " has been cancelled" + else: + continue text += self._textProduct.indentText(hazardText, indentFirstString = self.TAB + "- ", indentNextString = self.TAB + " ", @@ -2775,11 +2538,11 @@ class LegacyFormatter(): curAdditionalImpactText = "" count = 1 - print("MATT DEBUG: %d sectionDict['additionalImpactRange'] = '%s'" % (len(sectionDict['additionalImpactRange']), sectionDict['additionalImpactRange'])) + self._textProduct.debug_print("DEBUG: %d sectionDict['additionalImpactRange'] = '%s'" % (len(sectionDict['additionalImpactRange']), sectionDict['additionalImpactRange'])) for additionalImpact in sectionDict['additionalImpactRange']: - print("additionalImpact = '%s'" % (additionalImpact)) - print("count = %d" % (count)) + self._textProduct.debug_print("additionalImpact = '%s'" % (additionalImpact)) + self._textProduct.debug_print("count = %d" % (count)) curAdditionalImpactText += \ self._textProduct.indentText(additionalImpact, @@ -2789,7 +2552,7 @@ class LegacyFormatter(): len(curAdditionalImpactText) > 0: curAdditionalImpactText += "\n" - print("MATT DEBUG: curAdditionalImpactText ='%s'" % (curAdditionalImpactText)) + self._textProduct.debug_print("DEBUG: curAdditionalImpactText ='%s'" % (curAdditionalImpactText)) count += 1 @@ -2797,7 +2560,7 @@ class LegacyFormatter(): if additionalImpactRangeText.find(curAdditionalImpactText) == -1: # Add this additional impact text - print("Adding current impact. '%s'" % (curAdditionalImpactText)) + self._textProduct.debug_print("Adding current impact. '%s'" % (curAdditionalImpactText)) additionalImpactRangeText += curAdditionalImpactText text += additionalImpactRangeText @@ -2814,11 +2577,11 @@ class LegacyFormatter(): """ text = '' for i in range(len(subParts)): - print("SARAH: subpart subParts[i] = %s" % (subParts[i])) - print("SARAH: subpart infoDicts[i] = %s" % (infoDicts[i])) + self._textProduct.debug_print("subpart subParts[i] = %s" % (subParts[i])) + self._textProduct.debug_print("subpart infoDicts[i] = %s" % (infoDicts[i])) newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList')) - print("SARAH: subpart newtext type = %s" % (type(newtext))) - print("SARAH: subpart newtext = '%s'" % (repr(newtext))) + self._textProduct.debug_print("subpart newtext type = %s" % (type(newtext))) + self._textProduct.debug_print("subpart newtext = '%s'" % (self._pp.pformat(newtext))) text += newtext return text diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/Hazard_TCV.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/Hazard_TCV.py index 3013faf0db..ea032c7983 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/Hazard_TCV.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/textproducts/templates/product/Hazard_TCV.py @@ -1,6 +1,8 @@ -# Version 2014.12.03-0 +# Version 2015.1.6-0 + import GenericHazards import JsonSupport +import LocalizationSupport import time, types, copy, LogStream, collections import ModuleAccessor import math @@ -8,7 +10,6 @@ import math from AbsTime import * from StartupDialog import IFPDialog as Dialog -from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType AWIPS_ENVIRON = "AWIPS2" import HLSTCV_Common @@ -21,7 +22,7 @@ class TextProduct(HLSTCV_Common.TextProduct): Definition["database"] = "Official" # Source database Definition["debug"] = 1 Definition["mapNameForCombinations"] = "Zones_" - Definition["defaultEditAreas"] = "EditAreas_PublicZones_" + Definition["defaultEditAreas"] = "Combinations_TCV_" Definition["showZoneCombiner"] = 1 # 1 to cause zone combiner to display Definition["productName"] = "LOCAL WATCH/WARNING STATEMENT" @@ -49,65 +50,130 @@ class TextProduct(HLSTCV_Common.TextProduct): Definition["callToAction"] = 1 Definition["debug"] = { - # TextProduct class + #TextProduct "__init__": 0, "_inlandAreas": 0, "_coastalAreas": 0, "_cwa": 0, - "_analysisList": 0, - "_intersectAnalysisList": 0, "_productParts_TCV": 0, "_segmentParts_TCV": 0, + "_analysisList": 0, + "_intersectAnalysisList": 0, + "_extraRainfallAnalysisList": 0, "generateForecast": 0, "_initializeVariables": 0, - "_createProductDictionary": 0, - "_formatProductDictionary": 0, + "_noOpParts": 0, "_easMessage": 0, "_setup_segment": 0, - "_ugcHeader": 0, "_vtecRecords": 0, "_areaList": 0, + "_issuanceTimeDate": 0, + "_summaryHeadlines": 0, "_locationsAffected": 0, "_fcstConfidence": 0, "_infoSection": 0, "_endSection": 0, - "_issuanceTimeDate": 0, - "_summaryHeadlines": 0, - "_processProductParts": 0, - "_noOpParts": 0, - "_initializeProductDict": 0, - "_wrapUpProductDict": 0, - "_groupSegments": 0, - "_makeSegmentEditAreas": 0, - "_determineSegments": 0, - "_refineSegments": 0, - "_findSegment": 0, - "_formatUGC_entries": 0, - "_getUgcInfo": 0, "_hazardDefinition": 0, + "_threatKeyOrder": 0, "_sampleData": 0, "_getStats": 0, + "_determineSegments": 0, + "_refineSegments": 0, + "_groupSegments": 0, + "_makeSegmentEditAreas": 0, + "_findSegment": 0, + "_getAllVTECRecords": 0, + "_getHazardsForHLS": 0, + "_convertToISO": 0, + "_convertToDatetime": 0, + "_initializeSegmentZoneData": 0, + "_archiveCurrentAdvisory": 0, + "_saveAdvisory": 0, + "_overview_list": 0, + "_displayGUI": 0, + + #HLSTCV_Common + "allowedHazards": 0, + "allowedHeadlines": 0, + "_initializeVariables": 0, + "moderated_dict": 0, + "_wmoHeader": 0, + "_productHeader": 0, + "_ugcHeader": 0, + "_processProductParts": 0, + "_formatUGC_entries": 0, + "_getUgcInfo": 0, + "_createProductDictionary": 0, + "_initializeProductDictionary": 0, + "_formatProductDictionary": 0, + "_getStatValue": 0, + "_allAreas": 0, + "_computeIntersectAreas": 0, + "_initializeHazardsTable": 0, + "_getHazardsTable": 0, + "_ignoreActions": 0, + "_setVTECActiveTable": 0, + "_getVtecRecords": 0, + "_getAllowedHazardList": 0, + "_altFilterMethod": 0, + "_filterHazards": 0, + "_getAdditionalHazards": 0, + "_checkHazard": 0, + "_initializeTimeVariables": 0, + "_determineTimeRanges": 0, + "_calculateStartTime": 0, + "_resolution": 0, "_formatPeriod": 0, "_getTimeDesc": 0, "_getPartOfDay": 0, - "_convertToISO": 0, - "_convertToDatetime": 0, - "_overview_list": 0, - "_displayGUI": 0, - "_archiveCurrentAdvisory": 0, - "_saveAdvisory": 0, - "_getHazardsForHLS": 0, + "_initializeStormInformation": 0, + "_parseTCP": 0, + "_getStormTypeFromTCP": 0, + "_getStormNameFromTCP": 0, + "_getAdvisoryTypeFromTCP": 0, + "_getAdvisoryNumberStringFromTCP": 0, + "_getStormNumberStringFromTCP": 0, + "_useTestTCP": 0, + "_testTCP": 0, + "_initializeAdvisories": 0, + "_synchronizeAdvisories": 0, + "_getLocalAdvisoryDirectoryPath": 0, + "_getStormAdvisoryNames": 0, + "_loadLastTwoAdvisories": 0, + "_loadAdvisory": 0, + "_getAdvisoryPath": 0, + "_getAdvisoryFilename": 0, + "_processVariableList": 0, + "_GUI_sizing_dict": 0, + "_GUI1_configDict": 0, + "_font_GUI_dict": 0, - # SectionCommon + #Overview_Dialog + "body": 0, + "_makeButtons": 0, + "okCB": 0, + + #Common_Dialog + "getVarDict": 0, + "_makeRadioOrCheckList": 0, + "_makeEntry": 0, + "cancelCB": 0, + "_entryName": 0, + "_makeTuple": 0, + "_setVarDict": 0, + "status": 0, + "buttonbox": 0, + + #SectionCommon "_setProductPartValue": 0, "_finalSectionParts": 0, "_sectionHeader": 0, "_lifePropertyThreatSummary": 0, "_getThreatTrendSentence": 0, - "_getThreatTrendValue": 1, - "_threatDifference": 1, - "_isThreatDecreasing": 1, - "_isThreatIncreasing": 1, + "_getThreatTrendValue": 0, + "_threatDifference": 0, + "_isThreatDecreasing": 0, + "_isThreatIncreasing": 0, "_advisoryHasValidKey": 0, "_isMagnitudeIncreasing": 1, "_calculateThreatStatementTr": 0, @@ -118,17 +184,18 @@ class TextProduct(HLSTCV_Common.TextProduct): "_potentialImpactsStatements": 0, "_getPotentialImpactsStatements": 0, "_preparationStatement": 0, - - # Unique to each section, but common method name + + #Unique to each section, but common method name + "sectionParts": 0, + "_forecastSubsection": 0, + "_latestForecastSummary": 0, "_threatSubsection": 0, "_threatTrend": 0, "_threatStatements": 0, "_impactsSubsection": 0, + "_setStats": 1, - # WindSection - "sectionParts": 0, - "_forecastSubsection": 0, - "_latestForecastSummary": 0, + #WindSection "_peakWind": 0, "_windowTS": 0, "_windowHU": 0, @@ -136,54 +203,38 @@ class TextProduct(HLSTCV_Common.TextProduct): "_ktToMph": 0, "_increment": 0, - # StormSurgeSection - "sectionParts": 0, - "_forecastSubsection": 0, - "_latestForecastSummary": 1, + #StormSurgeSection "_peakSurge": 0, "_surgeWindow": 1, - "_lifePropertyThreatSummary": 0, - "_potentialImpactsSummary": 0, - # FloodingRainSection - "sectionParts": 0, - "_forecastSubsection": 0, - "_latestForecastSummary": 0, + #FloodingRainSection "_peakRain": 0, "_rainRange": 0, - - # TornadoSection - "sectionParts": 0, - "_forecastSubsection": 0, - "_latestForecastSummary": 0, - - # SectionCommonStats - "_initializeAdvisories": 0, + + #SectionCommonStats + "_initializeSegmentAdvisories": 0, "_updateThreatStats": 0, "_calculateHourOffset": 0, - - # Common to all SectionStats classes - "_setStats": 1, - # WindsSectionStats + #WindSectionStats "_updateStatsForPwsXXint": 0, "_updateStatsForPwsTXX": 1, - "windSpdProb_thresholds": 0, "_updateWindTimeInfo": 0, "_computeWindOnsetAndEnd": 1, "_createWindow": 1, - - # XMLFormatter + + #Unique to each formatter, but common method name "execute": 0, + + #XMLFormatter "xmlKeys": 0, "sectionKeys": 0, "getSectionKey": 0, "dictionary": 0, "list": 0, - # LegacyFormatter + #LegacyFormatter "_processProductParts": 0, - "_noOpParts": 0, "processWmoHeader": 0, "processProductHeader": 0, "processLocationsAffected": 0, @@ -192,12 +243,26 @@ class TextProduct(HLSTCV_Common.TextProduct): "processImpactsStatements": 0, "processInfoSection": 0, "_buildInfoSection": 0, - "formatIssueTime": 0, "processSummaryHeadlines": 0, "processSubParts": 0, + + #TextProductCommon + "setUp": 0, + "hazardTimeZones": 0, + "getExpireTime": 0, + "getHeadlinesAndSections": 0, + "formatUGCs": 0, + "getFormattedTime": 0, + "formatUGC_names": 0, + "formatNameString": 0, + "getVal": 0, + "formatDatetime": 0, + "flush": 0, + "makeUGCString": 0, + "checkLastArrow": 0, } # Definition["debug"] = 1 # turn on ALL debug messages -# Definition["debug"] = 0 # turn off ALL debug messages + Definition["debug"] = 0 # turn off ALL debug messages def __init__(self): @@ -206,42 +271,37 @@ class TextProduct(HLSTCV_Common.TextProduct): ##################################################################### ##################################################################### ### Organization of Formatter Code - + ############################################################### ### MUST OVERRIDE DEFINITIONS !!! ### _inlandAreas, _coastalAreas, _cwa ############################################################### + ############################################################### + ### TCV Product and Segment Parts Definition + ############################################################### + ############################################################### ### Analysis Lists, SampleAnalysis Overrides and other ### analysis related methods ############################################################### - ############################################################### - ### TCV Product and Segment Parts Definition - ############################################################### - - ############################################################### - ### Hazards and Additional Hazards - ### allowedHazards is used for VTEC records and summary - ### headlines - ### allowedHeadlines are additional hazards reported in - ### certain sections - ############################################################### - ############################################################### # CODE ############################################################### ### High level flow of formatter - ### generateForecast, initializeVariables, - ### determineSegments, determineTimeRanges, sampleData, - ### createProductDictionary, formatProductDictionary, - ### archiveCurrentAdvisory... + ### generateForecast, _initializeVariables, + ### _determineSegments, _determineTimeRanges, _sampleData, + ### _createProductDictionary, _formatProductDictionary, + ### _archiveCurrentAdvisory ############################################################### ############################################################### - ### Product Dictionary methods for creating the dictionary, - ### formatting the dictionary and populating product parts + ### Product Parts Implementation + ############################################################### + + ############################################################### + ### Sampling and Statistics related methods ############################################################### ############################################################### @@ -252,18 +312,10 @@ class TextProduct(HLSTCV_Common.TextProduct): ### Hazards related methods ############################################################### - ############################################################### - ### Sampling and Statistics related methods - ############################################################### - ############################################################### ### Time related methods ############################################################### - ############################################################### - ### Storm Information and TCP related methods - ############################################################### - ############################################################### ### Advisory related methods ############################################################### @@ -271,8 +323,8 @@ class TextProduct(HLSTCV_Common.TextProduct): ############################################################### ### GUI related methods ############################################################### - - + + ############################################################### ### MUST OVERRIDE DEFINITIONS !!! @@ -290,56 +342,6 @@ class TextProduct(HLSTCV_Common.TextProduct): def _cwa(self): return "" #"MFL" - ############################################################### - ### Analysis Lists, SampleAnalysis Overrides and other - ### analysis related methods - - def _analysisList(self): - # Sample over 120 hours beginning at current time - analysisList = [ - # Wind Section - ("Wind", self.vectorModeratedMax, [6]), - ("WindGust", self.moderatedMax, [6]), - ("WindThreat", self.mostSignificantDiscreteValue), - ("pws34int", self.moderatedMax, [6]), - ("pws64int", self.moderatedMax, [6]), - ("pwsD34", self.moderatedMax), - ("pwsN34", self.moderatedMax), - ("pwsD64", self.moderatedMax), - ("pwsN64", self.moderatedMax), -# ("pwsD34", self.moderatedMax, [0]), -# ("pwsN34", self.moderatedMax, [0]), -# ("pwsD64", self.moderatedMax, [0]), -# ("pwsN64", self.moderatedMax, [0]), - - # Flooding Rain Section - ("QPF", self.accumSum, [72]), - ("FloodingRainThreat", self.mostSignificantDiscreteValue), - - # Tornado Section - ("TornadoThreat", self.mostSignificantDiscreteValue), - ] - - return analysisList - - def _intersectAnalysisList(self): - # The grids for the Surge Section will be intersected with a special edit area - analysisList = [ - ("InundationMax", self.moderatedMax, [6]), - ("InundationTiming", self.moderatedMax, [6]), - ("StormSurgeThreat", self.mostSignificantDiscreteValue), - ] - - return analysisList - - def _extraRainfallAnalysisList(self): - # The grids for the Surge Section will be intersected with a special edit area - analysisList = [ - ("QPF", self.accumSum), - ] - - return analysisList - ############################################################### ### TCV Product and Segment Parts Definition @@ -390,23 +392,69 @@ class TextProduct(HLSTCV_Common.TextProduct): 'arguments': segment_vtecRecords_tuple, 'partsList': partsList } + + ############################################################### + ### Analysis Lists, SampleAnalysis Overrides and other + ### analysis related methods + + def _analysisList(self): + # Sample over 120 hours beginning at current time + analysisList = [ + # Wind Section + ("Wind", self.vectorModeratedMax, [6]), + ("WindGust", self.moderatedMax, [6]), + ("WindThreat", self.mostSignificantDiscreteValue), + ("pws34int", self.moderatedMax, [6]), + ("pws64int", self.moderatedMax, [6]), + ("pwsD34", self.moderatedMax), + ("pwsN34", self.moderatedMax), + ("pwsD64", self.moderatedMax), + ("pwsN64", self.moderatedMax), + + # Flooding Rain Section + ("QPF", self.accumSum, [72]), + ("FloodingRainThreat", self.mostSignificantDiscreteValue), + + # Tornado Section + ("TornadoThreat", self.mostSignificantDiscreteValue), + ] + return analysisList + + def _intersectAnalysisList(self): + # The grids for the Surge Section will be intersected with a special edit area + analysisList = [ + ("InundationMax", self.moderatedMax, [6]), + ("InundationTiming", self.moderatedMax, [6]), + ("StormSurgeThreat", self.mostSignificantDiscreteValue), + ] + + return analysisList + + def _extraRainfallAnalysisList(self): + analysisList = [ + ("QPF", self.accumSum), + ] + + return analysisList + ############################################################### ### High level flow of formatter def generateForecast(self, argDict): - import pprint - pp = pprint.PrettyPrinter() - self.debug_print("argDict = %s" % (pp.pformat(argDict)), 1) - # Generate Text Phrases for a list of edit areas + + self.debug_print("argDict = %s" % (self._pp.pformat(argDict)), 1) error = self._initializeVariables(argDict) if error is not None: return error + if self._stormName is None or self._stormName.strip() == "": + return "Could not determine the storm name" + self._segmentList = self._determineSegments() - self.debug_print("Segment Information: %s" % (repr(self._segmentList)), 1) + self.debug_print("Segment Information: %s" % (self._pp.pformat(self._segmentList)), 1) if len(self._segmentList) == 0: return "NO HAZARDS TO REPORT" @@ -417,34 +465,17 @@ class TextProduct(HLSTCV_Common.TextProduct): self._sampleData(argDict) # Create the product dictionary and format it to create the output - productDict = self._createProductDictionary() - productOutput = self._formatProductDictionary(productDict) + productDict = self._createProductDictionary(self._segmentList) + productOutput = self._formatProductDictionary(LegacyFormatter, productDict) self._archiveCurrentAdvisory() return productOutput def _initializeVariables(self, argDict): - # Get variables - error = self._getVariables(argDict) + error = HLSTCV_Common.TextProduct._initializeVariables(self, argDict) if error is not None: return error - - self._backupFullStationID = self._fullStationID - self._argDict = argDict - - argDict["definition"] = self._definition - - self._initializeTimeVariables(argDict) - - self._initializeHazardsTable(argDict) - - error = self._initializeStormInformation() - if error is not None: - return error - - if self._stormName is None or self._stormName.strip() == "": - return "Could not determine the storm name" self._windSection = dict() self._stormSurgeSection = dict() @@ -453,41 +484,18 @@ class TextProduct(HLSTCV_Common.TextProduct): self._initializeAdvisories() - # Set up the areaDictionary for all to use - accessor = ModuleAccessor.ModuleAccessor() - self._areaDict = accessor.variable(self._areaDictionary, "AreaDictionary") - self._tpc = HLSTCV_Common.TextProductCommon() - self._tpc.setUp(self._areaDict) - return None ############################################################### - ### Product Dictionary methods + ### Product Parts Implementation - def _createProductDictionary(self): - # Create the product dictionary - productSegmentGroup = self._groupSegments(self._segmentList) - - productDict = self._initializeProductDict(productSegmentGroup) - productParts = productSegmentGroup.get('productParts') - productDict['productParts'] = productParts - self._processProductParts(self, productDict, productSegmentGroup, productParts) - self._wrapUpProductDict(productDict) - - return productDict + def _noOpParts(self): + ''' + These represent product parts that should be skipped when calling product part methods. + They will be handled automatically by the formatters. + ''' + return ['CR', 'endProduct', 'endSegment', 'doubleAmpersand'] - def _formatProductDictionary(self, productDict): - legacyFormatter = LegacyFormatter(self) - product = legacyFormatter.execute(productDict) -# xmlFormatter = XMLFormatter(self) -# product = xmlFormatter.execute(productDict) - - return product - - ###################################################### - # Populate Product Parts for HLS and TCV - ###################################################### - ################# Product Level def _easMessage(self, productDict, productSegmentGroup, arguments=None): @@ -497,9 +505,9 @@ class TextProduct(HLSTCV_Common.TextProduct): def _setup_segment(self, segmentDict, productSegmentGroup, productSegment): segment, vtecRecords = productSegment - self.debug_print('setup_segment productSegment %s' % (repr(productSegment)), 1) - # NOTE -- using getVtecRecords to change to milliseconds - self._segmentVtecRecords = self.getVtecRecords(segment) + self.debug_print('setup_segment productSegment %s' % (self._pp.pformat(productSegment)), 1) + # NOTE -- using _getVtecRecords to change to milliseconds + self._segmentVtecRecords = self._getVtecRecords(segment) # UGCs and Expire Time # Assume that the geoType is the same for all hazard events in the segment i.e. area or point @@ -525,11 +533,6 @@ class TextProduct(HLSTCV_Common.TextProduct): nonUPGrecords.append(record) self._summaryHeadlines_value, self._headlines = self._tpc.getHeadlinesAndSections( nonUPGrecords, self._productID, self._issueTime_secs) - - def _ugcHeader(self, segmentDict, productSegmentGroup, productSegment): - segmentDict['ugcCodes'] = self._formatUGC_entries() - self._ugcHeader_value = self._tpc.formatUGCs(self._ugcs, self._expireTime) - segmentDict['ugcHeader'] = self._ugcHeader_value def _vtecRecords(self, segmentDict, productSegmentGroup, productSegment): segment, vtecRecords = productSegment @@ -538,14 +541,14 @@ class TextProduct(HLSTCV_Common.TextProduct): vstr = None vstr = vtecRecord["vtecstr"] - self.debug_print("vtecRecord = %s" % (repr(vtecRecord)), 1) + self.debug_print("vtecRecord = %s" % (self._pp.pformat(vtecRecord)), 1) # Post-process some VTEC codes which should not exist vstr = vstr.replace(".EXT.", ".CON.") vstr = vstr.replace(".EXB.", ".EXA.") if vtecRecord["phen"] == "SS": - # SARAH: Temporary? Change the vtec mode for SS hazards to be experimental + # Temporary? Change the vtec mode for SS hazards to be experimental vstr = vstr[0] + 'X' + vstr[2:] records.append(vstr) segmentDict['vtecRecords'] = records @@ -553,38 +556,10 @@ class TextProduct(HLSTCV_Common.TextProduct): def _areaList(self, segmentDict, productSegmentGroup, productSegment): # Area String segmentDict['areaList'] = self._tpc.formatUGC_names(self._ugcs) - - def _locationsAffected(self, segmentDict, productSegmentGroup, productSegment): - segment, vtecRecords = productSegment - import TCVAreaDictionary - tcv_AreaDictionary = TCVAreaDictionary.TCV_AreaDictionary - - segmentDict['locationsAffected'] = [] - if segment in tcv_AreaDictionary: - segmentDict['locationsAffected'] += tcv_AreaDictionary[segment]["locationsAffected"] - - def _fcstConfidence(self, segmentDict, productSegmentGroup, productSegment): - # SARAH: TODO - Get this from the TCM product potentially? Not included until provided from NHC - return "" - def _infoSection(self, segmentDict, productSegmentGroup, productSegment): - segment, vtecRecords = productSegment - import TCVAreaDictionary - tcv_AreaDictionary = TCVAreaDictionary.TCV_AreaDictionary - - segment, vtecRecords = productSegment - infoSection = [] - if segment in tcv_AreaDictionary: - infoSection = tcv_AreaDictionary[segment]["infoSection"] - - segmentDict['infoSection'] = infoSection - - def _endSection(self, segmentDict, productSegmentGroup, productSegment): - segmentDict['endSection'] = "\n$$" - def _issuanceTimeDate(self, segmentDict, productSegmentGroup, productSegment): segmentDict['issuanceTimeDate'] = self._timeLabel - + def _summaryHeadlines(self, segmentDict, productSegmentGroup, productSegment): segment, vtecRecords = productSegment numRecords = len(vtecRecords) @@ -615,291 +590,37 @@ class TextProduct(HLSTCV_Common.TextProduct): summaryDict['headlinesInEffect'] = headlinesInEffect summaryDict['headlineDefinitions'] = definitions segmentDict['summaryHeadlines'] = summaryDict - - ###################################################### - # Product Part processing - ###################################################### - - def _processProductParts(self, productGenerator, productDict, productSegmentGroup, productParts): - ''' - @param productDict - @param productSegmentGroup - @param productParts - @return product dictionary created from the product parts - - Note that this method is called recursively such that a product part is allowed to be - a set of subParts specified as follows: - (subPartLabel, list of productParts for each subPart) - For example, we have - ('segments', [list of [segment product parts]]) - - # Product Dictionary - # Contains information for all formats e.g. - # partner XML, CAP, and Legacy text - ''' - - - if type(productParts) is types.DictType: - arguments = productParts.get('arguments') - partsList = productParts.get('partsList') - else: - partsList = productParts - - removedParts = [] - for part in partsList: - if type(part) is types.TupleType: - # e.g. subPart == 'segments', subPartsLists == list of parts for each segment - subPart, subPartsLists = part - subParts = [] - for subPartsList in subPartsLists: - subDict = collections.OrderedDict() - self._processProductParts(productGenerator, subDict, productSegmentGroup, subPartsList) - subParts.append(subDict) - # e.g. productDict['segments'] = segment dictionaries - productDict[subPart] = subParts - else: - if part not in self._noOpParts(): - execString = 'productGenerator._'+part+'(productDict, productSegmentGroup, arguments)' - exec execString - if part not in productDict: - removedParts.append(part) - - for part in removedParts: - partsList.remove(part) - - def _noOpParts(self): - ''' - These represent product parts that should be skipped when calling product part methods. - They will be handled automatically by the formatters. - ''' - return ['CR', 'endProduct', 'endSegment', 'doubleAmpersand'] - ###################################################### - # Product Dictionary -- General product information - ###################################################### - - def _initializeProductDict(self, productSegmentGroup): - ''' - Set up the Product Dictionary for the given Product consisting of a - group of segments. + def _locationsAffected(self, segmentDict, productSegmentGroup, productSegment): + segment, vtecRecords = productSegment + import TCVAreaDictionary + tcv_AreaDictionary = TCVAreaDictionary.TCV_AreaDictionary - Fill in the dictionary information for the product header. - - @param productSegmentGroup: holds meta information about the product - @return initialized product dictionary - - *********** - Example segmented product: - - WGUS63 KBOU 080400 - FFABOU - - URGENT - IMMEDIATE BROADCAST REQUESTED - FLOOD WATCH - NATIONAL WEATHER SERVICE DENVER CO - 400 AM GMT TUE FEB 8 2011 - - Overview Headline - Overview - - *********** - Example non-segmented product: - WGUS63 KBOU 080400 - FFWBOU - - ''' - self._productID = productSegmentGroup.get('productID', 'NNN') - if self._areaName != '': - self._areaName = ' FOR ' + self._areaName + '\n' - self._geoType = productSegmentGroup.get('geoType') - self._mapType = productSegmentGroup.get('mapType') - self._productTimeZones = [] - - # Fill in product dictionary information - productDict = collections.OrderedDict() - productDict['productID'] = self._productID - return productDict - - def _wrapUpProductDict(self, productDict): - productDict['sentTimeZ'] = self._convertToISO(self._issueTime_ms) - productDict['sentTimeZ_datetime'] = self._convertToDatetime(self._issueTime_ms) - productDict['sentTimeLocal'] = self._convertToISO(self._issueTime_ms, local=True) - productDict['timeZones'] = self._productTimeZones - return productDict - - ############################################################### - ### Area, Zone and Segment related methods + segmentDict['locationsAffected'] = [] + if segment in tcv_AreaDictionary: + segmentDict['locationsAffected'] += tcv_AreaDictionary[segment]["locationsAffected"] - def _groupSegments(self, segmentsWithHazards): - ''' - Group the segments into the products - return a list of productSegmentGroup dictionaries - ''' + def _fcstConfidence(self, segmentDict, productSegmentGroup, productSegment): + # TODO - Get this from the TCM product potentially? Not included until provided from NHC + return "" + + def _infoSection(self, segmentDict, productSegmentGroup, productSegment): + segment, vtecRecords = productSegment + import TCVAreaDictionary + tcv_AreaDictionary = TCVAreaDictionary.TCV_AreaDictionary + + segment, vtecRecords = productSegment + infoSection = [] + if segment in tcv_AreaDictionary: + infoSection = tcv_AreaDictionary[segment]["infoSection"] - segment_vtecRecords_tuples = [] - - # We need to preserve the ordering of the zones based off the zone combiner ordering - sortedAreas = sorted(self._allAreas(), - key=lambda x: segmentsWithHazards.index(x) if x in segmentsWithHazards else 9999) - for segment in sortedAreas: - self._initializeSegmentZoneData(segment) - - # We need stats for all zones to be saved in the advisory, - # regardless of whether or not it has a hazard in it - windStats, stormSurgeStats, floodingRainStats, tornadoStats = \ - self._getStats(self._argDict, segment, self._editAreaDict, self._timeRangeList) - - # Only show zones with hazards in the output - if segment in segmentsWithHazards: - vtecRecords = self.getVtecRecords(segment) - segment_vtecRecords_tuples.append((segment, vtecRecords)) - - self._windSection[segment] = WindSection(self, segment, windStats) - self._stormSurgeSection[segment] = StormSurgeSection(self, segment, stormSurgeStats) - self._floodingRainSection[segment] = FloodingRainSection(self, segment, floodingRainStats) - self._tornadoSection[segment] = TornadoSection(self, segment, tornadoStats) + segmentDict['infoSection'] = infoSection - productSegmentGroup = { - 'productID' : 'TCV', - 'productName': self._productName, - 'geoType': 'area', - 'vtecEngine': self._hazardsTable, - 'mapType': 'publicZones', - 'segmented': True, - 'productParts': self._productParts_TCV(segment_vtecRecords_tuples), - } - - return productSegmentGroup + def _endSection(self, segmentDict, productSegmentGroup, productSegment): + segmentDict['endSection'] = "\n$$" - def _makeSegmentEditAreas(self, argDict): - areasList = self._allAreas() - #self.debug_print("areaList = %s" % (repr(areasList)), 1) - editAreas = [] - self._editAreaDict = {} - for area in areasList: - self._editAreaDict[area] = area - editAreas.append((area, area)) - return editAreas + ################# Product Parts Helper Methods - def _determineSegments(self): - # Get the segments based on hazards "overlaid" with combinations file - - # Get the segments resulting from Hazards - #self.debug_print("\nRaw Analyzed %s" % (repr(self._hazardsTable.rawAnalyzedTable())), 1) - hazSegments = self.organizeHazards(self._hazardsTable.rawAnalyzedTable()) - #self.debug_print("\nSegments from HazardsTable organizeHazards %s" % (repr(hazSegments)), 1) - - # Get the forecaster entered combinations - accessor = ModuleAccessor.ModuleAccessor() -# self.debug_print("self._defaultEditAreas = %s" % (repr(self._defaultEditAreas)), 1) - combos = accessor.variable(self._defaultEditAreas, "Combinations") - if combos is None: - LogStream.logVerbose("COMBINATION FILE NOT FOUND: " + self._defaultEditAreas) - return [], None - #self.debug_print("\nSegments from Zone Combiner = %s" % (repr(combos)), 1) - # "Overlay" the forecaster-entered combinations onto the segments - segmentList = self._refineSegments(hazSegments, combos) - #self.debug_print("\nNew segments = %s" % (repr(segmentList)), 1) - - # Instead of a segment being a group of zones, it will be just a single zone. - # So collapse this list of lists down to a list of zones (aka. segments) - segments = [] - for segment in segmentList: - segments += segment - - return segments - - def _refineSegments(self, hazSegments, combos): - """Break down each segment further according to combos given. - Make sure the resulting segments follow the ordering of the combos. - """ - if combos == []: - return hazSegments - newSegments = [] # list of lists - newAreas = [] - for combo, label in combos: - # Each combination will be tested to see if it can stay intact - # i.e. if all areas in the combo are in the same segment - # else split it into like segments - # - # segmentMapping is a list where each entry is - # the hazSegment in which the corresponding combo area appears. - # (We need to define self._segmentList for the mapping function - # to use) - self._segmentList = hazSegments - #self.debug_print("self._segmentList = %s" % (repr(self._segmentList)), 1) - segmentMapping = map(self._findSegment, combo) - #self.debug_print(" segmentMapping = %s" % (repr(segmentMapping)), 1) - - # segmentDict keys will be the hazSegments and - # we will gather all the areas of the combos that appear - # in each of these hazSegments - segmentDict = {} - keyList = [] - for areaName in combo: - #self.debug_print(" Adding %s" % (areaName), 1) - key = tuple(segmentMapping[combo.index(areaName)]) - if key == (): # If no hazard for area, do not include - continue - if key not in keyList: - keyList.append(key) - segmentDict.setdefault(key,[]).append(areaName) - #self.debug_print(" segmentDict = %s" % (repr(segmentDict)), 1) - - # Keep track of the areas that we are including - for key in keyList: - segAreas = segmentDict[key] - newAreas = newAreas + segAreas - newSegments.append(segAreas) - #self.debug_print(" newSegments = %s" % (repr(newSegments)), 1) - # Now add in the hazAreas that have not been accounted for - # in the combinations - for hazSegment in hazSegments: - newSeg = [] - for hazArea in hazSegment: - if hazArea not in newAreas: - newSeg.append(hazArea) - if newSeg != []: - newSegments.append(newSeg) - return newSegments - - def _findSegment(self, areaName): - for segment in self._segmentList: - if areaName in segment: - return segment - return [] - - def _formatUGC_entries(self): - ugcCodeList = [] - for ugc in self._ugcs: - areaDictEntry = self._areaDict.get(ugc) - if areaDictEntry is None: - # We are not localized correctly for the hazard - # So get the first dictionary entry - self.logger.info('Not Localized for the hazard area -- ugc' + ugc) - keys = self._areaDict.keys() - areaDictEntry = self._areaDict.get(keys[0]) - ugcEntry = collections.OrderedDict() - ugcEntry['state'] = areaDictEntry.get('stateAbbr') - ugcEntry['type'] = self._getUgcInfo(ugc, 'type') - ugcEntry['number'] = self._getUgcInfo(ugc, 'number') - ugcEntry['text'] = ugc - ugcEntry['subArea'] = '' - ugcCodeList.append(ugcEntry) - return ugcCodeList - - def _getUgcInfo(self, ugc, part='type'): - if part == 'type': - if ugc[2] == 'C': - return 'County' - else: - return 'Zone' - if part == 'number': - return ugc[3:] - - ############################################################### - ### Hazards related methods - def _hazardDefinition(self, phenSig): if phenSig == "HU.W": return "A HURRICANE WARNING MEANS HURRICANE WIND CONDITIONS ARE " + \ @@ -925,6 +646,9 @@ class TextProduct(HLSTCV_Common.TextProduct): ############################################################### ### Sampling and Statistics related methods + def _threatKeyOrder(self): + return [None, "None", "Elevated", "Mod", "High", "Extreme"] + def _sampleData(self, argDict): # Sample the data editAreas = self._makeSegmentEditAreas(argDict) @@ -955,13 +679,11 @@ class TextProduct(HLSTCV_Common.TextProduct): timeRangeList, editArea) - import pprint - pp = pprint.PrettyPrinter() - self.debug_print("*"*80) + self.debug_print("*"*80, 1) for index in range(len(timeRangeList)): self.debug_print("editArea =" + editArea, 1) - self.debug_print("timeRange = %s" % (pp.pformat(timeRangeList[index])), 1) - self.debug_print("statList = %s" % (pp.pformat(statList[index])), 1) + self.debug_print("timeRangeList = %s" % (self._pp.pformat(timeRangeList[index])), 1) + self.debug_print("statList = %s" % (self._pp.pformat(statList[index])), 1) self.debug_print("-"*40, 1) # These stats are for handling the extra rainfall @@ -987,6 +709,185 @@ class TextProduct(HLSTCV_Common.TextProduct): return (windStats, stormSurgeStats, floodingRainStats, tornadoStats) + ############################################################### + ### Area, Zone and Segment related methods + + def _determineSegments(self): + # Get the segments based on hazards "overlaid" with combinations file + + # Get the segments resulting from Hazards + self.debug_print("Raw Analyzed %s" % (self._pp.pformat(self._hazardsTable.rawAnalyzedTable())), 1) + hazSegments = self.organizeHazards(self._hazardsTable.rawAnalyzedTable()) + self.debug_print("Segments from HazardsTable organizeHazards %s" % (self._pp.pformat(hazSegments)), 1) + + # Get the forecaster entered combinations + accessor = ModuleAccessor.ModuleAccessor() + self.debug_print("self._defaultEditAreas = %s" % (self._pp.pformat(self._defaultEditAreas)), 1) + combos = accessor.variable(self._defaultEditAreas, "Combinations") + if combos is None: + LogStream.logVerbose("COMBINATION FILE NOT FOUND: " + self._defaultEditAreas) + return [], None + self.debug_print("Segments from Zone Combiner = %s" % (self._pp.pformat(combos)), 1) + # "Overlay" the forecaster-entered combinations onto the segments + segmentList = self._refineSegments(hazSegments, combos) + self.debug_print("New segments = %s" % (self._pp.pformat(segmentList)), 1) + + # Instead of a segment being a group of zones, it will be just a single zone. + # So collapse this list of lists down to a list of zones (aka. segments) + segments = [] + for segment in segmentList: + segments += segment + + return segments + + def _refineSegments(self, hazSegments, combos): + """Break down each segment further according to combos given. + Make sure the resulting segments follow the ordering of the combos. + """ + if combos == []: + return hazSegments + newSegments = [] # list of lists + newAreas = [] + for combo, label in combos: + # Each combination will be tested to see if it can stay intact + # i.e. if all areas in the combo are in the same segment + # else split it into like segments + # + # segmentMapping is a list where each entry is + # the hazSegment in which the corresponding combo area appears. + # (We need to define self._segmentList for the mapping function + # to use) + self._segmentList = hazSegments + self.debug_print("self._segmentList = %s" % (self._pp.pformat(self._segmentList)), 1) + segmentMapping = map(self._findSegment, combo) + self.debug_print(" segmentMapping = %s" % (self._pp.pformat(segmentMapping)), 1) + + # segmentDict keys will be the hazSegments and + # we will gather all the areas of the combos that appear + # in each of these hazSegments + segmentDict = {} + keyList = [] + for areaName in combo: + self.debug_print(" Adding %s" % (areaName), 1) + key = tuple(segmentMapping[combo.index(areaName)]) + if key == (): # If no hazard for area, do not include + continue + if key not in keyList: + keyList.append(key) + segmentDict.setdefault(key,[]).append(areaName) + self.debug_print(" segmentDict = %s" % (self._pp.pformat(segmentDict)), 1) + + # Keep track of the areas that we are including + for key in keyList: + segAreas = segmentDict[key] + newAreas = newAreas + segAreas + newSegments.append(segAreas) + self.debug_print(" newSegments = %s" % (self._pp.pformat(newSegments)), 1) + # Now add in the hazAreas that have not been accounted for + # in the combinations + for hazSegment in hazSegments: + newSeg = [] + for hazArea in hazSegment: + if hazArea not in newAreas: + newSeg.append(hazArea) + if newSeg != []: + newSegments.append(newSeg) + return newSegments + + def _groupSegments(self, segmentsWithHazards): + ''' + Group the segments into the products + return a list of productSegmentGroup dictionaries + ''' + + segment_vtecRecords_tuples = [] + + # We need to preserve the ordering of the zones based off the zone combiner ordering + sortedAreas = sorted(self._allAreas(), + key=lambda x: segmentsWithHazards.index(x) if x in segmentsWithHazards else 9999) + for segment in sortedAreas: + self._initializeSegmentZoneData(segment) + + # We need stats for all zones to be saved in the advisory, + # regardless of whether or not it has a hazard in it + windStats, stormSurgeStats, floodingRainStats, tornadoStats = \ + self._getStats(self._argDict, segment, self._editAreaDict, self._timeRangeList) + + # Only show zones with hazards in the output + if segment in segmentsWithHazards: + vtecRecords = self._getVtecRecords(segment) + segment_vtecRecords_tuples.append((segment, vtecRecords)) + + self._windSection[segment] = WindSection(self, segment, windStats) + self._stormSurgeSection[segment] = StormSurgeSection(self, segment, stormSurgeStats) + self._floodingRainSection[segment] = FloodingRainSection(self, segment, floodingRainStats) + self._tornadoSection[segment] = TornadoSection(self, segment, tornadoStats) + + productSegmentGroup = { + 'productID' : 'TCV', + 'productName': self._productName, + 'geoType': 'area', + 'vtecEngine': self._hazardsTable, + 'mapType': 'publicZones', + 'segmented': True, + 'productParts': self._productParts_TCV(segment_vtecRecords_tuples), + } + + return productSegmentGroup + + def _makeSegmentEditAreas(self, argDict): + areasList = self._allAreas() + self.debug_print("areasList = %s" % (self._pp.pformat(areasList)), 1) + editAreas = [] + self._editAreaDict = {} + for area in areasList: + self._editAreaDict[area] = area + editAreas.append((area, area)) + return editAreas + + def _findSegment(self, areaName): + for segment in self._segmentList: + if areaName in segment: + return segment + return [] + + ############################################################### + ### Hazards related methods + + def _getAllVTECRecords(self): + allRecords = [] + for segment in self._segmentList: + allRecords += self._getVtecRecords(segment) + + return allRecords + + def _getHazardsForHLS(self): + hazardTable = self._argDict["hazards"] + + + hazSegments = self.organizeHazards(hazardTable.rawAnalyzedTable()) + self.debug_print("Segments from HazardsTable organizeHazards %s" % + (self._pp.pformat(hazSegments)), 1) + + combos = [([self._allAreas()], "AllAreas")] + + self.debug_print("Segments from Zone Combiner %s" % (self._pp.pformat(combos)), 1) + # "Overlay" the forecaster-entered combinations onto the segments + segmentList = self._refineSegments(hazSegments, combos) + self.debug_print("SegmentList from refineSegments = %s" % + (self._pp.pformat(segmentList)), 1) + + allHazards = [] + for segment in segmentList: + hazardsList = hazardTable.getHazardList(segment) + for hazard in hazardsList: + if hazard['act'] == 'COR': + return self._previousAdvisory["HazardsForHLS"] + else: + allHazards.append(hazard) + + return allHazards + ############################################################### ### Time related methods @@ -1003,43 +904,21 @@ class TextProduct(HLSTCV_Common.TextProduct): import datetime return datetime.datetime.fromtimestamp(time_ms / 1000) - ############################################################### - ### GUI related methods - - def _overview_list(self): - return [ - { - "name": "StormInfo", - "label": "Obtain Storm Type/Name/Info", - "options": [ - "TCPAT1", "TCPAT2", "TCPAT3", "TCPAT4", "TCPAT5", - "Enter PIL below (e.g. TCPEP1):", - ], - "entryField": " ", - }, - { - "name": "PopulateSurge", - "label": "Populate Surge Section", - "options": [ - ("Populate", True), - ("Do not populate", False), - ], - "default": "None", - }, - ] - - def _displayGUI(self, infoDict=None): - dialog = Overview_Dialog(self, "TCV", infoDict) - status = dialog.status() - LogStream.logVerbose("status="+status) - if status == "Cancel": - return None - else: - return dialog.getVarDict() - ############################################################### ### Advisory related methods + def _initializeSegmentZoneData(self, segment): + # The current advisory will be populated when setting a section's stats + self._currentAdvisory['ZoneData'][segment] = { + "WindThreat": None, + "WindForecast": None, + "StormSurgeThreat": None, + "StormSurgeForecast": None, + "FloodingRainThreat": None, + "FloodingRainForecast": None, + "TornadoThreat": None, + } + def _archiveCurrentAdvisory(self): ### Determine if all actions are canceled allCAN = True @@ -1081,43 +960,50 @@ class TextProduct(HLSTCV_Common.TextProduct): advisoryDict["HazardsForHLS"] = newList try: - JsonSupport.saveToJson(LocalizationType.CAVE_STATIC, + JsonSupport.saveToJson(LocalizationSupport.CAVE_STATIC, self._site, fileName, advisoryDict) - self.debug_print("SARAH: Wrote file contents for: %s" % (fileName), 1) + self.debug_print("Wrote file contents for: %s" % (fileName), 1) self._synchronizeAdvisories() except Exception, e: - self.debug_print("SARAH Save Exception for %s : %s" % (fileName, e), 1) + self.debug_print("Save Exception for %s : %s" % (fileName, e), 1) - def _getHazardsForHLS(self): - hazardTable = self._argDict["hazards"] + ############################################################### + ### GUI related methods + + def _overview_list(self): + return [ + { + "name": "StormInfo", + "label": "Obtain Storm Type/Name/Info", + "options": [ + "TCPAT1", "TCPAT2", "TCPAT3", "TCPAT4", "TCPAT5", + "Enter PIL below (e.g. TCPEP1):", + ], + "entryField": " ", + }, + { + "name": "PopulateSurge", + "label": "Populate Surge Section", + "options": [ + ("Populate", True), + ("Do not populate", False), + ], + "default": "None", + }, + ] - - hazSegments = self.organizeHazards(hazardTable.rawAnalyzedTable()) - self.debug_print("Segments from HazardsTable organizeHazards %s" % - (repr(hazSegments)), 1) - - combos = [([self._allAreas()], "AllAreas")] - - self.debug_print("Segments from Zone Combiner %s" % (repr(combos)), 1) - # "Overlay" the forecaster-entered combinations onto the segments - segmentList = self._refineSegments(hazSegments, combos) - self.debug_print("SegmentList from refineSegments = %s" % - (repr(segmentList)), 1) - - allHazards = [] - for segment in segmentList: - hazardsList = hazardTable.getHazardList(segment) - for hazard in hazardsList: - if hazard['act'] == 'COR': - return self._previousAdvisory["HazardsForHLS"] - else: - allHazards.append(hazard) - - return allHazards + def _displayGUI(self, infoDict=None): + dialog = Overview_Dialog(self, "TCV", infoDict) + status = dialog.status() + LogStream.logVerbose("status="+status) + if status == "Cancel": + return None + else: + return dialog.getVarDict() import Tkinter class Overview_Dialog(HLSTCV_Common.Common_Dialog): @@ -1255,7 +1141,7 @@ class SectionCommon(): self._setProductPartValue(segmentDict, 'lifePropertyThreatSummary', "Threat to Life and Property: " + threatLevel) - # SARAH - this new method will convert the single word threat trend into + # This new method will convert the single word threat trend into # an appropriate sentence def _getThreatTrendSentence(self, section, threatTrendValue): @@ -1272,10 +1158,10 @@ class SectionCommon(): threatKey = elementName + "Threat" forecastKey = elementName + "Forecast" - self._textProduct.debug_print("SARAH: THREAT DEBUG for %s" % elementName, 1) + self._textProduct.debug_print("THREAT DEBUG for %s" % (elementName), 1) - self._textProduct.debug_print("SARAH: getThreatTrendValue _currentAdvisory =\n%s" % (repr(self._stats._currentAdvisory)), 1) - self._textProduct.debug_print("SARAH: getThreatTrendValue _previousAdvisory =\n%s" % (repr(self._stats._previousAdvisory)), 1) + self._textProduct.debug_print("getThreatTrendValue _currentAdvisory =\n%s" % (self._textProduct._pp.pformat(self._stats._currentAdvisory)), 1) + self._textProduct.debug_print("getThreatTrendValue _previousAdvisory =\n%s" % (self._textProduct._pp.pformat(self._stats._previousAdvisory)), 1) if (self._stats._currentAdvisory is None) or (self._stats._previousAdvisory is None): # Only compute a threat trend if we have 2 or more advisories @@ -1285,26 +1171,26 @@ class SectionCommon(): previousThreat = self._stats._previousAdvisory[threatKey] shorterTermTrendDifference = self._threatDifference(currentThreat, previousThreat) - self._textProduct.debug_print("SARAH: currentThreat = %s" % currentThreat, 1) - self._textProduct.debug_print("SARAH: previousThreat = %s" % previousThreat, 1) - self._textProduct.debug_print("SARAH: shorterTermTrendDifference = %s" % shorterTermTrendDifference, 1) + self._textProduct.debug_print("currentThreat = %s" % (self._textProduct._pp.pformat(currentThreat)), 1) + self._textProduct.debug_print("previousThreat = %s" % (self._textProduct._pp.pformat(previousThreat)), 1) + self._textProduct.debug_print("shorterTermTrendDifference = %s" % (shorterTermTrendDifference), 1) previousPreviousThreat = None longerTermTrendDifference = None if self._stats._previousPreviousAdvisory is not None: - self._textProduct.debug_print("SARAH: _previousPreviousAdvisory is not None", 1) + self._textProduct.debug_print("_previousPreviousAdvisory is not None", 1) previousPreviousThreat = self._stats._previousPreviousAdvisory[threatKey] - self._textProduct.debug_print("SARAH: previousPreviousThreat = %s" % previousPreviousThreat, 1) + self._textProduct.debug_print("previousPreviousThreat = %s" % (self._textProduct._pp.pformat(previousPreviousThreat)), 1) longerTermTrendDifference = self._threatDifference(currentThreat, previousPreviousThreat) - self._textProduct.debug_print("SARAH: longerTermTrendDifference = %s" % longerTermTrendDifference, 1) + self._textProduct.debug_print("longerTermTrendDifference = %s" % (longerTermTrendDifference), 1) threatTrendValue = "NEARLY STEADY" self._textProduct.debug_print("magnitudeIncreaseThreshold = %s forecastKey = '%s'" % (magnitudeIncreaseThreshold, forecastKey), 1) if self._isThreatDecreasing(shorterTermTrendDifference, longerTermTrendDifference): - self._textProduct.debug_print("SARAH: threat is decreasing", 1) + self._textProduct.debug_print("threat is decreasing", 1) threatTrendValue = "DECREASING" elif self._isThreatIncreasing(shorterTermTrendDifference, longerTermTrendDifference): - self._textProduct.debug_print("SARAH: threat is increasing", 1) + self._textProduct.debug_print("threat is increasing", 1) threatTrendValue = "INCREASING" elif currentThreat == "Extreme" and \ self._isMagnitudeIncreasing(forecastKey, magnitudeIncreaseThreshold): @@ -1314,9 +1200,9 @@ class SectionCommon(): return threatTrendValue def _threatDifference(self, threat1, threat2): - threatLevels = self._textProduct.threatKeyOrder() - self._textProduct.debug_print("SARAH: threat1 index = %s" % threatLevels.index(threat1), 1) - self._textProduct.debug_print("SARAH: threat2 index = %s" % threatLevels.index(threat2), 1) + threatLevels = self._textProduct._threatKeyOrder() + self._textProduct.debug_print("threat1 index = %s" % (threatLevels.index(threat1)), 1) + self._textProduct.debug_print("threat2 index = %s" % (threatLevels.index(threat2)), 1) return threatLevels.index(threat1) - threatLevels.index(threat2) def _isThreatDecreasing(self, shorterTermTrendDifference, longerTermTrendDifference): @@ -1324,14 +1210,14 @@ class SectionCommon(): if (shorterTermTrendDifference < 0 and \ longerTermTrendDifference is not None and \ longerTermTrendDifference < 0): - self._textProduct.debug_print("SARAH: the current threat is at least 1 category lower than both previous advisories", 1) + self._textProduct.debug_print("the current threat is at least 1 category lower than both previous advisories", 1) return True #Or if the current threat decreased by more than 1 category elif shorterTermTrendDifference < -1: - self._textProduct.debug_print("SARAH: the current threat decreased by more than 1 category", 1) + self._textProduct.debug_print("the current threat decreased by more than 1 category", 1) return True else: - self._textProduct.debug_print("SARAH: the current threat is not decreasing", 1) + self._textProduct.debug_print("the current threat is not decreasing", 1) return False def _isThreatIncreasing(self, shorterTermTrendDifference, longerTermTrendDifference): @@ -1339,14 +1225,14 @@ class SectionCommon(): if (shorterTermTrendDifference > 0 and \ longerTermTrendDifference is not None and \ longerTermTrendDifference > 0): - self._textProduct.debug_print("SARAH: the current threat is at least 1 category higher than both previous advisories", 1) + self._textProduct.debug_print("the current threat is at least 1 category higher than both previous advisories", 1) return True #Or if the current threat increased by more than 1 category elif shorterTermTrendDifference > 1: - self._textProduct.debug_print("SARAH: the current threat increased by more than 1 category", 1) + self._textProduct.debug_print("the current threat increased by more than 1 category", 1) return True else: - self._textProduct.debug_print("SARAH: the current threat is not increasing", 1) + self._textProduct.debug_print("the current threat is not increasing", 1) return False def _advisoryHasValidKey(self, advisory, key): @@ -1356,43 +1242,43 @@ class SectionCommon(): def _isMagnitudeIncreasing(self, forecastKey, threshold): # currentValue, previousValue, previousPreviousValue - self._textProduct.debug_print("SARAH: _isMagnitudeIncreasing", 1) - self._textProduct.debug_print("SARAH: forecastKey = %s" % forecastKey, 1) - self._textProduct.debug_print("SARAH: threshold = %s" % threshold, 1) + self._textProduct.debug_print("_isMagnitudeIncreasing", 1) + self._textProduct.debug_print("forecastKey = %s" % (forecastKey), 1) + self._textProduct.debug_print("threshold = %s" % (threshold), 1) if self._advisoryHasValidKey(self._stats._currentAdvisory, forecastKey) and \ self._advisoryHasValidKey(self._stats._previousAdvisory, forecastKey): currentValue = self._stats._currentAdvisory[forecastKey] previousValue = self._stats._previousAdvisory[forecastKey] - self._textProduct.debug_print("SARAH: currentValue = %s" % currentValue, 1) - self._textProduct.debug_print("SARAH: previousValue = %s" % previousValue, 1) + self._textProduct.debug_print("currentValue = %s" % (currentValue), 1) + self._textProduct.debug_print("previousValue = %s" % (previousValue), 1) if (currentValue - previousValue) >= threshold: - self._textProduct.debug_print("SARAH: the current magnitude has increased by more than the threshold since the last advisory", 1) + self._textProduct.debug_print("the current magnitude has increased by more than the threshold since the last advisory", 1) return True elif self._advisoryHasValidKey(self._stats._previousPreviousAdvisory, forecastKey): previousPreviousValue = self._stats._previousPreviousAdvisory[forecastKey] - self._textProduct.debug_print("SARAH: previousPreviousValue = %s" % previousPreviousValue, 1) + self._textProduct.debug_print("previousPreviousValue = %s" % (previousPreviousValue), 1) if (currentValue - previousPreviousValue) >= threshold: - self._textProduct.debug_print("SARAH: the current magnitude has increased by more than the threshold since the previous previous advisory", 1) + self._textProduct.debug_print("the current magnitude has increased by more than the threshold since the previous previous advisory", 1) return True else: - self._textProduct.debug_print("SARAH: the current magnitude does not meet the requirements to be considered increasing", 1) + self._textProduct.debug_print("the current magnitude does not meet the requirements to be considered increasing", 1) return False else: - self._textProduct.debug_print("SARAH: the current magnitude did not increase past threshold and could not look at the previous previous advisory", 1) + self._textProduct.debug_print("the current magnitude did not increase past threshold and could not look at the previous previous advisory", 1) return False else: - self._textProduct.debug_print("SARAH: the current advisory and/or previous advisory did not have key: %s" % forecastKey, 1) + self._textProduct.debug_print("the current advisory and/or previous advisory did not have key: %s" % (forecastKey), 1) return False def _calculateThreatStatementTr(self, onsetHour, endHour, threatTrendValue): tr = None - self._textProduct.debug_print("SARAH: onset hour = %s" % (onsetHour), 1) - self._textProduct.debug_print("SARAH: end hour = %s" % (endHour), 1) - self._textProduct.debug_print("SHANNON: threatTrendValue = %s" % + self._textProduct.debug_print("onset hour = %s" % (onsetHour), 1) + self._textProduct.debug_print("end hour = %s" % (endHour), 1) + self._textProduct.debug_print("threatTrendValue = %s" % (threatTrendValue), 1) if (onsetHour is not None) and \ @@ -1413,8 +1299,8 @@ class SectionCommon(): def _setThreatStatementsProductParts(self, segmentDict, productSegment, tr): - self._textProduct.debug_print("SHANNON: tr = %s %s" % - (repr(tr), self._sectionHeaderName), 1) + self._textProduct.debug_print("tr = %s %s" % + (self._textProduct._pp.pformat(tr), self._sectionHeaderName), 1) # if tr is not None and self._stats._maxThreat is not None: if tr is not None: (planning, action, preparation) = self._getThreatStatements(productSegment, @@ -1425,7 +1311,7 @@ class SectionCommon(): self._setProductPartValue(segmentDict, 'threatStatements', [planning, action, preparation]) else: - self._textProduct.debug_print("SHANNON messed up", 1) + self._textProduct.debug_print("this is not a valid time range", 1) return def _getThreatStatements(self, productSegment, sectionName, maxThreat, tr): @@ -1441,7 +1327,7 @@ class SectionCommon(): self._textProduct.debug_print(40*"-", 1) self._textProduct.debug_print("sectionName = %s, maxThreat = %s, tr = %s" % - (sectionName, maxThreat, repr(tr)), 1) + (sectionName, maxThreat, self._textProduct._pp.pformat(tr)), 1) # if maxThreat is None: # maxThreat = "None" @@ -1473,7 +1359,7 @@ class SectionCommon(): return "Potential Impacts: " + impactLevel def _potentialImpactsStatements(self, segmentDict, productSegmentGroup, productSegment): - self._textProduct.debug_print("SHANNON: segment = %s, elementName = %s, maxThreat = %s" % + self._textProduct.debug_print("segment = %s, elementName = %s, maxThreat = %s" % (productSegment[0], self._sectionHeaderName, self._stats._maxThreat), 1) if self._stats._maxThreat is not None: statements = self._getPotentialImpactsStatements(productSegment, self._sectionHeaderName, self._stats._maxThreat) @@ -1490,7 +1376,7 @@ class SectionCommon(): segment, vtecRecords = productSegment - self._textProduct.debug_print("SHANNON: zone number = %s, elementName = %s, maxThreat = %s" % + self._textProduct.debug_print("zone number = %s, elementName = %s, maxThreat = %s" % (segment, elementName, maxThreat), 1) if segment in tcv_AreaDictionary: @@ -1601,7 +1487,7 @@ class WindSection(SectionCommon): if self._stats._maxGust is not None: moderatedMaxWindGust = self._ktToMph(self._stats._maxGust, "WindGust") -# # SARAH - we want to round the wind gust to the nearest 5 kt +# # We want to round the wind gust to the nearest 5 kt # moderatedMaxWindGust = \ # self._textProduct.round(moderatedMaxWindGust, "Nearest", 5) @@ -1642,7 +1528,8 @@ class WindSection(SectionCommon): windTr = self._calculateThreatStatementTr(self._stats._onset34Hour, self._stats._end34Hour, self._threatTrendValue) -# self._textProduct.debug_print("MATT: in _threatStatements tr = %s" % (repr(windTr)) + self._textProduct.debug_print("in _threatStatements tr = %s" % + (self._textProduct._pp.pformat(windTr)), 1) if not hasattr(self._textProduct, "_windThreatStatementsTr"): self._textProduct._windThreatStatementsTr = dict() @@ -1659,7 +1546,7 @@ class WindSection(SectionCommon): # if len(subsectionDict) > 0: # self._setProductPartValue(segmentDict, 'impactsSubsection', subsectionDict) - # SARAH - modified to not include wind impacts during the "recovery" and + # Modified to not include wind impacts during the "recovery" and # "nothing to see here" phases of the tropical cyclone event def _impactsSubsection(self, segmentDict, productSegmentGroup, productSegment): @@ -1773,7 +1660,7 @@ class StormSurgeSection(SectionCommon): words = str(int(max - maxRange)) + "-" + str(int(max)) + " feet above ground" elif max > 0: - # SARAH - we were getting really weird values of peak surge + # We were getting really weird values of peak surge # (e.g. "UP TO 1.70000004768 FEET"). This fix will round up # to the nearest integer value # words = "Up to " + str(max) + " feet above ground" @@ -1820,7 +1707,7 @@ class StormSurgeSection(SectionCommon): threatTrendSentence) def _threatStatements(self, segmentDict, productSegmentGroup, productSegment): - self._textProduct.debug_print("SARAH: Surge Threat Statements", 1) + self._textProduct.debug_print("Surge Threat Statements", 1) surgeTr = self._calculateThreatStatementTr(self._stats._onsetSurgeHour, self._stats._endSurgeHour, self._threatTrendValue) @@ -1840,7 +1727,7 @@ class StormSurgeSection(SectionCommon): def _potentialImpactsSummary(self, segmentDict, productSegmentGroup, productSegment): if not self._textProduct._PopulateSurge: - # SARAH - We do not want the '(For plausible worst case)' in the text + # We do not want the '(For plausible worst case)' in the text # self._setProductPartValue(segmentDict, 'potentialImpactsSummary', # "Potential Impacts (For plausible worst case): Not available at this time. To be updated shortly.") self._setProductPartValue(segmentDict, 'potentialImpactsSummary', @@ -2049,36 +1936,36 @@ class SectionCommonStats(): self._textProduct = textProduct self._segment = segment - self._initializeAdvisories() + self._initializeSegmentAdvisories() self._maxThreat = None - def _initializeAdvisories(self): + def _initializeSegmentAdvisories(self): self._currentAdvisory = self._textProduct._currentAdvisory['ZoneData'][self._segment] self._previousAdvisory = None -# self._textProduct.debug_print("MATT textProduct._previousAdvisory = '%s'" % (textProduct._previousAdvisory)) + self._textProduct.debug_print("textProduct._previousAdvisory = '%s'" % (self._textProduct._previousAdvisory)) if self._textProduct._previousAdvisory is not None: if self._textProduct._previousAdvisory['ZoneData'].has_key(self._segment): self._previousAdvisory = self._textProduct._previousAdvisory['ZoneData'][self._segment] -# self._textProduct.debug_print("MATT textProduct._previousPreviousAdvisory = '%s'" % \ -# (textProduct._previousPreviousAdvisory)) + self._textProduct.debug_print("textProduct._previousPreviousAdvisory = '%s'" % \ + (self._textProduct._previousPreviousAdvisory)) self._previousPreviousAdvisory = None if self._textProduct._previousPreviousAdvisory is not None: self._previousPreviousAdvisory = self._textProduct._previousPreviousAdvisory['ZoneData'][self._segment] def _updateThreatStats(self, tr, statDict, threatGridName): - self._textProduct.debug_print("statDict = '%s'" % (repr(statDict)), 1) + self._textProduct.debug_print("statDict = '%s'" % (self._textProduct._pp.pformat(statDict)), 1) threatLevel = self._textProduct.getStats(statDict, threatGridName) if threatLevel is not None: - threatLevels = self._textProduct.threatKeyOrder() - self._textProduct.debug_print("SARAH: updateThreatStats for %s" % (threatGridName), 1) - self._textProduct.debug_print("SARAH: threatLevel = %s" % (threatLevel), 1) - self._textProduct.debug_print("SARAH: maxThreat = %s" % (self._maxThreat), 1) + threatLevels = self._textProduct._threatKeyOrder() + self._textProduct.debug_print("updateThreatStats for %s" % (threatGridName), 1) + self._textProduct.debug_print("threatLevel = %s" % (threatLevel), 1) + self._textProduct.debug_print("maxThreat = %s" % (self._maxThreat), 1) if self._maxThreat is None or \ threatLevels.index(threatLevel) > threatLevels.index(self._maxThreat): - self._textProduct.debug_print("SARAH: updating max threat to = %s" % (threatLevel), 1) + self._textProduct.debug_print("updating max threat to = %s" % (threatLevel), 1) self._maxThreat = threatLevel def _calculateHourOffset(self, targetTime): @@ -2101,8 +1988,8 @@ class WindSectionStats(SectionCommonStats): self._windowTS = None self._windowHU = None - print "*"*90 - print "Setting wind stats for %s" % (segment) + self._textProduct.debug_print("*"*90) + self._textProduct.debug_print("Setting wind stats for %s" % (segment), 1) self._setStats(statList, timeRangeList) @@ -2115,7 +2002,6 @@ class WindSectionStats(SectionCommonStats): dropFirstGridType = None droppedFirstGrid = False periodWithFirstCorrectGrid = None - onsetTime = None endTime = None class TimeInfo(): @@ -2140,6 +2026,7 @@ class WindSectionStats(SectionCommonStats): statDict = statList[index] for periodIndex, periodTr in enumerate(self._textProduct._periodList): + self._textProduct.debug_print("\n\nperiodIndex = %d periodList tr = %s" % (periodIndex, repr(periodTr)), 1) if (periodIndex == 0) and (tr.startTime().unixTime() < periodTr.startTime().unixTime()): # If the tr is before the first period, use the first period currentPeriod = periodIndex @@ -2174,7 +2061,7 @@ class WindSectionStats(SectionCommonStats): self._onset34Hour = onsetEndInfo.onsetHour self._end34Hour = onsetEndInfo.endHour - self._textProduct.debug_print("SARAH: Tropical Storm Window:", 1) + self._textProduct.debug_print("Tropical Storm Window:", 1) self._windowTS = self._createWindow("Tropical Storm", self._onset34Hour, self._end34Hour) @@ -2184,7 +2071,7 @@ class WindSectionStats(SectionCommonStats): self._onset64Hour = onsetEndInfo.onsetHour self._end64Hour = onsetEndInfo.endHour - self._textProduct.debug_print("SARAH: Hurricane Window:", 1) + self._textProduct.debug_print("Hurricane Window:", 1) self._windowHU = self._createWindow("Hurricane", self._onset64Hour, self._end64Hour) @@ -2200,68 +2087,84 @@ class WindSectionStats(SectionCommonStats): pwsXXintStats.max = pwsXXint pwsXXintStats.onsetHour = self._calculateHourOffset(tr.startTime()) - self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats gridName = %s" % (gridName), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats onsetHour = %s" % (pwsXXintStats.onsetHour), 1) + self._textProduct.debug_print("Wind Window Debug: pwsXXintStats gridName = %s" % (gridName), 1) + self._textProduct.debug_print("Wind Window Debug: pwsXXintStats onsetHour = %s" % (pwsXXintStats.onsetHour), 1) def _updateStatsForPwsTXX(self, tr, statDict, dayGridName, nightGridName, pwsTXXStats, period): pwsDXX = self._textProduct._getStatValue(statDict, dayGridName, "Max") pwsNXX = self._textProduct._getStatValue(statDict, nightGridName, "Max") if pwsTXXStats.firstRun: - self._textProduct.debug_print("SARAH: first run for _updateStatsForPwsTXX!", 1) - self._textProduct.debug_print("SARAH: grids: %s %s" % (dayGridName, nightGridName), 1) + self._textProduct.debug_print("first run for _updateStatsForPwsTXX!", 1) + self._textProduct.debug_print("grids: %s %s" % (dayGridName, nightGridName), 1) pwsTXXStats.firstRun = False localtime = time.localtime(self._textProduct._issueTime_secs) - self._textProduct.debug_print("SARAH: localtime = %s" % (localtime), 1) + self._textProduct.debug_print("localtime = %s" % (localtime), 1) if localtime.tm_hour >= 15: # 3PM to midnight - self._textProduct.debug_print("SARAH: between 3PM and midnight!", 1) + self._textProduct.debug_print("between 3PM and midnight!", 1) pwsTXXStats.dropFirstGridType = "DAY" - self._textProduct.debug_print("SARAH: need to drop the day grid(s) if they come first", 1) + self._textProduct.debug_print("need to drop the day grid(s) if they come first", 1) elif localtime.tm_hour >= 3 and localtime.tm_hour < 12: # 3AM to noon - self._textProduct.debug_print("SARAH: between 3AM and noon!", 1) + self._textProduct.debug_print("between 3AM and noon!", 1) pwsTXXStats.dropFirstGridType = "NIGHT" - self._textProduct.debug_print("SARAH: need to drop the night grid(s) if they come first", 1) + self._textProduct.debug_print("need to drop the night grid(s) if they come first", 1) else: - self._textProduct.debug_print("SARAH: not dropping any grids!", 1) + self._textProduct.debug_print("not dropping any grids!", 1) maxPws = None - self._textProduct.debug_print("MATT %s pwsDXX = %s pwsNXX = %s " % - (repr(tr),pwsDXX, pwsNXX), 1) + self._textProduct.debug_print("%s pwsDXX = %s pwsNXX = %s " % + (self._textProduct._pp.pformat(tr),pwsDXX, pwsNXX), 1) - if pwsDXX is not None: - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats DAY", 1) + # Determine coversion factor to get DAY and NIGHT in UTC + utcHourOffset = self._calculateUTCandLocalHourOffset() + + # See if this hour a valid DAYtime hour + isValidDay = self._isValidDayTime(tr.startTime().hour, + self._textProduct.DAY() + utcHourOffset, + self._textProduct.NIGHT() + utcHourOffset) + + # If we have pwsD data, and this is a time period it applies to + if pwsDXX is not None and isValidDay: + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats DAY", 1) if pwsTXXStats.dropFirstGridType == "DAY": - self._textProduct.debug_print("SARAH: Window Debug: dropping a day grid", 1) - self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) + self._textProduct.debug_print("Wind Window Debug: dropping a day grid", 1) + self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1) pwsTXXStats.droppedFirstGrid = True return elif pwsTXXStats.dropFirstGridType == "NIGHT": # We dropped all the necessary grids now that we found a day grid so stop dropping pwsTXXStats.dropFirstGridType = None pwsTXXStats.periodWithFirstCorrectGrid = period - self._textProduct.debug_print("SARAH: Window Debug: found day grid; done dropping night grids", 1) - self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) + self._textProduct.debug_print("Wind Window Debug: found day grid; done dropping night grids", 1) + self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1) maxPws = pwsDXX - elif pwsNXX is not None: - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats NIGHT", 1) + # If we have pwsN data, and this is a time period it applies to + elif pwsNXX is not None and not isValidDay: + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats NIGHT", 1) if pwsTXXStats.dropFirstGridType == "NIGHT": - self._textProduct.debug_print("SARAH: Window Debug: dropping a night grid", 1) - self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) + self._textProduct.debug_print("Wind Window Debug: dropping a night grid", 1) + self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1) pwsTXXStats.droppedFirstGrid = True return elif pwsTXXStats.dropFirstGridType == "DAY": # We dropped all the necessary grids now that we found a night grid so stop dropping pwsTXXStats.dropFirstGridType = None pwsTXXStats.periodWithFirstCorrectGrid = period - self._textProduct.debug_print("SARAH: Window Debug: found night grid; done dropping day grids", 1) - self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) + self._textProduct.debug_print("Wind Window Debug: found night grid; done dropping day grids", 1) + self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1) maxPws = pwsNXX + + elif pwsDXX is not None and tr.startTime().hour in [21, 0, 3]: + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats DAY ignored", 1) + + elif pwsNXX is not None and tr.startTime().hour in [9, 12, 15]: + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats NIGHT ignored", 1) threshold34index = 0 threshold64index = 1 @@ -2269,7 +2172,7 @@ class WindSectionStats(SectionCommonStats): # Don't shift if the period with the first correct grid is period 0 if pwsTXXStats.droppedFirstGrid and pwsTXXStats.periodWithFirstCorrectGrid != 0: period = period - 1 # We dropped the first grid so we are off-by-one - self._textProduct.debug_print("SARAH: shifting period back 1...new period = %s" % + self._textProduct.debug_print("shifting period back 1...new period = %s" % (period), 1) if "64" in dayGridName: @@ -2279,6 +2182,7 @@ class WindSectionStats(SectionCommonStats): threshold = None thresholds = self._textProduct.windSpdProb_thresholds(threshold, threshold) + self._textProduct.debug_print("Getting probability threshold for period %s" % (period), 1) if period == 0: (thresholdLow, thresholdHigh) = thresholds[period][index] threshold = thresholdLow @@ -2286,43 +2190,43 @@ class WindSectionStats(SectionCommonStats): threshold = thresholds[period][index] if maxPws > threshold: - pwsTXXStats.onsetTime = tr.startTime() pwsTXXStats.endTime = tr.endTime() - - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats dayGridName = %s" % (dayGridName), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats nightGridName = %s" % (nightGridName), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats original tr = %s" % (repr(tr)), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats maxPws = %s" %(repr(maxPws)), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats onsetTime = %s" % (repr(pwsTXXStats.onsetTime)), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats endTime = %s" % (repr(pwsTXXStats.endTime)), 1) + self._textProduct.debug_print("Wind Window Debug: probability threshold = %s (period index %s)" % (threshold, period), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats dayGridName = %s" % (dayGridName), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats nightGridName = %s" % (nightGridName), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats original tr = %s" % (self._textProduct._pp.pformat(tr)), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats maxPws = %s" %(self._textProduct._pp.pformat(maxPws)), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats endTime = %s" % (self._textProduct._pp.pformat(pwsTXXStats.endTime)), 1) def _updateWindTimeInfo(self, tr, wind, timeInfo, speed): if wind >= speed: timeInfo.endHour = self._calculateHourOffset(tr.endTime()) - self._textProduct.debug_print("SARAH: Window Debug: In _updateWindTimeInfo", 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo speed = %s" % (speed), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo tr = %s" % (repr(tr)), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo endHour = %s" % (timeInfo.endHour), 1) + self._textProduct.debug_print("Wind Window Debug: In _updateWindTimeInfo", 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo speed = %s" % (speed), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo tr = %s" % (self._textProduct._pp.pformat(tr)), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo endHour = %s" % (timeInfo.endHour), 1) if timeInfo.onsetHour is None: timeInfo.onsetHour = self._calculateHourOffset(tr.startTime()) - self._textProduct.debug_print("SARAH: Window Debug: onsetHour was None", 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo speed = %s" % (speed), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo tr = %s" % (repr(tr)), 1) - self._textProduct.debug_print("SARAH: Window Debug: timeInfo onsetHour = %s" % (timeInfo.onsetHour), 1) + self._textProduct.debug_print("Wind Window Debug: onsetHour was None", 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo speed = %s" % (speed), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo tr = %s" % (self._textProduct._pp.pformat(tr)), 1) + self._textProduct.debug_print("Wind Window Debug: timeInfo onsetHour = %s" % (timeInfo.onsetHour), 1) def _computeWindOnsetAndEnd(self, windTimeInfo, pwsXXintStats, pwsTXXStats): onsetEndInfo = self.TimeInfo() - self._textProduct.debug_print("SARAH: Window Debug: In _computeWindOnsetAndEnd", 1) - self._textProduct.debug_print("SARAH: Window Debug: windTimeInfo.onsetHour = %s" % (windTimeInfo.onsetHour), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats.onsetHour = %s" % (pwsXXintStats.onsetHour), 1) - self._textProduct.debug_print("SARAH: Window Debug: windTimeInfo.endHour = %s" % (windTimeInfo.endHour), 1) - self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats.endTime = %s" % (pwsTXXStats.endTime), 1) + self._textProduct.debug_print("Wind Window Debug: In _computeWindOnsetAndEnd", 1) + self._textProduct.debug_print("Wind Window Debug: windTimeInfo.onsetHour = %s" % (windTimeInfo.onsetHour), 1) + self._textProduct.debug_print("Wind Window Debug: pwsXXintStats.onsetHour = %s" % (pwsXXintStats.onsetHour), 1) + self._textProduct.debug_print("Wind Window Debug: windTimeInfo.endHour = %s" % (windTimeInfo.endHour), 1) + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats.endTime = %s" % (pwsTXXStats.endTime), 1) + if pwsTXXStats.endTime is not None: + self._textProduct.debug_print("Wind Window Debug: pwsTXXStats end hour = %s" % (self._calculateHourOffset(pwsTXXStats.endTime)), 1) if windTimeInfo.onsetHour is None: # We won't have a timing window @@ -2349,27 +2253,35 @@ class WindSectionStats(SectionCommonStats): self._textProduct.debug_print("endTime for pwsTXXStats is not None", 1) endUnixTime = pwsTXXStats.endTime.unixTime() endLocalTime = time.localtime(endUnixTime) - startUnixTime = pwsTXXStats.onsetTime.unixTime() - startLocalTime = time.localtime(startUnixTime) - - if endLocalTime.tm_hour >= 6 and endLocalTime.tm_hour < 18: - configuredTime = absTimeYMD(endLocalTime.tm_year, - endLocalTime.tm_mon, - endLocalTime.tm_mday, - self._textProduct.DAY()) - elif endLocalTime.tm_hour < 6: - # Use 6 PM of previous day - configuredTime = absTimeYMD(startLocalTime.tm_year, - startLocalTime.tm_mon, - startLocalTime.tm_mday, + utcHourOffset = self._calculateUTCandLocalHourOffset() + self._textProduct.debug_print("utcHourOffset = %s" % (utcHourOffset), 1) + self._textProduct.debug_print("endTime for pwsTXXStats in local time is %s" % + (self._textProduct._pp.pformat(endLocalTime)), 1) + + # Remember these times are in local time zone, so hour 0 is + # midnight of the current calendar day. + if endLocalTime.tm_hour > 6 and endLocalTime.tm_hour <= 18: + configuredTime = absTimeYMD(pwsTXXStats.endTime.year, + pwsTXXStats.endTime.month, + pwsTXXStats.endTime.day, self._textProduct.NIGHT()) else: - configuredTime = absTimeYMD(endLocalTime.tm_year, - endLocalTime.tm_mon, - endLocalTime.tm_mday, - self._textProduct.NIGHT()) + configuredTime = absTimeYMD(pwsTXXStats.endTime.year, + pwsTXXStats.endTime.month, + pwsTXXStats.endTime.day, + self._textProduct.DAY()) + self._textProduct.debug_print("configuredTime (local time) = %s" % + (self._textProduct._pp.pformat(configuredTime)), 1) + # The configured hour is localtime so we need to add an offset to make the entire date UTC + configuredUnixTime = configuredTime.unixTime() + (utcHourOffset * 3600) + configuredTime = AbsTime(configuredUnixTime) + self._textProduct.debug_print("configuredTime (UTC time) = %s" % + (self._textProduct._pp.pformat(configuredTime)), 1) + + probEndHour = self._calculateHourOffset(configuredTime) + onsetEndInfo.endHour = int(round(self._textProduct.average(windTimeInfo.endHour, probEndHour))) self._textProduct.debug_print("endHour = " + str(onsetEndInfo.endHour), 1) else: @@ -2380,13 +2292,13 @@ class WindSectionStats(SectionCommonStats): def _createWindow(self, windowName, onsetHour, endHour): window = "Window for " + windowName + " force winds: " - self._textProduct.debug_print("SARAH: In _createWindow", 1) - self._textProduct.debug_print("SARAH: window stats:", 1) - self._textProduct.debug_print("SARAH: onsetHour = %s" % (onsetHour), 1) - self._textProduct.debug_print("SARAH: endHour = %s" % (endHour), 1) + self._textProduct.debug_print("In _createWindow", 1) + self._textProduct.debug_print("window stats:", 1) + self._textProduct.debug_print("onsetHour = %s" % (onsetHour), 1) + self._textProduct.debug_print("endHour = %s" % (endHour), 1) if onsetHour is None: - # SARAH - we do not want a statement of a non-existent window + # We do not want a statement of a non-existent window # window += "None" window = None else: @@ -2396,7 +2308,7 @@ class WindSectionStats(SectionCommonStats): windowPeriod = self._textProduct.makeTimeRange(startTime, endTime) else: windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1) - self._textProduct.debug_print("SARAH: window period = %s" % (windowPeriod), 1) + self._textProduct.debug_print("window period = %s" % (windowPeriod), 1) startTimeDescriptor = "" if onsetHour >= 18: @@ -2429,6 +2341,33 @@ class WindSectionStats(SectionCommonStats): window += startTimeDescriptor + connector + endTimeDescriptor return window + + def _calculateUTCandLocalHourOffset(self): + utc = time.gmtime() + local = time.localtime() + + diffInSeconds = time.mktime(utc) - time.mktime(local) + return int(diffInSeconds // 3600) + + def _isValidDayTime(self, trStartHour, utcDay, utcNight): + + # Handle case where "night" starts at an "earlier" UTC hour than "day" + # (e.g. DAY = 18Z and NIGHT = 06Z) + if (utcNight < utcDay) and \ + (trStartHour >= utcDay or trStartHour < utcNight): + + # If we are toward the end of the daytime, and more than 1 hour + # from its end + if (trStartHour < utcNight) and (utcNight - trStartHour) > 1: + return True + + # Handle "normal" case where "day" starts before "night" in UTC + elif trStartHour >= utcDay and trStartHour < utcNight and \ + (utcNight - trStartHour) > 1: + return True + + # If we made it this far, this is not a valid "day" hour + return False class StormSurgeSectionStats(SectionCommonStats): @@ -2447,7 +2386,7 @@ class StormSurgeSectionStats(SectionCommonStats): possibleStop = 0 self._textProduct.debug_print("*"*100, 1) - self._textProduct.debug_print("MATT phishStartTime = %s phishEndTime = %s possibleStop = %d" % + self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s possibleStop = %d" % (str(phishStartTime), str(phishEndTime), possibleStop), 1) for period in range(len(statList)): @@ -2460,10 +2399,10 @@ class StormSurgeSectionStats(SectionCommonStats): self._inundationMax = phishPeak curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max") - self._textProduct.debug_print("MATT tr = %s" % (repr(tr)), 1) - self._textProduct.debug_print("MATT curPhish = '%s' possibleStop = %d" % + self._textProduct.debug_print("tr = %s" % (self._textProduct._pp.pformat(tr)), 1) + self._textProduct.debug_print("curPhish = '%s' possibleStop = %d" % (str(curPhish), possibleStop), 1) - self._textProduct.debug_print("MATT phishStartTime = %s phishEndTime = %s" % + self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s" % (str(phishStartTime), str(phishEndTime)), 1) if curPhish is not None and possibleStop != 2: @@ -2488,15 +2427,15 @@ class StormSurgeSectionStats(SectionCommonStats): self._onsetSurgeHour = self._calculateHourOffset(phishStartTime) startTime = AbsTime(self._textProduct._issueTime_secs + self._onsetSurgeHour*60*60) - self._textProduct.debug_print("MATT surge startTime = %s self._onsetSurgeHour = %s " % - (repr(startTime), self._onsetSurgeHour), 1) + self._textProduct.debug_print("surge startTime = %s self._onsetSurgeHour = %s " % + (self._textProduct._pp.pformat(startTime), self._onsetSurgeHour), 1) if phishEndTime is not None: self._endSurgeHour = self._calculateHourOffset(phishEndTime) endTime = AbsTime(self._textProduct._issueTime_secs + self._endSurgeHour*60*60) windowPeriod = self._textProduct.makeTimeRange(startTime, endTime) else: windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1) - self._textProduct.debug_print("SARAH: surge window period = %s" % (windowPeriod), 1) + self._textProduct.debug_print("surge window period = %s" % (windowPeriod), 1) startTimeDescriptor = self._textProduct._formatPeriod(windowPeriod) @@ -2564,7 +2503,7 @@ class FloodingRainSectionStats(SectionCommonStats): prevStatDict = extraRainfallStatList[period] prevStats = self._textProduct.getStats(prevStatDict, "QPF") - print "prevStats = ", prevStats + self._textProduct.debug_print("prevStats = %s" % (prevStats), 1) if prevStats is not None: self._prevAccum += prevStats else: @@ -2606,8 +2545,8 @@ class XMLFormatter(): def execute(self, productDict): xml = Element('product') self.dictionary(xml, productDict) - self._textProduct.debug_print("SARAH: XML = %s" % (xml), 1) - self._textProduct.debug_print("SARAH: XML dump = %s", dump(xml), 1) + self._textProduct.debug_print("XML = %s" % (xml), 1) + self._textProduct.debug_print("XML dump = %s", dump(xml), 1) prettyXML = minidom.parseString(tostring(xml)) return prettyXML.toprettyxml() #tostring(xml) @@ -2711,7 +2650,7 @@ class XMLFormatter(): if "._" in sectionKey: sectionKey = re.sub(".*\._", "", sectionKey) - self._textProduct.debug_print("SARAH: sectionKey = %s" % (sectionKey), 1) + self._textProduct.debug_print("sectionKey = %s" % (sectionKey), 1) return sectionKey def dictionary(self, xml, productDict): @@ -2731,7 +2670,7 @@ class XMLFormatter(): if key not in self.xmlKeys(): sectionKey = self.getSectionKey(key) if sectionKey not in self.sectionKeys(): - self._textProduct.debug_print("SARAH: skipping '%s' in XML" % (key), 1) + self._textProduct.debug_print("skipping '%s' in XML" % (key), 1) continue else: key = sectionKey @@ -2773,8 +2712,8 @@ class XMLFormatter(): if data is not None: if 'info' in key and 'Section' in key: subElement = SubElement(xml, key) - self._textProduct.debug_print("SARAH: info key = '%s'" % (key), 1) - self._textProduct.debug_print("SARAH: value = %s" % (data), 1) + self._textProduct.debug_print("info key = '%s'" % (key), 1) + self._textProduct.debug_print("value = %s" % (data), 1) if isinstance(data, list): subkey = 'info' + 'Sub' + key[4:] for value in data: @@ -2823,7 +2762,7 @@ class LegacyFormatter(): @return text -- product string ''' text = '' - self._textProduct.debug_print("productParts = %s" % (repr(productParts)), 1) + self._textProduct.debug_print("productParts = %s" % (self._textProduct._pp.pformat(productParts)), 1) for part in productParts: valtype = type(part) if valtype is str: @@ -3009,14 +2948,6 @@ class LegacyFormatter(): text += self._buildInfoSection(component, tabLevel+1) return text - def formatIssueTime(self): - text = '' - sentTimeZ = self._tpc.getVal(self.productDict, 'sentTimeZ_datetime') - timeZones = self._tpc.getVal(self.productDict, 'timeZones') - for timeZone in timeZones: - text += self._tpc.formatDatetime(sentTimeZ, '%I%M %p %Z %a %e %b %Y', timeZone) + '\n' - return text - def processSummaryHeadlines(self, summaryDict): text = "" for headline in summaryDict['headlinesInEffect']: @@ -3042,5 +2973,3 @@ class LegacyFormatter(): newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList')) text += newtext return text - - diff --git a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py index abefbfe7b1..82d2300a4e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py +++ b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py @@ -44,6 +44,7 @@ # May 15, 2014 2536 bclement moved WMO time parsing to WMOTimeParser # May 15, 2014 3157 dgilling Update location of WclInfo class. # Jun 10, 2014 3268 dgilling Update location of WclInfo class. +# Dec 17, 2014 4953 randerso Fixed decoding of non-VTEC from command line # # @@ -114,10 +115,10 @@ class StdWarningDecoder(): self._timeOffset = 0 #decode the command line - if text is None and filePath is None: + if command is not None: self._decodeCommandLine() self._rawMessage = None - checkForWmo = False + checkForWmo = True else: self._rawMessage = text checkForWmo = True diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/geospatialConfig_MARINE.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/geospatialConfig_MARINE.xml index 3b3531dda1..135a7f26a1 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/geospatialConfig_MARINE.xml +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/geospatialConfig_MARINE.xml @@ -13,6 +13,11 @@ THIS CHANGE WAS DONE SO THAT CONFIGURATIONS COULD BE MADE IN ONE LOCATION AND NOT ACROSS 20-30 TEMPLATES. A COUNTY-BASED and ZONE-BASED COUNTERPART EXISTS TO THIS FILE. + +SOFTWARE HISTORY +Date Ticket# Engineer Description +01/20/15 RM #14929 Qinglu Lin Changed false to true for tags in , + . --> @@ -96,10 +101,7 @@ AREA - - false + true 1 10.0 5 @@ -131,7 +133,7 @@ 1 AREA TRACK - false + true 10 10 @@ -154,7 +156,7 @@ 1 AREA TRACK - false + true 20 10 diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-ingest.xml b/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-ingest.xml index 5711041eb2..5fef97283c 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-ingest.xml @@ -42,6 +42,7 @@ + ${header?.notifygfe.booleanValue} diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java index 624e1c668b..7e712cffb1 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java @@ -34,7 +34,9 @@ import com.raytheon.uf.common.util.FileUtil; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 27, 2013 dgilling Initial creation + * Feb 27, 2013 dgilling Initial creation + * Dec 12, 2014 4953 randerso Added getCommonGfeIncludePath to allow use of + * LocalizationSupport in activetable python code * * * @@ -46,6 +48,8 @@ public class ActiveTablePyIncludeUtil extends PythonIncludePathUtil { public static final String GFE = "gfe"; + public static final String COMMON_GFE = FileUtil.join(PYTHON, GFE); + public static final String GFE_CONFIG = FileUtil.join("config", GFE); public static final String ISC = FileUtil.join(GFE, "isc"); @@ -74,4 +78,11 @@ public class ActiveTablePyIncludeUtil extends PythonIncludePathUtil { return PyUtil.buildJepIncludePath(siteDir, baseDir); } + public static String getCommonGfeIncludePath() { + String pythonDir = getCommonPythonIncludePath(); + String gfeDir = getPath(PATH_MANAGER.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE), + COMMON_GFE); + return PyUtil.buildJepIncludePath(pythonDir, gfeDir); + } } diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTableSrv.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTableSrv.java index 813d4344a4..caa176a2fe 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTableSrv.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTableSrv.java @@ -88,7 +88,7 @@ public class ActiveTableSrv { timer.start(); try { ActiveTable activeTable = threadLocalActiveTable.get(); - if (records != null && records.size() > 0) { + if ((records != null) && (records.size() > 0)) { activeTable.merge(ActiveTableRecord.transformFromWarnings( records, ActiveTableMode.OPERATIONAL)); } @@ -111,7 +111,7 @@ public class ActiveTableSrv { public void practiceVtecArrived(List records, Headers headers) { int offsetSeconds = getOffsetTime((String) headers.get("drtstring")); - if (records != null && records.size() > 0) { + if ((records != null) && (records.size() > 0)) { ActiveTable activeTable = threadLocalActiveTable.get(); try { activeTable.merge(ActiveTableRecord.transformFromWarnings( diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/decoder/PracticeVtecDecoder.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/decoder/PracticeVtecDecoder.java index 2f88b3ec59..05b1188fde 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/decoder/PracticeVtecDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/decoder/PracticeVtecDecoder.java @@ -46,6 +46,8 @@ import com.raytheon.uf.edex.python.decoder.PythonDecoder; * used for all practice VTEC products * Changed to take in the SendPracticeProductRequest * to simplify spring wiring + * Changed to set the filepath when calling Python decoder + * so _checkForVTEC will work * * * @@ -103,7 +105,7 @@ public class PracticeVtecDecoder extends PythonDecoder { // create an argument map to run the decoder Map decoderArgs = new HashMap(4); - decoderArgs.put("filePath", null); + decoderArgs.put("filePath", file.getAbsolutePath()); decoderArgs.put("command", sb.toString()); return decode(decoderArgs); diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/TCVUtil.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/TCVUtil.py new file mode 100644 index 0000000000..fe666be974 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/TCVUtil.py @@ -0,0 +1,79 @@ +## +# 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. +## +# +# Common utilities for sending/receiving TCV files +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 12/12/14 4953 randerso Initial Creation. +# +## +import glob, os, subprocess, time +import LocalizationSupport + +def getCaveStaticSiteDir(): + # this should return /awips2/edex/data/utility/cave_static/site + + import siteConfig + siteID = siteConfig.GFESUITE_SITEID + + siteDir = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, + siteID, "gfe").getFile() + siteDir = siteDir.getParentFile().getParentFile().getAbsolutePath() + return siteDir + +def purgeAllCanFiles(logger): + PURGE_AGE = 30 * 24 * 60 * 60 # 30 days in seconds + siteDir = getCaveStaticSiteDir() + + # purge allCan files older than PURGE_AGE + purgeTime = time.time() - PURGE_AGE + for f in glob.iglob(os.path.join(siteDir, "*/gfe/tcvAdvisories/*.allCAN")): + site = f.replace(siteDir,"").split("/")[1] + basename = os.path.basename(f) + try: + modTime = os.path.getmtime(f) + if modTime < purgeTime: + logger.debug("Purging "+basename+": "+time.strftime("%Y%m%d %H%M%S", time.gmtime(modTime))) + LocalizationSupport.deleteFile(LocalizationSupport.CAVE_STATIC, + LocalizationSupport.SITE, site, + "gfe/tcvAdvisories/" + basename) + except: + logger.exception("Unable to delete "+f) + +def packageTCVFiles(siteList, fileName, logger): + siteDir = getCaveStaticSiteDir() + cmd = "cd " + siteDir + "; tar cvzf " + fileName + + for siteID in siteList: + tcvDir = os.path.join(siteID, "gfe", "tcvAdvisories") + + for fileType in ["*.json", "*.allCAN"]: + path = os.path.join(tcvDir, fileType) + if len(glob.glob(os.path.join(siteDir, path))) > 0: + cmd += " " + path + + logger.debug("cmd: '" + cmd + "'") + subprocess.check_call([cmd], shell=True) + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py index 3409535112..d30168a103 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py @@ -57,7 +57,7 @@ VTEC_DECODER_SITES = [] # The following list is a set of product categories (e.g., ZFP, WOU) that # when decoded, the text for each segment is captured. The text is not # normally needed to be captured except for warning-style products. -VTEC_CAPTURE_TEXT_CATEGORIES = ['WSW', 'NPW', 'RFW', 'FFA', 'CFW', 'MWS', 'HLS', 'MWW'] +VTEC_CAPTURE_TEXT_CATEGORIES = ['WSW', 'NPW', 'RFW', 'FFA', 'CFW', 'MWS', 'HLS', 'MWW', 'TCV'] # Remapping of product pils. This is required for certain VTEC events # if a hazard is created in one pil and then updated or cancelled in another @@ -146,6 +146,7 @@ BackupDict = { 'HFO': ('GUM', 'MTR'), 'HGX': ('LCH', 'CRP'), 'HNX': ('STO', 'SGX'), + 'HPA': ('HFO', 'NH1'), 'HUN': ('JAN', 'BMX'), 'ICT': ('TOP', 'DDC'), 'ILM': ('CHS', 'MHX'), @@ -181,9 +182,13 @@ BackupDict = { 'MRX': ('OHX', 'FFC'), 'MSO': ('TFX', 'GGW'), 'MTR': ('LOX', 'EKA'), + 'NH1': ('NH2', 'ONP'), + 'NH2': ('NH1', 'ONA'), 'OAX': ('GID', 'FSD'), 'OHX': ('MRX', 'MEG'), 'OKX': ('BOX', 'PHI'), + 'ONA': ('ONP', 'NH2'), + 'ONP': ('ONA', 'NH1'), 'OTX': ('PDT', 'MSO'), 'OUN': ('TSA', 'FWD'), 'PAH': ('LMK', 'SGF'), @@ -221,10 +226,16 @@ BackupDict = { def get4ID(id): if id in ['SJU']: return "TJSJ" - elif id in ['AFG', 'AJK', 'HFO', 'GUM']: + elif id in ['AFG', 'AJK', 'GUM']: return "P" + id + elif id in ['HFO', 'HPA']: + return "PHFO" elif id in ['AER', 'ALU']: return "PAFC" + elif id in ['NH1', 'NH2']: + return "KNHC" + elif id in ['ONA', 'ONP']: + return "KWBC" else: return "K" + id diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestTCV.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestTCV.py new file mode 100644 index 0000000000..1a2df55c5e --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestTCV.py @@ -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. +## +# +# Request TCV Advisory Files +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 12/05/14 4953 randerso Initial Creation. +# +## +import os, errno, tempfile + +import xml +from xml.etree import ElementTree +from xml.etree.ElementTree import Element, SubElement + +import IrtAccess +import VTECPartners + +logger = None + +def init_logging(): + import iscUtil + import logging + global logger + logger = iscUtil.getLogger("requestTCV", logLevel=logging.DEBUG) + +def createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger): + #-------------------------------------------------------------------- + # Assemble XML source/destination document + #-------------------------------------------------------------------- + msgSendDest = [] #list of mhs sites to send request + + irt = IrtAccess.IrtAccess(ancf, bncf) + iscE = ElementTree.Element('isc') + # this is the requestor of the data + sourceServer = {'mhsid' : mhsid, + 'host' : host, + 'port' : port, + 'protocol': protocol, + 'site' : siteID} + irt.addSourceXML(iscE, sourceServer) + logger.info("Requesting Server: " + irt.printServerInfo(sourceServer)) + + # who is running the domains requested? + sites = VTECPartners.VTEC_TABLE_REQUEST_SITES + if not sites: + logger.error('No sites defined for VTEC_TABLE_REQUEST_SITES') + sys.exit(1) + + status, xml = irt.getServers(sites) + if not status: + logger.error('Failure to getServers from IRT') + sys.exit(1) + + # decode the XML + try: + serverTree = ElementTree.ElementTree(ElementTree.XML(xml)) + serversE = serverTree.getroot() + except: + logger.exception("Malformed XML on getServers()") + sys.exit(1) + + if serversE.tag != "servers": + logger.error("Servers packet missing from web server") + sys.exit(1) + + # process each requested domain returned to us + chosenServers = [] + matchingServers = [] + for domainE in serversE: + if domainE.tag != "domain": + continue + servers = [] #list of servers for this domain + + # decode each server in the domain + for addressE in domainE.getchildren(): + info = irt.decodeXMLAddress(addressE) + if info is None: + continue #not address tag + + # remove unneeded keys + for key in ['parms', 'area', 'domain']: + if info.has_key(key): + del info[key] + + servers.append(info) + matchingServers.append(info) + + # server search list in priority. The px3 entries are used for + # dual domain for AFC. + hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'), + ('px3', '98000001')] + + # choose one server from this domain, find first dx4, 98000000 + # try to use one with the same mhsidDest as the site, which + # would be the primary operational GFE. Note that the px3 entries + # are for AFC. + found = False + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort and server['mhsid'] == siteID: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + break + + # find first dx4, 98000000, but perhaps a different mhsid + # this is probably not the primary operational GFE + if not found: + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + break + + # if didn't find standard one, then take the first one, but don't + # take ourselves unless we are the only one. + if not found and servers: + for server in servers: + if server['mhsid'] != mhsid and server['host'] != host \ + and server['port'] != port and \ + server['mhsid'] != siteID: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + if not found: + chosenServers.append(server) + if servers[0]['mhsid'] not in msgSendDest: + msgSendDest.append(servers[0]['mhsid']) + + # Display the set of matching servers + s = "Matching Servers:" + for x in matchingServers: + s += "\n" + irt.printServerInfo(x) + logger.info(s) + + # Display the chosen set of servers + s = "Chosen Servers:" + for x in chosenServers: + s += "\n" + irt.printServerInfo(x) + logger.info(s) + + irt.addDestinationXML(iscE, chosenServers) + + return msgSendDest, iscE + +def runFromJava(siteID, config): + import siteConfig + host = str(config.getServerHost()) + port = str(config.getRpcPort()) + protocol = str(config.getProtocolVersion()) + mhsid = str(config.getMhsid()) + ancf = str(config.iscRoutingTableAddress().get("ANCF")) + bncf = str(config.iscRoutingTableAddress().get("BNCF")) + xmtScript = str(config.transmitScript()) + + init_logging() + + tempdir = os.path.join(siteConfig.GFESUITE_HOME, "products", "TCV") + try: + os.makedirs(tempdir, 0755) + except OSError, e: + if e.errno != errno.EEXIST: + logger.warn("%s: '%s'" % (e.strerror,e.filename)) + + try: + msgSendDest, xml = createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger) + # create the XML file + with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd: + fnameXML = fd.name + fd.write(ElementTree.tostring(xml)) + + # don't send to ourselves + if mhsid in msgSendDest: + msgSendDest.remove(mhsid) + + if len(msgSendDest) > 0: + # Now send the message + irt = IrtAccess.IrtAccess(ancf, bncf) + irt.transmitFiles("GET_TCV_FILES", msgSendDest, mhsid, [fnameXML], xmtScript) + except: + logger.exception('Error requesting TCV files for site: ' + siteID) diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendTCV.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendTCV.py new file mode 100644 index 0000000000..59e4c3b219 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendTCV.py @@ -0,0 +1,225 @@ +## +# 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. +## +# +# Send TCV Advisory Files to VTEC partners +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 12/05/14 4953 randerso Initial Creation. +# +## +import os, errno, tempfile + +import xml +from xml.etree import ElementTree +from xml.etree.ElementTree import Element, SubElement + +import IrtAccess +import TCVUtil +import VTECPartners + +logger = None + +def init_logging(): + import iscUtil + import logging + global logger + logger = iscUtil.getLogger("sendTCV", logLevel=logging.DEBUG) + + +def createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger): + #-------------------------------------------------------------------- + # Assemble XML source/destination document + #-------------------------------------------------------------------- + msgSendDest = [] #list of mhs sites to send request + + irt = IrtAccess.IrtAccess(ancf, bncf) + iscE = ElementTree.Element('isc') + # this is the requestor of the data + sourceServer = {'mhsid' : mhsid, + 'host' : host, + 'port' : port, + 'protocol': protocol, + 'site' : siteID} + irt.addSourceXML(iscE, sourceServer) + logger.info("Requesting Server: " + irt.printServerInfo(sourceServer)) + + # who is running the domains requested? + sites = VTECPartners.VTEC_TABLE_REQUEST_SITES + if not sites: + logger.error('No sites defined for VTEC_TABLE_REQUEST_SITES') + sys.exit(1) + + status, xml = irt.getServers(sites) + if not status: + logger.error('Failure to getServers from IRT') + sys.exit(1) + + # decode the XML + try: + serverTree = ElementTree.ElementTree(ElementTree.XML(xml)) + serversE = serverTree.getroot() + except: + logger.exception("Malformed XML on getServers()") + sys.exit(1) + + if serversE.tag != "servers": + logger.error("Servers packet missing from web server") + sys.exit(1) + + # process each requested domain returned to us + chosenServers = [] + matchingServers = [] + for domainE in serversE: + if domainE.tag != "domain": + continue + servers = [] #list of servers for this domain + + # decode each server in the domain + for addressE in domainE.getchildren(): + info = irt.decodeXMLAddress(addressE) + if info is None: + continue #not address tag + + # remove unneeded keys + for key in ['parms', 'area', 'domain']: + if info.has_key(key): + del info[key] + + servers.append(info) + matchingServers.append(info) + + # server search list in priority. The px3 entries are used for + # dual domain for AFC. + hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'), + ('px3', '98000001')] + + # choose one server from this domain, find first dx4, 98000000 + # try to use one with the same mhsidDest as the site, which + # would be the primary operational GFE. Note that the px3 entries + # are for AFC. + found = False + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort and server['mhsid'] == siteID: + if server['mhsid'] not in msgSendDest: + chosenServers.append(server) + msgSendDest.append(server['mhsid']) + found = True + break + + # find first dx4, 98000000, but perhaps a different mhsid + # this is probably not the primary operational GFE + if not found: + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort: + if server['mhsid'] not in msgSendDest: + chosenServers.append(server) + msgSendDest.append(server['mhsid']) + found = True + break + + # if didn't find standard one, then take the first one, but don't + # take ourselves unless we are the only one. + if not found and servers: + for server in servers: + if server['mhsid'] != mhsid and server['host'] != host \ + and server['port'] != port and \ + server['mhsid'] != siteID: + if server['mhsid'] not in msgSendDest: + chosenServers.append(server) + msgSendDest.append(server['mhsid']) + found = True + if not found: + if servers[0]['mhsid'] not in msgSendDest: + chosenServers.append(servers[0]) + msgSendDest.append(servers[0]['mhsid']) + + # Display the set of matching servers + s = "Matching Servers:" + for x in matchingServers: + s += "\n" + irt.printServerInfo(x) + logger.info(s) + + # Display the chosen set of servers + s = "Chosen Servers:" + for x in chosenServers: + s += "\n" + irt.printServerInfo(x) + logger.info(s) + + irt.addDestinationXML(iscE, chosenServers) + + return msgSendDest, iscE + +def runFromJava(siteID, config): + import siteConfig + host = str(config.getServerHost()) + port = str(config.getRpcPort()) + protocol = str(config.getProtocolVersion()) + mhsid = str(config.getMhsid()) + ancf = str(config.iscRoutingTableAddress().get("ANCF")) + bncf = str(config.iscRoutingTableAddress().get("BNCF")) + xmtScript = str(config.transmitScript()) + + init_logging() + + TCVUtil.purgeAllCanFiles(logger) + + tcvProductsDir = os.path.join(siteConfig.GFESUITE_HOME, "products", "TCV") + + # create tcvProductsDir if necessary + try: + os.makedirs(tcvProductsDir, 0755) + except OSError, e: + if e.errno != errno.EEXIST: + logger.warn("%s: '%s'" % (e.strerror,e.filename)) + + # get temporary file name for packaged TCV files + with tempfile.NamedTemporaryFile(suffix='.sendtcv', dir=tcvProductsDir, delete=False) as fp: + fname = fp.name + + try: + TCVUtil.packageTCVFiles([siteID], fname, logger) + + msgSendDest, xml = createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger) + + # create the XML file + with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd: + fnameXML = fd.name + fd.write(ElementTree.tostring(xml)) + + # don't send to ourselves + if mhsid in msgSendDest: + msgSendDest.remove(mhsid) + + if len(msgSendDest) > 0: + # Now send the message + irt = IrtAccess.IrtAccess(ancf, bncf) + logger.debug("msgSendDest: "+ str(msgSendDest)) + irt.transmitFiles("PUT_TCV_FILES", msgSendDest, mhsid, [fname, fnameXML], xmtScript) + + except: + logger.exception('Error sending TCV files for site: ' + siteID) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeDataAccessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeDataAccessor.java index 92deb66da3..0707a66854 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeDataAccessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeDataAccessor.java @@ -21,6 +21,7 @@ package com.raytheon.uf.edex.plugin.hpe.util; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.SortedMap; @@ -44,7 +45,7 @@ import com.raytheon.uf.edex.plugin.hpe.util.HpeEnums.HpeDataSource; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 26, 2014 3026 mpduff Initial creation - * Nov 12, 2014 3026 mpduff Fix handling of query results + * Nov 12, 2014 3026 mpduff Fix handling of query results and query by current hour * * * @@ -94,6 +95,16 @@ public class HpeDataAccessor { Date recdate, String productName) throws Exception { SortedMap> dataMap = new TreeMap>(); + /* + * Bias data are by the hour. Get the current hour to query on + */ + long ms = recdate.getTime(); + Calendar currentHour = TimeUtil.newGmtCalendar(); + currentHour.setTimeInMillis(ms); + currentHour.set(Calendar.MINUTE, 0); + currentHour.set(Calendar.SECOND, 0); + currentHour.set(Calendar.MILLISECOND, 0); + HpeRadarResult hpeResult = getHpeRadarResult(recdate, productName); HpeDataSource source = hpeResult.getRadarDataSource(); @@ -115,7 +126,8 @@ public class HpeDataAccessor { query.append(" from ").append(table); query.append(" where office_id ").append(" = '").append(office) .append("'"); - query.append(" and obstime = '").append(sdf.get().format(recdate)); + query.append(" and obstime = '").append( + sdf.get().format(currentHour.getTime())); query.append("'").append(" order by radid asc, memspan_ind asc"); Object[] results = dao.executeSQLQuery(query.toString()); @@ -126,14 +138,14 @@ public class HpeDataAccessor { rec.setRadarId((String) oa[0]); rec.setOfficeId((String) oa[1]); rec.setObsTime((Date) oa[2]); - rec.setMemspanIndex((Integer) oa[3]); - rec.setNumPairs((Float) oa[4]); + rec.setMemspanIndex((Short) oa[3]); + rec.setNumPairs((Double) oa[4]); rec.setSumGages((Float) oa[5]); rec.setSumRadars((Float) oa[6]); rec.setBias((Float) oa[7]); - if (!dataMap.containsKey(rec.getOfficeId())) { - dataMap.put(rec.getOfficeId(), + if (!dataMap.containsKey(rec.getRadarId())) { + dataMap.put(rec.getRadarId(), new ArrayList()); } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeLabelGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeLabelGenerator.java index 08a9c32672..bc08d927bd 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeLabelGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.hpe/src/com/raytheon/uf/edex/plugin/hpe/util/HpeLabelGenerator.java @@ -41,6 +41,7 @@ import com.raytheon.uf.edex.plugin.hpe.util.HpeEnums.HpeDataSource; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 26, 2014 3026 mpduff Initial creation + * Dec 16, 2014 3026 mpduff Add default value if numPairs < npairBiasSelect * * * @@ -172,7 +173,11 @@ public class HpeLabelGenerator { sb.append(bias).append(SLASH) .append((int) rec.getNumPairs()); sb.append(StringUtil.NEWLINE); - + return sb.toString(); + } else { + sb.append("1.00").append(SLASH) + .append((int) rec.getNumPairs()); + sb.append(StringUtil.NEWLINE); return sb.toString(); } } diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/cleanup_svcbu_logs b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/cleanup_svcbu_logs index 4f7e5d7d43..1d9b2493f4 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/cleanup_svcbu_logs +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/cleanup_svcbu_logs @@ -1,5 +1,6 @@ #!/bin/bash + if [ ${#AWIPS_HOME} = 0 ] then path_to_script=`readlink -f $0` @@ -8,6 +9,12 @@ fi . ${AWIPS_HOME}/GFESuite/ServiceBackup/configuration/svcbu.env +if [ ${#IFPS_LOG} = 0 ] +then + echo "ERROR: environment variable IFPS_LOG is undfined, exit." + exit 1 +fi + find ${IFPS_LOG}/* -mtime +7 -exec rm -fr {} \; 2>/dev/null diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MdlSoundingQuery.java b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MdlSoundingQuery.java index 8aedaca3e7..18b8febe91 100644 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MdlSoundingQuery.java +++ b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MdlSoundingQuery.java @@ -1,1045 +1,1057 @@ -package gov.noaa.nws.ncep.edex.uengine.tasks.profile; - -/** - * - * gov.noaa.nws.ncep.edex.uengine.tasks.profile.MdlSoundingQuery - * - * This java class performs the Grid model sounding data query functions. - * This code has been developed by the SIB for use in the AWIPS2 system. - * - *
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * -------		------- 	-------- 	-----------
- * 04/04/2011	301			Chin Chen	Initial coding
- * 02/28/2012               Chin Chen   modify several sounding query algorithms for better performance
- * 03/28/2012               Chin Chen   Add new API to support query multiple Points at one shoot and using
- * 										dataStore.retrieveGroups()
- * Oct 15, 2012 2473        bsteffen    Remove ncgrib
- * 03/2014		1116		T. Lee		Added DpD
- * 
- * - * @author Chin Chen - * @version 1.0 - */ -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingModel; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingTimeLines; - -import java.awt.Point; -import java.util.ArrayList; -import java.util.List; - -import javax.measure.converter.UnitConverter; -import javax.measure.unit.NonSI; -import javax.measure.unit.SI; - -import org.geotools.coverage.grid.GridGeometry2D; -import org.geotools.geometry.GeneralDirectPosition; -import org.opengis.geometry.DirectPosition; -import org.opengis.referencing.FactoryException; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.operation.MathTransform; - -import com.raytheon.edex.uengine.tasks.query.TableQuery; -import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; -import com.raytheon.uf.common.dataplugin.grid.GridInfoRecord; -import com.raytheon.uf.common.dataplugin.grid.GridRecord; -import com.raytheon.uf.common.geospatial.ISpatialObject; -import com.raytheon.uf.common.geospatial.MapUtil; -import com.raytheon.uf.common.geospatial.PointUtil; -import com.raytheon.uf.edex.database.DataAccessLayerException; -import com.raytheon.uf.edex.database.dao.CoreDao; -import com.raytheon.uf.edex.database.dao.DaoConfig; -import com.raytheon.uf.edex.database.query.DatabaseQuery; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.CoordinateSequence; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.GeometryFactory; -import com.vividsolutions.jts.geom.LinearRing; -import com.vividsolutions.jts.geom.Polygon; -import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; - -//import org.opengis.geometry.Envelope; - -public class MdlSoundingQuery { - private static final String D2DGRIB_TBL_NAME = "grid"; - - private static String D2D_PARMS = "GH, uW, vW,T, DWPK, SPFH,OMEG, RH, DpD"; - - private enum D2DParmNames { - GH, uW, vW, T, DWPK, SPFH, OMEG, RH, DpD - }; - - public static UnitConverter kelvinToCelsius = SI.KELVIN - .getConverterTo(SI.CELSIUS); - - private static final UnitConverter metersPerSecondToKnots = SI.METERS_PER_SECOND - .getConverterTo(NonSI.KNOT); - - // Note; we are using NCInventory now. So, this api is actually not used. - public static NcSoundingTimeLines getMdlSndTimeLine(String mdlType, - String currentDBTblName) { - NcSoundingTimeLines tl = new NcSoundingTimeLines(); - /* - * if(currentDBTblName.equals(NCGRIB_TBL_NAME)){ Object[] refTimeAry = - * null; String queryStr = new String("Select Distinct reftime FROM " + - * currentDBTblName + " where modelname='" + mdlType + - * "' ORDER BY reftime DESC"); - * - * CoreDao dao = new CoreDao(DaoConfig.forClass(NcgribRecord.class)); - * refTimeAry = (Object[]) dao.executeSQLQuery(queryStr); - * tl.setTimeLines(refTimeAry); }else - * if(currentDBTblName.equals(D2DGRIB_TBL_NAME)){ TableQuery query; try - * { query = new TableQuery("metadata", GridRecord.class.getName()); - * query.setDistinctField("dataTime.refTime"); - * query.addParameter(GridConstants.DATASET_ID, mdlType); - * query.setSortBy("dataTime.refTime", false); - * - * @SuppressWarnings("unchecked") List recList = - * (List) query.execute(); - * tl.setTimeLines(recList.toArray()); } catch (DataAccessLayerException - * e) { // TODO Auto-generated catch block e.printStackTrace(); } catch - * (Exception e) { // TODO Auto-generated catch block - * e.printStackTrace(); } - * - * } - */ - - // Chin: modified for Unified Grid DB - // Use the following SQL statement - // Select Distinct reftime FROM grid FULL JOIN grid_info ON - // grid.info_id=grid_info.id where grid_info.datasetid='gfs' ORDER BY - // reftime DESC - Object[] refTimeAry = null; - String queryStr = new String( - "Select Distinct reftime FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id where grid_info.datasetid='" - + mdlType + "' ORDER BY reftime DESC"); - - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - refTimeAry = dao.executeSQLQuery(queryStr); - tl.setTimeLines(refTimeAry); - - return tl; - } - - public static NcSoundingTimeLines getMdlSndRangeTimeLine(String mdlType, - String refTimeStr, String currentDBTblName) { - NcSoundingTimeLines tl = new NcSoundingTimeLines(); - /* - * if(currentDBTblName.equals(NCGRIB_TBL_NAME)){ Object[] refTimeAry = - * null; String queryStr = new String("Select Distinct rangestart FROM " - * + currentDBTblName + " where modelname='" + mdlType + "' AND " + - * "reftime='" + refTimeStr + ":00:00'" + " ORDER BY rangestart"); - * System.out.println("queryStr " + queryStr); - * - * CoreDao dao = new CoreDao(DaoConfig.forClass(SoundingSite.class)); - * refTimeAry = (Object[]) dao.executeSQLQuery(queryStr); - * tl.setTimeLines(refTimeAry); } else - * if(currentDBTblName.equals(D2DGRIB_TBL_NAME)){ TableQuery query; try - * { query = new TableQuery("metadata", GridRecord.class.getName()); - * query.setDistinctField("dataTime.validPeriod.start"); - * query.addParameter(GridConstants.DATASET_ID, mdlType); - * query.addParameter("dataTime.refTime", refTimeStr + ":00:00"); - * query.setSortBy("dataTime.validPeriod.start", true); - * - * @SuppressWarnings("unchecked") List recList = - * (List) query.execute(); - * tl.setTimeLines(recList.toArray()); } catch (DataAccessLayerException - * e) { // TODO Auto-generated catch block e.printStackTrace(); } catch - * (Exception e) { // TODO Auto-generated catch block - * e.printStackTrace(); } - */ - // Chin: modified for Unified Grid DB - // make sure data in DB is not just nHour data, as those data are not - // used by Nsharp. And when query to it, the returned will be - // null. We do not want to show such sounding time line to user. - // use this SQL query string for gfs as example. - /* - * Select Distinct rangestart FROM grid FULL JOIN grid_info ON - * grid.info_id=grid_info.id where grid.reftime = '2012-01-26 00:00:00' - * AND grid.rangestart = grid.rangeend AND - * grid_info.datasetid='mesoEta212' AND - * grid_info.parameter_abbreviation='T' order by rangestart - */ - Object[] soundingTimeAry = null; - List reSoundingTimeAry = new ArrayList(); - String queryStr = new String( - "Select Distinct rangestart FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id where grid.reftime = '" - + refTimeStr - + ":00:00' AND grid.rangestart = grid.rangeend AND grid_info.datasetid='" - + mdlType - + "' AND grid_info.parameter_abbreviation='T' order by rangestart"); - // System.out.println("queryStr " + queryStr); - - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - soundingTimeAry = (Object[]) dao.executeSQLQuery(queryStr); - for (int i = 0; i < soundingTimeAry.length; i++) { - /* - * Chin: make sure the time line has more than 5 T(temp) values at - * pressure (levelone) greater/equal than/to 100 hPa (mbar) use this - * SQL : Select count(rangestart) FROM (select rangestart FROM grid - * FULL JOIN grid_info ON grid.info_id=grid_info.id FULL JOIN level - * ON grid_info.level_id= level.id where grid.rangestart = - * '2012-01-26 03:00:00.0' AND grid.rangestart = grid.rangeend AND - * grid_info.datasetid='mesoEta212' AND - * grid_info.parameter_abbreviation='T' AND level.levelonevalue > - * 99) X HAVING count(X.rangestart) >5 - */ - String queryStr1 = new String( - "Select count(rangestart) FROM (select rangestart FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id FULL JOIN level ON grid_info.level_id= level.id where grid.rangestart = '" - + soundingTimeAry[i] - + "' AND grid.rangestart = grid.rangeend AND grid_info.datasetid='" - + mdlType - + "' AND grid_info.parameter_abbreviation='T' AND level.levelonevalue > 99) X HAVING count(X.rangestart) >2"); - Object[] countAry = null; - // System.out.println("queryStr1 " + queryStr1); - countAry = (Object[]) dao.executeSQLQuery(queryStr1); - java.math.BigInteger count = new java.math.BigInteger("0"); - if (countAry.length > 0) { - // System.out.println("rangestart =" - // +soundingTimeAry[i]+" number="+countAry[0]); - count = (java.math.BigInteger) countAry[0]; - } - // else{ - // System.out.println("rangestart =" - // +soundingTimeAry[i]+" return null"); - // } - if (count.intValue() > 2) { - Object timeLine = soundingTimeAry[i]; - reSoundingTimeAry.add(timeLine); - } - } - - tl.setTimeLines(reSoundingTimeAry.toArray()); - - // } - return tl; - } // public static NcSoundingProfile getMdlSndData(double lat, double lon, - - // String stn, long refTimeL, long validTimeL, String sndTypeStr, - // SndQueryKeyType queryType, String mdlName) { - // //*System.out.println("getPfcSndData input ref time = "+ - // refTimeL+" valid time is " + validTimeL); - // Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - // refTimeCal.setTimeInMillis(refTimeL); - // Calendar validTimeCal = - // Calendar.getInstance(TimeZone.getTimeZone("GMT")); - // validTimeCal.setTimeInMillis(validTimeL); - // return getMdlSndData( lat, lon, refTimeCal, validTimeCal, "ncgrib", - // mdlName); - // } - - /** - * Returns a list of profile for location (lat,lon) array, time, and model - * for grib or ncgrib data. - * - * @param double[][] latLonArray, e.g. at nth element, lat=[n][0], - * lon=[n][1] - * @param refTimeCal - * data record reference time - * @param validTimeCal - * data record valid time - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param mdlName - * the name of the model - * @return the profile created @ 3/28/2012 - */ - public static List getMdlSndDataProfileList( - double[][] latLonArray, String refTime, String validTime, - String pluginName, String mdlName) { - double lat, lon; - // System.out.println("getMdlSndData lat=" + lat + " lon="+lon); - long t01 = System.currentTimeMillis(); - NcSoundingProfile pf = new NcSoundingProfile(); - // NcSoundingCube cube = new NcSoundingCube(); - List soundingProfileList = new ArrayList(); - List levels = getModelLevels(refTime, validTime, pluginName, mdlName); - if (levels.size() == 0) { - System.out.println("getModelLevels return 0; file=" + refTime - + " stime=" + validTime + " gribtype=" + pluginName - + " modeltype=" + mdlName); - return soundingProfileList; - } - // System.out.println("getModelLevels = "+ - // levels.size()+" levels, took "+ (System.currentTimeMillis()-t01) + - // " ms"); - - List points = new ArrayList(); - for (int k = 0; k < latLonArray.length; k++) { - lat = latLonArray[k][0]; - lon = latLonArray[k][1]; - Point pnt = getLatLonIndices(lat, lon, refTime, validTime, levels - .get(0).toString(), pluginName, mdlName); - if (pnt == null) { - System.out.println("getLatLonIndices return 0; lat=" + lat - + " lon=" + lon + " stime=" + validTime + " gribtype=" - + pluginName + " modeltype=" + mdlName); - } else { - points.add(pnt); - } - } - if (points.size() == 0) { - return soundingProfileList; - } - long t011 = System.currentTimeMillis(); - soundingProfileList = queryProfileListByPointGroup(points, refTime, - validTime, pluginName, mdlName, levels); - System.out.println("queryProfileListByPointGroup took " - + (System.currentTimeMillis() - t011) + " ms"); - - return soundingProfileList; - /* - * The floowing should be done in queryProfileListByPointGroup() - * //System.out.println("getModelSoundingLayerList= "+ layerList.size()+ - * " layers, took "+ (System.currentTimeMillis()-t012) + " ms"); - * //pf.setStationLatitude( lat); //pf.setStationLongitude( lon); - * //Float sfcPressure = getModelSfcPressure(pnt, refTime, validTime, // - * pluginName, mdlName); - * //System.out.println("getModelSfcPressure took "+ - * (System.currentTimeMillis()-t013) + " ms"); //if (sfcPressure == - * null) { // pf.setSfcPress(-9999.f); //} //else { // if - * (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) // - * pf.setSfcPress(sfcPressure/100F); // else // - * pf.setSfcPress(sfcPressure); //} - * //System.out.println("surface pressure ="+pf.getSfcPress()+ - * " lat= "+lat+ " lon="+lon); //calculate dew point if necessary long - * t014 = System.currentTimeMillis(); MergeSounding ms = new - * MergeSounding(); //ms.spfhToDewpoint(layerList); - * ms.rhToDewpoint(layerList); System.out.println("MergeSounding took "+ - * (System.currentTimeMillis()-t014) + " ms"); - * - * - * pf.setSoundingLyLst(layerList); - * - * - * soundingProfileList.add(pf); - * //cube.setSoundingProfileList(soundingProfileList); - * //cube.setRtnStatus(NcSoundingCube.QueryStatus.OK); long t02 = - * System.currentTimeMillis(); - * System.out.println("MDL cube retreival took " + (t02 - t01)); return - * pf; - */ - - } - - /** - * Returns a profile for a specified location (lat,lon), time, and model for - * grib or ncgrib data. - * - * @param lat - * location latitude - * @param lon - * location longitude - * @param refTimeCal - * data record reference time - * @param validTimeCal - * data record valid time - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param mdlName - * the name of the model - * @return the profile - * - * public static NcSoundingProfile getMdlSndData(double lat, double - * lon, String refTime, String validTime, String pluginName, String - * mdlName) { System.out.println("getMdlSndData lat=" + lat + - * " lon="+lon); long t01 = System.currentTimeMillis(); - * NcSoundingProfile pf = new NcSoundingProfile(); List levels = - * getModelLevels(refTime, validTime, pluginName, mdlName); if - * (levels.size() == 0) { - * System.out.println("getModelLevels return 0; file=" + refTime+ - * " stime="+validTime + " gribtype="+ pluginName + - * " modeltype="+mdlName); - * pf.setRtnStatus(NcSoundingCube.QueryStatus.FAILED); return pf; } - * System.out.println("getModelLevels = "+ - * levels.size()+" levels, took "+ (System.currentTimeMillis()-t01) - * + " ms"); long t011 = System.currentTimeMillis(); Point pnt = - * getLatLonIndices(lat, lon, refTime, validTime, - * levels.get(0).toString(), pluginName, mdlName); if (pnt == null) - * { System.out.println("getLatLonIndices return 0; lat=" + lat + - * " lon="+lon+" stime="+validTime + " gribtype="+ pluginName + - * " modeltype="+mdlName); - * - * pf.setRtnStatus(NcSoundingCube.QueryStatus.LOCATION_NOT_FOUND); - * return pf; - * - * } System.out.println("getLatLonIndices pntX=" + pnt.getX()+ - * " pntY=" + pnt.getY()+ " took "+ - * (System.currentTimeMillis()-t011) + " ms"); long t012 = - * System.currentTimeMillis(); List layerList = - * getModelSoundingLayerList(pnt, refTime, validTime, pluginName, - * mdlName, levels); if (layerList.size() == 0) { - * System.out.println("getModelSoundingLayerList return 0; lat=" + - * lat + " lon="+lon+" stime="+validTime + " gribtype="+ pluginName - * + " modeltype="+mdlName); - * - * - * pf.setRtnStatus(NcSoundingCube.QueryStatus.FAILED); return pf; } - * - * System.out.println("getModelSoundingLayerList= "+ - * layerList.size()+ " layers, took "+ - * (System.currentTimeMillis()-t012) + " ms"); - * - * pf.setStationLatitude( lat); pf.setStationLongitude( lon); Float - * sfcPressure = getModelSfcPressure(pnt, refTime, validTime, - * pluginName, mdlName); - * //System.out.println("getModelSfcPressure took "+ - * (System.currentTimeMillis()-t013) + " ms"); if (sfcPressure == - * null) { pf.setSfcPress(-9999.f); } else { if - * (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) - * pf.setSfcPress(sfcPressure/100F); else - * pf.setSfcPress(sfcPressure); } - * //System.out.println("surface pressure ="+pf.getSfcPress()+ - * " lat= "+lat+ " lon="+lon); //calculate dew point if necessary - * long t014 = System.currentTimeMillis(); MergeSounding ms = new - * MergeSounding(); //ms.spfhToDewpoint(layerList); - * ms.rhToDewpoint(layerList); - * System.out.println("MergeSounding took "+ - * (System.currentTimeMillis()-t014) + " ms"); - * - * - * pf.setSoundingLyLst(layerList); - * - * long t02 = System.currentTimeMillis(); - * System.out.println("MDL cube retreival took " + (t02 - t01)); - * return pf; - * - * } - */ - - public static NcSoundingModel getMdls(String pluginName) { - NcSoundingModel mdls = new NcSoundingModel(); - Object[] mdlName = null; - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridInfoRecord.class)); - String queryStr = new String( - "Select Distinct modelname FROM grib_models ORDER BY modelname"); - mdlName = (Object[]) dao.executeSQLQuery(queryStr); - } - if (mdlName != null && mdlName.length > 0) { - List mdlList = new ArrayList(); - for (Object mn : mdlName) { - mdlList.add((String) mn); - } - mdls.setMdlList(mdlList); - } - return mdls; - } - - public static boolean isPointWithinGridGeometry(double lat, double lon, - String refTime, String validTime, String pluginName, - String modelName) { - - ISpatialObject spatialArea = null; - MathTransform crsFromLatLon = null; - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - - query.setMaxResults(new Integer(1)); - query.addQueryParam(GridConstants.DATASET_ID, modelName); - query.addQueryParam("dataTime.refTime", refTime); - query.addQueryParam("dataTime.validPeriod.start", validTime); - - try { - List recList = ((List) dao - .queryByCriteria(query)); - if (recList.size() == 0) { - return false; - } else { - GridRecord rec = recList.get(0); - spatialArea = rec.getSpatialObject(); - } - - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - } - - try { - crsFromLatLon = MapUtil - .getTransformFromLatLon(spatialArea.getCrs()); - } catch (FactoryException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - DirectPosition lowerCorner = MapUtil.getGridGeometry(spatialArea) - .getEnvelope().getLowerCorner(); - DirectPosition upperCorner = MapUtil.getGridGeometry(spatialArea) - .getEnvelope().getUpperCorner(); - - GeometryFactory gf = new GeometryFactory(); - - Coordinate p1 = new Coordinate(lowerCorner.getOrdinate(0), - lowerCorner.getOrdinate(1)); - Coordinate p2 = new Coordinate(lowerCorner.getOrdinate(0), - upperCorner.getOrdinate(1)); - Coordinate p3 = new Coordinate(upperCorner.getOrdinate(0), - upperCorner.getOrdinate(1)); - Coordinate p4 = new Coordinate(upperCorner.getOrdinate(0), - lowerCorner.getOrdinate(1)); - - LinearRing lr = gf.createLinearRing(new Coordinate[] { p1, p2, p3, p4, - p1 }); - - Polygon gridGeometry = gf.createPolygon(lr, null); - - DirectPosition ll = new GeneralDirectPosition(MapUtil.LATLON_PROJECTION); - - Coordinate coord = new Coordinate(lon, lat); - ll.setOrdinate(0, coord.x); - ll.setOrdinate(1, coord.y); - // DirectPosition crs = new GeneralDirectPosition(spatialArea.getCrs()); - // try { - // crsFromLatLon.transform(ll, crs); - // } catch (MismatchedDimensionException e) { - // // TODO Auto-generated catch block - // e.printStackTrace(); - // } catch (TransformException e) { - // // TODO Auto-generated catch block - // e.printStackTrace(); - // } - // - // Coordinate newC = new Coordinate(crs.getOrdinate(0), - // crs.getOrdinate(1)); - Coordinate newC = new Coordinate(ll.getOrdinate(0), ll.getOrdinate(1)); - - com.vividsolutions.jts.geom.Point p = gf.createPoint(newC); - - return gridGeometry.contains(p); - - } - - public static boolean isPointWithinGridGeometry2(double lat, double lon, - String refTime, String validTime, String pluginName, - String modelName) { - - ISpatialObject spatialArea = null; - MathTransform crsFromLatLon = null; - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - - query.setMaxResults(new Integer(1)); - query.addQueryParam(GridConstants.DATASET_ID, modelName); - query.addQueryParam("dataTime.refTime", refTime); - query.addQueryParam("dataTime.validPeriod.start", validTime); - - try { - List recList = ((List) dao - .queryByCriteria(query)); - if (recList.size() == 0) { - return false; - } else { - GridRecord rec = recList.get(0); - spatialArea = rec.getSpatialObject(); - } - - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - } - - Geometry g = spatialArea.getGeometry(); - - GeometryFactory geometryFactory = new GeometryFactory(); - CoordinateSequence sequence = new CoordinateArraySequence( - g.getCoordinates()); - - Coordinate[] oldCoords = sequence.toCoordinateArray(); - Coordinate[] newCoords = new Coordinate[oldCoords.length]; - /* - * adjust longitude for global grids whose lon span goes from 0 to 360 - * and the asked lon is negative. - */ - for (Coordinate c : oldCoords) { - double x = c.x; - double y = c.y; - double z = c.z; - if (x >= 180.0 && x <= 360.0 && lon < 0.0) { - lon = lon + 360.0; - break; - } - } - Coordinate coord = new Coordinate(lon, lat); - - LinearRing ring = new LinearRing(sequence, geometryFactory); - Polygon gridGeometry = new Polygon(ring, null, geometryFactory); - com.vividsolutions.jts.geom.Point p = geometryFactory - .createPoint(coord); - - return gridGeometry.contains(p); - - } - - /** - * Returns the value of surface pressure for a specified location, time, and - * model for grib or ncgrib data. - * - * @param pnt - * location - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param modelName - * the name of the model - * @return surface pressure - */ - public static Float getModelSfcPressure(Point pnt, String refTime, - String validTime, String pluginName, String modelName) { - - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - - query.addQueryParam(GridConstants.LEVEL_ONE, "0.0"); - query.addQueryParam(GridConstants.LEVEL_TWO, "-999999.0"); - query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MSL"); - query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "PMSL"); - query.addQueryParam(GridConstants.DATASET_ID, modelName); - query.addQueryParam("dataTime.refTime", refTime); - query.addQueryParam("dataTime.validPeriod.start", validTime); - - GridRecord rec = null; - try { - List recList = ((List) dao - .queryByCriteria(query)); - if (recList.size() == 0) { - return null; - } else { - rec = recList.get(0); - PointIn pointIn = new PointIn(pluginName, rec, pnt.x, pnt.y); - try { - float fdata = pointIn.getPointData(); - return new Float(fdata); - } catch (PluginException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - } - - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - } - return null; - - } - - /** - * Returns a list of NcSoundingProfile for a group of Point with specific - * ref and range time, and model for grib or ncgrib data. - * - * @param pnt - * location - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param modelName - * the name of the model - * @param levels - * list of vertical levels - * @return list of NcSoundingLayer objects - * - * Created @ 3/28/2012 - */ - - private static List queryProfileListByPointGroup( - List points, String refTime, String validTime, - String pluginName, String modelName, List levels) { - - List soundingProfileList = new ArrayList(); - List fdataArrayList = new ArrayList(); - // long t01 = System.currentTimeMillis(); - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - List recList = new ArrayList(); - ; - TableQuery query; - try { - query = new TableQuery("metadata", GridRecord.class.getName()); - query.addParameter(GridConstants.MASTER_LEVEL_NAME, "MB"); - query.addParameter(GridConstants.DATASET_ID, modelName); - query.addList(GridConstants.PARAMETER_ABBREVIATION, D2D_PARMS); - query.addParameter("dataTime.refTime", refTime); - query.addParameter("dataTime.validPeriod.start", validTime); - query.setSortBy(GridConstants.LEVEL_ONE, false); - recList = (List) query.execute(); - if (recList.size() != 0) { - PointIn pointIn = new PointIn(pluginName, recList.get(0)); - fdataArrayList = pointIn.getHDF5GroupDataPoints( - recList.toArray(), points); - } - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - int index = 0; - GridGeometry2D geom = MapUtil.getGridGeometry(spatialArea); - CoordinateReferenceSystem crs = geom.getCoordinateReferenceSystem(); - Coordinate coord = new Coordinate(45, 45); - - for (float[] fdataArray : fdataArrayList) { - // one fdataArray is for one Point or say one profile - NcSoundingProfile pf = new NcSoundingProfile(); - List soundLyList = new ArrayList(); - Point pnt = points.get(index); - Object[] recArray = recList.toArray(); - for (Object level : levels) { - NcSoundingLayer soundingLy = new NcSoundingLayer(); - double pressure = (Double) level; - soundingLy.setPressure((float) pressure); - for (int i = 0; i < recArray.length; i++) { - GridRecord rec1 = (GridRecord) recArray[i]; - float fdata = fdataArray[i]; - if (rec1.getLevel().getLevelonevalue() == pressure) { - String prm = rec1.getParameter().getAbbreviation(); - switch (D2DParmNames.valueOf(prm)) { - case GH: - soundingLy.setGeoHeight(fdata); - break; - case uW: - // HDF5 data in unit of m/s, convert to Knots - // 4/12/2012 - soundingLy - .setWindU((float) metersPerSecondToKnots - .convert(fdata)); - break; - case vW: - // HDF5 data in unit of m/s, convert to Knots - // 4/12/2012 - soundingLy - .setWindV((float) metersPerSecondToKnots - .convert(fdata)); - break; - case T: - soundingLy - .setTemperature((float) kelvinToCelsius - .convert(fdata)); - break; - case DWPK: - soundingLy.setDewpoint((float) kelvinToCelsius - .convert(fdata)); - break; - case OMEG: - soundingLy.setOmega(fdata); - break; - case RH: - soundingLy.setRelativeHumidity(fdata); - break; - case DpD: - soundingLy.setDpd(fdata); - break; - } - } - } - soundLyList.add(soundingLy); - } - try { - coord = PointUtil.determineLatLon(pnt, crs, geom); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // System.out.println(" point coord.y="+coord.y+ " coord.x="+ - // coord.x); - pf.setStationLatitude(coord.y); - pf.setStationLongitude(coord.x); - // Float sfcPressure = getModelSfcPressure(pnt, refTime, - // validTime, - // pluginName, modelName); - // System.out.println("getModelSfcPressure took "+ - // (System.currentTimeMillis()-t013) + " ms"); - // /if (sfcPressure == null) { - pf.setSfcPress(-9999.f); - // } - // else { - // pf.setSfcPress(sfcPressure/100F); - // } - // System.out.println("surface pressure ="+pf.getSfcPress()+ - // " lat= "+lat+ " lon="+lon); - // calculate dew point if necessary - MergeSounding ms = new MergeSounding(); - // ms.spfhToDewpoint(layerList); - ms.rhToDewpoint(soundLyList); - ms.dpdToDewpoint(soundLyList); - pf.setSoundingLyLst(soundLyList); - soundingProfileList.add(pf); - index++; - } - } - return soundingProfileList; - } - - /** - * Returns a list of NcSoundingLayer for a specified location, time, and - * model for grib or ncgrib data. - * - * @param pnt - * location - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param modelName - * the name of the model - * @param levels - * list of vertical levels - * @return list of NcSoundingLayer objects - * - * - * private static List - * getModelSoundingLayerList(Point pnt, String refTime, String - * validTime, String pluginName, String modelName, List levels) { - * List soundLyList = new - * ArrayList(); - * - * //long t01 = System.currentTimeMillis(); if - * (pluginName.equalsIgnoreCase(NCGRIB_TBL_NAME)) { - * - * TableQuery query; try { query = new TableQuery("metadata", - * NcgribRecord.class.getName()); query.addParameter("vcord", - * "PRES"); query.addParameter("modelName", modelName); - * query.addList("parm",NC_PARMS);//parmList.toString()); // - * query.addParameter("dataTime.refTime", refTime); - * query.addParameter("dataTime.validPeriod.start", validTime); - * //query.addParameter("glevel1", level.toString()); - * query.setSortBy("glevel1", false); - * - * - * List recList = (List) - * query.execute(); - * System.out.println("Ncgrib group query0 result size ="+ - * recList.size()); - * - * if (recList.size() != 0) { - * - * PointIn pointIn = new PointIn(pluginName, recList.get(0), pnt.x, - * pnt.y); //Chin note: // We query all levels (pressure) and all - * parameters (at that level) at once. // The return array - * (fdataArray) are listed in the same order as query array - * (recList.toArray()) //However, returned array does not tell you - * which parameter itself is. //Therefore, we have to use - * information in query array to find out returned value's type - * (which parameter it is) // Further, we have to sort and store - * returned values to NcSoundingLayer based on its level (pressure) - * // Parameters in same level should be stored in one same - * NcSoundingLayer float[] fdataArray = - * pointIn.getHDF5GroupDataPoint(recList.toArray()); Object[] - * recArray = recList.toArray(); for (Object level : levels){ - * NcSoundingLayer soundingLy = new NcSoundingLayer(); int pressure= - * (Integer)level; soundingLy.setPressure( pressure); - * - * for (int i=0; i < recArray.length; i++) { NcgribRecord rec1 = - * (NcgribRecord)recArray[i]; float fdata = fdataArray[i]; - * if(rec1.getGlevel1() == pressure){ String prm = rec1.getParm(); - * //System.out.println("point.x="+ pnt.x + - * " .y="+pnt.y+"pressure="+rec1 // .getGlevel1()+ " Parm="+prm ); - * //long t01 = System.currentTimeMillis(); switch - * (NcParmNames.valueOf(prm)) { case HGHT: - * soundingLy.setGeoHeight(fdata); break; case UREL: // HDF5 data in - * unit of Knots, no conversion needed soundingLy.setWindU(fdata); - * break; case VREL: // HDF5 data in unit of Knots, no conversion - * needed soundingLy.setWindV(fdata); break; case TMPK: - * soundingLy.setTemperature((float) kelvinToCelsius - * .convert(fdata)); break; case DWPK: - * soundingLy.setDewpoint((float) kelvinToCelsius .convert(fdata)); - * break; case SPFH: soundingLy.setSpecHumidity(fdata); break; case - * OMEG: soundingLy.setOmega(fdata); break; case RELH: - * soundingLy.setRelativeHumidity(fdata); break; } } } - * soundLyList.add(soundingLy); } } - * - * } catch (DataAccessLayerException e) { // TODO Auto-generated - * catch block e.printStackTrace(); } catch (Exception e) { // TODO - * Auto-generated catch block e.printStackTrace(); } - * //System.out.println("getModelSoundingLayerList:total level = "+ - * totalLevel + " total records= "+totalRecords ); - * - * } else if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { try { - * TableQuery query = new TableQuery("metadata", - * GribRecord.class.getName()); - * //query.addParameter("modelInfo.level.levelonevalue", // - * level.toString()); - * //query.addParameter("modelInfo.level.leveltwovalue", // - * "-999999.0"); - * query.addParameter("modelInfo.level.masterLevel.name", "MB"); - * query.addParameter("modelInfo.modelName", modelName); - * query.addList("modelInfo.parameterAbbreviation", D2D_PARMS); - * query.addParameter("dataTime.refTime", refTime); - * query.addParameter("dataTime.validPeriod.start", validTime); - * query.setSortBy("modelInfo.level.levelonevalue", false); - * //System.out.println("level = "+ level.toString()); - * - * List recList = (List) query.execute(); - * System.out.println("Grib group query0 result size ="+ - * recList.size()); - * - * if (recList.size() > 0) { PointIn pointIn = new - * PointIn(pluginName, recList.get(0), pnt.x, pnt.y); float[] - * fdataArray = pointIn.getHDF5GroupDataPoint(recList.toArray()); - * Object[] recArray = recList.toArray(); for (Object level : - * levels){ NcSoundingLayer soundingLy = new NcSoundingLayer(); - * double pressure= (Double)level; soundingLy.setPressure( - * (float)pressure); - * - * for (int i=0; i < recArray.length; i++) { GribRecord rec1 = - * (GribRecord)recArray[i]; float fdata = fdataArray[i]; - * if(rec1.getModelInfo().getLevelOneValue() == pressure){ String - * prm = rec1.getModelInfo().getParameterAbbreviation(); - * //System.out.println("point.x="+ pnt.x + - * " .y="+pnt.y+"pressure="+pressure+ " Parm="+prm ); //long t01 = - * System.currentTimeMillis(); switch (D2DParmNames.valueOf(prm)) { - * case GH: soundingLy.setGeoHeight(fdata); break; case uW: // HDF5 - * data in unit of Knots, no conversion needed - * soundingLy.setWindU(fdata); break; case vW: // HDF5 data in unit - * of Knots, no conversion needed soundingLy.setWindV(fdata); break; - * case T: soundingLy.setTemperature((float) kelvinToCelsius - * .convert(fdata)); break; case DWPK: - * soundingLy.setDewpoint((float) kelvinToCelsius .convert(fdata)); - * break; case OMEG: soundingLy.setOmega(fdata); break; case RH: - * soundingLy.setRelativeHumidity(fdata); break; } } } - * soundLyList.add(soundingLy); } } } catch - * (DataAccessLayerException e) { // TODO Auto-generated catch block - * e.printStackTrace(); } catch (Exception e) { // TODO - * Auto-generated catch block e.printStackTrace(); } } - * - * //long t02 = System.currentTimeMillis(); - * //System.out.println("MDL profile retreival took " + (t02 - - * t01)); - * - * for(NcSoundingLayer layer: soundLyList){ - * System.out.println("pre="+ layer.getPressure()+ - * " h="+layer.getGeoHeight()+ " T="+layer.getTemperature()+" D="+ - * layer.getDewpoint()+ " WS="+layer.getWindSpeed()+ - * " WD="+layer.getWindDirection() + " SH="+layer.getSpecHumidity()+ - * " RH="+layer.getRelativeHumidity()); } return soundLyList; } - */ - /** - * Return a list of data vertical levels for a specified time and model for - * grib or ncgrib data. - * - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param modelName - * the name of the model - * @return list of vertical levels - */ - public static List getModelLevels(String refTime, String validTime, - String pluginName, String modelName) { - - // Listvals = null; - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - query.addDistinctParameter(GridConstants.LEVEL_ONE); - query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "GH"); - query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MB"); - - query.addQueryParam(GridConstants.DATASET_ID, modelName); - query.addQueryParam("dataTime.refTime", refTime); - query.addQueryParam("dataTime.validPeriod.start", validTime); - query.addOrder(GridConstants.LEVEL_ONE, false); - - try { - return (List) dao.queryByCriteria(query); - - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - } - - return null; - - } - - private static ISpatialObject spatialArea = null; - - /** - * Returns the indices of the model grid of the closest point to the - * specified latitude, longitude. - * - * @param lat - * latitude - * @param lon - * longitude - * @param level - * vertical level - * @param pluginName - * the name of the data table ('grib' or 'ncgrib') - * @param modelName - * the name of the model - * @return the point indices - */ - public static Point getLatLonIndices(double lat, double lon, - String refTime, String validTime, String level, String pluginName, - String modelName) { - // ISpatialObject spatialArea = null; - - Point pnt = null; - - if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { - CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - - query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "GH"); - query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MB"); - query.addQueryParam(GridConstants.DATASET_ID, modelName); - query.addQueryParam("dataTime.refTime", refTime); - query.addQueryParam("dataTime.validPeriod.start", validTime); - query.addQueryParam(GridConstants.LEVEL_ONE, level); - query.addQueryParam(GridConstants.LEVEL_TWO, "-999999.0"); - - GridRecord rec; - try { - List recList = ((List) dao - .queryByCriteria(query)); - if (recList.size() == 0) { - return null; - } else { - rec = recList.get(0); - spatialArea = rec.getSpatialObject(); - } - } catch (DataAccessLayerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - - } else - return null; - - GridGeometry2D geom = MapUtil.getGridGeometry(spatialArea); - - CoordinateReferenceSystem crs = geom.getCoordinateReferenceSystem(); - Coordinate coord = new Coordinate(lon, lat); - - try { - pnt = PointUtil.determineIndex(coord, crs, geom); - Integer nx = spatialArea.getNx(); - Integer ny = spatialArea.getNy(); - - if (pnt.x > nx || pnt.y > ny) { - return null; - } - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return pnt; - - } - -} +package gov.noaa.nws.ncep.edex.uengine.tasks.profile; + +/** + * + * gov.noaa.nws.ncep.edex.uengine.tasks.profile.MdlSoundingQuery + * + * This java class performs the Grid model sounding data query functions. + * This code has been developed by the SIB for use in the AWIPS2 system. + * + *
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    	Engineer    Description
+ * -------		------- 	-------- 	-----------
+ * 04/04/2011	301			Chin Chen	Initial coding
+ * 02/28/2012               Chin Chen   modify several sounding query algorithms for better performance
+ * 03/28/2012               Chin Chen   Add new API to support query multiple Points at one shoot and using
+ * 										dataStore.retrieveGroups()
+ * Oct 15, 2012 2473        bsteffen    Remove ncgrib
+ * 03/2014		1116		T. Lee		Added DpD
+ * 01/2015      DR#16959    Chin Chen   Added DpT support to fix DR 16959 NSHARP freezes when loading a sounding from 
+ *                                      HiRes-ARW/NMM models
+ * 
+ * + * @author Chin Chen + * @version 1.0 + */ +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingModel; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingTimeLines; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +import javax.measure.converter.UnitConverter; +import javax.measure.unit.NonSI; +import javax.measure.unit.SI; + +import org.geotools.coverage.grid.GridGeometry2D; +import org.geotools.geometry.GeneralDirectPosition; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; + +import com.raytheon.edex.uengine.tasks.query.TableQuery; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.grid.GridConstants; +import com.raytheon.uf.common.dataplugin.grid.GridInfoRecord; +import com.raytheon.uf.common.dataplugin.grid.GridRecord; +import com.raytheon.uf.common.geospatial.ISpatialObject; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.geospatial.PointUtil; +import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.dao.CoreDao; +import com.raytheon.uf.edex.database.dao.DaoConfig; +import com.raytheon.uf.edex.database.query.DatabaseQuery; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.CoordinateSequence; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LinearRing; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; + +//import org.opengis.geometry.Envelope; + +public class MdlSoundingQuery { + private static final String GRID_TBL_NAME = "grid"; + + private static String GRID_PARMS = "GH, uW, vW,T, DWPK, SPFH,OMEG, RH, DpD, DpT"; + + private enum GridParmNames { + GH, uW, vW, T, DWPK, SPFH, OMEG, RH, DpD, DpT + }; + + public static UnitConverter kelvinToCelsius = SI.KELVIN + .getConverterTo(SI.CELSIUS); + + private static final UnitConverter metersPerSecondToKnots = SI.METERS_PER_SECOND + .getConverterTo(NonSI.KNOT); + + // Note; we are using NCInventory now. So, this api is actually not used. + public static NcSoundingTimeLines getMdlSndTimeLine(String mdlType, + String currentDBTblName) { + NcSoundingTimeLines tl = new NcSoundingTimeLines(); + /* + * if(currentDBTblName.equals(NCGRIB_TBL_NAME)){ Object[] refTimeAry = + * null; String queryStr = new String("Select Distinct reftime FROM " + + * currentDBTblName + " where modelname='" + mdlType + + * "' ORDER BY reftime DESC"); + * + * CoreDao dao = new CoreDao(DaoConfig.forClass(NcgribRecord.class)); + * refTimeAry = (Object[]) dao.executeSQLQuery(queryStr); + * tl.setTimeLines(refTimeAry); }else + * if(currentDBTblName.equals(D2DGRIB_TBL_NAME)){ TableQuery query; try + * { query = new TableQuery("metadata", GridRecord.class.getName()); + * query.setDistinctField("dataTime.refTime"); + * query.addParameter(GridConstants.DATASET_ID, mdlType); + * query.setSortBy("dataTime.refTime", false); + * + * @SuppressWarnings("unchecked") List recList = + * (List) query.execute(); + * tl.setTimeLines(recList.toArray()); } catch (DataAccessLayerException + * e) { // TODO Auto-generated catch block e.printStackTrace(); } catch + * (Exception e) { // TODO Auto-generated catch block + * e.printStackTrace(); } + * + * } + */ + + // Chin: modified for Unified Grid DB + // Use the following SQL statement + // Select Distinct reftime FROM grid FULL JOIN grid_info ON + // grid.info_id=grid_info.id where grid_info.datasetid='gfs' ORDER BY + // reftime DESC + Object[] refTimeAry = null; + String queryStr = new String( + "Select Distinct reftime FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id where grid_info.datasetid='" + + mdlType + "' ORDER BY reftime DESC"); + + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + refTimeAry = dao.executeSQLQuery(queryStr); + tl.setTimeLines(refTimeAry); + + return tl; + } + + public static NcSoundingTimeLines getMdlSndRangeTimeLine(String mdlType, + String refTimeStr, String currentDBTblName) { + NcSoundingTimeLines tl = new NcSoundingTimeLines(); + /* + * if(currentDBTblName.equals(NCGRIB_TBL_NAME)){ Object[] refTimeAry = + * null; String queryStr = new String("Select Distinct rangestart FROM " + * + currentDBTblName + " where modelname='" + mdlType + "' AND " + + * "reftime='" + refTimeStr + ":00:00'" + " ORDER BY rangestart"); + * System.out.println("queryStr " + queryStr); + * + * CoreDao dao = new CoreDao(DaoConfig.forClass(SoundingSite.class)); + * refTimeAry = (Object[]) dao.executeSQLQuery(queryStr); + * tl.setTimeLines(refTimeAry); } else + * if(currentDBTblName.equals(D2DGRIB_TBL_NAME)){ TableQuery query; try + * { query = new TableQuery("metadata", GridRecord.class.getName()); + * query.setDistinctField("dataTime.validPeriod.start"); + * query.addParameter(GridConstants.DATASET_ID, mdlType); + * query.addParameter("dataTime.refTime", refTimeStr + ":00:00"); + * query.setSortBy("dataTime.validPeriod.start", true); + * + * @SuppressWarnings("unchecked") List recList = + * (List) query.execute(); + * tl.setTimeLines(recList.toArray()); } catch (DataAccessLayerException + * e) { // TODO Auto-generated catch block e.printStackTrace(); } catch + * (Exception e) { // TODO Auto-generated catch block + * e.printStackTrace(); } + */ + // Chin: modified for Unified Grid DB + // make sure data in DB is not just nHour data, as those data are not + // used by Nsharp. And when query to it, the returned will be + // null. We do not want to show such sounding time line to user. + // use this SQL query string for gfs as example. + /* + * Select Distinct rangestart FROM grid FULL JOIN grid_info ON + * grid.info_id=grid_info.id where grid.reftime = '2012-01-26 00:00:00' + * AND grid.rangestart = grid.rangeend AND + * grid_info.datasetid='mesoEta212' AND + * grid_info.parameter_abbreviation='T' order by rangestart + */ + Object[] soundingTimeAry = null; + List reSoundingTimeAry = new ArrayList(); + String queryStr = new String( + "Select Distinct rangestart FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id where grid.reftime = '" + + refTimeStr + + ":00:00' AND grid.rangestart = grid.rangeend AND grid_info.datasetid='" + + mdlType + + "' AND grid_info.parameter_abbreviation='T' order by rangestart"); + // System.out.println("queryStr " + queryStr); + + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + soundingTimeAry = (Object[]) dao.executeSQLQuery(queryStr); + for (int i = 0; i < soundingTimeAry.length; i++) { + /* + * Chin: make sure the time line has more than 5 T(temp) values at + * pressure (levelone) greater/equal than/to 100 hPa (mbar) use this + * SQL : Select count(rangestart) FROM (select rangestart FROM grid + * FULL JOIN grid_info ON grid.info_id=grid_info.id FULL JOIN level + * ON grid_info.level_id= level.id where grid.rangestart = + * '2012-01-26 03:00:00.0' AND grid.rangestart = grid.rangeend AND + * grid_info.datasetid='mesoEta212' AND + * grid_info.parameter_abbreviation='T' AND level.levelonevalue > + * 99) X HAVING count(X.rangestart) >5 + */ + String queryStr1 = new String( + "Select count(rangestart) FROM (select rangestart FROM grid FULL JOIN grid_info ON grid.info_id=grid_info.id FULL JOIN level ON grid_info.level_id= level.id where grid.rangestart = '" + + soundingTimeAry[i] + + "' AND grid.rangestart = grid.rangeend AND grid_info.datasetid='" + + mdlType + + "' AND grid_info.parameter_abbreviation='T' AND level.levelonevalue > 99) X HAVING count(X.rangestart) >2"); + Object[] countAry = null; + // System.out.println("queryStr1 " + queryStr1); + countAry = (Object[]) dao.executeSQLQuery(queryStr1); + java.math.BigInteger count = new java.math.BigInteger("0"); + if (countAry.length > 0) { + // System.out.println("rangestart =" + // +soundingTimeAry[i]+" number="+countAry[0]); + count = (java.math.BigInteger) countAry[0]; + } + // else{ + // System.out.println("rangestart =" + // +soundingTimeAry[i]+" return null"); + // } + if (count.intValue() > 2) { + Object timeLine = soundingTimeAry[i]; + reSoundingTimeAry.add(timeLine); + } + } + + tl.setTimeLines(reSoundingTimeAry.toArray()); + + // } + return tl; + } // public static NcSoundingProfile getMdlSndData(double lat, double lon, + + // String stn, long refTimeL, long validTimeL, String sndTypeStr, + // SndQueryKeyType queryType, String mdlName) { + // //*System.out.println("getPfcSndData input ref time = "+ + // refTimeL+" valid time is " + validTimeL); + // Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + // refTimeCal.setTimeInMillis(refTimeL); + // Calendar validTimeCal = + // Calendar.getInstance(TimeZone.getTimeZone("GMT")); + // validTimeCal.setTimeInMillis(validTimeL); + // return getMdlSndData( lat, lon, refTimeCal, validTimeCal, "ncgrib", + // mdlName); + // } + + /** + * Returns a list of profile for location (lat,lon) array, time, and model + * for grib or ncgrib data. + * + * @param double[][] latLonArray, e.g. at nth element, lat=[n][0], + * lon=[n][1] + * @param refTimeCal + * data record reference time + * @param validTimeCal + * data record valid time + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param mdlName + * the name of the model + * @return the profile created @ 3/28/2012 + */ + public static List getMdlSndDataProfileList( + double[][] latLonArray, String refTime, String validTime, + String pluginName, String mdlName) { + double lat, lon; + // System.out.println("getMdlSndData lat=" + lat + " lon="+lon); + long t01 = System.currentTimeMillis(); + NcSoundingProfile pf = new NcSoundingProfile(); + // NcSoundingCube cube = new NcSoundingCube(); + List soundingProfileList = new ArrayList(); + List levels = getModelLevels(refTime, validTime, pluginName, mdlName); + if (levels.size() == 0) { + System.out.println("getModelLevels return 0; file=" + refTime + + " stime=" + validTime + " gribtype=" + pluginName + + " modeltype=" + mdlName); + return soundingProfileList; + } + // System.out.println("getModelLevels = "+ + // levels.size()+" levels, took "+ (System.currentTimeMillis()-t01) + + // " ms"); + + List points = new ArrayList(); + for (int k = 0; k < latLonArray.length; k++) { + lat = latLonArray[k][0]; + lon = latLonArray[k][1]; + Point pnt = getLatLonIndices(lat, lon, refTime, validTime, levels + .get(0).toString(), pluginName, mdlName); + if (pnt == null) { + System.out.println("getLatLonIndices return 0; lat=" + lat + + " lon=" + lon + " stime=" + validTime + " gribtype=" + + pluginName + " modeltype=" + mdlName); + } else { + points.add(pnt); + } + } + if (points.size() == 0) { + return soundingProfileList; + } + long t011 = System.currentTimeMillis(); + soundingProfileList = queryProfileListByPointGroup(points, refTime, + validTime, pluginName, mdlName, levels); + System.out.println("queryProfileListByPointGroup took " + + (System.currentTimeMillis() - t011) + " ms"); + + return soundingProfileList; + /* + * The floowing should be done in queryProfileListByPointGroup() + * //System.out.println("getModelSoundingLayerList= "+ layerList.size()+ + * " layers, took "+ (System.currentTimeMillis()-t012) + " ms"); + * //pf.setStationLatitude( lat); //pf.setStationLongitude( lon); + * //Float sfcPressure = getModelSfcPressure(pnt, refTime, validTime, // + * pluginName, mdlName); + * //System.out.println("getModelSfcPressure took "+ + * (System.currentTimeMillis()-t013) + " ms"); //if (sfcPressure == + * null) { // pf.setSfcPress(-9999.f); //} //else { // if + * (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) // + * pf.setSfcPress(sfcPressure/100F); // else // + * pf.setSfcPress(sfcPressure); //} + * //System.out.println("surface pressure ="+pf.getSfcPress()+ + * " lat= "+lat+ " lon="+lon); //calculate dew point if necessary long + * t014 = System.currentTimeMillis(); MergeSounding ms = new + * MergeSounding(); //ms.spfhToDewpoint(layerList); + * ms.rhToDewpoint(layerList); System.out.println("MergeSounding took "+ + * (System.currentTimeMillis()-t014) + " ms"); + * + * + * pf.setSoundingLyLst(layerList); + * + * + * soundingProfileList.add(pf); + * //cube.setSoundingProfileList(soundingProfileList); + * //cube.setRtnStatus(NcSoundingCube.QueryStatus.OK); long t02 = + * System.currentTimeMillis(); + * System.out.println("MDL cube retreival took " + (t02 - t01)); return + * pf; + */ + + } + + /** + * Returns a profile for a specified location (lat,lon), time, and model for + * grib or ncgrib data. + * + * @param lat + * location latitude + * @param lon + * location longitude + * @param refTimeCal + * data record reference time + * @param validTimeCal + * data record valid time + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param mdlName + * the name of the model + * @return the profile + * + * public static NcSoundingProfile getMdlSndData(double lat, double + * lon, String refTime, String validTime, String pluginName, String + * mdlName) { System.out.println("getMdlSndData lat=" + lat + + * " lon="+lon); long t01 = System.currentTimeMillis(); + * NcSoundingProfile pf = new NcSoundingProfile(); List levels = + * getModelLevels(refTime, validTime, pluginName, mdlName); if + * (levels.size() == 0) { + * System.out.println("getModelLevels return 0; file=" + refTime+ + * " stime="+validTime + " gribtype="+ pluginName + + * " modeltype="+mdlName); + * pf.setRtnStatus(NcSoundingCube.QueryStatus.FAILED); return pf; } + * System.out.println("getModelLevels = "+ + * levels.size()+" levels, took "+ (System.currentTimeMillis()-t01) + * + " ms"); long t011 = System.currentTimeMillis(); Point pnt = + * getLatLonIndices(lat, lon, refTime, validTime, + * levels.get(0).toString(), pluginName, mdlName); if (pnt == null) + * { System.out.println("getLatLonIndices return 0; lat=" + lat + + * " lon="+lon+" stime="+validTime + " gribtype="+ pluginName + + * " modeltype="+mdlName); + * + * pf.setRtnStatus(NcSoundingCube.QueryStatus.LOCATION_NOT_FOUND); + * return pf; + * + * } System.out.println("getLatLonIndices pntX=" + pnt.getX()+ + * " pntY=" + pnt.getY()+ " took "+ + * (System.currentTimeMillis()-t011) + " ms"); long t012 = + * System.currentTimeMillis(); List layerList = + * getModelSoundingLayerList(pnt, refTime, validTime, pluginName, + * mdlName, levels); if (layerList.size() == 0) { + * System.out.println("getModelSoundingLayerList return 0; lat=" + + * lat + " lon="+lon+" stime="+validTime + " gribtype="+ pluginName + * + " modeltype="+mdlName); + * + * + * pf.setRtnStatus(NcSoundingCube.QueryStatus.FAILED); return pf; } + * + * System.out.println("getModelSoundingLayerList= "+ + * layerList.size()+ " layers, took "+ + * (System.currentTimeMillis()-t012) + " ms"); + * + * pf.setStationLatitude( lat); pf.setStationLongitude( lon); Float + * sfcPressure = getModelSfcPressure(pnt, refTime, validTime, + * pluginName, mdlName); + * //System.out.println("getModelSfcPressure took "+ + * (System.currentTimeMillis()-t013) + " ms"); if (sfcPressure == + * null) { pf.setSfcPress(-9999.f); } else { if + * (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) + * pf.setSfcPress(sfcPressure/100F); else + * pf.setSfcPress(sfcPressure); } + * //System.out.println("surface pressure ="+pf.getSfcPress()+ + * " lat= "+lat+ " lon="+lon); //calculate dew point if necessary + * long t014 = System.currentTimeMillis(); MergeSounding ms = new + * MergeSounding(); //ms.spfhToDewpoint(layerList); + * ms.rhToDewpoint(layerList); + * System.out.println("MergeSounding took "+ + * (System.currentTimeMillis()-t014) + " ms"); + * + * + * pf.setSoundingLyLst(layerList); + * + * long t02 = System.currentTimeMillis(); + * System.out.println("MDL cube retreival took " + (t02 - t01)); + * return pf; + * + * } + */ + + public static NcSoundingModel getMdls(String pluginName) { + NcSoundingModel mdls = new NcSoundingModel(); + Object[] mdlName = null; + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridInfoRecord.class)); + String queryStr = new String( + "Select Distinct modelname FROM grib_models ORDER BY modelname"); + mdlName = (Object[]) dao.executeSQLQuery(queryStr); + } + if (mdlName != null && mdlName.length > 0) { + List mdlList = new ArrayList(); + for (Object mn : mdlName) { + mdlList.add((String) mn); + } + mdls.setMdlList(mdlList); + } + return mdls; + } + + public static boolean isPointWithinGridGeometry(double lat, double lon, + String refTime, String validTime, String pluginName, + String modelName) { + + ISpatialObject spatialArea = null; + MathTransform crsFromLatLon = null; + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + + query.setMaxResults(new Integer(1)); + query.addQueryParam(GridConstants.DATASET_ID, modelName); + query.addQueryParam("dataTime.refTime", refTime); + query.addQueryParam("dataTime.validPeriod.start", validTime); + + try { + List recList = ((List) dao + .queryByCriteria(query)); + if (recList.size() == 0) { + return false; + } else { + GridRecord rec = recList.get(0); + spatialArea = rec.getSpatialObject(); + } + + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } + + try { + crsFromLatLon = MapUtil + .getTransformFromLatLon(spatialArea.getCrs()); + } catch (FactoryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + DirectPosition lowerCorner = MapUtil.getGridGeometry(spatialArea) + .getEnvelope().getLowerCorner(); + DirectPosition upperCorner = MapUtil.getGridGeometry(spatialArea) + .getEnvelope().getUpperCorner(); + + GeometryFactory gf = new GeometryFactory(); + + Coordinate p1 = new Coordinate(lowerCorner.getOrdinate(0), + lowerCorner.getOrdinate(1)); + Coordinate p2 = new Coordinate(lowerCorner.getOrdinate(0), + upperCorner.getOrdinate(1)); + Coordinate p3 = new Coordinate(upperCorner.getOrdinate(0), + upperCorner.getOrdinate(1)); + Coordinate p4 = new Coordinate(upperCorner.getOrdinate(0), + lowerCorner.getOrdinate(1)); + + LinearRing lr = gf.createLinearRing(new Coordinate[] { p1, p2, p3, p4, + p1 }); + + Polygon gridGeometry = gf.createPolygon(lr, null); + + DirectPosition ll = new GeneralDirectPosition(MapUtil.LATLON_PROJECTION); + + Coordinate coord = new Coordinate(lon, lat); + ll.setOrdinate(0, coord.x); + ll.setOrdinate(1, coord.y); + // DirectPosition crs = new GeneralDirectPosition(spatialArea.getCrs()); + // try { + // crsFromLatLon.transform(ll, crs); + // } catch (MismatchedDimensionException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } catch (TransformException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + // + // Coordinate newC = new Coordinate(crs.getOrdinate(0), + // crs.getOrdinate(1)); + Coordinate newC = new Coordinate(ll.getOrdinate(0), ll.getOrdinate(1)); + + com.vividsolutions.jts.geom.Point p = gf.createPoint(newC); + + return gridGeometry.contains(p); + + } + + public static boolean isPointWithinGridGeometry2(double lat, double lon, + String refTime, String validTime, String pluginName, + String modelName) { + + ISpatialObject spatialArea = null; + MathTransform crsFromLatLon = null; + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + + query.setMaxResults(new Integer(1)); + query.addQueryParam(GridConstants.DATASET_ID, modelName); + query.addQueryParam("dataTime.refTime", refTime); + query.addQueryParam("dataTime.validPeriod.start", validTime); + + try { + List recList = ((List) dao + .queryByCriteria(query)); + if (recList.size() == 0) { + return false; + } else { + GridRecord rec = recList.get(0); + spatialArea = rec.getSpatialObject(); + } + + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } + + Geometry g = spatialArea.getGeometry(); + + GeometryFactory geometryFactory = new GeometryFactory(); + CoordinateSequence sequence = new CoordinateArraySequence( + g.getCoordinates()); + + Coordinate[] oldCoords = sequence.toCoordinateArray(); + Coordinate[] newCoords = new Coordinate[oldCoords.length]; + /* + * adjust longitude for global grids whose lon span goes from 0 to 360 + * and the asked lon is negative. + */ + for (Coordinate c : oldCoords) { + double x = c.x; + double y = c.y; + double z = c.z; + if (x >= 180.0 && x <= 360.0 && lon < 0.0) { + lon = lon + 360.0; + break; + } + } + Coordinate coord = new Coordinate(lon, lat); + + LinearRing ring = new LinearRing(sequence, geometryFactory); + Polygon gridGeometry = new Polygon(ring, null, geometryFactory); + com.vividsolutions.jts.geom.Point p = geometryFactory + .createPoint(coord); + + return gridGeometry.contains(p); + + } + + /** + * Returns the value of surface pressure for a specified location, time, and + * model for grib or ncgrib data. + * + * @param pnt + * location + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param modelName + * the name of the model + * @return surface pressure + */ + public static Float getModelSfcPressure(Point pnt, String refTime, + String validTime, String pluginName, String modelName) { + + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + + query.addQueryParam(GridConstants.LEVEL_ONE, "0.0"); + query.addQueryParam(GridConstants.LEVEL_TWO, "-999999.0"); + query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MSL"); + query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "PMSL"); + query.addQueryParam(GridConstants.DATASET_ID, modelName); + query.addQueryParam("dataTime.refTime", refTime); + query.addQueryParam("dataTime.validPeriod.start", validTime); + + GridRecord rec = null; + try { + List recList = ((List) dao + .queryByCriteria(query)); + if (recList.size() == 0) { + return null; + } else { + rec = recList.get(0); + PointIn pointIn = new PointIn(pluginName, rec, pnt.x, pnt.y); + try { + float fdata = pointIn.getPointData(); + return new Float(fdata); + } catch (PluginException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + return null; + + } + + /** + * Returns a list of NcSoundingProfile for a group of Point with specific + * ref and range time, and model for grib or ncgrib data. + * + * @param pnt + * location + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param modelName + * the name of the model + * @param levels + * list of vertical levels + * @return list of NcSoundingLayer objects + * + * Created @ 3/28/2012 + */ + + private static List queryProfileListByPointGroup( + List points, String refTime, String validTime, + String pluginName, String modelName, List levels) { + + List soundingProfileList = new ArrayList(); + List fdataArrayList = new ArrayList(); + // long t01 = System.currentTimeMillis(); + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + List recList = new ArrayList(); + ; + TableQuery query; + try { + query = new TableQuery("metadata", GridRecord.class.getName()); + query.addParameter(GridConstants.MASTER_LEVEL_NAME, "MB"); + query.addParameter(GridConstants.DATASET_ID, modelName); + query.addList(GridConstants.PARAMETER_ABBREVIATION, GRID_PARMS); + query.addParameter("dataTime.refTime", refTime); + query.addParameter("dataTime.validPeriod.start", validTime); + query.setSortBy(GridConstants.LEVEL_ONE, false); + recList = (List) query.execute(); + if (recList.size() != 0) { + PointIn pointIn = new PointIn(pluginName, recList.get(0)); + fdataArrayList = pointIn.getHDF5GroupDataPoints( + recList.toArray(), points); + } + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + int index = 0; + GridGeometry2D geom = MapUtil.getGridGeometry(spatialArea); + CoordinateReferenceSystem crs = geom.getCoordinateReferenceSystem(); + Coordinate coord = new Coordinate(45, 45); + + for (float[] fdataArray : fdataArrayList) { + // one fdataArray is for one Point or say one profile + NcSoundingProfile pf = new NcSoundingProfile(); + List soundLyList = new ArrayList(); + Point pnt = points.get(index); + Object[] recArray = recList.toArray(); + for (Object level : levels) { + NcSoundingLayer soundingLy = new NcSoundingLayer(); + double pressure = (Double) level; + soundingLy.setPressure((float) pressure); + for (int i = 0; i < recArray.length; i++) { + GridRecord rec1 = (GridRecord) recArray[i]; + float fdata = fdataArray[i]; + if (rec1.getLevel().getLevelonevalue() == pressure) { + String prm = rec1.getParameter().getAbbreviation(); + //System.out.println("prm="+prm+" value="+fdata); + switch (GridParmNames.valueOf(prm)) { + case GH: + soundingLy.setGeoHeight(fdata); + break; + case uW: + // HDF5 data in unit of m/s, convert to Knots + // 4/12/2012 + soundingLy + .setWindU((float) metersPerSecondToKnots + .convert(fdata)); + break; + case vW: + // HDF5 data in unit of m/s, convert to Knots + // 4/12/2012 + soundingLy + .setWindV((float) metersPerSecondToKnots + .convert(fdata)); + break; + case T: + soundingLy + .setTemperature((float) kelvinToCelsius + .convert(fdata)); + break; + case DWPK: + soundingLy.setDewpoint((float) kelvinToCelsius + .convert(fdata)); + break; + case OMEG: + soundingLy.setOmega(fdata); + break; + case RH: + soundingLy.setRelativeHumidity(fdata); + break; + case DpD: + soundingLy.setDpd(fdata); + break; + case DpT: + soundingLy.setDewpoint((float) kelvinToCelsius + .convert(fdata)); + break; + case SPFH: + soundingLy.setSpecHumidity(fdata); + break; + default: + break; + } + } + } + soundLyList.add(soundingLy); + } + try { + coord = PointUtil.determineLatLon(pnt, crs, geom); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // System.out.println(" point coord.y="+coord.y+ " coord.x="+ + // coord.x); + pf.setStationLatitude(coord.y); + pf.setStationLongitude(coord.x); + // Float sfcPressure = getModelSfcPressure(pnt, refTime, + // validTime, + // pluginName, modelName); + // System.out.println("getModelSfcPressure took "+ + // (System.currentTimeMillis()-t013) + " ms"); + // /if (sfcPressure == null) { + pf.setSfcPress(-9999.f); + // } + // else { + // pf.setSfcPress(sfcPressure/100F); + // } + // System.out.println("surface pressure ="+pf.getSfcPress()+ + // " lat= "+lat+ " lon="+lon); + // calculate dew point if necessary + MergeSounding ms = new MergeSounding(); + // ms.spfhToDewpoint(layerList); + ms.rhToDewpoint(soundLyList); + ms.dpdToDewpoint(soundLyList); + pf.setSoundingLyLst(soundLyList); + soundingProfileList.add(pf); + index++; + } + } + return soundingProfileList; + } + + /** + * Returns a list of NcSoundingLayer for a specified location, time, and + * model for grib or ncgrib data. + * + * @param pnt + * location + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param modelName + * the name of the model + * @param levels + * list of vertical levels + * @return list of NcSoundingLayer objects + * + * + * private static List + * getModelSoundingLayerList(Point pnt, String refTime, String + * validTime, String pluginName, String modelName, List levels) { + * List soundLyList = new + * ArrayList(); + * + * //long t01 = System.currentTimeMillis(); if + * (pluginName.equalsIgnoreCase(NCGRIB_TBL_NAME)) { + * + * TableQuery query; try { query = new TableQuery("metadata", + * NcgribRecord.class.getName()); query.addParameter("vcord", + * "PRES"); query.addParameter("modelName", modelName); + * query.addList("parm",NC_PARMS);//parmList.toString()); // + * query.addParameter("dataTime.refTime", refTime); + * query.addParameter("dataTime.validPeriod.start", validTime); + * //query.addParameter("glevel1", level.toString()); + * query.setSortBy("glevel1", false); + * + * + * List recList = (List) + * query.execute(); + * System.out.println("Ncgrib group query0 result size ="+ + * recList.size()); + * + * if (recList.size() != 0) { + * + * PointIn pointIn = new PointIn(pluginName, recList.get(0), pnt.x, + * pnt.y); //Chin note: // We query all levels (pressure) and all + * parameters (at that level) at once. // The return array + * (fdataArray) are listed in the same order as query array + * (recList.toArray()) //However, returned array does not tell you + * which parameter itself is. //Therefore, we have to use + * information in query array to find out returned value's type + * (which parameter it is) // Further, we have to sort and store + * returned values to NcSoundingLayer based on its level (pressure) + * // Parameters in same level should be stored in one same + * NcSoundingLayer float[] fdataArray = + * pointIn.getHDF5GroupDataPoint(recList.toArray()); Object[] + * recArray = recList.toArray(); for (Object level : levels){ + * NcSoundingLayer soundingLy = new NcSoundingLayer(); int pressure= + * (Integer)level; soundingLy.setPressure( pressure); + * + * for (int i=0; i < recArray.length; i++) { NcgribRecord rec1 = + * (NcgribRecord)recArray[i]; float fdata = fdataArray[i]; + * if(rec1.getGlevel1() == pressure){ String prm = rec1.getParm(); + * //System.out.println("point.x="+ pnt.x + + * " .y="+pnt.y+"pressure="+rec1 // .getGlevel1()+ " Parm="+prm ); + * //long t01 = System.currentTimeMillis(); switch + * (NcParmNames.valueOf(prm)) { case HGHT: + * soundingLy.setGeoHeight(fdata); break; case UREL: // HDF5 data in + * unit of Knots, no conversion needed soundingLy.setWindU(fdata); + * break; case VREL: // HDF5 data in unit of Knots, no conversion + * needed soundingLy.setWindV(fdata); break; case TMPK: + * soundingLy.setTemperature((float) kelvinToCelsius + * .convert(fdata)); break; case DWPK: + * soundingLy.setDewpoint((float) kelvinToCelsius .convert(fdata)); + * break; case SPFH: soundingLy.setSpecHumidity(fdata); break; case + * OMEG: soundingLy.setOmega(fdata); break; case RELH: + * soundingLy.setRelativeHumidity(fdata); break; } } } + * soundLyList.add(soundingLy); } } + * + * } catch (DataAccessLayerException e) { // TODO Auto-generated + * catch block e.printStackTrace(); } catch (Exception e) { // TODO + * Auto-generated catch block e.printStackTrace(); } + * //System.out.println("getModelSoundingLayerList:total level = "+ + * totalLevel + " total records= "+totalRecords ); + * + * } else if (pluginName.equalsIgnoreCase(D2DGRIB_TBL_NAME)) { try { + * TableQuery query = new TableQuery("metadata", + * GribRecord.class.getName()); + * //query.addParameter("modelInfo.level.levelonevalue", // + * level.toString()); + * //query.addParameter("modelInfo.level.leveltwovalue", // + * "-999999.0"); + * query.addParameter("modelInfo.level.masterLevel.name", "MB"); + * query.addParameter("modelInfo.modelName", modelName); + * query.addList("modelInfo.parameterAbbreviation", D2D_PARMS); + * query.addParameter("dataTime.refTime", refTime); + * query.addParameter("dataTime.validPeriod.start", validTime); + * query.setSortBy("modelInfo.level.levelonevalue", false); + * //System.out.println("level = "+ level.toString()); + * + * List recList = (List) query.execute(); + * System.out.println("Grib group query0 result size ="+ + * recList.size()); + * + * if (recList.size() > 0) { PointIn pointIn = new + * PointIn(pluginName, recList.get(0), pnt.x, pnt.y); float[] + * fdataArray = pointIn.getHDF5GroupDataPoint(recList.toArray()); + * Object[] recArray = recList.toArray(); for (Object level : + * levels){ NcSoundingLayer soundingLy = new NcSoundingLayer(); + * double pressure= (Double)level; soundingLy.setPressure( + * (float)pressure); + * + * for (int i=0; i < recArray.length; i++) { GribRecord rec1 = + * (GribRecord)recArray[i]; float fdata = fdataArray[i]; + * if(rec1.getModelInfo().getLevelOneValue() == pressure){ String + * prm = rec1.getModelInfo().getParameterAbbreviation(); + * //System.out.println("point.x="+ pnt.x + + * " .y="+pnt.y+"pressure="+pressure+ " Parm="+prm ); //long t01 = + * System.currentTimeMillis(); switch (D2DParmNames.valueOf(prm)) { + * case GH: soundingLy.setGeoHeight(fdata); break; case uW: // HDF5 + * data in unit of Knots, no conversion needed + * soundingLy.setWindU(fdata); break; case vW: // HDF5 data in unit + * of Knots, no conversion needed soundingLy.setWindV(fdata); break; + * case T: soundingLy.setTemperature((float) kelvinToCelsius + * .convert(fdata)); break; case DWPK: + * soundingLy.setDewpoint((float) kelvinToCelsius .convert(fdata)); + * break; case OMEG: soundingLy.setOmega(fdata); break; case RH: + * soundingLy.setRelativeHumidity(fdata); break; } } } + * soundLyList.add(soundingLy); } } } catch + * (DataAccessLayerException e) { // TODO Auto-generated catch block + * e.printStackTrace(); } catch (Exception e) { // TODO + * Auto-generated catch block e.printStackTrace(); } } + * + * //long t02 = System.currentTimeMillis(); + * //System.out.println("MDL profile retreival took " + (t02 - + * t01)); + * + * for(NcSoundingLayer layer: soundLyList){ + * System.out.println("pre="+ layer.getPressure()+ + * " h="+layer.getGeoHeight()+ " T="+layer.getTemperature()+" D="+ + * layer.getDewpoint()+ " WS="+layer.getWindSpeed()+ + * " WD="+layer.getWindDirection() + " SH="+layer.getSpecHumidity()+ + * " RH="+layer.getRelativeHumidity()); } return soundLyList; } + */ + /** + * Return a list of data vertical levels for a specified time and model for + * grib or ncgrib data. + * + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param modelName + * the name of the model + * @return list of vertical levels + */ + public static List getModelLevels(String refTime, String validTime, + String pluginName, String modelName) { + + // Listvals = null; + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + query.addDistinctParameter(GridConstants.LEVEL_ONE); + query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "GH"); + query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MB"); + + query.addQueryParam(GridConstants.DATASET_ID, modelName); + query.addQueryParam("dataTime.refTime", refTime); + query.addQueryParam("dataTime.validPeriod.start", validTime); + query.addOrder(GridConstants.LEVEL_ONE, false); + + try { + return (List) dao.queryByCriteria(query); + + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + return null; + + } + + private static ISpatialObject spatialArea = null; + + /** + * Returns the indices of the model grid of the closest point to the + * specified latitude, longitude. + * + * @param lat + * latitude + * @param lon + * longitude + * @param level + * vertical level + * @param pluginName + * the name of the data table ('grib' or 'ncgrib') + * @param modelName + * the name of the model + * @return the point indices + */ + public static Point getLatLonIndices(double lat, double lon, + String refTime, String validTime, String level, String pluginName, + String modelName) { + // ISpatialObject spatialArea = null; + + Point pnt = null; + + if (pluginName.equalsIgnoreCase(GRID_TBL_NAME)) { + CoreDao dao = new CoreDao(DaoConfig.forClass(GridRecord.class)); + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + + query.addQueryParam(GridConstants.PARAMETER_ABBREVIATION, "GH"); + query.addQueryParam(GridConstants.MASTER_LEVEL_NAME, "MB"); + query.addQueryParam(GridConstants.DATASET_ID, modelName); + query.addQueryParam("dataTime.refTime", refTime); + query.addQueryParam("dataTime.validPeriod.start", validTime); + query.addQueryParam(GridConstants.LEVEL_ONE, level); + query.addQueryParam(GridConstants.LEVEL_TWO, "-999999.0"); + + GridRecord rec; + try { + List recList = ((List) dao + .queryByCriteria(query)); + if (recList.size() == 0) { + return null; + } else { + rec = recList.get(0); + spatialArea = rec.getSpatialObject(); + } + } catch (DataAccessLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + } else + return null; + + GridGeometry2D geom = MapUtil.getGridGeometry(spatialArea); + + CoordinateReferenceSystem crs = geom.getCoordinateReferenceSystem(); + Coordinate coord = new Coordinate(lon, lat); + + try { + pnt = PointUtil.determineIndex(coord, crs, geom); + Integer nx = spatialArea.getNx(); + Integer ny = spatialArea.getNy(); + + if (pnt.x > nx || pnt.y > ny) { + return null; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return pnt; + + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp.win32/bignsharp.dll b/ncep/gov.noaa.nws.ncep.ui.nsharp.win32/bignsharp.dll index d394920f79..453b1030a8 100644 Binary files a/ncep/gov.noaa.nws.ncep.ui.nsharp.win32/bignsharp.dll and b/ncep/gov.noaa.nws.ncep.ui.nsharp.win32/bignsharp.dll differ diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpSoundingElementStateProperty.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpSoundingElementStateProperty.java index fccb434c63..e014e6e015 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpSoundingElementStateProperty.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpSoundingElementStateProperty.java @@ -19,6 +19,9 @@ import java.util.List; * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 04/23/2012 229 Chin Chen Initial coding + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -37,9 +40,10 @@ public class NsharpSoundingElementStateProperty { private int compColorIndex; private List sndLyLst; private List sndLyLstBk; + private boolean goodData = true; //#5929 public NsharpSoundingElementStateProperty(String elementDescription, String stnDescription, - String timeDescription, NsharpStationInfo stnInfo, List sndLyLst) { + String timeDescription, NsharpStationInfo stnInfo, List sndLyLst, boolean goodData) { super(); this.elementDescription = elementDescription; //this.elementState = elementState; @@ -49,6 +53,7 @@ public class NsharpSoundingElementStateProperty { this.sndType = stnInfo.getSndType(); this.compColorIndex = NsharpConstants.LINE_COMP1;; this.sndLyLst = sndLyLst; + this.goodData = goodData; //#5929 sndLyLstBk= new ArrayList(sndLyLst.size()); for(NcSoundingLayer ly : sndLyLst){ try { @@ -134,5 +139,13 @@ public class NsharpSoundingElementStateProperty { } } } + + public boolean isGoodData() { + return goodData; + } + + public void setGoodData(boolean goodData) { + this.goodData = goodData; + } } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpAbstractPaneDescriptor.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpAbstractPaneDescriptor.java index 2bbad12a99..d33f29f61f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpAbstractPaneDescriptor.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpAbstractPaneDescriptor.java @@ -13,7 +13,10 @@ * 05/02/2012 229 Chin Chen Initial coding for multiple display panes implementation * 03/11/2013 972 Greg Hull rm paneNumber * 03/11/2013 2491 bsteffen extend IDescriptor derictly for better serialization detection. - + * 01/13/2015 DR#17008, + * task#5930 Chin Chen NSHARP Hodograph Does Not Loop in D2D Lite Configuration + * moved "setFrameCoordinator()" from NsharpSkewTPaneDescriptor to here, + * so it can be used by other descriptor * * * @@ -24,6 +27,7 @@ package gov.noaa.nws.ncep.ui.nsharp.display; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpAbstractPaneResource; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpResourceHandler; +import gov.noaa.nws.ncep.viz.ui.display.NCLoopProperties; import java.util.List; @@ -34,15 +38,14 @@ import org.geotools.referencing.crs.DefaultEngineeringCRS; import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.datastructure.LoopProperties; +import com.raytheon.uf.viz.core.drawables.FrameCoordinator; import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.uf.viz.core.drawables.IFrameCoordinator; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.core.graphing.GraphDescriptor; @XmlAccessorType(XmlAccessType.NONE) public class NsharpAbstractPaneDescriptor extends GraphDescriptor implements IDescriptor { -// @XmlElement -// protected int paneNumber; - protected NsharpResourceHandler rscHandler=null; @@ -53,14 +56,6 @@ public class NsharpAbstractPaneDescriptor extends GraphDescriptor implements public void setRscHandler(NsharpResourceHandler rscHandler) { this.rscHandler = rscHandler; } - -// public int getPaneNumber() { -// return paneNumber; -// } -// -// public void setPaneNumber(int paneNumber) { -// this.paneNumber = paneNumber; -// } public NsharpAbstractPaneDescriptor() { super(); @@ -106,4 +101,64 @@ public class NsharpAbstractPaneDescriptor extends GraphDescriptor implements e.printStackTrace(); } } + //DR17008 + protected void setFrameCoordinator() { + frameCoordinator = new FrameCoordinator(this) { + @Override + /* + * Chin Note: this function handles keyboard up/down/left/right arrow keys for station and time line stepping. + */ + public void changeFrame( + IFrameCoordinator.FrameChangeOperation operation, + IFrameCoordinator.FrameChangeMode mode) { + if(rscHandler == null) + return; + //System.out.println("NsharpSkewTPaneDescriptor changeFrame(operation) called op="+operation+" mode"+mode); + if(mode == IFrameCoordinator.FrameChangeMode.SPACE_ONLY){ + //up/down arrow keys for stepping stations + //editor.getRscHandler().setSteppingStnIdList(operation); + rscHandler.setSteppingStnIdList(operation); + } else if(mode == IFrameCoordinator.FrameChangeMode.TIME_ONLY || mode == IFrameCoordinator.FrameChangeMode.TIME_AND_SPACE){ + //left/right arrow keys for stepping time lines + //editor.getRscHandler().setSteppingTimeLine(operation, mode); + rscHandler.setSteppingTimeLine(operation, mode); + } + } + /* + * (non-Javadoc) + * @see com.raytheon.uf.viz.core.drawables.FrameCoordinator#changeFrame(com.raytheon.uf.viz.core.datastructure.LoopProperties) + * This function handling nsharp looping. + * Chin: 12.8.1: let skewtPaneDescriptor handle looping. All other pane descriptor will do nothing. Otherwise, we will looping X times faster when we + * have X number of panes configured and each pane move frame once. + * + */ + @Override + public void changeFrame(LoopProperties loopProperties) { + if(rscHandler == null) + return; + + long waitTime = Long.MAX_VALUE; + //System.out.println("NsharpSkewTPaneDescriptor changeFrame(loop) called, loopDirection= "+loopDirection + " fwd="+loopProperties.getFwdFrameTime()+ + // " back="+loopProperties.getRevFrameTime() + " 1st dt="+loopProperties.getFirstFrameDwell()+ " lasDt="+loopProperties.getLastFrameDwell()); + if(loopProperties.getMode() == LoopProperties.LoopMode.Forward || loopProperties.getMode() == LoopProperties.LoopMode.Cycle) + waitTime = loopProperties.getFwdFrameTime(); + else + waitTime = loopProperties.getRevFrameTime(); + int frameSize= rscHandler.getTimeElementListSize(); + int curFrameIndex = rscHandler.getCurrentTimeElementListIndex(); + if(curFrameIndex == 0) + waitTime = loopProperties.getFirstFrameDwell(); + else if(curFrameIndex == frameSize-1) + waitTime = loopProperties.getLastFrameDwell(); + + loopProperties.drawAfterWait(waitTime); + //System.out.println("wait time="+waitTime); + if (loopProperties.isShouldDraw()) { + rscHandler.setLoopingDataTimeLine(loopProperties); + //System.out.println("loopinp step"); + } + } + + }; + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpEditor.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpEditor.java index f8a020eab7..35db1031d9 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpEditor.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpEditor.java @@ -18,6 +18,8 @@ package gov.noaa.nws.ncep.ui.nsharp.display; * 06/14/2011 11-5 Chin Chen migration * 03/11/2013 972 Greg Hull rm paneNum and editorNum; rm AbstractNcEditor * 03/25/2013 972 Greg Hull rm unused Add/RemoveListeners. + * 01/13/2015 DR#17008, + * task#5930 Chin Chen NSHARP Hodograph Does Not Loop in D2D Lite Configuration * * * @@ -178,7 +180,7 @@ public class NsharpEditor extends AbstractEditor implements private int futureHeightHint; private int futureWidthHint; - + private String paneConfigurationName; private IRenderableDisplay[] displayArray; @@ -1382,13 +1384,17 @@ public class NsharpEditor extends AbstractEditor implements DISPLAY_SPC_GRAPHS = -1; } else if (paneConfigurationName // d2dlite start .equals(NsharpConstants.PANE_LITE_D2D_CFG_STR)) { - if (rscHandler != null - && rscHandler.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { - DISPLAY_HODO = 0; + //5930 + NsharpPaletteWindow win = NsharpPaletteWindow.getInstance(); + if (win != null && + win.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { + //#5930if (rscHandler != null + // && rscHandler.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { + DISPLAY_HODO = 0 ; DISPLAY_TIMESTN = DISPLAY_HODO + 1; DISPLAY_SKEWT = -1; } else { - DISPLAY_SKEWT = 0; + DISPLAY_SKEWT = 0; DISPLAY_TIMESTN = DISPLAY_SKEWT + 1; DISPLAY_HODO = -1; } @@ -1459,8 +1465,12 @@ public class NsharpEditor extends AbstractEditor implements // d2dlite start } else if (paneConfigurationName .equals(NsharpConstants.PANE_LITE_D2D_CFG_STR)) { - if (rscHandler != null - && rscHandler.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { + //5930 + NsharpPaletteWindow win = NsharpPaletteWindow.getInstance(); + if (win != null && + win.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { + //#5930 if (rscHandler != null + //&& rscHandler.getCurrentGraphMode() == NsharpConstants.GRAPH_HODO) { displayArray[DISPLAY_HODO] = new NsharpHodoPaneDisplay( new PixelExtent(NsharpConstants.HODO_DISPLAY_REC), DISPLAY_HODO); @@ -1610,9 +1620,11 @@ public class NsharpEditor extends AbstractEditor implements nsharpComp = new Composite[DISPLAY_TOTAL]; displayPane = new VizDisplayPane[DISPLAY_TOTAL]; - EditorInput edInput = new EditorInput(new NCLoopProperties(), + //EditorInput edInput = new EditorInput(new NsharpLoopProperties(), + // displayArray); + //CHIN task#5930 use same loop properties + EditorInput edInput = new EditorInput(this.editorInput.getLoopProperties(), displayArray); - this.setInput(edInput); this.displaysToLoad = displayArray; for (IRenderableDisplay display : displayArray) { @@ -2130,4 +2142,10 @@ public class NsharpEditor extends AbstractEditor implements // + // pane.toString()+" newRenderableDisplay="+newRenderableDisplay.toString()); } + + public String getPaneConfigurationName() { + return paneConfigurationName; + } + + } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpHodoPaneDescriptor.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpHodoPaneDescriptor.java index b52bf3cb3d..d6ac487932 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpHodoPaneDescriptor.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpHodoPaneDescriptor.java @@ -11,6 +11,8 @@ * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 05/02/2012 229 Chin Chen Initial coding for multiple display panes implementation + * 01/13/2015 DR#17008, + * task#5930 Chin Chen NSHARP Hodograph Does Not Loop in D2D Lite Configuration * * * @@ -19,7 +21,9 @@ */ package gov.noaa.nws.ncep.ui.nsharp.display; +import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpHodoPaneResource; +import gov.noaa.nws.ncep.viz.common.ui.NmapCommon; import java.util.List; @@ -28,19 +32,36 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; import com.raytheon.uf.viz.core.PixelExtent; +import com.raytheon.uf.viz.core.drawables.IFrameCoordinator; +import com.raytheon.uf.viz.d2d.core.time.D2DTimeMatcher; +import com.raytheon.viz.ui.perspectives.VizPerspectiveListener; @XmlAccessorType(XmlAccessType.NONE) @XmlType(name = "nsharpHodoPaneDescriptor") public class NsharpHodoPaneDescriptor extends NsharpAbstractPaneDescriptor { public NsharpHodoPaneDescriptor(PixelExtent pe) { super(pe); - //System.out.println("NsharpHodoPaneDescriptor created " + this.toString()); + if((NsharpEditor.getActiveNsharpEditor() != null) && (NsharpEditor.getActiveNsharpEditor().getPaneConfigurationName().equals(NsharpConstants.PANE_LITE_D2D_CFG_STR))) + { + setTimeMatcher(new D2DTimeMatcher()); + setFrameCoordinator(); + } } public NsharpHodoPaneDescriptor(PixelExtent pe, int paneNumber) { super(pe, paneNumber); + if((NsharpEditor.getActiveNsharpEditor() != null) && (NsharpEditor.getActiveNsharpEditor().getPaneConfigurationName().equals(NsharpConstants.PANE_LITE_D2D_CFG_STR))) + { + setTimeMatcher(new D2DTimeMatcher()); + setFrameCoordinator(); + } } public NsharpHodoPaneDescriptor() { super(); + if((NsharpEditor.getActiveNsharpEditor() != null) && (NsharpEditor.getActiveNsharpEditor().getPaneConfigurationName().equals(NsharpConstants.PANE_LITE_D2D_CFG_STR))) + { + setTimeMatcher(new D2DTimeMatcher()); + setFrameCoordinator(); + } } public NsharpHodoPaneResource getHodoResource() { List list = resourceList @@ -50,5 +71,35 @@ public class NsharpHodoPaneDescriptor extends NsharpAbstractPaneDescriptor { } return null; } + @SuppressWarnings("deprecation") + @Override + /* + * Chin Note: this function handles time line stepping from NC Perspective tool bar left/right/first/last arrow Buttons. + */ + public void changeFrame(FrameChangeOperation operation, FrameChangeMode mode) { + synchronized (this) { + //Chin Note: there are multiple (6) panes. + //We only need to step one timeline. Therefore, we handle stepping by skewt pane. + //However, for D2D LITE display configuration, when switched to HODO pane, skewT pane is no longer + //in charge. therefore, we have to handle this special case here by HODO pane. + + if((rscHandler == null) ||(!rscHandler.getPaneConfigurationName().equals(NsharpConstants.PANE_LITE_D2D_CFG_STR))) + return; + + if( VizPerspectiveListener.getCurrentPerspectiveManager()!= null){ + //System.out.println("changeFrame: current perspective ="+VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId()); + if(!VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId().equals(NmapCommon.NatlCntrsPerspectiveID)){ + if(mode != FrameChangeMode.TIME_ONLY) + return; + } + } + + // we will have to do conversion here + IFrameCoordinator.FrameChangeOperation dop = IFrameCoordinator.FrameChangeOperation.valueOf(operation.name()); + IFrameCoordinator.FrameChangeMode dmode = IFrameCoordinator.FrameChangeMode.valueOf(mode.name()); + rscHandler.setSteppingTimeLine(dop, dmode); + + } + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSkewTPaneDescriptor.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSkewTPaneDescriptor.java index 8bf47918b0..8bf1a70bca 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSkewTPaneDescriptor.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSkewTPaneDescriptor.java @@ -11,6 +11,10 @@ * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 05/02/2012 229 Chin Chen Initial coding for multiple display panes implementation + * 01/13/2015 DR#17008, + * task#5930 Chin Chen NSHARP Hodograph Does Not Loop in D2D Lite Configuration + * moved "setFrameCoordinator()" to NsharpAbstractPaneDescriptor, + * so it can be used by other descriptor * * * @@ -29,8 +33,6 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; import com.raytheon.uf.viz.core.PixelExtent; -import com.raytheon.uf.viz.core.datastructure.LoopProperties; -import com.raytheon.uf.viz.core.drawables.FrameCoordinator; import com.raytheon.uf.viz.core.drawables.IFrameCoordinator; import com.raytheon.uf.viz.d2d.core.time.D2DTimeMatcher; import com.raytheon.viz.ui.perspectives.VizPerspectiveListener; @@ -54,69 +56,7 @@ public class NsharpSkewTPaneDescriptor extends NsharpAbstractPaneDescriptor { setTimeMatcher(new D2DTimeMatcher()); setFrameCoordinator(); } - - private void setFrameCoordinator() { - frameCoordinator = new FrameCoordinator(this) { - @Override - /* - * Chin Note: this function handles keyboard up/down/left/right arrow keys for station and time line stepping. - */ - public void changeFrame( - IFrameCoordinator.FrameChangeOperation operation, - IFrameCoordinator.FrameChangeMode mode) { - //NsharpEditor editor = NsharpEditor.getActiveNsharpEditor() ; - //if(editor== null || editor.getRscHandler()==null) - // return; - if(rscHandler == null) - return; - //System.out.println("NsharpSkewTPaneDescriptor changeFrame(operation) called op="+operation+" mode"+mode); - if(mode == IFrameCoordinator.FrameChangeMode.SPACE_ONLY){ - //up/down arrow keys for stepping stations - //editor.getRscHandler().setSteppingStnIdList(operation); - rscHandler.setSteppingStnIdList(operation); - } else if(mode == IFrameCoordinator.FrameChangeMode.TIME_ONLY || mode == IFrameCoordinator.FrameChangeMode.TIME_AND_SPACE){ - //left/right arrow keys for stepping time lines - //editor.getRscHandler().setSteppingTimeLine(operation, mode); - rscHandler.setSteppingTimeLine(operation, mode); - } - } - /* - * (non-Javadoc) - * @see com.raytheon.uf.viz.core.drawables.FrameCoordinator#changeFrame(com.raytheon.uf.viz.core.datastructure.LoopProperties) - * This function handling nsharp looping. - * Chin: 12.8.1: let skewtPaneDescriptor handle looping. All other pane descriptor will do nothing. Otherwise, we will looping X times faster when we - * have X number of panes configured and each pane move frame once. - * - */ - @Override - public void changeFrame(LoopProperties loopProperties) { - if(rscHandler == null) - return; - long waitTime = Long.MAX_VALUE; - //System.out.println("NsharpSkewTPaneDescriptor changeFrame(loop) called, loopDirection= "+loopDirection + " fwd="+loopProperties.getFwdFrameTime()+ - // " back="+loopProperties.getRevFrameTime() + " 1st dt="+loopProperties.getFirstFrameDwell()+ " lasDt="+loopProperties.getLastFrameDwell()); - if(loopProperties.getMode() == LoopProperties.LoopMode.Forward || loopProperties.getMode() == LoopProperties.LoopMode.Cycle) - waitTime = loopProperties.getFwdFrameTime(); - else - waitTime = loopProperties.getRevFrameTime(); - int frameSize= rscHandler.getTimeElementListSize(); - int curFrameIndex = rscHandler.getCurrentTimeElementListIndex(); - if(curFrameIndex == 0) - waitTime = loopProperties.getFirstFrameDwell(); - else if(curFrameIndex == frameSize-1) - waitTime = loopProperties.getLastFrameDwell(); - - loopProperties.drawAfterWait(waitTime); - - if (loopProperties.isShouldDraw()) { - rscHandler.setLoopingDataTimeLine(loopProperties); - - } - } - - }; - } - public NsharpSkewTPaneResource getSkewtResource() { + public NsharpSkewTPaneResource getSkewtResource() { List list = resourceList .getResourcesByTypeAsType(NsharpSkewTPaneResource.class); if (list != null && !list.isEmpty()) { diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpDataPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpDataPaneResource.java index 1ea1597a9e..50f81bcafe 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpDataPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpDataPaneResource.java @@ -13,6 +13,9 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * 04/23/2012 229 Chin Chen Initial coding * 04/23/2014 Chin Chen Add d2d lite page * 08/11/2014 Chin Chen fix typo + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -60,7 +63,8 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { // number of this page. index 0 // point to a dummy. - private static final String NO_DATA = "NO VALID DATA AVAILABLE"; + private static final String NO_DATA = "NO VALID DATA AVAILABLE FOR THIS PAGE"; + private static final String INSUFFICIENT_DATA = "INSUFFICIENT DATA FOR PARAMETERS COMPUTATION"; // private double charHeight = NsharpConstants.CHAR_HEIGHT_; private double curY; @@ -160,7 +164,7 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { handleResize(); } - if ((soundingLys != null) && (soundingLys.size() >= 4)) { + if ((soundingLys != null) && (rscHandler.isGoodData())) {//#5929 this.defaultFont.setSmoothing(false); this.defaultFont.setScaleFont(false); // write to panels @@ -187,6 +191,9 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { } } } + else { //#5929 + drawInsuffDataMessage(target, panelRectArray[0]); + } } @Override @@ -239,6 +246,28 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { super.resetData(soundingLys, prevsoundingLys); currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; } + + @SuppressWarnings("deprecation") //#5929 + private void drawInsuffDataMessage(IGraphicsTarget target, Rectangle rect) + throws VizException { + IFont myfont; + if (paneConfigurationName.equals(NsharpConstants.PANE_LITE_D2D_CFG_STR)) + myfont = font9; + else + myfont = font20; + + defineCharHeight(myfont); + myfont.setSmoothing(false); + myfont.setScaleFont(false); + sumP1Visible = true; + extent = new PixelExtent(rect); + target.setupClippingPlane(extent); + target.drawString(myfont, INSUFFICIENT_DATA, rect.x, + rect.y, 0.0, TextStyle.NORMAL, NsharpConstants.color_cyan, + HorizontalAlignment.LEFT, VerticalAlignment.TOP, null); + return; + + } private void drawPanel(IGraphicsTarget target, int pageOrderNumber, int dsiplayPanelNumber) throws VizException { @@ -344,7 +373,7 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { // if we can not Interpolates a temp with 700 mb pressure, then we dont // have enough raw data if ((nsharpNative.nsharpLib.qc(nsharpNative.nsharpLib.itemp(700.0F)) == 0)) { - target.drawString(myfont, " " + NO_DATA, rect.x, + target.drawString(myfont, NO_DATA, rect.x, rect.y, 0.0, TextStyle.NORMAL, NsharpConstants.color_cyan, HorizontalAlignment.LEFT, VerticalAlignment.TOP, null); return; @@ -1053,7 +1082,7 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { // if we can not Interpolates a temp with 700 mb pressure, then we dont // have enough raw data if (nsharpNative.nsharpLib.qc(nsharpNative.nsharpLib.itemp(700.0F)) == 0) { - target.drawString(myfont, " " + NO_DATA, rect.x, + target.drawString(myfont,NO_DATA, rect.x, rect.y, 0.0, TextStyle.NORMAL, NsharpConstants.color_cyan, HorizontalAlignment.LEFT, VerticalAlignment.TOP, null); return; @@ -3749,7 +3778,7 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource { // if we can not Interpolates a temp with 700 mb pressure, then we dont // have enough raw data if ((nsharpNative.nsharpLib.qc(nsharpNative.nsharpLib.itemp(700.0F)) == 0)) { - target.drawString(myfont, " " + NO_DATA, rect.x, + target.drawString(myfont, NO_DATA, rect.x, rect.y, 0.0, TextStyle.NORMAL, NsharpConstants.color_cyan, HorizontalAlignment.LEFT, VerticalAlignment.TOP, null); return; diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpHodoPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpHodoPaneResource.java index 3a32bf087d..460b89a7c6 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpHodoPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpHodoPaneResource.java @@ -10,6 +10,9 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 04/23/2012 229 Chin Chen Initial coding + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -127,7 +130,7 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ hodoWindRscShapeList.add(shNcolor); } - + float surfaceLevel = soundingLays.get(0).getGeoHeight(); //#5929 for (NcSoundingLayer layer : soundingLays){ if(layer.getPressure() < 100 || layer.getWindSpeed() <0) continue; @@ -138,15 +141,15 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ double [][] lines = {{world.mapX(c0.x), world.mapY(c0.y)},{world .mapX(c1.x), world.mapY(c1.y)}}; if(incolor == null){ - if(layer.getGeoHeight() = 4)) + if((soundingLys != null) && (soundingLys.size()> 2) ) { this.font10.setSmoothing(false); this.font10.setScaleFont(false); @@ -602,13 +606,11 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ } target.clearClippingPlane(); if(cursorInHodo){ - + drawHodoDynamicData(target, currentZoomLevel); } - - } - + } @Override diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpInsetPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpInsetPaneResource.java index 94d4c5a028..5b48dacb7e 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpInsetPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpInsetPaneResource.java @@ -10,6 +10,9 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 04/23/2012 229 Chin Chen Initial coding + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -181,7 +184,7 @@ public class NsharpInsetPaneResource extends NsharpAbstractPaneResource{ //Chin, since we only display 4 insets and their backgrounds have same size, only draws 4 backgrounds. //psblWatchTypeBackground.paint(target, paintProps); //thetaEPresureBackground.paint(target, paintProps); - if((soundingLys != null) && (soundingLys.size()>= 4)) + if((soundingLys != null) && rscHandler.isGoodData()) //#5929) { this.font10.setSmoothing(false); this.font10.setScaleFont(false); @@ -294,7 +297,7 @@ public class NsharpInsetPaneResource extends NsharpAbstractPaneResource{ return; //System.out.println("createRscWireFrameShapes called"); disposeInsetWireFrameShapes(); - if(soundingLys != null){ + if(soundingLys != null && rscHandler.isGoodData()){ //#5929 WGraphics WGc= thetaEPresureBackground.getWorld(); createRscThetaEPressureShape(WGc); diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java index f9f861282f..b100409d46 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java @@ -14,6 +14,10 @@ * 01/13/2014 Chin Chen TTR829- when interpolation, edit graph is allowed * 02/03/2014 1106 Chin Chen Need to be able to use clicking on the Src,Time, or StnId to select display * 08/12/2014 Chin Chen fixed issue that "load archive file with wrong time line displayed" + * 12/04/2014 DR16888 Chin Chen fixed issue that "Comp(Src) button not functioning properly in NSHARP display" + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @author Chin Chen @@ -160,6 +164,8 @@ public class NsharpResourceHandler { private int[] pageDisplayOrderNumberArray = new int[NsharpConstants.PAGE_MAX_NUMBER + 1]; + //#5929 + private boolean goodData=false; // index is the real page defined in NsharpConstants to be shown, value is // the order number of this page. // index 0 point to a dummy. @@ -187,7 +193,7 @@ public class NsharpResourceHandler { private int currentSoundingLayerIndex = 0; private int hodoEditingSoundingLayerIndex = 0; - + private boolean plotInteractiveTemp = false; private Coordinate interactiveTempPointCoordinate; @@ -575,11 +581,12 @@ public class NsharpResourceHandler { * The following code is to create a list of stns within the range * of user defined radius (minimum distance) to "current" station * and also has data loaded with same time line as "current" time - * line. Note that we have two time line formats, yymmdd/hh(day)Vxxx - * and yymmdd/hh(day). A same time line is compared by yymmdd/hh + * line. Note that we have two time line formats, MM.DDVxxx(day) + * and MM.DD(day). A same time line is compared by MM.DD * only. All qualified stations, including current station, found * will be listed and used for SND comparison. */ + String TIME_COMPARE_STRING = "MM.DD"; compSndSelectedElemList.clear(); // CompSndSelectedElem curStnTimeIndexCouple = new // CompSndSelectedElem(currentStnElementListIndex,currentTimeElementListIndex,currentSndElementListIndex); @@ -593,7 +600,12 @@ public class NsharpResourceHandler { .get(currentSndElementListIndex).getStnInfo(); gc.setStartingGeographicPoint(currentStnInfo.getLongitude(), currentStnInfo.getLatitude()); - int timeLineLengthToComp = "yymmdd/hh".length(); + + // String curTimeString = timeElementList.get(currentTimeElementListIndex).getElementDescription(); + + int timeLineLengthToComp = TIME_COMPARE_STRING.length(); + + String currentTimeLineToComp = timeElementList .get(currentTimeElementListIndex).getElementDescription() .substring(0, timeLineLengthToComp); @@ -974,6 +986,7 @@ public class NsharpResourceHandler { if (skewtPaneRsc != null) skewtPaneRsc .setCurrentSkewTEditMode(NsharpConstants.SKEWT_EDIT_MODE_EDITPOINT); + elem.setGoodData(checkDataIntegrity(soundingLys));//#5929 resetData(); } @@ -986,7 +999,12 @@ public class NsharpResourceHandler { // update active sounding layer and picked stn info // re-populate snd data to nsharp native code lib for later calculating - nsharpNative.populateSndgData(soundingLys); + //#5929 dont populate sounding data if data is bad + + if(getCurSoundingElementStateProperty()!=null) + goodData= getCurSoundingElementStateProperty().isGoodData(); + if(goodData) + nsharpNative.populateSndgData(soundingLys); if (skewtPaneRsc != null) skewtPaneRsc.resetData(soundingLys, previousSoundingLys); @@ -1006,7 +1024,7 @@ public class NsharpResourceHandler { // if soundingLys is null, then we stop here, after reset data. if (soundingLys == null) return; - if (soundingLys.size() > 0) { + if (soundingLys.size() > 0 && (goodData)) { // set initial hodohouseC // ----- set hodo circle at Bunkers Right, Chin according to TTR6065 @@ -1037,11 +1055,7 @@ public class NsharpResourceHandler { * that really meant to reset parcel type. */ } - // Chin: TBD remove handle resize here to fix sizing issue when swapped - // nsharp from side pane back to main pane - // but, may cause other problem? - // if(skewtPaneRsc!=null) - // skewtPaneRsc.handleResize(); + if (skewtPaneRsc != null) skewtPaneRsc.createRscWireFrameShapes(); if (hodoPaneRsc != null) @@ -1050,7 +1064,7 @@ public class NsharpResourceHandler { insetPaneRsc.createInsetWireFrameShapes(); if (witoPaneRsc != null) witoPaneRsc.createAllWireFrameShapes(); - if (spcGraphsPaneRsc != null) { + if (spcGraphsPaneRsc != null && (goodData) ){//#5929 // Chin: SPC graphs performance concern, as it need to call get // info functions from bigSharo.so and cause long delay. // Therefore, do it once only when reset data. @@ -1170,7 +1184,7 @@ public class NsharpResourceHandler { private void addElementToTableAndLists(String stnId_timeLine_sndType, String stnId, String tmLine, String sndType, - NsharpStationInfo stnInfo, List sndLyLst) { + NsharpStationInfo stnInfo, List sndLyLst, boolean goodData) { // System.out.println("stn to be added "+ stnId + " timeline "+tmLine); NsharpSoundingElementStateProperty newSndPropElem = null; int tmIndex = getIndexFromElementList(tmLine, timeElementList); @@ -1190,7 +1204,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); //#5929 stnTimeSndTable.get(stnIndex).get(tmIndex) .set(sndTpyeIndex, newSndPropElem); } @@ -1207,7 +1221,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1224,7 +1238,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1246,7 +1260,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1267,7 +1281,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1289,7 +1303,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1314,7 +1328,7 @@ public class NsharpResourceHandler { // NsharpSoundingElementStateProperty object newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); stnTimeSndTable.get(currentStnElementListIndex) .get(currentTimeElementListIndex) .set(currentSndElementListIndex, newSndPropElem); @@ -1350,7 +1364,7 @@ public class NsharpResourceHandler { // one new loaded sounding data newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, - tmLine, stnInfo, sndLyLst); + tmLine, stnInfo, sndLyLst,goodData); sndlistForTm.add(newSndPropElem); } else { @@ -1398,7 +1412,7 @@ public class NsharpResourceHandler { newSndPropElem = new NsharpSoundingElementStateProperty( stnId_timeLine_sndType, stnId, tmLine, stnInfo, - sndLyLst); + sndLyLst,goodData); newList.add(newSndPropElem); newListList.add(newList); stnTimeSndTable.add(newListList); @@ -1855,6 +1869,21 @@ public class NsharpResourceHandler { * * } */ + //task#5929 + private boolean checkDataIntegrity(List sndLayers){ + boolean gooddata = false; + int numberOfTemp=0; + int numberOfGoodDewPt=0; + for(NcSoundingLayer layer: sndLayers){ + if(layer.getTemperature() > -999) + numberOfTemp++; + if(layer.getDewpoint() > -999) + numberOfGoodDewPt++; + } + if(numberOfGoodDewPt >= 2 && numberOfTemp>=2) + gooddata=true; + return gooddata; + } // This api peforms real load data function private void addRsc(boolean displayNewData, @@ -1862,15 +1891,15 @@ public class NsharpResourceHandler { NsharpStationInfo stnInfo, boolean fromArchive) { // // testing code // stnInfo.setStnId("KUKI"); - // Set keysettest = new HashSet(soundMap.keySet()); - // for (String key : keysettest) { - // List sndLy = soundMap.remove(key); // String +// Set keysettest = new HashSet(soundMap.keySet()); +// for (String key : keysettest) { +// List sndLy = soundMap.remove(key); // String // // newkey= - // // key.replace("NCUAIR", "gpduair"); // String newkey = - // // key.replace("NAMS", "SSS"); - // String newkey = key.replace("140303/12", "120109/12"); - // soundMap.put(newkey, sndLy); - // } // +// String newkey =key.replace("NCUAIR", "gpduair"); // String newkey = + // String newkey= key.replace("NAMS", "SSS"); +// String newkey = key.replace("130925/17(Wed)V017", "131001/00(Thu)V000"); + // soundMap.put(newkey, sndLy); +// } // // stnInfo.setSndType(stnInfo.getSndType().replace("NCUAIR", // // // "gpduair")); // stnInfo.setSndType(stnInfo.getSndType().replace( // // "NAMS","SSS")); @@ -1924,9 +1953,15 @@ public class NsharpResourceHandler { // based on this KEY string format "KGRI 100616/03(Wed)Vxxx GFSSND" String stnId, sndType, timeLine, timeLine_sndType, stnId_timeLine_sndType; List sndLyLst; + try { stnId_timeLine_sndType = tempTimeLineArr[i].toString(); + if(stnId_timeLine_sndType.equals("N/A")) + { + continue; + } sndLyLst = soundMap.get(stnId_timeLine_sndType); + stnId = stnId_timeLine_sndType.substring(0, stnId_timeLine_sndType.indexOf(" ")); timeLine_sndType = stnId_timeLine_sndType @@ -2015,8 +2050,10 @@ public class NsharpResourceHandler { // No more needed? timeLine = timeLine.replace(" ", "-"); //fixed // DR15325 - sorting time line issue in D2D // add time line to stnTimeTable and set its index + //task#5929 + boolean goodData = checkDataIntegrity( sndLyLst); addElementToTableAndLists(stnId_timeLine_sndType, stnId, timeLine, - sndType, stnInfo, sndLyLst); + sndType, stnInfo, sndLyLst, goodData); } if (displayNewData) { // Set default parcel trace data @@ -4027,7 +4064,13 @@ public class NsharpResourceHandler { // re-populate snd data to nsharp native code lib for later calculating Collections.sort(soundingLys, NsharpDataHandling.reversePressureHeightWindComparator()); - nsharpNative.populateSndgData(soundingLys); + //#5929 + goodData = checkDataIntegrity( soundingLys); + if(getCurSoundingElementStateProperty()!=null){ + getCurSoundingElementStateProperty().setGoodData(goodData); + } + if(goodData) + nsharpNative.populateSndgData(soundingLys); // get storm motion wind data after populate sounding from NsharpLib // refresh test area if it is shown now NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); @@ -4053,6 +4096,13 @@ public class NsharpResourceHandler { } if (dataPaneRsc != null) dataPaneRsc.setSoundingLys(soundingLys); + + if (spcGraphsPaneRsc != null && (goodData) ){//#5929 + // Chin: SPC graphs performance concern, as it need to call get + // info functions from bigSharo.so and cause long delay. + // Therefore, do it once only when reset data. + spcGraphsPaneRsc.getSpcGraphsInfo(); + } } public void addNewLayer(float tp, float dp, float ws, float wd, @@ -4070,7 +4120,13 @@ public class NsharpResourceHandler { // re-populate snd data to nsharp native code lib for later calculating Collections.sort(soundingLys, NsharpDataHandling.reversePressureHeightWindComparator()); - nsharpNative.populateSndgData(soundingLys); + //#5929 + goodData = checkDataIntegrity( soundingLys); + if(getCurSoundingElementStateProperty()!=null){ + getCurSoundingElementStateProperty().setGoodData(goodData); + } + if(goodData) + nsharpNative.populateSndgData(soundingLys); // get storm motion wind data after populate sounding from NsharpLib // refresh text area if it is shown now NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); @@ -4096,6 +4152,12 @@ public class NsharpResourceHandler { } if (dataPaneRsc != null) dataPaneRsc.setSoundingLys(soundingLys); + if (spcGraphsPaneRsc != null && (goodData) ){//#5929 + // Chin: SPC graphs performance concern, as it need to call get + // info functions from bigSharo.so and cause long delay. + // Therefore, do it once only when reset data. + spcGraphsPaneRsc.getSpcGraphsInfo(); + } } public void setGraphConfigProperty(NsharpGraphProperty graphConfigProperty) { @@ -4424,4 +4486,9 @@ public class NsharpResourceHandler { refreshPane(); return true; } + //#5929 + public boolean isGoodData() { + return goodData; + } + } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSkewTPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSkewTPaneResource.java index e896e1b0c5..b4f5606f6b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSkewTPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSkewTPaneResource.java @@ -14,6 +14,9 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * May 08, 2013 1847 bsteffen Allow painting with no Wind Data. * 02/03/2014 1106 Chin Chen Need to be able to use clicking on the Src,Time, or StnId to select display * 08/04/2014 Chin Chen fixed effective level line drawing, height marker drawing + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -1739,6 +1742,8 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource { // box } target.drawStrings(str, latlonstr); + if(wwTypeColor == null) + wwTypeColor = NsharpConstants.color_gold; target.drawRect(boxExt, wwTypeColor, 2f, 1f); // box border line colored // with "Psbl Watch Type" // color @@ -1767,7 +1772,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource { // to check a scenario that sounding data is removed while // thread is locked if (soundingLys == null - || (soundingLys != null && soundingLys.size() <= 0)) { + || (soundingLys != null && soundingLys.size() < 2)) { reentryLock.unlock(); return; } @@ -1778,7 +1783,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource { } else if (justBackToMainPane) { reentryLock.lock(); if (soundingLys == null - || (soundingLys != null && soundingLys.size() <= 0)) { + || (soundingLys != null && soundingLys.size() < 2)) { reentryLock.unlock(); return; } @@ -1827,376 +1832,384 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource { this.font12.setScaleFont(false); // nsharpNative.populateSndgData(soundingLys); if (currentGraphMode == NsharpConstants.GRAPH_SKEWT) { - target.setupClippingPlane(pe); - // plot temp curve, when constructing pressureTempRscShapeList, - // it already considered - // comparison, overlay, etc..so, just draw it. - for (NsharpShapeAndLineProperty shapeNLp : pressureTempRscShapeList) { - target.drawWireframeShape(shapeNLp.getShape(), shapeNLp - .getLp().getLineColor(), shapeNLp.getLp() - .getLineWidth(), shapeNLp.getLp().getLineStyle(), - font10);// commonLinewidth*2,commonLineStyle,font10); - } - // plot real temp parcel trace, when constructing - // parcelRtShapeList, it already considered - // comparison, overlay, etc..so, just draw it. - // color is following comparison/overlay lines' configuration. - // line width and line style are following parcel line - // configuration - if (graphConfigProperty.isParcel() == true) { - NsharpLineProperty parcelLp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL]); - for (NsharpShapeAndLineProperty shapeNLp : parcelRtShapeList) { - target.drawWireframeShape(shapeNLp.getShape(), shapeNLp - .getLp().getLineColor(), parcelLp - .getLineWidth(), parcelLp.getLineStyle(), - font10);// commonLinewidth*2,commonLineStyle,font10); - } - } - boolean compareStnIsOn = rscHandler.isCompareStnIsOn(); - boolean compareSndIsOn = rscHandler.isCompareSndIsOn(); - boolean compareTmIsOn = rscHandler.isCompareTmIsOn(); - boolean editGraphOn = rscHandler.isEditGraphOn(); - boolean overlayIsOn = rscHandler.isOverlayIsOn(); - if (graphConfigProperty != null) { - if (graphConfigProperty.isTemp() == true && !compareStnIsOn - && !compareTmIsOn) { - if (editGraphOn) - plotPressureTempEditPoints(target, world, - NsharpConstants.color_red, TEMP_TYPE, - this.soundingLys); - } - // dew point curve - if (graphConfigProperty.isDewp() == true && !compareStnIsOn - && !compareTmIsOn) { - if (editGraphOn) - plotPressureTempEditPoints(target, world, - NsharpConstants.color_green, DEWPOINT_TYPE, - this.soundingLys); - } - // plot wet bulb trace - if (graphConfigProperty.isWetBulb() == true - && !compareStnIsOn && !compareTmIsOn) { - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_WETBULB]); - target.drawWireframeShape(wetBulbTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - } - // plot virtual temperature trace - if (graphConfigProperty.isVTemp() == true - && !compareStnIsOn && !compareTmIsOn) { - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_VIRTUAL_TEMP]); - target.drawWireframeShape(vtempTraceCurveRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - } - // virtual temperature parcel trace curve - if (graphConfigProperty.isParcelTv() == true - && !compareStnIsOn && !compareTmIsOn - && !overlayIsOn) { - if (soundingLys.size() > 0) { - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL_TV]); - target.drawWireframeShape(parcelVtTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - } - } - if (graphConfigProperty.isDcape() == true - && dacpeTraceRscShape != null && !compareStnIsOn - && !compareTmIsOn && !overlayIsOn) { - if (soundingLys.size() > 0) { - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_DCAPE]); - target.drawWireframeShape(dacpeTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); + target.setupClippingPlane(pe); + // plot temp curve, when constructing pressureTempRscShapeList, + // it already considered + // comparison, overlay, etc..so, just draw it. + for (NsharpShapeAndLineProperty shapeNLp : pressureTempRscShapeList) { + target.drawWireframeShape(shapeNLp.getShape(), shapeNLp + .getLp().getLineColor(), shapeNLp.getLp() + .getLineWidth(), shapeNLp.getLp().getLineStyle(), + font10);// commonLinewidth*2,commonLineStyle,font10); + } + // plot real temp parcel trace, when constructing + // parcelRtShapeList, it already considered + // comparison, overlay, etc..so, just draw it. + // color is following comparison/overlay lines' configuration. + // line width and line style are following parcel line + // configuration + if (graphConfigProperty.isParcel() == true && rscHandler.isGoodData()) { //#5929 + NsharpLineProperty parcelLp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL]); + for (NsharpShapeAndLineProperty shapeNLp : parcelRtShapeList) { + target.drawWireframeShape(shapeNLp.getShape(), shapeNLp + .getLp().getLineColor(), parcelLp + .getLineWidth(), parcelLp.getLineStyle(), + font10);// commonLinewidth*2,commonLineStyle,font10); + } + } + boolean compareStnIsOn = rscHandler.isCompareStnIsOn(); + boolean compareSndIsOn = rscHandler.isCompareSndIsOn(); + boolean compareTmIsOn = rscHandler.isCompareTmIsOn(); + boolean editGraphOn = rscHandler.isEditGraphOn(); + boolean overlayIsOn = rscHandler.isOverlayIsOn(); + if (graphConfigProperty != null) { + if (graphConfigProperty.isTemp() == true && !compareStnIsOn + && !compareTmIsOn) { + if (editGraphOn) + plotPressureTempEditPoints(target, world, + NsharpConstants.color_red, TEMP_TYPE, + this.soundingLys); + } + // dew point curve + if (graphConfigProperty.isDewp() == true && !compareStnIsOn + && !compareTmIsOn) { + if (editGraphOn) + plotPressureTempEditPoints(target, world, + NsharpConstants.color_green, DEWPOINT_TYPE, + this.soundingLys); + } + // plot wet bulb trace + if (graphConfigProperty.isWetBulb() == true && rscHandler.isGoodData() //#5929 + && !compareStnIsOn && !compareTmIsOn) { + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_WETBULB]); + target.drawWireframeShape(wetBulbTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + } + // plot virtual temperature trace + if (graphConfigProperty.isVTemp() == true && rscHandler.isGoodData() //#5929 + && !compareStnIsOn && !compareTmIsOn) { + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_VIRTUAL_TEMP]); + target.drawWireframeShape(vtempTraceCurveRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + } + // virtual temperature parcel trace curve + if (graphConfigProperty.isParcelTv() == true && rscHandler.isGoodData() //#5929 + && !compareStnIsOn && !compareTmIsOn + && !overlayIsOn) { + if (soundingLys.size() > 0) { + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL_TV]); + target.drawWireframeShape(parcelVtTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + } + } - } - } - if (graphConfigProperty.isEffLayer() == true - && !compareStnIsOn && !compareTmIsOn) { - // draw effective layer lines - // drawEffectiveLayerLines(target); - target.drawWireframeShape(effectiveLayerLineShape, - NsharpConstants.color_cyan_md, 2, - commonLineStyle, font10); - } - // cloud - if (graphConfigProperty.isCloud() == true - && !compareStnIsOn && !compareTmIsOn) { - if (cloudFMShape != null) - target.drawShadedShape(cloudFMShape, 1f); - if (cloudFMLabelShape != null) - target.drawWireframeShape(cloudFMLabelShape, - NsharpConstants.color_chocolate, - commonLinewidth * 3, commonLineStyle, font9); - if (cloudCEShape != null) - target.drawShadedShape(cloudCEShape, 1f); - } - if (graphConfigProperty.isOmega() == true - && !compareStnIsOn && !compareTmIsOn) { - if (NsharpLoadDialog.getAccess() != null - && (NsharpLoadDialog.getAccess() - .getActiveLoadSoundingType() == NsharpLoadDialog.MODEL_SND || NsharpLoadDialog - .getAccess() - .getActiveLoadSoundingType() == NsharpLoadDialog.PFC_SND)) { - // plot omega - drawOmega(); - } - } - } else { - // by default, draw everything - if (!compareStnIsOn && !compareTmIsOn) { - if (editGraphOn) - plotPressureTempEditPoints(target, world, - NsharpConstants.color_red, TEMP_TYPE, - this.soundingLys); - // dew point curve - if (editGraphOn) - plotPressureTempEditPoints(target, world, - NsharpConstants.color_green, DEWPOINT_TYPE, - this.soundingLys); - // plot wetbulb trace - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_WETBULB]); - target.drawWireframeShape(wetBulbTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - // plot virtual temp trace - lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_VIRTUAL_TEMP]); - target.drawWireframeShape(vtempTraceCurveRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); + if (graphConfigProperty.isDcape() == true && rscHandler.isGoodData() //#5929 + && dacpeTraceRscShape != null && !compareStnIsOn + && !compareTmIsOn && !overlayIsOn) { + if (soundingLys.size() > 0) { + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_DCAPE]); + target.drawWireframeShape(dacpeTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); - // virtual temperature parcel trace curve - if (!overlayIsOn) { - lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL_TV]); - target.drawWireframeShape(parcelVtTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - if (dacpeTraceRscShape != null) { - lp = linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_DCAPE]); - target.drawWireframeShape(dacpeTraceRscShape, - lp.getLineColor(), lp.getLineWidth(), - lp.getLineStyle(), font10); - } - } - // draw effective layer lines - // drawEffectiveLayerLines(target); - target.drawWireframeShape(effectiveLayerLineShape, - NsharpConstants.color_cyan_md, 2, - commonLineStyle, font10); - if (NsharpLoadDialog.getAccess() != null - && (NsharpLoadDialog.getAccess() - .getActiveLoadSoundingType() == NsharpLoadDialog.MODEL_SND || NsharpLoadDialog - .getAccess() - .getActiveLoadSoundingType() == NsharpLoadDialog.PFC_SND)) { - // plot omega - drawOmega(); - } - } - } - if (plotInteractiveTemp == true) { - if (currentSkewTEditMode == NsharpConstants.SKEWT_EDIT_MODE_EDITPOINT) - plotNsharpInteractiveEditingTemp(target, - currentZoomLevel, world, - NsharpConstants.color_white); - else if (currentSkewTEditMode == NsharpConstants.SKEWT_EDIT_MODE_MOVELINE) - plotNsharpMovingTempLine(target, world, - NsharpConstants.color_white); + } + } + if (graphConfigProperty.isEffLayer() == true && rscHandler.isGoodData() //#5929 + && !compareStnIsOn && !compareTmIsOn) { + // draw effective layer lines + // drawEffectiveLayerLines(target); + target.drawWireframeShape(effectiveLayerLineShape, + NsharpConstants.color_cyan_md, 2, + commonLineStyle, font10); + } + // cloud + if (graphConfigProperty.isCloud() == true && rscHandler.isGoodData() //#5929 + && !compareStnIsOn && !compareTmIsOn) { + if (cloudFMShape != null) + target.drawShadedShape(cloudFMShape, 1f); + if (cloudFMLabelShape != null) + target.drawWireframeShape(cloudFMLabelShape, + NsharpConstants.color_chocolate, + commonLinewidth * 3, commonLineStyle, font9); + if (cloudCEShape != null) + target.drawShadedShape(cloudCEShape, 1f); + } + if (graphConfigProperty.isOmega() == true + && !compareStnIsOn && !compareTmIsOn) { + if (NsharpLoadDialog.getAccess() != null + && (NsharpLoadDialog.getAccess() + .getActiveLoadSoundingType() == NsharpLoadDialog.MODEL_SND || NsharpLoadDialog + .getAccess() + .getActiveLoadSoundingType() == NsharpLoadDialog.PFC_SND)) { + // plot omega + drawOmega(); + } + } + } else { + // by default, draw everything + if (!compareStnIsOn && !compareTmIsOn) { + if (editGraphOn) + plotPressureTempEditPoints(target, world, + NsharpConstants.color_red, TEMP_TYPE, + this.soundingLys); + // dew point curve + if (editGraphOn) + plotPressureTempEditPoints(target, world, + NsharpConstants.color_green, DEWPOINT_TYPE, + this.soundingLys); + if(rscHandler.isGoodData()) { //#5929 + // plot wetbulb trace + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_WETBULB]); + target.drawWireframeShape(wetBulbTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + // plot virtual temp trace + lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_VIRTUAL_TEMP]); + target.drawWireframeShape(vtempTraceCurveRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); - } - target.clearClippingPlane(); + // virtual temperature parcel trace curve + if (!overlayIsOn) { + lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_PARCEL_TV]); + target.drawWireframeShape(parcelVtTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + if (dacpeTraceRscShape != null) { + lp = linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_DCAPE]); + target.drawWireframeShape(dacpeTraceRscShape, + lp.getLineColor(), lp.getLineWidth(), + lp.getLineStyle(), font10); + } + } + // draw effective layer lines + // drawEffectiveLayerLines(target); + target.drawWireframeShape(effectiveLayerLineShape, + NsharpConstants.color_cyan_md, 2, + commonLineStyle, font10); + } + if (NsharpLoadDialog.getAccess() != null + && (NsharpLoadDialog.getAccess() + .getActiveLoadSoundingType() == NsharpLoadDialog.MODEL_SND || NsharpLoadDialog + .getAccess() + .getActiveLoadSoundingType() == NsharpLoadDialog.PFC_SND)) { + // plot omega + drawOmega(); + } + } + } + if (plotInteractiveTemp == true) { + if (currentSkewTEditMode == NsharpConstants.SKEWT_EDIT_MODE_EDITPOINT) + plotNsharpInteractiveEditingTemp(target, + currentZoomLevel, world, + NsharpConstants.color_white); + else if (currentSkewTEditMode == NsharpConstants.SKEWT_EDIT_MODE_MOVELINE) + plotNsharpMovingTempLine(target, world, + NsharpConstants.color_white); + + } + target.clearClippingPlane(); + + // Wind Barb + if ((graphConfigProperty != null && graphConfigProperty + .isWindBarb() == true) || graphConfigProperty == null) { + double xPos = skewTBackground.getWindBarbXPosition(); + if (overlayIsOn == true && this.previousSoundingLys != null) { + drawNsharpWindBarb( + target, + currentZoomLevel, + world, + linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_OVERLAY1]) + .getLineColor(), this.soundingLys, + xPos, 100); + if (!previousSoundingLys.equals(soundingLys)) + drawNsharpWindBarb( + target, + currentZoomLevel, + world, + linePropertyMap + .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_OVERLAY2]) + .getLineColor(), + this.previousSoundingLys, + xPos - NsharpResourceHandler.BARB_LENGTH, + 100); + } else { + if (!compareStnIsOn && !compareTmIsOn + && !compareSndIsOn) { + drawNsharpWindBarb(target, currentZoomLevel, world, + graphConfigProperty.getWindBarbColor(), + this.soundingLys, xPos, 100); + } else { + int currentTimeListIndex = rscHandler + .getCurrentTimeElementListIndex(); + int currentStnListIndex = rscHandler + .getCurrentStnElementListIndex(); + int currentSndListIndex = rscHandler + .getCurrentSndElementListIndex(); + List stnElemList = rscHandler + .getStnElementList(); + List timeElemList = rscHandler + .getTimeElementList(); + List sndElemList = rscHandler + .getSndElementList(); + List>> stnTimeSndTable = rscHandler + .getStnTimeSndTable(); + if (compareTmIsOn && currentStnListIndex >= 0 + && currentSndListIndex >= 0) { + int colorIndex; + for (NsharpOperationElement elm : timeElemList) { + if (elm.getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(currentStnListIndex) + .get(timeElemList + .indexOf(elm)) + .get(currentSndListIndex) != null) { + List soundingLayeys = stnTimeSndTable + .get(currentStnListIndex) + .get(timeElemList.indexOf(elm)) + .get(currentSndListIndex) + .getSndLyLst(); + colorIndex = stnTimeSndTable + .get(currentStnListIndex) + .get(timeElemList.indexOf(elm)) + .get(currentSndListIndex) + .getCompColorIndex(); + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[colorIndex]); + drawNsharpWindBarb(target, + currentZoomLevel, world, + lp.getLineColor(), + soundingLayeys, xPos, 100); + } + } + } else if (compareStnIsOn + && currentTimeListIndex >= 0 + && currentSndListIndex >= 0) { + int colorIndex; + for (NsharpOperationElement elm : stnElemList) { + if (elm.getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(stnElemList + .indexOf(elm)) + .get(currentTimeListIndex) + .get(currentSndListIndex) != null) { + List soundingLayeys = stnTimeSndTable + .get(stnElemList.indexOf(elm)) + .get(currentTimeListIndex) + .get(currentSndListIndex) + .getSndLyLst(); + colorIndex = stnTimeSndTable + .get(stnElemList.indexOf(elm)) + .get(currentTimeListIndex) + .get(currentSndListIndex) + .getCompColorIndex(); + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[colorIndex]); + drawNsharpWindBarb(target, + currentZoomLevel, world, + lp.getLineColor(), + soundingLayeys, xPos, 100); + } + } + } else if (compareSndIsOn + && currentStnListIndex >= 0 + && currentTimeListIndex >= 0) { + int colorIndex; + // start FixMark:nearByStnCompSnd + List sndCompElementList = rscHandler + .getCompSndSelectedElemList(); + for (NsharpResourceHandler.CompSndSelectedElem compElem : sndCompElementList) { + NsharpSoundingElementStateProperty elemProp = stnTimeSndTable + .get(compElem.getStnIndex()) + .get(compElem.getTimeIndex()) + .get(compElem.getSndIndex()); + if (sndElemList.get(compElem.getSndIndex()) + .getActionState() == NsharpConstants.ActState.ACTIVE + && elemProp != null) { + List soundingLayeys = elemProp + .getSndLyLst(); + colorIndex = elemProp + .getCompColorIndex(); + NsharpLineProperty lp = linePropertyMap + .get(NsharpConstants.lineNameArray[colorIndex]); + drawNsharpWindBarb(target, + currentZoomLevel, world, + lp.getLineColor(), + soundingLayeys, xPos, 100); + } + } + + /* + * original code for(NsharpOperationElement elm: + * sndElemList) { if(elm.getActionState() == + * NsharpConstants.ActState.ACTIVE && + * stnTimeSndTable.get(currentStnListIndex).get( + * currentTimeListIndex + * ).get(sndElemList.indexOf(elm))!=null){ + * List soundingLayeys = + * stnTimeSndTable.get(currentStnListIndex).get( + * currentTimeListIndex + * ).get(sndElemList.indexOf( + * elm)).getSndLyLst(); colorIndex = + * stnTimeSndTable.get(currentStnListIndex).get( + * currentTimeListIndex + * ).get(sndElemList.indexOf( + * elm)).getCompColorIndex(); NsharpLineProperty + * lp = + * linePropertyMap.get(NsharpConstants.lineNameArray + * [colorIndex]); drawNsharpWindBarb(target, + * currentZoomLevel, world, lp.getLineColor(), + * soundingLayeys, xPos,100); } } + */ + // end start FixMark:nearByStnCompSnd + } + } + } + // System.out.println("x1 pos"+xPos+ " x2 pos="+ (xPos - + // NsharpResourceHandler.BARB_LENGTH)); + } + if( rscHandler.isGoodData() ){ //#5929) + drawHeightMark(target); + // draw EL, LFC, LCL, FZL, -20C, -30C lines + // drawLclLine(target); + target.drawWireframeShape(lclShape, + NsharpConstants.color_green, 2, LineStyle.SOLID, font10); + target.drawWireframeShape(elShape, NsharpConstants.color_red, + 2, LineStyle.SOLID, font10); + target.drawWireframeShape(lfcShape, + NsharpConstants.color_yellow, 2, LineStyle.SOLID, + font10); + target.drawWireframeShape(fzlShape, NsharpConstants.color_cyan, + 2, LineStyle.SOLID, font10); + + } + drawNsharpFileNameAndSampling(target, currentZoomLevel); + // draw cursor data + if (cursorInSkewT == true && rscHandler.isGoodData()) { + if ((curseToggledFontLevel < CURSER_STRING_OFF) + && (cursorTopWindBarb == false || windBarbMagnify == false)) + drawNsharpSkewtCursorData(target); + } - // Wind Barb - if ((graphConfigProperty != null && graphConfigProperty - .isWindBarb() == true) || graphConfigProperty == null) { - double xPos = skewTBackground.getWindBarbXPosition(); - if (overlayIsOn == true && this.previousSoundingLys != null) { - drawNsharpWindBarb( - target, - currentZoomLevel, - world, - linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_OVERLAY1]) - .getLineColor(), this.soundingLys, - xPos, 100); - if (!previousSoundingLys.equals(soundingLys)) - drawNsharpWindBarb( - target, - currentZoomLevel, - world, - linePropertyMap - .get(NsharpConstants.lineNameArray[NsharpConstants.LINE_OVERLAY2]) - .getLineColor(), - this.previousSoundingLys, - xPos - NsharpResourceHandler.BARB_LENGTH, - 100); - } else { - if (!compareStnIsOn && !compareTmIsOn - && !compareSndIsOn) { - drawNsharpWindBarb(target, currentZoomLevel, world, - graphConfigProperty.getWindBarbColor(), - this.soundingLys, xPos, 100); - } else { - int currentTimeListIndex = rscHandler - .getCurrentTimeElementListIndex(); - int currentStnListIndex = rscHandler - .getCurrentStnElementListIndex(); - int currentSndListIndex = rscHandler - .getCurrentSndElementListIndex(); - List stnElemList = rscHandler - .getStnElementList(); - List timeElemList = rscHandler - .getTimeElementList(); - List sndElemList = rscHandler - .getSndElementList(); - List>> stnTimeSndTable = rscHandler - .getStnTimeSndTable(); - if (compareTmIsOn && currentStnListIndex >= 0 - && currentSndListIndex >= 0) { - int colorIndex; - for (NsharpOperationElement elm : timeElemList) { - if (elm.getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable - .get(currentStnListIndex) - .get(timeElemList - .indexOf(elm)) - .get(currentSndListIndex) != null) { - List soundingLayeys = stnTimeSndTable - .get(currentStnListIndex) - .get(timeElemList.indexOf(elm)) - .get(currentSndListIndex) - .getSndLyLst(); - colorIndex = stnTimeSndTable - .get(currentStnListIndex) - .get(timeElemList.indexOf(elm)) - .get(currentSndListIndex) - .getCompColorIndex(); - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[colorIndex]); - drawNsharpWindBarb(target, - currentZoomLevel, world, - lp.getLineColor(), - soundingLayeys, xPos, 100); - } - } - } else if (compareStnIsOn - && currentTimeListIndex >= 0 - && currentSndListIndex >= 0) { - int colorIndex; - for (NsharpOperationElement elm : stnElemList) { - if (elm.getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable - .get(stnElemList - .indexOf(elm)) - .get(currentTimeListIndex) - .get(currentSndListIndex) != null) { - List soundingLayeys = stnTimeSndTable - .get(stnElemList.indexOf(elm)) - .get(currentTimeListIndex) - .get(currentSndListIndex) - .getSndLyLst(); - colorIndex = stnTimeSndTable - .get(stnElemList.indexOf(elm)) - .get(currentTimeListIndex) - .get(currentSndListIndex) - .getCompColorIndex(); - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[colorIndex]); - drawNsharpWindBarb(target, - currentZoomLevel, world, - lp.getLineColor(), - soundingLayeys, xPos, 100); - } - } - } else if (compareSndIsOn - && currentStnListIndex >= 0 - && currentTimeListIndex >= 0) { - int colorIndex; - // start FixMark:nearByStnCompSnd - List sndCompElementList = rscHandler - .getCompSndSelectedElemList(); - for (NsharpResourceHandler.CompSndSelectedElem compElem : sndCompElementList) { - NsharpSoundingElementStateProperty elemProp = stnTimeSndTable - .get(compElem.getStnIndex()) - .get(compElem.getTimeIndex()) - .get(compElem.getSndIndex()); - if (sndElemList.get(compElem.getSndIndex()) - .getActionState() == NsharpConstants.ActState.ACTIVE - && elemProp != null) { - List soundingLayeys = elemProp - .getSndLyLst(); - colorIndex = elemProp - .getCompColorIndex(); - NsharpLineProperty lp = linePropertyMap - .get(NsharpConstants.lineNameArray[colorIndex]); - drawNsharpWindBarb(target, - currentZoomLevel, world, - lp.getLineColor(), - soundingLayeys, xPos, 100); - } - } - /* - * original code for(NsharpOperationElement elm: - * sndElemList) { if(elm.getActionState() == - * NsharpConstants.ActState.ACTIVE && - * stnTimeSndTable.get(currentStnListIndex).get( - * currentTimeListIndex - * ).get(sndElemList.indexOf(elm))!=null){ - * List soundingLayeys = - * stnTimeSndTable.get(currentStnListIndex).get( - * currentTimeListIndex - * ).get(sndElemList.indexOf( - * elm)).getSndLyLst(); colorIndex = - * stnTimeSndTable.get(currentStnListIndex).get( - * currentTimeListIndex - * ).get(sndElemList.indexOf( - * elm)).getCompColorIndex(); NsharpLineProperty - * lp = - * linePropertyMap.get(NsharpConstants.lineNameArray - * [colorIndex]); drawNsharpWindBarb(target, - * currentZoomLevel, world, lp.getLineColor(), - * soundingLayeys, xPos,100); } } - */ - // end start FixMark:nearByStnCompSnd - } - } - } - // System.out.println("x1 pos"+xPos+ " x2 pos="+ (xPos - - // NsharpResourceHandler.BARB_LENGTH)); - } - drawHeightMark(target); - // draw EL, LFC, LCL, FZL, -20C, -30C lines - // drawLclLine(target); - target.drawWireframeShape(lclShape, - NsharpConstants.color_green, 2, LineStyle.SOLID, font10); - target.drawWireframeShape(elShape, NsharpConstants.color_red, - 2, LineStyle.SOLID, font10); - target.drawWireframeShape(lfcShape, - NsharpConstants.color_yellow, 2, LineStyle.SOLID, - font10); - target.drawWireframeShape(fzlShape, NsharpConstants.color_cyan, - 2, LineStyle.SOLID, font10); - drawNsharpFileNameAndSampling(target, currentZoomLevel); - // draw cursor data - if (cursorInSkewT == true) { - if ((curseToggledFontLevel < CURSER_STRING_OFF) - && (cursorTopWindBarb == false || windBarbMagnify == false)) - drawNsharpSkewtCursorData(target); - } }// end of currentGraphMode= NsharpConstants.GRAPH_SKEWT - else if (currentGraphMode == NsharpConstants.GRAPH_ICING) { + else if (currentGraphMode == NsharpConstants.GRAPH_ICING && rscHandler.isGoodData()) {//#5929 paintIcing(currentZoomLevel, target); - } else if (currentGraphMode == NsharpConstants.GRAPH_TURB) { + } else if (currentGraphMode == NsharpConstants.GRAPH_TURB && rscHandler.isGoodData()) {//#5929 paintTurbulence(currentZoomLevel, target); } // drawNsharpFileNameAndSampling(target, currentZoomLevel); @@ -3505,31 +3518,37 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource { */ public void createRscWireFrameShapes() { - // System.out.println("createRscWireFrameShapes called"); - if (target != null) { - disposeRscWireFrameShapes(); - if (soundingLys != null) { - // createRscOmegaShape(); - // createRscHeightMarkShape(); - createRscwetBulbTraceShape(); - createRscPressTempCurveShapeAll(target); - createRscVTempTraceShape(); - createRscParcelRtTraceShapesList(rscHandler.getCurrentParcel(), - rscHandler.getCurrentParcelLayerPressure());// real temp - // trace - createRscParcelTraceShapes(rscHandler.getCurrentParcel(), - rscHandler.getCurrentParcelLayerPressure()); // Virtual - // Temp - // Trace - // and - // DCAPE - // trace - createLCLEtcLinesShape(); - createEffectiveLayerLinesShape(); - createCloudsShape(); - updatePsblWatchColor(); - } - } + // System.out.println("createRscWireFrameShapes called"); + if (target != null) { + disposeRscWireFrameShapes(); + if (soundingLys != null){ + if( rscHandler.isGoodData()) {//#5929 + + // createRscOmegaShape(); + // createRscHeightMarkShape(); + createRscwetBulbTraceShape(); + createRscPressTempCurveShapeAll(target); + createRscVTempTraceShape(); + createRscParcelRtTraceShapesList(rscHandler.getCurrentParcel(), + rscHandler.getCurrentParcelLayerPressure());// real temp + // trace + createRscParcelTraceShapes(rscHandler.getCurrentParcel(), + rscHandler.getCurrentParcelLayerPressure()); // Virtual + // Temp + // Trace + // and + // DCAPE + // trace + createLCLEtcLinesShape(); + createEffectiveLayerLinesShape(); + createCloudsShape(); + updatePsblWatchColor(); + } + else {//#5929 + createRscPressTempCurveShapeAll(target); + } + } + } } public void disposeRscWireFrameShapes() { diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResource.java index 597aca18de..2a12ba4abb 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResource.java @@ -15,7 +15,11 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * 05/23/2014 Chin Chen update SHIP, STP Stats based on bigsharp version 2013Jun12 * 08/18/2014 Chin Chen implemented SARS, FIRE, HAIL, WINTER SPC graphs based on * bigsharp version 2013Jun12 - * + * 12/03/2014 DR#16884 Chin Chen fixed issue, NSHARP crashes if user loops a product and + * then clicks WINTER/FIRE buttons in Toolbar + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @author Chin Chen @@ -109,21 +113,11 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { private float nonSupercell[] = { 8.2f, 12.2f, 14.4f, 15.8f, 17.0f, 20.0f, 23.2f, 27.0f, 30.4f, 32.0f }; - private String hailSize[][] = { - { "", "<1", "1-1.5", "1.75", "2", "2.5", "2.75", "3-4", ">4" }, - { "+1 STD", "1.9", "2.0", "2.3", "2.8", "2.9", "3.0", "3.0", "3.0" }, - { "AVG", "1.5", "1.5", "1.8", "2.3", "2.5", "2.5", "2.6", "2.7" }, - { "-1 STD", "1.1", "1.1", "1.3", "1.7", "2.1", "2.1", "2.2", "2.4" } }; private RGB white = NsharpConstants.color_white; private RGB cyan = NsharpConstants.color_cyan_md; - private RGB hailSizeColor[][] = { - { white, white, white, white, white, white, white, white, white }, - { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan }, - { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan }, - { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan } }; private NsharpNative.NsharpLibrary.HailInfoStr hailInfo = new NsharpNative.NsharpLibrary.HailInfoStr(); @@ -133,6 +127,18 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { private NsharpNative.NsharpLibrary.WinterInfoStr winterInfo = new NsharpNative.NsharpLibrary.WinterInfoStr(); + private String hailSize[][] = { + { "", "<1", "1-1.5", "1.75", "2", "2.5", "2.75", "3-4", ">4" }, + { "+1 STD", "1.9", "2.0", "2.3", "2.8", "2.9", "3.0", "3.0", "3.0" }, + { "AVG", "1.5", "1.5", "1.8", "2.3", "2.5", "2.5", "2.6", "2.7" }, + { "-1 STD", "1.1", "1.1", "1.3", "1.7", "2.1", "2.1", "2.2", "2.4" } }; + + private RGB hailSizeColor[][] = { + { white, white, white, white, white, white, white, white, white }, + { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan }, + { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan }, + { white, cyan, cyan, cyan, cyan, cyan, cyan, cyan, cyan } }; + public NsharpSpcGraphsPaneResource(AbstractResourceData resourceData, LoadProperties loadProperties, NsharpAbstractPaneDescriptor desc) { super(resourceData, loadProperties, desc); @@ -140,21 +146,6 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { rightGraph = NsharpPaletteWindow.getRightGraph(); } - private void underDevelopment(int side) throws VizException { - double xpos; - if (side == left) - xpos = spcLeftXOrig + spcFrameWidth / 2; - else - xpos = spcRightXOrig + spcFrameWidth / 2; - DrawableString str = new DrawableString("under development", - NsharpConstants.color_green); - str.font = font12; - str.horizontalAlignment = HorizontalAlignment.LEFT; - str.verticallAlignment = VerticalAlignment.TOP; - ypos = spcYOrig + spcHeight / 2; - str.setCoordinates(xpos, ypos); - target.drawStrings(str); - } private void setXyStartingPosition(int side) { ystart = spcYOrig; @@ -298,35 +289,6 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { // System.out.println("java hail str #"+ (i+1)+ " "+ hailStr); } - /* - * ypos = spcYEnd - 4 * charHeight; for(int i=0; i < 2; i++){ String - * supStr = new String(sarsInfo.getTorStr(), (i*60), 60); - * //System.out.println("tor str #"+ (1+ i)+ " "+ supStr); RGB strColor - * = NsharpConstants.gempakColorToRGB.get(sarsInfo.getTorStrColor()); - * supStr = supStr.substring(0, supStr.indexOf('\0'));// get rid of - * tailing null char(s), as DrawableString will print them out - * DrawableString supercellMatchStr = new DrawableString(supStr, - * strColor); supercellMatchStr.font = font10; - * supercellMatchStr.horizontalAlignment = HorizontalAlignment.LEFT; - * supercellMatchStr.verticallAlignment = VerticalAlignment.TOP; xpos = - * xstart ; ypos = ypos + charHeight; - * supercellMatchStr.setCoordinates(xpos, ypos); - * strList.add(supercellMatchStr); - * - * String sighailStr = new String(sarsInfo.getSighailStr(), (i*60), 60); - * //System.out.println("sighail str #"+ (1+ i)+ " "+ sighailStr); RGB - * strColor1 = - * NsharpConstants.gempakColorToRGB.get(sarsInfo.getSighailStrColor()); - * sighailStr = sighailStr.substring(0, sighailStr.indexOf('\0'));// get - * rid of tailing null char(s), as DrawableString will print them out - * DrawableString sighailMatchStr = new DrawableString(sighailStr, - * strColor1); sighailMatchStr.font = font10; - * sighailMatchStr.horizontalAlignment = HorizontalAlignment.LEFT; - * sighailMatchStr.verticallAlignment = VerticalAlignment.TOP; xpos = - * xstart + 0.51 *spcFrameWidth; sighailMatchStr.setCoordinates(xpos, - * ypos); strList.add(sighailMatchStr); } - */ - target.drawStrings(strList.toArray(new DrawableString[strList.size()])); target.drawLine(lineList.toArray(new DrawableLine[lineList.size()])); } @@ -1621,13 +1583,15 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { // logic statements for Thompson et al. (2012) WAF sample // 39 sigtor, 28 non-sigtor supercells if (cin >= 10) { + // setcolor(7) psigt_stpcin = "0.58"; - stpcColor = NsharpConstants.color_magenta;// setcolor(7); + stpcColor = NsharpConstants.color_magenta;; } // 39 sigtor, 32 non-sigtor supercells else if (cin >= 8) { + // setcolor(7) psigt_stpcin = "0.55"; - stpcColor = NsharpConstants.color_magenta;// setcolor(7); + stpcColor = NsharpConstants.color_magenta; } // 54 sigtor, 104 non-sigtor supercells else if (cin >= 6) { @@ -1745,17 +1709,6 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { valueStp.verticallAlignment = VerticalAlignment.TOP; valueStp.setCoordinates(tboxValueStart, ypos); strList.add(valueStp); - - // reset parcel to previous "oldlplchoice" , TBD - /* - * float pres; if(oldlplchoice == - * NsharpNativeConstants.PARCELTYPE_USER_DEFINED){ - * if(NsharpParcelDialog.getAccess() != null){ pres = - * NsharpParcelDialog.getAccess().getUserDefdParcelMb(); } else pres = - * NsharpNativeConstants.parcelToLayerMap.get(oldlplchoice); } else pres - * = NsharpNativeConstants.parcelToLayerMap.get(oldlplchoice); - * nsharpNative.nsharpLib.define_parcel(oldlplchoice,pres); - */ target.drawStrings(strList.toArray(new DrawableString[strList.size()])); target.drawLine(lineList.toArray(new DrawableLine[lineList.size()])); @@ -1876,7 +1829,7 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { short oldlplchoice; _parcel pcl = new _parcel(); - ; + _lplvalues lpvls = new _lplvalues(); nsharpNative.nsharpLib.get_lpvaluesData(lpvls); // oldlplchoice = lpvls.flag; @@ -1931,12 +1884,6 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { lineList.add(ebsline); } float pres; - /* - * if(oldlplchoice == NsharpNativeConstants.PARCELTYPE_USER_DEFINED){ - * if(NsharpParcelDialog.getAccess() != null){ pres = - * NsharpParcelDialog.getAccess().getUserDefdParcelMb(); } else pres = - * NsharpNativeConstants.parcelToLayerMap.get(oldlplchoice); } else - */ oldlplchoice = rscHandler.getCurrentParcel(); pres = NsharpNativeConstants.parcelToLayerMap.get(oldlplchoice); nsharpNative.nsharpLib.define_parcel(oldlplchoice, pres); @@ -1951,27 +1898,24 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { PaintProperties paintProps) throws VizException { super.paintInternal(target, paintProps); // defineCharHeight(font10); - if (rscHandler == null || rscHandler.getSoundingLys() == null) + if (rscHandler == null || rscHandler.getSoundingLys() == null || !rscHandler.isGoodData())//#5929 return; this.font10.setSmoothing(false); this.font10.setScaleFont(false); hRatio = paintProps.getView().getExtent().getWidth() / paintProps.getCanvasBounds().width; DrawableLine line = new DrawableLine(); + line.setCoordinates(spcRightXOrig, spcYOrig); + line.addPoint(spcRightXOrig, spcYOrig + spcHeight); line.lineStyle = LineStyle.SOLID; line.basics.color = NsharpConstants.color_white; line.width = 1; - line.setCoordinates(spcRightXOrig, spcYOrig); - line.addPoint(spcRightXOrig, spcYOrig + spcHeight); target.drawLine(line); PixelExtent spcExt = new PixelExtent(new Rectangle((int) spcLeftXOrig, (int) spcYOrig, (int) spcWidth, (int) spcHeight)); target.drawRect(spcExt, NsharpConstants.color_white, 1f, 1f); // box // border // line - PixelExtent extent = new PixelExtent(new Rectangle((int) spcLeftXOrig, - (int) spcYOrig, (int) spcFrameWidth, (int) spcHeight)); - // target.setupClippingPlane(extent); switch (leftGraph) { case EBS: plotEBS(left); @@ -1995,10 +1939,6 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { plotSars(left); break; } - // target.clearClippingPlane(); - extent = new PixelExtent(new Rectangle((int) spcRightXOrig, - (int) spcYOrig, (int) spcFrameWidth, (int) spcHeight)); - // target.setupClippingPlane(extent); switch (rightGraph) { case EBS: plotEBS(right); @@ -2022,7 +1962,7 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { plotSars(right); break; } - // target.clearClippingPlane(); + } @Override @@ -2030,19 +1970,46 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { super.initInternal(target); } - /* - * private void disposeEbsShape(){ if(ebsBkgLblShape != null) - * ebsBkgLblShape.dispose(); if(ebsBkgLineShape != null) - * ebsBkgLineShape.dispose(); if(ebsSupercellShape != null) - * ebsSupercellShape.dispose(); if(ebsMrglSupShape != null) - * ebsMrglSupShape.dispose(); if(ebsNonSupSgape != null) - * ebsNonSupSgape.dispose(); } - */ @Override protected void disposeInternal() { super.disposeInternal(); } + + public NsharpConstants.SPCGraph getLeftGraph() { + return leftGraph; + } + + public void setGraphs(NsharpConstants.SPCGraph leftGraph, + NsharpConstants.SPCGraph rightGraph) { + this.leftGraph = leftGraph; + this.rightGraph = rightGraph; + getSpcGraphsInfo(); + rscHandler.refreshPane(); + } + + public NsharpConstants.SPCGraph getRightGraph() { + return rightGraph; + } + + public synchronized void getSpcGraphsInfo() { + if (rightGraph == NsharpConstants.SPCGraph.SARS + || leftGraph == NsharpConstants.SPCGraph.SARS) { + nsharpNative.nsharpLib.getSarsInfo(sarsInfo); + } + if (leftGraph == NsharpConstants.SPCGraph.WINTER + || rightGraph == NsharpConstants.SPCGraph.WINTER) { + nsharpNative.nsharpLib.getWinterInfo(winterInfo); + } + if (rightGraph == NsharpConstants.SPCGraph.FIRE + || leftGraph == NsharpConstants.SPCGraph.FIRE) { + nsharpNative.nsharpLib.getFireInfo(fireInfo); + } + if (leftGraph == NsharpConstants.SPCGraph.HAIL + || rightGraph == NsharpConstants.SPCGraph.HAIL) { + nsharpNative.nsharpLib.getHailInfo(hailInfo); + } + } @Override public void handleResize() { @@ -2064,38 +2031,4 @@ public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource { spcYEnd = ext.getMaxY(); } - public NsharpConstants.SPCGraph getLeftGraph() { - return leftGraph; - } - - public void setGraphs(NsharpConstants.SPCGraph leftGraph, - NsharpConstants.SPCGraph rightGraph) { - this.leftGraph = leftGraph; - this.rightGraph = rightGraph; - getSpcGraphsInfo(); - rscHandler.refreshPane(); - } - - public NsharpConstants.SPCGraph getRightGraph() { - return rightGraph; - } - - public void getSpcGraphsInfo() { - if (leftGraph == NsharpConstants.SPCGraph.WINTER - || rightGraph == NsharpConstants.SPCGraph.WINTER) { - nsharpNative.nsharpLib.getWinterInfo(winterInfo); - } - if (leftGraph == NsharpConstants.SPCGraph.FIRE - || rightGraph == NsharpConstants.SPCGraph.FIRE) { - nsharpNative.nsharpLib.getFireInfo(fireInfo); - } - if (leftGraph == NsharpConstants.SPCGraph.HAIL - || rightGraph == NsharpConstants.SPCGraph.HAIL) { - nsharpNative.nsharpLib.getHailInfo(hailInfo); - } - if (leftGraph == NsharpConstants.SPCGraph.SARS - || rightGraph == NsharpConstants.SPCGraph.SARS) { - nsharpNative.nsharpLib.getSarsInfo(sarsInfo); - } - } } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpWitoPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpWitoPaneResource.java index 30ac01fe00..c41f087f53 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpWitoPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpWitoPaneResource.java @@ -10,6 +10,9 @@ package gov.noaa.nws.ncep.ui.nsharp.display.rsc; * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 04/23/2012 229 Chin Chen Initial coding + * 01/27/2015 DR#17006, + * Task#5929 Chin Chen NSHARP freezes when loading a sounding from MDCRS products + * in Volume Browser * * * @@ -159,11 +162,14 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ float x1 = verticalWindXOrig+ (verticalWindWidth/2); target.drawLine(x1, verticalWindYOrig, 0, x1, verticalWindYOrig+verticalWindHeight, 0, NsharpConstants.color_white, 1, LineStyle.DASHED); - target.drawWireframeShape(verticalWindLabelShape, NsharpConstants.color_white, + if(verticalWindLabelShape!=null) //#5929 + target.drawWireframeShape(verticalWindLabelShape, NsharpConstants.color_white, 0.3F, commonLineStyle,font10); - target.drawWireframeShape(verticalWindRShape, NsharpConstants.color_red, + if(verticalWindRShape!=null) + target.drawWireframeShape(verticalWindRShape, NsharpConstants.color_red, 0.3F, commonLineStyle,font10); - target.drawWireframeShape(verticalWindSbShape, NsharpConstants.color_skyblue, + if(verticalWindSbShape!=null) + target.drawWireframeShape(verticalWindSbShape, NsharpConstants.color_skyblue, 0.3F, commonLineStyle,font10); target.clearClippingPlane(); } @@ -304,7 +310,7 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ windBoxWindRscShapeList.add(shNcolor); - + float surfaceLevel = soundingLys.get(0).getGeoHeight(); //#5929 //System.out.println("my wolrd minvY="+ myYViewMin+ " maxVY="+myYViewMax+ " YRange="+myYViewRange); for (NcSoundingLayer layer : soundingLys) { float pressure = layer.getPressure(); @@ -321,13 +327,14 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ //System.out.println("Wind p="+pressure+" yP="+ windBoxY+ " ratio="+yRatio); float geoHt = layer.getGeoHeight(); double [][] lines = {{windBoxX, windBoxY},{windBoxX + (spd) * xRatio,windBoxY}}; - if(geoHt