1396 lines
66 KiB
HTML
1396 lines
66 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type"
|
||
|
content="text/html; charset=iso-8859-1">
|
||
|
<meta name="GENERATOR"
|
||
|
content="Mozilla/4.8 [en] (X11; U; Linux 2.4.18-27.7.xsmp i686) [Netscape]">
|
||
|
<title>Text Products Reference</title>
|
||
|
<!--link REL="STYLESHEET" HREF="TextFormatter.html"-->
|
||
|
</head>
|
||
|
<body bgcolor="#ffffff">
|
||
|
<center><h1> <a name="Answers_to_Exercises"></a>Answers to Exercises</h1></center>
|
||
|
<hr>
|
||
|
|
||
|
<h2> <a name="Answer_to_Simple_Tabular_Product"></a>Answer to Simple
|
||
|
Tabular Product Exercise 1</h2>
|
||
|
########################################################################<br>
|
||
|
# Table Definition <br>
|
||
|
# <br>
|
||
|
########################################################################<br>
|
||
|
## EXAMPLE OUTPUT
|
||
|
<p>## Exercise1 for Apr 02 02 13:00:00 GMT - Apr 03
|
||
|
02 01:00:00 GMT. <br>
|
||
|
## <br>
|
||
|
## Edit Area QPF
|
||
|
Precip (%) Wind (mph) <br>
|
||
|
## <br>
|
||
|
## Area
|
||
|
1
|
||
|
0
|
||
|
6
|
||
|
NW 0 <br>
|
||
|
## Area
|
||
|
2
|
||
|
0
|
||
|
11
|
||
|
NE 5 <br>
|
||
|
## Area
|
||
|
3
|
||
|
0
|
||
|
4
|
||
|
W 10 </p>
|
||
|
<p>Definition = { <br>
|
||
|
## General Set-Up <br>
|
||
|
"type": "table", <br>
|
||
|
"displayName": "TextEx1", # for Product
|
||
|
Generation Menu <br>
|
||
|
"outputFile": "./Exercise1.txt", # default
|
||
|
output file </p>
|
||
|
<p> ## Table Layout <br>
|
||
|
"constantVariable": "TimePeriod", <br>
|
||
|
"rowVariable": "EditArea", <br>
|
||
|
"columnVariable": "WeatherElement", <br>
|
||
|
"beginningText": "Exercise1 for %TimePeriod.
|
||
|
\n\n", <br>
|
||
|
"endingText": " ", </p>
|
||
|
<p> ## Edit Areas <br>
|
||
|
"defaultEditAreas": [ <br>
|
||
|
|
||
|
("area1", "Area 1"), <br>
|
||
|
|
||
|
("area2", "Area 2"), <br>
|
||
|
|
||
|
("area3", "Area 3"), <br>
|
||
|
|
||
|
], <br>
|
||
|
"runTimeEditAreas" : "no", # if yes, ask user
|
||
|
at run time <br>
|
||
|
"areaType" : "Edit Area", # E.g. City, County,
|
||
|
Basin, etc. </p>
|
||
|
<p> ## Time Ranges <br>
|
||
|
"defaultRanges": ["Today"], <br>
|
||
|
"runTimeRanges" : "no", # if yes, ask user at
|
||
|
run time <br>
|
||
|
## Weather Elements <br>
|
||
|
# Name , Label , Analysis Method , ReportAs
|
||
|
Method , <br>
|
||
|
# DataType , Rounding , Conversion </p>
|
||
|
<p> "elementList": [ <br>
|
||
|
|
||
|
("QPF", "QPF", "avg", "singleValue", <br>
|
||
|
|
||
|
"Scalar", .01, None), </p>
|
||
|
<p>
|
||
|
("PoP", "Precip (%)", "avg", "singleValue", <br>
|
||
|
|
||
|
"Scalar", 1, None), </p>
|
||
|
<p>
|
||
|
("Wind","Wind (mph)", "vectorRange", "avgValue", <br>
|
||
|
|
||
|
"Vector", 5, None), <br>
|
||
|
|
||
|
], <br>
|
||
|
} <br>
|
||
|
</p>
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<div class="Code">
|
||
|
<h2><a name="Answer_to_Simple_Tabular_Products_"></a>Answer to Simple
|
||
|
Tabular Products Exercise 2</h2>
|
||
|
<div class="Code">########################################################################<br>
|
||
|
# Table Definition <br>
|
||
|
# <br>
|
||
|
########################################################################<br>
|
||
|
## EXAMPLE OUTPUT
|
||
|
<p>## Experimental Surface Temperature Guidance
|
||
|
Product <br>
|
||
|
## <br>
|
||
|
## Edit Area 13Z/2
|
||
|
16Z/2 19Z/2 22Z/2 <br>
|
||
|
## <br>
|
||
|
## Area
|
||
|
1
|
||
|
28
|
||
|
28
|
||
|
28 25 <br>
|
||
|
## Area
|
||
|
2
|
||
|
30
|
||
|
31
|
||
|
31 27 <br>
|
||
|
## Area
|
||
|
3
|
||
|
32
|
||
|
33
|
||
|
34 27 </p>
|
||
|
<p>Definition = { <br>
|
||
|
## General Set-up <br>
|
||
|
"type": "table", <br>
|
||
|
"displayName": "TextEx2", # for Product
|
||
|
Generation Menu <br>
|
||
|
"outputFile": "./SurfaceTemp.txt", # default
|
||
|
output file </p>
|
||
|
<p> ## Table Layout <br>
|
||
|
"constantVariable": "WeatherElement", <br>
|
||
|
"rowVariable": "EditArea", <br>
|
||
|
"columnVariable": "TimePeriod", <br>
|
||
|
"beginningText": "Experimental Surface
|
||
|
Temperature Guidance Product \n\n", <br>
|
||
|
"endingText": "", </p>
|
||
|
<p> ## Edit Areas <br>
|
||
|
"defaultEditAreas" : [ <br>
|
||
|
|
||
|
("area1", "Area 1"), <br>
|
||
|
|
||
|
("area2", "Area 2"), <br>
|
||
|
|
||
|
("area3", "Area 3"), <br>
|
||
|
], <br>
|
||
|
"runTimeEditAreas" : "yes", # if yes, ask user
|
||
|
at run time <br>
|
||
|
"areaType" : "Edit Area", # E.g. City, County,
|
||
|
Basin, etc. </p>
|
||
|
<p> ## Time Ranges <br>
|
||
|
"defaultRanges": ["Today"], <br>
|
||
|
"runTimeRanges" : "no", # if yes, ask user at
|
||
|
run time </p>
|
||
|
<p> ## Weather Elements <br>
|
||
|
|
||
|
"elementList": [ <br>
|
||
|
|
||
|
("T","Temp", "avg", "singleValue", <br>
|
||
|
|
||
|
"Scalar", 1, None), <br>
|
||
|
|
||
|
], </p>
|
||
|
<p> ## Time Period <br>
|
||
|
"timePeriod": 3, <br>
|
||
|
"runTimePeriod": "yes", # If yes, ask user at
|
||
|
run time for period <br>
|
||
|
} <br>
|
||
|
</p>
|
||
|
<p><br>
|
||
|
<span style="font-weight: bold;"><a
|
||
|
name="Answer_to_Smart_Tabular_Exercise_2"></a>Answer to Smart Tabular
|
||
|
Exercise 2<br>
|
||
|
</span></p>
|
||
|
<p>########################################################################<br>
|
||
|
# SmartElementTable_Local<br>
|
||
|
#<br>
|
||
|
# Type: smart<br>
|
||
|
# Local product:<br>
|
||
|
# SmartElementTable_Local(type: smart)<br>
|
||
|
# To customize this product for your site:<br>
|
||
|
# Set up SmartElementTable_Local (see
|
||
|
template below)<br>
|
||
|
# to override variables, definitions,
|
||
|
thresholds, and methods<br>
|
||
|
##<br>
|
||
|
##########################################################################<br>
|
||
|
import SmartElementTable<br>
|
||
|
import string, time, re, os, types, copy<br>
|
||
|
import TimeRange<br>
|
||
|
class TextProduct(SmartElementTable.TextProduct):<br>
|
||
|
Definition =
|
||
|
copy.deepcopy(SmartElementTable.TextProduct.Definition)<br>
|
||
|
<br>
|
||
|
Definition["displayName"] = "SmartElementTable"<br>
|
||
|
#Definition["outputFile"] =
|
||
|
"{prddir}/TEXT/SmartElementTable.txt"<br>
|
||
|
#Definition["regionList"] = [<br>
|
||
|
#
|
||
|
("area1","AREA 1"),<br>
|
||
|
#
|
||
|
("area2","AREA 2"),<br>
|
||
|
#
|
||
|
("area3","AREA 3"),<br>
|
||
|
# ],<br>
|
||
|
#Definition["regionList"] = [<br>
|
||
|
#
|
||
|
("/33",["AREA 1","AREA 2"]),<br>
|
||
|
#
|
||
|
("/19",["AREA 3"])<br>
|
||
|
# ],<br>
|
||
|
<br>
|
||
|
Definition["elementList"] = ["Temp", "PoP",
|
||
|
"Wind"] <br>
|
||
|
#Definition["elementList"] = ["Temp", "PoP"] #
|
||
|
Default <br>
|
||
|
#Definition["elementList"] = ["Temp", "Humidity"] <br>
|
||
|
#Definition["elementList"] = ["Temp", "Humidity",
|
||
|
"PoP"] <br>
|
||
|
#Definition["elementList"] = ["Temp", "PoP",
|
||
|
"Humidity"] <br>
|
||
|
#Definition["elementList"] = ["PoP", "Humidity",
|
||
|
"Temp"] <br>
|
||
|
#Definition["introLetters"] = ".<"<br>
|
||
|
<br>
|
||
|
def __init__(self):<br>
|
||
|
|
||
|
SmartElementTable.TextProduct.__init__(self)<br>
|
||
|
<br>
|
||
|
def _getAnalysisList(self):<br>
|
||
|
return [<br>
|
||
|
("MinT",
|
||
|
self.avg),<br>
|
||
|
("MaxT",
|
||
|
self.avg),<br>
|
||
|
("MinRH",
|
||
|
self.avg),<br>
|
||
|
("MaxRH",
|
||
|
self.avg),<br>
|
||
|
("PoP",
|
||
|
self.stdDevMaxAvg),<br>
|
||
|
("Wind",
|
||
|
self.vectorAvg),<br>
|
||
|
]<br>
|
||
|
<br>
|
||
|
def _titleDict(self):<br>
|
||
|
return {<br>
|
||
|
|
||
|
"Temp": "TEMPERATURE",<br>
|
||
|
|
||
|
"PoP": "PRECIPITATION",<br>
|
||
|
|
||
|
"Humidity":"HUMIDITY",<br>
|
||
|
|
||
|
"Wind": "WIND",<br>
|
||
|
}<br>
|
||
|
<br>
|
||
|
def _getWindValues(self, statList, argDict):<br>
|
||
|
# Return a string of PoP values in
|
||
|
the statList<br>
|
||
|
wind = []<br>
|
||
|
windStr = " "<br>
|
||
|
index = 0<br>
|
||
|
for stats in statList:<br>
|
||
|
val =
|
||
|
self._getWindValue(stats)<br>
|
||
|
if index
|
||
|
< len(statList)-1:<br>
|
||
|
|
||
|
windStr = windStr + val + " "<br>
|
||
|
else:<br>
|
||
|
|
||
|
windStr = windStr + val<br>
|
||
|
index += 1<br>
|
||
|
windStr = windStr + " "<br>
|
||
|
return windStr<br>
|
||
|
<br>
|
||
|
def _getWindValue(self, stats):<br>
|
||
|
wind = self.getStats(stats,"Wind")<br>
|
||
|
if wind is None:<br>
|
||
|
val =
|
||
|
" "<br>
|
||
|
else:<br>
|
||
|
mag, dir =
|
||
|
wind<br>
|
||
|
mag =
|
||
|
self.round(mag, "Nearest", 5)<br>
|
||
|
val =
|
||
|
self.getVectorVal((mag,dir))<br>
|
||
|
return val<br>
|
||
|
<br>
|
||
|
</p>
|
||
|
<h2><a name="Answer_to_Smart_Tabular_Exercise_3"></a>Answer to Smart
|
||
|
Tabular Exercise 3</h2>
|
||
|
<p>#
|
||
|
---------------------------------------------------------------------<br>
|
||
|
# This software is in the public domain, furnished "as is", without<br>
|
||
|
# technical support, and with no warranty, express or implied, as
|
||
|
to<br>
|
||
|
# its usefulness for any purpose.<br>
|
||
|
#<br>
|
||
|
# FWFTable_BOU_Overrides.TextUtility<br>
|
||
|
#<br>
|
||
|
# This file is used for WFO specific overrides of the FWFTable<br>
|
||
|
# formatter. <br>
|
||
|
#<br>
|
||
|
#<br>
|
||
|
# Methods:<br>
|
||
|
# Overrides:<br>
|
||
|
#<br>
|
||
|
# Additions:<br>
|
||
|
#<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
<br>
|
||
|
import string, time, re, os, types, copy<br>
|
||
|
import TimeRange<br>
|
||
|
import TextRules<br>
|
||
|
<br>
|
||
|
#**********************************************************************<br>
|
||
|
# MAKE NO CHANGES HERE<br>
|
||
|
# The minimum contents of this file are the following class definition<br>
|
||
|
# and the __init__ method with only "pass" line in it.<br>
|
||
|
<br>
|
||
|
class FWFTable_BOU_Overrides:<br>
|
||
|
def __init__(self):<br>
|
||
|
pass<br>
|
||
|
<br>
|
||
|
# End MAKE NO CHANGES HERE<br>
|
||
|
#**********************************************************************<br>
|
||
|
# Make sure to indent methods inside the class
|
||
|
statement.<br>
|
||
|
#----- WFO BOU FWFTable Overrides -----<br>
|
||
|
<br>
|
||
|
# It is helpful to put a debug statement at the
|
||
|
beginning of each<br>
|
||
|
# method to help with trouble-shooting.<br>
|
||
|
#def _method(self):<br>
|
||
|
#self.debug_print("Debug:
|
||
|
_method in FWFTable_CR_Overrides")<br>
|
||
|
<br>
|
||
|
# Example of Overriding a dictionary from TextRules<br>
|
||
|
#def phrase_descriptor_dict(self, tree, node):<br>
|
||
|
#dict =
|
||
|
TextRules.TextRules.phrase_descriptor_dict(self, tree, node)<br>
|
||
|
#dict["PoP"] = "chance of"<br>
|
||
|
#return dict<br>
|
||
|
<br>
|
||
|
def _rowList(self):<br>
|
||
|
# The rowList is controls
|
||
|
what parameters go into the table.<br>
|
||
|
# The list is a set of
|
||
|
(label:method) pairs.<br>
|
||
|
# You may change the label
|
||
|
if you like.<br>
|
||
|
# The order of the list
|
||
|
determines the order of the rows in the table<br>
|
||
|
# so you may re-arrange the
|
||
|
order if you like.<br>
|
||
|
return [<br>
|
||
|
#
|
||
|
Directive requirements<br>
|
||
|
<br>
|
||
|
#
|
||
|
MODIFICATION: Changing order of Precip and Cloud cover<br>
|
||
|
|
||
|
#("CLOUD COVER", self._cloudCover_row),<br>
|
||
|
|
||
|
#("PRECIP TYPE", self._precipType_row),<br>
|
||
|
|
||
|
("PRECIP TYPE", self._precipType_row),<br>
|
||
|
|
||
|
("CLOUD COVER", self._cloudCover_row),<br>
|
||
|
<br>
|
||
|
|
||
|
("CHANCE PRECIP (%)", self._chancePrecip_row),<br>
|
||
|
|
||
|
("TEMP (24H TREND)", self._tempWithTrend_row),<br>
|
||
|
("RH
|
||
|
% (24H TREND)",self._rhWithTrend_row),<br>
|
||
|
#
|
||
|
Use these if you do not want trends<br>
|
||
|
|
||
|
#("TEMP", self._temp_row),<br>
|
||
|
|
||
|
#("RH %", self._rh_row),<br>
|
||
|
|
||
|
("20FTWND-VAL/AM(MPH)", self._windValleyMph_row),<br>
|
||
|
|
||
|
("20FTWND-RDG/PM(MPH)", self._windRidgeMph_row),<br>
|
||
|
#
|
||
|
Directive optional products<br>
|
||
|
##
|
||
|
("PRECIP AMOUNT", self._precipAmount_row),<br>
|
||
|
##
|
||
|
("PRECIP DURATION", self._precipDuration_row),<br>
|
||
|
##
|
||
|
("PRECIP BEGIN", self._precipBegin_row),<br>
|
||
|
##
|
||
|
("PRECIP END", self._precipEnd_row),<br>
|
||
|
##
|
||
|
("MIXING HGT(M-AGL/MSL)", self._mixHgtM_row),<br>
|
||
|
##
|
||
|
("MIXING HGT(FT-AGL/MSL)", self._mixHgtFt_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (KTS)", self._transWindKts_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (M/S)", self._transWindMS_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (MPH)", self._transWindMph_row),<br>
|
||
|
##
|
||
|
("VENT RATE (KT-FT)", self._ventRateKtFt_row),<br>
|
||
|
##
|
||
|
("VENT RATE (M/S-M)", self._ventRate_row),<br>
|
||
|
##
|
||
|
("DISPERSION", self._dispersion_row),<br>
|
||
|
##
|
||
|
("DSI", self._dsi_row),<br>
|
||
|
##
|
||
|
("SUNSHINE HOURS", self._sunHours_row),<br>
|
||
|
## #
|
||
|
If you need Ceiling, uncomment the Ceiling line in _getAnalysisList<br>
|
||
|
##
|
||
|
("CEILING", self._ceiling_row),<br>
|
||
|
##
|
||
|
("CWR", self._cwr_row),<br>
|
||
|
##
|
||
|
("LAL", self._lal_row),<br>
|
||
|
##
|
||
|
("HAINES INDEX", self._haines_row),<br>
|
||
|
##
|
||
|
("RH RECOVERY", self._rhRecovery_row),<br>
|
||
|
## #
|
||
|
If you need 500m Mix Hgt Temp, uncomment the MixHgt500<br>
|
||
|
## #
|
||
|
line in _getAnalysisList<br>
|
||
|
##
|
||
|
("MIX HGT 500", self._mixHgt500_row),<br>
|
||
|
##
|
||
|
("STABILITY CLASS", self._stability_row),<br>
|
||
|
]<br>
|
||
|
|
||
|
<br>
|
||
|
def _getVariables(self, argDict):<br>
|
||
|
# Make argDict accessible<br>
|
||
|
self.__argDict = argDict<br>
|
||
|
<br>
|
||
|
# Get variables from
|
||
|
VariableList<br>
|
||
|
self._definition =
|
||
|
argDict["forecastDef"]<br>
|
||
|
for key in
|
||
|
self._definition.keys():<br>
|
||
|
exec
|
||
|
"self._" + key + "= self._definition[key]"<br>
|
||
|
<br>
|
||
|
varDict = argDict["varDict"]<br>
|
||
|
self._issuanceType =
|
||
|
varDict["Issuance Type"]<br>
|
||
|
self._productType =
|
||
|
varDict["Forecast Product"]<br>
|
||
|
<br>
|
||
|
# Determine issue time<br>
|
||
|
self._issueTime =
|
||
|
self.IFP().AbsTime.current()<br>
|
||
|
<br>
|
||
|
# Determine expiration time<br>
|
||
|
self._expirationTimeOffset =
|
||
|
12<br>
|
||
|
self._expireTime =
|
||
|
self._issueTime + self._expirationTimeOffset*3600<br>
|
||
|
#self._expireTime =
|
||
|
time.strftime("%d%H%M",time.gmtime(expireTime))<br>
|
||
|
<br>
|
||
|
# Set up product-specific
|
||
|
variables<br>
|
||
|
self._colWidth = 13<br>
|
||
|
if self._columnJustification
|
||
|
== "l":<br>
|
||
|
|
||
|
self._rowLabelWidth = 22<br>
|
||
|
else:<br>
|
||
|
|
||
|
self._rowLabelWidth = 24<br>
|
||
|
self._fixedValueWidth = 13<br>
|
||
|
self._analysisList =
|
||
|
self._getAnalysisList()<br>
|
||
|
<br>
|
||
|
# Calculate current times<br>
|
||
|
<br>
|
||
|
self._ddhhmmTime =
|
||
|
self.getCurrentTime(<br>
|
||
|
|
||
|
argDict, "%d%H%M", shiftToLocal=0, stripLeading=0)<br>
|
||
|
<br>
|
||
|
# MODIFICATION: Changing
|
||
|
format of current time<br>
|
||
|
#self._timeLabel =
|
||
|
self.getCurrentTime(<br>
|
||
|
# argDict,
|
||
|
"%l%M %p %Z %a %b %e %Y", stripLeading=1)<br>
|
||
|
self._timeLabel =
|
||
|
self.getCurrentTime(<br>
|
||
|
|
||
|
argDict, "%b %e %Y %l%M %p %Z %a", stripLeading=1)<br>
|
||
|
<br>
|
||
|
return None<br>
|
||
|
<br>
|
||
|
def _sky(self, statDict, timeRange, argList):<br>
|
||
|
# Return a sky value<br>
|
||
|
sky =
|
||
|
self.getStats(statDict, "Sky")<br>
|
||
|
print "USING OVERRIDDEN SKY
|
||
|
THRESHOLDS"<br>
|
||
|
# MODIFICATION -- Changing
|
||
|
sky thresholds<br>
|
||
|
## if sky is None:<br>
|
||
|
##
|
||
|
value = ""<br>
|
||
|
## elif sky < 10:<br>
|
||
|
##
|
||
|
value = "CLEAR"<br>
|
||
|
## elif sky < 30:<br>
|
||
|
##
|
||
|
value = "MCLEAR"<br>
|
||
|
## elif sky <= 60:<br>
|
||
|
##
|
||
|
value = "PCLDY"<br>
|
||
|
## elif sky <= 80:<br>
|
||
|
##
|
||
|
value = "MCLDY"<br>
|
||
|
## else:<br>
|
||
|
##
|
||
|
value = "CLOUDY"<br>
|
||
|
if sky is None:<br>
|
||
|
|
||
|
value = ""<br>
|
||
|
elif sky < 15:<br>
|
||
|
|
||
|
value = "CLEAR"<br>
|
||
|
elif sky < 40:<br>
|
||
|
|
||
|
value = "MCLEAR"<br>
|
||
|
elif sky <= 70:<br>
|
||
|
|
||
|
value = "PCLDY"<br>
|
||
|
elif sky <= 85:<br>
|
||
|
|
||
|
value = "MCLDY"<br>
|
||
|
else:<br>
|
||
|
|
||
|
value = "CLOUDY"<br>
|
||
|
return value<br>
|
||
|
<br>
|
||
|
</p>
|
||
|
<h2><a name="Answer_to_Smart_Tabular_Exercise_4"></a>Answer to Smart
|
||
|
Tabular Exercise 4</h2>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
# This software is in the public domain, furnished "as is", without<br>
|
||
|
# technical support, and with no warranty, express or implied, as
|
||
|
to<br>
|
||
|
# its usefulness for any purpose.<br>
|
||
|
#<br>
|
||
|
# FWFTable_BOU_Definition.TextUtility<br>
|
||
|
#<br>
|
||
|
# This file sets up all the Product Definition overrides for the <br>
|
||
|
# FWFTable formatter for a site. <br>
|
||
|
#<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
<br>
|
||
|
#**********************************************************************<br>
|
||
|
# MAKE NO CHANGES HERE<br>
|
||
|
# The minimum content of this file is the following Definition statement<br>
|
||
|
<br>
|
||
|
Definition = {}<br>
|
||
|
<br>
|
||
|
# End MAKE NO CHANGES HERE<br>
|
||
|
#**********************************************************************<br>
|
||
|
#####################################################<br>
|
||
|
# Override VariableList if desired<br>
|
||
|
#<br>
|
||
|
#VariableList = []<br>
|
||
|
<br>
|
||
|
#----- WFO BOU FWFTable Definition -----<br>
|
||
|
# Definition Statements must start in column 1.<br>
|
||
|
<br>
|
||
|
# REQUIRED CONFIGURATION ITEMS <br>
|
||
|
Definition['displayName'] = None<br>
|
||
|
#Definition['displayName'] = "FWF_Tabular"<br>
|
||
|
<br>
|
||
|
Definition["defaultEditAreas"] = "Combinations_FWFTable_BOU"<br>
|
||
|
Definition["mapNameForCombinations"] = "FireWxZones_BOU" # Map
|
||
|
background for creating Combinations<br>
|
||
|
<br>
|
||
|
# MODIFICATION -- Added gustWindDifferenceThreshold<br>
|
||
|
Definition["gustWindDifferenceThreshold"] = 15<br>
|
||
|
<br>
|
||
|
<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
# This software is in the public domain, furnished "as is", without<br>
|
||
|
# technical support, and with no warranty, express or implied, as
|
||
|
to<br>
|
||
|
# its usefulness for any purpose.<br>
|
||
|
#<br>
|
||
|
# FWFTable_BOU_Overrides.TextUtility<br>
|
||
|
#<br>
|
||
|
# This file is used for WFO specific overrides of the FWFTable<br>
|
||
|
# formatter. <br>
|
||
|
#<br>
|
||
|
#<br>
|
||
|
# Methods:<br>
|
||
|
# Overrides:<br>
|
||
|
#<br>
|
||
|
# Additions:<br>
|
||
|
#<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
<br>
|
||
|
import string, time, re, os, types, copy<br>
|
||
|
import TimeRange<br>
|
||
|
import TextRules<br>
|
||
|
<br>
|
||
|
#**********************************************************************<br>
|
||
|
# MAKE NO CHANGES HERE<br>
|
||
|
# The minimum contents of this file are the following class definition<br>
|
||
|
# and the __init__ method with only "pass" line in it.<br>
|
||
|
<br>
|
||
|
class FWFTable_BOU_Overrides:<br>
|
||
|
def __init__(self):<br>
|
||
|
pass<br>
|
||
|
<br>
|
||
|
# End MAKE NO CHANGES HERE<br>
|
||
|
#**********************************************************************<br>
|
||
|
# Make sure to indent methods inside the class
|
||
|
statement.<br>
|
||
|
#----- WFO BOU FWFTable Overrides -----<br>
|
||
|
<br>
|
||
|
# It is helpful to put a debug statement at the
|
||
|
beginning of each<br>
|
||
|
# method to help with trouble-shooting.<br>
|
||
|
#def _method(self):<br>
|
||
|
#self.debug_print("Debug:
|
||
|
_method in FWFTable_CR_Overrides")<br>
|
||
|
<br>
|
||
|
# Example of Overriding a dictionary from TextRules<br>
|
||
|
#def phrase_descriptor_dict(self, tree, node):<br>
|
||
|
#dict =
|
||
|
TextRules.TextRules.phrase_descriptor_dict(self, tree, node)<br>
|
||
|
#dict["PoP"] = "chance of"<br>
|
||
|
#return dict<br>
|
||
|
<br>
|
||
|
def _rowList(self):<br>
|
||
|
# The rowList is controls
|
||
|
what parameters go into the table.<br>
|
||
|
# The list is a set of
|
||
|
(label:method) pairs.<br>
|
||
|
# You may change the label
|
||
|
if you like.<br>
|
||
|
# The order of the list
|
||
|
determines the order of the rows in the table<br>
|
||
|
# so you may re-arrange the
|
||
|
order if you like.<br>
|
||
|
return [<br>
|
||
|
#
|
||
|
Directive requirements<br>
|
||
|
<br>
|
||
|
|
||
|
("CLOUD COVER", self._cloudCover_row),<br>
|
||
|
|
||
|
("PRECIP TYPE",
|
||
|
self._precipType_row),
|
||
|
<br>
|
||
|
|
||
|
("CHANCE PRECIP (%)", self._chancePrecip_row),<br>
|
||
|
|
||
|
("TEMP (24H TREND)", self._tempWithTrend_row),<br>
|
||
|
("RH
|
||
|
% (24H TREND)",self._rhWithTrend_row),<br>
|
||
|
#
|
||
|
Use these if you do not want trends<br>
|
||
|
|
||
|
#("TEMP", self._temp_row),<br>
|
||
|
|
||
|
#("RH %", self._rh_row),<br>
|
||
|
|
||
|
("20FTWND-VAL/AM(MPH)", self._windValleyMph_row),<br>
|
||
|
|
||
|
("20FTWND-RDG/PM(MPH)", self._windRidgeMph_row),<br>
|
||
|
#
|
||
|
Directive optional products<br>
|
||
|
<br>
|
||
|
#
|
||
|
MODIFICATION -- Added Wind Gust row<br>
|
||
|
|
||
|
("WIND
|
||
|
GUST",
|
||
|
self._windGust_row),<br>
|
||
|
<br>
|
||
|
##
|
||
|
("PRECIP AMOUNT", self._precipAmount_row),<br>
|
||
|
##
|
||
|
("PRECIP DURATION", self._precipDuration_row),<br>
|
||
|
##
|
||
|
("PRECIP BEGIN", self._precipBegin_row),<br>
|
||
|
##
|
||
|
("PRECIP END", self._precipEnd_row),<br>
|
||
|
##
|
||
|
("MIXING HGT(M-AGL/MSL)", self._mixHgtM_row),<br>
|
||
|
##
|
||
|
("MIXING HGT(FT-AGL/MSL)", self._mixHgtFt_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (KTS)", self._transWindKts_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (M/S)", self._transWindMS_row),<br>
|
||
|
##
|
||
|
("TRANSPORT WND (MPH)", self._transWindMph_row),<br>
|
||
|
##
|
||
|
("VENT RATE (KT-FT)", self._ventRateKtFt_row),<br>
|
||
|
##
|
||
|
("VENT RATE (M/S-M)", self._ventRate_row),<br>
|
||
|
##
|
||
|
("DISPERSION", self._dispersion_row),<br>
|
||
|
##
|
||
|
("DSI", self._dsi_row),<br>
|
||
|
##
|
||
|
("SUNSHINE HOURS", self._sunHours_row),<br>
|
||
|
## #
|
||
|
If you need Ceiling, uncomment the Ceiling line in _getAnalysisList<br>
|
||
|
##
|
||
|
("CEILING", self._ceiling_row),<br>
|
||
|
##
|
||
|
("CWR", self._cwr_row),<br>
|
||
|
##
|
||
|
("LAL", self._lal_row),<br>
|
||
|
##
|
||
|
("HAINES INDEX", self._haines_row),<br>
|
||
|
##
|
||
|
("RH RECOVERY", self._rhRecovery_row),<br>
|
||
|
## #
|
||
|
If you need 500m Mix Hgt Temp, uncomment the MixHgt500<br>
|
||
|
## #
|
||
|
line in _getAnalysisList<br>
|
||
|
##
|
||
|
("MIX HGT 500", self._mixHgt500_row),<br>
|
||
|
##
|
||
|
("STABILITY CLASS", self._stability_row),<br>
|
||
|
]<br>
|
||
|
<br>
|
||
|
def _getAnalysisList(self):<br>
|
||
|
return[<br>
|
||
|
("Sky",
|
||
|
self.avg),<br>
|
||
|
("PoP",
|
||
|
self.stdDevMaxAvg),<br>
|
||
|
("Wx",
|
||
|
self.dominantWx, [12]),<br>
|
||
|
("Wx",
|
||
|
self.dominantWx, [0]),<br>
|
||
|
("MaxT",
|
||
|
self.minMax),<br>
|
||
|
("MinT",
|
||
|
self.minMax),<br>
|
||
|
("T",
|
||
|
self.minMax),<br>
|
||
|
("Wind",
|
||
|
self.vectorAvg, [6]),<br>
|
||
|
("Wind20ft",
|
||
|
self.vectorAvg, [6]),<br>
|
||
|
("QPF",
|
||
|
self.minMaxSum),<br>
|
||
|
("MaxRH",
|
||
|
self.minMax),<br>
|
||
|
("MinRH",
|
||
|
self.minMax),<br>
|
||
|
("RH",
|
||
|
self.minMax),<br>
|
||
|
("MixHgt",
|
||
|
self.minMax, [0]),<br>
|
||
|
("TransWind",
|
||
|
self.vectorAvg, [0]),<br>
|
||
|
("VentRate",
|
||
|
self.minMax, [0]), # aka "Dispersion" prior to RPP20<br>
|
||
|
("DSI",
|
||
|
self.avg), <br>
|
||
|
("HrsOfSun",
|
||
|
self.avg),<br>
|
||
|
# Uncomment the
|
||
|
next line if you're carrying Cig Height<br>
|
||
|
#("Ceiling",
|
||
|
self.minMax),<br>
|
||
|
("CWR",
|
||
|
self.stdDevMaxAvg),<br>
|
||
|
("Haines",
|
||
|
self.minMaxAvg),<br>
|
||
|
("LAL",
|
||
|
self.maximum),<br>
|
||
|
("Ttrend",
|
||
|
self.minMax),<br>
|
||
|
("RHtrend",
|
||
|
self.minMax),<br>
|
||
|
("Stability",
|
||
|
self.avg),<br>
|
||
|
# Uncomment the
|
||
|
next line if you're carrying 500m mix height temp<br>
|
||
|
#("MixHgt500",
|
||
|
self.avg),<br>
|
||
|
<br>
|
||
|
# MODIFICATION
|
||
|
-- Added entries for Wind Gust<br>
|
||
|
("WindGust",
|
||
|
self.minMax),<br>
|
||
|
("Wind",
|
||
|
self.vectorMinMax),<br>
|
||
|
("Wind20ft",
|
||
|
self.vectorMinMax),<br>
|
||
|
]<br>
|
||
|
<br>
|
||
|
def _windGust_row(self, fcst, label, statList,
|
||
|
priorStatDict):<br>
|
||
|
fcst = fcst + self.makeRow(<br>
|
||
|
|
||
|
label, self._colWidth, self._timeRangeList, statList,<br>
|
||
|
|
||
|
self._windGust, None, self._rowLabelWidth, self._fixedValueWidth, <br>
|
||
|
|
||
|
self._columnJustification)<br>
|
||
|
return fcst<br>
|
||
|
<br>
|
||
|
def _windGust(self, statDict, timeRange, argList):<br>
|
||
|
# Use Wind20ft if available,
|
||
|
otherwise adjust Wind<br>
|
||
|
# Stats vectorAvg<br>
|
||
|
<br>
|
||
|
# See if there is any
|
||
|
WindGust data<br>
|
||
|
windGust =
|
||
|
self.getStats(statDict, "WindGust")<br>
|
||
|
if windGust is None:<br>
|
||
|
|
||
|
return ""<br>
|
||
|
<br>
|
||
|
# Get the wind information
|
||
|
and adjust if using Wind instead<br>
|
||
|
# of Wind20ft<br>
|
||
|
windStats =
|
||
|
self.getStats(statDict,"Wind20ft__vectorMinMax")<br>
|
||
|
if windStats is None:<br>
|
||
|
|
||
|
windStats = self.getStats(statDict,"Wind__vectorMinMax")<br>
|
||
|
if
|
||
|
windStats is None:<br>
|
||
|
|
||
|
return ""<br>
|
||
|
mag,
|
||
|
dir = windStats<br>
|
||
|
|
||
|
maxWind = self.getValue(mag, "Max")<br>
|
||
|
|
||
|
maxWind = maxWind * self._windAdjustmentFactor<br>
|
||
|
|
||
|
windStats = (maxWind, dir)<br>
|
||
|
<br>
|
||
|
# Check the
|
||
|
gustWindDifferenceThreshold<br>
|
||
|
mag, dir = windStats<br>
|
||
|
maxWind = self.getValue(mag,
|
||
|
"Max")<br>
|
||
|
maxGust =
|
||
|
self.getValue(windGust, "Max")<br>
|
||
|
if maxGust - maxWind <=
|
||
|
self._gustWindDifferenceThreshold:<br>
|
||
|
|
||
|
return ""<br>
|
||
|
else:<br>
|
||
|
|
||
|
return self.getScalarVal(maxGust) <br>
|
||
|
<br>
|
||
|
<br>
|
||
|
<a name="Answer_to_Phrase_Exercise_1"></a>Answer to Phrase Exercise 1<br>
|
||
|
<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
# This software is in the public domain, furnished "as is", without<br>
|
||
|
# technical support, and with no warranty, express or implied, as
|
||
|
to<br>
|
||
|
# its usefulness for any purpose.<br>
|
||
|
#<br>
|
||
|
# ZFP_BOU_Overrides.TextUtility<br>
|
||
|
#<br>
|
||
|
# This file is used for WFO specific overrides of the ZFP<br>
|
||
|
# formatter. <br>
|
||
|
#<br>
|
||
|
#<br>
|
||
|
# Methods:<br>
|
||
|
# Overrides:<br>
|
||
|
#<br>
|
||
|
# Additions:<br>
|
||
|
#<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
<br>
|
||
|
import string, time, re, os, types, copy<br>
|
||
|
import TimeRange<br>
|
||
|
import TextRules<br>
|
||
|
<br>
|
||
|
#**********************************************************************<br>
|
||
|
# MAKE NO CHANGES HERE<br>
|
||
|
# The minimum contents of this file are the following class definition<br>
|
||
|
# and the __init__ method with only "pass" line in it.<br>
|
||
|
<br>
|
||
|
class ZFP_BOU_Overrides:<br>
|
||
|
def __init__(self):<br>
|
||
|
pass<br>
|
||
|
<br>
|
||
|
# End MAKE NO CHANGES HERE<br>
|
||
|
#**********************************************************************<br>
|
||
|
# Make sure to indent methods inside the class
|
||
|
statement.<br>
|
||
|
#----- WFO BOU ZFP Overrides -----<br>
|
||
|
<br>
|
||
|
# It is helpful to put a debug statement at the
|
||
|
beginning of each<br>
|
||
|
# method to help with trouble-shooting.<br>
|
||
|
#def _method(self):<br>
|
||
|
#self.debug_print("Debug:
|
||
|
_method in ZFP_CR_Overrides")<br>
|
||
|
<br>
|
||
|
# Example of Overriding a dictionary from TextRules<br>
|
||
|
#def phrase_descriptor_dict(self, tree, node):<br>
|
||
|
#dict =
|
||
|
TextRules.TextRules.phrase_descriptor_dict(self, tree, node)<br>
|
||
|
#dict["PoP"] = "chance of"<br>
|
||
|
#return dict<br>
|
||
|
<br>
|
||
|
def snow_words(self, tree, node):<br>
|
||
|
"Create phrase for snow
|
||
|
accumulation"<br>
|
||
|
<br>
|
||
|
# First check if the pop
|
||
|
threshold has been met.<br>
|
||
|
# If not, then do not
|
||
|
generate phrase.<br>
|
||
|
threshold =
|
||
|
self.pop_snow_lower_threshold(tree, node)<br>
|
||
|
lowPopFlag =
|
||
|
self.lowPop_flag(tree, node, threshold)<br>
|
||
|
if lowPopFlag == 1:<br>
|
||
|
|
||
|
return self.setWords(node, "")<br>
|
||
|
<br>
|
||
|
# Second, check to see if it
|
||
|
is snowing based on a configurable<br>
|
||
|
# list called
|
||
|
accumulatingWx. If not, then do not generate phrase.<br>
|
||
|
timeRange =
|
||
|
node.getTimeRange()<br>
|
||
|
areaLabel =
|
||
|
node.getAreaLabel()<br>
|
||
|
wxStats =
|
||
|
tree.stats.get("Wx", timeRange, areaLabel, mergeMethod="List")<br>
|
||
|
if wxStats is None:<br>
|
||
|
|
||
|
return self.setWords(node, "")<br>
|
||
|
accumulatingWx = ['S', 'SW',
|
||
|
'IP', 'IC']<br>
|
||
|
accumulatingWxFlag = 0<br>
|
||
|
for rankList, tr in wxStats:<br>
|
||
|
|
||
|
subkeys = self.getSubkeys(rankList)<br>
|
||
|
for
|
||
|
subkey in subkeys:<br>
|
||
|
|
||
|
if subkey.wxType() in accumulatingWx:<br>
|
||
|
|
||
|
accumulatingWxFlag = 1<br>
|
||
|
if accumulatingWxFlag == 0:<br>
|
||
|
|
||
|
return self.setWords(node, "")<br>
|
||
|
<br>
|
||
|
# Third, load in the SnowAmt
|
||
|
statistics.<br>
|
||
|
threshold = 1<br>
|
||
|
statDict = node.getStatDict()<br>
|
||
|
stats =
|
||
|
self.getStats(statDict, "SnowAmt")<br>
|
||
|
if stats is None:<br>
|
||
|
|
||
|
return self.setWords(node, "") <br>
|
||
|
min, max =
|
||
|
self.getValue(stats, "MinMax")<br>
|
||
|
<br>
|
||
|
# Fourth, round accumulation
|
||
|
and create accumulation strings.<br>
|
||
|
if min%1 == 0:<br>
|
||
|
min
|
||
|
= int(min)<br>
|
||
|
|
||
|
minStr = `min`<br>
|
||
|
else:<br>
|
||
|
|
||
|
minStr = `int(min+0.5)`<br>
|
||
|
if max%1 == 0:<br>
|
||
|
max
|
||
|
= int(max)<br>
|
||
|
|
||
|
maxStr = `max`<br>
|
||
|
else:<br>
|
||
|
|
||
|
maxStr = `int(max+0.5)`<br>
|
||
|
<br>
|
||
|
#print "min, max", min, max,
|
||
|
node.getTimeRange(), node.getAreaLabel()<br>
|
||
|
<br>
|
||
|
# Finally, generate the snow
|
||
|
accumulation phrase. <br>
|
||
|
if min == 0 and max == 0:<br>
|
||
|
|
||
|
return self.setWords(node,"no")<br>
|
||
|
elif min < 0.5 and max
|
||
|
< 0.5:<br>
|
||
|
|
||
|
return self.setWords(node,"little or no")<br>
|
||
|
<br>
|
||
|
outUnits =
|
||
|
self.element_outUnits(tree, node, "SnowAmt", "SnowAmt")<br>
|
||
|
unit =
|
||
|
self.units_descriptor(tree, node,"unit", outUnits)<br>
|
||
|
units =
|
||
|
self.units_descriptor(tree, node,"units", outUnits)<br>
|
||
|
min = int(min+0.5)<br>
|
||
|
max = int(max+0.5)<br>
|
||
|
|
||
|
<br>
|
||
|
# Single Value input<br>
|
||
|
if min == max:<br>
|
||
|
#
|
||
|
Handle case of 1 inch<br>
|
||
|
if
|
||
|
min == 1:<br>
|
||
|
|
||
|
units = unit<br>
|
||
|
|
||
|
value = "around " + minStr<br>
|
||
|
<br>
|
||
|
# Range<br>
|
||
|
else:<br>
|
||
|
|
||
|
value = "of " + minStr + "-" + maxStr<br>
|
||
|
#
|
||
|
Handle case when lower value is 0<br>
|
||
|
if
|
||
|
min == 0:<br>
|
||
|
|
||
|
value = "up to " + maxStr<br>
|
||
|
if
|
||
|
max == 1:<br>
|
||
|
|
||
|
units = unit<br>
|
||
|
|
||
|
<br>
|
||
|
snowPhrase = value + " " +
|
||
|
units <br>
|
||
|
return self.setWords(node,
|
||
|
snowPhrase)<br>
|
||
|
<br>
|
||
|
<a name="Answer_to_Phrase_Exercise_4_"></a>Answer to Phrase Exercise 4<br>
|
||
|
<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
# This software is in the public domain, furnished "as is", without<br>
|
||
|
# technical support, and with no warranty, express or implied, as
|
||
|
to<br>
|
||
|
# its usefulness for any purpose.<br>
|
||
|
#<br>
|
||
|
# ZFP_BOU_Overrides.TextUtility<br>
|
||
|
#<br>
|
||
|
# This file is used for WFO specific overrides of the ZFP<br>
|
||
|
# formatter. <br>
|
||
|
#<br>
|
||
|
#<br>
|
||
|
# Methods:<br>
|
||
|
# Overrides:<br>
|
||
|
#<br>
|
||
|
# Additions:<br>
|
||
|
#<br>
|
||
|
# ---------------------------------------------------------------------<br>
|
||
|
<br>
|
||
|
import string, time, re, os, types, copy<br>
|
||
|
import TimeRange<br>
|
||
|
import TextRules<br>
|
||
|
<br>
|
||
|
#**********************************************************************<br>
|
||
|
# MAKE NO CHANGES HERE<br>
|
||
|
# The minimum contents of this file are the following class definition<br>
|
||
|
# and the __init__ method with only "pass" line in it.<br>
|
||
|
<br>
|
||
|
class ZFP_BOU_Overrides:<br>
|
||
|
def __init__(self):<br>
|
||
|
pass<br>
|
||
|
<br>
|
||
|
# End MAKE NO CHANGES HERE<br>
|
||
|
#**********************************************************************<br>
|
||
|
# Make sure to indent methods inside the class
|
||
|
statement.<br>
|
||
|
#----- WFO BOU ZFP Overrides -----<br>
|
||
|
<br>
|
||
|
# It is helpful to put a debug statement at the
|
||
|
beginning of each<br>
|
||
|
# method to help with trouble-shooting.<br>
|
||
|
#def _method(self):<br>
|
||
|
#self.debug_print("Debug:
|
||
|
_method in ZFP_CR_Overrides")<br>
|
||
|
<br>
|
||
|
# Example of Overriding a dictionary from TextRules<br>
|
||
|
#def phrase_descriptor_dict(self, tree, node):<br>
|
||
|
#dict =
|
||
|
TextRules.TextRules.phrase_descriptor_dict(self, tree, node)<br>
|
||
|
#dict["PoP"] = "chance of"<br>
|
||
|
#return dict<br>
|
||
|
<br>
|
||
|
def phrase_descriptor_dict(self, tree, node):<br>
|
||
|
# Descriptors for phrases<br>
|
||
|
dict =
|
||
|
TextRules.TextRules.phrase_descriptor_dict(self, tree, node)<br>
|
||
|
# This is the default.
|
||
|
Triggers if ALL coverage terms are areal<br>
|
||
|
#dict["PoP"] =
|
||
|
self.allAreal_or_chance_pop_descriptor,<br>
|
||
|
# Uncomment this line for
|
||
|
invoking areal or chance pop descriptor<br>
|
||
|
# Triggers
|
||
|
if ANY coverage terms are areal<br>
|
||
|
#dict["PoP"] =
|
||
|
self.areal_or_chance_pop_descriptor,<br>
|
||
|
# Uncomment this line to use
|
||
|
"chance" descriptor in all cases<br>
|
||
|
#dict["PoP"] = "chance of"<br>
|
||
|
dict["QPF"] = "qualitative
|
||
|
precipitation"<br>
|
||
|
return dict<br>
|
||
|
<br>
|
||
|
<br>
|
||
|
def qpf_phrase(self):<br>
|
||
|
return {<br>
|
||
|
|
||
|
"setUpMethod": self.qpf_setUp,<br>
|
||
|
|
||
|
"wordMethod": self.qpf_words,<br>
|
||
|
|
||
|
"phraseMethods": self.standard_phraseMethods() <br>
|
||
|
|
||
|
} <br>
|
||
|
def qpf_setUp(self, tree, node):<br>
|
||
|
elementInfoList =
|
||
|
[self.ElementInfo("QPF", "List")]<br>
|
||
|
self.subPhraseSetUp(tree,
|
||
|
node, elementInfoList,
|
||
|
self.scalarConnector) <br>
|
||
|
return self.DONE()<br>
|
||
|
<br>
|
||
|
def qpf_words(self, tree, node) :<br>
|
||
|
"Create phrase for QPF"<br>
|
||
|
# Wait for weather phrase to
|
||
|
complete<br>
|
||
|
statDict = node.getStatDict()<br>
|
||
|
qpf =
|
||
|
self.getStats(statDict, "QPF")<br>
|
||
|
if qpf is None:<br>
|
||
|
|
||
|
return self.setWords(node, "")<br>
|
||
|
<br>
|
||
|
# Analysis-driven<br>
|
||
|
min, max =
|
||
|
self.getValue(qpf, "MinMax")<br>
|
||
|
units =
|
||
|
self.units_descriptor(tree, node, "units", "in")<br>
|
||
|
min = int(min)<br>
|
||
|
max = int(max)<br>
|
||
|
minStr = self.fformat(min,
|
||
|
.01)<br>
|
||
|
maxStr = self.fformat(max,
|
||
|
.01)<br>
|
||
|
#print "min, max", min, max<br>
|
||
|
if min==max:<br>
|
||
|
|
||
|
words = minStr + " " + units<br>
|
||
|
else:<br>
|
||
|
|
||
|
words =minStr + "-" + maxStr + " " + units<br>
|
||
|
<br>
|
||
|
return self.setWords(node,
|
||
|
words)<br>
|
||
|
<br>
|
||
|
def Period_1(self):<br>
|
||
|
component = { <br>
|
||
|
|
||
|
"type": "component",<br>
|
||
|
|
||
|
"methodList": [<br>
|
||
|
|
||
|
self.orderPhrases,<br>
|
||
|
|
||
|
self.assemblePhrases, <br>
|
||
|
|
||
|
self.wordWrap, <br>
|
||
|
|
||
|
],<br>
|
||
|
|
||
|
"analysisList": [<br>
|
||
|
|
||
|
#("MinT", self.avg),<br>
|
||
|
|
||
|
#("MaxT", self.avg),<br>
|
||
|
|
||
|
("MinT", self.stdDevMinMax),<br>
|
||
|
|
||
|
("MaxT", self.stdDevMinMax),<br>
|
||
|
|
||
|
("T", self.hourlyTemp),<br>
|
||
|
|
||
|
("T", self.minMax),<br>
|
||
|
|
||
|
("Sky", self.median, [3]),<br>
|
||
|
|
||
|
("PoP", self._PoP_analysisMethod("Period_1"), [3]),<br>
|
||
|
|
||
|
("PoP", self.binnedPercent, [3]),<br>
|
||
|
|
||
|
("SnowAmt", self.accumMinMax),<br>
|
||
|
|
||
|
("StormTotalSnow", self.accumMinMax),<br>
|
||
|
|
||
|
("IceAccum", self.accumMinMax),<br>
|
||
|
|
||
|
("SnowLevel", self.avg),<br>
|
||
|
|
||
|
("Wind", self.vectorMedianRange, [6]),<br>
|
||
|
|
||
|
("Wind", self.vectorMinMax, [6]),<br>
|
||
|
|
||
|
("WindGust", self.maximum, [6]),<br>
|
||
|
|
||
|
("Wx", self.rankedWx, [3]),<br>
|
||
|
|
||
|
("WindChill", self.minMax, [6]),<br>
|
||
|
|
||
|
("HeatIndex", self.minMax, [6]),<br>
|
||
|
|
||
|
("QPF", self.accumMinMax, [6]),<br>
|
||
|
|
||
|
],<br>
|
||
|
|
||
|
"phraseList":[<br>
|
||
|
|
||
|
self.sky_phrase,<br>
|
||
|
|
||
|
self.skyPopWx_phrase,<br>
|
||
|
|
||
|
self.wind_summary,<br>
|
||
|
|
||
|
self.reportTrends,<br>
|
||
|
|
||
|
self.weather_phrase,<br>
|
||
|
|
||
|
self.severeWeather_phrase,<br>
|
||
|
|
||
|
self.heavyPrecip_phrase,<br>
|
||
|
|
||
|
self.visibility_phrase,<br>
|
||
|
|
||
|
self.snow_phrase,<br>
|
||
|
|
||
|
self.total_snow_phrase,<br>
|
||
|
|
||
|
self.snowLevel_phrase,<br>
|
||
|
|
||
|
self.iceAccumulation_phrase,<br>
|
||
|
|
||
|
self.highs_phrase,<br>
|
||
|
|
||
|
self.lows_phrase,<br>
|
||
|
|
||
|
#self.highs_range_phrase,<br>
|
||
|
|
||
|
#self.lows_range_phrase,<br>
|
||
|
|
||
|
self.temp_trends,<br>
|
||
|
|
||
|
self.wind_withGusts_phrase,<br>
|
||
|
|
||
|
self.lake_wind_phrase,<br>
|
||
|
|
||
|
self.popMax_phrase,<br>
|
||
|
|
||
|
self.windChill_phrase,<br>
|
||
|
|
||
|
# Alternative<br>
|
||
|
|
||
|
#self.windBased_windChill_phrase,<br>
|
||
|
|
||
|
self.heatIndex_phrase,<br>
|
||
|
|
||
|
self.qpf_phrase,<br>
|
||
|
|
||
|
],<br>
|
||
|
##
|
||
|
"additionalAreas": [ <br>
|
||
|
##
|
||
|
# Areas listed by weather element that will be<br>
|
||
|
##
|
||
|
# sampled and analysed.<br>
|
||
|
##
|
||
|
# E.g. used for reporting population centers for temperatures. <br>
|
||
|
##
|
||
|
("MaxT", ["City1", "City2"]),<br>
|
||
|
##
|
||
|
("MinT", ["City1", "City2"]),<br>
|
||
|
##
|
||
|
],<br>
|
||
|
##
|
||
|
"intersectAreas": [ <br>
|
||
|
##
|
||
|
# Areas listed by weather element that will be<br>
|
||
|
##
|
||
|
# intersected with the current area then<br>
|
||
|
##
|
||
|
# sampled and analysed. <br>
|
||
|
##
|
||
|
# E.g. used in local effects methods.<br>
|
||
|
##
|
||
|
("MaxT", ["Mountains"]),<br>
|
||
|
##
|
||
|
("MinT", ["Valleys"]),<br>
|
||
|
##
|
||
|
],<br>
|
||
|
}<br>
|
||
|
if self._arealSkyAnalysis:<br>
|
||
|
|
||
|
component["analysisList"].append(("Sky", self.binnedPercent, [6]))<br>
|
||
|
if self._useStormTotalSnow:<br>
|
||
|
|
||
|
phraseList = component["phraseList"]<br>
|
||
|
|
||
|
index = phraseList.index(self.total_snow_phrase)<br>
|
||
|
|
||
|
phraseList[index] = self.stormTotalSnow_phrase<br>
|
||
|
|
||
|
component["phraseList"] = phraseList<br>
|
||
|
return
|
||
|
component <br>
|
||
|
<p></p>
|