This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
David, Thanks for catching these errors. I made the matches more strigent to correct the problems. Included is a modified metar2nc with the fixes. Robb... On Fri, 16 Jan 2004, David Larson wrote: > Robb, > > Could you check the parsing of a METAR for me? > > KPDX 160555Z 15003KT 1/4SM R10R/2800V5000FT BR OVC004 05/05 A3013 > > What I see as a result of parsing is that part of the runway data > (800V500) gets parsed out of the METAR into the DIRmin/DIRmax, and then > subsequently the runway data isn't parsed out properly either (of course). > > I've made a few changes to the metar decoder from version 2.4.3 for > tweaks here and there ... so I must admit this might again be a problem > I've inflicted on myself. > > The following code seems to interfere with the runway processing code: > # get min|max wind direction > if( s#(\d{3})V(\d{3})\s*## ) { > $DIRmin = $1 ; > $DIRmax = $2 ; > } > > What do you think about the following mod: > if( s#(\d{3})V(\d{3})(\s+|$)## ) { > > The point of the above being just to ensure there is at least one > trailing whitespace (or EOL). > > Thanks for the help, > Dave > > =============================================================================== Robb Kambic Unidata Program Center Software Engineer III Univ. Corp for Atmospheric Research address@hidden WWW: http://www.unidata.ucar.edu/ ===============================================================================
#! /usr/local/bin/perl # # usage: metar2nc cdlfile [datatdir] [yymm] < ncfile # # #chdir( "/home/rkambic/code/decoders/src/metar" ) ; use NetCDF ; use Time::Local ; # process command line switches while ($_ = $ARGV[0], /^-/) { shift; last if /^--$/; /^(-v)/ && $verbose++; } # process input parameters if( $#ARGV == 0 ) { $cdlfile = $ARGV[ 0 ] ; } elsif( $#ARGV == 1 ) { $cdlfile = $ARGV[ 0 ] ; if( $ARGV[ 1 ] =~ /^\d/ ) { $yymm = $ARGV[ 1 ] ; } else { $datadir = $ARGV[ 1 ] ; } } elsif( $#ARGV == 2 ) { $cdlfile = $ARGV[ 0 ] ; $datadir = $ARGV[ 1 ] ; $yymm = $ARGV[ 2 ] ; } else { die "usage: metar2nc cdlfile [datatdir] [yymm] < ncfile $!\n" ; } print "Missing cdlfile file $cdlfile: $!\n" unless -e $cdlfile ; if( -e "util/ncgen" ) { $ncgen = "util/ncgen" ; } elsif( -e "/usr/local/ldm/util/ncgen" ) { $ncgen = "/usr/local/ldm/util/ncgen" ; } elsif( -e "/upc/netcdf/bin/ncgen" ) { $ncgen = "/upc/netcdf/bin/ncgen" ; } elsif( -e "./ncgen" ) { $ncgen = "./ncgen" ; } else { open( NCGEN, "which ncgen |" ) ; $ncgen = <NCGEN> ; close( NCGEN ) ; if( $ncgen =~ /no ncgen/ ) { die "Can't find NetCDF utility 'ncgen' in PATH, util/ncgen /usr/local/ldm/util/ncgen, /upc/netcdf/bin/ncgen, or ./ncgen : $!\n" ; } else { $ncgen = "ncgen" ; } } # the data and the metadata directories $datadir = "." if( ! $datadir ) ; $metadir = $datadir . "/../metadata/surface/metar" ; # redirect STDOUT and STDERR open( STDOUT, ">$datadir/metarLog.$$.log" ) || die "could not open $datadir/metarLog.$$.log: $!\n" ; open( STDERR, ">&STDOUT" ) || die "could not dup stdout: $!\n" ; select( STDERR ) ; $| = 1 ; select( STDOUT ) ; $| = 1 ; die "Missing cdlfile file $cdlfile: $!\n" unless -e $cdlfile ; # year and month if( ! $yymm ) { $theyear = (gmtime())[ 5 ] ; $theyear = ( $theyear < 100 ? $theyear : $theyear - 100 ) ; $theyear = sprintf( "%02d", $theyear ) ; $themonth = (gmtime())[ 4 ] ; $themonth++ ; $yymm = $theyear . sprintf( "%02d", $themonth ) ; } else { $theyear = substr( $yymm, 0, 2 ) ; $themonth = substr( $yymm, 2 ) ; } # file used for bad metars or prevention of overwrites to ncfiles open( OPN, ">>$datadir/rawmetars.$$.nc" ) || die "could not open $datadir/rawmetars.$$.nc: $!\n" ; # set error handling to verbose only $result = NetCDF::opts( VERBOSE ) ; # set interrupt handler $SIG{ 'INT' } = 'atexit' ; $SIG{ 'KILL' } = 'atexit' ; $SIG{ 'TERM' } = 'atexit' ; $SIG{ 'QUIT' } = 'atexit' ; # set defaults $F = -99999 ; $A = \$F ; $S1 = "\0" ; $AS1 = \$S1 ; $S2 = "\0\0" ; $AS2 = \$S2 ; $S3 = "\0\0\0" ; $AS3 = \$S3 ; $S4 = "\0\0\0\0" ; $AS4 = \$S4 ; $S8 = "\0" x 8 ; $AS8 = \$S8 ; $S10 = "\0" x 10 ; $AS10 = \$S10 ; $S15 = "\0" x 15 ; $AS15 = \$S15 ; $S32 = "\0" x 32 ; $AS32 = \$S32 ; $S128 = "\0" x 128 ; $AS128 = \$S128 ; %CDL = ( "rep_type", 0, "stn_name", 1, "wmo_id", 2, "lat", 3, "lon", 4, "elev", 5, "ob_hour", 6, "ob_min", 7, "ob_day", 8, "time_obs", 9, "time_nominal", 10, "AUTO", 11, "UNITS", 12, "DIR", 13, "SPD", 14, "GUST", 15, "VRB", 16, "DIRmin", 17, "DIRmax", 18, "prevail_VIS_SM", 19, "prevail_VIS_KM", 20, "plus_VIS_SM", 21, "plus_VIS_KM", 22, "prevail_VIS_M", 23, "VIS_dir", 24, "CAVOK", 25, "RVRNO", 26, "RV_designator", 27, "RV_above_max", 28, "RV_below_min", 29, "RV_vrbl", 30, "RV_min", 31, "RV_max", 32, "RV_visRange", 33, "WX", 34, "vert_VIS", 35, "cloud_type", 36, "cloud_hgt", 37, "cloud_meters", 38, "cloud_phenom", 39, "T", 40, "TD", 41, "hectoPasc_ALTIM", 42, "inches_ALTIM", 43, "NOSIG", 44, "TornadicType", 45, "TornadicLOC", 46, "TornadicDIR", 47, "BTornadic_hh", 48, "BTornadic_mm", 49, "ETornadic_hh", 50, "ETornadic_mm", 51, "AUTOindicator", 52, "PKWND_dir", 53, "PKWND_spd", 54, "PKWND_hh", 55, "PKWND_mm", 56, "WshfTime_hh", 57, "WshfTime_mm", 58, "Wshft_FROPA", 59, "VIS_TWR", 60, "VIS_SFC", 61, "VISmin", 62, "VISmax", 63, "VIS_2ndSite", 64, "VIS_2ndSite_LOC", 65, "LTG_OCNL", 66, "LTG_FRQ", 67, "LTG_CNS", 68, "LTG_CG", 69, "LTG_IC", 70, "LTG_CC", 71, "LTG_CA", 72, "LTG_DSNT", 73, "LTG_AP", 74, "LTG_VcyStn", 75, "LTG_DIR", 76, "Recent_WX", 77, "Recent_WX_Bhh", 78, "Recent_WX_Bmm", 79, "Recent_WX_Ehh", 80, "Recent_WX_Emm", 81, "Ceiling_min", 82, "Ceiling_max", 83, "CIG_2ndSite_meters", 84, "CIG_2ndSite_LOC", 85, "PRESFR", 86, "PRESRR", 87, "SLPNO", 88, "SLP", 89, "SectorVIS_DIR", 90, "SectorVIS", 91, "GR", 92, "GRsize", 93, "VIRGA", 94, "VIRGAdir", 95, "SfcObscuration", 96, "OctsSkyObscured", 97, "CIGNO", 98, "Ceiling_est", 99, "Ceiling", 100, "VrbSkyBelow", 101, "VrbSkyLayerHgt", 102, "VrbSkyAbove", 103, "Sign_cloud", 104, "Sign_dist", 105, "Sign_dir", 106, "ObscurAloft", 107, "ObscurAloftSkyCond", 108, "ObscurAloftHgt", 109, "ACFTMSHP", 110, "NOSPECI", 111, "FIRST", 112, "LAST", 113, "Cloud_low", 114, "Cloud_medium", 115, "Cloud_high", 116, "SNINCR", 117, "SNINCR_TotalDepth", 118, "SN_depth", 119, "SN_waterequiv", 120, "SunSensorOut", 121, "SunShineDur", 122, "PRECIP_hourly", 123, "PRECIP_amt", 124, "PRECIP_24_amt", 125, "T_tenths", 126, "TD_tenths", 127, "Tmax", 128, "Tmin", 129, "Tmax24", 130, "Tmin24", 131, "char_Ptend", 132, "Ptend", 133, "PWINO", 134, "FZRANO", 135, "TSNO", 136, "PNO", 137, "maintIndicator", 138, "PlainText", 139, "report", 140, "remarks", 141 ) ; # default netCDF record structure, contains all vars for the METAR reports @defaultrec = ( $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS3, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS2, $A, $A, [( $S3, $S3, $S3, $S3 )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], [( $F, $F, $F, $F )], $AS32, $A, [( $S4, $S4, $S4, $S4, $S4, $S4 )], [( $F, $F, $F, $F, $F, $F )], [( $F, $F, $F, $F, $F, $F )], [( $S4, $S4, $S4, $S4, $S4, $S4 )], $A, $A, $A, $A, $A, $AS15, $AS10, $AS2, $A, $A, $A, $A, $AS4, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS10, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS2, [( $S8, $S8, $S8 )], [( $F, $F, $F )], [( $F, $F, $F )], [( $F, $F, $F )], [( $F, $F, $F )], $A, $A, $A, $A, $A, $A, $A, $A, $AS2, $A, $A, $A, $A, $AS2, $AS8, $A, $A, $A, $A, $AS3, $A, $AS3, $AS10, $AS10, $AS10, $AS8, $AS3, $A, $A, $A, $A, $A, $AS1, $AS1, $AS1, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $A, $AS128, $AS128, $AS128 ) ; # two fold purpose array, if entry > 0, then var is requested and it's value # is the position in the record, except first entry @W = ( 0 ) x ( $#defaultrec +1 ) ; $W[ 0 ] = -1 ; # open cdl and create record structure according to variables open( CDL, "$cdlfile" ) || die "could not open $cdlfile: $!\n" ; $i = 0 ; while( <CDL> ) { if( s#^\s*(char|int|long|double|float) (\w{1,25})## ) { ( $number ) = $CDL{ $2 } ; push( @rec, $defaultrec[ $number ] ) ; $W[ $number ] = $i++ ; } } close CDL ; undef( @defaultrec ) ; undef( %CDL ) ; # read in station data if( -e "etc/sfmetar_sa.tbl" ) { $sfile = "etc/sfmetar_sa.tbl" ; } elsif( -e "./sfmetar_sa.tbl" ) { $sfile = "./sfmetar_sa.tbl" ; } else { die "Can't find sfmetar_sa.tbl station file.: $!\n" ; } open( STATION, "$sfile" ) || die "could not open $sfile: $!\n" ; while( <STATION> ) { s#^(\w{3,6})?\s+(\d{4,5}).{40}## ; $id = $1 ; $wmo_id = $2 ; $wmo_id = "0" . $wmo_id if( length( $wmo_id ) == 4 ) ; ( $lat, $lon, $elev ) = split ; $lat = sprintf( "%7.2f", $lat / 100 ) ; $lon = sprintf( "%7.2f", $lon / 100) ; # set these vars ( $wmo_id, $lat, $lon, $elev ) $STATIONS{ "$id" } = "$wmo_id $lat $lon $elev" ; } close STATION ; # read in list of already processed reports if it exists # open metar.lst, list of reports processed in the last 4 hours. if( -e "$datadir/metar.lst" ) { open( LST, "$datadir/metar.lst" ) || die "could not open $datadir/metar.lst: $!\n" ; while( <LST> ) { ( $stn, $rtptime, $hr ) = split ; $reportslist{ "$stn $rtptime" } = $hr ; } close LST ; #unlink( "$datadir/metar.lst" ) ; } # Now begin parsing file and decoding observations breaking on cntrl C $/ = "\cC" ; # set select processing here from STDIN START: while( 1 ) { open( STDIN, '-' ) ; vec($rin,fileno(STDIN),1) = 1; $timeout = 1200 ; # 20 minutes $nfound = select( $rout = $rin, undef, undef, $timeout ); # timed out if( ! $nfound ) { print "Shut down, time out 20 minutes\n" ; &atexit() ; } &atexit( "eof" ) if( eof( STDIN ) ) ; # Process each line of metar bulletins, header first $_ = <STDIN> ; #next unless /METAR|SPECI/ ; s#\cC## ; s#\cM##g ; s#\cA\n## ; s#\c^##g ; s#\d\d\d \n## ; s#\w{4}\d{1,2} \w{4} (\d{2})(\d{2})(\d{2})?.*\n## ; $tday = $1 ; $thour = $2 ; $thour = "23" if( $thour eq "24" ) ; $tmin = $3 ; $tmin = "00" unless( $tmin ) ; next unless ( $tday && defined( $thour ) ) ; $time_trans = thetime( "trans" ) ; if( s#(METAR|SPECI) \d{4,6}Z?\n## ) { $rep_type = $1 ; } elsif( s#(METAR|SPECI)\s*\n## ) { $rep_type = $1 ; } else { $rep_type = "METAR" ; } # Separate bulletins into reports if( /=\n/ ) { s#=\s+\n#=\n#g ; @reports = split( /=\n/ ) ; } else { @reports = split ( /\n/ ) ; } for ( @reports ) { # Process each report in the bulletin undef( $report ) ; undef( $remarks ) ; undef( $stn_name ) ; undef( $ob_day ) ; next if( /^\n/ ) ; s#^(METAR|M E T A R|SPECI|TESTM|TESTS)\s*\n?## ; if( /\n\w{4} \d{4,6}Z/ ) { # reports appended together wrongly ( $_, $tmp ) = split( "\n", $_ ) ; print OPN "$tday$thour$tmin\n$tmp\n" ; } s#\n# #g ; # save original report and remarks if( s#(.*)( RMK| REMARKS)(.*)?#$1# ) { $report = $1 ; $remarks = $3 unless( ! $3 || $3 =~ /NIL/ ) ; } else { $report = $_ ; } $_ = "$_ " ; $rep_type = $1 if( s#^(METAR|SPECI|TESTM|TESTS)\s+## ) ; $stn_name = $1 if( s#^(\w{4})\s+## ) ; next unless( $stn_name ) ; #if( $stn_name =~ /CWDJ|GBYD/ ) { #print $stn_name ; #} # get date hour minute next unless( s#^(\d{4,6})Z\s+## ); if( length( $1 ) == 4 ) { $rpt_time = $1 ; if( $rpt_time =~ /^$tday/ ) { $ob_min = "00" ; $ob_hour = substr( $rpt_time, 2, 2 ) ; $ob_day = substr( $rpt_time, 0, 2 ) ; $rpt_time = $ob_hour . $ob_min ; } else { $ob_min = substr( $rpt_time, 2, 2 ) ; $ob_hour = substr( $rpt_time, 0, 2 ) ; $ob_day = $tday ; } } elsif( length( $1 ) == 5 ) { $rpt_time = substr( $1, 1 ) ; $ob_day = sprintf( "%02d", substr( $1, 0, 1 ) ) ; $ob_hour = substr( $1, 1, 2 ) ; $ob_min = substr( $1, 3, 2 ) ; } else { $rpt_time = substr( $1, 2 ) ; $ob_day = substr( $1, 0, 2 ) ; $ob_hour = substr( $1, 2, 2 ) ; $ob_min = substr( $1, 4, 2 ) ; } if( $ob_min > 59 || $ob_hour > 23 || $ob_day > 31 ) { print OPN "$tday$thour$tmin\n$report\n$remarks\n" ; next ; } # Skip duplicate reports based on stn and time if( defined( $reportslist{ "$stn_name $rpt_time" } ) ) { next ; } else { # ob hr = 23 and ob min > 45 if( $ob_hour == 23 && $ob_min > 45 ) { $ob_day = $tday ; $yymmdd = $yymm . $tday ; $ob_hour = $ob_min = "00" ; # push report to next hour } elsif( $ob_min > 45 ) { $ob_min = "00" ; $ob_hour = sprintf( "%02d", ++$ob_hour ) ; $yymmdd = $yymm . $ob_day ; # ob day != bulletin day } elsif( $ob_day != $tday ) { $yymmdd = thetime( "yesterday" ) ; #$ob_day = substr( $yymmdd, 4 ) ; # ob hr > bulletin hr } elsif( $ob_hour > ( $thour +1 )) { $yymmdd = thetime( "yesterday" ) ; $ob_day = substr( $yymmdd, 4 ) ; } else { $yymmdd = $yymm . sprintf( "%02d", $ob_day ) ; } $hour = $ob_hour ; $reportslist{ "$stn_name $rpt_time" } = "$hour" ; $time_obs = thetime( "obs" ) ; if( abs( $time_trans - $time_obs) > 10800 ) { print OPN "$tday$thour$tmin\n$report\n$remarks\n"; next ; } $time_nominal = thetime( "nominal" ) ; } # skip NIL reports next if( s#NIL\s*## ) ; # extract wmo_id, lat, lon, elev if( $STATIONS{ "$stn_name" } ) { ( $wmo_id, $lat, $lon, $elev ) = split( " ", $STATIONS{ "$stn_name" } ) ; } elsif( $stn_name =~ /^K|^C/ ) { # US & Canadian stations $tmp = substr( $stn_name, 1 ) ; ( $wmo_id, $lat, $lon, $elev ) = split( " ", $STATIONS{ "$tmp" } ) if( $STATIONS{ "$tmp" } ) ; } $AUTO = 1 if( s#AUTO\s+## ) ; # get wind direction and speed if( s#(E|W|N|S)?(\d{3}|VRB)(\d{2,3})(G)?(\d{2,3})?(KMH|KT|MPS|MPH)\s+## ) { if( $2 eq "VRB" ) { $VRB = 1 ; } else { $DIR = $2 ; } $SPD = $3 ; $GUST = $5 if( $4 eq "G" ) ; $UNITS = $6 ; $UNITS = padstr( $UNITS, 3 ) ; } # get min|max wind direction if( s#^(\d{3})V(\d{3})\s+## ) { $DIRmin = $1 ; $DIRmax = $2 ; } # some reports use a place holder for visibility s#9999\s+## ; # get visibility $prevail_VIS_SM = 0.0 if( s#^M1/4SM\s+|<1/4SM\s+## ) ; $prevail_VIS_KM = 0.0 if( s#^M1/4KM\s+|<1/4KM\s+## ) ; $plus_VIS_SM = 1 if( s#^P(\d{1,3})SM\s+#$1SM # ) ; $plus_VIS_KM = 1 if( s#^P(\d{1,3})KM\s+#$1KM # ) ; if( s#^(\d{1,4}) (\d{1,3})/(\d{1,3})(SM|KM)\s+## ) { $prevail_VIS_SM = $1 + ( $2 / $3 ) if( $4 eq "SM" ) ; $prevail_VIS_KM = $1 + ( $2 / $3 ) if( $4 eq "KM" ) ; } elsif( s#^(\d{1,3})/(\d{1,3})(KM|SM)\s+## ) { $prevail_VIS_SM = $1 / $2 if( $3 eq "SM" ) ; $prevail_VIS_KM = $1 / $2 if( $3 eq "KM" ) ; } elsif( s#^(\d{1,4})(KM|SM)\s+## ) { $prevail_VIS_SM = $1 if( $2 eq "SM" ) ; $prevail_VIS_KM = $1 if( $2 eq "KM" ) ; } elsif( s#^(\d{4})((NE)|(NW)|(SE)|(SW)|(N)|(S)|(E)|(W))\s+## ){ $prevail_VIS_M = $1 ; $VIS_dir = $2 ; $VIS_dir = padstr( $VIS_dir, 2 ) ; } # clear $CAVOK = 1 if( s#CAVOK\s+## ) ; # runway decoding here $RVRNO = 1 if( s#RVRNO\s+## ) ; for( $i = 0; $i < 4; $i++ ) { if( s#R(\d{2})(R|L|C)?/(M|P)?(\d{4})V?(M|P)?(\d{4})?(FT|N|D)?\s+## ){ if( $i == 0 ) { @RV_designator = ( $S3, $S3, $S3, $S3 ); @RV_above_max = ( $F, $F, $F, $F ) ; @RV_below_min = ( $F, $F, $F, $F ) ; @RV_vrbl = ( $F, $F, $F, $F ) ; @RV_min = ( $F, $F, $F, $F ) ; @RV_max = ( $F, $F, $F, $F ) ; @RV_visRange = ( $F, $F, $F, $F ) ; } $RV_designator[ $i ] = "$1$2" ; $RV_designator[ $i ] = padstr( $RV_designator[ $i ], 3 ) ; $RV_above_max[ $i ] = 1 if( $3 eq "P" || $5 eq "P" ) ; $RV_below_min[ $i ] = 1 if( $3 eq "M" || $5 eq "M" ) ; $RV_vrbl[ $i ] = 1 if( $6 ne "" ) ; if( $RV_vrbl[ $i ] ) { $RV_min[ $i ] = $4 * 1; $RV_max[ $i ] = $6 * 1; } else { $RV_visRange[ $i ] = $4 * 1; } $i++ ; } else { last ; } } # Get weather conditions for( $i = 0; $i < 4; $i++ ) { # code table 4678 if( s#^(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?\s+## ) { last unless "$1$2$3$4$5" ; $WX .= "$1$2$3$4$5 " ; } else { last ; } } $WX = padstr( $WX, 32 ) if( defined( $WX ) ) ; # Interpret cloud conditions #$cloud_type[ 0 ] = $1 if( s#(CLR|SKC)\s+## ) ; @cloud_type = ( "$1\0", $S4, $S4, $S4, $S4, $S4 ) if( s#^(CLR|SKC)\s+## ) ; $vert_VIS = cloud_hgt2_meters( $1 ) if( s#^VV(\d{3})\s+## ) ; for( $i = 0; $i < 6; $i++ ) { # layers up to 6 if( s#^(\+|-)?(OVC|SCT|FEW|BKN)(\d{3})(\w{1,3})?\s+## ){ if( $i == 0 ) { @cloud_type = ( $S4,$S4,$S4,$S4,$S4,$S4 ) ; @cloud_hgt = ( $F,$F,$F,$F,$F,$F ) ; @cloud_meters = ( $F,$F,$F,$F,$F,$F ) ; @cloud_phenom = ( $S4,$S4,$S4,$S4,$S4,$S4 ) ; } $cloud_type[ $i ] = padstr( "$1$2", 4 ) ; $cloud_hgt[ $i ] = $3 * 100 ; $cloud_meters[ $i ] = cloud_hgt2_meters( $3 ) ; $cloud_phenom[ $i ] = padstr( $4, 4 ) if( $4 ) ; } else { last ; } } # get temperature and dew point if( s#^(M)?(\d{2})/(M)?(\d{2})?\s+## ) { $T = $2 ; $T *= -1 if( $1 ) ; $TD = $4 if( $4 ) ; $TD *= -1 if( $3 ) ; } # get Altimeter settings if( s#^(A|Q)(\d{4}\.?\d?)\s+## ) { if( $1 eq "A" ) { $inches_ALTIM = $2 * 0.01 ; } else { $hectoPasc_ALTIM = $2 ; } } $NOSIG = 1 if( s#NOSIG## ) ; # get remarks if( defined( $remarks ) ) { doRemarks( "$remarks " ) ; } else { $T_tenths = $T if( defined( $T ) ) ; $TD_tenths = $TD if( defined( $TD ) ) ; } # debug output printvars() if( $verbose ) ; # we have a legal report, open a Netcdf file $result = doNet( $hour ) ; if( $result ) { # OK to write data # set variable into dataref setvars() ; # enter report data into proper record location $result = NetCDF::recput( $ncid, $recnum, [ @dataref ]); if( $result ) { print "NetCDF::recput result = $result\n" ; chop $report while( index( $report, "\0" ) != -1 ) ; chop $remarks while( index( $remarks, "\0" ) != -1 ) ; print "$ncfile\n$report\n$remarks\n" ; } else { $recnum++ ; } } # undefine vars undefinevars() ; # &atexit( "eof" ) if( eof( STDIN ) ) ; } # end foreach report } # end while( 1 ) &atexit( "eof" ); exit( 0 ) ; #should never get here # Interpet Remarks sub doRemarks { ( $_ ) = @_ ; # get Tornado data if present if( s#(TORNADO\w{0,2}|WATERSPOUTS*|FUNNEL CLOUDS*)\s+## ) { $TornadicType = padstr( $1, 15 ) ; if( s#(B|E)(\d\d)(\d\d)?\s+## ) { if( $1 eq "B" ) { $BTornadic_hh = $2 ; $BTornadic_mm = $3 if( defined( $3 ) ) ; } else { $ETornadic_hh = $2 ; $ETornadic_mm = $3 if( defined( $3 ) ) ; } } $TornadicLOC = padstr( $1, 10 ) if( s#^(DSNT|VCY STN|VC STN|VCY|VC)\s+## ) ; $TornadicDIR = padstr( $1, 2 ) if( s#^(NE|NW|SE|SW|N|S|E|W)\s+## ) ; } # get Automated reports $AUTOindicator = padstr( $1, 4 ) if( s#(A01|A01A|A02|A02A|AO1|AO1A|AO2|AO2A|AOA)\s+## ) ; # get Peak winds if( s#PK WND (\d{3})(\d{1,3})/(\d\d)?(\d\d)\s+## ) { $PKWND_dir = $1 ; $PKWND_spd = $2 ; $PKWND_hh = $3 if( defined( $3 ) ) ; $PKWND_mm = $4 ; } # get Wind shift if( s#WSHFT (\d\d)?(\d\d)\s+## ) { $WshfTime_hh = $1 if( defined( $1 ) ); $WshfTime_mm = $2 ; } # get FROPO ( wind shift because of frontal passage ) $Wshft_FROPA = 1 if( s#FROPA\s+## ) ; # Tower visibility if( s#TWR (VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $VIS_TWR = $2 + ( $3 / $4 ) ; } elsif( s#TWR (VIS|VSBY) (\d{1,2})/(\d{1,2})\s+## ) { $VIS_TWR = ( $2 / $3 ) ; } elsif( s#TWR (VIS|VSBY) (\d{1,3})\s+## ) { $VIS_TWR = $2 ; } # Surface visibility if( s#SFC (VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $VIS_SFC = $2 + ( $3 / $4 ) ; } elsif( s#SFC (VIS|VSBY) (\d{1,2})/(\d{1,2})\s+## ) { $VIS_SFC = ( $2 / $3 ) ; } elsif( s#SFC (VIS|VSBY) (\d{1,3})\s+## ) { $VIS_SFC = $2 ; } # Variable visibility if( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})V(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $VISmin = $2 + ( $3 / $4 ) ; $VISmax = $5 + ( $6 / $7 ) ; } elsif( s#(VIS|VSBY) (\d{1,3})V(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $VISmin = $2 ; $VISmax = $3 + ( $4 / $5 ) ; } elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2})V(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $VISmin = ( $2 / $3 ) ; $VISmax = $4 + ( $5 / $6 ) ; } elsif( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2})V(\d{1,3})\s+## ) { $VISmin = $2 + ( $3 / $4 ) ; $VISmax = $5 ; } elsif( s#(VIS|VSBY) (\d{1,3})V(\d{1,3})\s+## ) { $VISmin = $2 ; $VISmax = $3 ; } elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2})V(\d{1,3})\s+## ) { $VISmin = ( $2 / $3 ) ; $VISmax = $4 ; } # Second site visiblity if( s#(VIS|VSBY) (\d{1,3}) (\d{1,2})/(\d{1,2}) (RY\d{1,2})\s+## ) { $VIS_2ndSite = $2 + ( $3 / $4 ) ; $VIS_2ndSite_LOC = padstr( $5, 10 ) ; } elsif( s#(VIS|VSBY) (\d{1,3}) (RY\d{1,2})\s+## ) { $VIS_2ndSite = $2 ; $VIS_2ndSite_LOC = padstr( $3, 10 ) ; } elsif( s#(VIS|VSBY) (\d{1,2})/(\d{1,2}) (RY\d{1,2})\s+## ) { $VIS_2ndSite = ( $2 / $3 ) ; $VIS_2ndSite_LOC = padstr( $4, 10 ) ; } # Lightning data ( Occasional,Frequent,Continuous) and # (Cloud-Ground,In-Cloud,Cloud-Cloud,Cloud-Air) if( s#(OCNL|FRQ|CNS) LTG\s?(CG|IC|CC|CA)\s?(DSNT|AP|VCY STN|VCNTY STN)?\s?(NE|NW|SE|SW|N|S|E|W)?\s+## ) { $LTG_OCNL = 1 if( $1 eq "OCNL" ) ; $LTG_FRQ = 1 if( $1 eq "FRQ" ) ; $LTG_CNS = 1 if( $1 eq "CNS" ) ; $LTG_CG = 1 if( $2 eq "CG" ) ; $LTG_IC = 1 if( $2 eq "IC" ) ; $LTG_CC = 1 if( $2 eq "CC" ) ; $LTG_CA = 1 if( $2 eq "CA" ) ; $LTG_DSNT = 1 if( $3 eq "DSNT" ) ; $LTG_AP = 1 if( $3 eq "AP" ) ; $LTG_VcyStn = 1 if( $3 eq "VCY STN" || $3 eq "VCNTY STN" ) ; $LTG_DIR = padstr( $4, 2 ) if( defined( $4 ) ) ; } # get min/max for Variable Ceiling if( s#CIG (\d{1,4})V(\d{1,4})\s+## ) { $Ceiling_min = $1 ; $Ceiling_max = $2 ; } # ? about SKY condition at 2nd location # get 2nd site ceiling and location if( s#CIG (\d{3}) (RY\d{1,2})\s+## ) { $CIG_2ndSite_meters = $1 * 10 ; $CIG_2ndSite_LOC = $2 ; } # Presure falling rapidly $PRESFR = 1 if( s#PRESFR/?\s+## ) ; # Presure rising rapidly $PRESRR = 1 if( s#PRESRR/?\s+## ) ; # Sea-Level presure $SLPNO = 1 if( s#SLPNO\s+## ) ; if( s#SLP\s?(\d{3})\s+## ) { if( $1 >= 550 ) { $SLP = $1 / 10. + 900. ; } else { $SLP = $1 / 10. + 1000. ; } } # Sector visibility if( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $SectorVIS_DIR = padstr( $2, 2 ) ; $SectorVIS = $3 + ( $4 / $5 ) ; } elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W) (\d{1,2})/(\d{1,2})\s+## ) { $SectorVIS_DIR = padstr( $2, 2 ) ; $SectorVIS = ( $3 / $4 ) ; } elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d{1,3})\s+## ) { $SectorVIS_DIR = padstr( $2, 2 ) ; $SectorVIS = $3 ; } # Hailstone activity and size $GR = 1 if( s#GS\s+## ) ; if( s#GR M1/4\s+## ) { $GR = 1 ; $GRsize = 1 / 8 ; } elsif( s#GR (\d{1,3}) (\d{1,2})/(\d{1,2})\s+## ) { $GR = 1 ; $GRsize = $1 + ( $2 / $3 ) ; } elsif( s#GR (\d{1,2})/(\d{1,2})\s+## ) { $GR = 1 ; $GRsize = ( $1 / $2 ) ; } elsif( s#GR (\d{1,3})\s+## ) { $GR = 1 ; $GRsize = $1 ; } # VIRGA activity if( s#VIRGA (DSNT )?(NE|NW|SE|SW|N|S|E|W)?\s+## ) { $VIRGA = 1 ; $VIRGAdir = padstr( $2, 2 ) if( $2 ) ; } # Surface-based Obscuring Phenomena SfcObscuration weather conditions # code table 4678 if( s#-X(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(\d)\s+## ) { $SfcObscuration = padstr( "$1$2$3$4$5", 8 ) ; $OctsSkyObscured = $6 ; } # get Ceiling_est or Ceiling height $CIGNO = 1 if( s#CIGNO\s+## ) ; if( s#CIG(E)?(\d{3})\s+## ) { if( $1 eq "E" ) { $Ceiling_est = $2 * 100 ; } else { $Ceiling = $2 * 100 ; } } # Variable Sky conditions if( s#(FEW|SCT|BKN|OVC)(\d{3})? V (FEW|SCT|BKN|OVC)\s+## ) { $VrbSkyBelow = $1 ; $VrbSkyLayerHgt = $2 * 100 if( defined( $2 ) ) ; $VrbSkyAbove = $3 ; } # Significant Cloud Types if( s#(CB|CBMAM|TCU|ACC|SCSL|ACSL|ROTOR CLD|ROPE|ROPE CLD)\s+## ) { $Sign_cloud = padstr( $1, 10 ) ; $Sign_dist = padstr( $1, 10 ) if( s#^(VCNTY STN|VCY STN|VC STN|VCY|VC|DSNT|OMT)\s+## ) ; $Sign_dir = padstr( "$1$2$3", 10 ) if( s#^(NE|NW|SE|SW|N|S|E|W)(\-| MOV )?(NE|NW|SE|SW|N|S|E|W)?/?\s+## ) ; } # Obscuring Phenomena Aloft if( s#(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)? (FEW|SCT|BKN|OVC)(\d{3})\s+## ) { $ObscurAloft = padstr( "$1$2$3$4$5", 8 ) ; $ObscurAloftSkyCond = $6 ; $ObscurAloftHgt = $7 * 100 ; } # Air craft mishap ACFTMSHP $ACFTMSHP = 1 if( s#\(?ACFT\s?MSHP\)?\s+## ) ; # No changes in weather conditions until next report NOSPECI $NOSPECI = 1 if( s#NOSPECI\s+## ) ; # This is first report of the day FIRST $FIRST = 1 if( s#FIRST\s+## ) ; # This is last report in observation coverage LAST $LAST = 1 if( s#LAST\s+## ) ; # Cloud Types if( s# 8/(\d|/)(\d|/)(\d|/)/?\s+# # ) { $Cloud_low = $1 ; $Cloud_medium = $2 ; $Cloud_high = $3 ; } # Snow Increasing Rapidly SNINCR if( s#SNINCR (\d{1,3})/(\d{1,3})\s+## ) { $SNINCR = $1 ; $SNINCR_TotalDepth = $2 ; } # Snow depth on ground if( s# 4/(\d{1,3})\s+# # ) { $SN_depth = $1 ; } # Water equivalent of snow on ground $SN_waterequiv = $1 / 10 if( s# 933(\d{3})\s+# # ) ; # Duration of sunshine if( s# 98(\d{1,3}|///)\s+# # ) { if( $1 eq "///" ) { $SunSensorOut = 1 ; } else { $SunShineDur = $1 ; } } # Hourly precipitation amount $PRECIP_hourly = $1 / 100 if( s#P ?(\d{1,5})\s+## ) ; # Precipitation amount if( s# 6(\d{4}|////)\s+# # ) { $PRECIP_amt = $1 / 100 if( $1 ne "////" ) ; } # 24 Hour Precipitation amount if( s# 7(\d{4}|////)\s+# # ) { $PRECIP_24_amt = $1 / 100 if( $1 ne "////" ) ; } # Temperature and Dew Point if( s#T(0|1)(\d{3})(0|1)?(\d{3})?\s+## ) { if( $1 == 0 ) { $T_tenths = 0.1 * $2 ; } else { $T_tenths = -0.1 * $2 ; } if( defined( $3 ) && $3 == 0 ) { $TD_tenths = 0.1 * $4 ; } elsif( defined( $3 ) && $3 == 1 ) { $TD_tenths = -0.1 * $4 ; } else { $TD_tenths = $TD if( defined( $TD ) ) ; } } else { $T_tenths = $T if( defined( $T ) ) ; $TD_tenths = $TD if( defined( $TD ) ) ; } # Maximum Temperature if( s# 1(0|1|/)(\d{3}|///)\s+# # ) { $Tmax = $2 / 10 if( $2 ne "///" ) ; $Tmax *= -1.0 if( $1 == 1 ) ; } # Minimum Temperature if( s# 2(0|1|/)(\d{3}|///)\s+# # ) { $Tmin = $2 / 10 if( $2 ne "///" ) ; $Tmin *= -1.0 if( $1 == 1 ) ; } # 24-Hour Maximum and Minimum Temperature if( s# 4(0|1|/)(\d{3}|///)(0|1|/)(\d{3}|///)\s+# # ) { $Tmax24 = $2 / 10 if( $2 ne "///" ) ; $Tmax24 *= -1.0 if( $1 == 1 ) ; $Tmin24 = $4 / 10 if( $4 ne "///" ) ; $Tmin24 *= -1.0 if( $3 == 1 ) ; } # Presure Tendency if( s# 5(0|1|2|3|4|5|6|7|8)(\d{3}/?|///)\s+# # ) { $char_Ptend = $1 ; $Ptend = $2 / 10 if( $2 ne "///" ) ; } # Sensor Status Indicators # precipitation sensor not working PWINO $PWINO = 1 if( s#PWINO\s+## ) ; # Freezing Rain sensor not working FZRANO $FZRANO = 1 if( s#FZRANO\s+## ) ; # Lightning detection sensor not working TSNO $TSNO = 1 if( s#TSNO\s+## ) ; # Tipping bucket rain gauge is inoperative. $PNO = 1 if( s#PNO\s+## ) ; # Maintenance is needed on system Indicator $maintIndicator = 1 if( s#\$\s+## ) ; # Get Recent weather conditions with Beginning and Ending times, moved # because the RE are too general and they match wrongly # code table 4678 for( $i = 0; $i < 3; $i++ ) { if( s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(B\d{2,4})(E\d{2,4})\s+## ) { initReWX() if( $i == 0 ) ; $Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ; if( length( $6 ) == 5 ) { $Recent_WX_Bhh[ $i ] = substr( $6, 1, 2 ) * 1 ; $Recent_WX_Bmm[ $i ] = substr( $6, 3, 2 ) * 1 ; } elsif( length( $6 ) == 3 ) { $Recent_WX_Bmm[ $i ] = substr( $6, 1, 2 ) * 1 ; } if( length( $7 ) == 5 ) { $Recent_WX_Ehh[ $i ] = substr( $7, 1, 2 ) * 1 ; $Recent_WX_Emm[ $i ] = substr( $7, 3, 2 ) * 1 ; } elsif( length( $7 ) == 3 ) { $Recent_WX_Emm[ $i ] = substr( $7, 1, 2 ) * 1 ; } } elsif( s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(B|E)(\d{2,4})\s+## ) { initReWX() if( $i == 0 ) ; $Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ; if( $6 eq "B" && ( length( $7 ) == 4 )) { $Recent_WX_Bhh[ $i ] = substr( $7, 0, 2 ) * 1 ; $Recent_WX_Bmm[ $i ] = substr( $7, 2, 2 ) * 1 ; } elsif( $6 eq "B" && ( length( $7 ) == 2 )) { $Recent_WX_Bmm[ $i ] = substr( $7, 0, 2 ) * 1 ; } elsif( $6 eq "E" && ( length( $7 ) == 4 )) { $Recent_WX_Ehh[ $i ] = substr( $7, 0, 2 ) * 1 ; $Recent_WX_Emm[ $i ] = substr( $7, 2, 2 ) * 1 ; } elsif( $6 eq "E" && ( length( $7 ) == 2 )) { $Recent_WX_Emm[ $i ] = substr( $7, 0, 2 ) * 1 ; } } else { last ; } } # Plain Language remarks includes Volcanic eruptions $PlainText = padstr( $1, 128 ) if( s#(\w.*)## ) ; #print "Not decoded. $_ \n\n" if( $_ ) ; } # end doRemarks # convert cloud height to meters sub cloud_hgt2_meters { my( $value, $meters ) ; ( $value ) = @_ ; if( $value == 999 ) { $meters = 30000 ; } else { $meters = 30 * $value ; } } # end cloud_hgt2_meters # undefine all report vars sub undefinevars { # report vars undef( $wmo_id ) ; undef( $lat ) ; undef( $lon ) ; undef( $elev ) ; undef( $ob_hour ) ; undef( $ob_min ) ; undef( $ob_day ) ; undef( $time_obs ) ; undef( $time_nominal ) ; undef( $AUTO ) ; undef( $GUST ) ; undef( $VRB ) ; undef( $DIR ) ; undef( $SPD ) ; undef( $UNITS ) ; undef( $DIRmin ) ; undef( $DIRmax ) ; undef( $prevail_VIS_SM ) ; undef( $prevail_VIS_KM ) ; undef( $plus_VIS_SM ) ; undef( $plus_VIS_KM ) ; undef( $prevail_VIS_M ) ; undef( $VIS_dir ) ; undef( $CAVOK ) ; undef( $RVRNO ) ; undef( @RV_designator ) ; undef( @RV_above_max ) ; undef( @RV_below_min ) ; undef( @RV_vrbl ) ; undef( @RV_min ) ; undef( @RV_max ) ; undef( @RV_visRange ) ; undef( $WX ) ; undef( $vert_VIS ) ; undef( @cloud_type ) ; undef( @cloud_hgt ) ; undef( @cloud_meters ) ; undef( @cloud_phenom ) ; undef( $T ) ; undef( $TD ) ; undef( $inches_ALTIM ) ; undef( $hectoPasc_ALTIM ) ; undef( $NOSIG ) ; # remarks vars undef( $TornadicType ) ; undef( $TornadicLOC ) ; undef( $TornadicDIR ) ; undef( $BTornadic_hh ) ; undef( $BTornadic_mm ) ; undef( $ETornadic_hh ) ; undef( $ETornadic_mm ) ; undef( $AUTOindicator ) ; undef( $PKWND_dir ) ; undef( $PKWND_spd ) ; undef( $PKWND_hh ) ; undef( $PKWND_mm ) ; undef( $WshfTime_hh ) ; undef( $WshfTime_mm ) ; undef( $Wshft_FROPA ) ; undef( $VIS_TWR ) ; undef( $VIS_SFC ) ; undef( $VISmin ) ; undef( $VISmax ) ; undef( $VIS_2ndSite ) ; undef( $VIS_2ndSite_LOC ) ; undef( $LTG_OCNL ) ; undef( $LTG_FRQ ) ; undef( $LTG_CNS ) ; undef( $LTG_CG ) ; undef( $LTG_IC ) ; undef( $LTG_CC ) ; undef( $LTG_CA ) ; undef( $LTG_DSNT ) ; undef( $LTG_AP ) ; undef( $LTG_VcyStn ) ; undef( $LTG_DIR ) ; # Recent_WX ReWX[3]; undef( @Recent_WX ) ; undef( @Recent_WX_Bhh ) ; undef( @Recent_WX_Bmm ) ; undef( @Recent_WX_Ehh ) ; undef( @Recent_WX_Emm ) ; undef( $Ceiling_min ) ; undef( $Ceiling_max ) ; undef( $CIG_2ndSite_meters ) ; undef( $CIG_2ndSite_LOC ) ; undef( $PRESFR ) ; undef( $PRESRR ) ; undef( $SLPNO ) ; undef( $SLP ) ; undef( $SectorVIS_DIR ) ; undef( $SectorVIS ) ; undef( $GR ) ; undef( $GRsize ) ; undef( $VIRGA ) ; undef( $VIRGAdir ) ; undef( $SfcObscuration ) ; undef( $OctsSkyObscured ) ; undef( $CIGNO ) ; undef( $Ceiling_est ) ; undef( $Ceiling ) ; undef( $VrbSkyBelow ) ; undef( $VrbSkyLayerHgt ) ; undef( $VrbSkyAbove ) ; undef( $Sign_cloud ) ; undef( $Sign_dist ) ; undef( $Sign_dir ) ; undef( $ObscurAloft ) ; undef( $ObscurAloftSkyCond ) ; undef( $ObscurAloftHgt ) ; undef( $ACFTMSHP ) ; undef( $NOSPECI ) ; undef( $FIRST ) ; undef( $LAST ) ; undef( $Cloud_low ) ; undef( $Cloud_medium ) ; undef( $Cloud_high ) ; undef( $SNINCR ) ; undef( $SNINCR_TotalDepth ) ; undef( $SN_depth ) ; undef( $SN_waterequiv ) ; undef( $SunSensorOut ) ; undef( $SunShineDur ) ; undef( $PRECIP_hourly ) ; undef( $PRECIP_amt ) ; undef( $PRECIP_24_amt ) ; undef( $T_tenths ) ; undef( $TD_tenths ) ; undef( $Tmax ) ; undef( $Tmin ) ; undef( $Tmax24 ) ; undef( $Tmin24 ) ; undef( $char_Ptend ) ; undef( $Ptend ) ; undef( $PWINO ) ; undef( $FZRANO ) ; undef( $TSNO ) ; undef( $PNO ) ; undef( $maintIndicator ) ; undef( $PlainText ) ; } # end of undefinevARS # setvars into record sub setvars { $remarks = padstr( $remarks, 128 ) if( defined( $remarks ) ) ; $report = padstr( $report, 128 ) ; undef( @dataref ) ; @dataref = @rec ; # report vars $dataref[ $W[ 0 ] ] = \$rep_type if( $W[ 0 ] != -1 ) ; $dataref[ $W[ 1 ] ] = \$stn_name ; $dataref[ $W[ 2 ] ] = \$wmo_id if( $W[ 2 ] && defined( $wmo_id ) ) ; $dataref[ $W[ 3 ] ] = \$lat if( $W[ 3 ] && defined( $lat ) ) ; $dataref[ $W[ 4 ] ] = \$lon if( $W[ 4 ] && defined( $lon ) ) ; $dataref[ $W[ 5 ] ] = \$elev if( $W[ 5 ] && defined( $elev ) ) ; $dataref[ $W[ 6 ] ] = \$ob_hour if( $W[ 6 ] ) ; $dataref[ $W[ 7 ] ] = \$ob_min if( $W[ 7 ] ) ; $dataref[ $W[ 8 ] ] = \$ob_day if( $W[ 8 ] && defined( $ob_day ) ) ; $dataref[ $W[ 9 ] ] = \$time_obs if( $W[ 9 ] && defined( $time_obs ) ) ; $dataref[ $W[ 10 ] ] = \$time_nominal if( $W[ 10 ] && defined( $time_nominal )); $dataref[ $W[ 11 ] ] = \$AUTO if( $W[ 11 ] && defined( $AUTO ) ) ; $dataref[ $W[ 12 ] ] = \$UNITS if( $W[ 12 ] && defined( $UNITS ) ) ; $dataref[ $W[ 13 ] ] = \$DIR if( $W[ 13 ] && defined( $DIR ) ) ; $dataref[ $W[ 14 ] ] = \$SPD if( $W[ 14 ] && defined( $SPD ) ) ; $dataref[ $W[ 15 ] ] = \$GUST if( $W[ 15 ] && defined( $GUST ) ) ; $dataref[ $W[ 16 ] ] = \$VRB if( $W[ 16 ] && defined( $VRB ) ) ; $dataref[ $W[ 17 ] ] = \$DIRmin if( $W[ 17 ] && defined( $DIRmin ) ) ; $dataref[ $W[ 18 ] ] = \$DIRmax if( $W[ 18 ] && defined( $DIRmax ) ) ; $dataref[ $W[ 19 ] ] = \$prevail_VIS_SM if( $W[ 19 ] && defined( $prevail_VIS_SM ) ) ; $dataref[ $W[ 20 ] ] = \$prevail_VIS_KM if( $W[ 20 ] && defined( $prevail_VIS_KM ) ) ; $dataref[ $W[ 21 ] ] = \$plus_VIS_SM if( $W[ 21 ] && defined( $plus_VIS_SM ) ) ; $dataref[ $W[ 22 ] ] = \$plus_VIS_KM if( $W[ 22 ] && defined( $plus_VIS_KM ) ) ; $dataref[ $W[ 23 ] ] = \$prevail_VIS_M if( $W[ 23 ] && defined( $prevail_VIS_M ) ) ; $dataref[ $W[ 24 ] ] = \$VIS_dir if( $W[ 24 ] && defined( $VIS_dir ) ) ; $dataref[ $W[ 25 ] ] = \$CAVOK if( $W[ 25 ] && defined( $CAVOK ) ) ; $dataref[ $W[ 26 ] ] = \$RVRNO if( $W[ 26 ] && defined( $RVRNO ) ) ; $dataref[ $W[ 27 ] ] = \@RV_designator if( $W[ 27 ] && defined( @RV_designator ) ) ; $dataref[ $W[ 28 ] ] = \@RV_above_max if( $W[ 28 ] && defined( @RV_above_max ) ) ; $dataref[ $W[ 29 ] ] = \@RV_below_min if( $W[ 29 ] && defined( @RV_below_min ) ) ; $dataref[ $W[ 30 ] ] = \@RV_vrbl if( $W[ 30 ] && defined( @RV_vrbl ) ) ; $dataref[ $W[ 31 ] ] = \@RV_min if( $W[ 31 ] && defined( @RV_min ) ) ; $dataref[ $W[ 32 ] ] = \@RV_max if( $W[ 32 ] && defined( @RV_max ) ) ; $dataref[ $W[ 33 ] ] = \@RV_visRange if( $W[ 33 ] && defined( @RV_visRange ) ) ; $dataref[ $W[ 34 ] ] = \$WX if( $W[ 34 ] && defined( $WX ) ) ; $dataref[ $W[ 35 ] ] = \$vert_VIS if( $W[ 35 ] && defined( $vert_VIS ) ) ; $dataref[ $W[ 36 ] ] = \@cloud_type if( $W[ 36 ] && defined( @cloud_type ) ) ; $dataref[ $W[ 37 ] ] = \@cloud_hgt if( $W[ 37 ] && defined( @cloud_hgt ) ) ; $dataref[ $W[ 38 ] ] = \@cloud_meters if( $W[ 38 ] && defined( @cloud_meters )); $dataref[ $W[ 39 ] ] = \@cloud_phenom if( $W[ 39 ] && defined( @cloud_phenom )); $dataref[ $W[ 40 ] ] = \$T if( $W[ 40 ] && defined( $T ) ) ; $dataref[ $W[ 41 ] ] = \$TD if( $W[ 41 ] && defined( $TD ) ) ; $dataref[ $W[ 42 ] ] = \$hectoPasc_ALTIM if( $W[ 42 ] && defined( $hectoPasc_ALTIM ) ) ; $dataref[ $W[ 43 ] ] = \$inches_ALTIM if( $W[ 43 ] && defined( $inches_ALTIM )); $dataref[ $W[ 44 ] ] = \$NOSIG if( $W[ 44 ] && defined( $NOSIG ) ) ; # remarks vars $dataref[ $W[ 45 ] ] = \$TornadicType if( $W[ 45 ] && defined( $TornadicType )); $dataref[ $W[ 46 ] ] = \$TornadicLOC if( $W[ 46 ] && defined( $TornadicLOC ) ) ; $dataref[ $W[ 47 ] ] = \$TornadicDIR if( $W[ 47 ] && defined( $TornadicDIR ) ) ; $dataref[ $W[ 48 ] ] = \$BTornadic_hh if( $W[ 48 ] && defined( $BTornadic_hh )); $dataref[ $W[ 49 ] ] = \$BTornadic_mm if( $W[ 49 ] && defined( $BTornadic_mm )); $dataref[ $W[ 50 ] ] = \$ETornadic_hh if( $W[ 50 ] && defined( $ETornadic_hh )); $dataref[ $W[ 51 ] ] = \$ETornadic_mm if( $W[ 51 ] && defined( $ETornadic_mm )); $dataref[ $W[ 52 ] ] = \$AUTOindicator if( $W[ 52 ] && defined($AUTOindicator)); $dataref[ $W[ 53 ] ] = \$PKWND_dir if( $W[ 53 ] && defined( $PKWND_dir ) ) ; $dataref[ $W[ 54 ] ] = \$PKWND_spd if( $W[ 54 ] && defined( $PKWND_spd ) ) ; $dataref[ $W[ 55 ] ] = \$PKWND_hh if( $W[ 55 ] && defined( $PKWND_hh ) ) ; $dataref[ $W[ 56 ] ] = \$PKWND_mm if( $W[ 56 ] && defined( $PKWND_mm ) ) ; $dataref[ $W[ 57 ] ] = \$WshfTime_hh if( $W[ 57 ] && defined( $WshfTime_hh ) ) ; $dataref[ $W[ 58 ] ] = \$WshfTime_mm if( $W[ 58 ] && defined( $WshfTime_mm ) ) ; $dataref[ $W[ 59 ] ] = \$Wshft_FROPA if( $W[ 59 ] && defined( $Wshft_FROPA ) ) ; $dataref[ $W[ 60 ] ] = \$VIS_TWR if( $W[ 60 ] && defined( $VIS_TWR ) ) ; $dataref[ $W[ 61 ] ] = \$VIS_SFC if( $W[ 61 ] && defined( $VIS_SFC ) ) ; $dataref[ $W[ 62 ] ] = \$VISmin if( $W[ 62 ] && defined( $VISmin ) ) ; $dataref[ $W[ 63 ] ] = \$VISmax if( $W[ 63 ] && defined( $VISmax ) ) ; $dataref[ $W[ 64 ] ] = \$VIS_2ndSite if( $W[ 64 ] && defined( $VIS_2ndSite ) ) ; $dataref[ $W[ 65 ] ] = \$VIS_2ndSite_LOC if( $W[ 65 ] && defined( $VIS_2ndSite_LOC ) ) ; $dataref[ $W[ 66 ] ] = \$LTG_OCNL if( $W[ 66 ] && defined( $LTG_OCNL ) ) ; $dataref[ $W[ 67 ] ] = \$LTG_FRQ if( $W[ 67 ] && defined( $LTG_FRQ ) ) ; $dataref[ $W[ 68 ] ] = \$LTG_CNS if( $W[ 68 ] && defined( $LTG_CNS ) ) ; $dataref[ $W[ 69 ] ] = \$LTG_CG if( $W[ 69 ] && defined( $LTG_CG ) ) ; $dataref[ $W[ 70 ] ] = \$LTG_IC if( $W[ 70 ] && defined( $LTG_IC ) ) ; $dataref[ $W[ 71 ] ] = \$LTG_CC if( $W[ 71 ] && defined( $LTG_CC ) ) ; $dataref[ $W[ 72 ] ] = \$LTG_CA if( $W[ 72 ] && defined( $LTG_CA ) ) ; $dataref[ $W[ 73 ] ] = \$LTG_DSNT if( $W[ 73 ] && defined( $LTG_DSNT ) ) ; $dataref[ $W[ 74 ] ] = \$LTG_AP if( $W[ 74 ] && defined( $LTG_AP ) ) ; $dataref[ $W[ 75 ] ] = \$LTG_VcyStn if( $W[ 75 ] && defined( $LTG_VcyStn ) ) ; $dataref[ $W[ 76 ] ] = \$LTG_DIR if( $W[ 76 ] && defined( $LTG_DIR ) ) ; # Recent_WX ReWX[3]; $dataref[ $W[ 77 ] ] = \@Recent_WX if( $W[ 77 ] && defined( @Recent_WX ) ) ; $dataref[ $W[ 78 ] ] = \@Recent_WX_Bhh if( $W[ 78 ] && defined( @Recent_WX_Bhh ) ) ; $dataref[ $W[ 79 ] ] = \@Recent_WX_Bmm if( $W[ 79 ] && defined( @Recent_WX_Bmm ) ) ; $dataref[ $W[ 80 ] ] = \@Recent_WX_Ehh if( $W[ 80 ] && defined( @Recent_WX_Ehh ) ) ; $dataref[ $W[ 81 ] ] = \@Recent_WX_Emm if( $W[ 81 ] && defined( @Recent_WX_Emm ) ) ; $dataref[ $W[ 82 ] ] = \$Ceiling_min if( $W[ 82 ] && defined( $Ceiling_min ) ) ; $dataref[ $W[ 83 ] ] = \$Ceiling_max if( $W[ 83 ] && defined( $Ceiling_max ) ) ; $dataref[ $W[ 84 ] ] = \$CIG_2ndSite_meters if( $W[ 83 ] && defined( $CIG_2ndSite_meters ) ) ; $dataref[ $W[ 85 ] ] = \$CIG_2ndSite_LOC if( $W[ 85 ] && defined( $CIG_2ndSite_LOC ) ) ; $dataref[ $W[ 86 ] ] = \$PRESFR if( $W[ 86 ] && defined( $PRESFR ) ) ; $dataref[ $W[ 87 ] ] = \$PRESRR if( $W[ 87 ] && defined( $PRESRR ) ) ; $dataref[ $W[ 88 ] ] = \$SLPNO if( $W[ 88 ] && defined( $SLPNO ) ) ; $dataref[ $W[ 89 ] ] = \$SLP if( $W[ 89 ] && defined( $SLP ) ) ; $dataref[ $W[ 90 ] ] = \$SectorVIS_DIR if( $W[ 90 ] && defined( $SectorVIS_DIR ) ) ; $dataref[ $W[ 91 ] ] = \$SectorVIS if( $W[ 91 ] && defined( $SectorVIS ) ) ; $dataref[ $W[ 92 ] ] = \$GR if( $W[ 92 ] && defined( $GR ) ) ; $dataref[ $W[ 93 ] ] = \$GRsize if( $W[ 93 ] && defined( $GRsize ) ) ; $dataref[ $W[ 94 ] ] = \$VIRGA if( $W[ 94 ] && defined( $VIRGA ) ) ; $dataref[ $W[ 95 ] ] = \$VIRGAdir if( $W[ 95 ] && defined( $VIRGAdir ) ) ; $dataref[ $W[ 96 ] ] = \$SfcObscuration if( $W[ 96 ] && defined( $SfcObscuration ) ) ; $dataref[ $W[ 97 ] ] = \$OctsSkyObscured if( $W[ 97 ] && defined( $OctsSkyObscured ) ) ; $dataref[ $W[ 98 ] ] = \$CIGNO if( $W[ 98 ] && defined( $CIGNO ) ) ; $dataref[ $W[ 99 ] ] = \$Ceiling_est if( $W[ 99 ] && defined( $Ceiling_est ) ) ; $dataref[ $W[ 100 ] ] = \$Ceiling if( $W[ 100 ] && defined( $Ceiling ) ) ; $dataref[ $W[ 101 ] ] = \$VrbSkyBelow if( $W[ 101 ] && defined( $VrbSkyBelow )); $dataref[ $W[ 102 ] ] = \$VrbSkyLayerHgt if( $W[ 102 ] && defined( $VrbSkyLayerHgt ) ) ; $dataref[ $W[ 103 ] ] = \$VrbSkyAbove if( $W[ 103 ] && defined( $VrbSkyAbove ) ) ; $dataref[ $W[ 104 ] ] = \$Sign_cloud if( $W[ 104 ] && defined( $Sign_cloud ) ) ; $dataref[ $W[ 105 ] ] = \$Sign_dist if( $W[ 105 ] && defined( $Sign_dist ) ) ; $dataref[ $W[ 106 ] ] = \$Sign_dir if( $W[ 106 ] && defined( $Sign_dir ) ) ; $dataref[ $W[ 107 ] ] = \$ObscurAloft if( $W[ 107 ] && defined( $ObscurAloft )); $dataref[ $W[ 108 ] ] = \$ObscurAloftSkyCond if( $W[ 108 ] && defined( $ObscurAloftSkyCond ) ) ; $dataref[ $W[ 109 ] ] = \$ObscurAloftHgt if( $W[ 109 ] && defined( $ObscurAloftHgt ) ) ; $dataref[ $W[ 110 ] ] = \$ACFTMSHP if( $W[ 110 ] && defined( $ACFTMSHP ) ) ; $dataref[ $W[ 111 ] ] = \$NOSPECI if( $W[ 111 ] && defined( $NOSPECI ) ) ; $dataref[ $W[ 112 ] ] = \$FIRST if( $W[ 112 ] && defined( $FIRST ) ) ; $dataref[ $W[ 113 ] ] = \$LAST if( $W[ 113 ] && defined( $LAST ) ) ; $dataref[ $W[ 114 ] ] = \$Cloud_low if( $W[ 114 ] && defined( $Cloud_low ) ) ; $dataref[ $W[ 115 ] ] = \$Cloud_medium if( $W[ 115 ] && defined( $Cloud_medium ) ) ; $dataref[ $W[ 116 ] ] = \$Cloud_high if( $W[ 116 ] && defined( $Cloud_high ) ) ; $dataref[ $W[ 117 ] ] = \$SNINCR if( $W[ 117 ] && defined( $SNINCR ) ) ; $dataref[ $W[ 118 ] ] = \$SNINCR_TotalDepth if( $W[ 118 ] && defined( $SNINCR_TotalDepth ) ) ; $dataref[ $W[ 119 ] ] = \$SN_depth if( $W[ 119 ] && defined( $SN_depth ) ) ; $dataref[ $W[ 120 ] ] = \$SN_waterequiv if( $W[ 120 ] && defined( $SN_waterequiv ) ) ; $dataref[ $W[ 121 ] ] = \$SunSensorOut if( $W[ 121 ] && defined( $SunSensorOut ) ) ; $dataref[ $W[ 122 ] ] = \$SunShineDur if( $W[ 122 ] && defined( $SunShineDur )); $dataref[ $W[ 123 ] ] = \$PRECIP_hourly if( $W[ 123 ] && defined( $PRECIP_hourly ) ) ; $dataref[ $W[ 124 ] ] = \$PRECIP_amt if( $W[ 124 ] && defined( $PRECIP_amt ) ) ; $dataref[ $W[ 125 ] ] = \$PRECIP_24_amt if( $W[ 125 ] && defined( $PRECIP_24_amt ) ) ; $dataref[ $W[ 126 ] ] = \$T_tenths if( $W[ 126 ] && defined( $T_tenths ) ) ; $dataref[ $W[ 127 ] ] = \$TD_tenths if( $W[ 127 ] && defined( $TD_tenths ) ) ; $dataref[ $W[ 128 ] ] = \$Tmax if( $W[ 128 ] && defined( $Tmax ) ) ; $dataref[ $W[ 129 ] ] = \$Tmin if( $W[ 129 ] && defined( $Tmin ) ) ; $dataref[ $W[ 130 ] ] = \$Tmax24 if( $W[ 130 ] && defined( $Tmax24 ) ) ; $dataref[ $W[ 131 ] ] = \$Tmin24 if( $W[ 131 ] && defined( $Tmin24 ) ) ; $dataref[ $W[ 132 ] ] = \$char_Ptend if( $W[ 132 ] && defined( $char_Ptend ) ) ; $dataref[ $W[ 133 ] ] = \$Ptend if( $W[ 133 ] && defined( $Ptend ) ) ; $dataref[ $W[ 134 ] ] = \$PWINO if( $W[ 134 ] && defined( $PWINO ) ) ; $dataref[ $W[ 135 ] ] = \$FZRANO if( $W[ 135 ] && defined( $FZRANO ) ) ; $dataref[ $W[ 136 ] ] = \$TSNO if( $W[ 136 ] && defined( $TSNO ) ) ; $dataref[ $W[ 137 ] ] = \$PNO if( $W[ 137 ] && defined( $PNO ) ) ; $dataref[ $W[ 138 ] ] = \$maintIndicator if( $W[ 138 ] && defined( $maintIndicator ) ) ; $dataref[ $W[ 139 ] ] = \$PlainText if( $W[ 139 ] && defined( $PlainText ) ) ; # original report and remarks $dataref[ $W[ 140 ] ] = \$report if( $W[ 140 ] && defined( $report ) ) ; $dataref[ $W[ 141 ] ] = \$remarks if( $W[ 141 ] && defined( $remarks ) ) ; } # end setvars # create a netcdf file or reopen a existing one sub doNet { my( $hour, $file, $Id, $Num, $Time, $stn, $hr, $i ) ; ( $hour ) = @_ ; $ncfile = $datadir . "/" . $yymmdd . $hour . "_metar.nc" ; $metafile = $metadir . "/" . $yymmdd . $hour . "_metar.meta" ; # writing to same file return 1 if( $ncfile eq $lastNc ) ; # current time $thetime = time() ; # save current file info $Nets{ $lastNc } = "$ncid $recnum $thetime" if( $lastNc ) ; # File is open, get ncfile id and recnum and reset the time if( defined( $Nets{ $ncfile } ) ) { # already open for writes ( $ncid, $recnum, $ncTime ) = split( " ", $Nets{ $ncfile } ) ; $ncTime = $thetime ; $lastNc = $ncfile ; return 1 ; } # close files with no activity for 20 minutes foreach $file ( keys %Nets ) { ( $Id, $Num, $Time ) = split( " ", $Nets{ $file } ) ; if( $thetime - $Time > 1200 ) { print "Closing $file with ncid $Id, No write for > 1200 Sec\n" ; $result = NetCDF::close( $Id ) ; delete( $Nets{ $file } ) ; } else { $result = NetCDF::sync( $Id ) ; } } # remove stn entries older than 4 hours foreach $stn ( keys %reportslist ) { ( $hr ) = $reportslist{ $stn } ; $hr = abs( $hour - $hr ) ; delete( $reportslist{ $stn } ) if( $hr > 3 && $hr < 21 ) ; } # open or create ncfiles if( -e $ncfile ) { $ncid = NetCDF::open( "$ncfile", WRITE ) ; $recNum_id = NetCDF::dimid( $ncid, "recNum" ) ; $name_id = "xxxxxxxx" ; $recnum = -1 ; # get current value of recnum NetCDF::diminq( $ncid, $recNum_id, $name_id, $recnum ) ; } else { die "Wrong or missing cdlfile parameter: $!\n" unless -e $cdlfile ; system( "mkdir -p $datadir" ) if( ! -e $datadir ) ; system( "$ncgen -o $ncfile $cdlfile" ) ; $ncid = NetCDF::open( "$ncfile", WRITE ) ; # NetCDF record counter $recnum = 0 ; # create metadata file and populate print "metar metadata file = $metafile\n" ; open( META, ">$metafile" ) ; close META ; } $Nets{ $ncfile } = "$ncid $recnum $thetime" ; $lastNc = $ncfile ; print "Opening $ncfile with ncid $ncid\n" ; # check for to many files open if( $ncid > 25 ) { foreach $file ( keys %Nets ) { ( $Id, $Num, $Time ) = split( " ", $Nets{ $file } ) ; if( $ncid != $Id ) { print "Closing $file with Id $Id, To many open files\n" ; $result = NetCDF::close( $Id ) ; delete( $Nets{ $file } ) ; } } } return 1 ; } # end doNet # print vars sub printvars { # original report and remarks print "report = $report \n" if( defined( $report ) ) ; print "remarks = $remarks \n" if( defined( $remarks ) ) ; print "\n" ; # report vars print "rep_type = $rep_type \n" if( defined( $rep_type ) ) ; print "stn_name = $stn_name \n" if( defined( $stn_name ) ) ; print "wmo_id = $wmo_id \n" if( defined( $wmo_id ) ) ; print "lat = $lat \n" if( defined( $lat ) ) ; print "lon = $lon \n" if( defined( $lon ) ) ; print "elev = $elev \n" if( defined( $elev ) ) ; print "ob_hour = $ob_hour \n" if( defined( $ob_hour ) ) ; print "ob_min = $ob_min \n" if( defined( $ob_min ) ) ; print "ob_day = $ob_day \n" if( defined( $ob_day ) ) ; print "time_obs = $time_obs \n" if( defined( $time_obs ) ) ; print "time_nominal = $time_nominal \n" if( defined( $time_nominal ) ) ; print "AUTO = $AUTO \n" if( defined( $AUTO ) ) ; print "GUST = $GUST \n" if( defined( $GUST ) ) ; print "VRB = $VRB \n" if( defined( $VRB ) ) ; print "DIR = $DIR \n" if( defined( $DIR ) ) ; print "SPD = $SPD \n" if( defined( $SPD ) ) ; print "UNITS = $UNITS \n" if( defined( $UNITS ) ) ; print "DIRmin = $DIRmin \n" if( defined( $DIRmin ) ) ; print "DIRmax = $DIRmax \n" if( defined( $DIRmax ) ) ; print "prevail_VIS_SM = $prevail_VIS_SM \n" if( defined( $prevail_VIS_SM ) ) ; print "prevail_VIS_KM = $prevail_VIS_KM \n" if( defined( $prevail_VIS_KM ) ) ; print "plus_VIS_SM = $plus_VIS_SM \n" if( defined( $plus_VIS_SM ) ) ; print "plus_VIS_KM = $plus_VIS_KM \n" if( defined( $plus_VIS_KM ) ) ; print "prevail_VIS_M = $prevail_VIS_M \n" if( defined( $prevail_VIS_M ) ) ; print "VIS_dir = $VIS_dir \n" if( defined( $VIS_dir ) ) ; print "CAVOK = $CAVOK \n" if( defined( $CAVOK ) ) ; print "RVRNO = $RVRNO \n" if( defined( $RVRNO ) ) ; print "RV_designator = @RV_designator \n" if( defined( @RV_designator ) ) ; print "RV_above_max = @RV_above_max \n" if( defined( @RV_above_max ) ) ; print "RV_below_min = @RV_below_min \n" if( defined( @RV_below_min ) ) ; print "RV_vrbl = @RV_vrbl \n" if( defined( @RV_vrbl ) ) ; print "RV_min = @RV_min \n" if( defined( @RV_min ) ) ; print "RV_max = @RV_max \n" if( defined( @RV_max ) ) ; print "RV_visRange = @RV_visRange \n" if( defined( @RV_visRange ) ) ; print "WX = $WX \n" if( defined( $WX ) ) ; print "vert_VIS = $vert_VIS \n" if( defined( $vert_VIS ) ) ; print "cloud_type = @cloud_type \n" if( defined( @cloud_type ) ) ; print "cloud_hgt = @cloud_hgt \n" if( defined( @cloud_hgt ) ) ; print "cloud_meters = @cloud_meters \n" if( defined( @cloud_meters ) ) ; print "cloud_phenom = @cloud_phenom \n" if( defined( @cloud_phenom ) ) ; print "T = $T \n" if( defined( $T ) ) ; print "TD = $TD \n" if( defined( $TD ) ) ; print "inches_ALTIM = $inches_ALTIM \n" if( defined( $inches_ALTIM ) ) ; print "hectoPasc_ALTIM = $hectoPasc_ALTIM \n" if( defined( $hectoPasc_ALTIM )) ; print "NOSIG = $NOSIG \n" if( defined( $NOSIG ) ) ; # remarks vars print "\n" ; #print "remarks = $remarks \n" if( defined( $remarks ) ) ; #print "\n" ; print "TornadicType = $TornadicType \n" if( defined( $TornadicType ) ) ; print "TornadicLOC = $TornadicLOC \n" if( defined( $TornadicLOC ) ) ; print "TornadicDIR = $TornadicDIR \n" if( defined( $TornadicDIR ) ) ; print "BTornadic_hh = $BTornadic_hh \n" if( defined( $BTornadic_hh ) ) ; print "BTornadic_mm = $BTornadic_mm \n" if( defined( $BTornadic_mm ) ) ; print "ETornadic_hh = $ETornadic_hh \n" if( defined( $ETornadic_hh ) ) ; print "ETornadic_mm = $ETornadic_mm \n" if( defined( $ETornadic_mm ) ) ; print "AUTOindicator = $AUTOindicator \n" if( defined( $AUTOindicator ) ) ; print "PKWND_dir = $PKWND_dir \n" if( defined( $PKWND_dir ) ) ; print "PKWND_spd = $PKWND_spd \n" if( defined( $PKWND_spd ) ) ; print "PKWND_hh = $PKWND_hh \n" if( defined( $PKWND_hh ) ) ; print "PKWND_mm = $PKWND_mm \n" if( defined( $PKWND_mm ) ) ; print "WshfTime_hh = $WshfTime_hh \n" if( defined( $WshfTime_hh ) ) ; print "WshfTime_mm = $WshfTime_mm \n" if( defined( $WshfTime_mm ) ) ; print "Wshft_FROPA = $Wshft_FROPA \n" if( defined( $Wshft_FROPA ) ) ; print "VIS_TWR = $VIS_TWR \n" if( defined( $VIS_TWR ) ) ; print "VIS_SFC = $VIS_SFC \n" if( defined( $VIS_SFC ) ) ; print "VISmin = $VISmin \n" if( defined( $VISmin ) ) ; print "VISmax = $VISmax \n" if( defined( $VISmax ) ) ; print "VIS_2ndSite = $VIS_2ndSite \n" if( defined( $VIS_2ndSite ) ) ; print "VIS_2ndSite_LOC = $VIS_2ndSite_LOC \n" if( defined( $VIS_2ndSite_LOC )) ; print "LTG_OCNL = $LTG_OCNL \n" if( defined( $LTG_OCNL ) ) ; print "LTG_FRQ = $LTG_FRQ \n" if( defined( $LTG_FRQ ) ) ; print "LTG_CNS = $LTG_CNS \n" if( defined( $LTG_CNS ) ) ; print "LTG_CG = $LTG_CG \n" if( defined( $LTG_CG ) ) ; print "LTG_IC = $LTG_IC \n" if( defined( $LTG_IC ) ) ; print "LTG_CC = $LTG_CC \n" if( defined( $LTG_CC ) ) ; print "LTG_CA = $LTG_CA \n" if( defined( $LTG_CA ) ) ; print "LTG_DSNT = $LTG_DSNT \n" if( defined( $LTG_DSNT ) ) ; print "LTG_AP = $LTG_AP \n" if( defined( $LTG_AP ) ) ; print "LTG_VcyStn = $LTG_VcyStn \n" if( defined( $LTG_VcyStn ) ) ; print "LTG_DIR = $LTG_DIR \n" if( defined( $LTG_DIR ) ) ; # Recent_WX ReWX[3]; print "Recent_WX = @Recent_WX \n" if( defined( @Recent_WX ) ) ; print "Recent_WX_Bhh = @Recent_WX_Bhh \n" if( defined( @Recent_WX_Bhh ) ) ; print "Recent_WX_Bmm = @Recent_WX_Bmm \n" if( defined( @Recent_WX_Bmm ) ) ; print "Recent_WX_Ehh = @Recent_WX_Ehh \n" if( defined( @Recent_WX_Ehh ) ) ; print "Recent_WX_Emm = @Recent_WX_Emm \n" if( defined( @Recent_WX_Emm ) ) ; print "Ceiling_min = $Ceiling_min \n" if( defined( $Ceiling_min ) ) ; print "Ceiling_max = $Ceiling_max \n" if( defined( $Ceiling_max ) ) ; print "CIG_2ndSite_meters = $CIG_2ndSite_meters \n" if( defined( $CIG_2ndSite_meters ) ) ; print "CIG_2ndSite_LOC = $CIG_2ndSite_LOC \n" if( defined( $CIG_2ndSite_LOC )) ; print "PRESFR = $PRESFR \n" if( defined( $PRESFR ) ) ; print "PRESRR = $PRESRR \n" if( defined( $PRESRR ) ) ; print "SLPNO = $SLPNO \n" if( defined( $SLPNO ) ) ; print "SLP = $SLP \n" if( defined( $SLP ) ) ; print "SectorVIS_DIR = $SectorVIS_DIR \n" if( defined( $SectorVIS_DIR ) ) ; print "SectorVIS = $SectorVIS \n" if( defined( $SectorVIS ) ) ; print "GR = $GR \n" if( defined( $GR ) ) ; print "GRsize = $GRsize \n" if( defined( $GRsize ) ) ; print "VIRGA = $VIRGA \n" if( defined( $VIRGA ) ) ; print "VIRGAdir = $VIRGAdir \n" if( defined( $VIRGAdir ) ) ; print "SfcObscuration = $SfcObscuration \n" if( defined( $SfcObscuration ) ) ; print "OctsSkyObscured = $OctsSkyObscured \n" if( defined( $OctsSkyObscured )) ; print "CIGNO = $CIGNO \n" if( defined( $CIGNO ) ) ; print "Ceiling_est = $Ceiling_est \n" if( defined( $Ceiling_est ) ) ; print "Ceiling = $Ceiling \n" if( defined( $Ceiling ) ) ; print "VrbSkyBelow = $VrbSkyBelow \n" if( defined( $VrbSkyBelow ) ) ; print "VrbSkyLayerHgt = $VrbSkyLayerHgt \n" if( defined( $VrbSkyLayerHgt ) ) ; print "VrbSkyAbove = $VrbSkyAbove \n" if( defined( $VrbSkyAbove ) ) ; print "Sign_cloud = $Sign_cloud \n" if( defined( $Sign_cloud ) ) ; print "Sign_dist = $Sign_dist \n" if( defined( $Sign_dist ) ) ; print "Sign_dir = $Sign_dir \n" if( defined( $Sign_dir ) ) ; print "ObscurAloft = $ObscurAloft \n" if( defined( $ObscurAloft ) ) ; print "ObscurAloftSkyCond = $ObscurAloftSkyCond \n" if( defined( $ObscurAloftSkyCond ) ) ; print "ObscurAloftHgt = $ObscurAloftHgt \n" if( defined( $ObscurAloftHgt ) ) ; print "ACFTMSHP = $ACFTMSHP \n" if( defined( $ACFTMSHP ) ) ; print "NOSPECI = $NOSPECI \n" if( defined( $NOSPECI ) ) ; print "FIRST = $FIRST \n" if( defined( $FIRST ) ) ; print "LAST = $LAST \n" if( defined( $LAST ) ) ; print "Cloud_low = $Cloud_low \n" if( defined( $Cloud_low ) ) ; print "Cloud_medium = $Cloud_medium \n" if( defined( $Cloud_medium ) ) ; print "Cloud_high = $Cloud_high \n" if( defined( $Cloud_high ) ) ; print "SNINCR = $SNINCR \n" if( defined( $SNINCR ) ) ; print "SNINCR_TotalDepth = $SNINCR_TotalDepth \n" if( defined( $SNINCR_TotalDepth ) ) ; print "SN_depth = $SN_depth \n" if( defined( $SN_depth ) ) ; print "SN_waterequiv = $SN_waterequiv \n" if( defined( $SN_waterequiv ) ) ; print "SunSensorOut = $SunSensorOut \n" if( defined( $SunSensorOut ) ) ; print "SunShineDur = $SunShineDur \n" if( defined( $SunShineDur ) ) ; print "PRECIP_hourly = $PRECIP_hourly \n" if( defined( $PRECIP_hourly ) ) ; print "PRECIP_amt = $PRECIP_amt \n" if( defined( $PRECIP_amt ) ) ; print "PRECIP_24_amt = $PRECIP_24_amt \n" if( defined( $PRECIP_24_amt ) ) ; print "T_tenths = $T_tenths \n" if( defined( $T_tenths ) ) ; print "TD_tenths = $TD_tenths \n" if( defined( $TD_tenths ) ) ; print "Tmax = $Tmax \n" if( defined( $Tmax ) ) ; print "Tmin = $Tmin \n" if( defined( $Tmin ) ) ; print "Tmax24 = $Tmax24 \n" if( defined( $Tmax24 ) ) ; print "Tmin24 = $Tmin24 \n" if( defined( $Tmin24 ) ) ; print "char_Ptend = $char_Ptend \n" if( defined( $char_Ptend ) ) ; print "Ptend = $Ptend \n" if( defined( $Ptend ) ) ; print "PWINO = $PWINO \n" if( defined( $PWINO ) ) ; print "FZRANO = $FZRANO \n" if( defined( $FZRANO ) ) ; print "TSNO = $TSNO \n" if( defined( $TSNO ) ) ; print "PNO = $PNO \n" if( defined( $PNO ) ) ; print "maintIndicator = $maintIndicator \n" if( defined( $maintIndicator ) ) ; print "PlainText Language = $PlainText \n" if( defined( $PlainText ) ) ; print "\n" ; } # end printvars # execute at exit sub atexit { local( $sig ) = @_ ; if( $sig eq "eof" ) { print "eof on STDIN --shutting down\n" ; } elsif( defined( $sig )) { print "Caught SIG$sig --shutting down\n" ; } # open metar.lst, list of reports processed in the last 4 hours. open( LST, ">$datadir/metar.lst" ) || die "could not open $datadir/metar.lst: $!\n" ; select( LST ) ; # remove stn entries older than 4 hours foreach $stn ( keys %reportslist ) { ( $hr ) = $reportslist{ $stn } ; $hr = abs( $hour - $hr ) ; print "$stn $reportslist{ $stn }\n" if( !( $hr > 3 && $hr < 21 ) ) ; } close LST ; foreach $file ( keys %Nets ) { ( $ncid, $recnum, $nctime ) = split( " ", $Nets{ $file } ) ; print STDOUT "Closing $file with ncid $ncid\n" ; $result = NetCDF::close( $ncid ) ; #print STDOUT "NetCDF::close result = $result\n" ; } close( OPN ) ; close( STDOUT ) ; close( STDERR ) ; exit( 0 ) ; } # init Recent weather arrays sub initReWX { # Recent_WX ReWX[3]; @Recent_WX = ( $S8, $S8, $S8 ) ; @Recent_WX_Bhh = ( $F, $F, $F ) ; @Recent_WX_Bmm = ( $F, $F, $F ) ; @Recent_WX_Ehh = ( $F, $F, $F ) ; @Recent_WX_Emm = ( $F, $F, $F ) ; } # end initReWX # pad str to correct length sub padstr { ( $str, $len ) = @_ ; local( $size, $i ) ; $size = length( $str ) ; for( $i = $size; $i < $len; $i++ ) { $str .= "\0" ; #print "$str,\n" ; } if( $size > $len ) { print STDOUT "String length is over $len chars long:\n $str\n" ; $str = substr( $str, 0, $len ) ; #exit 0 ; } return $str ; } sub thetime { my( $when, $add, $ss, $mm, $hh, $mday, $mon, $year, $wday, $yday, $isdst ) ; ( $when ) = @_ ; $add = 0 ; $mm = 0 ; $hh = 0 ; $mday = $ob_day ; if( $when eq "tomorrow" ) { $add = 86400 ; } elsif( $when eq "yesterday" ) { $add = -86400 ; $mday = $tday ; } elsif( $when eq "obs" ) { $mm = $ob_min ; $hh = $ob_hour ; $year = substr( $yymmdd, 0, 2 ) ; $mon = substr( $yymmdd, 2, 2 ) ; $time = timegm(0, $mm, $hh, $mday, $mon -1, $year, 0, 0, 0) ; return $time ; } elsif( $when eq "nominal" ) { $mm = $ob_min if( $ob_min > 14 && $ob_min < 45 ) ; $hh = $hour ; } elsif( $when eq "trans" ) { $mm = $tmin ; $hh = $thour ; $mday = $tday ; } $time = timegm(0, $mm, $hh, $mday, $themonth -1, $theyear, 0, 0, 0) ; return $time if( $when eq "obs" || $when eq "nominal" || $when eq "trans" ) ; ( $ss, $mm, $hh, $mday, $mon, $year, $wday, $yday, $isdst ) = gmtime( $time + $add ) ; $year = ( $year < 100 ? $year : $year - 100 ) ; $year = sprintf( "%02d", $year ) ; $mon++ ; $mon = sprintf( "%02d", $mon ) ; $mday = sprintf( "%02d", $mday ) ; return "$year$mon$mday" ; }