## # 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. # # FirePhrases.py # Methods for producing text forecast from SampleAnalysis statistics. # # Author: hansen # ---------------------------------------------------------------------------- # # SOFTWARE HISTORY # # Date Ticket# Engineer Description # ------------- -------- --------- -------------------------------------------- # Feb 15, 2018 6975 randerso Fixed smokeDispersal_words to eliminate # "excellent to excellent" phrasing # Feb 27, 2018 7101 randerso Fixed haines_words to handle haines_dict # with empty strings. Removed "or " from # haines_dict strings to avoid repeated "or" # when 2 values are present. # # ## ## # This is a base file that is not intended to be overridden. ## import ScalarPhrases import VectorRelatedPhrases import WxPhrases import DiscretePhrases class FirePhrases(ScalarPhrases.ScalarPhrases, VectorRelatedPhrases.VectorRelatedPhrases, WxPhrases.WxPhrases, DiscretePhrases.DiscretePhrases): def __init__(self): ScalarPhrases.ScalarPhrases.__init__(self) VectorRelatedPhrases.VectorRelatedPhrases.__init__(self) WxPhrases.WxPhrases.__init__(self) DiscretePhrases.DiscretePhrases.__init__(self) ############################################ ### FIRE WEATHER PHRASES ### Sky and Weather def includeSkyRanges_flag(self, tree, node): # Set to 0 if you do not want ranges reported with sky phrases: # Partly cloudy (35-40 PERCENT) return 1 def skyWeather_byTimeRange_compoundPhrase(self): return { "phraseList": [ self.fireSky_phrase, self.weather_phrase, ], "phraseMethods": [ self.consolidateSubPhrases, self.assembleSentences, self.skyWeather_finishUp, ], } def skyWeather_finishUp(self, tree, node): "Create a phrase for sky/weather" words = node.get("words") if words is None: return if words == "": words = "MISSING" node.set("descriptor", "") node.set("indentLabel", "Sky/weather.........") node.set("compound", 1) return self.DONE() def fireSky_phrase(self): return { "setUpMethod": self.fireSky_setUp, "wordMethod": self.fireSky_words, "phraseMethods": [ self.checkLocalEffects, self.combineSky, self.combineWords, self.fillNulls, self.assembleSubPhrases, self.postProcessPhrase, ], } def fireSky_setUp(self, tree, node): elementInfoList = [self.ElementInfo("Sky", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) return self.DONE() def fireSky_words(self, tree, node): # Report average as a worded summary, also return average statDict = node.getStatDict() stats = self.getStats(statDict, "Sky") if stats is None: return self.setWords(node, "") avg = self.getValue(stats) dayNight = self.getPeriod(node.getTimeRange(), 1) words = self.sky_value(tree, node, avg, dayNight) words = self.addSkyRange(tree, node, words, avg) return self.setWords(node, words) def addSkyRange(self, tree, node, words, avg): # Add range if desired if self.includeSkyRanges_flag(tree, node): roundAvg = int(self.round(avg, "Nearest", 5)) if roundAvg < 5: min = 0 else: min = roundAvg - 5 if roundAvg >= 100: max = 100 else: max = roundAvg + 5 units = self.units_descriptor(tree, node, "units", "%") words = words + " (" + repr(min) + "-" + repr(max) + units + ")" return words # Trends ### MinT, MaxT, MinRH, MaxRH, RH def trend_DayOrNight_phrase(self): return { "setUpMethod": self.trend_DayOrNight_setUp, "wordMethod": self.trend_DayOrNight_words, "phraseMethods": [ self.checkLocalEffects, self.assembleSubPhrases, self.postProcessPhrase, ], } def trend_DayOrNight_setUp(self, tree, node): dayElement, nightElement, trendElement, indent, endWithPeriod = node.get("args") dayNight = self.getPeriod(node.getTimeRange(), 1) if dayNight == self.DAYTIME(): elementName = dayElement else: elementName = nightElement elementInfoList = [self.ElementInfo(elementName, "MinMax")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("trendElement", trendElement) node.set("descriptor", "") if indent == 1: node.set("indentLabel", " 24 hr trend......") return self.DONE() def trend_DayOrNight_words(self, tree, node): "Compare current analysis to previous analysis for trends" elementName = node.get("elementName") higher = self.phrase_descriptor(tree, node, "higher", elementName) lower = self.phrase_descriptor(tree, node, "lower", elementName) threshold = self.trend_threshold(tree, node, elementName, elementName) if elementName == "MinT" or elementName == "MaxT": units = self.units_descriptor(tree, node, "units", "degrees") unit = self.units_descriptor(tree, node, "unit", "degree") if elementName == "MaxRH" or elementName == "MinRH" or elementName == "RH": units = self.units_descriptor(tree, node, "units", "%") unit = self.units_descriptor(tree, node, "unit", "%") trendElement = node.getAncestor("trendElement") words, diff = self.getTrend( tree, node, elementName, trendElement, "", units, unit, threshold, higher, lower) if words is not None: if diff == 0: words = self.phrase_descriptor(tree, node, "unchanged", elementName) else: words = self.phrase_descriptor(tree, node, "missing", elementName) return self.setWords(node, words) def getTrend(self, tree, phrase, element, trendElement, introWords, units, unit, threshold, positiveDescriptor, negativeDescriptor): timeRange = phrase.getTimeRange() areaLabel = phrase.getAreaLabel() absDiff, rawDiff = self.getTrendStats( tree, phrase, element, timeRange, areaLabel, trendElement) if absDiff is None: return absDiff, rawDiff diff = int(absDiff) if absDiff >= threshold: if rawDiff >= 0: descriptor = positiveDescriptor else: descriptor = negativeDescriptor if diff == 1: units = unit introWords = self.addSpace(introWords) if units != "%": units = " " + units words = introWords + repr(diff) + units + " " + descriptor else: words = "" #print "returning", words, diff return words, diff def getTrendStats(self, tree, phrase, element, timeRange, areaLabel, trendElement): # NO CONVERSION DONE # Try the trend element first stats = tree.stats.get(trendElement, timeRange, areaLabel, mergeMethod="Average") #print "\ngetTrendStats" if stats is not None: rawDiff = int(self.getValue(stats)) absDiff = abs(rawDiff) else: #Use Max/Min element curStats = tree.stats.get(element, timeRange, areaLabel, mergeMethod="Average", statLabel="mode") #print "curstats", curStats if curStats is None: return None, 0 prevTimeRange = self.adjustTimeRange(timeRange, -24) prevStats = tree.stats.get(element, prevTimeRange, areaLabel, mergeMethod="Average", statLabel="mode") #print "prevstats", prevStats if prevStats is None: return None, 0 prevStats = self.getValue(prevStats) curStats = self.getValue(curStats) #print "cur, prev", element, curStats, prevStats absDiff = self.absDiff(curStats, prevStats) rawDiff = curStats - prevStats #print "absDiff, rawDiff", absDiff, rawDiff return absDiff, rawDiff def dayOrNight_phrase(self): return { "setUpMethod": self.dayOrNight_setUp, "wordMethod": self.fire_dayOrNight_words, "phraseMethods": [ self.checkLocalEffects, self.assembleSubPhrases, self.postProcessPhrase, ], } def dayOrNight_setUp(self, tree, node): dayElement, nightElement, indent, endWithPeriod = node.get("args") elementName = self.dayOrNight_element(tree, node, dayElement, nightElement) indentName = elementName + "_FireWx" method = "MinMax" if elementName == "RH": dayNight = self.getPeriod(node.getTimeRange(), 1) if dayNight == self.DAYTIME(): indentName = "MinRH_FireWx" method = "Min" else: indentName = "MaxRH_FireWx" method = "Max" elementInfoList = [self.ElementInfo(elementName, method)] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", indentName) return self.DONE() def fire_dayOrNight_words(self, tree, node): elementName = node.getAncestor("elementName") statDict = node.getStatDict() if elementName == "MaxT" or elementName == "MinT": stats = self.getTempStats(tree, node) if stats is None: return self.setWords(node.parent, "MISSING") words = self.getTempRangePhrase(tree, node, stats, elementName) else: # MinRH, MaxRH or RH stats = self.getStats(statDict, elementName) if stats is None: return self.setWords(node.parent, "MISSING") connector = self.value_connector(tree, node, elementName, elementName) min, max = self.getValue(stats, "MinMax") if min == max: words = repr(int(min)) else: words = repr(int(min)) + connector + repr(int(max)) outUnits = self.element_outUnits(tree, node, elementName, elementName) units = self.units_descriptor(tree, node, "units", outUnits) words = words + units return self.setWords(node, words) ### CWR def cwr_phrase(self): return { "setUpMethod": self.cwr_setUp, "wordMethod": self.cwr_words, "phraseMethods": self.standard_phraseMethods(), } def cwr_setUp(self, tree, node): try: cwr = self._cwrParm except: cwr = "CWR" elementInfoList = [self.ElementInfo(cwr, "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "CWR.................") return self.DONE() def cwr_words(self, tree, node) : "Create phrase Probability of Precipitation" statDict = node.getStatDict() cwr = self.getStats(statDict, "CWR") if cwr is None: return self.setWords(node.parent, "MISSING") cwr = self.getValue(cwr) threshold = self.nlValue(self.null_nlValue( tree, node, "CWR", "CWR"), cwr) if int(cwr) < threshold: return self.setWords(node, "null") else: words = repr(int(cwr)) + " percent" return self.setWords(node, words) ### VentRate or smoke dispersal phrase def smokeDispersal_phrase(self): return { "setUpMethod": self.smokeDispersal_setUp, "wordMethod": self.smokeDispersal_words, "phraseMethods": self.standard_phraseMethods(), } def smokeDispersal_setUp(self, tree, node): elementInfoList = [self.ElementInfo("VentRate", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "Smoke dispersal.....") return self.DONE() def smokeDispersal_words(self, tree, node): "Create phrase for Smoke Dispersal" statDict = node.getStatDict() stats = self.getStats(statDict, "VentRate") if stats is None: return self.setWords(node.parent, "MISSING") vr1, vr2 = self.getValue(stats, "MinMax") vr1 = int(vr1) vr2 = int(vr2) vrCat1 = self.smokeDispersal_valueStr(vr1) vrCat2 = self.smokeDispersal_valueStr(vr2) # Single Value input if vr1 == vr2: words = vrCat1 + " (" + repr(vr1) + " knot-ft)" # Range elif vrCat1 == vrCat2: words = vrCat1 + " (" + repr(vr1) + "-" + \ repr(vr2) + " knot-ft)" else: words = vrCat1 + " to " + vrCat2 + " (" + repr(vr1) + "-" + \ repr(vr2) + " knot-ft)" return self.setWords(node, words) # SMOKE DISPERSAL CATEGORIES def smokeDispersal_valueStr(self, value): "Convert smoke dispersal value to corresponding category" if value < 40000 : return "poor" if value >= 40000 and value < 60000: return "fair" if value >= 60000 and value < 100000 : return "good" if value >= 100000 and value < 150000 : return "very good" if value >= 150000 : return "excellent" ### Fire Winds def transportWind_phrase(self): return { "setUpMethod": self.transportWind_setUp, "wordMethod": self.vector_words, "phraseMethods": self.standard_vector_phraseMethods(), } def transportWind_setUp(self, tree, node): self.wind_setUp(tree, node, gustFlag=0, element="TransWind") node.set("descriptor", "") node.set("indentLabel", "Transport winds.....") return self.DONE() def freeWind_phrase(self): return { "setUpMethod": self.freeWind_setUp, "wordMethod": self.vector_words, "phraseMethods": self.standard_vector_phraseMethods(), } def freeWind_setUp(self, tree, node): self.wind_setUp(tree, node, gustFlag=0, element="FreeWind") node.set("descriptor", "") node.set("indentLabel", "Free winds..........") return self.DONE() def ridgeValleyAreas(self, tree, node): # List of edit area names for which we want # ridge/valley winds reported: # # 20-foot winds... # Valleys/lwr slopes... # Ridges/upr slopes.... # # e.g. # return ["Area1"] # return [] def valleyRidgeAreaNames(self, tree, node): # These are the areas for valleys and ridges, respectively, # to be intersected with the current edit area for # reporting valley winds and ridge winds, respectively. # NOTE: If you change these area names, you will also # need to change the names in the FirePeriod "intersectAreas" # section. return "Valleys", "Ridges" def fireWind_compoundPhrase(self): return { "phraseList": [ self.wind_summary, self.wind_phrase, ], "phraseMethods": [ self.consolidateSubPhrases, self.assembleSentences, self.fireWind_finishUp ], } def fireWind_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", "20-foot winds.......") node.set("compound", 1) return self.setWords(node, words) def fireWind_label_phrase(self): return { "setUpMethod": self.fireWind_label_setUp, "phraseMethods": [self.postProcessPhrase], } def fireWind_label_setUp(self, tree, node): if self.currentAreaContains( tree, self.ridgeValleyAreas(tree, node)) == 0: return self.setWords(node, "") self.setWords(node, "") node.set("descriptor", "") node.set("indentLabel", "20-foot winds.......") return self.DONE() # Valley/Ridge split set-up def fireValleyWind_compoundPhrase(self): return { "phraseList": [ self.wind_summary, self.wind_phrase, ], "phraseMethods": [ self.fireRidgeValleyWind_setUp, self.consolidateSubPhrases, self.assembleSentences, self.fireValleyWind_finishUp ], } def fireRidgeValleyWind_setUp(self, tree, node): # Used for set-up of fireRidgeWind_compoundPhrase as well. if self.currentAreaContains( tree, self.ridgeValleyAreas(tree, node)) == 0: return self.setWords(node, "") # Set up intersect area to be used for the node areaName = node.getAreaLabel() phraseName = node.get("name") valleys, ridges = self.valleyRidgeAreaNames(tree, node) if phraseName.find("Valley") >= 0: area = valleys else: area = ridges intersectName = self.getIntersectName(areaName, area) #print "setting intersect", intersectName node.set("areaLabel", intersectName) return self.DONE() def fireValleyWind_finishUp(self, tree, node): "Create a phrase for Winds" words = node.get("words") if words is None: return if words == "": words = "MISSING" node.set("descriptor", "") node.set("indentLabel", " Valleys/lwr slopes...") node.set("compound", 1) return self.setWords(node, words) def fireRidgeWind_compoundPhrase(self): return { "phraseList": [ self.wind_summary, self.wind_phrase, ], "phraseMethods": [ self.fireRidgeValleyWind_setUp, self.consolidateSubPhrases, self.assembleSentences, self.fireRidgeWind_finishUp ], } def fireRidgeWind_finishUp(self, tree, node): "Create a phrase for Winds" words = node.get("words") if words is None: return if words == "": words = "MISSING" node.set("descriptor", "") node.set("indentLabel", " Ridges/upr slopes....") node.set("compound", 1) return self.setWords(node, words) ### Haines def hainesDict(self): return { 0:"very low potential for large plume dominated fire growth", 1:"very low potential for large plume dominated fire growth", 2:"very low potential for large plume dominated fire growth", 3:"very low potential for large plume dominated fire growth", 4:"low potential for large plume dominated fire growth", 5:"moderate potential for large plume dominated fire growth", 6:"high potential for large plume dominated fire growth", 7:"high potential for large plume dominated fire growth", 8:"high potential for large plume dominated fire growth", 9:"high potential for large plume dominated fire growth", 10:"high potential for large plume dominated fire growth" } def haines_phrase(self): return { "setUpMethod": self.haines_setUp, "wordMethod": self.haines_words, "phraseMethods": [ self.consolidatePhrase, self.checkLocalEffects, self.combinePhraseStats, self.combineWords, self.fillNulls, self.timeDescriptorModeration, self.assembleSubPhrases, self.postProcessPhrase, ] } def haines_setUp(self, tree, node): elementInfoList = [self.ElementInfo("Haines", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "Haines Index........") return self.DONE() def haines_words(self, tree, node): "Create phrase for Haines Index" statDict = node.getStatDict() stats = self.getStats(statDict, "Haines") if stats is None: return self.setWords(node.parent, "MISSING") haines1, haines2 = self.getValue(stats, "MinMax") hainesDict = self.hainesDict() haines1 = int(haines1) haines2 = int(haines2) words1 = hainesDict[haines1] words2 = hainesDict[haines2] # Single Value input if haines1 == haines2: words = repr(haines1) # Range else: words = repr(haines1) + " to " + repr(haines2) if words1: words += " or " + words1 if words2 and words2 != words1: words += " to " + words2 elif words2: words += " or " + words2 return self.setWords(node, words) ### Humidity def humidityRecovery_percentage(self, tree, node): # If the maximum humidity is greater than this percentage, # humidity recovery will be Excellent. return 50 def humidityRecovery_phrase(self): return { "setUpMethod": self.humidityRecovery_setUp, "wordMethod": self.humidityRecovery_words, "phraseMethods": self.standard_phraseMethods(), } def humidityRecovery_setUp(self, tree, node): timeRange = node.getTimeRange() dayNight = self.getPeriod(timeRange, 1) if dayNight != self.NIGHTTIME(): return self.setWords(node, "") if self._useRH: elementName = "RH" else: elementName = "MaxRH" elementInfoList = [self.ElementInfo(elementName, "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "Humidity recovery...") return self.DONE() def humidityRecovery_words(self, tree, node): "Create phrase for Humidity recovery" if self._useRH: elementName = "RH" else: elementName = "MaxRH" statDict = node.getStatDict() curStats = self.getStats(statDict, elementName) if curStats is None: return self.setWords(node.parent, "MISSING") maxRH = self.getValue(curStats, "Max") if maxRH > self.humidityRecovery_percentage(tree, node): return self.setWords(node, "Excellent") timeRange = node.getTimeRange() prevTimeRange = self.adjustTimeRange(timeRange, -24) prevStats = tree.stats.get(elementName, prevTimeRange, node.getAreaLabel(), statLabel="mode", mergeMethod="Max") if prevStats is None: return self.setWords(node, "") curStats = self.getValue(curStats) prevStats = self.getValue(prevStats) diff = curStats - prevStats words = "" for threshold, label in self.humidityRecovery_valueList(tree, node): if diff <= threshold: words = label break return self.setWords(node, words) # Humidity recovery values def humidityRecovery_valueList(self, tree, node): "Used to convert percent difference to corresponding category" # If you want to return different thresholds based on edit areas: # # editAreaNames = ["area1", "area2"] # if self.currentAreaContains(tree, editAreaNames): # return [ # (15, "Poor"), # (20, "Fair"), # (30, "Good"), # ] return [ (25, "Poor"), (55, "Moderate"), (70, "Good"), (100, "Excellent"), ] ### LAL ## ################################### ## # General LAL Definition # ## # mainly defined for wrn 1/2 of US# ## # but still different across the # ## # country (from Dave Metze # ## ################################### ## LALs.....(L)ightning (A)ctivity (L)evels numbered 1 through 6. ## * LAL 1 - No thunderstorms. ## * LAL 2 - isolated/slight chance thunderstorms..............PoP 5-14% ## * LAL 3 - isolated/slight chance thunderstorms..............PoP 15-24% ## * LAL 4 - scattered/chance thunderstorms....................PoP 25-54% ## * LAL 5 - numerous/likely to wide/def thunderstorms.........PoP 55-100% ## * LAL 6 - Dry lightning(thunderstorms) for LAL 3 through 5..PoP 15-100% ## The number of lightning strikes is also a variable, but not sure if the ## science of meteorology is in place to forecast the actual number of ## lightning strikes, so most offices use the potential/coverage of ## thunderstorms to determine the LAL value. def lal_phrase(self): return { "setUpMethod": self.lal_setUp, "wordMethod": self.lal_words, "phraseMethods": [ self.consolidatePhrase, self.checkLocalEffects, self.combinePhraseStats, self.combineWords, self.fillNulls, self.timeDescriptorModeration, self.assembleSubPhrases, self.postProcessPhrase, ] } def lal_setUp(self, tree, node): # Wait for all Wx (and other) phrases to complete # NOTE that we are sending the areaLabel so IF you have a local # effect set up for LAL, you must have the same local effect set up # for weather, AND LAL and weather should be consistent in the grids. phraseList = self.checkPhrasesDone( tree, node, areaLabel=node.getAreaLabel(), exceptions=[node.get('name')]) if phraseList is None: return # Check to see if the weather phrase changed it's resolution. # If so, we want to match it in the LAL phrase nodeRes = None for phrase in phraseList: firstElement = phrase.get("firstElement") if firstElement is not None and firstElement.name == "Wx": resolution = phrase.get('resolution') if resolution is not None: nodeRes = resolution break # Use resolution of Wx phrase elementInfoList = [self.ElementInfo("LAL", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector, resolution=nodeRes) node.set("descriptor", "") node.set("indentLabel", "LAL.................") return self.DONE() def lal_words(self, tree, node) : "Create phrase for Lightning Activity Level" #statDict = node.getStatDict() #stats = self.getStats(statDict, "LAL") # Check low pop. If low, set LAL to 1. popThreshold = self.pop_wx_lower_threshold(tree, node) lowPopFlag = self.lowPop_flag(tree, node, popThreshold) if lowPopFlag == 1: lal = 1 else: lal = self.matchToWx(tree, node, "LAL") if lal is None: return self.setWords(node, "null") if self._lightningPhrases: words = self.lal_value(tree, node, lal) else: words = repr(int(lal)) return self.setWords(node, words) def lal_value(self, tree, node, lal): value = "No Tstms" if lal > 1: value = "1-8 strikes" if lal > 2: value = "9-15 strikes" if lal > 3: value = "16-25 strikes" if lal > 4: value = ">25 strikes" if lal > 5: value = "Dry lightning" return value def coverageLAL_value(self, coverage): # LAL ranges that correspond to each of the weather coverages lalValue = self.coverageLAL_table() return lalValue[coverage] def coverageLAL_table(self): # LAL ranges that correspond to each of the weather coverages return { "": (1, 1), "Iso": self.lal_2_3, "SChc": self.lal_2_3, "Patchy": self.lal_wx_value, "Areas":self.lal_wx_value, "Chc": self.lal_wx_value, "Sct": self.lal_wx_value, "Lkly": self.lal_wx_value, "Num": self.lal_wx_value, "Brf": self.lal_wx_value, "Frq": self.lal_wx_value, "Ocnl": self.lal_wx_value, "Pds": self.lal_wx_value, "Inter":self.lal_wx_value, "Def": self.lal_wx_value, "Wide": self.lal_wx_value, } def lal_2_3(self, tree, node, highKey): pop = tree.stats.get("PoP", node.getTimeRange(), node.getAreaLabel(), mergeMethod="Max") if pop > 10: if highKey.wxType() == "T" and "Dry" in highKey.attributes(): return (6, 6) else: return (3, 3) else: return (2, 2) def lal_wx_value(self, tree, node, highKey): # Check for Dry Thunderstorms if highKey.wxType() == "T" and "Dry" in highKey.attributes(): return (6, 6) coverage = highKey.coverage() lal_dict = { "Patchy": (2, 2), "Areas":(4, 4), "Chc": (4, 4), "Sct": (4, 4), "Lkly": (5, 5), "Num": (5, 5), "Brf": (5, 5), "Frq": (5, 5), "Ocnl": (5, 5), "Pds": (5, 5), "Inter":(5, 5), "Def": (5, 5), "Wide": (5, 5), } return lal_dict[coverage] ### MixHgt def mixingHgt_phrase(self): return { "setUpMethod": self.mixingHgt_setUp, "wordMethod": self.mixingHgt_words, "phraseMethods": self.standard_phraseMethods(), } def mixingHgt_setUp(self, tree, node): elementInfoList = [self.ElementInfo("MixHgt", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) node.set("descriptor", "") node.set("indentLabel", "Mixing height.......") return self.DONE() def mixingHgt_words(self, tree, node): "Create phrase for Mixing Height" statDict = node.getStatDict() stats = self.getStats(statDict, "MixHgt") if stats is None: return self.setWords(node.parent, "MISSING") mix1, mix2 = self.getValue(stats, "MinMax") outUnits = self.element_outUnits(tree, node, "MixHgt", "MixHgt") mix1 = int(mix1) mix2 = int(mix2) threshold = self.nlValue(self.null_nlValue( tree, node, "MixHgt", "MixHgt"), max) if int(mix1) < threshold and int(mix2) < threshold: return self.setWords(node, "null") # Single Value input if mix1 == mix2: words = repr(mix1) + " " + outUnits + " AGL" # Range else: words = repr(mix1) + "-" + repr(mix2) + " " + outUnits + " AGL" return self.setWords(node, words) ###--------------------------------------------------------- ### OPTIONAL Phrase: Contributed by Ben Moyer, LOX ### Marine Layer - taken from mixingHgt phrase methods ###--------------------------------------------------------- def marineLayer_phrase(self): return { "setUpMethod": self.marineLayer_setUp, "wordMethod": self.marineLayer_words, "phraseMethods": self.standard_phraseMethods(), } def marineLayer_setUp(self, tree, node): elementInfoList = [self.ElementInfo("MarineLayer", "List")] self.subPhraseSetUp(tree, node, elementInfoList, self.scalarConnector) # Do not generate for desert areas #desertArea = ["Desert"] #if self.currentAreaContains(tree, desertArea): # return self.DONE() node.set("descriptor", "") node.set("indentLabel", "Marine layer........") return self.DONE() def marineLayer_words(self, tree, node): "Create phrase for Marine Layer" statDict = node.getStatDict() stats = self.getStats(statDict, "MarineLayer") if stats is None: return self.setWords(node.parent, "MISSING") mix1, mix2 = self.getValue(stats, "MinMax") outUnits = self.element_outUnits(tree, node, "MixHgt", "MixHgt") mix1 = int(mix1) mix2 = int(mix2) # Single Value input # Makes "0 ft asl" be returned as "none" if mix1 == 0 and mix2 == 0: words = "none" elif mix1 == mix2: words = repr(mix1) + " " + outUnits + " asl" # Makes phrases such as "0-800 ft asl" be simply "800 ft asl" elif mix1 == 0 and mix2 > 0: words = repr(mix2) + " " + outUnits + " asl" # Range else: words = repr(mix1) + "-" + repr(mix2) + " " + outUnits + " asl" return self.setWords(node, words)