LDAD Ingest Manual

written by Christopher E. Steffen, Ph.D.


Contents:

1) Introduction

2) Diagrams

2.a) Data Flow Diagram

2.b) Text Ingest Sequence Diagram

2.c) Non-text Ingest Sequence Diagram

2.d) Client Sequence Diagram

2.e) Overview Client Block Diagram

2.f) Detailed Client Block Diagram

3) Website Files Layout

3.a) Web Pages

3.b) Install

3.c) Applications

3.d) Data

3.e) Monitor

4) Purpose of PollForData

5) Purpose of the Dynamic Data Format Converter

6) How the Client uses the data on the website

7) Adding Static Data to the website

7.a) Shapefile

7.b) Image

7.c) Icon

7.d) Observation Station location and geographical information files

8) Adding Static Data Exercise.

9) Testing Static Data.

10) Removing Static Data

11) Troubleshooting Static Data

12) Adding Dynamic Data to the website

12.a) Adding Supported Dynamic Data Types to the website

12.a.1) Creating the Object Definition Files

12.a.1.a) ODEF File Structure Top Down Overview

12.a.1.b) Individual Object Definition (ODEF) Files for supported data types

12.a.1.b.1) Analysis Grid and Forecast Grid

12.a.1.b.2) Radar Polar Grid

12.a.1.b.3) Text Product

12.a.1.b.4) Graphical Forecast Editor (GFE) Forecast Grid

12.a.1.b.5) Observation Station data

12.a.1.b.6) Quality Control Observation Station Data

12.a.2) NetCDFvariables Object Definition (ODEF) Files

12.a.3) Factor Mill Object Definition (ODEF) Files

12.a.3.a) GridFactorMill

12.a.3.b) TextFactorMill

12.a.3.c) StreamMill

12.a.3.d) ObsFactorMill

12.a.4) Ingest Object Definition (ODEF) Files

12.a.2) Compiling the Object Definition files (odef) into Configuration Files (cnf)

12.a.3) Editing PollForData.cnf

12.a.4) Running Menu Configurator to update the menu items

12.a.5) Installing *.cnf files on the runtime system

12.b) Adding Unsupported Dynamic Data Types to the website and client

13) Text: Configuring maximum expiration time

14) Enabling Graphical Forecast Editor (GFE) dissemination

15) Adding Dynamic Data Exercises

16) Testing Dynamic Data

17) Removing Dynamic Data

18) Troubleshooting Dynamic Data

18.a) Data Flow Troubleshooting

18.b) Reading the INDEX.dat File

18.c) Reading Compressed Radar, Grid, and Text data files

19) Software Module's Application Programming Interface (API)


Introduction:

The LDAD Ingest Manual documents how to add new data to the website. The data can be subdivided into two catagories: 1) Static data, and 2) Dynamic data. Static data refers to shapefile maps, gif or jpeg images, and icons for the icon maps. Dynamic data refers to Analysis Grids, Radar Polar Grids, Text Products, Forecast Grids, Graphical Forecast Editor (GFE) Forecast Grids, and Observation Station data. Each reinstallation will wipe out what was added previously unless the additions have been incorporated into the build process.

Data Flow Diagram:


Fig. 1: Data Flow Diagram.

Fig. 2: Text Ingest Sequence Diagram


Fig. 3: Non-text Ingest Sequence Diagram.


Fig. 4: Client Sequence Diagram.


Fig. 5: Overview Client Block Diagram.


Fig. 6: Detailed Client Block Diagram.




Website Files Layout:

There are provisions for two LDAD websites on the "ls" computer. The first is located at "data/ldad/emwww/htdocs/" and typically has a website name of "http://ls1-???.noaa.gov/". The second is located at "data/ldad/pubwww/htdocs/" and typically has a website name of "http://www-???.noaa.gov/". The first website is configured with Username/Password restrictions for the emergency managers. The second website is configured unrestricted for the general public. Having two different web servers running allows the web site administrator to set the number of daemon threads allowed on each web server ensuring that the Emergency Managers can always access the website.

Web Pages:

index.html

"/data/ldad/emwww/htdocs/index.html" initial web page with table of contents on left.

index_em.html

"/data/ldad/emwww/htdocs/index_em.html" copy of initial web page but is not used.

main_em.html

"/data/ldad/emwww/htdocs/main_em.html" is the top web page frame.

toc_em.html

"/data/ldad/emwww/htdocs/toc_em.html" is the table of contents in left web page frame.

overview_em.html

"/data/ldad/emwww/htdocs/overview_em.html" is the overview web page see initial web page table of contents.

reqs_application.html

"/data/ldad/emwww/htdocs/reqs_application.html" is the requirements web page see initial web page table of contents.

contact.html

"/data/ldad/emwww/htdocs/contact.html" is the contact web page see initial web page bottom frame.

dialin.html

"/data/ldad/emwww/htdocs/dialin.html" is the dialin web page see initial web page table of contents.

FAQ.html

"/data/ldad/emwww/htdocs/FAQ.html" is the FAQ web page see initial web page table of contents.

download.html

"/data/ldad/emwww/htdocs/download.html" defines the download page see initial web page table of contents.

feedback.html

"/data/ldad/emwww/htdocs/feedback.html" feedback web page see initial web page table of contents.

user-survey*.html

"/data/ldad/emwww/htdocs/user-survey*.html" contains a user survey see initial web page table of contents.

display.html

"/data/ldad/emwww/htdocs/display.html" contains the web page which has the start button for the applet and downloads the jar files. See initial web page table of contents.

displayclass.html

"/data/ldad/emwww/htdocs/displayclass.html" contains a the web page which has the start button for the applet and ignors jar files but downloads class files see initial web page table of contents. Unused.

icons

"/data/ldad/emwww/htdocs/icons" contains the icons used with the web pages.

Install:

installShield

"/data/ldad/emwww/htdocs/installShield" contains setup.exe and jre.exe which are used with the download page.

Applications:

display0.jar, display1.jar, display2.jar, symantec.jar, ptolemy.plot.jar, JGrid, URLConUsrPW.class, and Base64Convert.jar, and hmlib

"/data/ldad/emwww/htdocs/display0.jar"

"/data/ldad/emwww/htdocs/display1.jar"

"/data/ldad/emwww/htdocs/display2.jar"

"/data/ldad/emwww/htdocs/symantec.jar"

"/data/ldad/emwww/htdocs/ptolemy.plot.jar"

"/data/ldad/emwww/htdocs/JGrid"

"/data/ldad/emwww/htdocs/hmlib"

"/data/ldad/emwww/htdocs/Base64Convert.jar"

"/data/ldad/emwww/htdocs/URLConUsrPW.class"

contain the class files used to define the EMDS, MapClipper, and Configurator applications.

Sync.class, StatusText.class, StatusWindow.class, URLConUsrPW.class, and Base64Convert.jar

"/data/ldad/emwww/htdocs/Sync.class"

"/data/ldad/emwww/htdocs/StatusText.class"

"/data/ldad/emwww/htdocs/StatusWindow.class"

"/data/ldad/emwww/htdocs/Base64Convert.jar"

"/data/ldad/emwww/htdocs/URLConUsrPW.class"

the class files used to define the upgraded Sync application. The initial Sync application is downloaded in "/data/ldad/emwww/htdocs/installShield/setup.exe"

siteId.txt

"/data/ldad/emwww/htdocs/siteId.txt" contains the site id which is used by the the EMDS application to select the proper localized maps, menus, and images.

syncFiles.txt

"/data/ldad/emwww/htdocs/syncFiles.txt" contains the files/directories to be downloaded by the Sync application.

webSiteName.txt

"/data/ldad/emwww/htdocs/webSiteName.txt" contains the web site name which is downloaded by the Sync application. The EMDS application reads the webSiteName.txt and uses it as the default website name in a popup dialog box requesting the web site name.

ldadhelp

"/data/ldad/emwww/htdocs/ldadhelp" contains the HTML HELP files for the EMDS, MapClipper, Sync, and Configurator applications.

wkspace

"/data/ldad/emwww/htdocs/wkspace" contains an unlocalized copy of the menu config files and is unused.

localConfig

"/data/ldad/emwww/htdocs/localConfig" is not generally there. The server log will list access errors to this directory when running as an applet. This is a harmless bug which is caused since the application looks at the local hard drive for these files/directories, but the applet should not be looking for them. I entered this bug in the database.

Data:

data

"/data/ldad/emwww/htdocs/data" contains all Dynamic Data.

localizations

"/data/ldad/emwww/htdocs/localizations" contains Menu files, Shapefiles, and Images which are all static data.

imagedata

"/data/ldad/emwww/htdocs/imagedata" contains the icons used with the EMDS application.

Monitor:

ldadmon

"/data/ldad/emwww/htdocs/ldadmon" contains all ldad monitor files.

Purpose of PollForData:

The PollForData Module's job is to connect to the AWIPS triggers or poll for new AWIPS data. Once new data is available, the PollForData Module sends it to the "hmingestd" process.

Purpose of the Dynamic Data Format Converter:

The Dynamic Data Format Converter Module's job is to receive the data from PollForData, convert the data into small compressed java serialized objects, store it in the "/data" directory on the website and update the "/data/INDEX.dat" and "/data/INDEXTS.dat" index files. Conversion of the data into small compressed java serialized objects may require splitting the dataset into multiple files. The Dynamic Data Format Converter also filters out observation stations which are not in the local area.

Input file format Output file format
netCDF Multiple small compressed java serialized Objects
Radar Single small compressed java serialized Object
Observations Multiple merged small compressed java serialized Object
Text Single small compressed java serialized Object
Table: Dynamic Data Converter File Formats

Brief History:

Originally the WebDissem LDAD (Server Side) component was not broken up into modules. So the original implementation required implementing a server as well as a format converter. The server was designed with the intent of extracting planes of data from a volumetric database rather than just surface conditions. Due to time, budget, computer performance, and computer memory constraints in addition to the fact that most users are only interested in the surface or composite conditions, the WebDissem LDAD (Server Side) component was broken up into modules. These modules are the Dynamic Data Format Converter, a set of files to disseminate, and a Standard HTTP Server. Due to this history, the complexity of the configuration files and code is higher than necessary for a Dynamic Data Format Converter and it may be desirable to restructure this component.

How the Client uses the data on the website:

Application:

Static Data:

The synchronize application downloads much of the static data to the client computer's local hard disk drive. The application first looks on the local hard disk drive under "/localizations/<siteId>/mapdata" (Shapefiles), "/localizations/<siteId>/imagedata" (Images), or "imagedata/icons" (Icons) for static data. If it cannot find the data on the local hard disk drive it then looks on the website under "/localizations/<siteId>/mapdata" (Shapefiles), "/localizations/<siteId>/imagedata" (Images), or "imagedata/icons" (Icons) for static data.

Dynamic Data:

Initially the client downloads the "data/INDEX.dat" and enables/disables menu items based on the data available entries in the "data/INDEX.dat" file. When a menu item is selected, the client module searches for the data key in the INDEX.dat file to find the name of the file to download. The client module then uses HTTP to download the file into memory. The client module also monitors the time stamp stored in "data/INDEXTS.dat". When the time stamp changes, the client module downloads the "data/INDEX.dat" file. The client module then compares the list of items it has downloaded. If a data item has been updated, the client module downloads the newest version and updates the screen.

Applet in Browser:

Static Data:

The applet cannot access the local disk drive. The applet looks on the website under "/localizations/<siteId>/mapdata" (Shapefiles), "/localizations/<siteId>/imagedata" (Images), or "imagedata/icons" (Icons) for static data.

Dynamic Data:

Handled the same as in the Application above.

Adding Static Data to the website.

Shapefile:

Procedure:

Download the application from the LDAD website and install it on your personal computer.

Synchronize the application.

Copy the three components of a shapefile (*.shp, *.dbf, *.shx) to a temporary directory.

Run MapClipper on the shapefile to clip and compress the shapefile into two files with suffixes .shpm.gzip and .dbfm.gzip but the same prefix.

Copy the two files with suffixes .shpm.gzip and .dbfm.gzip to the website in the directory "/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/".

Run Menu Configurator to add menu items accessing the new shapefile data.

Run EMDS as an application and test the new menu items.

Copy the modified menu files to the website.

Modify syncFiles.txt to allow Synchronize to download these new static files to the client computer's local hard drive.

Image:

Procedure:

Download the application from the LDAD website and install it on your personal computer.

Synchronize the application.

Copy the image (*.gif, *.jpg) to the "/data/ldad/emwww/htdocs/localizations/<siteId>/imagedata/" website directory.

Run Menu Configurator to add menu items accessing the new image data.

Run EMDS as an application and test the new menu items.

Copy the modified menu files to the website.

Modify syncFiles.txt to allow Synchronize to download these new static files to the client computer's local hard drive.

Icon: (Typical size is 16 by 16 pixels or 32 by 32 pixels)

Procedure:

Download the application from the LDAD website and install it on your personal computer.

Synchronize the application.

Copy the icons (*.gif, *.jpg) to "/data/ldad/emwww/htdocs/imagedata/icons/" website directory.

Run Menu Configurator to modify menu items using the new icons in IconMaps (See CPIcon software modules).

Run EMDS as an application and test the new menu items.

Copy the modified menu files to the website.

Modify syncFiles.txt to allow Synchronize to download these new static files to the client computer's local hard drive.

Observation Station location and geographical information files:

Overview:

Observation station geographical information and observation station data are merged by the client software. Both files contain information associated with keys. The keys have the form "<ProviderName>&<ProviderID>". The client software uses the keys to match the data to the longitude and latitude as well as text describing the location. The static observation station geographical information is downloaded using the Synchronize function. The client then reads it from the local disk drive when running as an application. This improves performance.

The dynamic data is clipped to the local area at runtime

Procedure:

Acquire a new Observation network into LDAD. (See LDAD System Manager's Manual)

Relocalize the webDissem portion of LDAD.

The static station location and geographical information files are generated upon localization from the "*Station.txt" files in LDAD. They are stored in:

"/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-metar-station-national.gzip",

"/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-qcmesonet-station-local.gzip",

"/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-hydro-station-local.gzip",

and

"/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-manual-station-local.gzip".

Next, add new ODEF files for the dynamic Observation Station data.

Next, run the Menu Configurator and add a new Network menu item.

Copy the modified menu files to the website.

Modify syncFiles.txt to allow Synchronize to download these new static files to the client computer's local hard drive.

Adding Static Data Exercise.

See MenuEditor.html Exercises

Testing Static Data.

Start the EMDS and select the menu item associated with the static data to be tested. Verify that the data is displayed on screen as expected.

Removing Static Data:

Run the Menu Configurator and remove all menu items referencing the static data.

Copy the modified menu files to the website.

Run EMDS to test that the menu items have been removed.

If it is desirable to free up memory, remove the entry in syncFiles.txt which causes Synchronize to download these static files to the client computer's local hard drive. Then remove the static data from the website.

Troubleshooting Static Data.

Symptom: Geographic data (Shapefiles) is not displayable in the EMDS Client Graphical User Interface.

Solution:

1) Start up the Menu Configurator in "Web Site Administrator" Mode.

2) View the Graphics.mnu.

3) Expand the Tree view until the menu item selected is visible.

4) Select the menu item.

5) If the menu item is black, then verify the Software module's Parm 2 contains the prefix for the shapefile name and verify the file exists on the website under "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/*.shpm.gz" and "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/*.dbfm.gz" (Or "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/*.shp", "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/*.dbf" and "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/*.shx").

If the menu item is red, then verify the Software module's Parm 2 contains the prefix for the shapefile name and verify the file exists on the personal computer under "c:\Program Files\EMDS\localConfig\*.shpm.gz" and "c:\Program Files\EMDS\localConfig\*.dbfm.gz" (Or "c:\Program Files\EMDS\localConfig\*.shp" and "c:\Program Files\EMDS\localConfig\*.dbf" and "c:\Program Files\EMDS\localConfig\*.shx").

Symptom: Image data (GIF or JPEG) is not displayable in the EMDS Client Graphical User Interface.

Solution:

1) Start up the Menu Configurator in "Web Site Administrator" Mode.

2) View the Graphics.mnu.

3) Expand the Tree view until the menu item selected is visible.

4) Select the menu item.

5) If the menu item is black, then verify the Software module's Parm 2 contains the image's filename and verify the file exists on the website under "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/imagedata/".

If the menu item is red, then verify the Software module's Parm 2 contains the image's filename and verify the file exists on the personal computer under "c:\Program Files\EMDS\localConfig\".

Symptom: Icons in icon bar/legend is not displayable in the EMDS Client Graphical User Interface.

Solution:

1) Start up the Menu Configurator in "Web Site Administrator" Mode.

2) View the Graphics.mnu.

3) Expand the Tree view until the menu item selected is visible.

4) Select the menu item.

5) If the menu item is black, then verify the Software module's Parm 2 contains the icon's filename and verify the file exists on the website under "ls:/data/ldad/emwww/htdocs/imagedata/icons/".

If the menu item is red, then verify the Software module's Parm 2 contains the icon's filename and verify the file exists on the personal computer under "c:\Program Files\EMDS\localConfig\".

Adding Dynamic Data to the website.

Adding Supported Dynamic Data Types to the website.

ODEF File Structure Top Down Overview:

The odef file compiler, GENCONFIG, will read the Ingest.odef file and find the other odef files from the information in the Ingest.odef file.

Ingest.odef is the top level configuration file. The Ingest.odef file contains links between the ConfigProp (Configuration Property) and one of four possible mills which handles processing the file. The possible mills are: GridFactorMill, TextFactorMill, StreamMill, and ObsFactorMill.

The GridFactorMill, TextFactorMill, StreamMill, or ObsFactorMill files are used to define a mFactorProp (Mill Factor Property) and a mFileProp (Mill File Property) and to link the ConfigProp to be used in the NetCDFvariables.odef file to the definition of the mFileProp. The mFactorProp block defines a mFactorProp for each name in the block. There is one mFactorProp for each parameter to be extracted from the input file. The mFileProp definition defines links to each of the mFactorProp's. This section also identifies if the data comes from a netCDF file and that the config file name prefix to be used in interpreting the data is "NetCDFvariables".

The NetCDFvariables.odef file is used if the mFileProp definition sets netCDFconfigFileName String = "NetCDFvariables";. The NetCDFvariables.odef file links the ConfigProp defined in the GridFactorMill to the netCDFdefProp defined in the NetCDFvariables.odef file. The netCDFdefProp block links the factor names with their corresponding names in the netCDF data input file using the form "netCDFvariable=FactorName".

For example, in "t=model:eta:TempAir:national" the name before the equals sign "=" is the variable name as it is defined in the netCDF data file.  The name after the "=" is the parm name that should match the names of the parms (odef filenames) in the webDissem/hmlib/factorDefs directory (Only here, the dashes "-" in the filenames are replaced with colons ":" )

The netCDFdefProp also defines unit conversions for the parameters using the form "netCDFvariable@InputUnits=OutputUnits". For example, in "t@kelvin=degF", the "t" is the netCDF variable, "kelvin" is the Input Units, and degF is the Output Units.

Caution: The LDAD ingest process only populates the prototype NetCDF file with data. It cannot add new data items. If you want to add new data items you must change the prototype NetCDF file so it contains the new data fields. See the LDAD System Manager's Manual, ldadSMM.html.

The Individual Object Definition files are the last component. A Individual Object Definition file defines a factor and links the factor definition to a ConfigProp.

Individual Object Definition (ODEF) Files:

All Individual Object Definition Files are located in "/data/ldad/emwww/htdocs/hmlib/factorDefs". If this directory is empty then create it and put your individual ODEF files in it. Be sure to back up this directory before installation since it will be deleted. It may be empty since the default ODEF files are compiled into CNF files which are published on the website at: "/ldad/data/ingest/factor". The source code for the ODEF files are at: "ldad/src/webDissem/hmlib/factorDefs".

HyphenDelimitedName - The name is generated out of three or four fields.

ColonDelimitedName - Same as HyphenDelimitedName but with hyphens replaced with colons.

HmScaleEnum - Modify default scale. Options are {LOCAL, NATIONAL, REGIONAL}

content String - Modify string describing the data.

UnitEnum - Modify Units. Options are {FAHRENHEIT, CENTIGRADE}. Unused by LDAD webDissem client.

maxRealLimit Double - Largest double value for colorbar range.

minRealLimit Double - Smallest double value for colorbar range.

maxIntLimit Long - Largest integer value for colorbar range.

minIntLimit Long - Smallest integer value for colorbar range.

Analysis Grid or Forecast Grid from Models

If the Analysis Grid product is unsupported, then one ODEF file (model-<modelName>-<parameter>-local) must be created for each parameter and level in the model and three ODEF files must also be updated (Ingest.odef, NetCDFvariables.odef, and GridFactorMill.odef):


In order to support the display of the Gridded Model output it is necessary to define a projection/scale/_REGION in "localizations/<siteId>/wkspace/Xtensible.frm" and to make the scale visible on the menus using the MenuConfigurator. (See MenuEditor.html)


Documentation for two fields for _REGION lines in Xtensibl.frm

BProjection.setRegions - creates a new projection
strParameters1 = strRegionName such as "Local" or "National".


strParameters2: This variable is parsed into pieces based on the "|" character.
1) strProjectionType = "Lambert Conformal", "Mercator" , or "Polar Stereographic".
2) Phi0StandardParallelYOriginDeg
If "Lambert Conformal", then StandardParallel/YOrigin.
If "Mercator", then ignorred.
If "Polar Stereographic", then Y origin at the pole.
3) Lambda0LongitudeWhereNorthIsUpOrCenterLongitudeDeg
If "Lambert Conformal", then LongitudeWhereNorthIsUp.
If "Mercator", then CenterLongitude.
If "Polar Stereographic", then LongitudeWhereNorthIsUp.
4) Top Left Corner X Deg Lon (Possibly Ignorred)
5) Top Left Corner Y Deg Lat (Possibly Ignorred)
6) Top Right Corner Y Deg Lat
7) Top Right Corner Y Deg Lat
8) Bottom Left Corner X Deg Lon
9) Bottom Left Corner Y Deg Lat
10) Bottom Right Corner X Deg Lon (Possibly Ignorred)
11) Bottom Right Corner Y Deg Lat (Possibly Ignorred)
12) GridSizeX = number of grid points in Horizontal direction.
13) GridSizeY = number of grid points in Vertical direction.
14) GridResolutionKilometers = Number of kilometers per grid point.
15) If "Lambert Conformal", then ignorred.
If "Mercator", then YRadialOrigin.
If "Polar Stereographic", then ignorred.


Examples:
strParameters1 = CONUS211
strParameters2 = Lambert Conformal|25.0|-95.0|-152.856|54.536|-49.385|57.290|-133.459|12.190|-65.091|14.335|93|65|40.63525|0.0


strParameters1 = Alaska
strParameters2 = Polar Stereographic|0.0|-150.0|153.690|63.975|-93.689|63.975|-175.641|42.085|-124.358|42.085|97|69|47.625|0.0


strParameters1 = Puerto Rico
strParameters2 = Mercator|0.0|-67.8125|-77.000|26.422|-58.625|26.422|-77.000|9.000|-58.625|26.422|25|25|80.0|0.15773

strParameters1 = Hawaii
strParameters2 = Mercator|0.0d|-157.0315|-166.219|27.917|-147.844|27.917|-166.219|10.656|-147.844|10.656|25|25|80.0|0.18706


strParameters1 = IFP
strParameters2 = Lambert Conformal|25.0|-95.0|-152.856|54.536|-49.385|57.290|-133.459|12.190|-65.091|14.335|93|65|40.63525|0.0

strParameters1 = CONUS215
strParameters2 = Lambert Conformal|25.0|-95.0|-152.856|54.536|-49.385|57.290|-133.459|12.190|-65.091|14.335|390|257|19.654|0.0


strParameters1 = clipped CONUS215
strParameters2 = Lambert Conformal|25.0|-95.0|0.0|0.0|-91.76945|54.36781|-126.913|20.95828|0.0|0.0|175|173|19.654|0.0


strParameters1 = CONUS202
strParameters2 = Polar Stereographic|0.0|-105.0|-191.423|35.616|-18.576|35.617|-141.028|7.838|-68.973|7.838|65|43|179.6|0.0


strParameters1 = MAPS40
strParameters2 = Lambert Conformal|25.0|-95.0|0.0000|0.0000|-57.3794|55.4818|-126.1378|16.281|0.000|0.000|151|113|39.15|0.0


strParameters1 = MSAS
strParameters2 = Polar Stereographic|0.0|-105.0|0.0000|0.0000|-60.82924|46.01516|-120.4906|22.87267|0.000|0.000|81|62|59.92|0.0

strParameters1 = LAPS
strParameters2 = Polar Stereographic|0.0|-105.0|-107.8875|41.9901|-100.70992|42.405991|-107.74736|37.024307|-101.0305|36.56353|61|61|10.0|0.0

strParameters1 = OLD LAPS
strParameters2 = Polar Stereographic|0.0|-105.0|-107.8875|41.9901|-100.70689|42.407955|-107.74974|37.022182|-101.0305|36.56353|61|61|10.0|0.0

strParameters1 = NexradKFTG
strParameters2 = Polar Stereographic|0.0|-105.0|-105.6479|40.40555|-104.2250|40.4035|-105.6322|39.32689|-104.2438|39.32573|61|61|12.0|0.0

Examples of tab delimited projection entries occupy one line per entry and for Xtensibl.frm are:

# Xtensibl.frm (_REGION Lines)

# Regions must be defined before products can be added to the canvases

#_REGION Regions CONUS211 display.InfoDialog2 S Lambert Conformal|25.0|-95.0|-152.856|54.536|-49.385|57.290|-133.459|12.190|-65.091|14.335|93|65|40.63525|0.0

#_REGION Regions CONUS215 display.InfoDialog2 S Lambert Conformal|25.0|-95.0|-152.856|54.536|-49.385|57.290|-133.459|12.190|-65.091|14.335|390|257|19.654|0.0

#_REGION Regions clipped CONUS215 display.InfoDialog2 S Lambert Conformal|25.0|-95.0|0.0|0.0|-91.76945|54.36781|-126.913|20.95828|0.0|0.0|175|173|19.654|0.0

#_REGION Regions CONUS202 display.InfoDialog2 S Polar Stereographic|0.0|-105.0|-191.423|35.616|-18.576|35.617|-141.028|7.838|-68.973|7.838|65|43|179.6|0.0

#_REGION Regions CONUS202 display.InfoDialog2 S Polar Stereographic|0.0|-105.0|0.0|0.0|-18.576|35.617|-141.028|7.838|0.0|0.0|65|43|179.6|0.0

#_REGION Regions MAPS40 display.InfoDialog2 S Lambert Conformal|25.0|-95.0|0.0000|0.0000|-57.3794|55.4818|-126.1378|16.281|0.000|0.000|151|113|39.15|0.0

#_REGION Regions MSAS display.InfoDialog2 S Polar Stereographic|0.0|-105.0|0.0000|0.0000|-60.82924|46.01516|-120.4906|22.87267|0.000|0.000|81|62|59.92|0.0

#_REGION Regions Alaska display.InfoDialog2 S Polar Stereographic|0.0|-150.0|153.690|63.975|-93.689|63.975|-175.641|42.085|-124.358|42.085|97|69|47.625|0.0

#_REGION Regions Puerto Rico display.InfoDialog2 S Mercator|0.0|-67.8125|-77.000|26.422|-58.625|26.422|-77.000|9.000|-58.625|26.422|25|25|80.0|0.15773

#_REGION Regions Hawaii display.InfoDialog2 S Mercator|0.0|-157.0315|-166.219|27.917|-147.844|27.917|-166.219|10.656|-147.844|10.656|25|25|80.0|0.18706

#_REGION Regions Regional display.InfoDialog2 S Polar Stereographic|0.0|-105.5|-113.855|45.325|-97.244|45.438|-112.13|36.0145|-98.756|36.0988|105|125|10.0|0.0

#_REGION Regions National display.InfoDialog2 S Polar Stereographic|0.0|-105.0|0.0000|0.0000|-60.82944|46.01516|-120.4906|22.87267|0.000|0.000|81|62|59.92|0.0

#_REGION Regions Local display.InfoDialog2 S Polar Stereographic|0.0|-105.0|-107.8875|41.9901|-100.70992|42.405991|-107.74736|37.024307|-101.0305|36.56353|61|61|10.0|0.0

_REGION Regions National display.InfoDialog2 S Polar Stereographic|0.000000|-105.000000|-136.454742|52.486553|-60.829231|46.015156|-120.490631|22.872671|-81.243790|20.125643|81|62|59.92|0.0

_REGION Regions Local display.InfoDialog2 S Polar Stereographic|0.000000|-104.443657|-107.508423|42.002762|-101.384727|42.002918|-107.312469|37.455650|-101.580315|37.455784|61|61|10.0|0.0

_REGION Regions CONUS211 display.InfoDialog2 S Lambert Conformal|25.000000|-95.000000|-152.855835|54.536327|-49.384918|57.289951|-133.458984|12.190041|-65.091370|14.334693|93|65|40.63525|0.0

"#" indicate the line is commented out and not active. The three Graphic.mnu lines corresponding to the three uncommented projection lines are:

#Graphic.mnu (Scale lines)

_MENU Scale Local,, null Local Radio1 true false null ChangeProjection EMDSUsersGuide.html null Set:L

_MENU Scale Local Forecast,, null CONUS211 Radio1 false false null ChangeProjection EMDSUsersGuide.html null Set:F

_MENU Scale National,, null National Radio1 false false null ChangeProjection EMDSUsersGuide.html null Set:N

Currently supported Models generating Analysis/Forecast Grids include: 1) LAPS, 2) AVN, 3) RUC, 4) MSAS, 5) ETA, 6) MesoEta, 7) MRF, and 8) MAPS40. The pollForData.cnf file has some entries commented out which stops the EMDS ingest preprocessor of all but LAPS and MSAS although the models are specified in the odef files. Caution: Adding all models will have a significant impact on server perfomance and disk usage.


Individual Grid Object Definition (ODEF) File (model-<modelName>-<parameter>-local) items which must be modified are highlighted as hyperlinks.

Analysis Grid Individual ODEF File


This file defines a factor and links the factor definition to a ConfigProp. The link occurs in th following line:

model-eta-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-eta-TempAir-national];

#F>=========================================================================

#
model-eta-TempAir-national.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.
model-eta-TempAir-national FactorDef

{

name String = "
model:eta:TempAir:national";

metaName String = null;

scale HmScaleEnum =
NATIONAL;

version String = "0.0.1";

source String = "configuration file";

content String = "
national ETA TempAir data";

classification HmClassEnum = MODEL;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = CARTESIAN;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum =
FAHRENHEIT;

maxRealLimit Double =
125.0;

minRealLimit Double =
-75.0;

maxIntLimit Long =
125;

minIntLimit Long =
-75;

}

model-eta-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-eta-TempAir-national];



Forecast Grid Individual ODEF file:

This file defines a factor and links the factor definition to a ConfigProp. The link occurs in th following line:

model-ruc-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-ruc-TempAir-national];


#F>=========================================================================

# model-ruc-TempAir-national.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];# group the factor's members together

def.model-ruc-TempAir-national FactorDef

{

name String = "model:ruc:TempAir:national";

metaName String = null;

scale HmScaleEnum = NATIONAL;

version String = "0.0.1";

source String = "configuration file";

content String = "national RUC TempAir data";

classification HmClassEnum = MODEL;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = CARTESIAN;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum = FAHRENHEIT;

maxRealLimit Double = 125.0;

minRealLimit Double = -75.0;

maxIntLimit Long = 125;

minIntLimit Long = -75;

}

model-ruc-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-ruc-TempAir-national];

Radar Polar Grid

Due to the popularity of multiple radars, the localization procedure has the capability to specify one or more radar stations. The menu entries for the first two radars are automatically generated. If three or more radars are added on ingest, it is necessary to run the Menu Configurator and add the new radar menu items. If you would rather do it manually, the the odef files will have to be created by hand.

If the radar product is unsupported, then one ODEF file must be created (radar-<product>-local) and two ODEF files must also be updated (Ingest.odef and StreamMill.odef):

Table III in the first document will contain a list of radar products which may or may not be generated by AWIPS. Display errors may be fixed by editing the hard coded Table III in the source code "ls:/ldad/data/webDissemSrc/ldadapp/radar/RadarReader.java" and recompiling. Only the radial radar products are currently supported in the web dissemination portion of LDAD.

For Radar file formats see:
Interface Control Document for the RPG Associated PUP.
Document Number 2620001A
Code Identification 0WY55
WSR-88D OSF
26 June 1998
Build 10.0

For how the images appear on the screen see:
Interface Control Document for Product Specification.
Document Number 2620003A
Code Identification 0WY55
WSR-88D OSF
26 June 1998
Build 10.0

Individual Radar Object Definition (ODEF) File (radar-<product>-local) items which must be modified are highlighted as hyperlinks.

This file defines a factor and links the factor definition to a ConfigProp. The link occurs in th following line: radar-Reflectivity-local ConfigProp = [FactorDef, GOVERNING, @def.radar-Reflectivity-local];

#F>=========================================================================

# radar-Reflectivity-local.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.radar-Reflectivity-local FactorDef

{

name String = "radar:Reflectivity:local";

metaName String = "";

scale HmScaleEnum = LOCAL;

version String = "0.0.1";

source String = "configuration file";

content String = "local radar Reflectivity data";

classification HmClassEnum = OBSERVATION;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = NAMED;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum = MILES;

maxRealLimit Double = 100.0;

minRealLimit Double = 0.0;

maxIntLimit Long = 100;

minIntLimit Long = 0;

}

radar-Reflectivity-local ConfigProp = [FactorDef, GOVERNING, @def.radar-Reflectivity-local];

Text Product

It is not necessary to add new ODEF files when adding Text products unless a new catagory is being supported. Catagories which are currently supported are: 1) watch, 2) warning, 3) forecast, 4) outlook, 5) report, 6) statement, 7) qctext. (See TextFactorMill.odef file.)

If the catagory is supported, then adding text products is a four step process:

1.) Make entry into ldadTrigger.template. (See the LDAD System Managers Manual, ldadSMM.html)

2.) Make entry into Text.mnu using the Menu Configurator and copy Text.mnu to "ls1:/data/ldad/emwww/htdocs/localization/<siteId>/wkspace/". (See MenuEditor.html)

Additionally for Watches and Warnings it is necessary to update the Graphic.mnu (Watches/Warnings submenu) using the Menu Configurator and to copy Graphic.mnu to "ls1:/data/ldad/emwww/htdocs/localization/<siteId>/wkspace/". (See MenuEditor.html)

3.) Copy the ldadTrigger.template to appropriate directory and then run mainscript -trigger on the DS1. (See the LDAD System Managers Manual, ldadSMM.html)

4.) Verify that once a product is issued, it shows up as a selectable item in the EMDS text menu and can be displayed in the Text Pane. Also, if it is a watch or warning, verify that the UGC or LAT...LON areas can be colored in by selecting the appropriate menuitem under Watches/Warnings in the Graphic pane.

If the catagory is unsupported, then one ODEF file must be created (nwstext-<catagory>-local) and two ODEF files must also be updated (Ingest.odef and TextFactorMill.odef):

Individual Text Object Definition (ODEF) File (nwstext-<catagory>-local) items which must be modified are highlighted as hyperlinks.

This file defines a factor and links the factor definition to a ConfigProp. The link occurs in th following line: nwstext-warning-local ConfigProp = [FactorDef, GOVERNING, @def.nwstext-warning-local];

#F>=========================================================================

# nwstext-warning-local.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimension types

.InnerDimtypes [Object] = [];

.OuterDimtypes [Object] = [];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.nwstext-warning-local FactorDef

{

name String = "nwstext:warning:local";

metaName String = null;

scale HmScaleEnum = LOCAL;

version String = "0.0.1";

source String = "configuration file";

content String = "local warning NWS text";

classification HmClassEnum = ALERT;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = CARTESIAN;

continuity HmContinuityEnum = UNDEFINED;

valueType HmDatatypeEnum = TEXT;

units UnitEnum = UNDEFINED;

maxRealLimit Double = 0.0;

minRealLimit Double = 0.0;

maxIntLimit Long = 0;

minIntLimit Long = 0;

}

nwstext-warning-local ConfigProp = [FactorDef, GOVERNING, @def.nwstext-warning-local];

Graphical Forecast Editor (GFE) Forecast Grid

If the GFE Forecast Grid product is unsupported, then as long as the model-ifp-TempAir-national.odef file exists and is supported in Ingest.odef, NetCDFvariables.odef, and GridFactorMill.odef, nothing more needs to be done here. To avoid reading the file multiple times the ingest process is triggered by only one of the Odef files (TempAir).

Individual GFE Forecast Grid Object Definition (ODEF) File (model-<modelName>-<parameter>-local) items which must be modified are highlighted as hyperlinks.

This file defines a factor and links the factor definition to a ConfigProp. The link occurs in th following line: model-ifp-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-ifp-TempAir-national];

#F>=========================================================================

# model-ifp-TempAir-national.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.model-ifp-TempAir-national FactorDef

{

name String = "model:ifp:TempAir:national";

metaName String = null;

scale HmScaleEnum = LOCAL;

version String = "0.0.1";

source String = "configuration file";

content String = "national IFP Grid temperature data";

classification HmClassEnum = MODEL;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = CARTESIAN;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum = FAHRENHEIT;

maxRealLimit Double = 125.0;

minRealLimit Double = -75.0;

maxIntLimit Long = 125;

minIntLimit Long = -75;

}

model-ifp-TempAir-national ConfigProp = [FactorDef, GOVERNING, @def.model-ifp-TempAir-national];

Observation Station data

Currently supported station groups include obs-metar-station-national, obs-qcmesonet-station-local, obs-hydro-station-local, and obs-manual-station-local. Each can contain multiple networks.

If the Observation Station group is supported, then it is not necessary to modify the ODEF files in order to add a new observation station network to the group. The observation station network must be ingested into LDAD. (See ldadSMM.html) Then the EMDS localization must be rerun to create the static station location and geographical information files. Be sure to back up all modifications since they may be overwritten. Next, the Menu Configurator must be run to add a new network to the Observations->Networks menu. (See MenuEditor.html)

The static station location and geographical information files are generated upon localization from the "*Station.txt" files in LDAD. They are stored in: "/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-metar-station-national.gzip", "/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-qcmesonet-station-local.gzip", "/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-hydro-station-local.gzip", and "/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/obs-manual-station-local.gzip".

If the Observation Station group is unsupported, then one ODEF file must be created (obs/vobs/wobs-<networkType>-<parameter>-local) and three ODEF files must also be updated (Ingest.odef, NetCDFvariables.odef, and ObsFactorMill.odef):

Individual Obs Object Definition (ODEF) File (obs/vobs/wobs-<networkType>-<parameter>-local) items which must be modified are highlighted as hyperlinks.

The obs, vobs, or wobs prefixes refer to magnitude data, vector data, and text data, respectively.

This file defines a factor and links the factor definition to a ConfigProp.

Magnitude

#F>=========================================================================

# obs-mesonet-TempAir-local.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.obs-mesonet-TempAir-local FactorDef

{

name String = "obs:mesonet:TempAir:local";

metaName String = "station:mesonet:local";

scale HmScaleEnum = LOCAL;

version String = "0.0.1";

source String = "configuration file";

content String = "local mesonet TempAir data";

classification HmClassEnum = OBSERVATION;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = NAMED;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum = FAHRENHEIT;

maxRealLimit Double = 125.0;

minRealLimit Double = -75.0;

maxIntLimit Long = 125;

minIntLimit Long = -75;

}

obs-mesonet-TempAir-local ConfigProp = [FactorDef, GOVERNING, @def.obs-mesonet-TempAir-local];

**********

Vector

#F>=========================================================================

# obs-mesonet-WindDir-local.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.obs-mesonet-WindDir-local FactorDef

{

name String = "obs:mesonet:WindDir:local";
metaName String = "station:mesonet:local";
scale HmScaleEnum =
LOCAL;
version String = "0.0.1";
source String = "configuration file";
content String = "
local mesonet WindDir data";
classification HmClassEnum = OBSERVATION;
innerDimTypes [Object] = @.InnerDimtypes;
outerDimTypes [Object] = @.OuterDimtypes;
trivialDimTypes [Object] = @.TrivialDimtypes;
coordsystem HmCoordSysEnum = NAMED;
continuity HmContinuityEnum = POINT;
valueType HmDatatypeEnum = FLOAT;
units UnitEnum =
DEGREES;
maxRealLimit Double =
360.0;
minRealLimit Double =
0.0;
maxIntLimit Long =
360;
minIntLimit Long =
0;
}

obs-mesonet-WindDir-local ConfigProp = [FactorDef, GOVERNING, @def.obs-mesonet-WindDir-local];

**********

Word

#F>=========================================================================

# obs-metar-PresentWeather-national.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

#group the factor's members together

def.obs-metar-PresentWeather-national FactorDef

{

name String = "obs:metar:PresentWeather:national";

metaName String = "station:metar:national";

scale HmScaleEnum = NATIONAL;

version String = "0.0.1";

source String = "configuration file";

content String = "national METAR present weather";

classification HmClassEnum = OBSERVATION;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = NAMED;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = TEXT;

units UnitEnum = UNDEFINED;

maxRealLimit Double = 0.0;

minRealLimit Double = 0.0;

maxIntLimit Long = 0;

minIntLimit Long = 0;

}

obs-metar-PresentWeather-national ConfigProp = [FactorDef, GOVERNING, @def.obs-metar-PresentWeather-national];

Quality Control Observation Station data

Individual QCObs Object Definition (ODEF) File items which must be modified are highlighted as hyperlinks.

The quality control information is generated by MSAS model code. It provides sanity checks and statistical quality control to ensure that the data is accurate. (See EMDSUsersGuide.html) Values from sensors which are suspect are colored yellow or red depending upon if tests failed in the previous measurement or the current measurement.

See the following two papers for a detailed description.

Miller, Patricia A., Barth, Michael F., Hartsough, Craig S., and Savoie, Matthew H., THE LDAD OBSERVATION QUALITY CONTROL AND MONTORING SYSTEM: AN OVERALL SYSTEM DESCRIPTION, Tenth Symposium on Meteorological Observations and Instrumentation, January 11-16,
1998, Phoenix, Arizona, 5.7

Miller, Patricia A., Barth, Michael F., THE LDAD OBSERVATION QUALITY CONTROL AND MONTORING SYSTEM: AN UPDATE FOR AWIPS BUILD 4.2, 15th Conf. on IIPS for Meteorology, Oceanography, and Hydrology, January 10-15, 1999, Dallas, Texas, 12.1

This file defines a factor and links the factor definition to a ConfigProp.

QCMagnitude

#F>=========================================================================

# obs-qcmesonet-TempAir-local.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

#F>>>=======================================================================

# make some dimensions types

.Xdimtype HmDimEnum = X;

.Ydimtype HmDimEnum = Y;

.Zdimtype HmDimEnum = LEVEL;

.Tdimtype HmDimEnum = TIME;

.InnerDimtypes [Object] = [@.Xdimtype, @.Ydimtype];

.OuterDimtypes [Object] = [@.Zdimtype, @.Tdimtype];

.TrivialDimtypes [Object] = [];

# group the factor's members together

def.obs-qcmesonet-TempAir-local FactorDef

{

name String = "obs:qcmesonet:TempAir:local";

metaName String = "obs:qcmesonet:station:local";

scale HmScaleEnum = LOCAL;

version String = "0.0.1";

source String = "configuration file";

content String = "local qcmesonet TempAir data";

classification HmClassEnum = OBSERVATION;

innerDimTypes [Object] = @.InnerDimtypes;

outerDimTypes [Object] = @.OuterDimtypes;

trivialDimTypes [Object] = @.TrivialDimtypes;

coordsystem HmCoordSysEnum = NAMED;

continuity HmContinuityEnum = POINT;

valueType HmDatatypeEnum = FLOAT;

units UnitEnum = FAHRENHEIT;

maxRealLimit Double = 125.0;

minRealLimit Double = -75.0;

maxIntLimit Long = 125;

minIntLimit Long = -75;

}

obs-qcmesonet-TempAir-local ConfigProp = [FactorDef, GOVERNING, @def.obs-qcmesonet-TempAir-local];

NetCDFvariables.odef File:

The netCDFvariables Object Definition File is located in "/ldad/classes/hmserve/ingestDefs". It may be empty since the default ODEF files are compiled into CNF files which are published on the website at: /ldad/data/ingest/ingest". The source code for the ODEF files are at: "ldad/src/webDissem/hmserve/ingestDefs". The netCDFvariables file connects the varible names in the netCDF file with the variable names of the individual compressed java serialized objects to be created.

The NetCDFvariables.odef file is used if the mFileProp definition sets netCDFconfigFileName String = "NetCDFvariables";. The NetCDFvariables.odef file links the ConfigProp defined in the GridFactorMill to the netCDFdefProp defined in the NetCDFvariables.odef file. The netCDFdefProp block links the factor names with their corresponding names in the netCDF data input file using the form "netCDFvariable=FactorName".

For example, in "t=model:eta:TempAir:national" the name before the equals sign "=" is the variable name as it is defined in the netCDF data file.  The name after the "=" is the parm name that should match the names of the parms (odef filenames) in the webDissem/hmlib/factorDefs directory (Only here, the dashes "-" in the filenames are replaced with colons ":" )

The netCDFdefProp also defines unit conversions for the parameters using the form "netCDFvariable@InputUnits=OutputUnits". For example, in "t@kelvin=degF", the "t" is the netCDF variable, "kelvin" is the Input Units, and degF is the Output Units.

Caution: The LDAD ingest process only populates the prototype NetCDF file with data. It cannot add new data items. If you want to add new data items you must change the prototype NetCDF file so it contains the new data fields. See the LDAD System Manager's Manual, ldadSMM.html.

The first section defines

def.model.eta.national.netCDFdefProp FMConfig

{

_type String = "ETA";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:eta:TempAir:national",

"uw=model:eta:windU:national",

"vw=model:eta:windV:national",

"rh=model:eta:RelHumidity:national",

"emsp=model:eta:PressureSeaLevel:national",

"tp=model:eta:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"emsp@pascal=millibar",

"tp@millimeter=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

The second section links the ConfigProp defined in the GridFactorMill to the netCDFdefProp defined in the first section of this file.

model-eta-national ConfigProp = [FMConfig, GOVERNING, @def.model.eta.national.netCDFdefProp];


Model Tag -
Model Name -

Assume that we wish to add the ETA model to the output then we must add the following items.

Variable Associations -

The following are variables defined in the ETA netCDF file: {t, uw, vw, rh, emsp, tp} which we wish to connect to the following colon delimited names {model:eta:TempAir:national, model:eta:windU:national, model:eta:windV:national, model:eta:RelHumidity:national, model:eta:PressureSeaLevel:national, model:eta:TotalPrecip:national}.

Unit Conversions -

We also need to define the unit conversions using the format: "netCDFvariable@InputUnits=OutputUnits".

NetCDFvariables.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# NetCDFvariables.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a StreamMill configuration file.

#F>>>=======================================================================

#-----------------------------------------------------------------

# MillFactorProps supporting each filetype.

# NOTE: Factor names have colons!!!

#-----------------------------------------------------------------

#def.model.laps.local.netCDFdefProp FMConfig

{

_type String = "LAPS";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:laps:TempAir:local",

"dpt=model:laps:TempDewPoint:local",

"uw=model:laps:windU:local",

"vw=model:laps:windV:local",

"rh=model:laps:RelHumidity:local",

"fd=model:laps:FireIndex:local",

"smc=model:laps:SoilMoisture:local",

"vis=model:laps:Vis:local",

"pc=model:laps:1HourRain:local",

"stpa=model:laps:TotalRain:local",

"s1hr=model:laps:1HourSnow:local",

"stot=model:laps:TotalSnow:local",

"scp=model:laps:SnowCoverage:local",

"ptt=model:laps:PrecipType:local"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"dpt@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"fd@none=none",

"smc@meter/meter=meter/meter",

"vis@meter=mile",

"pc@meter=inch",

"stpa@meter=inch",

"s1hr@meter=inch",

"stot@meter=inch",

"scp@none=none",

"ptt@none=none"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.avn.national.netCDFdefProp FMConfig

{

_type String = "AVN";

_fmType Integer = 0;

_varNameMap Hashtable[String] = ["t=model:avn:TempAir:national",

"uw=model:avn:windU:national",

"vw=model:avn:windV:national",

"rh=model:avn:RelHumidity:national",

"pmsl=model:avn:PressureSeaLevel:national",

"tp=model:avn:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"pmsl@pascal=millibar",

"tp@kg/meter^2=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.eta.national.netCDFdefProp FMConfig

{

_type String = "ETA";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:eta:TempAir:national",

"uw=model:eta:windU:national",

"vw=model:eta:windV:national",

"rh=model:eta:RelHumidity:national",

"emsp=model:eta:PressureSeaLevel:national",

"tp=model:eta:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"emsp@pascal=millibar",

"tp@millimeter=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.mesoeta.national.netCDFdefProp FMConfig

{

_type String = "MESOETA";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:mesoeta:TempAir:national",

"uw=model:mesoeta:windU:national",

"vw=model:mesoeta:windV:national",

"dpt=model:mesoeta:TempDewPoint:national",

"rh=model:mesoeta:RelHumidity:national",

"emsp=model:mesoeta:PressureSeaLevel:national",

"tp=model:mesoeta:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"dpt@kelvin=degF",

"emsp@pascal=millibar",

"tp@millimeter=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.ruc.national.netCDFdefProp FMConfig

{

_type String = "RUC";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:ruc:TempAir:national",

"uw=model:ruc:windU:national",

"vw=model:ruc:windV:national",

"rh=model:ruc:RelHumidity:national",

"mmsp=model:ruc:PressureSeaLevel:national",

"tp=model:ruc:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"mmsp@pascal=millibar",

"tp@kg/meter^2=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.mrf.national.netCDFdefProp FMConfig

{

_type String = "MRF";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "t=model:mrf:TempAir:national",

"uw=model:mrf:windU:national",

"vw=model:mrf:windV:national",

"rh=model:mrf:RelHumidity:national",

"pmsl=model:mrf:PressureSeaLevel:national",

"tp=model:mrf:TotalPrecip:national"];

_inUnitsOutUnits Hashtable[String] = [ "t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots",

"rh@%=%",

"pmsl@pascal=millibar",

"tp@kg/meter^2=inch"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.msas.national.netCDFdefProp FMConfig

{

_type String = "MSAS";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "uw=model:msas:windU:national",

"vw=model:msas:windV:national",

"dpt=model:msas:TempDewPoint:national",

"mslp=model:msas:PressureSeaLevel:national"];

_inUnitsOutUnits Hashtable[String] = [ "uw@meter/second=knots",

"vw@meter/second=knots",

"dpt@kelvin=degF",

"mslp@pascal=millibar"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.model.maps40.national.netCDFdefProp FMConfig

{

_type String = "MAPS-40";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "rh=model:maps40:RelHumidity:national",

"mmsp=model:maps40:PressureSeaLevel:national",

"t=model:maps40:TempAir:national",

"uw=model:maps40:windU:national",

"vw=model:maps40:windV:national"];

_inUnitsOutUnits Hashtable[String] = [ "rh@%=%",

"mmsp@pascal=millibar",

"t@kelvin=degF",

"uw@meter/second=knots",

"vw@meter/second=knots"];

_timeVar String = "valtimeMINUSreftime";

_projName String = "depictorName";

}

def.obs.metar.national.netCDFdefProp FMConfig

{

_type String = "METAR";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "latitude=obs:metar:Latitude:national",

"longitude=obs:metar:Longitude:national",

"stationName=obs:metar:StationID:national",

"temperature=obs:metar:TempAir:national",

"dewpoint=obs:metar:TempDewPoint:national",

"seaLevelPress=obs:metar:PressureSeaLevel:national",

"windDir=obs:metar:WindDir:national",

"windSpeed=obs:metar:WindSpeed:national",

"presWeather=obs:metar:PresentWeather:national",

"visibility=obs:metar:Vis:national",

"precip1Hour=obs:metar:Precip1Hour:national"];

_inUnitsOutUnits Hashtable[String] = [ "latitude@degrees=degrees",

"longitude@degrees=degrees",

"stationName@none=none",

"temperature@kelvin=degF",

"dewpoint@kelvin=degF",

"seaLevelPress@pascal=millibar",

"windDir@degrees=degrees",

"windSpeed@meter/second=knots",

"presWeather@none=none",

"visibility@meter=mile",

"precip1Hour@meter=inch"];

_timeVar String = "timeObs";

_projName String = "";

}

def.obs.qcmesonet.local.netCDFdefProp FMConfig

{

_type String = "MESONET";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "latitude=obs:qcmesonet:Latitude:local",

"longitude=obs:qcmesonet:Longitude:local",

"stationId=obs:qcmesonet:StationID:local",

"dataProvider=obs:qcmesonet:ProviderID:local",

"temperature=obs:qcmesonet:TempAir:local",

"dewpoint=obs:qcmesonet:TempDewPoint:local",

"relHumidity=obs:qcmesonet:RelHumidity:local",

"seaLevelPressure=obs:qcmesonet:PressureSeaLevel:local",

"windDir=obs:qcmesonet:WindDir:local",

"windSpeed=obs:qcmesonet:WindSpeed:local",

"visibility=obs:qcmesonet:Vis:local",

"presWeather=obs:qcmesonet:PresentWeather:local",

"precipAccum=obs:qcmesonet:PrecipAccum:local",

"precipAccumQCR=obs:qcmesonet:PrecipAccumQCR:local",

"precipAccumQCA=obs:qcmesonet:PrecipAccumQCA:local",

"precipAccumQCD=obs:qcmesonet:PrecipAccumQCD:local",

"temperatureQCR=obs:qcmesonet:TempAirQCR:local",

"temperatureQCA=obs:qcmesonet:TempAirQCA:local",

"temperatureQCD=obs:qcmesonet:TempAirQCD:local",

"dewpointQCR=obs:qcmesonet:TempDewPointQCR:local",

"dewpointQCA=obs:qcmesonet:TempDewPointQCA:local",

"dewpointQCD=obs:qcmesonet:TempDewPointQCD:local",

"relHumidityQCR=obs:qcmesonet:RelHumidityQCR:local",

"relHumidityQCA=obs:qcmesonet:RelHumidityQCA:local",

"relHumidityQCD=obs:qcmesonet:RelHumidityQCD:local",

"seaLevelPressureQCR=obs:qcmesonet:PressureSeaLevelQCR:local",

"seaLevelPressureQCA=obs:qcmesonet:PressureSeaLevelQCA:local",

"seaLevelPressureQCD=obs:qcmesonet:PressureSeaLevelQCD:local",

"visibilityQCR=obs:qcmesonet:VisQCR:local",

"visibilityQCA=obs:qcmesonet:VisQCA:local",

"visibilityQCD=obs:qcmesonet:VisQCD:local",

"windDirQCR=obs:qcmesonet:WindDirQCR:local",

"windDirQCA=obs:qcmesonet:WindDirQCA:local",

"windDirQCD=obs:qcmesonet:WindDirQCD:local",

"windSpeedQCR=obs:qcmesonet:WindSpeedQCR:local",

"windSpeedQCA=obs:qcmesonet:WindSpeedQCA:local",

"windSpeedQCD=obs:qcmesonet:WindSpeedQCD:local"];

_inUnitsOutUnits Hashtable[String] = [ "latitude@degrees=degrees",

"longitude@degrees=degrees",

"stationId@none=none",

"dataProvider@none=none",

"temperature@kelvin=degF",

"dewpoint@kelvin=degF",

"relHumidity@%=%",

"seaLevelPressure@pascal=millibar",

"windDir@degrees=degrees",

"windSpeed@meter/second=knots",

"visibility@meter=mile",

"presWeather@none=none",

"precipAccum@millimeter=inch",

"precipAccumQCR@none=none",

"precipAccumQCA@none=none",

"precipAccumQCD@millimeter=inch",

"temperatureQCR@none=none",

"temperatureQCA@none=none",

"temperatureQCD@millimeter=inch",

"dewpointQCR@none=none",

"dewpointQCA@none=none",

"dewpointQCD@millimeter=inch",

"relHumidityQCR@none=none",

"relHumidityQCA@none=none",

"relHumidityQCD@%=%",

"seaLevelPressureQCR@none=none",

"seaLevelPressureQCA@none=none",

"seaLevelPressureQCD@millimeter=inch",

"visibilityQCR@none=none",

"visibilityQCA@none=none",

"visibilityQCD@millimeter=inch",

"windDirQCR@none=none",

"windDirQCA@none=none",

"windDirQCD@millimeter=inch",

"windSpeedQCR@none=none",

"windSpeedQCA@none=none",

"windSpeedQCD@millimeter=inch"];

_timeVar String = "observationTime";

_projName String = "";

}

def.obs.hydro.local.netCDFdefProp FMConfig

{

_type String = "MESONET";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "latitude=obs:hydro:Latitude:local",

"longitude=obs:hydro:Longitude:local",

"stationId=obs:hydro:StationID:local",

"dataProvider=obs:hydro:ProviderID:local",

"precip5min=obs:hydro:Precip5Min:local",

"precip1hr=obs:hydro:Precip1Hour:local",

"precip3hr=obs:hydro:Precip3Hour:local",

"precip6hr=obs:hydro:Precip6Hour:local",

"precip12hr=obs:hydro:Precip12Hour:local",

"precip24hr=obs:hydro:Precip24Hour:local",

"precipAccum=obs:hydro:PrecipAccum:local",

"riverStage=obs:hydro:RiverStage:local",

"riverFlow=obs:hydro:RiverDischarge:local"];

_inUnitsOutUnits Hashtable[String] = [ "latitude@degrees=degrees",

"longitude@degrees=degrees",

"stationId@none=none",

"dataProvider@none=none",

"precip5min@millimeter=inch",

"precip1hr@millimeter=inch",

"precip3hr@millimeter=inch",

"precip6hr@millimeter=inch",

"precip12hr@millimeter=inch",

"precip24hr@millimeter=inch",

"precipAccum@millimeter=inch",

"riverStage@meter=foot",

"riverFlow@m^3/sec=ft^3/sec"];

_timeVar String = "observationTime";

_projName String = "";

}

def.obs.manual.local.netCDFdefProp FMConfig

{

_type String = "MESONET";

_fmType Integer = 0;

_varNameMap Hashtable[String] = [ "latitude=obs:manual:Latitude:local",

"longitude=obs:manual:Longitude:local",

"code73=obs:manual:IceCover:local",

"code17=obs:manual:Precip1Month:local",

"code16=obs:manual:Precip1Week:local",

"code10=obs:manual:Precip24Hour:local",

"code15=obs:manual:PrecipStorm:local",

"code20=obs:manual:PrecipType:local",

"code84=obs:manual:PresentWeather:local",

"code86=obs:manual:RelHumidity:local",

"code43=obs:manual:RiverDischarge:local",

"code49=obs:manual:RiverDischargePeak:local",

"code33=obs:manual:RiverStage:local",

"code41=obs:manual:RiverStageTrend:local",

"code68=obs:manual:SnowDepthTotal:local",

"code67=obs:manual:SnowCoverage:local",

"code83=obs:manual:SoilMoisture:local",

"code69=obs:manual:SnowDepthNew:local",

"stationId=obs:manual:StationID:local",

"code21=obs:manual:TempAir:local",

"code22=obs:manual:TempAirMaxDay:local",

"code23=obs:manual:TempAirMinDay:local",

"code32=obs:manual:TempDewPoint:local",

"code89=obs:manual:WindDir:local",

"code88=obs:manual:WindSpeed:local"];

_inUnitsOutUnits Hashtable[String] = [ "latitude@degrees=degrees",

"longitude@degrees=degrees",

"code73@%=%",

"code17@inch=inch",

"code16@inch=inch",

"code10@inch=inch",

"code15@inch=inch",

"code20@none=none",

"code84@none=none",

"code86@%=%",

"code43@1000 ft^3/sec=1000 ft^3/sec",

"code49@1000 ft^3/sec=1000 ft^3/sec",

"code33@foot=foot",

"code41@none=none",

"code68@inch=inch",

"code67@%=%",

"code83@inch=inch",

"code69@inch=inch",

"stationId@none=none",

"code21@degF=degF",

"code22@degF=degF",

"code23@degF=degF",

"code32@degF=degF",

"code89@tensOfDegrees=degrees",

"code88@tensOfDegrees=degrees"];

_timeVar String = "observationTime";

_projName String = "";

}

#-----------------------------------------------------------------

# FILETYPES supported by this factor mill configuration.

#-----------------------------------------------------------------

model-laps-local ConfigProp = [FMConfig, GOVERNING, @def.model.laps.local.netCDFdefProp];

model-avn-national ConfigProp = [FMConfig, GOVERNING, @def.model.avn.national.netCDFdefProp];

model-eta-national ConfigProp = [FMConfig, GOVERNING, @def.model.eta.national.netCDFdefProp];

model-mesoeta-national ConfigProp = [FMConfig, GOVERNING, @def.model.mesoeta.national.netCDFdefProp];

model-ruc-national ConfigProp = [FMConfig, GOVERNING, @def.model.ruc.national.netCDFdefProp];

model-mrf-national ConfigProp = [FMConfig, GOVERNING, @def.model.mrf.national.netCDFdefProp];

model-msas-national ConfigProp = [FMConfig, GOVERNING, @def.model.msas.national.netCDFdefProp];

model-maps40-national ConfigProp = [FMConfig, GOVERNING, @def.model.maps40.national.netCDFdefProp];

obs-metar-national ConfigProp = [FMConfig, GOVERNING, @def.obs.metar.national.netCDFdefProp];

obs-qcmesonet-local ConfigProp = [FMConfig, GOVERNING, @def.obs.qcmesonet.local.netCDFdefProp];

obs-hydro-local ConfigProp = [FMConfig, GOVERNING, @def.obs.hydro.local.netCDFdefProp];

obs-manual-local ConfigProp = [FMConfig, GOVERNING, @def.obs.manual.local.netCDFdefProp];


***************

Factor Mill Object Definition (ODEF) Files:

All Factor Mill Object Definition Files are located in "/ldad/classes/hmserve/ingestDefs". It may be empty since the default ODEF files are compiled into CNF files which are published on the website at: /ldad/data/ingest/ingest". The source code for the ODEF files are at: "ldad/src/webDissem/hmserve/ingestDefs".

Example GridFactorMill.odef File

Assume we are adding ETA Grids.

The GridFactorMill.odef file can be broken into three sections.

The first section is used to define a mFactorProp. This links the mFactorProp name to the factor name.

model.eta.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:eta:TempAir:national; }

model.eta.windU.national.mFactorProp MillFactorProp

{ factorName String = model:eta:windU:national; }

model.eta.windV.national.mFactorProp MillFactorProp

{ factorName String = model:eta:windV:national; }

model.eta.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:eta:RelHumidity:national; }

model.eta.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:eta:PressureSeaLevel:national; }

model.eta.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:eta:TotalPrecip:national; }

The second section is used to define a mFileProp. This links the mFileProp definition to mFactorProp's for each parameter to be extracted from the file. The mFactorProp's are defined in the first section of this file. This section also identifies that the data comes from a netCDF file and the config file name to be used in interpreting the data is NetCDFvariables.cnf which is a compiled version of NetCDFvariables.odef.

def.model.eta.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [ @model.eta.TempAir.national.mFactorProp,

@model.eta.windU.national.mFactorProp,

@model.eta.windV.national.mFactorProp,

@model.eta.RelHumidity.national.mFactorProp,

@model.eta.PressureSeaLevel.national.mFactorProp,

@model.eta.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

The third section is used to link the ConfigProp to be used in the NetCDFvariables.odef file to the definition of a mFileProp in the second section of this file.

model-eta-national ConfigProp = [MillFileProp, GOVERNING, @def.model.eta.national.mFileProp];

Factor Prop -

Factor Name -

GridFactorMill.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# GridFactorMill.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a StreamMill configuration file.

#F>>>=======================================================================

#-----------------------------------------------------------------

# MillFactorProps supporting each filetype.

# NOTE: Factor names have colons!!!

#-----------------------------------------------------------------

model.laps.TempAir.local.mFactorProp MillFactorProp

{ factorName String = model:laps:TempAir:local; }

model.laps.TempDewPoint.local.mFactorProp MillFactorProp

{ factorName String = model:laps:TempDewPoint:local; }

model.laps.windU.local.mFactorProp MillFactorProp

{ factorName String = model:laps:windU:local; }

model.laps.windV.local.mFactorProp MillFactorProp

{ factorName String = model:laps:windV:local; }

model.laps.RelHumidity.local.mFactorProp MillFactorProp

{ factorName String = model:laps:RelHumidity:local; }

model.laps.FireIndex.local.mFactorProp MillFactorProp

{ factorName String = model:laps:FireIndex:local; }

model.laps.SoilMoisture.local.mFactorProp MillFactorProp

{ factorName String = model:laps:SoilMoisture:local; }

model.laps.Vis.local.mFactorProp MillFactorProp

{ factorName String = model:laps:Vis:local; }

model.laps.1HourRain.local.mFactorProp MillFactorProp

{ factorName String = model:laps:1HourRain:local; }

model.laps.TotalRain.local.mFactorProp MillFactorProp

{ factorName String = model:laps:TotalRain:local; }

model.laps.1HourSnow.local.mFactorProp MillFactorProp

{ factorName String = model:laps:1HourSnow:local; }

model.laps.TotalSnow.local.mFactorProp MillFactorProp

{ factorName String = model:laps:TotalSnow:local; }

model.laps.SnowCoverage.local.mFactorProp MillFactorProp

{ factorName String = model:laps:SnowCoverage:local; }

model.laps.PrecipType.local.mFactorProp MillFactorProp

{ factorName String = model:laps:PrecipType:local; }

model.avn.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:avn:TempAir:national; }

model.avn.windU.national.mFactorProp MillFactorProp

{ factorName String = model:avn:windU:national; }

model.avn.windV.national.mFactorProp MillFactorProp

{ factorName String = model:avn:windV:national; }

model.avn.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:avn:RelHumidity:national; }

model.avn.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:avn:PressureSeaLevel:national; }

model.avn.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:avn:TotalPrecip:national; }

model.eta.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:eta:TempAir:national; }

model.eta.windU.national.mFactorProp MillFactorProp

{ factorName String = model:eta:windU:national; }

model.eta.windV.national.mFactorProp MillFactorProp

{ factorName String = model:eta:windV:national; }

model.eta.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:eta:RelHumidity:national; }

model.eta.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:eta:PressureSeaLevel:national; }

model.eta.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:eta:TotalPrecip:national; }

model.mesoeta.TempDewPoint.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:TempDewPoint:national; }

model.mesoeta.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:RelHumidity:national; }

model.mesoeta.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:PressureSeaLevel:national; }

model.mesoeta.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:TempAir:national; }

model.mesoeta.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:TotalPrecip:national; }

model.mesoeta.windU.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:windU:national; }

model.mesoeta.windV.national.mFactorProp MillFactorProp

{ factorName String = model:mesoeta:windV:national; }

model.ruc.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:TempAir:national; }

model.ruc.windU.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:windU:national; }

model.ruc.windV.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:windV:national; }

model.ruc.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:RelHumidity:national; }

model.ruc.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:PressureSeaLevel:national; }

model.ruc.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:ruc:TotalPrecip:national; }

model.mrf.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:TempAir:national; }

model.mrf.windU.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:windU:national; }

model.mrf.windV.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:windV:national; }

model.mrf.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:RelHumidity:national; }

model.mrf.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:PressureSeaLevel:national; }

model.mrf.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:mrf:TotalPrecip:national; }

model.msas.windU.national.mFactorProp MillFactorProp

{ factorName String = model:msas:windU:national; }

model.msas.windV.national.mFactorProp MillFactorProp

{ factorName String = model:msas:windV:national; }

model.msas.TempDewPoint.national.mFactorProp MillFactorProp

{ factorName String = model:msas:TempDewPoint:national; }

model.msas.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:msas:PressureSeaLevel:national; }

model.maps40.RelHumidity.national.mFactorProp MillFactorProp

{ factorName String = model:maps40:RelHumidity:national; }

model.maps40.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = model:maps40:PressureSeaLevel:national; }

model.maps40.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:maps40:TempAir:national; }

model.maps40.windU.national.mFactorProp MillFactorProp

{ factorName String = model:maps40:windU:national; }

model.maps40.windV.national.mFactorProp MillFactorProp

{ factorName String = model:maps40:windV:national; }

#-----------------------------------------------------------------

# MillFileProps supporting each filetype.

#-----------------------------------------------------------------

def.model.laps.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@model.laps.TempAir.local.mFactorProp,

@model.laps.TempDewPoint.local.mFactorProp,

@model.laps.windU.local.mFactorProp,

@model.laps.windV.local.mFactorProp,

@model.laps.RelHumidity.local.mFactorProp,

@model.laps.FireIndex.local.mFactorProp,

@model.laps.SoilMoisture.local.mFactorProp,

@model.laps.Vis.local.mFactorProp,

@model.laps.1HourRain.local.mFactorProp,

@model.laps.TotalRain.local.mFactorProp,

@model.laps.1HourSnow.local.mFactorProp,

@model.laps.TotalSnow.local.mFactorProp,

@model.laps.SnowCoverage.local.mFactorProp,

@model.laps.PrecipType.local.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.avn.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.avn.TempAir.national.mFactorProp,

@model.avn.windU.national.mFactorProp,

@model.avn.windV.national.mFactorProp,

@model.avn.RelHumidity.national.mFactorProp,

@model.avn.PressureSeaLevel.national.mFactorProp,

@model.avn.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.eta.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.eta.TempAir.national.mFactorProp,

@model.eta.windU.national.mFactorProp,

@model.eta.windV.national.mFactorProp,

@model.eta.RelHumidity.national.mFactorProp,

@model.eta.PressureSeaLevel.national.mFactorProp,

@model.eta.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.mesoeta.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.mesoeta.TempAir.national.mFactorProp,

@model.mesoeta.windU.national.mFactorProp,

@model.mesoeta.windV.national.mFactorProp,

@model.mesoeta.TempDewPoint.national.mFactorProp,

@model.mesoeta.RelHumidity.national.mFactorProp,

@model.mesoeta.PressureSeaLevel.national.mFactorProp,

@model.mesoeta.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.ruc.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.ruc.TempAir.national.mFactorProp,

@model.ruc.windU.national.mFactorProp,

@model.ruc.windV.national.mFactorProp,

@model.ruc.RelHumidity.national.mFactorProp,

@model.ruc.PressureSeaLevel.national.mFactorProp,

@model.ruc.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.mrf.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.mrf.TempAir.national.mFactorProp,

@model.mrf.windU.national.mFactorProp,

@model.mrf.windV.national.mFactorProp,

@model.mrf.RelHumidity.national.mFactorProp,

@model.mrf.PressureSeaLevel.national.mFactorProp,

@model.mrf.TotalPrecip.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.msas.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.msas.windU.national.mFactorProp,

@model.msas.windV.national.mFactorProp,

@model.msas.TempDewPoint.national.mFactorProp,

@model.msas.PressureSeaLevel.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.model.maps40.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@model.maps40.RelHumidity.national.mFactorProp,

@model.maps40.PressureSeaLevel.national.mFactorProp,

@model.maps40.TempAir.national.mFactorProp,

@model.maps40.windU.national.mFactorProp,

@model.maps40.windV.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

#-----------------------------------------------------------------

# FILETYPES supported by this factor mill configuration.

#-----------------------------------------------------------------

model-laps-local ConfigProp = [MillFileProp, GOVERNING, @def.model.laps.local.mFileProp];

model-avn-national ConfigProp = [MillFileProp, GOVERNING, @def.model.avn.national.mFileProp];

model-eta-national ConfigProp = [MillFileProp, GOVERNING, @def.model.eta.national.mFileProp];

model-mesoeta-national ConfigProp = [MillFileProp, GOVERNING, @def.model.mesoeta.national.mFileProp];

model-ruc-national ConfigProp = [MillFileProp, GOVERNING, @def.model.ruc.national.mFileProp];

model-mrf-national ConfigProp = [MillFileProp, GOVERNING, @def.model.mrf.national.mFileProp];

model-msas-national ConfigProp = [MillFileProp, GOVERNING, @def.model.msas.national.mFileProp];

model-maps40-national ConfigProp = [MillFileProp, GOVERNING, @def.model.maps40.national.mFileProp];

Example TextFactorMill.odef File

Assume we are adding a text warning.

The TextFactorMill.odef file can be broken into three sections.

The first section is used to define a mFactorProp. This links the mFactorProp name to the factor name.

nwstextlocal.warning.mFactorProp MillFactorProp

{ factorName String = nwstext:warning:local; }

The second section is used to define a mFileProp. This links the mFileProp definition to mFactorProp's for each parameter to be extracted from the file. The mFactorProp's are defined in the first section of this file. This section also identifies that the data does not come from a netCDF file.

nwstextlocal.warning.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.warning.mFactorProp];

netCDFconfigFileName String = null;

}

The third section is used to link the ConfigProp to the definition of a mFileProp in the second section of this file.

nwstext-warning-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.warning.mFileProp];

mFactorProp - nwstextlocal.warning.mFactorProp

factorName -

mFileProp -

HmScaleEnum -

netCDFconfigFileName

ConfigProp -

TextFactorMill.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# TextFactorMill.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a TextFactorMill configuration file.

#F>>>=======================================================================

#-----------------------------------------------------------------

# MillFactorProps supporting each filetype.

# NOTE: Factor names have colons!!!

#-----------------------------------------------------------------

nwstextlocal.forecast.mFactorProp MillFactorProp

{ factorName String = nwstext:forecast:local; }

nwstextlocal.outlook.mFactorProp MillFactorProp

{ factorName String = nwstext:outlook:local; }

nwstextlocal.qctext.mFactorProp MillFactorProp

{ factorName String = nwstext:qctext:local; }

nwstextlocal.report.mFactorProp MillFactorProp

{ factorName String = nwstext:report:local; }

nwstextlocal.statement.mFactorProp MillFactorProp

{ factorName String = nwstext:statement:local; }

nwstextlocal.warning.mFactorProp MillFactorProp

{ factorName String = nwstext:warning:local; }

nwstextlocal.watch.mFactorProp MillFactorProp

{ factorName String = nwstext:watch:local; }

localtext.report.mFactorProp MillFactorProp

{ factorName String = localtext:report:local; }

#-----------------------------------------------------------------

# MillFileProps supporting each filetype.

#-----------------------------------------------------------------

nwstextlocal.forecast.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.forecast.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.outlook.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.outlook.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.qctext.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.qctext.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.report.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.report.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.statement.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.statement.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.warning.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.warning.mFactorProp];

netCDFconfigFileName String = null;

}

nwstextlocal.watch.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@nwstextlocal.watch.mFactorProp];

netCDFconfigFileName String = null;

}

localtext.report.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@localtext.report.mFactorProp];

netCDFconfigFileName String = null;

}

#-----------------------------------------------------------------

# FILETYPES supported by this factor mill configuration.

#-----------------------------------------------------------------

nwstext-forecast-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.forecast.mFileProp];

nwstext-outlook-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.outlook.mFileProp];

nwstext-qctext-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.qctext.mFileProp];

nwstext-report-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.report.mFileProp];

nwstext-statement-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.statement.mFileProp];

nwstext-warning-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.warning.mFileProp];

nwstext-watch-local ConfigProp = [MillFileProp, GOVERNING, @nwstextlocal.watch.mFileProp];

localtext-report-local ConfigProp = [MillFileProp, GOVERNING, @localtext.report.mFileProp];

Example StreamMill.odef File:

The StreamMill is used to process maps, radial radar data, and Graphical Forecast Editor ASCII grids. (Note: the Graphical Forecast Editor was previously called the Interactive Forecast Editor which explains the "ifp" rather than "gfe" designation in the configuration files.

The webDissem client does not use maps which are processed by the Dynamic Data Format Converter so all of the items pertaining to maps could possibly be removed. The localization process will automatically add multiple radars except to the Menu files. Thus relocalizing may be the best way to add new radar products.

Assume we wish to manually add a Graphical Forecast Editor product such as TempAir.

The StreamMill.odef file can be broken into three sections.

The first section is used to define a mFactorProp. This links the mFactorProp name to the factor name.

model.ifp.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TempAir:national; }

The second section is used to define a mFileProp. This links the mFileProp definition to mFactorProp's for each parameter to be extracted from the file. The mFactorProp's are defined in the first section of this file. This section also identifies that the data does not come from a netCDF file.

def.model.ifp.national.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [ @model.ifp.TempAir.national.mFactorProp,

@model.ifp.TempDewPoint.national.mFactorProp,

@model.ifp.WindVector.national.mFactorProp,

@model.ifp.PercentCloudCover.national.mFactorProp,

@model.ifp.TotalPrecip.national.mFactorProp,

@model.ifp.ProbabilityOfPrecip.national.mFactorProp,

@model.ifp.1HourSnow.national.mFactorProp,

@model.ifp.TempAirMaxDay.national.mFactorProp,

@model.ifp.TempAirMinDay.national.mFactorProp,

@model.ifp.PresentWeather.national.mFactorProp,

@model.ifp.FreezingLevel.national.mFactorProp,

@model.ifp.WaveHeight.national.mFactorProp,

@model.ifp.SwellHeight.national.mFactorProp,

@model.ifp.ChanceOfWettingRain.national.mFactorProp,

@model.ifp.LightningActitityLvl.national.mFactorProp,

@model.ifp.HainesIndex.national.mFactorProp,

@model.ifp.MixingHeight.national.mFactorProp,

@model.ifp.FreeAirWind.national.mFactorProp,

@model.ifp.TransportWind.national.mFactorProp];

netCDFconfigFileName String = null;

}

The third section is used to link the ConfigProp to the definition of a mFileProp in the second section of this file.

model-ifp-national ConfigProp = [MillFileProp, GOVERNING, @def.model.ifp.national.mFileProp];

mFactorProp -

factorName -

mFileProp -

HmScaleEnum -

netCDFconfigFileName

ConfigProp -



StreamMill.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# streamMill.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a StreamMill configuration file.

#F>>>=======================================================================

#-----------------------------------------------------------------

# MillFactorProps supporting each filetype.# NOTE: Factor names have colons!!!

#-----------------------------------------------------------------

local.RFCs.mFactorProp MillFactorProp

{ factorName String = map:RFCs:local; }

region.RFCs.mFactorProp MillFactorProp

{ factorName String = map:RFCs:regional; }

local.CWAs.mFactorProp MillFactorProp

{ factorName String = map:CWAs:local; }

region.CWAs.mFactorProp MillFactorProp

{ factorName String = map:CWAs:regional; }

local.highways.mFactorProp MillFactorProp

{ factorName String = map:highways:local; }

region.highways.mFactorProp MillFactorProp

{ factorName String = map:highways:regional; }

local.counties.mFactorProp MillFactorProp

{ factorName String = map:counties:local; }

region.counties.mFactorProp MillFactorProp

{ factorName String = map:counties:regional; }

local.cities.mFactorProp MillFactorProp

{ factorName String = map:cities:local; }

region.cities.mFactorProp MillFactorProp

{ factorName String = map:cities:regional; }

local.parks.mFactorProp MillFactorProp

{ factorName String = map:parks:local; }

region.parks.mFactorProp MillFactorProp

{ factorName String = map:parks:regional; }

local.lakes.mFactorProp MillFactorProp

{ factorName String = map:lakes:local; }

region.lakes.mFactorProp MillFactorProp

{ factorName String = map:lakes:regional; }

local.interstates.mFactorProp MillFactorProp

{ factorName String = map:interstates:local; }

region.interstates.mFactorProp MillFactorProp

{ factorName String = map:interstates:regional; }

local.basins.mFactorProp MillFactorProp

{ factorName String = map:basins:local; }

region.basins.mFactorProp MillFactorProp

{ factorName String = map:basins:regional; }

local.rivers.mFactorProp MillFactorProp

{ factorName String = map:rivers:local; }

region.rivers.mFactorProp MillFactorProp

{ factorName String = map:rivers:regional; }

local.railroads.mFactorProp MillFactorProp

{ factorName String = map:railroads:local; }

region.railroads.mFactorProp MillFactorProp

{ factorName String = map:railroads:regional; }

radar.Reflectivity.local.mFactorProp MillFactorProp

{ factorName String = radar:Reflectivity:local; }

radar.1HourRain.local.mFactorProp MillFactorProp

{ factorName String = radar:1HourRain:local; }

radar.3HourRain.local.mFactorProp MillFactorProp

{ factorName String = radar:3HourRain:local; }

radar.TotalRain.local.mFactorProp MillFactorProp

{ factorName String = radar:TotalRain:local; }

model.ifp.TempAir.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TempAir:national; }

model.ifp.TempDewPoint.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TempDewPoint:national; }

model.ifp.WindVector.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:WindVector:national; }

model.ifp.PercentCloudCover.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:PercentCloudCover:national; }

model.ifp.TotalPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TotalPrecip:national; }

model.ifp.ProbabilityOfPrecip.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:ProbabilityOfPrecip:national; }

model.ifp.1HourSnow.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:1HourSnow:national; }

model.ifp.TempAirMaxDay.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TempAirMaxDay:national; }

model.ifp.TempAirMinDay.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TempAirMinDay:national; }

model.ifp.PresentWeather.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:PresentWeather:national; }

model.ifp.FreezingLevel.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:FreezingLevel:national; }

model.ifp.WaveHeight.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:WaveHeight:national; }

model.ifp.SwellHeight.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:SwellHeight:national; }

model.ifp.ChanceOfWettingRain.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:ChanceOfWettingRain:national; }

model.ifp.LightningActitityLvl.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:LightningActitityLvl:national; }

model.ifp.HainesIndex.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:HainesIndex:national; }

model.ifp.MixingHeight.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:MixingHeight:national; }

model.ifp.FreeAirWind.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:FreeAirWind:national; }

model.ifp.TransportWind.national.mFactorProp MillFactorProp

{ factorName String = model:ifp:TransportWind:national; }

#-----------------------------------------------------------------

# MillFileProps supporting each filetype.

#-----------------------------------------------------------------

local.RFCs.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.RFCs.mFactorProp];

netCDFconfigFileName String = null;

}

region.RFCs.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.RFCs.mFactorProp];

netCDFconfigFileName String = null;

}

local.CWAs.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.CWAs.mFactorProp];

netCDFconfigFileName String = null;

}

region.CWAs.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.CWAs.mFactorProp];

netCDFconfigFileName String = null;

}

local.highways.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.highways.mFactorProp];

netCDFconfigFileName String = null;

}

region.highways.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.highways.mFactorProp];

netCDFconfigFileName String = null;

}

local.counties.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.counties.mFactorProp];

netCDFconfigFileName String = null;

}

region.counties.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.counties.mFactorProp];

netCDFconfigFileName String = null;

}

local.cities.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.cities.mFactorProp];

netCDFconfigFileName String = null;

}

region.cities.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.cities.mFactorProp];

netCDFconfigFileName String = null;

}

local.parks.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.parks.mFactorProp];

netCDFconfigFileName String = null;

}

region.parks.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.parks.mFactorProp];

netCDFconfigFileName String = null;

}

local.lakes.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.lakes.mFactorProp];

netCDFconfigFileName String = null;

}

region.lakes.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.lakes.mFactorProp];

netCDFconfigFileName String = null;

}

local.interstates.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.interstates.mFactorProp];

netCDFconfigFileName String = null;

}

region.interstates.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.interstates.mFactorProp];

netCDFconfigFileName String = null;

}

local.basins.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.basins.mFactorProp];

netCDFconfigFileName String = null;

}

region.basins.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.basins.mFactorProp];

netCDFconfigFileName String = null;

}

local.rivers.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.rivers.mFactorProp];

netCDFconfigFileName String = null;

}

region.rivers.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.rivers.mFactorProp];

netCDFconfigFileName String = null;

}

local.railroads.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@local.railroads.mFactorProp];

netCDFconfigFileName String = null;

}

region.railroads.mFileProp MillFileProp

{

scale HmScaleEnum = REGIONAL;

factors [Object] = [@region.railroads.mFactorProp];

netCDFconfigFileName String = null;

}

radar.Reflectivity.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@radar.Reflectivity.local.mFactorProp];

netCDFconfigFileName String = null;

}

radar.1HourRain.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@radar.1HourRain.local.mFactorProp];

netCDFconfigFileName String = null;

}

radar.3HourRain.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@radar.3HourRain.local.mFactorProp];

netCDFconfigFileName String = null;

}

radar.TotalRain.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@radar.TotalRain.local.mFactorProp];

netCDFconfigFileName String = null;

}

def.model.ifp.national.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@model.ifp.TempAir.national.mFactorProp,

@model.ifp.TempDewPoint.national.mFactorProp,

@model.ifp.WindVector.national.mFactorProp,

@model.ifp.PercentCloudCover.national.mFactorProp,

@model.ifp.TotalPrecip.national.mFactorProp,

@model.ifp.ProbabilityOfPrecip.national.mFactorProp,

@model.ifp.1HourSnow.national.mFactorProp,

@model.ifp.TempAirMaxDay.national.mFactorProp,

@model.ifp.TempAirMinDay.national.mFactorProp,

@model.ifp.PresentWeather.national.mFactorProp,

@model.ifp.FreezingLevel.national.mFactorProp,

@model.ifp.WaveHeight.national.mFactorProp,

@model.ifp.SwellHeight.national.mFactorProp,

@model.ifp.ChanceOfWettingRain.national.mFactorProp,

@model.ifp.LightningActitityLvl.national.mFactorProp,

@model.ifp.HainesIndex.national.mFactorProp,

@model.ifp.MixingHeight.national.mFactorProp,

@model.ifp.FreeAirWind.national.mFactorProp,

@model.ifp.TransportWind.national.mFactorProp];

netCDFconfigFileName String = null;

}

#-----------------------------------------------------------------

# FILETYPES supported by this factor mill configuration.

#-----------------------------------------------------------------

map-RFCs-local ConfigProp = [MillFileProp, GOVERNING, @local.RFCs.mFileProp];

map-RFCs-regional ConfigProp = [MillFileProp, GOVERNING, @region.RFCs.mFileProp];

map-CWAs-local ConfigProp = [MillFileProp, GOVERNING, @local.CWAs.mFileProp];

map-CWAs-regional ConfigProp = [MillFileProp, GOVERNING, @region.CWAs.mFileProp];

map-highways-local ConfigProp = [MillFileProp, GOVERNING, @local.highways.mFileProp];

map-highways-regional ConfigProp = [MillFileProp, GOVERNING, @region.highways.mFileProp];

map-counties-local ConfigProp = [MillFileProp, GOVERNING, @local.counties.mFileProp];

map-counties-regional ConfigProp = [MillFileProp, GOVERNING, @region.counties.mFileProp];

map-cities-local ConfigProp = [MillFileProp, GOVERNING, @local.cities.mFileProp];

map-cities-regional ConfigProp = [MillFileProp, GOVERNING, @region.cities.mFileProp];

map-parks-local ConfigProp = [MillFileProp, GOVERNING, @local.parks.mFileProp];

map-parks-regional ConfigProp = [MillFileProp, GOVERNING, @region.parks.mFileProp];

map-lakes-local ConfigProp = [MillFileProp, GOVERNING, @local.lakes.mFileProp];

map-lakes-regional ConfigProp = [MillFileProp, GOVERNING, @region.lakes.mFileProp];

map-interstates-local ConfigProp = [MillFileProp, GOVERNING, @local.interstates.mFileProp];

map-interstates-regional ConfigProp = [MillFileProp, GOVERNING, @region.interstates.mFileProp];

map-basins-local ConfigProp = [MillFileProp, GOVERNING, @local.basins.mFileProp];

map-basins-regional ConfigProp = [MillFileProp, GOVERNING, @region.basins.mFileProp];

map-rivers-local ConfigProp = [MillFileProp, GOVERNING, @local.rivers.mFileProp];

map-rivers-regional ConfigProp = [MillFileProp, GOVERNING, @region.rivers.mFileProp];

map-railroads-local ConfigProp = [MillFileProp, GOVERNING, @local.railroads.mFileProp];

map-railroads-regional ConfigProp = [MillFileProp, GOVERNING, @region.railroads.mFileProp];

radar-Reflectivity-local ConfigProp = [MillFileProp, GOVERNING, @radar.Reflectivity.local.mFileProp];

radar-1HourRain-local ConfigProp = [MillFileProp, GOVERNING, @radar.1HourRain.local.mFileProp];

radar-3HourRain-local ConfigProp = [MillFileProp, GOVERNING, @radar.3HourRain.local.mFileProp];

radar-TotalRain-local ConfigProp = [MillFileProp, GOVERNING, @radar.TotalRain.local.mFileProp];

model-ifp-national ConfigProp = [MillFileProp, GOVERNING, @def.model.ifp.national.mFileProp];

Example ObsFactorMill.odef File:

Assume we wish to manually add a mesonet product which has quality control statistics.

The ObsFactorMill.odef file can be broken into three sections.

The first section is used to define a mFactorProp. This links the mFactorProp name to the factor name.

obs.qcmesonet.TempAir.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempAir:local; }

The second section is used to define a mFileProp. This links the mFileProp definition to mFactorProp's for each parameter to be extracted from the file. The mFactorProp's are defined in the first section of this file. This section also identifies that the data comes from a netCDF file and the config file name to be used in interpreting the data is NetCDFvariables.cnf which is a compiled version of NetCDFvariables.odef.

def.obs.qcmesonet.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@obs.qcmesonet.Latitude.local.mFactorProp,

@obs.qcmesonet.Longitude.local.mFactorProp,

@obs.qcmesonet.StationID.local.mFactorProp,

@obs.qcmesonet.ProviderID.local.mFactorProp,

@obs.qcmesonet.TempAir.local.mFactorProp,

@obs.qcmesonet.TempDewPoint.local.mFactorProp,

@obs.qcmesonet.RelHumidity.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevel.local.mFactorProp,

@obs.qcmesonet.WindDir.local.mFactorProp,

@obs.qcmesonet.WindSpeed.local.mFactorProp,

@obs.qcmesonet.Vis.local.mFactorProp,

@obs.qcmesonet.PresentWeather.local.mFactorProp,

@obs.qcmesonet.PrecipAccum.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCR.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCA.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCD.local.mFactorProp,

@obs.qcmesonet.TempAirQCR.local.mFactorProp,

@obs.qcmesonet.TempAirQCA.local.mFactorProp,

@obs.qcmesonet.TempAirQCD.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCR.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCA.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCD.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCR.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCA.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCD.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCR.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCA.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCD.local.mFactorProp,

@obs.qcmesonet.VisQCR.local.mFactorProp,

@obs.qcmesonet.VisQCA.local.mFactorProp,

@obs.qcmesonet.VisQCD.local.mFactorProp,

@obs.qcmesonet.WindDirQCR.local.mFactorProp,

@obs.qcmesonet.WindDirQCA.local.mFactorProp,

@obs.qcmesonet.WindDirQCD.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCR.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCA.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCD.local.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

The third section is used to link the ConfigProp to be used in the NetCDFvariables.odef file to the definition of a mFileProp in the second section of this file.

obs-qcmesonet-local ConfigProp = [MillFileProp, GOVERNING, @def.obs.qcmesonet.local.mFileProp];

mFactorProp -

factorName -

mFileProp -

HmScaleEnum -

netCDFconfigFileName

ConfigProp -

ObsFactorMill.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# ObsFactorMill.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a StreamMill configuration file.

#F>>>=======================================================================

#-----------------------------------------------------------------

# MillFactorProps supporting each filetype.

# NOTE: Factor names have colons!!!

#-----------------------------------------------------------------

obs.metar.Latitude.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:Latitude:national; }

obs.metar.Longitude.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:Longitude:national; }

obs.metar.StationID.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:StationID:national; }

obs.metar.TempAir.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:TempAir:national; }

obs.metar.TempDewPoint.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:TempDewPoint:national; }

obs.metar.PressureSeaLevel.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:PressureSeaLevel:national; }

obs.metar.WindDir.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:WindDir:national; }

obs.metar.WindSpeed.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:WindSpeed:national; }

obs.metar.PresentWeather.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:PresentWeather:national; }

obs.metar.Vis.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:Vis:national; }

obs.metar.Precip1Hour.national.mFactorProp MillFactorProp

{ factorName String = obs:metar:Precip1Hour:national; }

obs.qcmesonet.Latitude.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:Latitude:local; }

obs.qcmesonet.Longitude.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:Longitude:local; }

obs.qcmesonet.StationID.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:StationID:local; }

obs.qcmesonet.ProviderID.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:ProviderID:local; }

obs.qcmesonet.TempAir.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempAir:local; }

obs.qcmesonet.TempDewPoint.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempDewPoint:local; }

obs.qcmesonet.RelHumidity.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:RelHumidity:local; }

obs.qcmesonet.PressureSeaLevel.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PressureSeaLevel:local; }

obs.qcmesonet.WindDir.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindDir:local; }

obs.qcmesonet.WindSpeed.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindSpeed:local; }

obs.qcmesonet.Vis.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:Vis:local; }

obs.qcmesonet.PresentWeather.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PresentWeather:local; }

obs.qcmesonet.PrecipAccum.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PrecipAccum:local; }

obs.qcmesonet.PrecipAccumQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PrecipAccumQCR:local; }

obs.qcmesonet.PrecipAccumQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PrecipAccumQCA:local; }

obs.qcmesonet.PrecipAccumQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PrecipAccumQCD:local; }

obs.qcmesonet.TempAirQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempAirQCR:local; }

obs.qcmesonet.TempAirQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempAirQCA:local; }

obs.qcmesonet.TempAirQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempAirQCD:local; }

obs.qcmesonet.TempDewPointQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempDewPointQCR:local; }

obs.qcmesonet.TempDewPointQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempDewPointQCA:local; }

obs.qcmesonet.TempDewPointQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:TempDewPointQCD:local; }

obs.qcmesonet.RelHumidityQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:RelHumidityQCR:local; }

obs.qcmesonet.RelHumidityQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:RelHumidityQCA:local; }

obs.qcmesonet.RelHumidityQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:RelHumidityQCD:local; }

obs.qcmesonet.PressureSeaLevelQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PressureSeaLevelQCR:local; }

obs.qcmesonet.PressureSeaLevelQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PressureSeaLevelQCA:local; }

obs.qcmesonet.PressureSeaLevelQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:PressureSeaLevelQCD:local; }

obs.qcmesonet.VisQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:VisQCR:local; }

obs.qcmesonet.VisQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:VisQCA:local; }

obs.qcmesonet.VisQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:VisQCD:local; }

obs.qcmesonet.WindDirQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindDirQCR:local; }

obs.qcmesonet.WindDirQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindDirQCA:local; }

obs.qcmesonet.WindDirQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindDirQCD:local; }

obs.qcmesonet.WindSpeedQCR.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindSpeedQCR:local; }

obs.qcmesonet.WindSpeedQCA.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindSpeedQCA:local; }

obs.qcmesonet.WindSpeedQCD.local.mFactorProp MillFactorProp

{ factorName String = obs:qcmesonet:WindSpeedQCD:local; }

obs.hydro.Precip5Min.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip5Min:local; }

obs.hydro.Precip1Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip1Hour:local; }

obs.hydro.Precip3Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip3Hour:local; }

obs.hydro.Precip6Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip6Hour:local; }

obs.hydro.Precip12Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip12Hour:local; }

obs.hydro.Precip24Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Precip24Hour:local; }

obs.hydro.PrecipAccum.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:PrecipAccum:local; }

obs.hydro.Latitude.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Latitude:local; }

obs.hydro.Longitude.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:Longitude:local; }

obs.hydro.RiverStage.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:RiverStage:local; }

obs.hydro.RiverDischarge.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:RiverDischarge:local; }

obs.hydro.StationID.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:StationID:local; }

obs.hydro.ProviderID.local.mFactorProp MillFactorProp

{ factorName String = obs:hydro:ProviderID:local; }

obs.manual.Latitude.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:Latitude:local; }

obs.manual.Longitude.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:Longitude:local; }

obs.manual.IceCover.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:IceCover:local; }

obs.manual.Precip1Month.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:Precip1Month:local; }

obs.manual.Precip1Week.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:Precip1Week:local; }

obs.manual.Precip24Hour.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:Precip24Hour:local; }

obs.manual.PrecipStorm.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:PrecipStorm:local; }

obs.manual.PrecipType.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:PrecipType:local; }

obs.manual.PresentWeather.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:PresentWeather:local; }

obs.manual.RelHumidity.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:RelHumidity:local; }

obs.manual.RiverDischarge.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:RiverDischarge:local; }

obs.manual.RiverDischargePeak.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:RiverDischargePeak:local; }

obs.manual.RiverStage.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:RiverStage:local; }

obs.manual.RiverStageTrend.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:RiverStageTrend:local; }

obs.manual.SnowDepthTotal.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:SnowDepthTotal:local; }

obs.manual.SnowCoverage.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:SnowCoverage:local; }

obs.manual.SoilMoisture.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:SoilMoisture:local; }

obs.manual.SnowDepthNew.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:SnowDepthNew:local; }

obs.manual.StationID.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:StationID:local; }

obs.manual.TempAir.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:TempAir:local; }

obs.manual.TempAirMaxDay.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:TempAirMaxDay:local; }

obs.manual.TempAirMinDay.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:TempAirMinDay:local; }

obs.manual.TempDewPoint.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:TempDewPoint:local; }

obs.manual.WindDir.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:WindDir:local; }

obs.manual.WindSpeed.local.mFactorProp MillFactorProp

{ factorName String = obs:manual:WindSpeed:local; }

#-----------------------------------------------------------------

# MillFileProps supporting each filetype.

#-----------------------------------------------------------------

def.obs.metar.national.mFileProp MillFileProp

{

scale HmScaleEnum = NATIONAL;

factors [Object] = [@obs.metar.Latitude.national.mFactorProp,

@obs.metar.Longitude.national.mFactorProp,

@obs.metar.StationID.national.mFactorProp,

@obs.metar.TempAir.national.mFactorProp,

@obs.metar.TempDewPoint.national.mFactorProp,

@obs.metar.PressureSeaLevel.national.mFactorProp,

@obs.metar.WindDir.national.mFactorProp,

@obs.metar.WindSpeed.national.mFactorProp,

@obs.metar.PresentWeather.national.mFactorProp,

@obs.metar.Vis.national.mFactorProp,

@obs.metar.Precip1Hour.national.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.obs.qcmesonet.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@obs.qcmesonet.Latitude.local.mFactorProp,

@obs.qcmesonet.Longitude.local.mFactorProp,

@obs.qcmesonet.StationID.local.mFactorProp,

@obs.qcmesonet.ProviderID.local.mFactorProp,

@obs.qcmesonet.TempAir.local.mFactorProp,

@obs.qcmesonet.TempDewPoint.local.mFactorProp,

@obs.qcmesonet.RelHumidity.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevel.local.mFactorProp,

@obs.qcmesonet.WindDir.local.mFactorProp,

@obs.qcmesonet.WindSpeed.local.mFactorProp,

@obs.qcmesonet.Vis.local.mFactorProp,

@obs.qcmesonet.PresentWeather.local.mFactorProp,

@obs.qcmesonet.PrecipAccum.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCR.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCA.local.mFactorProp,

@obs.qcmesonet.PrecipAccumQCD.local.mFactorProp,

@obs.qcmesonet.TempAirQCR.local.mFactorProp,

@obs.qcmesonet.TempAirQCA.local.mFactorProp,

@obs.qcmesonet.TempAirQCD.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCR.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCA.local.mFactorProp,

@obs.qcmesonet.TempDewPointQCD.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCR.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCA.local.mFactorProp,

@obs.qcmesonet.RelHumidityQCD.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCR.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCA.local.mFactorProp,

@obs.qcmesonet.PressureSeaLevelQCD.local.mFactorProp,

@obs.qcmesonet.VisQCR.local.mFactorProp,

@obs.qcmesonet.VisQCA.local.mFactorProp,

@obs.qcmesonet.VisQCD.local.mFactorProp,

@obs.qcmesonet.WindDirQCR.local.mFactorProp,

@obs.qcmesonet.WindDirQCA.local.mFactorProp,

@obs.qcmesonet.WindDirQCD.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCR.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCA.local.mFactorProp,

@obs.qcmesonet.WindSpeedQCD.local.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.obs.hydro.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@obs.hydro.Latitude.local.mFactorProp,

@obs.hydro.Longitude.local.mFactorProp,

@obs.hydro.StationID.local.mFactorProp,

@obs.hydro.ProviderID.local.mFactorProp,

@obs.hydro.Precip5Min.local.mFactorProp,

@obs.hydro.Precip1Hour.local.mFactorProp,

@obs.hydro.Precip3Hour.local.mFactorProp,

@obs.hydro.Precip6Hour.local.mFactorProp,

@obs.hydro.Precip12Hour.local.mFactorProp,

@obs.hydro.Precip24Hour.local.mFactorProp,

@obs.hydro.PrecipAccum.local.mFactorProp,

@obs.hydro.RiverStage.local.mFactorProp,

@obs.hydro.RiverDischarge.local.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

def.obs.manual.local.mFileProp MillFileProp

{

scale HmScaleEnum = LOCAL;

factors [Object] = [@obs.manual.Latitude.local.mFactorProp,

@obs.manual.Longitude.local.mFactorProp,

@obs.manual.IceCover.local.mFactorProp,

@obs.manual.Precip1Month.local.mFactorProp,

@obs.manual.Precip1Week.local.mFactorProp,

@obs.manual.Precip24Hour.local.mFactorProp,

@obs.manual.PrecipStorm.local.mFactorProp,

@obs.manual.PrecipType.local.mFactorProp,

@obs.manual.PresentWeather.local.mFactorProp,

@obs.manual.RelHumidity.local.mFactorProp,

@obs.manual.RiverDischarge.local.mFactorProp,

@obs.manual.RiverDischargePeak.local.mFactorProp,

@obs.manual.RiverStage.local.mFactorProp,

@obs.manual.RiverStageTrend.local.mFactorProp,

@obs.manual.SnowDepthTotal.local.mFactorProp,

@obs.manual.SnowCoverage.local.mFactorProp,

@obs.manual.SoilMoisture.local.mFactorProp,

@obs.manual.SnowDepthNew.local.mFactorProp,

@obs.manual.StationID.local.mFactorProp,

@obs.manual.TempAir.local.mFactorProp,

@obs.manual.TempAirMaxDay.local.mFactorProp,

@obs.manual.TempAirMinDay.local.mFactorProp,

@obs.manual.TempDewPoint.local.mFactorProp,

@obs.manual.WindDir.local.mFactorProp,

@obs.manual.WindSpeed.local.mFactorProp];

netCDFconfigFileName String = "NetCDFvariables";

}

#-----------------------------------------------------------------

# FILETYPES supported by this factor mill configuration.

#-----------------------------------------------------------------

obs-metar-national ConfigProp = [MillFileProp, GOVERNING, @def.obs.metar.national.mFileProp];

obs-qcmesonet-local ConfigProp = [MillFileProp, GOVERNING, @def.obs.qcmesonet.local.mFileProp];

obs-hydro-local ConfigProp = [MillFileProp, GOVERNING, @def.obs.hydro.local.mFileProp];

obs-manual-local ConfigProp = [MillFileProp, GOVERNING, @def.obs.manual.local.mFileProp];


Example Ingest.odef File:

The Ingest Object Definition File is located in "/ldad/classes/hmserve/ingestDefs". It may be empty since the default ODEF files are compiled into CNF files which are published on the website at: /ldad/data/ingest/ingest". The source code for the ODEF files are at: "ldad/src/webDissem/hmserve/ingestDefs".

The Ingest.odef file contains links between the ConfigProp and one of four possible mills which handles processing the file. The possible mills are: GridFactorMill, TextFactorMill, StreamMill, and ObsFactorMill. (ie. model-eta-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];)

Ingest.odef File items which must be modified are highlighted as hyperlinks.

#F>=========================================================================

# Ingest.odef

# RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $

#========================================DISCLAIMER=========================

# This file has been developed by and/or for the U.S. government within the

# Forecast Systems Laboratory by government and/or contract personnel.

# As required by government regulations, this file is in the public

# domain, and is furnished "as is", without technical support, and with

# no warranty, express or implied, as to its usefulness for any purpose.

#F>>=====================================description (optional)=============

# This file is used to create a ingest configuration file.

#F>>>=======================================================================


# config package name...

configPackage ConfigProp = [String, GOVERNING, "ingest"];

# UNIX data directory path...

#unixDirPath ConfigProp = [String, GOVERNING, "ldadapp/tstdata/Shapefiles"];

unixDirPath ConfigProp = [String, GOVERNING, "/tmp"];

# DOS data directory path...

dosDirPath ConfigProp = [String, GOVERNING, "\\SOME_DIR"];

# UNIX test data directory path...

#unixTestDirPath ConfigProp = [String, GOVERNING, "ldadapp/tstdata/Shapefiles"];

unixTestDirPath ConfigProp = [String, GOVERNING, "/tmp"];

# DOS test data directory path...

dosTestDirPath ConfigProp = [String, GOVERNING, "\\SOME_DIR"];

# Factor mill package name...

millPackage ConfigProp = [String, GOVERNING, "hmserve.ingest"];

# The names of all mills to be started by ingest.

mill.names [String] = ["StreamMill", "LAPStempFactorMill"];

millNames ConfigProp = ["[String]", GOVERNING, @mill.names];


#-----------------------------------------------------------------

# FILETYPES supported by Ingest, and their mill names

# These last lines map filetypes to appropriate mill names.

#-----------------------------------------------------------------

map-RFCs-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-RFCs-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-CWAs-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-CWAs-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-highways-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-highways-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-counties-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-counties-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-cities-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-cities-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-parks-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-parks-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-lakes-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-lakes-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-interstates-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-interstates-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-basins-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-basins-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-rivers-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-rivers-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-railroads-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

map-railroads-regionalMill ConfigProp = [String, GOVERNING, "StreamMill"];

model-laps-temperature-localMill ConfigProp = [String, GOVERNING, "LAPStempFactorMill"];

model-laps-localMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-avn-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-eta-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-mesoeta-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-ruc-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-mrf-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-msas-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

model-maps40-nationalMill ConfigProp = [String, GOVERNING, "GridFactorMill"];

obs-metar-nationalMill ConfigProp = [String, GOVERNING, "ObsFactorMill"];

obs-qcmesonet-localMill ConfigProp = [String, GOVERNING, "ObsFactorMill"];

obs-hydro-localMill ConfigProp = [String, GOVERNING, "ObsFactorMill"];

obs-manual-localMill ConfigProp = [String, GOVERNING, "ObsFactorMill"];

nwstext-forecast-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-outlook-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-qctext-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-report-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-statement-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-warning-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

nwstext-watch-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

localtext-report-localMill ConfigProp = [String, GOVERNING, "TextFactorMill"];

radar-Reflectivity-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

radar-1HourRain-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

radar-3HourRain-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

radar-TotalRain-localMill ConfigProp = [String, GOVERNING, "StreamMill"];

model-ifp-nationalMill ConfigProp = [String, GOVERNING, "StreamMill"];

Compiling the Object Definition files (odef) into Configuration Files (cnf):

The default value for LDAD_HOME is "/ldad".

If you have created or modified Individual ODEF files, copy them to "${LDAD_HOME}/classes/hmlib/factorODEF/" on "ls1".

If you have created or modified scale ODEF files, copy them to "${LDAD_HOME}/classes/hmlib/scaleDefs/" on "ls1".

If you have created or modified FactorMill ODEF files, copy them to "${LDAD_HOME}/classes/hmlib/ingestDefs/" on "ls1".

If you have created or modified the NetCDFvariables.odef file, copy it to "${LDAD_HOME}/classes/hmserve/ingestDefs/" on "ls1".

If you have created or modified the ingest.odef file, copy it to "${LDAD_HOME}/classes/hmserve/ingestDefs/" on "ls1".

First backup "${LDAD_HOME}/data" so you can recover if something does not work.

Next add an entry in "compileODEF.csh" corresponding to your new ODEF file. Copy the compileODEF.csh script to the ${LDAD_HOME}/" directory on "ls1". Please verify that the directory "${LDAD_HOME}/data" exists on "ls1". If it does not exist, either relocalize or create a directory called "${LDAD_HOME}/data". Under this directory the following files/directories should exist:

Three files:

             ParmToIFP.table

             logconf.ini

             pollForData.conf

Three directories:

             factor

             ingest

             scale

If the three directories do not exist, then create them using "mkdir". Next find and copy the ParmToIFP.table, logconf.ini, and pollForData.conf files to the "${LDAD_HOME}/data" directory on "ls1".

Next, type "source compileODEF.csh" on the command line and enter. (Alternatively, type "chmod +x compileODEF.csh" and enter. Then type "compileODEF.csh" and enter.) This will populate "factor", "scale", and "ingest" directories in "${LDAD_HOME}/data/" with the config files (*.cnf) that are needed by the makeData.java and hmingestd.java programs.  For example, "${LDAD_HOME}/classes/hmlib/factorDefs/obs-qcmesonet-TempDewPoint-local.odef" is compiled into "${LDAD_HOME}/data/factor/obs-qcmesonet-TempDewPoint-local.cnf".

For example, "${LDAD_HOME}/classes/hmserve/ingestDefs/NetCDFvariables.odef" is compiled into "${LDAD_HOME}/data/ingest/NetCDFvariables.cnf".

compileODEF.csh

#!/bin/csh -f
#compileODEF.csh


cp ./classes/hmlib/utils/*.ini .
setenv CLASSPATH .:../ldad/classes:../ldad/classes/hmlib/utils:./data:
setenv PATH ${PATH}:.:../ldad/classes/hmlib/utils:

setenv JAVA /opt/java/bin/java
setenv CBDir ../ldad/classes/hmlib/factorDefs
setenv CBDirM ../ldad/classes/hmlib/miscDefs
setenv CBDirS ../ldad/classes/hmlib/scaleDefs
setenv CBDirIngest ../ldad/classes/hmserve/ingestDefs
setenv RUNROOT ../ldad/data
setenv GENCONFIG "$JAVA -Drun.config.dir=$RUNROOT hmlib.utils.genconfig"


#################################
${GENCONFIG} -g ${CBDirIngest}/ingest.odef ingest.ingest

${GENCONFIG} -g ${CBDirIngest}/StreamMill.odef ingest.StreamMill

${GENCONFIG} -g ${CBDirIngest}/GridFactorMill.odef ingest.GridFactorMill

${GENCONFIG} -g ${CBDirIngest}/ObsFactorMill.odef ingest.ObsFactorMill

${GENCONFIG} -g ${CBDirIngest}/TextFactorMill.odef ingest.TextFactorMill

${GENCONFIG} -g ${CBDirIngest}/hmingestd.odef ingest.hmingestd

${GENCONFIG} -g ${CBDirIngest}/NetCDFvariables.odef ingest.NetCDFvariables

####################################

${GENCONFIG} -g ${CBDir}/model-laps-1HourRain-local factor.model-laps-1HourRain-local

${GENCONFIG} -g ${CBDir}/model-laps-1HourSnow-local factor.model-laps-1HourSnow-local

${GENCONFIG} -g ${CBDir}/model-laps-TempDewPoint-local factor.model-laps-TempDewPoint-local

${GENCONFIG} -g ${CBDir}/model-laps-FireIndex-local factor.model-laps-FireIndex-local

${GENCONFIG} -g ${CBDir}/model-laps-PrecipType-local factor.model-laps-PrecipType-local

${GENCONFIG} -g ${CBDir}/model-laps-RelHumidity-local factor.model-laps-RelHumidity-local

${GENCONFIG} -g ${CBDir}/model-laps-SnowCoverage-local factor.model-laps-SnowCoverage-local

${GENCONFIG} -g ${CBDir}/model-laps-SoilMoisture-local factor.model-laps-SoilMoisture-local

${GENCONFIG} -g ${CBDir}/model-laps-TempAir-local factor.model-laps-TempAir-local

${GENCONFIG} -g ${CBDir}/model-laps-TotalRain-local factor.model-laps-TotalRain-local

${GENCONFIG} -g ${CBDir}/model-laps-TotalSnow-local factor.model-laps-TotalSnow-local

${GENCONFIG} -g ${CBDir}/model-laps-Vis-local factor.model-laps-Vis-local

${GENCONFIG} -g ${CBDir}/model-laps-windU-local factor.model-laps-windU-local

${GENCONFIG} -g ${CBDir}/model-laps-windV-local factor.model-laps-windV-local

${GENCONFIG} -g ${CBDir}/model-avn-RelHumidity-national factor.model-avn-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-avn-PressureSeaLevel-national factor.model-avn-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-avn-TempAir-national factor.model-avn-TempAir-national

${GENCONFIG} -g ${CBDir}/model-avn-TotalPrecip-national factor.model-avn-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-avn-windU-national factor.model-avn-windU-national

${GENCONFIG} -g ${CBDir}/model-avn-windV-national factor.model-avn-windV-national

${GENCONFIG} -g ${CBDir}/model-eta-RelHumidity-national factor.model-eta-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-eta-PressureSeaLevel-national factor.model-eta-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-eta-TempAir-national factor.model-eta-TempAir-national

${GENCONFIG} -g ${CBDir}/model-eta-TotalPrecip-national factor.model-eta-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-eta-windU-national factor.model-eta-windU-national

${GENCONFIG} -g ${CBDir}/model-eta-windV-national factor.model-eta-windV-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-TempDewPoint-national factor.model-mesoeta-TempDewPoint-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-RelHumidity-national factor.model-mesoeta-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-PressureSeaLevel-national factor.model-mesoeta-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-TempAir-national factor.model-mesoeta-TempAir-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-TotalPrecip-national factor.model-mesoeta-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-windU-national factor.model-mesoeta-windU-national

${GENCONFIG} -g ${CBDir}/model-mesoeta-windV-national factor.model-mesoeta-windV-national

${GENCONFIG} -g ${CBDir}/model-mrf-RelHumidity-national factor.model-mrf-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-mrf-PressureSeaLevel-national factor.model-mrf-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-mrf-TempAir-national actor.model-mrf-TempAir-national

${GENCONFIG} -g ${CBDir}/model-mrf-TotalPrecip-national factor.model-mrf-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-mrf-windU-national factor.model-mrf-windU-national

${GENCONFIG} -g ${CBDir}/model-mrf-windV-national factor.model-mrf-windV-national

${GENCONFIG} -g ${CBDir}/model-ruc-RelHumidity-national factor.model-ruc-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-ruc-PressureSeaLevel-national factor.model-ruc-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-ruc-TempAir-national factor.model-ruc-TempAir-national

${GENCONFIG} -g ${CBDir}/model-ruc-TotalPrecip-national factor.model-ruc-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-ruc-windU-national factor.model-ruc-windU-national

${GENCONFIG} -g ${CBDir}/model-ruc-windV-national factor.model-ruc-windV-national

${GENCONFIG} -g ${CBDir}/model-msas-TempDewPoint-national factor.model-msas-TempDewPoint-national

${GENCONFIG} -g ${CBDir}/model-msas-PressureSeaLevel-national factor.model-msas-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-msas-windU-national factor.model-msas-windU-national

${GENCONFIG} -g ${CBDir}/model-msas-windV-national factor.model-msas-windV-national

${GENCONFIG} -g ${CBDir}/model-maps40-RelHumidity-national factor.model-maps40-RelHumidity-national

${GENCONFIG} -g ${CBDir}/model-maps40-PressureSeaLevel-national factor.model-maps40-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/model-maps40-TempAir-national factor.model-maps40-TempAir-national

${GENCONFIG} -g ${CBDir}/model-maps40-windU-national factor.model-maps40-windU-national

${GENCONFIG} -g ${CBDir}/model-maps40-windV-national factor.model-maps40-windV-national

${GENCONFIG} -g ${CBDir}/model-ifp-TempAir-national factor.model-ifp-TempAir-national

${GENCONFIG} -g ${CBDir}/model-ifp-TempDewPoint-national factor.model-ifp-TempDewPoint-national

${GENCONFIG} -g ${CBDir}/model-ifp-WindVector-national factor.model-ifp-WindVector-national

${GENCONFIG} -g ${CBDir}/model-ifp-PercentCloudCover-national factor.model-ifp-PercentCloudCover-national

${GENCONFIG} -g ${CBDir}/model-ifp-TotalPrecip-national factor.model-ifp-TotalPrecip-national

${GENCONFIG} -g ${CBDir}/model-ifp-ProbabilityOfPrecip-national factor.model-ifp-ProbabilityOfPrecip-national

${GENCONFIG} -g ${CBDir}/model-ifp-1HourSnow-national factor.model-ifp-1HourSnow-national

${GENCONFIG} -g ${CBDir}/model-ifp-TempAirMaxDay-national factor.model-ifp-TempAirMaxDay-national

${GENCONFIG} -g ${CBDir}/model-ifp-TempAirMinDay-national factor.model-ifp-TempAirMinDay-national

${GENCONFIG} -g ${CBDir}/model-ifp-PresentWeather-national factor.model-ifp-PresentWeather-national

${GENCONFIG} -g ${CBDir}/model-ifp-FreezingLevel-national factor.model-ifp-FreezingLevel-national

${GENCONFIG} -g ${CBDir}/model-ifp-WaveHeight-national factor.model-ifp-WaveHeight-national

${GENCONFIG} -g ${CBDir}/model-ifp-SwellHeight-national factor.model-ifp-SwellHeight-national

${GENCONFIG} -g ${CBDir}/model-ifp-ChanceOfWettingRain-national factor.model-ifp-ChanceOfWettingRain-national

${GENCONFIG} -g ${CBDir}/model-ifp-LightningActitityLvl-national factor.model-ifp-LightningActitityLvl-national

${GENCONFIG} -g ${CBDir}/model-ifp-HainesIndex-national factor.model-ifp-HainesIndex-national

${GENCONFIG} -g ${CBDir}/model-ifp-MixingHeight-national factor.model-ifp-MixingHeight-national

${GENCONFIG} -g ${CBDir}/model-ifp-FreeAirWind-national factor.model-ifp-FreeAirWind-national

${GENCONFIG} -g ${CBDir}/model-ifp-TransportWind-national factor.model-ifp-TransportWind-national

${GENCONFIG} -g ${CBDir}/obs-metar-Precip1Hour-national factor.obs-metar-Precip1Hour-national

${GENCONFIG} -g ${CBDir}/obs-metar-TempDewPoint-national factor.obs-metar-TempDewPoint-national

${GENCONFIG} -g ${CBDir}/obs-metar-PressureSeaLevel-national factor.obs-metar-PressureSeaLevel-national

${GENCONFIG} -g ${CBDir}/obs-metar-TempAir-national factor.obs-metar-TempAir-national

${GENCONFIG} -g ${CBDir}/obs-metar-Vis-national factor.obs-metar-Vis-national

${GENCONFIG} -g ${CBDir}/obs-metar-WindDir-national factor.obs-metar-WindDir-national

${GENCONFIG} -g ${CBDir}/obs-metar-WindSpeed-national factor.obs-metar-WindSpeed-national

${GENCONFIG} -g ${CBDir}/obs-metar-PresentWeather-national factor.obs-metar-PresentWeather-national

${GENCONFIG} -g ${CBDir}/obs-metar-StationID-national factor.obs-metar-StationID-national

${GENCONFIG} -g ${CBDir}/obs-metar-Latitude-national factor.obs-metar-Latitude-national

${GENCONFIG} -g ${CBDir}/obs-metar-Longitude-national factor.obs-metar-Longitude-national

${GENCONFIG} -g ${CBDir}/obs-metar-station-national factor.obs-metar-station-national

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PrecipAccum-local factor.obs-qcmesonet-PrecipAccum-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempDewPoint-local factor.obs-qcmesonet-TempDewPoint-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-Latitude-local factor.obs-qcmesonet-Latitude-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-Longitude-local factor.obs-qcmesonet-Longitude-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-RelHumidity-local factor.obs-qcmesonet-RelHumidity-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PressureSeaLevel-local factor.obs-qcmesonet-PressureSeaLevel-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-StationID-local factor.obs-qcmesonet-StationID-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-ProviderID-local factor.obs-qcmesonet-ProviderID-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempAir-local factor.obs-qcmesonet-TempAir-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-Vis-local factor.obs-qcmesonet-Vis-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PresentWeather-local factor.obs-qcmesonet-PresentWeather-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindDir-local factor.obs-qcmesonet-WindDir-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindSpeed-local factor.obs-qcmesonet-WindSpeed-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PrecipAccumQCR-local factor.obs-qcmesonet-PrecipAccumQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PrecipAccumQCA-local factor.obs-qcmesonet-PrecipAccumQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PrecipAccumQCD-local factor.obs-qcmesonet-PrecipAccumQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempAirQCR-local factor.obs-qcmesonet-TempAirQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempAirQCA-local factor.obs-qcmesonet-TempAirQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempAirQCD-local factor.obs-qcmesonet-TempAirQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempDewPointQCR-local factor.obs-qcmesonet-TempDewPointQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempDewPointQCA-local factor.obs-qcmesonet-TempDewPointQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-TempDewPointQCD-local factor.obs-qcmesonet-TempDewPointQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-RelHumidityQCR-local factor.obs-qcmesonet-RelHumidityQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-RelHumidityQCA-local factor.obs-qcmesonet-RelHumidityQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-RelHumidityQCD-local factor.obs-qcmesonet-RelHumidityQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PressureSeaLevelQCR-local factor.obs-qcmesonet-PressureSeaLevelQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PressureSeaLevelQCA-local factor.obs-qcmesonet-PressureSeaLevelQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-PressureSeaLevelQCD-local factor.obs-qcmesonet-PressureSeaLevelQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-VisQCR-local factor.obs-qcmesonet-VisQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-VisQCA-local factor.obs-qcmesonet-VisQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-VisQCD-local factor.obs-qcmesonet-VisQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindDirQCR-local factor.obs-qcmesonet-WindDirQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindDirQCA-local factor.obs-qcmesonet-WindDirQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindDirQCD-local factor.obs-qcmesonet-WindDirQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindSpeedQCR-local factor.obs-qcmesonet-WindSpeedQCR-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindSpeedQCA-local factor.obs-qcmesonet-WindSpeedQCA-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-WindSpeedQCD-local factor.obs-qcmesonet-WindSpeedQCD-local

${GENCONFIG} -g ${CBDir}/obs-qcmesonet-station-local factor.obs-qcmesonet-station-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip5Min-local factor.obs-hydro-Precip5Min-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip1Hour-local factor.obs-hydro-Precip1Hour-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip3Hour-local factor.obs-hydro-Precip3Hour-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip6Hour-local factor.obs-hydro-Precip6Hour-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip12Hour-local factor.obs-hydro-Precip12Hour-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Precip24Hour-local factor.obs-hydro-Precip24Hour-local

${GENCONFIG} -g ${CBDir}/obs-hydro-PrecipAccum-local factor.obs-hydro-PrecipAccum-local

${GENCONFIG} -g ${CBDir}/obs-hydro-ProviderID-local factor.obs-hydro-ProviderID-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Latitude-local factor.obs-hydro-Latitude-local

${GENCONFIG} -g ${CBDir}/obs-hydro-Longitude-local factor.obs-hydro-Longitude-local

${GENCONFIG} -g ${CBDir}/obs-hydro-RiverStage-local factor.obs-hydro-RiverStage-local

${GENCONFIG} -g ${CBDir}/obs-hydro-RiverDischarge-local factor.obs-hydro-RiverDischarge-local

${GENCONFIG} -g ${CBDir}/obs-hydro-StationID-local factor.obs-hydro-StationID-local

${GENCONFIG} -g ${CBDir}/obs-hydro-station-local factor.obs-hydro-station-local

${GENCONFIG} -g ${CBDir}/obs-manual-Latitude-local factor.obs-manual-Latitude-local

${GENCONFIG} -g ${CBDir}/obs-manual-Longitude-local factor.obs-manual-Longitude-local

${GENCONFIG} -g ${CBDir}/obs-manual-IceCover-local factor.obs-manual-IceCover-local

${GENCONFIG} -g ${CBDir}/obs-manual-Precip1Month-local factor.obs-manual-Precip1Month-local

${GENCONFIG} -g ${CBDir}/obs-manual-Precip1Week-local factor.obs-manual-Precip1Week-local

${GENCONFIG} -g ${CBDir}/obs-manual-Precip24Hour-local factor.obs-manual-Precip24Hour-local

${GENCONFIG} -g ${CBDir}/obs-manual-PrecipStorm-local factor.obs-manual-PrecipStorm-local

${GENCONFIG} -g ${CBDir}/obs-manual-PrecipType-local factor.obs-manual-PrecipType-local

${GENCONFIG} -g ${CBDir}/obs-manual-PresentWeather-local factor.obs-manual-PresentWeather-local

${GENCONFIG} -g ${CBDir}/obs-manual-RelHumidity-local factor.obs-manual-RelHumidity-local

${GENCONFIG} -g ${CBDir}/obs-manual-RiverDischarge-local factor.obs-manual-RiverDischarge-local

${GENCONFIG} -g ${CBDir}/obs-manual-RiverDischargePeak-local factor.obs-manual-RiverDischargePeak-local

${GENCONFIG} -g ${CBDir}/obs-manual-RiverStage-local factor.obs-manual-RiverStage-local

${GENCONFIG} -g ${CBDir}/obs-manual-RiverStageTrend-local factor.obs-manual-RiverStageTrend-local

${GENCONFIG} -g ${CBDir}/obs-manual-SnowCoverage-local factor.obs-manual-SnowCoverage-local

${GENCONFIG} -g ${CBDir}/obs-manual-SnowDepthNew-local factor.obs-manual-SnowDepthNew-local

${GENCONFIG} -g ${CBDir}/obs-manual-SnowDepthTotal-local factor.obs-manual-SnowDepthTotal-local

${GENCONFIG} -g ${CBDir}/obs-manual-SoilMoisture-local factor.obs-manual-SoilMoisture-local

${GENCONFIG} -g ${CBDir}/obs-manual-StationID-local factor.obs-manual-StationID-local

${GENCONFIG} -g ${CBDir}/obs-manual-TempAir-local factor.obs-manual-TempAir-local

${GENCONFIG} -g ${CBDir}/obs-manual-TempAirMaxDay-local factor.obs-manual-TempAirMaxDay-local

${GENCONFIG} -g ${CBDir}/obs-manual-TempAirMinDay-local factor.obs-manual-TempAirMinDay-local

${GENCONFIG} -g ${CBDir}/obs-manual-TempDewPoint-local factor.obs-manual-TempDewPoint-local

${GENCONFIG} -g ${CBDir}/obs-manual-WindDir-local factor.obs-manual-WindDir-local

${GENCONFIG} -g ${CBDir}/obs-manual-WindSpeed-local factor.obs-manual-WindSpeed-local

${GENCONFIG} -g ${CBDir}/obs-manual-station-local factor.obs-manual-station-local

${GENCONFIG} -g ${CBDir}/radar-Reflectivity-local factor.radar-Reflectivity-local

${GENCONFIG} -g ${CBDir}/radar-1HourRain-local factor.radar-1HourRain-local

${GENCONFIG} -g ${CBDir}/radar-3HourRain-local factor.radar-3HourRain-local

${GENCONFIG} -g ${CBDir}/radar-TotalRain-local factor.radar-TotalRain-local

${GENCONFIG} -g ${CBDir}/nwstext-forecast-local factor.nwstext-forecast-local

${GENCONFIG} -g ${CBDir}/nwstext-outlook-local factor.nwstext-outlook-local

${GENCONFIG} -g ${CBDir}/nwstext-qctext-local factor.nwstext-qctext-local

${GENCONFIG} -g ${CBDir}/nwstext-report-local factor.nwstext-report-local

${GENCONFIG} -g ${CBDir}/nwstext-statement-local factor.nwstext-statement-local

${GENCONFIG} -g ${CBDir}/nwstext-warning-local factor.nwstext-warning-local

${GENCONFIG} -g ${CBDir}/nwstext-watch-local factor.nwstext-watch-local

${GENCONFIG} -g ${CBDir}/localtext-report-local factor.localtext-report-local

Editing PollForData.conf:

See ldadWebSMM.html and the LDAD System Managers manual.

Edit the file "ds:~ldad/data/pollForData.conf".

Copy the file "ds:~ldad/data/pollForData.conf" to "ls:/ldad/data/pollForData.conf". (Ingest of radar has hmingestd using pollForData.conf.)

Stop and restart LDAD on the ds computer.

Example of pollForData.conf file for the above ODEF files:

###################################################################

# pollForData.conf: configuration file for the LDAD polling function

#

# Each line describes one dataset via 7 fields

# Tag Source of data (unused)

# Key Description of the data

# Type "model, obs, radar, nwstext, localtext"

# Source "laps, msas, ifp, maps40, ruc, eta, mesoeta, avn, mrf";

# "metar, qcmesonet, hydro, manual";

# "r1r, r2r, etc.."; (radar IDs substituted during localization)

# "warning, watch, forecast, outlook, report, statement, qctext";

# "warning, watch, forecast, outlook, report, statement, qctext"

# DataType "Reflectivity, 1HourRain, 3HourRain, TotalRain, Tornado"

# (This field applies to radar only.)

# Scale "local, national" (dissemination system display scale)

# SrcDir Source directory (on ds).

# Time(s) The source directory is checked at these times (minutes past

# the hour) to see if the data have updated. If -1, checks at

# each pollForData cycle (30 seconds).

# Script "/awips/ldad/bin/sendLDADnotification.pl"

# Arguments Parameters passed to the script - always 'R "KKK FFF" HHH PPP'

# R means send to ls and notify hmIngest

# pollForData.pl makes substitutions for the rest with the key,

# file name, host, and internal port number, respectively.

# DestDir Destination directory (on ls).

###################################################################

# LAPS Analysis

FSL|model:laps:local|/data/fxa/Grid/FSL/netCDF/LAPS_Grid/LAPS|30,35,40|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/LAPS

# MSAS Analysis

FSL|model:msas:national|/data/fxa/Grid/FSL/netCDF/MSAS|30,35|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/MSAS

# IFP Grids

FSL|model:ifp:Official:national|/data/fxa/LDAD/ifp/Official|10,30|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/ifp/Official

# IFP Grids

FSL|model:ifp:RUC:national|/data/fxa/LDAD/ifp/RUC|30,50|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/ifp/RUC

# MAPS 40 km Model

#FSL|model:maps40:national|/data/fxa/Grid/FSL/netCDF/MAPS_National/40km_MAPS|30,35|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/MAPS40

# RUC Model

#FSL|model:ruc:national|/data/fxa/Grid/SBN/netCDF/CONUS211/RUC|25,45|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/RUC

# Eta Model

#FSL|model:eta:national|/data/fxa/Grid/SBN/netCDF/CONUS211/Eta|20,45|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/Eta

# mesoEta model

#FSL|model:mesoeta:national|/data/fxa/Grid/SBN/netCDF/CONUS215/MesoEta|20,45|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/MesoEta

# AVN Model

#FSL|model:avn:national|/data/fxa/Grid/SBN/netCDF/CONUS211/AVN|20,45|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/AVN

# MRF Model

#FSL|model:mrf:national|/data/fxa/Grid/SBN/netCDF/CONUS202/MRF|20,45|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/MRF

# National METAR Observations

FSL|obs:metar:national|/data/fxa/point/metar/netcdf|20,50|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/point/metar

# Local QC-Mesonet Observations

FSL|obs:qcmesonet:local|/data/fxa/LDAD/mesonet/qc|5,15,25,35,45,55|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/point/qcmesonet

# Local Hydro Observations

FSL|obs:hydro:local|/data/fxa/LDAD/hydro/netCDF|2,12,22,32,42,52|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/point/hydro

# Local Manual Observations

FSL|obs:manual:local|/data/fxa/LDAD/manual/netCDF|1,11,21,31,41,51|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/point/manual

# Nexrad r1r Reflectivity

FSL|radar:r1r:Reflectivity:local|/data/fxa/radar/r1r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r1r/Z

# Nexrad r1r One Hour Precip

FSL|radar:r1r:1HourRain:local|/data/fxa/radar/r1r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r1r/OHP

# Nexrad r1r Three Hour Precip

FSL|radar:r1r:3HourRain:local|/data/fxa/radar/r1r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r1r/THP

# Nexrad r1r Storm Total

FSL|radar:r1r:TotalRain:local|/data/fxa/radar/r1r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r1r/STP

# Nexrad r1r Tornado Vorticity Signature

FSL|radar:r1r:Tornado:local|/data/fxa/radar/r1r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r1r/TVS

# Nexrad r2r Reflectivity

FSL|radar:r2r:Reflectivity:local|/data/fxa/radar/r2r/Z/elev0_5/res1/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r2r/Z

# Nexrad r2r One Hour Precip

FSL|radar:r2r:1HourRain:local|/data/fxa/radar/r2r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r2r/OHP

# Nexrad r2r Three Hour Precip

FSL|radar:r2r:3HourRain:local|/data/fxa/radar/r2r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r2r/THP

# Nexrad r2r Storm Total

FSL|radar:r2r:TotalRain:local|/data/fxa/radar/r2r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r2r/STP

# Nexrad r2r Tornado Vorticity Signature

FSL|radar:r2r:Tornado:local|/data/fxa/radar/r2r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r2r/TVS

# Nexrad r3r Reflectivity

FSL|radar:r3r:Reflectivity:local|/data/fxa/radar/r3r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r3r/Z

# Nexrad r3r One Hour Precip

FSL|radar:r3r:1HourRain:local|/data/fxa/radar/r3r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r3r/OHP

# Nexrad r3r Three Hour Precip

FSL|radar:r3r:3HourRain:local|/data/fxa/radar/r3r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r3r/THP

# Nexrad r3r Storm Total

FSL|radar:r3r:TotalRain:local|/data/fxa/radar/r3r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r3r/STP

# Nexrad r3r Tornado Vorticity Signature

FSL|radar:r3r:Tornado:local|/data/fxa/radar/r3r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r3r/TVS

# Nexrad r4r Reflectivity

FSL|radar:r4r:Reflectivity:local|/data/fxa/radar/r4r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r4r/Z

# Nexrad r4r One Hour Precip

FSL|radar:r4r:1HourRain:local|/data/fxa/radar/r4r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r4r/OHP

# Nexrad r4r Three Hour Precip

FSL|radar:r4r:3HourRain:local|/data/fxa/radar/r4r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r4r/THP

# Nexrad r4r Storm Total

FSL|radar:r4r:TotalRain:local|/data/fxa/radar/r4r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r4r/STP

# Nexrad r4r Tornado Vorticity Signature

FSL|radar:r4r:Tornado:local|/data/fxa/radar/r4r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r4r/TVS

# Nexrad r5r Reflectivity

FSL|radar:r5r:Reflectivity:local|/data/fxa/radar/r5r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r5r/Z

# Nexrad r5r One Hour Precip

FSL|radar:r5r:1HourRain:local|/data/fxa/radar/r5r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r5r/OHP

# Nexrad r5r Three Hour Precip

FSL|radar:r5r:3HourRain:local|/data/fxa/radar/r5r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r5r/THP

# Nexrad r5r Storm Total

FSL|radar:r5r:TotalRain:local|/data/fxa/radar/r5r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r5r/STP

# Nexrad r5r Tornado Vorticity Signature

FSL|radar:r5r:Tornado:local|/data/fxa/radar/r5r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r5r/TVS

# Nexrad r6r Reflectivity

FSL|radar:r6r:Reflectivity:local|/data/fxa/radar/r6r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r6r/Z

# Nexrad r6r One Hour Precip

FSL|radar:r6r:1HourRain:local|/data/fxa/radar/r6r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r6r/OHP

# Nexrad r6r Three Hour Precip

FSL|radar:r6r:3HourRain:local|/data/fxa/radar/r6r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r6r/THP

# Nexrad r6r Storm Total

FSL|radar:r6r:TotalRain:local|/data/fxa/radar/r6r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r6r/STP

# Nexrad r6r Tornado Vorticity Signature

FSL|radar:r6r:Tornado:local|/data/fxa/radar/r6r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r6r/TVS

# Nexrad r7r Reflectivity

FSL|radar:r7r:Reflectivity:local|/data/fxa/radar/r7r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r7r/Z

# Nexrad r7r One Hour Precip

FSL|radar:r7r:1HourRain:local|/data/fxa/radar/r7r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r7r/OHP

# Nexrad r7r Three Hour Precip

FSL|radar:r7r:3HourRain:local|/data/fxa/radar/r7r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r7r/THP

# Nexrad r7r Storm Total

FSL|radar:r7r:TotalRain:local|/data/fxa/radar/r7r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r7r/STP

# Nexrad r7r Tornado Vorticity Signature

FSL|radar:r7r:Tornado:local|/data/fxa/radar/r7r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r7r/TVS

# Nexrad r8r Reflectivity

FSL|radar:r8r:Reflectivity:local|/data/fxa/radar/r8r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r8r/Z

# Nexrad r8r One Hour Precip

FSL|radar:r8r:1HourRain:local|/data/fxa/radar/r8r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r8r/OHP

# Nexrad r8r Three Hour Precip

FSL|radar:r8r:3HourRain:local|/data/fxa/radar/r8r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r8r/THP

# Nexrad r8r Storm Total

FSL|radar:r8r:TotalRain:local|/data/fxa/radar/r8r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r8r/STP

# Nexrad r8r Tornado Vorticity Signature

FSL|radar:r8r:Tornado:local|/data/fxa/radar/r8r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r8r/TVS

# Nexrad r9r Reflectivity

FSL|radar:r9r:Reflectivity:local|/data/fxa/radar/r9r/Z/elev0_5/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r9r/Z

# Nexrad r9r One Hour Precip

FSL|radar:r9r:1HourRain:local|/data/fxa/radar/r9r/OHP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r9r/OHP

# Nexrad r9r Three Hour Precip

FSL|radar:r9r:3HourRain:local|/data/fxa/radar/r9r/THP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r9r/THP

# Nexrad r9r Storm Total

FSL|radar:r9r:TotalRain:local|/data/fxa/radar/r9r/STP/layer0/res2/level16|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r9r/STP

# Nexrad r9r Tornado Vorticity Signature

FSL|radar:r9r:Tornado:local|/data/fxa/radar/r9r/TVS|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/nexrad/r9r/TVS

#
# This part is used on ls1 by hmIngest to determine where to store text

# products. Do not edit this section; all message types are listed.

FSL|nwstext:warning:local|||||/data/ldad/public/nwswwasFSL|nwstext:watch:local|||||/data/ldad/public/nwswwas

FSL|nwstext:forecast:local|||||/data/ldad/public/nwswwasFSL|nwstext:outlook:local|||||/data/ldad/public/nwswwas

FSL|nwstext:report:local|||||/data/ldad/public/nwswwasFSL|nwstext:statement:local|||||/data/ldad/public/nwswwas

FSL|nwstext:qctext:local|||||/data/ldad/public/qcmessagesFSL|localtext:report:local|||||/data/ldad/public/nwswwas

Running Menu Configurator to update the menu items.

See MenuEditor.html

Making Data Manually to Test the Configuration Files:

Run the makeData scripts to test making the data.

"makeData" is a simple test program that can be run to manually create Serialized Java Object (SJO) files from raw data.  The raw data is usually in the form of netCDF files, but it can be other formats as well (such as radar, and IFP grids).  Once the data is created, it is viewable using the LDAD web dissemination applet/application.

There are two parts to the test program, makeData.java and MakeData.csh.

To run the program:

(1) Build the makeData.java into a class file (ie. "javac makeData.java" where javac.exe is the java compiler which comes with the Java Development Kit version 1.1.7B, JDK1.1.7B, or above.)

(2) MakeData.csh script:

2.a) Before running the MakeData script please do the following:

2.a.1)

Please set LDAD_HOME in the second line of the MakeData.csh script should be set to:

setenv LDAD_HOME /ldad

Please set SITEID to the contents of your "/data/ldad/emwww/htdocs/siteId.txt" file. For example, the Boulder Colorado weather forecast office's <siteId> is "BOU":

setenv SITEID BOU

Please verify that the website has been localized by verifying the existance of:

"/data/ldad/emwww/htdocs/localizations/<siteId>/imagedata/"

"/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/"

"/data/ldad/emwww/htdocs/localizations/<siteId>/wkspace/"

Where the <siteId> matches the value in the "/data/ldad/emwww/htdocs/siteId.txt" file. 

       2.b)  Next run the MakeData.csh script.

2.b.1) The MakeData.csh script will prompt for a data file name. (e.g. 20000304_1200)

2.b.2) Then the MakeData.csh script will prompt for the file type (e.g. obs:metar:national)

(HINT: The file type are associated with a particular data type is listed in the second column of the pollForData.conf file. 

2.b.3)  Next MakeData.csh will prompt you for the fully qualified pathname of the file you entered above.

For example, if the data is at "/data/fxa/point/metar/netcdf/20000304_1200", then the fully qualified pathname of the file is "/data/fxa/point/metar/netcdf".

2.c) The website data files that have been manually created will be put into the "/data/ldad/emwww/htdocs/data" directory. The LDAD web dissemination applet will search this directory for them.

#-----------------------------MakeData.csh---------------------------------------------------
#!/bin/csh -f
setenv JAVA_DIR /opt/java/bin

setenv LDAD_HOME /ldad

setenv SITEID BOU
#
echo "Set filename to process (eg. 20000304_1200)"
set fileName = $<
echo "Set file type (eg. obs:metar:national)"
set fileType = $<
echo "Set fully qualified directory that contains the filename entered above"
set dirName = $<
#
${JAVA_DIR}/java -nojit -mx65536000 -Drun.root.dir=${LDAD_HOME} \
  -Drun.config.dir=${LDAD_HOME}/runroot/data \
  -Drun.data.dir=${LDAD_HOME}/data \
  -Drun.localization.dir=${LDAD_HOME}/localizations/${SITEID} \
  -Drun.ldaddata.dir=${LDAD_HOME}/runroot/data \
   makeData ${fileName} ${fileType} ${dirName} ${LDAD_HOME}

-------------------------------makeData.java------------------------------------------------
import hmserve.ingest.IngestShell;
import hmlib.common.DataFault;
import hmlib.common.Log;
import hmlib.common.AppProperties;

class makeData
    {
    public static void main(String args[])
        {
        String fileName = new String(args[0]);
        String fileType = new String(args[1]);
        String dirPath  = new String(args[2]);
//
        _log = Log.employ((String)null, (String)null);
        IngestShell testShell = new IngestShell(_log);

        try {
            testShell.cacheData(fileName, fileType, dirPath);
            }
        catch (DataFault df)
            {
            System.out.println("DataFault....\n");
            }

        return;
        }

    private static Log _log;
    }
 

Installing *.cnf files on the runtime system.

Run the makeData scripts to test making the data.

Wait until all critical weather passes.

Stop LDAD on ds1.

Install cnf files.

Delete all files in "/data/ldad/emwww/htdocs/data/" (old data) to avoid format conflicts (ClassCastExceptions).

Relocalize LDAD.

Restart LDAD on ds1.

Adding Unsupported Dynamic Data Types to the website and client:

It is desirable to bypass the current mechanism for ingest and create a new mechanism which is strictly a data format converter. Since hmingestd/IngestSensor is notified by pollForData of the location of new data when new data arrives, we need to call our new code from the hmingestd. The hmingestd must inform our new code of the location of the new data. The new code must read the old data format into a new data structure, compress and serialize the new data structure to the website, and update the INDEX.dat and INDEXTS.dat files on the website.

(HINT: Investigate using the MakeData scripts defined earlier.)


The hmingestd daemon is run on the LS1 computer.
"hmingestd.java
" Source code

//F>=========================================================================
// hmingestd.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
import hmlib.utils.Argv;
import hmlib.common.TestAid;
import hmlib.common.Fault;
import hmlib.common.AppProperties;
import hmlib.utils.ConfigSet;
import hmserve.ingest.IngestSensor;

//C============================================================================
// hmingestd
// This class is an executable class that starts a particular ingest
// sensor (hmingestd). Invoke it with a '-h' option to get usage information.
//=============================================================================
public class hmingestd
{
//@>_static

// Debug level, if activated
private static final int DEBUG_LEVEL = 2;

// Log configurations for various modes.
private static final String NORMAL_LOGCONFIG = "daemon";
private static final String TEST_LOGCONFIG = "daemondiag";
private static final String DEBUG_LOGCONFIG = "daemondebug";

// Default location of configuration information.
private static final String DAEMON_NAME = "hmingestd";
private static final String CONFIG_SUBDIR
= System.getProperty("file.separator") + "data";
private static final String LOG_SUBDIR
= System.getProperty("file.separator") + "logs";
private static final String CONFIG_NAME = "hmingestd";
private static final String CONFIG_PKG = "ingest";


//>>static()>>>>>>>>>>>>>>>> Public Static Methods

//M========================================================================
// main()
// ENTRY POINT for this class.
// args: command-line arguments (see dieUsage())
//=========================================================================
public static void main(String [] args)
{
boolean dbmode;
boolean testmode;
String arg;
String configDir;
String logDir;
String configName = CONFIG_NAME;
String configPkg = CONFIG_PKG;
String logConfig;
int delimAt;
char fileSep = System.getProperty("file.separator", "/").charAt(0);

//-------------------------------------------------
// Process command-line.
//-------------------------------------------------
// Sift command-line options.
String [] specs = { "testmode|t|*", "dbmode|d|*", "logdir|L|=s",
"configdir|C|=s", "configname|N|=s", "configpkg|P|=s", "help|h|*" };
Argv argv = new Argv(specs);
try { argv.sift(args); }
catch (Fault e)
{ TestAid.abort(e.getMessage()); }
catch (Exception e)
{ TestAid.abortOnThrow(e); }

//-------------------------------------------------
// Save usage info and terminate, if requested.
//-------------------------------------------------
if (argv.booleanValue("help"))
dieUsage();


//-------------------------------------------------
// Set and validate mode options.
//-------------------------------------------------
testmode = argv.booleanValue("testmode");
dbmode = argv.booleanValue("dbmode");
if (testmode)
logConfig = TEST_LOGCONFIG;
else if (dbmode)
{
testmode = true;
logConfig = DEBUG_LOGCONFIG;
TestAid.setDebug(DEBUG_LEVEL);
}
else
logConfig = NORMAL_LOGCONFIG;

//-------------------------------------------------
// Interpret parameters
//-------------------------------------------------
if (argv.size() < 1)
TestAid.abort("Missing arguments. Use '-h' to view usage info.");
String rootDir = argv.shift();


//-------------------------------------------------
// Set and validate remaining options.
//-------------------------------------------------
configDir = rootDir + CONFIG_SUBDIR;
logDir = AppProperties.getProperty("run.log.dir");
if (argv.hasAValue("logdir"))
logDir = argv.stringValue("logdir");
if (argv.hasAValue("configdir"))
configDir = argv.stringValue("configdir");
if (argv.hasAValue("configname"))
configName = argv.stringValue("configname");
if (argv.hasAValue("configpkg"))
configPkg = argv.stringValue("configpkg");

//-------------------------------------------------
// Instantiate an ingest sensor daemon.
//-------------------------------------------------
IngestSensor deamon;
if (testmode)
{
TestAid.println(DAEMON_NAME + " configured from set "
+ configPkg + "." + configName + " in " + configDir);
}
IngestSensor.create(DAEMON_NAME, rootDir, configDir, configPkg,
configName, logDir, logConfig);
if (testmode)
{
TestAid.println("Starting " + DAEMON_NAME + " in test mode.");
IngestSensor.startup(DAEMON_NAME);
}
else
IngestSensor.startup(DAEMON_NAME);

System.exit(0);
}


//>>private()>>>>>>>>>>>>>>>> Private Methods


//M========================================================================
// hmingestd()
// override public constructor to prevent instantiation.
//=========================================================================
private hmingestd() { }

//M========================================================================
// dieUsage()
// override public constructor to prevent instantiation.
//=========================================================================
private static void dieUsage()
{
TestAid.println("USAGE:\n"
+ "hmingestd [-dth] [-C configDir] [-N configName]\n"
+ " [-P configPkg] [-L logDir] rootdir &\n\n"
+ "where:\n"
+ "rootdir = a root installation directory representing a portion of \n"
+ " the filesystem dedicated to a particular operable version\n"
+ " of software.\n\n"
+ "Activates an ingest sensor daemon, using a port number acquired\n"
+ "from the sensor's configuration file, located by default in set\n"
+ CONFIG_PKG + ".hmingestd at 'rootdir'" + CONFIG_SUBDIR + ".\n\n"
+ "Options modify this behavior as follows:\n"
+ " -d runs daemon in debug mode\n"
+ " -h shows this usage information\n"
+ " -t runs daemon in test mode\n"
+ " -C configdir specifies a base configuration directory\n"
+ " (defaults to 'rootdir'/config)\n"
+ " -N configname specifies a configuration set name\n"
+ " -P configpkg specifies a configuration set package\n"
+ " -L logdir specifies a directory to contain log files\n"
+ " (defaults to 'rootdir'/logs)\n\n"
+ "Message format: \"reqType dataType filePath\"\n"
+ "where:\n"
+ "reqType = a single-character request type ('R'=repository)\n"
+ "dataType = the type of data file to be processed\n"
+ "filePath = the path of the data file to be processed\n");
System.exit(0);
}
}

The hmingestd daemon reads the command line arguements and creates/starts the IngestSensor module. The IngestSensor module implements the background thread which listens for new data arriving from PollForData on the DS computer.
IngestSensor.java Source code
//F>=========================================================================
// IngestSensor.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
package hmserve.ingest;
import java.util.Hashtable;
import java.util.Enumeration;
import hmlib.utils.Task;
import hmlib.utils.TaskStateEnum;
import hmlib.utils.ConfigSet;
import hmlib.common.Log;
import hmlib.common.Error;
import hmlib.common.UsageError;
import hmlib.common.ParamError;
import hmlib.common.StateError;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.PrintWriter;
import hmlib.common.PropertyError;
import hmlib.common.NetworkError;
import hmlib.common.AppProperties;
import hmlib.common.TestAid;

//C============================================================================
// IngestSensor
// This class supports singleton sensor objects that manage
// a single ingest sensor thread, and ensure that it remains alive.
// Each instantiated sensor has a unique name through which it is accessed.
//=============================================================================
public class IngestSensor implements Runnable
{
//>>_static>>>>>>>>>>>>>>>> Non-Public Static Data Members
private static Hashtable _sensors; // IngestSensor Task singleton.
private static String SENSOR_LOG_CONFIG = "daemon";
private static int SENSOR_PRIORITY = 6;
private static int HANDLER_PRIORITY = 5;
private static String INGEST_SET = "ingest";
private static int SHUTDOWN_DELAY = 1000;
//>>static()>>>>>>>>>>>>>>>> Public Static Methods

//M========================================================================
// create()
// This static method creates a named sensor object. It throws an
// error if such a sensor already exists. Only a single sensor object
// with a given name is thus allowed to exist. IngestSensor names must
// consist entirely of letters, and must end with 'd' for 'daemon'
// (e.g., inetd, mountd).
// name: a name uniquely identifying a sensor
// rootdir: root directory for installed files.
// configDir: base directory for configuration files.
// configPkg: configuration package name
// configName: configuration set name
// logDir: base directory for log files
// logConfig: log configuration to use
//=========================================================================
public static synchronized void create(String name, String rootDir,
String configDir, String configPkg, String configName, String logDir)
{
create(name, rootDir, configDir, configPkg, configName, logDir, null);
return;
}
public static synchronized void create(String name, String rootDir,
String configDir, String configPkg, String configName, String logDir,
String logConfig)
{
char c;
IngestSensor sensor;

TestAid.db(2, "name=" + name);
TestAid.db(2, "rootDir=" + rootDir);
TestAid.db(2, "configDir=" + configDir);
TestAid.db(2, "configPkg=" + configPkg);
TestAid.db(2, "configName=" + configName);
TestAid.db(2, "logDir=" + logDir);
TestAid.db(2, "logConfig=" + logConfig);

// Ensure that _sensors is initialized.
if (_sensors == null)
_sensors = new Hashtable();

// Ensure that valid directory parameters have been provided.
if (rootDir == null || logDir == null)
{
throw new ParamError("IngestSensor.create",
ParamError.NullParam, "Null directory parameter");
}

// Ensure that valid configuration parameters have been provided.
if (configDir == null || configPkg == null || configName == null)
{
throw new ParamError("IngestSensor.create",
ParamError.NullParam, "Null configuration parameter");
}

// Ensure that a valid name has been provided.
if (name == null)
{
throw new ParamError("IngestSensor.create",
ParamError.NullParam, "Null sensor name");
}
for (int i=0; i<name.length(); i++)
{
c = name.charAt(i);
if (Character.isLetter(c) == false)
{
throw new ParamError("IngestSensor.create",
ParamError.InvalidName,
"sensor name=" + name);
}
}

// Save the directories as application properties.
AppProperties.setProperty("run.root.dir", rootDir);
AppProperties.setProperty("run.config.dir", configDir);
AppProperties.setProperty("run.log.dir", logDir);

// Check to see if the sensor already exists.
sensor = (IngestSensor)_sensors.get(name);
if (sensor != null)
{
throw new StateError("IngestSensor.create",
StateError.InvalidState,
"IngestSensor " + name + " already exists.");
}

// Instantiate the sensor and save it in the hash.
sensor = new IngestSensor(name, configDir,
configPkg, configName, logConfig);
_sensors.put((Object)name, (Object)sensor);
return;
}


//M========================================================================
// startup()
// This method was originally designed to run a sensor in test mode.
// It was originally intended that startup() would not call join(),
// but would simply return, allowing all but the sensor thread itself
// to terminate. Unfortunately, even though setDaemon() was used, the
// sensor thread would also terminate.
//
// This startup() method therefore calls join(), and shuts down the
// sensor's thread group when it stops.
// name: a name uniquely identifying a sensor
//=========================================================================
public static synchronized void startup(String name)
{
IngestSensor sensor;
// Acquire the specified sensor.
if (name == null)
{
throw new ParamError("IngestSensor.test", ParamError.NullParam,
"Null sensor name");
}
sensor = (IngestSensor)_sensors.get((Object)name);
if (sensor == null)
{
throw new StateError("IngestSensor.test", StateError.InvalidState,
"IngestSensor " + name + " does not exist.");
}

// Start the sensor through its internal task object.
// Wait for it to complete, and then destroy it's thread group.
sensor.useTask().startAsUser();
try { sensor.useTask().join(); }
catch (InterruptedException e)
{ }
finally
{
System.runFinalizersOnExit(true);
shutdown(name);
}

return;
}

//M========================================================================
// shutdown()
// This method disables communications immediately by stopping a sensor's
// listener threads. Other subsidiary threads continue to process
// current and queued requests for the number of minutes specified in
// delayInMinutes. All subsidiary threads and resources are stopped.
// name: a name uniquely identifying a sensor
//=========================================================================
public static synchronized void shutdown(String name)
{
IngestSensor sensor;

// Acquire the specified sensor.
if (name == null)
{
throw new ParamError("IngestSensor.shutdown",
ParamError.NullParam, "Null sensor name");
}
sensor = (IngestSensor)_sensors.get((Object)name);
if (sensor == null)
{
throw new StateError("IngestSensor.shutdown",
StateError.InvalidState,
"IngestSensor " + name + " does not exist.");
}

// TestAid.println("Shutting down sensor " + name);

// _sensor.setState(TaskStateEnum.RUNNING);

// Stop the sensor through its internal task object.
sensor.useTask().stop();

// Delay slightly, to allow current handlers to terminate.
try { Thread.currentThread().sleep(SHUTDOWN_DELAY); }
catch (Exception e)
{
// An interrupt stops the sleep, but not the shutdown.
}

// Destroy all threads in its group.
sensor.useTask().useGroup().destroy();

// Remove the sensor from the hash.
_sensors.remove((Object)name);

return;
}


//>>public()>>>>>>>>>>>>>>>> Public Methods

//M========================================================================
// run()
// This method implements the Runnable interface, being the method
// called to run an IngestSensor in a separate thread.
//=========================================================================
public void run()
{
IngestHandler runnable;
Task handler;
Socket socket;
TaskStateEnum state;

// Prepare to accept requests.
String address = _srvSocket.getInetAddress().getHostAddress();
int port = _srvSocket.getLocalPort();
// TestAid.println(_name + " listening on port " + port + " at "
// + address);
_log.diag("IngestSensor", " IngestSensor.run(): "
+ _name + " listening on port " + port + " at "
+ address);

_sensor.setState(TaskStateEnum.RUNNING);

// Generate a handler for each request.
// NOTE: There is no limitation on the number of handlers.
try {
while (true)
{
// Accept a connection.
socket = _srvSocket.accept();

// Pass the connection off to a handler.
state = new TaskStateEnum(TaskStateEnum.INIT);
handler = new Task(_group, _nextName, state);
handler.setPriority(_handlerPriority);
handler.placeLog(_log);
handler.placeGroupConfig(_set);

// Pass the connection off to a handler.
runnable = new IngestHandler(handler, socket);
handler.start(runnable);

// Compute a new handler name.
_seq = (_seq+1) % 1000;
_nextName = _name + "Handler" + _seq;
}
}
catch (Exception e)
{
// Log the throw, and then terminate.
_sensor.setState(TaskStateEnum.THROW);
_sensor.placeStatus(e);
_log.error("IngestSensor", "Sensor exception was caught... "
+ e.toString(), e);
}
}

//M========================================================================
// useTask()
// Allow the caller to access the internal task object.
//=========================================================================
public Task useTask()
{ return _sensor; }


//>>_data>>>>>>>>>>>>>>>> Private (instantiated) Data Members

private String _name;
private IngestShell _shell;
private String _nextName;
private int _seq;
private ThreadGroup _group;
private int _handlerPriority;
private Task _sensor;
private ConfigSet _set;
private Log _log;
private int _port;
private ServerSocket _srvSocket;


//>>private()>>>>>>>>>>>>>>>> Private Methods

//G========================================================================
// IngestSensor()
// IngestSensor objects are instantiated via the static create() method.
// This is the private constructor called by create(). This method fully
// initializes a IngestSensor object, so an init() method is not required.
//=========================================================================
private IngestSensor(String name, String configDir, String configPkg,
String configName, String logConfig)
{
TaskStateEnum state;
String ingestShellSet;
int priority;
Runnable runnable;
String logName;
String serverClass;

if (name == null)
{
throw new StateError("IngestSensor", StateError.InvalidState,
"Null sensor name");
}
if (configDir == null)
{
throw new StateError("IngestSensor", StateError.InvalidState,
"Null sensor configuration directory");
}
if (configPkg == null)
{
throw new StateError("IngestSensor", StateError.InvalidState,
"Null sensor configuration package");
}
if (configName == null)
{
throw new StateError("IngestSensor", StateError.InvalidState,
"Null sensor configuration name");
}
_name = name;
_seq = 1;
_nextName = _name + "Handler" + _seq;
_set = ConfigSet.createSet(configName, configPkg, configDir);

//-------------------------------------------------------------
// Configure an internal sensor task.
//-------------------------------------------------------------
_group = new ThreadGroup(name);
state = new TaskStateEnum(TaskStateEnum.INIT);
_sensor = new Task(_group, name, state);
logName = _set.getString("sensorLogName", _sensor.getName());
priority = _set.getInt("sensorPriority", SENSOR_PRIORITY);
ingestShellSet = _set.getString("ingestShellSet", INGEST_SET);

// Let a logConfig parameter override the configuration.
if (logConfig == null)
logConfig = _set.getString("sensorLogConfig", SENSOR_LOG_CONFIG);

// Create a log.
_log = Log.employ(logName, logConfig);
_log.diag("IngestSensor", " IngestSensor.IngestSensor(): "
+ "Configured from set " + configPkg
+ "." + configName + " in " + configDir);

// Initialize task info.
_sensor.setPriority(priority);
_sensor.placeLog(_log);
_sensor.placeGroupConfig(_set);
_sensor.prime((Runnable)this);

//-------------------------------------------------------------
// Get the configured port number.
//-------------------------------------------------------------
if (_set.isDefined("sensorPort") == false)
{
throw new PropertyError("IngestSensor",
PropertyError.Undefined, "Undefined sensor port");
}
_port = _set.getInt("sensorPort");

//-------------------------------------------------------------
// Get handler configuration info.
//-------------------------------------------------------------
_handlerPriority = _set.getInt("handlerPriority", HANDLER_PRIORITY);

//-------------------------------------------------------------
// Configure an ingest shell task
//-------------------------------------------------------------
state = new TaskStateEnum(TaskStateEnum.INIT);
Task ingestTask = new Task(_group, "IngestShell", state);
ingestTask.setPriority(priority);
ingestTask.placeLog(_log);
ingestTask.placeGroupConfig(_set);
ConfigSet taskSet = ConfigSet.readSet(ingestShellSet, configPkg,
configDir);
ingestTask.placeTaskConfig(taskSet);
_shell = new IngestShell(ingestTask);

//-------------------------------------------------------------
// Listen at the port.
//-------------------------------------------------------------
try { _srvSocket = new ServerSocket(_port);}
catch (Exception e)
{
throw new NetworkError("IngestSensor",
NetworkError.NoListener);
}
}


//>>protected()>>>>>>>>>>>>>>>> Protected Methods


//M========================================================================
// finalize()
// This method releases resources on termination
//=========================================================================
protected void finalize()
{
if (_srvSocket != null)
{
// TestAid.println("Closing server socket.");
_log.diag("IngestSensor", " IngestSensor.finalize(): "
+ " Closing server socket.");

try { _srvSocket.close(); }
catch (Exception e)
{
throw new NetworkError("Listener.finalize",
NetworkError.ListenerHung, _name);
}
}
}
}

When the IngestSensor module receives a new task from PollForData it creates a new IngestHandler module which runs in its own thread and handles the new task.

IngestHandler.java Source code
//F>=========================================================================
// IngestHandler.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
package hmserve.ingest;

import hmlib.utils.Task;
import hmlib.utils.TaskStateEnum;
import hmlib.utils.ConfigSet;
import hmlib.common.Log;
import java.net.Socket;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.util.StringTokenizer;
import java.util.Hashtable;
import java.io.ByteArrayOutputStream;
import hmlib.common.DataFault;
import hmlib.common.FileFault;
import hmlib.common.ParamError;
import hmlib.common.NetworkError;
import hmlib.common.TestAid;


//C============================================================================
// IngestHandler
// Objects of this class implement handler threads that are instantiated by
// IngestSensor objects.
//=============================================================================
public class IngestHandler implements Runnable
{
//>>_data>>>>>>>>>>>>>>>> Private (instantiated) Data Members

private ConfigSet _set;
private Task _task;
private String _name;
private Log _log;
private Socket _socket;
private char _reqType;
private String _message;
private String _dataType;
private String _fileName;
private String _incomingDir;

private final char BREAK_LOG = 'L';
private final char REPOSITORY = 'R';

//>>public()>>>>>>>>>>>>>>>> Public Methods


//M========================================================================
// IngestHandler()
// This constructor uses task information to initialize itself.
// task: the handler's task object
// socket: an accepted socket
//=========================================================================
public IngestHandler(Task task, Socket socket)
{
_task = task;
_socket = socket;
_set = _task.useGroupConfig();
_log = _task.useLog();
_name = _task.getName();
_incomingDir = _set.getString("incomingDir", null);
}

//M========================================================================
// run()
// This method implements the Runnable interface, being the method
// called to run an IngestHandler in a separate thread.
//=========================================================================
public void run()
{
BufferedInputStream bufferedIn;
DataInputStream dataIn;

try {
_task.setState(TaskStateEnum.RUNNING);
_log.start("IngestSensor", _name);

// Buffer the input stream to improve performance.
try {
bufferedIn = new BufferedInputStream(_socket.getInputStream());
dataIn = new DataInputStream(bufferedIn);
}
catch (Exception e)
{
throw new NetworkError("IngestHandler.run",
NetworkError.NoReader, _task.getName(), e);
}

// Read the message.
readMessage(dataIn);

_log.diag("IngestHandler", _name
+ " IngestHandler.run(): "
+ " processing request ("
+ _reqType + " " + _dataType + " " + _fileName + ")");

// Close the connection.
try {
dataIn.close();
_socket.close();
_socket = null;
}
catch (Exception e)
{
throw new NetworkError("IngestHandler.run",
NetworkError.SocketHung, _task.getName(), e);
}

// Process the incoming data.
processData();
_task.setState(TaskStateEnum.TERM);
}
catch (Exception e)
{
// Log the throw and terminate.
_task.setState(TaskStateEnum.THROW);
_task.placeStatus(e);
// _log.error("IngestHandler", "Aborted on request ("
// + _reqType + " " + _dataType + " " + _fileName + "): " + e, e);
_log.error("IngestHandler",
" IngestHandler.run(): "
+ " Aborted on request ("
+ _reqType + " " + _dataType + " " + _fileName + "): " + e, e);
}
_log.stop("IngestSensor", _name);
return;
}


//>>private()>>>>>>>>>>>>>>>> Private Methods


//M========================================================================
// processData()
// This method invokes an IngestShell to cache incoming data.
//=========================================================================
private void processData() throws DataFault, FileFault
{
if (_reqType == REPOSITORY)
{
// _log.diag("IngestHandler", "Accepting request ("
// + _reqType + " " + _dataType + " " + _fileName + ")");
_log.diag("IngestHandler", _name
+ " IngestHandler.processData(): "
+ " Accepting request ("
+ _reqType + " " + _dataType + " " + _fileName + ")");

}
else if (_reqType == BREAK_LOG)
{
// _log.diag("IngestHandler", "Break Log ("
// + _reqType + " " + _dataType + " " + _fileName + ")");
_log.diag("IngestHandler", _name
+ " IngestHandler.processData(): "
+ " Break Log ("
+ _reqType + " " + _dataType + " " + _fileName + ")");

_log.breakLog();
}
else
{
// _log.notice("IngestHandler", "Rejected request ("
// + _reqType + " " + _dataType + " " + _fileName + ")");
_log.notice("IngestHandler", _name
+ " IngestHandler.processData(): "
+ " Rejected request ("
+ _reqType + " " + _dataType + " " + _fileName + ")");

return;
}

// Assumes that _fileName is an absolute file path.
File file = new File(_fileName);
if (file.exists() == false)
{
throw new FileFault("IngestHandler.processMessage()",
FileFault.NoFile, file.getPath());
}
if (file.canRead() == false)
{
throw new FileFault("IngestHandler.processMessage()",
FileFault.AccessDenied, file.getPath());
}
String fileName = file.getName();
String dirPath = file.getParent();

// Cache the data.
IngestShell testShell = new IngestShell(_log);

testShell.cacheData(fileName, _dataType, dirPath);

// _log.diag("IngestHandler", _name + " Completed request ("
// + _reqType + " " + _dataType + " " + _fileName + ")");

_log.diag("IngestHandler", _name
+ " IngestHandler.processData(): "
+ " Completed request ("
+ _reqType + " " + _dataType + " " + _fileName + ")");

return;
}

//M========================================================================
// readMessage()
// This method interprets a request, saving request information
// into member data, which can then be used by processData().
// dis:
//=========================================================================
private void readMessage(DataInputStream dataIn)
{
int count;
byte buffer[];

// Get the message contents.
// Assume that the message is small, fitting in a single packet.
try {
// Get the opType.
_reqType = (char)dataIn.readByte();

// Get the remaining bytes as a string.
count = dataIn.available();
buffer = new byte[count];
dataIn.readFully(buffer, 0, count);
}
catch (Exception e)
{
throw new NetworkError("IngestHandler.run",
NetworkError.ReadFailed, _task.getName(), e);
}
String msg = new String(buffer);

if (_reqType == BREAK_LOG)
return;

// Parse the message to get the type and filename.
// These fields can be separated by any amount of whitespace.
StringTokenizer st = new StringTokenizer(msg, " \t\r\n\0");
if (st.countTokens() < 2)
{
throw new ParamError("IngestHandler.readMessage",
ParamError.InvalidParam, "invalid message=\"" + msg + "\"");
}
_dataType = st.nextToken();
_fileName = st.nextToken();
return;
}
}

The IngestHandler module gets the path/filename of the input data and the type of the data and calls an IngestShell module.

IngestShell.java Source code

//F>=========================================================================
// IngestShell.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
package hmserve.ingest;
import hmserve.ingest.IngestCmdEnum;
import hmlib.common.Enumeratable;
import hmlib.utils.TaskStateEnum;
import hmlib.utils.ReqStateEnum;
import hmlib.utils.TaskReq;
import hmlib.utils.TaskReqError;
import hmlib.utils.Task;
import hmlib.utils.QueueCluster;
import hmlib.utils.ConfigSet;
import hmlib.common.TestAid;
import hmlib.access.HmBundle;
import hmlib.common.DumpWriter;
import hmlib.common.Log;
import hmlib.common.Error;
import hmlib.common.ParamError;
import hmlib.common.PropertyError;
import hmlib.common.ConfigError;
import hmlib.common.StateError;
import hmlib.common.DataFault;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;

//C============================================================================
// IngestShell
// This class is responsible for acquiring data for a client via an
// HmSteward class. IngestShells receive a data request, start up a
// FactorMill thread to retrieve the data in an HmBundle, stop the thread,
// and, finally, return the HmBundle to the client. All this functionality
// is accomplished via the IngestShell.readData() method.
//
//=============================================================================
public class IngestShell
{
//@>_static

private final static int CONTROL_QUEUE = 0;
private final static int MILL_PRIORITY = 4;

//@>public()

//M========================================================================
// Constructor
// Default constructor.
// The _stdout member is used for test purposes.
//=========================================================================
public IngestShell()
{ this((Task)null); }
public IngestShell(Log log)
{
this((Task)null);
_log = log;
}
public IngestShell(Task task)
{
_shell = task;
_stdout = TestAid.getStdout();
_srcCluster = new QueueCluster();
_destCluster = new QueueCluster();

if (_shell == null)
{
//-------------------------------------------------------------
// This instantiation is not being made by a daemon, but is a
// one-time request. Initialize accordingly.
//
// No log is available. Throws are caught by the caller.
//-------------------------------------------------------------
// Get the ingest ConfigSet.
_set = ConfigSet.readSet("ingest", "ingest");

// Create a thread group...
_group = new ThreadGroup("IngestShell");
}
else
{
//-------------------------------------------------------------
// This instantiation is being made by a daemon, so grab
// initialization information from the passed-in task object.
//
// NOTE: The log is available, but not currently used herein.
// Instead, throws are caught by the caller and logged there.
//-------------------------------------------------------------
_group = _shell.useGroup();
_set = _shell.useTaskConfig();
if (_group == null || _set == null)
{
throw new StateError("IngestShell", StateError.InvalidState,
"Shell task was not initialized.");
}
}
_millPriority = _set.getInt("millPriority", MILL_PRIORITY);
}

//G========================================================================
// readData()
// This static method does all the work of this class. This class
// can be called directly, as it is a public static member function
// of the IngestShell class.
//
// fileName: Fully qualified file name to be retrieved.
// fileType: String file type describing the data type (e.g. MAPdata)
// dirPath: Directory path for the fileName
// bundle: HmBundle in which the retrieved data is placed.
//=========================================================================
public HmBundle readData(String fileName, String fileType, HmBundle bundle)
throws DataFault
{
try {
makeRequest(IngestCmdEnum.READ, fileName, fileType,
null, bundle);
}
catch (ParamError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (PropertyError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (ConfigError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (StateError e)
{ throw e.rethrow("IngestShell.readData"); }
return bundle;
}
public HmBundle readData(String fileName, String fileType,
String dirPath, HmBundle bundle) throws DataFault
{
try {
// TestAid.db(2, "IngestShell.readData: " + "\n fileName = " +
// fileName + "\n fileType = " + fileType + "\n dirPath = " +
// dirPath + "\n bundle = " + bundle);

_log.diag("IngestShell", " IngestShell.readData(): "
+ "\n fileName = " + fileName + "\n fileType = "
+ fileType + "\n dirPath = " + dirPath + "\n bundle = "
+ bundle);

makeRequest(IngestCmdEnum.READ, fileName, fileType,
dirPath, bundle);
}
catch (ParamError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (PropertyError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (ConfigError e)
{ throw e.rethrow("IngestShell.readData"); }
catch (StateError e)
{ throw e.rethrow("IngestShell.readData"); }
return bundle;
}

//M========================================================================
// cacheData()
// This static method does all the work of this class. This class
// can be called directly, as it is a public static member function
// of the IngestShell class.
//
// fileName: Fully qualified file name to be retrieved.
// fileType: String file type describing the data type (e.g. MAPdata)
// dirPath: Directory path for the fileName
// bundle: HmBundle in which the retrieved data is placed.
//=========================================================================
public void cacheData(String fileName, String fileType, String dirPath)
throws DataFault
{
try {
makeRequest(IngestCmdEnum.CACHE, fileName, fileType, dirPath,
null);
}
catch (ParamError e)
{ throw e.rethrow("IngestShell.cacheData"); }
catch (PropertyError e)
{ throw e.rethrow("IngestShell.cacheData"); }
catch (ConfigError e)
{ throw e.rethrow("IngestShell.cacheData"); }
catch (StateError e)
{ throw e.rethrow("IngestShell.cacheData"); }
return;
}

//@>private()

//M========================================================================
// makeRequest()
// This static method does all the work of this class. This class
// can be called directly, as it is a public static member function
// of the IngestShell class.
//
// fileName: Fully qualified file name to be retrieved.
// fileType: String file type describing the data type (e.g. MAPdata)
// dirPath: Directory path for the fileName
// bundle: HmBundle in which the retrieved data is placed.
//=========================================================================
public void makeRequest(int command, String fileName, String fileType,
String dirPath, HmBundle bundle) throws DataFault
{
// Save parameters.
_cmd = new IngestCmdEnum(command);
_fileType = fileType;
_fileName = fileName;
_dirPath = dirPath;
_bundle = bundle;

// Validate parameters
if (fileName == null)
{
throw new ParamError("IngestShell.makeRequest",
ParamError.NullParam, "fileName parameter");
}
if (fileType == null)
{
throw new ParamError("IngestShell.makeRequest",
ParamError.NullParam, "fileType parameter");
}

String configName = null;

//-----------------------------------------------------------
// If this is radar data then we need to remove the radar
// station name from the fileType value.
//-----------------------------------------------------------
if (_fileType.indexOf("radar") >= 0)
{
String token = ":";
StringTokenizer st = new StringTokenizer(_fileType, token);
String type = st.nextToken();
String name = st.nextToken();
String variable = st.nextToken();
String scale = st.nextToken();
_fileType = new String(type + token + variable + token + scale);
}

//-----------------------------------------------------------
// If this is Interactive Forecast Preparation (IFP) system data
// then we need to remove the specific model type (e.g. RUC, Eta,etc)
// from the fileType value.
//-----------------------------------------------------------
if ((_fileType.indexOf("ifp") >= 0)||(_fileType.indexOf("IFP")>= 0))
{
String token = ":";
StringTokenizer st = new StringTokenizer(_fileType, token);
String type = st.nextToken();
String source = st.nextToken();
String model = st.nextToken();
String scale = st.nextToken();
_fileType = new String(type + token + source + token + scale);
}

// Create a task request...
TaskReq req = createTaskRequest();

//-----------------------------------------------------------
// Determine which factor mill to use by examining the
// millName property.
// Filetype (and factor names) have colons. Property names are
// derived from them by replacing colons with dashes.
// The name of the millName property is a modified filetype
// with an appended "Mill".
//-----------------------------------------------------------
String propName = _fileType.replace(':','-') + "Mill";
String millName;
try { millName = _set.getString(propName); }
catch (PropertyError e)
{
throw new TaskReqError("IngestShell.makeRequest",
TaskReqError.NotAssignable, "Mill name " + propName
+ " is not configured.");
}

//-----------------------------------------------------------
// Both the classname and the configuration name for a
// factor mill are derived from the millName.
// The millName property value is either a simple classname,
// in which case it is used for both millClass and millConfig,
// or it is of the form: millClass@millConfig.
// Parse the factorMillProp string accordingly.
//-----------------------------------------------------------
String millClass;
String millConfig;
int delimAt = millName.indexOf('@');
int length = millName.length();
if (delimAt == -1)
{
millClass = millName;
millConfig = millName;
}
else
{
millClass = millName.substring(0,delimAt);
millConfig = millName.substring(delimAt+1,length);
}

// Create an appropriate factor mill.
FactorMill mill = (FactorMill) createMill(millClass);

// Create a task for the mill.
Task task = createTask(millName);

// Initialize the mill.
mill.init(task, millConfig, _log);
int millQueue = task.getSrcQueue();

// Start the factor mill task...
// TestAid.db(1, "\nIngestShell: MILL THREAD STARTING...\n");
_log.diag("IngestShell", " IngestShell.makeRequest(): "
+ "MILL THREAD STARTING...");

task.start((Runnable)mill);

// Put the task request onto the mill's input queue...
_destCluster.enqueue(millQueue, (Object)req);

// Wait for a response.
TaskReq ingestReq = (TaskReq) (_srcCluster.dequeue(CONTROL_QUEUE));
switch (ingestReq.getState())
{
case ReqStateEnum.DONE:
// TestAid.db(1, "IngestShell: Mill has processed a request.\n");
_log.diag("IngestShell", " IngestShell.makeRequest(): "
+ "Mill has processed a request.");
break;
case ReqStateEnum.FAIL:
task.stop();
Exception e = task.useStatus();
if (e == null)
{
throw new TaskReqError("IngestShell.makeRequest",
TaskReqError.UnknownFailure);
}
if (e instanceof DataFault)
throw (DataFault)e;
if (e instanceof Error)
throw (Error)e;
throw (RuntimeException)e;
default:
task.stop();
throw new TaskReqError("IngestShell.makeRequest",
TaskReqError.UnknownState, "request status="
+ new ReqStateEnum(ingestReq.getState()));
}

// TestAid.db(1, "\nIngestShell: MILL THREAD STOPPING NORMALLY...");
_log.diag("IngestShell", " IngestShell.makeRequest(): "
+ "MILL THREAD STOPPING NORMALLY...");

task.stop();
return;
}

//M========================================================================
// createTaskRequest()
// This method creates a TaskReq object.
//
// returns: An instantiated TaskReq object.
//=========================================================================
private TaskReq createTaskRequest()
{
ReqStateEnum status = new ReqStateEnum(ReqStateEnum.INACTIVE);
String [] quals;
TaskReq req;
if (_dirPath != null)
{
quals = new String [2];

// The first qualifier is a selector that is a file type
// translated into a form that can be used as a property name.
quals[0] = _fileType.replace(':','-');

// The second qualifier is the path of the directory where
// the target file is located.
quals[1] = _dirPath;
}
else
{
quals = new String [1];

// The only qualifier is a selector that is a file type
// translated into a form that can be used as a property name.
quals[0] = _fileType.replace(':','-');
}

req = new TaskReq(_cmd, quals, _fileName, null, status);

req.placeProduct(_bundle);

return req;
}

//M========================================================================
// createTask()
// This method creates a Task object.
//
// returns: An instantiated Task object.
//=========================================================================
private Task createTask(String name)
{
TaskStateEnum state = new TaskStateEnum(TaskStateEnum.INIT);
Task task = new Task(_group, name, state);
task.setPriority(_millPriority);
task.setState(TaskStateEnum.IDLE);
int queue = _srcCluster.allocate(name);
task.setSrcQueue(queue);
task.setDestQueue(CONTROL_QUEUE);
task.placeSrcCluster(_destCluster);
task.placeDestCluster(_srcCluster);
task.placeGroupConfig(_set);
return task;
}

//M========================================================================
// createMill()
// This method returns an instantiated factor mill of the specified
// class, which must be a subclass of FactorMill. The factor mill
// classname was derived from the mill name property corresponding
// to the current filetype.
//
// millClass: classname of desired factor mill
// returns: instantiated factor mill
//=========================================================================
private FactorMill createMill(String millClass)
{
FactorMill mill = null;
String millPackage = null;
Class theClass;

// Get a Class object corresponding to the specified type.
millPackage = _set.getString("millPackage") + "." + millClass;

try { theClass = Class.forName(millPackage); }
catch (Exception e)
{
throw new PropertyError("IngestShell.createMill",
PropertyError.InvalidName, "class name " + millPackage, e);
}

// Instantiate the mill.
// Perform the cast to FactorMill here, so we can catch a failure.
try { mill = (FactorMill)theClass.newInstance(); }
catch (Exception e)
{
throw new PropertyError("IngestShell.createMill",
PropertyError.InvalidName, "class name millPackage", e);
}
return mill;
}

//@>_data
private Task _shell;
private int _millPriority;
private PrintWriter _stdout;
private String _fileType;
private String _fileName;
private String _dirPath;
private HmBundle _bundle;
private ConfigSet _set;
private IngestCmdEnum _cmd;
private ThreadGroup _group;

private QueueCluster _srcCluster;
private QueueCluster _destCluster;
private Log _log;
}

The IngestShell module calls one of four "Mill" modules based on the type of the data. The IngestShell module then reads in the data to be format converted and stored on the website and calls the appropriate store function in IFPFileWriter using the parameters to uniquely identify the store function used. For example, the StreamMill is:

StreamMill.java Source code
//F>=========================================================================
// StreamMill.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
package hmserve.ingest;
import hmlib.utils.ConfigSet;
import hmlib.utils.Task;
import hmlib.common.TestAid;
import java.io.PrintWriter;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.StringTokenizer;
import hmlib.common.ConfigError;
import hmlib.common.DataFault;
import hmlib.common.ParamError;
import hmlib.common.StateError;
import hmlib.common.Log;
import hmlib.utils.TaskReqError;
import hmlib.access.HmSteward;
import hmlib.access.HmFactor;
import hmlib.access.FactorDef;
import hmlib.access.HmPointAccessor;
import ifp.init.IFPWriter;
import ifp.init.IFPFileWriter;
import ifp.data.TimeRange;
import ifp.data.Grid;
import hmserve.ingest.RadarParameters;
import hmserve.ingest.IfpAsciiGrids;

import ldadapp.radar.*;
import ldadapp.data.PolarGrid;

//C============================================================================
// StreamMill
// This class is a factor mill that can be used to read data files that
// are placed into factors as streams, without interpretation of their
// content.
//=============================================================================
public final class StreamMill extends FactorMill
{
//@>public()

//M========================================================================
// init()
// Override parent to set specialized members. Setting _inFormat
// appropriately allows use of parent's openTarget() and closeTarget().
//=========================================================================
public void init(Task task, String configName, Log log) throws ConfigError
{
super.init(task, configName, log);
_log = log;
_inFormat = FactorMill.BYTESTREAM;
}

//@>protected()

//M========================================================================
// processTarget()
// This method reads from the target file input stream created in
// openTarget(), placing all of the data into a ByteArrayOutputStream
// that is saved into the current factor.
// returns: true if successful, or false otherwise
// prop: a relevant mill factor property
// file: File associated with target (from openTarget())
// factor: Factor to save data into
//=========================================================================
protected void processTarget(MillFactorProp prop, File file,
HmFactor factor) throws DataFault
{
//------------------------------------------------------------------
// Processing is the same for all types of factors.
// Simply transfer the entire contents of the file into the factor.
//------------------------------------------------------------------

// Read file into a byte array.
int data;
int offset;
int numRead;
int remaining;
HmPointAccessor accessor;

// TestAid.db(1, _configName + ": Reading a file.");
_log.event("StreamMill", _configName
+ " StreamMill.processTarget(): "
+ "Reading a file.");
// This implementation is limited to a 16 megabyte file size.
if (file.length() > (long)Integer.MAX_VALUE)
{
throw new DataFault("StreamMill.processTarget",
DataFault.FileSize, "mill config=" + _configName);
}

if (file == null)
{
throw new ParamError("TextFactorMill.processTarget",
ParamError.NullParam, "Null file");
}

// This mill does not support cacheing of data.
/*
if (factor == null)
{
throw new TaskReqError("StreamMill.run",
TaskReqError.RequestDenied, "StreamMill does not cache data.");
}
*/

// NEW >>>>>>>>>>>>
if (file == null)
{
throw new ParamError("StreamFactorMill.processTarget",
ParamError.NullParam, "Null file");
}
_fileName = file.getName();
// TestAid.db(1, _configName + ": Reading file " + _fileName);
_log.event("StreamMill", _configName
+ " StreamMill.processTarget(): "
+ "Reading file " + _fileName);

// Read file-type-specific information form a configuration file.
// Place it in the super-class _taskConfig.
// Place it in the task object so that the parent thread can see it.
if (_factorMill == null)
{
try { _taskConfig = ConfigSet.readSet(_configName,_configPkg); }
catch (ParamError e)
{ throw e.rethrow("processTarget"); }
catch (ConfigError e)
{ throw e.rethrow("processTarget"); }
_task.placeTaskConfig(_taskConfig);
}

// NEW <<<<<<<<<<<<

// TestAid.db(1, _configName + ": Acquiring a point accessor.");
_log.event("StreamMill", _configName
+ " StreamMill.processTarget(): "
+ " Acquiring a point accessor.");

// Get a point accessor.
// accessor = factor.createPointAccessor();

String validFactorName = prop.factorName.replace(':','-');

// Get the factor definition ConfigSet.
try { _set = ConfigSet.readSet(validFactorName, "factor"); }
catch (ConfigError e)
{ throw new ConfigError("ObsFactorMill.processTarget",
ConfigError.SetNotFound); }

try { factorDef = (FactorDef)_set.use(validFactorName); }
catch (StateError e)
{ throw new StateError ("StreamFactorMill.processTarget",
StateError.AssertFailed, "couldn't retrieve a hashtable"); }

if (validFactorName.indexOf("radar") >= 0)
{
retrieveFactorData(file.getPath());
cache();
}
else if(validFactorName.indexOf("ifp") >= 0)
{
IfpAsciiGrids ifp = new IfpAsciiGrids(file, validFactorName, _log);
ifp.cache();
}

// printFactorDefs(factorDef);

// TestAid.db(1, _configName + ": Processing is complete.");
_log.event("StreamMill", _configName
+ " StreamMill.processTarget(): "
+ " Processing is complete.");

return;
}

//M========================================================================
// retrieveFactorData()
//
//=========================================================================
public void retrieveFactorData(String fileName)
{
if(_inStream != null)
{
try {
RadarReader rr = new RadarReader(_inStream);
_rdr = rr.readRadar();
}
catch(IOException ioe)
{
_log.event("StreamMill",
"CPRadar.constructBean ERROR: IOException "
+ " file = " + fileName
+ ioe.toString());
}

}
return;
}

//M========================================================================
// retrieveFactorData()
//
//=========================================================================
public byte [] retrieveFactorData(File file) throws DataFault
{
int data;
int offset;
int numRead;
int remaining;

byte buffer[] = null;

_xdim = (int)file.length();
buffer = new byte [_xdim];
remaining = buffer.length;
offset = 0;
// TestAid.db(1, _configName + ": total to read: " + remaining);
_log.event("StreamMill", _configName
+ " StreamMill.retrieveFactorData(): "
+ "total to read: " + remaining);

try {
while (remaining > 0)
{
// TestAid.db(2, _configName + ": offset=" + offset
// + ", remaining=" + remaining);
_log.event("StreamMill", _configName
+ " StreamMill.retrieveFactorData(): "
+ "offset=" + offset + ", remaining=" + remaining);

numRead = _inStream.read(buffer, offset, remaining);
if (numRead < 0)
{
throw new DataFault("StreamMill.processTarget",
DataFault.IncompleteFile, "mill config=" + _configName);
}
// TestAid.db(2, _configName + ": received " + numRead
// + " bytes");
_log.event("StreamMill", _configName
+ " StreamMill.retrieveFactorData(): "
+ "received " + numRead + " bytes");

offset += numRead;
remaining = buffer.length - offset;
}
}
catch (Exception e)
{
throw new DataFault("StreamMill.processTarget",
DataFault.ReadFailed, "mill config=" + _configName, e);
}
// TestAid.db(1, _configName + ": all bytes read");
_log.event("StreamMill", _configName
+ " StreamMill.retrieveFactorData(): "
+ "all bytes read");
// TestAid.db(1, _configName + ": Saving data into factor.");
_log.event("StreamMill", _configName
+ " StreamMill.retrieveFactorData(): "
+ "Saving data into factor.");

return buffer;
}

//M========================================================================
// cache()
//
//=========================================================================
public void cache()
{
Date [] startTimes = null;
Date [] endTimes = null;

Date fileInitialTime = getInitialTime(_fileName);

startTimes = new Date[1];
endTimes = new Date[1];

TimeRange tr = getTimeValid(_rdr.getProdBlk());
startTimes[0] = tr.startTime();
endTimes[0] = tr.endTime();

String incomingUnits = null;
String outgoingUnits = null;

try
{
IFPFileWriter outStream = new IFPFileWriter();

RadarParameters rp = new RadarParameters(_log);

float lat = _rdr.getProdBlk().getRdrLon();
float lon = _rdr.getProdBlk().getRdrLat();
float stationElev = _rdr.getProdBlk().getRdrHt();
float beamElev = rp.getBeamElev() * FT_TO_M; // feet -> meter
float radarRes = rp.getRadarRes() * KM_TO_M; // km -> meter
String name = rp.getRadarStationName();

outgoingUnits = "dbZ";

PolarGrid pGrid = getPolarGrid();

String token = ".";
StringTokenizer st = new StringTokenizer(_fileName, token);
String validFileName = st.nextToken();

String legendName = makeLegendName(validFileName,
(String) null, false);

outStream.store(validFileName, legendName, outgoingUnits,
(float)factorDef.minRealLimit,
(float)factorDef.maxRealLimit,
lat, lon, stationElev, beamElev, radarRes,
pGrid, startTimes, endTimes);

}
catch (Exception e)
{
_log.event("StreamMill", _fileName
+ " StreamMill.cache(): "
+ "StreamFactorMill.cache Exception:"
+ "e.toString() = " + e.toString() + "\n"
+ " file = " + _fileName);

return;
// throw new ParamError("StreamFactorMill.cache",
// ParamError.InvalidParam, "e.toString() = " + e.toString());
}

return;
}

private PolarGrid getPolarGrid()
{
PolarGrid pGrid = null;
if(_rdr == null)
// System.out.println("getPolarGrid DEBUG _rdr == null");
if((_rdr != null) && (_rdr.getSymBlk() == null))
// System.out.println("getPolarGrid DEBUG _rdr.getSymBlk() == null");
if((_rdr != null) && (_rdr.getSymBlk() != null)
&& (_rdr.getSymBlk().getSymDataPkt(0) == null))
{
// System.out.println("getPolarGrid DEBUG _rdr.getSymBlk().getSymDataPkt() == null");
// System.out.println("getPolarGrid DEBUG _rdr.getSymBlk().getSymDataPktSize() = "+_rdr.getSymBlk().getSymDataPktSize());
}
if((_rdr != null) && (_rdr.getSymBlk() != null)
&& (_rdr.getSymBlk().getSymDataPkt(0) != null))
{
int nNumPkts = _rdr.getSymBlk().getSymDataPkt(0).getNumDataPkts();
DataPkt dp = null;
int i = 0;
do {
dp = _rdr.getSymBlk().getSymDataPkt(0).getDataPkt(i);
i++;
}while(!(dp instanceof RadialPkt) && (i < nNumPkts));
if(dp != null)
pGrid = ((RadialPkt)dp).getPolarGrid();
}

return pGrid;
}

/**
* getTimeValid gets the time range the data is valid for.
* Per Bob Lipschutz the only way to tell is via the VolCovPat.
* VolCovPat = 11 implies time of validity is Five Min.
* VolCovPat = 21 implies time of validity is Six Min.
* VolCovPat = 31 implies time of validity is Ten Min.
* VolCovPat = 32 implies time of validity is Ten Min.
*/
public TimeRange getTimeValid(ProdBlk pb)
{
//Per Bob Lipschutz
long lnFiveMin = 5 * 60 * 1000;
long lnSixMin = 6 * 60 * 1000;
long lnTenMin = 10 * 60 * 1000;
Date dVolScan = RadarReader.getDate(pb.getVolScnDate(),
pb.getVolScnStartTm());
long lnStartTm = dVolScan.getTime();
long lnEndTm = lnStartTm + lnTenMin;
if(pb.getVolCovPat() == 11)// 11 per Bob Lipschutz
lnEndTm = lnStartTm + lnFiveMin;
if(pb.getVolCovPat() == 21)// 21 per Bob Lipschutz
lnEndTm = lnStartTm + lnSixMin;
if(pb.getVolCovPat() == 31)// 31 per Bob Lipschutz
lnEndTm = lnStartTm + lnTenMin;
if(pb.getVolCovPat() == 32)// 32 per Bob Lipschutz
lnEndTm = lnStartTm + lnTenMin;
Date dEnd = new Date(lnEndTm);
return(new TimeRange(dVolScan, dEnd));
}

//@>data

private ConfigSet _set;
private FMConfig _factorMill;
private String _configFile;
private String _fileName;
private FactorDef factorDef;
private int _xdim;

private static float FT_TO_M = (float) 0.3048;
private static float KM_TO_M = (float) 1000;

private String _variableName = null;
private Log _log;
private Radar _rdr = null;
}

The Mill module calls a the IFPFileWriter Module which updates the INDEX.dat and INDEXTS.dat files on the website and stores the data on the website. It has different store functions for each type of data it stores.

IFPFileWriter.java Source code

package ifp.init;


import ifp.data.ParmInfo;
import ifp.data.GridParmInfo;
//import ifp.data.ObsParmInfo;
import ifp.data.RadarParmInfo;
import ifp.data.TimeRange;
import ifp.data.Projection;
import ifp.data.Domain;
import ifp.data.ScalarGrid;
import ifp.data.VectorGrid;
import ifp.data.WeatherGrid;

//import ifp.data.LocationObs;
import ifp.data.WorldPoint;
import ifp.data.Parm;
//import ifp.data.GridParm;
//import ifp.data.ObsParm;
//import ifp.data.RadarParm;
import ifp.data.TextParmInfo;
import ifp.data.TextParm;

import hmlib.common.AppProperties;
import hmlib.common.PropertyError;

import hmserve.ingest.QCclass;
import ldadapp.text.Alert;
import ldadapp.text.AlertReader;

import ldadapp.data.*;
import ldadapp.radar.*;

import ldadapp.data.obs.*;

import datapool.DataAvail;
import datapool.DataInfo;

import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.zip.GZIPOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.Hashtable;
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.StringTokenizer;
import java.util.Enumeration;
import java.util.Vector;
import java.text.NumberFormat;
import java.text.DateFormat;
//F>=========================================================================
// IFPFileWriter.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================

/**
* An IFPFileWriter is a class which implements the IFPWriter interface.
* methods are provided to store scalar, vector, and categorical data
* types.
*
*
* @see ifp.data.IFPWriter
* @author Romberg
* @author $Author: steffen $
* @since $Date: 2001/07/13 23:03:40 $
*
* @version $Revision: 1.13 $
*/
public class IFPFileWriter implements IFPWriter
{
/**
* Constructor for an IFPWriter.
*/
public IFPFileWriter()
{
}

/**
* Stores scalar gridded data.
* @see IFPWriter#store(String, String, String, float, float,
* int, int, String, float, float,
* float, float, float[][][], Date[],
* Date[])
*/
public void store(String name, String longName, String units,
float minVal, float maxVal, int xDim, int yDim, String projName,
float xorigin, float yorigin, float xextent, float yextent,
float data[][][], Date startTimes[], Date endTimes[]) throws IOException
{
int i = 0;
GridParmInfo pi = new GridParmInfo(name, longName, units, minVal,
maxVal, xDim, yDim, new Projection(projName,
new Domain(xorigin, yorigin, xextent, yextent)));

ScalarGrid grids[] = new ScalarGrid[data.length];
for (i = 0 ; i < data.length ; i++)
grids[i] = new ScalarGrid(pi,
new TimeRange(startTimes[i], endTimes[i]), data[i]);

// store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new GridParm(pi,grids));
store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new Parm(pi,(Data[])grids));
}

/**
* Used to store vector grided data.
* @see IFPWriter#store(String, String, String, float, float,
* int, int, String, float, float, float,
* float, float[][][], float[][][], Date[], Date[])
*/
public void store(String name, String longName, String units,
float minVal, float maxVal, int xDim, int yDim, String projName,
float xorigin, float yorigin, float xextent, float yextent,
float uData[][][], float vData[][][], Date startTimes[],
Date endTimes[]) throws IOException
{
int i = 0;
GridParmInfo pi = new GridParmInfo(name, longName, units, minVal,
maxVal, xDim, yDim, new Projection(projName,
new Domain(xorigin, yorigin, xextent, yextent)));

VectorGrid grids[] = new VectorGrid[uData.length];
for (i = 0 ; i < uData.length ; i++)
{
float mag[][] = new float[xDim][yDim];
float dir[][] = new float[xDim][yDim];
for (int x = 0 ; x < xDim ; x++)
for (int y = 0 ; y < yDim ; y++)
{
// Calc the magnitude
mag[x][y] = (float)Math.sqrt(Math.pow(uData[i][x][y],
2.0) + Math.pow(vData[i][x][y], 2.0));
// Find the direction (in radians)
dir[x][y] = (float)Math.atan2(vData[i][x][y],
uData[i][x][y]);
if (dir[x][y] < 0.0)
dir[x][y] += (Math.PI * 2.0);

// Convert to degrees.
dir[x][y] = (float)(dir[x][y] * 180.0 / Math.PI);
}

grids[i] = new VectorGrid(pi, new TimeRange(startTimes[i],
endTimes[i]), mag, dir);
}

// store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new GridParm(pi,grids));
store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new Parm(pi,(Data[])grids));
}

/**
* Used to store categorical gridded data.
* @see IFPWriter#store(String, String, String,
* int, int, String, float, float, float,
* float, int[][][], String[], Date[], Date[])
*/
public void store(String name, String longName, String units,
int xDim, int yDim, String projName,
float xorigin, float yorigin, float xextent, float yextent,
int data[][][], String key[], Date startTimes[],
Date endTimes[]) throws IOException
{
int i = 0;
GridParmInfo pi = new GridParmInfo(name, longName, units, 0, 0,
xDim, yDim, new Projection(projName, new Domain(xorigin, yorigin,
xextent, yextent)));

WeatherGrid grids[] = new WeatherGrid[data.length];
for (i = 0 ; i < data.length ; i++)
{
String tmp[][] = new String[xDim][yDim];
for (int x = 0 ; x < xDim ; x++)
for (int y = 0 ; y < yDim ; y++)
tmp[x][y] = key[data[i][x][y]];

grids[i] = new WeatherGrid(pi,
new TimeRange(startTimes[i], endTimes[i]), tmp);
}

// store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new GridParm(pi,grids));
store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new Parm(pi,(Data[])grids));
}


/**
* Stores radar data.
* @see IFPWriter#store(String, String, String, float, float,
* int, byte [], Date[], Date[])
*/
public void store(String name, String longName, String units,
float minVal, float maxVal, float lat, float lon,
float stationElev, float beamElev, float radarRes, PolarGrid pGrid,
Date startTimes[], Date endTimes[]) throws IOException
{
// RadarParmInfo pi = new RadarParmInfo(name, longName, units, minVal,
// maxVal, lat, lon, stationElev, beamElev, radarRes);

ParmInfo pi = new ParmInfo(name, longName, units, minVal, maxVal);
PolarGrid data[] = new PolarGrid[1];

data[0] = pGrid;
data[0].setTimeRange(new TimeRange(startTimes[0], endTimes[0]));

// store(new RadarParm(pi, (Data[])data));
// store(new TimeRange(startTimes[0],endTimes[0]),new RadarParm(pi, data));
store(new TimeRange(startTimes[0],endTimes[0]),
new Parm(pi,(Data[])data));
}

// Used to store scalar observation data
public void store(String name, String longName, String units,
float minVal, float maxVal, float data[][], String ids[][],
String provIds[][], Date startTimes[], Date endTimes[], Date obsTimes[][])
throws IOException
{
ParmInfo pi = new ParmInfo(name, longName, units, minVal, maxVal);

MagReadGrp mrg = new MagReadGrp();
// MagReadGrp[] mrg = new MagReadGrp[1];
String[] strIDs = new String[ids[0].length];

for(int i=0;i<ids[0].length;i++)
strIDs[i] = provIds[0][i] + "&" + ids[0][i];

mrg.setTimeRange(new TimeRange(startTimes[0], endTimes[0]));
mrg.setFullName(name);
mrg.setAbbrName(longName);
mrg.setUnits(units);

fillMagReadGrp(mrg, strIDs, data[0],
new TimeRange(startTimes[0], endTimes[0]), obsTimes[0]);

MagReadGrp[] mrgArray = new MagReadGrp[1];
mrgArray[0] = mrg;

store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),
new Parm(pi,(Data[])mrgArray));
}

// Used to store vector observation data
public void store(String name, String longName, String units,
float minVal, float maxVal, float uData[][], float vData[][],
String ids[][], String provIds[][],
Date startTimes[], Date endTimes[], Date obsTimes[][]) throws IOException
{
name = "v" + name; // change obs to vobs.

ParmInfo pi = new ParmInfo(name, longName, units, minVal, maxVal);

VecReadGrp vrg = new VecReadGrp();
String[] strIDs = new String[ids[0].length];

for(int i=0;i<ids[0].length;i++)
strIDs[i] = provIds[0][i] + "&" + ids[0][i];

vrg.setTimeRange(new TimeRange(startTimes[0], endTimes[0]));
vrg.setFullName(name);
vrg.setAbbrName(longName);
vrg.setUnits(units);

// vData = magnitude...
// uData = direction...

fillVecReadGrp(vrg, strIDs, vData[0], uData[0],
new TimeRange(startTimes[0], endTimes[0]), obsTimes[0]);

VecReadGrp[] vrgArray = new VecReadGrp[1];
vrgArray[0] = vrg;

store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),
new Parm(pi,(Data[])vrgArray));
}

// Used to store categorical observation data
public void store(String name, String longName, String units,
String data[][], String ids[][],
String provIds[][], Date startTimes[],
Date endTimes[], Date obsTimes[][]) throws IOException
{
name = "w" + name; // change obs to wobs.

ParmInfo pi = new ParmInfo(name, longName, units, (float)0.0,
(float)0.0);

WordReadGrp wrg = new WordReadGrp();
String[] strIDs = new String[ids[0].length];

for(int i=0;i<ids[0].length;i++)
strIDs[i] = provIds[0][i] + "&" + ids[0][i];

wrg.setTimeRange(new TimeRange(startTimes[0], endTimes[0]));
wrg.setFullName(name);
wrg.setAbbrName(longName);
wrg.setUnits(units);

fillWordReadGrp(wrg, strIDs, data[0],
new TimeRange(startTimes[0], endTimes[0]), obsTimes[0]);

WordReadGrp[] wrgArray = new WordReadGrp[1];
wrgArray[0] = wrg;

store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),
new Parm(pi,(Data[])wrgArray));
}

// Used to store QC data
public void store(String name, String longName, String units,
float minVal, float maxVal, QCclass qcClass,
String ids[][], String provIds[][],
Date startTimes[], Date endTimes[], Date obsTimes[][]) throws IOException
{
ParmInfo pi = new ParmInfo(name, longName, units, minVal, maxVal);

QualityCtrlGrp qcg = new QualityCtrlGrp(QualityCtrl._PROVIDER,
QualityCtrl._PROVIDERID, "QC",
qcClass.getQCT());

String[] strIDs = new String[ids[0].length];

for(int i=0;i<ids[0].length;i++)
strIDs[i] = provIds[0][i] + "&" + ids[0][i];

qcg.setTimeRange(new TimeRange(startTimes[0], endTimes[0]));
qcg.setFullName(name);
qcg.setAbbrName(longName);
qcg.setUnits(units);

QCTst[] qcTst = new QCTst[strIDs.length];
String strTstGrpNameQCT = "Quality Control Test";

qcTst = getQCTst(strTstGrpNameQCT, qcClass.getQCA(),
qcClass.getQCR(), qcClass.getQCD());

String[] qcSubjective = new String[strIDs.length];

fillQualityCtrlGrp(qcg, strIDs, qcClass.getDD(), qcSubjective, qcTst,
new TimeRange(startTimes[0], endTimes[0]), obsTimes[0]);

QualityCtrlGrp[] qcgArray = new QualityCtrlGrp[1];
qcgArray[0] = qcg;

store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),
new Parm(pi,(Data[])qcgArray));
}

// Used to store station location data
public void store(String name, String ids[][], float lat[][], float lon[][],
Date startTimes[], Date endTimes[]) throws IOException
{
int i = 0;
// ObsParmInfo pi = new ObsParmInfo("station-metar-national", "Station Locations", "FAHRENHEIT", (float)0.0, (float)0.0);
ParmInfo pi = new ParmInfo(name, "Station Locations", "FAHRENHEIT", (float)0.0, (float)0.0);

// LocationObs lobs[] = new LocationObs[startTimes.length];

for (i = 0 ; i < startTimes.length ; i++)
{
WorldPoint locations[] = new WorldPoint[ids[i].length];
for (int j = 0 ; j < ids[i].length; j++)
{
locations[j] = new WorldPoint(lon[i][j], lat[i][j]);
}
// lobs[i] = new LocationObs(pi, locations, ids[i],
// new TimeRange(startTimes[i], endTimes[i]));
}
// store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new ObsParm(pi, lobs));
// store(new TimeRange(startTimes[0],endTimes[endTimes.length-1]),new Parm(pi, lobs));
}

/**
* Used to store text alert data.
* @param strGroupName The strGroupName of the parameter (should be unique).
* It is also equivalent to the VTEC significance code.
* Example: nwstext-warning-local, or localtext-report-local.
* @param strFileName[] The strFileName[] this is also used as an alertID.
* Example: DENNOWDEN1.txt
*/
public void store(String strGroupName, String strPathFileName)
throws IOException, FileNotFoundException
{ // GroupName = VTEC Significance Code
// I need to merge in the DEN...DEN1.txt file with the current alert catagory.
// I must also compile a list of files which belong to the WATCH/WARNING/etc catagories.

StringTokenizer st;
String strFileName = null;
Alert alert = new Alert();
FileInputStream fis = null;
InputStreamReader isr = null;
AlertReader ar = null;
//BEGIN: Parse the PathFileName to get AlertID.
st = new StringTokenizer(strPathFileName, "/");
int nNumPathFileNames = st.countTokens();
for(int j=0;j<nNumPathFileNames;j++)
{ // Strip off the path.
strFileName = st.nextToken();
}
st = new StringTokenizer(strFileName,".");
strFileName = st.nextToken(); // Strip of file type prefix.
strFileName = st.nextToken();


//BEGIN: Parse the GroupName
st = new StringTokenizer(strGroupName,"-");
int nNumGroupNames = st.countTokens();
String astrGroupName[] = new String[nNumGroupNames];
for(int i=0;i<nNumGroupNames;i++)
{
astrGroupName[i] = st.nextToken();
}
//END: Parse the GroupName

String str = astrGroupName[1].toUpperCase();

//END: Parse the PathFileName to get AlertID.
fis = new FileInputStream(strPathFileName);
isr = new InputStreamReader(fis);
ar = new AlertReader(isr);
alert = ar.readAlertText(strFileName, str);
ar.close();
isr.close();
fis.close();

String strGNmAlrtID = new String(astrGroupName[0] +"-"+ astrGroupName[1]
+"-"+ strFileName +"-"+ astrGroupName[2]);
TextParmInfo tpf = null;
tpf = new TextParmInfo(strGNmAlrtID, str);
alert.setFullName(tpf.name()); // <- New
alert.setAbbrName(tpf.name()); // <- New
alert.setUnits(tpf.units()); // <- New
Date [] startTimes = null; // <- New
Date [] endTimes = null; // <- New
startTimes = new Date[1]; // <- New
endTimes = new Date[1]; // <- New
startTimes[0] = new Date(System.currentTimeMillis());
long offset = 3600000L;
if (str.equals(AlertReader.REPORT))
offset = AlertReader.REPORTTIME;
else if (str.equals(AlertReader.UNKNOWN))
offset = AlertReader.UNKNOWNTIME;
else if (str.equals(AlertReader.QCTEXT))
offset = AlertReader.QCTEXTTIME;
else if (str.equals(AlertReader.STATEMENT))
offset = AlertReader.STATEMENTTIME;
else if (str.equals(AlertReader.OUTLOOK))
offset = AlertReader.OUTLOOKTIME;
else if (str.equals(AlertReader.WATCH))
offset = AlertReader.WATCHTIME;
else if (str.equals(AlertReader.WARNING))
offset = AlertReader.WARNINGTIME;
else if (str.equals(AlertReader.FORECAST))
offset = AlertReader.FORECASTTIME;
else if (str.equals(AlertReader.ADVISORY))
offset = AlertReader.ADVISORYTIME;

endTimes[0] = new Date((long)(startTimes[0].getTime()+offset));

alert.setTimeRange(new TimeRange(startTimes[0],endTimes[0]));
alert.setFileDate(new Date(System.currentTimeMillis()));

TextParm tp = null;
Alert mergeAlerts[] = null;
try {
TextParm tpOld = (TextParm)fetchParm(strGroupName);
tpOld.removeExpired();
tpOld.mergeAlert(alert);
mergeAlerts = tpOld.alerts();
}
catch (IOException e)
{
mergeAlerts = new Alert[1];
mergeAlerts[0] = alert;
}

//BEGIN: Create TextParmInfo.
// String strGNmAlrtID = new String(astrGroupName[0] +"-"+ astrGroupName[1]
// +"-"+ mergeAlerts[0].getAlertID() +"-"+ astrGroupName[2]);
// New Format........
// tp = new TextParm(tpf, mergeAlerts);
// store(new TimeRange(startTimes[0],endTimes[0]), tp);

store(new TimeRange(startTimes[0],endTimes[0]),
new Parm(tpf, (Data[])mergeAlerts));

// Old Format........
// tpf = new TextParmInfo(strGroupName, str);
// tp = new TextParm(tpf, mergeAlerts);
// store(new TimeRange(startTimes[0],endTimes[0]), tp);
}


public synchronized String store(TimeRange tr, Parm p) throws IOException
{
synchronized(p)
{
if (p != null)
{
String fname
= _dataPath + _fileSep + p.parmInfo().name() + ".dat";
synchronized(_index)
{
archiveData(tr, p, fname);
}
}
}
return null;
}

public synchronized void writeObjectFile(Parm p, String fname)
throws IOException
{
FileOutputStream fos = new FileOutputStream(fname + ".incoming");
GZIPOutputStream zos = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(zos);
oos.writeObject(p);
oos.close();
File oldFile = new File(fname + ".incoming");
if(oldFile.length() == 0)
{
oldFile.delete();
}
else
{
File newFile = new File(fname);
oldFile.renameTo(newFile);
}
return;
}

private void saveIndex() throws IOException
{
FileOutputStream fos =
new FileOutputStream(_dataPath + _fileSep + IFILENAME + ".incoming");
GZIPOutputStream zos = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(zos);
oos.writeObject(_index);
oos.close();
File oldFile =
new File(_dataPath + _fileSep + IFILENAME + ".incoming");
File newFile = new File(_dataPath + _fileSep + IFILENAME);
oldFile.renameTo(newFile);
touchTimeFile();
}

private void touchTimeFile() throws IOException
{
FileOutputStream fos = new FileOutputStream(_dataPath
+ _fileSep + TIMEFILENAME + ".incoming");

GZIPOutputStream zos = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(zos);
long lnTime[] = new long[1];
lnTime[0] = System.currentTimeMillis();
oos.writeObject(lnTime);
oos.close();
zos.close();
fos.close();
File oldFile =
new File(_dataPath + _fileSep + TIMEFILENAME + ".incoming");
File newFile = new File(_dataPath + _fileSep + TIMEFILENAME);
oldFile.renameTo(newFile);
return;
}

private Parm fetchParm(String name) throws IOException
{
Parm p = null;
String fname = _dataPath + _fileSep + name + ".dat";
p = (Parm)readFile(fname);
return p;
}
private Object readFile(String fname) throws IOException
{
FileInputStream fis = new FileInputStream(fname);
GZIPInputStream zis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(zis);
Object rval = null;
try
{
rval = ois.readObject();
}
catch (Exception e)
{
if(e instanceof IOException)
{
IOException ioe = (IOException)e;
throw ioe;
}
else
e.printStackTrace();
}

ois.close();
return rval;
}

private static Hashtable initIndex()
{
// For operations, construct a data directory path.
_dataPath = AppProperties.getProperty("run.data.dir");
if (_dataPath == null)
_dataPath = new String("data");

Hashtable index = new Hashtable();

_fileSep = System.getProperty("file.separator", "/").charAt(0);

File ifile = new File(new String(_dataPath + _fileSep + IFILENAME));
try
{
FileInputStream fis = new FileInputStream(ifile);
GZIPInputStream zis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(zis);
index = (Hashtable)ois.readObject();
}
catch (FileNotFoundException e)
{
}
catch (IOException e)
{
e.printStackTrace();
index = new Hashtable();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
index = new Hashtable();
}
return index;
}

private synchronized void archiveData(TimeRange tr, Parm p, String fname) throws IOException
{
int i,j = 1;
int dataInfoSize = 0;
String parmInfoName = p.parmInfo().name();
DataAvail da = null;

ParmInfo key = findKey(parmInfoName);

if (key != null)
{
da = (DataAvail) _index.get(key);
dataInfoSize = da.getDataInfoSize();
}
else
da = new DataAvail();

if (parmInfoName.indexOf("text") >= 0)
da = new DataAvail();

if (dataInfoSize == _maxMsgNum)
{
File file = new File(da.getDataInfo(0).getFileName());
String name = file.getName();
String filename = _dataPath + _fileSep + name;

file = new File(filename);
file.delete();
da.removeDataInfo(da.getDataInfo(0));
}

Date currentTime = new Date(System.currentTimeMillis());

String indexFileName;
String outputFileName;
if (p.parmInfo().name().indexOf("text") >= 0)
{
indexFileName = "data" + _fileSep + parmInfoName + ".dat";
outputFileName = _dataPath + _fileSep + parmInfoName + ".dat";
}
else
{
indexFileName = "data" + _fileSep + parmInfoName + "-"
+ setFileTime(currentTime) + ".dat";
outputFileName = _dataPath + _fileSep + parmInfoName + "-"
+ setFileTime(currentTime) + ".dat";
}

DataInfo ndi = new DataInfo(indexFileName, currentTime, tr);
da.addDataInfo(ndi);

if (parmInfoName.indexOf("text") >= 0)
{
purgeOldAlerts(currentTime);
_index.remove(p.parmInfo());
_index.put(p.parmInfo(), da);
}
else
_index.put(p.parmInfo(), da);

saveIndex();

writeObjectFile(p, outputFileName);

return;
}

private ParmInfo findKey(String name)
{
ParmInfo key = null;
if (_index.isEmpty())
return key;

Enumeration keys = _index.keys();
while (keys.hasMoreElements())
{
key = (ParmInfo)keys.nextElement();
DataAvail da = (DataAvail) _index.get((Object)key);
if (key.name().trim().equals(name.trim()))
return key;
}
return null;
}

private String setFileTime(Date date)
{
// UTC is not something M$ or netscape does. So...
TimeZone tz = TimeZone.getTimeZone("GMT");
tz.setRawOffset(0);
Calendar calendar = Calendar.getInstance(tz);

calendar.setTime(date);

NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumIntegerDigits(2);
nf.setMaximumIntegerDigits(2);
String rval
= nf.format(calendar.get(Calendar.YEAR))
+ nf.format(calendar.get(Calendar.MONTH)+(int)1)
+ nf.format(calendar.get(Calendar.DAY_OF_MONTH))
+ nf.format(calendar.get(Calendar.HOUR_OF_DAY))
+ nf.format(calendar.get(Calendar.MINUTE))
+ nf.format(calendar.get(Calendar.SECOND));

nf.setMinimumIntegerDigits(3);
nf.setMaximumIntegerDigits(3);
rval += nf.format(calendar.get(Calendar.MILLISECOND));

return rval;
}

void fillMagReadGrp(MagReadGrp mrg, String[] strIDs, float fData[],
TimeRange tr, Date[] obsTimes)
{
float[] fMag = null;

Vector vfaMag = new Vector(10, 10);

Hashtable htIdToVecOfMag = new Hashtable();
Hashtable htIdToVecOfTime = new Hashtable();
Hashtable htIdToMags = new Hashtable();
Hashtable htIdToDates = new Hashtable();
Hashtable htIdToTimes = new Hashtable();
float fa[] = new float[1];
Date fa3[] = new Date[1];
Vector vfa = null;

//BEGIN: sort so the latest one is the first element in the vector.
for(int i=strIDs.length-1;i>=0;i--)
{
//BEGIN: sort Mag so the latest one is the first element in Vector.
Vector vfMag = (Vector)htIdToVecOfMag.get(strIDs[i]);
if(vfMag == null)
{
fa = new float[1];
fa[0] = fData[i];
vfa = new Vector(4, 1);
vfa.addElement(fa);
htIdToVecOfMag.put(strIDs[i], vfa);
}
else
{
fa = new float[1];
fa[0] = fData[i];
vfa = new Vector(4, 1);
vfMag.addElement(fa);
}
//END: sort Mag so the latest one is the first element in Vector.
//BEGIN: sort Time so the latest one is the first element in Vector.
Vector vTime = (Vector)htIdToVecOfTime.get(strIDs[i]);
if(vTime == null)
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vfa.addElement(fa3);
htIdToVecOfTime.put(strIDs[i], vfa);
}
else
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vTime.addElement(fa3);
}
//END: sort Time so the latest one is the first element in Vector.
}
//END: sort so the latest one is the first element in the vector
//BEGIN: Convert Mag vectors to arrays.
Enumeration eKeys = htIdToVecOfMag.keys();
Vector vfMag = null;
String strCurKey = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vfMag = (Vector)htIdToVecOfMag.get(strCurKey);
fMag = new float[vfMag.size()];
for(int i=0;i<vfMag.size();i++)
fMag[i] = ((float[])(vfMag.elementAt(i)))[0];
htIdToMags.put(strCurKey, fMag);
}
//END: Convert Mag vectors to arrays.

//BEGIN: Convert Time vectors to arrays.
eKeys = htIdToVecOfTime.keys();
Vector vTime = null;
Date[] time = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vTime = (Vector)htIdToVecOfTime.get(strCurKey);
time = new Date[vTime.size()];
for(int i=0;i<vTime.size();i++)
time[i] = ((Date[])(vTime.elementAt(i)))[0];
int j=time.length-1;
for(int i=0; i < j; i++)
{
Date dt = time[i];
time[i] = time[j];
time[j] = dt;
j--;
}

htIdToTimes.put(strCurKey, time);
}
//END: Convert Time vectors to arrays.

//BEGIN: Estimate Times so the latest one is the first element in vec.

int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToMags.keys();
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.endTime().getTime();
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
fMag = (float [])htIdToMags.get(strCurKey);
nNumTimes = fMag.length;
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.

//BEGIN: Add to MagReadGrp.
eKeys = htIdToMags.keys();
String strStaIdKey = null;
while(eKeys.hasMoreElements())
{
strStaIdKey = (String)(eKeys.nextElement());
// System.out.println("MagReadGrp.readMagReadGrp DEBUG: strStaIdKey = "+strStaIdKey);
// System.out.println("MagReadGrp.readMagReadGrp DEBUG: htIdToMags.get(strStaIdKey) = "+htIdToMags.get(strStaIdKey));
// System.out.println("MagReadGrp.readMagReadGrp DEBUG: htIdToDates.get(strStaIdKey) = "+htIdToDates.get(strStaIdKey));

mrg.addMagReads(strStaIdKey, (float[])htIdToMags.get(strStaIdKey),
(Date[])htIdToTimes.get(strStaIdKey));
// (Date[])htIdToDates.get(strStaIdKey));
}
//END: Add to MagReadGrp.

// return mrg;

return;
}

void fillVecReadGrp(VecReadGrp vrg, String[] strIDs, float fData[],
float fDir[], TimeRange tr, Date[] obsTimes)
{
float[] fMag = null;

Vector vfaMag = new Vector(10, 10);

Hashtable htIdToVecOfMag = new Hashtable();
Hashtable htIdToVecOfDir = new Hashtable();
Hashtable htIdToVecOfTime = new Hashtable();
Hashtable htIdToMags = new Hashtable();
Hashtable htIdToDirs = new Hashtable();
Hashtable htIdToDates = new Hashtable();
Hashtable htIdToTimes = new Hashtable();
float fa[] = new float[1];
Date fa3[] = new Date[1];
Vector vfa = null;

//BEGIN: sort so the latest one is the first element in the vector.
for(int i=strIDs.length-1;i>=0;i--)
{
//BEGIN: sort Mag so the latest one is the first element in Vector.
Vector vfMag = (Vector)htIdToVecOfMag.get(strIDs[i]);
if(vfMag == null)
{
fa = new float[1];
fa[0] = fData[i];
vfa = new Vector(4, 1);
vfa.addElement(fa);
htIdToVecOfMag.put(strIDs[i], vfa);
}
else
{
fa = new float[1];
fa[0] = fData[i];
vfa = new Vector(4, 1);
vfMag.addElement(fa);
}
//END: sort Mag so the latest one is the first element in Vector.
//BEGIN: sort Dir so the latest one is the first element in Vector.
Vector vfDir = (Vector)htIdToVecOfDir.get(strIDs[i]);
if(vfDir == null)
{
fa = new float[1];
fa[0] = fDir[i];
vfa = new Vector(4, 1);
vfa.addElement(fa);
htIdToVecOfDir.put(strIDs[i], vfa);
}
else
{
fa = new float[1];
fa[0] = fData[i];
vfa = new Vector(4, 1);
vfDir.addElement(fa);
}
//END: sort Dir so the latest one is the first element in Vector.
//BEGIN: sort Time so the latest one is the first element in Vector.
Vector vTime = (Vector)htIdToVecOfTime.get(strIDs[i]);
if(vTime == null)
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vfa.addElement(fa3);
htIdToVecOfTime.put(strIDs[i], vfa);
}
else
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vTime.addElement(fa3);
}
//END: sort Time so the latest one is the first element in Vector.
}
//END: sort so the latest one is the first element in the vector
//BEGIN: Convert Mag vectors to arrays.
Enumeration eKeys = htIdToVecOfMag.keys();
Vector vfMag = null;
String strCurKey = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vfMag = (Vector)htIdToVecOfMag.get(strCurKey);
fMag = new float[vfMag.size()];
for(int i=0;i<vfMag.size();i++)
fMag[i] = ((float[])(vfMag.elementAt(i)))[0];
htIdToMags.put(strCurKey, fMag);
}
//END: Convert Mag vectors to arrays.

//BEGIN: Convert Dir vectors to arrays.
eKeys = htIdToVecOfDir.keys();
Vector vfDir = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vfDir = (Vector)htIdToVecOfDir.get(strCurKey);
fDir = new float[vfDir.size()];
for(int i=0;i<vfDir.size();i++)
fDir[i] = ((float[])(vfDir.elementAt(i)))[0];
htIdToDirs.put(strCurKey, fDir);
}
//END: Convert Dir vectors to arrays.

//BEGIN: Convert Time vectors to arrays.
eKeys = htIdToVecOfTime.keys();
Vector vTime = null;
Date[] time = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vTime = (Vector)htIdToVecOfTime.get(strCurKey);
time = new Date[vTime.size()];
for(int i=0;i<vTime.size();i++)
time[i] = ((Date[])(vTime.elementAt(i)))[0];
int j=time.length-1;
for(int i=0; i < j; i++)
{
Date dt = time[i];
time[i] = time[j];
time[j] = dt;
j--;
}

htIdToTimes.put(strCurKey, time);
}
//END: Convert Time vectors to arrays.

/* //BEGIN: Estimate Times so the latest one is the first element in vec.
int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToMags.keys();
while(eKeys.hasMoreElements())
{
fMag = (float [])htIdToMags.get((String)(eKeys.nextElement()));
nNumTimes = fMag.length;
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.startTime().getTime();
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.
*/


//////////
//BEGIN: Estimate Times so the latest one is the first element in vec.

int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToMags.keys();
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.endTime().getTime();
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
fMag = (float [])htIdToMags.get(strCurKey);
nNumTimes = fMag.length;
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.
//////////

//BEGIN: Add to VecReadGrp.
eKeys = htIdToMags.keys();
String strStaIdKey = null;
while(eKeys.hasMoreElements())
{
strStaIdKey = (String)(eKeys.nextElement());

//BEGIN: DEBUG-
// float fMagA[] = (float[])htIdToMags.get(strStaIdKey);
// for(int j=0;j<fMagA.length;j++)
// fMagA[j] = 70;
//// fMagA[j] = 275;
// float fDirA[] = (float[])htIdToDirs.get(strStaIdKey);
// for(int j=0;j<fDirA.length;j++)
// fDirA[j] = 225;
//END: DEBUG-




vrg.addVecReads(strStaIdKey, (float[])htIdToMags.get(strStaIdKey),
(float[])htIdToDirs.get(strStaIdKey),
(Date[])htIdToTimes.get(strStaIdKey));
// (Date[])htIdToDates.get(strStaIdKey));
}

//END: Add to VecReadGrp.
// return vrg;

return;
}

void fillWordReadGrp(WordReadGrp wrg, String[] strIDs, String strData[],
TimeRange tr, Date[] obsTimes)
{
String[] strWord = null;

Vector vstraWord = new Vector(10, 10);

Hashtable htIdToVecOfWord = new Hashtable();
Hashtable htIdToVecOfTime = new Hashtable();
Hashtable htIdToWords = new Hashtable();
Hashtable htIdToDates = new Hashtable();
Hashtable htIdToTimes = new Hashtable();
String stra[] = new String[1];
Date fa3[] = new Date[1];
Vector vstra = null;

//BEGIN: sort so the latest one is the first element in the vector.
for(int i=strIDs.length-1;i>=0;i--)
{
//BEGIN: sort Word so the latest one is the first element in Vector.
Vector vstrWord = (Vector)htIdToVecOfWord.get(strIDs[i]);
if(vstrWord == null)
{
stra = new String[1];
stra[0] = strData[i];
vstra = new Vector(4, 1);
vstra.addElement(stra);
htIdToVecOfWord.put(strIDs[i], vstra);
}
else
{
stra = new String[1];
stra[0] = strData[i];
vstra = new Vector(4, 1);
vstrWord.addElement(stra);
}
//END: sort Word so the latest one is the first element in Vector.
//BEGIN: sort Time so the latest one is the first element in Vector.
Vector vTime = (Vector)htIdToVecOfTime.get(strIDs[i]);
if(vTime == null)
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vstra = new Vector(4, 1);
vstra.addElement(fa3);
htIdToVecOfTime.put(strIDs[i], vstra);
}
else
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vstra = new Vector(4, 1);
vTime.addElement(fa3);
}
//END: sort Time so the latest one is the first element in Vector.
}
//END: sort so the latest one is the first element in the vector
//BEGIN: Convert Word vectors to arrays.
Enumeration eKeys = htIdToVecOfWord.keys();
Vector vstrWord = null;
String strCurKey = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vstrWord = (Vector)htIdToVecOfWord.get(strCurKey);
strWord = new String[vstrWord.size()];
for(int i=0;i<vstrWord.size();i++)
strWord[i] = ((String[])(vstrWord.elementAt(i)))[0];
htIdToWords.put(strCurKey, strWord);
}
//END: Convert Word vectors to arrays.

//BEGIN: Convert Time vectors to arrays.
eKeys = htIdToVecOfTime.keys();
Vector vTime = null;
Date[] time = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vTime = (Vector)htIdToVecOfTime.get(strCurKey);
time = new Date[vTime.size()];
for(int i=0;i<vTime.size();i++)
time[i] = ((Date[])(vTime.elementAt(i)))[0];
int j=time.length-1;
for(int i=0; i < j; i++)
{
Date dt = time[i];
time[i] = time[j];
time[j] = dt;
j--;
}

htIdToTimes.put(strCurKey, time);
}
//END: Convert Time vectors to arrays.

//BEGIN: Estimate Times so the latest one is the first element in vec.

int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToWords.keys();
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.endTime().getTime();
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
// fMag = (float [])htIdToWords.get(strCurKey);
strWord = (String [])htIdToWords.get(strCurKey);
// nNumTimes = fMag.length;
nNumTimes = strWord.length;
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.


//BEGIN: Add to WordReadGrp.
eKeys = htIdToWords.keys();
String strStaIdKey = null;
while(eKeys.hasMoreElements())
{
strStaIdKey = (String)(eKeys.nextElement());
// System.out.println("WordReadGrpReader.readWordGrp DEBUG: strStaIdKey = "+strStaIdKey);
// System.out.println("WordReadGrpReader.readWordGrp DEBUG: (String[])htIdToWords.get(strStaIdKey) = "+(String[])htIdToWords.get(strStaIdKey));
String str2[] = (String[])htIdToWords.get(strStaIdKey);
// System.out.println("WordReadGrpReader.readWordGrp DEBUG: (Date[])htIdToDates.get(strStaIdKey) = "+(Date[])htIdToDates.get(strStaIdKey));
wrg.addWordReads(strStaIdKey, (String[])htIdToWords.get(strStaIdKey),
(Date[])htIdToTimes.get(strStaIdKey));
// (Date[])htIdToDates.get(strStaIdKey));
}

//END: Add to WordReadGrp.
// return wrg;

return;
}

QCTst[] getQCTst(String strTstGrpNameQCT, int[] snAppliedQCT,
int[] snResultQCT, float[][] fEstErrorQCT)
{
QCTst[] qcTst = new QCTst[snAppliedQCT.length];

for(int i=0;i<snAppliedQCT.length;i++)
qcTst[i] = new QCTst(strTstGrpNameQCT, (short)snAppliedQCT[i],
(short)snResultQCT[i], fEstErrorQCT[i]);

return qcTst;
}

void fillQualityCtrlGrp(QualityCtrlGrp qcg,
String[] strIDs, String[] qcStatus, String[] qcSubjective,
QCTst qcTst[], TimeRange tr, Date obsTimes[])
{
String[] fMag = null;

Vector vfaMag = new Vector(10, 10);

Hashtable htIdToVecOfMag = new Hashtable();
Hashtable htIdToVecOfqcTst = new Hashtable();
Hashtable htIdToVecOfTime = new Hashtable();
Hashtable htIdToMags = new Hashtable();
Hashtable htIdToDirs = new Hashtable();
Hashtable htIdToTimes = new Hashtable();
Hashtable htIdToDates = new Hashtable();
String fa[] = new String[1];
QCTst faa[] = new QCTst[1];
Date fa3[] = new Date[1];
Vector vfa = null;

for(int i=0;i<qcStatus.length;i++)
{
if (qcStatus[i] == "Z")
qcStatus[i] = QualityCtrl._PRELIMINARY;
if (qcStatus[i] == "C")
qcStatus[i] = QualityCtrl._COARSEPASS;
if (qcStatus[i] == "S")
qcStatus[i] = QualityCtrl._SCREENED;
if (qcStatus[i] == "Q")
qcStatus[i] = QualityCtrl._QUESTIONABLE;
if (qcStatus[i] == "V")
qcStatus[i] = QualityCtrl._VERIFIED;
if (qcStatus[i] == "X")
qcStatus[i] = QualityCtrl._ERRONEOUS;
if (qcStatus[i] == "G")
qcStatus[i] = QualityCtrl._GOOD;
if (qcStatus[i] == "B")
qcStatus[i] = QualityCtrl._BAD;
}

//BEGIN: sort so the latest one is the first element in the vector.
for(int i=strIDs.length-1;i>=0;i--)
{
//BEGIN: sort Mag so the latest one is the first element in Vector.
Vector vfMag = (Vector)htIdToVecOfMag.get(strIDs[i]);
if(vfMag == null)
{
fa = new String[1];
fa[0] = qcStatus[i];
vfa = new Vector(4, 1);
vfa.addElement(fa);
htIdToVecOfMag.put(strIDs[i], vfa);
}
else
{
fa = new String[1];
fa[0] = qcStatus[i];
vfa = new Vector(4, 1);
vfMag.addElement(fa);
}
//END: sort Mag so the latest one is the first element in Vector.
//BEGIN: sort Dir so the latest one is the first element in Vector.
Vector vqcTst = (Vector)htIdToVecOfqcTst.get(strIDs[i]);
if(vqcTst == null)
{
faa = new QCTst[1];
faa[0] = qcTst[i];
vfa = new Vector(4, 1);
vfa.addElement(faa);
htIdToVecOfqcTst.put(strIDs[i], vfa);
}
else
{
faa = new QCTst[1];
faa[0] = qcTst[i];
vfa = new Vector(4, 1);
vqcTst.addElement(faa);
}
//END: sort Dir so the latest one is the first element in Vector.
//BEGIN: sort Time so the latest one is the first element in Vector.
Vector vTime = (Vector)htIdToVecOfTime.get(strIDs[i]);
if(vTime == null)
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vfa.addElement(fa3);
htIdToVecOfTime.put(strIDs[i], vfa);
}
else
{
fa3 = new Date[1];
fa3[0] = obsTimes[i];
vfa = new Vector(4, 1);
vTime.addElement(fa3);
}
//END: sort Mag so the latest one is the first element in Vector.
}
//END: sort so the latest one is the first element in the vector

//BEGIN: Convert Mag vectors to arrays.
Enumeration eKeys = htIdToVecOfMag.keys();
Vector vfMag = null;
String strCurKey = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vfMag = (Vector)htIdToVecOfMag.get(strCurKey);
fMag = new String[vfMag.size()];
for(int i=0;i<vfMag.size();i++)
fMag[i] = ((String[])(vfMag.elementAt(i)))[0];
htIdToMags.put(strCurKey, fMag);
}
//END: Convert Mag vectors to arrays.

//BEGIN: Convert Dir vectors to arrays.
eKeys = htIdToVecOfqcTst.keys();
Vector vqcTst = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vqcTst = (Vector)htIdToVecOfqcTst.get(strCurKey);
qcTst = new QCTst[vqcTst.size()];
for(int i=0;i<vqcTst.size();i++)
{
qcTst[i] = ((QCTst[])(vqcTst.elementAt(i)))[0];
}
htIdToDirs.put(strCurKey, qcTst);
}
//END: Convert Dir vectors to arrays.

//BEGIN: Convert Time vectors to arrays.
eKeys = htIdToVecOfTime.keys();
Vector vTime = null;
Date[] time = null;
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
vTime = (Vector)htIdToVecOfTime.get(strCurKey);
time = new Date[vTime.size()];
for(int i=0;i<vTime.size();i++)
time[i] = ((Date[])(vTime.elementAt(i)))[0];
int j=time.length-1;
for(int i=0; i < j; i++)
{
Date dt = time[i];
time[i] = time[j];
time[j] = dt;
j--;
}

htIdToTimes.put(strCurKey, time);
}
//END: Convert Time vectors to arrays.

/* //BEGIN: Estimate Times so the latest one is the first element in vec.
int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToMags.keys();
while(eKeys.hasMoreElements())
{
fMag = (String [])htIdToMags.get((String)(eKeys.nextElement()));
nNumTimes = fMag.length;
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.startTime().getTime();
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.
*/

//////////
//BEGIN: Estimate Times so the latest one is the first element in vec.

int nNumTimes = 0;
long lnStartTm = 0L;
long lnEndTm = 0L;
long lnIncTm = 0L;
long lnTm = 0L;
Date[] dtDates = null;

eKeys = htIdToMags.keys();
lnStartTm = tr.startTime().getTime();
lnEndTm = tr.endTime().getTime();
while(eKeys.hasMoreElements())
{
strCurKey = (String)(eKeys.nextElement());
fMag = (String [])htIdToMags.get(strCurKey);
nNumTimes = fMag.length;
lnIncTm = Math.round(((double)(lnEndTm - lnStartTm)) / ((double)(nNumTimes - 1)));
dtDates = new Date[nNumTimes];
for(int i=nNumTimes-1;i>=0;i--)
{
lnTm = lnStartTm + i * lnIncTm;
if(lnTm > lnEndTm)
lnTm = lnEndTm;
else if(lnTm < lnStartTm)
lnTm = lnStartTm;
dtDates[i]= new Date(lnTm);
}
htIdToDates.put(strCurKey, dtDates);
}
//END: Estimate Times so the latest one is the first element in vec.
//////////

//BEGIN: Add to VecReadGrp.
eKeys = htIdToMags.keys();
String strStaIdKey = null;
while(eKeys.hasMoreElements())
{
strStaIdKey = (String)(eKeys.nextElement());
qcg.addQualityCtrls(strStaIdKey,
(String[])htIdToMags.get(strStaIdKey),
(QCTst[])htIdToDirs.get(strStaIdKey),
(Date[])htIdToTimes.get(strStaIdKey));
// (Date[])htIdToDates.get(strStaIdKey));
}

return;
}

private synchronized void purgeOldAlerts(Date currentTime)
{
Enumeration keys = _index.keys();
while (keys.hasMoreElements())
{
ParmInfo key = (ParmInfo)keys.nextElement();
if(key.name().indexOf("text") >= 0)
{
DataAvail da = (DataAvail) _index.get((Object)key);
DataInfo[] di = da.getDIArray();
if (di[0].getTimeRange().endTime().getTime()
< currentTime.getTime())
{
try
{
File file = new File(da.getDataInfo(0).getFileName());
String name = file.getName();
String filename = _dataPath + _fileSep + name;
file = new File(filename);

file.delete();
_index.remove(key);
}
catch (Exception e)
{
System.out.println("EXCEPTION IN purgeOldAlerts: ");
e.printStackTrace();
}
}
}
}

return;
}

private static final String IFILENAME = new String("INDEX.dat");
private static final String TIMEFILENAME = new String("INDEXTS.dat");
private static Hashtable _index = initIndex();
protected static String _dataPath;

protected static char _fileSep;

private static int _maxMsgNum = 12;
}


Adding a New Component Painter Software Module to the Client:

The Menu's integrate in software modules at runtime. The main requirements on these software modules are that they implement the "display/CompPainterIF.java" and the "ifp/data/DataPoolListener.java" interfaces. Default behavior is facilitated through the use of skeleton classes which can be inserted in the class hierarchy, (See "display/SK*.java"). Implement a new component painter software module which provides services to the Display and registers to get data from the datapool. For a prototype use CPRadar.java. If there is data which must be shared between several component painters, then follow the observation station component painter model with the view controller. See also Software Module's Application Programming Interface

See the graphical-user-interface/client software architecture overview in:

Steffen, C. E, and C. Subramaniam, "Weather Data Fusion Application Implemented in Java", Conference on Imaging Science, Systems, and Technology (CISST 2000), Las Vegas, NV, June 26-29, 2000.

Text: Configuring maximum expiration time

Start LDAD at least once to have the AlertReader software create a default "ls:/ldad/bin/maxExpired.conf" file. Edit the maximum number of milliseconds to retain a text message of a particular type before deleting the text message. Default value is two days.

Enabling Graphical Forecast Editor (GFE) dissemination.

To get the GFE output data to be ingested into the EMDS, the following must be done.

Step 1)

Create the directory "ds:/data/fxa/LDAD/ifp/Official/".
Create the directory "ls:/data/ldad/public/Grid/ifp/Official".

Setup the purger to purge these directories. ( Probably a cron job)

Step 2)

If "ds:~ldad/data/pollForData.conf" and "ls:/ldad/data/pollForData.conf" are identical and contain the line:

# IFP Grids
FSL|model:ifp:Official:national|/data/fxa/LDAD/ifp/Official|-1|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/ifp/Official

The "-1" in the fourth field means the pollForData.pl program will copy them to the ls about 30 sec after they are published.

Step 3)

Determine the projection and corners of the projection (in latitude/longitude) used by the Graphical Forecast Editor, GFE, to generate gridded products to be published.

The Graphical Forecast Editor stores default projection information in the "serverConfig.py" file which can be overridden by projection information in the "localConfig.py" file. See the GFE documentation in "serverConfig.html".

The serverConfig.py (Use localConfig.py if you modified the GFE projection) default format is:
#---------------------------------------------------------------------------
# Grid Domain configuration section
# xdim/ydim: Defines the dimensions of the grids. (GFE grid size)
# origin: Defines the lower-left corner of the grid (point 0,0) in
# world coordinates.
# extent: Defines the "size" of the grid in world coordinates. The upper
# right corner is the origin+extent.
# TimeZone: Defines the timezone used by this site in standard TZ format.
# Projection: Defines the projection identifier to be used for this domain.
# Note that all parameters for an existing database must use the same
# projection, though not necessarily the same grid size and location.
# These values are set up for AWIPS. There is a script at the end
# of this section that adjusts the resolution for the RPP sites.
# [xdim, ydim] / (origin) /( extent) / TimeZone / Projection
SITES = {
'TSA' : ([145, 145], (48.00, 22.00), (9.0, 9.0), 'CST6CDT', Grid211),

.

.

.

We notice that Tulsa OK (TSA) uses Grid211 (Sometimes called CONUS211) as the projection. Also, the corners are specified in AWIPS coordinates as (48.00, 22.00) for the origin and (9.0, 9.0) for the extent. The origin is the south west corner and adding the extent coordinates to the origin generates the other three corners. The GFE comes with a coordinate conversion routine which converts the AWIPS coord to/from latitude/longitude. See the GFE documentation in "coordConversion.html".

For example, in Tulsa OK (TSA) the default projection converts as:
This means the origin (SouthWest corner) is:
48.00, 22.00 in AWIPS coord
Should convert to: -99.307 E Longitude, 32.777 N Latitude

This means the (NorthWest corner) is:
48.00, 31.00 in AWIPS coord
Because 22.00 + 9.0 = 31.00
Should convert to: -99.568 E Longitude, 39.223 N Latitude

This means the (NorthEast corner) is:
57.00, 31.00 in AWIPS coord
Because 22.00 + 9.0 = 31.00
Because 48.00 + 9.0 = 57.00
Should convert to: -91.346 E Longitude, 39.244 N Latitude

This means the (SouthEast corner) is:
57.00, 22.00 in AWIPS coord
Because 48.00 + 9.0 = 57.00
Should convert to: -91.555 E Longitude, 32.798 N Latitude

Once the corners are converted, update the EMDS "Local Forecast" projection per the instructions in: "LDADIngestManual.html#Analysis Grid"
Notice that some of the common projections have slightly different names. (ie. Grid211 ~ CONUS211) The "Local Forecast" projection is in "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/wkspace/Xtensibl.frm". (Note: The original Xtensibl.frm with comments containing common projections is at "ls:/data/ldad/emwww/htdocs/wkspace/Xtensibl.frm")It must be modified to reflect the projection the data is supplied in. (Alternatively, you could update the tables in "ls:/ldad/classes/hmserve/ingest/IFPDomains.table" and rerun the localizeWWW.pl script.)

Select a common projection (CONUS211) and modify the corners to match your GFE area.

Note: If you want to add more projections to the EMDS you must add the _REGION definitions in "Xtensibl.frm". Add the Scale menus in "Graphic.mnu" and set the "grayed out tag" for products you want enabled for that projection.


Step 4)

You will also have to reclip the local shapefile maps located in "ls:/data/ldad/mapdata/usa/" maps to the GFE "Local Forecast" projection corners and save them to "ls:/data/ldad/emwww/htdocs/localizations/<siteId>/mapdata/". (Note: Two maps are clipped to the national scale and should not be reclipped to the "Local Forecast" scale. See Example below. To do this you may either use the client desktop application called MapClipper or a script which calls: "java -mx54536000 ldadapp.map.MapClipper" with the parameters:

/**
* Used to clip and store map data as a compressed (gzip) serialized class.
* Command line arguements
* @param args[0] = strShapefileName; The Shapefile Name without the suffix.
* @param args[1] = boClipped; "clip" means the shape files are clipped.
* @param args[2] = UpperLeft X value in Longitude.
* @param args[3] = UpperLeft Y value in Lattitude.
* @param args[4] = UpperRight X value in Longitude.
* @param args[5] = UpperRight Y value in Lattitude.
* @param args[6] = LowerLeft X value in Longitude.
* @param args[7] = LowerLeft Y value in Lattitude.
* @param args[8] = LowerRight X value in Longitude.
* @param args[9] = LowerRight Y value in Lattitude.
* @param args[10] = siteId = three character siteId.
*/
For Example:

REM MAPS TO CLIP to the NATIONAL SCALE/////////////////////////////////////////////////////////////////////
java -mx54536000 ldadapp.map.MapClipper northamerica_001 Clip -152.856 49.500 -49.385 49.500 -133.459 12.190 -65.091 14.335 WFO
java -mx54536000 ldadapp.map.MapClipper wforfc_us Clip -152.856 49.500 -49.385 49.500 -133.459 12.190 -65.091 14.335 WFO
REM LAPS CLIPPING FOR LOCAL COLORADO AREA /////////////////////////////////////////////////////////////////////
java -mx54536000 ldadapp.map.MapClipper cities_us Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx54536000 ldadapp.map.MapClipper cous_0005 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx65536000 ldadapp.map.MapClipper hwy_us_001 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx54536000 ldadapp.map.MapClipper mzus_001 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx54536000 ldadapp.map.MapClipper rivers_us_001 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx54536000 ldadapp.map.MapClipper roads_us_001 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO
java -mx54536000 ldadapp.map.MapClipper wzus_001 Clip -107.8875 41.9901 -100.70689 42.407955 -107.74974 37.022182 -101.0305 36.56353 WFO

Step 5)

To enable and disable EMDS dissemination of individual GFE products, set the third field equal to "yes" or "no" in "ls:/ldad/classes/hmserve/ingest/ParmToIFP.table". Stop and restart LDAD on ds1 to read the new table.

Step 6)

Update the "Local Forecast" menu items in two menus: 1) Graphic.mnu and 2) Probe.mnu.

Note that the hmingest process breaks the GFE file up into products which are further subdivided into files containing 12 grids apiece.

After the products are generated do a:

login to the "ls" computer.

ls /data/ldad/public/javadata/model-ifpOfficial*

to determine the names of the available GFE products. Add one menuitem per product.

Step 7)

Verify that the GFE Menu selection "Products->Generate Products->Official Grids to LDAD" radio button is selected and publish the data. Verify the correct gziped ASCII grids without the "gz" suffix are copied to the "ds:/data/fxa/LDAD/ifp/Official/<date>" file. Where date is similiar to the dates used in other gridded products. The EMDS hmingest process should begin processing the GFE Official grids about 30 seconds after they are published. View the hmingest logs at: "ls:/data/logs/ldad/<Date>/hm*" to verify the GFE data is being read.

Then the data should be ingested to the EMDS.
It will be copied to "ls:/data/ldad/public/Grid/ifp/Official"
It will be copied to "ls:/data/ldad/public/javadata/model-ifpOfficial*"

Note: The pollForData.pl keys off of the time stamp in the filename so you may manually trigger the data by changing the filename date to a newer filename date.

Adding Dynamic Data Exercises:


Testing Dynamic Data:

Start the EMDS application/applet and select the menu item associated with the data. Verify that the data behaves as expected.

Removing Dynamic Data:

Comment out the line in PollForData.cnf corresponding to the data to be removed from being ingested.

Troubleshooting Dynamic Data:

Data Flow Troubleshooting:

Symptom: Text is not displayable in the EMDS Client Graphical User Interface.

Solution:

1) Login as "ldad" on DS1, use "textdb -r PIF" to verify the text message is in the Informix database.

For example, "textdb -r DENNOWDEN".

If it is not in the text database then edit "ldadTriggers.template" and rerun the installation of the Informix database triggers.

See the ldadSMM.html (LDAD System Managers Manual).

Example lines:

wwwSPSww1 | | | /awips/fxa/ldad/bin/textdbNotify.pl statement |

wwwTORww1 | | | /awips/fxa/ldad/bin/textdbNotify.pl warning |

2) If the message is in the text database then fire another message of the same type. Login as "ldad" on DS1, use "textdb -w PIF < DENTORDEN.txt". Where DENTORDEN.txt is a text message with body stating "TEST ONLY".

Example: "textdb -w DENTORDEN < DENTORDEN.txt".

3) Verify that the DENTORDEN.txt message is copied to the directory "ds:

4) Verify that the "ls:/data/logs/ldad/<date>/hmingst*" logs state that the DENTORDEN.txt message has been successfully processed.

5) Monitor the "ls:/data/ldad/hmIngest/" directory and see if a filename with the DENTORDEN string embedded in it appears and then is deleted.

6) Verify that the "ls:/data/ldad/public/javadata/*" directory contains a filename with the DENTORDEN string embedded in it.

7) Verify that the "ls:/data/ldad/public/nwswwas/*" directory contains queue with the filenames DENTORDEN1.txt to DENTORDEN10.txt embedded in them. The DENTORDEN1.txt contains the latest message.

8) Verify the "ls:/data/ldad/emwww/htdocs/data/" directory is soft linked to the "ls:/data/ldad/public/javadata/" directory.

9) The "hmingestd" reads the raw data on the LS1 computer, converts it, copies it into "/data/ldad/public/javadata", and updates both the INDEXTS.dat (index time stamp file) and INDEX.dat files. Verify that the index files have been updated.

10) Use ReadIndex.java to view the contents of the INDEX.dat file in "ls:/data/ldad/public/javadata/" and verify that there is an entry with DENTORDEN embedded in it.

11) Use ScreenDump.java to read the contents of the compressed text message in "ls:/data/ldad/public/javadata/" and verify that all none expired text messages remain in the file.

12) Start up the Menu Configurator in "Web Site Administrator" Mode.

13) View the Text.mnu.

14) Expand the Tree view until the menu item selected is visible.

15) Select the menu item.

16) Verify that the menu item is black. Next verify the Software module's Parm 2 contains the DENTORDEN name in the proper places. (See Menu Configurator documentation)

Symptom: Non-text data is not displayable in the EMDS Client Graphical User Interface.

Solution:

1) Verify the data exists on the ds computer.

Verify the specified data is arriving in the following directories listed in the "ds:~ldad/data/pollForData.conf"

The pollForData.conf file contains "|" delimited fields. the third field indicates the directory the data is stored in on the ds computer.

For Example:

# LAPS Analysis
FSL|model:laps:local|/data/fxa/Grid/FSL/netCDF/LAPS_Grid/LAPS|30,35,40|/awips/ldad/bin/sendLDADnotification.pl|R "KKK FFF" HHH PPP|/data/ldad/public/Grid/LAPS

The third field is "/data/fxa/Grid/FSL/netCDF/LAPS_Grid/LAPS" which means the data is at "ds:/data/fxa/Grid/FSL/netCDF/LAPS_Grid/LAPS".

2) Change the time stamp filename of the netcdf file on the "ds" computer to get the pollForData.pl routine to copy over the new data. Note that pollForData.pl will only check for new files based on the entry in the fourth field of pollForData.conf.

For Example:

The fourth field in step one is "30,35,40" which means pollForData checks for new data at 30, 35, and 40 minutes past the hour. (ie. If the hour is 1:00PM, then pollForData.pl checks at 1:30PM, 1:35PM, and 1:40PM.)

3) After the designated time verify that pollForData has copied the file to the directory on the ls computer which is described by the seventh field of pollForData.conf.

For Example:

The seventh field in step one is "/data/ldad/public/Grid/LAPS" which means that pollForData copies the data from the ds computer to the ls computer at "ls:/data/ldad/public/Grid/LAPS".

4) Verify that the "ls:/data/logs/ldad/<date>/hmingst*" logs state that the data has been successfully processed.

5) Monitor the "ls:/data/ldad/hmIngest/" directory and see if a filename with the appropriate data name appears and then is deleted.

6) Verify that the "ls:/data/ldad/public/javadata/*" directory contains a filename with the appropriate data name.

7) Verify the "ls:/data/ldad/emwww/htdocs/data/" directory is soft linked to the "ls:/data/ldad/public/javadata/" directory.

8) The "hmingestd" reads the raw data on the LS1 computer, converts it, copies it into "/data/ldad/public/javadata", and updates both the INDEXTS.dat (index time stamp file) and INDEX.dat files. Verify that the index files have been updated.

9) Use ReadIndex.java to view the contents of the INDEX.dat file in "ls:/data/ldad/public/javadata/" and verify that there is an entry with DENTORDEN embedded in it.

10) Use ScreenDump.java to read the contents of the compressed text message in "ls:/data/ldad/public/javadata/" and verify that all none expired text messages remain in the file.

11) Start up the Menu Configurator in "Web Site Administrator" Mode.

12) View the appropriate menu.

13) Expand the Tree view until the menu item selected is visible.

14) Select the menu item.

15) Verify that the menu item is black. Next verify the Software module's Parm 2 contains the appropriate data names in the proper places. (See Menu Configurator documentation)

Symptom: If the problem is that the EMDS menu items are disabled (grayed out).

Solution: Copy the contents of "/data/ldad/emwww/htdocs/data" to "C:\Program Files\EMDS\data" and, when it asks for a web site, set the field to blank and hit OK to select the data on the local disk drive. Determine if the data is displayable by selecting the associated menu items.

Reading the INDEX.dat File

(1) Build the ReadIndex.java into a class file. (ie. "javac ReadIndex.java" where javac.exe is the java compiler which comes with the Java Development Kit version 1.1.7B, JDK1.1.7B, or above). Then run it using:

"java -mx65536000 -ms55000000 ReadIndex INDEX.dat".
//ReadIndex.java

import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Stack;
import java.util.Enumeration;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.io.ObjectInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import ifp.data.*;
//F>=========================================================================
// ReadIndex.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
/**
* A ReadIndex is the main class that dumps the contents of the INDEX.dat
*
* The <a href="ReadIndex.java">Source</a>
* @author Leigh Angus
* @author $Author: steffen $
* @version $Revision: 1.13 $
* @since $Date: 2001/07/13 23:03:40 $
*
*/
class ReadIndex
{
public static void main(String args[])
{
// String indexFile = new String("/data/ldad/public/lapsjava/data/INDEX.dat");
String indexFile = args[0];

Hashtable hash = null;
try
{
hash = (Hashtable)fetchIndex(indexFile);
}
catch (IOException ioe)
{
System.out.println("IOException...");
}

// Show what we got.
Enumeration keys = hash.keys();
while (keys.hasMoreElements())
{
ParmInfo key = (ParmInfo)keys.nextElement();
String name = (String) hash.get((Object)key);
System.out.println(key.name() + " " + name);
}

}

private static Object fetchIndex(String fileName) throws IOException
{
Hashtable index = new Hashtable();
try
{
FileInputStream fis = new FileInputStream(fileName);
GZIPInputStream zis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(zis);
index = (Hashtable)ois.readObject();
}
catch (FileNotFoundException e)
{
System.out.println("fetchIndex.FileNotFoundException");
e.printStackTrace();
index = new Hashtable();
}
catch (IOException e)
{
e.printStackTrace();
index = new Hashtable();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
index = new Hashtable();
}
return index;
}

}

Reading Compressed Radar, Grid, and Text data files:

(1) Build the ScreenDump.java into a class file. (ie. "javac ScreenDump.java" where javac.exe is the java compiler which comes with the Java Development Kit version 1.1.7B, JDK1.1.7B, or above). Then copy the data to the same directory and run it using:

"java -mx65536000 -ms55000000 ScreenDump radar-Reflectivity-local-990908200755484.dat"

"java -mx65536000 -ms55000000 ScreenDump model-laps-TempAir-local-990928232939137.dat"

"java -mx65536000 -ms55000000 ScreenDump nwstext-warning-DENTORDEN-local.dat"

//ScreenDump.java
import java.io.FileNotFoundException;
import java.lang.NumberFormatException;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import ldadapp.data.PolarGrid;
import ifp.data.ScalarGrid;
import ldadapp.text.Alert;
import ifp.data.Parm;
import ldadapp.data.Data;
import ldadapp.text.UGC;
import ldadapp.text.LATLON;
//F>=========================================================================
// ScrnDump.java
// RCS: $Revision: 1.13 $ $Date: 2001/07/13 23:03:40 $ $Author: steffen $
//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================
/**
* A ScrnDump is the main class that dumps the contents of three types
* of serialized objects to the screen.
*
* <applet code="display.ScrnDump.class" width=300 height=330>
* </applet>
*
* The <a href="ScrnDump.java">Source</a>
* @author Chris Steffen
* @author $Author: steffen $
* @version $Revision: 1.13 $
* @since $Date: 2001/07/13 23:03:40 $
*
*/


//===========================================================================
// Main Class for applet ScrnDump
//
//===========================================================================

public class ScrnDump
{

public ScrnDump()
{
super();
}



/**
* Used to clip and store map data as a compressed (gzip) serialized class.
* Command line arguements
* @param args[0] = strFileName; The Shapefile Name without the suffix.
* @param args[1] = strFileType; Grid, Radar, Text.
*/
public static void main(String args[])
{
ScrnDump scrnDmp = new ScrnDump();
String strFileName = args[0];
System.out.println("strFileName = "+strFileName);

Object obj = null;
try {
FileInputStream fis = new FileInputStream(strFileName);
GZIPInputStream zis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(zis);
obj = (Object)ois.readObject();
ois.close();
ois = null;
zis.close();
zis = null;
fis.close();
fis = null;
}
catch(ClassNotFoundException cnfe)
{
System.out.println("ScrnDump.main() 98"
+" \nstrFileName = "+strFileName
+", \nClassNotFoundException = "+cnfe.toString());
cnfe.printStackTrace();
// System.exit(-1);
}
catch(FileNotFoundException fnfe)
{
System.out.println("ScrnDump.main() 98"
+" \nstrFileName = "+strFileName
+", \nFileNotFoundException = "+fnfe.toString());
fnfe.printStackTrace();
// System.exit(-1);
}
catch(IOException io)
{
System.out.println("ScrnDump.main() 90"
+" \nstrFileName = "+strFileName
+", \n\nIOException = "+io.toString());
io.printStackTrace();
}

System.out.println("obj = "+obj);
Parm p = null;
if(obj != null)
{
p = (Parm)obj;
}
System.out.println("parm = "+p);
Data dat = null;
if(p != null)
{
for(int i=0;i<p.getDataSize();i++)
{
dat = p.getData(i);
// System.out.println("dat = "+dat);
if(dat != null)
{
if(dat instanceof PolarGrid)
{
scrnDmp.printPolarGrid((PolarGrid)dat);
}
else if(dat instanceof Alert)
{
scrnDmp.printAlert((Alert)dat);
}
else if(dat instanceof ScalarGrid)
{
scrnDmp.printGrid((ScalarGrid)dat);
}
}
}
}
}


/**
* printPolarGrid print the variables of the compressed (gzip)
* serialized class.
*/
public void printPolarGrid(PolarGrid pg)
{
System.out.println("pg.getFullName() = " +pg.getFullName());
System.out.println("pg.getAbbrName() = " +pg.getAbbrName());
System.out.println("pg.getUnits() = " +pg.getUnits());
System.out.println("pg.getFileDate() = " +pg.getFileDate());
System.out.println("pg.getFileID() = " +pg.getFileID());
System.out.println("pg.getParent() = " +pg.getParent());

System.out.println("pg.isRunGrid() = "+pg.isRunGrid());
System.out.println("pg.getCenXLon() = "+pg.getCenXLon()+" deg");
System.out.println("pg.getCenYLat() = "+pg.getCenYLat()+" deg");
System.out.println("pg.getRadius() = "+pg.getRadius()+" km");
System.out.println("pg.getRBinRadius() = "+pg.getRBinRadius()+" range bins");
System.out.println("pg.getKmPerRBin() = "+pg.getKmPerRBin()+" km per range bin");
System.out.println("\n\n\n");

System.out.println("RdlAng = Angle from due north giving the starting side of the range bin.");
for(int i=0;i<pg.getRdlAngsSize();i++)
{
System.out.println("pg.getRdlAngs("+i+") = "+pg.getRdlAngs(i));
}
System.out.println("\n\n\n");

System.out.println("DeltaAng = Angle added to RdlAng to get other side of the range bin.");
for(int i=0;i<pg.getDeltaAngSize();i++)
{
System.out.println("pg.getDeltaAng("+i+") = "+pg.getDeltaAng(i));
}
System.out.println("\n\n\n");

System.out.println("RunValue = run of range bins of the same color. 0 - 15");
System.out.println("Value = color of the run. 0 - 15");
for(int i=0;i<pg.getXGridSize();i++)
{
for(int j=0;j<pg.getYGridSize(i);j++)
{
System.out.println("pg.getRunValue("+i+", "+j+") = "
+pg.getRunValue(i, j)+", pg.getValue("+i+", "+j+") = "
+pg.getValue(i, j));
// System.out.println("pg.getRunValue("+i+", "+j+") = "
// +(((int)pg.getRunValue(i, j)) & 0x000F)+", pg.getValue("+i+", "+j+") = "
// +pg.getValue(i, j));
}
System.out.println("\n\n\n");
}

for(int i=0;i<pg.getValMapSize();i++)
{
System.out.println("pg.getValMap("+i+") = "+pg.getValMap(i));
}
System.out.println("\n\n\n");

for(int i=0;i<pg.getValModSize();i++)
{
System.out.println("pg.getValMod("+i+") = "+pg.getValMod(i));
}
System.out.println("\n\n\n");


}
/**
* printAlert print the variables of the compressed (gzip)
* serialized class.
*/
public void printAlert(Alert alrt)
{
System.out.println("alrt.getFullName() = " +alrt.getFullName());
System.out.println("alrt.getAbbrName() = " +alrt.getAbbrName());
System.out.println("alrt.getUnits() = " +alrt.getUnits());
System.out.println("alrt.getFileDate() = " +alrt.getFileDate());
System.out.println("alrt.getFileID() = " +alrt.getFileID());
System.out.println("alrt.getParent() = " +alrt.getParent());

System.out.println("alrt.getAlertID() = "+alrt.getAlertID());
System.out.println("alrt.isNoExpired() = "+alrt.isNoExpired());
System.out.println("alrt.getFillColor() = "+alrt.getFillColor());

for(int i=0;i<alrt.getTextSize();i++)
{
System.out.println("Print Message: "+i);
for(int j=0;j<alrt.getText(i).size();j++)
{
System.out.println("Msg: "+i+", Line: "+j+", "
+((String)(alrt.getText(i).elementAt(j))));
}
System.out.println("");
if(alrt.getVTEC(i) != null)
System.out.println("alrt.getVTEC("+i+") = "+alrt.getVTEC(i));
UGC ugc = null;
if(alrt.getUGC(i) != null)
{
ugc = alrt.getUGC(i);
System.out.println("alrt.getUGC("+i+").getEndDayUTC() = "+ugc.getEndDayUTC());
System.out.println("alrt.getUGC("+i+").getEndHourUTC() = "+ugc.getEndHourUTC());
System.out.println("alrt.getUGC("+i+").getEndMinuteUTC() = "+ugc.getEndMinuteUTC());
System.out.println("alrt.getUGC("+i+").isParsable() = "+ugc.isParsable());

System.out.println("alrt.getUGC("+i+").getNumStates() = "+ugc.getNumStates());
for(int k=0;k<ugc.getNumStates();k++)
{
System.out.println("alrt.getUGC("+i+").getStateAbbr("+k+") = "+ugc.getStateAbbr(k));
System.out.println("alrt.getUGC("+i+").isCountyMap("+k+") = "+ugc.isCountyMap(k));
System.out.println("alrt.getUGC("+i+").isZoneMap("+k+") = "+ugc.isZoneMap(k));

System.out.println("alrt.getUGC("+i+").getNumPolyIDs("+k+") = "+ugc.getNumPolyIDs(k));
for(int q=0;q<ugc.getNumPolyStates();q++)
System.out.println("alrt.getUGC("+i+").getPolyIDs("+k+", "+q+") = "+ugc.getPolyIDs(k, q));
}
}

LATLON ll = null;
if(alrt.getLATLON(i) != null)
{
ll = alrt.getLATLON(i);
System.out.println("alrt.getLATLON("+i+").getLATLON() = "+ll.getLATLON());
System.out.println("alrt.getLATLON("+i+").getPolyLATLON() = "+ll.getPolyLATLON());
System.out.println("alrt.getLATLON("+i+").getPolyScaleFactor() = "+ll.getPolyScaleFactor());
}
System.out.println("alrt.getExprTime("+i+") = "+alrt.getExprTime(i));
System.out.println("alrt.isMaxExpired("+i+") = "+alrt.isMaxExpired(i));
}
System.out.println("\n\n\n");
}
/**
* printPolarGrid print the variables of the compressed (gzip)
* serialized class.
*/
public void printGrid(ScalarGrid grd)
{
System.out.println("grd.getFullName() = " +grd.getFullName());
System.out.println("grd.getAbbrName() = " +grd.getAbbrName());
System.out.println("grd.getUnits() = " +grd.getUnits());
System.out.println("grd.getFileDate() = " +grd.getFileDate());
System.out.println("grd.getFileID() = " +grd.getFileID());
System.out.println("grd.getParent() = " +grd.getParent());



System.out.println("grd.name() = " +grd.name());
System.out.println("grd.xDim() = " +grd.xDim());
System.out.println("grd.yDim() = " +grd.yDim());

System.out.println("grd.parmInfo().toString() = " +grd.parmInfo().toString());

System.out.println("grd.timeRange().toString() = " +grd.timeRange().toString());

float [][] fdata = grd.data();
for(int i=0;i<fdata.length;i++)
{
for(int j=0;j<fdata[i].length;j++)
{
System.out.println("fdata["+i+"]["+j+"] = " +fdata[i][j]);
}
}
}
}

Software Module's Application Programming Interface (API)

By Christopher E. Steffen 1/17/01

Introduction:

The following tutorial will familiarize you with the software module application programming interface by describing the steps which should be taken in adding a module. The software modules described here are the same as the software module which are merged into the menus via the EMDS MenuConfigurator. After becoming familiar with a few simple examples, the interfaces and skeleton will be described. Please don't modify the source code if the same thing can be accomplished by copying the source code into a file of another name, editing the new file, and integrating the file into the application via the Menu Configurator as a software module.

The source code is included in the website distribution at "ls:/ldad/webDissemSrc" since it is desirable for the Weather Forecast Offices to be able to extend the capabilities of the EMDS system. Please submit all changes back to the Forecast Systems Laboratory for review and possible incorporation into the standard release. This will allow all Weather Forecast Offices to benefit from your work and reduce the number of patches you must maintain. The source code is organized into packages under webDissemSrc. In order to compile the source code, you may have to retrieve the ptolemy.plot.jar, JGrid.jar, symantec.jar, and Base64Convert.jar from the website and expand them under webDissemSrc. To create a simple makefile to compile all of the code, create a class which imports every class and compile it. The java compiler will then compile each class incrementally as needed.


Example 1: Basic Hello World Software Module (Component Painter)

Assignment: Paint Hello World in different colors at several points on the screen.

Create a file named:

"/data/ldad/emwww/htdocs/bou/hello/CPHelloWorld.java"

Cut and paste the following code into the new file.



//BEGIN CODE ***************************************************


// CPHelloWorld1.java


package bou.hello;
//Import statements:
import display.SKCPObject;
import display.PaintOnMeEvent;
import java.awt.Color;
public class CPHelloWorld1 extends SKCPObject
    {
    public void paintOnMe(PaintOnMeEvent pome)
        {
        if((pome == null) || (pome.g == null))
            return;
        pome.g.drawString(_strHelloWorld, 100, 100);
        pome.g.setColor(Color.green);
        pome.g.drawString(_strHelloWorld, 200, 200);
        pome.g.setColor(Color.red);
        pome.g.drawString(_strHelloWorld, 300, 300);
        }
    private String _strHelloWorld = "Hello World";
    }



// END CODE ***************************************************


Assuming your PATH is set to find the java compiler, compile the code as follows:

"javac /data/ldad/emwww/htdocs/bou/hello/CPHelloWorld.java"
This will create a file: "/data/ldad/emwww/htdocs/bou/hello/CPHelloWorld.class"

Link the software module to the EMDS using the EMDS Menu Configurator.

Module Initialization Section

Software Module = "bou.hello.CPHelloWorld"

Module Parameter 1 = "null"

Module Parameter 2 = "null"

Update the syncFiles.txt to download "/data/ldad/emwww/htdocs/bou/hello/CPHelloWorld.class".

#BEGIN: syncFiles.txt

#This file is the config file for auto syncing of the webSite and your local system.

#Please do not change this file. This could cause your system to become unstable.

#logs/aaa.txtlocalizations/iii/mapdata/cities_us.dbfm.gzip

localizations/iii/mapdata/cities_us.shpm.gzip

localizations/iii/mapdata/cous_0005.dbfm.gzip

localizations/iii/mapdata/cous_0005.shpm.gzip

localizations/iii/mapdata/hwy_us_001.dbfm.gzip

localizations/iii/mapdata/hwy_us_001.shpm.gzip

localizations/iii/mapdata/mzus_001.dbfm.gzip

localizations/iii/mapdata/mzus_001.shpm.gzip

localizations/iii/mapdata/northamerica_001.dbfm.gzip

localizations/iii/mapdata/northamerica_001.shpm.gzip

localizations/iii/mapdata/obs-hydro-station-local.gzip

localizations/iii/mapdata/obs-manual-station-local.gzip

localizations/iii/mapdata/obs-metar-station-national.gzip

localizations/iii/mapdata/obs-qcmesonet-station-local.gzip

localizations/iii/mapdata/riverBasins_us.dbfm.gzip

localizations/iii/mapdata/riverBasins_us.shpm.gzip

localizations/iii/mapdata/rivers_us_001.dbfm.gzip

localizations/iii/mapdata/rivers_us_001.shpm.gzip

localizations/iii/mapdata/roads_us_001.dbfm.gzip

localizations/iii/mapdata/roads_us_001.shpm.gzip

localizations/iii/mapdata/wforfc_us.dbfm.gzip

localizations/iii/mapdata/wforfc_us.shpm.gzip

localizations/iii/mapdata/wzus_001.dbfm.gzip

localizations/iii/mapdata/wzus_001.shpm.gzip

localizations/iii/imagedata/Topogr_us.gif

imagedata/icons/0.125.gif

imagedata/icons/0.25.gif

imagedata/icons/0.5.gif

imagedata/icons/1.gif

imagedata/icons/2.gif

imagedata/icons/20.gif

imagedata/icons/5.gif

imagedata/icons/Frzrain.gif

imagedata/icons/Hail.gif

imagedata/icons/Rain.gif

imagedata/icons/Sleet.gif

imagedata/icons/Snow.gif

imagedata/icons/cs_nws16.jpg

imagedata/icons/cs_noaa16.jpg

imagedata/icons/ldad.jpg

ldadhelp/hlp1hrain.html

ldadhelp/hlp1hsnow.html

ldadhelp/hlp3hrain.html

ldadhelp/hlp6hrain.html

ldadhelp/hlpDewpt.html

ldadhelp/hlpFire.html

ldadhelp/hlpGeography.html

ldadhelp/hlpIntro.htm

ldadhelp/hlpLanduse.htm

ldadhelp/hlpPrectype.htm

ldadhelp/hlpProbe.htm

ldadhelp/hlpRadar.htm

ldadhelp/hlpRhum.htm

ldadhelp/hlpScales.htm

ldadhelp/hlpSnowcov.htm

ldadhelp/hlpSoilm.htm

ldadhelp/hlpTemp.htm

ldadhelp/hlpTopo.htm

ldadhelp/hlpTotrain.htm

ldadhelp/hlpTotsnow.htm

ldadhelp/hlpVis.htm

ldadhelp/hlpWchill.htm

ldadhelp/hlpWind.htm

ldadhelp/hlpWxImg.htm

ldadhelp/hlpWxOvly.htm

ldadhelp/user1.html

ldadhelp/user2.html

ldadhelp/user3.html

ldadhelp/user3a.html

ldadhelp/user4.html

ldadhelp/EMDSUsersGuide.html

ldadhelp/MenuEditor.html

ldadhelp/Check.gif

ldadhelp/aboutFsl.gif

ldadhelp/aboutLdad.gif

ldadhelp/annotatedImage.gif

ldadhelp/changeAnimTimeWindow.gif

ldadhelp/changeDelayBetweenFrames.gif

ldadhelp/changeDelayBetweenLoops.gif

ldadhelp/changeMaxFrames.gif

ldadhelp/clearButton.gif

ldadhelp/emds.gif

ldadhelp/emds2.gif

ldadhelp/helpCursor1.gif

ldadhelp/helpCursor2.gif

ldadhelp/helpCursor3.gif

ldadhelp/imageMenuBar.gif

ldadhelp/ldadWebPage.gif

ldadhelp/obsDisplay.gif

ldadhelp/probeDisplay.gif

ldadhelp/probeMenuBar.gif

ldadhelp/qcData.gif

ldadhelp/tempImage.gif

ldadhelp/textMenuBar.gif

ldadhelp/textScrollerMenuBar.gif

ldadhelp/textScrollers.gif

ldadhelp/toolbar.gif

ldadhelp/weatherMenu.gif

bou/hello/CPHelloWorld.class

######### DO NOT CHANGE/ADD/REMOVE ITEMS BELOW#############

webSiteName.txt

logconf.ini

siteId.txt

display0.jar

display1.jar

display2.jar

ptolemy.plot.jar

symantec.jar

localizations/iii/wkspace/Graphic.mnu

localizations/iii/wkspace/Text.mnu

localizations/iii/wkspace/Probe.mnu

localizations/iii/wkspace/Scroll.mnu

localizations/iii/wkspace/Edit.mnu

localizations/iii/wkspace/Edit.frm

localizations/iii/wkspace/Xtensibl.frm

Sync.class

StatusText.class

StatusWindow.class

ldad.jpg

#END: syncFiles.txt

Restart the EMDS Applet or Synchronize the EMDS application and restart.

BEGIN:Batch file to compile code.

REM Begin:DOS JAVA Start Command
ECHO OFF
VERIFY OHTER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 ECHO error:Unable to enable extensions
SET CLASSPATH=.;C:\jdk117B\lib;C:\jdk117B\bin;C:\data\ldad\emwww\htdocs;..;
SET PATH=.;C:\jdk117B\lib;C:\jdk117B\bin;C:\data\ldad\emwww\htdocs;..;c:\Program Files\Netscape\Communicator\Program\;c:\Program Files\Plus!\Microsoft Internet\;
ECHO ON
java -help
java -version
java -nojit -mx65536000 -ms55000000 -Drun.config.dir=D:\steffen\webDissem\hmlib\miscDefs\ display.Display /webSite=d:///steffen/ldadjavaA/ /toolbar=true
ECHO OFF
ENDLOCAL

END:Batch file to compile code.

Standard Disclaimer comment added to all source code.

//========================================DISCLAIMER=========================
// This file has been developed by and/or for the U.S. government within the
// Forecast Systems Laboratory by government and/or contract personnel.
// As required by government regulations, this file is in the public
// domain, and is furnished "as is", without technical support, and with
// no warranty, express or implied, as to its usefulness for any purpose.
//F>>=====================================description (optional)=============
//F>>>=======================================================================

WARNING: Back up your software package, help file, and menu file changes or they will be lost when new installations are performed.



Example 2: Hello World Software Module with Cursor Text

Assignment: Paint Hello World in different colors at several points on the screen and add cursor text to display the name of the hello world as you move over it.



//BEGIN CODE ***************************************************


// CPHelloWorld2.java


package bou.hello;
//Import statements:
import display.SKCPObject;
import display.PaintOnMeEvent;
import display.PointXLonYLat;
import java.awt.Color;
import display.ProjectorIF;
import display.BCanvas;
import java.util.Date;
import java.awt.Rectangle;

public class CPHelloWorld2 extends SKCPObject
    {
    public void paintOnMe(PaintOnMeEvent pome) // Paints basic "Hello World" on screen.
        {
        if((pome == null) || (pome.g == null) || (_strHelloWorld1 == null)
          || (_strHelloWorld2 == null) || (_strHelloWorld3 == null))
            return;
        //BEGIN: Initialize the point holding the corners
        _pxyFirstC = new PointXLonYLat(pome.dFirstCornerX, pome.dFirstCornerY);
        _pxyOppC = new PointXLonYLat(pome.dOppositeCornerX, pome.dOppositeCornerY);

        //END: Initialize the point holding the corners
        pome.g.drawString(_strHelloWorld1, 100, 100);
        pome.g.setColor(Color.green);
        pome.g.drawString(_strHelloWorld2, 200, 200);
        pome.g.setColor(Color.red);
        pome.g.drawString(_strHelloWorld3, 300, 300);
        }
    public String getValueAt(PointXLonYLat pLonLat, Date time) // Adds Cursor Text
        {
        //BEGIN: Convert pLonLat to screen Coordinates.
        if(_pxyOppC == _pxyFirstC) // Hold off until painted once.
            return "";
        PointXLonYLat pxyFirstC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat( _pxyFirstC);
        PointXLonYLat pxyOppC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(_pxyOppC);
        double dTRCornFlat[] = new double[2];
        double dBLCornFlat[] = new double[2];
        dTRCornFlat[0] = Math.max(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dBLCornFlat[0] = Math.min(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dTRCornFlat[1] = Math.max(pxyFirstC.getYLat(), pxyOppC.getYLat());
        dBLCornFlat[1] = Math.min(pxyFirstC.getYLat(), pxyOppC.getYLat());
        PointXLonYLat pxyFlat = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(pLonLat);
        Rectangle rComp = getCompOwner().getBounds();
        int nScrnXY[] = ((BCanvas)getCompOwner()).getProj().flatToScrn(pxyFlat, 1, rComp, dBLCornFlat, dTRCornFlat);
        //END: Convert pLonLat to screen Coordinates.
        //BEGIN: Find nearest Hello World
        int nSquaredDist1 = (nScrnXY[0] - 100) * (nScrnXY[0] - 100) + (nScrnXY[1] - 100) * (nScrnXY[1] - 100);
        int nSquaredDist2 = (nScrnXY[0] - 200) * (nScrnXY[0] - 200) + (nScrnXY[1] - 200) * (nScrnXY[1] - 200);
        int nSquaredDist3 = (nScrnXY[0] - 300) * (nScrnXY[0] - 300) + (nScrnXY[1] - 300) * (nScrnXY[1] - 300);
        String strNearestHelloWorld = null;
        if((nSquaredDist1 < nSquaredDist2) && (nSquaredDist1 < nSquaredDist3))
            strNearestHelloWorld = _strHelloWorld1;
        else if((nSquaredDist2 < nSquaredDist1) && (nSquaredDist2 < nSquaredDist3))
            strNearestHelloWorld = _strHelloWorld2;
        else
            strNearestHelloWorld = _strHelloWorld3;
        //END: Find nearest Hello World
        return strNearestHelloWorld;
        }

    private String _strHelloWorld1 = "Hello World";
    private String _strHelloWorld2 = "Hi World!";
    private String _strHelloWorld3 = "Whazzup World!";
    private PointXLonYLat _pxyFirstC = new PointXLonYLat(0.0d, 0.0d);
    private PointXLonYLat _pxyOppC = _pxyFirstC;
    }
// END CODE ***************************************************




Example 3: Hello World Software Module with Cursor Text and File Access

Assignment: Paint Hello World in different colors at several points on the screen and add cursor text to display the name of the hello world as you move over it. Also, load a java serialized object from the website which specifies the location of the Hello Worlds.


//BEGIN CODE ***************************************************


// CPHelloWorld3.java


package bou.hello;
//Import statements:
import java.awt.MenuItem;
import display.FramDyna;
import display.MenuDyna;
import display.SKCPObject;
import display.FramDir;
import display.PaintOnMeEvent;
import display.PointXLonYLat;
import java.awt.Color;
import display.ProjectorIF;
import java.util.Date;
import display.BCanvas;
import java.awt.Rectangle;
import ldadapp.urlfile.DMLayer;
import java.io.DataInputStream;
import java.util.zip.GZIPInputStream;
import java.io.ObjectInputStream;
import display.PaintYourselfListener;

public class CPHelloWorld3 extends SKCPObject
    {
    public void paintOnMe(PaintOnMeEvent pome) // Paints basic "Hello World" on screen.
        {
        if((pome == null) || (pome.g == null) || (_strHelloWorld1 == null)
          || (_strHelloWorld2 == null) || (_strHelloWorld3 == null))
            return;
        //BEGIN: Initialize the point holding the corners
        _pxyFirstC = new PointXLonYLat(pome.dFirstCornerX, pome.dFirstCornerY);
        _pxyOppC = new PointXLonYLat(pome.dOppositeCornerX, pome.dOppositeCornerY);
        //END: Initialize the point holding the corners
        //BEGIN: Convert pLonLat to screen Coordinates.
        PointXLonYLat pxyFirstC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat( _pxyFirstC);
        PointXLonYLat pxyOppC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(_pxyOppC);
        double dTRCornFlat[] = new double[2];
        double dBLCornFlat[] = new double[2];
        dTRCornFlat[0] = Math.max(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dBLCornFlat[0] = Math.min(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dTRCornFlat[1] = Math.max(pxyFirstC.getYLat(), pxyOppC.getYLat());
        dBLCornFlat[1] = Math.min(pxyFirstC.getYLat(), pxyOppC.getYLat());
        Rectangle rComp = getCompOwner().getBounds();
        //PointXLonYLat pxyFlat = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(pLonLat);
        //int nScrnXY[] = ((BCanvas)getCompOwner()).getProj().flatToScrn(pxyFlat), 1, rComp, dBLCornFlat, dTRCornFlat);
        PointXLonYLat pxyFlat = null;
        int nScrnXY[] = null;
        //END: Convert pLonLat to screen Coordinates.
        for(int i=0;i<_HelloWorld.length;i++)
            {
            pxyFlat = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(new PointXLonYLat(_HelloWorld[i].getLon(),_HelloWorld[i].getLat()));
            nScrnXY = ((BCanvas)getCompOwner()).getProj().flatToScrn(pxyFlat, 1, rComp, dBLCornFlat, dTRCornFlat);
            pome.g.setColor(_HelloWorld[i].getColor());
            pome.g.drawString(_HelloWorld[i].getGreeting(), nScrnXY[0], nScrnXY[1]);
            }
        }
    public String getValueAt(PointXLonYLat pLonLat, Date time) // Adds Cursor Text
        {
        //BEGIN: Convert pLonLat to screen Coordinates.
        if(_pxyOppC == _pxyFirstC) // Hold off until painted once.
        return "";
        PointXLonYLat pxyFirstC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat( _pxyFirstC);
        PointXLonYLat pxyOppC = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(_pxyOppC);
        double dTRCornFlat[] = new double[2];
        double dBLCornFlat[] = new double[2];
        dTRCornFlat[0] = Math.max(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dBLCornFlat[0] = Math.min(pxyFirstC.getXLon(), pxyOppC.getXLon());
        dTRCornFlat[1] = Math.max(pxyFirstC.getYLat(), pxyOppC.getYLat());
        dBLCornFlat[1] = Math.min(pxyFirstC.getYLat(), pxyOppC.getYLat());
        Rectangle rComp = getCompOwner().getBounds();
        PointXLonYLat pxyFlat = ((BCanvas)getCompOwner()).getProj().xLonYLatToFlat(pLonLat);
        int nScrnXY[] = ((BCanvas)getCompOwner()).getProj().flatToScrn(pxyFlat, 1, rComp, dBLCornFlat, dTRCornFlat);
        //END: Convert pLonLat to screen Coordinates.
        //BEGIN: Find nearest Hello World
        int nSquaredDist1 = (nScrnXY[0] - 100) * (nScrnXY[0] - 100) + (nScrnXY[1] - 100) * (nScrnXY[1] - 100);
        int nSquaredDist2 = (nScrnXY[0] - 200) * (nScrnXY[0] - 200) + (nScrnXY[1] - 200) * (nScrnXY[1] - 200);
        int nSquaredDist3 = (nScrnXY[0] - 300) * (nScrnXY[0] - 300) + (nScrnXY[1] - 300) * (nScrnXY[1] - 300);
        String strNearestHelloWorld = null;
        if((nSquaredDist1 < nSquaredDist2) && (nSquaredDist1 < nSquaredDist3))
            strNearestHelloWorld = _strHelloWorld1;
        else if((nSquaredDist2 < nSquaredDist1) && (nSquaredDist2 < nSquaredDist3))
            strNearestHelloWorld = _strHelloWorld2;
        else
            strNearestHelloWorld = _strHelloWorld3;
        //END: Find nearest Hello World
        return strNearestHelloWorld;
        }

    /**
    * CPHelloWorld.constructBean -
    *
    * @param frmParent = reference to the frame class.
    *
    * @param strParameters1 = null.
    *
    * @param strParameters2: HelloWorldLocnFile
    * Example: HelloWorld.dat
    *
    * @param menuitem = menuitem used to instantiate this component painter.
    *
    * @see display.InitBeanIF#constructBean
    *
    */
    public void constructBean(FramDyna frmParent, String strParameters1,
      String strParameters2, MenuItem menuitem)
        {
        super.constructBean(frmParent, strParameters1, strParameters2, menuitem);
        _strHelloWorldLocnFile = strParameters2;
        //BEGIN: Connect a data input stream to the file.
        DMLayer dml = new DMLayer();
        DataInputStream dis = null;
        if(dis == null)
            {
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.SITEID, _strHelloWorldLocnFile); // strSiteId
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.WKSPACE, _strHelloWorldLocnFile); // "/wkspace/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDWKSPACE, _strHelloWorldLocnFile); // "/wkspace/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HELP, _strHelloWorldLocnFile); // "ldadhelp/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDHELP, _strHelloWorldLocnFile); // "ldadhelp/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.MAPLOCN, _strHelloWorldLocnFile); // "/mapdata/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDMAPLOCN, _strHelloWorldLocnFile); // "/mapdata/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.MAPLOCNNTNL, _strHelloWorldLocnFile); // "mapdata/usa/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDMAPLOCNNTNL, _strHelloWorldLocnFile); // "mapdata/usa/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.IMGLOCN, _strHelloWorldLocnFile); // strSiteId + "/imagedata/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDIMGLOCN, _strHelloWorldLocnFile); // strSiteId + "/imagedata/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.IMGLOCNNTNL, _strHelloWorldLocnFile); // "imagedata/usa/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDIMGLOCNNTNL, _strHelloWorldLocnFile); // "imagedata/usa/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.LOCALCNFLOCN, _strHelloWorldLocnFile); // "localConfig/"
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.MAPLOCN, _strHelloWorldLocnFile);
            //dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.HDCODEBASE, _strHelloWorldLocnFile);
            dis = FramDir.getFileDIS(this.getfrmParent(), dml, FramDir.CODEBASE, _strHelloWorldLocnFile);
            }
        if(dis != null)
            {
            _HelloWorld = null;
            try {
                GZIPInputStream zis = new GZIPInputStream(dis);
                ObjectInputStream ois = new ObjectInputStream(zis);
                _HelloWorld = (HelloWorld[])(ois.readObject());
                ois.close();
                zis.close();
                }
            catch(Exception e)
                {
                this.getfrmParent().displayUserMsg("Exception ERROR: "
                  +_strHelloWorldLocnFile+ ".\n\n"+e.toString() );
                  e.printStackTrace();
                }
            }
        dml.close();
        }

    /**
    * CPHelloWorld.destructBean - Used to deregister the bean with any other
    * component painters or notification beans you registered it with.
    * The garbage collector requires that it be dereferenced by all
    * objects that still exist before it can be cleaned up.
    *
    * @param frmParent = @see ldadapp.radar.CPRadar#constructBean
    * @param strParameters1: @see ldadapp.radar.CPRadar#constructBean
    * @param strParameters2: @see ldadapp.radar.CPRadar#constructBean
    * @param menuitem = @see ldadapp.radar.CPRadar#constructBean
    * @see display.InitBeanIF#constructBean
    */
    public void destructBean(FramDyna frmParent, String strParameters1,
      String strParameters2, MenuItem menuitem)
        {
        removePaintYourselfListener((PaintYourselfListener)getCompOwner());
        super.destructBean(frmParent,strParameters1,strParameters2,menuitem);
        }

    private String _strHelloWorld1 = "Hello World";
    private String _strHelloWorld2 = "Hi World!";
    private String _strHelloWorld3 = "Whazzup World!";
    private PointXLonYLat _pxyFirstC = new PointXLonYLat(0.0d, 0.0d);
    private PointXLonYLat _pxyOppC = _pxyFirstC;
    private HelloWorld _HelloWorld[] = null;
    private String _strHelloWorldLocnFile = null;
    }



// END CODE ***************************************************



Application Programming Interface

The most important classes and interfaces used in writing classes compatible with the application programming interface include:

The Interfaces:

display.InitBeanIF.java

public void constructBean(FramDyna frmParent, String strParameters1, String strParameters2, MenuItem menuitem);
public void destructBean(FramDyna frmParent, String strParameters1, String strParameters2, MenuItem menuitem);

display.PaintOnMeListener.java

public void paintOnMe(PaintOnMeEvent ppe);
public byte getPaintPriority();
public String getValueAt(PointXLonYLat pLonLat, Date time);
public void paintDataKeys(PaintOnMeEvent ppe);
public boolean isStaticData();
public boolean isAnimatable();
public TimeRange[] getTimeRanges();
public String getNameAt(PointXLonYLat pLonLat);
public String getUnitsAt(PointXLonYLat pLonLat);
public Object[] getPolygon(PointXLonYLat pLonLat, String strID, ProjectorIF proj);
// Object[0] is the polygon the Object[1] is the Integer ScaleFactor.
public Properties probePolygon(int nScaleFactor,Polygon polyScaledIntAWIPS, ProjectorIF proj, Properties pFieldKeys, Date date);
public String getLegendEntry(Date time);
public Color getForegroundColor();
public String getImageIdentifierString();
public FramDyna getfrmParent();
public String getParameters1();
public String getParameters2();
public MenuItem getMenuItem();
public ProjectorIF getProj();
public void setProj(ProjectorIF proj);
public ViewCntrlIF getViewCntrl();

/*
* The following is a list of the paint priorities in the LDAD system:
* SKVCCanvas.java = 10 default
* SKVCObject.java = 10 default
* SKVCScrollingText.java = 10 default
* SKVCTextArea.java = 0 default
* SKCPObject.java = 10 default
* FramDyna.java = 0 default
* BPanelD.java = 10 default
* The following classes override the defaults:
* TEXT MENUS:
* BAlertMap.java = 70 or byPaintPriority (see class code)
* GRIDS:
* BImage.java = 200
* CONTOURS:
* BContour = 100
* OBSERVATIONS:
* BLocationObs.java = 100
* BVectorObs.java = 100
* BWeatherObs.java = 100
* BScalarObs.java = 100
* RADAR:
* CPRadar.java = 200
* IMAGES:
* CPImage.java = 200
*/


display.PaintYourselfSpeaker.java

public void speakPaintYourself();
public void addPaintYourselfListener( PaintYourselfListener poml);
public void removePaintYourselfListener( PaintYourselfListener poml);

display.CompPainterIF.java extends PaintOnMeListener, PaintYourselfSpeaker, InitBeanIF

The component painter interface defines the abstract public functions and their paramenters which should be implemented. These functions are called by the display framework at the appropriate time to generate the images displayed on the screen.

public double getFirstCornerXDegLon();
public double getFirstCornerYDegLat();
public double getOppositeCornerXDegLon();
public double getOppositeCornerYDegLat();
public ProjectorIF getProj();
public void setProj(ProjectorIF proj);
public void setSlidingTmWin(long mSecSTW);
public void setMaxFrames(int nMaxFrames);
public String getGeographyDesc(GeoDescAtEvent gdae);

The Skeleton Code:

display.SKCPObject.java

The purpose of the component painter skeleton code is to implement a set of default behaviors for the component painter interface in a single class which can be copied, renamed, and inserted into the inheritance hierarchy of a class being developed. This allows the developer to implement and test the functions in the interface on an "as needed" basis. This also prevents the lack of implementation of a function in the interface from generating errors.

The Useful Utilities:

EMDS source code should be at: "ls:/ldad/webDissemSrc/"


display.FramDir.java

Contains easy ways to access the website or harddrive.

display.ProjectorIF.java

Interface to the projection code.

ldadapp.map.BProjection.java

Performs Lambert Conformal, Mercator, Polar Stereographic, and AWIPS projections. Suggest accessing via the ProjectorIF.

ldadapp.obs.BoxContains.java

Contains fast algorithm to determine if a longitude/lattitude point is in a box. Useful in valueAt for Obs.

ldadapp.util.EarthDist.java

Converts two longitude/lattitude points to/from one longitude/lattitude point and a direction and radius.

ldadapp.util.ColorMap.java

Associates a line in Red Green Blue space with a series of numbers.

ldadapp.util.IconMap.java

Associates a set of icons with a series of numbers.