diff --git a/RadarServer/com.raytheon.rcm.lib/src/com/raytheon/rcm/config/awips1/Awips1RpsListUtil.java b/RadarServer/com.raytheon.rcm.lib/src/com/raytheon/rcm/config/awips1/Awips1RpsListUtil.java old mode 100755 new mode 100644 diff --git a/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/config/awips1/Awips1ConfigProvider.java b/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/config/awips1/Awips1ConfigProvider.java old mode 100755 new mode 100644 diff --git a/cave/build/static/common/cave/etc/gfe/userPython/gfeConfig/gfeConfig.py b/cave/build/static/common/cave/etc/gfe/userPython/gfeConfig/gfeConfig.py index c67a721978..c5cad4ba33 100644 --- a/cave/build/static/common/cave/etc/gfe/userPython/gfeConfig/gfeConfig.py +++ b/cave/build/static/common/cave/etc/gfe/userPython/gfeConfig/gfeConfig.py @@ -354,10 +354,10 @@ MaxMenuItemsBeforeCascade = 30 # Defines the percent that the office domain will be expanded for the # spatial editor full-screen view. The user can specify the expansion # for each of the four directions. If not specified, the default is 10%. -OfficeDomain_expandLeft = 10 # ifpIMAGE only -OfficeDomain_expandRight = 10 # ifpIMAGE only -OfficeDomain_expandTop = 10 # ifpIMAGE only -OfficeDomain_expandBottom = 10 # ifpIMAGE only +OfficeDomain_expandLeft = 10 +OfficeDomain_expandRight = 10 +OfficeDomain_expandTop = 10 +OfficeDomain_expandBottom = 10 # Initial location of Edit Action Dialog # These are absolute screen coordinates (not relative to GFE window) diff --git a/cave/build/static/common/cave/etc/gfe/userPython/smartTools/QPF_SmartTool.py b/cave/build/static/common/cave/etc/gfe/userPython/smartTools/QPF_SmartTool.py index a405abe30e..66ed1fcda0 100644 --- a/cave/build/static/common/cave/etc/gfe/userPython/smartTools/QPF_SmartTool.py +++ b/cave/build/static/common/cave/etc/gfe/userPython/smartTools/QPF_SmartTool.py @@ -1,207 +1,99 @@ -## -# This software was developed and / or modified by Raytheon Company, -# pursuant to Contract DG133W-05-CQ-1067 with the US Government. -# -# U.S. EXPORT CONTROLLED TECHNICAL DATA -# This software product contains export-restricted data whose -# export/transfer/disclosure is restricted by U.S. law. Dissemination -# to non-U.S. persons whether in the United States or abroad requires -# an export license or other authorization. -# -# Contractor Name: Raytheon Company -# Contractor Address: 6825 Pine Street, Suite 340 -# Mail Stop B8 -# Omaha, NE 68106 -# 402.291.0100 -# -# See the AWIPS II Master Rights File ("Master Rights File.pdf") for -# further licensing information. -## # ---------------------------------------------------------------------------- # This software is in the public domain, furnished "as is", without technical # support, and with no warranty, express or implied, as to its usefulness for # any purpose. -# +# # QPF_SmartTool.py -# This is an example of a more complicated tool. -# It determines a QPF value based on the current QPF value, -# the Wind value, and surrounding Topography -# information. # -# It has sub-methods that are called by the main method. -# These sub-methods calculate Vertical Motion and translate -# it into a QPF term. -# -# Author: wier (translated to Python by hansen) -# Updated by hansen 1/00 based on suggestions from Rusty Billingsley -# Updated by njensen for AWIPS-II # ---------------------------------------------------------------------------- -WeatherElementEdited = "QPF" + + ToolType = "numeric" +WeatherElementEdited = "QPF" +from numpy import * +import MetLib, time + +HideTool = 0 + +# You can screen the elements for which your tool will appear by using +# a ScreenList. For example: +# VariableList = [ - ("Vertical Motion Influence" , 50, "scale", [0,100]), + ("Vertical Motion Influence" , 50, "scale", [0,100]), ] - -# This allows us to use the sin and cos functions -from math import * -from numpy import * - -AVG_GRID_SPACE = 10000 -RAD_TO_DEG = 57.2958 - -#################### -# QPF Smart Tool +# Set up Class import SmartScript +# For available commands, see SmartScript + class Tool (SmartScript.SmartScript): def __init__(self, dbss): SmartScript.SmartScript.__init__(self, dbss) - def execute(self, QPF, Wind, Topo, varDict): - "Sets QPF within Active Edit Area based on Wind and Topo." + # Smooths the specified grid by the specified factor + # With factor == 3, 3x3 smooth, factor == 5 5x5 smooth, etc. + # Even factors (4, 6, 8,...) round up to the next odd value + # If factors <3 are specified, the unmodified grid is returned. + def smoothGrid(self, grid, factor): + # factors of less than 3 are useless or dangerous + if factor < 3: + return grid + st = time.time() + half = int(factor)/ 2 + sg = zeros(grid.shape,float64) + count = zeros(grid.shape,float64) + gridOfOnes = ones(grid.shape,float64) + for y in xrange(-half, half + 1): + for x in xrange(-half, half + 1): + if y < 0: + yTargetSlice = slice(-y, None, None) + ySrcSlice = slice(0, y, None) + if y == 0: + yTargetSlice = slice(0, None, None) + ySrcSlice = slice(0, None, None) + if y > 0: + yTargetSlice = slice(0, -y, None) + ySrcSlice = slice(y, None, None) + if x < 0: + xTargetSlice = slice(-x, None, None) + xSrcSlice = slice(0, x, None) + if x == 0: + xTargetSlice = slice(0, None, None) + xSrcSlice = slice(0, None, None) + if x > 0: + xTargetSlice = slice(0, -x, None) + xSrcSlice = slice(x, None, None) - VerticalMotion_Grid = self.VerticalMotionGrid(Wind, Topo) - - scale = varDict["Vertical Motion Influence"] / 50.0 - - value = QPF * (1.0 + scale * VerticalMotion_Grid) - return value.astype('float32') - - def VerticalMotionGrid(self, Wind_Grid, Topo_Grid): - # Create Vertical Motion grid from Wind Grid and Topography - - # The Topo_Grid is a 2-D array where - # each entry is a scalar elevation, for example: - # x = 0 - # y = 0 - # elevation = Topo_Grid[x][y] - - # The Wind_Grid is 2-D array where - # each entry is a 2-tuple of magnitude and direction, - # for example: - # wind_tuple = Wind_Grid[x][y] - # magnitude = wind_tuple[0] - # direction = wind_tuple[1] - - # Create a VerticalMotion_Grid that is - # a 2-D array - - xGridSize = len(Topo_Grid) - yGridSize = len(Topo_Grid[0]) - vmArray = [] - - first = 1 - for x in range(xGridSize): - # Add a new column - vmArray = zeros(Topo_Grid.shape) - - for y in range(yGridSize): - # Calculate the value for this point - wind_tuple = (Wind_Grid[0][x][y], Wind_Grid[1][x][y]) - vmValue = self.VerticalMotion(wind_tuple,Topo_Grid,x,y) - - # Set the value - vmArray[x][y] = vmValue - - # Keep track of min/max values - if first: - first = 0 - min = vmValue - max = vmValue - else: - if vmValue < min: - min = vmValue - if vmValue > max: - max = vmValue - - # Now normalize the grid to values between -1 and 1 - factor1 = (max + min) / 2 - factor2 = (max-min) / 2 - for x in range(xGridSize): - for y in range(yGridSize): - vmArray[x][y] = (vmArray[x][y] - factor1) / factor2 - - return vmArray - - - def VerticalMotion(self, Wind, Topo_Grid, x,y): - # wind is a 2-tuple: wind[0] is magnitude, wind[1] is direction - magnitude = Wind[0] - direction = Wind[1] - - # Determine wind u and v components. - # First compute wind vector angle from north, in radians. - rads = (direction - 180) / RAD_TO_DEG - - # u and v components - # (convert from knots to meters per second 1.94384 knots / m/s ) - uw = sin(rads) * magnitude / 1.94384 - vw = cos(rads) * magnitude / 1.94384 - - # find slope vector components (svx, svy) at this point (x, y). - # Direction is that of maximum slope and magnitude is the - # slope = rise/run, unitless. - svx, svy = self.findSlopeVector(x, y, Topo_Grid) - - # multiply (dot product) wind vector by slope vector - # to get the value of the vertical air motion. - vertAirSpeed = uw * svx + vw * svy - - return vertAirSpeed - - def findSlopeVector(self, x,y, Topo_Grid): - # the Topo_Grid of the center grid point at x,y. - # Topo_Grid is a tuple of tuples representing a 2-D grid. - - sumxcomp = sumycomp = count = 0 - centerh = Topo_Grid[x][y] - - gridSizeX = len(Topo_Grid) - gridSizeY = len(Topo_Grid[0]) - - for i in range(x-1, x+2): - for j in range(y-1, y+2): - # skip indices beyond limits of grid - if i < 0 or j < 0 or i >= gridSizeX or j >= gridSizeY: - continue - # components of vector pointing from the center xc,yc - # to the grid point (i,j) - xcomp = i-x - ycomp = j-y - - # if at center point; distance is 0, do not compute - if i == x and j == y: - continue - - # distance between pair of grid points - dist = AVG_GRID_SPACE * sqrt(xcomp*xcomp + ycomp*ycomp) - - # error trap to avoid 0 divide; should never occur - if dist == 0.0: - continue - - # slope from center to the other grid point; + if up from center - # (dist and _Topo_Grid values must be in same units) - slope = (Topo_Grid[i][j] - centerh) / dist - - # multiply original components by slope to get the slope vector - # components from (xc,yc) to (i,j), - # and add into summation of all x and y components - sumxcomp += xcomp * slope - sumycomp += ycomp * slope - count += 1 - - # average all slope vectors to neighbor points - svx = sumxcomp / count - svy = sumycomp / count - - # ensure "reasonable" values - less than 45 degrees - if abs(svx) > 1.0: - svx /= abs(svx) - if abs(svy) > 1.0: - svy /= abs(svy) - - return svx, svy + target = [yTargetSlice, xTargetSlice] + src = [ySrcSlice, xSrcSlice] + sg[target] += grid[src] + count[target] += gridOfOnes[src] + return sg / count + # Required Method: Execute + # %comment + # Fill in the arguments you want to use -- WeatherElement1, WeatherElement2... + def execute(self, QPF, Wind, varDict): + + # get the scale value + scale = float(varDict["Vertical Motion Influence"]) / 50.0 + + # Calculate the gridient of the topoGrid + topoGrid = self.getTopo() + + d_dx, d_dy = MetLib.gradient(topoGrid) + + # Convert wind to u and v components + u, v = self.MagDirToUV(Wind[0], Wind[1]) + + # Calculate the dot product which is positive when wind blows + # upslope and negative when it blows downslope + dotGrid = MetLib.dot((d_dx, d_dy), (u, -v)) / 5000.0 + dotGrid = self.smoothGrid(dotGrid, 9) + + # adjust the existing QPF grid using the scale and dot product + QPF = QPF * (1 + scale * dotGrid) + + return QPF diff --git a/cave/build/static/common/cave/etc/gfe/userPython/textUtilities/regular/FWS_Overrides.py b/cave/build/static/common/cave/etc/gfe/userPython/textUtilities/regular/FWS_Overrides.py index da8aa3b5d4..5f0d2e7f27 100644 --- a/cave/build/static/common/cave/etc/gfe/userPython/textUtilities/regular/FWS_Overrides.py +++ b/cave/build/static/common/cave/etc/gfe/userPython/textUtilities/regular/FWS_Overrides.py @@ -1,19 +1,19 @@ ## # This software was developed and / or modified by Raytheon Company, -# pursuant to Contract DG133W-05-CQ-1067 with the US Government. -# -# U.S. EXPORT CONTROLLED TECHNICAL DATA +# 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. ## @@ -81,28 +81,31 @@ Definition["defaultEditAreas"] = [] # and will try to first guess the agency abbreviation from the # "REQUESTING AGENCY" line of the STQ product. If the first guess # is found in your agencyList list, then the Quality Control GUI -# with have that agency pre-selected. +# with have that agency pre-selected. If list is left empty, +# then the formatter will always use what the user submitted +# for the agency. -Definition["agencyList"] = [ - (1,"AGENCY 1"), - (2,"AGENCY 2"), - (3,"AGENCY 3"), - (4,"AGENCY 4"), - (5,"AGENCY 5"), - ] +#Definition["agencyList"] = [ +# (1,"AGENCY 1"), +# (2,"AGENCY 2"), +# (3,"AGENCY 3"), +# (4,"AGENCY 4"), +# (5,"AGENCY 5"), +# ] +Definition["agencyList"] = [] -# forecasterList - This is a list of forecaster numbers, forecaster initials, +# forecasterList - This is a list of forecaster numbers, forecaster awips login name, # and forecaster last names. The Quality Control GUI will # list the forecaster's last name and the forecaster will # check all of the forecaster's names that were involved # in that forecast. Definition["forecasterList"] = [ - (1,"FRA","FORECASTER A"), - (2,"FRB","FORECASTER B"), - (3,"FRC","FORECASTER C"), - (4,"FRD","FORECASTER D"), - (5,"FRE","FORECASTER E"), + (1,"forecastera","FORECASTER A"), + (2,"forecasterb","FORECASTER B"), + (3,"forecasterc","FORECASTER C"), + (4,"forecasterd","FORECASTER D"), + (5,"forecastere","FORECASTER E"), ] # stqNumberVersions - When you launch the FWS formatter, you will get a GUI @@ -118,10 +121,6 @@ Definition["stqNumberVersions"] = 10 Definition["stqWmoID"] = "BMBB91 K" -# typeList - This is a list of project types and are formatted in the "REASON FOR -# REQUEST" line of the FWS forecast. Do not edit this list unless WSH -# directs you to do so. - # wind20ftHeader: This definition set to "1" allows offices to # format winds in this format... # @@ -135,8 +134,11 @@ Definition["stqWmoID"] = "BMBB91 K" # RIDGETOP WIND.......NORTHWEST 20 MPH Definition["wind20ftHeader"] = 1 # Use 1 for yes, 0 for no +# typeList - This is a list of project types and are formatted in the "REASON FOR +# REQUEST" line of the FWS forecast. Do not edit this list unless WSH +# directs you to do so. -Definition["typeList"] = ["WILDFIRE", "PRESCRIBED", "WFU", "HAZMAT", "SAR", "TEST"] +Definition["typeList"] = ["WILDFIRE", "PRESCRIBED", "HAZMAT", "SAR", "TEST"] # Set shortTermOnly to 1 if you don't want to give your forecasters an option # include extended forecasts and/or outlooks with their spot forecasts. @@ -233,11 +235,18 @@ Definition["stqPil"] = "STQ" # STQ pil # The following variable sets a wind adjustment factor for surface # (20 ft) winds. Wind speeds will be multiplied by this factor. # Winds reported by RAWS sites are frequently lower than ASOS winds -# due to the fact that they use a 10-min average. A common adjustment -# factor is 80% (0.80). If you want no adjustment to the winds -# then set this variable to 1.00 +# due to the fact that they measure wind speeds at lower heights. +# A common adjustment factor is 80% (0.80). If you want no adjustment +# to the winds then set this variable to 1.00 #Definition["windAdjustmentFactor"] = 1.00 +# The following variable sets a wind adjustment factor for eye level +# winds. Wind speeds will be multiplied by this factor. Eye level +# winds are frequently lower than ASOS winds due to the fact that +# winds are slower when measured closer to the ground. A common +# adjustment factor is 60% (0.60). If you want no adjustment to +# the winds then set this variable to 1.00 +Definition["eyeWindAdjustmentFactor"] = 0.60 #Definition["language"] = "english" @@ -416,12 +425,31 @@ Definition["ignitionForecastTypeList"] = [] Definition["elementFormatDict"] = { "Sky" : "numeric", "Wind": "alpha", + "Wind20ft": "alpha", "EyeWind": "alpha", "RidgeWind": "alpha", "TransWind": "alpha", "TransMetWind": "alpha", } +# bothAlphaNumericDict - For certain elements both alpha and numeric values +# are needed. In particular, sky cover and wind direction. +# Only possible values are "Yes" or "No". +# If you do configure a wind element to "Yes", then +# ensure the corresponding setting for elementFormatDict +# is set to "alpha". Otherwise, you will get two lines +# of numeric values. + +Definition["bothAlphaNumericDict"] = { + "Sky" : "No", + "Wind": "No", + "Wind20ft": "No", + "EyeWind": "No", + "SfcWind": "No", + "RidgeWind": "No", + "TransWind": "No", + } + # tabularMixingHeightUnits - This definition allows the WFO to specify their preferance # on how mixing height is expressed. In thousands of feet or # in just feet? The definition can only be set to "kft" or @@ -563,6 +591,52 @@ Definition["tableRidgeElementSplit"] = "no" #Definition["tableTransElementSplit"] = "yes" Definition["tableTransElementSplit"] = "no" +# tableSwellElementSplit - When the time resolution of the table is 1 hour, then +# I am forced to create separate lines for swell direction +# and swell height. When the resolution is 2 hours or more, +# then a WFO has a choice of formats. They can set +# tableSwellElementSplit to "yes" and swell direction and +# height will remain in their separate lines. Or the WFO +# can set tableSwellElementSplit to "no" and the swell +# direction and height will be combined into one line. +# Examples follow... + +# yes 2hr: SWELL DIRECTION.W W W W W W W +# : SWELL HGT (FT)..36 36 36 36 36 36 16 + +# no 2 hr: SWELL HGT (FT)..W 36 W 36 W 36 W 36 W 36 W 36 W 16 + +#Definition["tableSwellElementSplit"] = "yes" +Definition["tableSwellElementSplit"] = "no" + +# tableSfcWindElementSplit - When the time resolution of the table is 1 hour, then +# I am forced to create separate lines for wind direction, +# wind speed, and wind gust speed. When the resolution +# is 2 hours or more, then a WFO has a choice of formats. +# They can set tableSfcWindElementSplit to "yes" and wind +# direction, speed, and gusts will remain in their +# separate lines. Or the WFO can set tableSfcWindElementSplit +# to "no". For the two hour resolution, direction and +# speed will be combined. For three and four hour +# resolution, direction, speed, and gusts will be +# combined. Examples follow... + +# yes 2hr: SURFACE WND DIR.SW W W W W W W +# : SURFACE WND SPD.26 26 18 18 18 14 14 +# : SURFACE WND GST.40 40 + +# no 2 hr: SURFACE WIND....W 26 W 26 W 18 W 18 W 18 W 14 W 14 +# : SURFACE WND GST.40 40 + +# yes 3hr: SURFACE WND DIR.W W W W W +# : SURFACE WND SPD.26 25 13 14 13 +# : SURFACE WND GST.40 40 + +# no 3 hr: SURFACE WIND....W 26G40 W 25G40 W 13 W 14 W 13 + +#Definition["tableSfcWindElementSplit"] = "yes" +Definition["tableSfcWindElementSplit"] = "no" + # cwrParm - Some WFOs (especially in wetter climates) use the PoP grid for # chance of wetting rain, whereas offices in dry climates create a # CWR grid that has values lower than the PoP grid. Value values @@ -599,7 +673,7 @@ class FWS_Overrides: #self.debug_print("Debug: _method in FWS_Overrides") def _processVariableList(self, definition): - + # Get Definition variables for key in definition.keys(): exec "self._" + key + "= definition[key]" @@ -667,10 +741,15 @@ class FWS_Overrides: def _getFireProduct(self, products): # Create the fireNameList used for the spot selection menu. fireNameList = [] + ofileList = [] validProductFound = 0 + productNumber = 0 + masterProductList = [] for product in products: fireName = "NAME MISSING" timeStamp = "DDHHMM" + tag = "YYYYMMDD.XXXXX.NN" + tagFlag = 0 feedbackFlag=0 deleteFlag=0 for line in product: @@ -679,31 +758,50 @@ class FWS_Overrides: fireName = string.upper(line[22:]) if self._stqWmoID in line: timeStamp = line[12:] - fireNameList.append(fireName + " -- " + timeStamp) + if "OFILE" in line: + tag = string.upper(line[8:]) + if tag not in ofileList: + ofileList.append(tag) + tagFlag = 1 + productNumber = productNumber + 1 + if tagFlag: + fireNameList.append(`productNumber` + ") " + fireName + \ + " -- " + timeStamp + " -- " + tag) + masterProductList.append(product) validProductFound = 1 varList = [] if validProductFound: + fireNameList.append("Manually Enter in Request Info") desFireName = "Please Choose a Fire", "fireName" varList.append((desFireName, fireNameList[0], "radio", fireNameList)) # Product Issuance Processing issuanceList = [ "Morning", "Morning Update", "Afternoon Update", - "Afternoon", "Evening Update", - "Early Morning Update", "Next Day" + "Afternoon", "Afternoon with 4 periods", "Evening Update", + "Evening Update with 4 periods", "Early Morning Update", + "Early Morning Update with 4 periods", "Next Day" ] desIssuanceList = "Product Issuance:", "productIssuance" varList.append((desIssuanceList, issuanceList[0], "radio", issuanceList)) # Forecaster List Section of the GUI forecasterNameList = [] + defaultForecasterNameList = [] + cmd = "whoami" + db = os.popen(cmd,'r') + awipsLogin = db.read() + db.close() + awipsLogin = string.replace(awipsLogin, "\n", "") for forecaster in self._forecasterList: - id, initial, name = forecaster + id, awipsName, name = forecaster forecasterNameList.append(name) + if awipsLogin == awipsName: + defaultForecasterNameList.append(name) desForecasterNameList = "Forecaster:", "forecaster" - varList.append((desForecasterNameList, [], "check", forecasterNameList)) + varList.append((desForecasterNameList, defaultForecasterNameList, "check", forecasterNameList)) if self._includeCreationTimeOnGUI: # Get start date and time from user @@ -724,8 +822,11 @@ class FWS_Overrides: self._creationTime = varDict[desCreationTime] if validProductFound: - stqIndex = fireNameList.index(varDict[desFireName]) - return products[stqIndex], productIssuance, forecasters + if varDict[desFireName] == "Manually Enter in Request Info": + return None, productIssuance, forecasters + else: + stqIndex = fireNameList.index(varDict[desFireName]) + return masterProductList[stqIndex], productIssuance, forecasters else: return None, productIssuance, forecasters @@ -784,6 +885,8 @@ class FWS_Overrides: ["20", "WIND", ("FT", "FOOT")]), ("EYE LEVEL WINDS", 1, self.fireEyeWind_compoundPhrase, [("EYE","10"), "WIND"]), + ("SURFACE WINDS", 0, self.fireSfcWind_compoundPhrase, + ["SURFACE", "WIND"]), ("WIND SHIFT", 0, self.fireWindShift_label_phrase, ["WIND", "SHIFT"]), ("RIDGE TOP WIND", 0, self.freeWind_phrase, @@ -806,6 +909,8 @@ class FWS_Overrides: ["LDSI"]), ("LVORI", 0, self.lvori_phrase, ["LVORI"]), + ("ADI",0, self.adi_phrase, + ["ADI"]), ("DISPERSION INDEX", 0, self.dsi_phrase, ["DISPERSION", "INDEX"]), ("CLEARING INDEX", 0, self.smokeDispersal_phrase, @@ -816,6 +921,32 @@ class FWS_Overrides: ["MARINE", "LAYER"]), ("HAINES INDEX", 0, self.haines_phrase, ["HAINES", "INDEX"]), + ("VENTILATION RATE", 0, self.smokeDispersal_phrase, + ["VENTILATION", "RATE"]), + ("SWELL HEIGHT", 0, self.swell_phrase, + ["SWELL", "HEIGHT"]), + ("WAVE HEIGHT", 0, self.waveHeight_phrase, + ["WAVE","HEIGHT"]), + ("SWELL PERIOD", 0, self.period_phrase, + ["SWELL", "PERIOD"]), + ("WIND WAVE", 0, self.windWave_phrase, + ["WIND", "WAVE"]), + ("RAINFALL AMOUNT", 0, self.qpf_phrase, + ["RAINFALL", "AMOUNT"]), + ("SNOWFALL AMOUNT", 0, self.snow_phrase, + ["SNOWFALL", "AMOUNT"]), + ("FREEZING LEVEL", 0, self.freezingLevel_phrase, + ["FREEZING", "LEVEL"]), + ("CEILING", 0, self.ceiling_phrase, + ["CEILING"]), + ("VISIBILITY", 0, self.visibility_phrase, + ["VISIBILITY"]), + ("ICING", 0, self.icing_phrase, + ["ICING"]), + ("HAZARDS", 0, self.ceiling_phrase, + ["HAZARDS"]), + ("HEAT INDEX", 0, self.heatIndex_phrase, + ["HEAT", "INDEX"]), ] def _weInfoHiddenList(self): @@ -847,6 +978,7 @@ class FWS_Overrides: ## ("DEWPOINT", 0), ## ("20 FOOT WINDS", 0), ## ("EYE LEVEL WINDS", 0), +## ("SURFACE WINDS", 0), ## ("WIND SHIFT", 0), ## ("RIDGE TOP WIND", 0), ## ("SURROUNDING RIDGE", 0), @@ -859,38 +991,140 @@ class FWS_Overrides: ## ("DISPERSION INDEX", 0), ## ("LDSI", 0), ## ("LVORI", 0), +## ("ADI", 0), ## ("CLEARING INDEX", 0), ## ("STABILITY CLASS", 0), ## ("MARINE LAYER", 0), ## ("HAINES INDEX", 0), +## ("VENTILATION RATE", 0), +## ("SWELL HEIGHT", 0), +## ("WAVE HEIGHT", 0), +## ("SWELL PERIOD", 0), +## ("WIND WAVE", 0), +## ("RAINFALL AMOUNT", 0), +## ("SNOWFALL AMOUNT", 0), +## ("FREEZING LEVEL", 0), +## ("CEILING", 0), +## ("VISIBILITY", 0), +## ("ICING", 0), +## ("HAZARDS", 0), +## ("HEAT INDEX", 0), ] def _rowList(self, colWidth=1): - if self._tableWindElementSplit == "no" and colWidth == 7: # 2 hourly - wind = [("20 FT WIND......", self._wind_value), - ("20 FT WIND GUST.", self._windGust_value)] - elif self._tableWindElementSplit == "no" and colWidth > 7: # 3-4 hourly - wind = [("20 FT WIND......", self._windWithGust_value)] - else: - wind = [("20 FT WIND DIR..", self._windDir_value), # 1 hourly - ("20 FT WIND SPD..", self._windSpd_value), - ("20 FT WIND GUST.", self._windGust_value)] - if self._tableEyeWindElementSplit =="no" and colWidth == 7: - eyewind = [("EYE LEVEL WIND..", self._eyewind_value), - ("EYE LEVEL WIND..", self._eyewindGust_value)] - elif self._tableEyeWindElementSplit == "no" and colWidth > 7: - eyewind = [("EYE LEVEL WIND..", self._eyewindWithGust_value)] - else: - eyewind = [("EYE LVL WND DIR.", self._eyewindDir_value), - ("EYE LVL WND SPD.", self._eyewindSpd_value), - ("EYE LVL WND GST.", self._eyewindGust_value)] - if self._tableRidgeElementSplit == "no" and colWidth >=7: - ridge = [("RIDGETOP WIND...", self._ridge_value)] - else: - ridge = [("RIDGE WIND DIR..", self._ridgeDir_value), - ("RIDGE WIND SPD..", self._ridgeSpd_value)] - # Mixing Height and Transport winds + ### 20 foot wind tabular phrase configuration ### + + if self._tableWindElementSplit == "no" and colWidth == 7: # 2 hourly + if self._bothAlphaNumericDict.get(self._20ftWindParm, "No") == "No": + wind = [("20 FT WIND......", self._wind_value), + ("20 FT WIND GUST.", self._windGust_value)] + else: + wind = [("20 FT WIND......", self._wind_value), + ("20 FT WIND GUST.", self._windGust_value), + ("20 FT WIND DIR..", self._windNumDir_value)] + elif self._tableWindElementSplit == "no" and colWidth > 7: # 3-4 hourly + if self._bothAlphaNumericDict.get(self._20ftWindParm, "No") == "No": + wind = [("20 FT WIND......", self._windWithGust_value)] + else: + wind = [("20 FT WIND......", self._windWithGust_value), + ("20 FT WIND DIR..", self._windNumDir_value)] + else: + if self._bothAlphaNumericDict.get(self._20ftWindParm, "No") == "No": + wind = [("20 FT WIND DIR..", self._windDir_value), # 1 hourly + ("20 FT WIND SPD..", self._windSpd_value), + ("20 FT WIND GUST.", self._windGust_value)] + else: + wind = [("20 FT WIND DIR..", self._windDir_value), # 1 hourly + ("20 FT WIND DIR..", self._windNumDir_value), + ("20 FT WIND SPD..", self._windSpd_value), + ("20 FT WIND GUST.", self._windGust_value)] + + ### eye level wind tabular phrase configuration ### + + if self._tableEyeWindElementSplit =="no" and colWidth == 7: + if self._bothAlphaNumericDict.get("EyeWind", "No") == "No": + eyewind = [("EYE LEVEL WIND..", self._eyewind_value), + ("EYE LVL WND GST.", self._eyewindGust_value)] + else: + eyewind = [("EYE LEVEL WIND..", self._eyewind_value), + ("EYE LVL WND GST.", self._eyewindGust_value), + ("EYE LVL WND DIR.", self._eyewindNumDir_value)] + elif self._tableEyeWindElementSplit == "no" and colWidth > 7: + if self._bothAlphaNumericDict.get("EyeWind", "No") == "No": + eyewind = [("EYE LEVEL WIND..", self._eyewindWithGust_value)] + else: + eyewind = [("EYE LEVEL WIND..", self._eyewindWithGust_value), + ("EYE LVL WND DIR.", self._eyewindNumDir_value)] + else: + if self._bothAlphaNumericDict.get("EyeWind", "No") == "No": + eyewind = [("EYE LVL WND DIR.", self._eyewindDir_value), + ("EYE LVL WND SPD.", self._eyewindSpd_value), + ("EYE LVL WND GST.", self._eyewindGust_value)] + else: + eyewind = [("EYE LVL WND DIR.", self._eyewindDir_value), + ("EYE LVL WND DIR.", self._eyewindNumDir_value), + ("EYE LVL WND SPD.", self._eyewindSpd_value), + ("EYE LVL WND GST.", self._eyewindGust_value)] + + ### surface wind (10m) tabular phrase configuration ### + + if self._tableSfcWindElementSplit =="no" and colWidth == 7: + + if self._bothAlphaNumericDict.get("SfcWind", "No") == "No": + sfcwind = [("SURFACE WIND....", self._sfcwind_value), + ("SURFACE WND GST.", self._sfcwindGust_value)] + else: + sfcwind = [("SURFACE WIND....", self._sfcwind_value), + ("SURFACE WND GST.", self._sfcwindGust_value), + ("SURFACE WND DIR.", self._sfcwindNumDir_value)] + + elif self._tableSfcWindElementSplit == "no" and colWidth > 7: + + if self._bothAlphaNumericDict.get("SfcWind", "No") == "No": + sfcwind = [("SURFACE WIND....", self._sfcwindWithGust_value)] + else: + sfcwind = [("SURFACE WIND....", self._sfcwindWithGust_value), + ("SURFACE WND DIR.", self._sfcwindNumDir_value)] + + else: + + if self._bothAlphaNumericDict.get("SfcWind", "No") == "No": + sfcwind = [("SURFACE WND DIR.", self._sfcwindDir_value), + ("SURFACE WND SPD.", self._sfcwindSpd_value), + ("SURFACE WND GST.", self._sfcwindGust_value)] + else: + sfcwind = [("SURFACE WND DIR.", self._sfcwindDir_value), + ("SURFACE WND DIR.", self._sfcwindNumDir_value), + ("SURFACE WND SPD.", self._sfcwindSpd_value), + ("SURFACE WND GST.", self._sfcwindGust_value)] + + ### ridge top wind tabular phrase configuration ### + + if self._tableRidgeElementSplit == "no" and colWidth >=7: + if self._bothAlphaNumericDict.get("RidgeWind", "No") == "No": + ridge = [("RIDGETOP WIND...", self._ridge_value)] + else: + ridge = [("RIDGETOP WIND...", self._ridge_value), + ("RIDGE WIND DIR..", self._ridgeNumDir_value)] + else: + if self._bothAlphaNumericDict.get("RidgeWind", "No") == "No": + ridge = [("RIDGE WIND DIR..", self._ridgeDir_value), + ("RIDGE WIND SPD..", self._ridgeSpd_value)] + else: + ridge = [("RIDGE WIND DIR..", self._ridgeDir_value), + ("RIDGE WIND DIR..", self._ridgeNumDir_value), + ("RIDGE WIND SPD..", self._ridgeSpd_value)] + + ### swell tabular phrase configuration ### + + if self._tableSwellElementSplit == "no" and colWidth >=7: + swell = [("SWELL HGT (FT)..", self._swell_value)] + else: + swell = [("SWELL DIRECTION.", self._swellDir_value), + ("SWELL HGT (FT)..", self._swellHgt_value)] + + ### Mixing Height and Transport wind label configuration ### if self._tabularMixingHeightUnits == "ft" and colWidth > 4: mixLabel = "MIX HGT (FT)...." @@ -915,39 +1149,101 @@ class FWS_Overrides: if self._tableTransElementSplit == "no" and colWidth >=7: # Baseline if self._includeMetricDispersion == "yes": - smoke = [(mixLabel, self._mixingHeight_value), - (mixMetricLabel, self._mixingHeightMetric_value), - (transLabel, self._trans_value), - (transMetricLabel, self._transMetric_value)] - trans = [(transLabel, self._trans_value), - (transMetricLabel, self._transMetric_value)] + if self._bothAlphaNumericDict.get("TransWind", "No") == "No": + smoke = [(mixLabel, self._mixingHeight_value), + (mixMetricLabel, self._mixingHeightMetric_value), + (transLabel, self._trans_value), + (transMetricLabel, self._transMetric_value)] + trans = [(transLabel, self._trans_value), + (transMetricLabel, self._transMetric_value)] + else: + smoke = [(mixLabel, self._mixingHeight_value), + (mixMetricLabel, self._mixingHeightMetric_value), + (transLabel, self._trans_value), + (transDirLabel, self._transNumDir_value), + (transMetricLabel, self._transMetric_value)] + trans = [(transLabel, self._trans_value), + (transDirLabel, self._transNumDir_value), + (transMetricLabel, self._transMetric_value)] else: - smoke = [(mixLabel, self._mixingHeight_value), - (transLabel, self._trans_value)] - trans = [(transLabel, self._trans_value)] + if self._bothAlphaNumericDict.get("TransWind", "No") == "No": + smoke = [(mixLabel, self._mixingHeight_value), + (transLabel, self._trans_value)] + trans = [(transLabel, self._trans_value)] + else: + smoke = [(mixLabel, self._mixingHeight_value), + (transLabel, self._trans_value), + (transDirLabel, self._transNumDir_value)] + trans = [(transLabel, self._trans_value), + (transDirLabel, self._transNumDir_value)] else: # Baseline if self._includeMetricDispersion == "yes": - smoke = [(mixLabel, self._mixingHeight_value), - (mixMetricLabel, self._mixingHeightMetric_value), - (transDirLabel, self._transDir_value), - (transSpdLabel, self._transSpd_value), - (transSpdMetricLabel, self._transSpdMetric_value)] - trans = [(transDirLabel, self._transDir_value), - (transSpdLabel, self._transSpd_value), - (transSpdMetricLabel, self._transSpdMetric_value)] + if self._bothAlphaNumericDict.get("TransWind", "No") == "No": + smoke = [(mixLabel, self._mixingHeight_value), + (mixMetricLabel, self._mixingHeightMetric_value), + (transDirLabel, self._transDir_value), + (transSpdLabel, self._transSpd_value), + (transSpdMetricLabel, self._transSpdMetric_value)] + trans = [(transDirLabel, self._transDir_value), + (transSpdLabel, self._transSpd_value), + (transSpdMetricLabel, self._transSpdMetric_value)] + else: + smoke = [(mixLabel, self._mixingHeight_value), + (mixMetricLabel, self._mixingHeightMetric_value), + (transDirLabel, self._transDir_value), + (transDirLabel, self._transNumDir_value), + (transSpdLabel, self._transSpd_value), + (transSpdMetricLabel, self._transSpdMetric_value)] + trans = [(transDirLabel, self._transDir_value), + (transDirLabel, self._transNumDir_value), + (transSpdLabel, self._transSpd_value), + (transSpdMetricLabel, self._transSpdMetric_value)] else: - smoke = [(mixLabel, self._mixingHeight_value), - (transDirLabel, self._transDir_value), - (transSpdLabel, self._transSpd_value)] - trans = [(transDirLabel, self._transDir_value), - (transSpdLabel, self._transSpd_value)] + if self._bothAlphaNumericDict.get("TransWind", "No") == "No": + smoke = [(mixLabel, self._mixingHeight_value), + (transDirLabel, self._transDir_value), + (transSpdLabel, self._transSpd_value)] + trans = [(transDirLabel, self._transDir_value), + (transSpdLabel, self._transSpd_value)] + else: + smoke = [(mixLabel, self._mixingHeight_value), + (transDirLabel, self._transDir_value), + (transDirLabel, self._transNumDir_value), + (transSpdLabel, self._transSpd_value)] + trans = [(transDirLabel, self._transDir_value), + (transDirLabel, self._transNumDir_value), + (transSpdLabel, self._transSpd_value)] if self._includeMetricDispersion == "yes": mix = [(mixLabel, self._mixingHeight_value), (mixMetricLabel, self._mixingHeightMetric_value)] else: mix = [(mixLabel, self._mixingHeight_value)] + ### sky/wx/hazard tabular phrase configuration ### + + if self._elementFormatDict.get("Sky", "alpha") == "alpha": + if self._bothAlphaNumericDict.get("Sky", "No") == "No": + skywx = [("SKY COVER.......", self._sky_value), + ("WEATHER COV.....", self._weatherCov_value), + ("WEATHER TYPE....", self._weatherType_value), + ("TSTM COV........", self._tstmCov_value)] + else: + skywx = [("SKY COVER.......", self._sky_value), + ("SKY (%).........", self._numSky_value), + ("WEATHER COV.....", self._weatherCov_value), + ("WEATHER TYPE....", self._weatherType_value), + ("TSTM COV........", self._tstmCov_value)] + else: + skywx = [("SKY (%).........", self._sky_value), + ("WEATHER COV.....", self._weatherCov_value), + ("WEATHER TYPE....", self._weatherType_value), + ("TSTM COV........", self._tstmCov_value)] + + hazard = [("HAZARD VTEC 1...", self._wwa_value), + ("HAZARD VTEC 2...", self._wwa2_value), + ("HAZARD VTEC 3...", self._wwa3_value)] + return [ # Set to Directive requirements # Each entry is a tuple: @@ -957,15 +1253,13 @@ class FWS_Overrides: # in the narrative portion of the product as well. # tableRows is a list of (label:method) pairs. # - ("SKY/WEATHER" , 1, - [("SKY (%).........", self._sky_value), - ("WEATHER COV.....", self._weatherCov_value), - ("WEATHER TYPE....", self._weatherType_value), - ]), + ("SKY/WEATHER" , 1, skywx), ("TEMPERATURE" , 1,[("TEMP............", self._temp_value)]), + ("DEWPOINT" , 1,[("DEWPOINT........", self._td_value)]), ("HUMIDITY" , 1,[("RH..............", self._rh_value)]), ("20 FOOT WINDS" , 1, wind), ("EYE LEVEL WINDS" , 1, eyewind), + ("SURFACE WINDS" , 1, sfcwind), #("RIDGE TOP WIND" , 1, ridge), #("SMOKE DISPERSION" , 1, smoke), #("MIXING HEIGHT" , 1, mix), @@ -973,15 +1267,27 @@ class FWS_Overrides: ("DISPERSION INDEX" , 1,[("DISPERSION......", self._dsi_value)]), ("LDSI" , 1,[("DISPERSION IDX..", self._ldsi_value)]), ("LVORI" , 1,[("LVORI...........", self._lvori_value)]), + ("ADI" , 1,[("ADI.............", self._adi_value)]), #("CWR" , 1,[("CWR.............", self._cwr_value)]), ("POP" , 1,[("CHC OF PCPN (%).", self._pop_value)]), #("LIGHTNING ACTIVITY LEVEL", 1,[("LAL.............", self._lal_value)]), ("HAINES INDEX" , 1,[("HAINES INDEX....", self._haines_value)]), + ("VENTILATION RATE" , 1,[("VRATE KT-FT/1000", self._ventrate_value)]), + ("SWELL HEIGHT" , 1, swell), + ("SWELL PERIOD" , 1,[("SWELL PERIOD (S)", self._swellPeriod_value)]), + ("WIND WAVE" , 1,[("WIND WAVE (FT)..", self._windWave_value)]), + ("WAVE HEIGHT" , 1,[("WAVE HEIGHT (FT)", self._waveHeight_value)]), + ("FREEZING LEVEL" , 1,[("FZ LEVEL (KFT)..", self._freezingLevel_value)]), + ("CEILING" , 1,[("CEILING (KFT)...", self._ceiling_value)]), + ("VISIBILITY" , 1,[("VISIBILITY (SM).", self._visibility_value)]), + ("ICING" , 1,[("ICING...........", self._ceiling_value)]), + ("HAZARDS" , 0, hazard), + ("HEAT INDEX" , 1,[("HEAT INDEX (F)..", self._heatIndex_value)]), ] def _getProductInfo(self, product, issuance, forecasters): # Parse the spot request information selected and - # return the FireInfo for display. + # return the FireInfo for display. timezone = os.environ["TZ"] spotRequestInfo = [ ("PROJECT NAME:", "fireName", "'xxxx'"), @@ -1071,7 +1377,7 @@ class FWS_Overrides: value = cleanLine[index+1:].strip() for field, variable, default in spotRequestInfo: - if field in cleanLine: + if field in cleanLine and cleanLine.find(field) == 0: # Assign to variable exec "self._"+variable + " = value" @@ -1213,6 +1519,23 @@ class FWS_Overrides: varList.append((desTableRes, self._defaultTabularResolution["Tomorrow"],"radio", self._tabularResolutionDict["Tomorrow"])) + if self._productIssuance in ["Afternoon with 4 periods", "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + desElementList = "Tomorrow Night Elements", "tomorrowNightElements" + varList.append((desElementList, self._periodElementDict["Tomorrow"], + "check", self._periodAllElementDict["Tomorrow"] )) + if self._tabularAllPeriods == "yes": + desTableRes = tableHoursDesc,"tomorrowNightTableRes" + varList.append((desTableRes, self._defaultTabularResolution["Tomorrow"],"radio", + self._tabularResolutionDict["Tomorrow"])) + desElementList = "Next Day Elements", "nextDayElements" + varList.append((desElementList, self._periodElementDict["Tomorrow"], + "check", self._periodAllElementDict["Tomorrow"] )) + if self._tabularAllPeriods == "yes": + desTableRes = tableHoursDesc,"nextDayTableRes" + varList.append((desTableRes, self._defaultTabularResolution["Tomorrow"],"radio", + self._tabularResolutionDict["Tomorrow"])) + # Launch the Spot Request Quality Control GUI. varDict = self._callProcessVariableList("Input Info", varList, varDict={}) if varDict is None: @@ -1426,7 +1749,7 @@ class FWS_Overrides: # Add a "custom" component to sample data from current time # to product start time ct = self._issuanceInfo.issueTime() - currentTime = AbsTime.absTimeYMD(ct.year, ct.month, ct.day, + currentTime = AbsTime.AbsTimeYMD(ct.year, ct.month, ct.day, ct.hour) productStart = self._issuanceInfo.timeRange().startTime() tr = TimeRange.TimeRange(currentTime, productStart) @@ -1477,7 +1800,7 @@ class FWS_Overrides: self._fireSize = int(float(self._fireSize)+0.5) except ValueError: self._fireSize = 1 - if self._fireSize == 0: + if self._fireSize <= 0: self._fireSize = 1 try: @@ -1499,6 +1822,10 @@ class FWS_Overrides: if self._productIssuance in ["Next Day", "Morning", "Morning Update", "Afternoon Update"]: elementLists = [self._todayElements, self._tonightElements, self._tomorrowElements] + elif self._productIssuance in ["Afternoon with 4 periods", "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + elementLists = [self._tonightElements, self._tomorrowElements, + self._tomorrowNightElements, self._nextDayElements] else: elementLists = [self._tonightElements, self._tomorrowElements] @@ -1562,9 +1889,13 @@ class FWS_Overrides: self._todayTableRes = "None" self._tonightTableRes = "None" self._tomorrowTableRes = "None" + self._tomorrowNightTableRes = "None" + self._nextDayTableRes = "None" self._todayElements = [] self._tonightElements = [] self._tomorrowElements = [] + self._tomorrowNightElements = [] + self._nextDayElements = [] # Get Definition variables self._definition = argDict["forecastDef"] @@ -1831,7 +2162,7 @@ class FWS_Overrides: self.filterMethod, argDict["databaseID"], self._fullStationID, activeTableName = argDict['vtecActiveTable'], - vtecMode = argDict['vtecMode'], + vtecMode = argDict['vtecMode'], dataMgr=argDict['dataMgr']) argDict["hazards"] = hazards # Remove from server @@ -2026,6 +2357,18 @@ class FWS_Overrides: self._fireTR = None if self._withIgnitionTimes == "yes" or self._tableStartTimeMode == "ignitionTime": fcst = self._makeFcstTimeStatement(fcst, argDict) + try: + timeTup = time.strptime(self._timeLabel, '%I%M %p %Z %a %b %d %Y') + issueTime = time.mktime(timeTup) + except: + issueTime = time.time() + now = time.time() + if ((issueTime - now) < -24*3600) or ((issueTime - now) > 9*24*3600): + message = \ +'''|* The start time for this product is %s. +This is either more than a day in the past or more than 9 days +in the future. *|''' % self._timeLabel + fcst = '%s\n%s\n\n' % (fcst, message) return fcst def _postProcessProduct(self, fcst, argDict): @@ -2090,6 +2433,22 @@ class FWS_Overrides: else: period = ("FirePeriod3", 12) narrativeDef.append(period) + if self._productIssuance in ["Afternoon with 4 periods", + "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + # Add the third period + if len(self._tomorrowNightElements) == 0: + period = (phantom, 12) + else: + period = ("FirePeriod4", 12) + narrativeDef.append(period) + + # Add the fourth period + if len(self._nextDayElements) == 0: + period = (phantom, 12) + else: + period = ("FirePeriod5", 12) + narrativeDef.append(period) # Add extended if configured to appear if "Include Day 3-5 Extended?" in self._extendedQuestions: @@ -2099,6 +2458,14 @@ class FWS_Overrides: ("FireExtendedShortTerm", 24), ("FireExtendedShortTerm", 24), ] + elif self._productIssuance in ["Afternoon with 4 periods", + "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + extendedShortTerm = [ + ("FireExtendedShortTerm", 24), + ("FireExtendedShortTerm", 24), + ("FireExtendedShortTerm", 24), + ] else: extendedShortTerm = [ ("FireExtendedShortTerm", 24), @@ -2113,6 +2480,14 @@ class FWS_Overrides: ("Phantom", 24), ("Phantom", 24), ] + elif self._productIssuance in ["Afternoon with 4 periods", + "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + extendedShortTerm = [ + ("Phantom", 24), + ("Phantom", 24), + ("Phantom", 24), + ] else: extendedShortTerm = [ ("Phantom", 24), @@ -2156,9 +2531,15 @@ class FWS_Overrides: ("Afternoon", self.NIGHT(), 24 + self.DAY(), 24 + self.DAY(), ".TONIGHT...", "late in the night", "early in the evening", 1, narrativeDef), + ("Afternoon with 4 periods", self.NIGHT(), 24 + self.DAY(), 24 + self.DAY(), + ".TONIGHT...", "late in the night", "early in the evening", + 1, narrativeDef), ("Evening Update", "issuanceHour", 24 + self.DAY(), 24 + self.DAY(), ".REST OF TONIGHT...", "late in the night","early in the evening", 1, narrativeDef), + ("Evening Update with 4 periods", "issuanceHour", 24 + self.DAY(), 24 + self.DAY(), + ".REST OF TONIGHT...", "late in the night","early in the evening", + 1, narrativeDef), # For the early morning update, this produces: # REST OF TONIGHT: # MONDAY @@ -2166,6 +2547,9 @@ class FWS_Overrides: ("Early Morning Update", "issuanceHour", self.DAY(), self.DAY(), ".REST OF TONIGHT...", "early in the morning","late in the afternoon", 0, narrativeDef), + ("Early Morning Update with 4 periods", "issuanceHour", self.DAY(), self.DAY(), + ".REST OF TONIGHT...", "early in the morning","late in the afternoon", + 0, narrativeDef), ] def FirePeriod1(self): @@ -2210,6 +2594,34 @@ class FWS_Overrides: "intersectAreas": intersectAreas, } + def FirePeriod4(self): + phraseList = self.getFirePeriod_phraseList(self._tomorrowNightElements) + analysisList = self.getFirePeriod_analysisList() + intersectAreas = self.getFirePeriod_intersectAreas(4) + return { + "type": "component", + "methodList": [ + self.assembleIndentedPhrases, + ], + "analysisList": analysisList, + "phraseList": phraseList, + "intersectAreas": intersectAreas, + } + + def FirePeriod5(self): + phraseList = self.getFirePeriod_phraseList(self._nextDayElements) + analysisList = self.getFirePeriod_analysisList() + intersectAreas = self.getFirePeriod_intersectAreas(5) + return { + "type": "component", + "methodList": [ + self.assembleIndentedPhrases, + ], + "analysisList": analysisList, + "phraseList": phraseList, + "intersectAreas": intersectAreas, + } + def EmptyFirePeriod(self): phraseList = [] analysisList = self.getFirePeriod_analysisList() @@ -2288,8 +2700,31 @@ class FWS_Overrides: dict["Wind20ft"] = 1 dict["TransWind"] = 1 dict["CWR"] = 1 + dict["QPF"] = .0001 + dict["Vsby"] = .01 return dict + def scalar_difference_nlValue_dict(self, tree, node): + # Scalar difference. If the difference between scalar values + # for 2 sub-periods is greater than this value, + # the different values will be noted in the phrase. + dict = TextRules.TextRules.scalar_difference_nlValue_dict(self, tree, node) + dict["Vsby"] = { + (0.00,1.00) : 0.25, + (1.00,3.00) : 0.50, + (3.00,5.00) : 1.00, + "default" : 2.00, + } + dict["PredHgt"] = { + (0,10) : 1, + (10,30) : 5, + (30,100) : 10, + "default" : 25, + } + dict["Td"] = 5 + dict["PoP"] = 10 + return dict + def getFirePeriod_phraseList(self, periodElements): phraseList = [] if self._forecastType in ["Tabular/Narrative"]: @@ -2340,6 +2775,8 @@ class FWS_Overrides: ("T", self.avg, [1]), ("T", self.hourlyTemp), ("T", self.minMax), + ("Td", self.avg, [1]), + ("Td", self.hourlyTemp), ("Td", self.minMax), ("Wind", self.vectorMinMax, [1]), ("WindGust", self.maximum, [1]), @@ -2352,9 +2789,22 @@ class FWS_Overrides: ("DSI", self.maximum,[1]), ("LDSI", self.maximum,[1]), ("LVORI", self.maximum,[1]), + ("ADI", self.maximum,[1]), ("CWR", self.maximum, [1]), ("Stability", self.maximum, [1]), ("MarineLayer", self.maximum, [1]), + ("Swell", self.vectorMinMax, [1]), + ("Period", self.maximum, [1]), + ("WindWaveHgt", self.maximum, [1]), + ("WaveHeight", self.maximum, [1]), + ("QPF", self.accumSum, [6]), + ("SnowAmt", self.accumSum, [6]), + ("FzLevel", self.median, [1]), + ("Hazards", self.dominantDiscreteValue, [1]), + ("Vsby", self.minimum, [1]), + ("PredHgt", self.minimum, [1]), + ("HeatIndex", self.maximum, [1]), + ("ApparentT", self.maximum, [1]), ] else: analysisList = [ @@ -2378,6 +2828,8 @@ class FWS_Overrides: ("T", self.avg, [1]), ("T", self.hourlyTemp), ("T", self.minMax), + ("Td", self.avg, [1]), + ("Td", self.hourlyTemp), ("Td", self.minMax), ("Wind", self.vectorMinMax, [6]), ("WindGust", self.maximum, [6]), @@ -2391,8 +2843,21 @@ class FWS_Overrides: ("DSI", self.maximum,[12]), ("LDSI", self.maximum,[12]), ("LVORI", self.maximum,[12]), + ("ADI", self.maximum,[12]), ("Stability", self.maximum), ("MarineLayer", self.maximum), + ("Swell", self.vectorMinMax, [6]), + ("Period", self.maximum, [6]), + ("WindWaveHgt", self.maximum, [6]), + ("WaveHeight", self.maximum, [6]), + ("QPF", self.accumMinMax, [6]), + ("SnowAmt", self.accumMinMax, [6]), + ("FzLevel", self.median, [6]), + ("Hazards", self.dominantDiscreteValue), + ("Vsby", self.minimum, [6]), + ("PredHgt", self.minimum, [6]), + ("HeatIndex", self.maximum, [6]), + ("ApparentT", self.maximum, [6]), ] return analysisList @@ -2413,6 +2878,7 @@ class FWS_Overrides: dict["FREE WINDS.........."]="RIDGETOP WIND......." dict["SURROUNDING RIDGE..."]="SURROUNDING RIDGE..." dict["EYE LEVEL WINDS....."]="EYE LEVEL WINDS....." + dict["SURFACE WINDS......."]="SURFACE WINDS......." dict["WIND SHIFT.........."]="WIND SHIFT.........." if self._transportWindLabel == "mix": dict["TRANSPORT WINDS....."]="MIXING WINDS........" @@ -2422,10 +2888,22 @@ class FWS_Overrides: dict["DSI................."]="DISPERSION.........." dict["LDSI................"]="DISPERSION INDEX...." dict["LVORI..............."]="LVORI..............." + dict["ADI................."]="ADI................." dict["POP................."]="CHANCE OF PCPN......" dict["DEWPOINT............"]="DEWPOINT............" dict["BEGIN/END OF PCPN..."]="BEGIN/END OF PCPN..." dict["STABILITY CLASS....."]="STABILITY CLASS....." + dict["WIND WAVE..........."]="WIND WAVE..........." + dict["RAINFALL AMOUNT....."]="RAINFALL AMOUNT....." + dict["SNOWFALL AMOUNT....."]="SNOWFALL AMOUNT....." + dict["SWELL PERIOD........"]="SWELL PERIOD........" + dict["SWELL HEIGHT........"]="SWELL HEIGHT........" + dict["FREEZING LEVEL......"]="FREEZING LEVEL......" + dict["CEILING............."]="CEILING............." + dict["VISIBILITY.........."]="VISIBILITY.........." + dict["ICING..............."]="ICING..............." + dict["HEAT INDEX.........."]="HEAT INDEX.........." + dict["erraticWind"]="gusty and erratic winds expected near thunderstorms" if self._withIgnitionTimes == "yes": dict["MinT_FireWx"]="TEMPERATURE........." dict["MaxT_FireWx"]="TEMPERATURE........." @@ -2466,6 +2944,10 @@ class FWS_Overrides: connector = self.value_connector(tree, node, elementName, elementName) igWords = `int(self.getValue(stats, "avg"))` min, max = self.getValue(stats, "MinMax") + if min > 100: + min = 100 + if max > 100: + max = 100 if min == max: words = `int(min)` else: @@ -2509,6 +2991,7 @@ class FWS_Overrides: self.wind_summary, #self.wind_phrase, self.wind_withGusts_phrase, + self.erraticWind_phrase ], "phraseMethods": [ self.assembleSentences, @@ -2544,6 +3027,93 @@ class FWS_Overrides: node.set("compound", 1) return self.setWords(node, words) + def fireSfcWind_compoundPhrase(self): + return { + "phraseList": [ + self.wind_summary, + self.wind_phrase, + ], + "phraseMethods": [ + self.consolidateSubPhrases, + self.assembleSentences, + self.fireSfcWind_finishUp + ], + } + + def fireSfcWind_finishUp(self, tree, node): + "Create a phrase for Winds" + # Empty phrase if doing ridge/valley winds + if self.currentAreaContains( + tree, self.ridgeValleyAreas(tree, node)) == 1: + return self.setWords(node, "") + words = node.get("words") + if words is None: + return + if words == "": + words = "MISSING" + node.set("descriptor", "") + node.set("indentLabel", "SURFACE WINDS.......") + node.set("compound", 1) + return self.setWords(node, words) + + def erraticWind_phrase(self): + return { + "setUpMethod": self.erraticWind_setUp, + "wordMethod": self.erraticWind_words, + "phraseMethods": [ + self.preProcessWx, + self.combineWords, + self.fillNulls, + self.timeDescriptorModeration, + self.assembleSubPhrases, + self.postProcessPhrase, + ], + } + + def erraticWind_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("Wx", "List", self.WEATHER())] + self.subPhraseSetUp(tree, node, elementInfoList, self.wxConnector) + # Set this flag used by the "checkWeatherSimilarity" method + node.set("noIntensityCombining", 1) + self.determineSevereTimeDescriptors(tree, node) + return self.DONE() + + def erraticWind_words(self, tree, node): + # If T is in the Wx grids, then produce phrase. + # Wx Statistics: rankedWx + + statDict = node.getStatDict() + rankList = self.getStats(statDict, "Wx") + if rankList is None or len(rankList) == 0: + return self.setWords(node, "") + # Check against PoP + #rankList = self.checkPoP(tree, node, rankList) + subkeyList = self.getSubkeys(rankList) + + severe = 0 + thunder = 0 + attrTextList = [] + for subkey in subkeyList: + wxType = subkey.wxType() + if wxType == "T": + thunder = 1 + intensity = subkey.intensity() + if intensity == "+": + severe = 1 + wxDef = subkey.wxDef() + for attr in subkey.attributes(): + if attr in ["Primary", "Mention", "Dry"]: + continue + attrText = wxDef.attributeDesc(subkey.wxType(), attr).lower() + if attrText not in attrTextList: + attrTextList.append(attrText) + + if thunder == 0: + return self.setWords(node, "") + words = self.phrase_descriptor(tree, node, "erraticWind", "Wx") + + return self.setWords(node, words) + def smokeDispersal_words(self, tree, node): "Create phrase for Smoke Dispersal" statDict = node.getStatDict() @@ -2638,6 +3208,29 @@ class FWS_Overrides: return self.setWords(node, words) + def adi_phrase(self): + return { + "setUpMethod": self.adi_setUp, + "wordMethod": self.adi_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def adi_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("ADI", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "ADI.................") + return self.DONE() + + def adi_words(self, tree, node): + statDict = node.getStatDict() + adi = self.getStats(statDict, "ADI") + if adi is None: + return self.setWords(node.parent, "MISSING") + adi = self.getValue(adi) + words = `int(adi + 0.5)` + return self.setWords(node, words) + def haines_words(self, tree, node): "Create phrase for Haines Index" statDict = node.getStatDict() @@ -2695,6 +3288,318 @@ class FWS_Overrides: words = `int(cwr)` + " percent" return self.setWords(node, words) + def windWave_phrase(self): + return { + "setUpMethod": self.windWave_setUp, + "wordMethod": self.windWave_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def windWave_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("WindWaveHgt", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "WIND WAVE...........") + return self.DONE() + + def windWave_words(self, tree, node): + "Create phrase Wind Wave" + statDict = node.getStatDict() + height = self.getValue(self.getStats(statDict, "WindWaveHgt"), "Max") + if height is None: + return self.setWords(node.parent, "MISSING") + words = `int(height + 0.5)` + " FEET" + return self.setWords(node, words) + + def waveHeight_phrase(self): + return { + "setUpMethod": self.waveHeight_setUp, + "wordMethod": self.waveHeight_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def waveHeight_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("WaveHeight", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "WAVE HEIGHT.........") + return self.DONE() + + def waveHeight_words(self, tree, node): + "Create phrase Wind Wave" + statDict = node.getStatDict() + height = self.getValue(self.getStats(statDict, "WaveHeight"), "Max") + if height is None: + return self.setWords(node.parent, "MISSING") + words = `int(height + 0.5)` + " FEET" + return self.setWords(node, words) + + def qpf_phrase(self): + return { + "setUpMethod": self.qpf_setUp, + "wordMethod": self.qpf_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def qpf_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("QPF", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "RAINFALL AMOUNT.....") + return self.DONE() + + def qpf_words(self, tree, node): + "Create phrase QPF" + statDict = node.getStatDict() + qpf = self.getValue(self.getStats(statDict, "QPF"), "Max") + if qpf is None: + return self.setWords(node.parent, "MISSING") + if qpf == 0.0: + qpfWords = "0.00" + else: + qpf = qpf + 0.005 + qpfWords = string.strip("%5.2f" % qpf) + words = qpfWords + " INCHES" + return self.setWords(node, words) + + def period_phrase(self): + return { + "setUpMethod": self.period_setUp, + "wordMethod": self.period_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def period_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("Period", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "SWELL PERIOD........") + return self.DONE() + + def period_words(self, tree, node): + "Create phrase Swell Period" + statDict = node.getStatDict() + period = self.getValue(self.getStats(statDict, "Period"), "Max") + if period is None: + return self.setWords(node.parent, "MISSING") + words = `int(period + 0.5)` + " SECONDS" + return self.setWords(node, words) + + def swell_phrase(self): + return { + "setUpMethod": self.swell_setUp, + "wordMethod": self.swell_words, + "phraseMethods": self.standard_vector_phraseMethods(), + } + + def swell_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("Swell", self.VECTOR())] + self.subPhraseSetUp(tree, node, elementInfoList, self.vectorConnector) + node.set("descriptor", "") + node.set("indentLabel", "SWELL HEIGHT........") + return self.DONE() + + def swell_words(self, tree, node): + "Create phrase Swell Height" + statDict = node.getStatDict() + stats = self.getStats(statDict, "Swell") + if stats is None: + return self.setWords(node, "") + height, dir = self.getValue(stats, "Max", self.VECTOR()) + if height is None: + return self.setWords(node.parent, "MISSING") + if dir >= 22.5 and dir < 67.5: + dirWords = "NORTHEAST" + elif dir >= 67.5 and dir < 112.5: + dirWords = "EAST" + elif dir >= 112.5 and dir < 157.5: + dirWords = "SOUTHEAST" + elif dir >= 157.5 and dir < 202.5: + dirWords = "SOUTH" + elif dir >= 202.5 and dir < 247.5: + dirWords = "SOUTHWEST" + elif dir >= 247.5 and dir < 292.5: + dirWords = "WEST" + elif dir >= 292.5 and dir < 337.5: + dirWords = "NORTHWEST" + else: + dirWords = "NORTH" + heightWords = `int(height + 0.5)` + words = dirWords + " SWELL " + heightWords + " FEET" + return self.setWords(node, words) + + def ceiling_phrase(self): + return { + "setUpMethod": self.ceiling_setUp, + "wordMethod": self.ceiling_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def ceiling_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("PredHgt", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "CEILING (KFT).......") + return self.DONE() + + def ceiling_words(self, tree, node): + "Create phrase Visibility" + statDict = node.getStatDict() + hgt = self.getValue(self.getStats(statDict, "PredHgt"), "Min") + if hgt is None: + return self.setWords(node.parent, "MISSING") + hgt = hgt / 10.0 + if hgt == 0.0: + hgtWords = "less than 0.1" + else: + if hgt < 10: + hgtWords = string.strip("%5.1f" % hgt) + else: + hgtWords = `int(hgt + 0.5)` + words = hgtWords + return self.setWords(node, words) + + def visibility_phrase(self): + return { + "setUpMethod": self.visibility_setUp, + "wordMethod": self.visibility_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def visibility_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("Vsby", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "VISIBILITY (SM).....") + return self.DONE() + + def visibility_words(self, tree, node): + "Create phrase Visibility" + statDict = node.getStatDict() + vis = self.getValue(self.getStats(statDict, "Vsby"), "Min") + if vis is None: + return self.setWords(node.parent, "MISSING") + if vis == 0.0: + visWords = "0.0" + else: + if vis < 3: + visWords = string.strip("%5.2f" % vis) + else: + visWords = `int(vis + 0.5)` + words = visWords + return self.setWords(node, words) + + def icing_phrase(self): + return { + "setUpMethod": self.icing_setUp, + "phraseMethods": [self.postProcessPhrase], + } + + def icing_setUp(self, tree, node): + self.setWords(node, "") + node.set("descriptor", "") + node.set("indentLabel", "ICING...............") + return self.DONE() + + def freezingLevel_phrase(self): + return { + "setUpMethod": self.freezingLevel_setUp, + "wordMethod": self.freezingLevel_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def freezingLevel_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("FzLevel", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "FREEZING LEVEL......") + return self.DONE() + + def freezingLevel_words(self, tree, node): + "Create phrase for Freezing Level" + + statDict = node.getStatDict() + stats = self.getStats(statDict, "FzLevel") + if stats is None: + return self.setWords(node.parent, "MISSING") + + mix1, mix2 = self.getValue(stats, "MinMax") + outUnits = self.element_outUnits(tree, node, "FzLevel", "FzLevel") + mix1 = int(mix1) + mix2 = int(mix2) + threshold = self.nlValue(self.null_nlValue( + tree, node, "FzLevel", "FzLevel"), max) + if int(mix1) < threshold and int(mix2) < threshold: + return self.setWords(node, "null") + + # Single Value input + if mix1 == mix2: + words = `mix1` + " " + outUnits + # Range + else: + words = `mix1`+ "-" + `mix2` + " " + outUnits + + # Handle ignition time + if self._checkFireTR(node.getTimeRange()): + reqType = self._getRequestWords() + ignitionMixStats = tree.stats.get( + "FzLevel", self._fireTR, node.getAreaLabel(), mergeMethod="Max") + igWords = `int(ignitionMixStats)` + " " + outUnits + " at " + reqType +"...otherwise " + words = igWords + words + + return self.setWords(node, words) + + def snow_phrase(self): + return { + "setUpMethod": self.snow_setUp, + "wordMethod": self.snow_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def snow_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("SnowAmt", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "SNOWFALL AMOUNT.....") + return self.DONE() + + def snow_words(self, tree, node): + "Create phrase Snow" + statDict = node.getStatDict() + snow = self.getValue(self.getStats(statDict, "SnowAmt"), "Max") + if snow is None: + return self.setWords(node.parent, "MISSING") + if snow == 0.0: + snowWords = "0.0" + else: + snow = snow + 0.05 + snowWords = string.strip("%5.1f" % snow) + words = snowWords + " INCHES" + return self.setWords(node, words) + + def heatIndex_phrase(self): + return { + "setUpMethod": self.heatIndex_setUp, + "wordMethod": self.heatIndex_words, + "phraseMethods": self.standard_phraseMethods(), + } + + def heatIndex_setUp(self, tree, node): + elementInfoList = [self.ElementInfo("HeatIndex", "List")] + self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) + node.set("descriptor", "") + node.set("indentLabel", "HEAT INDEX..........") + return self.DONE() + + def heatIndex_words(self, tree, node): + "Create phrase Td" + statDict = node.getStatDict() + hi = self.getValue(self.getStats(statDict, "HeatIndex"), "Max") + if hi is None: + return self.setWords(node.parent, "MISSING") + words = `int(hi)` + return self.setWords(node, words) + ### Methods for Spot Table ### def _fwsTable_phrase(self): @@ -2741,11 +3646,25 @@ class FWS_Overrides: # Get table resolution (period) based on today, tonight, tomorrow componentName = node.getComponentName() period = None - for name, variable, elements in [ - ("FirePeriod1", self._todayTableRes, self._todayElements), - ("FirePeriod2", self._tonightTableRes, self._tonightElements), - ("FirePeriod3", self._tomorrowTableRes, self._tomorrowElements), - ]: + + if self._productIssuance in ["Afternoon with 4 periods", + "Evening Update with 4 periods", + "Early Morning Update with 4 periods"]: + tablePeriodList = [ + ("FirePeriod1", self._todayTableRes, self._todayElements), + ("FirePeriod2", self._tonightTableRes, self._tonightElements), + ("FirePeriod3", self._tomorrowTableRes, self._tomorrowElements), + ("FirePeriod4", self._tomorrowNightTableRes, self._tomorrowNightElements), + ("FirePeriod5", self._nextDayTableRes, self._nextDayElements), + ] + else: + tablePeriodList = [ + ("FirePeriod1", self._todayTableRes, self._todayElements), + ("FirePeriod2", self._tonightTableRes, self._tonightElements), + ("FirePeriod3", self._tomorrowTableRes, self._tomorrowElements), + ] + + for name, variable, elements in tablePeriodList: if componentName == name: period = variable tableElements = elements @@ -2973,6 +3892,15 @@ class FWS_Overrides: break return value + def _numSky_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + sky = self._getTableStats(tree, "Sky", timeRange, node.getAreaLabel()) + if sky is None: + value = "M" + else: + value = `int(sky + 0.5)` + return value + def _skyTableValues(self): return [ (5, "CLR", "CLEAR"), @@ -2997,10 +3925,10 @@ class FWS_Overrides: hiRank = -1 for subkey, rank in wxStats: # Find top 2 ranked subkeys to look for mixtures - if rank > hiRank: + if rank > hiRank and subkey.wxType() != "T": hiKey = subkey hiRank = rank - elif rank == hiRank: + elif rank == hiRank and subkey.wxType() != "T": coKey = subkey coRank = rank keyAttrs = hiKey.attributes() @@ -3035,10 +3963,29 @@ class FWS_Overrides: # If not found, return the hiKey attributes and wxType for attr1, type1, attr2, type2, keyAttr, keyType in self._weatherMixTable(): for key1, key2 in [(hiKey, coKey), (coKey, hiKey)]: - if attr1 in key1.attributes() and type1 == key1.wxType() and \ - attr2 in key2.attributes() and type2 == key2.wxType(): - # Match found - return [keyAttr], keyType + if type1 == key1.wxType() and type2 == key2.wxType(): + if len(key1.attributes()) == 0 and \ + len(key2.attributes()) == 0 and \ + attr1 == "" and attr2 == "": + # Match found + return [keyAttr], keyType + elif len(key1.attributes()) == 0 and \ + len(key2.attributes()) != 0 and \ + attr1 == "" and attr2 in key2.attributes(): + # Match found + return [keyAttr], keyType + elif len(key1.attributes()) != 0 and \ + len(key2.attributes()) == 0 and \ + attr1 in key1.attributes() and attr2 == "": + # Match found + return [keyAttr], keyType + elif len(key1.attributes()) != 0 and \ + len(key2.attributes()) != 0 and \ + attr1 in key1.attributes() and \ + attr2 in key2.attributes(): + # Match found + return [keyAttr], keyType + # No match found return hiKey.attributes(), hiKey.wxType() @@ -3094,6 +4041,36 @@ class FWS_Overrides: ("", "ZR","","SW","", "ZRS"), ] + def _tstmCov_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + areaLabel = node.getAreaLabel() + wxStats = tree.stats.get("Wx", timeRange, areaLabel, mergeMethod="Max") + if wxStats is None or len(wxStats) == 0: + return "M" + hiRank = -1 + for subkey, rank in wxStats: + print "*** vtm ***" + print subkey, rank + if rank > hiRank and subkey.wxType() == "T": + hiKey = subkey + hiRank = rank + if hiRank == -1: + return "" + value = None + for cov, shortVal, longVal in self._coverageCodeTable(): + if hiKey.coverage() == cov: + if colWidth == 4: + value = shortVal + else: + value = longVal + break + if value is None: + if colWidth == 4: + value = "???" + else: + value = "??????" + return value + def _weatherCov_value(self, statDict, timeRange, argList): tree, node, colWidth = tuple(argList) areaLabel = node.getAreaLabel() @@ -3102,9 +4079,11 @@ class FWS_Overrides: return "M" hiRank = -1 for subkey, rank in wxStats: - if rank > hiRank: + if rank > hiRank and subkey.wxType() != "T": hiKey = subkey hiRank = rank + if hiRank == -1: + return "" value = None for cov, shortVal, longVal in self._coverageCodeTable(): if hiKey.coverage() == cov: @@ -3192,6 +4171,84 @@ class FWS_Overrides: spdString = `wspd` return dirString, spdString + def _getWindNumDirSpdStr(self, tree, node, timeRange, element, formatElement=None, units=None): + windStats = tree.stats.get(element, timeRange, node.getAreaLabel(), + mergeMethod="Max") + if windStats is None: + return None + wspd,wdir = windStats + if formatElement is None: + formatElement = element + dir = int(wdir/10.0 + 0.5) * 10 + if dir < 10: + dirString = "00" + `dir` + elif dir < 100: + dirString = "0" + `dir` + else: + dirString = `dir` + if element == "Wind": + wspd = wspd * self._windAdjustmentFactor + if units == "Metric": + wspd = int(wspd*.44704 + 0.5) + else: + wspd = int(wspd + 0.5) + spdString = `wspd` + return dirString, spdString + + def _getEyeWindDirSpdStr(self, tree, node, timeRange, element, formatElement=None, units=None): + windStats = tree.stats.get(element, timeRange, node.getAreaLabel(), + mergeMethod="Max") + if windStats is None: + return None + wspd,wdir = windStats + if formatElement is None: + formatElement = element + if self._elementFormatDict.get(formatElement, "alpha") == "alpha": + wdir = int(wdir + 0.5) + dirString = self._dirConvert(wdir) + else: + dir = int(wdir/10.0 + 0.5) * 10 + if dir < 10: + dirString = "00" + `dir` + elif dir < 100: + dirString = "0" + `dir` + else: + dirString = `dir` + if element == "Wind": + wspd = wspd * self._eyeWindAdjustmentFactor + if units == "Metric": + wspd = int(wspd*.44704 + 0.5) + else: + wspd = int(wspd + 0.5) + spdString = `wspd` + return dirString, spdString + + def _getSfcWindDirSpdStr(self, tree, node, timeRange, element, formatElement=None, units=None): + windStats = tree.stats.get(element, timeRange, node.getAreaLabel(), + mergeMethod="Max") + if windStats is None: + return None + wspd,wdir = windStats + if formatElement is None: + formatElement = element + if self._elementFormatDict.get(formatElement, "alpha") == "alpha": + wdir = int(wdir + 0.5) + dirString = self._dirConvert(wdir) + else: + dir = int(wdir/10.0 + 0.5) * 10 + if dir < 10: + dirString = "00" + `dir` + elif dir < 100: + dirString = "0" + `dir` + else: + dirString = `dir` + if units == "Metric": + wspd = int(wspd*.44704 + 0.5) + else: + wspd = int(wspd + 0.5) + spdString = `wspd` + return dirString, spdString + def _dirConvert(self, wdir): dirString = "" if wdir >= 338 or wdir <= 22: @@ -3212,6 +4269,12 @@ class FWS_Overrides: dirString = "NW" return dirString + def _adjustEyeWind(self, value): + # adjustment for winds + factor = self.nlValue(self._eyeWindAdjustmentFactor, value) + value = value * factor + return value + def _wind_value(self, statDict, timeRange, argList, element=None, formatElement=None): if element is None: element = self._20ftWindParm @@ -3220,6 +4283,10 @@ class FWS_Overrides: tree, node, colWidth = tuple(argList) if formatElement == "TransMetWind": windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement, "Metric") + elif formatElement == "EyeWind": + windString = self._getEyeWindDirSpdStr(tree, node, timeRange, element, formatElement) + elif formatElement == "SfcWind": + windString = self._getSfcWindDirSpdStr(tree, node, timeRange, element, formatElement) else: windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement) if windString is None: @@ -3237,7 +4304,12 @@ class FWS_Overrides: if formatElement is None: formatElement = self._20ftWindParm tree, node, colWidth = tuple(argList) - windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement) + if formatElement == "EyeWind": + windString = self._getEyeWindDirSpdStr(tree, node, timeRange, element, formatElement) + elif formatElement == "SfcWind": + windString = self._getSfcWindDirSpdStr(tree, node, timeRange, element, formatElement) + else: + windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement) if windString is None: return "M" dirString, spdString = windString @@ -3267,6 +4339,45 @@ class FWS_Overrides: dirString, spdString = windString return dirString + def _windNumDir_value(self, statDict, timeRange, argList, element=None, formatElement=None): + if element is None: + element = self._20ftWindParm + if formatElement is None: + formatElement = self._20ftWindParm + tree, node, colWidth = tuple(argList) + windString = self._getWindNumDirSpdStr(tree, node, timeRange, element, formatElement) + if windString is None: + return "M" + dirString, spdString = windString + return dirString + + def _eyewindNumDir_value(self, statDict, timeRange, argList): + return self._windNumDir_value(statDict, timeRange, argList, "Wind", "EyeWind") + + def _sfcwind_value(self, statDict, timeRange, argList): + return self._wind_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _sfcwindWithGust_value(self, statDict, timeRange, argList): + return self._windWithGust_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _sfcwindDir_value(self, statDict, timeRange, argList): + return self._windDir_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _sfcwindSpd_value(self, statDict, timeRange, argList): + return self._windSpd_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _sfcwindGust_value(self, statDict, timeRange, argList): + return self._windGust_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _sfcwindNumDir_value(self, statDict, timeRange, argList): + return self._windNumDir_value(statDict, timeRange, argList, "Wind", "SfcWind") + + def _ridgeNumDir_value(self, statDict, timeRange, argList): + return self._windNumDir_value(statDict, timeRange, argList, "FreeWind", "RidgeWind") + + def _transNumDir_value(self, statDict, timeRange, argList): + return self._windNumDir_value(statDict, timeRange, argList, "TransWind", "TransWind") + def _windSpd_value(self, statDict, timeRange, argList, element=None, formatElement=None): if element is None: element = self._20ftWindParm @@ -3275,6 +4386,10 @@ class FWS_Overrides: tree, node, colWidth = tuple(argList) if formatElement == "TransMetWind": windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement, "Metric") + elif formatElement == "EyeWind": + windString = self._getEyeWindDirSpdStr(tree, node, timeRange, element, formatElement) + elif formatElement == "SfcWind": + windString = self._getSfcWindDirSpdStr(tree, node, timeRange, element, formatElement) else: windString = self._getWindDirSpdStr(tree, node, timeRange, element, formatElement) if windString is None: @@ -3434,6 +4549,13 @@ class FWS_Overrides: return "M" return `int(lvori + 0.5)` + def _adi_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + adi = self._getTableStats(tree, "ADI", timeRange, node.getAreaLabel()) + if adi is None: + return "M" + return `int(adi + 0.5)` + def _haines_value(self, statDict, timeRange, argList): tree, node, colWidth = tuple(argList) stats = self._getTableStats(tree, "Haines", timeRange, node.getAreaLabel()) @@ -3441,6 +4563,166 @@ class FWS_Overrides: return "M" return `int(stats + 0.5)` + def _ventrate_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + ventrate = self._getTableStats(tree, "VentRate", timeRange, node.getAreaLabel()) + if ventrate is None: + return "M" + return `int(ventrate/1000.0 + 0.5)` + + def _windWave_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "WindWaveHgt", timeRange, node.getAreaLabel()) + if stats is None: + return "M" + return `int(stats + 0.5)` + + def _waveHeight_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "WaveHeight", timeRange, node.getAreaLabel()) + if stats is None: + return "M" + return `int(stats + 0.5)` + + def _swellPeriod_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "Period", timeRange, node.getAreaLabel()) + if stats is None: + return "M" + return `int(stats + 0.5)` + + def _swell_value(self, statDict, timeRange, argList): + return self._wind_value(statDict, timeRange, argList,"Swell", "RidgeWind" ) + + def _swellDir_value(self, statDict, timeRange, argList): + return self._windDir_value(statDict, timeRange, argList, "Swell", "RidgeWind") + + def _swellHgt_value(self, statDict, timeRange, argList): + return self._windSpd_value(statDict, timeRange, argList, "Swell", "RidgeWind") + + def _freezingLevel_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + mix = self._getTableStats(tree, "FzLevel", timeRange, node.getAreaLabel()) + if mix is None: + return "M" + if mix < 50: + mix = 100.0 + kmix = mix / 1000.0 + kmix = round(kmix,1) + if kmix < 10: + value = str(round(kmix,1)) + else: + kmix = mix / 1000.0 + kmix = int(kmix + 0.5) + value = `kmix` + return value + + def _ceiling_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + temp = self._getTableStats(tree, "PredHgt", timeRange, node.getAreaLabel()) + if temp is None: + return " " + temp = temp / 10.0 + if temp < 10: + tempWords = string.strip("%4.1f" % temp) + else: + tempWords = `int(temp + 0.5)` + return tempWords + + def _visibility_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + temp = self._getTableStats(tree, "Vsby", timeRange, node.getAreaLabel()) + if temp is None: + return " " + print "colWidth =", colWidth + if colWidth > 4: + if temp < 1.0: + tempWords = string.strip("%4.2f" % temp) + elif temp >= 1.0 and temp < 3.0: + tempWords = string.strip("%4.1f" % temp) + else: + tempWords = `int(temp + 0.5)` + else: + if temp < 1.0: + tempWords = string.strip("%3.2f" % temp) + tempWords = tempWords[1:] + elif temp >= 1.0 and temp < 3.0: + tempWords = string.strip("%3.1f" % temp) + else: + tempWords = `int(temp + 0.5)` + return tempWords + + def _icing_value(self, statDict, timeRange, argList): + return " " + + def _td_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + temp = self._getTableStats(tree, "Td", timeRange, node.getAreaLabel()) + if temp is None: + return "M" + if temp >= 0: + temp = int(temp + 0.5) + else: + temp = int(temp - 0.5) + return `temp` + + def _heatIndex_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + temp = self._getTableStats(tree, "HeatIndex", timeRange, node.getAreaLabel()) + if temp is None: + return "M" + if temp >= 0: + temp = int(temp + 0.5) + else: + temp = int(temp - 0.5) + return `temp` + + def _wwa_exclude(self,stats): + list = [] + index = 0 + newstats = [] + while index < len(stats): + eidx = 0 + flag = 1 + while eidx < len(list): + if stats[index] == list[eidx]: + flag = 0 + eidx = eidx + 1 + if flag: + newstats.append(stats[index]) + index = index + 1 + return newstats + + def _wwa_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "Hazards", timeRange, node.getAreaLabel()) + if stats is None: + return " " + if stats[0] == "": + return " " + stats = self._wwa_exclude(stats) + return stats[0][0:2] + stats[0][3:4] + + def _wwa2_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "Hazards", timeRange, node.getAreaLabel()) + if stats is None: + return " " + stats = self._wwa_exclude(stats) + if len(stats) < 2: + return " " + return stats[1][0:2] + stats[1][3:4] + + def _wwa3_value(self, statDict, timeRange, argList): + tree, node, colWidth = tuple(argList) + stats = self._getTableStats(tree, "Hazards", timeRange, node.getAreaLabel()) + if stats is None: + return " " + stats = self._wwa_exclude(stats) + if len(stats) < 3: + return " " + return stats[2][0:2] + stats[2][3:4] + ### NEW NARRATIVE PHRASES ### def dsi_phrase(self): @@ -3525,7 +4807,7 @@ class FWS_Overrides: "phraseMethods": self.standard_phraseMethods(), } def pop_setUp(self, tree, node): - elementInfoList = [self.ElementInfo("PoP", "Average")] + elementInfoList = [self.ElementInfo("PoP", "Max")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "POP.................") @@ -3703,7 +4985,7 @@ class FWS_Overrides: def td_words(self, tree, node): "Create phrase Td" statDict = node.getStatDict() - td = self.getValue(self.getStats(statDict, "Td"), "Max") + td = self.getValue(self.getStats(statDict, "Td"), "Avg") if td is None: return self.setWords(node.parent, "MISSING") words = `int(td)` diff --git a/cave/build/static/linux/cave/caveEnvironment/bin/tmbRemoteCheck b/cave/build/static/linux/cave/caveEnvironment/bin/tmbRemoteCheck old mode 100755 new mode 100644 diff --git a/cave/build/static/linux/cave/caveEnvironment/bin/tmcp b/cave/build/static/linux/cave/caveEnvironment/bin/tmcp old mode 100755 new mode 100644 diff --git a/cave/build/static/linux/cave/caveEnvironment/lib/libgempak.so b/cave/build/static/linux/cave/caveEnvironment/lib/libgempak.so old mode 100755 new mode 100644 diff --git a/cave/com.raytheon.uf.viz.core/META-INF/spring/viz.xml b/cave/com.raytheon.uf.viz.core/META-INF/spring/viz.xml index 353c8991fb..ed0ae947f1 100644 --- a/cave/com.raytheon.uf.viz.core/META-INF/spring/viz.xml +++ b/cave/com.raytheon.uf.viz.core/META-INF/spring/viz.xml @@ -22,7 +22,7 @@ diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/jobs/JobPool.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/jobs/JobPool.java index 536ba25252..c9ca861fe3 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/jobs/JobPool.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/jobs/JobPool.java @@ -34,7 +34,7 @@ import org.eclipse.core.runtime.jobs.Job; * if you have dozens or hundreds of tasks that each take a short time. Creating * a job for each task can result in more threads than is useful. If you instead * use a JobPool it reduces the number of threads by limiting the number of - * eclipse jobs tBhat are created. For many tasks a JobPool may perform faster + * eclipse jobs that are created. For many tasks a JobPool may perform faster * than using eclipse Jobs directly because thread creation and context * switching are reduced. * @@ -59,6 +59,12 @@ public class JobPool { protected List jobList; + protected boolean cancel = false; + + protected Object cancelLock = new Object(); + + protected Object joinLock = new Object(); + public JobPool(String name, int size) { this(name, size, null, null); } @@ -82,46 +88,75 @@ public class JobPool { } } - public synchronized void schedule(Runnable runnable) { - workQueue.offer(runnable); - Job job = jobQueue.poll(); - if (job != null) { - job.schedule(); + public void schedule(Runnable runnable) { + // do not schedule while canceling(cancel should be fast). + synchronized (cancelLock) { + if (cancel) { + return; + } + // do not schedule while joining, join might be slow but the javaDoc + // warns others. + synchronized (joinLock) { + workQueue.offer(runnable); + Job job = jobQueue.poll(); + if (job != null) { + job.schedule(); + } + } } } /** * Join on the Runnables in the pool. Attempting to schedule other Runnables - * will block until join as returned so be careful when calling + * will block until join has returned so be careful when calling */ - public synchronized void join() { - for (Job j : jobList) { - try { - j.join(); - } catch (InterruptedException e) { - // Ignore interupt + public void join() { + synchronized (joinLock) { + for (Job j : jobList) { + try { + j.join(); + } catch (InterruptedException e) { + // Ignore interupt + } } } } /** * Cancel the job pool, will clear out the workQueue then join on all jobs - * running + * running. Once canceled all future calls to schedule will be ignored. */ - public synchronized void cancel() { - workQueue.clear(); - join(); + public void cancel() { + cancel(true); + } + + /** + * Cancel the job pool, will clear out the workQueue and optionally join + * runnning jobs. Once canceled all future calls to schedule will be + * ignored. + * + * @param join + * true if you want to join before returning. + */ + public void cancel(boolean join) { + synchronized (cancelLock) { + cancel = true; + workQueue.clear(); + } + if (join) { + join(); + } } /** * Cancels the specified runnable. Returns true if the provided runnable was - * waiting to be run but now is now. Returns false if the provided runnable + * waiting to be run but now is not. Returns false if the provided runnable * is already running or if it was not enqueued to begin with. * * @param runnable * @return */ - public synchronized boolean cancel(Runnable runnable) { + public boolean cancel(Runnable runnable) { return workQueue.remove(runnable); } diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java index c75e8c66d7..0c81f13840 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java @@ -286,9 +286,8 @@ public class ThriftClient { .postBinary(httpAddress, message); long time = System.currentTimeMillis() - t0; if (time >= SIMPLE_LOG_TIME) { - System.out.println("Time to execute " + request); - System.out.println("Took " + time + "ms"); - + System.out.println("Took " + time + "ms to run request " + + request); } if (time >= BAD_LOG_TIME) { new Exception() { diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java index dbf1221d70..b4acf0afe6 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java @@ -69,7 +69,6 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableData; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpBasinTableDlg; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfig; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData; -import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.IFFMPMonitorListener; import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.IFFMPResourceListener; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE; @@ -95,8 +94,7 @@ import com.raytheon.uf.viz.monitor.listeners.IMonitorListener; * @version 1 */ -public class FFMPMonitor extends ResourceMonitor implements - IFFMPMonitorListener { +public class FFMPMonitor extends ResourceMonitor { private static long SECONDS_PER_HOUR = 60 * 60; /** boolean for initialization **/ @@ -517,11 +515,13 @@ public class FFMPMonitor extends ResourceMonitor implements fsource, fhuc); if (!uris.containsKey(fdataUri)) { try { - FFMPRecord ffmpRec = loadRecordFromDatabase(fdataUri); + SourceXML sourceXML = fscm.getSource(fsource); + FFMPCacheRecord ffmpRec = populateFFMPRecord(true, + fdataUri, fsiteKey, fsource, fhuc); + //FFMPRecord ffmpRec = loadRecordFromDatabase(fdataUri); File loc = HDF5Util.findHDF5Location(ffmpRec); IDataStore dataStore = DataStoreFactory .getDataStore(loc); - SourceXML sourceXML = fscm.getSource(fsource); if (sourceXML.getSourceType().equals( SOURCE_TYPE.GAGE.getSourceType()) @@ -918,16 +918,11 @@ public class FFMPMonitor extends ResourceMonitor implements if (loadType == LOADER_TYPE.SECONDARY) { //hucsToLoad.remove("ALL"); //hucsToLoad.remove(getConfig().getFFMPConfigData().getLayer()); - - timeBack = new Date( - (long) (resource.getMostRecentTime().getTime() - ((getConfig() - .getFFMPConfigData().getTimeFrame() * 3) * 3600 * 1000))); - + timeBack = new Date(resource.getMostRecentTime().getTime() - (6 * 1000 * 24)); frd.timeBack = timeBack; } else if (loadType == LOADER_TYPE.TERTIARY) { hucsToLoad.clear(); hucsToLoad.add("ALL"); - startTime = new Date(resource.getMostRecentTime().getTime() - (3600 * 1000 * 6)); timeBack = new Date(resource.getMostRecentTime().getTime() - (3600 * 1000 * 24)); } @@ -1116,24 +1111,6 @@ public class FFMPMonitor extends ResourceMonitor implements resourceListeners.remove(listener); } - @Override - public void updateDialogTime(DataTime tableTime) { - - for (IFFMPResourceListener listener : getResourceListenerList()) { - if (listener instanceof FFMPResource) { - FFMPResource res = (FFMPResource) listener; - if (res.isLinkToFrame()) { - res.setTableTime(tableTime.getRefTime()); - if (res.basinTableDlg != null) { - updateDialog(res); - } - } - } - - } - - } - public ArrayList getResourceListenerList() { return resourceListeners; } @@ -1885,7 +1862,7 @@ public class FFMPMonitor extends ResourceMonitor implements public void run() { SourceXML source = getSourceConfig().getSource(fsourceName); - + if (furiMap != null) { for (List uris : furiMap.descendingMap() .values()) { @@ -2451,7 +2428,7 @@ public class FFMPMonitor extends ResourceMonitor implements curRecord = ffmpData.get(fsiteKey).get(mySource); if (curRecord == null) { curRecord = new FFMPCacheRecord(fffmpRec, - mySource); + mySource, getRunConfig().getRunner(wfo).getCacheDir()); ffmpData.get(fsiteKey).put(mySource, curRecord); } } @@ -2489,7 +2466,6 @@ public class FFMPMonitor extends ResourceMonitor implements statusHandler.handle(Priority.PROBLEM, "FFMP Can't retrieve FFMP URI, " + dataUri, e); - e.printStackTrace(); } } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java index f683b30327..62a18c9fc8 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java @@ -78,6 +78,8 @@ public abstract class FFMPTable extends Composite { /** DR14406: For columns with more words */ protected static final int EXTRA_COLUMN_WIDTH = 28; + protected String currentPfaf = null; + /** * Main table control. */ @@ -324,7 +326,10 @@ public abstract class FFMPTable extends Composite { cols[j].setImage(null); cols[j].setWidth(defaultColWidth); } - + + // reset the tableIndex + tableIndex = -1; + /* * Check of the column is sortable. */ @@ -453,6 +458,11 @@ public abstract class FFMPTable extends Composite { } indexArray.add(t); + + // Check to see if this is the selected row + if (rowData.getPfaf().equals(currentPfaf)) { + tableIndex = indexArray.indexOf(t); + } } /* * VIRTUAL TABLE diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTableComp.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTableComp.java index f7d2850030..a8ceb44430 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTableComp.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTableComp.java @@ -33,8 +33,6 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig.ThreshColNames; public class FFMPTableComp extends FFMPTable { private FfmpTableConfig tableConfig; - private String currentPfaf = null; - /** * Table selection callback. */ diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java index 3eb7026847..83b2f6ab01 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java @@ -23,6 +23,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.TimeZone; import org.eclipse.swt.SWT; @@ -108,6 +109,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(FfmpBasinTableDlg.class); + private List retrievalQueue = new ArrayList(); + private MenuItem linkToFrameMI; private MenuItem worstCaseMI; @@ -216,8 +219,10 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements private Composite tableComp; - private Thread dataRetrieveThread = null; + private FFMPTableDataLoader dataRetrieveThread = null; + private boolean sweet = true; + public FfmpBasinTableDlg(Shell parent, FFMPTableData tData, FFMPResource resource) { super(parent, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.INDEPENDENT_SHELL @@ -1184,6 +1189,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements @Override public void timeDurationUpdated(double val, boolean split) { shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); + updateTimeDurationLabel(val, split); if (dialogInitialized) { fireTimeChangedEvent(val, split, false); @@ -1375,7 +1381,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements if (waitCursor == true) { shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); } - + FFMPFieldChangeEvent ffce = new FFMPFieldChangeEvent(field); Iterator iter = ffmpListeners.iterator(); @@ -1675,11 +1681,15 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements @Override public void tableSelection(String pfaf, String name) { + if (groupLbl.getText().length() > 0) { + sweet = false; + } + if ((groupLbl.getText().length() == 0) || allOnlySmallBasinsMI.getSelection()) { groupLbl.setText(name); } - + shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); fireScreenRecenterEvent(pfaf, 1); } @@ -2028,13 +2038,29 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements FFMPTableDataLoader tableLoader = new FFMPTableDataLoader(me, resource, basinTrendDlg, allowNewTableUpdate, sourceUpdate, date, this); - if (dataRetrieveThread != null) { - dataRetrieveThread.interrupt(); - dataRetrieveThread = null; - } - dataRetrieveThread = new Thread(tableLoader); - dataRetrieveThread.start(); + synchronized (retrievalQueue) { + if (dataRetrieveThread == null || dataRetrieveThread.isDone()) { + retrievalQueue.clear(); + dataRetrieveThread = tableLoader; + dataRetrieveThread.start(); + } else { + retrievalQueue.add(tableLoader); + } + } + } + } + + /** + * Get the latest TableDataLoader and clear all previous loaders + * + * @return + */ + private FFMPTableDataLoader getLoader() { + synchronized (retrievalQueue) { + FFMPTableDataLoader loader = retrievalQueue.get(retrievalQueue.size() - 1); + retrievalQueue.clear(); + return loader; } } @@ -2071,11 +2097,10 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements Display.getDefault().asyncExec(new Runnable() { @Override public void run() { - allowNewTableUpdate = fupdateData.isAllowNewTableUpdate(); sourceUpdate = fupdateData.isSourceUpdate(); - if (fupdateData.getTableData() != null) { + if (fupdateData.getTableData() != null && sweet) { resetData(fupdateData.getTableData()); } @@ -2088,6 +2113,12 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements updateGapValueLabel(fupdateData.getGapValueLabel()); resetCursor(); + sweet = true; + + if (retrievalQueue.size() > 0) { + dataRetrieveThread = getLoader(); + dataRetrieveThread.start(); + } } }); } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/listeners/IFFMPMonitorListener.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/listeners/IFFMPMonitorListener.java deleted file mode 100644 index 65fc5b4fdc..0000000000 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/listeners/IFFMPMonitorListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.raytheon.uf.viz.monitor.ffmp.ui.listeners; - -import com.raytheon.uf.common.time.DataTime; - -public interface IFFMPMonitorListener { - - public void updateDialogTime(DataTime time); - -} diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataGenerator.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataGenerator.java index ae4aa8c0f9..da4b6b76ac 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataGenerator.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataGenerator.java @@ -950,8 +950,8 @@ public class FFMPDataGenerator { } if (qpeBasin != null) { qpe = qpeBasin.getAccumMaxValue(pfafs, monitor - .getQpeWindow().getAfterTime(), monitor - .getQpeWindow().getBeforeTime(), expirationTime, + .getQpeWindow().getBeforeTime(), monitor + .getQpeWindow().getAfterTime(), expirationTime, isRate); trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe)); @@ -1223,7 +1223,6 @@ public class FFMPDataGenerator { if (resource.isWorstCase() || (resource.centeredAggregationKey != null)) { // make sure that "ALL" is loaded huc = "ALL"; - rateRecord = monitor.getRateRecord(product, siteKey, dataKey, product.getRate(), resource.getPaintTime().getRefTime(), huc, true); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataLoader.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataLoader.java index f0cf2743a5..e1f96f3c3a 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataLoader.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPDataLoader.java @@ -19,7 +19,9 @@ **/ package com.raytheon.uf.viz.monitor.ffmp.ui.rsc; +import java.io.BufferedInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; @@ -35,11 +37,9 @@ import com.raytheon.uf.common.monitor.xml.ProductRunXML; import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.ohd.AppsDefaults; +import com.raytheon.uf.common.serialization.DynamicSerializationManager; +import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; import com.raytheon.uf.common.serialization.SerializationException; -import com.raytheon.uf.common.serialization.SerializationUtil; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.monitor.ffmp.FFMPMonitor; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig; @@ -64,8 +64,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPLoaderEvent; */ public class FFMPDataLoader extends Thread { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPDataLoader.class); + //private static final transient IUFStatusHandler statusHandler = UFStatus + // .getHandler(FFMPDataLoader.class); private String sharePath = null; @@ -101,7 +101,6 @@ public class FFMPDataLoader extends Thread { sharePath = AppsDefaults.getInstance().getToken("apps_dir") + File.separator + "ffmp" + File.separator; - //sharePath = "/awips2/edex/data/share/hydroapps/ffmp/"; this.product = resourceData.getProduct(); this.siteKey = resourceData.siteKey; @@ -206,7 +205,7 @@ public class FFMPDataLoader extends Thread { NavigableMap> iguidURIs = null; Date guidTime = timeBack; - + if (loadType == LOADER_TYPE.GENERAL) { guidTime = getMonitor().getPreviousQueryTime(siteKey, guidSource.getSourceName()); @@ -252,8 +251,7 @@ public class FFMPDataLoader extends Thread { isDone); FFMPBasinData qpeData = null; - if ((loadType == LOADER_TYPE.INITIAL) - || (loadType == LOADER_TYPE.SECONDARY)) { + if (loadType == LOADER_TYPE.INITIAL) { SourceXML source = getMonitor().getSourceConfig() .getSource(product.getQpe()); @@ -285,8 +283,7 @@ public class FFMPDataLoader extends Thread { fireLoaderEvent(loadType, "Processing "+product.getQpf(i) + "/" + phuc, isDone); FFMPBasinData qpfData = null; - if ((loadType == LOADER_TYPE.INITIAL) - || (loadType == LOADER_TYPE.SECONDARY)) { + if (loadType == LOADER_TYPE.INITIAL) { SourceXML source = getMonitor().getSourceConfig() .getSource(qpfSources.get(i)); @@ -341,8 +338,7 @@ public class FFMPDataLoader extends Thread { isDone); FFMPBasinData vgbData = null; - if ((loadType == LOADER_TYPE.INITIAL) - || (loadType == LOADER_TYPE.SECONDARY)) { + if (loadType == LOADER_TYPE.INITIAL) { SourceXML source = getMonitor().getSourceConfig() .getSource(product.getVirtual()); @@ -478,28 +474,67 @@ public class FFMPDataLoader extends Thread { String sourceName = source.getSourceName(); File file = new File(sharePath + wfo + File.separator + sourceName + "-" + siteKey + "-" + pdataKey + "-" + huc + ".bin"); - System.out.println("Buddy File path: " + file.getAbsolutePath()); + File lockFile = new File(sharePath + wfo + File.separator + sourceName + + "-" + siteKey + "-" + pdataKey + ".lock"); + + while (lockFile.exists()) { + for (int i = 0; i < 4; i++) { + try { + sleep(100); + i++; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + break; + } + System.out.println("Buddy File expected path: " + file.getAbsolutePath()); FFMPBasinData basinData = null; if (file.exists()) { System.out.println("Last mod: " + new Date(file.lastModified())); - //System.out.println("6 hour mod: " + new Date((System.currentTimeMillis() - (6 * 1000 * 3600)))); - //System.out.println("DIFF: "+(file.lastModified() - (System.currentTimeMillis() - (6 * 1000 * 3600)))); if (file.lastModified() > (System.currentTimeMillis() - (6 * 1000 * 3600))) { - - System.out.println("Buddy File path: " + file.getName()); + + while (lockFile.exists()) { + for (int i = 0; i < 4; i++) { + try { + System.out.println("Waiting for new file: " + file.getAbsolutePath()); + sleep(100); + i++; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + break; + } + + BufferedInputStream is = null; try { - basinData = (FFMPBasinData) SerializationUtil - .transformFromThrift(FileUtil.file2bytes(file, - false)); + + System.out.println("Loading file: " + file.getName()); + is = new BufferedInputStream( + new FileInputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + basinData = (FFMPBasinData) dsm.deserialize(is); } catch (SerializationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } } } 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 96098d006c..e5e565d4c3 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 @@ -73,10 +73,8 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.monitor.config.FFFGDataMgr; -import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager; import com.raytheon.uf.common.monitor.xml.DomainXML; -import com.raytheon.uf.common.monitor.xml.ProductRunXML; import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -236,7 +234,7 @@ public class FFMPResource extends // time used by the resource private DataTime paintTime = null; - + /** mouse handler **/ private final IInputHandler inspectAdapter = new InputAdapter() { @@ -409,6 +407,7 @@ public class FFMPResource extends FFFGDataMgr.getUpdatedInstance(); PluginDataObject[] pdos = (PluginDataObject[]) object; FFMPRecord ffmpRec = (FFMPRecord) pdos[pdos.length - 1]; + // only care about the most recent one try { if (ffmpRec.getSourceName() @@ -432,23 +431,35 @@ public class FFMPResource extends + previousMostRecentTime + " New: " + ffmpRec.getDataTime().getRefTime()); - if (getResourceData().tableLoad) { + if (getResourceData().tableLoad) { - startLoader(previousMostRecentTime, ffmpRec - .getDataTime().getRefTime(), - LOADER_TYPE.GENERAL); + if (loader == null) { + startLoader(previousMostRecentTime, ffmpRec + .getDataTime().getRefTime(), + LOADER_TYPE.GENERAL); + } else { + while (!loader.isDone) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + startLoader(previousMostRecentTime, ffmpRec + .getDataTime().getRefTime(), + LOADER_TYPE.GENERAL); + } - while (!loader.isDone) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + while (!loader.isDone) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - setTableTime(); - purge(ffmpRec.getDataTime().getRefTime()); - } + purge(ffmpRec.getDataTime().getRefTime()); + } qpeRecord = null; isNewQpe = true; @@ -463,19 +474,17 @@ public class FFMPResource extends isNewQpf = true; } - if (getResourceData().tableLoad) { - - isFirst = true; - allowNewTableUpdate(); - monitor.updateDialog(this); - } - } catch (VizException ve) { statusHandler.handle(Priority.PROBLEM, "Error updating record", ve); } } - + + if (getResourceData().tableLoad) { + allowNewTableUpdate(); + isFirst = true; + } + refresh(); } @@ -579,7 +588,7 @@ public class FFMPResource extends return getColorUtil().colorByValue(value); } else { if (getCenteredAggregatePfafs().contains(key) && isParent()) { - + // this is for a reason } else { if (!isMaintainLayer() && isParent()) { return getColorUtil().colorByValue(value); @@ -652,8 +661,8 @@ public class FFMPResource extends value = getQpeRecord().getBasinData("ALL") .getAccumMaxValue( pfafs, - getTableTime(), recentTime, + getTableTime(), getQpeSourceExpiration(), getResourceData().getPrimarySourceXML() .isRate()); @@ -683,7 +692,9 @@ public class FFMPResource extends pfafs); break; } - case RATE:// fall through + case RATE: + value = getBasin(key, field, recentTime, aggregate).getValue(recentTime); + break; case QPF: { value = getBasin(key, field, recentTime, aggregate) .getAverageValue(recentTime, getQpfSourceExpiration()); @@ -780,7 +791,13 @@ public class FFMPResource extends sfield = FFMPRecord.FIELDS.QPE; } - PluginDataObject pdo = getRecord(sfield, paintTime.getRefTime()); + PluginDataObject pdo = null; + + try { + pdo = getRecord(sfield, paintTime.getRefTime()); + } catch (NullPointerException npe) { + return "No Data Available"; + } if (pdo == null) { return "No Data Available"; @@ -817,9 +834,9 @@ public class FFMPResource extends /** * Gets the record currently used * - * @return FFMPRecord + * @return FFMPCacheRecord */ - public FFMPRecord getRateRecord(Date recentTime) { + public FFMPCacheRecord getRateRecord(Date recentTime) { if ((rateRecord == null) && isNewRate) { try { @@ -847,9 +864,9 @@ public class FFMPResource extends /** * Gets the record currently used * - * @return FFMPRecord + * @return FFMPCacheRecord */ - public FFMPRecord getQpeRecord() { + public FFMPCacheRecord getQpeRecord() { try { if ((qpeRecord == null) && (getTableTime() != null) && isNewQpe) { @@ -876,9 +893,9 @@ public class FFMPResource extends /** * Gets the record currently used * - * @return FFMPRecord + * @return FFMPCacheRecord */ - public FFMPRecord getGuidanceRecord() { + public FFMPCacheRecord getGuidanceRecord() { try { if ((guidRecord == null) || isNewGuid) { Date date = null; @@ -915,9 +932,9 @@ public class FFMPResource extends /** * Gets the record currently used * - * @return FFMPRecord + * @return FFMPReFFMPCacheRecordcord */ - public FFMPRecord getQpfRecord(Date recentTime) { + public FFMPCacheRecord getQpfRecord(Date recentTime) { try { if ((qpfRecord == null) && isNewQpf) { Date date = null; @@ -951,9 +968,9 @@ public class FFMPResource extends /** * Gets the record currently used * - * @return FFMPRecord + * @return FFMPCacheRecord */ - public FFMPRecord getVirtualRecord() { + public FFMPCacheRecord getVirtualRecord() { try { if ((virtualRecord == null) && isNewVirtual) { virtualRecord = monitor.getVirtualRecord(getProduct(), @@ -973,9 +990,9 @@ public class FFMPResource extends * General get record call * * @param pfield - * @return FFMPRecord + * @return FFMPCacheRecord */ - public FFMPRecord getRecord(FIELDS pfield, Date recentTime) { + public FFMPCacheRecord getRecord(FIELDS pfield, Date recentTime) { if (pfield == FIELDS.GUIDANCE) { return getGuidanceRecord(); } else if (pfield == FIELDS.RATIO) { @@ -1174,10 +1191,11 @@ public class FFMPResource extends if (getResourceData().tableLoad && !paintTime.getRefTime().equals(getMostRecentTime())) { - setMostRecentTime(paintTime.getRefTime()); setTableTime(); - monitor.updateDialog(this); + if (isLinkToFrame) { + updateDialog(); + } } } else { if (getResourceData().getMonitor().ffmpSplash != null) { @@ -1469,6 +1487,20 @@ public class FFMPResource extends shadedShapes.clear(); } + if (streamShadedShape != null) { + streamShadedShape.dispose(); + streamShadedShape = null; + } + if (streamOutlineShape != null) { + streamOutlineShape.dispose(); + streamOutlineShape = null; + } + + if (smallBasinOverlayShape != null) { + smallBasinOverlayShape.dispose(); + smallBasinOverlayShape = null; + } + setQuery(true); refresh(); } @@ -1731,12 +1763,12 @@ public class FFMPResource extends if (getResourceData().tableLoad) { if (isUpdateDialog) { - monitor.updateDialog(this); + updateDialog(); } // stops the annoying wait cursor every time you re-center if (getHuc().equals("ALL") - && (lowestCenter == FFMPRecord.ZOOM.BASIN)) { + || (lowestCenter == FFMPRecord.ZOOM.BASIN)) { basinTableDlg.getShell().setCursor(null); } } @@ -2242,9 +2274,9 @@ public class FFMPResource extends * @param value */ private void addWorstCase(Long aggPfaf, Date recentTime, Float value) { - if (drawables.get(new DataTime(recentTime)) != null) { - drawables.get(new DataTime(recentTime)).worstCaseHash.put(aggPfaf, - value); + FFMPDrawable drawable = drawables.get(new DataTime(recentTime)); + if (drawable != null && drawable.worstCaseHash != null) { + drawable.worstCaseHash.put(aggPfaf, value); } } @@ -2535,7 +2567,6 @@ public class FFMPResource extends } else { // center selected, determine center key if (!phuc.equals("ALL")) { - if (centeredAggregationKey instanceof String) { if (lowestCenter != ZOOM.BASIN) { @@ -2546,6 +2577,10 @@ public class FFMPResource extends } else { centeredAggr = (Long) drawable .getCenterAggrKey(); + // this is a fall back for VGB's + if (centeredAggr == null) { + centeredAggr = templates.findAggregatedVGB((String) centeredAggregationKey, getSiteKey(), phuc); + } } } else { @@ -2554,6 +2589,9 @@ public class FFMPResource extends } else { centeredAggr = (Long) drawable .getCenterAggrKey(); + if (centeredAggr == null) { + centeredAggr = templates.getAggregatedPfaf((Long)centeredAggregationKey, getSiteKey(), phuc); + } } } @@ -2782,6 +2820,11 @@ public class FFMPResource extends // check whether or not the dialog needs to be dumped monitor.splashDisposeAndDataLoad(getResource()); + + if (getResourceData().tableLoad && isFirst) { + isFirst = false; + updateDialog(); + } } }); @@ -3112,6 +3155,7 @@ public class FFMPResource extends } refresh(); + updateDialog(); } @@ -3796,7 +3840,7 @@ public class FFMPResource extends long fips = monitor.getTemplates(getSiteKey()).getCountyFipsByPfaf( basin.getPfaf()); basin.setCountyFips(fips); - + if (getResourceData().tableLoad) { // interpolating if (getGuidanceInterpolation(guidType).isInterpolate()) { @@ -4235,7 +4279,7 @@ public class FFMPResource extends if (status.getLoaderType() == LOADER_TYPE.SECONDARY) { if (status.isDone() && !this.getResourceData().isTertiaryLoad) { try { - Date startDate = new Date(getMostRecentTime().getTime() - 12 * 3600 * 1000); + Date startDate = new Date(getMostRecentTime().getTime() - (6 * 3600 * 1000)); FFMPMonitor.getInstance().startLoad(this, startDate, LOADER_TYPE.TERTIARY); } catch (VizException e) { diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResourceData.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResourceData.java index 3f6145738a..48aa91bf4b 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResourceData.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResourceData.java @@ -40,7 +40,6 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE; -import com.raytheon.uf.common.monitor.config.FFMPTemplateConfigurationManager; import com.raytheon.uf.common.monitor.xml.DomainXML; import com.raytheon.uf.common.monitor.xml.ProductRunXML; import com.raytheon.uf.common.monitor.xml.ProductXML; @@ -230,18 +229,39 @@ public class FFMPResourceData extends AbstractRequestableResourceData { this.timeBack = new Date( (long) (mostRecentTime.getRefTime().getTime() - (cfgBasinXML .getTimeFrame() * 3600 * 1000))); - ArrayList hucsToLoad = FFMPTemplateConfigurationManager.getInstance().getHucLevels(); + ArrayList hucsToLoad = monitor.getTemplates(siteKey).getTemplateMgr().getHucLevels(); + //ArrayList hucsToLoad = new ArrayList(); + //hucsToLoad.add(cfgBasinXML.getLayer()); + //hucsToLoad.add("ALL"); // goes back X hours and pre populates the Data Hashes FFMPDataLoader loader = new FFMPDataLoader(this, timeBack, mostRecentTime.getRefTime(), LOADER_TYPE.INITIAL, hucsToLoad); loader.start(); + int i = 0; + // make the table load wait for finish of initial data load + while (!loader.isDone) { + try { + // give it 120 or so seconds + if (i > 4000) { + statusHandler + .handle(Priority.WARN, + "Didn't load initial data in allotted time, releasing table"); + break; + } + Thread.sleep(30); + i++; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } else { SourceXML source = getPrimarySourceXML(); this.domains = monitor.getRunConfig().getDomains(); - + for (int i = 0; i < objects.length; i++) { FFMPRecord rec = (FFMPRecord) objects[i]; rec.setExpiration(source.getExpirationMinutes(siteKey)); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java index 7aba78010f..1d80cf92f8 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java @@ -49,7 +49,7 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpBasinTableDlg; * @version 1.0 */ -public class FFMPTableDataLoader implements Runnable { +public class FFMPTableDataLoader extends Thread { private IMonitorEvent fme = null; @@ -64,6 +64,8 @@ public class FFMPTableDataLoader implements Runnable { private Date date = null; private FfmpBasinTableDlg callback = null; + + private boolean isDone = false; private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(FFMPTableDataLoader.class); @@ -96,7 +98,6 @@ public class FFMPTableDataLoader implements Runnable { public void run() { if (fme.getSource() instanceof FFMPMonitor) { - FFMPTableDataUpdate tableDataUpdate = new FFMPTableDataUpdate(); FFMPMonitor ffmp = (FFMPMonitor) fme.getSource(); @@ -109,12 +110,12 @@ public class FFMPTableDataLoader implements Runnable { FFMPTableData tData = null; - try { - - FFMPDrawable drawable = resource.getDrawable(resource - .getPaintTime()); - - if ((drawable != null) + try { + + FFMPDrawable drawable = resource.getDrawable(resource + .getPaintTime()); + + if ((drawable != null) && (drawable.getDrawTime() == resource .getTime())) { String iHuc = null; @@ -124,8 +125,7 @@ public class FFMPTableDataLoader implements Runnable { iHuc = "ALL"; } if (drawable.getTableData(iHuc) != null) { - - //System.out.println(" Cache HITTTTTTTTT!!!!!"); +// System.out.println(" Cache HITTTTTTTTT!!!!!"); tData = drawable.getTableData(iHuc); } } @@ -140,8 +140,8 @@ public class FFMPTableDataLoader implements Runnable { iHuc = "ALL"; } - //System.out - // .println(" Cache MISSSSSSSSSSSS!!!!!"); +// System.out +// .println(" Cache MISSSSSSSSSSSS!!!!!"); FFMPDataGenerator dg = new FFMPDataGenerator( ffmp, resource); tData = dg.generateFFMPData(); @@ -174,8 +174,7 @@ public class FFMPTableDataLoader implements Runnable { tableDataUpdate.setFireGraph(true); tableDataUpdate.setGraphPfaf(basinTrendDlg .getPfaf()); - tableDataUpdate.setGraphTime(resource - .getTableTime()); + tableDataUpdate.setGraphTime(resource.getMostRecentTime()); } sourceUpdate = false; @@ -204,8 +203,14 @@ public class FFMPTableDataLoader implements Runnable { tableDataUpdate.setGapValueLabel(gapVal); tableDataUpdate.setAllowNewTableUpdate(allowNewTableUpdate); tableDataUpdate.setSourceUpdate(sourceUpdate); + + isDone = true; callback.tableDataUpdateComplete(tableDataUpdate); } } + + public boolean isDone() { + return isDone; + } } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java old mode 100755 new mode 100644 index b909d29196..247f812f67 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java @@ -212,6 +212,8 @@ import com.raytheon.viz.texteditor.msgs.IAviationObserver; * 06/27/2011 9940 rferrel sendTafToEditor now loads just the latest TAF. * 08/12/2011 10612 rferrel saveFile will now always push file back to the server. * 11/29/2011 11612 rferrel Added getViewerTabList. + * 20JUL2012 14570 gzhang/zhao Highlight correct time groups in TAF Viewer + * * * * @author lvenable @@ -3643,7 +3645,7 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, sb.append(TafUtil.safeFormatTaf(t, showHeaders)); sb.append("\n"); } - } + }//System.out.println("TEMPO "+sb.toString().indexOf("TEMPO")+"/"+sb.toString().indexOf("\n",72)); tafViewerStTxt.setText(sb.toString()); hightlightTAF(); @@ -3672,50 +3674,93 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, } ResourceConfigMgr configMgr = ResourceConfigMgr.getInstance(); - String taf = tafViewerStTxt.getText(); + String taf = tafViewerStTxt.getText(); int offset = taf.indexOf("TAF"); - try { int end = taf.indexOf("TAF", offset + 3); if (end > 0) { taf = taf.substring(offset, end); } else { taf = taf.substring(offset); - } + } } catch (IndexOutOfBoundsException ex) { // Assume no TAF in the viewer return; } + + Map alertTimeMap=TafMonitorDlg.getCurrentAlertTimeMap(stationName);// DR 14570 + + // 20120712 for TEMPO + String TEMPO_TXT = "TEMPO"; + + if(taf.contains(TEMPO_TXT)){ + + Map tempoMap = TafMonitorDlg.getCurrentTempoMap(stationName);//20120711 + if(tempoMap != null){ + int tempoStart = taf.indexOf(TEMPO_TXT); + int tempoEnd = taf.indexOf(TafUtil.LINE_BREAK, tempoStart);//end of the TEMPO line + + StringBuilder str = new StringBuilder(" "); + + for (String alertKey : tempoMap.keySet()) { + //System.out.println("2___alertKey: "+ alertKey); + for (String value : tempoMap.get(alertKey)) { + System.out.println("3___value: "+ value); + str.setLength(1); + str.append(value); + int len = str.length(); + str.append(" "); + + int startIndex = taf.indexOf(str.toString(),tempoStart);// for tempo only + + if (startIndex < 0) { + str.setLength(len); + str.append("\n"); + startIndex = taf.indexOf(str.toString()); + } + if (startIndex >= 0 /*within tempo line*/&& startIndex= 0 /*within the same line*/&& startIndex < endIndex) { + StyleRange sr = new StyleRange(offset + startIndex + 1, + len - 1, null, configMgr.getViwerAlertColor()); - if (startIndex >= 0) { - StyleRange sr = new StyleRange(offset + startIndex + 1, - len - 1, null, configMgr.getViwerAlertColor()); + tafViewerStTxt.setStyleRange(sr); + } else { + // Should not get here. The first TAF in the viewer and the + // values in the alertMap should both be from the latest + // TAF. This indicates a program bug. + System.out.println("highlightTAF unable to find: \"" + + str.toString() + "\" in the first TAF"); + } - tafViewerStTxt.setStyleRange(sr); - } else { - // Should not get here. The first TAF in the viewer and the - // values in the alertMap should both be from the latest - // TAF. This indicates a program bug. - System.out.println("highlightTAF unable to find: \"" - + str.toString() + "\" in the first TAF"); - } - - } + } } } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java index 0e20bfdb5c..ab01929c16 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java @@ -63,6 +63,7 @@ import com.raytheon.viz.aviation.resource.ResourceConfigMgr.ResourceTag; * and set default value for check hours. * 04/28/2011 8065 rferrel Add flag to indicate display is current * and implement data caching + * 20JUL2012 14570 gzhang/zhao Added "tempo" to alertMap * * * @@ -126,6 +127,7 @@ public class MetarViewer extends ViewerTab implements */ private static final HashMap alertMap = new HashMap(); static { + alertMap.put("tempo", new String[] { "", "", "", "", "", "", "", "" }); // 14570 alertMap.put("vsby", new String[] { "", "" }); alertMap.put("wind", new String[] { "", "" }); alertMap.put("wx", new String[] { "", "" }); diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java index bc4d32c6e9..ad6f475855 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java @@ -62,6 +62,7 @@ import com.raytheon.viz.aviation.xml.MonitorCfg; * Nov 4, 2010 6866 rferrel Impact statements no longer malformed. * May 13, 2011 8611 rferrel Added type to help determine blink state. * Apr 30, 2012 14717 zhao Indicators turn gray when Metar is outdated + * 20JUL2012 14570 gzhang/zhao Modified for highlighting correct time groups in TAF Viewer * * * @@ -125,6 +126,7 @@ public class SiteMonitor implements IRequestCompleteListener> { */ private static final Map ALERT_KEY_MAP = new HashMap(); { + ALERT_KEY_MAP.put("tempo", new String[] { "wind", "vsby", "pcp", "obv", "vcnty", "sky" } ); // 14570 ALERT_KEY_MAP.put("vsby", new String[] { "vsby" }); ALERT_KEY_MAP.put("wind", new String[] { "wind" }); ALERT_KEY_MAP.put("wx", new String[] { "pcp", "obv", "vcnty" }); @@ -139,12 +141,13 @@ public class SiteMonitor implements IRequestCompleteListener> { * @param stationName */ public SiteMonitor(Composite parent, TafSiteComp parentSiteComp, - MonitorCfg config, Map alertMap) { + MonitorCfg config, Map alertMap, Map alertTimeMap/* DR 14570 */,Map tempoMap) { this.parent = parent; this.parentSiteComp = parentSiteComp; this.cfg = config; this.alertMap = alertMap; - + this.tempoMap = tempoMap;//20120711 + this.alertTimeMap = alertTimeMap;// DR 14570 monitorItems = StringUtil.split(cfg.getMonitorItems(), ","); initMonitorLabels(cfg.getMonitorLabels()); @@ -446,7 +449,9 @@ public class SiteMonitor implements IRequestCompleteListener> { if (severity > maxSeverity) { maxSeverity = severity; } - +// if ( severity >= 2 ) { +// System.out.println("0***key/severity: "+key.toString()+" / "+severity); +// } String msg = (String) valueMap.get("msg"); /** @@ -526,17 +531,64 @@ public class SiteMonitor implements IRequestCompleteListener> { ArrayList> group = (ArrayList>) dcd .get("group"); Map oncl = group.get(0); - Map obs = (Map) oncl.get("prev"); + Map obs = (Map) oncl.get("prev"); ArrayList alertValues = new ArrayList(); + + Map tempo=null;//20120711 + ArrayList tempoAlertValues = new ArrayList();//20120711 + // DR 14570: based on A1 Python code in TafViewer.highlight() + long tsys= SimulatedTime.getSystemTime().getTime().getTime(); + long tfrom= ((Float)((Map)((Map)oncl.get("prev")).get("time")).get("from")).longValue()*1000; + long time = tsys>tfrom ? tsys : tfrom; + long tto = 0; - for (String tafKey : tafKeys) { - Map alert = (Map) obs.get(tafKey); - if (alert != null) { - String value = (String) alert.get("str"); - alertValues.add(value); - } + for(Map map : group){ + //for( Object o : map.keySet())System.out.println("^^^^^^^^^^^^ map keys: "+(String)o); + tto = ((Float)((Map)((Map)map.get("prev")).get("time")).get("to")).longValue()*1000; + //System.out.println("---1---time/tto: "+new java.util.Date(time)+" / "+new java.util.Date(tto)+" key: "+key.toString()); + if(time < tto){ + + + + //20120711: see A1 TafViewer.py's highlight(), should be outside the if(severity >= 2) block? + + //System.out.println("1+++map.keySet().contains(oncl): "+new Boolean(map.keySet().contains("oncl"))); + String[] keyArray = map.keySet().toArray(new String[]{});//for TEMPO highlight + for(String s : keyArray){ + if(s.equals("ocnl")){ + long oFrom=((Float)((Map)((Map)map.get("ocnl")).get("time")).get("from")).longValue()*1000; + long oTo=((Float)((Map)((Map)map.get("ocnl")).get("time")).get("to")).longValue()*1000; + + //System.out.println("2+++oFrom**time**oTo: "+oFrom+"**"+time+"**"+oTo); + + if(oFrom<=time && time) map.get("ocnl"); + } + } + + obs = (Map) map.get("prev"); //System.out.println("______2___time/tto: "+new java.util.Date(time)+" / "+new java.util.Date(tto)+" key: "+key.toString()); + break; + } } + Map obsTimeMap = (Map) obs.get("time");//for getting correct line using time + + for (String tafKey : tafKeys) { + // DR 14570 20120711 + Map tempoAlert = (tempo==null) ? null:(Map)tempo.get(tafKey); + //System.out.println("tempo==null***tempoAlert != null: "+new Boolean(tempo==null)+"***"+new Boolean(tempoAlert != null)); + if(tempoAlert != null){ + tempoAlertValues.add((String)tempoAlert.get("str")); + //System.out.println("(String)tempoAlert.get(str): "+(String)tempoAlert.get("str")); + }// END 20120711 + Map alert = (Map) obs.get(tafKey); + if (alert != null) { + String value = (String) alert.get("str"); + alertValues.add(value); + } + } //System.out.println("________3___obsTimeMap: "+(String)obsTimeMap.get("str")); + tempoMap.put((String)key, tempoAlertValues.toArray(new String[tempoAlertValues.size()]));//20120711 + if(alertTimeMap!=null) alertTimeMap.put((String)key, (String)obsTimeMap.get("str"));// DR 14570 String[] s = new String[alertValues.size()]; alertMap.put((String) key, alertValues.toArray(s)); } @@ -643,4 +695,13 @@ public class SiteMonitor implements IRequestCompleteListener> { public Color getGraySeverityColor() { return getSeverityColors()[GRAY_COLOR_SEVERITY]; } + + + //----------------------DR 14570: + + private Map alertTimeMap;// = new HashMap(); + public Map tempoMap;// = new HashMap(); + public void setAlertTimeMap(Map map){ + alertTimeMap = map; + } } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafSiteComp.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafSiteComp.java old mode 100755 new mode 100644 index 219fe6d9b7..8f5bbf5c7e --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafSiteComp.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafSiteComp.java @@ -90,6 +90,7 @@ import com.raytheon.viz.avnconfig.IStatusSettable; * 05/13/2011 8611 rferrel Added type to Site Monitor requests and update * Viewer when a METAR changes alert status. * 04/26/2012 14717 zhao Indicator labels turn gray when Metar is outdated + * 20JUL2012 14570 gzhang/zhao Add data structure for highlighting correct time groups in TAF viewer * * * @@ -383,14 +384,15 @@ public class TafSiteComp { monitorArray = new ArrayList(); alertMap = new HashMap(); ArrayList monitorCfgs = tafMonCfg.getMonitorCfgs(); - + alertTimeMap = new HashMap();/* DR 14570 */ + tempoMap = new HashMap();//20120711 for (MonitorCfg monCfg : monitorCfgs) { SiteMonitor monitor = null; if ("MetarMonitor".equals(monCfg.getClassName())) { - monitor = new SiteMonitor(parent, this, monCfg, alertMap); - metarMontiorIndex = monitorArray.size(); + monitor = new SiteMonitor(parent, this, monCfg, alertMap, /* DR 14570 */alertTimeMap,tempoMap); + metarMontiorIndex = monitorArray.size(); } else { - monitor = new SiteMonitor(parent, this, monCfg, null); + monitor = new SiteMonitor(parent, this, monCfg, null, /* DR 14570 */null,null); } monitorArray.add(monitor); } @@ -652,7 +654,7 @@ public class TafSiteComp { long currentTime = SimulatedTime.getSystemTime().getTime() .getTime(); - if ( currentTime > ( metarTime + METAR_TIMEOUT_4HR10MIN ) ) { + if ( currentTime > ( metarTime + METAR_TIMEOUT_4HR10MIN ) ) { mtrTimeLbl.setText("None"); mtrTimeLbl.setBackground(getBackgroundColor()); if ( persistMonitorProcessedFirst ) { @@ -815,7 +817,7 @@ public class TafSiteComp { public void setPersistMonitorProcessedFirst(boolean b) { persistMonitorProcessedFirst = b; } - + public void setLatestMtrTime(long latestMtrTime) { this.latestMtrTime = latestMtrTime; } @@ -823,4 +825,10 @@ public class TafSiteComp { public long getLatestMtrTime() { return latestMtrTime; } + + //------------------------------- DR 14570: + private Map tempoMap = null;//20120711 + private Map alertTimeMap = null; + public Map getAlertTimeMap(){ return alertTimeMap;} + public Map getTempoMap(){return tempoMap;}//20120711 } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/TafMonitorDlg.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/TafMonitorDlg.java index 57a4d37123..77186428b0 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/TafMonitorDlg.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/TafMonitorDlg.java @@ -128,6 +128,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 10/27/2010 7383 rferrel Save changed blink state in configMgr. * 3/14/2011 8588 rferrel Allow monitoring multiple products. * 11/29/2011 11612 rferrel Added observers to update viewer tabs. + * 20JUL2012 14570 gzhang/zhao Added methods for highlighting in TAF viewer * * * @@ -917,4 +918,38 @@ public class TafMonitorDlg extends CaveSWTDialog { public final List getViewerTabList() { return tveDlg.getViewerTabList(); } + + //------------------------- DR 14570: + + public static Map getCurrentAlertTimeMap(String siteID){ + Map alertTimeMap = null; + if (currentDlg != null) { + if (currentDlg.getDisplay().isDisposed()) { + currentDlg = null; + } else { + for (TafSiteComp siteRow : currentDlg.getTafSiteComps()) { + if (siteRow.getStationName().equals(siteID)) { + alertTimeMap = siteRow.getAlertTimeMap(); + } + } + } + } + return alertTimeMap; + } + //20120711 + public static Map getCurrentTempoMap(String siteID){ + Map tempoMap = null; + if (currentDlg != null) { + if (currentDlg.getDisplay().isDisposed()) { + currentDlg = null; + } else { + for (TafSiteComp siteRow : currentDlg.getTafSiteComps()) { + if (siteRow.getStationName().equals(siteID)) { + tempoMap= siteRow.getTempoMap(); + } + } + } + } + return tempoMap; + } } diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/ContourSupport.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/ContourSupport.java index 2c7aeb6cad..2d503e9b04 100644 --- a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/ContourSupport.java +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/ContourSupport.java @@ -85,6 +85,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 26, 2009 #2172 chammack Use zoomLevel to calculate label spacing * Apr 26, 2010 #4583 rjpeter Replaced fortran fortconbuf with java port. * Mar 4, 2011 #7747 njensen Cached subgrid envelopes + * Jul 9, 2012 DR 14940 M. Porricelli Adjust arrow size for streamlines * * * @author chammack @@ -1125,7 +1126,12 @@ public class ContourSupport { } double gridPixelSize = offCenter[0] - center[0]; + double gridPixelMax = 2000.; + // If gridPixelSize is large, arrows on streamline will be too small, so adjust here + if(gridPixelSize > gridPixelMax) { + gridPixelSize = gridPixelSize/5; + } float arrowSize = (float) (currentMagnification * 5 / zoom / gridPixelSize); double spadiv = zoom * density * gridPixelSize / 25; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java index 5cfcbef830..46468d8a97 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java @@ -38,6 +38,7 @@ import com.raytheon.viz.gfe.core.msgs.IParmInventoryChangedListener; import com.raytheon.viz.gfe.core.msgs.IParmListChangedListener; import com.raytheon.viz.gfe.core.msgs.ISystemTimeRangeChangedListener; import com.raytheon.viz.gfe.core.parm.Parm; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModuleJobPool; /** * Placeholder for ParmManager interface @@ -47,6 +48,7 @@ import com.raytheon.viz.gfe.core.parm.Parm; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 01/28/2008 chammack Initial creation of skeleton. + * 06/25/2012 #766 dgilling Added getVCModulePool(). * * * @@ -570,4 +572,6 @@ public interface IParmManager extends IParmInventoryChangedListener, public ParmID fromExpression(String parmName); public JobPool getNotificationPool(); + + public VCModuleJobPool getVCModulePool(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java index 27fedb138d..09330252a8 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java @@ -75,6 +75,7 @@ import com.raytheon.viz.gfe.core.msgs.ShowISCGridsMsg; import com.raytheon.viz.gfe.core.parm.ABVParmID; import com.raytheon.viz.gfe.core.parm.Parm; import com.raytheon.viz.gfe.core.parm.vcparm.VCModule; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModuleJobPool; /** * Implements common parm manager functionality shared between concrete and mock @@ -93,6 +94,8 @@ import com.raytheon.viz.gfe.core.parm.vcparm.VCModule; * 03/01/2012 #354 dgilling Modify setParms to always load (but not * necessarily display) the ISC parms that * correspond to a visible mutable parm. + * 06/25/2012 #766 dgilling Move to a shared thread pool for VCModule + * execution. * * * @@ -247,6 +250,8 @@ public abstract class AbstractParmManager implements IParmManager { private JobPool notificationPool; + private VCModuleJobPool vcModulePool; + protected AbstractParmManager(final DataManager dataManager) { this.dataManager = dataManager; this.parms = new RWLArrayList(); @@ -261,6 +266,8 @@ public abstract class AbstractParmManager implements IParmManager { // Get virtual parm definitions vcModules = initVirtualCalcParmDefinitions(); + vcModulePool = new VCModuleJobPool("GFE Virtual ISC Python executor", + this.dataManager, vcModules.size(), Boolean.TRUE); PythonPreferenceStore prefs = Activator.getDefault() .getPreferenceStore(); @@ -437,11 +444,12 @@ public abstract class AbstractParmManager implements IParmManager { parms.releaseReadLock(); } + notificationPool.cancel(); + + vcModulePool.cancel(); for (VCModule module : vcModules) { module.dispose(); } - - notificationPool.cancel(); } protected DatabaseID decodeDbString(final String string) { @@ -2084,4 +2092,9 @@ public abstract class AbstractParmManager implements IParmManager { public JobPool getNotificationPool() { return notificationPool; } + + @Override + public VCModuleJobPool getVCModulePool() { + return vcModulePool; + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/GFESpatialDisplayManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/GFESpatialDisplayManager.java index fb61ad3ea1..1fab7da2db 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/GFESpatialDisplayManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/GFESpatialDisplayManager.java @@ -94,6 +94,7 @@ public class GFESpatialDisplayManager extends AbstractSpatialDisplayManager private static final String GFE_PERSPECTIVE = GFEPerspective.ID_PERSPECTIVE; private final ISampleSetChangedListener sampleSetListener = new ISampleSetChangedListener() { + @Override public void sampleSetChanged(ISampleSetManager sampleSetMgr) { GFESpatialDisplayManager.this.refresh(); } @@ -163,14 +164,40 @@ public class GFESpatialDisplayManager extends AbstractSpatialDisplayManager GridLocation gloc = parmManager.compositeGridLocation(); GridGeometry2D gridGeometry = MapUtil.getGridGeometry(gloc); Envelope envelope = gridGeometry.getEnvelope(); - double dx = (envelope.getSpan(0) / 8.0); - double dy = (envelope.getSpan(1) / 8.0); + double colorBarHeight = GFEColorbarResource.HEIGHT + * envelope.getSpan(1) / pane.getBounds().height; + + PythonPreferenceStore prefs = Activator.getDefault() + .getPreferenceStore(); + + double expandLeft = 10; + if (prefs.contains("OfficeDomain_expandLeft")) { + expandLeft = prefs.getDouble("OfficeDomain_expandLeft"); + } + double expandRight = 0.1; + if (prefs.contains("OfficeDomain_expandRight")) { + expandRight = prefs.getDouble("OfficeDomain_expandRight"); + } + double expandTop = 0.1; + if (prefs.contains("OfficeDomain_expandTop")) { + expandTop = prefs.getDouble("OfficeDomain_expandTop"); + } + double expandBottom = 0.1; + if (prefs.contains("OfficeDomain_expandBottom")) { + expandBottom = prefs.getDouble("OfficeDomain_expandBottom"); + } + + double dxLeft = (envelope.getSpan(0) * expandLeft / 100.0); + double dxRight = (envelope.getSpan(0) * expandRight / 100.0); + double dyTop = (envelope.getSpan(1) * expandTop / 100.0); + double dyBottom = (envelope.getSpan(1) * expandBottom / 100.0); + GeneralEnvelope newEnvelope = new GeneralEnvelope( envelope.getCoordinateReferenceSystem()); - newEnvelope.setRange(0, envelope.getMinimum(0) - dx, - envelope.getMaximum(0) + dx); - newEnvelope.setRange(1, envelope.getMinimum(1) - dy, - envelope.getMaximum(1) + dy); + newEnvelope.setRange(0, envelope.getMinimum(0) - dxLeft, + envelope.getMaximum(0) + dxRight); + newEnvelope.setRange(1, envelope.getMinimum(1) - dyBottom, + envelope.getMaximum(1) + colorBarHeight + dyTop); GridGeometry2D newGridGeometry = new GridGeometry2D( gridGeometry.getGridRange(), newEnvelope); descriptor.setGridGeometry(newGridGeometry); @@ -323,6 +350,7 @@ public class GFESpatialDisplayManager extends AbstractSpatialDisplayManager * com.raytheon.viz.gfe.core.ISpatialDisplayManager#setGlobalTimeRange(com * .raytheon.edex.plugin.time.TimeRange) */ + @Override public void setGlobalTimeRange(TimeRange timeRange) { this.globalTimeRange = timeRange; @@ -337,6 +365,7 @@ public class GFESpatialDisplayManager extends AbstractSpatialDisplayManager * @see * com.raytheon.viz.gfe.core.ISpatialDisplayManager#getGlobalTimeRange() */ + @Override public TimeRange getGlobalTimeRange() { return this.globalTimeRange; } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java index 1b16042b98..6bb9008366 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java @@ -71,6 +71,8 @@ import com.raytheon.viz.gfe.types.MutableInteger; * 08/19/09 2547 rjpeter Implement Test/Prac database display. * 02/23/12 #346 dgilling Call Parm's dispose method when removing * a Parm. + * 06/25/12 #766 dgilling Fix NullPointerException from VCModules + * when running in practice mode. * * * @author bphillip @@ -437,6 +439,12 @@ public class ParmManager extends AbstractParmManager { @Override public ParmID[] getAvailableParms(DatabaseID dbID) { + // a derivation from AWIPS1: + // short-circuit the checks and just return an empty array back + // if we have an invalid DatabaseID + if ((dbID == null) || (!dbID.isValid())) { + return new ParmID[0]; + } // Check the cache List cacheParmIDs = null; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java index 6a826d7206..71cf6c9270 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java @@ -67,6 +67,9 @@ import com.raytheon.viz.gfe.core.parm.vcparm.VCModule.VCInventory; * Mar 02, 2012 #346 dgilling Use Parm's new disposed flag to * prevent leaks through * ListenerLists. + * Jun 25, 2012 #766 dgilling Cleanup error logging so we + * don't spam alertViz in practice + * mode. * * * @@ -104,7 +107,7 @@ public class VCParm extends VParm implements IParmListChangedListener, // Need to check that the above call to mod.getGpi() did not fail if (!mod.isValid()) { - statusHandler.handle(Priority.PROBLEM, "Can't get GPI: ", + statusHandler.handle(Priority.EVENTB, "Can't get GPI: ", this.mod.getErrorString()); } @@ -410,7 +413,7 @@ public class VCParm extends VParm implements IParmListChangedListener, // ensure we have parms* for all of the dependent parms List args = new ArrayList(mod.dependentParms()); if (!mod.isValid()) { - statusHandler.handle(Priority.PROBLEM, + statusHandler.handle(Priority.EVENTB, "Error getting dependent WeatherElements: ", mod.getErrorString()); } @@ -455,7 +458,7 @@ public class VCParm extends VParm implements IParmListChangedListener, // get list of dependent parms List args = new ArrayList(mod.dependentParms()); if (!mod.isValid()) { - statusHandler.handle(Priority.PROBLEM, + statusHandler.handle(Priority.EVENTB, "Error getting dependent WeatherElements: ", mod.getErrorString()); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java index 3919ae81cf..a50bc048c2 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java @@ -70,6 +70,8 @@ import com.raytheon.viz.gfe.core.parm.Parm; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 17, 2011 dgilling Initial creation + * Jun 20, 2012 #766 dgilling Refactor to improve + * performance. * * * @@ -149,7 +151,7 @@ public class VCModule { private GridParmInfo gpi; - private VCModuleJob python; + private Collection depParms; private DataManager dataMgr; @@ -161,12 +163,11 @@ public class VCModule { this.dataMgr = dataMgr; this.parmMgr = parmMgr; this.id = module.getName().split("\\.(?=[^\\.]+$)")[0]; - this.python = new VCModuleJob(this.dataMgr); - this.python.schedule(); + this.depParms = Collections.emptyList(); } public void dispose() { - this.python.cancel(); + // no-op } public boolean isValid() { @@ -185,7 +186,7 @@ public class VCModule { Map args = new HashMap(); args.put(PyConstants.METHOD_NAME, method); VCModuleRequest req = new VCModuleRequest(id, "getMethodArgs", args); - python.enqueue(req); + parmMgr.getVCModulePool().enqueue(req); Object result = req.getResult(); String[] argNames = (String[]) result; @@ -193,14 +194,20 @@ public class VCModule { } public Collection dependentParms() { - Collection rval = new ArrayList(); + // this is a derivation from AWIPS1 + // like getGpi(), this should only ever need to be calculated once + // since VCModule does not support dynamic updates. + if (!depParms.isEmpty()) { + return depParms; + } try { Collection parameters = getMethodArgs("getInventory"); + depParms = new ArrayList(parameters.size()); for (String parmName : parameters) { ParmID pid = parmMgr.fromExpression(parmName); if (pid.isValid()) { - rval.add(pid); + depParms.add(pid); } else { throw new IllegalArgumentException( "Can't find Weather Element for " + parmName); @@ -210,10 +217,10 @@ public class VCModule { error = t; // statusHandler.handle(Priority.DEBUG, "dependentParms: " + id // + " error", t); - return Collections.emptyList(); + depParms = Collections.emptyList(); } - return rval; + return depParms; } private long[] encodeTR(final TimeRange tr) { @@ -235,9 +242,9 @@ public class VCModule { Object[] item = new Object[3]; item[0] = encodeTR(gd.getGridTime()); - // since we have to go through a bunch of hoops in VCModuleScript to get - // the IGridData in python-useable format, no need doing anything here - // but storing the data + // since we have to go through a bunch of hoops in VCModuleController to + // get the IGridData in python-useable format, no need doing anything + // here but storing the data item[1] = gd; // add a mask indicating the set of valid points. Note for all data @@ -328,7 +335,7 @@ public class VCModule { } VCModuleRequest req = new VCModuleRequest(id, "getInventory", cargs); - python.enqueue(req); + parmMgr.getVCModulePool().enqueue(req); Object reqResult = req.getResult(); // what's returned from the script here is a list of tuples. @@ -389,7 +396,7 @@ public class VCModule { // commenting out this python call because it is completely // superfluous--all the baseline VCMODULE files have a calcHistory // method so there's no point in checking and it saves a call into the - // VCModuleJob queue. If at some point there's a desire to support + // VCModuleJobPool queue. If at some point there's a desire to support // user/site-defined modules, this check should probably return. // TODO: Reimplement using a call to BaseGfePyController.hasMethod(). @@ -442,7 +449,7 @@ public class VCModule { } VCModuleRequest req = new VCModuleRequest(id, "calcHistory", cargs); - python.enqueue(req); + parmMgr.getVCModulePool().enqueue(req); Object reqResult = req.getResult(); List result = (List) reqResult; @@ -500,7 +507,7 @@ public class VCModule { VCModuleRequest req = new VCModuleRequest(id, "calcGrid", cargs, getGpi().getGridType()); - python.enqueue(req); + parmMgr.getVCModulePool().enqueue(req); Object reqResult = req.getResult(); return decodeGD(reqResult, invEntry); @@ -521,7 +528,7 @@ public class VCModule { try { VCModuleRequest req = new VCModuleRequest(id, "getWEInfo", null); - python.enqueue(req); + parmMgr.getVCModulePool().enqueue(req); Object reqResult = req.getResult(); List> result = (List>) reqResult; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java deleted file mode 100644 index d7a588d031..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.viz.gfe.core.parm.vcparm; - -import java.util.concurrent.TimeUnit; - -import jep.JepException; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; - -import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; -import com.raytheon.uf.common.python.PyConstants; -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.viz.core.jobs.AbstractQueueJob; -import com.raytheon.viz.gfe.core.DataManager; - -/** - * Job which allows VCModule python calls to run off a - * common thread. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Dec 20, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -public class VCModuleJob extends AbstractQueueJob { - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(VCModuleJob.class); - - private VCModuleController python = null; - - private DataManager dataMgr; - - public VCModuleJob(DataManager dataMgr) { - super("GFE Virtual ISC Python executor"); - setSystem(true); - this.dataMgr = dataMgr; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime. - * IProgressMonitor) - */ - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - try { - python = VCModuleControllerFactory.buildInstance(dataMgr); - } catch (JepException e) { - return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, - "Error initializing VCModule python object", e); - } - - while (!monitor.isCanceled()) { - VCModuleRequest request = null; - try { - request = queue.poll(1000L, TimeUnit.MILLISECONDS); - if (request != null) { - processRequest(request); - } - - // TODO: Reinstate this call, if we ever want to support - // dynamic editing of VCMODULE files through the - // Localization perspective. - // python.processFileUpdates(); - } catch (InterruptedException e) { - statusHandler.handle(Priority.PROBLEM, - "VC Module python thread interrupted.", e); - break; - } catch (Throwable t) { - // statusHandler.handle(Priority.DEBUG, - // "Error running VCModule method.", t); - request.setResult(t); - } - } - } finally { - - if (python != null) { - python.dispose(); - python = null; - } - } - - return Status.OK_STATUS; - } - - private void processRequest(VCModuleRequest request) throws JepException { - Object result = null; - - if (request.getMethodName().equals("getMethodArgs")) { - result = python.getMethodArguments(request.getModuleName(), - (String) request.getArgMap().get(PyConstants.METHOD_NAME)); - } else { - result = python.executeMethod(request.getModuleName(), - request.getMethodName(), request.getJepArgs(), - request.getType()); - } - - request.setResult(result); - } -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJobPool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJobPool.java new file mode 100644 index 0000000000..5840481746 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJobPool.java @@ -0,0 +1,228 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import jep.JepException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; + +import com.raytheon.uf.common.python.PyConstants; +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.viz.gfe.core.DataManager; + +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 22, 2012            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModuleJobPool { + + protected static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(VCModuleJobPool.class); + + protected LinkedBlockingQueue workQueue = new LinkedBlockingQueue(); + + protected List jobList; + + protected boolean cancel = false; + + protected Object cancelLock = new Object(); + + protected Object joinLock = new Object(); + + public VCModuleJobPool(String name, DataManager dataMgr, int size) { + this(name, dataMgr, size, null, null); + } + + public VCModuleJobPool(String name, DataManager dataMgr, int size, + Boolean system) { + this(name, dataMgr, size, system, null); + } + + public VCModuleJobPool(String name, DataManager dataMgr, int size, + Boolean system, Integer priority) { + jobList = new ArrayList(size); + for (int i = 0; i < size; i++) { + PooledJob job = new PooledJob(name, null); + if (system != null) { + job.setSystem(system); + } + if (priority != null) { + job.setPriority(priority); + } + jobList.add(job); + job.schedule(); + } + } + + public void enqueue(VCModuleRequest request) { + // do not schedule while canceling(cancel should be fast. + synchronized (cancelLock) { + if (cancel) { + return; + } + // do not schedule while joining, join might be slow but the + // javaDoc warns others. + synchronized (joinLock) { + workQueue.offer(request); + } + } + } + + /** + * Join on the Jobs in the pool. Attempting to schedule other + * Jobs will block until join as returned so be careful when + * calling + */ + public void join() { + synchronized (joinLock) { + for (Job j : jobList) { + try { + j.join(); + } catch (InterruptedException e) { + // Ignore interrupt + } + } + } + } + + /** + * Cancel the job pool, will clear out the workQueue then join on all jobs + * running + */ + public void cancel() { + synchronized (cancelLock) { + cancel = true; + workQueue.clear(); + } + for (Job job : jobList) { + job.cancel(); + } + join(); + } + + /** + * Cancels the specified request. Returns true if the provided runnable was + * waiting to be run but now is now. Returns false if the provided runnable + * is already running or if it was not enqueued to begin with. + * + * @param request + * @return + */ + public boolean cancel(VCModuleRequest request) { + return workQueue.remove(request); + } + + protected class PooledJob extends Job { + + protected DataManager dataMgr; + + protected VCModuleController python; + + public PooledJob(String name, DataManager dataMgr) { + super(name); + this.dataMgr = dataMgr; + this.python = null; + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + if (python == null) { + python = VCModuleControllerFactory.buildInstance(dataMgr); + } + + while (!monitor.isCanceled()) { + try { + VCModuleRequest request = workQueue.poll(1L, + TimeUnit.SECONDS); + if (request != null) { + processRequest(request); + } + } catch (InterruptedException e) { + // ignore, but log + statusHandler.handle( + Priority.DEBUG, + "VCModuleJobPool received interrupt: " + + e.getLocalizedMessage(), e); + } + } + } catch (JepException e) { + statusHandler.handle( + Priority.WARN, + "Could not instantiate VCMoudleController: " + + e.getLocalizedMessage(), e); + } finally { + if (python != null) { + python.dispose(); + } + } + + return Status.CANCEL_STATUS; + } + + protected void processRequest(VCModuleRequest request) { + Object result = null; + + try { + if (request.getMethodName().equals("getMethodArgs")) { + result = python.getMethodArguments( + request.getModuleName(), + (String) request.getArgMap().get( + PyConstants.METHOD_NAME)); + } else { + result = python.executeMethod(request.getModuleName(), + request.getMethodName(), request.getJepArgs(), + request.getType()); + } + } catch (Throwable t) { + statusHandler.handle( + Priority.DEBUG, + "Exception thrown in VCModule's python.execute(): " + + t.getLocalizedMessage(), t); + result = t; + } + + request.setResult(result); + } + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductAreaComp.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductAreaComp.java old mode 100755 new mode 100644 diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/SelectPointsTool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/SelectPointsTool.java index fa33c20b3a..93e62d00da 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/SelectPointsTool.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/SelectPointsTool.java @@ -178,6 +178,7 @@ public class SelectPointsTool extends AbstractFreeformTool { if (parms.length == 0) { statusHandler.handle(Priority.VERBOSE, "No displayed parms. Cannot select points."); + return new Coordinate[0]; } else { parm = parms[0]; } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/ifpimage/ImageLegendResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/ifpimage/ImageLegendResource.java index 5e5cf36057..070105c6fb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/ifpimage/ImageLegendResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/ifpimage/ImageLegendResource.java @@ -55,6 +55,7 @@ import com.raytheon.viz.gfe.rsc.GFEResource; * ------------ ---------- ----------- -------------------------- * Jan 24, 2011 mschenke Initial creation * Jun 25, 2012 15080 ryu Ron's local time fix + * Jul 10, 2012 15186 ryu Set legend font * * * @@ -104,6 +105,7 @@ public class ImageLegendResource extends GFELegendResource { LegendEntry[] entries = new LegendEntry[data.length]; for (int i = 0; i < entries.length; ++i) { entries[i] = new LegendEntry(); + entries[i].font = font; entries[i].legendParts = new LegendData[] { data[i] }; } return entries; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFELegendResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFELegendResource.java index 104eda15cd..8a6fd10cb1 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFELegendResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFELegendResource.java @@ -1,19 +1,19 @@ /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * + * * U.S. EXPORT CONTROLLED TECHNICAL DATA * This software product contains export-restricted data whose * export/transfer/disclosure is restricted by U.S. law. Dissemination * to non-U.S. persons whether in the United States or abroad requires * an export license or other authorization. - * + * * Contractor Name: Raytheon Company * Contractor Address: 6825 Pine Street, Suite 340 * Mail Stop B8 * Omaha, NE 68106 * 402.291.0100 - * + * * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ @@ -74,17 +74,18 @@ import com.raytheon.viz.gfe.edittool.GridID; import com.raytheon.viz.ui.input.InputAdapter; /** - * + * * Port of SELegendVisual from AWIPS I GFE - * + * *
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * 03/17/2008              chammack    Initial Creation.
  * 08/19/2009   2547       rjpeter     Implement Test/Prac database display.
+ * 07/10/2012   15186      ryu         Clean up initInternal per Ron
  * 
- * + * * @author chammack * @version 1.0 */ @@ -106,7 +107,7 @@ public class GFELegendResource extends /* * (non-Javadoc) - * + * * @see java.lang.Enum#toString() */ @Override @@ -272,7 +273,7 @@ public class GFELegendResource extends /* * (non-Javadoc) - * + * * @see java.lang.Object#finalize() */ @SuppressWarnings("unchecked") @@ -289,7 +290,7 @@ public class GFELegendResource extends /* * (non-Javadoc) - * + * * @see * com.raytheon.viz.core.legend.ILegendDecorator#getLegendData(com.raytheon * .viz.core.drawables.IDescriptor) @@ -527,7 +528,7 @@ public class GFELegendResource extends /** * Get the legend mode - * + * * @return the legend mode */ public LegendMode getLegendMode() { @@ -537,10 +538,10 @@ public class GFELegendResource extends /** * Works in a single pass to perform the operations performed in AWIPS I * getLargestLevelName, etc. - * + * * The fields in order:
  • FieldName
  • LevelName
  • Units
  • ModelName - * - * + * + * * @param descriptor * @return */ @@ -606,7 +607,7 @@ public class GFELegendResource extends /** * Create a map between parms and gfe resources. This will avoid expensive * searching - * + * * @param descriptor * @return */ @@ -646,19 +647,11 @@ public class GFELegendResource extends @Override protected void initInternal(IGraphicsTarget target) throws VizException { super.initInternal(target); - // Using a proportional font messes up the legend columns. - // Use the bold VeraMono font and only use font # to control size. - File fontFile = PathManagerFactory.getPathManager().getStaticFile( - "fonts" + File.separator + "VeraMono.ttf"); int fontNum = 3; if (GFEPreference.contains("SELegend_font")) { fontNum = GFEPreference.getIntPreference("SELegend_font"); } - FontData fd = GFEFonts.getFontData(fontNum); - font = target.initializeFont(fontFile, fd.getHeight(), - new IFont.Style[] { IFont.Style.BOLD }); - - font.setSmoothing(true); + font = GFEFonts.getFont(target, fontNum); IDisplayPaneContainer container = getResourceContainer(); if (container != null) { @@ -684,7 +677,7 @@ public class GFELegendResource extends /** * Set the legend mode - * + * * @param mode * the legend mode */ @@ -695,7 +688,7 @@ public class GFELegendResource extends /* * (non-Javadoc) - * + * * @see * com.raytheon.viz.gfe.core.msgs.Message.IMessageClient#receiveMessage( * com.raytheon.viz.gfe.core.msgs.Message) diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java index f069050076..120f0c8a92 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java @@ -109,6 +109,8 @@ public class GFEColorbarResource extends IContextMenuProvider, IPickupValueChangedListener, IDisplayModeChangedListener, IMessageClient, IDisplayedParmListChangedListener { + + public static final double HEIGHT = 25.0; private class GFEColorbarInputHandler extends InputAdapter { @@ -375,10 +377,6 @@ public class GFEColorbarResource extends PaintProperties paintProps) throws VizException { // this.target = target; - if (currentParm == null) { - return; - } - // int curIndex = this.descriptor.getCurrentTimeFrame(); if (colorbarScaleFont == null) { @@ -398,9 +396,9 @@ public class GFEColorbarResource extends IExtent screenExtent = paintProps.getView().getExtent(); - // Construct a bar that is 25 pixels high - double height = 25.0 * screenExtent.getHeight() - / paintProps.getCanvasBounds().height; + // Construct a bar that is HEIGHT pixels high + double height = HEIGHT * screenExtent.getHeight() + / paintProps.getCanvasBounds().height; PixelExtent pe = new PixelExtent(screenExtent.getMinX(), screenExtent.getMaxX(), screenExtent.getMinY(), @@ -414,7 +412,11 @@ public class GFEColorbarResource extends // erase the whole colorbar to a black background target.drawShadedRect(pe, ColorUtil.BLACK, 1.0, null); - target.drawRect(pe, GFEColorbarResource.COLORBAR_GRAY, 1.0f, 1.0f); + target.drawRect(pe, GFEColorbarResource.COLORBAR_GRAY, 2.0f, 1.0f); + + if (currentParm == null) { + return; + } if (/* * !currentParm.getDisplayAttributes().getVisMode().equals(VisMode. diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java index c1838c22b9..8fa9be7ced 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java @@ -106,7 +106,8 @@ import com.vividsolutions.jts.geom.Coordinate; * 05/08/2012 14828 D. Friedman Use nearest-neighbor interpolation for * reprojected grids. * 05/16/2012 14993 D. Friedman Fix "blocky" contours - * 06/19/2012 14988 D. Friedman Reproject based on conformality + * 06/19/2012 14988 D. Friedman Reproject based on conformality + * 07/09/2012 14940 M. Porricelli Apply reprojection to streamlines * * * @@ -264,7 +265,8 @@ public class GridVectorResource extends AbstractMapVectorResource implements boolean isVector = false; if (displayType == DisplayType.BARB - || displayType == DisplayType.ARROW) { + || displayType == DisplayType.ARROW + || displayType == DisplayType.STREAMLINE) { isVector = true; for (int i = 0; i < len; i++) { diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDataManager.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDataManager.java index 561ac5a378..ceda995796 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDataManager.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDataManager.java @@ -897,41 +897,73 @@ public class TimeSeriesDataManager extends HydroDataManager { HydroConstants.IHFS, QueryLanguage.SQL); } + private Object getDataFromDB (ForecastData dr, String field) { + StringBuilder sql = new StringBuilder("select "+field+" from "); + String tablename = DbUtils.getTableName(dr.getPe(), dr.getTs()); + sql.append(tablename + " where "); + sql.append("lid = '" + dr.getLid() + "' "); + sql.append("and pe = '" + dr.getPe().toUpperCase() + "' "); + sql.append("and dur =" +dr.getDur()+" "); + sql.append("and ts = '"+dr.getTs().toUpperCase()+"' "); + sql.append("and extremum = '" +dr.getExtremum().toUpperCase()+"' "); + if (dr.getTs().toUpperCase().startsWith("F") || dr.getTs().toUpperCase().startsWith("C")){ + sql.append("and validtime = '"+dr.getValidTime()+"' "); + sql.append("and basistime = '"+dr.getBasisTime()+"';"); + }else {//obs data + sql.append("and obstime = '"+dr.getObsTime()+"';"); + } + List sqlResult; + try { + sqlResult = (ArrayList) (DirectDbQuery.executeQuery(sql.toString(), HydroConstants.IHFS, QueryLanguage.SQL)); + if (sqlResult !=null && sqlResult.size()>0 && sqlResult.get(0)[0]!=null) + return sqlResult.get(0)[0]; + } catch (VizException e) { + e.printStackTrace(); + return null; + } + + return null; + } + public int insertRejectedData(List deleteList) throws VizException { StringBuilder sb = new StringBuilder(); Date currentTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime(); for (ForecastData dr : deleteList) { - - Date productTime=dr.getProductTime(); - if(productTime==null){ //get product time from DB if not available - StringBuilder sql = new StringBuilder("select producttime from "); - String tablename = DbUtils.getTableName(dr.getPe(), dr.getTs()); - sql.append(tablename + " where "); - sql.append("lid = '" + dr.getLid() + "' "); - sql.append("and dur = " + dr.getDur() + " "); - sql.append("and ts = '" + dr.getTs().toUpperCase() + "' "); - sql.append("and extremum = '" + dr.getExtremum().toUpperCase() + "' "); - sql.append("and obstime = '" + dr.getObsTime() + "' "); - sql.append("and value = "+dr.getValue()); - List sqlResult = (ArrayList) (DirectDbQuery.executeQuery(sql.toString(), HydroConstants.IHFS, QueryLanguage.SQL)); - if (sqlResult !=null && sqlResult.size()>0 && sqlResult.get(0)[0]!=null) - productTime=(Date)sqlResult.get(0)[0]; - else - productTime=currentTime; //use current time if still not available + + int probability=-1; + int revision=0; + if (dr.getTs().toUpperCase().startsWith("F") || dr.getTs().toUpperCase().startsWith("C")) { + probability=0; + revision=1; } - + + Date productTime=dr.getProductTime(); + if (productTime==null) { + productTime=(Date)getDataFromDB(dr,"producttime"); + } + + String productID=(String)getDataFromDB(dr,"product_id"); + if (productID==null) { + productID=dr.getProductID(); + } + + Integer qualityCode=(Integer)getDataFromDB(dr,"quality_code"); + if (qualityCode==null) { + qualityCode=new Integer(dr.getQualityCode()); + } + sb.append("insert into rejecteddata(lid, pe, dur, ts, extremum, "); sb.append("probability, validtime, basistime, postingtime, value, "); sb.append("revision, shef_qual_code, product_id, producttime, quality_code, "); sb.append("reject_type, userid) VALUES("); sb.append("'" + dr.getLid() + "', "); - sb.append("'" + dr.getPe() + "', "); + sb.append("'" + dr.getPe().toUpperCase() + "', "); sb.append(dr.getDur() + ", "); - sb.append("'" + dr.getTs() + "', "); - sb.append("'" + dr.getExtremum() + "', "); - sb.append(-1 + ", "); + sb.append("'" + dr.getTs().toUpperCase() + "', "); + sb.append("'" + dr.getExtremum().toUpperCase() + "', "); + sb.append(probability + ", "); /* set validtime for observed data */ if (dr.getValidTime() != null) { @@ -955,13 +987,13 @@ public class TimeSeriesDataManager extends HydroDataManager { sb.append("'" + HydroConstants.DATE_FORMAT.format(currentTime) + "', "); sb.append(dr.getValue() + ", "); - sb.append(dr.getRevision() + ", "); - sb.append("'" + dr.getShefQualCode() + "', "); - sb.append("'" + dr.getProductID() + "', "); + sb.append(revision + ", "); + sb.append("'M', ");//shef_qual_code always M + sb.append("'" + productID + "', "); sb.append("'" + HydroConstants.DATE_FORMAT.format(productTime) + "', "); - sb.append(dr.getQualityCode() + ", "); + sb.append(qualityCode + ", "); sb.append("'M', "); sb.append("'" + LocalizationManager.getInstance().getCurrentUser() + "');"); @@ -1001,9 +1033,12 @@ public class TimeSeriesDataManager extends HydroDataManager { StringBuilder sql = new StringBuilder("delete from "); sql.append(tablename + " where "); sql.append("lid = '" + data.getLid() + "' "); - sql.append("and dur = " + data.getDur() + " "); - sql.append("and extremum = '" + data.getExtremum().toUpperCase() + sql.append("and pe = '"+data.getPe().toUpperCase()+"' "); + sql.append("and dur = " + data.getDur() + " "); + sql.append("and ts = '"+data.getTs().toUpperCase()+"' "); + sql.append("and extremum = '" + data.getExtremum().toUpperCase() + "' "); + if (data.getValidTime() != null) { sql.append("and validtime = '" + dbFormat.format(data.getValidTime()) + "'"); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java index 00d350e75f..06e09dd4da 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java @@ -769,6 +769,9 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements int labelStartX = 0; int labelStartY = 0; + //store the label to be plotted on the gc legend later + ArrayList noDataLabels = new ArrayList(); + for (int j = 0; j < traceArray.size(); j++) { TraceData td = traceArray.get(j); boolean traceValid = true; @@ -959,7 +962,7 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements setForegroundColor(td, j, gc); if (graphData.getTraces().size() > 1) { - if (traceValid) { + if (td.getLineData()!=null && td.getLineData().length>0) { if (td.isTraceOn()) { if (stackLabels || ((dataString.length() * fontAveWidth) + 50 + index > canvasWidth)) { int[] xy = getLabelLocation(index, dataString, stackCount); @@ -977,23 +980,8 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements } } } else { - // setForegroundColor(td, 23, gc); - setForegroundColor(gc, SWT.COLOR_WHITE); - if (stackLabels || ((dataString.length() * fontAveWidth) + 50 + index > canvasWidth)) { - int[] xy = getLabelLocation(index, dataString, stackCount); - stackCount++; - labelStartX = xy[0]; - labelStartY = xy[1]; - stackLabels = true; - } else { - labelStartX = index; - labelStartY = GRAPHBORDER - fontHeight; - } - gc.drawString(noDataString, labelStartX, labelStartY); - if (!stackLabels) { - index += (noDataString.length() + 2) * fontAveWidth; - } - setForegroundColor(td, j, gc); + noDataLabels.add(noDataString); + } } else { if (graphData.getTraceData(0).getPe().startsWith("Q")) { @@ -1088,6 +1076,27 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements } } } + + //draw no data legends + setForegroundColor(gc, SWT.COLOR_WHITE); + for (int i=0;i canvasWidth)) { + int[] xy = getLabelLocation(index, labelString, stackCount); + stackCount++; + labelStartX = xy[0]; + labelStartY = xy[1]; + stackLabels = true; + } else { + labelStartX = index; + labelStartY = GRAPHBORDER - fontHeight; + } + gc.drawString(labelString,labelStartX ,labelStartY); + if (!stackLabels) { + index += (labelString.length() + 2) * fontAveWidth; + } + } + // draw X/Y axis setForegroundColor(gc, SWT.COLOR_WHITE); @@ -1536,7 +1545,7 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements s = getPEDTSE(td); } MenuItem mi = new MenuItem(m, SWT.CHECK); - if (!validGraph.get(i)) { + if (td.getLineData()!=null && td.getLineData().length>0) { if (td.isTraceOn()) mi.setSelection(true); else @@ -1805,20 +1814,15 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements } } } else { - for (int i = 0; i < listRegionList.size(); i++) { - ArrayList rList = listRegionList.get(i); - for (int j = 0; j < rList.size(); j++) { - if (rList.get(j).contains(e.x, e.y)) { - setCursor(handCursor); - selectableTrace = true; - selectedTraceId = j; - break; - } else { - setCursor(arrowCursor); - selectableTrace = false; - } - } - } + int traceId=findTracePoint(e.x,e.y); + if (traceId>=0){ + setCursor(handCursor); + selectableTrace = true; + selectedTraceId = traceId; + }else { + setCursor(arrowCursor); + selectableTrace = false; + } } } } @@ -1826,6 +1830,72 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements } } + /** + * + * @param x : location x (of mouse pointer) + * @param y : location y (of mouse pointer) + * @return the nearest trace. -999 if x,y is too far away + */ + private int findTracePoint(int x, int y) { + double distance=Double.MAX_VALUE; + int choosingTrace=-999; + ArrayList traceList=graphData.getTraces(); + + //this loop is to find the closest point/line for every trace that's on + int closePoints[] = new int[traceList.size()]; + for (int traceIndex=0; traceIndex< traceList.size(); traceIndex++) { + TraceData td= traceList.get(traceIndex); + closePoints[traceIndex]=-999; //default to not found + int[] dataPts = td.getLineData(); //dataPts stores x1,y1,x2,y2,x3... + if (td.isTraceOn() && dataPts!=null) { + for (int i = 0; i < dataPts.length - 1; i+= 2) { + int x1 = dataPts[i]; + int y1 = dataPts[i + 1]; + int x2 = x1; + int y2 = y1; + if (i+4 <= dataPts.length) { + x2 = dataPts[i + 2]; + y2 = dataPts[i + 3]; + } + double curDistance=Double.MAX_VALUE; + if (x1==x2 && y1==y2) //distance from a point + curDistance=Math.sqrt(Math.pow(x-x1,2)+Math.pow(y-y1, 2)); + else {//distance from a line segment + //from http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment + double p2X=x2-x1; + double p2Y=y2-y1; + + double something=p2X*p2X + p2Y*p2Y; + + double u=((x-x1)*p2X+(y-y1)*p2Y)/something; + + if (u > 1) + u = 1; + else if (u < 0) + u = 0; + + double xx=x1+u*p2X; + double yy=y1+u*p2Y; + + double dx=xx-x; + double dy=yy-y; + + curDistance=Math.sqrt(dx*dx+dy*dy); + } + if (curDistance * @@ -533,6 +534,12 @@ public class CrestHistoryCanvas extends Canvas { pixelsPerIncX = HLINE_LENGTH / years; } + //Init the counts + this.majorCount=0; + this.minorCount=0; + this.actionCount=0; + this.modCount=0; + for (CrestData crestData : crestHistoryData.getCrestDataArray()) { int yCoord = (int) (maxPixValue - Math diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MPELegendResource.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MPELegendResource.java index db490180de..2694704632 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MPELegendResource.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MPELegendResource.java @@ -155,7 +155,7 @@ public class MPELegendResource extends double cmapHeight = textHeight * 1.25; - legendHeight = cmapHeight + 2.0 * textSpace + 2.0 * padding; + legendHeight = cmapHeight + 3.0 * textSpace + 2.0 * padding; double y1 = yMax - legendHeight; DrawableColorMap cmap = new DrawableColorMap(rsc.getCapability( diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MeanArealPrecipResource.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MeanArealPrecipResource.java index 12b56b6f8b..7314a9a6fc 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MeanArealPrecipResource.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/MeanArealPrecipResource.java @@ -594,7 +594,7 @@ public class MeanArealPrecipResource extends StringBuilder sb = new StringBuilder(); sb.append(dman.getAccumInterval() + " hr Accumulated Best Estimate QPE Ending " - + HydroConstants.DISPLAY_DATE_FORMAT.format(dman.getDataDate())); + + HydroConstants.DISPLAY_DATE_FORMAT.format(dman.getDataDate())+"z (in)"); if (noData) { sb.append(" No Data Available"); diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/XmrgResource.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/XmrgResource.java index 7602425c57..5c7d816643 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/XmrgResource.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/XmrgResource.java @@ -235,13 +235,13 @@ public class XmrgResource extends name = "FFG No Data Available"; } else { name = "FFG " + res.getResolution() + " " + hours + " " - + hourStr + " " + sdf.format(dataDate) + noData; + + hourStr + " " + sdf.format(dataDate)+"z (in)" + noData; } } else { name = dman.getAccumInterval() + " hr Accumulated Best Estimate QPE Ending " + HydroConstants.DISPLAY_DATE_FORMAT.format(dman - .getDataDate()) + noData; + .getDataDate()) +"z (in)"+ noData; } return name; } 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 0a6273c1c9..7c74f0c558 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 @@ -468,7 +468,11 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { if (dateInfo != null) { lastSave.setText(sdf.format(dateInfo.getLastSaveTime())); lastExec.setText(sdf.format(dateInfo.getLastExecTime())); - manuallySaved.setText(dateInfo.isAutoSave() ? "NO" : "YES"); + if (dateInfo.isAutoSave()){ + manuallySaved.setText("NO"); + } else{ + manuallySaved.setText("YES"); + } } else { lastSave.setText("NA"); lastExec.setText("NA"); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java index cbc43518a8..e41d6e5084 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java @@ -833,7 +833,7 @@ public class GageTableDlg extends JFrame { try { JAXB.marshal(getSettingsXML(), newXmlFile.getFile()); - + newXmlFile.save(); } catch (Exception e) { e.printStackTrace(); } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MPEDataManager.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MPEDataManager.java index 62e49c3c5b..c819ed6b4d 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MPEDataManager.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MPEDataManager.java @@ -746,10 +746,8 @@ public class MPEDataManager { } public Map getDateMap(boolean update) { - if (dateMap == null || update) { - getDates(update); - } - + + getDates(update); return dateMap; } diff --git a/cave/com.raytheon.viz.pointdata/localization/pointdata/RefTimePointDataRetrieve.py b/cave/com.raytheon.viz.pointdata/localization/pointdata/RefTimePointDataRetrieve.py index f5538335ce..581e40f3a5 100644 --- a/cave/com.raytheon.viz.pointdata/localization/pointdata/RefTimePointDataRetrieve.py +++ b/cave/com.raytheon.viz.pointdata/localization/pointdata/RefTimePointDataRetrieve.py @@ -32,6 +32,8 @@ import PointDataView, PointDataContainer, NoDataException, PointDataRetrieve # ------------ ---------- ----------- -------------------------- # 25Apr2012 14688 rferrel Initial Creation. # 06JUL2012 15153 zhao retrieve latest Metar for MetarMonitor & PersistMonitor +# 16JUL2012 14655 zhao fixed a problem that occurs when there is no Metar +# record within a selected number of hours # # @@ -55,17 +57,17 @@ class RefTimePointDataRetrieve(PointDataRetrieve.PointDataRetrieve): from java.lang import String import jep from com.raytheon.uf.common.time import DataTime - #dts = self._createJarray(availableTimes, maxSize) length = len(availableTimes) dts = jep.jarray(length,DataTime) if maxSize==0 : #DR15153: retrive latest Metar for Metarmonitor & PersistMonitor - #from com.raytheon.uf.common.time import DataTime dts = jep.jarray(1,DataTime) - #length = len(availableTimes) dts[0] = DataTime(availableTimes[length-1]) else : # for maxSize >= 1 dts = self._createJarray(availableTimes, maxSize) + if len(dts)==0 : + dts = jep.jarray(1,DataTime) + dts[0] = DataTime(availableTimes[length-1]) constraints = self._buildConstraints(None) #times are explicitly set so we don't need to constrain those params = jep.jarray(len(parameters), String) diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource2.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource2.java index a1f15de6e8..4d66daffa9 100644 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource2.java +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource2.java @@ -677,6 +677,7 @@ public class PlotResource2 extends public void project(CoordinateReferenceSystem crs) throws VizException { clearImages(); frameRetrievalPool.cancel(); + frameRetrievalPool = new JobPool("Retrieving plot frame", 8, true); frameMap.clear(); } diff --git a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java index 021cfcc55a..56c7f4f5ef 100644 --- a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java +++ b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java @@ -30,6 +30,10 @@ import java.util.Set; import javax.measure.unit.UnitFormat; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.swt.graphics.RGB; import org.geotools.geometry.DirectPosition2D; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -39,6 +43,9 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.radar.RadarRecord; import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.ReferencedCoordinate; +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.time.DataTime; import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.drawables.ColorMapParameters; @@ -84,6 +91,9 @@ public class RadarMosaicResource extends AbstractVizResource implements IResourceDataChanged, IRadarTextGeneratingResource, IRefreshListener { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(RadarMosaicResource.class); + private static final RGB DEFAULT_COLOR = new RGB(255, 255, 255); private IRadarMosaicRenderer mosaicRenderer; @@ -100,6 +110,16 @@ public class RadarMosaicResource extends private Map, DataTime[]> timeMatchingMap = new HashMap, DataTime[]>(); + private Job timeUpdateJob = new Job("Time Matching Mosaic") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + updateTimes(); + return Status.OK_STATUS; + } + + }; + protected RadarMosaicResource(RadarMosaicResourceData rrd, LoadProperties loadProps) throws VizException { super(rrd, loadProps); @@ -178,6 +198,8 @@ public class RadarMosaicResource extends rp.getResource().registerListener(this); } } + + timeUpdateJob.setSystem(true); } private int getSeverity(ResourcePair rp) { @@ -217,10 +239,12 @@ public class RadarMosaicResource extends PaintProperties paintProps) throws VizException { DataTime[] frameTimes = paintProps.getFramesInfo().getTimeMap() .get(this); - if (force || !Arrays.equals(timeMatchingMap.get(this), frameTimes)) { - redoTimeMatching( - !Arrays.equals(timeMatchingMap.get(this), frameTimes), - frameTimes); + if (!Arrays.equals(timeMatchingMap.get(this), frameTimes)) { + timeUpdateJob.schedule(); + force = true; + } + if (force) { + redoTimeMatching(frameTimes); } List recordsToMosaic = constructRecordsToMosaic(target); if (recordsToMosaic.isEmpty() == false) { @@ -312,82 +336,119 @@ public class RadarMosaicResource extends return dt[idx]; } - private void redoTimeMatching(boolean requery, DataTime[] frameTimes) - throws VizException { + /** + * redoTimeMatching will not trigger an server requests and should be safe + * to run within paint to guarantee that the latest times for any resources + * match the frame times for the mosaic resource. + * + * @param frameTimes + * @throws VizException + */ + private void redoTimeMatching(DataTime[] frameTimes) throws VizException { timeMatchingMap.clear(); if (frameTimes == null) { return; } - List dataTimes = Arrays.asList(frameTimes); timeMatchingMap.put(this, frameTimes); for (ResourcePair pair : getResourceList()) { DataTime[] availableTimes = pair.getResource().getDataTimes(); - if (requery - && pair.getResourceData() instanceof AbstractRequestableResourceData) { - availableTimes = ((AbstractRequestableResourceData) pair - .getResourceData()).getAvailableTimes(); - } - DataTime[] displayTimes = new DataTime[frameTimes.length]; - for (int i = 0; i < frameTimes.length; i++) { - DataTime frameTime = frameTimes[i]; - if (frameTime == null) { + DataTime[] displayTimes = timeMatch(frameTimes, availableTimes); + timeMatchingMap.put(pair.getResource(), displayTimes); + } + } + + /** + * Update times will cause all times to be requested for all child resources + * and possibly also trigger data requests therefore it should always be run + * off the UI thread, preferably in the timeUpdateJob. + */ + private void updateTimes() { + for (ResourcePair pair : getResourceList()) { + try { + if (!(pair.getResourceData() instanceof AbstractRequestableResourceData)) { continue; } - if (resourceData.getBinOffset() != null) { - frameTime = resourceData.getBinOffset().getNormalizedTime( - frameTime); - long frameSeconds = frameTime.getMatchValid() / 1000; - for (DataTime displayTime : availableTimes) { - long dispSeconds = displayTime.getMatchValid() / 1000; - // Match at twice the range of binOffset this makes - // things much smoother - if (Math.abs(dispSeconds - frameSeconds) < resourceData - .getBinOffset().getInterval() * 2) { - if (displayTimes[i] != null) { - long d1 = Math.abs(frameTime.getMatchValid() - - displayTimes[i].getMatchValid()); - long d2 = Math.abs(frameTime.getMatchValid() - - displayTime.getMatchValid()); - if (d1 < d2) { - continue; - } - } - displayTimes[i] = displayTime; - } - } - } else if (Arrays.asList(availableTimes).contains(frameTime)) { - displayTimes[i] = frameTime; - } - } - timeMatchingMap.put(pair.getResource(), displayTimes); - availableTimes = pair.getResource().getDataTimes(); - // request any new times. - if (requery - && pair.getResourceData() instanceof AbstractRequestableResourceData) { AbstractRequestableResourceData arrd = (AbstractRequestableResourceData) pair .getResourceData(); + DataTime[] availableTimes = arrd.getAvailableTimes(); + DataTime[] frameTimes = descriptor.getTimeMatchingMap().get( + this); + DataTime[] displayTimes = timeMatch(frameTimes, availableTimes); + // request any new times. PluginDataObject[] pdos = arrd.getLatestPluginDataObjects( displayTimes, availableTimes); if (pdos.length > 1) { resourceData.update(pdos); + refresh(); } - } - // remove any extra times - for (DataTime availableTime : availableTimes) { - DataTime adjAvailTime = availableTime; - if (resourceData.getBinOffset() != null) { - adjAvailTime = resourceData.getBinOffset() - .getNormalizedTime(availableTime); - } - if (!dataTimes.contains(adjAvailTime) - && !Arrays.asList(displayTimes).contains(availableTime)) { - pair.getResourceData().fireChangeListeners( - ChangeType.DATA_REMOVE, availableTime); + // remove any extra times + List displayList = Arrays.asList(displayTimes); + List frameList = Arrays.asList(frameTimes); + for (DataTime availableTime : pair.getResource().getDataTimes()) { + DataTime adjAvailTime = availableTime; + if (resourceData.getBinOffset() != null) { + adjAvailTime = resourceData.getBinOffset() + .getNormalizedTime(availableTime); + } + if (!frameList.contains(adjAvailTime) + && !displayList.contains(availableTime)) { + pair.getResourceData().fireChangeListeners( + ChangeType.DATA_REMOVE, availableTime); + } } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); } } } + /** + * Attempt to match the times for the mosaic with the times for an individual radar. + * + * @param frameTimes the frame times for the mosaic resource + * @param availableTimes the times for a radar within a mosaic + * @return + */ + private DataTime[] timeMatch(DataTime[] frameTimes, + DataTime[] availableTimes) { + DataTime[] displayTimes = new DataTime[frameTimes.length]; + for (int i = 0; i < frameTimes.length; i++) { + DataTime frameTime = frameTimes[i]; + if (frameTime == null) { + continue; + } + if (resourceData.getBinOffset() != null) { + frameTime = resourceData.getBinOffset().getNormalizedTime( + frameTime); + long frameValid = frameTime.getMatchValid(); + // Match at twice the range of binOffset this makes + // things much smoother + int interval = resourceData.getBinOffset().getInterval() * 2000; + for (DataTime displayTime : availableTimes) { + if(displayTime == null){ + continue; + } + long dispValid = displayTime.getMatchValid(); + if (Math.abs(dispValid - frameValid) < interval) { + if (displayTimes[i] != null) { + long d1 = Math.abs(frameValid + - displayTimes[i].getMatchValid()); + long d2 = Math.abs(frameValid - dispValid); + if (d1 < d2) { + continue; + } + } + displayTimes[i] = displayTime; + } + } + } else if (Arrays.asList(availableTimes).contains(frameTime)) { + displayTimes[i] = frameTime; + } + } + return displayTimes; + } + /* * (non-Javadoc) * diff --git a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/util/RadarDataCubeAdapter.java b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/util/RadarDataCubeAdapter.java index 7bec38cf7c..84a691ecb2 100644 --- a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/util/RadarDataCubeAdapter.java +++ b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/util/RadarDataCubeAdapter.java @@ -161,6 +161,7 @@ public class RadarDataCubeAdapter extends PointDataCubeAdapter { if (!latestOnly) { request.addRequestField(LEVEL_FIELD); } + request.setDistinct(true); return request; } diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/TextSegmentCheck.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/TextSegmentCheck.java index 1261df7ecc..b07f02c0cf 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/TextSegmentCheck.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/TextSegmentCheck.java @@ -48,6 +48,10 @@ import com.raytheon.viz.texteditor.util.VtecUtil; * Initial creation * 25 AUG 2011 10719 rferrel Changed ugcPtrn to handle multi-line UGCs * 01 SEP 2011 10764 rferrel Allow multiple bullet types for given Vtec. + * 20 JUL 2012 15003 mgamazaychikov Allow standalone MWS have no headline + * Add vtec to checkHeadline signature + * 20 JUL 2012 15006 mgamazaychikov Do not perform search for a list of + * county/zones names in the MWS segment heading. * * * @@ -135,7 +139,12 @@ public class TextSegmentCheck implements IQCCheck { segment = "Secondary"; ugc = ""; - errorMsg.append(checkHeadline(headline, nnn)); + /* + * DR15003 - Add vtec to signature ias n order + * to distinguish between standalone + * and followup MWS a check of VTEC is needed. + */ + errorMsg.append(checkHeadline(headline, nnn, vtec)); headline = ""; if (segmentCount > 1 @@ -221,9 +230,16 @@ public class TextSegmentCheck implements IQCCheck { if (expectNamesList) { m = listOfAreaNamePtrn.matcher(line); - if (!m.find()) { - errorMsg.append("List of county/zone names missing.\n"); - } + /* + * DR15006 - MWS does not have the list of + * marine zones names in the segment heading, + * so skip the check for MWS + */ + if ( !nnn.equalsIgnoreCase("MWS")) { + if (!m.find()) { + errorMsg.append("List of county/zone names missing.\n"); + } + } expectNamesList = false; continue; } @@ -477,12 +493,26 @@ public class TextSegmentCheck implements IQCCheck { return errorMsg; } - private String checkHeadline(String headline, String nnn) { + private String checkHeadline(String headline, String nnn, VtecObject vtec) { String errorMsg = ""; if (!QualityControl.segmentedNNN.contains(nnn) || nnn.equals("FLS")) { // non-follow ups do not have a head line return errorMsg; } + /* + * DR15003 standalone MWS can have no headline. + * To distinguish between standalone and follow up MWS + * the VTEC check is performed as standalone MWS + * do not contain VTEC + */ + if (nnn.equals("MWS") && vtec == null) { + if (headline.length() == 0) { + return errorMsg; + } else if (!headline.endsWith("...")) { + errorMsg += "Headline should end with '...'.\n"; + } + return errorMsg; + } if (headline.length() == 0) { errorMsg += "Headline is missing or malformed.\n"; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java index cb88bd0282..6808209fb6 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; +import java.util.HashMap; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; @@ -93,6 +94,7 @@ import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch; import com.raytheon.viz.warnings.DateUtil; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.io.WKTReader; @@ -111,6 +113,8 @@ import com.vividsolutions.jts.io.WKTReader; * May 9, 2012 14887 Qinglu Lin Changed one argument passed to calculatePortion(). * May 31, 2012 15047 Qinglu Lin Added additional logic to canOrExpCal for CAN and EXP. * Jun 15, 2012 15043 Qinglu Lin Added duration to context. + * Jul 16, 2012 15091 Qinglu Lin Compute intersection area, which is used for prevent 2nd timezone + * from appearing in 2nd and 3rd bullets when not necessary. * * * @@ -241,23 +245,77 @@ public class TemplateRunner { context.put(ia, intersectAreas.get(ia)); } + Map intersectSize = new HashMap(); + String[] oneLetterTZ; + double minSize = 1.0E-3d; if (areas != null && areas.length > 0) { Set timeZones = new HashSet(); for (AffectedAreas area : areas) { if (area.getTimezone() != null) { - // Handles counties that span two counties + // Handles counties that span two time zones String oneLetterTimeZones = area.getTimezone().trim(); + oneLetterTZ = new String[oneLetterTimeZones.length()]; if (oneLetterTimeZones.length() == 1) { timeZones.add(String.valueOf(oneLetterTimeZones.charAt(0))); } else { + // Determine if one letter timezone is going to be put into timeZones. + Polygon[] poly1, poly2; + int n1, n2; + double size, totalSize; for (int i = 0; i < oneLetterTimeZones.length(); i++) { - String oneLetterTimeZone = String.valueOf(oneLetterTimeZones.charAt(i)); - Geometry timezoneGeom = warngenLayer.getTimezoneGeom(oneLetterTimeZone); - if (timezoneGeom != null && GeometryUtil.intersects(warningArea, timezoneGeom)) { - timeZones.add(oneLetterTimeZone); + oneLetterTZ[i] = String.valueOf(oneLetterTimeZones.charAt(i)); + Geometry timezoneGeom = warngenLayer.getTimezoneGeom(oneLetterTZ[i]); + t0 = System.currentTimeMillis(); + poly1 = null; poly2 = null; + n1 = 0; n2 = 0; + size = 0.0d; totalSize = 0.0d; + if (timezoneGeom != null && warningArea!= null) { + if (intersectSize.get(oneLetterTZ[i]) != null) continue; + poly1 = new Polygon[warningArea.getNumGeometries()]; + n1 = warningArea.getNumGeometries(); + for (int j = 0; j < n1; j++) { + poly1[j] = (Polygon)warningArea.getGeometryN(j); + } + poly2 = new Polygon[timezoneGeom.getNumGeometries()]; + n2 = timezoneGeom.getNumGeometries(); + for (int j = 0; j < n2; j++) { + poly2[j] = (Polygon)timezoneGeom.getGeometryN(j); + } + // Calculate the total size of intersection + for (Polygon p1: poly1) { + for (Polygon p2: poly2) { + size = p1.intersection(p2).getArea(); + if (size > 0.0) + totalSize += size; + } + if (totalSize > minSize) break; //save time when the size of poly1 or poly2 is large + } + intersectSize.put(oneLetterTZ[i],totalSize); + } else + throw new VizException("Either timezoneGeom or/and warningArea is null. " + + "Timezone cannot be determined."); + System.out.println("Time to do size computation = " + + (System.currentTimeMillis() - t0)); + if (totalSize > minSize) { + timeZones.add(oneLetterTZ[i]); } } + // If timeZones has nothing in it when the hatched area is very small, + // use the timezone of larger intersection size. + if (timeZones.size() == 0 ) { + if (intersectSize.size() > 1) + if (intersectSize.get(oneLetterTZ[0]) > intersectSize.get(oneLetterTZ[1])) { + timeZones.add(oneLetterTZ[0]); + } else { + timeZones.add(oneLetterTZ[1]); + } + else + throw new VizException("The size of intersectSize is less than 1, " + + "timezone cannot be determined."); + } } + } else { + throw new VizException("Calling to area.getTimezone() returns null."); } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java index 44a5400437..eebb62648d 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java @@ -63,6 +63,7 @@ import com.raytheon.viz.warngen.gis.AffectedAreasComparator; * c)Locking does not work for areal flood advisory followup; * d)NullointException/locking does not work for special marine warning * and locking beyond first paragragh. + * Jul 17, 2012 14989 Qinglu Lin Removed locks, and , for county names in pathcast line. * * * @@ -340,6 +341,7 @@ public class WarningTextHandler { } } + boolean ruralFound=false, ruralReplace=false; ArrayList usedAreaNotations = new ArrayList(); for (int lineIndex = 0; lineIndex < seperatedLines.length; ++lineIndex) { String line = seperatedLines[lineIndex]; @@ -347,7 +349,11 @@ public class WarningTextHandler { if (line.contains("THE NATIONAL WEATHER SERVICE IN") || line.contains("OTHER LOCATIONS IMPACTED")) { before = false; } - + + if (!ruralFound && line.contains("MAINLY RURAL AREAS")) { + ruralFound = true; + } + // This prevents blank line(s) after the header from being locked. if (startLines && lineIndex > 1) { startLines = line.trim().length() == 0; @@ -419,6 +425,21 @@ public class WarningTextHandler { continue; } + if (ruralFound) + if (!ruralReplace) + ruralReplace = true; + else + if (ruralReplace) { + if (line.trim().length() == 0) + ruralFound = false; + else { + line = line.replace("",""); + line = line.replace("",""); + sb.append(line + "\n"); + continue; + } + } + if (line.trim().length() == 0) { headlineFound = false; if (smwCan) { diff --git a/deltaScripts/12.5.1/drop_gfe_tables.sh b/deltaScripts/12.5.1/drop_gfe_tables.sh old mode 100644 new mode 100755 diff --git a/edexOsgi/build.edex/esb/conf/modes.xml b/edexOsgi/build.edex/esb/conf/modes.xml index a23c27c66a..1f53de9a6d 100644 --- a/edexOsgi/build.edex/esb/conf/modes.xml +++ b/edexOsgi/build.edex/esb/conf/modes.xml @@ -58,37 +58,16 @@ nctaf-ingest.xml nctext-ingest.xml ncuair-ingest.xml - - - - - .*request.* - grib-ingest.xml - ncairep-ingest.xml - ncgrib-ingest.xml - ffmp-ingest.*.xml - scan-ingest.*.xml - cwat-ingest.*.xml - fog-ingest.*.xml - vil-ingest.*.xml - preciprate-ingest.*.xml - qpf-ingest.*.xml - fssobs-ingest.*.xml + + ffmp-ingest.xml + scan-ingest.xml + cwat-ingest.xml + fog-ingest.xml + vil-ingest.xml + preciprate-ingest.xml + qpf-ingest.xml + fssobs-ingest.xml cpgsrv-spring.xml - ncgrib-ingest.xml - - aww-ingest.xml - ncccfp-ingest.xml - ncgrib-distribution.xml - ncep-util-on-edex-ingest - ncep-util-on-edex-ingestGrib - ncscd-ingest.xml - ncpafm-ingest.xml - ncpirep-ingest.xml - nctaf-ingest.xml - nctext-ingest.xml - ncuair-ingest.xml - time-common.xml @@ -107,7 +86,7 @@ h5scd-ingest.xml - + time-common.xml ffmp-ingest.xml diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm index b0bb60993d..4f1e3eee88 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm @@ -8,7 +8,8 @@ ## Added Volcano Information for version 1.3 ## ## VERSION AWIPS II 1.4 -- JAN 26 2012 OB12.1.1-1 ## ## Cleaned up wind coding for version 1.4 ## -## VERSION AWIPS II 1.5 -- MAR 2 2012 OB12.2.1-4 ## +## VERSION AWIPS II 1.5 -- MAR 2 2012 OB12.2.1-4 ## +## BY MGAMAZAYCHIKOV -- JUL 20 2012 DR15006 ## ##################################################### ## Added Volcano Information in version 1.3 for sites where ## Volcanoes affect their marine zones. If sites wish to hide @@ -81,7 +82,7 @@ ${dateUtil.format(${now}, ${timeFormat.header}, ${localtimezone})} #if(${productClass}=="T") THIS IS A TEST MESSAGE.## #end -...THE ${warningType} IS CANCELLED... +...THE ${warningType} IS CANCELLED... THE AFFECTED AREAS WERE... #foreach (${area} in ${areas}) @@ -509,7 +510,7 @@ ${dateUtil.format(${now}, ${timeFormat.header}, ${localtimezone})} #if(${productClass}=="T") THIS IS A TEST MESSAGE.## #end -...THE ${warningType} IS CANCELLED... +...THE ${warningType} IS CANCELLED... THE AFFECTED AREAS WERE... #foreach (${area} in ${cancelareas}) @@ -922,7 +923,7 @@ ${dateUtil.format(${now}, ${timeFormat.header}, ${localtimezone})} #if(${productClass}=="T") THIS IS A TEST MESSAGE.## #end -...THE ${warningType} IS CANCELLED... +...THE ${warningType} IS CANCELLED... THE AFFECTED AREAS WERE... #foreach (${area} in ${cancelareas}) diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_RFW_MultiPil.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_RFW_MultiPil.py index 520ee6f951..39f473ef5b 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_RFW_MultiPil.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_RFW_MultiPil.py @@ -639,7 +639,7 @@ class TextProduct(GenericHazards.TextProduct): ugcState = entry['fullStateName'] else: ugcState = areaName #missing fullStateName - LogStream.logProblem(\ + LogStream.logEvent(\ "AreaDictionary missing fullStateName definition for [" + \ areaName + "].") if ugcName not in ugcList: 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 048d9b095b..8d4231b747 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 @@ -76,6 +76,7 @@ import com.raytheon.uf.edex.site.ISiteActivationListener; * Oct 26, 2010 #6811 jclark changed listener type * Apr 06, 2012 #457 dgilling Clear site's ISCSendRecords on * site deactivation. + * Jul 12, 2012 15162 ryu added check for invalid db at activation * * * @@ -335,7 +336,8 @@ public class GFESiteActivation implements ISiteActivationListener { site).get(i)); // cluster locked since IFPGridDatabase can modify the grids // based on changes to grid size, etc - db.updateDbs(); + if (db.databaseIsValid()) + db.updateDbs(); } } } finally { @@ -591,4 +593,4 @@ public class GFESiteActivation implements ISiteActivationListener { return retVal; } -} \ No newline at end of file +} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java index 6a218a98cb..e7e496b41d 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java @@ -77,6 +77,7 @@ import com.raytheon.uf.edex.database.plugin.PluginFactory; * 04/08/08 #875 bphillip Initial Creation * 06/17/08 #940 bphillip Implemented GFE Locking * 07/09/09 #2590 njensen Changed from singleton to static + * 07/12/12 15162 ryu added check for invalid db * * * @@ -1144,12 +1145,15 @@ public class GridParmManager { } } + boolean isIFP = (db == null); if (db == null) { db = new IFPGridDatabase(dbId); - ((IFPGridDatabase) db).updateDbs(); + if (db.databaseIsValid()) + ((IFPGridDatabase) db).updateDbs(); } - dbMap.put(dbId, db); + if (!isIFP || db.databaseIsValid()) + dbMap.put(dbId, db); } return db; } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java index 706437fdd2..78b7845bd2 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java @@ -100,6 +100,7 @@ import com.vividsolutions.jts.io.WKTReader; * 06/17/08 #940 bphillip Implemented GFE Locking * 06/18/08 njensen Added discrete/wx to getGridData() * 05/04/12 #574 dgilling Restructure class to better match AWIPS1. + * 07/11/12 15162 ryu No raising exception in c'tor * * * @@ -148,7 +149,7 @@ public class IFPGridDatabase extends GridDatabase { * @param dbId * The database ID for this database */ - public IFPGridDatabase(DatabaseID dbId) throws GfeException { + public IFPGridDatabase(DatabaseID dbId) { super(dbId); try { this.gridConfig = IFPServerConfigManager.getServerConfig( @@ -159,12 +160,11 @@ public class IFPGridDatabase extends GridDatabase { "Server config contains no gridDbConfig for database " + dbId.toString()); } + valid = true; } catch (GfeException e) { statusHandler.handle(Priority.PROBLEM, "Unable to get gridConfig for: " + dbId, e); - throw e; } - valid = true; } /** diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py index 0ec8296d2d..64e6eaca5a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py @@ -21,13 +21,13 @@ import string, getopt, sys, time, gzip, os, LogStream, stat, traceback import numpy -#import pupynere as NetCDF -try: - # dev environment - from Scientific.IO import NetCDF -except: - # runtime we don't have the whole scientific package - import NetCDF +import pupynere as NetCDF +#try: +# # dev environment +# from Scientific.IO import NetCDF +#except: +# # runtime we don't have the whole scientific package +# import NetCDF import JUtil import iscUtil @@ -1492,9 +1492,9 @@ def executeIfpNetCDF(host, port, outputFilename, parmList, databaseID, startTime argDict = checkArgs(argDict) - start = time.time() a = os.times() cpu0 = a[0] + a[1] + start = a[4] client = None try: @@ -1568,9 +1568,9 @@ def executeIfpNetCDF(host, port, outputFilename, parmList, databaseID, startTime fu = os.stat(argDict['outputFilename'])[stat.ST_SIZE] mb = fu / (1024.0 * 1024.0) logEvent("Uncompressed Size: ", "%-.3f" % (mb), " MBytes") - stop1 = time.time() a = os.times() cpu = a[0] + a[1] + stop1 = a[4] # Grid statistics logEvent("Original Grid Size:", origGridSize) @@ -1611,10 +1611,10 @@ def executeIfpNetCDF(host, port, outputFilename, parmList, databaseID, startTime a = os.times() cpugz = a[0] + a[1] - stop = time.time() - logEvent("Elapsed/CPU time: ", "%-.2f" % (stop1 - start), - "/", "%-.2f" % (cpu - cpu0), "processing,", "%-.2f" % (stop - stop1), "/", - "%-.2f" % (cpugz - cpu), "compress,", + stop = a[4] + logEvent("Elapsed/CPU time: ", + "%-.2f" % (stop1 - start), "/", "%-.2f" % (cpu - cpu0), "processing,", + "%-.2f" % (stop - stop1), "/", "%-.2f" % (cpugz - cpu), "compress,", "%-.2f" % (stop - start), "/", "%-.2f" % (cpugz - cpu0), "total") #logEvent("stats: ", client.getStats()) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscExtract.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscExtract.py old mode 100755 new mode 100644 index 4c9aa8138c..6c2b1ee1ae --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscExtract.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscExtract.py @@ -436,6 +436,8 @@ def executeIscExtract(parmNames, databaseName, startTime, endTime, argv.append(siteConfig.GFESUITE_PORT) argv.append("-o") argv.append(fname) + argv.append("-C") + argv.append("iscSendSampleDef") for p in dest['parms']: argv.append("-p") argv.append(p) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py index 2703d3c280..86351b0109 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py @@ -21,13 +21,13 @@ import os, stat, time, string, bisect, getopt, sys, traceback import LogStream, iscTime, iscUtil, mergeGrid -#import pupynere as netcdf -try: - # dev environment - from Scientific.IO import NetCDF -except: - # runtime we don't have the whole scientific package - import NetCDF +import pupynere as NetCDF +#try: +# # dev environment +# from Scientific.IO import NetCDF +#except: +# # runtime we don't have the whole scientific package +# import NetCDF import numpy import JUtil @@ -215,6 +215,8 @@ class IscMosaic: self.__getArgs(args) + self.__initLogger() + def logEvent(self,*msg): self.__logger.info(iscUtil.tupleToString(*msg)) @@ -322,11 +324,10 @@ class IscMosaic: self.__inFiles = JUtil.pyValToJavaObj(self.__inFiles) self.__processTimePeriod = (startTime, endTime) - self.__initLogger() - self.logEvent("iscMosaic Starting") def execute(self): - + self.logEvent("iscMosaic Starting") + # get the WxDefinition and DiscreteDefinition config = IFPServerConfigManager.getServerConfig(self.__mysite) self.__wxDef = config.getWxDefinition() @@ -348,9 +349,15 @@ class IscMosaic: for i in range(0, self.__inFiles.size()): self.__processInputFile(str(self.__inFiles.get(i))) + + self.logEvent("iscMosaic Finished") def __processInputFile(self, filename): + a = os.times() + cpu0 = a[0] + a[1] + start = a[4] + self.logEvent("Processing file=", filename) fsize = os.stat(filename)[stat.ST_SIZE] self.logEvent("Input file size: ", fsize) @@ -373,7 +380,21 @@ class IscMosaic: unzippedFile.close() os.remove(unzippedFile.name) - file = NetCDF.NetCDFFile(filename, "r") + a = os.times() + cpu = a[0] + a[1] + stop1 = a[4] + + if hasattr(NetCDF, "netcdf_file"): + # use this for pupynere + + # TODO: Remove False flag passed to constructor to resolve memory + # allocation error found in #7788. If AWIPS2 ever moves to 64-bit + # we'll probably have enough address space to allow the file to be + # memory-mapped. + file = NetCDF.netcdf_file(filename, "r", False) + else: + # use this for ScientificIO.NetCDF + file = NetCDF.NetCDFFile(filename, "r") # check version fileV = getattr(file, 'fileFormatVersion') @@ -471,6 +492,13 @@ class IscMosaic: notification = UserMessageNotification(msg, Priority.EVENTA, "ISC", self.__mysite) SendNotifications.send(notification) + a = os.times() + cpugz = a[0] + a[1] + stop = a[4] + self.logEvent("Elapsed/CPU time: ", + "%-.2f" % (stop1 - start), "/", "%-.2f" % (cpu - cpu0), "decompress,", + "%-.2f" % (stop - stop1), "/", "%-.2f" % (cpugz - cpu), "processing,", + "%-.2f" % (stop - start), "/", "%-.2f" % (cpugz - cpu0), "total") def __processParm(self, parmName, vars, history, filename): @@ -540,8 +568,8 @@ class IscMosaic: if tr is not None: inTimesProc.append(tr) try: - #self.logDebug("Processing Grid: ", parmName, \ - #" TR=", self.__printTR(tr)) + self.logDebug("Processing Grid: ", parmName, \ + " TR=", self.__printTR(tr)) # get the grid and remap it grid = self.__getGridFromNetCDF(gridType, vars, i) @@ -631,8 +659,8 @@ class IscMosaic: # get the associated db grids, merge, and store for m in merge: - #self.logDebug("Merge: ", self.__printTR(m[0]), - #self.__printTR(m[1]), m[2]) + self.logDebug("Merge: ", self.__printTR(m[0]), + self.__printTR(m[1]), m[2]) gotGrid = self.__getDbGrid(m[0]) if gotGrid is not None: @@ -698,13 +726,13 @@ class IscMosaic: if tr not in self.__dbinv: self.__dbinv = self._wec.keys() #self.__dbinv = self.__dbwe.keys() - #self.logDebug("Store:", self.__printTR(tr)) + self.logDebug("Store:", self.__printTR(tr)) else: self._wec[tr] = None self.__dbinv = self._wec.keys() #self.__dbwe[tr] = None #self.__dbinv = self.__dbwe.keys() - #self.logDebug("Erase:", self.__printTR(tr)) + self.logDebug("Erase:", self.__printTR(tr)) #--------------------------------------------------------------------- @@ -868,41 +896,41 @@ class IscMosaic: # all projections have this information data = getattr(var, "latLonLL") - inProjData['latLonLL'] = (data[0], data[1]) + inProjData['latLonLL'] = (float(data[0]), float(data[1])) data = getattr(var, "latLonUR") - inProjData['latLonUR'] = (data[0], data[1]) - inProjData['projectionType'] = getattr(var, "projectionType") + inProjData['latLonUR'] = (float(data[0]), float(data[1])) + inProjData['projectionType'] = str(getattr(var, "projectionType")) data = getattr(var, "gridPointLL") - inProjData['gridPointLL'] = (data[0], data[1]) + inProjData['gridPointLL'] = (int(data[0]), int(data[1])) data = getattr(var, "gridPointUR") - inProjData['gridPointUR'] = (data[0], data[1]) + inProjData['gridPointUR'] = (int(data[0]), int(data[1])) # lambert conformal specific information if inProjData['projectionType'] == 'LAMBERT_CONFORMAL': data = getattr(var, "latLonOrigin") - inProjData['latLonOrigin'] = (data[0], data[1]) + inProjData['latLonOrigin'] = (float(data[0]), float(data[1])) data = getattr(var, "stdParallelOne") - inProjData['stdParallelOne'] = data + inProjData['stdParallelOne'] = float(data) data = getattr(var, "stdParallelTwo") - inProjData['stdParallelTwo'] = data + inProjData['stdParallelTwo'] = float(data) # polar stereographic elif inProjData['projectionType'] == 'POLAR_STEREOGRAPHIC': data = getattr(var, "lonOrigin") - inProjData['lonOrigin'] = data + inProjData['lonOrigin'] = float(data) # mercator elif inProjData['projectionType'] == 'MERCATOR': data = getattr(var, "lonCenter") - inProjData['lonCenter'] = data + inProjData['lonCenter'] = float(data) # get specific grid sizes and domains data = getattr(var, "gridSize") - inProjData['gridSize'] = (data[0], data[1]) + inProjData['gridSize'] = (int(data[0]), int(data[1])) origin = getattr(var, "domainOrigin") extent = getattr(var, "domainExtent") inProjData['gridDomain'] = \ - ((origin[0], origin[1]), (extent[0], extent[1])) + ((float(origin[0]), float(origin[1])), (float(extent[0]), float(extent[1]))) return inProjData @@ -1148,17 +1176,17 @@ class IscMosaic: def __decodeProj(self, pdata): pid = "GrandUnifiedRemappingProj" - type = ProjectionType.valueOf(pdata["projectionType"]).ordinal() - llLL = Coordinate(float(str(pdata["latLonLL"][0])), float(str(pdata["latLonLL"][1]))) - llUR = Coordinate(float(str(pdata["latLonUR"][0])), float(str(pdata["latLonUR"][1]))) - llo = Coordinate(float(str(pdata["latLonOrigin"][0])), float(str(pdata["latLonOrigin"][1]))) - sp1 = float(pdata["stdParallelOne"]) - sp2 = float(pdata["stdParallelTwo"]) - gpll = Point(int(str(pdata["gridPointLL"][0])), int(str(pdata["gridPointLL"][1]))) - gpur = Point(int(str(pdata["gridPointUR"][0])), int(str(pdata["gridPointUR"][1]))) - lati = float(pdata["latIntersect"]) - lonc = float(pdata["lonCenter"]) - lono = float(pdata["lonOrigin"]) + type = ProjectionType.valueOf(pdata["projectionType"]) + llLL = Coordinate(pdata["latLonLL"][0], pdata["latLonLL"][1]) + llUR = Coordinate(pdata["latLonUR"][0], pdata["latLonUR"][1]) + llo = Coordinate(pdata["latLonOrigin"][0], pdata["latLonOrigin"][1]) + sp1 = pdata["stdParallelOne"] + sp2 = pdata["stdParallelTwo"] + gpll = Point(pdata["gridPointLL"][0], pdata["gridPointLL"][1]) + gpur = Point(pdata["gridPointUR"][0], pdata["gridPointUR"][1]) + lati = pdata["latIntersect"] + lonc = pdata["lonCenter"] + lono = pdata["lonOrigin"] return ProjectionData(pid, type, llLL, llUR, llo, sp1, sp2, gpll, gpur, lati, lonc, lono) diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java index 4975116462..2e990fb88c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java @@ -44,6 +44,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 11, 2010 mnash Initial creation + * Jul 16, 2012 DR 14723 D.Friedman Decompress files atomically * * * @@ -124,18 +125,21 @@ public class RadarDecompressor { } /** - * Used for things that need to write the data back out to a file + * Decompress file atomically. * - * @param messageData + * @param file + * @param headers + * @param keepHeader If true, keep any WMO/AWIPS heading found in file * @return */ - public File decompressToFile(File file, Headers headers) { - int fileSize = (int) file.length(); - byte[] messageData = new byte[fileSize]; + private File decompressToFileImpl(File file, Headers headers, boolean keepHeader) { + byte[] messageData = null; FileInputStream input = null; try { input = new FileInputStream(file); + int fileSize = (int) input.getChannel().size(); + messageData = new byte[fileSize]; input.read(messageData); } catch (FileNotFoundException e) { theHandler.handle(Priority.ERROR, e.getMessage()); @@ -151,6 +155,11 @@ public class RadarDecompressor { } } + /* + * TODO: If reading fails, the code below will NPE. Is this + * done intentionally to stop processing? + */ + String headerSearch = ""; int start = 0; if (messageData.length < 80) { @@ -164,21 +173,45 @@ public class RadarDecompressor { messageData = decompress(messageData, headers); FileOutputStream output = null; + File tmpFile = null; try { - output = new FileOutputStream(file); - } catch (FileNotFoundException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } - try { - output.write(headerSearch.getBytes()); + tmpFile = File.createTempFile(file.getName() + ".", ".decompress", file.getParentFile()); + output = new FileOutputStream(tmpFile); + if (keepHeader) + output.write(headerSearch.getBytes()); output.write(messageData); output.close(); + output = null; + if (tmpFile.renameTo(file)) + tmpFile = null; + else + theHandler.handle(Priority.ERROR, + String.format("Cannot rename %s to %s", tmpFile, file)); } catch (IOException e) { theHandler.handle(Priority.ERROR, e.getMessage()); + } finally { + if (output != null) + try { + output.close(); + } catch (IOException e) { + theHandler.handle(Priority.ERROR, "error closing file", e); + } + if (tmpFile != null) + tmpFile.delete(); } return file; } + /** + * Used for things that need to write the data back out to a file + * + * @param messageData + * @return + */ + public File decompressToFile(File file, Headers headers) { + return decompressToFileImpl(file, headers, true); + } + /** * Used for things that need to write the data back out to a file, without a * header. Same as decompressToFile, but will strip the header off before @@ -188,52 +221,7 @@ public class RadarDecompressor { * @return */ public File decompressToFileWithoutHeader(File file, Headers headers) { - int fileSize = (int) file.length(); - byte[] messageData = new byte[fileSize]; - FileInputStream input = null; - - try { - input = new FileInputStream(file); - input.read(messageData); - } catch (FileNotFoundException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } catch (IOException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } - } - } - - String headerSearch = ""; - int start = 0; - if (messageData.length < 80) { - } else { - // skip the WMO header if any - headerSearch = new String(messageData, 0, 80); - start = findStartRadarData(headerSearch); - headerSearch = headerSearch.substring(0, start); - } - - messageData = decompress(messageData, headers); - - FileOutputStream output = null; - try { - output = new FileOutputStream(file); - } catch (FileNotFoundException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } - try { - output.write(messageData); - output.close(); - } catch (IOException e) { - theHandler.handle(Priority.ERROR, e.getMessage()); - } - return file; + return decompressToFileImpl(file, headers, false); } private int findStartRadarData(String headerInfo) { diff --git a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java index 47d9f14716..a926e0576d 100644 --- a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java +++ b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java @@ -549,7 +549,8 @@ public class PostShef { break; } } - log.info(unkmsg); + log.warn(unkmsg); + stats.incrementWarningMessages(); continue; } diff --git a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/transform/shef/MetarToShefTransformer.java b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/transform/shef/MetarToShefTransformer.java index c2f618a76f..b390410395 100644 --- a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/transform/shef/MetarToShefTransformer.java +++ b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/transform/shef/MetarToShefTransformer.java @@ -19,8 +19,12 @@ **/ package com.raytheon.edex.transform.shef; +import java.sql.Date; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Iterator; +import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -90,6 +94,12 @@ public class MetarToShefTransformer extends // Transformed METAR PluginDataObject to SHEF byte[] result = null; + DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + Calendar nowCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + Calendar metarTime = TimeTools.getSystemCalendar((String) headers + .get(DecoderTools.INGEST_FILE_NAME)); + + logger.debug("report object type = " + report.getClass().getName()); incrementMessageCount(); @@ -131,6 +141,21 @@ public class MetarToShefTransformer extends } startMessageLine(sb); + metarTime=rec.getTimeObs(); + if (metarTime.compareTo(nowCalendar)> 0) { + sb.append(": WARNING: observation time is greater than the system time for the same day"); + startMessageLine(sb); + sb.append(": observation time= " + rec.getDataTime() + + " System time= "+ dateFormat.format(nowCalendar.getTime())); + startMessageLine(sb); + } else { + sb.append(": WARNING: observation time is less than the system time for the same day"); + startMessageLine(sb); + sb.append("observation time= " + rec.getDataTime() + + " System time= "+ dateFormat.format(nowCalendar.getTime())); + startMessageLine(sb); + } + sb.append(":SHEF derived data created by MetarToShefTransformer:"); startMessageLine(sb); sb.append(":TRACEID = "); diff --git a/edexOsgi/com.raytheon.uf.common.cache/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.cache/META-INF/MANIFEST.MF index c46fdf3f58..53d64f4fd6 100644 --- a/edexOsgi/com.raytheon.uf.common.cache/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.cache/META-INF/MANIFEST.MF @@ -9,4 +9,5 @@ Require-Bundle: com.raytheon.uf.common.serialization, com.raytheon.uf.common.localization, com.raytheon.uf.common.status, com.raytheon.uf.common.util -Export-Package: com.raytheon.uf.common.cache +Export-Package: com.raytheon.uf.common.cache, + com.raytheon.uf.common.cache.disk diff --git a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/DiskCache.java b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/DiskCache.java deleted file mode 100644 index 98d2cdacfd..0000000000 --- a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/DiskCache.java +++ /dev/null @@ -1,550 +0,0 @@ -package com.raytheon.uf.common.cache; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -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.LocalizationFile; -import com.raytheon.uf.common.localization.PathManagerFactory; -import com.raytheon.uf.common.serialization.DynamicSerializationManager; -import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; -import com.raytheon.uf.common.serialization.SerializationUtil; -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.common.util.SystemUtil; - -/** - * 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. - **/ - -/** - * TODO Remove old cache/hung cache. Cache should be removed on workspace exit. - * - * A object cache that writes all objects to disk. Each object is also kept in a - * map of soft references. This will allow for the cache to grow as needed and - * will objects in memory until a garbage collection is requested. Items can be - * removed from the cache if they are no longer needed. - * - * TODO Features to add: - * - * 1) Configure cache to allow hard references based on configuration (last 20 - * objects for example) - * - * 2) Specifcy a name/configuration for DiskCache's to allow for disk caches - * with different configurations. - * - *
    - * 
    - * SOFTWARE HISTORY
    - * 
    - * Date         Ticket#    Engineer    Description
    - * ------------ ---------- ----------- --------------------------
    - * Sep 5, 2011            rjpeter     Initial creation
    - * 
    - * 
    - * - * @author rjpeter - * @version 1.0 - */ - -public class DiskCache implements ICache { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(DiskCache.class.getPackage().getName(), "CAVE", - "WORKSTATION"); - - protected String name; - - protected String baseCacheDir; - - /** - * Number of items allowed in the mem cache map. Defaults to 100 items. - */ - private int sizeMemCacheMap = 100; - - // unique per jvm, configured DiskCache instance, not clusterable - protected File cacheDir; - - /** - * Should this be static or one writer thread per cache? Only have so much - * through put to disk. - */ - protected DiskCacheWriter cacheWriter = null; - - private ConcurrentMap softMetaDataMap = new ConcurrentHashMap( - 512); - - private LinkedHashMap metaDataMap = new RefMap( - 128, 0.75f, true); - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.cache.ICache#getFromCache(java.lang.String) - */ - @SuppressWarnings("unchecked") - @Override - public K getFromCache(String id) { - MetaData md = null; - K obj = null; - - // check the hard ref map - synchronized (metaDataMap) { - md = metaDataMap.get(id); - } - - if (md != null) { - obj = md.ref; - } else { - // check the soft ref map - md = softMetaDataMap.get(id); - - if (md == null) { - // object not cached - return null; - } - - if (obj == null) { - SoftReference ref = md.softRef; - if (ref != null) { - obj = ref.get(); - - if (obj != null) { - md.ref = obj; - - // cancel pending write for data if pending - cacheWriter.cancelWrite(md); - } - } - } - - if (obj == null) { - // object no longer in memory, read from disk - - try { - synchronized (md.syncObj) { - // verify data wasn't already retrieved - if (md.ref == null) { - // data wasn't pending, read from disk - File f = new File(md.cacheFilePath); - byte[] data = FileUtil.file2bytes(f); - - obj = (K) SerializationUtil - .transformFromThrift(data); - md.ref = obj; - } - } - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "Error occurred retrieving cached data from disk", - e); - } - } - - // add object back to hard cache - md.ref = obj; - md.softRef = null; - md.weakRef = null; - - synchronized (metaDataMap) { - metaDataMap.put(id, md); - } - } - - return obj; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.cache.ICache#removeFromCache(java.lang.String) - */ - @Override - public void removeFromCache(String id) { - MetaData md = null; - synchronized (metaDataMap) { - md = metaDataMap.remove(id); - } - if (md == null) { - md = softMetaDataMap.remove(id); - } else { - softMetaDataMap.remove(id); - } - - if (md != null && md.cacheFilePath != null) { - cacheWriter.cancelWrite(md); - } - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.cache.ICache#addToCache(java.lang.String, K) - */ - @Override - public void addToCache(String id, K obj) throws IOException { - MetaData md = null; - - // check map of hard refs - synchronized (metaDataMap) { - md = metaDataMap.get(id); - } - - // No hard ref, check for soft ref - if (md == null) { - md = softMetaDataMap.get(id); - } - - // no previous cache'd entry, make new one - if (md == null) { - md = new MetaData(); - md.syncObj = new Object(); - md.cacheFilePath = File.createTempFile("cache", ".bin", cacheDir) - .getAbsolutePath(); - } - - synchronized (metaDataMap) { - metaDataMap.put(id, md); - } - - md.softRef = null; - md.ref = obj; - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.cache.ICache#addToCache(K) - */ - @Override - public String addToCache(K obj) throws IOException { - MetaData md = new MetaData(); - md.syncObj = new Object(); - md.cacheFilePath = File.createTempFile("cache", ".bin", cacheDir) - .getAbsolutePath(); - - synchronized (metaDataMap) { - metaDataMap.put(md.cacheFilePath, md); - } - - md.ref = obj; - md.softRef = null; - md.weakRef = null; - - // unique id will be the unique temp file created - return md.cacheFilePath; - } - - public void closeCache() { - cacheWriter.run = false; - } - - public void clearCache() { - softMetaDataMap.clear(); - } - - public int getSizeMemCacheMap() { - return sizeMemCacheMap; - } - - public void setSizeMemCacheMap(int sizeMemCacheMap) { - this.sizeMemCacheMap = sizeMemCacheMap; - - // need to push extra entries to disk? - if (sizeMemCacheMap > metaDataMap.size()) { - synchronized (metaDataMap) { - RefMap tmp = new RefMap( - (int) (sizeMemCacheMap * 1.25) + 1, 0.75f, true); - tmp.putAll(metaDataMap); - metaDataMap = tmp; - } - } - - this.sizeMemCacheMap = sizeMemCacheMap; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getBaseCacheDir() { - return baseCacheDir; - } - - public void setBaseCacheDir(String baseCacheDir) { - this.baseCacheDir = baseCacheDir; - } - - public void activateCache() { - int pid = SystemUtil.getPid(); - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext userContext = pathMgr.getContext( - LocalizationType.CAVE_STATIC, LocalizationLevel.WORKSTATION); - - if (baseCacheDir == null) { - baseCacheDir = "diskCache"; - } - - String path = baseCacheDir + File.separator + name + File.separator - + File.separator + "pid_" + pid; - this.cacheDir = PathManagerFactory.getPathManager().getFile( - userContext, path); - - if (!cacheDir.exists()) { - cacheDir.mkdirs(); - } - - if (cacheWriter == null) { - cacheWriter = new DiskCacheWriter(name); - cacheWriter.start(); - } - - CacheFactory factory = CacheFactory.getInstance(); - factory.addCache(name, this); - - // TODO: Throw exception if not properly configured - } - - public void activateEdexCache() { - int pid = SystemUtil.getPid(); - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext context = pathMgr.getContext( - LocalizationType.EDEX_STATIC, LocalizationLevel.SITE); - - if (baseCacheDir == null) { - baseCacheDir = "diskCache"; - } - - String path = baseCacheDir + File.separator + name + File.separator - + File.separator + "pid_" + pid; - try { - LocalizationFile dir = PathManagerFactory.getPathManager() - .getLocalizationFile(context, path); - this.cacheDir = dir.getFile(); - } catch (Exception e) { - // no localization file exists - this.cacheDir = new File(path); - } - - if (!cacheDir.exists()) { - cacheDir.mkdirs(); - } - - if (cacheWriter == null) { - cacheWriter = new DiskCacheWriter(name); - cacheWriter.start(); - } - - CacheFactory factory = CacheFactory.getInstance(); - factory.addCache(name, this); - - // TODO: Throw exception if not properly configured - } - - protected class MetaData { - private Object syncObj = null; - - private String cacheFilePath = null; - - private SoftReference softRef = null; - - private WeakReference weakRef = null; - - private K ref = null; - } - - protected class RefMap extends - LinkedHashMap { - - /** - * - */ - public RefMap() { - super(); - // TODO Auto-generated constructor stub - } - - /** - * @param initialCapacity - * @param loadFactor - * @param accessOrder - */ - public RefMap(int initialCapacity, float loadFactor, boolean accessOrder) { - super(initialCapacity, loadFactor, accessOrder); - // TODO Auto-generated constructor stub - } - - /** - * @param initialCapacity - * @param loadFactor - */ - public RefMap(int initialCapacity, float loadFactor) { - super(initialCapacity, loadFactor); - // TODO Auto-generated constructor stub - } - - /** - * @param initialCapacity - */ - public RefMap(int initialCapacity) { - super(initialCapacity); - // TODO Auto-generated constructor stub - } - - /** - * @param m - */ - public RefMap(Map m) { - super(m); - // TODO Auto-generated constructor stub - } - - @Override - protected boolean removeEldestEntry(Entry eldest) { - boolean rval = size() > sizeMemCacheMap; - - if (rval) { - MetaData md = eldest.getValue(); - md.softRef = new SoftReference(md.ref); - cacheWriter.asyncWrite(md); - md.ref = null; - softMetaDataMap.put(eldest.getKey(), eldest.getValue()); - } - - return rval; - } - } - - protected class DiskCacheWriter extends Thread { - protected boolean run = true; - - protected ReferenceQueue pendingWrites = new ReferenceQueue(); - - private Map, MetaData> dataMap = new HashMap, MetaData>(); - - public DiskCacheWriter(String name) { - super(name); - } - - public void asyncWrite(MetaData md) { - synchronized (dataMap) { - // if we are currently writing to disk, let that flush finish - // before continuing - while (pendingWrites.poll() != null) { - try { - dataMap.wait(); - } catch (InterruptedException e) { - - } - } - - md.weakRef = new WeakReference(md.ref, pendingWrites); - dataMap.put(md.weakRef, md); - } - } - - public void cancelWrite(MetaData md) { - synchronized (dataMap) { - dataMap.remove(md.weakRef); - } - - synchronized (md.syncObj) { - // wait for any pending writes to finish - } - } - - @Override - public void run() { - while (run) { - try { - Reference ref = pendingWrites.remove(60000); - if (ref != null) { - MetaData md = null; - - // verify write wasn't cancelled - synchronized (dataMap) { - md = dataMap.get(ref); - } - - if (md != null) { - synchronized (md.syncObj) { - if (md.ref == null && md.softRef != null) { - K dataObject = md.softRef.get(); - OutputStream os = null; - - try { - File f = new File(md.cacheFilePath); - - if (dataObject != null) { - // serialize object and write data - // to disk - os = new BufferedOutputStream( - new FileOutputStream(f)); - DynamicSerializationManager dsm = DynamicSerializationManager - .getManager(SerializationType.Thrift); - dsm.serialize(dataObject, os); - - dataObject = null; - f.deleteOnExit(); - } else { - // delete file - f.delete(); - } - } finally { - synchronized (dataMap) { - dataMap.notifyAll(); - } - } - - md.softRef = null; - md.weakRef = null; - } - } - } - } - } catch (Throwable e) { - statusHandler.handle(Priority.ERROR, - "Error occurred writing data to disk cache", e); - } - } - } - } -} diff --git a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/ICache.java b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/ICache.java index 2942915de4..2a423a1367 100644 --- a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/ICache.java +++ b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/ICache.java @@ -43,48 +43,69 @@ import com.raytheon.uf.common.serialization.SerializationException; public interface ICache { - /** - * Returns the cache'd object. Do not hold on to object or keep a reference - * to it for extended period. This will making caching not work as well. An - * internal memory cache is kept of the object that is managed for memory - * efficiency. Do no manually manage memory of object. - * - * @param id - * @return The object from the cache or null if the object was not in the - * cache. - */ - public abstract K getFromCache(String id); + /** + * Returns the cache'd object. If you need to edit the object call + * getFromCache(String, true). Do not hold on to object or keep a reference + * to it for extended period. This will making caching not work as well. An + * internal memory cache is kept of the object that is managed for memory + * efficiency. Do no manually manage memory of object. + * + * @param id + * @param lockForEdit + * @return The object from the cache or null if the object was not in the + * cache. + */ + public abstract K getFromCache(String id); - /** - * Removes the object and any related meta data from the cache. - * - * @param id - */ - public abstract void removeFromCache(String id); + /** + * Returns the cache'd object. If the object is going to be edited you must + * pass true for lockForEdit. This will guarantee the object will not be + * cached out avoiding concurrent mod exception and also will ensure the + * object gets written back to disk. Note: any planned editing must still be + * externally synchronized if done from multiple threads. When the object is + * done being edited, addToCache must be called to release the object from + * editing. Do not hold on to object or keep a reference to it for extended + * period. This will making caching not work as well. An internal memory + * cache is kept of the object that is managed for memory efficiency. Do no + * manually manage memory of object. + * + * @param id + * @param lockForEdit + * @return The object from the cache or null if the object was not in the + * cache. + */ + public abstract K getFromCache(String id, boolean lockForEdit); - /** - * Object must implement dynamic serialize to be cached. If object is - * changed after addToCache is called, change is not persisted to disk until - * addToCache is called again. Change may be available in the pure memory - * first level cache if the object has not been evicted. - * - * @param id - * @param obj - */ - public abstract void addToCache(String id, K obj) - throws SerializationException, IOException; + /** + * Removes the object and any related meta data from the cache. + * + * @param id + */ + public abstract void removeFromCache(String id); - /** - * Object must implement dynamic serialize to be cached. If object is - * changed after addToCache is called, change is not persisted to disk until - * addToCache is called again. Change may be available in the pure memory - * first level cache if the object has not been evicted. - * - * @param obj - * @return The id of the object for retrievals from cache. - * @throws SerializationException - * @throws IOException - */ - public abstract String addToCache(K obj) throws SerializationException, - IOException; + /** + * Object must implement dynamic serialize to be cached. If object is + * changed after addToCache is called, change is not persisted to disk until + * addToCache is called again. Change may be available in the pure memory + * first level cache if the object has not been evicted. + * + * @param id + * @param obj + */ + public abstract void addToCache(String id, K obj) + throws SerializationException, IOException; + + /** + * Object must implement dynamic serialize to be cached. If object is + * changed after addToCache is called, change is not persisted to disk until + * addToCache is called again. Change may be available in the pure memory + * first level cache if the object has not been evicted. + * + * @param obj + * @return The id of the object for retrievals from cache. + * @throws SerializationException + * @throws IOException + */ + public abstract String addToCache(K obj) throws SerializationException, + IOException; } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCache.java b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCache.java new file mode 100644 index 0000000000..38be03b234 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCache.java @@ -0,0 +1,500 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.cache.disk; + +import java.io.File; +import java.io.IOException; +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.raytheon.uf.common.cache.CacheFactory; +import com.raytheon.uf.common.cache.ICache; +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.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.SerializationUtil; +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.common.util.SystemUtil; + +/** + * A object cache that writes all objects to disk. Each object is also kept in a + * map of soft references. This will allow for the cache to grow as needed and + * will objects in memory until a garbage collection is requested. Items can be + * removed from the cache if they are no longer needed. + * + * TODO Features to add: + * + * 1) Configure cache to allow hard references based on configuration (last 20 + * objects for example) + * + * 2) Specifcy a name/configuration for DiskCache's to allow for disk caches + * with different configurations. + * + *
    + * 
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    Engineer    Description
    + * ------------ ---------- ----------- --------------------------
    + * Sep 5, 2011            rjpeter     Initial creation
    + * 
    + * 
    + * + * @author rjpeter + * @version 1.0 + */ + +public class DiskCache implements ICache { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(DiskCache.class.getPackage().getName(), "CAVE", + "WORKSTATION"); + + /** + * Should this be static or one writer thread per cache? Only have so much + * through put to disk. + */ + protected static final DiskCacheWriter cacheWriter; + + static { + cacheWriter = new DiskCacheWriter(); + cacheWriter.start(); + } + + protected String name; + + protected String baseCacheDir; + + /** + * Number of items allowed in the mem cache map. Defaults to 100 items. + */ + private int sizeMemCacheMap = 100; + + // unique per jvm, configured DiskCache instance, not clusterable + protected File cacheDir; + + protected static final int MAX_PENDING_WRITES_PER_THREAD = 2; + + /** + * Contains objects that are in edit or have been evicted from in memory + * cache. + */ + private Map> metaDataMap = new HashMap>( + 128, 0.75f); + + /** + * Cached objects + */ + private LinkedHashMap> cacheMap = new RefMap>( + 128, 0.75f, true); + + private Object mapSyncLock = new Object(); + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.cache.ICache#getFromCache(java.lang.String) + */ + @Override + public K getFromCache(String id) { + return getFromCache(id, false); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.cache.ICache#getFromCache(java.lang.String, + * boolean) + */ + @SuppressWarnings("unchecked") + @Override + public K getFromCache(String id, boolean lockForEdit) { + MetaData md = null; + + // get the meta data object + synchronized (mapSyncLock) { + md = cacheMap.get(id); + if (md == null) { + md = metaDataMap.get(id); + if (md != null && md.numLockRequests.get() == 0 && !lockForEdit) { + // move to cacheMap if not locked for edit and not going to + // lock for edit + cacheMap.put(id, md); + metaDataMap.remove(id); + } + } + + if (md != null && lockForEdit + && md.numLockRequests.getAndIncrement() == 0) { + // wasn't previously locked, and now needs to be locked + metaDataMap.put(id, md); + cacheMap.remove(id); + } + } + + if (md == null) { + // object not cached + return null; + } + + K obj = md.ref; + + if (obj == null) { + // check the soft reference + SoftReference ref = md.softRef; + + if (ref != null) { + obj = ref.get(); + + if (obj != null) { + md.ref = obj; + + // cancel pending write for data if pending + md.modified = cacheWriter.cancelWrite(md); + } + + // clear the soft reference + md.softRef = null; + } + + if (obj == null) { + // object no longer in memory, read from disk + + synchronized (md.syncObj) { + // verify data wasn't already retrieved + if (md.ref == null) { + int tries = 0; + boolean retry = true; + while (retry) { + File f = new File(md.cacheFilePath); + + try { + // read from disk + if (f.exists()) { + int timeWaited = 0; + while (f.length() == 0 && timeWaited < 1000) { + // file should never be zero size, wait + // for I/O operation to complete + try { + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore + } + timeWaited += 50; + } + + byte[] data = FileUtil.file2bytes(f); + + obj = (K) SerializationUtil + .transformFromThrift(data); + md.ref = obj; + } + + retry = false; + } catch (Exception e) { + if (tries++ < 2) { + statusHandler.handle(Priority.INFO, + "Problem occurred retrieving cached data from disk: [" + + md.cacheFilePath + + "], size[" + f.length() + + "], retrying", e); + + } else { + retry = false; + statusHandler.handle(Priority.ERROR, + "Failed to retrieve cached data from disk " + + tries + " times: [" + + md.cacheFilePath + + "], size[" + f.length() + + "]", e); + } + } + } + } else { + obj = md.ref; + } + } + } + } + + return obj; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.cache.ICache#removeFromCache(java.lang.String) + */ + @Override + public void removeFromCache(String id) { + MetaData md = null; + synchronized (mapSyncLock) { + md = cacheMap.remove(id); + if (md == null) { + md = metaDataMap.remove(id); + } + } + + if (md != null && md.cacheFilePath != null) { + cacheWriter.cancelWrite(md); + File f = new File(md.cacheFilePath); + if (f.exists()) { + f.delete(); + } + } + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.cache.ICache#addToCache(java.lang.String, K) + */ + @Override + public void addToCache(String id, K obj) throws IOException { + MetaData md = null; + + // check map for refs + synchronized (mapSyncLock) { + md = cacheMap.get(id); + if (md == null) { + md = metaDataMap.get(id); + + if (md != null && md.numLockRequests.get() > 0) { + if (md.numLockRequests.decrementAndGet() == 0) { + cacheMap.put(id, md); + metaDataMap.remove(id); + } + } + } + } + + // no previous cache'd entry, make new one + if (md == null) { + md = new MetaData(id, File.createTempFile("cache", ".bin", + cacheDir).getAbsolutePath(), obj); + + synchronized (mapSyncLock) { + cacheMap.put(id, md); + } + } + + md.ref = obj; + md.softRef = null; + md.modified = true; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.cache.ICache#addToCache(K) + */ + @Override + public String addToCache(K obj) throws IOException { + MetaData md = new MetaData(File.createTempFile("cache", ".bin", + cacheDir).getAbsolutePath(), obj); + + md.softRef = null; + md.modified = true; + + synchronized (mapSyncLock) { + cacheMap.put(md.cacheFilePath, md); + } + + // unique id will be the unique temp file created + return md.id; + } + + public void closeCache() { + // cacheWriter.run = false; + // TODO: set flag that cache is closed that throws errors on access + clearCache(); + } + + public void clearCache() { + synchronized (mapSyncLock) { + // cancel the writes + for (MetaData md : cacheMap.values()) { + cacheWriter.cancelWrite(md); + } + for (MetaData md : metaDataMap.values()) { + cacheWriter.cancelWrite(md); + } + // delete the files + for (MetaData md : cacheMap.values()) { + File f = new File(md.cacheFilePath); + if (f.exists()) { + f.delete(); + } + } + for (MetaData md : metaDataMap.values()) { + File f = new File(md.cacheFilePath); + if (f.exists()) { + f.delete(); + } + } + + cacheMap.clear(); + metaDataMap.clear(); + } + } + + public int getSizeMemCacheMap() { + return sizeMemCacheMap; + } + + public void setSizeMemCacheMap(int sizeMemCacheMap) { + this.sizeMemCacheMap = sizeMemCacheMap; + + // need to push extra entries to disk? + synchronized (mapSyncLock) { + if (sizeMemCacheMap > cacheMap.size()) { + RefMap> tmp = new RefMap>( + (int) (sizeMemCacheMap * 1.25) + 1, 0.75f, true); + tmp.putAll(cacheMap); + cacheMap = tmp; + } + } + + this.sizeMemCacheMap = sizeMemCacheMap; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBaseCacheDir() { + return baseCacheDir; + } + + public void setBaseCacheDir(String baseCacheDir) { + this.baseCacheDir = baseCacheDir; + } + + public void activateCache() { + int pid = SystemUtil.getPid(); + + if (baseCacheDir == null) { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext userContext = pathMgr + .getContext(LocalizationType.CAVE_STATIC, + LocalizationLevel.WORKSTATION); + String path = "diskCache" + File.separator + name + File.separator + + File.separator + "pid_" + pid; + this.cacheDir = PathManagerFactory.getPathManager().getFile( + userContext, path); + } else { + this.cacheDir = new File(baseCacheDir + File.separator + + "diskCache" + File.separator + name + File.separator + + File.separator + "pid_" + pid); + } + + if (!cacheDir.exists()) { + cacheDir.mkdirs(); + } + + CacheFactory factory = CacheFactory.getInstance(); + factory.addCache(name, this); + + // TODO: Throw exception if not properly configured + } + + public void activateEdexCache() { + int pid = SystemUtil.getPid(); + + if (baseCacheDir == null) { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext context = pathMgr.getContext( + LocalizationType.EDEX_STATIC, LocalizationLevel.SITE); + String path = "diskCache" + File.separator + name + File.separator + + File.separator + "pid_" + pid; + + try { + LocalizationFile dir = PathManagerFactory.getPathManager() + .getLocalizationFile(context, path); + this.cacheDir = dir.getFile(); + } catch (Exception e) { + // no localization file exists + this.cacheDir = new File(path); + } + } else { + this.cacheDir = new File(baseCacheDir + File.separator + + "diskCache" + File.separator + name + File.separator + + File.separator + "pid_" + pid); + } + + if (!cacheDir.exists()) { + cacheDir.mkdirs(); + } + + CacheFactory factory = CacheFactory.getInstance(); + factory.addCache(name, this); + + // TODO: Throw exception if not properly configured + } + + protected class RefMap extends + LinkedHashMap { + /** + * @param initialCapacity + * @param loadFactor + * @param accessOrder + */ + public RefMap(int initialCapacity, float loadFactor, boolean accessOrder) { + super(initialCapacity, loadFactor, accessOrder); + } + + @Override + protected boolean removeEldestEntry(Entry eldest) { + boolean rval = size() > sizeMemCacheMap; + + if (rval) { + @SuppressWarnings("unchecked") + MetaData md = eldest.getValue(); + + if (md.modified) { + md.modified = false; + cacheWriter.asyncWrite(DiskCache.this, md); + } + + md.softRef = new SoftReference(md.ref); + md.ref = null; + + synchronized (mapSyncLock) { + metaDataMap.put(eldest.getKey(), md); + } + } + + return rval; + } + } +} diff --git a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCacheWriter.java b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCacheWriter.java new file mode 100644 index 0000000000..d6556af64c --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/DiskCacheWriter.java @@ -0,0 +1,178 @@ +package com.raytheon.uf.common.cache.disk; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.raytheon.uf.common.serialization.DynamicSerializationManager; +import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; + +/** + * 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. + **/ + +public class DiskCacheWriter extends Thread { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(DiskCacheWriter.class.getPackage().getName(), "CAVE", + "WORKSTATION"); + + protected static final int MAX_PENDING_WRITES = 100; + + protected boolean run = true; + + protected Map pendingWrites = new LinkedHashMap(); + + private class Container { + DiskCache cache; + Object obj; + } + + public DiskCacheWriter() { + super("DiskCacheWriter"); + } + + public void asyncWrite(DiskCache cache, MetaData md) { + synchronized (pendingWrites) { + // if we have too many writes pending, wait for a write to + // finish + while (pendingWrites.size() >= MAX_PENDING_WRITES && run) { + try { + pendingWrites.wait(1000); + } catch (InterruptedException e) { + } + } + + Container c = new Container(); + c.cache = cache; + c.obj = md.ref; + pendingWrites.put(md, c); + pendingWrites.notify(); + } + } + + /** + * Cancels a pending write. If a write was pending, returns true. + * + * @param md + * @return + */ + public boolean cancelWrite(MetaData md) { + boolean rval = false; + synchronized (pendingWrites) { + rval = (pendingWrites.remove(md) != null); + } + + synchronized (md.syncObj) { + // wait for any pending writes to finish + } + + return rval; + } + + @Override + public void run() { + while (run) { + try { + Map.Entry entry = null; + synchronized (pendingWrites) { + if (pendingWrites.size() == 0) { + try { + pendingWrites.wait(60000); + } catch (InterruptedException e) { + // ignore + } + } + + // did we get notified or did enough time pass? + if (pendingWrites.size() > 0) { + Iterator> iter = pendingWrites + .entrySet().iterator(); + if (iter.hasNext()) { + entry = iter.next(); + iter.remove(); + } + } + } + + if (entry != null) { + MetaData md = entry.getKey(); + + synchronized (md.syncObj) { + // verify write wasn't canceled + if (md.ref == null) { + Container container = entry.getValue(); + Object dataObject = container.obj; + OutputStream os = null; + boolean success = false; + + try { + File f = new File(md.cacheFilePath); + + if (dataObject != null) { + // serialize object and write data + // to disk + os = new BufferedOutputStream( + new FileOutputStream(f)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + dsm.serialize(dataObject, os); + f.deleteOnExit(); + } else if (f.exists()) { + // data is null, delete file + f.delete(); + } + success = true; + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + statusHandler.handle(Priority.ERROR, + "Failed to close stream to cache file: " + + md.cacheFilePath, e); + } + } + + if (!success) { + // failed to save, don't evict from memory + container.cache.addToCache(md.id, + dataObject); + } + + synchronized (pendingWrites) { + // notify threads that may have been + // waiting for write to finish + pendingWrites.notifyAll(); + } + } + } + } + } + } catch (Throwable e) { + statusHandler.handle(Priority.ERROR, + "Error occurred writing data to disk cache", e); + } + } + } +} diff --git a/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/MetaData.java b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/MetaData.java new file mode 100644 index 0000000000..b966ce6033 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.cache/src/com/raytheon/uf/common/cache/disk/MetaData.java @@ -0,0 +1,66 @@ +package com.raytheon.uf.common.cache.disk; + +import java.lang.ref.SoftReference; +import java.util.concurrent.atomic.AtomicInteger; + +public class MetaData { + protected final String id; + + protected final Object syncObj; + + protected final String cacheFilePath; + + protected SoftReference softRef = null; + + protected K ref = null; + + protected boolean modified = true; + + protected AtomicInteger numLockRequests = new AtomicInteger(0); + + protected MetaData(String cacheFilePath, K ref) { + this.id = cacheFilePath; + this.cacheFilePath = cacheFilePath; + this.syncObj = new Object(); + this.ref = ref; + } + + protected MetaData(String id, String cacheFilePath, K ref) { + this.id = id; + this.cacheFilePath = cacheFilePath; + this.syncObj = new Object(); + this.ref = ref; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((cacheFilePath == null) ? 0 : cacheFilePath.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MetaData other = (MetaData) obj; + if (cacheFilePath == null) { + if (other.cacheFilePath != null) + return false; + } else if (!cacheFilePath.equals(other.cacheFilePath)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java b/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java index 8f293582b3..02e07e7cc7 100644 --- a/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java +++ b/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java @@ -23,6 +23,9 @@ package com.raytheon.uf.common.comm; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.GZIPOutputStream; import org.apache.http.Header; @@ -35,6 +38,8 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.client.entity.GzipDecompressingEntity; import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ConnectionPoolTimeoutException; +import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.AbstractHttpClient; @@ -63,6 +68,7 @@ import com.raytheon.uf.common.util.ByteArrayOutputStreamPool.ByteArrayOutputStre * 7/1/06 #1088 chammack Initial Creation. * 5/17/10 #5901 njensen Moved to common * 03/02/11 #8045 rferrel Add connect reestablished message. + * 07/17/12 #911 njensen Refactored significantly * * * @@ -80,8 +86,8 @@ public class HttpClient { private static HttpClient instance; /** - * Number of times to retry in the event of a socket exception. Default is - * 1. + * Number of times to retry in the event of a connection exception. Default + * is 1. */ private int retryCount = 1; @@ -94,6 +100,9 @@ public class HttpClient { private boolean gzipRequests = false; + /** number of requests currently in process by the application per host */ + private Map currentRequestsCount = new ConcurrentHashMap(); + private HttpClient() { connManager = new ThreadSafeClientConnManager(); DefaultHttpClient client = new DefaultHttpClient(connManager); @@ -221,166 +230,170 @@ public class HttpClient { return executePostMethod(put); } - private byte[] executePostMethod(HttpPost put) throws IOException, - HttpException, CommunicationException { + /** + * Sends the request to the server, checks the status code (in case of 404, + * 403, etc), and returns the response if there was no error code. + * + * @param put + * the request to send + * @return the response from the server + * @throws IOException + * @throws CommunicationException + */ + private HttpResponse postRequest(HttpPost put) throws IOException, + CommunicationException { + HttpResponse resp = client.execute(put); + int code = resp.getStatusLine().getStatusCode(); + if (code != SUCCESS_CODE) { + throw new CommunicationException( + "Error reading server response. Got error message: " + + EntityUtils.toString(resp.getEntity())); + } else if (previousConnectionFailed) { + previousConnectionFailed = false; + statusHandler.handle(Priority.INFO, + "Connection with server reestablished."); + } + return resp; + } + + /** + * Posts the request to the server and passes the response stream to the + * handler callback. Will also retry the request if it fails due to a + * timeout or IO problem. + * + * @param put + * the request to post + * @param handlerCallback + * the handler to handle the response stream + * @throws CommunicationException + */ + private void process(HttpPost put, IStreamHandler handlerCallback) + throws CommunicationException { int tries = 0; boolean retry = true; - // long ts = System.currentTimeMillis(); + HttpResponse resp = null; + AtomicInteger ongoing = null; - while (retry) { - retry = false; - tries++; - - try { - HttpResponse resp = client.execute(put); - int code = resp.getStatusLine().getStatusCode(); - - if (code != SUCCESS_CODE) { - throw new CommunicationException( - "Error reading server response. Got error message: " - + EntityUtils.toString(resp.getEntity())); - } else if (previousConnectionFailed) { - previousConnectionFailed = false; - statusHandler.handle(Priority.INFO, - "Connection with server reestablished."); - } - - ByteArrayOutputStream baos = null; - InputStream is = null; + try { + String host = put.getURI().getHost(); + ongoing = currentRequestsCount.get(host); + if (ongoing == null) { + ongoing = new AtomicInteger(); + currentRequestsCount.put(host, ongoing); + } + int currentCount = ongoing.incrementAndGet(); + if (currentCount > getMaxConnectionsPerHost()) { + statusHandler.debug(currentCount + " ongoing http requests to " + + host + + ". Likely waiting for free connection from pool."); + } + while (retry) { + retry = false; + tries++; + String errorMsg = null; + Exception exc = null; try { - // long t0 = System.currentTimeMillis(); - HttpEntity entity = resp.getEntity(); + resp = postRequest(put); + } catch (ConnectionPoolTimeoutException e) { + errorMsg = "Timed out waiting for http connection from pool: " + + e.getMessage(); + errorMsg += ". Currently " + ongoing.get() + + " requests ongoing"; + exc = e; + } catch (IOException e) { + errorMsg = "Error occurred communicating with server: " + + e.getMessage(); + exc = e; + } - // TODO: print error if entity larger than int, won't be - // able to deserialize - int size = (int) entity.getContentLength(); - is = entity.getContent(); - byte[] rval = null; - - if (size > 0) { - rval = new byte[size]; - int read = 0; - int index = 0; - // int count = 0; - do { - read = is.read(rval, index, rval.length - index); - - if (read > 0) { - index += read; - // count++; - } - } while (read > 0 && index != rval.length); - // long t2 = System.currentTimeMillis(); - // System.out.println("ContentLength: Read " + - // rval.length - // + " bytes in " + count + " reads, took" - // + (t2 - t0) + "ms, total round trip " - // + (t2 - ts)); + if (errorMsg != null && exc != null) { + if (tries > retryCount) { + previousConnectionFailed = true; + // close/abort connection + if (put != null) { + put.abort(); + } + errorMsg += ". Hit retry limit, aborting connection."; + throw new CommunicationException(errorMsg, exc); } else { - // grabbing an instance of the pool to use the - // underlying array so as to not create a tmp buffer all - // the time - // TODO: Update edex/jetty to set chunked=false so that - // it sends content length, currently broken as jetty is - // scrambling -128 to 63... - baos = ByteArrayOutputStreamPool.getInstance() - .getStream(); - byte[] underlyingArray = baos.getUnderlyingArray(); - int read = 0; - int index = 0; - // int count = 0; - do { - read = is.read(underlyingArray, index, - underlyingArray.length - index); - - if (read > 0) { - index += read; - // count++; - if (index == underlyingArray.length) { - baos.setCapacity(underlyingArray.length << 1); - underlyingArray = baos.getUnderlyingArray(); - } - } - } while (read > 0); - - baos.setCount(index); - rval = new byte[index]; - System.arraycopy(underlyingArray, 0, rval, 0, index); - // long t2 = System.currentTimeMillis(); - // System.out.println("Read " + rval.length + - // " bytes in " - // + count + " reads, took" + (t2 - t0) - // + "ms, total round trip " + (t2 - ts)); - } - - return rval; - } finally { - if (baos != null) { - try { - baos.close(); - } catch (IOException e) { - // ignore - } - } - - // It seems we do not need to do this with 4.1 closing the - // input stream from the entity ( 'is' at the time of - // writing ) should allow the connection to be released - - // if (put != null) { - // put.releaseConnection(); - // } - - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // ignore - } - } - - if (resp != null && resp.getEntity() != null) { - try { - EntityUtils.consume(resp.getEntity()); - } catch (IOException e) { - // if there was an error reading the input stream, - // notify but continue - statusHandler - .handle(Priority.EVENTB, - "Error reading InputStream, assuming closed", - e); - } + errorMsg += ". Retrying..."; + statusHandler.handle(Priority.INFO, errorMsg); + retry = true; } } - } catch (IOException e) { - if (tries <= retryCount) { - statusHandler.handle( - Priority.INFO, - "Error occurred communicating with server: " - + e.getMessage() + ". Retrying..."); - retry = true; - continue; - } + } - previousConnectionFailed = true; - // close/abort connection - if (put != null) { - put.abort(); - } - statusHandler.handle(Priority.EVENTA, - "IO error in HttpClient, aborting connection.", e); - throw e; + // should only be able to get here if we didn't encounter the + // exceptions above on the most recent try + processResponse(resp, handlerCallback); + } finally { + if (ongoing != null) { + ongoing.decrementAndGet(); } } + } - // This point should never be reached - CommunicationException e = new CommunicationException( - "Error ocurred while contacting host, did not get a reponse or an exception", - new Exception( - "Error ocurred while contacting host, did not get a reponse or an exception")); - statusHandler.handle(Priority.CRITICAL, e.getLocalizedMessage(), e); - throw e; + /** + * Streams the response content to the handler callback and closes the http + * connection once finished. + * + * @param resp + * the http response to stream + * @param handlerCallback + * the handler that should process the response stream + * @throws CommunicationException + */ + private void processResponse(HttpResponse resp, + IStreamHandler handlerCallback) throws CommunicationException { + InputStream is = null; + if (resp != null && resp.getEntity() != null) { + try { + is = resp.getEntity().getContent(); + handlerCallback.handleStream(is); + } catch (IOException e) { + throw new CommunicationException( + "IO error processing http response", e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + + // Closes the stream if it's still open + try { + EntityUtils.consume(resp.getEntity()); + } catch (IOException e) { + // if there was an error reading the input stream, + // notify but continue + statusHandler.handle(Priority.EVENTB, + "Error reading InputStream, assuming closed", e); + } + } + } else { + // this should be impossible to reach + throw new CommunicationException( + "Error ocurred while contacting server, did not get a reponse or an exception"); + } + } + + /** + * Posts the request and uses a DefaultInternalStreamHandler to + * automatically stream the response into a byte[]. + * + * @param put + * the post to send to the server + * @return the byte[] of the response + * @throws CommunicationException + */ + private byte[] executePostMethod(HttpPost put) + throws CommunicationException { + DefaultInternalStreamHandler handlerCallback = new DefaultInternalStreamHandler(); + this.process(put, handlerCallback); + return handlerCallback.byteResult; } /** @@ -427,91 +440,13 @@ public class HttpClient { * the message to send * @param handlerCallback * the handler callback - * @throws VizCommunicationException + * @throws CommunicationException * if an error occurred during transmission - * @throws VizException - * if an error occurred inside the callback */ public void postStreamingByteArray(String address, byte[] message, IStreamHandler handlerCallback) throws CommunicationException { - HttpPost put = new HttpPost(address); - - put.setEntity(new ByteArrayEntity(message)); - int tries = 0; - boolean retry = true; - while (retry) { - retry = false; - tries++; - try { - HttpResponse resp = client.execute(put); - int code = resp.getStatusLine().getStatusCode(); - - if (code != SUCCESS_CODE) { - throw new CommunicationException( - "Error reading server response. Got error message: " - + EntityUtils.toString(resp.getEntity())); - } else if (previousConnectionFailed) { - previousConnectionFailed = false; - statusHandler.handle(Priority.INFO, - "Connection with server reestablished."); - } - InputStream is = null; - try { - is = resp.getEntity().getContent(); - handlerCallback.handleStream(is); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // ignore - } - } - - // It seems we do not need to do this with 4.1 closing the - // input stream from the entity ( 'is' at the time of - // writing ) should allow the connection te be released - - // if (put != null) { - // put.releaseConnection(); - // } - - try { - // Do not consume if content length unknown: breaks - // compression - if (resp != null && resp.getEntity() != null) { - EntityUtils.consume(resp.getEntity()); - } - } catch (IOException e) { - // if there was an error reading the input stream, - // notify but continue - statusHandler - .handle(Priority.EVENTB, - "Error reading InputStream, assuming closed", - e); - } - } - } catch (IOException e) { - if (tries <= retryCount) { - statusHandler.handle( - Priority.INFO, - "Error occurred communicating with server: " - + e.getMessage() + ". Retrying..."); - retry = true; - continue; - } - - previousConnectionFailed = true; - // close/abort connection - if (put != null) { - put.abort(); - } - statusHandler.handle(Priority.EVENTA, - "IO error in HttpClient, aborting connection.", e); - throw new CommunicationException( - "Error ocurred while contacting host", e); - } - } + postStreamingEntity(address, new ByteArrayEntity(message), + handlerCallback); } /** @@ -526,95 +461,30 @@ public class HttpClient { * @param handlerCallback * the handler callback * @throws UnsupportedEncodingException - * @throws VizCommunicationException - * if an error occurred during transmission - * @throws VizException - * if an error occurred inside the callback + * @throws CommunicationException */ @Deprecated public void postStreamingString(String address, String message, IStreamHandler handlerCallback) throws CommunicationException, UnsupportedEncodingException { + postStreamingEntity(address, new StringEntity(message), handlerCallback); + } + + /** + * Posts an entity to the address and stream the result back. + * + * @param address + * the http address to post to + * @param entity + * an entity containing the message to send + * @param handlerCallback + * the handler callback + * @throws CommunicationException + */ + private void postStreamingEntity(String address, AbstractHttpEntity entity, + IStreamHandler handlerCallback) throws CommunicationException { HttpPost put = new HttpPost(address); - - put.setEntity(new StringEntity(message)); - int tries = 0; - boolean retry = true; - while (retry) { - retry = false; - tries++; - try { - HttpResponse resp = client.execute(put); - int code = resp.getStatusLine().getStatusCode(); - - if (code != SUCCESS_CODE) { - throw new CommunicationException( - "Error reading server response. Got error message: " - + EntityUtils.toString(resp.getEntity())); - } else if (previousConnectionFailed) { - previousConnectionFailed = false; - statusHandler.handle(Priority.INFO, - "Connection with server reestablished."); - } - - InputStream is = null; - try { - is = resp.getEntity().getContent(); - handlerCallback.handleStream(is); - } finally { - try { - if (is != null) { - is.close(); - } - } catch (IOException e) { - // ignore - } - - // It seems we do not need to do this with 4.1 closing the - // input stream from the entity ( 'is' at the time of - // writing ) should allow the connection te be released - - // if (put != null) { - // put.releaseConnection(); - // } - - try { - // Do not consume if content length unknown: breaks - // compression - if (resp != null && resp.getEntity() != null) { - EntityUtils.consume(resp.getEntity()); - } - } catch (IOException e) { - // if there was an error reading the input stream, - // notify but continue - statusHandler - .handle(Priority.EVENTB, - "Error reading InputStream, assuming closed", - e); - } - } - } catch (IOException e) { - if (tries <= retryCount) { - statusHandler.handle( - Priority.INFO, - "Error occurred communicating with server: " - + e.getMessage() + ". Retrying..."); - retry = true; - continue; - } - - previousConnectionFailed = true; - // close/abort connection - if (put != null) { - put.abort(); - } - statusHandler.handle(Priority.EVENTA, - "IO error in HttpClient, aborting connection.", e); - throw new CommunicationException( - "Error ocurred while contacting host", e); - } - } - + process(put, handlerCallback); } public void setMaxConnectionsPerHost(int maxConnections) { @@ -681,4 +551,56 @@ public class HttpClient { throws CommunicationException; } + /** + * Automatically reads a stream into a byte array and stores the byte array + * in byteResult. Should only be used internally in HttpClient with + * convenience methods that do not take an IStreamHandler as an argument. + * + */ + private static class DefaultInternalStreamHandler implements IStreamHandler { + + private byte[] byteResult; + + @Override + public void handleStream(InputStream is) throws CommunicationException { + ByteArrayOutputStream baos = ByteArrayOutputStreamPool + .getInstance().getStream(); + try { + byte[] underlyingArray = baos.getUnderlyingArray(); + int read = 0; + int index = 0; + do { + try { + read = is.read(underlyingArray, index, + underlyingArray.length - index); + } catch (IOException e) { + throw new CommunicationException( + "Error reading byte response", e); + } + + if (read > 0) { + index += read; + if (index == underlyingArray.length) { + baos.setCapacity(underlyingArray.length << 1); + underlyingArray = baos.getUnderlyingArray(); + } + } + } while (read > 0); + + baos.setCount(index); + byteResult = new byte[index]; + System.arraycopy(underlyingArray, 0, byteResult, 0, index); + } finally { + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + } + } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasin.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasin.java index a6a0e389be..43bd34031e 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasin.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasin.java @@ -153,16 +153,15 @@ public class FFMPBasin implements ISerializableObject, Cloneable { long expirationTime, boolean rate) { float dvalue = 0.0f; Date prevDate = null; + // map ordered newest first, so grab from newest date to oldest date if (afterDate.before(beforeDate) && (values.size() > 0)) { - // if (values.containsKey(beforeDate) && - // values.containsKey(afterDate)) synchronized (values) { ArrayList keys = new ArrayList(); - for (Date date : values.keySet()) { + for (Date date : values.descendingKeySet()) { if (date.before(beforeDate) && date.after(afterDate)) { keys.add(date); } @@ -178,26 +177,32 @@ public class FFMPBasin implements ISerializableObject, Cloneable { prevDate = beforeDate; } - float factor = 0; + if (val > 0.0f) { + + float factor = 0.0f; - if ((prevDate.getTime() - tdate.getTime()) > expirationTime) { - // handle the gap and accumulate the book ends of it - factor = (float) ((prevDate.getTime() - (prevDate - .getTime() - expirationTime)) / (1000.0 * 60.0 * 60.0)); - - } else { - factor = (float) ((prevDate.getTime() - tdate - .getTime()) / (1000.0 * 60.0 * 60.0)); - } - val = (val * factor); + if ((prevDate.getTime() - tdate.getTime()) > expirationTime) { + // handle the gap and accumulate the book ends + // of it + factor = (float) ((prevDate.getTime() - (prevDate + .getTime() - expirationTime)) / (1000.0 * 60.0 * 60.0)); + } else { + factor = (float) ((prevDate.getTime() - tdate + .getTime()) / (1000.0 * 60.0 * 60.0)); + } + // do absolute values so it dosen't matter which way + // you traverse the list + val = val * Math.abs(factor); + } } + dvalue += val; prevDate = key; - } } } + return dvalue; } @@ -248,7 +253,11 @@ public class FFMPBasin implements ISerializableObject, Cloneable { for (Date date : values.keySet()) { if (date.before(beforeDate) && date.after(afterDate)) { - val += values.get(date); + float val1 = values.get(date); + if (val1 > 0.0) { + val += val1; + i++; + } } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java index c2c8de7b1c..3255488b3d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java @@ -468,15 +468,19 @@ public class FFMPBasinData implements ISerializableObject { float tvalue = 0.0f; for (Long pfaf : pfaf_ids) { + FFMPBasin basin = basins.get(pfaf); if (basin != null) { - float val = basin.getAccumValue(beforeDate, afterDate, + + float val = basin.getAccumValue(afterDate, beforeDate, expirationTime, rate); + if (val > tvalue) { tvalue = val; } } } + return tvalue; } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPCacheRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPCacheRecord.java index 99f58e290a..400167c282 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPCacheRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPCacheRecord.java @@ -1,14 +1,27 @@ package com.raytheon.uf.common.dataplugin.ffmp; +import java.awt.Point; import java.io.IOException; import java.util.ArrayList; import java.util.Date; +import java.util.LinkedHashMap; import java.util.Map.Entry; import com.raytheon.uf.common.cache.CacheException; import com.raytheon.uf.common.cache.CacheFactory; -import com.raytheon.uf.common.cache.DiskCache; import com.raytheon.uf.common.cache.ICache; +import com.raytheon.uf.common.cache.disk.DiskCache; +import com.raytheon.uf.common.datastorage.IDataStore; +import com.raytheon.uf.common.datastorage.Request; +import com.raytheon.uf.common.datastorage.records.FloatDataRecord; +import com.raytheon.uf.common.datastorage.records.IDataRecord; +import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager; +import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE; +import com.raytheon.uf.common.monitor.xml.DomainXML; +import com.raytheon.uf.common.monitor.xml.SourceXML; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; /** * Cache coherent record @@ -29,185 +42,513 @@ import com.raytheon.uf.common.cache.ICache; public class FFMPCacheRecord extends FFMPRecord { - private String sourceCacheName = null; + private final String sourceCacheName; + + private final String cacheName; + private final String cacheDir; + private ArrayList hucs = new ArrayList(); - - public FFMPCacheRecord(FFMPRecord rec, String sourceCacheName) { - + + //private static final boolean useCache = !Boolean + // .getBoolean("com.raytheon.uf.common.ffmp.disableCache"); + private static final boolean useCache = false; + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPCacheRecord.class); + + + /** + * Public constructor + * @param rec + * @param sourceCacheName + * @param cacheDir + */ + public FFMPCacheRecord(FFMPRecord rec, String sourceCacheName, String cacheDir) { + this.setSiteKey(rec.getSiteKey()); this.setWfo(rec.getWfo()); this.setDataKey(rec.getDataKey()); this.setSourceName(rec.getSourceName()); this.setPluginName(rec.getPluginName()); - this.setSourceCacheName(sourceCacheName); - - } - - /** - * Data path setter - * @param dataPath - */ - private void setSourceCacheName(String sourceCacheName) { this.sourceCacheName = sourceCacheName; + this.cacheName = "FFMP-" + getWfo() + "-" + getSiteKey() + "-" +getDataKey()+ "-" + + getSourceCacheName(); + // set a default value + if (cacheDir == null) { + cacheDir = "/tmp"; + } + this.cacheDir = cacheDir; } - - + public String getSourceCacheName() { return sourceCacheName; } - + /** * */ private static final long serialVersionUID = 1L; @SuppressWarnings({ "unchecked" }) - private synchronized DiskCache getCache() { + private DiskCache getCache() { DiskCache diskCache = null; - + CacheFactory cf = CacheFactory.getInstance(); try { - diskCache = (DiskCache) CacheFactory.getInstance() - .getCache( - "FFMP-" + getWfo() + "-" + getSiteKey() + "-" - + getSourceCacheName()); - + diskCache = (DiskCache) cf.getCache(this.cacheName); } catch (CacheException e) { - if (diskCache == null) { - diskCache = createCache("FFMP-" + getWfo() + "-" + getSiteKey() - + "-" + getSourceCacheName()); - CacheFactory.getInstance().addCache( - "FFMP-" + getWfo() + "-" + getSiteKey() + "-" - + getSourceCacheName(), diskCache); - return diskCache; + synchronized (this) { + // make sure not done on another thread + try { + diskCache = (DiskCache) cf + .getCache(this.cacheName); + } catch (CacheException e1) { + diskCache = createCache(this.cacheName); + CacheFactory.getInstance().addCache(this.cacheName, + diskCache); + } } } return diskCache; } - - /** - * Get BasinData Map from cache - * @param siteKey - * @param sourceName - * @return - */ - public FFMPBasinData getBasinData(String hucName) { - - FFMPBasinData basins = null; - - if (hucName != null) { - try { - - DiskCache diskCache = getCache(); - basins = (FFMPBasinData) diskCache.getFromCache(hucName); - - if (basins == null) { - basins = new FFMPBasinData(hucName); - if (!hucs.contains(hucName)) { - hucs.add(hucName); - } - } - - } catch (Exception e) { - e.printStackTrace(); - } - } + /** + * Get BasinData Map from cache + * + * @param siteKey + * @param sourceName + * @return + */ + @Override + public FFMPBasinData getBasinData(String hucName) { + return getBasinData(hucName, false); + } + + /** + * Get BasinData Map from cache + * + * @param siteKey + * @param sourceName + * @return + */ + public FFMPBasinData getBasinData(String hucName, boolean lock) { + FFMPBasinData basins = null; - return basins; - } - - /** - * Create cache objects if needed - * @param siteKey - * @return - */ - private DiskCache createCache(String name) { - ICache cache = new DiskCache(); - DiskCache dc = (DiskCache) cache; - dc.setName(name); - dc.setSizeMemCacheMap(1); // For FFMP hold two generally COUNTY and ALL - dc.activateCache(); - - return dc; - } - - /** - * Set source record to cache - * @param siteKey - * @param sourceName - * @param record - */ - - public void setBasinData(FFMPBasinData basins, String hucName) { if (hucName != null) { - try { - synchronized (basins) { + if (useCache) { + try { DiskCache diskCache = getCache(); + basins = (FFMPBasinData) diskCache.getFromCache(hucName, lock); - try { - diskCache.addToCache(hucName, basins); - } catch (IOException e) { - e.printStackTrace(); + if (basins == null) { + basins = new FFMPBasinData(hucName); + if (!hucs.contains(hucName)) { + hucs.add(hucName); + } } + + } catch (Exception e) { + e.printStackTrace(); } - } catch (Exception e) { - e.printStackTrace(); + + } else { + basins = super.getBasinData(hucName); + } + } + + return basins; + } + + + /** + * Create cache objects if needed + * + * @param siteKey + * @return + */ + private DiskCache createCache(String name) { + ICache cache = new DiskCache(); + DiskCache dc = (DiskCache) cache; + dc.setName(name); + dc.setBaseCacheDir(getCacheDir()); + dc.setSizeMemCacheMap(2); // For FFMP hold two generally COUNTY and ALL + dc.activateCache(); + + return dc; + } + + /** + * Set source record to cache + * + * @param siteKey + * @param sourceName + * @param record + */ + @Override + public void setBasinData(FFMPBasinData basins, String hucName) { + if (hucName != null) { + if (useCache) { + try { + synchronized (basins) { + DiskCache diskCache = getCache(); + + try { + diskCache.addToCache(hucName, basins); + } catch (IOException e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + super.setBasinData(basins, hucName); } } } - - /** - * maybe this will work - * - * @param basins - * @param hucName - */ - public void setBasinBuddyData(FFMPBasinData basins, String hucName) { + /** + * Buddy File reader + * + * @param basins + * @param hucName + */ + public void setBasinBuddyData(FFMPBasinData basins, String hucName) { if (getBasinData(hucName) != null) { - - for (Entry entry : basins.getBasins().entrySet()) { - FFMPBasin basin = getBasinData(hucName).get(entry.getKey()); - if (basin != null) { - if (basin instanceof FFMPGuidanceBasin) { - FFMPGuidanceBasin gbasin = (FFMPGuidanceBasin) basin; - gbasin.getGuidValues().putAll( - ((FFMPGuidanceBasin) entry.getValue()) - .getGuidValues()); + + basins = getBasinData(hucName, true); + //System.out.println("Adding pieces Buddy Data: "+hucName+" "+getSourceName()); + + synchronized (basins) { + for (Entry entry : basins.getBasins() + .entrySet()) { + FFMPBasin basin = basins.get(entry.getKey()); + if (basin != null) { + if (basin instanceof FFMPGuidanceBasin) { + FFMPGuidanceBasin gbasin = (FFMPGuidanceBasin) basin; + gbasin.getGuidValues().putAll( + ((FFMPGuidanceBasin) entry.getValue()) + .getGuidValues()); + } else { + basin.getValues().putAll( + entry.getValue().getValues()); + } } else { - basin.getValues().putAll(entry.getValue().getValues()); + basins.put(entry.getKey(), entry.getValue()); } - } else { - getBasinData(hucName).put(entry.getKey(), entry.getValue()); } } + + setBasinData(basins, hucName); + } else { setBasinData(basins, hucName); + //System.out.println("Adding Whole Object Buddy Data: "+hucName+" "+getSourceName()); } - } - - /** - * Purges out old data + } + + /** + * Gets the Hash out of the datastore by HUC * - * @param date + * @param dataStore + * @param huc */ - public synchronized void purgeData(Date date) { + public void retrieveMapFromDataStore(IDataStore dataStore, String uri, + FFMPTemplates template, String huc, Date date, String sourceName) + throws Exception { + + FFMPBasinData fbd = null; + + boolean aggregate = true; - for (String ihuc : hucs) { - FFMPBasinData basinData = getBasinData(ihuc); - basinData.purgeData(date); + if (huc.equals("ALL")) { + aggregate = false; } + + fbd = getBasinData(huc, true); + String key = getSiteKey(); + + synchronized (template) { + + SourceXML source = FFMPSourceConfigurationManager.getInstance() + .getSource(sourceName); + + for (DomainXML domain : template.getDomains()) { + LinkedHashMap map = template.getMap(key, + domain.getCwa(), huc); + + if (map != null && map.keySet().size() > 0) { + + IDataRecord rec = null; + + try { + rec = dataStore.retrieve(uri + "/" + domain.getCwa(), + huc, Request.ALL); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "FFMPRecord: no data record for: " + uri + "/" + + domain.getCwa()); + } + + if (rec != null) { + float[] values = ((FloatDataRecord) rec).getFloatData(); + + int j = 0; + if (values != null) { + // System.err.println(sourceName); + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + for (Long pfaf : map.keySet()) { + try { + FFMPGuidanceBasin basin = (FFMPGuidanceBasin) fbd + .get(pfaf); + + if (basin == null) { + basin = new FFMPGuidanceBasin(pfaf, + aggregate); + fbd.put(pfaf, basin); + } + + if (basin.containsKey(date, sourceName)) { + if (basin + .getValue(date, sourceName) == FFMPUtils.MISSING + || basin.getValue(date, + sourceName).isNaN()) { + + float curval = basin.getValue( + date, sourceName); + + if (curval >= 0.0f + && values[j] >= 0.0f) { + basin.setValue(sourceName, + date, (curval + values[j])/ 2); + } else { + basin.setValue(sourceName, + date, values[j]); + } + + } + } else { + basin.setValue(sourceName, date, + values[j]); + } + + j++; + } catch (Exception e) { + break; + } + + } + } else { + for (Long pfaf : map.keySet()) { + try { + FFMPBasin basin = fbd.get(pfaf); + if (basin == null) { + basin = new FFMPBasin(pfaf, + aggregate); + fbd.put(pfaf, basin); + } + + if (basin.contains(date)) { + float curval = basin.getValue(date); + if (curval >= 0.0f + && values[j] >= 0.0f) { + basin.setValue(date, (curval + values[j]) / 2); + } else { + basin.setValue(date, values[j]); + } + } else { + basin.setValue(date, values[j]); + } + j++; + } catch (Exception e) { + break; + } + } + } + } + } + } + } + } + + setBasinData(fbd, huc); } /** - * Close cache + * Gets a single basin out of the dataStore + * + * @param dataStore + * @param huc */ - public void closeCache() { - getCache().clearCache(); - getCache().closeCache(); + public void retrieveBasinFromDataStore(IDataStore dataStore, String uri, + FFMPTemplates template, String huc, Date date, String sourceName, + FFMPBasin basin) { + + FFMPBasinData fbd = null; + + try { + + SourceXML source = FFMPSourceConfigurationManager.getInstance() + .getSource(sourceName); + Long pfaf = basin.getPfaf(); + fbd = getBasinData("ALL", true); + + synchronized (template) { + + for (DomainXML domain : template.getDomains()) { + + LinkedHashMap map = template.getMap(getSiteKey(), + domain.getCwa(), huc); + + if (map != null && map.get(pfaf) != null) { + + int index = 0; + for (Long pfafToCheck : map.keySet()) { + if (pfafToCheck.equals(pfaf)) { + break; + } + index++; + } + + try { + IDataRecord rec = dataStore.retrieve(uri + "/" + + domain.getCwa(), huc, Request + .buildPointRequest(new Point(index, 0))); + + if (rec != null) { + float[] values = ((FloatDataRecord) rec) + .getFloatData(); + + boolean isFFG = false; + + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + isFFG = true; + } + + if (values != null) { + // System.err.println(sourceName); + if (isFFG) { + ((FFMPGuidanceBasin) basin).setValue( + sourceName, date, values[0]); + } else { + basin.setValue(date, values[0]); + } + } + } + } catch (Throwable e) { + statusHandler.handle(Priority.PROBLEM, + "ERROR Retrieving Map for URI: " + uri + + "..." + huc); + e.printStackTrace(); + } + } + } + } + + setBasinData(fbd, "ALL"); + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, "ERROR Retrieving HUC..." + + huc); + } } - + + + /** + * Gets the Virtual Hash out of the datastore by HUC + * + * @param dataStore + * @param huc + */ + public void retrieveVirtualBasinFromDataStore(IDataStore dataStore, + String uri, FFMPTemplates template, Date date, FFMPBasin basin) { + FFMPBasinData fbd = null; + try { + boolean aggregate = false; + fbd = getBasinData("ALL", true); + String key = getDataKey(); + + for (DomainXML domain : template.getDomains()) { + + LinkedHashMap lids = template + .getVirtualGageBasins(key, domain.getCwa()); + int size = lids.size(); + + if (size > 0) { + try { + IDataRecord rec = dataStore + .retrieve(uri + "/" + domain.getCwa(), "ALL", + Request.ALL); + + if (rec != null) { + float[] values = ((FloatDataRecord) rec) + .getFloatData(); + if (values != null) { + int j = 0; + + for (Entry entry : lids + .entrySet()) { + FFMPVirtualGageBasinMetaData fvgbmd = entry + .getValue(); + FFMPVirtualGageBasin vgbasin = (FFMPVirtualGageBasin) fbd + .get(fvgbmd.getLookupId()); + if (vgbasin == null) { + vgbasin = new FFMPVirtualGageBasin( + fvgbmd.getLid(), + fvgbmd.getLookupId(), aggregate); + fbd.put(fvgbmd.getLookupId(), vgbasin); + } + vgbasin.setValue(date, values[j]); + j++; + } + } + } + } + + catch (Throwable e) { + statusHandler.handle( + Priority.PROBLEM, + "ERROR Retrieving Virtual ..." + + domain.getCwa() + " : " + "ALL"); + } + } + } + + setBasinData(fbd, "ALL"); + + } catch (Throwable e) { + statusHandler.handle(Priority.ERROR, "ERROR Retrieving Virtual..." + + "ALL"); + } + } + + + /** + * Purges out old data + * + * @param date + */ + public void purgeData(Date date) { + for (String ihuc : hucs) { + FFMPBasinData basinData = getBasinData(ihuc, true); + basinData.purgeData(date); + setBasinData(basinData, ihuc); + } + } + + /** + * Dump cache + */ + public void closeCache() { + getCache().closeCache(); + } + + public String getCacheDir() { + return cacheDir; + } + } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java index 2458ae34ac..41cc02bc04 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java @@ -19,9 +19,8 @@ **/ package com.raytheon.uf.common.dataplugin.ffmp; -import java.io.File; -import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map.Entry; @@ -29,12 +28,8 @@ import java.util.Set; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE; import com.raytheon.uf.common.monitor.xml.SourceXML; -import com.raytheon.uf.common.serialization.DynamicSerializationManager; -import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; -import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.util.FileUtil; /** @@ -62,6 +57,8 @@ public class FFMPDataContainer { private HashMap basinDataMap = new HashMap(); private String sourceName = null; + + private String filePath = null; public FFMPDataContainer() { // public unused constructor @@ -73,7 +70,7 @@ public class FFMPDataContainer { // System.out.println("Creating source: " + sourceName); } - public FFMPDataContainer(String sourceName, Set hucs) { + public FFMPDataContainer(String sourceName, ArrayList hucs) { // System.out.println("Creating source with hucs: " + sourceName); this.sourceName = sourceName; for (String huc : hucs) { @@ -105,7 +102,6 @@ public class FFMPDataContainer { * @param hucName */ public void setBasinBuddyData(FFMPBasinData basins, String hucName) { - long time = System.currentTimeMillis(); for (Entry entry : basins.getBasins().entrySet()) { FFMPBasin basin = getBasinData(hucName).get(entry.getKey()); if (basin != null) { @@ -121,8 +117,6 @@ public class FFMPDataContainer { getBasinData(hucName).put(entry.getKey(), entry.getValue()); } } - long time2 = System.currentTimeMillis(); - System.out.println("time to load HUC: " + (time2 - time) + " ms"); } /** @@ -351,6 +345,9 @@ public class FFMPDataContainer { orderedTimes.add(time); } } + + Collections.reverse(orderedTimes); + return orderedTimes; } } catch (Exception e) { @@ -461,13 +458,10 @@ public class FFMPDataContainer { public double getMaxValue(ArrayList pfafs, Date backDate, Date currDate, long expirationTime, boolean rate) { - // System.out.println("BackDate: " + backDate); - // System.out.println("CurrDate: " + currDate); - // System.out.println("expirationTime: " + (expirationTime / 1000) / - // 3600); - - return getBasinData("ALL").getAccumMaxValue(pfafs, backDate, currDate, + double val = getBasinData("ALL").getAccumMaxValue(pfafs, currDate, backDate, expirationTime, rate); + + return val; } /* @@ -479,30 +473,12 @@ public class FFMPDataContainer { } } - /** - * Write out the loader buddy files - * - * @param fileName - */ - public void writeDataContainer(String fileName, String path, String wfo) { + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getFilePath() { + return filePath; + } - if (fileName != null) { - try { - synchronized (basinDataMap) { - for (String huc : basinDataMap.keySet()) { - byte[] bdata = DynamicSerializationManager.getManager( - SerializationType.Thrift).serialize( - getBasinData(huc)); - File file = new File(path + wfo + "/" + fileName + "-" - + huc + ".bin"); - FileUtil.bytes2File(bdata, file); - } - } - } catch (SerializationException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPGuidanceBasin.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPGuidanceBasin.java index 8bb605ac50..789e091989 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPGuidanceBasin.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPGuidanceBasin.java @@ -186,15 +186,18 @@ public class FFMPGuidanceBasin extends FFMPBasin implements ISerializableObject */ public Float getValue(String sourceName, Date date, FFMPGuidanceInterpolation interpolation, long expiration) { + Float dvalue = Float.NaN; - - if (getValue(sourceName, expiration) != null) { - dvalue = getValue(date, sourceName); + Float value = getValue(date, sourceName); + + if (!value.isNaN()) { FFFGDataMgr dman = FFFGDataMgr.getInstance(); if (dman.isExpired() == false) { dvalue = dman.adjustValue(dvalue, sourceName, this.pfaf, this.countyFips); + } else { + dvalue = value; } } @@ -203,54 +206,34 @@ public class FFMPGuidanceBasin extends FFMPBasin implements ISerializableObject } /** - * get youngest key + * Get Youngest Key * * @param sourceName * @return */ public Date getMostRecent(String sourceName, long expiration) { - Date markerDate = null; - - if ((guidValues != null) && !guidValues.keySet().isEmpty()) { - markerDate = guidValues.firstKey(); - } - Date rdate = null; - // System.out.println("Highest time: " + markerDate); - if ((markerDate != null) && (guidValues.size() > 0)) { - if (guidValues.get(markerDate).containsKey(sourceName)) { - float val = guidValues.get(markerDate).get(sourceName); - if (val != FFMPUtils.MISSING) { - rdate = markerDate; - } - } - - if (rdate == null) { - // take care of interpolated guidance delays (updates to - // guidance - // data essentially) - long time1 = markerDate.getTime(); - for (Date date : guidValues.keySet()) { - - long time2 = date.getTime(); - if ((time1 - time2) < expiration) { - if (rdate == null) { - rdate = date; - } else { - if (date.before(rdate)) { - // System.out.println("New Date: " + date); - Float val = guidValues.get(rdate).get( - sourceName); - if ((val != null) && (val != FFMPUtils.MISSING)) { - return rdate; - } - } - } - } - } - } + if (guidValues != null && guidValues.size() > 0) { + + Date markerDate = guidValues.firstKey(); + + for (Date checkDate : guidValues.keySet()) { + if (guidValues.get(checkDate).containsKey(sourceName)) { + float val = guidValues.get(checkDate).get(sourceName); + if (val != FFMPUtils.MISSING) { + + long time1 = markerDate.getTime(); + long time2 = checkDate.getTime(); + + if ((time1 - time2) < expiration) { + rdate = checkDate; + } + break; + } + } + } } return rdate; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java index 60468e44e3..1451b8e874 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java @@ -109,7 +109,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements private String siteKey; @Transient - protected HashMap basinsMap = new HashMap(); + private HashMap basinsMap = new HashMap(); @Transient private int expiration = 0; @@ -346,7 +346,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements public void setBasinData(FFMPBasinData basins, String hucName) { basinsMap.put(hucName, basins); } - + /** * finds the correct basin bin by hucName to place into * @@ -388,7 +388,6 @@ public class FFMPRecord extends PersistablePluginDataObject implements } fbd = getBasinData(huc); - String key = getSiteKey(); synchronized (template) { @@ -396,7 +395,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements .getSource(sourceName); for (DomainXML domain : template.getDomains()) { - LinkedHashMap map = template.getMap(key, + LinkedHashMap map = template.getMap(getSiteKey(), domain.getCwa(), huc); if (map != null && map.keySet().size() > 0) { @@ -407,7 +406,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements rec = dataStore.retrieve(uri + "/" + domain.getCwa(), huc, Request.ALL); } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, + statusHandler.handle(Priority.DEBUG, "FFMPRecord: no data record for: " + uri + "/" + domain.getCwa()); } @@ -443,9 +442,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements if (curval >= 0.0f && values[j] >= 0.0f) { basin.setValue(sourceName, - date, curval - + values[j] - / 2); + date, (curval + values[j])/ 2); } else { basin.setValue(sourceName, date, values[j]); @@ -477,8 +474,7 @@ public class FFMPRecord extends PersistablePluginDataObject implements float curval = basin.getValue(date); if (curval >= 0.0f && values[j] >= 0.0f) { - basin.setValue(date, curval - + values[j] / 2); + basin.setValue(date, (curval + values[j])/ 2);; } else { basin.setValue(date, values[j]); } @@ -496,8 +492,6 @@ public class FFMPRecord extends PersistablePluginDataObject implements } } } - - setBasinData(fbd, huc); } /** @@ -638,8 +632,6 @@ public class FFMPRecord extends PersistablePluginDataObject implements } } } - - setBasinData(fbd, "ALL"); } /** @@ -701,9 +693,6 @@ public class FFMPRecord extends PersistablePluginDataObject implements } } } - - setBasinData(fbd, "ALL"); - } catch (Throwable e) { statusHandler.handle(Priority.ERROR, "ERROR Retrieving Virtual..." + "ALL"); @@ -777,6 +766,19 @@ public class FFMPRecord extends PersistablePluginDataObject implements return isRate; } + /** + * Purges out old data + * + * @param date + */ + public void purgeData(Date date) { + + for (String ihuc : getBasinsMap().keySet()) { + FFMPBasinData basinData = getBasinsMap().get(ihuc); + basinData.purgeData(date); + } + } + public void setSiteKey(String siteKey) { this.siteKey = siteKey; } @@ -784,5 +786,5 @@ public class FFMPRecord extends PersistablePluginDataObject implements public String getSiteKey() { return siteKey; } - + } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/DatabaseID.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/DatabaseID.java index 24540f5ed6..ffe9888f79 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/DatabaseID.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/DatabaseID.java @@ -47,8 +47,9 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdap * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 3/6/08 875 bphillip Initial Creation - * 8/19/09 2899 njensen Rewrote equals() for performance - * 5/08/12 #600 dgilling Implement clone(). + * 8/19/09 2899 njensen Rewrote equals() for performance + * 5/08/12 #600 dgilling Implement clone(). + * 6/25/12 #766 dgilling Fix isValid(). * * * @@ -247,7 +248,7 @@ public class DatabaseID implements Serializable, Comparable, */ public boolean isValid() { - return !this.format.equals("NONE"); + return !this.format.equals(DataType.NONE); } /** diff --git a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/xml/FFMPRunXML.java b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/xml/FFMPRunXML.java index 15fe33a256..d8d2ead2e0 100644 --- a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/xml/FFMPRunXML.java +++ b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/xml/FFMPRunXML.java @@ -57,6 +57,9 @@ public class FFMPRunXML implements ISerializableObject { @XmlElements({ @XmlElement(name = "domain", type = DomainXML.class) }) private ArrayList domains; + + @XmlElement(name = "cacheDir") + private String cacheDir; public void setProducts(ArrayList products) { this.products = products; @@ -211,4 +214,12 @@ public class FFMPRunXML implements ISerializableObject { } } + public void setCacheDir(String cacheDir) { + this.cacheDir = cacheDir; + } + + public String getCacheDir() { + return cacheDir; + } + } diff --git a/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonScript.java b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonScript.java index 3f7cf1ac52..9f92a1cc25 100644 --- a/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonScript.java +++ b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonScript.java @@ -54,8 +54,9 @@ import jep.JepException; * Feb 4, 2008 njensen Initial creation * Mar 21, 2008 njensen Major refactor * June 9, 2008 njensen Refactor - * Sep 18, 2009 2899 njensen Added cProfile support - * Dec 7, 2009 3310 njensen Separated some functionality up to PythonInterpreter + * Sep 18, 2009 2899 njensen Added cProfile support + * Dec 7, 2009 3310 njensen Separated some functionality up to PythonInterpreter + * Jun 26, 2012 #776 dgilling Fix leaking of global names. * * * @@ -244,10 +245,10 @@ public class PythonScript extends PythonInterpreter { } protected void cleanupArgs(List args) throws JepException { - if (args != null && args.size() > 0) { + if (args != null && !args.isEmpty()) { for (String key : args) { if (!key.equals("self")) { - jep.eval(key + " = None"); + jep.eval("del " + key); } } } diff --git a/edexOsgi/com.raytheon.uf.edex.cpgsrv/res/spring/cpgsrv-spring.xml b/edexOsgi/com.raytheon.uf.edex.cpgsrv/res/spring/cpgsrv-spring.xml index 06c340a304..1a9afb90d1 100644 --- a/edexOsgi/com.raytheon.uf.edex.cpgsrv/res/spring/cpgsrv-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.cpgsrv/res/spring/cpgsrv-spring.xml @@ -34,6 +34,7 @@ + java.lang.Throwable diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java index 43d70b9054..72c1f255e6 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java @@ -27,6 +27,9 @@ import java.util.Enumeration; import java.util.List; import org.apache.camel.CamelContext; +import org.apache.camel.Consumer; +import org.apache.camel.Route; +import org.apache.camel.impl.ServiceSupport; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -46,6 +49,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 10, 2010 5050 rjpeter Initial creation + * Jul 16, 2012 DR 15073 D. Friedman Stop consumers instead of whole context * * * @author rjpeter @@ -128,11 +132,39 @@ public class ClusteredContextManager { ClusterLockUtils.updateLockTime(taskName, contextName, System.currentTimeMillis()); - if (camelContext.getStatus().isStopped()) { + if (! camelContext.getStatus().isStarted()) camelContext.start(); + else + for (Route route: camelContext.getRoutes()) { + Consumer consumer = route.getConsumer(); + /* + * It is safe to call Consumer.start/.stop + * unconditionally (assuming the component is + * written correctly), but in order to provide + * useful logging of these events, we must perform a + * status check. + */ + if (consumer instanceof ServiceSupport) { + if (! ((ServiceSupport) consumer).getStatus().isStarted()) { + statusHandler.handle(Priority.INFO, + "Starting consumer for route " + route.getId()); + consumer.start(); + } + } else + consumer.start(); + } + } else { + for (Route route: camelContext.getRoutes()) { + Consumer consumer = route.getConsumer(); + if (consumer instanceof ServiceSupport) { + if (((ServiceSupport) consumer).getStatus().isStarted()) { + statusHandler.handle(Priority.INFO, + "Stopping consumer for route " + route.getId()); + consumer.stop(); + } + } else + consumer.stop(); } - } else if (camelContext.getStatus().isStarted()) { - camelContext.stop(); } } catch (Exception e) { statusHandler.handle(Priority.ERROR, diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMComponent.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMComponent.java index d523d93c69..c4a98f58b1 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMComponent.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMComponent.java @@ -27,6 +27,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import org.apache.camel.Endpoint; import org.apache.camel.component.direct.DirectComponent; import org.apache.camel.impl.DefaultConsumer; +import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.util.ServiceHelper; /** @@ -38,6 +39,7 @@ import org.apache.camel.util.ServiceHelper; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 18, 2008 chammack Initial creation + * Jul 16, 2012 DR 15073 D. Friedman Don't stop all consumer in doStop. * * * @@ -76,11 +78,18 @@ public class DirectVMComponent extends DirectComponent { protected void doStop() throws Exception { Collection> set = CONSUMERS .values(); - for (CopyOnWriteArrayList consumerList : set) { - ServiceHelper.stopService(consumerList); - } + + /* Stop only the consumers created through this instance of the + * component. + */ + for (CopyOnWriteArrayList consumerList : set) + for (DefaultConsumer consumer : consumerList) { + Endpoint endpoint = consumer.getEndpoint(); + if (endpoint instanceof DefaultEndpoint) + if (((DefaultEndpoint) endpoint).getComponent() == this) + ServiceHelper.stopService(consumer); + } - CONSUMERS.clear(); super.doStop(); } } diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMEndpoint.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMEndpoint.java index b1ac8c2246..a0822449b3 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMEndpoint.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/directvm/DirectVMEndpoint.java @@ -36,6 +36,7 @@ import org.apache.camel.impl.DefaultConsumer; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 18, 2008 chammack Initial creation + * Jul 16, 2012 DR 15073 D. Friedman Override correct methods * * * @@ -72,7 +73,7 @@ public class DirectVMEndpoint extends DirectEndpoint { throws Exception { return new DefaultConsumer(this, processor) { @Override - public void start() throws Exception { + protected void doStart() throws Exception { if (!allowMultipleConsumers && !consumers.isEmpty()) { throw new IllegalStateException( "Endpoint " @@ -81,12 +82,12 @@ public class DirectVMEndpoint extends DirectEndpoint { } consumers.add(this); - super.start(); + super.doStart(); } @Override - public void stop() throws Exception { - super.stop(); + protected void doStop() throws Exception { + super.doStop(); consumers.remove(this); } }; diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml index 51bfa56764..278c919249 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml @@ -8,11 +8,11 @@ - - + + - + @@ -34,4 +34,10 @@ + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java index 5eb04921b5..53fabfb6bd 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java @@ -19,15 +19,18 @@ **/ package com.raytheon.uf.edex.plugin.ffmp; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.regex.Pattern; @@ -36,10 +39,6 @@ import com.raytheon.edex.msg.DataURINotificationMessage; import com.raytheon.edex.plugin.radar.dao.RadarStationDao; import com.raytheon.edex.urifilter.URIFilter; import com.raytheon.edex.urifilter.URIGenerateMessage; -import com.raytheon.uf.common.cache.CacheException; -import com.raytheon.uf.common.cache.CacheFactory; -import com.raytheon.uf.common.cache.DiskCache; -import com.raytheon.uf.common.cache.ICache; import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinData; import com.raytheon.uf.common.dataplugin.ffmp.FFMPDataContainer; import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord; @@ -72,6 +71,8 @@ import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceIngestConfigXML; import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.ohd.AppsDefaults; +import com.raytheon.uf.common.serialization.DynamicSerializationManager; +import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -89,6 +90,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.plugin.ffmp.common.FFMPConfig; import com.raytheon.uf.edex.plugin.ffmp.common.FFMPProcessor; import com.raytheon.uf.edex.plugin.ffmp.common.FFTI; +import com.raytheon.uf.edex.plugin.ffmp.common.FFTIData; import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; /** @@ -108,1143 +110,1230 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; */ public class FFMPGenerator extends CompositeProductGenerator implements - MonitorConfigListener { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPGenerator.class); + MonitorConfigListener { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPGenerator.class); - /** - * Public constructor for FFMPGenerator - * - * @param name - * @param compositeProductType - */ - public FFMPGenerator(Executor executor) { - super(genName, productType, executor); - } + /** + * Public constructor for FFMPGenerator + * + * @param name + * @param compositeProductType + */ + public FFMPGenerator(Executor executor) { - private static final String genName = "FFMP"; + super(genName, productType, executor); + } - private static final String templateTaskName = "FFMP Template"; + /** writer thread executor **/ + public Executor writerExecutor = null; - private static final String productType = "ffmp"; + private static final String genName = "FFMP"; - /** ArrayList of domains to filter for */ - private ArrayList domains = null; + private static final String templateTaskName = "FFMP Template"; - /** template loader bool **/ - public boolean loaded = false; + private static final String productType = "ffmp"; - /** check ffg first time you run **/ - public boolean ffgCheck = false; - - /** ffti finished processing **/ - public boolean fftiDone = true; - - /** products **/ - private ConcurrentHashMap products = null; + /** ArrayList of domains to filter for */ + private ArrayList domains = null; - /** Processes map **/ - private ConcurrentHashMap processes = null; - - /** array list of sources to evaluate **/ - public ArrayList fftiSources = new ArrayList(); - - /** Stored data for FFMP/FFTI comparisons */ - private HashMap ffmpData = new HashMap(); - - /** run configuration manager **/ - public FFMPRunConfigurationManager frcm = null; - - /** source configuration manager **/ - public FFMPSourceConfigurationManager fscm = null; - - /** template config manager **/ - public FFMPTemplateConfigurationManager tempConfig = null; - - /** FFMPConfig object **/ - public FFMPConfig config = null; - - /** template **/ - public FFMPTemplates template = null; - - private IPathManager pathManager; - - public static String sharePath = AppsDefaults.getInstance().getToken( - "apps_dir") - + File.separator + "ffmp" + File.separator; - - @Override - protected void configureFilters() { - - this.pathManager = PathManagerFactory.getPathManager(); - - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " process Filter Config..."); - domains = new ArrayList(); - boolean configValid = getRunConfig().isPopulated(); - - if (configValid) { - for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { - domains = run.getDomains(); - } - } else { - - /** - * Don't have one, so create an EDEX generated default - */ - LocalizationContext commonStaticSite = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - List sites = RadarsInUseUtil.getSite(null, - RadarsInUseUtil.LOCAL_CONSTANT); - - FFMPRunXML runner = new FFMPRunXML(); - ArrayList products = new ArrayList(); - // these two are always there in default setups - ProductRunXML hpeProduct = new ProductRunXML(); - hpeProduct.setProductName("DHRMOSAIC"); - hpeProduct.setProductKey("hpe"); - products.add(hpeProduct); - - ProductRunXML biasHpeProduct = new ProductRunXML(); - biasHpeProduct.setProductName("BDHRMOSAIC"); - biasHpeProduct.setProductKey("bhpe"); - products.add(biasHpeProduct); - - ArrayList rfc = new ArrayList(); - - if (sites.isEmpty()) { - RadarStationDao dao = new RadarStationDao(); - List stations = null; - try { - stations = dao.queryByWfo(PropertiesFactory.getInstance() - .getEnvProperties().getEnvValue("SITENAME")); - } catch (DataAccessLayerException e) { - statusHandler - .handle(Priority.ERROR, - "Unable to access data object for radar station table"); - } - - for (RadarStation station : stations) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(station.getRdaId().toLowerCase()); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - - sites.add(station.getRdaId().toLowerCase()); - } - - } else { - for (String site : sites) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(site); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - } - } - - runner.setProducts(products); - - // Apply site list to all QPE types - for (String source : getSourceConfig().getQPESources()) { - SourceXML qpeSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources - if (qpeSource.getDataType().equals( - DATA_TYPE.RADAR.getDataType())) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpeSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - // We have a list of available RFC's, now find mosaic - // Apply this to all RFCFFG sources - for (String source : getSourceConfig().getGuidances()) { - SourceXML guidSource = getSourceConfig().getSource(source); - - // Auto config for RFC sources - if (guidSource.isRfc()) { - // add a source mosaic config to the Run Config - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(guidSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String dataKey : rfc) { - sicm.addDataKey(dataKey); - } - - runner.addSourceIngest(sicm); - } - } - - // Apply site list to all SCANQPF default - for (String source : getSourceConfig().getQPFSources()) { - SourceXML qpfSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources (QPFSCAN) for - // example - if (qpfSource.getSourceName().equals("QPFSCAN")) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpfSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - DomainXML domain = new DomainXML(); - domain.setPrimary(true); - domain.setCwa(commonStaticSite.getContextName()); - runner.addDomain(domain); - - getRunConfig().addFFMPRunner(runner); - getRunConfig().saveConfigXml(); - getRunConfig().setPopulated(true); - - domains.add(domain); - } - - // kick off template generation - this.getExecutor().execute(new TemplateLoader(domains)); - } - - @Override - protected void createFilters() { - // do more here if you wish - - ArrayList runners = getRunConfig().getFFMPRunners(); - ArrayList tmp = new ArrayList( - runners.size()); - - for (FFMPRunXML runner : runners) { - DomainXML domain = runner.getPrimaryDomain(); - try { - tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" - + getRFCString(runner) + ":" + domain.getCwa())); - - statusHandler.handle(Priority.INFO, "Created FFMP Filter.." - + " primary Domain: " + domain.getCwa()); - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "Couldn't create FFMP Filter.." + " primary Domain: " - + domain.getCwa() - + " this RUNNER is not a viable FFMP config."); - e.printStackTrace(); - } - } - - filters = tmp.toArray(new URIFilter[tmp.size()]); - - } - - /** - * Slight difference in the way ffmp operates as opposed to the URIFilter in - * general. - */ - @Override - public void matchURIs(DataURINotificationMessage messages) { - - if (messages instanceof DataURINotificationMessage) { - URIFilter[] filters = getFilters(); - if (filters != null) { - for (int i = 0; i < filters.length; i++) { - if (filters[i] != null) { - FFMPURIFilter filter = (FFMPURIFilter) filters[i]; - - if (loaded) { - - synchronized (filter) { - - if (filter.isMatched(messages)) { - - if (!ffgCheck) { - - filter = getFFG(filter); - filter.setValidTime(filter - .getCurrentTime()); - ffgCheck = true; - } - - dispatch(filter); - } - } - } else { - statusHandler - .debug(getGeneratorName() - + ": templates not loaded yet. Skipping product"); - } - } - } - } - } - } - - @Override - public void generateProduct(URIGenerateMessage genMessage) { - if (loaded) { - try { - long time = System.currentTimeMillis(); - this.config = new FFMPConfig( - (FFMPURIGenerateMessage) genMessage, this); - products = new ConcurrentHashMap(); - processes = new ConcurrentHashMap(); - // read config updates, make sure we don't miss something - getRunConfig().readConfigXml(); - getSourceConfig().readConfigXml(); - - if (config.getSources() != null) { - for (String source : config.getSources().keySet()) { - processes.put(source, - getSourceConfig().getSource(source)); - } - } - - // start threads - - for (String source : processes.keySet()) { - this.getExecutor().execute( - new ProcessProduct(processes.get(source), this)); - } - - // count down latch - while (processes.size() > 0) { - // wait for all threads to finish before returning - try { - Thread.sleep(200); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + processes.size()); - for (String source : processes.keySet()) { - statusHandler.handle(Priority.DEBUG, - "Still processing ..." + source); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (products.size() > 0) { - - // Do the FFTI evaluation, if we have FFTI sources - if (fftiSources.size() > 0) { - this.getExecutor().execute(new FFTI(this)); - } - - ArrayList records = new ArrayList( - products.size()); - for (String source : products.keySet()) { - for (FFMPRecord rec : products.get(source)) { - records.add(rec); - } - } - - FFMPRecord[] recs = new FFMPRecord[records.size()]; - for (int i = 0; i < records.size(); i++) { - recs[i] = records.get(i); - } - - this.setPluginDataObjects(recs); - this.setPluginDao(new FFMPDao(getCompositeProductType(), - template, fscm, config.getCWA())); - - while (fftiSources.size() > 0) { - try { - Thread.sleep(200); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + fftiDone); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - statusHandler.handle( - Priority.INFO, - config.getCWA() + " finished, duration: " - + (System.currentTimeMillis() - time) - + " ms, wrote " + records.size() + " "); - - } else { - statusHandler.handle(Priority.INFO, config.getCWA() - + " no new products to produce."); - } - - } catch (Throwable e) { - statusHandler.handle(Priority.ERROR, - "Unable to process FFMP Records."); - } - } - } - - /** - * Get the list of domains - * - * @return - */ - public ArrayList getDomains() { - return domains; - } - - /** - * Add a filtering CWA - * - * @param domain - */ - public void addDomain(DomainXML domain) { - domains.add(domain); - } - - @Override - public boolean isRunning() { - return getConfigManager().getFFMPState(); - } - - /** - * Set list of CWA's - * - * @param cwas - */ - public void setDomains(ArrayList domains) { - this.domains = domains; - } - - /** - * Inner class to thread the ffmp processing - * - * @author dhladky - * - */ - private class ProcessProduct implements Runnable { - - SourceXML ffmpProduct; - - FFMPGenerator generator; - - @Override - public void run() { - try { - logger.debug("ProcessProduct: Starting thread " - + ffmpProduct.getSourceName()); - process(); - logger.debug("ProcessProduct: Finishing thread " - + ffmpProduct.getSourceName()); - } catch (Exception e) { - processes.remove(ffmpProduct.getSourceName()); - logger.error("ProcessProduct: removed " - + ffmpProduct.getSourceName()); - e.printStackTrace(); - } - } - - public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { - this.ffmpProduct = ffmpProduct; - this.generator = generator; - } - - /** - * The actual work gets done here - */ - public void process() throws Exception { - - HashMap dataHash = config.getSourceData(ffmpProduct - .getSourceName()); - ArrayList ffmpRecords = new ArrayList( - dataHash.size()); - - FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); - - // process all of the dataKeys for this source - for (String dataKey : dataHash.keySet()) { - - ArrayList sites = new ArrayList(); - - // is it a mosaic? - if (ffmpProduct.isMosaic()) { - - // Take care of defaults, all in this case - for (ProductRunXML product : runner.getProducts()) { - // no duplicate keys! - if (!sites.contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - - // do filtering - for (ProductRunXML product : runner.getProducts()) { - // includes - if (product.hasIncludes()) { - for (String includeSourceName : product - .getIncludes()) { - if (ffmpProduct.getSourceName().equals( - includeSourceName)) { - // no duplicate keys! - if (!sites - .contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - } - } - // excludes - if (product.hasExcludes()) { - for (String excludeSourceName : product - .getExcludes()) { - if (ffmpProduct.getSourceName().equals( - excludeSourceName)) { - sites.remove(product.getProductKey()); - } - } - } - } - } else { - // No mosaic, just individual site run - String siteKey = dataKey; - - // special case for XMRG's - if (ffmpProduct.getDataType().equals( - FFMPSourceConfigurationManager.DATA_TYPE.XMRG - .getDataType())) { - - siteKey = null; - String primarySource = null; - - for (ProductXML product : getSourceConfig() - .getProducts()) { - if (product.containsSource(ffmpProduct - .getSourceName())) { - primarySource = product.getPrimarySource(); - break; - } - } - - for (ProductRunXML productRun : runner.getProducts()) { - if (productRun.getProductName().equals( - primarySource)) { - siteKey = productRun.getProductKey(); - break; - } - } - } - - sites.add(siteKey); - } - - for (String productKey : sites) { - - FFMPRecord ffmpRec = new FFMPRecord(); - ffmpRec.setSourceName(ffmpProduct.getSourceName()); - ffmpRec.setDataKey(dataKey); - ffmpRec.setSiteKey(productKey); - ffmpRec.setPluginName(getCompositeProductType()); - ffmpRec.setWfo(config.getCWA()); - FFMPProcessor ffmp = new FFMPProcessor(config, generator, - ffmpRec, template); - ffmpRec = ffmp.processFFMP(ffmpProduct); - ffmpRec.constructDataURI(); - - if (ffmpRec != null) { - - if (ffmp.isFFTI()) { - fftiDone = false; - if (!fftiSources.contains(ffmp.getFFTISource())) { - FFTIProcessor ffti = new FFTIProcessor( - generator, ffmpRec, - ffmp.getFFTISource()); - fftiSources.add(ffmp.getFFTISource()); - ffti.processFFTI(); - } - } - - // Don't write loader buddy's on long duration - // sources. Not necessary 6*60 = 360 - if (getSourceConfig() - .getSource(ffmpRec.getSourceName()) - .getExpirationMinutes(productKey) < 360) { - - processDataContainer(ffmpRec); - } - - ffmpRecords.add(ffmpRec); - } - } - } - - FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; - for (int i = 0; i < ffmpRecords.size(); i++) { - recs[i] = ffmpRecords.get(i); - } - products.put(ffmpProduct.getSourceName(), recs); - processes.remove(ffmpProduct.getSourceName()); - } - } - - /** - * Inner class to background template creation - * - * @author dhladky - * - */ - private class TemplateLoader implements Runnable { - - ArrayList templateDomains; - - DomainXML primaryDomain; - - @Override - public void run() { - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Start loader "); - - for (DomainXML domain : templateDomains) { - if (domain.isPrimary()) { - primaryDomain = domain; - } - } - - // generate templates and unify geometries - loaded = load(); - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Finishing loader "); - } - - public TemplateLoader(ArrayList templateDomains) { - this.templateDomains = templateDomains; - } - - /** - * - * @param domain - * @return - */ - public void createUnifiedGeometries(DomainXML domain) { - ArrayList hucsToGen = new ArrayList(); - hucsToGen.add("ALL"); - hucsToGen.add("COUNTY"); - - for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { - hucsToGen.add("HUC" + i); - } - - for (String huc : hucsToGen) { - template.verifyUnifiedGeometries(huc, domain.getCwa()); - } - } - - public boolean load() { - // load / create primary domain - ClusterTask task = null; - String lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); - try { - do { - task = ClusterLockUtils.lock(templateTaskName, lockDetails, - 600 * 1000, true); - } while (task.getLockState() != LockState.SUCCESSFUL); - - template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); - // setup the config - getTemplateConfig(); - createUnifiedGeometries(primaryDomain); - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - - // load the secondary domains - List domainsToGen = new ArrayList( - templateDomains); - while (domainsToGen.size() > 0) { - Iterator iter = domainsToGen.iterator(); - boolean processedDomain = false; - while (iter.hasNext()) { - DomainXML domain = iter.next(); - lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + domain.getCwa(); - try { - task = ClusterLockUtils.lock(templateTaskName, - lockDetails, 300 * 1000, false); - - if (task.getLockState() == LockState.SUCCESSFUL) { - template.addDomain(domain); - createUnifiedGeometries(domain); - iter.remove(); - processedDomain = true; - } - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - } - - if (!processedDomain) { - // Didn't process a domain, locked by another cluster - // member, sleep and try again - try { - Thread.sleep(100); - } catch (InterruptedException e) { - - } - } - } - - return template.done; - } - } - - /** - * Gets the string buffer for the RFC's - * - * @param run - * @return - */ - private String getRFCString(FFMPRunXML run) { - StringBuffer buf = new StringBuffer(); - - for (SourceIngestConfigXML ingest : run.getSourceIngests()) { - SourceXML source = FFMPSourceConfigurationManager.getInstance() - .getSource(ingest.getSourceName()); - if (source.isRfc()) { - int i = 0; - for (String dataKey : ingest.getDataKey()) { - if (i < ingest.getDataKey().size() - 1) { - buf.append(dataKey + ","); - } else { - buf.append(dataKey); - } - i++; - } - break; - } - } - return buf.toString(); - } - - /** - * Gets the string buffer for the sites, specific to RADAR type data - * - * @param run - * @return - */ - private String getSiteString(FFMPRunXML run) { - String sites = null; - StringBuffer buf = new StringBuffer(); - for (ProductRunXML product : run.getProducts()) { - SourceXML source = getSourceConfig().getSource( - product.getProductName()); - if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { - buf.append(product.getProductKey() + ","); - } - } - sites = buf.toString(); - if (sites.endsWith(",")) { - sites = sites.substring(0, sites.length() - 1); - } - return sites; - } - - /** - * Write your new SourceBins - * - * @param sourceList - */ - public void writeSourceBins(SourceBinList sourceList) { - - try { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - LocalizationFile lflist = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceList.getSourceId())); - - FileUtil.bytes2File( - SerializationUtil.transformToThrift(sourceList), - lflist.getFile(), true); - - lflist.save(); - - statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " - + sourceList.getSourceId()); - - } catch (SerializationException se) { - se.printStackTrace(); - } catch (FileNotFoundException fnfe) { - fnfe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (LocalizationOpFailedException e) { - e.printStackTrace(); - } - } - - /** - * Read out your SourceBins - * - * @param sourceId - * @return - */ - public SourceBinList readSourceBins(String sourceId) { - - SourceBinList sbl = null; - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - - try { - sbl = (SourceBinList) SerializationUtil - .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); - } catch (FileNotFoundException fnfe) { - statusHandler.handle(Priority.ERROR, - "Unable to locate file " + f.getName()); - } catch (SerializationException se) { - statusHandler.handle(Priority.ERROR, - "Unable to read file " + f.getName()); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - return sbl; - } - - /** - * Gets the completed filename - * - * @return - */ - public String getAbsoluteFileName(String sourceId) { - return "ffmp" + File.separator + "sources" + File.separator + sourceId - + ".bin"; - } - - /** - * See if you have one - * - * @param sourceId - * @return - */ - public boolean isExistingSourceBin(String sourceId) { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - return f.exists(); - } - - /** - * Gets the list of bins for that source - * - * @param sourceId - * @return - */ - public SourceBinList getSourceBinList(String sourceId) { - SourceBinList sbl = null; - - sbl = getSourceBin(sourceId); - - if (sbl == null) { - sbl = readSourceBins(sourceId); - setSourceBin(sbl, sourceId); - } - - return sbl; - } - - /** - * Sets the source bins, first time - * - * @param sbl - */ - public void setSourceBinList(SourceBinList sbl) { - - setSourceBin(sbl, sbl.getSourceId()); - writeSourceBins(sbl); - } - - /** - * Do pull strategy on FFG data - * - * @param filter - * @return - */ - private FFMPURIFilter getFFG(FFMPURIFilter filter) { - - ArrayList uris = new ArrayList(); - - for (String rfc : filter.getRFC()) { - // get a hash of the sources and their grib ids - HashMap sources = FFMPUtils.getFFGModelInfo(rfc); - if (sources != null) { - if (sources.size() > 0) { - for (String source : sources.keySet()) { - - SourceXML sourceXml = getSourceConfig().getSource( - source); - - if (sourceXml != null) { - - String plugin = getSourceConfig().getSource(source) - .getPlugin(); - uris.add(FFMPUtils.getFFGDataURI( - sources.get(source), plugin)); - } - } - } - } - } - // treat it like a regular uri in the filter. - if (uris.size() > 0) { - for (String dataUri : uris) { - // add your pattern checks to the key - for (Pattern pattern : filter.getMatchURIs().keySet()) { - statusHandler.handle(Priority.DEBUG, - "Pattern: " + pattern.toString() + " Key: " - + dataUri); - try { - if (pattern.matcher(dataUri).find()) { - // matches one of them, which one? - String matchKey = filter.getPatternName(pattern); - // put the sourceName:dataPath key into the sources - // array list - filter.getSources().put(matchKey, dataUri); - } - } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "Unable to locate new FFG file. " - + pattern.toString()); - } - } - } - } - - return filter; - } - - /** - * get the hash - * - * @return - */ - public HashMap getFFMPData() { - return ffmpData; - } - - /** - * get the FFMP data container for this source - * - * @param sourceName - * - * @return - */ - public FFMPDataContainer getFFMPDataContainer(String sourceName) { - - FFMPDataContainer container = ffmpData.get(sourceName); - - return container; - } - - /* - * Gets the FFTI sources to be run - */ - public ArrayList getFFTISources() { - return fftiSources; - } - - /** - * source config manager - * - * @return - */ - public FFMPSourceConfigurationManager getSourceConfig() { - if (fscm == null) { - fscm = FFMPSourceConfigurationManager.getInstance(); - fscm.addListener(this); - } - return fscm; - } - - /** - * run config manager - * - * @return - */ - public FFMPRunConfigurationManager getRunConfig() { - if (frcm == null) { - frcm = FFMPRunConfigurationManager.getInstance(); - frcm.addListener(this); - } - return frcm; - } - - /** - * Template config manager - * - * @return - */ - public FFMPTemplateConfigurationManager getTemplateConfig() { - if (tempConfig == null) { - tempConfig = FFMPTemplateConfigurationManager.getInstance(); - tempConfig.addListener(this); - } - return tempConfig; - } - - /** - * dispatch a filter for processing - * - * @param filter - */ - private void dispatch(FFMPURIFilter filter) { - - try { - EDEXUtil.getMessageProducer().sendAsync( - routeId, - SerializationUtil.transformToThrift(filter - .createGenerateMessage())); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, getGeneratorName() - + ": filter: " + filter.getName() - + ": failed to route filter to generator", e); - e.printStackTrace(); - } - filter.setValidTime(new Date(System.currentTimeMillis())); - filter.reset(); - } - - /** - * FFMP buddy loader - * - * @param ffmpRec - * @param siteKey - */ - private void processDataContainer(FFMPRecord ffmpRec) { - - // write out the fast loader buddy file - long time = System.currentTimeMillis(); - SourceXML source = getSourceConfig().getSource(ffmpRec.getSourceName()); - String sourceName = null; - String dataKey = null; - - if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { - sourceName = source.getDisplayName(); - dataKey = SOURCE_TYPE.GUIDANCE.getSourceType(); - } else { - sourceName = ffmpRec.getSourceName(); - dataKey = ffmpRec.getDataKey(); - } - - String sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() - + "-" + dataKey; - FFMPDataContainer fdc = ffmpData.get(sourceSiteDataKey); - - // Make a 6 hour "Buddy" loader file - Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() - - (3600 * 1000 * 6)); - - // cache management - if (fdc == null) { - fdc = loadFFMPDataContainer(sourceSiteDataKey, ffmpRec - .getBasinsMap().keySet(), ffmpRec.getSiteKey(), - ffmpRec.getWfo(), backDate); - // brand new - if (fdc == null) { - fdc = new FFMPDataContainer(sourceSiteDataKey, ffmpRec - .getBasinsMap().keySet()); - } - - fdc = FFTIProcessor.populateDataContainer(fdc, template, ffmpRec - .getBasinsMap().keySet(), backDate, ffmpRec.getDataTime() - .getRefTime(), ffmpRec.getWfo(), source, ffmpRec - .getSiteKey()); - } + /** template loader bool **/ + public boolean loaded = false; + /** check ffg first time you run **/ + public boolean ffgCheck = false; + + /** ffti finished processing **/ + public boolean fftiDone = true; + + /** products **/ + private ConcurrentHashMap products = null; + + /** Processes map **/ + private ConcurrentHashMap processes = null; + + /** array list of sources to evaluate **/ + public ArrayList fftiSources = new ArrayList(); + + /** run configuration manager **/ + public FFMPRunConfigurationManager frcm = null; + + /** source configuration manager **/ + public FFMPSourceConfigurationManager fscm = null; + + /** temp cache **/ + public ConcurrentHashMap ffmpData = new ConcurrentHashMap(); + + /** FFTI accum/ratio/diff cache **/ + public ConcurrentHashMap fftiData = new ConcurrentHashMap(); + + /** checks for initial load **/ + public ArrayList loadedData = new ArrayList(); + + /** template config manager **/ + public FFMPTemplateConfigurationManager tempConfig = null; + + /** FFMPConfig object **/ + public FFMPConfig config = null; + + /** template **/ + public FFMPTemplates template = null; + + private IPathManager pathManager; + + public static String sharePath = AppsDefaults.getInstance().getToken( + "apps_dir") + + File.separator + "ffmp" + File.separator; + + /** source bins used for finding basin to data correlations **/ + private HashMap sourceBins = new HashMap(); + + @Override + protected void configureFilters() { + + this.pathManager = PathManagerFactory.getPathManager(); + + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " process Filter Config..."); + domains = new ArrayList(); + boolean configValid = getRunConfig().isPopulated(); + + if (configValid) { + for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { + domains = run.getDomains(); + } + } else { + + /** + * Don't have one, so create an EDEX generated default + */ + LocalizationContext commonStaticSite = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + List sites = RadarsInUseUtil.getSite(null, + RadarsInUseUtil.LOCAL_CONSTANT); + + FFMPRunXML runner = new FFMPRunXML(); + ArrayList products = new ArrayList(); + // these two are always there in default setups + ProductRunXML hpeProduct = new ProductRunXML(); + hpeProduct.setProductName("DHRMOSAIC"); + hpeProduct.setProductKey("hpe"); + products.add(hpeProduct); + + ProductRunXML biasHpeProduct = new ProductRunXML(); + biasHpeProduct.setProductName("BDHRMOSAIC"); + biasHpeProduct.setProductKey("bhpe"); + products.add(biasHpeProduct); + + ArrayList rfc = new ArrayList(); + + if (sites.isEmpty()) { + RadarStationDao dao = new RadarStationDao(); + List stations = null; + try { + stations = dao.queryByWfo(PropertiesFactory.getInstance() + .getEnvProperties().getEnvValue("SITENAME")); + } catch (DataAccessLayerException e) { + statusHandler + .handle(Priority.ERROR, + "Unable to access data object for radar station table"); + } + + for (RadarStation station : stations) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(station.getRdaId().toLowerCase()); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + + sites.add(station.getRdaId().toLowerCase()); + } + + } else { + for (String site : sites) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(site); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + } + } + + runner.setProducts(products); + + // Apply site list to all QPE types + for (String source : getSourceConfig().getQPESources()) { + SourceXML qpeSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources + if (qpeSource.getDataType().equals( + DATA_TYPE.RADAR.getDataType())) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpeSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + // We have a list of available RFC's, now find mosaic + // Apply this to all RFCFFG sources + for (String source : getSourceConfig().getGuidances()) { + SourceXML guidSource = getSourceConfig().getSource(source); + + // Auto config for RFC sources + if (guidSource.isRfc()) { + // add a source mosaic config to the Run Config + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(guidSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String dataKey : rfc) { + sicm.addDataKey(dataKey); + } + + runner.addSourceIngest(sicm); + } + } + + // Apply site list to all SCANQPF default + for (String source : getSourceConfig().getQPFSources()) { + SourceXML qpfSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources (QPFSCAN) for + // example + if (qpfSource.getSourceName().equals("QPFSCAN")) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpfSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + DomainXML domain = new DomainXML(); + domain.setPrimary(true); + domain.setCwa(commonStaticSite.getContextName()); + runner.addDomain(domain); + + getRunConfig().addFFMPRunner(runner); + getRunConfig().saveConfigXml(); + getRunConfig().setPopulated(true); + + domains.add(domain); + } + + // kick off template generation + this.getExecutor().execute(new TemplateLoader(domains)); + } + + @Override + protected void createFilters() { + // do more here if you wish + + ArrayList runners = getRunConfig().getFFMPRunners(); + ArrayList tmp = new ArrayList( + runners.size()); + + for (FFMPRunXML runner : runners) { + DomainXML domain = runner.getPrimaryDomain(); + try { + tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" + + getRFCString(runner) + ":" + domain.getCwa())); + + statusHandler.handle(Priority.INFO, "Created FFMP Filter.." + + " primary Domain: " + domain.getCwa()); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Couldn't create FFMP Filter.." + " primary Domain: " + + domain.getCwa() + + " this RUNNER is not a viable FFMP config."); + e.printStackTrace(); + } + } + + filters = tmp.toArray(new URIFilter[tmp.size()]); + + } + + /** + * Slight difference in the way ffmp operates as opposed to the URIFilter in + * general. + */ + @Override + public void matchURIs(DataURINotificationMessage messages) { + + if (messages instanceof DataURINotificationMessage) { + URIFilter[] filters = getFilters(); + if (filters != null) { + for (int i = 0; i < filters.length; i++) { + if (filters[i] != null) { + FFMPURIFilter filter = (FFMPURIFilter) filters[i]; + + if (loaded) { + + synchronized (filter) { + + if (filter.isMatched(messages)) { + + if (!ffgCheck) { + + filter = getFFG(filter); + filter.setValidTime(filter + .getCurrentTime()); + ffgCheck = true; + } + + dispatch(filter); + } + } + } else { + statusHandler + .debug(getGeneratorName() + + ": templates not loaded yet. Skipping product"); + } + } + } + } + } + } + + @Override + public void generateProduct(URIGenerateMessage genMessage) { + if (loaded) { + try { + long time = System.currentTimeMillis(); + this.config = new FFMPConfig( + (FFMPURIGenerateMessage) genMessage, this); + products = new ConcurrentHashMap(); + processes = new ConcurrentHashMap(); + // read config updates, make sure we don't miss something + getRunConfig().readConfigXml(); + getSourceConfig().readConfigXml(); + + if (config.getSources() != null) { + for (String source : config.getSources().keySet()) { + processes.put(source, + getSourceConfig().getSource(source)); + } + } + + // start threads + + for (String source : processes.keySet()) { + this.getExecutor().execute( + new ProcessProduct(processes.get(source), this)); + } + + // count down latch + while (processes.size() > 0) { + // wait for all threads to finish before returning + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + processes.size()); + for (String source : processes.keySet()) { + statusHandler.handle(Priority.DEBUG, + "Still processing ..." + source); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if (products.size() > 0) { + + // Do the FFTI evaluation, if we have FFTI sources + if (fftiSources.size() > 0) { + this.getExecutor().execute(new FFTI(this)); + } + + ArrayList records = new ArrayList( + products.size()); + for (String source : products.keySet()) { + for (FFMPRecord rec : products.get(source)) { + records.add(rec); + } + } + + FFMPRecord[] recs = new FFMPRecord[records.size()]; + for (int i = 0; i < records.size(); i++) { + recs[i] = records.get(i); + } + + this.setPluginDataObjects(recs); + this.setPluginDao(new FFMPDao(getCompositeProductType(), + template, fscm, config.getCWA())); + + while (fftiSources.size() > 0) { + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + fftiDone); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + statusHandler.handle( + Priority.INFO, + config.getCWA() + " finished, duration: " + + (System.currentTimeMillis() - time) + + " ms, wrote " + records.size() + " "); + + } else { + statusHandler.handle(Priority.INFO, config.getCWA() + + " no new products to produce."); + } + // dump data we don't need anymore + ffmpData.clear(); + + } catch (Throwable e) { + statusHandler.handle(Priority.ERROR, + "Unable to process FFMP Records."); + e.printStackTrace(); + } + } + } + + /** + * Get the list of domains + * + * @return + */ + public ArrayList getDomains() { + return domains; + } + + /** + * Add a filtering CWA + * + * @param domain + */ + public void addDomain(DomainXML domain) { + domains.add(domain); + } + + @Override + public boolean isRunning() { + return getConfigManager().getFFMPState(); + } + + /** + * Set list of CWA's + * + * @param cwas + */ + public void setDomains(ArrayList domains) { + this.domains = domains; + } + + /** + * Inner class to thread the ffmp processing + * + * @author dhladky + * + */ + private class ProcessProduct implements Runnable { + + SourceXML ffmpProduct; + + FFMPGenerator generator; + + @Override + public void run() { + try { + logger.debug("ProcessProduct: Starting thread " + + ffmpProduct.getSourceName()); + process(); + logger.debug("ProcessProduct: Finishing thread " + + ffmpProduct.getSourceName()); + } catch (Exception e) { + processes.remove(ffmpProduct.getSourceName()); + logger.error("ProcessProduct: removed " + + ffmpProduct.getSourceName()); + e.printStackTrace(); + } + } + + public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { + this.ffmpProduct = ffmpProduct; + this.generator = generator; + } + + /** + * The actual work gets done here + */ + public void process() throws Exception { + + HashMap dataHash = config.getSourceData(ffmpProduct + .getSourceName()); + ArrayList ffmpRecords = new ArrayList( + dataHash.size()); + + FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); + + // process all of the dataKeys for this source + for (String dataKey : dataHash.keySet()) { + + ArrayList sites = new ArrayList(); + + // is it a mosaic? + if (ffmpProduct.isMosaic()) { + + // Take care of defaults, all in this case + for (ProductRunXML product : runner.getProducts()) { + // no duplicate keys! + if (!sites.contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + + // do filtering + for (ProductRunXML product : runner.getProducts()) { + // includes + if (product.hasIncludes()) { + for (String includeSourceName : product + .getIncludes()) { + if (ffmpProduct.getSourceName().equals( + includeSourceName)) { + // no duplicate keys! + if (!sites + .contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + } + } + // excludes + if (product.hasExcludes()) { + for (String excludeSourceName : product + .getExcludes()) { + if (ffmpProduct.getSourceName().equals( + excludeSourceName)) { + sites.remove(product.getProductKey()); + } + } + } + } + } else { + // No mosaic, just individual site run + String siteKey = dataKey; + + // special case for XMRG's + if (ffmpProduct.getDataType().equals( + FFMPSourceConfigurationManager.DATA_TYPE.XMRG + .getDataType())) { + + siteKey = null; + String primarySource = null; + + for (ProductXML product : getSourceConfig() + .getProducts()) { + if (product.containsSource(ffmpProduct + .getSourceName())) { + primarySource = product.getPrimarySource(); + break; + } + } + + for (ProductRunXML productRun : runner.getProducts()) { + if (productRun.getProductName().equals( + primarySource)) { + siteKey = productRun.getProductKey(); + break; + } + } + } + + sites.add(siteKey); + } + + for (String productKey : sites) { + + FFMPRecord ffmpRec = new FFMPRecord(); + ffmpRec.setSourceName(ffmpProduct.getSourceName()); + ffmpRec.setDataKey(dataKey); + ffmpRec.setSiteKey(productKey); + ffmpRec.setPluginName(getCompositeProductType()); + ffmpRec.setWfo(config.getCWA()); + FFMPProcessor ffmp = new FFMPProcessor(config, generator, + ffmpRec, template); + ffmpRec = ffmp.processFFMP(ffmpProduct); + ffmpRec.constructDataURI(); + + if (ffmpRec != null) { + + // Don't write loader buddy's on long duration + // sources. Not necessary 6*60 = 360 + if (getSourceConfig() + .getSource(ffmpRec.getSourceName()) + .getExpirationMinutes(productKey) < 360) { + + processDataContainer(ffmpRec); + } + + if (ffmp.isFFTI()) { + fftiDone = false; + if (!fftiSources.contains(ffmp.getFFTISource())) { + FFTIProcessor ffti = new FFTIProcessor( + generator, ffmpRec, + ffmp.getFFTISource()); + fftiSources.add(ffmp.getFFTISource()); + ffti.processFFTI(); + } + } + + ffmpRecords.add(ffmpRec); + } + } + } + + FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; + for (int i = 0; i < ffmpRecords.size(); i++) { + recs[i] = ffmpRecords.get(i); + } + products.put(ffmpProduct.getSourceName(), recs); + processes.remove(ffmpProduct.getSourceName()); + } + } + + /** + * Inner class to background template creation + * + * @author dhladky + * + */ + private class TemplateLoader implements Runnable { + + ArrayList templateDomains; + + DomainXML primaryDomain; + + @Override + public void run() { + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Start loader "); + + for (DomainXML domain : templateDomains) { + if (domain.isPrimary()) { + primaryDomain = domain; + } + } + + // generate templates and unify geometries + loaded = load(); + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Finishing loader "); + } + + public TemplateLoader(ArrayList templateDomains) { + this.templateDomains = templateDomains; + } + + /** + * + * @param domain + * @return + */ + public void createUnifiedGeometries(DomainXML domain) { + ArrayList hucsToGen = new ArrayList(); + hucsToGen.add("ALL"); + hucsToGen.add("COUNTY"); + + for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { + hucsToGen.add("HUC" + i); + } + + for (String huc : hucsToGen) { + template.verifyUnifiedGeometries(huc, domain.getCwa()); + } + } + + public boolean load() { + // load / create primary domain + ClusterTask task = null; + String lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); + try { + do { + task = ClusterLockUtils.lock(templateTaskName, lockDetails, + 600 * 1000, true); + } while (task.getLockState() != LockState.SUCCESSFUL); + + template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); + // setup the config + getTemplateConfig(); + createUnifiedGeometries(primaryDomain); + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + + // load the secondary domains + List domainsToGen = new ArrayList( + templateDomains); + while (domainsToGen.size() > 0) { + Iterator iter = domainsToGen.iterator(); + boolean processedDomain = false; + while (iter.hasNext()) { + DomainXML domain = iter.next(); + lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + domain.getCwa(); + try { + task = ClusterLockUtils.lock(templateTaskName, + lockDetails, 300 * 1000, false); + + if (task.getLockState() == LockState.SUCCESSFUL) { + template.addDomain(domain); + createUnifiedGeometries(domain); + iter.remove(); + processedDomain = true; + } + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + } + + if (!processedDomain) { + // Didn't process a domain, locked by another cluster + // member, sleep and try again + try { + Thread.sleep(100); + } catch (InterruptedException e) { + + } + } + } + + return template.done; + } + } + + /** + * Gets the string buffer for the RFC's + * + * @param run + * @return + */ + private String getRFCString(FFMPRunXML run) { + StringBuffer buf = new StringBuffer(); + + for (SourceIngestConfigXML ingest : run.getSourceIngests()) { + SourceXML source = FFMPSourceConfigurationManager.getInstance() + .getSource(ingest.getSourceName()); + if (source.isRfc()) { + int i = 0; + for (String dataKey : ingest.getDataKey()) { + if (i < ingest.getDataKey().size() - 1) { + buf.append(dataKey + ","); + } else { + buf.append(dataKey); + } + i++; + } + break; + } + } + return buf.toString(); + } + + /** + * Gets the string buffer for the sites, specific to RADAR type data + * + * @param run + * @return + */ + private String getSiteString(FFMPRunXML run) { + String sites = null; + StringBuffer buf = new StringBuffer(); + for (ProductRunXML product : run.getProducts()) { + SourceXML source = getSourceConfig().getSource( + product.getProductName()); + if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { + buf.append(product.getProductKey() + ","); + } + } + sites = buf.toString(); + if (sites.endsWith(",")) { + sites = sites.substring(0, sites.length() - 1); + } + return sites; + } + + /** + * Write your new SourceBins + * + * @param sourceList + */ + public void writeSourceBins(SourceBinList sourceList) { + + try { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + LocalizationFile lflist = pathManager.getLocalizationFile(lc, + getAbsoluteFileName(sourceList.getSourceId())); + + FileUtil.bytes2File( + SerializationUtil.transformToThrift(sourceList), + lflist.getFile(), true); + + lflist.save(); + + statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " + + sourceList.getSourceId()); + + } catch (SerializationException se) { + se.printStackTrace(); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (LocalizationOpFailedException e) { + e.printStackTrace(); + } + } + + /** + * Read out your SourceBins + * + * @param sourceId + * @return + */ + public SourceBinList readSourceBins(String sourceId) { + + SourceBinList sbl = null; + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFileName(sourceId)); + + try { + sbl = (SourceBinList) SerializationUtil + .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); + } catch (FileNotFoundException fnfe) { + statusHandler.handle(Priority.ERROR, + "Unable to locate file " + f.getName()); + } catch (SerializationException se) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + return sbl; + } + + /** + * Gets the completed filename + * + * @return + */ + public String getAbsoluteFileName(String sourceId) { + return "ffmp" + File.separator + "sources" + File.separator + sourceId + + ".bin"; + } + + /** + * See if you have one + * + * @param sourceId + * @return + */ + public boolean isExistingSourceBin(String sourceId) { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFileName(sourceId)); + return f.exists(); + } + + /** + * Gets the list of bins for that source + * + * @param sourceId + * @return + */ + public SourceBinList getSourceBinList(String sourceId) { + SourceBinList sbl = null; + if (!sourceBins.containsKey(sourceId)) { + sbl = readSourceBins(sourceId); + sourceBins.put(sourceId, sbl); + } else { + sbl = sourceBins.get(sourceId); + } + + return sbl; + } + + /** + * Sets the source bins, first time + * + * @param sbl + */ + public void setSourceBinList(SourceBinList sbl) { + sourceBins.put(sbl.getSourceId(), sbl); + writeSourceBins(sbl); + } + + /** + * Do pull strategy on FFG data + * + * @param filter + * @return + */ + private FFMPURIFilter getFFG(FFMPURIFilter filter) { + + ArrayList uris = new ArrayList(); + + for (String rfc : filter.getRFC()) { + // get a hash of the sources and their grib ids + HashMap sources = FFMPUtils.getFFGModelInfo(rfc); + if (sources != null) { + if (sources.size() > 0) { + for (String source : sources.keySet()) { + + SourceXML sourceXml = getSourceConfig().getSource( + source); + + if (sourceXml != null) { + + String plugin = getSourceConfig().getSource(source) + .getPlugin(); + uris.add(FFMPUtils.getFFGDataURI( + sources.get(source), plugin)); + } + } + } + } + } + // treat it like a regular uri in the filter. + if (uris.size() > 0) { + for (String dataUri : uris) { + // add your pattern checks to the key + for (Pattern pattern : filter.getMatchURIs().keySet()) { + statusHandler.handle(Priority.DEBUG, + "Pattern: " + pattern.toString() + " Key: " + + dataUri); + try { + if (pattern.matcher(dataUri).find()) { + // matches one of them, which one? + String matchKey = filter.getPatternName(pattern); + // put the sourceName:dataPath key into the sources + // array list + filter.getSources().put(matchKey, dataUri); + } + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "Unable to locate new FFG file. " + + pattern.toString()); + } + } + } + } + + return filter; + } + + /** + * get the FFMP data container for this source + * + * @param sourceName + * + * @return + */ + + public FFMPDataContainer getFFMPDataContainer(String siteSourceKey, ArrayList hucs, Date backDate) { + + FFMPDataContainer container = ffmpData.get(siteSourceKey); + + if (container == null) { + + String siteKey = null; + + String[] parts = siteSourceKey.split("-"); + + if (parts.length > 1) { + siteKey = parts[0]; + } + + container = loadFFMPDataContainer(siteSourceKey, + + hucs, siteKey, + + config.getCWA(), backDate); + + if (container != null) { + ffmpData.put(siteSourceKey, container); + } + } + + return container; + } + + /* + * Gets the FFTI sources to be run + */ + public ArrayList getFFTISources() { + return fftiSources; + } + + /** + * source config manager + * + * @return + */ + public FFMPSourceConfigurationManager getSourceConfig() { + if (fscm == null) { + fscm = FFMPSourceConfigurationManager.getInstance(); + fscm.addListener(this); + } + return fscm; + } + + /** + * run config manager + * + * @return + */ + public FFMPRunConfigurationManager getRunConfig() { + if (frcm == null) { + frcm = FFMPRunConfigurationManager.getInstance(); + frcm.addListener(this); + } + return frcm; + } + + /** + * Template config manager + * + * @return + */ + public FFMPTemplateConfigurationManager getTemplateConfig() { + if (tempConfig == null) { + tempConfig = FFMPTemplateConfigurationManager.getInstance(); + tempConfig.addListener(this); + } + return tempConfig; + } + + /** + * dispatch a filter for processing + * + * @param filter + */ + private void dispatch(FFMPURIFilter filter) { + + try { + EDEXUtil.getMessageProducer().sendAsync( + routeId, + SerializationUtil.transformToThrift(filter + .createGenerateMessage())); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, getGeneratorName() + + ": filter: " + filter.getName() + + ": failed to route filter to generator", e); + e.printStackTrace(); + } + + filter.setValidTime(new Date(System.currentTimeMillis())); + filter.reset(); + } + + /** + * FFMP buddy loader + * + * @param ffmpRec + * @param siteKey + */ + private void processDataContainer(FFMPRecord ffmpRec) { + + // write out the fast loader buddy file + SourceXML source = getSourceConfig().getSource(ffmpRec.getSourceName()); + String sourceName = null; + String dataKey = null; + + if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { + sourceName = source.getDisplayName(); + dataKey = SOURCE_TYPE.GUIDANCE.getSourceType(); + } else { + sourceName = ffmpRec.getSourceName(); + dataKey = ffmpRec.getDataKey(); + } + + String sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() + + "-" + dataKey; + + // Make a 6 hour "Buddy" loader file + Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() + - (3600 * 1000 * 6)); + + ArrayList hucs = template.getTemplateMgr().getHucLevels(); + + if (source.getSourceType().equals(SOURCE_TYPE.GAGE.getSourceType())) { + hucs.clear(); + hucs.add("ALL"); + } else { + hucs.remove("VIRTUAL"); + } + + // pull from disk if there + FFMPDataContainer fdc = loadFFMPDataContainer(sourceSiteDataKey, + hucs, ffmpRec.getSiteKey(), + ffmpRec.getWfo(), backDate); + + // brand new or initial load up + if (fdc == null || !loadedData.contains(sourceSiteDataKey)) { + + long time = System.currentTimeMillis(); + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + fdc = FFTIProcessor.populateDataContainer(fdc, template, hucs, backDate, ffmpRec.getDataTime() + .getRefTime(), ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); + loadedData.add(sourceSiteDataKey); + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.INFO, + "Populated new source: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + + } else { + // guidance sources are treated as a mosaic and are handled differently + // This is the main line sequence a source will take when updated. + if (!source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + + long time = System.currentTimeMillis(); + Date newDate = fdc.getNewest(); + Date oldDate = fdc.getOldest(); + + if (newDate != null && oldDate != null) { + if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate + .getTime()) >= (source.getExpirationMinutes(ffmpRec + .getSiteKey()) * 60 * 1000)) { + // force a re-query back to the newest time in + // existing source container, this will fill in gaps if + // they exist. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, newDate, ffmpRec.getDataTime() + .getRefTime(), ffmpRec.getWfo(), + source, ffmpRec.getSiteKey()); + + } else if (oldDate.after(new Date( + backDate.getTime() + - (source.getExpirationMinutes(ffmpRec + .getSiteKey()) * 60 * 1000)))) { + // force a re-query back to barrierTime for + // existing source container, this happens if the + // ingest was turned off for some period of time. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, backDate, oldDate, + ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); + } + } + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.INFO, + "Checked Source files: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + + // purge it up + fdc.purge(backDate); + } + } + // add current record data for (String huc : ffmpRec.getBasinsMap().keySet()) { fdc.addFFMPEntry(ffmpRec.getDataTime().getRefTime(), source, ffmpRec.getBasinData(huc), huc, ffmpRec.getSiteKey()); } + + // set the name + fdc.setFilePath("" + sharePath + ffmpRec.getWfo() + "/"+ sourceSiteDataKey); + // cache it temporarily for FFTI use + ffmpData.put(sourceSiteDataKey, fdc); + // write it out + writeLoaderBuddyFiles(fdc); + } - fdc.purge(backDate); - fdc.writeDataContainer(sourceSiteDataKey, sharePath, ffmpRec.getWfo()); + /** + * load existing container + * + * @param sourceSiteDataKey + * @param hucs + * @param siteKey + * @param wfo + * @return + */ + public FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, + ArrayList hucs, String siteKey, String wfo, Date backDate) { - // write it back - ffmpData.put(sourceSiteDataKey, fdc); - long time2 = System.currentTimeMillis(); - - statusHandler.handle(Priority.INFO, "Wrote loader buddy files: " - + sourceSiteDataKey + " in " + (time2 - time) + " ms"); - - } - - /** - * load existing container - * - * @param sourceSiteDataKey - * @param hucs - * @param siteKey - * @param wfo - * @return - */ - private FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, - Set hucs, String siteKey, String wfo, Date backDate) { - - FFMPDataContainer fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); - - for (String huc : hucs) { + long time = System.currentTimeMillis(); + FFMPDataContainer fdc = null; + + for (String huc : hucs) { + FFMPBasinData basinData = null; + if (checkBuddyFile(sourceSiteDataKey, huc, wfo, backDate)) { basinData = readLoaderBuddyFile(sourceSiteDataKey, huc, wfo, backDate); + + if (fdc == null) { + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + } } + if (basinData != null) { fdc.setBasinBuddyData(basinData, huc); - } else { - // rebuild it - return null; - } + } } + + if (fdc != null) { + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, "Loaded Source files: in " + + (time2 - time) + " ms: source: " + sourceSiteDataKey); + } + + return fdc; + } - return fdc; - } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, String huc, String wfo, Date backDate) { File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" @@ -1252,8 +1341,12 @@ public class FFMPGenerator extends CompositeProductGenerator implements FFMPBasinData basinData = null; try { - basinData = (FFMPBasinData) SerializationUtil - .transformFromThrift(FileUtil.file2bytes(file)); + BufferedInputStream is = new BufferedInputStream( + new FileInputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + basinData = (FFMPBasinData) dsm.deserialize(is); + is.close(); } catch (SerializationException e) { e.printStackTrace(); } catch (IOException e) { @@ -1263,157 +1356,245 @@ public class FFMPGenerator extends CompositeProductGenerator implements return basinData; } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - public boolean checkBuddyFile(String sourceSiteDataKey, - String huc, String wfo, Date backDate) { - File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" - + huc + ".bin"); + /** + * Write buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public void writeLoaderBuddyFiles(FFMPDataContainer fdc) { - if (file.exists() && (file.lastModified() > backDate.getTime())) { - return true; - } - - return false; - - } - - - @Override - public synchronized void configChanged(MonitorConfigEvent fce) { - - boolean reload = false; - - if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { - statusHandler - .handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Template Config change"); - reload = true; - FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce - .getSource(); - if (ftcm.isRegenerate()) { - template.dumpTemplates(); - } - - tempConfig = null; - - } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Run Config change"); - reload = true; - frcm = null; - } - - else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Source Config change"); - reload = true; - fscm = null; - } - - if (reload) { - ffgCheck = false; - resetFilters(); - getSourceBinCache().clearCache(); - getSourceBinCache().closeCache(); - if (ffmpData != null) { - ffmpData.clear(); - } - DatMenuUtil dmu = new DatMenuUtil(); - dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() - .getEnvValue("SITENAME")); - dmu.setOverride(true); - dmu.createMenus(); - } - } - - /** - * Get SourceBins from cache - * @param siteKey - * @param sourceName - * @return - */ - public SourceBinList getSourceBin(String sourceName) { - - SourceBinList bins = null; - - if (sourceName != null) { - try { - - DiskCache diskCache = getSourceBinCache(); - bins = (SourceBinList) diskCache.getFromCache(sourceName); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - return bins; - } - - /** - * Set Source Bins to cache - * @param sourceName - * @param record - */ - - public void setSourceBin(SourceBinList list, String sourceName) { - if (sourceName != null) { - try { - - DiskCache diskCache = getSourceBinCache(); - - try { - diskCache.addToCache(sourceName, list); - } catch (IOException e) { - e.printStackTrace(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @SuppressWarnings({ "unchecked" }) - private DiskCache getSourceBinCache() { - - DiskCache diskCache = null; - - try { - diskCache = (DiskCache)CacheFactory.getInstance() - .getCache("FFMP-SourceBinList-cache"); - - } catch (CacheException e) { - DiskCache dc = createSourceCache("FFMP-SourceBinList-cache", 4); - CacheFactory.getInstance().addCache("FFMP-SourceBinList-cache", dc); - return dc; + // Write all huc levels in separate files + File fileDir = new File("" + sharePath + config.getCWA()); + if (!fileDir.exists()) { + fileDir.mkdir(); } - - return diskCache; - } - - /** - * Create cache objects if needed - * @param siteKey - * @return - */ - private DiskCache createSourceCache(String name, int size) { - ICache cache = new DiskCache(); - DiskCache dc = (DiskCache) cache; - dc.setName(name); - dc.setSizeMemCacheMap(size); - dc.activateEdexCache(); - - return dc; - } - -} + WriteFiles writer = new WriteFiles(fdc); + writer.run(); + } + + /** + * Inner class to thread writing of BuddyFiles + * + * @author dhladky + * + */ + private class WriteFiles implements Runnable { + + private FFMPDataContainer fdc; + + public void run() { + try { + long time = System.currentTimeMillis(); + write(); + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, + "Wrote loader files: in " + (time2 - time) + + " ms"); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "WriteFile: removed " + e.getMessage()); + } + } + + public WriteFiles(FFMPDataContainer fdc) { + this.fdc = fdc; + statusHandler.handle(Priority.DEBUG, "Created FileWriter"); + } + + /** + * The actual work gets done here + */ + public void write() throws Exception { + + try { + + String fileName = fdc.getFilePath(); + // lock for atomic write and read + HashMap fileNames = new HashMap(); + File lockfile = new File(fileName + ".lock"); + lockfile.createNewFile(); + + try { + + for (String huc : fdc.getKeys()) { + + FFMPBasinData fbd = fdc.getBasinData(huc); + + if (fbd.getBasins().size() > 0) { + + String tmpFilePath = fileName + "-" + huc + ".tmp"; + fileNames.put(tmpFilePath, fileName + "-" + huc + + ".bin"); + BufferedOutputStream os = null; + + try { + File file = new File(tmpFilePath); + os = new BufferedOutputStream( + new FileOutputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + dsm.serialize(fbd, os); + } catch (SerializationException e) { + statusHandler.handle(Priority.ERROR, + "Serialization Error Writing buddy file: " + + e.getMessage()); + } catch (IOException e) { + statusHandler.handle( + Priority.ERROR, + "IO Error Writing buddy file: " + + e.getMessage()); + } finally { + if (os != null) { + os.close(); + } + } + } + } + } catch (Exception e) { + statusHandler + .handle(Priority.ERROR, + "Error writing Buddy File group: " + + e.getMessage()); + } finally { + // rename the files to real path + try { + for (String tmpName : fileNames.keySet()) { + File file = new File(tmpName); + file.renameTo(new File(fileNames.get(tmpName))); + } + + lockfile.delete(); + + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "IO Error Renaming buddy file: " + + e.getMessage()); + } + } + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "IO Error writing buddy files: " + e.getMessage()); + } + } + } + + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public boolean checkBuddyFile(String sourceSiteDataKey, String huc, + String wfo, Date backDate) { + + File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" + + huc + ".bin"); + + if (file.exists() && (file.lastModified() > backDate.getTime())) { + // System.out.println("File update and exists..."+sourceSiteDataKey); + return true; + } + + return false; + + } + + @Override + public synchronized void configChanged(MonitorConfigEvent fce) { + + boolean reload = false; + + if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { + statusHandler + .handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Template Config change"); + reload = true; + FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce + .getSource(); + if (ftcm.isRegenerate()) { + template.dumpTemplates(); + } + + tempConfig = null; + + } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Run Config change"); + reload = true; + frcm = null; + } + + else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Source Config change"); + reload = true; + fscm = null; + } + + if (reload) { + + ffgCheck = false; + resetFilters(); + + if (sourceBins != null) { + sourceBins.clear(); + } + + loadedData.clear(); + + DatMenuUtil dmu = new DatMenuUtil(); + dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() + .getEnvValue("SITENAME")); + dmu.setOverride(true); + dmu.createMenus(); + } + } + + /** + * FFTI data cache + * @param ffti + */ + public void addFFTIData(String fftiName, FFTIData ffti) { + if (fftiData.containsKey(fftiName)) { + fftiData.replace(fftiName, ffti); + } else { + fftiData.put(fftiName, ffti); + } + } + + /** + * Get FFTI data cache + * @param fftiName + * @return + */ + public FFTIData getFFTIData(String fftiName) { + return fftiData.get(fftiName); + } + + /** + * Check existence + * @param fftiName + * @return + */ + public boolean isFFTI(String fftiName) { + return fftiData.containsKey(fftiName); + } + + /** + * get the whole container + * @return + */ + public ConcurrentHashMap getFFTIDataContainer() { + return fftiData; + } + +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java index 47f8772d17..e37efdc150 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java @@ -89,16 +89,19 @@ public class FFMPInterpolatedGuidanceDelay { FFMPDataContainer qpeContainer = null; - if (qpeSource.isMosaic()) { - qpeContainer = generator.getFFMPDataContainer(qpeSource - .getSourceName()); - } else { - qpeContainer = generator.getFFMPDataContainer(siteKey + "-" - + qpeSource.getSourceName()); - } + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - long expirationTime = qpeSource.getExpirationMinutes(siteKey) * 60 * 1000; - // determine lag_time + // if (qpeSource.isMosaic()) { + // qpeContainer = generator.getFFMPDataContainer(qpeSource + // .getSourceName(), hucs, backDate); + // } else { + qpeContainer = generator.getFFMPDataContainer(qpeSource.getSourceName() + + "-" + siteKey + "-" + siteKey, hucs, backDate); + // } + + long expirationTime = qpeSource.getExpirationMinutes(siteKey) * 60 * 1000; + // determine lag_time long lagTime = (currentRecord.getDataTime().getRefTime().getTime()) + (long) (ffgSource.getDurationHour() * 60 * 1000); // Determine hour fraction. diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPProcessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPProcessor.java index 8ae41c5269..40cfaeaa4b 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPProcessor.java @@ -622,8 +622,15 @@ public class FFMPProcessor { + source.getDisplayName(); } - FFMPDataContainer ffgContainer = generator - .getFFMPDataContainer(sourceNameString); + Date backDate = new Date(ffmpRec.getDataTime().getRefTime() + .getTime() + + - (3600 * 1000 * 6)); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); + FFMPDataContainer ffgContainer = generator + .getFFMPDataContainer(sourceNameString, hucs, + backDate); if (ffgContainer != null && ffgContainer.containsKey(source.getSourceName())) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java index d0b5a05d2a..e17a1ad813 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinData; import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinMetaData; import com.raytheon.uf.common.dataplugin.ffmp.FFMPDataContainer; import com.raytheon.uf.common.dataplugin.ffmp.FFMPGap; @@ -225,21 +226,31 @@ public class FFTI implements Runnable { for (String displayName : displayNames) { String[] fftiKeys = displayName.split("-"); - // monolithic processing + + // monolithic processing for mosaic sources if (fftiKeys.length == 1) { source = ffmpgen.getSourceConfig().getSourceByDisplayName( displayName); ArrayList sites = getSites(source); ArrayList accums = new ArrayList(); + // process all pieces of the mosaic - for (int i = 0; i < sites.size(); i++) { - FFTIAccum faccum = getAccumulationForSite(displayName, - sites.get(i), duration); - if (faccum != null) { - accums.add(faccum); - } - } + for (int i = 0; i < sites.size(); i++) { + + String dataKey = sites.get(i); + + for (int j = 0; j < sites.size(); j++) { + + FFTIAccum faccum = getAccumulationForSite(displayName, + sites.get(j), dataKey, duration, + source.getUnit()); + + if (faccum != null) { + accums.add(faccum); + } + } + } // find the highest for the entire mosaic accum = new FFTIAccum(); @@ -256,24 +267,26 @@ public class FFTI implements Runnable { } accum.setName(faccum.getName()); + accum.setUnit(faccum.getUnit()); } - accum.setUnit(source.getUnit()); + statusHandler.handle( Priority.INFO, "FFTI mosaic ACCUM: " + source.getSourceName() + " " + accum.getAccumulation() + " gap: " + accum.getGap()); accumList.add(accum); + } else { + fftiSiteKey = fftiKeys[0]; fftiSourceKey = fftiKeys[1]; source = ffmpgen.getSourceConfig().getSourceByDisplayName( fftiSourceKey); - accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, - duration); + accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, fftiSiteKey, duration, source.getUnit()); if (accum != null) { accum.setUnit(source.getUnit()); @@ -323,7 +336,7 @@ public class FFTI implements Runnable { FFTIRatioDiff values = getRatioAndDiffForSite( qSourceXML.getSourceName(), site, - guidDisplayNames.get(0), duration); + guidDisplayNames.get(0), duration, unit); Float tempVal = Float.NaN; @@ -333,13 +346,19 @@ public class FFTI implements Runnable { .equals(FFTIAttributeXML.ATTRIBUTE.RATIO .getAttribute())) { - tempVal = FFMPUtils.getMaxRatioValue( - values.getQpes(), values.getGuids()); - } else if (attribute.getAttributeName().equals( - FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxRatioValue( + values.getQpes(), values.getGuids()); + } + } else if (attribute.getAttributeName().equals( + FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - tempVal = FFMPUtils.getMaxDiffValue( - values.getQpes(), values.getGuids()); + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxDiffValue( + values.getQpes(), values.getGuids()); + } } if ((tempVal != Float.NaN) @@ -379,20 +398,27 @@ public class FFTI implements Runnable { FFTIRatioDiff values = getRatioAndDiffForSite( qSourceXML.getSourceName(), qSiteKey, - guidDisplayNames.get(0), duration); + guidDisplayNames.get(0), duration, unit); if (values != null) { if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.RATIO.getAttribute())) { - val = FFMPUtils.getMaxRatioValue(values.getQpes(), - values.getGuids()); + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxRatioValue(values.getQpes(), + values.getGuids()); + } + } else if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - val = FFMPUtils.getMaxDiffValue(values.getQpes(), - values.getGuids()); + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxDiffValue(values.getQpes(), + values.getGuids()); + } } gap = values.getGap(); @@ -766,67 +792,89 @@ public class FFTI implements Runnable { * @return */ private FFTIAccum getAccumulationForSite(String fftiSourceKey, - String fftiSiteKey, double duration) { + String fftiSiteKey, String fftiDataKey, double duration, String unit) { + SourceXML ffmpSource = ffmpgen.getSourceConfig() .getSourceByDisplayName(fftiSourceKey); - FFTIAccum accumulator = null; - long cur = config.getDate().getTime(); - long timeBack = (long) (duration * 3600 * 1000); - Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; - - FFMPDataContainer fdc = null; - - if (ffmpSource.isMosaic()) { - fdc = ffmpgen.getFFMPDataContainer(ffmpSource.getDisplayName()); + String siteDataKey = ffmpSource.getDisplayName() + "-" + fftiSiteKey + "-"+ fftiDataKey; + + if (ffmpgen.isFFTI(siteDataKey)) { + accumulator = (FFTIAccum) ffmpgen.getFFTIData(siteDataKey); } else { - fdc = ffmpgen.getFFMPDataContainer(ffmpSource.getDisplayName() + "-" - + fftiSiteKey + "-" + fftiSiteKey); + accumulator = new FFTIAccum(); } - if (fdc != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); + // This will only happen at initial load, update, and duration changes. + if (accumulator.isReset() || accumulator.getDuration() != duration) { - Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); + accumulator.setDuration(duration); + accumulator.setUnit(unit); - if (gap != Double.NaN) { + if (ffmpSource.isMosaic()) { + accumulator.setName(ffmpSource.getDisplayName()); + } else { + accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); + } + + long cur = config.getDate().getTime(); + long timeBack = (long) (duration * 3600 * 1000); + Date backDate = new Date(cur - timeBack); + long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; - accumulator = new FFTIAccum(); - if (ffmpSource.isMosaic()) { - accumulator.setName(ffmpSource.getDisplayName()); - } else { - accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); - } - for (String cwa : cwaList) { - for (Long key : fdc.getBasinData("ALL").getBasins() - .keySet()) { + FFMPDataContainer fdc = null; - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - pfafs.add(key); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); + + fdc = ffmpgen.getFFMPDataContainer(siteDataKey, hucs, backDate); + + if (fdc != null) { + + FFMPBasinData fbd = fdc.getBasinData("ALL"); + + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); + + Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); + + if (gap != Double.NaN) { + + for (String cwa : cwaList) { + for (Long key : fbd.getBasins().keySet()) { + + FFMPBasinMetaData basin = templates.getBasin(key); + if ((basin != null) && (basin.getCwa() != null)) { + if (basin.getCwa().equals(cwa)) { + if (!pfafs.contains(key)) { + pfafs.add(key); + } + } } } } + + double amount = fdc.getMaxValue(pfafs, backDate, + config.getDate(), expirationTime, + ffmpSource.isRate()); + + // max value for monitored area + accumulator.setAccumulation(amount); + accumulator.setGap(gap); } - - double amount = fdc.getMaxValue(pfafs, backDate, - config.getDate(), expirationTime, false); - // max value for monitored area - accumulator.setAccumulation(amount); - - accumulator.setGap(gap); } + + // replace or insert it + accumulator.reset(false); + ffmpgen.addFFTIData(siteDataKey, accumulator); } return accumulator; } private FFTIRatioDiff getRatioAndDiffForSite(String qSourceKey, - String qSiteKey, String ffgType, double duration) { + String qSiteKey, String ffgType, double duration, String unit) { FFTIRatioDiff values = null; SourceXML ffmpQSource = ffmpgen.fscm.getSourceByDisplayName(qSourceKey); @@ -834,132 +882,121 @@ public class FFTI implements Runnable { if (ffmpQSource == null) { ffmpQSource = ffmpgen.fscm.getSource(qSourceKey); } - - // make sure we have data - Date ffgBackDate = new Date(config.getDate().getTime() - - (3600 * 1000 * 24)); - String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); - ProductXML product = ffmpgen.fscm.getProduct(primarySource); - - FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer(ffgType); - long guidSourceExpiration = 0l; - - if (guidContainer == null) { - statusHandler.handle(Priority.PROBLEM, - "FFTI: No guidance sources available for " + qSiteKey + " " - + qSourceKey + " " + " comparison."); - return null; + + String siteDataKey = ffgType + "-" + ffmpQSource.getSourceName() + "-"+ qSiteKey; + + if (ffmpgen.isFFTI(siteDataKey)) { + values = (FFTIRatioDiff) ffmpgen.getFFTIData(siteDataKey); + } else { + values = new FFTIRatioDiff(); } - for (SourceXML iguidSource : product.getGuidanceSourcesByType(ffgType)) { + // This will only happen at initial load, update, and duration changes. + if (values.isReset() || values.getDuration() != duration) { - if (guidSourceExpiration == 0l) { - guidSourceExpiration = iguidSource - .getExpirationMinutes(qSiteKey) * 60 * 1000; - } - - if (!guidContainer.containsKey(iguidSource.getSourceName())) { - - guidContainer = FFTIProcessor.populateDataContainer( - guidContainer, templates, null, ffgBackDate, - config.getDate(), config.getCWA(), iguidSource, - qSiteKey); - } - } - - // if still nothing, punt! - if (guidContainer.size() == 0) { - - statusHandler.handle(Priority.PROBLEM, - "FFTI: No guidance sources available for " + qSiteKey + " " - + qSourceKey + " " + " comparison."); - return null; - } - - FFMPDataContainer qpeContainer = null; - - if (ffmpQSource.isMosaic()) { - qpeContainer = ffmpgen.getFFMPDataContainer(ffmpQSource - .getDisplayName()); - } else { - qpeContainer = ffmpgen.getFFMPDataContainer(ffmpQSource - .getSourceName() + "-" + qSiteKey + "-" + qSiteKey); - } - - if (qpeContainer != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList qpfafs = new ArrayList(); - ArrayList gpfafs = new ArrayList(); - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); + values.setDuration(duration); + values.setUnit(unit); - for (String cwa : cwaList) { - for (Long key : guidContainer.getBasinData("ALL").getBasins() - .keySet()) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - gpfafs.add(key); - } - } - } - } - - for (String cwa : cwaList) { - for (Long key : qpeContainer.getBasinData("ALL").getBasins() - .keySet()) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - qpfafs.add(key); - } - } - } - } - // find common pfafs - if (qpfafs.size() < gpfafs.size()) { - for (Long pfaf: gpfafs) { - if (qpfafs.contains(pfaf)) { - pfafs.add(pfaf); - } - } - } else { - for (Long pfaf: qpfafs) { - if (gpfafs.contains(pfaf)) { - pfafs.add(pfaf); - } - } - } - long cur = config.getDate().getTime(); long timeBack = (long) (duration * 3600 * 1000); Date backDate = new Date(cur - timeBack); long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; - Double gap = getGap(qpeContainer, ffmpQSource, duration, qSiteKey); + // make sure we have data + Date ffgBackDate = new Date(config.getDate().getTime() + - (3600 * 1000 * 24)); - if (gap != Double.NaN) { + String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); + ProductXML product = ffmpgen.fscm.getProduct(primarySource); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - ArrayList qpes = qpeContainer.getBasinData("ALL") - .getAccumValues(pfafs, backDate, config.getDate(), - expirationTime, false); + FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer( + ffgType, hucs, ffgBackDate); + long guidSourceExpiration = 0l; - FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( - ffmpgen.fscm, product, ffmpgen.frcm.getRunner( - config.getCWA()).getProduct(qSiteKey), - primarySource, ffgType, qSiteKey); - interpolator.setInterpolationSources(duration); + if (guidContainer != null) { - ArrayList guids = guidContainer.getBasinData("ALL") - .getGuidanceValues(pfafs, interpolator, + for (SourceXML iguidSource : product + .getGuidanceSourcesByType(ffgType)) { + + if (guidSourceExpiration == 0l) { + guidSourceExpiration = iguidSource + .getExpirationMinutes(qSiteKey) * 60 * 1000; + } + + if (!guidContainer.containsKey(iguidSource.getSourceName())) { + + guidContainer = FFTIProcessor.populateDataContainer( + guidContainer, templates, null, ffgBackDate, + config.getDate(), config.getCWA(), iguidSource, + qSiteKey); + } + } + + // if still nothing, punt! + if (guidContainer.size() == 0) { + + statusHandler.handle(Priority.PROBLEM, + "FFTI: No guidance sources available for " + + qSiteKey + " " + qSourceKey + " " + + " comparison."); + return null; + } + + FFMPDataContainer qpeContainer = ffmpgen.getFFMPDataContainer( + ffmpQSource.getSourceName() + "-" + qSiteKey + "-" + + qSiteKey, hucs, backDate); + + if (qpeContainer != null) { + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); + for (String cwa : cwaList) { + for (Long key : qpeContainer.getBasinData("ALL") + .getBasins().keySet()) { + FFMPBasinMetaData basin = templates.getBasin(key); + if ((basin != null) && (basin.getCwa() != null)) { + if (basin.getCwa().equals(cwa)) { + pfafs.add(key); + } + } + } + } + + Double gap = getGap(qpeContainer, ffmpQSource, duration, + qSiteKey); + + if (gap != Double.NaN) { + + ArrayList qpes = qpeContainer + .getBasinData("ALL").getAccumValues(pfafs, + backDate, config.getDate(), + expirationTime, false); + + FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( + ffmpgen.fscm, product, ffmpgen.frcm.getRunner( + config.getCWA()).getProduct(qSiteKey), + primarySource, ffgType, qSiteKey); + interpolator.setInterpolationSources(duration); + + ArrayList guids = guidContainer.getBasinData( + "ALL").getGuidanceValues(pfafs, interpolator, guidSourceExpiration); - - values = new FFTIRatioDiff(qpes, guids, gap); - + + values.setQpes(qpes); + values.setGuids(guids); + values.setGap(gap); + } + } } + + // replace or insert it + values.reset(false); + ffmpgen.addFFTIData(siteDataKey, values); } - return values; + return values; } /** @@ -976,7 +1013,7 @@ public class FFTI implements Runnable { long cur = config.getDate().getTime(); long timeBack = (long) (duration * 3600 * 1000); Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; + long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey); Double gapVal = 0.0; if (qpeContainer.getOrderedTimes(backDate) != null) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java index f32e97dab6..c8b240798a 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java @@ -35,16 +35,10 @@ package com.raytheon.uf.edex.plugin.ffmp.common; * @version 1.0 */ -public class FFTIAccum { +public class FFTIAccum extends FFTIData { private Double accumulation = 0.0; - - private Double gap = 0.0; - - private String name = null;; - - private String unit = null; - + public Double getAccumulation() { return accumulation; } @@ -54,42 +48,4 @@ public class FFTIAccum { this.accumulation = accumulation; } - public Double getGap() { - return gap; - } - - public void setGap(Double gap) { - this.gap = gap; - } - - /** - * @param name - * the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param unit - * the unit to set - */ - public void setUnit(String unit) { - this.unit = unit; - } - - /** - * @return the unit - */ - public String getUnit() { - return unit; - } - } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java new file mode 100644 index 0000000000..b91432139f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java @@ -0,0 +1,113 @@ +package com.raytheon.uf.edex.plugin.ffmp.common; + +/** + * 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. + **/ + +/** + * FFTIData + * + *
    + * 
    + * SOFTWARE HISTORY
    + * Date         Ticket#    Engineer    Description
    + * ------------ ---------- ----------- --------------------------
    + * July 16, 2012            dhladky     Initial creation
    + * 
    + * 
    + * + * @author dhladky + * @version 1.0 + */ + +public class FFTIData { + + private Double gap = 0.0; + + private Double duration = 0.0; + + private String name = null; + + private String unit = null; + + private boolean isReset = true; + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + public Double getGap() { + return gap; + } + + public void setGap(Double gap) { + this.gap = gap; + } + + public Double getDuration() { + return duration; + } + + public void setDuration(Double duration) { + this.duration = duration; + } + + /** + * @param unit + * the unit to set + */ + public void setUnit(String unit) { + this.unit = unit; + } + + /** + * @return the unit + */ + public String getUnit() { + return unit; + } + + /** + * Change status + * @param isReset + */ + public void reset(boolean isReset) { + this.isReset = isReset; + } + + /** + * Check status + * @return + */ + public boolean isReset() { + return isReset; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java index f3f99f49f4..98bac0f5cc 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java @@ -22,8 +22,6 @@ package com.raytheon.uf.edex.plugin.ffmp.common; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; -import java.util.Set; import java.util.TimeZone; import com.raytheon.uf.common.dataplugin.PluginException; @@ -75,12 +73,18 @@ public class FFTIProcessor { private String wfo = null; - private Date barrierTime = null; + private Date ffgBarrierTime = null; private FFMPDataContainer sourceContainer = null; /** Pattern for dates in radar */ public static String datePattern = "yyyy-MM-dd HH:mm:ss"; + + /** 6 hour back time multiplier */ + public static long backTime = 3600 * 1000 * 6; + + /** FFG back time multiplier */ + public static long ffgbackTime = 3600 * 1000 * 24; /** * useful constructor @@ -98,8 +102,8 @@ public class FFTIProcessor { this.fftiSource = fftiSource; this.wfo = ffmpRec.getWfo(); long curr = ffmpRec.getDataTime().getRefTime().getTime(); - long fftiBarrier = (long) (fftiSource.getDurationHour() * 60.0 * 60.0 * 1000); - this.barrierTime = new Date(curr - fftiBarrier); + long fftiFFGBarrier = (long) (24.0 * 60.0 * 60.0 * 1000); + this.ffgBarrierTime = new Date(curr - fftiFFGBarrier); } /** @@ -110,6 +114,7 @@ public class FFTIProcessor { for (String sourceNameString : dispNameList) { String iSiteKey = ffmpRec.getSiteKey(); + String iDataKey = ffmpRec.getDataKey(); String sourceString = sourceNameString; String[] parts = sourceNameString.split("-"); @@ -120,35 +125,56 @@ public class FFTIProcessor { String sourceName = parts[1]; source = FFMPSourceConfigurationManager.getInstance() .getSource(sourceName); - // check for it by displayName one last time, XMRG sources do this - if (source == null) { - source = FFMPSourceConfigurationManager.getInstance() - .getSourceByDisplayName(sourceName); - } } else { + // mosaic source source = FFMPSourceConfigurationManager.getInstance() .getSourceByDisplayName(sourceString); } - - if (!source.getSourceType().equals( + + if (source.getSourceType().equals( FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE - .getSourceType()) - && !source.isMosaic()) { - if (source.getDataType().equals(FFMPSourceConfigurationManager.DATA_TYPE.XMRG - .getDataType())) { - sourceString = source.getSourceName() + "-" + iSiteKey + "-" - + iSiteKey; - } else { - sourceString = source.getDisplayName() + "-" + iSiteKey + "-" - + iSiteKey; - } - } else { + .getSourceType())) { + sourceString = source.getDisplayName(); + + // Mark all GUIDANCE related sources as dirty for FFTI + for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { + if (fftiName.startsWith(sourceString)) { + System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); + ffmpgen.getFFTIData(fftiName).reset(true); + } + } + + } else { + + sourceString = source.getDisplayName() + "-" + iSiteKey + "-"+ iDataKey; + + // Mark this source as dirty for FFTI + if (ffmpgen.isFFTI(sourceString)) { + //System.out.println("Resetting FFTI source for processing!!!!! "+sourceString); + ffmpgen.getFFTIData(sourceString).reset(true); + + // Mark associated sources as dirty for FFTI + for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { + String[] name = fftiName.split("-"); + if (name.length == 3) { + if (name[1].equals(source.getDisplayName()) && name[2].equals(iDataKey)) { + //System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); + ffmpgen.getFFTIData(fftiName).reset(true); + } + } + } + } } + + Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() + - (backTime)); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - sourceContainer = ffmpgen.getFFMPDataContainer(sourceString); + sourceContainer = ffmpgen.getFFMPDataContainer(sourceString, hucs, backDate); - // we attempt to reload sourecs + // we attempt to reload sources // this is done to keep all of the clustered // FFMP's in sync. otherwise one JVM would never // be updated with what the other had processed. @@ -157,28 +183,21 @@ public class FFTIProcessor { // check back this far for an existing file boolean reload = false; - if (source.getSourceName().equals(ffmpRec.getSourceName()) - && iSiteKey.equals(ffmpRec.getSiteKey()) - || source - .getSourceType() + if (source.getSourceType() .equals(FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE .getSourceType())) { reload = true; - } else { - if (ffmpgen.checkBuddyFile(source.getSourceName() + "-" - + iSiteKey + "-" + iSiteKey, "ALL", sourceString, - barrierTime)) { - reload = true; - } - } + } if (reload) { sourceContainer = new FFMPDataContainer(sourceString); - ffmpgen.getFFMPData().put(sourceString, sourceContainer); } } if (sourceContainer != null) { + + boolean write = false; + if (source.getSourceType().equals( SOURCE_TYPE.GUIDANCE.getSourceType())) { @@ -187,7 +206,7 @@ public class FFTIProcessor { ProductXML product = ffmpgen.fscm.getProduct(primarySource); Date ffgBackDate = new Date(ffmpRec.getDataTime() .getRefTime().getTime() - - (3600 * 1000 * 6)); + - (ffgbackTime)); // try to load any missing one's, other than the new one for (SourceXML guidSource : product @@ -196,15 +215,19 @@ public class FFTIProcessor { .getSourceName()) && !source.getSourceName().equals( guidSource.getSourceName())) { + sourceContainer = populateDataContainer( sourceContainer, ffmpgen.template, null, ffgBackDate, ffmpRec.getDataTime() .getRefTime(), wfo, source, iSiteKey); + + sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); + write = true; } } - } else { + } /*else { Date newDate = sourceContainer.getNewest(); Date oldDate = sourceContainer.getOldest(); @@ -220,6 +243,10 @@ public class FFTIProcessor { newDate, ffmpRec.getDataTime().getRefTime(), wfo, source, iSiteKey); + + sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); + write = true; + } else if (oldDate .after(new Date( barrierTime.getTime() @@ -230,6 +257,9 @@ public class FFTIProcessor { sourceContainer = populateDataContainer( sourceContainer, ffmpgen.template, null, barrierTime, oldDate, wfo, source, iSiteKey); + + sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); + write = true; } } else { // COMPLETELY EMPTY SOURCE CONTAINER @@ -240,13 +270,21 @@ public class FFTIProcessor { barrierTime, ffmpRec.getDataTime().getRefTime(), wfo, source, iSiteKey); + + sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); + write = true; } } - - purge(barrierTime, sourceContainer); + + */ + + if (write) { + sourceContainer.purge(ffgBarrierTime); + //System.out.println("Writing from with in the FFTI Processor!!! "+sourceContainer.getFilePath()); + ffmpgen.writeLoaderBuddyFiles(sourceContainer); + } } } - } /** @@ -262,7 +300,7 @@ public class FFTIProcessor { */ public static FFMPDataContainer populateDataContainer( FFMPDataContainer sourceContainer, FFMPTemplates template, - Set hucs, Date startDate, Date endDate, String wfo, + ArrayList hucs, Date startDate, Date endDate, String wfo, SourceXML source, String siteKey) { ArrayList uris = getUris(startDate, endDate, wfo, source, @@ -288,12 +326,12 @@ public class FFTIProcessor { if (!contains) { try { + if (hucs == null) { - HashMap myHucs = new HashMap(); - myHucs.put("ALL", "ALL"); - hucs = myHucs.keySet(); + hucs = new ArrayList(); + hucs.add("ALL"); } - + for (String huc : hucs) { rec = populateRecord(rec, huc, template); @@ -417,16 +455,4 @@ public class FFTIProcessor { return rec; } - - /** - * Rid us of old entries - * - * @param barrierTime - * @param sourceContainer - */ - private void purge(Date barrierTime, FFMPDataContainer sourceContainer) { - for (String huc : sourceContainer.getKeys()) { - sourceContainer.getBasinData(huc).purgeData(barrierTime); - } - } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java index 19550d1dd7..8f088bb4b4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java @@ -38,14 +38,12 @@ import java.util.ArrayList; * @version 1.0 */ -public class FFTIRatioDiff { +public class FFTIRatioDiff extends FFTIData { private ArrayList qpes; private ArrayList guids; - - private Double gap = 0.0; - + public FFTIRatioDiff() { } @@ -72,13 +70,5 @@ public class FFTIRatioDiff { public void setGuids(ArrayList guids) { this.guids = guids; } - - public Double getGap() { - return gap; - } - - public void setGap(Double gap) { - this.gap = gap; - } - + } diff --git a/edexOsgi/com.raytheon.uf.tools.cli/impl/capture b/edexOsgi/com.raytheon.uf.tools.cli/impl/capture old mode 100755 new mode 100644 index 4de6b7b53b..22d95b42b8 --- a/edexOsgi/com.raytheon.uf.tools.cli/impl/capture +++ b/edexOsgi/com.raytheon.uf.tools.cli/impl/capture @@ -13,9 +13,11 @@ REMOTE_SERVERS_TO_CHECK="dx1f dx3 dx4" # Flags to control what data capure grabs, to enable flag must be YES, anything else will be considered off. RUN_JSTACK="Y" RUN_JMAP="Y" +RUN_QPID_STAT="Y" MOVE_ALL_HS_ERR_PID="Y" # For remote top you must have ssh keys setup to allow automatic login, otherwise password prompt will get sent to log file and script will never exit GRAB_REMOTE_TOP="Y" +GRAB_REMOTE_VMSTAT="Y" GRAB_CAVE_AND_ALERTVIZ_LOGS="Y" EDEX_MODE="N" FORCE="N" @@ -46,6 +48,9 @@ usage() { echo -e "-f {y/n}\t\tdefault [$FORCE]" echo " Force a jstack/jmap by default" echo + echo -e "-q {y/n}\t\tdefault [$RUN_QPID_STAT]" + echo " Force a qpid-stat by default" + echo echo -e "-m {y/n}\t\tdefault [$MOVE_ALL_HS_ERR_PID]" echo " Captures all hs_err_pid's found" echo @@ -55,6 +60,9 @@ usage() { echo -e "-t {y/n}\t\tdefault [$GRAB_REMOTE_TOP]" echo " Captures top information from servers, auto login must be enabled" echo + echo -e "-v {y/n}\t\tdefault [$GRAB_REMOTE_VMSTAT]" + echo " Captures vmstat information from servers, auto login must be enabled" + echo echo -e "-c \"{host names}\"\tdefault [$REMOTE_SERVERS_TO_CHECK]" echo " The servers to grab top information from, make sure list is quoted and space delimited" echo @@ -116,11 +124,26 @@ grabRemoteTop() { t1=`date "+%Y%m%d %H:%M:%S"` echo "${t1}: Capturing top for $server" >> $processFile out_file="${dataPath}/top_$server.log" - ssh $server "export COLUMNS=160; top -b -c -n1" >> $out_file 2>&1 & + ssh $server "sh -c 'export COLUMNS=160; top -b -c -n1' " >> $out_file 2>&1 & done fi } +# runs ssh command to grab vmstat on a remote server, requires auto login to be setup +grabRemoteVmstat() { + if [ "$GRAB_REMOTE_VMSTAT" == "y" ]; then + echo "Capturing vmstat on remote servers" + for server in ${REMOTE_SERVERS_TO_CHECK}; + do + t1=`date "+%Y%m%d %H:%M:%S"` + echo "${t1}: Capturing vmstat for $server" >> $processFile + out_file="${dataPath}/vmstat_$server.log" + ssh $server "sh -c 'vmstat -w 1 5' " >> $out_file 2>&1 & + done + fi +} + + checkForProcsAsOtherUsers() { if [ ! -z "$procs" ]; then numMyProcs=`echo "$myProcs" | wc -l` @@ -225,6 +248,21 @@ runJmap() { $cmd >> ${prePath}dump.log 2>&1 & } +# runs qpid-stat +runQpidStat() { + local qpidHost=cp1f + local prePath="${dataPath}/" + local t1=`date "+%Y%m%d %H:%M:%S"` + local cmd="/awips2/python/bin/qpid-stat -q -Smsg -L100 ${qpidHost}" + echo "${t1}: Running command: $cmd >> ${prepath}qpid-stat.log 2>&1 &" >> $processFile + if [ "$ACCUM" = "y" ]; then + echo >> ${prePath}qpid-stat.log + echo >> ${prePath}qpid-stat.log + echo "Running for $t1" >> ${prePath}qpid-stat.log + fi + $cmd >> ${prePath}qpid-stat.log 2>&1 & +} + # runs versions.sh to grab version info runVersions() { local t1=`date "+%Y%m%d %H:%M:%S"` @@ -240,6 +278,7 @@ while [ ! -z "$1" ]; do case $arg in -p) cavePid="$1"; shift 1;; + -q) RUN_QPID_STAT="$1"; shift 1;; -g) grepString="$1"; shift 1;; -r) REMOTE_SERVERS_TO_CHECK="$1"; shift 1;; -s) RUN_JSTACK="$1"; shift 1;; @@ -251,6 +290,7 @@ while [ ! -z "$1" ]; do -z) TGZ_OUTPUT="$1"; shift 1;; -e) EDEX_MODE="Y"; edexProcs[$edexProcCount]="$1"; shift 1; let "edexProcCount+=1";; -a) ACCUM="$1"; shift 1;; + -v) GRAB_REMOTE_VMSTAT="$1"; shift 1;; -h|*) usage;; esac done @@ -258,9 +298,11 @@ done # validate inputs checkYes RUN_JSTACK $RUN_JSTACK checkYes RUN_JMAP $RUN_JMAP +checkYes RUN_QPID_STAT $RUN_QPID_STAT checkYes FORCE $FORCE checkYes MOVE_ALL_HS_ERR_PID $MOVE_ALL_HS_ERR_PID checkYes GRAB_REMOTE_TOP $GRAB_REMOTE_TOP +checkYes GRAB_REMOTE_VMSTAT $GRAB_REMOTE_VMSTAT checkYes GRAB_CAVE_AND_ALERTVIZ_LOGS $GRAB_CAVE_AND_ALERTVIZ_LOGS checkYes EDEX_MODE $EDEX_MODE checkYes TGZ_OUTPUT $TGZ_OUTPUT @@ -283,6 +325,7 @@ if [ "$EDEX_MODE" == "y" ]; then GRAB_CAVE_AND_ALERTVIZ_LOGS="n" MOVE_ALL_HS_ERR_PID="n" GRAB_REMOTE_TOP="n" + GRAB_REMOTE_VMSTAT="n" fi umask 0002 @@ -315,10 +358,12 @@ cd $dataPath processFile=${dataPath}/capture_info.log export COLUMNS=160 top -b -c -n1 >> "${dataPath}/top_$hostName.log" +vmstat -w 1 5 >> "${dataPath}/vmstat_$hostName.log" if [ "$ACCUM" == "y" ]; then echo "" >> "${dataPath}/top_$hostName.log" echo "" >> "${dataPath}/top_$hostName.log" + echo "" >> "${dataPath}/vmstat_$hostName.log" fi @@ -412,8 +457,12 @@ if [ ! -z "${myProcs}" ]; then done fi + runQpidStat + grabRemoteTop + grabRemoteVmstat + # grab all jmaps if [ "$RUN_JMAP" == "y" ]; then if [ ! -z ${cavePid} ]; then @@ -450,7 +499,9 @@ else echo "${t1}: NO processes found for $user" >> $processFile echo "" >> $processFile + runQpidStat grabRemoteTop + grabRemoteVmstat fi # move all hs_err_pid from user's home directory to capture directory diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/export_configuration b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/export_configuration index e011a11baf..d38bc35396 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/export_configuration +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/export_configuration @@ -58,7 +58,7 @@ mkdir -p $commonDest/site log_msg 25 log_msg Making temporary cave configuration directories -mkdir -p $caveDest/site +mkdir -p $caveDest/site/colormaps log_msg 30 # Copies the localization information to the staging area @@ -78,8 +78,12 @@ log_msg Copying cave site configuration for site ${CAPS_SITE} to temporary direc cp -r ${LOCALIZATION_PATH}/cave_static/site/${CAPS_SITE}/gfe $caveDest/site log_msg 70 +log_msg Copying cave site configuration for site ${CAPS_SITE} to temporary directory... +cp -r ${LOCALIZATION_PATH}/cave_static/site/${CAPS_SITE}/colormaps/GFE $caveDest/site/colormaps +log_msg 80 + # Tar up everything. -log_msg 75 +log_msg 85 log_msg Tarring and zipping configuration to file GFEconfig.${SITE}.tar.gz tar cf - GFEconfig|gzip -9 - > GFEconfig.${SITE}.tar.gz if [ $? -ne 0 ] @@ -92,12 +96,12 @@ fi log_msg Cleaning up temporary files rm -fR GFEconfig -log_msg 85 +log_msg 90 log_msg Preparing compressed file for exporting to central server... log_msg Compressing to file svc_bkup_${SITE}.tar tar cf svc_bkup_${SITE}.tar *.gz siteID.txt -log_msg 95 +log_msg 93 #check for failure of the tar file if [ $? -ne 0 ] @@ -117,7 +121,7 @@ rm siteID.txt log_msg Sending the tar file to the central server... -log_msg 100 +log_msg 95 # Check to see if ${SVCBU_WMO_HEADER} is assigned a value. If so, call msg_send with -i. # Otherwise, don't call it with -i @@ -147,5 +151,5 @@ log_msg Successfully sent message. MESSAGE ID: $msgSendOutput #echo ${SVCBU_HOME}/* | xargs rm -rf rm -f ${LOCK_DIR}/${SITE}exportConfig log_msg Configuration data has been exported! -log_msg 110 +log_msg 100 exit 0 diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/proc_receive_config b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/proc_receive_config index 5dee535a17..d82567bcdc 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/proc_receive_config +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/scripts/proc_receive_config @@ -132,8 +132,8 @@ cp -r GFEconfig/edex_static/site/gfe ${edex_site_dest} log_msg 80 cp -r GFEconfig/edex_static/site/smartinit ${edex_site_si_dest} log_msg 90 -cp -r GFEconfig/cave_static/site/gfe ${cave_site_dest} -log_msg 100 +cp -r GFEconfig/cave_static/site ${cave_site_dest} +log_msg 93 log_msg "Files successfully copied!" log_msg "Changing ownership of received configuration" @@ -150,7 +150,7 @@ else fi -log_msg 105 +log_msg 95 #Change the MHS ID of the received configuration backup_config=${LOCALIZATION_PATH}/edex_static/site/${my_site_caps}/config/gfe/siteConfig.py @@ -170,6 +170,6 @@ cd ${SVCBU_HOME} rm -rf * rm -f ${LOCK_DIR}/importConfiguration -log_msg 110 +log_msg 100 touch ${LOCK_DIR}/${SITE}svcbuMode log_msg "Configuration Import Complete!" diff --git a/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_SiteSpecific b/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_SiteSpecific old mode 100755 new mode 100644 diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp.linux32/libbignsharp.so b/ncep/gov.noaa.nws.ncep.ui.nsharp.linux32/libbignsharp.so index 8976fbfd55..08b347ea2f 100644 Binary files a/ncep/gov.noaa.nws.ncep.ui.nsharp.linux32/libbignsharp.so and b/ncep/gov.noaa.nws.ncep.ui.nsharp.linux32/libbignsharp.so differ diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp.linux64/libbignsharp.so b/ncep/gov.noaa.nws.ncep.ui.nsharp.linux64/libbignsharp.so index 1019181247..f1fe2c24a5 100644 Binary files a/ncep/gov.noaa.nws.ncep.ui.nsharp.linux64/libbignsharp.so and b/ncep/gov.noaa.nws.ncep.ui.nsharp.linux64/libbignsharp.so differ diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/AwcNsharp/basics.c b/ncep/gov.noaa.nws.ncep.ui.nsharp/AwcNsharp/basics.c index b770e8851a..06703b91c7 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/AwcNsharp/basics.c +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/AwcNsharp/basics.c @@ -657,12 +657,14 @@ /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (m) to (ft). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if( value <= -998.0F ) { return -999; } else - { return value / .3049F; } + { return value / .3048F; } } /*NP*/ @@ -672,12 +674,14 @@ /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (ft) to (m). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if( value <= -998.0F ) { return -999; } else - { return value * .3049F; } + { return value * .3048F; } } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics.c b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics.c index c5f01e6913..4f90b549e0 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics.c +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics.c @@ -499,12 +499,14 @@ float mtof(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (m) to (ft). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value / 0.3049); + return (value / 0.3048); } @@ -514,12 +516,14 @@ float ftom(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (ft) to (m). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value * .3049); + return (value * .3048); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.c b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.c index c772aa9716..9d024771d3 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.c +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.c @@ -498,12 +498,14 @@ float mtof(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (m) to (ft). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value / 0.3049); + return (value / 0.3048); } @@ -513,12 +515,14 @@ float ftom(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (ft) to (m). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value * .3049); + return (value * .3048); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.cold b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.cold index c772aa9716..9d024771d3 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.cold +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/basics_old.cold @@ -498,12 +498,14 @@ float mtof(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (m) to (ft). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value / 0.3049); + return (value / 0.3048); } @@ -513,12 +515,14 @@ float ftom(float value) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (ft) to (m). */ + /* */ + /* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if (!qc(value)) return RMISSD; else - return (value * .3049); + return (value * .3048); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF index 95c46b9696..12fc02ed5e 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF @@ -59,12 +59,17 @@ Import-Package: com.raytheon.edex.meteoLib, org.geotools.referencing, org.opengis.referencing.crs Export-Package: gov.noaa.nws.ncep.ui.nsharp, + gov.noaa.nws.ncep.ui.nsharp.background, + gov.noaa.nws.ncep.ui.nsharp.display, + gov.noaa.nws.ncep.ui.nsharp.display.map, + gov.noaa.nws.ncep.ui.nsharp.display.rsc, gov.noaa.nws.ncep.ui.nsharp.maprsc, gov.noaa.nws.ncep.ui.nsharp.menu, gov.noaa.nws.ncep.ui.nsharp.natives, gov.noaa.nws.ncep.ui.nsharp.palette, gov.noaa.nws.ncep.ui.nsharp.skewt, gov.noaa.nws.ncep.ui.nsharp.skewt.bkgd, - gov.noaa.nws.ncep.ui.nsharp.skewt.rsc + gov.noaa.nws.ncep.ui.nsharp.skewt.rsc, + gov.noaa.nws.ncep.ui.nsharp.view Bundle-ClassPath: ., jna.jar diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject index 2055dee5c1..d476cd80a2 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject @@ -1,2 +1,10 @@ gov.noaa.nws.ncep.ui.nsharp.NsharpConfigStore -gov.noaa.nws.ncep.ui.nsharp.NsharpLineProperty \ No newline at end of file +gov.noaa.nws.ncep.ui.nsharp.NsharpLineProperty +gov.noaa.nws.ncep.ui.nsharp.NsharpGraphProperty +gov.noaa.nws.ncep.ui.nsharp.NsharpDataPageProperty +gov.noaa.nws.ncep.ui.nsharp.display.NsharpSkewTPaneDisplay +gov.noaa.nws.ncep.ui.nsharp.display.NsharpInsetPaneDisplay +gov.noaa.nws.ncep.ui.nsharp.display.NsharpDataPaneDisplay +gov.noaa.nws.ncep.ui.nsharp.display.NsharpHodoPaneDisplay +gov.noaa.nws.ncep.ui.nsharp.display.NsharpTimeStnPaneDisplay +gov.noaa.nws.ncep.ui.nsharp.display.NsharpWitoPaneDisplay diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/basics.c b/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/basics.c index 1e5933939a..45b7c09f14 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/basics.c +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/basics.c @@ -682,12 +682,14 @@ float mtof ( float value ) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (m) to (ft). */ +/* */ +/* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if( value <= -998.0F ) { return -999; } else - { return value / .3049F; } + { return value / .3048F; } } /*=============================================================================*/ @@ -698,12 +700,14 @@ float ftom ( float value ) /* John Hart NSSFC KCMO */ /* */ /* Converts given distance (ft) to (m). */ +/* */ +/* T. Lee 7/2012 Changed .3049 to .3048 */ /*************************************************************/ { if( value <= -998.0F ) { return -999; } else - { return value * .3049F; } + { return value * .3048F; } } /*=============================================================================*/ diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/plugin.xml b/ncep/gov.noaa.nws.ncep.ui.nsharp/plugin.xml index 6145b024cf..83da9d88cb 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/plugin.xml +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/plugin.xml @@ -10,9 +10,9 @@ - + @@ -25,9 +25,25 @@ category="gov.noaa.nws.ncep.ui.nsharp.view" allowMultiple="false" restorable="true" - class="gov.noaa.nws.ncep.ui.nsharp.palette.NsharpPaletteWindow" + class="gov.noaa.nws.ncep.ui.nsharp.view.NsharpPaletteWindow" id="gov.noaa.nws.ncep.ui.nsharp" name="NSHARP"/> + + + + diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConfigManager.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConfigManager.java index 4785f5a438..3414fdcc3f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConfigManager.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConfigManager.java @@ -22,7 +22,6 @@ */ package gov.noaa.nws.ncep.ui.nsharp; -import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNativeConstants; import gov.noaa.nws.ncep.viz.localization.NcPathManager.NcPathConstants; import java.io.File; diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConstants.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConstants.java index 11dbbc9784..5dc6970cfe 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConstants.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpConstants.java @@ -23,12 +23,14 @@ import gov.noaa.nws.ncep.viz.localization.NcPathManager; import gov.noaa.nws.ncep.viz.localization.NcPathManager.NcPathConstants; import java.text.DecimalFormat; + import javax.measure.converter.UnitConverter; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; + import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle; public class NsharpConstants { @@ -379,16 +381,17 @@ public class NsharpConstants { * * ****/ - public static final int DISPLAY_SKEWT=0; - public static final int DISPLAY_WITO= DISPLAY_SKEWT+1; //Wind box + InferredTemp + Omega - public static final int DISPLAY_INSET= DISPLAY_WITO+1; - public static final int DISPLAY_HODO= DISPLAY_INSET+1; - public static final int DISPLAY_TIMESTN= DISPLAY_HODO+1; - public static final int DISPLAY_DATA=DISPLAY_TIMESTN+1; - public static final int DISPLAY_TOTAL= DISPLAY_DATA+1; - public static final int CHAR_HEIGHT_ = 15; + /*public static final int DISPLAY_SKEWT=0; + public static final int DISPLAY_WITO= DISPLAY_SKEWT+1; //Wind box + InferredTemp + Omega + public static final int DISPLAY_INSET= DISPLAY_WITO+1; + public static final int DISPLAY_HODO= DISPLAY_INSET+1; + public static final int DISPLAY_TIMESTN= DISPLAY_HODO+1; + public static final int DISPLAY_DATA=DISPLAY_TIMESTN+1; + public static final int DISPLAY_SPC_GRAPHS= DISPLAY_DATA+1; + public static final int DISPLAY_TOTAL= DISPLAY_SPC_GRAPHS+1;*/ + public static final int CHAR_HEIGHT_ = 15; - //note: dimensions are used as reference for its components inside its pane and only relative within its own pane. + //note: dimensions are used as reference for its components inside its pane and only relative within its own pane. //Sizes defined here have no significant meaning between two different panes. public static final int DISPLAY_WIDTH= 1600; public static final int DISPLAY_HEIGHT= 820; @@ -408,8 +411,10 @@ public class NsharpConstants { public static Rectangle WITO_DISPLAY_REC = new Rectangle(0, 0, WITO_PANE_REC_WIDTH, WITO_PANE_REC_HEIGHT); public static Rectangle HODO_DISPLAY_REC = new Rectangle(0, 0, HODO_PANE_REC_WIDTH, HODO_PANE_REC_HEIGHT); public static Rectangle TIMESTN_DISPLAY_REC = new Rectangle(0, 0, TIMESTN_PANE_REC_WIDTH, TIMESTN_PANE_REC_HEIGHT); + public static Rectangle FUTURE_DISPLAY_REC = new Rectangle(0, 0, TIMESTN_PANE_REC_WIDTH, TIMESTN_PANE_REC_HEIGHT); public static Rectangle DATA_DISPLAY_REC = new Rectangle(0, 0, DATA_PANE_REC_WIDTH, DATA_PANE_REC_HEIGHT); public static Rectangle INSET_DISPLAY_REC = new Rectangle(0, 0, INSET_PANE_REC_WIDTH, INSET_PANE_REC_HEIGHT); + public static Rectangle SPC_GRAPH_DISPLAY_REC = new Rectangle(0, 0, DATA_PANE_REC_WIDTH, DATA_PANE_REC_HEIGHT); public static final int SKEWT_WIDTH = SKEWT_PANE_REC_WIDTH;//=550 public static final int SKEWT_HEIGHT = SKEWT_PANE_REC_HEIGHT;//570 public static final int SKEWT_X_ORIG = 0; @@ -443,7 +448,7 @@ public class NsharpConstants { public static final int OMEGA_WIDTH = WITO_PANE_REC_WIDTH/3; public static final int OMEGA_HEIGHT = SKEWT_HEIGHT; public static final int OMEGA_Y_END = SKEWT_Y_END; - public static final int OMEGA_MAGNIFICATION_FACTOR = 35; + public static final int OMEGA_MAGNIFICATION_FACTOR = 20; public static final int HODO_X_ORIG = 0; public static final int HODO_Y_ORIG = 0;//40; public static final int HODO_WIDTH = HODO_PANE_REC_WIDTH; @@ -451,6 +456,11 @@ public class NsharpConstants { public static final int HODO_X_END = HODO_X_ORIG + HODO_WIDTH; public static final float HODO_CENTER_X_ = HODO_X_ORIG + (float)(5.00/12.00) * HODO_WIDTH; public static final float HODO_CENTER_Y_ = HODO_Y_ORIG + (float)(1.00/2.00) * HODO_HEIGHT; + public static final int HODO_COORDINATE_X1 = -50; + public static final int HODO_COORDINATE_Y1 = 75; + public static final int HODO_COORDINATE_X2 = 70; + public static final int HODO_COORDINATE_Y2 = -95; + public static final int DATA_TIMELINE_X_ORIG = 0; public static final int DATA_TIMELINE_Y_ORIG = 40; public static final int DATA_TIMELINE_WIDTH = TIMESTN_PANE_REC_WIDTH/2; @@ -518,7 +528,93 @@ public class NsharpConstants { public static final int SRWINDVTRS_Y_ORIG = THETAP_Y_ORIG; public static final int SRWINDVTRS_X_END = SRWINDVTRS_X_ORIG+INSET_WIDTH; public static final int SRWINDVTRS_Y_END = SRWINDVTRS_Y_ORIG+INSET_HEIGHT; + + public static final String PANE_LEGACY_CFG_STR = "Legacy Configuration (obsoleting)"; + public static final String PANE_DEF_CFG_1_STR = "Default Configuration 1"; + public static final String PANE_DEF_CFG_2_STR = "Default Configuration 2"; + public static final String PANE_SPCWS_CFG_STR = "SPC Wide Screen Configuration"; + public static final String PANE_SIMPLE_D2D_CFG_STR = "D2D Skewt Standard Screen Configuration"; + public static final String[] PANE_CONFIGURATION_NAME = {PANE_DEF_CFG_1_STR, PANE_DEF_CFG_2_STR,PANE_SPCWS_CFG_STR,PANE_SIMPLE_D2D_CFG_STR, PANE_LEGACY_CFG_STR}; + + //pane width and height ratio to full canvas size + // pane default configuration 1 + // full canvas consists of left group and right group + // left group has left top and bottom groups + // left top group contains skewt and wito panes + // left bottom group contains time/stn and insets panes + // right group has hodo and data panes + public static final double PANE_DEF_CFG_1_LEFT_GP_WIDTH_RATIO = 0.75; + public static final double PANE_DEF_CFG_1_LEFT_TOP_GP_HEIGHT_RATIO = 0.8; + public static final double PANE_DEF_CFG_1_RIGHT_TOP_GP_HEIGHT_RATIO = 0.4; + public static final double PANE_DEF_CFG_1_SKEWT_WIDTH_RATIO = 0.8; + public static final double PANE_DEF_CFG_1_SKEWT_HEIGHT_RATIO = PANE_DEF_CFG_1_LEFT_TOP_GP_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_1_WITO_WIDTH_RATIO = 1-PANE_DEF_CFG_1_SKEWT_WIDTH_RATIO; + public static final double PANE_DEF_CFG_1_WITO_HEIGHT_RATIO = PANE_DEF_CFG_1_SKEWT_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_1_HODO_WIDTH_RATIO = 1; + public static final double PANE_DEF_CFG_1_HODO_HEIGHT_RATIO = PANE_DEF_CFG_1_RIGHT_TOP_GP_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_1_INSET_WIDTH_RATIO = 0.5; + public static final double PANE_DEF_CFG_1_INSET_HEIGHT_RATIO = 1-PANE_DEF_CFG_1_SKEWT_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_1_TIMESTN_WIDTH_RATIO = 1-PANE_DEF_CFG_1_INSET_WIDTH_RATIO; + public static final double PANE_DEF_CFG_1_TIMESTN_HEIGHT_RATIO = PANE_DEF_CFG_1_INSET_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_1_DATA_WIDTH_RATIO = 1; + public static final double PANE_DEF_CFG_1_DATA_HEIGHT_RATIO = 1-PANE_DEF_CFG_1_HODO_HEIGHT_RATIO; + // pane default configuration 2 + // full canvas consists of left group and right group + // both groups contains top and bottom groups + // left top group contains skewt and wito panes + // left bottom group contains insets panes + // right top group has hodo and time/stn panes + // right bottom contains data panes + public static final double PANE_DEF_CFG_2_LEFT_GP_WIDTH_RATIO = 0.5; + public static final double PANE_DEF_CFG_2_LEFT_TOP_GP_HEIGHT_RATIO = 0.8; + public static final double PANE_DEF_CFG_2_RIGHT_TOP_GP_HEIGHT_RATIO = 0.7; + public static final double PANE_DEF_CFG_2_SKEWT_WIDTH_RATIO = 0.85; + public static final double PANE_DEF_CFG_2_SKEWT_HEIGHT_RATIO = PANE_DEF_CFG_2_LEFT_TOP_GP_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_2_WITO_WIDTH_RATIO = 1-PANE_DEF_CFG_2_SKEWT_WIDTH_RATIO; + public static final double PANE_DEF_CFG_2_WITO_HEIGHT_RATIO = PANE_DEF_CFG_2_SKEWT_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_2_HODO_WIDTH_RATIO = 0.65; + public static final double PANE_DEF_CFG_2_HODO_HEIGHT_RATIO = PANE_DEF_CFG_2_RIGHT_TOP_GP_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_2_INSET_WIDTH_RATIO = 1; + public static final double PANE_DEF_CFG_2_INSET_HEIGHT_RATIO = 1-PANE_DEF_CFG_2_SKEWT_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_2_TIMESTN_WIDTH_RATIO = 0.35; + public static final double PANE_DEF_CFG_2_TIMESTN_HEIGHT_RATIO = PANE_DEF_CFG_2_HODO_HEIGHT_RATIO; + public static final double PANE_DEF_CFG_2_DATA_WIDTH_RATIO = 1; + public static final double PANE_DEF_CFG_2_DATA_HEIGHT_RATIO = 1-PANE_DEF_CFG_2_HODO_HEIGHT_RATIO; + + // pane SPC wide screen configuration + public static final double PANE_SPCWS_CFG_TOP_GP_HEIGHT_RATIO = 0.714; //5/7 + public static final double PANE_SPCWS_CFG_BOT_GP_HEIGHT_RATIO = 1-PANE_SPCWS_CFG_TOP_GP_HEIGHT_RATIO; + //skewt, wito, hodo/inset (hodo stack on inset) panes are located on top group + public static final double PANE_SPCWS_CFG_SKEWT_WIDTH_RATIO = 0.4938;//5/10.125; + public static final double PANE_SPCWS_CFG_SKEWT_HEIGHT_RATIO = 1; + public static final double PANE_SPCWS_CFG_WITO_WIDTH_RATIO = 0.1111;//1.125/10.125; + public static final double PANE_SPCWS_CFG_WITO_HEIGHT_RATIO = 1; + public static final double PANE_SPCWS_CFG_HODO_WIDTH_RATIO = 1- PANE_SPCWS_CFG_SKEWT_WIDTH_RATIO-PANE_SPCWS_CFG_WITO_WIDTH_RATIO; + public static final double PANE_SPCWS_CFG_HODO_HEIGHT_RATIO = 0.825;//4.125/5; + public static final double PANE_SPCWS_CFG_INSET_WIDTH_RATIO = PANE_SPCWS_CFG_HODO_WIDTH_RATIO; + public static final double PANE_SPCWS_CFG_INSET_HEIGHT_RATIO = 1- PANE_SPCWS_CFG_HODO_HEIGHT_RATIO; + //data and other graphs panes are located on bottom group + public static final double PANE_SPCWS_CFG_DATA_WIDTH_RATIO = 0.5; + public static final double PANE_SPCWS_CFG_DATA_HEIGHT_RATIO = 1; + public static final double PANE_SPCWS_CFG_SPC_GRAPHS_WIDTH_RATIO = 0.5; + public static final double PANE_SPCWS_CFG_SPC_GRAPHS_HEIGHT_RATIO = 1; + //simple D2D pane configuration. + // full canvas consists of top and bottom group + public static final double PANE_SIMPLE_D2D_CFG_TOP_GP_HEIGHT_RATIO = 0.71; + public static final double PANE_SIMPLE_D2D_CFG_BOT_GP_HEIGHT_RATIO = 1-PANE_SIMPLE_D2D_CFG_TOP_GP_HEIGHT_RATIO; + // top group contains left (skewt) and right groups (time/stn stack on future pane) + public static final double PANE_SIMPLE_D2D_CFG_SKEWT_WIDTH_RATIO = 0.75; + public static final double PANE_SIMPLE_D2D_CFG_SKEWT_HEIGHT_RATIO = 1; + public static final double PANE_SIMPLE_D2D_CFG_TIMESTN_WIDTH_RATIO = 1-PANE_SIMPLE_D2D_CFG_SKEWT_WIDTH_RATIO; + public static final double PANE_SIMPLE_D2D_CFG_TIMESTN_HEIGHT_RATIO = 0.5; + public static final double PANE_SIMPLE_D2D_CFG_FUTURE_WIDTH_RATIO = PANE_SIMPLE_D2D_CFG_TIMESTN_WIDTH_RATIO; + public static final double PANE_SIMPLE_D2D_CFG_FUTURE_HEIGHT_RATIO = 1-PANE_SIMPLE_D2D_CFG_TIMESTN_HEIGHT_RATIO; + // bottom group has hodo on left and data pane on right + public static final double PANE_SIMPLE_D2D_CFG_HODO_WIDTH_RATIO = 0.34; + public static final double PANE_SIMPLE_D2D_CFG_HODO_HEIGHT_RATIO = 1; + public static final double PANE_SIMPLE_D2D_CFG_DATA_WIDTH_RATIO = 1-PANE_SIMPLE_D2D_CFG_HODO_WIDTH_RATIO; + public static final double PANE_SIMPLE_D2D_CFG_DATA_HEIGHT_RATIO = 1; /*** * * MULTIPLE PANES IMPLEMENTATIONS end diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpGraphProperty.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpGraphProperty.java index 7decc47ed4..6140f9d971 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpGraphProperty.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpGraphProperty.java @@ -90,6 +90,8 @@ public class NsharpGraphProperty implements ISerializableObject{ @XmlAttribute private int tempOffset=0; + @XmlAttribute + private String paneConfigurationName= NsharpConstants.PANE_LEGACY_CFG_STR; public boolean isTemp() { return temp; @@ -259,4 +261,14 @@ public class NsharpGraphProperty implements ISerializableObject{ public void setTempOffset(int tempOffset) { this.tempOffset = tempOffset; } + + public String getPaneConfigurationName() { + return paneConfigurationName; + } + + public void setPaneConfigurationName(String paneConfigurationName) { + this.paneConfigurationName = paneConfigurationName; + } + + } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpViewAction.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpViewAction.java new file mode 100644 index 0000000000..4ea0697cad --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpViewAction.java @@ -0,0 +1,90 @@ +/** + * + * gov.noaa.nws.ncep.ui.nsharp.palette.NsharpViewAction + * + * + * This code has been developed by the NCEP-SIB for use in the AWIPS2 system. + * + *
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    	Engineer    Description
    + * -------		------- 	-------- 	-----------
    + * 06/25/2012	229			Chin Chen	Initial coding
    + *
    + * 
    + * + * @author Chin Chen + * @version 1.0 + */ +package gov.noaa.nws.ncep.ui.nsharp; + + + +import gov.noaa.nws.ncep.ui.nsharp.display.map.NsharpMapResource; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; + +public class NsharpViewAction extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent arg0) throws ExecutionException { + NsharpConfigManager configMgr = NsharpConfigManager.getInstance(); + NsharpConfigStore configStore = configMgr.retrieveNsharpConfigStoreFromFs(); + NsharpGraphProperty graphConfigProperty = configStore.getGraphProperty(); + String paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); + System.out.println("paneConfigurationName ="+paneConfigurationName); + String viewid = "gov.noaa.nws.ncep.ui.nsharp.defaultview1"; + if(!paneConfigurationName.equals(NsharpConstants.PANE_LEGACY_CFG_STR)){ + /* + * The viewID string is in the XML file for NSHARP extension point. + */ + // multiple panes + viewid = "gov.noaa.nws.ncep.ui.nsharp.defaultview1"; + } + else { + //legacy configuration + /* + * The viewID string is in the XML file for NSHARP extension point. + */ + viewid = "gov.noaa.nws.ncep.ui.nsharp.defaultview2"; + } + + IWorkbenchPage wpage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + + IViewPart vpart = wpage.findView( viewid); + + try { + + if ( vpart == null ){ + + vpart = wpage.showView(viewid ); + //Chin MERGE moved this here from the NsharpPaletteWindow so we can open the view without an editor. + if (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) { + NsharpMapResource nsharpMapResource = NsharpMapResource.getOrCreateNsharpMapResource(); + nsharpMapResource.setPoints(null); + } + + } + else { + + if ( ! wpage.isPartVisible(vpart) ) vpart = wpage.showView( viewid ); + + } + } + catch (Exception e) { + + e.printStackTrace(); + + } + + + return null; + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/SurfaceStationPointData.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/SurfaceStationPointData.java index 9d08b68a16..090b7fcaa7 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/SurfaceStationPointData.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/SurfaceStationPointData.java @@ -20,9 +20,9 @@ package gov.noaa.nws.ncep.ui.nsharp; import gov.noaa.nws.ncep.viz.common.dbQuery.NcDirectDbQuery; -import java.io.IOException; import java.util.ArrayList; import java.util.List; + import org.geotools.referencing.GeodeticCalculator; import org.geotools.referencing.datum.DefaultEllipsoid; @@ -30,7 +30,6 @@ import com.raytheon.uf.common.dataquery.db.QueryResult; import com.raytheon.uf.common.dataquery.db.QueryResultRow; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage; -import com.raytheon.uf.viz.core.exception.VizException; import com.vividsolutions.jts.geom.Coordinate; public class SurfaceStationPointData { diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpGenericPaneBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpGenericPaneBackground.java index 7eb8f585a2..ae06dc65a9 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpGenericPaneBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpGenericPaneBackground.java @@ -29,7 +29,6 @@ import java.util.List; import org.eclipse.swt.graphics.Rectangle; -import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.drawables.IFont; diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpHodoPaneBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpHodoPaneBackground.java index e6c3bac968..91e0dd5214 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpHodoPaneBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpHodoPaneBackground.java @@ -49,14 +49,16 @@ public class NsharpHodoPaneBackground extends NsharpGenericPaneBackground { * @param paintProps * @throws VizException */ + //private float coordinateWtoHRatio; public NsharpHodoPaneBackground(NsharpHodoPaneDescriptor desc) { super(); - this.rectangle = new Rectangle(NsharpConstants.HODO_X_ORIG, NsharpConstants.HODO_Y_ORIG, - NsharpConstants.HODO_WIDTH, NsharpConstants.HODO_HEIGHT); + //this.rectangle = new Rectangle(NsharpConstants.HODO_X_ORIG, NsharpConstants.HODO_Y_ORIG, + // NsharpConstants.HODO_WIDTH, NsharpConstants.HODO_HEIGHT); + this.rectangle = new Rectangle(0,0,NsharpConstants.HODO_COORDINATE_X2-NsharpConstants.HODO_COORDINATE_X1, NsharpConstants.HODO_COORDINATE_Y2-NsharpConstants.HODO_COORDINATE_Y1); pe = new PixelExtent(this.rectangle); world = new WGraphics(this.rectangle); - world.setWorldCoordinates(-50,75,90,-95);//(-50, 90, 90, -50); - + world.setWorldCoordinates(NsharpConstants.HODO_COORDINATE_X1,NsharpConstants.HODO_COORDINATE_Y1,NsharpConstants.HODO_COORDINATE_X2,NsharpConstants.HODO_COORDINATE_Y2); + //coordinateWtoHRatio = ((float)NsharpConstants.HODO_COORDINATE_X2-(float)NsharpConstants.HODO_COORDINATE_X1)/ (NsharpConstants.HODO_COORDINATE_Y1-NsharpConstants.HODO_COORDINATE_Y2); //System.out.println("NsharpHodoPaneBackground constructed"); this.desc = desc; } @@ -82,8 +84,8 @@ public class NsharpHodoPaneBackground extends NsharpGenericPaneBackground { // draw the spokes. //System.out.println("paintInternal Begin"); for (double angle = 0; angle < 2 * Math.PI; angle += Math.PI / 2) { - double x = 200 * Math.cos(angle); - double y = 200 * Math.sin(angle); + double x = 360 * Math.cos(angle); + double y = 360 * Math.sin(angle); /*target.drawLine(c.x, c.y, 0.0, world.mapX(x), world.mapY( y), 0.0, NsharpConstants.degreeSpokeColor, 1, LineStyle.DOTTED);*/ @@ -94,7 +96,7 @@ public class NsharpHodoPaneBackground extends NsharpGenericPaneBackground { } // draw circles - for (int spd = 10; spd <= 120; spd += 10) { + for (int spd = 20; spd <= 360; spd += 20) { Coordinate c0, c1; c0 = WxMath.uvComp(spd, 0); @@ -105,6 +107,8 @@ public class NsharpHodoPaneBackground extends NsharpGenericPaneBackground { c0 = c1; } + if(spd > 100 && spd%20 != 0 ) + continue; //plot speed mark at 270 degree Coordinate uv = WxMath.uvComp(spd, 270); if (spd != 0) { @@ -232,7 +236,10 @@ public class NsharpHodoPaneBackground extends NsharpGenericPaneBackground { pe = new PixelExtent(this.rectangle); desc.setNewPe(pe); world = new WGraphics(this.rectangle); - world.setWorldCoordinates(-50,75,90,-95); + float hRatio = (NsharpConstants.HODO_COORDINATE_Y1-NsharpConstants.HODO_COORDINATE_Y2)/ (float)ext.getHeight(); + + float x2 = hRatio* (float)ext.getWidth()+ NsharpConstants.HODO_COORDINATE_X1; + world.setWorldCoordinates(NsharpConstants.HODO_COORDINATE_X1,NsharpConstants.HODO_COORDINATE_Y1,x2,NsharpConstants.HODO_COORDINATE_Y2); if(hodoShape!=null){ hodoShape.dispose(); hodoShape=null; diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpIcingPaneBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpIcingPaneBackground.java index 957ded21fe..5237b2f180 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpIcingPaneBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpIcingPaneBackground.java @@ -242,7 +242,7 @@ public class NsharpIcingPaneBackground extends NsharpGenericPaneBackground { double xmin = ext.getMinX(); world.setWorldCoordinates(NsharpConstants.ICING_RELATIVE_HUMIDITY_LEFT, toLogScale(NsharpConstants.ICING_PRESSURE_LEVEL_TOP), NsharpConstants.ICING_RELATIVE_HUMIDITY_RIGHT, toLogScale(NsharpConstants.ICING_PRESSURE_LEVEL_BOTTOM)); - Coordinate c = world.unMap(xmin, ymax); + //Coordinate c = world.unMap(xmin, ymax); double viewablePmax = reverseLogScale(world.unMap(xmin, ymax).y); return viewablePmax; } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java index 8aee4e2303..034caa753e 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java @@ -28,7 +28,6 @@ import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; import gov.noaa.nws.ncep.ui.nsharp.NsharpGraphProperty; import gov.noaa.nws.ncep.ui.nsharp.NsharpWxMath; import gov.noaa.nws.ncep.ui.nsharp.display.NsharpSkewTPaneDescriptor; -import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpResourceHandler; import java.awt.geom.Line2D; import java.awt.geom.Point2D; @@ -44,7 +43,10 @@ import com.raytheon.edex.util.Equations; import com.raytheon.edex.util.UAPoint; import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle; +import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle; +import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.drawables.IWireframeShape; import com.raytheon.uf.viz.core.drawables.PaintProperties; @@ -240,10 +242,11 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { createMoistAdiabatsShape(); createDryAdiabatsShape(); createMixingRatioShape(); - createPressureLineNumberShape(); + //createPressureLineNumberShape(); createTempNumberAndLineShape(); } - private void createPressureLineNumberShape(){ + @SuppressWarnings("unused") + private void createPressureLineNumberShape(){ //pressureLineNumberShape if(target==null) return; @@ -272,7 +275,7 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { //we only care about pressure for this case, temp is no important when calling getSkewTXY Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_MARK_LEVELS[i],0); - double [][] lines = {{world.mapX(NsharpConstants.left), world.mapY(coor.y)},{ world.mapX(NsharpConstants.left)+25* currentZoomLevel*xRatio, + double [][] lines = {{world.mapX(NsharpConstants.left), world.mapY(coor.y)},{ world.mapX(NsharpConstants.left)+15* currentZoomLevel*xRatio, world.mapY(coor.y)}}; presslinesNumbersShape.addLineSegment(lines); //System.out.println("coor.x="+coor.x+"coor.y="+coor.y); @@ -300,6 +303,64 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { } presslinesNumbersShape.compile(); } + // Chin: to handle dynamically moving pressure lines and its number within viewable zone when zooming, I could not use wireframeShape successfully + // It will chop off lower part. Therefore use this draw function. + @SuppressWarnings("deprecation") + private void drawPressureLineNumber(){ + //pressureLineNumberShape + if(target==null) + return; + String s = ""; + presslinesNumbersShape = target.createWireframeShape(false,desc ); + presslinesNumbersShape.allocate(150); + // System.out.println("NsharpConstants.left="+NsharpConstants.left+"NsharpConstants.right"+NsharpConstants.right+" top="+NsharpConstants.top + " bot="+ NsharpConstants.bottom); + // System.out.println("MAIN*******************"); + for (int i = 0; i < NsharpConstants.PRESSURE_MAIN_LEVELS.length; i++) { + //we only care about pressure for this case, temp is no important when calling getSkewTXY + Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_MAIN_LEVELS[i],0); + try { + target.drawLine(world.mapX(NsharpConstants.left), world.mapY(coor.y), 0.0, world.mapX(NsharpConstants.right), + world.mapY(coor.y), 0.0, + NsharpConstants.pressureColor, 1); + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + //System.out.println("MARK*******************"); + for (int i = 0; i < NsharpConstants.PRESSURE_MARK_LEVELS.length; i++) { + //we only care about pressure for this case, temp is no important when calling getSkewTXY + Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_MARK_LEVELS[i],0); + try { + target.drawLine(world.mapX(NsharpConstants.left), world.mapY(coor.y), 0.0, world.mapX(NsharpConstants.left)+15* currentZoomLevel*xRatio, + world.mapY(coor.y), 0.0, + NsharpConstants.pressureColor, 1); + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + IExtent ext = desc.getRenderableDisplay().getExtent(); + double xmin = ext.getMinX(); //Extent's viewable envelope min x and y + double xDefault = world.mapX(NsharpConstants.left); + if(xmin + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------- ------- -------- ----------- + * 05/02/2012 229 Chin Chen Initial coding for multiple display panes implementation + * + * + * + * @author Chin Chen + * @version 1.0 + */ +package gov.noaa.nws.ncep.ui.nsharp.display; + +import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpSpcGraphsPaneResource; + +import java.util.List; + +import com.raytheon.uf.viz.core.PixelExtent; + +public class NsharpSpcGraphsPaneDescriptor extends NsharpAbstractPaneDescriptor { + + public NsharpSpcGraphsPaneDescriptor(PixelExtent pe) { + super(pe); + //System.out.println("NsharpSpcGraphsPaneDescriptor created " + this.toString()); + } + public NsharpSpcGraphsPaneDescriptor(PixelExtent pe, int paneNumber) { + super(pe, paneNumber); + } + public NsharpSpcGraphsPaneResource getSpcGraphsResource() { + List list = resourceList + .getResourcesByTypeAsType(NsharpSpcGraphsPaneResource.class); + if (list != null && !list.isEmpty()) { + return list.get(0); + } + return null; + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSpcGraphsPaneDisplay.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSpcGraphsPaneDisplay.java new file mode 100644 index 0000000000..7a243aec5a --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpSpcGraphsPaneDisplay.java @@ -0,0 +1,89 @@ +/** + * + * gov.noaa.nws.ncep.ui.nsharp.display.NsharpSpcGraphsPaneDisplay + * + * This java class performs the NSHARP NsharpSpcGraphsPaneDisplay functions. + * This code has been developed by the NCEP-SIB for use in the AWIPS2 system. + * + *
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    	Engineer    Description
    + * -------		------- 	-------- 	-----------
    + * 07/2/2012	229			Chin Chen	Initial coding for multiple display panes implementation
    + *
    + * 
    + * + * @author Chin Chen + * @version 1.0 + */ +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.NsharpSpcGraphsPaneResourceData; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.PixelExtent; +import com.raytheon.uf.viz.core.drawables.PaintProperties; +import com.raytheon.uf.viz.core.drawables.ResourcePair; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractResourceData; +import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.uf.viz.core.rsc.ResourceList; +import com.raytheon.uf.viz.core.rsc.ResourceProperties; +import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement +public class NsharpSpcGraphsPaneDisplay extends NsharpAbstractPaneDisplay { + public NsharpSpcGraphsPaneDisplay(PixelExtent pixelExtent,int paneNumber) { + super(pixelExtent,paneNumber, "HodoPane",(NsharpAbstractPaneDescriptor)( new NsharpSpcGraphsPaneDescriptor(pixelExtent, paneNumber))); + } + + public NsharpSpcGraphsPaneDisplay() { + super(); + // TODO Auto-generated constructor stub + } + + public NsharpSpcGraphsPaneDisplay(PixelExtent pixelExtent, int paneNumber, + String name, NsharpAbstractPaneDescriptor desc) { + super(pixelExtent, paneNumber, name, desc); + // TODO Auto-generated constructor stub + } + + //@Override + //public NsharpSpcGraphsPaneDescriptor getDescriptor() { + // return (NsharpSpcGraphsPaneDescriptor) super.getDescriptor(); + //} + @Override + public void paint(IGraphicsTarget target, PaintProperties paintProps) + throws VizException { + super.paint(target, paintProps); + } + + @Override + protected void customizeResourceList(ResourceList resourceList) { + AbstractResourceData resourceData = new NsharpSpcGraphsPaneResourceData(); + // get a load properties + LoadProperties loadProperties = new LoadProperties(); + ColorableCapability colorableCapability = new ColorableCapability(); + colorableCapability.setColor(NsharpConstants.backgroundColor); + loadProperties.getCapabilities().addCapability(colorableCapability); + // get some resource properties + ResourceProperties resourceProperties = new ResourceProperties(); + resourceProperties.setVisible(true); + resourceProperties.setMapLayer(true); + resourceProperties.setSystemResource(true); + // Make a resource pair + ResourcePair resourcePair = new ResourcePair(); + resourcePair.setResourceData(resourceData); + resourcePair.setLoadProperties(loadProperties); + resourcePair.setProperties(resourceProperties); + // add it to the resource list. + resourceList.add(resourcePair); + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneDisplay.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneDisplay.java index 2194202e2b..71465bd2f9 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneDisplay.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneDisplay.java @@ -19,6 +19,10 @@ */ package gov.noaa.nws.ncep.ui.nsharp.display; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpTimeStnPaneResourceData; @@ -29,12 +33,19 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.ResourceList; import com.raytheon.uf.viz.core.rsc.ResourceProperties; import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; - +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement public class NsharpTimeStnPaneDisplay extends NsharpAbstractPaneDisplay { public NsharpTimeStnPaneDisplay(PixelExtent pixelExtent,int paneNumber) { super(pixelExtent,paneNumber, "TimeStnPane", new NsharpAbstractPaneDescriptor(pixelExtent, paneNumber)); } - @Override + + public NsharpTimeStnPaneDisplay() { + super(); + // TODO Auto-generated constructor stub + } + + @Override public NsharpAbstractPaneDescriptor getDescriptor() { return (NsharpAbstractPaneDescriptor) super.getDescriptor(); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneMouseHandler.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneMouseHandler.java index be2c1ee056..dc5118f502 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneMouseHandler.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpTimeStnPaneMouseHandler.java @@ -20,8 +20,6 @@ package gov.noaa.nws.ncep.ui.nsharp.display; -import org.eclipse.swt.widgets.Event; - import gov.noaa.nws.ncep.ui.nsharp.display.map.NsharpMapResource; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpTimeStnPaneResource; import gov.noaa.nws.ncep.ui.nsharp.palette.NsharpShowTextDialog; diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpWitoPaneDisplay.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpWitoPaneDisplay.java index 9e9b5fa3cd..375b1460c3 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpWitoPaneDisplay.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/NsharpWitoPaneDisplay.java @@ -19,6 +19,10 @@ */ package gov.noaa.nws.ncep.ui.nsharp.display; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpWitoPaneResourceData; @@ -29,12 +33,19 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.ResourceList; import com.raytheon.uf.viz.core.rsc.ResourceProperties; import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; - +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement public class NsharpWitoPaneDisplay extends NsharpAbstractPaneDisplay { public NsharpWitoPaneDisplay(PixelExtent pixelExtent,int paneNumber) { super(pixelExtent,paneNumber, "witoPane", new NsharpAbstractPaneDescriptor(pixelExtent, paneNumber)); } - @Override + + public NsharpWitoPaneDisplay() { + super(); + // TODO Auto-generated constructor stub + } + + @Override public NsharpAbstractPaneDescriptor getDescriptor() { return (NsharpAbstractPaneDescriptor) super.getDescriptor(); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapMouseHandler.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapMouseHandler.java index ba3c05a831..7fbf55634f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapMouseHandler.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapMouseHandler.java @@ -156,7 +156,7 @@ public class NsharpMapMouseHandler extends InputHandlerDefaultImpl { List points = NsharpMapResource.getOrCreateNsharpMapResource().getPoints();//loadDia.getNsharpMapResource().getPoints(); if(points.isEmpty() == false){ // create an editor NsharpEditor - NsharpEditor skewtEdt = NsharpEditor.createOrOpenEditor(); + //NsharpEditor skewtEdt = NsharpEditor.createOrOpenEditor(); //get the stn close to loc "enough" and retrieve report for it // Note::One stn may have more than one dataLine, if user picked multiple data time lines diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapResource.java index b4021d2896..9f29bef3b8 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/map/NsharpMapResource.java @@ -147,6 +147,7 @@ public class NsharpMapResource extends AbstractVizResource barb = WindBarbFactory.getWindGraphics( (double)nsharpNative.nsharpLib.iwspd(nsharpNative.nsharpLib.ipres(nsharpNative.nsharpLib.msl(1000))), (double)nsharpNative.nsharpLib.iwdir(nsharpNative.nsharpLib.ipres(nsharpNative.nsharpLib.msl(1000)))); @@ -3143,26 +3168,55 @@ public class NsharpDataPaneResource extends NsharpAbstractPaneResource{ public void setPageDisplayOrderNumberArray(int[] pageDisplayOrderNumberArray) { this.pageDisplayOrderNumberArray = pageDisplayOrderNumberArray; } - - + @Override + protected void adjustFontSize(float canvasW, float canvasH ) { + if(canvasH < myDefaultCanvasHeight/3 || canvasW< myDefaultCanvasWidth/3){ + if(font10!=null){ + font10.dispose(); + } + font10 = target.initializeFont("Monospace", 8, null); + } else if(canvasH < myDefaultCanvasHeight/2 || canvasW< myDefaultCanvasWidth/2){ + if(font10!=null){ + font10.dispose(); + } + font10 = target.initializeFont("Monospace", 8, null); + } + } @Override public void handleResize(){ super.handleResize(); + //Chin Note; ext size is its view size Not canvas size IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); ext.reset(); + defineCharHeight(font10); float prevHeight = dataPaneHeight; float prevWidth = dataPaneWidth; - dataPaneWidth= (int) (ext.getWidth()/2); - dataPaneHeight= (int) ext.getHeight(); + if(paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR) || + paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)|| + paneConfigurationName.equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)){ + //these 2 configurations lay 2 data panels side by side + dataPaneWidth= (int) (ext.getWidth()/2); + dataPaneHeight= (int) ext.getHeight(); + dp1XOrig = (int) (ext.getMinX()); + dp1YOrig = (int) (ext.getMinY()); + dp2XOrig = dp1XOrig+ dataPaneWidth; + dp2YOrig = dp1YOrig; + } else if(paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)){ + //this configuration lays 2 data panels top/down + dataPaneWidth= (int) ext.getWidth(); + dataPaneHeight= (int) ext.getHeight()/2; + dp1XOrig = (int) (ext.getMinX()); + dp1YOrig = (int) (ext.getMinY()); + dp2XOrig = dp1XOrig; + dp2YOrig = dp1YOrig+dataPaneHeight; + } + xRatio = xRatio* dataPaneWidth/prevWidth; - xRatio=1; + xRatio=1; //turn off yRatio = yRatio* dataPaneHeight/prevHeight; - yRatio=1; - charHeight = charHeight * yRatio; - dp1XOrig = (int) (ext.getMinX()); - dp1YOrig = (int) (ext.getMinY()); - dp2XOrig = dp1XOrig+ dataPaneWidth; - dp2YOrig = dp1YOrig; + yRatio=1;//turn off + charHeight = (int) (charHeight * yRatio); + Rectangle rectangle = new Rectangle(dp1XOrig, dp1YOrig,dataPaneWidth,dataPaneHeight); dataPanel1Background.handleResize(rectangle); rectangle = new Rectangle(dp2XOrig, dp2YOrig,dataPaneWidth,dataPaneHeight); 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 b41eb326f3..3e5893a048 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 @@ -73,10 +73,10 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ private IFont fixedFont; private int hodoWidth = NsharpConstants.HODO_WIDTH; private int hodoHeight = NsharpConstants.HODO_HEIGHT; - private int hodoXOrig = NsharpConstants.HODO_X_ORIG; - private int hodoYOrig = NsharpConstants.HODO_Y_ORIG; - private int hodoXEnd = NsharpConstants.HODO_X_END; - private int hodoYEnd = NsharpConstants.HODO_Y_ORIG+ NsharpConstants.HODO_HEIGHT; + //private int hodoXOrig = NsharpConstants.HODO_X_ORIG; + //private int hodoYOrig = NsharpConstants.HODO_Y_ORIG; + //private int hodoXEnd = NsharpConstants.HODO_X_END; + //private int hodoYEnd = NsharpConstants.HODO_Y_ORIG+ NsharpConstants.HODO_HEIGHT; private Coordinate hodoHouseC = new Coordinate(NsharpConstants.HODO_CENTER_X_, NsharpConstants.HODO_CENTER_Y_); private float xRatio=1; private float yRatio=1; @@ -177,7 +177,7 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ } public void createRscHodoWindShapeAll(){ - if(target == null || rscHandler ==null || soundingLys==null) + if(target == null || rscHandler ==null || soundingLys==null || hodoWindRscShapeList == null) return; if(hodoWindRscShapeList.size()>0){ for(NsharpShapeAndLineProperty shapeColor: hodoWindRscShapeList){ @@ -236,6 +236,7 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ //for future createHodoWindMotionBoxShape(); } + @SuppressWarnings("unused") private void createHodoWindMotionBoxShape(/*WGraphics world*/){ hodoWindMotionBoxShape = target.createWireframeShape(false,descriptor ); hodoWindMotionBoxShape.allocate(12); @@ -496,7 +497,7 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ } } //To be used later... - @SuppressWarnings("unused") + @SuppressWarnings({ "unused", "deprecation" }) private void drawHodoWindMotionBox(IGraphicsTarget target, Rectangle rect) throws VizException { target.drawShadedRect(new PixelExtent(rect.x, rect.x+rect.width, rect.y, rect.y+rect.height), NsharpConstants.color_black, 1.0, null); target.drawWireframeShape(hodoWindMotionBoxShape, NsharpConstants.color_cyan, commonLinewidth,commonLineStyle,font10); @@ -661,22 +662,31 @@ public class NsharpHodoPaneResource extends NsharpAbstractPaneResource{ @Override public void handleResize() { - super.handleResize(); + //super.handleResize(); + this.resize=false; IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); ext.reset(); //System.out.println("skewtPane: handleResize"); float prevHeight = hodoHeight; float prevWidth = hodoWidth; - hodoXOrig = (int) (ext.getMinX()); - hodoYOrig = (int) ext.getMinY(); + //hodoXOrig = (int) (ext.getMinX()); + //hodoYOrig = (int) ext.getMinY(); hodoWidth = (int) (ext.getWidth()); hodoHeight = (int) ext.getHeight(); - hodoXEnd = hodoXOrig+ hodoWidth; - hodoYEnd = hodoYOrig+ hodoHeight; + //hodoXEnd = hodoXOrig+ hodoWidth; + //hodoYEnd = hodoYOrig+ hodoHeight; xRatio = xRatio* hodoWidth/prevWidth; yRatio = yRatio* hodoHeight/prevHeight; hodoBackground.handleResize(ext); - + world = hodoBackground.computeWorld(); + Coordinate c; + FloatByReference value1= new FloatByReference(-999); + FloatByReference value2= new FloatByReference(-999); + FloatByReference bwdir= new FloatByReference(-999); + FloatByReference bwspd= new FloatByReference(-999); + nsharpNative.nsharpLib.bunkers_storm_motion(value1, value2, bwdir, bwspd); + c = WxMath.uvComp(bwspd.getValue(),bwdir.getValue()); + hodoHouseC= world.map(c); createRscHodoWindShapeAll(); } 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 ab991ac188..881655c9f3 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 @@ -169,6 +169,7 @@ public class NsharpInsetPaneResource extends NsharpAbstractPaneResource{ super.paintInternal(target, paintProps); if(rscHandler== null) return; + float zoomLevel = paintProps.getZoomLevel(); if(zoomLevel != currentZoomLevel) { magnifyFont(zoomLevel); @@ -312,13 +313,14 @@ public class NsharpInsetPaneResource extends NsharpAbstractPaneResource{ } } + /* private void plotPsblWatchShape(IGraphicsTarget target, double zoomLevel, WGraphics world, Rectangle rect) throws VizException { String wwtypeStr; double dispX, dispY; //int width = getCapability(OutlineCapability.class).getOutlineWidth(); - /* ----- Plot Label ----- */ + // ----- Plot Label ----- dispX = world.getViewXmin()+ 100 ; dispY = world.getViewYmin()+15; System.out.println("plotPsblWatchShape called w="+insetWidth+ " h="+insetHeight+" psbWatchXOrig="+psbWatchXOrig+ " psbWatchYOrig=" + psbWatchYOrig+ " dispX="+dispX+" dispY="+dispY); @@ -370,7 +372,7 @@ public class NsharpInsetPaneResource extends NsharpAbstractPaneResource{ VerticalAlignment.MIDDLE, null); target.drawLine(world.getViewXmin() , dispY+10, 0.0, world.getViewXmax(),dispY+10, 0.0, wwTypeColor, commonLinewidth); - } + }*/ public void createBkgPsblWatchShape(WGraphics world){ String wwtypeStr; 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 51759eb7c6..a51d8a8595 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 @@ -64,8 +64,9 @@ import com.raytheon.uf.common.sounding.WxMath; import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.viz.core.IDisplayPaneContainer; import com.raytheon.uf.viz.core.datastructure.LoopProperties; -import com.raytheon.uf.viz.core.drawables.IDescriptor.FrameChangeMode; -import com.raytheon.uf.viz.core.drawables.IDescriptor.FrameChangeOperation; +//import com.raytheon.uf.viz.core.drawables.IDescriptor.FrameChangeMode; +//import com.raytheon.uf.viz.core.drawables.IDescriptor.FrameChangeOperation; +import com.raytheon.uf.viz.core.drawables.IFrameCoordinator; import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; import com.raytheon.uf.viz.core.drawables.IWireframeShape; import com.raytheon.uf.viz.core.drawables.ResourcePair; @@ -87,6 +88,8 @@ public class NsharpResourceHandler { private NsharpTimeStnPaneResource timeStnPaneRsc; private NsharpInsetPaneResource insetPaneRsc; private NsharpDataPaneResource dataPaneRsc; + private NsharpSpcGraphsPaneResource spcGraphsPaneRsc; + private NsharpSpcGraphsPaneResource futurePaneRsc; NsharpNative nsharpNative=null; private static final int DATAPAGEMAX = NsharpConstants.PAGE_MAX_NUMBER/ 2; private static final int INSETPAGEMAX =2; @@ -100,8 +103,10 @@ public class NsharpResourceHandler { private static final int HODO_NORMAL = 0; //private static int HODO_EFFECTIVE= 1; not used in BigNsharp source code private static final int HODO_STORMRELATIVE= 2; + @SuppressWarnings("unused") private static final int HODO_BNDRY= 3; private static final int HODO_MEANWIND= 4; + @SuppressWarnings("unused") private int currentHodoWindMode = HODO_MEANWIND; private NsharpConfigManager configMgr; private NsharpConfigStore configStore; @@ -142,7 +147,7 @@ public class NsharpResourceHandler { private List previousSoundingLys = null; private String pickedStnInfoStr; // current picked stn info with time line, e.g. "ATLH 2010-12-12 12:00:00" private NsharpStationInfo pickedStnInfo = null; - private FrameChangeOperation currentOpDirection = FrameChangeOperation.NEXT; // next =forward + private IFrameCoordinator.FrameChangeOperation currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; // next =forward private HashMap stormSlinkyColorMap = new HashMap(); @@ -305,8 +310,10 @@ public class NsharpResourceHandler { preSndProfileProp = null; this.overlayIsOn = overlay; - hodoPaneRsc.createRscHodoWindShapeAll(); - skewtPaneRsc.createRscPressTempCurveShapeAll(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); } public void setInterpolateIsOn(boolean interpolateIsOn) { this.interpolateIsOn = interpolateIsOn; @@ -347,8 +354,10 @@ public class NsharpResourceHandler { setCurrentSoundingLayerInfo(); resetData(); if(soundingLys!=null){ - hodoPaneRsc.createRscHodoWindShapeAll(); - skewtPaneRsc.createRscPressTempCurveShapeAll(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); } } public void setCompareTmIsOn(boolean compareIsOn) { @@ -374,8 +383,10 @@ public class NsharpResourceHandler { setCurrentSoundingLayerInfo(); resetData(); if(soundingLys!=null){ - hodoPaneRsc.createRscHodoWindShapeAll(); - skewtPaneRsc.createRscPressTempCurveShapeAll(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); } } @@ -394,7 +405,8 @@ public class NsharpResourceHandler { public void setCurrentGraphMode(int currentGraphMode) { this.currentGraphMode = currentGraphMode; - skewtPaneRsc.setCurrentGraphMode(currentGraphMode); + if(skewtPaneRsc!=null) + skewtPaneRsc.setCurrentGraphMode(currentGraphMode); /*NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); //getWitoPaneRsc().recreateShapes(); @@ -474,7 +486,8 @@ public class NsharpResourceHandler { */ public void setParcelList(List parcelList) { this.parcelList = parcelList; - skewtPaneRsc.createParcelShapes(parcelList); + if(skewtPaneRsc!=null) + skewtPaneRsc.createParcelShapes(parcelList); } public void updateParcelFromPanel(short currentParcel){ this.currentParcel = currentParcel; @@ -514,18 +527,22 @@ public class NsharpResourceHandler { this.soundingLysList = soundingLysList; } public void setHodoHouseC(Coordinate hodoHouseC) { + if(hodoPaneRsc==null) + return; hodoPaneRsc.setHodoHouseC(hodoHouseC); Coordinate c = hodoPaneRsc.getHodoBackground().getWorld().unMap(hodoHouseC.x, hodoHouseC.y); c = WxMath.speedDir((float) c.x, (float) c.y); smWindDir = (float) c.y; smWindSpd = (float)c.x; nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); + if(insetPaneRsc!=null){ + WGraphics WGc = insetPaneRsc.getPsblWatchTypeBackground().getWorld(); + insetPaneRsc.createBkgPsblWatchShape(WGc); - WGraphics WGc = insetPaneRsc.getPsblWatchTypeBackground().getWorld(); - insetPaneRsc.createBkgPsblWatchShape(WGc); - //Sr wind vs Height graph shape need to recreate - WGc= insetPaneRsc.getSrWindsBackground().getWorld(); - insetPaneRsc.createRscSrWindShape(WGc); + //Sr wind vs Height graph shape need to recreate + WGc= insetPaneRsc.getSrWindsBackground().getWorld(); + insetPaneRsc.createRscSrWindShape(WGc); + } } @@ -556,18 +573,27 @@ public class NsharpResourceHandler { nsharpNative.populateSndgData(soundingLys); - skewtPaneRsc.resetData(soundingLys,previousSoundingLys); - hodoPaneRsc.resetData(soundingLys,previousSoundingLys); - witoPaneRsc.resetData(soundingLys, previousSoundingLys); - dataPaneRsc.resetData(soundingLys, previousSoundingLys); - insetPaneRsc.resetData(soundingLys, previousSoundingLys); + if(skewtPaneRsc!=null) + skewtPaneRsc.resetData(soundingLys,previousSoundingLys); + if(hodoPaneRsc!=null) + hodoPaneRsc.resetData(soundingLys,previousSoundingLys); + if(witoPaneRsc!=null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); + if(dataPaneRsc!=null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if(insetPaneRsc!=null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); //re-create shape - skewtPaneRsc.createRscWireFrameShapes(); - hodoPaneRsc.createRscHodoWindShapeAll(); - insetPaneRsc.createInsetWireFrameShapes(); - witoPaneRsc.createRscWireFrameShapes(); - insetPaneRsc.createInsetWireFrameShapes(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(insetPaneRsc!=null) + insetPaneRsc.createInsetWireFrameShapes(); + if(witoPaneRsc!=null) + witoPaneRsc.createRscWireFrameShapes(); + } @@ -615,12 +641,16 @@ 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); - - skewtPaneRsc.resetData(soundingLys,previousSoundingLys); - hodoPaneRsc.resetData(soundingLys,previousSoundingLys); - insetPaneRsc.resetData(soundingLys, previousSoundingLys); - dataPaneRsc.resetData(soundingLys, previousSoundingLys); - witoPaneRsc.resetData(soundingLys, previousSoundingLys); + if(skewtPaneRsc!=null) + skewtPaneRsc.resetData(soundingLys,previousSoundingLys); + if(hodoPaneRsc!=null) + hodoPaneRsc.resetData(soundingLys,previousSoundingLys); + if(insetPaneRsc!=null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); + if(dataPaneRsc!=null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if(witoPaneRsc!=null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); if(textarea != null){ @@ -639,8 +669,10 @@ public class NsharpResourceHandler { FloatByReference bwspd= new FloatByReference(-999); nsharpNative.nsharpLib.bunkers_storm_motion(dummy1, dummy2, bwdir, bwspd); Coordinate c = WxMath.uvComp(bwspd.getValue(),bwdir.getValue()); - Coordinate hodoHouseC= hodoPaneRsc.getHodoBackground().getWorld().map(c); - hodoPaneRsc.setHodoHouseC(hodoHouseC); + if(hodoPaneRsc!=null){ + Coordinate hodoHouseC= hodoPaneRsc.getHodoBackground().getWorld().map(c); + hodoPaneRsc.setHodoHouseC(hodoHouseC); + } smWindSpd = bwspd.getValue(); smWindDir = bwdir.getValue(); nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); @@ -658,10 +690,14 @@ public class NsharpResourceHandler { drawPanel.resetCurrentParcel(); }*/ } - skewtPaneRsc.handleResize(); - hodoPaneRsc.createRscHodoWindShapeAll(); - insetPaneRsc.createInsetWireFrameShapes(); - witoPaneRsc.createAllWireFrameShapes(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(insetPaneRsc!=null) + insetPaneRsc.createInsetWireFrameShapes(); + if(witoPaneRsc!=null) + witoPaneRsc.createAllWireFrameShapes(); } //NOTE: this comparator is coded only for dataTimelineList and stationIdList to use //Typical time line string: e.g. KNJX 110810/00V000 (NAMS) meaning stnId=KNJX date=2011/Aug/10 Hour:00 @@ -1471,6 +1507,7 @@ public class NsharpResourceHandler { } } public void addRsc(Map> soundMap, NsharpStationInfo stnInfo){ + deepCopyDataMap(this.originalDataTimelineSndLysListMap,this.dataTimelineSndLysListMap); //make sure not adding duplicated sounding data //System.out.println("NsharpSkewTResource addRsc called"); Set duplicateKeys = new HashSet(); @@ -1481,7 +1518,7 @@ public class NsharpResourceHandler { for(String key: duplicateKeys) { soundMap.remove(key); } - if(soundMap.size() <=0){ + if(soundMap.size() <=0 || (skewtPaneRsc==null)){ return; } //add new data @@ -1509,7 +1546,7 @@ public class NsharpResourceHandler { //set total time line group and stn id list page number int numTimeLinePerPage = (cnYOrig-dtNextPageEnd)/charHeight; - + //System.out.println("numTimeLinePerPage="+numTimeLinePerPage); totalTimeLinePage = timeLineStateList.size()/numTimeLinePerPage + 1; //NEW CODE curTimeLinePage = currentTimeLineStateListIndex/numTimeLinePerPage + 1; //NEW CODE totalStnIdPage = stnStateList.size()/numTimeLinePerPage + 1; //NEW CODE @@ -1631,16 +1668,18 @@ public class NsharpResourceHandler { return; } - - findCurrentElementIndexesAfterConfig(); - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - - if(compareStnIsOn){ - hodoPaneRsc.createRscHodoWindShapeAll(); - skewtPaneRsc.createRscPressTempCurveShapeAll(); - } + + findCurrentElementIndexesAfterConfig(); + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + + if(compareStnIsOn){ + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); + } } } @@ -1688,11 +1727,11 @@ public class NsharpResourceHandler { currentTimeLineStateListIndex = previousTimeLineStateListIndex; break; } - if(currentOpDirection == FrameChangeOperation.NEXT ){ + if(currentOpDirection == IFrameCoordinator.FrameChangeOperation.NEXT ){ currentTimeLineStateListIndex--; if(currentTimeLineStateListIndex <= 0){ //the end of forward direction, change direction to backward - currentOpDirection = FrameChangeOperation.PREVIOUS; + currentOpDirection = IFrameCoordinator.FrameChangeOperation.PREVIOUS; currentTimeLineStateListIndex=0; } @@ -1701,7 +1740,7 @@ public class NsharpResourceHandler { currentTimeLineStateListIndex++; if(currentTimeLineStateListIndex >= timeLineStateList.size()-1){ //the end of backward direction, change direction to forward - currentOpDirection = FrameChangeOperation.NEXT; + currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; currentTimeLineStateListIndex = timeLineStateList.size()-1; } } @@ -1766,7 +1805,7 @@ public class NsharpResourceHandler { } return n; } - public void setSteppingTimeLine(FrameChangeOperation operation, FrameChangeMode mode) { + public void setSteppingTimeLine(IFrameCoordinator.FrameChangeOperation operation, IFrameCoordinator.FrameChangeMode mode) { if( this.timeLineStateList.size() > 0 && getActiveTimeLineNumber()>1/* && getAvailTimeLineNumber(currentStnStateListIndex)>1*/) { int targetIndex = currentTimeLineStateListIndex; //previousTimeLineStateListIndex = currentTimeLineStateListIndex; @@ -1848,20 +1887,20 @@ public class NsharpResourceHandler { } /* - * Stn index stepping is only controlled by up/down arrow keys, down key = NEXT operation, up key = PREVIOUS operation + * Stn index stepping is only controlled by up/down arrow keys, down key = PREVIOUS operation, up key = NEXT operation */ - public void setSteppingStnIdList(FrameChangeOperation operation) { + public void setSteppingStnIdList(IFrameCoordinator.FrameChangeOperation operation) { if( this.stnStateList.size() > 0 && getActiveStnNumber()>1/* && getAvailStnNumber(currentTimeLineStateListIndex) > 1*/){ int counter=0; while(true){ switch(operation){ - case PREVIOUS: + case NEXT: currentStnStateListIndex= currentStnStateListIndex + this.stnStateList.size(); currentStnStateListIndex--; currentStnStateListIndex = currentStnStateListIndex % this.stnStateList.size(); break; - case NEXT: + case PREVIOUS: // so, we wont get a negative number currentStnStateListIndex++; currentStnStateListIndex = currentStnStateListIndex % this.stnStateList.size(); @@ -1939,8 +1978,10 @@ public class NsharpResourceHandler { */ public Coordinate getClosestHodoPoint(Coordinate inputC){ //System.out.println("picked pt CX "+ inputC.x + " CY "+ inputC.y); + Coordinate closeptC = new Coordinate(0,0); + if(hodoPaneRsc==null) + return closeptC; - Coordinate closeptC = new Coordinate(); double curSmallestDist=10000; // picked a impossible big number to start with double distance; boolean ptFound = false; @@ -2069,6 +2110,100 @@ public class NsharpResourceHandler { } } + public void updateDisplay(IRenderableDisplay[] displayArray, String paneConfigurationName) { + skewtPaneRsc = null; + witoPaneRsc = null; + hodoPaneRsc = null; + timeStnPaneRsc = null; + insetPaneRsc = null; + dataPaneRsc = null; + spcGraphsPaneRsc = null; + futurePaneRsc = null; + ResourcePair skewtRscPair = displayArray[NsharpEditor.DISPLAY_SKEWT].getDescriptor().getResourceList().get(0); + if (skewtRscPair.getResource() instanceof NsharpSkewTPaneResource){ + skewtPaneRsc = (NsharpSkewTPaneResource)skewtRscPair.getResource() ; + skewtPaneRsc.setLinePropertyMap(linePropertyMap); + skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); + skewtPaneRsc.setNsharpNative(nsharpNative); + } + ResourcePair dataRscPair = displayArray[NsharpEditor.DISPLAY_DATA].getDescriptor().getResourceList().get(0); + if (dataRscPair.getResource() instanceof NsharpDataPaneResource){ + dataPaneRsc = (NsharpDataPaneResource)dataRscPair.getResource() ; + dataPaneRsc.setLinePropertyMap(linePropertyMap); + dataPaneRsc.setGraphConfigProperty(graphConfigProperty); + dataPaneRsc.setNsharpNative(nsharpNative); + dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray); + } + ResourcePair hodoRscPair = displayArray[NsharpEditor.DISPLAY_HODO].getDescriptor().getResourceList().get(0); + if (hodoRscPair.getResource() instanceof NsharpHodoPaneResource){ + hodoPaneRsc = (NsharpHodoPaneResource)hodoRscPair.getResource() ; + hodoPaneRsc.setLinePropertyMap(linePropertyMap); + hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); + hodoPaneRsc.setNsharpNative(nsharpNative); + } + if(paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)|| + paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)|| + paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR)){ + + ResourcePair witoRscPair = displayArray[NsharpEditor.DISPLAY_WITO].getDescriptor().getResourceList().get(0); + if (witoRscPair.getResource() instanceof NsharpWitoPaneResource){ + witoPaneRsc = (NsharpWitoPaneResource)witoRscPair.getResource() ; + witoPaneRsc.setLinePropertyMap(linePropertyMap); + witoPaneRsc.setGraphConfigProperty(graphConfigProperty); + witoPaneRsc.setNsharpNative(nsharpNative); + } + ResourcePair insetRscPair = displayArray[NsharpEditor.DISPLAY_INSET].getDescriptor().getResourceList().get(0); + if (insetRscPair.getResource() instanceof NsharpInsetPaneResource){ + insetPaneRsc = (NsharpInsetPaneResource)insetRscPair.getResource() ; + insetPaneRsc.setLinePropertyMap(linePropertyMap); + insetPaneRsc.setGraphConfigProperty(graphConfigProperty); + insetPaneRsc.setNsharpNative(nsharpNative); + } + } + + if(paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)){ + ResourcePair spcRscPair = displayArray[NsharpEditor.DISPLAY_SPC_GRAPHS].getDescriptor().getResourceList().get(0); + if (spcRscPair.getResource() instanceof NsharpSpcGraphsPaneResource){ + spcGraphsPaneRsc = (NsharpSpcGraphsPaneResource)spcRscPair.getResource() ; + spcGraphsPaneRsc.setLinePropertyMap(linePropertyMap); + spcGraphsPaneRsc.setGraphConfigProperty(graphConfigProperty); + spcGraphsPaneRsc.setNsharpNative(nsharpNative); + } + } + if(paneConfigurationName.equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)){ + ResourcePair futureRscPair = displayArray[NsharpEditor.DISPLAY_FUTURE].getDescriptor().getResourceList().get(0); + if (futureRscPair.getResource() instanceof NsharpSpcGraphsPaneResource){ + futurePaneRsc = (NsharpSpcGraphsPaneResource)futureRscPair.getResource() ; + futurePaneRsc.setLinePropertyMap(linePropertyMap); + futurePaneRsc.setGraphConfigProperty(graphConfigProperty); + futurePaneRsc.setNsharpNative(nsharpNative); + } + } + if(paneConfigurationName.equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)|| + paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)|| + paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR)){ + ResourcePair timeStnRscPair = displayArray[NsharpEditor.DISPLAY_TIMESTN].getDescriptor().getResourceList().get(0); + if (timeStnRscPair.getResource() instanceof NsharpTimeStnPaneResource){ + timeStnPaneRsc = (NsharpTimeStnPaneResource)timeStnRscPair.getResource() ; + timeStnPaneRsc.setLinePropertyMap(linePropertyMap); + timeStnPaneRsc.setGraphConfigProperty(graphConfigProperty); + timeStnPaneRsc.setNsharpNative(nsharpNative); + } + } + this.displayArray = displayArray; + } + public void resetRscSoundingData(){ + if(skewtPaneRsc!=null) + skewtPaneRsc.resetData(soundingLys,previousSoundingLys); + if(hodoPaneRsc!=null) + hodoPaneRsc.resetData(soundingLys,previousSoundingLys); + if(witoPaneRsc!=null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); + if(dataPaneRsc!=null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if(insetPaneRsc!=null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); + } public NsharpResourceHandler(IRenderableDisplay[] displayArray) { //System.out.println("NsharpResourceHandler constructed"); this.soundingMap = new HashMap(); @@ -2092,55 +2227,14 @@ public class NsharpResourceHandler { configMgr = NsharpConfigManager.getInstance(); configStore = configMgr.retrieveNsharpConfigStoreFromFs(); graphConfigProperty = configStore.getGraphProperty(); + String paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); + int tempOffset = graphConfigProperty.getTempOffset(); NsharpWxMath.setTempOffset(tempOffset); linePropertyMap = configStore.getLinePropertyMap(); dataPageProperty = configStore.getDataPageProperty(); updatePageOrderArray(); - ResourcePair skewtRscPair = displayArray[NsharpConstants.DISPLAY_SKEWT].getDescriptor().getResourceList().get(0); - if (skewtRscPair.getResource() instanceof NsharpSkewTPaneResource){ - skewtPaneRsc = (NsharpSkewTPaneResource)skewtRscPair.getResource() ; - skewtPaneRsc.setLinePropertyMap(linePropertyMap); - skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); - skewtPaneRsc.setNsharpNative(nsharpNative); - } - ResourcePair hodoRscPair = displayArray[NsharpConstants.DISPLAY_HODO].getDescriptor().getResourceList().get(0); - if (hodoRscPair.getResource() instanceof NsharpHodoPaneResource){ - hodoPaneRsc = (NsharpHodoPaneResource)hodoRscPair.getResource() ; - hodoPaneRsc.setLinePropertyMap(linePropertyMap); - hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); - hodoPaneRsc.setNsharpNative(nsharpNative); - } - ResourcePair witoRscPair = displayArray[NsharpConstants.DISPLAY_WITO].getDescriptor().getResourceList().get(0); - if (witoRscPair.getResource() instanceof NsharpWitoPaneResource){ - witoPaneRsc = (NsharpWitoPaneResource)witoRscPair.getResource() ; - witoPaneRsc.setLinePropertyMap(linePropertyMap); - witoPaneRsc.setGraphConfigProperty(graphConfigProperty); - witoPaneRsc.setNsharpNative(nsharpNative); - } - ResourcePair timeStnRscPair = displayArray[NsharpConstants.DISPLAY_TIMESTN].getDescriptor().getResourceList().get(0); - if (timeStnRscPair.getResource() instanceof NsharpTimeStnPaneResource){ - timeStnPaneRsc = (NsharpTimeStnPaneResource)timeStnRscPair.getResource() ; - timeStnPaneRsc.setLinePropertyMap(linePropertyMap); - timeStnPaneRsc.setGraphConfigProperty(graphConfigProperty); - timeStnPaneRsc.setNsharpNative(nsharpNative); - } - ResourcePair insetRscPair = displayArray[NsharpConstants.DISPLAY_INSET].getDescriptor().getResourceList().get(0); - if (insetRscPair.getResource() instanceof NsharpInsetPaneResource){ - insetPaneRsc = (NsharpInsetPaneResource)insetRscPair.getResource() ; - insetPaneRsc.setLinePropertyMap(linePropertyMap); - insetPaneRsc.setGraphConfigProperty(graphConfigProperty); - insetPaneRsc.setNsharpNative(nsharpNative); - } - ResourcePair dataRscPair = displayArray[NsharpConstants.DISPLAY_DATA].getDescriptor().getResourceList().get(0); - if (dataRscPair.getResource() instanceof NsharpDataPaneResource){ - dataPaneRsc = (NsharpDataPaneResource)dataRscPair.getResource() ; - dataPaneRsc.setLinePropertyMap(linePropertyMap); - dataPaneRsc.setGraphConfigProperty(graphConfigProperty); - dataPaneRsc.setNsharpNative(nsharpNative); - dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray); - } - this.displayArray = displayArray; + updateDisplay(displayArray,paneConfigurationName); pspLsner = new NsharpPerspectiveListener(); pspLsner.setRscHandler(this); pspLsner.setMyPerspectiveId(VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId()); @@ -2546,17 +2640,22 @@ public class NsharpResourceHandler { public void setPlotInteractiveTemp(boolean plotInteractiveTemp) { this.plotInteractiveTemp = plotInteractiveTemp; - skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); + if(skewtPaneRsc!=null) + skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); } public void setInteractiveTempPointCoordinate( Coordinate interactiveTempPointCoordinate) { - System.out.println("setInteractiveTempPointCoordinate called"); + //System.out.println("setInteractiveTempPointCoordinate called"); this.interactiveTempPointCoordinate = interactiveTempPointCoordinate; plotInteractiveTemp = true; - skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); - skewtPaneRsc.setInteractiveTempPointCoordinate(interactiveTempPointCoordinate); + if(skewtPaneRsc!=null){ + skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); + skewtPaneRsc.setInteractiveTempPointCoordinate(interactiveTempPointCoordinate); + } } public void setInteractiveHodoPointCoordinate(Coordinate c){ + if(hodoPaneRsc == null) + return; try { NcSoundingLayer hodoLayer = soundingLys.get(hodoEditingSoundingLayerIndex); if(hodoLayer != null){ @@ -2570,9 +2669,12 @@ public class NsharpResourceHandler { hodoLayer.setWindSpeed((float)c1.x); hodoLayer.setWindDirection((float)c1.y); hodoPaneRsc.createRscHodoWindShapeAll(); - witoPaneRsc.createAllWireFrameShapes(); - insetPaneRsc.createInsetWireFrameShapes(); - skewtPaneRsc.createRscWireFrameShapes(); + if(witoPaneRsc!=null) + witoPaneRsc.createAllWireFrameShapes(); + if(insetPaneRsc!=null) + insetPaneRsc.createInsetWireFrameShapes(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); } } catch(Exception e) { @@ -2580,13 +2682,15 @@ public class NsharpResourceHandler { } } public void applyInteractiveTempPoint(){ + if(skewtPaneRsc==null) + return; Coordinate inC = NsharpWxMath.reverseSkewTXY(skewtPaneRsc.getWorld().unMap(interactiveTempPointCoordinate)); double inTemp = inC.x; currentSoundingLayerIndex = skewtPaneRsc.getCurrentSoundingLayerIndex(); NcSoundingLayer layer = this.soundingLys.get(currentSoundingLayerIndex); currentTempCurveType = skewtPaneRsc.getCurrentTempCurveType(); - System.out.println("applyInteractiveTempPoint called pressure " + inC.y + " temp "+ inTemp + - " currentTempCurveType " + currentTempCurveType ); + //System.out.println("applyInteractiveTempPoint called pressure " + inC.y + " temp "+ inTemp + + // " currentTempCurveType " + currentTempCurveType ); if(currentTempCurveType == TEMP_TYPE){ if(inTemp < layer.getDewpoint()) @@ -2609,13 +2713,15 @@ public class NsharpResourceHandler { nsharpNative.populateSndgData(soundingLys); //get storm motion wind data after populate sounding from NsharpLib skewtPaneRsc.setSoundingLys(soundingLys); - skewtPaneRsc.createRscPressTempCurveShapeAll(); - skewtPaneRsc.createRscwetBulbTraceShape(); - skewtPaneRsc.createRscVTempTraceShape(); - skewtPaneRsc.createParcelShapes(parcelList); - - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); + skewtPaneRsc.handleResize(); + //skewtPaneRsc.createRscPressTempCurveShapeAll(); + //skewtPaneRsc.createRscwetBulbTraceShape(); + //skewtPaneRsc.createRscVTempTraceShape(); + //skewtPaneRsc.createParcelShapes(parcelList); + if(hodoPaneRsc!=null){ + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } } public void applySfcEditing(float tp, float dp, float ws, float wd, float pressure){ @@ -2631,11 +2737,16 @@ public class NsharpResourceHandler { this.dataTimelineSndLysListMap.put(pickedStnInfoStr, this.soundingLys); //re-populate snd data to nsharp native code lib for later calculating nsharpNative.populateSndgData(soundingLys); - skewtPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.setSoundingLys(soundingLys); - insetPaneRsc.setSoundingLys(soundingLys); - witoPaneRsc.setSoundingLys(soundingLys); - dataPaneRsc.setSoundingLys(soundingLys); + if(skewtPaneRsc!=null) + skewtPaneRsc.setSoundingLys(soundingLys); + if(hodoPaneRsc!=null) + hodoPaneRsc.setSoundingLys(soundingLys); + if(insetPaneRsc!=null) + insetPaneRsc.setSoundingLys(soundingLys); + if(witoPaneRsc!=null) + witoPaneRsc.setSoundingLys(soundingLys); + if(dataPaneRsc!=null) + dataPaneRsc.setSoundingLys(soundingLys); } public void updateLayer(int layerIndex, float tp, float dp, float ws, float wd, float pressure){ if(layerIndex <0 || layerIndex >= soundingLys.size()) @@ -2660,15 +2771,24 @@ public class NsharpResourceHandler { if(textarea != null){ textarea.refreshTextData(); } - skewtPaneRsc.setSoundingLys(soundingLys); - skewtPaneRsc.createRscWireFrameShapes(); - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - insetPaneRsc.setSoundingLys(soundingLys); - insetPaneRsc.createInsetWireFrameShapes(); - witoPaneRsc.setSoundingLys(soundingLys); - witoPaneRsc.createAllWireFrameShapes(); - dataPaneRsc.setSoundingLys(soundingLys); + if(skewtPaneRsc!=null){ + skewtPaneRsc.setSoundingLys(soundingLys); + skewtPaneRsc.handleResize(); + } + if(hodoPaneRsc!=null){ + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if(insetPaneRsc!=null){ + insetPaneRsc.setSoundingLys(soundingLys); + insetPaneRsc.createInsetWireFrameShapes(); + } + if(witoPaneRsc!=null) { + witoPaneRsc.setSoundingLys(soundingLys); + witoPaneRsc.createAllWireFrameShapes(); + } + if(dataPaneRsc!=null) + dataPaneRsc.setSoundingLys(soundingLys); } public void addNewLayer(float tp, float dp, float ws, float wd, float pressure){ //NsharpBackgroundResource bkRsc = descriptor.getSkewTBkGResource(); @@ -2691,15 +2811,24 @@ public class NsharpResourceHandler { if(textarea != null){ textarea.refreshTextData(); } - skewtPaneRsc.setSoundingLys(soundingLys); - skewtPaneRsc.createRscWireFrameShapes(); - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - insetPaneRsc.setSoundingLys(soundingLys); - insetPaneRsc.createInsetWireFrameShapes(); - witoPaneRsc.setSoundingLys(soundingLys); - witoPaneRsc.createAllWireFrameShapes(); - dataPaneRsc.setSoundingLys(soundingLys); + if(skewtPaneRsc!=null){ + skewtPaneRsc.setSoundingLys(soundingLys); + skewtPaneRsc.handleResize(); + } + if(hodoPaneRsc!=null){ + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if(insetPaneRsc!=null){ + insetPaneRsc.setSoundingLys(soundingLys); + insetPaneRsc.createInsetWireFrameShapes(); + } + if(witoPaneRsc!=null) { + witoPaneRsc.setSoundingLys(soundingLys); + witoPaneRsc.createAllWireFrameShapes(); + } + if(dataPaneRsc!=null) + dataPaneRsc.setSoundingLys(soundingLys); } @@ -2709,15 +2838,23 @@ public class NsharpResourceHandler { this.graphConfigProperty = graphConfigProperty; int tempOffset = graphConfigProperty.getTempOffset(); NsharpWxMath.setTempOffset(tempOffset); - skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); - skewtPaneRsc.createRscWireFrameShapes(); - skewtPaneRsc.getSkewTBackground().setGraphConfigProperty(graphConfigProperty); - hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); - hodoPaneRsc.createRscHodoWindShapeAll(); - witoPaneRsc.setGraphConfigProperty(graphConfigProperty); - witoPaneRsc.createAllWireFrameShapes(); - insetPaneRsc.setGraphConfigProperty(graphConfigProperty); - insetPaneRsc.createInsetWireFrameShapes(); + if(skewtPaneRsc!=null){ + skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); + skewtPaneRsc.handleResize(); + skewtPaneRsc.getSkewTBackground().setGraphConfigProperty(graphConfigProperty); + } + if(hodoPaneRsc!=null) { + hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if(witoPaneRsc!=null) { + witoPaneRsc.setGraphConfigProperty(graphConfigProperty); + witoPaneRsc.createAllWireFrameShapes(); + } + if(insetPaneRsc!=null){ + insetPaneRsc.setGraphConfigProperty(graphConfigProperty); + insetPaneRsc.createInsetWireFrameShapes(); + } } @@ -2729,11 +2866,16 @@ public class NsharpResourceHandler { public void setLinePropertyMap( HashMap linePropertyMap) { this.linePropertyMap = linePropertyMap; - skewtPaneRsc.setLinePropertyMap(linePropertyMap); - skewtPaneRsc.createRscPressTempCurveShapeAll(); - hodoPaneRsc.setLinePropertyMap(linePropertyMap); - hodoPaneRsc.createRscHodoWindShapeAll(); - timeStnPaneRsc.setLinePropertyMap(linePropertyMap); + if(skewtPaneRsc!=null){ + skewtPaneRsc.setLinePropertyMap(linePropertyMap); + skewtPaneRsc.handleResize(); + } + if(hodoPaneRsc!=null){ + hodoPaneRsc.setLinePropertyMap(linePropertyMap); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if(timeStnPaneRsc!=null) + timeStnPaneRsc.setLinePropertyMap(linePropertyMap); } private void updatePageOrderArray(){ pageDisplayOrderNumberArray[NsharpConstants.PAGE_SUMMARY1 ] = dataPageProperty.getSummary1Page(); @@ -2750,7 +2892,8 @@ public class NsharpResourceHandler { public void setDataPageProperty(NsharpDataPageProperty dataPageProperty) { this.dataPageProperty = dataPageProperty; updatePageOrderArray(); - dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray); + if(dataPaneRsc!=null) + dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray); } @@ -2768,8 +2911,10 @@ public class NsharpResourceHandler { setCurrentSoundingLayerInfo(); resetData(); if(compareStnIsOn){ - hodoPaneRsc.createRscHodoWindShapeAll(); - skewtPaneRsc.createRscPressTempCurveShapeAll(); + if(hodoPaneRsc!=null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if(skewtPaneRsc!=null) + skewtPaneRsc.handleResize(); } } public void handleStationActConfig(List stnList, NsharpConstants.State actSt){ @@ -2796,7 +2941,9 @@ public class NsharpResourceHandler { public int getCurrentTimeLineStateListIndex() { return currentTimeLineStateListIndex; } - + public int getTimeLineStateListSize() { + return this.timeLineStateList.size(); + } public int getCurrentStnStateListIndex() { return currentStnStateListIndex; @@ -2850,7 +2997,7 @@ public class NsharpResourceHandler { } - public FrameChangeOperation getCurrentOpDirection() { + public IFrameCoordinator.FrameChangeOperation getCurrentOpDirection() { return currentOpDirection; } @@ -2889,7 +3036,7 @@ public class NsharpResourceHandler { } - public void setCnYOrig(int cnYOrig) { + /*public void setCnYOrig(int cnYOrig) { this.cnYOrig = cnYOrig; } @@ -2901,14 +3048,31 @@ public class NsharpResourceHandler { public void setDtYOrig(int dtYOrig) { this.dtYOrig = dtYOrig; - } - - - public void setCharHeight(int charHeight) { + }*/ + public void setTimeStnBoxData(int cnYOrig,int dtNextPage_end, int dtYOrig , int charHeight){ this.charHeight = charHeight; + this.dtYOrig = dtYOrig; + this.cnYOrig = cnYOrig; + this.dtNextPageEnd = dtNextPage_end; + int numTimeLinePerPage = (cnYOrig-dtNextPageEnd)/charHeight; + if(numTimeLinePerPage<=0) + numTimeLinePerPage=1; + //System.out.println("numTimeLinePerPage="+numTimeLinePerPage); + totalTimeLinePage = timeLineStateList.size()/numTimeLinePerPage ; + if(timeLineStateList.size()%numTimeLinePerPage != 0) + totalTimeLinePage= totalTimeLinePage+1; + curTimeLinePage = currentTimeLineStateListIndex/numTimeLinePerPage+1; + totalStnIdPage = stnStateList.size()/numTimeLinePerPage; + if(stnStateList.size()%numTimeLinePerPage != 0) + totalStnIdPage++; + curStnIdPage= currentStnStateListIndex/numTimeLinePerPage + 1; //NEW CODE } + + /*public void setCharHeight(int charHeight) { + this.charHeight = charHeight; + }*/ public void refreshPane(){ - for(int i =0; i< NsharpConstants.DISPLAY_TOTAL; i++){ + for(int i =0; i< NsharpEditor.DISPLAY_TOTAL; i++){ displayArray[i].refresh(); } } 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 36f568e81c..8af1019223 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 @@ -30,18 +30,22 @@ import gov.noaa.nws.ncep.ui.nsharp.background.NsharpGenericPaneBackground; import gov.noaa.nws.ncep.ui.nsharp.background.NsharpIcingPaneBackground; import gov.noaa.nws.ncep.ui.nsharp.background.NsharpSkewTPaneBackground; import gov.noaa.nws.ncep.ui.nsharp.background.NsharpTurbulencePaneBackground; -import gov.noaa.nws.ncep.ui.nsharp.display.NsharpEditor; import gov.noaa.nws.ncep.ui.nsharp.display.NsharpSkewTPaneDescriptor; import gov.noaa.nws.ncep.ui.nsharp.display.rsc.NsharpResourceHandler.ParcelData; import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNative; import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNative.NsharpLibrary._lplvalues; import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNative.NsharpLibrary._parcel; import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNativeConstants; +import gov.noaa.nws.ncep.ui.nsharp.view.NsharpLoadDialog; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import javax.measure.converter.UnitConverter; +import javax.measure.unit.NonSI; +import javax.measure.unit.SI; + import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; @@ -81,8 +85,14 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ private int skewtHeight = NsharpConstants.SKEWT_HEIGHT; private int skewtXOrig = NsharpConstants.SKEWT_X_ORIG; private int skewtYOrig = NsharpConstants.SKEWT_Y_ORIG; - private int skewtXEnd = NsharpConstants.SKEWT_X_END; - private int skewtYEnd = NsharpConstants.SKEWT_Y_END; + //private int skewtXEnd = NsharpConstants.SKEWT_X_END; + //private int skewtYEnd = NsharpConstants.SKEWT_Y_END; + private float omegaXOrig = NsharpConstants.OMEGA_X_ORIG; + private float omegaYOrig = NsharpConstants.OMEGA_Y_ORIG; + private float omegaWidth = NsharpConstants.OMEGA_WIDTH; + private float omegaHeight = NsharpConstants.OMEGA_HEIGHT; + private float omegaYEnd = NsharpConstants.OMEGA_Y_END; + //private float omegaMF = NsharpConstants.OMEGA_MAGNIFICATION_FACTOR; private float xRatio=1; private float yRatio=1; private String sTemperatureC= ""; @@ -96,6 +106,8 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ private IWireframeShape heightMarkRscShape=null; private IWireframeShape wetBulbTraceRscShape = null; private IWireframeShape vtempTraceCurveRscShape = null; + private IWireframeShape omegaBkgShape = null; + private IWireframeShape omegaRscShape=null; private IShadedShape cloudFMShape = null; private IWireframeShape cloudFMLabelShape = null; private IShadedShape cloudCEShape = null; @@ -186,9 +198,9 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ double dispX3; IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); dispX0 = ext.getMinX() + ext.getWidth()/5; - dispX1 = dispX0+ 20 * zoomLevel* xRatio; - dispX2 = dispX1+ 20 * zoomLevel* xRatio; - dispX3 = dispX2+ 20 * zoomLevel* xRatio; + dispX1 = dispX0+ 20 * currentZoomLevel* xRatio; + dispX2 = dispX1+ 20 * currentZoomLevel* xRatio; + dispX3 = dispX2+ 20 * currentZoomLevel* xRatio; String botStr, topStr; float aglTop, aglBot; aglTop = nsharpNative.nsharpLib.agl(nsharpNative.nsharpLib.ihght(topPF.getValue())); @@ -245,7 +257,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ double dispX2; IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); dispX1 = ext.getMaxX() -ext.getWidth()/3; - dispX2 = dispX1+ 40 * zoomLevel* xRatio; + dispX2 = dispX1+ 40 * currentZoomLevel* xRatio; nsharpNative.nsharpLib.define_parcel(rscHandler.getCurrentParcel(), rscHandler.getCurrentParcelLayerPressure()); _lplvalues lpvls = new _lplvalues(); nsharpNative.nsharpLib.get_lpvaluesData(lpvls); @@ -310,7 +322,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ double y = world.mapY(NsharpWxMath.getSkewTXY(pressure, 10).y); target.drawLine( dispX1, y, 0.0, dispX2, y, 0.0, NsharpConstants.color_cyan, 2); - String textStr = "FGZ= %.0f'"; + String textStr = "FZL= %.0f'"; textStr = String.format(textStr,fgzft); target.drawString(font10, textStr, dispX1, y-10*yRatio, 0.0, TextStyle.NORMAL, @@ -416,7 +428,9 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ double windX = xPosition; float lastHeight = -999; double windY=0; - double barbScaleFactorx=1, barbScaleFactory=1; + double barbScaleFactorx, barbScaleFactory; + barbScaleFactorx = zoomLevel; + barbScaleFactory = zoomLevel; //System.out.println("zoom="+zoomLevel +"world viewYmin="+world.getViewYmin()+" viewYmax="+world.getViewYmax()+" wolrdYmin="+ world.getWorldYmin()+" wolrdYmax="+ world.getWorldYmax() // +"world viewXmin="+world.getViewXmin()+" viewXmax="+world.getViewXmax()+" wolrdXmin="+ world.getWorldXmin()+" wolrdXmax="+ world.getWorldXmax()); for (NcSoundingLayer layer : sndLys) { @@ -434,20 +448,23 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } // Get the vertical ordinate. - if(currentGraphMode== NsharpConstants.GRAPH_SKEWT) + if(currentGraphMode== NsharpConstants.GRAPH_SKEWT){ windY = NsharpWxMath.getSkewTXY(pressure, 0).y; + barbScaleFactorx = 0.5*zoomLevel; + barbScaleFactory= zoomLevel; + } else if(currentGraphMode== NsharpConstants.GRAPH_ICING ){ //Chin:Y axis (pressure) is scaled using log scale and increaing downward //WorldYmin= at pressure 1000,its value actually is 1000 (max), wolrdYmax = at pressure 300, its value is 825 (min) windY = world.getWorldYmax() + (world.getWorldYmin()-icingBackground.toLogScale(pressure)); - barbScaleFactorx = 2.5; - barbScaleFactory= 3.5;//experimental value: depends on the world coordinate size set + barbScaleFactorx = 1.3*zoomLevel; + barbScaleFactory= 2.5*zoomLevel;//experimental value: depends on the world coordinate size set }else if( currentGraphMode== NsharpConstants.GRAPH_TURB){ //Chin:Y axis (pressure) is scaled using log scale and increaing downward //WorldYmin= at pressure 1000,its value actually is 1000 (max), wolrdYmax = at pressure 300, its value is 825 (min) windY = world.getWorldYmax() + (world.getWorldYmin()-turbBackground.toLogScale(pressure)); - barbScaleFactorx = .23;//experimental value: depends on the world coordinate size set - barbScaleFactory=5.5; + barbScaleFactorx = .12*zoomLevel;//experimental value: depends on the world coordinate size set + barbScaleFactory=3.8*zoomLevel; } else continue; @@ -498,17 +515,28 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ if (nsharpNative.nsharpLib.itemp((float)p_mb) > -9998.0 && nsharpNative.nsharpLib.idwpt((float)p_mb) > -9998.0){ FloatByReference parm= new FloatByReference(0); relh= nsharpNative.nsharpLib.relh((float)p_mb, parm); - curStrFormat= "%4.0fmb %5.0fft/%.0fm agl %2.0f%%\n"; - curStr = String.format(curStrFormat, p_mb,htFt,htM,relh); + curStrFormat= "%4.0f/%.0fkt %4.0fmb %5.0fft/%.0fm agl %2.0f%%\n"; + curStr = String.format(curStrFormat, nsharpNative.nsharpLib.iwdir((float)p_mb), + nsharpNative.nsharpLib.iwspd((float)p_mb), p_mb,htFt,htM,relh); } else{ - curStrFormat= "%4.0fmb %5.0fft/%.0fm agl\n"; - curStr = String.format(curStrFormat, p_mb,htFt,htM); + curStrFormat= "%4.0f/%.0fkt %4.0fmb %5.0fft/%.0fm agl\n"; + curStr = String.format(curStrFormat, nsharpNative.nsharpLib.iwdir((float)p_mb), + nsharpNative.nsharpLib.iwspd((float)p_mb),p_mb,htFt,htM); } - curStrFormat1 = "%s/%s %4.1f/%4.1f%cC %4.0f/%.0f kt\n"; + /*curStrFormat1 = "%s/%s %4.1f/%4.1f%cC %4.0f/%.0f kt\n"; curStr1 = String.format(curStrFormat1,sTemperatureC,sTemperatureF, nsharpNative.nsharpLib.itemp((float)p_mb), nsharpNative.nsharpLib.idwpt((float)p_mb),NsharpConstants.DEGREE_SYMBOL, nsharpNative.nsharpLib.iwdir((float)p_mb), - nsharpNative.nsharpLib.iwspd((float)p_mb)); + nsharpNative.nsharpLib.iwspd((float)p_mb));*/ + + curStrFormat1 = "%s(%s) %4.1f/%4.1f%cF(%4.1f/%4.1f%cC)\n"; + temp = nsharpNative.nsharpLib.itemp((float)p_mb); + UnitConverter celciusToFahrenheit = SI.CELSIUS.getConverterTo(NonSI.FAHRENHEIT); + double tempF= celciusToFahrenheit.convert(temp); + double dp = nsharpNative.nsharpLib.idwpt((float)p_mb); + double dpF= celciusToFahrenheit.convert(dp); + curStr1 = String.format(curStrFormat1,sTemperatureF,sTemperatureC, tempF,dpF, NsharpConstants.DEGREE_SYMBOL,temp, + dp,NsharpConstants.DEGREE_SYMBOL); //String tempS= String.format("%5.1f%cC ",temp,NsharpConstants.DEGREE_SYMBOL); //curStr2 =sThetaInK+" "+sWThetaInK+" "+sEThetaInK+"\n"; @@ -540,7 +568,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ double dispX; double dispY; IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); - dispX = ext.getMinX() + 20 * zoomLevel* xRatio; + dispX = ext.getMinX() + 100 * zoomLevel* xRatio; dispY = ext.getMinY() + 70 * zoomLevel* yRatio; //Column 1: pressure, C and F target.drawString(font10, sPressure, dispX, dispY, 0.0, @@ -706,24 +734,19 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } - @SuppressWarnings("deprecation") @Override protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { //System.out.println("NsharpSkewTPaneResource paintInternal called! I am pane #"+ descriptor.getPaneNumber()); //double X = NsharpConstants.WIND_BX_X_ORIG; //double Y = 80; + if(soundingLys==null) + return; super.paintInternal(target, paintProps); //System.out.println("skew paintInternal zoomL="+currentZoomLevel); if(rscHandler== null) return; - /*if(mycurrentZoomLevel != currentZoomLevel){ - mycurrentZoomLevel = currentZoomLevel; - if(heightMarkRscShape!=null) - heightMarkRscShape.dispose(); - createRscHeightMarkShape(); - rscHandler.getWitoPaneRsc().handleZooming(); - }*/ + /* Chin : turn it off for now skewTBackground.setCurrentFont(currentFont10Size); icingBackground.setCurrentFont(currentFont10Size); @@ -802,6 +825,18 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ 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(); + //target.drawWireframeShape(omegaRscShape, NsharpConstants.color_cyan, commonLinewidth, + // commonLineStyle,font10); + //target.drawWireframeShape(omegaBkgShape, NsharpConstants.color_violet_red, commonLinewidth, + // LineStyle.DASHED,font10); + } + } } else{ //by default, draw everything @@ -827,6 +862,16 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } //draw effective layer lines drawEffectiveLayerLines(target); + if(NsharpLoadDialog.getAccess()!= null && + (NsharpLoadDialog.getAccess().getActiveLoadSoundingType()== NsharpLoadDialog.MODEL_SND || + NsharpLoadDialog.getAccess().getActiveLoadSoundingType()== NsharpLoadDialog.PFC_SND )){ + //plot omega + drawOmega(); + //target.drawWireframeShape(omegaRscShape, NsharpConstants.color_cyan, commonLinewidth, + // commonLineStyle,font10); + //target.drawWireframeShape(omegaBkgShape, NsharpConstants.color_violet_red, commonLinewidth, + // LineStyle.DASHED,font10); + } } } if(plotInteractiveTemp == true ){ @@ -852,8 +897,8 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } //System.out.println("x1 pos"+xPos+ " x2 pos="+ (xPos - NsharpResourceHandler.BARB_LENGTH)); } - - target.drawWireframeShape(heightMarkRscShape, NsharpConstants.color_red, 1, LineStyle.SOLID, font10); + drawHeightMark(); + //target.drawWireframeShape(heightMarkRscShape, NsharpConstants.color_red, 1, LineStyle.SOLID, font10); //if(!compareStnIsOn){ //draw EL, LFC, LCL, FZL, -20C, -30C lines @@ -1016,6 +1061,55 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ createRscParcelTraceShape( parData.parcelType,parData.parcelLayerPressure); } } + // Chin: to handle dynamically moving height mark within viewable zone when zooming, I could not use wireframeShape successfully + // It will chop off lower part of marks. Therefore use this draw function. + @SuppressWarnings("deprecation") + private void drawHeightMark(){ + //plot meter scales... + IExtent ext = descriptor.getRenderableDisplay().getExtent(); + double xmin = ext.getMinX(); //Extent's viewable envelope min x and y + double xDefault = world.mapX(NsharpConstants.left); + if(xmin -999){ + omega = -layer.getOmega()* omegaWidth*(float)currentZoomLevel*0.5f; + Coordinate c1 = NsharpWxMath.getSkewTXY(p, t); + Coordinate c2 = new Coordinate();; + c2.y = world.mapY(c1.y); // what we need here is only pressure for Y-axix, + //System.out.println("p="+p+" t=" + t+" c1y="+c1.y+ " c2y="+c2.y); + double [][] lines3 = {{xAxisOrigin, c2.y},{xAxisOrigin+ omega, c2.y}}; + omegaRscShape.addLineSegment(lines3); + } + } + omegaRscShape.compile(); + } + // Chin: to handle dynamically moving omega within viewable zone when zooming, I could not use wireframeShape successfully + // It will chop off lower part of omega. Therefore use this draw function for omega. + @SuppressWarnings("deprecation") + private void drawOmega() { + //draw label and vertical lines + IExtent ext = descriptor.getRenderableDisplay().getExtent(); + float xmin = (float) ext.getMinX(); + //System.out.println("ex xmin="+ xmin+ " ymin= "+ ext.getMinY() + " ymax="+ ext.getMaxY()); + float xWoldMin = (float)world.mapX(NsharpConstants.left); + if(xmin > xWoldMin) + omegaXOrig = xmin+40*xRatio*(float)currentZoomLevel; + else + omegaXOrig = xWoldMin+40*xRatio*(float)currentZoomLevel; + //we dont really care about temp, as we use pressure for Y axis. + try { + //left dash line + target.drawLine( omegaXOrig+omegaWidth*currentZoomLevel, omegaYOrig, 0.0, omegaXOrig+omegaWidth*currentZoomLevel, omegaYEnd, 0.0, + NsharpConstants.color_violet_red, 1,LineStyle.DASHED); + + //center line + target.drawLine(omegaXOrig+omegaWidth*currentZoomLevel*0.5f, omegaYOrig, 0.0, omegaXOrig+omegaWidth*currentZoomLevel*0.5f, omegaYEnd, 0.0, + NsharpConstants.color_violet_red, 1,LineStyle.DASHED); + //right dash line, + target.drawLine(omegaXOrig, omegaYOrig, 0.0, omegaXOrig, omegaYEnd, 0.0, + NsharpConstants.color_violet_red, 1,LineStyle.DASHED); + target.drawString(font10,"+1 OMEGA -1", omegaXOrig+omegaWidth*currentZoomLevel*0.5f, omegaYOrig+10*yRatio, 0.0, TextStyle.NORMAL, + NsharpConstants.color_violet_red, HorizontalAlignment.CENTER, + VerticalAlignment.BOTTOM, null); + + + float p, omega, t; + double xAxisOrigin=omegaXOrig+omegaWidth*currentZoomLevel*0.5f; + for (NcSoundingLayer layer : this.soundingLys) { + p = layer.getPressure(); + t = layer.getTemperature(); + if (layer.getOmega() > -999){ + omega = -layer.getOmega()* omegaWidth*(float)currentZoomLevel*0.5f; + Coordinate c1 = NsharpWxMath.getSkewTXY(p, t); + Coordinate c2 = new Coordinate();; + c2.y = world.mapY(c1.y); // what we need here is only pressure for Y-axix, + //System.out.println("p="+p+" t=" + t+" c1y="+c1.y+ " c2y="+c2.y); + target.drawLine(xAxisOrigin, c2.y, 0.0,xAxisOrigin+ omega, c2.y, 0.0, + NsharpConstants.color_cyan, 1); + } + } + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } /** * Create all wire frame shapes at one place. @@ -1538,7 +1733,8 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ if(target!=null){ disposeRscWireFrameShapes(); if(soundingLys != null){ - createRscHeightMarkShape(); + //createRscOmegaShape(); + //createRscHeightMarkShape(); createRscwetBulbTraceShape(); createRscPressTempCurveShapeAll(); createRscVTempTraceShape(); @@ -1552,6 +1748,14 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } public void disposeRscWireFrameShapes(){ + if(omegaBkgShape!=null){ + omegaBkgShape.dispose(); + omegaBkgShape=null; + } + if(omegaRscShape!=null){ + omegaRscShape.dispose(); + omegaRscShape=null; + } if(heightMarkRscShape!=null){ heightMarkRscShape.dispose(); heightMarkRscShape=null; @@ -1628,7 +1832,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ //System.out.println("user inout pt pressure "+ inPressure+ " temp "+inTemp ); double prevPressure=1000; double prevT=0, prevD=0; - Coordinate closeptC = new Coordinate(1,1,0); + Coordinate closeptC = new Coordinate(0,0,0); boolean firstPrevPicked= false; /* @@ -1668,9 +1872,14 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ pickedDewpoint = d; currentSoundingLayerIndex = this.soundingLys.indexOf(layer); } - //decide which line, temp or dewpoint, closer to user picked point double disTemp = Math.abs(pickedTemp- inTemp); double disDew = Math.abs(pickedDewpoint- inTemp); + //if both dis is not witin editing distance, ie.e 2 degree, then return with (0,0); + if(disTemp > 2 && disDew > 2){ + return closeptC; + } + + //decide which line, temp or dewpoint, closer to user picked point if(disTemp <= disDew){ closeptC = NsharpWxMath.getSkewTXY(pickedPressure, pickedTemp); closeptC = world.map(closeptC); @@ -1733,7 +1942,9 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ } public void setCurrentGraphMode(int currentGraphMode) { this.currentGraphMode = currentGraphMode; - rscHandler.getWitoPaneRsc().handleResize(); + if(rscHandler.getWitoPaneRsc()!=null) + //simple D2D pane does not display WITO pane + rscHandler.getWitoPaneRsc().handleResize(); } public void setPlotInteractiveTemp(boolean plotInteractiveTemp) { @@ -1751,7 +1962,7 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ @Override public void handleResize() { - + //System.out.println("NsharpSkewTPaneResource handleResize called! "); super.handleResize(); IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); ext.reset(); @@ -1769,32 +1980,52 @@ public class NsharpSkewTPaneResource extends NsharpAbstractPaneResource{ skewtYOrig = (int) ext.getMinY(); skewtWidth = (int) (ext.getWidth()); skewtHeight = (int) ext.getHeight(); - skewtXEnd = skewtXOrig+ skewtWidth; - skewtYEnd = skewtYOrig+ skewtHeight; + //skewtXEnd = skewtXOrig+ skewtWidth; + //skewtYEnd = skewtYOrig+ skewtHeight; xRatio = xRatio* skewtWidth/prevWidth; yRatio = yRatio* skewtHeight/prevHeight; + omegaYOrig = skewtYOrig; + omegaWidth = skewtWidth*0.05f; + omegaHeight = skewtHeight; + omegaYEnd = omegaYOrig + omegaHeight; createRscWireFrameShapes(); skewTBackground.handleResize(ext); turbBackground.handleResize(ext); icingBackground.handleResize(ext); + //System.out.println(descriptor.getPaneNumber()+":calling wito handle resize"); - rscHandler.getWitoPaneRsc().handleResize(); + if(rscHandler.getWitoPaneRsc()!=null) + //simple D2D pane does not display WITO pane + rscHandler.getWitoPaneRsc().handleResize(); } @Override public void handleZooming() { + //System.out.println("NsharpSkewTPaneResource handleZooming called! "); if(heightMarkRscShape!=null) heightMarkRscShape.dispose(); - createRscHeightMarkShape(); + if(omegaBkgShape!=null){ + omegaBkgShape.dispose(); + omegaBkgShape=null; + } + if(omegaRscShape!=null){ + omegaRscShape.dispose(); + omegaRscShape=null; + } + + //createRscHeightMarkShape(); + //createRscOmegaShape(); skewTBackground.handleZooming(); turbBackground.handleZooming(); icingBackground.handleZooming(); - rscHandler.getWitoPaneRsc().handleZooming(); + if(rscHandler.getWitoPaneRsc()!=null) + //simple D2D pane does not display WITO pane + rscHandler.getWitoPaneRsc().handleZooming(); } @Override - protected void adjustFontSize(int canvasW, int canvasH) { + protected void adjustFontSize(float canvasW, float canvasH) { // TODO Auto-generated method stub super.adjustFontSize(canvasW, canvasH); //make a bit bigger font10 size for skewT 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 new file mode 100644 index 0000000000..d0131f6ab9 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResource.java @@ -0,0 +1,82 @@ +package gov.noaa.nws.ncep.ui.nsharp.display.rsc; +/** + * + * + * This code has been developed by the NCEP-SIB for use in the AWIPS2 system. + * + *
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    	Engineer    Description
    + * -------		------- 	-------- 	-----------
    + * 07/10/2012	229			Chin Chen	Initial coding
    + *
    + * 
    + * + * @author Chin Chen + * @version 1.0 + */ + +import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; +import gov.noaa.nws.ncep.ui.nsharp.display.NsharpAbstractPaneDescriptor; + +import com.raytheon.uf.viz.core.IExtent; +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; +import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; +import com.raytheon.uf.viz.core.drawables.PaintProperties; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractResourceData; +import com.raytheon.uf.viz.core.rsc.LoadProperties; + +public class NsharpSpcGraphsPaneResource extends NsharpAbstractPaneResource{ + private int spcXOrig; + private int spcYOrig; + private int spcWidth; + private int spcHeight; + public NsharpSpcGraphsPaneResource(AbstractResourceData resourceData, + LoadProperties loadProperties, NsharpAbstractPaneDescriptor desc) { + super(resourceData, loadProperties, desc); + + } + + @SuppressWarnings("deprecation") + @Override + protected void paintInternal(IGraphicsTarget target, + PaintProperties paintProps) throws VizException { + super.paintInternal(target, paintProps); + //defineCharHeight(font10); + if(rscHandler== null) + return; + this.font10.setSmoothing(false); + this.font10.setScaleFont(false); + target.drawLine(spcXOrig+ spcWidth/2, spcYOrig, 0.0, spcXOrig+ spcWidth/2, spcYOrig+spcHeight, 0.0, NsharpConstants.color_white, 1); + target.drawString(this.font10,"FUTURE display", spcXOrig+ spcWidth/2, + spcYOrig + spcHeight/2, 0.0, + IGraphicsTarget.TextStyle.NORMAL, + NsharpConstants.color_green, + HorizontalAlignment.CENTER, + VerticalAlignment.BOTTOM, null); + } + + @Override + protected void initInternal(IGraphicsTarget target) throws VizException { + super.initInternal(target); + } + @Override + protected void disposeInternal() { + + super.disposeInternal(); + } + @Override + public void handleResize() { + + super.handleResize(); + IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); + ext.reset(); + spcXOrig = (int) (ext.getMinX()); + spcYOrig = (int) ext.getMinY(); + spcWidth = (int) (ext.getWidth()); + spcHeight = (int) ext.getHeight(); + } +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResourceData.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResourceData.java new file mode 100644 index 0000000000..798516abf9 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpSpcGraphsPaneResourceData.java @@ -0,0 +1,51 @@ +package gov.noaa.nws.ncep.ui.nsharp.display.rsc; +/** + * + * + * This code has been developed by the NCEP-SIB for use in the AWIPS2 system. + * + *
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    	Engineer    Description
    + * -------		------- 	-------- 	-----------
    + * 04/23/2012	229			Chin Chen	Initial coding
    + *
    + * 
    + * + * @author Chin Chen + * @version 1.0 + */ + +import gov.noaa.nws.ncep.ui.nsharp.display.NsharpSpcGraphsPaneDescriptor; + +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractResourceData; +import com.raytheon.uf.viz.core.rsc.AbstractVizResource; +import com.raytheon.uf.viz.core.rsc.LoadProperties; + +public class NsharpSpcGraphsPaneResourceData extends AbstractResourceData { + + @Override + public AbstractVizResource construct(LoadProperties loadProperties, + IDescriptor descriptor) throws VizException { + NsharpSpcGraphsPaneDescriptor desc=(NsharpSpcGraphsPaneDescriptor)descriptor; + //System.out.println("NsharpSpcGraphsPaneResourceData construct called Panes="+desc.getPaneNumber()); + return new NsharpSpcGraphsPaneResource(this, loadProperties, desc); + + } + + @Override + public void update(Object updateData) { + // TODO Auto-generated method stub + + } + + @Override + public boolean equals(Object obj) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpTimeStnPaneResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpTimeStnPaneResource.java index 2fa9bbc7a9..bc503bbb37 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpTimeStnPaneResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpTimeStnPaneResource.java @@ -28,6 +28,7 @@ import java.util.List; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; +import com.raytheon.uf.viz.core.DrawableString; import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; @@ -57,7 +58,6 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ private int dtWidth = NsharpConstants.DATA_TIMELINE_WIDTH; private int dtHeight = NsharpConstants.DATA_TIMELINE_HEIGHT; private int dtNextPageEnd = NsharpConstants.DATA_TIMELINE_NEXT_PAGE_END_; - private int charHeight = NsharpConstants.CHAR_HEIGHT_; private int stnXOrig = NsharpConstants.STATION_ID_X_ORIG; private int stnYOrig = NsharpConstants.STATION_ID_Y_ORIG; private int stnXEnd = NsharpConstants.STATION_ID_X_END; @@ -65,7 +65,7 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ private int stnHeight = NsharpConstants.STATION_ID_HEIGHT; private int cnXOrig = NsharpConstants.COLOR_NOTATION_X_ORIG; private int cnYOrig = NsharpConstants.COLOR_NOTATION_Y_ORIG; - private int cnXEnd = NsharpConstants.COLOR_NOTATION_X_END; + //private int cnXEnd = NsharpConstants.COLOR_NOTATION_X_END; private int cnWidth = NsharpConstants.COLOR_NOTATION_WIDTH; private int cnHeight = NsharpConstants.COLOR_NOTATION_HEIGHT; private float xRatio=1; @@ -81,56 +81,7 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ colorNoteRectangle = new Rectangle(cnXOrig,cnYOrig, cnWidth,cnHeight); } - - - @SuppressWarnings("deprecation") - private void drawNsharpTimelineTitle(IGraphicsTarget target) throws VizException { - String s = timeLineStateList.size() + " time lines"; - double x = dtXOrig; - double y = dtYOrig-25*yRatio; - - target.drawString(font10, s, x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - NsharpConstants.color_white, - HorizontalAlignment.LEFT, - VerticalAlignment.MIDDLE, null); - y = y+charHeight; - s = "page " + curTimeLinePage+"/"+totalTimeLinePage; - target.drawString(font10, s, x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - NsharpConstants.color_green, - HorizontalAlignment.LEFT, - VerticalAlignment.MIDDLE, null); - } - @SuppressWarnings("deprecation") - private void drawNsharpStationIdTitle(IGraphicsTarget target) throws VizException { - //darw title first - String s; - s = stnStateList.size() + " stations"; - double x = stnXOrig; - double y = stnYOrig - 25*yRatio; - - target.drawString(font10, s, x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - NsharpConstants.color_white, - HorizontalAlignment.LEFT, - VerticalAlignment.MIDDLE, null); - y = y+charHeight; - s = "page " + curStnIdPage+"/"+totalStnIdPage; - target.drawString(font10, s, x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - NsharpConstants.color_green, - HorizontalAlignment.LEFT, - VerticalAlignment.MIDDLE, null); - - } - - @SuppressWarnings("deprecation") private void drawNsharpColorNotation(IGraphicsTarget target, Rectangle rect) throws VizException { PixelExtent extent = new PixelExtent(rect); RGB color; @@ -139,202 +90,208 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ //plot notations: double x = cnXOrig+5*xRatio; - double y = cnYOrig+charHeight; - double xGap = paneWidth/3*xRatio; + double y = cnYOrig+1.5*charHeight; + //double xGap = paneWidth/3*xRatio; color = NsharpConstants.color_white; - target.drawString(font10, "TimeLine/Station State Color Notations:", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - - y=y+charHeight; + DrawableString str =new DrawableString( "State:",color); + str.font = font10; + str.setCoordinates(x, y); + str.horizontalAlignment = HorizontalAlignment.LEFT; + str.verticallAlignment = VerticalAlignment.BOTTOM; + target.drawStrings(str); + double horizRatio = paintProps.getView().getExtent().getWidth() / paintProps.getCanvasBounds().width; + x = x + target.getStringsBounds(str).getWidth() * horizRatio ; + color = NsharpConstants.color_green; - target.drawString(font10, "Current:green", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); + str.setText( "Current", color); + str.setCoordinates(x, y); + target.drawStrings(str); + x = x + target.getStringsBounds(str).getWidth() * horizRatio *1.1; - //x = x+xGap; - y=y+charHeight; color = NsharpConstants.color_yellow; - target.drawString(font10, "Active:yellow", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); + str.setText( "Active", color); + str.setCoordinates(x, y); + target.drawStrings(str); + x = x + target.getStringsBounds(str).getWidth() * horizRatio * 1.1; - - //x = x+xGap; + color = NsharpConstants.color_white; + str.setText( "InActive", color); + str.setCoordinates(x, y); + target.drawStrings(str); + + x = cnXOrig+5*xRatio; y=y+charHeight; color = NsharpConstants.color_white; - target.drawString(font10, "InActive:white", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - - //x = cnXOrig+5*xRatio; - //y=y+25*yRatio; - y=y+charHeight; - color = NsharpConstants.color_white; - target.drawString(font10, "TimeLine/Station Data Loading Status:", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - - //x = cnXOrig+5*xRatio; - y=y+charHeight; + str.setText( "Status:", color); + str.setCoordinates(x, y); + target.drawStrings(str); + x = x + target.getStringsBounds(str).getWidth() * horizRatio * 1.1; color = NsharpConstants.color_red; - target.drawString(font10, "* :Data Loaded", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - - y=y+charHeight; + str.setText( "* :Loaded", color); + str.setCoordinates(x, y); + target.drawStrings(str); + x = x + target.getStringsBounds(str).getWidth() * horizRatio * 1.1; color = NsharpConstants.color_cyan; - target.drawString(font10, "* :Data Not Loaded", x, - y, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - + str.setText( "* :UnLoaded", color); + str.setCoordinates(x, y); + target.drawStrings(str); target.clearClippingPlane(); } @SuppressWarnings("deprecation") - private void drawNsharpTimelinBox(IGraphicsTarget target, Rectangle rect) throws VizException { - PixelExtent extent = new PixelExtent(rect); - target.setupClippingPlane(extent); - target.drawRect(extent,NsharpConstants.backgroundColor, 1.0f, 1.0f); - //System.out.println("drawNsharpDataTimelines picked stn info: "+ pickedStnInfoStr); - double x = dtXOrig + 5;//, x1 ; - double nextPageY = dtNextPageEnd;//DATA_TIMELINE_Y_ORIG + charHeight; - RGB color = NsharpConstants.color_yellow; - String s = "nextPage"; - target.drawString(font10, s, x, - nextPageY, 0.0, + private void drawNsharpTimelinBox(IGraphicsTarget target, Rectangle rect) throws VizException { + PixelExtent extent = new PixelExtent(rect); + target.setupClippingPlane(extent); + target.drawRect(extent,NsharpConstants.backgroundColor, 1.0f, 1.0f); + double x = dtXOrig; + double y = dtYOrig-1.5*charHeight*yRatio; + String s = timeLineStateList.size() + " time lines, page " + curTimeLinePage+"/"+totalTimeLinePage; + target.drawString(font10, s, x, + y, 0.0, IGraphicsTarget.TextStyle.NORMAL, - color, + NsharpConstants.color_green, + HorizontalAlignment.LEFT, + VerticalAlignment.TOP, null); + y = dtYOrig; + target.drawLine(dtXOrig, y, 0.0,dtXEnd , y, 0.0,NsharpConstants.color_white,1, LineStyle.SOLID); + //System.out.println("drawNsharpDataTimelines picked stn info: "+ pickedStnInfoStr); + x = dtXOrig + 5;//, x1 ; + + y = y+1.2*charHeight*yRatio; + s = "nextPage"; + target.drawString(font10, s, x, + y, 0.0, + IGraphicsTarget.TextStyle.NORMAL, + NsharpConstants.color_yellow, HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM, null); - target.drawLine(dtXOrig, nextPageY, 0.0, - dtXEnd , nextPageY, 0.0, + target.drawLine(dtXOrig, y, 0.0, + dtXEnd , y, 0.0, NsharpConstants.color_white,1, LineStyle.SOLID); - - - int numTimeLineToShowPerPage = (cnYOrig-dtNextPageEnd)/charHeight; + + + int numTimeLineToShowPerPage = (cnYOrig-dtNextPageEnd)/charHeight; int startIndex = (curTimeLinePage-1) * numTimeLineToShowPerPage; - int i = 1; - if(timeLineStateList!= null){ - int compIndex= 1; - int colorIndex; - boolean compareTmIsOn = rscHandler.isCompareTmIsOn(); - int currentStnStateListIndex = rscHandler.getCurrentStnStateListIndex(); + + if(timeLineStateList!= null){ + int compIndex= 1; + int colorIndex; + boolean compareTmIsOn = rscHandler.isCompareTmIsOn(); + int currentStnStateListIndex = rscHandler.getCurrentStnStateListIndex(); int currentTimeLineStateListIndex = rscHandler.getCurrentTimeLineStateListIndex(); - for (int j = startIndex; j< timeLineStateList.size(); j++) - { - boolean avail=false; - NsharpTimeLineStateProperty elm = timeLineStateList.get(j); - NsharpConstants.State sta = elm.getTimeState(); - double ly = dtNextPageEnd + charHeight * i; - if(sta == NsharpConstants.State.ACTIVE && j == currentTimeLineStateListIndex) + double ly = dtNextPageEnd + charHeight; + RGB color; + double hRatio = paintProps.getView().getExtent().getWidth() / paintProps.getCanvasBounds().width; + Rectangle2D strBD = target.getStringBounds(font10, "*"); + double xGap = 2*strBD.getWidth()*hRatio; + for (int j = startIndex; j< timeLineStateList.size(); j++) + { + x = dtXOrig + 5; + boolean avail=false; + NsharpTimeLineStateProperty elm = timeLineStateList.get(j); + NsharpConstants.State sta = elm.getTimeState(); + + if(sta == NsharpConstants.State.ACTIVE && j == currentTimeLineStateListIndex) sta = NsharpConstants.State.CURRENT; - if(currentStnStateListIndex>=0){ - + if(currentStnStateListIndex>=0){ + s = "*"; + if ( rscHandler.getStnTimeTable().get(currentStnStateListIndex).get(j).elementState == NsharpConstants.State.AVAIL ){ + avail = true; + } + if(avail){ + color = NsharpConstants.color_red; + } + else { + color = NsharpConstants.color_cyan; + } + //System.out.println("selectedTimeList: "+ s); - if ( rscHandler.getStnTimeTable().get(currentStnStateListIndex).get(j).elementState == NsharpConstants.State.AVAIL ){ - avail = true; - } - if(avail){ - color = NsharpConstants.color_red; - s = "*"; - } - else { - color = NsharpConstants.color_cyan; - s = "*"; - } - //System.out.println("selectedTimeList: "+ s); - - target.drawString(font10, s, x, - ly, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - } - - color = rscHandler.getElementColorMap().get(sta); - s = elm.timeDescription; - target.drawString(font10, s, x+10, - ly, 0.0, - IGraphicsTarget.TextStyle.NORMAL, - color, - HorizontalAlignment.LEFT, - VerticalAlignment.BOTTOM, null); - Rectangle2D bd = target.getStringBounds(font10, s); - i++; - if(compareTmIsOn && elm.timeState == NsharpConstants.State.ACTIVE && avail){ - colorIndex = (compIndex-1)%(NsharpConstants.LINE_COMP10-NsharpConstants.LINE_COMP1+1)+ NsharpConstants.LINE_COMP1; - s ="Cp "+ compIndex; - target.drawString(font10,s, x+bd.getWidth()+15, + target.drawString(font10, s, x, + ly, 0.0, + IGraphicsTarget.TextStyle.NORMAL, + color, + HorizontalAlignment.LEFT, + VerticalAlignment.BOTTOM, null); + } + + x=x+xGap; + color = rscHandler.getElementColorMap().get(sta); + s = elm.timeDescription; + target.drawString(font10, s, x, + ly, 0.0, + IGraphicsTarget.TextStyle.NORMAL, + color, + HorizontalAlignment.LEFT, + VerticalAlignment.BOTTOM, null); + + if(compareTmIsOn && elm.timeState == NsharpConstants.State.ACTIVE && avail){ + colorIndex = (compIndex-1)%(NsharpConstants.LINE_COMP10-NsharpConstants.LINE_COMP1+1)+ NsharpConstants.LINE_COMP1; + strBD = target.getStringBounds(font10, s); + s ="Cp "+ compIndex; + x=x+ strBD.getWidth()*hRatio+5; + target.drawString(font10,s, x, ly, 0.0, IGraphicsTarget.TextStyle.NORMAL, linePropertyMap.get(NsharpConstants.lineNameArray[colorIndex]).getLineColor(), HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM, null); - compIndex++; - } - if (ly >= cnYOrig-charHeight) - //we dont show time line that extends below time line box - break; - } - } - - + compIndex++; + } + ly = ly + charHeight; + if (ly >= cnYOrig)//-charHeight) + //we dont show time line that extends below time line box + break; + } + } } @SuppressWarnings("deprecation") - private void drawNsharpStationIdBox(IGraphicsTarget target, Rectangle rect) throws VizException { + private void drawNsharpStationIdBox(IGraphicsTarget target, Rectangle rect) throws VizException { PixelExtent extent = new PixelExtent(rect); - target.setupClippingPlane(extent); - target.drawRect(extent,NsharpConstants.backgroundColor, 1.0f, 1.0f); - double x= stnXOrig + 5; - double nextPageY = dtNextPageEnd; - RGB color = NsharpConstants.color_yellow; - String s = "nextPage"; - target.drawString(font10, s, x, - nextPageY, 0.0, + target.setupClippingPlane(extent); + target.drawRect(extent,NsharpConstants.backgroundColor, 1.0f, 1.0f); + double x = stnXOrig; + double y = stnYOrig -1.5*charHeight*yRatio; + String s = stnStateList.size() + " stations, page " + curStnIdPage+"/"+totalStnIdPage; + target.drawString(font10, s, x, + y, 0.0, + IGraphicsTarget.TextStyle.NORMAL, + NsharpConstants.color_green, + HorizontalAlignment.LEFT, + VerticalAlignment.TOP, null); + y = dtYOrig; + target.drawLine(stnXOrig, y, 0.0,stnXEnd , y, 0.0,NsharpConstants.color_white,1, LineStyle.SOLID); + //System.out.println("drawNsharpDataTimelines picked stn info: "+ pickedStnInfoStr); + x = stnXOrig + 5; + + y = y+1.2*charHeight*yRatio; + s = "nextPage"; + target.drawString(font10, s, x, + y, 0.0, IGraphicsTarget.TextStyle.NORMAL, - color, + NsharpConstants.color_yellow, HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM, null); - target.drawLine(stnXOrig, nextPageY, 0.0, - stnXEnd , nextPageY, 0.0, + target.drawLine(stnXOrig, y, 0.0, + stnXEnd , y, 0.0, NsharpConstants.color_white,1, LineStyle.SOLID); int numStnToShow = (cnYOrig-dtNextPageEnd)/charHeight; int startIndex = (rscHandler.getCurStnIdPage()-1) * numStnToShow; - int i = 1; int compIndex= 1; int colorIndex; boolean compareStnIsOn = rscHandler.isCompareStnIsOn(); int currentStnStateListIndex = rscHandler.getCurrentStnStateListIndex(); int currentTimeLineStateListIndex = rscHandler.getCurrentTimeLineStateListIndex(); - - for (int j = startIndex; j< stnStateList.size(); j++) + double ly = dtNextPageEnd + charHeight; + RGB color; + Rectangle2D strBD = target.getStringBounds(font10, "*"); + double hRatio = paintProps.getView().getExtent().getWidth() / paintProps.getCanvasBounds().width; + double xGap = 2*strBD.getWidth()*hRatio; + for (int j = startIndex; j< stnStateList.size(); j++) { boolean avail=false; + x = stnXOrig + 5; NsharpStationStateProperty elm = stnStateList.get(j); NsharpConstants.State sta ; if(elm.stnState == NsharpConstants.State.ACTIVE && j == currentStnStateListIndex) @@ -342,7 +299,7 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ else sta = elm.stnState; // set its state based on stn state - double ly = dtNextPageEnd + charHeight * i; + if (currentTimeLineStateListIndex>=0){ if(rscHandler.getStnTimeTable().get(j).get(currentTimeLineStateListIndex).elementState == NsharpConstants.State.AVAIL ){ avail =true; @@ -355,30 +312,29 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ color = NsharpConstants.color_cyan; s = "*"; } - //System.out.println("selectedTimeList: "+ s); - - target.drawString(font10, s, x, + target.drawString(font10, s, x, ly, 0.0, IGraphicsTarget.TextStyle.NORMAL, color, HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM, null); } - + x=x+xGap; String stnId = elm.stnDescription; color = rscHandler.getElementColorMap().get(sta); - target.drawString(font10, stnId, x+10, + target.drawString(font10, stnId, x, ly, 0.0, IGraphicsTarget.TextStyle.NORMAL, color, HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM, null); if(compareStnIsOn && elm.stnState == NsharpConstants.State.ACTIVE && avail){ - Rectangle2D bd = target.getStringBounds(font10, stnId); + strBD = target.getStringBounds(font10, stnId); colorIndex = (compIndex-1)%(NsharpConstants.LINE_COMP10-NsharpConstants.LINE_COMP1+1)+ NsharpConstants.LINE_COMP1; s ="Cp "+ compIndex; - target.drawString(font10,s, x+bd.getWidth()+25, + x=x+ strBD.getWidth()*hRatio+5; + target.drawString(font10,s, x, ly, 0.0, IGraphicsTarget.TextStyle.NORMAL, linePropertyMap.get(NsharpConstants.lineNameArray[colorIndex]).getLineColor(), @@ -390,9 +346,8 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ //anything to do? //} - - i++; - if (ly >= cnYOrig-charHeight) + ly = ly + charHeight; + if (ly >= cnYOrig) //we dont show stn id that extends below box break; } @@ -402,6 +357,7 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { super.paintInternal(target, paintProps); + //defineCharHeight(font10); if(rscHandler== null) return; timeLineStateList = rscHandler.getTimeLineStateList(); //System.out.println("NsharpTimeStnPaneResource "+ descriptor.getPaneNumber()); @@ -417,11 +373,6 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ this.font12.setSmoothing(false); this.font12.setScaleFont(false); - //data time title - drawNsharpTimelineTitle(target); - drawNsharpStationIdTitle(target); - - //plot data time line drawNsharpTimelinBox(target, timeLineRectangle); @@ -436,10 +387,17 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ @Override protected void initInternal(IGraphicsTarget target) throws VizException { super.initInternal(target); - currentCanvasBoundWidth = NsharpConstants.TIMESTN_PANE_REC_WIDTH; - currentCanvasBoundHeight = NsharpConstants.TIMESTN_PANE_REC_HEIGHT; - myDefaultCanvasWidth = NsharpConstants.TIMESTN_PANE_REC_WIDTH; - myDefaultCanvasHeight = NsharpConstants.TIMESTN_PANE_REC_HEIGHT; + /*if(paneConfigurationNumber == NsharpConstants.PANE_CONFIGURATION_0){ + currentCanvasBoundWidth = (int)(NsharpConstants.DISPLAY_WIDTH * (1-NsharpConstants.PC0_LEFT_GP_WIDTH_RATIO)* NsharpConstants.PC0_TIMESTN_WIDTH_RATIO); + currentCanvasBoundHeight = (int)(NsharpConstants.DISPLAY_HEIGHT* NsharpConstants.PC0_TIMESTN_HEIGHT_RATIO); + myDefaultCanvasWidth = currentCanvasBoundWidth; + myDefaultCanvasHeight = currentCanvasBoundHeight; + } else if(paneConfigurationNumber == NsharpConstants.PANE_CONFIGURATION_1){ + currentCanvasBoundWidth = (int)(NsharpConstants.DISPLAY_WIDTH * NsharpConstants.PC1_LEFT_GP_WIDTH_RATIO* NsharpConstants.PC1_TIMESTN_WIDTH_RATIO); + currentCanvasBoundHeight = (int)(NsharpConstants.DISPLAY_HEIGHT* NsharpConstants.PC1_TIMESTN_HEIGHT_RATIO); + myDefaultCanvasWidth = currentCanvasBoundWidth; + myDefaultCanvasHeight = currentCanvasBoundHeight; + }*/ } @Override protected void disposeInternal() { @@ -461,20 +419,23 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ super.handleResize(); IExtent ext = getDescriptor().getRenderableDisplay().getExtent(); ext.reset(); + + defineCharHeight(font10); + //rscHandler.setCharHeight(charHeight); float prevHeight = paneHeight; float prevWidth = paneWidth; paneHeight = (int) ext.getHeight(); paneWidth = (int) (ext.getWidth()); xRatio = xRatio* paneWidth/prevWidth; yRatio = yRatio* paneHeight/prevHeight; - charHeight = (int)(NsharpConstants.CHAR_HEIGHT_*yRatio); + //charHeight = (int)(NsharpConstants.CHAR_HEIGHT_*yRatio); dtXOrig = (int) (ext.getMinX()); - dtYOrig = (int) ext.getMinY()+(int)( NsharpConstants.DATA_TIMELINE_Y_ORIG*yRatio); + dtYOrig = (int) ext.getMinY()+(int)(2* charHeight*yRatio); dtWidth = paneWidth/2; dtXEnd = dtXOrig + dtWidth; - cnHeight = (int)(NsharpConstants.COLOR_NOTATION_HEIGHT*yRatio); + cnHeight = (int)(3* charHeight*yRatio); dtHeight = paneHeight-dtYOrig-cnHeight; - dtNextPageEnd = dtYOrig+ charHeight; + dtNextPageEnd = dtYOrig+ (int) (2*charHeight*yRatio); stnXOrig = dtXEnd; stnYOrig = dtYOrig; stnWidth = dtWidth; @@ -483,17 +444,19 @@ public class NsharpTimeStnPaneResource extends NsharpAbstractPaneResource{ cnXOrig = dtXOrig; cnYOrig = dtYOrig+ dtHeight; cnWidth = paneWidth; - cnXEnd = cnXOrig+cnWidth; - timeLineRectangle = new Rectangle(dtXOrig,dtYOrig, - dtWidth,dtHeight); - stnIdRectangle = new Rectangle(stnXOrig,stnYOrig, - stnWidth,stnHeight); + //cnXEnd = cnXOrig+cnWidth; + timeLineRectangle = new Rectangle(dtXOrig,(int) ext.getMinY(), + dtWidth,paneHeight-cnHeight); + stnIdRectangle = new Rectangle(stnXOrig,(int) ext.getMinY(), + stnWidth,paneHeight-cnHeight); colorNoteRectangle = new Rectangle(cnXOrig,cnYOrig, cnWidth,cnHeight); - rscHandler.setDtNextPageEnd(dtNextPageEnd); + rscHandler.setTimeStnBoxData( cnYOrig, dtNextPageEnd, dtYOrig , charHeight); + /*rscHandler.setDtNextPageEnd(dtNextPageEnd); rscHandler.setDtYOrig(dtYOrig); rscHandler.setCnYOrig(cnYOrig); - rscHandler.setCharHeight(charHeight); - + rscHandler.setCharHeight(charHeight);*/ + + //System.out.println("pane 4 height="+paneHeight); } } 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 3e838e78b5..f04233a429 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 @@ -24,7 +24,6 @@ import gov.noaa.nws.ncep.ui.nsharp.background.NsharpGenericPaneBackground; import gov.noaa.nws.ncep.ui.nsharp.background.NsharpGenericPaneBackground.ViewablePressureContainer; import gov.noaa.nws.ncep.ui.nsharp.display.NsharpAbstractPaneDescriptor; import gov.noaa.nws.ncep.ui.nsharp.natives.NsharpNativeConstants; -import gov.noaa.nws.ncep.ui.nsharp.view.NsharpLoadDialog; import java.util.ArrayList; import java.util.List; @@ -53,18 +52,18 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ private int omegaHeight = NsharpConstants.OMEGA_HEIGHT; private int omegaYEnd = NsharpConstants.OMEGA_Y_END; private int omegaMF = NsharpConstants.OMEGA_MAGNIFICATION_FACTOR; - private int windBoxXOrig = NsharpConstants.WIND_BX_X_ORIG; - private int windBoxYOrig = NsharpConstants.WIND_BX_Y_ORIG; - private int windBoxWidth = NsharpConstants.WIND_BX_WIDTH; - private int windBoxHeight = NsharpConstants.WIND_BX_HEIGHT; - private int windBoxYEnd = windBoxYOrig + windBoxHeight; - private int verticalWindXOrig = NsharpConstants.VRTCAL_WIND_X_ORIG; - private int verticalWindYOrig = NsharpConstants.VRTCAL_WIND_Y_ORIG; - private int verticalWindWidth = NsharpConstants.VRTCAL_WIND_WIDTH; - private int verticalWindHeight = NsharpConstants.VRTCAL_WIND_HEIGHT; - private int verticalWindYEnd = NsharpConstants.VRTCAL_WIND_Y_END; - private int witoPanewidth = NsharpConstants.WITO_PANE_REC_WIDTH; - private int witoPaneHeight = NsharpConstants.WITO_PANE_REC_HEIGHT; + private float windBoxXOrig = NsharpConstants.WIND_BX_X_ORIG; + private float windBoxYOrig = NsharpConstants.WIND_BX_Y_ORIG; + private float windBoxWidth = NsharpConstants.WIND_BX_WIDTH; + private float windBoxHeight = NsharpConstants.WIND_BX_HEIGHT; + //private float windBoxYEnd = windBoxYOrig + windBoxHeight; + private float verticalWindXOrig = NsharpConstants.VRTCAL_WIND_X_ORIG; + private float verticalWindYOrig = NsharpConstants.VRTCAL_WIND_Y_ORIG; + private float verticalWindWidth = NsharpConstants.VRTCAL_WIND_WIDTH; + private float verticalWindHeight = NsharpConstants.VRTCAL_WIND_HEIGHT; + private float verticalWindYEnd = NsharpConstants.VRTCAL_WIND_Y_END; + private float witoPanewidth = NsharpConstants.WITO_PANE_REC_WIDTH; + private float witoPaneHeight = NsharpConstants.WITO_PANE_REC_HEIGHT; private IWireframeShape omegaBkgShape = null; private IWireframeShape windBoxBkgShape = null; private IWireframeShape omegaRscShape=null; @@ -104,6 +103,7 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ this.font9.setScaleFont(false); this.font12.setSmoothing(false); this.font12.setScaleFont(false); + /* PixelExtent extent = new PixelExtent(new Rectangle(omegaXOrig,omegaYOrig, omegaWidth,omegaHeight)); @@ -131,13 +131,13 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ target.drawWireframeShape(omegaRscShape, NsharpConstants.color_cyan, commonLinewidth, commonLineStyle,font10); } - } + }*/ //target.clearClippingPlane(); //wind box background and wind - extent = new PixelExtent(new Rectangle(windBoxXOrig,windBoxYOrig, - windBoxWidth,windBoxHeight)); + PixelExtent extent = new PixelExtent(new Rectangle((int)windBoxXOrig,(int)windBoxYOrig, + (int)windBoxWidth,(int)windBoxHeight)); //target.setupClippingPlane(extent); target.drawRect(extent, NsharpConstants.backgroundColor, 1.0f, 1.0f); target.drawWireframeShape(windBoxBkgShape, NsharpConstants.color_white, @@ -148,8 +148,8 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ //plot vertical wind profile (advection layer) - extent = new PixelExtent(new Rectangle(verticalWindXOrig,verticalWindYOrig, - verticalWindWidth,verticalWindHeight)); + extent = new PixelExtent(new Rectangle((int)verticalWindXOrig,(int)verticalWindYOrig, + (int)verticalWindWidth,(int)verticalWindHeight)); target.setupClippingPlane(extent); target.drawRect(extent, NsharpConstants.backgroundColor, 1.0f, 1.0f); float x1 = verticalWindXOrig+ (verticalWindWidth/2); @@ -173,8 +173,8 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ myDefaultCanvasWidth = witoPanewidth; myDefaultCanvasHeight = witoPaneHeight; //System.out.print("NsharpWitoPaneResource ::: initInternal entered!!!!!\n"); - this.rectangle = new Rectangle(windBoxXOrig, windBoxYOrig, - witoPanewidth, witoPaneHeight); + this.rectangle = new Rectangle((int)windBoxXOrig,(int) windBoxYOrig, + (int)witoPanewidth,(int) witoPaneHeight); pe = new PixelExtent(this.rectangle); world = new WGraphics(this.rectangle); @@ -207,7 +207,7 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ double [][] lines2 = {{xtemp, yOri},{xtemp, yOri+windBoxHeight-2}}; windBoxBkgShape.addLineSegment(lines2); if( (i==20) || (i==60) || (i==100)){ - double [] lblXy2 = {xtemp, yOri+windBoxHeight-2}; + double [] lblXy2 = {xtemp, yOri+windBoxHeight-10}; windBoxBkgShape.addLabel(String.format("%d",i), lblXy2); } @@ -362,11 +362,13 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ double [][] lines = {{0, 0},{0,0}}; verticalWindLabelShape.addLineSegment(lines); double [] lblXy = { verticalWindXOrig+verticalWindWidth/2, verticalWindYOrig+20*yMagFactor}; - verticalWindLabelShape.addLabel("Inferred Temp", lblXy); + verticalWindLabelShape.addLabel("Inferred", lblXy); double [] lblXy1 = { verticalWindXOrig+verticalWindWidth/2, verticalWindYOrig+35*yMagFactor}; - verticalWindLabelShape.addLabel("Advection", lblXy1); - double [] lblXy2 = { verticalWindXOrig+verticalWindWidth/2, verticalWindYOrig+55*yMagFactor}; - verticalWindLabelShape.addLabel("(C/hr)", lblXy2); + verticalWindLabelShape.addLabel("Temp", lblXy1); + double [] lblXy2 = { verticalWindXOrig+verticalWindWidth/2, verticalWindYOrig+50*yMagFactor}; + verticalWindLabelShape.addLabel("Advection", lblXy2); + double [] lblXy3 = { verticalWindXOrig+verticalWindWidth/2, verticalWindYOrig+65*yMagFactor}; + verticalWindLabelShape.addLabel("(C/hr)", lblXy3); verticalWindSbShape = target.createWireframeShape(false,descriptor ); verticalWindSbShape.allocate(72); @@ -531,15 +533,15 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ omegaWidth = (int) (witoPanewidth/3); omegaHeight = (int) ext.getHeight(); omegaYEnd = omegaYOrig + omegaHeight; - windBoxXOrig = (int) (ext.getMinX()); - windBoxYOrig = (int) ext.getMinY(); - windBoxWidth = (int) (witoPanewidth/3); - windBoxHeight = (int) ext.getHeight(); - windBoxYEnd = windBoxYOrig + windBoxHeight; - verticalWindXOrig = (int) (ext.getMinX()+witoPanewidth/3); - verticalWindYOrig = (int) ext.getMinY(); - verticalWindWidth = (int) (witoPanewidth/3); - verticalWindHeight = (int) ext.getHeight(); + windBoxXOrig = (float) (ext.getMinX()); + windBoxYOrig = (float) ext.getMinY(); + windBoxWidth = (witoPanewidth/9*5); + windBoxHeight = (float) ext.getHeight(); + //windBoxYEnd = windBoxYOrig + windBoxHeight; + verticalWindXOrig = (float) (ext.getMinX()+windBoxWidth); + verticalWindYOrig = (float) ext.getMinY(); + verticalWindWidth = (witoPanewidth/9*4); + verticalWindHeight = (float) ext.getHeight(); verticalWindYEnd = verticalWindYOrig + verticalWindHeight; //System.out.println("Wito: handle resize w="+witoPanewidth+ " h="+ witoPaneHeight); createAllWireFrameShapes(); @@ -549,6 +551,18 @@ public class NsharpWitoPaneResource extends NsharpAbstractPaneResource{ public void handleZooming() { createAllWireFrameShapes(); } - + @Override + protected void adjustFontSize(float canvasW, float canvasH) { + /* + super.adjustFontSize(canvasW, canvasH); + //make a bit bigger font10 size + float font10Size=10; + if(font10!=null){ + font10Size = font10.getFontSize()+1; + font10.dispose(); + } + font10 = target.initializeFont("Monospace", font10Size, null); + */ + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/natives/NsharpNativeConstants.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/natives/NsharpNativeConstants.java index a9849153f6..5e1f85078a 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/natives/NsharpNativeConstants.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/natives/NsharpNativeConstants.java @@ -11,6 +11,7 @@ * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 03/23/2010 229 Chin Chen Initial coding + * 7/2012 T. Lee Changed Rogash QPF to Rainfall Rate * * * @@ -339,8 +340,9 @@ public static final String OPC_MIXINGPRESSURE_MISSING = "Mixing Pressure * HEAVY RAINFALL data strings */ public static final String HEAVY_RAINFALL_STR = "\t\t\t\t HEAVY RAINFALL \r\n"; - public static final String HEAVY_ROGASH_LINE = "Rogash QPF = %.2f in\r\n"; - public static final String HEAVY_ROGASH_MISSING = "Rogash QPF = M \r\n"; + // change Rogash QPF to Rainfall Rate (TL) + public static final String HEAVY_ROGASH_LINE = "Rogash Rainfall Rate = %.2f in/hr\r\n"; + public static final String HEAVY_ROGASH_MISSING = "Rogash Rainfall Rate = M \r\n"; // use parcel type to retrieve parcel header string for display diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpConfigDialog.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpConfigDialog.java index 705d03d8d8..d4f34c2e30 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpConfigDialog.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpConfigDialog.java @@ -20,6 +20,8 @@ package gov.noaa.nws.ncep.ui.nsharp.palette; */ +import gov.noaa.nws.ncep.viz.common.ui.NmapCommon; + import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.window.IShellProvider; @@ -33,14 +35,17 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; +import com.raytheon.viz.ui.perspectives.VizPerspectiveListener; + public class NsharpConfigDialog extends Dialog { - private Button parameterBtn, dataDisplayBtn, timeLineBtn, stnBtn; + private Button parameterBtn, dataDisplayBtn, timeLineBtn, stnBtn, paneCfgBtn; private static NsharpConfigDialog thisDialog=null; private static NsharpParametersSelectionConfigDialog parameterSelDialog = null; private static NsharpDataDisplayConfigDialog dataDislpayDialog = null; private static NsharpTimeLineConfigDialog timelineDialog = null; private static NsharpStnConfigDialog stnDialog = null; + private static NsharpPaneConfigDialog paneCfgDialog = null; public NsharpConfigDialog(Shell parentShell) { super(parentShell); // TODO Auto-generated constructor stub @@ -73,15 +78,17 @@ public class NsharpConfigDialog extends Dialog { timeLineBtn.setEnabled( false ); dataDisplayBtn.setEnabled(false); stnBtn.setEnabled( false ); + paneCfgBtn.setEnabled( false ); parameterSelDialog.open(); dataDisplayBtn.setEnabled(true); timeLineBtn.setEnabled( true ); stnBtn.setEnabled( true ); + paneCfgBtn.setEnabled( true ); } } } ); dataDisplayBtn = new Button(parent, SWT.PUSH); - dataDisplayBtn.setText("Data Display"); + dataDisplayBtn.setText("Data Display Configuration"); dataDisplayBtn.setEnabled( true ); //lineBtn.setSize(btnWidth,pushbtnHeight); dataDisplayBtn.addListener( SWT.MouseUp, new Listener() { @@ -92,15 +99,17 @@ public class NsharpConfigDialog extends Dialog { timeLineBtn.setEnabled( false ); parameterBtn.setEnabled(false); stnBtn.setEnabled( false ); + paneCfgBtn.setEnabled( false ); dataDislpayDialog.open(); parameterBtn.setEnabled(true); timeLineBtn.setEnabled( true ); stnBtn.setEnabled( true ); + paneCfgBtn.setEnabled( true ); } } } ); timeLineBtn = new Button(parent, SWT.PUSH); - timeLineBtn.setText("Time Line"); + timeLineBtn.setText("Time Line Activation"); timeLineBtn.setEnabled( true ); //lineBtn.setSize(btnWidth,pushbtnHeight); timeLineBtn.addListener( SWT.MouseUp, new Listener() { @@ -111,15 +120,17 @@ public class NsharpConfigDialog extends Dialog { dataDisplayBtn.setEnabled(false); parameterBtn.setEnabled(false); stnBtn.setEnabled( false ); + paneCfgBtn.setEnabled( false ); timelineDialog.open(); parameterBtn.setEnabled(true); dataDisplayBtn.setEnabled(true); stnBtn.setEnabled( true ); + paneCfgBtn.setEnabled( true ); } } } ); stnBtn = new Button(parent, SWT.PUSH); - stnBtn.setText("Station"); + stnBtn.setText("Station Activation"); stnBtn.setEnabled( true ); //lineBtn.setSize(btnWidth,pushbtnHeight); stnBtn.addListener( SWT.MouseUp, new Listener() { @@ -130,10 +141,41 @@ public class NsharpConfigDialog extends Dialog { dataDisplayBtn.setEnabled(false); parameterBtn.setEnabled(false); timeLineBtn.setEnabled( false ); + paneCfgBtn.setEnabled( false ); stnDialog.open(); parameterBtn.setEnabled(true); dataDisplayBtn.setEnabled(true); timeLineBtn.setEnabled( true ); + paneCfgBtn.setEnabled( true ); + } + } + } ); + + paneCfgBtn = new Button(parent, SWT.PUSH); + paneCfgBtn.setText("Diaplay Pane Configuration"); + if( VizPerspectiveListener.getCurrentPerspectiveManager()!= null){ + //System.out.println("changeFrame: current perspective ="+VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId()); + if(VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId().equals(NmapCommon.NatlCntrsPerspectiveID)) + paneCfgBtn.setEnabled( true ); + else + paneCfgBtn.setEnabled( false ); + } + //lineBtn.setSize(btnWidth,pushbtnHeight); + paneCfgBtn.addListener( SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + paneCfgDialog = NsharpPaneConfigDialog.getInstance(shell); + if ( paneCfgDialog != null ) { + dataDisplayBtn.setEnabled(false); + parameterBtn.setEnabled(false); + timeLineBtn.setEnabled( false ); + stnBtn.setEnabled( false ); + paneCfgDialog.open(); + parameterBtn.setEnabled(true); + dataDisplayBtn.setEnabled(true); + timeLineBtn.setEnabled( true ); + stnBtn.setEnabled( true ); + } } } ); @@ -172,7 +214,7 @@ public class NsharpConfigDialog extends Dialog { protected void configureShell( Shell shell ) { super.configureShell( shell ); shell.setText( "Nsharp Configuration" ); - shell.setSize(250, 250); + shell.setSize(250, 300); } @Override public int open( ) { diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaletteWindow.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaletteWindow.java index 81cd9135c4..3978b2a0a9 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaletteWindow.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaletteWindow.java @@ -109,7 +109,7 @@ DisposeListener, IPartListener{ public NsharpPaletteWindow() { super(); instance = this; - //System.out.println("NsharpPaletteWindow condtructed!!"); + //System.out.println("palette NsharpPaletteWindow constructed!!"); printHandle = NsharpPrintHandle.getPrintHandle(); shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaneConfigDialog.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaneConfigDialog.java new file mode 100644 index 0000000000..1eebdcf1db --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/palette/NsharpPaneConfigDialog.java @@ -0,0 +1,217 @@ +package gov.noaa.nws.ncep.ui.nsharp.palette; +/** + * + * gov.noaa.nws.ncep.ui.nsharp.palette.NsharpPaneConfigDialog + * + * + * This code has been developed by the NCEP-SIB for use in the AWIPS2 system. + * + *
    + * SOFTWARE HISTORY
    + * 
    + * Date         Ticket#    	Engineer    Description
    + * -------		------- 	-------- 	-----------
    + * 06/28/2012	229			Chin Chen	Initial coding
    + *
    + * 
    + * + * @author Chin Chen + * @version 1.0 + */ + +import gov.noaa.nws.ncep.ui.nsharp.NsharpConfigManager; +import gov.noaa.nws.ncep.ui.nsharp.NsharpConfigStore; +import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; +import gov.noaa.nws.ncep.ui.nsharp.NsharpGraphProperty; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.raytheon.uf.viz.core.exception.VizException; + +public class NsharpPaneConfigDialog extends Dialog { + private static NsharpPaneConfigDialog thisDialog=null; + private NsharpConfigStore configStore=null; + private NsharpConfigManager mgr; + private int btnWidth = 300; + private int btnHeight = 20; + private int labelGap = 20; + private int btnGapX = 5; + private int btnGapY = 5; + private Combo paneCfgCombo; + private String paneConfigurationName; + private MessageBox mb ; + private void updateCfgStore(){ + if(configStore != null){ + configStore.getGraphProperty().setPaneConfigurationName(paneConfigurationName); + } + } + + public static NsharpPaneConfigDialog getInstance( Shell parShell){ + + if ( thisDialog == null ){ + try { + thisDialog = new NsharpPaneConfigDialog( parShell ); + + } catch (VizException e) { + e.printStackTrace(); + } + + } + + return thisDialog; + + } + + public static NsharpPaneConfigDialog getAccess() { + return thisDialog; + } + + public NsharpPaneConfigDialog(Shell parentShell) throws VizException { + super(parentShell); + thisDialog = this; + mgr =NsharpConfigManager.getInstance(); + configStore = mgr.retrieveNsharpConfigStoreFromFs(); + if(configStore != null){ + paneConfigurationName = configStore.getGraphProperty().getPaneConfigurationName(); + } + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + mb = new MessageBox(shell, SWT.ICON_WARNING + | SWT.OK ); + mb.setMessage( "New pane configuration will take effect after Cave restarted!"); + + } + private void createDialogContents(Composite parent){ + + Group btnGp = new Group(parent, SWT.SHADOW_ETCHED_IN | SWT.NO_RADIO_GROUP); + Label paneCfgComboLbl = new Label(btnGp, SWT.BORDER ); + paneCfgComboLbl.setText("Pane Configuration Selection :"); + paneCfgComboLbl.setBounds(btnGp.getBounds().x+ btnGapX, btnGp.getBounds().y + labelGap, btnWidth,btnHeight); + paneCfgCombo = new Combo(btnGp, SWT.NULL); + paneCfgCombo.setBounds(btnGp.getBounds().x+ btnGapX, paneCfgComboLbl.getBounds().y + paneCfgComboLbl.getBounds().height+ btnGapY,btnWidth,btnHeight); + int selectIndex=0; + configStore = mgr.retrieveNsharpConfigStoreFromFs(); + if(configStore != null){ + paneConfigurationName = configStore.getGraphProperty().getPaneConfigurationName(); + } + for(int i=0; i" : paneCfgCombo.getItem(paneCfgCombo.getSelectionIndex())) + ", text content in the text field: " + paneCfgCombo.getText()); + String text = paneCfgCombo.getText(); + if(paneCfgCombo.indexOf(text) < 0) { // Not in the list yet. + paneCfgCombo.add(text); + // Re-sort + String[] items = paneCfgCombo.getItems(); + paneCfgCombo.setItems(items); + } + } + }); + + + } + + @Override + public void createButtonsForButtonBar(Composite parent) { + Button saveBtn = createButton(parent, IDialogConstants.INTERNAL_ID, + "Save",false); + saveBtn.addListener( SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + try { + //save to xml + paneConfigurationName = paneCfgCombo.getItem(paneCfgCombo.getSelectionIndex()); + updateCfgStore(); + mgr.saveConfigStoreToFs(configStore); + mb.open(); + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + } + } ); + + Button canBtn = createButton(parent, IDialogConstants.CLOSE_ID, + IDialogConstants.CLOSE_LABEL, false); + canBtn.addListener( SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + //System.out.println("close listener is called"); + close(); + } + } ); + } + + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) + */ + @Override + protected void configureShell( Shell shell ) { + super.configureShell( shell ); + shell.setText( "Nsharp Pane Configuration Selection" ); + + } + @Override + public Control createDialogArea(Composite parent) { + Composite top; + top = (Composite) super.createDialogArea(parent); + + // Create the main layout for the shell. + GridLayout mainLayout = new GridLayout(1, false); + mainLayout.marginHeight = 3; + mainLayout.marginWidth = 3; + top.setLayout(mainLayout); + + // Initialize all of the menus, controls, and layouts + createDialogContents(top); + + return top; + } + + + @Override + public int open( ) { + if ( this.getShell() == null ){ + this.create(); + } + this.getShell().setLocation(this.getShell().getParent().getLocation().x+1100, + this.getShell().getParent().getLocation().y+200); + return super.open(); + + } + @Override + public boolean close() { + paneCfgCombo.dispose(); + paneCfgCombo=null; + return (super.close()); + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/NsharpSkewTDescriptor.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/NsharpSkewTDescriptor.java index c6e4892a10..5b5afa7388 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/NsharpSkewTDescriptor.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/NsharpSkewTDescriptor.java @@ -47,6 +47,7 @@ public class NsharpSkewTDescriptor extends GraphDescriptor { public void changeFrame(FrameChangeOperation operation, FrameChangeMode mode) { synchronized (this) { //From stepping commands + //System.out.println("changeFrame"); NsharpSkewTResource skewRsc = getSkewtResource(); if( VizPerspectiveListener.getCurrentPerspectiveManager()!= null){ //System.out.println("current perspective ="+VizPerspectiveListener.getCurrentPerspectiveManager().getPerspectiveId()); @@ -67,6 +68,7 @@ public class NsharpSkewTDescriptor extends GraphDescriptor { @Override public void checkDrawTime(LoopProperties loopProperties) { super.checkDrawTime(loopProperties); + //System.out.println("checkDrawTime"); //handleDataTimeIndex is no longer available since 11.5 //called from DrawCoordinatedPane //Chin: 11.11 note: it is now called from NsharpSkewTDisplay.paint() when animation is started. diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/bkgd/NsharpAbstractBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/bkgd/NsharpAbstractBackground.java index c2829e9977..c065f95905 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/bkgd/NsharpAbstractBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/bkgd/NsharpAbstractBackground.java @@ -47,6 +47,8 @@ public abstract class NsharpAbstractBackground implements IRenderable { if(smallFont!=null){ smallFont.dispose(); } + if(target==null) + return; smallFont = target.initializeFont( target.getDefaultFont().getFontName(), currentFontSize, null); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/rsc/NsharpSkewTResource.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/rsc/NsharpSkewTResource.java index 67859100b1..061484d3f5 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/rsc/NsharpSkewTResource.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/skewt/rsc/NsharpSkewTResource.java @@ -4016,7 +4016,9 @@ public class NsharpSkewTResource extends AbstractVizResource + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------- ------- -------- ----------- + * 06/28/2012 229 Chin Chen Initial coding + * + * + * + * @author Chin Chen + * @version 1.0 + */ + +import gov.noaa.nws.ncep.ui.nsharp.NsharpConfigManager; +import gov.noaa.nws.ncep.ui.nsharp.NsharpConfigStore; +import gov.noaa.nws.ncep.ui.nsharp.NsharpConstants; +import gov.noaa.nws.ncep.ui.nsharp.display.NsharpEditor; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.raytheon.uf.viz.core.exception.VizException; + +public class NsharpPaneConfigDialog extends Dialog { + private static NsharpPaneConfigDialog thisDialog=null; + private NsharpConfigStore configStore=null; + private NsharpConfigManager mgr; + private int btnWidth = 300; + private int btnHeight = 20; + private int labelGap = 20; + private int btnGapX = 5; + private int btnGapY = 5; + private Combo paneCfgCombo; + private String paneConfigurationName; + private MessageBox mb ; + private void updateCfgStore(){ + if(configStore != null){ + configStore.getGraphProperty().setPaneConfigurationName(paneConfigurationName); + } + } + + public static NsharpPaneConfigDialog getInstance( Shell parShell){ + + if ( thisDialog == null ){ + try { + thisDialog = new NsharpPaneConfigDialog( parShell ); + + } catch (VizException e) { + e.printStackTrace(); + } + + } + + return thisDialog; + + } + + public static NsharpPaneConfigDialog getAccess() { + return thisDialog; + } + + public NsharpPaneConfigDialog(Shell parentShell) throws VizException { + super(parentShell); + thisDialog = this; + mgr =NsharpConfigManager.getInstance(); + configStore = mgr.retrieveNsharpConfigStoreFromFs(); + if(configStore != null){ + paneConfigurationName = configStore.getGraphProperty().getPaneConfigurationName(); + } + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + mb = new MessageBox(shell, SWT.ICON_WARNING + | SWT.OK ); + mb.setMessage( "Switching configuration from/to Legacy to/from all other configurations will only take effect after SAVE configuration, CLOSE Nsharp (editor and control view) and RESTART Nsharp!"); + + } + private void createDialogContents(Composite parent){ + + Group btnGp = new Group(parent, SWT.SHADOW_ETCHED_IN | SWT.NO_RADIO_GROUP); + Label paneCfgComboLbl = new Label(btnGp, SWT.BORDER ); + paneCfgComboLbl.setText("Pane Configuration Selection :"); + paneCfgComboLbl.setBounds(btnGp.getBounds().x+ btnGapX, btnGp.getBounds().y + labelGap, btnWidth,btnHeight); + paneCfgCombo = new Combo(btnGp, SWT.NULL); + paneCfgCombo.setBounds(btnGp.getBounds().x+ btnGapX, paneCfgComboLbl.getBounds().y + paneCfgComboLbl.getBounds().height+ btnGapY,btnWidth,btnHeight); + int selectIndex=0; + configStore = mgr.retrieveNsharpConfigStoreFromFs(); + if(configStore != null){ + paneConfigurationName = configStore.getGraphProperty().getPaneConfigurationName(); + } + for(int i=0; i" : paneCfgCombo.getItem(paneCfgCombo.getSelectionIndex())) + ", text content in the text field: " + paneCfgCombo.getText()); + String text = paneCfgCombo.getText(); + if(paneCfgCombo.indexOf(text) < 0) { // Not in the list yet. + paneCfgCombo.add(text); + // Re-sort + String[] items = paneCfgCombo.getItems(); + paneCfgCombo.setItems(items); + } + } + }); + + + } + + @Override + public void createButtonsForButtonBar(Composite parent) { + // create OK button but using Apply label for applying user entered data + //Chin note: when "apply" button is selected or Return key is entered, + // okPressed() will be called. So, handle event at one place, ie.e at okPressed(). + createButton(parent, IDialogConstants.OK_ID, + "Apply", + true); + + Button saveBtn = createButton(parent, IDialogConstants.INTERNAL_ID, + "Save",false); + saveBtn.addListener( SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + try { + //save to xml + paneConfigurationName = paneCfgCombo.getItem(paneCfgCombo.getSelectionIndex()); + updateCfgStore(); + mgr.saveConfigStoreToFs(configStore); + //mb.open(); + + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + } + } ); + + Button canBtn = createButton(parent, IDialogConstants.CLOSE_ID, + IDialogConstants.CLOSE_LABEL, false); + canBtn.addListener( SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + //System.out.println("close listener is called"); + close(); + } + } ); + } + + @Override + public void okPressed() { + //"Enter" key is pressed, or "Apply" button is pressed. + //Chin: handle user entered data and apply its changes. + //System.out.println("CR is pressed"); + paneConfigurationName = paneCfgCombo.getItem(paneCfgCombo.getSelectionIndex()); + if(paneConfigurationName.equals(NsharpConstants.PANE_LEGACY_CFG_STR)){ + mb.open(); + } + else{ + updateCfgStore(); + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + if(editor!=null) + editor.restartEditor(paneConfigurationName); + } + setReturnCode(OK); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) + */ + @Override + protected void configureShell( Shell shell ) { + super.configureShell( shell ); + shell.setText( "Nsharp Pane Configuration Selection" ); + + } + @Override + public Control createDialogArea(Composite parent) { + Composite top; + top = (Composite) super.createDialogArea(parent); + + // Create the main layout for the shell. + GridLayout mainLayout = new GridLayout(1, false); + mainLayout.marginHeight = 3; + mainLayout.marginWidth = 3; + top.setLayout(mainLayout); + + // Initialize all of the menus, controls, and layouts + createDialogContents(top); + + return top; + } + + + @Override + public int open( ) { + if ( this.getShell() == null ){ + this.create(); + } + this.getShell().setLocation(this.getShell().getParent().getLocation().x+1100, + this.getShell().getParent().getLocation().y+200); + return super.open(); + + } + @Override + public boolean close() { + paneCfgCombo.dispose(); + paneCfgCombo=null; + return (super.close()); + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpParametersSelectionConfigDialog.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpParametersSelectionConfigDialog.java index ce663e399b..367e51672b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpParametersSelectionConfigDialog.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpParametersSelectionConfigDialog.java @@ -635,7 +635,7 @@ public class NsharpParametersSelectionConfigDialog extends Dialog { // create OK button but using Apply label for applying user entered data //Chin note: when "apply" button is selected or Return key is entered, // okPressed() will be called. So, handle event at one place, ie.e at okPressed(). - Button appBtn = createButton(parent, IDialogConstants.OK_ID, + createButton(parent, IDialogConstants.OK_ID, "Apply", true); diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpSaveHandle.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpSaveHandle.java index b6cd54ac7f..0b23a41f82 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpSaveHandle.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpSaveHandle.java @@ -56,8 +56,6 @@ public class NsharpSaveHandle { dlg.setFilterExtensions(filterExt); if( rsc.getPickedStnInfoStr()!= null && rsc.getPickedStnInfoStr().length() >0){ StringTokenizer st = new StringTokenizer(rsc.getPickedStnInfoStr(), " \t\n\r\f/"); - int i =0; - if(st.hasMoreTokens()== true){ fileName = ""; while (st.hasMoreTokens()) { diff --git a/pythonPackages/pupynere/PKG-INFO b/pythonPackages/pupynere/PKG-INFO index c02a56a8b2..797ff47f15 100644 --- a/pythonPackages/pupynere/PKG-INFO +++ b/pythonPackages/pupynere/PKG-INFO @@ -1,22 +1,32 @@ Metadata-Version: 1.0 Name: pupynere -Version: 1.0.13 +Version: 1.0.15 Summary: NetCDF file reader and writer. -Home-page: http://dealmeida.net/2008/07/14/pupynere +Home-page: http://bitbucket.org/robertodealmeida/pupynere/ Author: Roberto De Almeida Author-email: roberto@dealmeida.net License: MIT -Download-URL: http://cheeseshop.python.org/packages/source/p/pupynere/pupynere-1.0.13.tar.gz +Download-URL: http://cheeseshop.python.org/packages/source/p/pupynere/pupynere-1.0.15.tar.gz Description: Pupynere is a Python module for reading and writing NetCDF files, using the same API as Scientific.IO.NetCDF and pynetcdf. It depends only on Numpy, so you don't need to have the NetCDF library installed. Changelog: + 1.0.15 + Added fix for empty attributes. + + 1.0.14 + Added support for Unicode attributes. + + 1.0.13 + Fixed bug when reading character variables without mmap. + 1.0.12 + Fixed bug. 1.0.11 - Fixed bug + Fixed bug. 1.0.10 Fixed bug when packing integer attributes in 64-bit systems. diff --git a/pythonPackages/pupynere/pupynere.egg-info/PKG-INFO b/pythonPackages/pupynere/pupynere.egg-info/PKG-INFO index c02a56a8b2..797ff47f15 100644 --- a/pythonPackages/pupynere/pupynere.egg-info/PKG-INFO +++ b/pythonPackages/pupynere/pupynere.egg-info/PKG-INFO @@ -1,22 +1,32 @@ Metadata-Version: 1.0 Name: pupynere -Version: 1.0.13 +Version: 1.0.15 Summary: NetCDF file reader and writer. -Home-page: http://dealmeida.net/2008/07/14/pupynere +Home-page: http://bitbucket.org/robertodealmeida/pupynere/ Author: Roberto De Almeida Author-email: roberto@dealmeida.net License: MIT -Download-URL: http://cheeseshop.python.org/packages/source/p/pupynere/pupynere-1.0.13.tar.gz +Download-URL: http://cheeseshop.python.org/packages/source/p/pupynere/pupynere-1.0.15.tar.gz Description: Pupynere is a Python module for reading and writing NetCDF files, using the same API as Scientific.IO.NetCDF and pynetcdf. It depends only on Numpy, so you don't need to have the NetCDF library installed. Changelog: + 1.0.15 + Added fix for empty attributes. + + 1.0.14 + Added support for Unicode attributes. + + 1.0.13 + Fixed bug when reading character variables without mmap. + 1.0.12 + Fixed bug. 1.0.11 - Fixed bug + Fixed bug. 1.0.10 Fixed bug when packing integer attributes in 64-bit systems. diff --git a/pythonPackages/pupynere/pupynere.egg-info/SOURCES.txt b/pythonPackages/pupynere/pupynere.egg-info/SOURCES.txt index 3c25249ada..f661feccf4 100644 --- a/pythonPackages/pupynere/pupynere.egg-info/SOURCES.txt +++ b/pythonPackages/pupynere/pupynere.egg-info/SOURCES.txt @@ -1,5 +1,4 @@ pupynere.py -setup.cfg setup.py pupynere.egg-info/PKG-INFO pupynere.egg-info/SOURCES.txt diff --git a/pythonPackages/pupynere/pupynere.py b/pythonPackages/pupynere/pupynere.py index d9d4c25a5e..af6e710076 100644 --- a/pythonPackages/pupynere/pupynere.py +++ b/pythonPackages/pupynere/pupynere.py @@ -1,4 +1,5 @@ -""" +# -*- coding: utf-8 -*- +u""" NetCDF reader/writer module. This module implements the Scientific.IO.NetCDF API to read and create @@ -43,15 +44,20 @@ are automatically stored in the ``_attributes`` attribute by overloading ``obj.__dict__['key'] = value``, instead of simply ``obj.key = value``; otherwise the key would be inserted into userspace attributes. +Unicode attribute values are allowed (although not required). This deals +with the common use case of non-ASCII units, placenames, etc. Attribute +values are encoded via UTF-8, as required by NetCDF and udunits2. + To create a NetCDF file:: >>> import time >>> f = netcdf_file('simple.nc', 'w') >>> f.history = 'Created for a test' + >>> f.location = u'北京' >>> f.createDimension('time', 10) >>> time = f.createVariable('time', 'i', ('time',)) >>> time[:] = range(10) - >>> time.units = 'days since 2008-01-01' + >>> time.units = u'µs since 2008-01-01' >>> f.close() To read the NetCDF file we just created:: @@ -59,9 +65,11 @@ To read the NetCDF file we just created:: >>> f = netcdf_file('simple.nc', 'r') >>> print f.history Created for a test + >>> print f.location + 北京 >>> time = f.variables['time'] >>> print time.units - days since 2008-01-01 + µs since 2008-01-01 >>> print time.shape (10,) >>> print time[-1] @@ -344,8 +352,12 @@ class netcdf_file(object): ] try: sample = values[0] - except TypeError: + except (IndexError, TypeError): sample = values + if isinstance(sample, unicode): + assert isinstance(values, unicode), type(values) + ## NetCDF requires that text be encoded via UTF-8 + values = values.encode('utf-8') for class_, nc_type in types: if isinstance(sample, class_): break @@ -522,7 +534,8 @@ class netcdf_file(object): values = fromstring(values, dtype='>%s%d' % (typecode, size)) if values.shape == (1,): values = values[0] else: - values = values.rstrip('\x00') + ## text values are encoded via UTF-8, per NetCDF standard + values = values.rstrip('\x00').decode('utf-8') return values def _pack_begin(self, begin): diff --git a/pythonPackages/pupynere/setup.cfg b/pythonPackages/pupynere/setup.cfg index 53a09d35b2..861a9f5542 100644 --- a/pythonPackages/pupynere/setup.cfg +++ b/pythonPackages/pupynere/setup.cfg @@ -3,8 +3,3 @@ tag_build = tag_date = 0 tag_svn_revision = 0 -[nosetests] -verbosity = 2 -doctest-extension = txt -with-doctest = 1 - diff --git a/pythonPackages/pupynere/setup.py b/pythonPackages/pupynere/setup.py index cf12fd4a34..ee2e7d5f38 100644 --- a/pythonPackages/pupynere/setup.py +++ b/pythonPackages/pupynere/setup.py @@ -15,7 +15,7 @@ Topic :: Scientific/Engineering Topic :: Software Development :: Libraries :: Python Modules """ -version = '1.0.13' +version = '1.0.15' setup( name='pupynere', @@ -28,10 +28,20 @@ on Numpy, so you don't need to have the NetCDF library installed. Changelog: +1.0.15 + Added fix for empty attributes. + +1.0.14 + Added support for Unicode attributes. + +1.0.13 + Fixed bug when reading character variables without mmap. + 1.0.12 + Fixed bug. 1.0.11 - Fixed bug + Fixed bug. 1.0.10 Fixed bug when packing integer attributes in 64-bit systems. @@ -78,7 +88,7 @@ Changelog: keywords='netcdf data array math', author='Roberto De Almeida', author_email='roberto@dealmeida.net', - url='http://dealmeida.net/2008/07/14/pupynere', + url='http://bitbucket.org/robertodealmeida/pupynere/', download_url = "http://cheeseshop.python.org/packages/source/p/pupynere/pupynere-%s.tar.gz" % version, license='MIT', py_modules=['pupynere'], diff --git a/rpms/awips2.64/Installer.h5py/component.spec b/rpms/awips2.64/Installer.h5py/component.spec index 94bf589897..601e5df45b 100644 --- a/rpms/awips2.64/Installer.h5py/component.spec +++ b/rpms/awips2.64/Installer.h5py/component.spec @@ -88,6 +88,14 @@ popd > /dev/null rm -rf ${HDF5_PATH} rm -rf %{_build_root}/build-python +# patch: copy the szip libraries into the installation. +szip_lib=%{_baseline_workspace}/Installer.rpm/awips2.64/Installer.h5py/lib +cp -vP ${szip_lib}/* \ + %{_build_root}/awips2/python/lib +if [ $? -ne 0 ]; then + exit 1 +fi + %pre %post @@ -101,5 +109,5 @@ rm -rf %{_build_root} %files %defattr(644,awips,fxalpha,755) -%dir /awips2/python/lib/python2.7/site-packages -/awips2/python/lib/python2.7/site-packages/* \ No newline at end of file +%dir /awips2/python/lib +/awips2/python/lib/* diff --git a/rpms/awips2.64/Installer.h5py/lib/libsz.so b/rpms/awips2.64/Installer.h5py/lib/libsz.so new file mode 100644 index 0000000000..4dabb477e4 Binary files /dev/null and b/rpms/awips2.64/Installer.h5py/lib/libsz.so differ diff --git a/rpms/awips2.64/Installer.h5py/lib/libsz.so.2 b/rpms/awips2.64/Installer.h5py/lib/libsz.so.2 new file mode 100644 index 0000000000..4dabb477e4 Binary files /dev/null and b/rpms/awips2.64/Installer.h5py/lib/libsz.so.2 differ diff --git a/rpms/awips2.64/Installer.h5py/lib/libsz.so.2.0.0 b/rpms/awips2.64/Installer.h5py/lib/libsz.so.2.0.0 new file mode 100644 index 0000000000..4dabb477e4 Binary files /dev/null and b/rpms/awips2.64/Installer.h5py/lib/libsz.so.2.0.0 differ diff --git a/rpms/awips2.64/Installer.python/component.spec b/rpms/awips2.64/Installer.python/component.spec index 36e53f46bc..cd745ef68d 100644 --- a/rpms/awips2.64/Installer.python/component.spec +++ b/rpms/awips2.64/Installer.python/component.spec @@ -6,7 +6,7 @@ Name: awips2-python Summary: AWIPS II Python Distribution - 64 Bit Version: 2.7.1 -Release: 1 +Release: 3 Group: AWIPSII BuildRoot: %{_build_root} URL: N/A @@ -174,7 +174,7 @@ fi popd > /dev/null PYTHON_SRC_DIR="${PYTHON_PROJECT_DIR}/src" -LAPACK_TAR="lapack-3.0.tgz" +LAPACK_TAR="lapack-3.1.1.tgz" LAPACK_PATCH="lapack.patch1" # Copy the LAPACK tar file and patch to our build directory. @@ -198,16 +198,20 @@ if [ ${RC} -ne 0 ]; then exit 1 fi rm -fv ${LAPACK_TAR} -if [ ! -d LAPACK ]; then - file LAPACK +if [ ! -d lapack-3.1.1 ]; then + file lapack-3.1.1 exit 1 fi -cd LAPACK +cd lapack-3.1.1 patch -p1 -i ../${LAPACK_PATCH} RC=$? if [ ${RC} -ne 0 ]; then exit 1 fi +mv make.inc.example make.inc +if [ $? -ne 0 ]; then + exit 1 +fi make blaslib RC=$? if [ ${RC} -ne 0 ]; then @@ -264,4 +268,4 @@ rm -rf %{_build_root} %dir /awips2/python/include /awips2/python/include/* %dir /awips2/python/bin -/awips2/python/bin/* \ No newline at end of file +/awips2/python/bin/* diff --git a/rpms/awips2.64/Installer.python/src/lapack-3.1.1.tgz b/rpms/awips2.64/Installer.python/src/lapack-3.1.1.tgz new file mode 100644 index 0000000000..ef61a14f28 Binary files /dev/null and b/rpms/awips2.64/Installer.python/src/lapack-3.1.1.tgz differ diff --git a/rpms/awips2.64/Installer.python/src/lapack.patch1 b/rpms/awips2.64/Installer.python/src/lapack.patch1 index c047033609..a16532a9a7 100644 --- a/rpms/awips2.64/Installer.python/src/lapack.patch1 +++ b/rpms/awips2.64/Installer.python/src/lapack.patch1 @@ -1,125 +1,155 @@ -diff -cr LAPACK/BLAS/SRC/Makefile LAPACK.patched/BLAS/SRC/Makefile -*** LAPACK/BLAS/SRC/Makefile 1999-11-04 13:23:14.000000000 -0600 ---- LAPACK.patched/BLAS/SRC/Makefile 2011-07-26 17:51:27.000000000 -0500 +diff -crB lapack-3.1.1-a/BLAS/SRC/Makefile lapack-3.1.1-b/BLAS/SRC/Makefile +*** lapack-3.1.1-a/BLAS/SRC/Makefile 2007-02-20 17:35:40.000000000 -0600 +--- lapack-3.1.1-b/BLAS/SRC/Makefile 2012-07-19 10:27:03.000000000 -0500 *************** -*** 50,56 **** +*** 55,61 **** # ####################################################################### -! all: single double complex complex16 +! all: $(BLASLIB) #--------------------------------------------------------- # Comment out the next 6 definitions if you already have ---- 50,56 ---- +--- 55,61 ---- # ####################################################################### -! all: single double complex complex16 libblas.so +! all: $(BLASLIB) libblas.so #--------------------------------------------------------- # Comment out the next 6 definitions if you already have *************** -*** 149,154 **** ---- 149,160 ---- - $(ALLBLAS) $(ZBLAS2) $(ZBLAS3) - $(RANLIB) $(BLASLIB) +*** 137,146 **** +--- 137,154 ---- + $(CBLAS1) $(CB1AUX) $(CBLAS2) $(CBLAS3) $(ZBLAS1) $(ZB1AUX) \ + $(ZBLAS2) $(ZBLAS3) $(ALLBLAS) -+ libblas.so: $(SBLAS1) $(CBLAS1) $(DBLAS1) $(ZBLAS1) \ -+ $(CB1AUX) $(ZB1AUX) $(ALLBLAS) $(SBLAS2) \ -+ $(CBLAS2) $(DBLAS2) $(ZBLAS2) $(SBLAS3) \ -+ $(CBLAS3) $(DBLAS3) $(ZBLAS3) -+ cc -shared -Wl,-soname,$@ -lgfortran -lg2c -o $@ *.o ++ # Prevent linking code twice ++ SHAREDOBJ=$(SBLAS1) $(SBLAS2) $(SBLAS3) $(DBLAS1) $(DBLAS2) $(DBLAS3) \ ++ $(CBLAS1) $(CBLAS2) $(CBLAS3) $(ZBLAS1) $(ZBLAS2) $(ZBLAS3) \ ++ $(ALLBLAS) + - FRC: - @FRC=$(FRC) + $(BLASLIB): $(ALLOBJ) + $(ARCH) $(ARCHFLAGS) $@ $(ALLOBJ) + $(RANLIB) $@ -diff -cr LAPACK/make.inc LAPACK.patched/make.inc -*** LAPACK/make.inc 1999-11-04 13:23:14.000000000 -0600 ---- LAPACK.patched/make.inc 2011-07-26 17:05:59.000000000 -0500 ++ libblas.so: $(SHAREDOBJ) ++ cc -shared -Wl,-soname,$@ -lgfortran -lg2c -o $@ $(SHAREDOBJ) ++ + single: $(SBLAS1) $(ALLBLAS) $(SBLAS2) $(SBLAS3) + $(ARCH) $(ARCHFLAGS) $(BLASLIB) $(SBLAS1) $(ALLBLAS) \ + $(SBLAS2) $(SBLAS3) *************** -*** 8,14 **** - # - # The machine (platform) identifier to append to the library names - # -! PLAT = _SUN4SOL2 - # - # Modify the FORTRAN and OPTS definitions to refer to the - # compiler and desired compiler options for your machine. NOOPT ---- 8,14 ---- - # - # The machine (platform) identifier to append to the library names - # -! PLAT = - # - # Modify the FORTRAN and OPTS definitions to refer to the - # compiler and desired compiler options for your machine. NOOPT +*** 166,171 **** +--- 174,180 ---- + + clean: + rm -f *.o ++ rm -f *.so + + .f.o: + $(FORTRAN) $(OPTS) -c $< -o $@ +diff -crB lapack-3.1.1-a/INSTALL/Makefile lapack-3.1.1-b/INSTALL/Makefile +*** lapack-3.1.1-a/INSTALL/Makefile 2007-02-23 14:07:35.000000000 -0600 +--- lapack-3.1.1-b/INSTALL/Makefile 2012-07-19 10:27:25.000000000 -0500 *************** -*** 16,31 **** +*** 29,35 **** + clean: + rm -f *.o + +! slamch.o: slamch.f ; $(FORTRAN) $(NOOPT) -c $< -o $@ +! dlamch.o: dlamch.f ; $(FORTRAN) $(NOOPT) -c $< -o $@ + + .f.o: ; $(FORTRAN) $(OPTS) -c $< -o $@ +--- 29,35 ---- + clean: + rm -f *.o + +! slamch.o: slamch.f ; $(FORTRAN) $(NOOPT) -fPIC -c $< -o $@ +! dlamch.o: dlamch.f ; $(FORTRAN) $(NOOPT) -fPIC -c $< -o $@ + + .f.o: ; $(FORTRAN) $(OPTS) -c $< -o $@ +diff -crB lapack-3.1.1-a/make.inc.example lapack-3.1.1-b/make.inc.example +*** lapack-3.1.1-a/make.inc.example 2007-02-23 14:07:35.000000000 -0600 +--- lapack-3.1.1-b/make.inc.example 2012-07-19 10:33:06.000000000 -0500 +*************** +*** 18,28 **** # selected. Define LOADER and LOADOPTS to refer to the loader and # desired load options for your machine. # -! FORTRAN = f77 - #OPTS = -O4 -u -f -mt - #OPTS = -u -f -dalign -native -xO5 -xarch=v8plusa -! OPTS = -u -f -dalign -native -xO5 -xarch=v8plusa +! FORTRAN = g77 +! OPTS = -funroll-all-loops -O3 DRVOPTS = $(OPTS) -! NOOPT = -u -f - #NOOPT = -u -f -mt -! LOADER = f77 - #LOADOPTS = -mt -! LOADOPTS = -f -dalign -native -xO5 -xarch=v8plusa + NOOPT = +! LOADER = g77 + LOADOPTS = # - # The archiver and the flag(s) to use when building archive (library) - # If you system has no ranlib, set RANLIB = echo. ---- 16,33 ---- + # Timer for the SECOND and DSECND routines +--- 18,28 ---- # selected. Define LOADER and LOADOPTS to refer to the loader and # desired load options for your machine. # ! FORTRAN = gfortran - #OPTS = -O4 -u -f -mt - #OPTS = -u -f -dalign -native -xO5 -xarch=v8plusa -! #OPTS = -u -f -dalign -native -xO5 -xarch=v8plusa -! OPTS = -funroll-all-loops -O3 -fPIC +! OPTS = -funroll-all-loops -O3 -fPIC DRVOPTS = $(OPTS) -! #NOOPT = -u -f - #NOOPT = -u -f -mt -! NOOPT = -fPIC + NOOPT = ! LOADER = gfortran - #LOADOPTS = -mt -! #LOADOPTS = -f -dalign -native -xO5 -xarch=v8plusa + LOADOPTS = # - # The archiver and the flag(s) to use when building archive (library) - # If you system has no ranlib, set RANLIB = echo. -diff -cr LAPACK/SRC/Makefile LAPACK.patched/SRC/Makefile -*** LAPACK/SRC/Makefile 1999-11-04 13:26:09.000000000 -0600 ---- LAPACK.patched/SRC/Makefile 2011-07-26 17:53:28.000000000 -0500 + # Timer for the SECOND and DSECND routines +diff -crB lapack-3.1.1-a/SRC/Makefile lapack-3.1.1-b/SRC/Makefile +*** lapack-3.1.1-a/SRC/Makefile 2007-02-23 15:33:05.000000000 -0600 +--- lapack-3.1.1-b/SRC/Makefile 2012-07-19 10:31:27.000000000 -0500 *************** -*** 277,283 **** - zunmtr.o zupgtr.o \ - zupmtr.o izmax1.o dzsum1.o +*** 288,294 **** + zupmtr.o izmax1.o dzsum1.o zstemr.o \ + zcgesv.o zlag2c.o clag2z.o -! all: single complex double complex16 +! all: ../$(LAPACKLIB) - single: $(SLASRC) $(ALLAUX) $(SCLAUX) - $(ARCH) $(ARCHFLAGS) ../$(LAPACKLIB) $(SLASRC) $(ALLAUX) \ ---- 277,283 ---- - zunmtr.o zupgtr.o \ - zupmtr.o izmax1.o dzsum1.o + ALLOBJ=$(SLASRC) $(DLASRC) $(CLASRC) $(ZLASRC) $(SCLAUX) $(DZLAUX) \ + $(ALLAUX) +--- 288,294 ---- + zupmtr.o izmax1.o dzsum1.o zstemr.o \ + zcgesv.o zlag2c.o clag2z.o -! all: single complex double complex16 liblapack.so +! all: ../$(LAPACKLIB) liblapack.so - single: $(SLASRC) $(ALLAUX) $(SCLAUX) - $(ARCH) $(ARCHFLAGS) ../$(LAPACKLIB) $(SLASRC) $(ALLAUX) \ + ALLOBJ=$(SLASRC) $(DLASRC) $(CLASRC) $(ZLASRC) $(SCLAUX) $(DZLAUX) \ + $(ALLAUX) *************** -*** 299,304 **** ---- 299,308 ---- - $(DZLAUX) - $(RANLIB) ../$(LAPACKLIB) +*** 297,302 **** +--- 297,305 ---- + $(ARCH) $(ARCHFLAGS) $@ $(ALLOBJ) + $(RANLIB) $@ -+ liblapack.so: $(ALLAUX) $(SCLAUX) $(DZLAUX) $(SLASRC) \ -+ $(CLASRC) $(DLASRC) $(ZLASRC) -+ cc -shared -Wl,-soname,$@ -L../BLAS/SRC -lgfortran -lblas -o $@ *.o ++ liblapack.so: $(ALLOBJ) ++ cc -shared -Wl,-soname,$@ -lgfortran -lg2c -o $@ $(ALLOBJ) + - $(ALLAUX): $(FRC) - $(SCLAUX): $(FRC) - $(DZLAUX): $(FRC) + single: $(SLASRC) $(ALLAUX) $(SCLAUX) + $(ARCH) $(ARCHFLAGS) ../$(LAPACKLIB) $(SLASRC) $(ALLAUX) \ + $(SCLAUX) +*************** +*** 330,339 **** + + clean: + rm -f *.o + + .f.o: + $(FORTRAN) $(OPTS) -c $< -o $@ + +! slaruv.o: slaruv.f ; $(FORTRAN) $(NOOPT) -c $< -o $@ +! dlaruv.o: dlaruv.f ; $(FORTRAN) $(NOOPT) -c $< -o $@ + +--- 333,343 ---- + + clean: + rm -f *.o ++ rm -f *.so + + .f.o: + $(FORTRAN) $(OPTS) -c $< -o $@ + +! slaruv.o: slaruv.f ; $(FORTRAN) $(NOOPT) -fPIC -c $< -o $@ +! dlaruv.o: dlaruv.f ; $(FORTRAN) $(NOOPT) -fPIC -c $< -o $@ + diff --git a/rpms/awips2.core/Installer.ldm/component.spec b/rpms/awips2.core/Installer.ldm/component.spec index c256d78ae3..0f0cccdfe5 100644 --- a/rpms/awips2.core/Installer.ldm/component.spec +++ b/rpms/awips2.core/Installer.ldm/component.spec @@ -5,7 +5,7 @@ Name: awips2-ldm Summary: AWIPS II LDM Distribution Version: 6.8.1 -Release: 22 +Release: 23 Group: AWIPSII BuildRoot: /tmp URL: N/A diff --git a/rpms/awips2.core/Installer.ldm/patch/etc/pqact.conf.template b/rpms/awips2.core/Installer.ldm/patch/etc/pqact.conf.template old mode 100644 new mode 100755 index 9b9c83c405..a753d3fcb4 --- a/rpms/awips2.core/Installer.ldm/patch/etc/pqact.conf.template +++ b/rpms/awips2.core/Installer.ldm/patch/etc/pqact.conf.template @@ -157,7 +157,7 @@ HDS ^(YVW[ABCDGJM][0-9][0-9]) KKCI (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/ # AWIPS1: GRID ^[LM].[ABDHMNRSTU].*KWB.* /Grid/SBN/rawGrib2 # LTHO70 KWBC 011800 !grib2/ncep/GFS/#213/201102011800F120/TMPK/700 hPa PRES -NGRID ^([LM].[ABDHMNRSTU].{1,3}) (KWB.) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^([LM].[ABDHMNRSTU].{1,3}) (KWB.) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # MosGuidance, perhaps others? @@ -168,37 +168,37 @@ HDS ^([LM].[ABDHMNRSTU].{1,3}) (KWB.) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/] # AWIPS1: GRID ^[LM].[MN].98.*KWNH /Grid/SBN/rawGrib2 # LEMG98 KWNH 020600 !grib2/ncep/NCEP_QPF/#001/201102020600F036/P06M/0 - NONE -NGRID ^([LM].[MN].98) (KWNH) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^([LM].[MN].98) (KWNH) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^[LM].E.*KWBD* /Grid/SBN/rawGrib2 # MUEU98 KWBD 020600 !grib2/ncep/DGEX_115/#185/201102020600F090/UREL/10 m HGHT -NGRID ^([LM].E.{1,3}) (KWBD) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^([LM].E.{1,3}) (KWBD) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^L.U.*KWBN* /Grid/SBN/rawGrib2 # LAUE06 KWBN 021200 !grib2/ncep/NDFD/#197/201102021200F096/CLD/0 - NONE -#NGRID ^(L.U.*) (KWBN) (..)(..)(..) .*!(grib|grib2)/.*/(.*)/#(.*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +#NGRID|HDS ^(L.U.*) (KWBN) (..)(..)(..) .*!(grib|grib2)/.*/(.*)/#(.*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) # FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^L[AB]U[ABC].*KWNO* /Grid/SBN/rawGrib2 # LBUB05 KWNO 012200 !grib2/ncep/LAMP/#197/201102012200F007/CTSTM02/0 - NONE -NGRID ^(L[AB]U[ABC].{1,3}) (KWNO) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^(L[AB]U[ABC].{1,3}) (KWNO) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^L[UV]I.*KWBJ* /Grid/SBN/rawGrib2 # LVIB88 KWBJ 011800 !grib2/ncep/GFS/#255/201102011800F003/VSBY/10 m HGHT -NGRID ^(L[UV]I.{1,3}) (KWBJ) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^(L[UV]I.{1,3}) (KWBJ) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^[LM]DG.*KNHC* /Grid/SBN/rawGrib2 # LDGG98 KNHC 021200 !grib2/ncep/FORECASTER/#255/201102021200F036/SPED360025PA/10 m HGHT -NGRID ^([LM]DG.{1,3}) (KNHC) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^([LM]DG.{1,3}) (KNHC) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^LJ[NP][NT]98.*KWNM /Grid/SBN/rawGrib2 @@ -207,25 +207,25 @@ NGRID ^([LM]DG.{1,3}) (KNHC) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/] # AWIPS1: GRID ^LJPZ98.*KNHC /Grid/SBN/rawGrib2 # LJPZ98 KNHC 020024 -NGRID ^(LJNT98) (KWBC|KWNM) (..)(..)(..) +NGRID|HDS ^(LJNT98) (KWBC|KWNM) (..)(..)(..) FILE -overwrite -log -close -edex /data_store/grib2/GRID180/MPC/opcWave/\3/\4/\1_\2_\3\4\5_(seq).grib2.%Y%m%d -NGRID ^(LJPN98) (KWNM|KWBC) (..)(..)(..) +NGRID|HDS ^(LJPN98) (KWNM|KWBC) (..)(..)(..) FILE -overwrite -log -close -edex /data_store/grib2/GRID181/MPC/opcWave/\3/\4/\1_\2_\3\4\5_(seq).grib2.%Y%m%d -NGRID ^(LJPZ98) (KNHC|KWNM|KWBC) (..)(..)(..) +NGRID|HDS ^(LJPZ98) (KNHC|KWNM|KWBC) (..)(..)(..) FILE -overwrite -log -close -edex /data_store/grib2/GRID182/TPC/opcWave/\3/\4/\1_\2_\3\4\5_(seq).grib2.%Y%m%d # AWIPS1: GRID ^ETWA88.*KWBI /Grid/SBN/rawGrib2 # ETWA88 KWBI 010000 !grib2/ncep/SST/#173/201102010000F000/TMPK/0 - NONE -NGRID ^(ETWA88) (KWBI) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^(ETWA88) (KWBI) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^LAMA98.*KNES /Grid/SBN/rawGrib2 # LAMA98 KNES 012200 !grib2/ncep/RTMA/#197/201102012201F000/CLD/0-0 - NONE -NGRID ^(LAMA98) (KNES) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^(LAMA98) (KNES) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^L.Z.*KWBX /Grid/SBN/rawGrib2 @@ -242,7 +242,7 @@ EXP ^/data_store/grib2/ECMWF_HiRes/ecmwf_raw/(ecmwf_decrypted.*) # AWIPS1: GRID ^E.[ABCGHI].*KWBJ /Grid/SBN/rawGrib2 # EWAW88 KWBJ 021200 !grib2/ncep/GMGWM/#255/201102021200F180/WSTP/0 - NONE -NGRID ^(E.[ABCGHI].{1,3}) (KWBJ) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) +NGRID|HDS ^(E.[ABCGHI].{1,3}) (KWBJ) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*) FILE -overwrite -log -close -edex /data_store/\6/GRID\8/\7/\9/\(10)Z_\(11)_\(12)-\1_\2_(seq).\6.%Y%m%d # AWIPS1: GRID ^[LM].[AB].*KWBS* /Grid/SBN/rawGrib2 diff --git a/rpms/awips2.edex/deploy.builder/build.sh b/rpms/awips2.edex/deploy.builder/build.sh old mode 100755 new mode 100644 diff --git a/rpms/python.site-packages/Installer.pupynere/component.spec b/rpms/python.site-packages/Installer.pupynere/component.spec index 6077a67621..e42a379337 100644 --- a/rpms/python.site-packages/Installer.pupynere/component.spec +++ b/rpms/python.site-packages/Installer.pupynere/component.spec @@ -3,8 +3,8 @@ # Name: awips2-python-pupynere Summary: AWIPS II Python pupynere Site-Package -Version: 1.0.13 -Release: 2 +Version: 1.0.15 +Release: 1 Group: AWIPSII BuildRoot: /tmp URL: N/A diff --git a/rpms/python.site-packages/Installer.pupynere/component.spec_ORIG b/rpms/python.site-packages/Installer.pupynere/component.spec_ORIG new file mode 100644 index 0000000000..0a751cf91f --- /dev/null +++ b/rpms/python.site-packages/Installer.pupynere/component.spec_ORIG @@ -0,0 +1,89 @@ +# +# AWIPS II Python pupynere Site-Package Spec File +# +Name: awips2-python-pupynere +Summary: AWIPS II Python pupynere Site-Package +Version: 1.0.15 +Release: 1 +Group: AWIPSII +BuildRoot: /tmp +URL: N/A +License: N/A +Distribution: N/A +Vendor: Raytheon +Packager: Bryan Kowal + +AutoReq: no +requires: awips2-python +requires: awips2-python-numpy +provides: awips2-python-pupynere +%define _docdir python.pupynere + +%description +AWIPS II Python pupynere Site-Package - Installs the AWIPS II Python +pupynere Site-Package in the Python installation. + +# Turn off the brp-python-bytecompile script +%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g') + +%prep +# Verify That The User Has Specified A BuildRoot. +if [ "${RPM_BUILD_ROOT}" = "/tmp" ] +then + echo "An Actual BuildRoot Must Be Specified. Use The --buildroot Parameter." + echo "Unable To Continue ... Terminating" + exit 1 +fi + +mkdir -p ${RPM_BUILD_ROOT} + +%build +SITE_PACKAGE_SRC_DIR="pythonPackages/pupynere" +PREREQ_PACKAGE_SRC_DIR="pythonPackages/setuptools" + +# Build and install the pre-req setuptools +cd ${WORKSPACE_DIR}/${PREREQ_PACKAGE_SRC_DIR} +${PYTHON_EXE} setup.py build +${PYTHON_EXE} setup.py install + +# Build pupynere +cd ${WORKSPACE_DIR}/${SITE_PACKAGE_SRC_DIR} +${PYTHON_EXE} setup.py build + +%install +SITE_PACKAGE_SRC_DIR="pythonPackages/pupynere" + +cd ${WORKSPACE_DIR}/${SITE_PACKAGE_SRC_DIR} + +${PYTHON_EXE} setup.py install --root=${RPM_BUILD_ROOT} \ + --prefix=/awips2/python + +%pre +if [ -d /usr/share/doc/awips2/%{_docdir} ]; then + rm -rf /usr/share/doc/awips2/%{_docdir} +fi + +PYTHON_INSTALL="/awips2/python" +echo -e "\e[1;34m--------------------------------------------------------------------------------\e[m" +echo -e "\e[1;34m\| Installing the AWIPS II Python pupynere Site-Package...\e[m" +echo -e "\e[1;34m--------------------------------------------------------------------------------\e[m" +echo -e "\e[1;34m Python Install Root = ${PYTHON_INSTALL}\e[m" + +%post +PYTHON_INSTALL="/awips2/python" + +echo -e "\e[1;32m--------------------------------------------------------------------------------\e[m" +echo -e "\e[1;32m\| AWIPS II Python pupynere Site-Package Installation - COMPLETE\e[m" +echo -e "\e[1;32m--------------------------------------------------------------------------------\e[m" + +%preun + +%postun +echo -e "\e[1;34m--------------------------------------------------------------------------------\e[m" +echo -e "\e[1;34m\| The AWIPS II Python pupynere Site-Package Has Been Successfully Removed\e[m" +echo -e "\e[1;34m--------------------------------------------------------------------------------\e[m" +echo "" + +%files +%defattr(644,awips,fxalpha,755) +/awips2/python/lib/python2.7/site-packages/* \ No newline at end of file